1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2025-01-11 20:30:08 +00:00

Added support for clobber, registers, addressing modes and instructions in the 65CE02 instruction set.

This commit is contained in:
jespergravgaard 2020-07-29 23:52:38 +02:00
parent 1881fb17d0
commit 96cabc382f
15 changed files with 1128 additions and 637 deletions

View File

@ -5,44 +5,77 @@ import java.io.Serializable;
/** Information about what registers/flags of the CPU an ASM instruction clobbers */
public class CpuClobber implements Serializable {
public static final CpuClobber CLOBBER_ALL = new CpuClobber(true, true, true, true, true, true, true, true, true, true, true);
public static final CpuClobber CLOBBER_ALL = new CpuClobber(true, true, true, true, true, true, true, true, true, true, true, true, true, true);
public static final CpuClobber CLOBBER_NONE = new CpuClobber(false, false, false, false, false, false, false, false, false, false, false, false, false, false);
/** True if the A register is modified. */
final boolean registerA;
/** True if the X register is modified. */
final boolean registerX;
/** True if the Y register is modified. */
final boolean registerY;
/** True if the Z register is modified. (65ce02+). */
final boolean registerZ;
/** True if the carry flag is modified. */
final boolean flagC;
/** True if the negative flag is modified. */
final boolean flagN;
/** true if the zero (equals) flag is modified. */
final boolean flagZ;
/** True if the overflow flag is modified. */
final boolean flagV;
/** True if the interrupt flag is modified. */
final boolean flagI;
/** True if the decimal flag is modified. */
final boolean flagD;
/** True if the disable extended stack flag is modified. */
final boolean flagE;
/** true if the program counter is modified (not just incremented to the next instruction). */
final boolean registerPC;
/** true if the stack pointer is modified.*/
/** true if the stack pointer is modified. */
final boolean registerSP;
/** true if the base page register is modified. (65ce02+)*/
final boolean registerBP;
public CpuClobber(boolean registerA, boolean registerX, boolean registerY, boolean flagC, boolean flagN, boolean flagZ, boolean flagV, boolean flagI, boolean flagD, boolean registerPC, boolean registerSP) {
public CpuClobber(boolean registerA, boolean registerX, boolean registerY, boolean registerZ, boolean flagC, boolean flagN, boolean flagZ, boolean flagV, boolean flagI, boolean flagD, boolean flagE, boolean registerPC, boolean registerSP, boolean registerBP) {
this.registerA = registerA;
this.registerX = registerX;
this.registerY = registerY;
this.registerZ = registerZ;
this.flagC = flagC;
this.flagN = flagN;
this.flagZ = flagZ;
this.flagV = flagV;
this.flagI = flagI;
this.flagD = flagD;
this.flagE = flagE;
this.registerPC = registerPC;
this.registerSP = registerSP;
}
public CpuClobber() {
this(false, false, false, false, false, false, false, false, false, false, false);
this.registerBP = registerBP;
}
/**
* Create clobber from a string containing the names of the clobbered registers/flags.
* Registers are upper-case and flags are lower-case. (This is because the 65C02 has both a "Z" register and a "Z" flag. )
* EG. "AXcz" means that the A and X registers a and the carry and zero flags are clobbered.
* Here is the meaning of each name usable in the string
* <ul>
* <li> <b>A</b> A register </li>
* <li> <b>X</b> X register </li>
* <li> <b>Y</b> Y register </li>
* <li> <b>Z</b> Z register </li>
* <li> <b>c</b> carry flag </li>
* <li> <b>v</b> overflow flag </li>
* <li> <b>z</b> zero flag </li>
* <li> <b>n</b> negative flag </li>
* <li> <b>i</b> interrupt flag </li>
* <li> <b>d</b> decimal flag </li>
* <li> <b>e</b> extended stack disable flag </li>
* <li> <b>S</b> stack pointer </li>
* <li> <b>B</b> base page register is modified. </li>
* <li> <b>P</b> program counter is modified (not just incremented to the next instruction). </li>
* </ul>
*
* @param clobberString The clobber string.
*/
@ -51,14 +84,17 @@ public class CpuClobber implements Serializable {
clobberString.contains("A"),
clobberString.contains("X"),
clobberString.contains("Y"),
clobberString.contains("Z"),
clobberString.contains("c"),
clobberString.contains("n"),
clobberString.contains("z"),
clobberString.contains("v"),
clobberString.contains("i"),
clobberString.contains("d"),
clobberString.contains("e"),
clobberString.contains("P"),
clobberString.contains("S")
clobberString.contains("S"),
clobberString.contains("B")
);
}
@ -73,17 +109,38 @@ public class CpuClobber implements Serializable {
clobber1.registerA | clobber2.registerA,
clobber1.registerX | clobber2.registerX,
clobber1.registerY | clobber2.registerY,
clobber1.registerZ | clobber2.registerZ,
clobber1.flagC | clobber2.flagC,
clobber1.flagN | clobber2.flagN,
clobber1.flagZ | clobber2.flagZ,
clobber1.flagV | clobber2.flagV,
clobber1.flagI | clobber2.flagI,
clobber1.flagD | clobber2.flagD,
clobber1.flagE | clobber2.flagE,
clobber1.registerPC | clobber2.registerPC,
clobber1.registerSP | clobber2.registerSP
clobber1.registerSP | clobber2.registerSP,
clobber1.registerBP | clobber2.registerBP
);
}
private String toClobberString() {
return
(registerA ? "A" : "") +
(registerX ? "X" : "") +
(registerY ? "Y" : "") +
(registerZ ? "Z" : "") +
(flagC ? "c" : "") +
(flagN ? "n" : "") +
(flagZ ? "z" : "") +
(flagV ? "v" : "") +
(flagI ? "i" : "") +
(flagD ? "d" : "") +
(flagE ? "e" : "") +
(registerPC ? "P" : "") +
(registerSP ? "S" : "") +
(registerBP ? "B" : "") ;
}
public boolean isRegisterA() {
return registerA;
@ -97,6 +154,10 @@ public class CpuClobber implements Serializable {
return registerY;
}
public boolean isRegisterZ() {
return registerY;
}
public boolean isFlagC() {
return flagC;
}
@ -121,6 +182,10 @@ public class CpuClobber implements Serializable {
return flagD;
}
public boolean isFlagE() {
return flagE;
}
public boolean isRegisterPC() {
return registerPC;
}
@ -129,21 +194,13 @@ public class CpuClobber implements Serializable {
return registerSP;
}
public boolean isRegisterBP() {
return registerBP;
}
@Override
public String toString() {
return
(registerA ? "A" : "") +
(registerX ? "X" : "") +
(registerY ? "Y" : "") +
(flagC ? "c" : "") +
(flagN ? "n" : "") +
(flagZ ? "z" : "") +
(flagV ? "v" : "") +
(flagI ? "i" : "") +
(flagD ? "d" : "") +
(registerPC ? "P" : "") +
(registerSP ? "S" : "") ;
return toClobberString();
}
}

