1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-12-24 20:32:39 +00:00

Added support fro 45GS02 CPU addressing modes and instructions. Added a few 45GS02 optimized fragments.

This commit is contained in:
jespergravgaard 2020-07-30 14:11:17 +02:00
parent 1a436a67a3
commit f27fe1a75c
27 changed files with 1641 additions and 740 deletions

View File

@ -1,4 +1,4 @@
//KICKC FRAGMENT CACHE 155084773d //KICKC FRAGMENT CACHE 15bc71afc6
//FRAGMENT vbsz1=_deref_pbsc1 //FRAGMENT vbsz1=_deref_pbsc1
lda {c1} lda {c1}
sta {z1} sta {z1}

View File

@ -0,0 +1,44 @@
//KICKC FRAGMENT CACHE 15bc71afc6
//FRAGMENT vduz1=vduc1
lda #<{c1}
sta {z1}
lda #>{c1}
sta {z1}+1
lda #<{c1}>>$10
sta {z1}+2
lda #>{c1}>>$10
sta {z1}+3
//FRAGMENT vbuz1=vbuc1
lda #{c1}
sta {z1}
//FRAGMENT vbuz1_lt_vbuc1_then_la1
lda {z1}
cmp #{c1}
bcc {la1}
//FRAGMENT _deref_pduc1=vduz1
ldq {z1}
stq {c1}
//FRAGMENT vduz1=vduz1_plus_vduz2
clc
ldq {z1}
adcq {z2}
stq {z1}
//FRAGMENT vduz1=vduz1_plus_vbuz2
lda {z2}
clc
adc {z1}
sta {z1}
lda {z1}+1
adc #0
sta {z1}+1
lda {z1}+2
adc #0
sta {z1}+2
lda {z1}+3
adc #0
sta {z1}+3
//FRAGMENT vbuz1=_inc_vbuz1
inc {z1}
//FRAGMENT vbuaa_lt_vbuc1_then_la1
cmp #{c1}
bcc {la1}

View File

@ -1,4 +1,4 @@
//KICKC FRAGMENT CACHE 155084773d //KICKC FRAGMENT CACHE 15bc71afc6
//FRAGMENT vbuz1=vbuc1 //FRAGMENT vbuz1=vbuc1
lda #{c1} lda #{c1}
sta {z1} sta {z1}

View File

@ -1,4 +1,4 @@
//KICKC FRAGMENT CACHE 155084773d //KICKC FRAGMENT CACHE 15bc71afc6
//FRAGMENT vbuz1=vbuc1 //FRAGMENT vbuz1=vbuc1
lda #{c1} lda #{c1}
sta {z1} sta {z1}

View File

@ -1,4 +1,4 @@
//KICKC FRAGMENT CACHE 155084773d //KICKC FRAGMENT CACHE 15bc71afc6
//FRAGMENT vbuz1=_deref_pbuc1 //FRAGMENT vbuz1=_deref_pbuc1
lda {c1} lda {c1}
sta {z1} sta {z1}

View File

@ -0,0 +1,2 @@
ldq {m1}
stq {c1}

View File

@ -0,0 +1,4 @@
clc
ldq {m1}
adcq {m2}
stq {m1}

View File

