mirror of
https://gitlab.com/camelot/kickc.git
synced 2024-12-24 04:31:02 +00:00
Added support fro 45GS02 CPU addressing modes and instructions. Added a few 45GS02 optimized fragments.
This commit is contained in:
parent
1a436a67a3
commit
f27fe1a75c
@ -1,4 +1,4 @@
|
||||
//KICKC FRAGMENT CACHE 155084773d
|
||||
//KICKC FRAGMENT CACHE 15bc71afc6
|
||||
//FRAGMENT vbsz1=_deref_pbsc1
|
||||
lda {c1}
|
||||
sta {z1}
|
||||
|
44
src/main/fragment/cache/fragment-cache-mega45gs02.asm
vendored
Normal file
44
src/main/fragment/cache/fragment-cache-mega45gs02.asm
vendored
Normal 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}
|
@ -1,4 +1,4 @@
|
||||
//KICKC FRAGMENT CACHE 155084773d
|
||||
//KICKC FRAGMENT CACHE 15bc71afc6
|
||||
//FRAGMENT vbuz1=vbuc1
|
||||
lda #{c1}
|
||||
sta {z1}
|
||||
|
@ -1,4 +1,4 @@
|
||||
//KICKC FRAGMENT CACHE 155084773d
|
||||
//KICKC FRAGMENT CACHE 15bc71afc6
|
||||
//FRAGMENT vbuz1=vbuc1
|
||||
lda #{c1}
|
||||
sta {z1}
|
||||
|
@ -1,4 +1,4 @@
|
||||
//KICKC FRAGMENT CACHE 155084773d
|
||||
//KICKC FRAGMENT CACHE 15bc71afc6
|
||||
//FRAGMENT vbuz1=_deref_pbuc1
|
||||
lda {c1}
|
||||
sta {z1}
|
||||
|
@ -0,0 +1,2 @@
|
||||
ldq {m1}
|
||||
stq {c1}
|
@ -0,0 +1,4 @@
|
||||
clc
|
||||
ldq {m1}
|
||||
adcq {m2}
|
||||
stq {m1}
|
@ -1,13 +1,16 @@
|
||||
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.
|
||||
*/
|
||||
public class Cpu65xx {
|
||||
|
||||
/** The CPU name. */
|
||||
/** The CPU name. */
|
||||
private final String name;
|
||||
|
||||
/** All opcodes in the instruction set. */
|
||||
@ -40,8 +43,19 @@ public class Cpu65xx {
|
||||
* @param cycles The number of cycles
|
||||
*/
|
||||
protected void addOpcode(int opcode, String mnemonic, CpuAddressingMode addressingMode, double cycles, String clobberString) {
|
||||
CpuOpcode cpuOpcode = new CpuOpcode(opcode, mnemonic, addressingMode, cycles, clobberString);
|
||||
addOpcode(cpuOpcode);
|
||||
addOpcode(new int[opcode], mnemonic, addressingMode, cycles, clobberString);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -26,8 +26,8 @@ public class CpuOpcode {
|
||||
/** Which registers/flags of the CPU are clobbered by the instruction. */
|
||||
private final CpuClobber clobber;
|
||||
|
||||
CpuOpcode(int opcode, String mnemonic, CpuAddressingMode addressingMode, double cycles, String clobberString) {
|
||||
this.opcode = new int[]{opcode};
|
||||
CpuOpcode(int[] opcode, String mnemonic, CpuAddressingMode addressingMode, double cycles, String clobberString) {
|
||||
this.opcode = opcode;
|
||||
this.mnemonic = mnemonic;
|
||||
this.addressingMode = addressingMode;
|
||||
this.cycles = cycles;
|
||||
|
@ -1,6 +1,7 @@
|
||||
package dk.camelot64.cpufamily6502.cpus;
|
||||
|
||||
import dk.camelot64.cpufamily6502.Cpu65xx;
|
||||
import dk.camelot64.cpufamily6502.CpuAddressingMode;
|
||||
|
||||
/**
|
||||
* The 45GS02 instruction set.
|
||||
@ -16,8 +17,88 @@ public class Cpu45GS02 extends Cpu65xx {
|
||||
|
||||
public Cpu45GS02() {
|
||||
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?
|
||||
}
|
||||
|
||||
|
@ -338,7 +338,7 @@ public class AsmFragmentInstance {
|
||||
String operand1 = param1 == null ? null : param1.getParam();
|
||||
String operand2 = param2 == null ? null : param2.getParam();
|
||||
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);
|
||||
}
|
||||
|
@ -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' |
|
||||
'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' |
|
||||
'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 : '#' ;
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
@ -42,6 +42,11 @@ public class TestPrograms {
|
||||
public TestPrograms() {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCpu45GS02AddressingModes() throws IOException, URISyntaxException {
|
||||
compileAndCompare("cpu-45gs02-addressing-modes.c");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCpu65CE02AddressingModes() throws IOException, URISyntaxException {
|
||||
compileAndCompare("cpu-65ce02-addressing-modes.c");
|
||||
@ -58,13 +63,13 @@ public class TestPrograms {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMega65C65ce02() throws IOException, URISyntaxException {
|
||||
public void testCpu45GS02() throws IOException, URISyntaxException {
|
||||
compileAndCompare("cpu-45gs02.c");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCpu65CE02() throws IOException, URISyntaxException {
|
||||
compileAndCompare("cpu-65ce02.c", log());
|
||||
compileAndCompare("cpu-65ce02.c");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
57
src/test/kc/cpu-45gs02-addressing-modes.c
Normal file
57
src/test/kc/cpu-45gs02-addressing-modes.c
Normal 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 };
|
@ -1,11 +1,16 @@
|
||||
// Tests compiling inline C65CE02/45GS02 Assembler
|
||||
// Test the 45GS02 CPU
|
||||
// A program that uses 45GS02 instructions
|
||||
|
||||
#pragma cpu(MEGA45GS02)
|
||||
|
||||
unsigned long* SCREEN = 0x0400;
|
||||
|
||||
void main() {
|
||||
kickasm {{
|
||||
ldz #2
|
||||
stz $0800
|
||||
adcq ($2)
|
||||
}}
|
||||
unsigned long sum = 0;
|
||||
unsigned long addend = 123456;
|
||||
for(char i=0;i<100;i++) {
|
||||
sum += addend; // will utilize ADQ/STQ
|
||||
addend += i;
|
||||
}
|
||||
*SCREEN = sum; // will utilize LDQ/STQ
|
||||
}
|
@ -37,19 +37,6 @@ void main() {
|
||||
lbl2:
|
||||
// 65C02: ($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))
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -45,13 +45,6 @@ void main() {
|
||||
lbl2:
|
||||
// 65C02: ($1234,X)
|
||||
jmp ($1234,x)
|
||||
|
||||
// TODO Indirect Long,Z
|
||||
//lda (($12)),z
|
||||
|
||||
// TODO Indirect Long
|
||||
//lda (($12))
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
35
src/test/ref/cpu-45gs02-addressing-modes.asm
Normal file
35
src/test/ref/cpu-45gs02-addressing-modes.asm
Normal 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
|
8
src/test/ref/cpu-45gs02-addressing-modes.cfg
Normal file
8
src/test/ref/cpu-45gs02-addressing-modes.cfg
Normal 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
|
218
src/test/ref/cpu-45gs02-addressing-modes.log
Normal file
218
src/test/ref/cpu-45gs02-addressing-modes.log
Normal 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
|
||||
|
4
src/test/ref/cpu-45gs02-addressing-modes.sym
Normal file
4
src/test/ref/cpu-45gs02-addressing-modes.sym
Normal file
@ -0,0 +1,4 @@
|
||||
(const byte*) far[] = { (byte) $60 }
|
||||
(void()) main()
|
||||
(label) main::@return
|
||||
|
@ -1,14 +1,63 @@
|
||||
// Tests compiling inline C65CE02/45GS02 Assembler
|
||||
// Test the 45GS02 CPU
|
||||
// A program that uses 45GS02 instructions
|
||||
.cpu _45gs02
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
.label SCREEN = $400
|
||||
main: {
|
||||
// kickasm
|
||||
ldz #2
|
||||
stz $0800
|
||||
adcq ($2)
|
||||
|
||||
.label sum = 3
|
||||
.label addend = 7
|
||||
.label i = 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
|
||||
__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
|
||||
}
|
||||
|
@ -1,11 +1,22 @@
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from
|
||||
kickasm() {{ ldz #2
|
||||
stz $0800
|
||||
adcq ($2)
|
||||
}}
|
||||
[0] phi()
|
||||
to:main::@1
|
||||
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
|
||||
main::@return: scope:[main] from main
|
||||
[1] return
|
||||
main::@return: scope:[main] from main::@3
|
||||
[4] 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
|
||||
|
@ -1,157 +1,497 @@
|
||||
Inlined call call __init
|
||||
|
||||
CONTROL FLOW GRAPH SSA
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from __start
|
||||
kickasm() {{ ldz #2
|
||||
stz $0800
|
||||
adcq ($2)
|
||||
}}
|
||||
main: scope:[main] from __start::@1
|
||||
(dword) main::sum#0 ← (dword) 0
|
||||
(dword) main::addend#0 ← (dword) $1e240
|
||||
(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
|
||||
main::@return: scope:[main] from main
|
||||
main::@return: scope:[main] from main::@3
|
||||
return
|
||||
to:@return
|
||||
|
||||
(void()) __start()
|
||||
__start: scope:[__start] from
|
||||
call main
|
||||
to:__start::__init1
|
||||
__start::__init1: scope:[__start] from __start
|
||||
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
|
||||
__start::@return: scope:[__start] from __start::@1
|
||||
__start::@return: scope:[__start] from __start::@2
|
||||
return
|
||||
to:@return
|
||||
|
||||
SYMBOL TABLE SSA
|
||||
(const dword*) SCREEN = (dword*)(number) $400
|
||||
(void()) __start()
|
||||
(label) __start::@1
|
||||
(label) __start::@2
|
||||
(label) __start::@return
|
||||
(label) __start::__init1
|
||||
(void()) main()
|
||||
(bool~) main::$0
|
||||
(label) main::@1
|
||||
(label) main::@2
|
||||
(label) main::@3
|
||||
(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 block __start
|
||||
Removing unused procedure block __start::__init1
|
||||
Removing unused procedure block __start::@1
|
||||
Removing unused procedure block __start::@2
|
||||
Removing unused procedure block __start::@return
|
||||
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
|
||||
|
||||
Created 0 initial phi equivalence classes
|
||||
Coalesced down to 0 phi equivalence classes
|
||||
Created 3 initial 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
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from
|
||||
kickasm() {{ ldz #2
|
||||
stz $0800
|
||||
adcq ($2)
|
||||
}}
|
||||
[0] phi()
|
||||
to:main::@1
|
||||
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
|
||||
main::@return: scope:[main] from main
|
||||
[1] return
|
||||
main::@return: scope:[main] from main::@3
|
||||
[4] 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
|
||||
(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
|
||||
[ main::i#2 main::i#1 ]
|
||||
[ main::sum#2 main::sum#1 ]
|
||||
[ main::addend#2 main::addend#1 ]
|
||||
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
|
||||
Target platform is c64basic / MEGA45GS02
|
||||
// File Comments
|
||||
// Tests compiling inline C65CE02/45GS02 Assembler
|
||||
// Test the 45GS02 CPU
|
||||
// A program that uses 45GS02 instructions
|
||||
// Upstart
|
||||
.cpu _45gs02
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
// main
|
||||
main: {
|
||||
// kickasm() {{ ldz #2 stz $0800 adcq ($2) }}
|
||||
ldz #2
|
||||
stz $0800
|
||||
adcq ($2)
|
||||
|
||||
.label sum = 3
|
||||
.label addend = 7
|
||||
.label i = 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
|
||||
// main::@return
|
||||
__breturn:
|
||||
// [1] return
|
||||
// [4] return
|
||||
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
|
||||
|
||||
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
|
||||
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 []
|
||||
|
||||
Uplifting [main] best 265 combination
|
||||
Uplifting [] 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 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
|
||||
// File Comments
|
||||
// Tests compiling inline C65CE02/45GS02 Assembler
|
||||
// Test the 45GS02 CPU
|
||||
// A program that uses 45GS02 instructions
|
||||
// Upstart
|
||||
.cpu _45gs02
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
// main
|
||||
main: {
|
||||
// kickasm() {{ ldz #2 stz $0800 adcq ($2) }}
|
||||
ldz #2
|
||||
stz $0800
|
||||
adcq ($2)
|
||||
|
||||
.label sum = 3
|
||||
.label addend = 7
|
||||
.label i = 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
|
||||
// main::@return
|
||||
__breturn:
|
||||
// [1] return
|
||||
// [4] return
|
||||
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
|
||||
|
||||
ASSEMBLER OPTIMIZATIONS
|
||||
Removing instruction jmp __b1
|
||||
Removing instruction jmp __b3
|
||||
Removing instruction jmp __breturn
|
||||
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 __b1_from___b2:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
|
||||
FINAL SYMBOL TABLE
|
||||
(const dword*) SCREEN = (dword*) 1024
|
||||
(void()) main()
|
||||
(label) main::@1
|
||||
(label) main::@2
|
||||
(label) main::@3
|
||||
(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
|
||||
Score: 262
|
||||
Score: 1218
|
||||
|
||||
// File Comments
|
||||
// Tests compiling inline C65CE02/45GS02 Assembler
|
||||
// Test the 45GS02 CPU
|
||||
// A program that uses 45GS02 instructions
|
||||
// Upstart
|
||||
.cpu _45gs02
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
// main
|
||||
main: {
|
||||
// kickasm
|
||||
// kickasm() {{ ldz #2 stz $0800 adcq ($2) }}
|
||||
ldz #2
|
||||
stz $0800
|
||||
adcq ($2)
|
||||
|
||||
.label sum = 3
|
||||
.label addend = 7
|
||||
.label i = 2
|
||||
// [1] phi from main to main::@1 [phi:main->main::@1]
|
||||
// [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
|
||||
// }
|
||||
// [1] return
|
||||
// [4] return
|
||||
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
|
||||
|
||||
|
@ -1,3 +1,19 @@
|
||||
(const dword*) SCREEN = (dword*) 1024
|
||||
(void()) main()
|
||||
(label) main::@1
|
||||
(label) main::@2
|
||||
(label) main::@3
|
||||
(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 ]
|
||||
|
Loading…
Reference in New Issue
Block a user