View File

@ -65,12 +65,10 @@ public class Cpu65C02 extends Cpu65xx {
addOpcode(0xB7,"smb3", CpuAddressingMode.ZP,5,"");
addOpcode(0xBF,"bbs3", CpuAddressingMode.REZ,5,"");
addOpcode(0xC7,"smb4", CpuAddressingMode.ZP,5,"");
addOpcode(0xCB,"wai", CpuAddressingMode.NON,3,"");
addOpcode(0xCF,"bbs4", CpuAddressingMode.REZ,5,"");
addOpcode(0xD2,"cmp", CpuAddressingMode.INZ,5,"cnz");
addOpcode(0xD7,"smb5", CpuAddressingMode.ZP,5,"");
addOpcode(0xDA,"phx", CpuAddressingMode.NON,3,"");
addOpcode(0xDB,"stp", CpuAddressingMode.NON,3,"");
addOpcode(0xDF,"bbs5", CpuAddressingMode.REZ,5,"");
addOpcode(0xE7,"smb6", CpuAddressingMode.ZP,5,"");
addOpcode(0xEF,"bbs6", CpuAddressingMode.REZ,5,"");
@ -79,7 +77,12 @@ public class Cpu65C02 extends Cpu65xx {
addOpcode(0xFA,"plx", CpuAddressingMode.NON,4,"Xnz");
addOpcode(0xFF,"bbs7", CpuAddressingMode.REZ,5,"");
// TODO: Cycle differences for ASL LSR ROL ROR abs,X - http://6502.org/tutorials/65c02opcodes.html
// TODO: Cycle differences for ASL LSR ROL ROR abs,X - http://6502.org/tutorials/65c02opcodes.html
// TODO: Maybe add the 65C02S CPU - which adds the following 2 instructions
//addOpcode(0xCB,"wai", CpuAddressingMode.NON,3,"");
//addOpcode(0xDB,"stp", CpuAddressingMode.NON,3,"");
}
}

View File