@ -1,13 +1,16 @@
package dk.camelot64.cpufamily6502; package dk.camelot64.cpufamily6502;
import java.util.*; import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/** /**
* A 6502 family CPU. The CPU has an instruction set. * A 6502 family CPU. The CPU has an instruction set.
*/ */
public class Cpu65xx { public class Cpu65xx {
/** The CPU name. */ /** The CPU name. */
private final String name; private final String name;
/** All opcodes in the instruction set. */ /** All opcodes in the instruction set. */
@ -40,8 +43,19 @@ public class Cpu65xx {
* @param cycles The number of cycles * @param cycles The number of cycles
*/ */
protected void addOpcode(int opcode, String mnemonic, CpuAddressingMode addressingMode, double cycles, String clobberString) { protected void addOpcode(int opcode, String mnemonic, CpuAddressingMode addressingMode, double cycles, String clobberString) {
CpuOpcode cpuOpcode = new CpuOpcode(opcode, mnemonic, addressingMode, cycles, clobberString); addOpcode(new int[opcode], mnemonic, addressingMode, cycles, clobberString);
addOpcode(cpuOpcode); }
/**
* Add an instruction opcode to the instruction set.
*
* @param opcode The numeric opcodes
* @param mnemonic The lower case mnemonic
* @param addressingMode The addressing mode
* @param cycles The number of cycles
*/
protected void addOpcode(int[] opcode, String mnemonic, CpuAddressingMode addressingMode, double cycles, String clobberString) {
addOpcode(new CpuOpcode(opcode, mnemonic, addressingMode, cycles, clobberString));
} }
/** /**

View File

@ -26,8 +26,8 @@ public class CpuOpcode {
/** Which registers/flags of the CPU are clobbered by the instruction. */ /** Which registers/flags of the CPU are clobbered by the instruction. */
private final CpuClobber clobber; private final CpuClobber clobber;
CpuOpcode(int opcode, String mnemonic, CpuAddressingMode addressingMode, double cycles, String clobberString) { CpuOpcode(int[] opcode, String mnemonic, CpuAddressingMode addressingMode, double cycles, String clobberString) {
this.opcode = new int[]{opcode}; this.opcode = opcode;
this.mnemonic = mnemonic; this.mnemonic = mnemonic;
this.addressingMode = addressingMode; this.addressingMode = addressingMode;
this.cycles = cycles; this.cycles = cycles;

View File

@ -1,6 +1,7 @@
package dk.camelot64.cpufamily6502.cpus; package dk.camelot64.cpufamily6502.cpus;
import dk.camelot64.cpufamily6502.Cpu65xx; import dk.camelot64.cpufamily6502.Cpu65xx;
import dk.camelot64.cpufamily6502.CpuAddressingMode;
/** /**
* The 45GS02 instruction set. * The 45GS02 instruction set.
@ -16,8 +17,88 @@ public class Cpu45GS02 extends Cpu65xx {
public Cpu45GS02() { public Cpu45GS02() {
super(NAME, Cpu65CE02.INSTANCE); super(NAME, Cpu65CE02.INSTANCE);
// TODO: Add 45GS02 instructions addOpcode(new int[]{0x42, 0x42, 0x5}, "orq", CpuAddressingMode.ZP, 8, "AXYZnz");
addOpcode(new int[]{0x42, 0x42, 0x6}, "aslq", CpuAddressingMode.ZP, 12, "cnz");
addOpcode(new int[]{0x42, 0x42, 0xA}, "aslq", CpuAddressingMode.NON, 3, "AXYZcnz");
addOpcode(new int[]{0x42, 0x42, 0xD}, "orq", CpuAddressingMode.ABS, 9, "AXYZnz");
addOpcode(new int[]{0x42, 0x42, 0xE}, "aslq", CpuAddressingMode.ABS, 13, "cnz");
addOpcode(new int[]{0x42, 0x42, 0x12}, "orq", CpuAddressingMode.INZ, 10, "AXYZnz");
addOpcode(new int[]{0x42, 0x42, 0x16}, "aslq", CpuAddressingMode.ZPX, 13, "cnz");
addOpcode(new int[]{0x42, 0x42, 0x1A}, "inq", CpuAddressingMode.NON, 3, "AXYZnz");
addOpcode(new int[]{0x42, 0x42, 0x1E}, "aslq", CpuAddressingMode.ABS, 13, "cnz");
addOpcode(new int[]{0x42, 0x42, 0x24}, "bitq", CpuAddressingMode.ZP, 8, "cnz");
addOpcode(new int[]{0x42, 0x42, 0x25}, "andq", CpuAddressingMode.ZP, 8, "AXYZnz");
addOpcode(new int[]{0x42, 0x42, 0x26}, "rolq", CpuAddressingMode.ZP, 12, "cnz");
addOpcode(new int[]{0x42, 0x42, 0x2A}, "rolq", CpuAddressingMode.NON, 3, "AXYZcnz");
addOpcode(new int[]{0x42, 0x42, 0x2C}, "bitq", CpuAddressingMode.ABS, 8, "cnz");
addOpcode(new int[]{0x42, 0x42, 0x2D}, "andq", CpuAddressingMode.ABS, 9, "AXYZnz");
addOpcode(new int[]{0x42, 0x42, 0x2E}, "rolq", CpuAddressingMode.ABS, 13, "cnz");
addOpcode(new int[]{0x42, 0x42, 0x32}, "andq", CpuAddressingMode.INZ, 10, "AXYZnz");
addOpcode(new int[]{0x42, 0x42, 0x36}, "rolq", CpuAddressingMode.ZPX, 12, "cnz");
addOpcode(new int[]{0x42, 0x42, 0x3A}, "deq", CpuAddressingMode.NON, 3, "AXYZnz");
addOpcode(new int[]{0x42, 0x42, 0x3E}, "rolq", CpuAddressingMode.ABS, 13, "cnz");
addOpcode(new int[]{0x42, 0x42, 0x43}, "asrq", CpuAddressingMode.NON, 3, "AXYZcnz");
addOpcode(new int[]{0x42, 0x42, 0x44}, "asrq", CpuAddressingMode.ZP, 12, "cnz");
addOpcode(new int[]{0x42, 0x42, 0x45}, "eorq", CpuAddressingMode.ZP, 8, "AXYZnz");
addOpcode(new int[]{0x42, 0x42, 0x46}, "lsrq", CpuAddressingMode.ZP, 12, "cnz");
addOpcode(new int[]{0x42, 0x42, 0x4A}, "lsrq", CpuAddressingMode.NON, 3, "AXYZcnz");
addOpcode(new int[]{0x42, 0x42, 0x4D}, "eorq", CpuAddressingMode.ABS, 9, "AXYZnz");
addOpcode(new int[]{0x42, 0x42, 0x4E}, "lsrq", CpuAddressingMode.ABS, 13, "cnz");
addOpcode(new int[]{0x42, 0x42, 0x52}, "eorq", CpuAddressingMode.INZ, 10, "AXYZnz");
addOpcode(new int[]{0x42, 0x42, 0x54}, "asrq", CpuAddressingMode.ZPX, 12, "cnz");
addOpcode(new int[]{0x42, 0x42, 0x56}, "lsrq", CpuAddressingMode.ZPX, 12, "cnz");
addOpcode(new int[]{0x42, 0x42, 0x5E}, "lsrq", CpuAddressingMode.ABS, 13, "cnz");
addOpcode(new int[]{0x42, 0x42, 0x65}, "adcq", CpuAddressingMode.ZP, 8, "AXYZcvnz");
addOpcode(new int[]{0x42, 0x42, 0x66}, "rorq", CpuAddressingMode.ZP, 12, "cnz");
addOpcode(new int[]{0x42, 0x42, 0x6A}, "rorq", CpuAddressingMode.NON, 3, "AXYZcnz");
addOpcode(new int[]{0x42, 0x42, 0x6D}, "adcq", CpuAddressingMode.ABS, 9, "AXYZcvnz");
addOpcode(new int[]{0x42, 0x42, 0x6E}, "rorq", CpuAddressingMode.ABS, 13, "cnz");
addOpcode(new int[]{0x42, 0x42, 0x72}, "adcq", CpuAddressingMode.INZ, 10, "AXYZcvnz");
addOpcode(new int[]{0x42, 0x42, 0x76}, "rorq", CpuAddressingMode.ZPX, 12, "cnz");
addOpcode(new int[]{0x42, 0x42, 0x7E}, "rorq", CpuAddressingMode.ABS, 13, "cnz");
addOpcode(new int[]{0x42, 0x42, 0x82}, "stq", CpuAddressingMode.ISY, 10, "");
addOpcode(new int[]{0x42, 0x42, 0x85}, "stq", CpuAddressingMode.ZP, 8, "");
addOpcode(new int[]{0x42, 0x42, 0x8D}, "stq", CpuAddressingMode.ABS, 9, "");
addOpcode(new int[]{0x42, 0x42, 0x92}, "stq", CpuAddressingMode.INZ, 10, "");
addOpcode(new int[]{0x42, 0x42, 0xA1}, "ldq", CpuAddressingMode.ISY, 10, "AXYZnz");
addOpcode(new int[]{0x42, 0x42, 0xA5}, "ldq", CpuAddressingMode.ZP, 8, "AXYZnz");
addOpcode(new int[]{0x42, 0x42, 0xAD}, "ldq", CpuAddressingMode.ABS, 9, "AXYZnz");
addOpcode(new int[]{0x42, 0x42, 0xB1}, "ldq", CpuAddressingMode.INZ, 10, "AXYZnz");
addOpcode(new int[]{0x42, 0x42, 0xB2}, "ldq", CpuAddressingMode.INZ, 10, "AXYZnz");
addOpcode(new int[]{0x42, 0x42, 0xB5}, "ldq", CpuAddressingMode.ZPX, 9, "AXYZnz");
addOpcode(new int[]{0x42, 0x42, 0xB9}, "ldq", CpuAddressingMode.ABS, 10, "AXYZnz");
addOpcode(new int[]{0x42, 0x42, 0xBD}, "ldq", CpuAddressingMode.ABS, 10, "AXYZnz");
addOpcode(new int[]{0x42, 0x42, 0xC5}, "cpq", CpuAddressingMode.ZP, 8, "cnz");
addOpcode(new int[]{0x42, 0x42, 0xC6}, "deq", CpuAddressingMode.ZP, 12, "nz");
addOpcode(new int[]{0x42, 0x42, 0xCD}, "cpq", CpuAddressingMode.ABS, 9, "cnz");
addOpcode(new int[]{0x42, 0x42, 0xCE}, "deq", CpuAddressingMode.ABS, 13, "nz");
addOpcode(new int[]{0x42, 0x42, 0xD2}, "cpq", CpuAddressingMode.INZ, 10, "cnz");
addOpcode(new int[]{0x42, 0x42, 0xD6}, "deq", CpuAddressingMode.ZPX, 12, "nz");
addOpcode(new int[]{0x42, 0x42, 0xDE}, "deq", CpuAddressingMode.ABS, 13, "nz");
addOpcode(new int[]{0x42, 0x42, 0xE2}, "ldq", CpuAddressingMode.ISY, 10, "AXYZnz");
addOpcode(new int[]{0x42, 0x42, 0xE5}, "sbcq", CpuAddressingMode.ZP, 8, "AXYZcvnz");
addOpcode(new int[]{0x42, 0x42, 0xE6}, "inq", CpuAddressingMode.ZP, 13, "nz");
addOpcode(new int[]{0x42, 0x42, 0xea, 0x12}, "orq", CpuAddressingMode.LIN, 13, "AXYZnz");
addOpcode(new int[]{0x42, 0x42, 0xea, 0x32}, "andq", CpuAddressingMode.LIN, 13, "AXYZnz");
addOpcode(new int[]{0x42, 0x42, 0xea, 0x52}, "eorq", CpuAddressingMode.LIN, 13, "AXYZnz");
addOpcode(new int[]{0x42, 0x42, 0xea, 0x72}, "adcq", CpuAddressingMode.LIN, 13, "AXYZcvnz");
addOpcode(new int[]{0x42, 0x42, 0xea, 0x92}, "stq", CpuAddressingMode.LIN, 13, "");
addOpcode(new int[]{0x42, 0x42, 0xea, 0xB2}, "ldq", CpuAddressingMode.LIN, 13, "AXYZnz");
addOpcode(new int[]{0x42, 0x42, 0xea, 0xD2}, "cpq", CpuAddressingMode.LIN, 13, "cnz");
addOpcode(new int[]{0x42, 0x42, 0xea, 0xF2}, "sbcq", CpuAddressingMode.LIN, 13, "AXYZcvnz");
addOpcode(new int[]{0x42, 0x42, 0xED}, "sbcq", CpuAddressingMode.ABS, 9, "AXYZcvnz");
addOpcode(new int[]{0x42, 0x42, 0xEE}, "inq", CpuAddressingMode.ABS, 14, "nz");
addOpcode(new int[]{0x42, 0x42, 0xF2}, "sbcq", CpuAddressingMode.INZ, 10, "AXYZcvnz");
addOpcode(new int[]{0x42, 0x42, 0xF6}, "inq", CpuAddressingMode.ZPX, 13, "nz");
addOpcode(new int[]{0x42, 0x42, 0xFE}, "inq", CpuAddressingMode.ABS, 14, "nz");
addOpcode(new int[]{0xea, 0x12}, "ora", CpuAddressingMode.LIZ, 7, "Anz");
addOpcode(new int[]{0xea, 0x32}, "and", CpuAddressingMode.LIZ, 7, "Anz");
addOpcode(new int[]{0xea, 0x52}, "eor", CpuAddressingMode.LIZ, 7, "Anz");
addOpcode(new int[]{0xea, 0x72}, "adc", CpuAddressingMode.LIZ, 7, "Acvnz");
addOpcode(new int[]{0xea, 0x92}, "sta", CpuAddressingMode.LIZ, 8, "");
addOpcode(new int[]{0xea, 0xB2}, "lda", CpuAddressingMode.LIZ, 7, "Anz");
addOpcode(new int[]{0xea, 0xD2}, "cmp", CpuAddressingMode.LIZ, 7, "cnz");
addOpcode(new int[]{0xea, 0xF2}, "sbc", CpuAddressingMode.LIZ, 8, "Acvnz");
// TODO: Disable NOP? // TODO: Disable NOP?
} }

View File

@ -338,7 +338,7 @@ public class AsmFragmentInstance {
String operand1 = param1 == null ? null : param1.getParam(); String operand1 = param1 == null ? null : param1.getParam();
String operand2 = param2 == null ? null : param2.getParam(); String operand2 = param2 == null ? null : param2.getParam();
if(cpuOpcode == null) { if(cpuOpcode == null) {
throw new InternalError("Error in " + name + ".asm line " + instructionCtx.getStart().getLine() + " - Instruction type not supported " + addressingMode.getAsm(mnemonic, operand1, operand2)); throw new InternalError("Error in " + name + ".asm line " + instructionCtx.getStart().getLine() + " - Instruction type not supported " + addressingMode.getAsm(mnemonic, operand1, operand2) +" by CPU "+this.fragmentInstance.fragmentTemplate.getTargetCpu().getName());
} }
return new AsmInstruction(cpuOpcode, operand1, operand2); return new AsmInstruction(cpuOpcode, operand1, operand2);
} }

View File

@ -177,7 +177,8 @@ ASM_MNEMONIC:
'bbr2'| 'bbr3'| 'bbr4'| 'bbr5'| 'bbr6'| 'bbr7'| 'bbs0'| 'bbs1'| 'bbs2'| 'bbs3'| 'bbs4'| 'bbs5'| 'bbs6'| 'bbs7'| 'bra' | 'phx' | 'phy' | 'plx' | 'ply' | 'bbr2'| 'bbr3'| 'bbr4'| 'bbr5'| 'bbr6'| 'bbr7'| 'bbs0'| 'bbs1'| 'bbs2'| 'bbs3'| 'bbs4'| 'bbs5'| 'bbs6'| 'bbs7'| 'bra' | 'phx' | 'phy' | 'plx' | 'ply' |
'rmb0'| 'rmb1'| 'rmb2'| 'rmb3'| 'rmb4'| 'rmb5'| 'rmb6'| 'rmb7'| 'smb0'| 'smb1'| 'smb2'| 'smb3'| 'smb4'| 'smb5'| 'smb6'| 'smb7'| 'stp' | 'stz' | 'trb' | 'rmb0'| 'rmb1'| 'rmb2'| 'rmb3'| 'rmb4'| 'rmb5'| 'rmb6'| 'rmb7'| 'smb0'| 'smb1'| 'smb2'| 'smb3'| 'smb4'| 'smb5'| 'smb6'| 'smb7'| 'stp' | 'stz' | 'trb' |
'tsb' | 'wai' | 'cle' | 'see' | 'tsy' | 'lbpl'| 'inz' | 'tys' | 'lbmi'| 'dez' | 'neg' | 'asr' | 'taz' | 'lbvc'| 'tab' | 'map' | 'rtn' | 'lbsr'| 'tza' | 'tsb' | 'wai' | 'cle' | 'see' | 'tsy' | 'lbpl'| 'inz' | 'tys' | 'lbmi'| 'dez' | 'neg' | 'asr' | 'taz' | 'lbvc'| 'tab' | 'map' | 'rtn' | 'lbsr'| 'tza' |
'lbvs'| 'tba' | 'lbra'| 'lbcc'| 'ldz' | 'lbcs'| 'cpz' | 'dew' | 'asw' | 'lbne'| 'phz' | 'inw' | 'row' | 'lbeq'| 'phw' | 'plz' | 'eom' 'lbvs'| 'tba' | 'lbra'| 'lbcc'| 'ldz' | 'lbcs'| 'cpz' | 'dew' | 'asw' | 'lbne'| 'phz' | 'inw' | 'row' | 'lbeq'| 'phw' | 'plz' | 'eom' | 'adcq'| 'andq'|
'aslq'| 'asrq'| 'bitq'| 'cpq' | 'deq' | 'eorq'| 'inq' | 'ldq' | 'lsrq'| 'orq' | 'rolq'| 'rorq'| 'sbcq'| 'stq'
; ;
ASM_IMM : '#' ; ASM_IMM : '#' ;

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -42,6 +42,11 @@ public class TestPrograms {
public TestPrograms() { public TestPrograms() {
} }
@Test
public void testCpu45GS02AddressingModes() throws IOException, URISyntaxException {
compileAndCompare("cpu-45gs02-addressing-modes.c");
}
@Test @Test
public void testCpu65CE02AddressingModes() throws IOException, URISyntaxException { public void testCpu65CE02AddressingModes() throws IOException, URISyntaxException {
compileAndCompare("cpu-65ce02-addressing-modes.c"); compileAndCompare("cpu-65ce02-addressing-modes.c");
@ -58,13 +63,13 @@ public class TestPrograms {
} }
@Test @Test
public void testMega65C65ce02() throws IOException, URISyntaxException { public void testCpu45GS02() throws IOException, URISyntaxException {
compileAndCompare("cpu-45gs02.c"); compileAndCompare("cpu-45gs02.c");
} }
@Test @Test
public void testCpu65CE02() throws IOException, URISyntaxException { public void testCpu65CE02() throws IOException, URISyntaxException {
compileAndCompare("cpu-65ce02.c", log()); compileAndCompare("cpu-65ce02.c");
} }
@Test @Test

View File

@ -0,0 +1,57 @@
// Tests the different ASM addressing modes
#pragma cpu(mega45gs02)
void main() {
asm {
// 6502:impl
inx
// 6502:imm
lda #$12
// 65CE02:immword
phw #$1234
// 6502:zp
lda $12
// 6502:zp,x
lda $12,x
// 6502:zp,y
ldx $12,y
// 65C02: (zp)
//ora ($12)
// 6502:(zp,x)
lda ($12,x)
// 6502:(zp),y
lda ($12),y
// 65CE02: (zp),z
ora ($12),z
// 65CE02: Stack Pointer Indirect Indexed
lda ($12,sp),y
// 6502:absolute
lda $1234
// 6502:abs,x
lda $1234,x
// 6502:abs,y
lda $1234,y
// 6502:relative
beq lbl1
// 65CE02:word relative
lbeq far
// 65C02: $12, rel
bbr0 $12,lbl2
lbl1:
// 6502:(abs)
jmp ($1234)
lbl2:
// 65C02: ($1234,X)
jmp ($1234,x)
lbl3:
// 45GS02: Indirect Long,Z
lda (($12)),z
// 45GS02: Indirect Long
ldq (($12))
}
}
__address(0x2000) char far[] = { 0x60 };

View File

@ -1,11 +1,16 @@
// Tests compiling inline C65CE02/45GS02 Assembler // Test the 45GS02 CPU
// A program that uses 45GS02 instructions
#pragma cpu(MEGA45GS02) #pragma cpu(MEGA45GS02)
unsigned long* SCREEN = 0x0400;
void main() { void main() {
kickasm {{ unsigned long sum = 0;
ldz #2 unsigned long addend = 123456;
stz $0800 for(char i=0;i<100;i++) {
adcq ($2) sum += addend; // will utilize ADQ/STQ
}} addend += i;
}
*SCREEN = sum; // will utilize LDQ/STQ
} }

View File

@ -37,19 +37,6 @@ void main() {
lbl2: lbl2:
// 65C02: ($1234,X) // 65C02: ($1234,X)
jmp ($1234,x) jmp ($1234,x)
// TODO Stack Pointer Indirect Indexed
//lda ($12,sp),y
// TODO Indirect,Z
//lda ($12),z
// TODO Indirect Long,Z
//lda (($12)),z
// TODO Indirect Long
//lda (($12))
} }
} }

View File

@ -45,13 +45,6 @@ void main() {
lbl2: lbl2:
// 65C02: ($1234,X) // 65C02: ($1234,X)
jmp ($1234,x) jmp ($1234,x)
// TODO Indirect Long,Z
//lda (($12)),z
// TODO Indirect Long
//lda (($12))
} }

View File

@ -0,0 +1,35 @@
// Tests the different ASM addressing modes
.cpu _45gs02
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
main: {
// asm
inx
lda #$12
phw #$1234
lda.z $12
lda.z $12,x
ldx.z $12,y
lda ($12,x)
lda ($12),y
ora.z ($12),z
lda.z ($12,sp),y
lda $1234
lda $1234,x
lda $1234,y
beq lbl1
lbeq far
bbr0 $12,lbl2
lbl1:
jmp ($1234)
lbl2:
jmp ($1234,x)
lbl3:
lda.z (($12)),z
ldq.z (($12))
// }
rts
}
.pc = $2000 "far"
far: .byte $60

View File

@ -0,0 +1,8 @@
(void()) main()
main: scope:[main] from
asm { inx lda#$12 phw#$1234 lda$12 lda$12,x ldx$12,y lda($12,x) lda($12),y ora($12),z lda($12,sp),y lda$1234 lda$1234,x lda$1234,y beqlbl1 lbeqfar bbr0$12,lbl2 lbl1: jmp($1234) lbl2: jmp($1234,x) lbl3: lda(($12)),z ldq(($12)) }
to:main::@return
main::@return: scope:[main] from main
[1] return
to:@return

View File

@ -0,0 +1,218 @@
Resolved forward reference far to (const byte*) far
CONTROL FLOW GRAPH SSA
(void()) main()
main: scope:[main] from __start
asm { inx lda#$12 phw#$1234 lda$12 lda$12,x ldx$12,y lda($12,x) lda($12),y ora($12),z lda($12,sp),y lda$1234 lda$1234,x lda$1234,y beqlbl1 lbeqfar bbr0$12,lbl2 lbl1: jmp($1234) lbl2: jmp($1234,x) lbl3: lda(($12)),z ldq(($12)) }
to:main::@return
main::@return: scope:[main] from main
return
to:@return
(void()) __start()
__start: scope:[__start] from
call main
to:__start::@1
__start::@1: scope:[__start] from __start
to:__start::@return
__start::@return: scope:[__start] from __start::@1
return
to:@return
SYMBOL TABLE SSA
(void()) __start()
(label) __start::@1
(label) __start::@return
(const byte*) far[] = { (byte) $60 }
(void()) main()
(label) main::@return
Removing unused procedure __start
Removing unused procedure block __start
Removing unused procedure block __start::@1
Removing unused procedure block __start::@return
Successful SSA optimization PassNEliminateEmptyStart
CALL GRAPH
Created 0 initial phi equivalence classes
Coalesced down to 0 phi equivalence classes
FINAL CONTROL FLOW GRAPH
(void()) main()
main: scope:[main] from
asm { inx lda#$12 phw#$1234 lda$12 lda$12,x ldx$12,y lda($12,x) lda($12),y ora($12),z lda($12,sp),y lda$1234 lda$1234,x lda$1234,y beqlbl1 lbeqfar bbr0$12,lbl2 lbl1: jmp($1234) lbl2: jmp($1234,x) lbl3: lda(($12)),z ldq(($12)) }
to:main::@return
main::@return: scope:[main] from main
[1] return
to:@return
VARIABLE REGISTER WEIGHTS
(void()) main()
Initial phi equivalence classes
Complete equivalence classes
INITIAL ASM
Target platform is c64basic / MEGA45GS02
// File Comments
// Tests the different ASM addressing modes
// Upstart
.cpu _45gs02
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
// Global Constants & labels
// main
main: {
// asm { inx lda#$12 phw#$1234 lda$12 lda$12,x ldx$12,y lda($12,x) lda($12),y ora($12),z lda($12,sp),y lda$1234 lda$1234,x lda$1234,y beqlbl1 lbeqfar bbr0$12,lbl2 lbl1: jmp($1234) lbl2: jmp($1234,x) lbl3: lda(($12)),z ldq(($12)) }
inx
lda #$12
phw #$1234
lda.z $12
lda.z $12,x
ldx.z $12,y
lda ($12,x)
lda ($12),y
ora.z ($12),z
lda.z ($12,sp),y
lda $1234
lda $1234,x
lda $1234,y
beq lbl1
lbeq far
bbr0 $12,lbl2
lbl1:
jmp ($1234)
lbl2:
jmp ($1234,x)
lbl3:
lda.z (($12)),z
ldq.z (($12))
jmp __breturn
// main::@return
__breturn:
// [1] return
rts
}
// File Data
.pc = $2000 "far"
far: .byte $60
REGISTER UPLIFT POTENTIAL REGISTERS
Statement asm { inx lda#$12 phw#$1234 lda$12 lda$12,x ldx$12,y lda($12,x) lda($12),y ora($12),z lda($12,sp),y lda$1234 lda$1234,x lda$1234,y beqlbl1 lbeqfar bbr0$12,lbl2 lbl1: jmp($1234) lbl2: jmp($1234,x) lbl3: lda(($12)),z ldq(($12)) } always clobbers reg byte a reg byte x reg byte y
REGISTER UPLIFT SCOPES
Uplift Scope [main]
Uplift Scope []
Uplifting [main] best 106 combination
Uplifting [] best 106 combination
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
// Tests the different ASM addressing modes
// Upstart
.cpu _45gs02
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
// Global Constants & labels
// main
main: {
// asm { inx lda#$12 phw#$1234 lda$12 lda$12,x ldx$12,y lda($12,x) lda($12),y ora($12),z lda($12,sp),y lda$1234 lda$1234,x lda$1234,y beqlbl1 lbeqfar bbr0$12,lbl2 lbl1: jmp($1234) lbl2: jmp($1234,x) lbl3: lda(($12)),z ldq(($12)) }
inx
lda #$12
phw #$1234
lda.z $12
lda.z $12,x
ldx.z $12,y
lda ($12,x)
lda ($12),y
ora.z ($12),z
lda.z ($12,sp),y
lda $1234
lda $1234,x
lda $1234,y
beq lbl1
lbeq far
bbr0 $12,lbl2
lbl1:
jmp ($1234)
lbl2:
jmp ($1234,x)
lbl3:
lda.z (($12)),z
ldq.z (($12))
jmp __breturn
// main::@return
__breturn:
// [1] return
rts
}
// File Data
.pc = $2000 "far"
far: .byte $60
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp __breturn
Succesful ASM optimization Pass5NextJumpElimination
Removing instruction __breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
FINAL SYMBOL TABLE
(const byte*) far[] = { (byte) $60 }
(void()) main()
(label) main::@return
FINAL ASSEMBLER
Score: 103
// File Comments
// Tests the different ASM addressing modes
// Upstart
.cpu _45gs02
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
// Global Constants & labels
// main
main: {
// asm
// asm { inx lda#$12 phw#$1234 lda$12 lda$12,x ldx$12,y lda($12,x) lda($12),y ora($12),z lda($12,sp),y lda$1234 lda$1234,x lda$1234,y beqlbl1 lbeqfar bbr0$12,lbl2 lbl1: jmp($1234) lbl2: jmp($1234,x) lbl3: lda(($12)),z ldq(($12)) }
inx
lda #$12
phw #$1234
lda.z $12
lda.z $12,x
ldx.z $12,y
lda ($12,x)
lda ($12),y
ora.z ($12),z
lda.z ($12,sp),y
lda $1234
lda $1234,x
lda $1234,y
beq lbl1
lbeq far
bbr0 $12,lbl2
lbl1:
jmp ($1234)
lbl2:
jmp ($1234,x)
lbl3:
lda.z (($12)),z
ldq.z (($12))
// main::@return
// }
// [1] return
rts
}
// File Data
.pc = $2000 "far"
far: .byte $60

View File

@ -0,0 +1,4 @@
(const byte*) far[] = { (byte) $60 }
(void()) main()
(label) main::@return

View File

@ -1,14 +1,63 @@
// Tests compiling inline C65CE02/45GS02 Assembler // Test the 45GS02 CPU
// A program that uses 45GS02 instructions
.cpu _45gs02 .cpu _45gs02
.pc = $801 "Basic" .pc = $801 "Basic"
:BasicUpstart(main) :BasicUpstart(main)
.pc = $80d "Program" .pc = $80d "Program"
.label SCREEN = $400
main: { main: {
// kickasm .label sum = 3
ldz #2 .label addend = 7
stz $0800 .label i = 2
adcq ($2) lda #<$1e240
sta.z addend
lda #>$1e240
sta.z addend+1
lda #<$1e240>>$10
sta.z addend+2
lda #>$1e240>>$10
sta.z addend+3
lda #<0
sta.z sum
sta.z sum+1
lda #<0>>$10
sta.z sum+2
lda #>0>>$10
sta.z sum+3
lda #0
sta.z i
__b1:
// for(char i=0;i<100;i++)
lda.z i
cmp #$64
bcc __b2
// *SCREEN = sum
ldq.z sum
stq SCREEN
// } // }
rts rts
__b2:
// sum += addend
clc
ldq.z sum
adcq.z addend
stq.z sum
// addend += i
// will utilize ADQ/STQ
lda.z i
clc
adc.z addend
sta.z addend
lda.z addend+1
adc #0
sta.z addend+1
lda.z addend+2
adc #0
sta.z addend+2
lda.z addend+3
adc #0
sta.z addend+3
// for(char i=0;i<100;i++)
inc.z i
jmp __b1
} }

View File

@ -1,11 +1,22 @@
(void()) main() (void()) main()
main: scope:[main] from main: scope:[main] from
kickasm() {{ ldz #2 [0] phi()
stz $0800 to:main::@1
adcq ($2) main::@1: scope:[main] from main main::@2
}} [1] (dword) main::addend#2 ← phi( main/(dword) $1e240 main::@2/(dword) main::addend#1 )
[1] (dword) main::sum#2 ← phi( main/(dword) 0 main::@2/(dword) main::sum#1 )
[1] (byte) main::i#2 ← phi( main/(byte) 0 main::@2/(byte) main::i#1 )
[2] if((byte) main::i#2<(byte) $64) goto main::@2
to:main::@3
main::@3: scope:[main] from main::@1
[3] *((const dword*) SCREEN) ← (dword) main::sum#2
to:main::@return to:main::@return
main::@return: scope:[main] from main main::@return: scope:[main] from main::@3
[1] return [4] return
to:@return to:@return
main::@2: scope:[main] from main::@1
[5] (dword) main::sum#1 ← (dword) main::sum#2 + (dword) main::addend#2
[6] (dword) main::addend#1 ← (dword) main::addend#2 + (byte) main::i#2
[7] (byte) main::i#1 ← ++ (byte) main::i#2
to:main::@1

View File

@ -1,157 +1,497 @@
Inlined call call __init
CONTROL FLOW GRAPH SSA CONTROL FLOW GRAPH SSA
(void()) main() (void()) main()
main: scope:[main] from __start main: scope:[main] from __start::@1
kickasm() {{ ldz #2 (dword) main::sum#0 ← (dword) 0
stz $0800 (dword) main::addend#0 ← (dword) $1e240
adcq ($2) (byte) main::i#0 ← (byte) 0
}} to:main::@1
main::@1: scope:[main] from main main::@2
(dword) main::addend#3 ← phi( main/(dword) main::addend#0 main::@2/(dword) main::addend#1 )
(dword) main::sum#4 ← phi( main/(dword) main::sum#0 main::@2/(dword) main::sum#1 )
(byte) main::i#2 ← phi( main/(byte) main::i#0 main::@2/(byte) main::i#1 )
(bool~) main::$0 ← (byte) main::i#2 < (number) $64
if((bool~) main::$0) goto main::@2
to:main::@3
main::@2: scope:[main] from main::@1
(byte) main::i#3 ← phi( main::@1/(byte) main::i#2 )
(dword) main::addend#2 ← phi( main::@1/(dword) main::addend#3 )
(dword) main::sum#2 ← phi( main::@1/(dword) main::sum#4 )
(dword) main::sum#1 ← (dword) main::sum#2 + (dword) main::addend#2
(dword) main::addend#1 ← (dword) main::addend#2 + (byte) main::i#3
(byte) main::i#1 ← ++ (byte) main::i#3
to:main::@1
main::@3: scope:[main] from main::@1
(dword) main::sum#3 ← phi( main::@1/(dword) main::sum#4 )
*((const dword*) SCREEN) ← (dword) main::sum#3
to:main::@return to:main::@return
main::@return: scope:[main] from main main::@return: scope:[main] from main::@3
return return
to:@return to:@return
(void()) __start() (void()) __start()
__start: scope:[__start] from __start: scope:[__start] from
call main to:__start::__init1
__start::__init1: scope:[__start] from __start
to:__start::@1 to:__start::@1
__start::@1: scope:[__start] from __start __start::@1: scope:[__start] from __start::__init1
call main
to:__start::@2
__start::@2: scope:[__start] from __start::@1
to:__start::@return to:__start::@return
__start::@return: scope:[__start] from __start::@1 __start::@return: scope:[__start] from __start::@2
return return
to:@return to:@return
SYMBOL TABLE SSA SYMBOL TABLE SSA
(const dword*) SCREEN = (dword*)(number) $400
(void()) __start() (void()) __start()
(label) __start::@1 (label) __start::@1
(label) __start::@2
(label) __start::@return (label) __start::@return
(label) __start::__init1
(void()) main() (void()) main()
(bool~) main::$0
(label) main::@1
(label) main::@2
(label) main::@3
(label) main::@return (label) main::@return
(dword) main::addend
(dword) main::addend#0
(dword) main::addend#1
(dword) main::addend#2
(dword) main::addend#3
(byte) main::i
(byte) main::i#0
(byte) main::i#1
(byte) main::i#2
(byte) main::i#3
(dword) main::sum
(dword) main::sum#0
(dword) main::sum#1
(dword) main::sum#2
(dword) main::sum#3
(dword) main::sum#4
Adding number conversion cast (unumber) $64 in (bool~) main::$0 ← (byte) main::i#2 < (number) $64
Successful SSA optimization PassNAddNumberTypeConversions
Simplifying constant pointer cast (dword*) 1024
Simplifying constant integer cast $64
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (byte) $64
Successful SSA optimization PassNFinalizeNumberTypeConversions
Alias main::sum#2 = main::sum#4 main::sum#3
Alias main::addend#2 = main::addend#3
Alias main::i#2 = main::i#3
Successful SSA optimization Pass2AliasElimination
Simple Condition (bool~) main::$0 [5] if((byte) main::i#2<(byte) $64) goto main::@2
Successful SSA optimization Pass2ConditionalJumpSimplification
Constant (const dword) main::sum#0 = 0
Constant (const dword) main::addend#0 = $1e240
Constant (const byte) main::i#0 = 0
Successful SSA optimization Pass2ConstantIdentification
Removing unused procedure __start Removing unused procedure __start
Removing unused procedure block __start Removing unused procedure block __start
Removing unused procedure block __start::__init1
Removing unused procedure block __start::@1 Removing unused procedure block __start::@1
Removing unused procedure block __start::@2
Removing unused procedure block __start::@return Removing unused procedure block __start::@return
Successful SSA optimization PassNEliminateEmptyStart Successful SSA optimization PassNEliminateEmptyStart
Inlining constant with var siblings (const dword) main::sum#0
Inlining constant with var siblings (const dword) main::addend#0
Inlining constant with var siblings (const byte) main::i#0
Constant inlined main::i#0 = (byte) 0
Constant inlined main::addend#0 = (dword) $1e240
Constant inlined main::sum#0 = (dword) 0
Successful SSA optimization Pass2ConstantInlining
Adding NOP phi() at start of main
CALL GRAPH CALL GRAPH
Created 0 initial phi equivalence classes Created 3 initial phi equivalence classes
Coalesced down to 0 phi equivalence classes Coalesced [8] main::i#4 ← main::i#1
Coalesced [9] main::sum#5 ← main::sum#1
Coalesced [10] main::addend#4 ← main::addend#1
Coalesced down to 3 phi equivalence classes
Adding NOP phi() at start of main
FINAL CONTROL FLOW GRAPH FINAL CONTROL FLOW GRAPH
(void()) main() (void()) main()
main: scope:[main] from main: scope:[main] from
kickasm() {{ ldz #2 [0] phi()
stz $0800 to:main::@1
adcq ($2) main::@1: scope:[main] from main main::@2
}} [1] (dword) main::addend#2 ← phi( main/(dword) $1e240 main::@2/(dword) main::addend#1 )
[1] (dword) main::sum#2 ← phi( main/(dword) 0 main::@2/(dword) main::sum#1 )
[1] (byte) main::i#2 ← phi( main/(byte) 0 main::@2/(byte) main::i#1 )
[2] if((byte) main::i#2<(byte) $64) goto main::@2
to:main::@3
main::@3: scope:[main] from main::@1
[3] *((const dword*) SCREEN) ← (dword) main::sum#2
to:main::@return to:main::@return
main::@return: scope:[main] from main main::@return: scope:[main] from main::@3
[1] return [4] return
to:@return to:@return
main::@2: scope:[main] from main::@1
[5] (dword) main::sum#1 ← (dword) main::sum#2 + (dword) main::addend#2
[6] (dword) main::addend#1 ← (dword) main::addend#2 + (byte) main::i#2
[7] (byte) main::i#1 ← ++ (byte) main::i#2
to:main::@1
VARIABLE REGISTER WEIGHTS VARIABLE REGISTER WEIGHTS
(void()) main() (void()) main()
(dword) main::addend
(dword) main::addend#1 11.0
(dword) main::addend#2 11.0
(byte) main::i
(byte) main::i#1 22.0
(byte) main::i#2 11.0
(dword) main::sum
(dword) main::sum#1 7.333333333333333
(dword) main::sum#2 12.0
Initial phi equivalence classes Initial phi equivalence classes
[ main::i#2 main::i#1 ]
[ main::sum#2 main::sum#1 ]
[ main::addend#2 main::addend#1 ]
Complete equivalence classes Complete equivalence classes
[ main::i#2 main::i#1 ]
[ main::sum#2 main::sum#1 ]
[ main::addend#2 main::addend#1 ]
Allocated zp[1]:2 [ main::i#2 main::i#1 ]
Allocated zp[4]:3 [ main::sum#2 main::sum#1 ]
Allocated zp[4]:7 [ main::addend#2 main::addend#1 ]
INITIAL ASM INITIAL ASM
Target platform is c64basic / MEGA45GS02 Target platform is c64basic / MEGA45GS02
// File Comments // File Comments
// Tests compiling inline C65CE02/45GS02 Assembler // Test the 45GS02 CPU
// A program that uses 45GS02 instructions
// Upstart // Upstart
.cpu _45gs02 .cpu _45gs02
.pc = $801 "Basic" .pc = $801 "Basic"
:BasicUpstart(main) :BasicUpstart(main)
.pc = $80d "Program" .pc = $80d "Program"
// Global Constants & labels // Global Constants & labels
.label SCREEN = $400
// main // main
main: { main: {
// kickasm() {{ ldz #2 stz $0800 adcq ($2) }} .label sum = 3
ldz #2 .label addend = 7
stz $0800 .label i = 2
adcq ($2) // [1] phi from main to main::@1 [phi:main->main::@1]
__b1_from_main:
// [1] phi (dword) main::addend#2 = (dword) $1e240 [phi:main->main::@1#0] -- vduz1=vduc1
lda #<$1e240
sta.z addend
lda #>$1e240
sta.z addend+1
lda #<$1e240>>$10
sta.z addend+2
lda #>$1e240>>$10
sta.z addend+3
// [1] phi (dword) main::sum#2 = (dword) 0 [phi:main->main::@1#1] -- vduz1=vduc1
lda #<0
sta.z sum
lda #>0
sta.z sum+1
lda #<0>>$10
sta.z sum+2
lda #>0>>$10
sta.z sum+3
// [1] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#2] -- vbuz1=vbuc1
lda #0
sta.z i
jmp __b1
// main::@1
__b1:
// [2] if((byte) main::i#2<(byte) $64) goto main::@2 -- vbuz1_lt_vbuc1_then_la1
lda.z i
cmp #$64
bcc __b2
jmp __b3
// main::@3
__b3:
// [3] *((const dword*) SCREEN) ← (dword) main::sum#2 -- _deref_pduc1=vduz1
ldq.z sum
stq SCREEN
jmp __breturn jmp __breturn
// main::@return // main::@return
__breturn: __breturn:
// [1] return // [4] return
rts rts
// main::@2
__b2:
// [5] (dword) main::sum#1 ← (dword) main::sum#2 + (dword) main::addend#2 -- vduz1=vduz1_plus_vduz2
clc
ldq.z sum
adcq.z addend
stq.z sum
// [6] (dword) main::addend#1 ← (dword) main::addend#2 + (byte) main::i#2 -- vduz1=vduz1_plus_vbuz2
// will utilize ADQ/STQ
lda.z i
clc
adc.z addend
sta.z addend
lda.z addend+1
adc #0
sta.z addend+1
lda.z addend+2
adc #0
sta.z addend+2
lda.z addend+3
adc #0
sta.z addend+3
// [7] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuz1=_inc_vbuz1
inc.z i
// [1] phi from main::@2 to main::@1 [phi:main::@2->main::@1]
__b1_from___b2:
// [1] phi (dword) main::addend#2 = (dword) main::addend#1 [phi:main::@2->main::@1#0] -- register_copy
// [1] phi (dword) main::sum#2 = (dword) main::sum#1 [phi:main::@2->main::@1#1] -- register_copy
// [1] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@2->main::@1#2] -- register_copy
jmp __b1
} }
// File Data // File Data
REGISTER UPLIFT POTENTIAL REGISTERS REGISTER UPLIFT POTENTIAL REGISTERS
Statement [3] *((const dword*) SCREEN) ← (dword) main::sum#2 [ ] ( [ ] { } ) always clobbers reg byte a reg byte x reg byte y
Statement [5] (dword) main::sum#1 ← (dword) main::sum#2 + (dword) main::addend#2 [ main::i#2 main::addend#2 main::sum#1 ] ( [ main::i#2 main::addend#2 main::sum#1 ] { } ) always clobbers reg byte a reg byte x reg byte y
Removing always clobbered register reg byte a as potential for zp[1]:2 [ main::i#2 main::i#1 ]
Removing always clobbered register reg byte x as potential for zp[1]:2 [ main::i#2 main::i#1 ]
Removing always clobbered register reg byte y as potential for zp[1]:2 [ main::i#2 main::i#1 ]
Statement [6] (dword) main::addend#1 ← (dword) main::addend#2 + (byte) main::i#2 [ main::i#2 main::sum#1 main::addend#1 ] ( [ main::i#2 main::sum#1 main::addend#1 ] { } ) always clobbers reg byte a
Statement [2] if((byte) main::i#2<(byte) $64) goto main::@2 [ main::i#2 main::sum#2 main::addend#2 ] ( [ main::i#2 main::sum#2 main::addend#2 ] { } ) always clobbers reg byte a
Statement [3] *((const dword*) SCREEN) ← (dword) main::sum#2 [ ] ( [ ] { } ) always clobbers reg byte a reg byte x reg byte y
Statement [5] (dword) main::sum#1 ← (dword) main::sum#2 + (dword) main::addend#2 [ main::i#2 main::addend#2 main::sum#1 ] ( [ main::i#2 main::addend#2 main::sum#1 ] { } ) always clobbers reg byte a reg byte x reg byte y
Statement [6] (dword) main::addend#1 ← (dword) main::addend#2 + (byte) main::i#2 [ main::i#2 main::sum#1 main::addend#1 ] ( [ main::i#2 main::sum#1 main::addend#1 ] { } ) always clobbers reg byte a
Potential registers zp[1]:2 [ main::i#2 main::i#1 ] : zp[1]:2 ,
Potential registers zp[4]:3 [ main::sum#2 main::sum#1 ] : zp[4]:3 ,
Potential registers zp[4]:7 [ main::addend#2 main::addend#1 ] : zp[4]:7 ,
REGISTER UPLIFT SCOPES REGISTER UPLIFT SCOPES
Uplift Scope [main] Uplift Scope [main] 33: zp[1]:2 [ main::i#2 main::i#1 ] 22: zp[4]:7 [ main::addend#2 main::addend#1 ] 19.33: zp[4]:3 [ main::sum#2 main::sum#1 ]
Uplift Scope [] Uplift Scope []
Uplifting [main] best 265 combination Uplifting [main] best 1301 combination zp[1]:2 [ main::i#2 main::i#1 ] zp[4]:7 [ main::addend#2 main::addend#1 ] zp[4]:3 [ main::sum#2 main::sum#1 ]
Uplifting [] best 265 combination Uplifting [] best 1301 combination
Attempting to uplift remaining variables inzp[1]:2 [ main::i#2 main::i#1 ]
Uplifting [main] best 1301 combination zp[1]:2 [ main::i#2 main::i#1 ]
ASSEMBLER BEFORE OPTIMIZATION ASSEMBLER BEFORE OPTIMIZATION
// File Comments // File Comments
// Tests compiling inline C65CE02/45GS02 Assembler // Test the 45GS02 CPU
// A program that uses 45GS02 instructions
// Upstart // Upstart
.cpu _45gs02 .cpu _45gs02
.pc = $801 "Basic" .pc = $801 "Basic"
:BasicUpstart(main) :BasicUpstart(main)
.pc = $80d "Program" .pc = $80d "Program"
// Global Constants & labels // Global Constants & labels
.label SCREEN = $400
// main // main
main: { main: {
// kickasm() {{ ldz #2 stz $0800 adcq ($2) }} .label sum = 3
ldz #2 .label addend = 7
stz $0800 .label i = 2
adcq ($2) // [1] phi from main to main::@1 [phi:main->main::@1]
__b1_from_main:
// [1] phi (dword) main::addend#2 = (dword) $1e240 [phi:main->main::@1#0] -- vduz1=vduc1
lda #<$1e240
sta.z addend
lda #>$1e240
sta.z addend+1
lda #<$1e240>>$10
sta.z addend+2
lda #>$1e240>>$10
sta.z addend+3
// [1] phi (dword) main::sum#2 = (dword) 0 [phi:main->main::@1#1] -- vduz1=vduc1
lda #<0
sta.z sum
lda #>0
sta.z sum+1
lda #<0>>$10
sta.z sum+2
lda #>0>>$10
sta.z sum+3
// [1] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#2] -- vbuz1=vbuc1
lda #0
sta.z i
jmp __b1
// main::@1
__b1:
// [2] if((byte) main::i#2<(byte) $64) goto main::@2 -- vbuz1_lt_vbuc1_then_la1
lda.z i
cmp #$64
bcc __b2
jmp __b3
// main::@3
__b3:
// [3] *((const dword*) SCREEN) ← (dword) main::sum#2 -- _deref_pduc1=vduz1
ldq.z sum
stq SCREEN
jmp __breturn jmp __breturn
// main::@return // main::@return
__breturn: __breturn:
// [1] return // [4] return
rts rts
// main::@2
__b2:
// [5] (dword) main::sum#1 ← (dword) main::sum#2 + (dword) main::addend#2 -- vduz1=vduz1_plus_vduz2
clc
ldq.z sum
adcq.z addend
stq.z sum
// [6] (dword) main::addend#1 ← (dword) main::addend#2 + (byte) main::i#2 -- vduz1=vduz1_plus_vbuz2
// will utilize ADQ/STQ
lda.z i
clc
adc.z addend
sta.z addend
lda.z addend+1
adc #0
sta.z addend+1
lda.z addend+2
adc #0
sta.z addend+2
lda.z addend+3
adc #0
sta.z addend+3
// [7] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuz1=_inc_vbuz1
inc.z i
// [1] phi from main::@2 to main::@1 [phi:main::@2->main::@1]
__b1_from___b2:
// [1] phi (dword) main::addend#2 = (dword) main::addend#1 [phi:main::@2->main::@1#0] -- register_copy
// [1] phi (dword) main::sum#2 = (dword) main::sum#1 [phi:main::@2->main::@1#1] -- register_copy
// [1] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@2->main::@1#2] -- register_copy
jmp __b1
} }
// File Data // File Data
ASSEMBLER OPTIMIZATIONS ASSEMBLER OPTIMIZATIONS
Removing instruction jmp __b1
Removing instruction jmp __b3
Removing instruction jmp __breturn Removing instruction jmp __breturn
Succesful ASM optimization Pass5NextJumpElimination Succesful ASM optimization Pass5NextJumpElimination
Removing instruction lda #>0
Succesful ASM optimization Pass5UnnecesaryLoadElimination
Removing instruction __b1_from_main:
Removing instruction __b3:
Removing instruction __breturn: Removing instruction __breturn:
Removing instruction __b1_from___b2:
Succesful ASM optimization Pass5UnusedLabelElimination Succesful ASM optimization Pass5UnusedLabelElimination
FINAL SYMBOL TABLE FINAL SYMBOL TABLE
(const dword*) SCREEN = (dword*) 1024
(void()) main() (void()) main()
(label) main::@1
(label) main::@2
(label) main::@3
(label) main::@return (label) main::@return
(dword) main::addend
(dword) main::addend#1 addend zp[4]:7 11.0
(dword) main::addend#2 addend zp[4]:7 11.0
(byte) main::i
(byte) main::i#1 i zp[1]:2 22.0
(byte) main::i#2 i zp[1]:2 11.0
(dword) main::sum
(dword) main::sum#1 sum zp[4]:3 7.333333333333333
(dword) main::sum#2 sum zp[4]:3 12.0
zp[1]:2 [ main::i#2 main::i#1 ]
zp[4]:3 [ main::sum#2 main::sum#1 ]
zp[4]:7 [ main::addend#2 main::addend#1 ]
FINAL ASSEMBLER FINAL ASSEMBLER
Score: 262 Score: 1218
// File Comments // File Comments
// Tests compiling inline C65CE02/45GS02 Assembler // Test the 45GS02 CPU
// A program that uses 45GS02 instructions
// Upstart // Upstart
.cpu _45gs02 .cpu _45gs02
.pc = $801 "Basic" .pc = $801 "Basic"
:BasicUpstart(main) :BasicUpstart(main)
.pc = $80d "Program" .pc = $80d "Program"
// Global Constants & labels // Global Constants & labels
.label SCREEN = $400
// main // main
main: { main: {
// kickasm .label sum = 3
// kickasm() {{ ldz #2 stz $0800 adcq ($2) }} .label addend = 7
ldz #2 .label i = 2
stz $0800 // [1] phi from main to main::@1 [phi:main->main::@1]
adcq ($2) // [1] phi (dword) main::addend#2 = (dword) $1e240 [phi:main->main::@1#0] -- vduz1=vduc1
lda #<$1e240
sta.z addend
lda #>$1e240
sta.z addend+1
lda #<$1e240>>$10
sta.z addend+2
lda #>$1e240>>$10
sta.z addend+3
// [1] phi (dword) main::sum#2 = (dword) 0 [phi:main->main::@1#1] -- vduz1=vduc1
lda #<0
sta.z sum
sta.z sum+1
lda #<0>>$10
sta.z sum+2
lda #>0>>$10
sta.z sum+3
// [1] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#2] -- vbuz1=vbuc1
lda #0
sta.z i
// main::@1
__b1:
// for(char i=0;i<100;i++)
// [2] if((byte) main::i#2<(byte) $64) goto main::@2 -- vbuz1_lt_vbuc1_then_la1
lda.z i
cmp #$64
bcc __b2
// main::@3
// *SCREEN = sum
// [3] *((const dword*) SCREEN) ← (dword) main::sum#2 -- _deref_pduc1=vduz1
ldq.z sum
stq SCREEN
// main::@return // main::@return
// } // }
// [1] return // [4] return
rts rts
// main::@2
__b2:
// sum += addend
// [5] (dword) main::sum#1 ← (dword) main::sum#2 + (dword) main::addend#2 -- vduz1=vduz1_plus_vduz2
clc
ldq.z sum
adcq.z addend
stq.z sum
// addend += i
// [6] (dword) main::addend#1 ← (dword) main::addend#2 + (byte) main::i#2 -- vduz1=vduz1_plus_vbuz2
// will utilize ADQ/STQ
lda.z i
clc
adc.z addend
sta.z addend
lda.z addend+1
adc #0
sta.z addend+1
lda.z addend+2
adc #0
sta.z addend+2
lda.z addend+3
adc #0
sta.z addend+3
// for(char i=0;i<100;i++)
// [7] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuz1=_inc_vbuz1
inc.z i
// [1] phi from main::@2 to main::@1 [phi:main::@2->main::@1]
// [1] phi (dword) main::addend#2 = (dword) main::addend#1 [phi:main::@2->main::@1#0] -- register_copy
// [1] phi (dword) main::sum#2 = (dword) main::sum#1 [phi:main::@2->main::@1#1] -- register_copy
// [1] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@2->main::@1#2] -- register_copy
jmp __b1
} }
// File Data // File Data

View File

@ -1,3 +1,19 @@
(const dword*) SCREEN = (dword*) 1024
(void()) main() (void()) main()
(label) main::@1
(label) main::@2
(label) main::@3
(label) main::@return (label) main::@return
(dword) main::addend
(dword) main::addend#1 addend zp[4]:7 11.0
(dword) main::addend#2 addend zp[4]:7 11.0
(byte) main::i
(byte) main::i#1 i zp[1]:2 22.0
(byte) main::i#2 i zp[1]:2 11.0
(dword) main::sum
(dword) main::sum#1 sum zp[4]:3 7.333333333333333
(dword) main::sum#2 sum zp[4]:3 12.0
zp[1]:2 [ main::i#2 main::i#1 ]
zp[4]:3 [ main::sum#2 main::sum#1 ]
zp[4]:7 [ main::addend#2 main::addend#1 ]