@ -1,6 +1,7 @@
package dk.camelot64.cpufamily6502.cpus;
import dk.camelot64.cpufamily6502.Cpu65xx;
import dk.camelot64.cpufamily6502.CpuAddressingMode;
/**
* The 65CE02 instruction set.
@ -16,7 +17,64 @@ public class Cpu65CE02 extends Cpu65xx {
public Cpu65CE02() {
super(NAME, Cpu65C02.INSTANCE);
// TODO: Add 65CE02 instructions
addOpcode(0x2, "cle", CpuAddressingMode.NON, 2, "e");
addOpcode(0x3, "see", CpuAddressingMode.NON, 2, "e");
addOpcode(0xB, "tsy", CpuAddressingMode.NON, 1, "Ynz");
addOpcode(0x12, "ora", CpuAddressingMode.IZZ, 5, "Anz");
addOpcode(0x13, "lbpl", CpuAddressingMode.REL, 3, "P");
addOpcode(0x1B, "inz", CpuAddressingMode.NON, 1, "Znz");
addOpcode(0x22, "jsr", CpuAddressingMode.IND, 7, "PS");
addOpcode(0x23, "jsr", CpuAddressingMode.IAX, 7, "PS");
addOpcode(0x2B, "tys", CpuAddressingMode.NON, 1, "S");
addOpcode(0x32, "and", CpuAddressingMode.IZZ, 5, "Anz");
addOpcode(0x33, "lbmi", CpuAddressingMode.REL, 3, "P");
addOpcode(0x3B, "dez", CpuAddressingMode.NON, 1, "Znz");
addOpcode(0x42, "neg", CpuAddressingMode.NON, 2, "Anz");
addOpcode(0x43, "asr", CpuAddressingMode.NON, 2, "Anzc");
addOpcode(0x44, "asr", CpuAddressingMode.ZP, 4, "nzc");
addOpcode(0x4B, "taz", CpuAddressingMode.NON, 1, "Znz");
addOpcode(0x52, "eor", CpuAddressingMode.IZZ, 5, "Anz");
addOpcode(0x53, "lbvc", CpuAddressingMode.REL, 3, "P");
addOpcode(0x54, "asr", CpuAddressingMode.ZPX, 4, "nzc");
addOpcode(0x5B, "tab", CpuAddressingMode.NON, 1, "B");
addOpcode(0x5C, "map", CpuAddressingMode.NON, 2, "");
addOpcode(0x62, "rtn", CpuAddressingMode.IMM, 7, "P");
addOpcode(0x63, "lbsr", CpuAddressingMode.REL, 3, "P");
addOpcode(0x6B, "tza", CpuAddressingMode.NON, 1, "Anz");
addOpcode(0x72, "adc", CpuAddressingMode.IZZ, 5, "Anzvc");
addOpcode(0x73, "lbvs", CpuAddressingMode.REL, 3, "P");
addOpcode(0x7B, "tba", CpuAddressingMode.NON, 1, "Anz");
addOpcode(0x82, "sta", CpuAddressingMode.ISY, 6, "");
addOpcode(0x83, "lbra", CpuAddressingMode.REL, 3, "P");
addOpcode(0x8B, "sty", CpuAddressingMode.ABS, 4, "");
addOpcode(0x92, "sta", CpuAddressingMode.IZZ, 5, "");
addOpcode(0x93, "lbcc", CpuAddressingMode.REL, 3, "P");
addOpcode(0x9B, "stx", CpuAddressingMode.ABS, 4, "");
addOpcode(0xA3, "ldz", CpuAddressingMode.IMM, 2, "Znz");
addOpcode(0xAB, "ldz", CpuAddressingMode.ABS, 4, "Znz");
addOpcode(0xB2, "lda", CpuAddressingMode.IZZ, 5, "Anz");
addOpcode(0xB3, "lbcs", CpuAddressingMode.REL, 3, "P");
addOpcode(0xBB, "ldz", CpuAddressingMode.ABS, 4, "Znz");
addOpcode(0xC2, "cpz", CpuAddressingMode.IMM, 2, "nzc");
addOpcode(0xC3, "dew", CpuAddressingMode.ABS, 5, "nz");
addOpcode(0xCB, "asw", CpuAddressingMode.ABS, 7, "nzc");
addOpcode(0xD2, "cmp", CpuAddressingMode.IZZ, 5, "nzc");
addOpcode(0xD3, "lbne", CpuAddressingMode.REL, 3, "P");
addOpcode(0xD4, "cpz", CpuAddressingMode.ZP, 3, "nzc");
addOpcode(0xDB, "phz", CpuAddressingMode.NON, 3, "S");
addOpcode(0xDC, "cpz", CpuAddressingMode.ABS, 4, "nzc");
addOpcode(0xE2, "lda", CpuAddressingMode.ISY, 6, "Anz");
addOpcode(0xE3, "inw", CpuAddressingMode.ABS, 5, "nz");
addOpcode(0xEA, "eom", CpuAddressingMode.NON, 1, "");
addOpcode(0xEB, "row", CpuAddressingMode.ABS, 6, "nzc");
addOpcode(0xF2, "sbc", CpuAddressingMode.IZZ, 5, "Anzcv");
addOpcode(0xF3, "lbeq", CpuAddressingMode.REL, 3, "P");
addOpcode(0xF4, "phw", CpuAddressingMode.IMM, 5, "S");
addOpcode(0xFB, "plz", CpuAddressingMode.NON, 3, "ZnzS");
addOpcode(0xFC, "phw", CpuAddressingMode.ABS, 7, "S");
// TODO: Instruction Cycle changes on 65CE02
}
}

View File

@ -174,7 +174,7 @@ public class AsmChunk {
if(clobberOverwrite != null) {
return clobberOverwrite;
}
CpuClobber chunkClobber = new CpuClobber();
CpuClobber chunkClobber = CpuClobber.CLOBBER_NONE;
for(AsmLine line : lines) {
if(line instanceof AsmInstruction) {
AsmInstruction asmInstruction = (AsmInstruction) line;

View File

@ -229,7 +229,7 @@ public class AsmProgram {
* @return The clobbered registers
*/
public CpuClobber getClobber() {
CpuClobber programClobber = new CpuClobber();
CpuClobber programClobber = CpuClobber.CLOBBER_NONE;
for(AsmChunk chunk : chunks) {
programClobber = new CpuClobber(programClobber, chunk.getClobber());
}

View File

@ -176,7 +176,8 @@ ASM_MNEMONIC:
'cpy' | 'cmp' | 'cpx' | 'dcp' | 'dec' | 'inc' | 'axs' | 'bne' | 'cld' | 'sbc' | 'isc' | 'inx' | 'beq' | 'sed' | 'dex' | 'iny' | 'ror' | 'bbr0'| 'bbr1'|
'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'
'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'
;
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

@ -70,7 +70,7 @@ public class Pass4InterruptClobberFix extends Pass2Base {
private CpuClobber getProcedureClobber(Procedure procedure) {
AsmProgram asm = getProgram().getAsm();
CpuClobber procClobber = new CpuClobber();
CpuClobber procClobber = CpuClobber.CLOBBER_NONE;
for(AsmChunk asmChunk : asm.getChunks()) {
if(procedure.getFullName().equals(asmChunk.getScopeLabel())) {
if(asmChunk.getSource().contains(Procedure.InterruptType.HARDWARE_CLOBBER.name())) {

View File

@ -42,6 +42,11 @@ public class TestPrograms {
public TestPrograms() {
}
@Test
public void testCpu65CE02AddressingModes() throws IOException, URISyntaxException {
compileAndCompare("cpu-65ce02-addressing-modes.c");
}
@Test
public void testCpu65C02AddressingModes() throws IOException, URISyntaxException {
compileAndCompare("cpu-65c02-addressing-modes.c");

View File

@ -0,0 +1,61 @@
// Tests the different ASM addressing modes
#pragma cpu(csg65ce02)
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)
// TODO Indirect Long,Z
//lda (($12)),z
// TODO Indirect Long
//lda (($12))
}
}
__address(0x2000) char far[] = { 0x60 };

View File

@ -0,0 +1,31 @@
// Tests the different ASM addressing modes
.cpu _65ce02
.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)
// }
}
.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) }
to:main::@return
main::@return: scope:[main] from main
[1] return
to:@return

View File

@ -0,0 +1,210 @@
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) }
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) }
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 / CSG65CE02
// File Comments
// Tests the different ASM addressing modes
// Upstart
.cpu _65ce02
.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) }
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)
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) } always clobbers reg byte a reg byte x
REGISTER UPLIFT SCOPES
Uplift Scope [main]
Uplift Scope []
Uplifting [main] best 86 combination
Uplifting [] best 86 combination
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
// Tests the different ASM addressing modes
// Upstart
.cpu _65ce02
.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) }
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)
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
Removing unreachable instruction rts
Succesful ASM optimization Pass5UnreachableCodeElimination
FINAL SYMBOL TABLE
(const byte*) far[] = { (byte) $60 }
(void()) main()
(label) main::@return
FINAL ASSEMBLER
Score: 77
// File Comments
// Tests the different ASM addressing modes
// Upstart
.cpu _65ce02
.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) }
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)
// main::@return
// }
// [1] return
}
// File Data
.pc = $2000 "far"
far: .byte $60

View File

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