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

Now the ASM generation uses the instruction set of the declared CPU. Added support for addressing modes and instructions in the 65C02 instruction set.

This commit is contained in:
jespergravgaard 2020-07-28 22:40:24 +02:00
parent ba9f99059a
commit 1881fb17d0
52 changed files with 1163 additions and 1064 deletions

View File

@ -1,69 +0,0 @@
package dk.camelot64.cpufamily6502;
import java.util.*;
/**
* A 6502 family CPU. The CPU has an instruction set.
*/
public class AsmCpu {
/** The CPU name. */
private final String name;
/** All opcodes in the instruction set. */
private final List<AsmOpcode> allOpcodes;
/** Maps mnemonic_addressingMode to the instruction opcode */
private final Map<String, AsmOpcode> opcodesByMnemonicAddrMode;
public AsmCpu(String name) {
this.name = name;
this.allOpcodes = new ArrayList<>();
this.opcodesByMnemonicAddrMode = new LinkedHashMap<>();
}
public AsmCpu(String name, AsmCpu basedOn) {
this.name = name;
this.allOpcodes = new ArrayList<>();
this.opcodesByMnemonicAddrMode = new LinkedHashMap<>();
for(AsmOpcode opcode : basedOn.allOpcodes) {
addOpcode(opcode);
}
}
/**
* Get a specific instruction opcode form the instruction set
*
* @param mnemonic The mnemonic
* @param addressingMode The addressing mode
* @return The opcode, if is exists. Null if the instruction set does not have the opcode.
*/
private AsmOpcode getOpcode(String mnemonic, AsmAddressingMode addressingMode) {
String key = mnemonic.toLowerCase() + "_" + addressingMode.getName();
return opcodesByMnemonicAddrMode.get(key);
}
/**
* Add an instruction opcode to the instruction set.
*
* @param opcode The numeric opcode
* @param mnemonic The lower case mnemonic
* @param addressingMode The addressing mode
* @param cycles The number of cycles
*/
protected void addOpcode(int opcode, String mnemonic, AsmAddressingMode addressingMode, double cycles, String clobberString) {
AsmOpcode asmOpcode = new AsmOpcode(opcode, mnemonic, addressingMode, cycles, clobberString);
addOpcode(asmOpcode);
}
/**
* Add an instruction opcode to the instruction set.
*
* @param opcode The opcode to add
*/
private void addOpcode(AsmOpcode asmOpcode) {
allOpcodes.add(asmOpcode);
opcodesByMnemonicAddrMode.put(asmOpcode.getMnemonic() + "_" + asmOpcode.getAddressingMode().getName(), asmOpcode);
}
}

View File

@ -1,349 +0,0 @@
package dk.camelot64.cpufamily6502;
import java.util.*;
/**
* The set of all 6502 assembler instructions
*/
public class AsmInstructionSet {
private static AsmInstructionSet set = new AsmInstructionSet();
/** All instructions in the instruction set. */
private List<AsmOpcode> instructions;
/** Maps mnemonic_addressingMode to the instruction opcode information */
private Map<String, AsmOpcode> instructionsMap;
public AsmInstructionSet() {
this.instructions = new ArrayList<>();
this.instructionsMap = new HashMap<>();
add(0x00, "brk", AsmAddressingMode.NON, 7.0, "");
add(0x01, "ora", AsmAddressingMode.IZX, 6.0, "Azn");
add(0x01, "ora", AsmAddressingMode.IZX, 6.0, "Azn");
add(0x02, "kil", AsmAddressingMode.NON, 0.0, "");
add(0x03, "slo", AsmAddressingMode.IZX, 8.0, "Aczn");
add(0x04, "nop", AsmAddressingMode.ZP, 3.0, "");
add(0x05, "ora", AsmAddressingMode.ZP, 3.0, "Azn");
add(0x06, "asl", AsmAddressingMode.ZP, 5.0, "czn");
add(0x07, "slo", AsmAddressingMode.ZP, 5.0, "Aczn");
add(0x08, "php", AsmAddressingMode.NON, 3.0, "S");
add(0x09, "ora", AsmAddressingMode.IMM, 2.0, "Azn");
add(0x0a, "asl", AsmAddressingMode.NON, 2.0, "Aczn");
add(0x0b, "anc", AsmAddressingMode.IMM, 2.0, "Aczn");
add(0x0c, "nop", AsmAddressingMode.ABS, 4.0, "");
add(0x0d, "ora", AsmAddressingMode.ABS, 4.0, "Azn");
add(0x0e, "asl", AsmAddressingMode.ABS, 6.0, "czn");
add(0x0f, "slo", AsmAddressingMode.ABS, 6.0, "Aczn");
add(0x10, "bpl", AsmAddressingMode.REL, 2.5, "P");
add(0x11, "ora", AsmAddressingMode.IZY, 5.5, "Azn");
add(0x12, "kil", AsmAddressingMode.NON, 0.0, "");
add(0x13, "slo", AsmAddressingMode.IZY, 8.0, "Aczn");
add(0x14, "nop", AsmAddressingMode.ZPX, 4.0, "");
add(0x15, "ora", AsmAddressingMode.ZPX, 4.0, "Azn");
add(0x16, "asl", AsmAddressingMode.ZPX, 6.0, "czn");
add(0x17, "slo", AsmAddressingMode.ZPX, 6.0, "Aczn");
add(0x18, "clc", AsmAddressingMode.NON, 2.0, "c");
add(0x19, "ora", AsmAddressingMode.ABY, 4.5, "Azn");
add(0x1a, "nop", AsmAddressingMode.NON, 2.0, "");
add(0x1b, "slo", AsmAddressingMode.ABY, 7.0, "Aczn");
add(0x1c, "nop", AsmAddressingMode.ABX, 4.5, "");
add(0x1d, "ora", AsmAddressingMode.ABX, 4.5, "Azn");
add(0x1e, "asl", AsmAddressingMode.ABX, 7.0, "czn");
add(0x1f, "slo", AsmAddressingMode.ABX, 7.0, "Aczn");
add(0x20, "jsr", AsmAddressingMode.ABS, 6.0, "PS");
add(0x21, "and", AsmAddressingMode.IZX, 6.0, "Azn");
add(0x22, "kil", AsmAddressingMode.NON, 0.0, "");
add(0x23, "rla", AsmAddressingMode.IZX, 8.0, "Aczn");
add(0x24, "bit", AsmAddressingMode.ZP, 3.0, "vzn");
add(0x25, "and", AsmAddressingMode.ZP, 3.0, "Azn");
add(0x26, "rol", AsmAddressingMode.ZP, 5.0, "czn");
add(0x27, "rla", AsmAddressingMode.ZP, 5.0, "Aczn");
add(0x28, "plp", AsmAddressingMode.NON, 4.0, "cvznS");
add(0x29, "and", AsmAddressingMode.IMM, 2.0, "Azn");
add(0x2a, "rol", AsmAddressingMode.NON, 2.0, "Aczn");
add(0x2b, "anc", AsmAddressingMode.IMM, 2.0, "Aczn");
add(0x2c, "bit", AsmAddressingMode.ABS, 4.0, "vzn");
add(0x2d, "and", AsmAddressingMode.ABS, 4.0, "Azn");
add(0x2e, "rol", AsmAddressingMode.ABS, 6.0, "czn");
add(0x2f, "rla", AsmAddressingMode.ABS, 6.0, "Aczn");
add(0x30, "bmi", AsmAddressingMode.REL, 2.5, "P");
add(0x31, "and", AsmAddressingMode.IZY, 5.5, "Azn");
add(0x32, "kil", AsmAddressingMode.NON, 0.0, "");
add(0x33, "rla", AsmAddressingMode.IZY, 8.0, "Aczn");
add(0x34, "nop", AsmAddressingMode.ZPX, 4.0, "");
add(0x35, "and", AsmAddressingMode.ZPX, 4.0, "Azn");
add(0x36, "rol", AsmAddressingMode.ZPX, 6.0, "czn");
add(0x37, "rla", AsmAddressingMode.ZPX, 6.0, "Aczn");
add(0x38, "sec", AsmAddressingMode.NON, 2.0, "c");
add(0x39, "and", AsmAddressingMode.ABY, 4.5, "Azn");
add(0x3a, "nop", AsmAddressingMode.NON, 2.0, "");
add(0x3b, "rla", AsmAddressingMode.ABY, 7.0, "Aczn");
add(0x3c, "nop", AsmAddressingMode.ABX, 4.5, "");
add(0x3d, "and", AsmAddressingMode.ABX, 4.5, "Azn");
add(0x3e, "rol", AsmAddressingMode.ABX, 7.0, "czn");
add(0x3f, "rla", AsmAddressingMode.ABX, 7.0, "Aczn");
add(0x40, "rti", AsmAddressingMode.NON, 6.0, "cvznPS");
add(0x41, "eor", AsmAddressingMode.IZX, 6.0, "Azn");
add(0x42, "kil", AsmAddressingMode.NON, 0.0, "");
add(0x43, "sre", AsmAddressingMode.IZX, 8.0, "Aczn");
add(0x44, "nop", AsmAddressingMode.ZP, 3.0, "");
add(0x45, "eor", AsmAddressingMode.ZP, 3.0, "Azn");
add(0x46, "lsr", AsmAddressingMode.ZP, 5.0, "czn");
add(0x47, "sre", AsmAddressingMode.ZP, 5.0, "Aczn");
add(0x48, "pha", AsmAddressingMode.NON, 3.0, "S");
add(0x49, "eor", AsmAddressingMode.IMM, 2.0, "Azn");
add(0x4a, "lsr", AsmAddressingMode.NON, 2.0, "Aczn");
add(0x4b, "alr", AsmAddressingMode.IMM, 2.0, "Aczn");
add(0x4c, "jmp", AsmAddressingMode.ABS, 3.0, "P");
add(0x4d, "eor", AsmAddressingMode.ABS, 4.0, "Azn");
add(0x4e, "lsr", AsmAddressingMode.ABS, 6.0, "czn");
add(0x4f, "sre", AsmAddressingMode.ABS, 6.0, "Aczn");
add(0x50, "bvc", AsmAddressingMode.REL, 2.5, "P");
add(0x51, "eor", AsmAddressingMode.IZY, 5.5, "Azn");
add(0x52, "kil", AsmAddressingMode.NON, 0.0, "");
add(0x53, "sre", AsmAddressingMode.IZY, 8.0, "Aczn");
add(0x54, "nop", AsmAddressingMode.ZPX, 4.0, "");
add(0x55, "eor", AsmAddressingMode.ZPX, 4.0, "Azn");
add(0x56, "lsr", AsmAddressingMode.ZPX, 6.0, "czn");
add(0x57, "sre", AsmAddressingMode.ZPX, 6.0, "Aczn");
add(0x58, "cli", AsmAddressingMode.NON, 2.0, "i");
add(0x59, "eor", AsmAddressingMode.ABY, 4.5, "Azn");
add(0x5a, "nop", AsmAddressingMode.NON, 2.0, "");
add(0x5b, "sre", AsmAddressingMode.ABY, 7.0, "Aczn");
add(0x5c, "nop", AsmAddressingMode.ABX, 4.5, "");
add(0x5d, "eor", AsmAddressingMode.ABX, 4.5, "Azn");
add(0x5e, "lsr", AsmAddressingMode.ABX, 7.0, "czn");
add(0x5f, "sre", AsmAddressingMode.ABX, 7.0, "Aczn");
add(0x60, "rts", AsmAddressingMode.NON, 6.0, "PS");
add(0x61, "adc", AsmAddressingMode.IZX, 6.0, "Acvzn");
add(0x62, "kil", AsmAddressingMode.NON, 0.0, "");
add(0x63, "rra", AsmAddressingMode.IZX, 8.0, "Acvzn");
add(0x64, "nop", AsmAddressingMode.ZP, 3.0, "");
add(0x65, "adc", AsmAddressingMode.ZP, 3.0, "Acvzn");
add(0x66, "ror", AsmAddressingMode.ZP, 5.0, "czn");
add(0x67, "rra", AsmAddressingMode.ZP, 5.0, "Acvzn");
add(0x68, "pla", AsmAddressingMode.NON, 4.0, "AznS");
add(0x69, "adc", AsmAddressingMode.IMM, 2.0, "Acvzn");
add(0x6a, "ror", AsmAddressingMode.NON, 2.0, "Aczn");
add(0x6b, "arr", AsmAddressingMode.IMM, 2.0, "Acvzn");
add(0x6c, "jmp", AsmAddressingMode.IND, 5.0, "P");
add(0x6d, "adc", AsmAddressingMode.ABS, 4.0, "Acvzn");
add(0x6e, "ror", AsmAddressingMode.ABS, 6.0, "czn");
add(0x6f, "rra", AsmAddressingMode.ABS, 6.0, "Acvzn");
add(0x70, "bvs", AsmAddressingMode.REL, 2.5, "P");
add(0x71, "adc", AsmAddressingMode.IZY, 5.5, "Acvzn");
add(0x72, "kil", AsmAddressingMode.NON, 0.0, "");
add(0x73, "rra", AsmAddressingMode.IZY, 8.0, "Acvzn");
add(0x74, "nop", AsmAddressingMode.ZPX, 4.0, "");
add(0x75, "adc", AsmAddressingMode.ZPX, 4.0, "Acvzn");
add(0x76, "ror", AsmAddressingMode.ZPX, 6.0, "czn");
add(0x77, "rra", AsmAddressingMode.ZPX, 6.0, "Acvzn");
add(0x78, "sei", AsmAddressingMode.NON, 2.0, "i");
add(0x79, "adc", AsmAddressingMode.ABY, 4.5, "Acvzn");
add(0x7a, "nop", AsmAddressingMode.NON, 2.0, "");
add(0x7b, "rra", AsmAddressingMode.ABY, 7.0, "Acvzn");
add(0x7c, "nop", AsmAddressingMode.ABX, 4.5, "");
add(0x7d, "adc", AsmAddressingMode.ABX, 4.5, "Acvzn");
add(0x7e, "ror", AsmAddressingMode.ABX, 7.0, "czn");
add(0x7f, "rra", AsmAddressingMode.ABX, 7.0, "Acvzn");
add(0x80, "nop", AsmAddressingMode.IMM, 2.0, "");
add(0x81, "sta", AsmAddressingMode.IZX, 6.0, "");
add(0x82, "nop", AsmAddressingMode.IMM, 2.0, "");
add(0x83, "sax", AsmAddressingMode.IZX, 6.0, "");
add(0x84, "sty", AsmAddressingMode.ZP, 3.0, "");
add(0x85, "sta", AsmAddressingMode.ZP, 3.0, "");
add(0x86, "stx", AsmAddressingMode.ZP, 3.0, "");
add(0x87, "sax", AsmAddressingMode.ZP, 3.0, "");
add(0x88, "dey", AsmAddressingMode.NON, 2.0, "Yzn");
add(0x89, "nop", AsmAddressingMode.IMM, 2.0, "");
add(0x8a, "txa", AsmAddressingMode.NON, 2.0, "Azn");
add(0x8b, "xaa", AsmAddressingMode.IMM, 2.0, "Azn");
add(0x8c, "sty", AsmAddressingMode.ABS, 4.0, "");
add(0x8d, "sta", AsmAddressingMode.ABS, 4.0, "");
add(0x8e, "stx", AsmAddressingMode.ABS, 4.0, "");
add(0x8f, "sax", AsmAddressingMode.ABS, 4.0, "");
add(0x90, "bcc", AsmAddressingMode.REL, 2.5, "P");
add(0x91, "sta", AsmAddressingMode.IZY, 6.0, "");
add(0x92, "kil", AsmAddressingMode.NON, 0.0, "");
add(0x93, "ahx", AsmAddressingMode.IZY, 6.0, "");
add(0x94, "sty", AsmAddressingMode.ZPX, 4.0, "");
add(0x95, "sta", AsmAddressingMode.ZPX, 4.0, "");
add(0x96, "stx", AsmAddressingMode.ZPY, 4.0, "");
add(0x97, "sax", AsmAddressingMode.ZPY, 4.0, "");
add(0x98, "tya", AsmAddressingMode.NON, 2.0, "Azn");
add(0x99, "sta", AsmAddressingMode.ABY, 5.0, "");
add(0x9a, "txs", AsmAddressingMode.NON, 2.0, "S");
add(0x9b, "tas", AsmAddressingMode.ABY, 5.0, "");
add(0x9c, "shy", AsmAddressingMode.ABX, 5.0, "");
add(0x9d, "sta", AsmAddressingMode.ABX, 5.0, "");
add(0x9e, "shx", AsmAddressingMode.ABY, 5.0, "");
add(0x9f, "ahx", AsmAddressingMode.ABY, 5.0, "");
add(0xa0, "ldy", AsmAddressingMode.IMM, 2.0, "Yzn");
add(0xa1, "lda", AsmAddressingMode.IZX, 6.0, "Azn");
add(0xa2, "ldx", AsmAddressingMode.IMM, 2.0, "Xzn");
add(0xa3, "lax", AsmAddressingMode.IZX, 6.0, "AXzn");
add(0xa4, "ldy", AsmAddressingMode.ZP, 3.0, "Yzn");
add(0xa5, "lda", AsmAddressingMode.ZP, 3.0, "Azn");
add(0xa6, "ldx", AsmAddressingMode.ZP, 3.0, "Xzn");
add(0xa7, "lax", AsmAddressingMode.ZP, 3.0, "AXzn");
add(0xa8, "tay", AsmAddressingMode.NON, 2.0, "Yzn");
add(0xa9, "lda", AsmAddressingMode.IMM, 2.0, "Azn");
add(0xaa, "tax", AsmAddressingMode.NON, 2.0, "Xzn");
add(0xab, "lax", AsmAddressingMode.IMM, 2.0, "AXzn");
add(0xac, "ldy", AsmAddressingMode.ABS, 4.0, "Yzn");
add(0xad, "lda", AsmAddressingMode.ABS, 4.0, "Azn");
add(0xae, "ldx", AsmAddressingMode.ABS, 4.0, "Xzn");
add(0xaf, "lax", AsmAddressingMode.ABS, 4.0, "AXzn");
add(0xb0, "bcs", AsmAddressingMode.REL, 2.5, "P");
add(0xb1, "lda", AsmAddressingMode.IZY, 5.5, "Azn");
add(0xb2, "kil", AsmAddressingMode.NON, 0.0, "");
add(0xb3, "lax", AsmAddressingMode.IZY, 5.5, "AXzn");
add(0xb4, "ldy", AsmAddressingMode.ZPX, 4.0, "Yzn");
add(0xb5, "lda", AsmAddressingMode.ZPX, 4.0, "Azn");
add(0xb6, "ldx", AsmAddressingMode.ZPY, 4.0, "Xzn");
add(0xb7, "lax", AsmAddressingMode.ZPY, 4.0, "AXzn");
add(0xb8, "clv", AsmAddressingMode.NON, 2.0, "v");
add(0xb9, "lda", AsmAddressingMode.ABY, 4.5, "Azn");
add(0xba, "tsx", AsmAddressingMode.NON, 2.0, "Xzn");
add(0xbb, "las", AsmAddressingMode.ABY, 4.5, "AXzn");
add(0xbc, "ldy", AsmAddressingMode.ABX, 4.5, "Yzn");
add(0xbd, "lda", AsmAddressingMode.ABX, 4.5, "Azn");
add(0xbe, "ldx", AsmAddressingMode.ABY, 4.5, "Xzn");
add(0xbf, "lax", AsmAddressingMode.ABY, 4.5, "AXzn");
add(0xc0, "cpy", AsmAddressingMode.IMM, 2.0, "czn");
add(0xc1, "cmp", AsmAddressingMode.IZX, 6.0, "czn");
add(0xc2, "nop", AsmAddressingMode.IMM, 2.0, "");
add(0xc3, "dcp", AsmAddressingMode.IZX, 8.0, "czn");
add(0xc4, "cpy", AsmAddressingMode.ZP, 3.0, "czn");
add(0xc5, "cmp", AsmAddressingMode.ZP, 3.0, "czn");
add(0xc6, "dec", AsmAddressingMode.ZP, 5.0, "zn");
add(0xc7, "dcp", AsmAddressingMode.ZP, 5.0, "czn");
add(0xc8, "iny", AsmAddressingMode.NON, 2.0, "Yzn");
add(0xc9, "cmp", AsmAddressingMode.IMM, 2.0, "czn");
add(0xca, "dex", AsmAddressingMode.NON, 2.0, "Xzn");
add(0xcb, "axs", AsmAddressingMode.IMM, 2.0, "Xczn");
add(0xcc, "cpy", AsmAddressingMode.ABS, 4.0, "czn");
add(0xcd, "cmp", AsmAddressingMode.ABS, 4.0, "czn");
add(0xce, "dec", AsmAddressingMode.ABS, 6.0, "zn");
add(0xcf, "dcp", AsmAddressingMode.ABS, 6.0, "czn");
add(0xd0, "bne", AsmAddressingMode.REL, 2.5, "P");
add(0xd1, "cmp", AsmAddressingMode.IZY, 5.5, "czn");
add(0xd2, "kil", AsmAddressingMode.NON, 0.0, "");
add(0xd3, "dcp", AsmAddressingMode.IZY, 8.0, "czn");
add(0xd4, "nop", AsmAddressingMode.ZPX, 4.0, "");
add(0xd5, "cmp", AsmAddressingMode.ZPX, 4.0, "czn");
add(0xd6, "dec", AsmAddressingMode.ZPX, 6.0, "zn");
add(0xd7, "dcp", AsmAddressingMode.ZPX, 6.0, "czn");
add(0xd8, "cld", AsmAddressingMode.NON, 2.0, "d");
add(0xd9, "cmp", AsmAddressingMode.ABY, 4.5, "czn");
add(0xda, "nop", AsmAddressingMode.NON, 2.0, "");
add(0xdb, "dcp", AsmAddressingMode.ABY, 7.0, "czn");
add(0xdc, "nop", AsmAddressingMode.ABX, 4.5, "");
add(0xdd, "cmp", AsmAddressingMode.ABX, 4.5, "czn");
add(0xde, "dec", AsmAddressingMode.ABX, 7.0, "zn");
add(0xef, "cpx", AsmAddressingMode.IMM, 2.0, "czn");
add(0xe0, "sbc", AsmAddressingMode.IZX, 6.0, "Acvzn");
add(0xe1, "nop", AsmAddressingMode.IMM, 2.0, "");
add(0xe2, "isc", AsmAddressingMode.IZX, 8.0, "Acvzn");
add(0xe3, "cpx", AsmAddressingMode.ZP, 3.0, "czn");
add(0xe4, "sbc", AsmAddressingMode.ZP, 3.0, "Acvzn");
add(0xe5, "inc", AsmAddressingMode.ZP, 5.0, "zn");
add(0xe6, "isc", AsmAddressingMode.ZP, 5.0, "Acvzn");
add(0xe7, "inx", AsmAddressingMode.NON, 2.0, "Xzn");
add(0xe8, "sbc", AsmAddressingMode.IMM, 2.0, "Acvzn");
add(0xe9, "nop", AsmAddressingMode.NON, 2.0, "");
add(0xea, "sbc", AsmAddressingMode.IMM, 2.0, "Acvzn");
add(0xeb, "cpx", AsmAddressingMode.ABS, 4.0, "czn");
add(0xec, "sbc", AsmAddressingMode.ABS, 4.0, "Acvzn");
add(0xed, "inc", AsmAddressingMode.ABS, 6.0, "zn");
add(0xee, "isc", AsmAddressingMode.ABS, 6.0, "Acvzn");
add(0xef, "dcp", AsmAddressingMode.ABX, 7.0, "czn");
add(0xf0, "beq", AsmAddressingMode.REL, 2.5, "P");
add(0xf1, "sbc", AsmAddressingMode.IZY, 5.5, "Acvzn");
add(0xf2, "kil", AsmAddressingMode.NON, 0.0, "");
add(0xf3, "isc", AsmAddressingMode.IZY, 8.0, "Acvzn");
add(0xf4, "nop", AsmAddressingMode.ZPX, 4.0, "");
add(0xf5, "sbc", AsmAddressingMode.ZPX, 4.0, "Acvzn");
add(0xf6, "inc", AsmAddressingMode.ZPX, 6.0, "zn");
add(0xf7, "isc", AsmAddressingMode.ZPX, 6.0, "Acvzn");
add(0xf8, "sed", AsmAddressingMode.NON, 2.0, "d");
add(0xf9, "sbc", AsmAddressingMode.ABY, 4.5, "Acvzn");
add(0xfa, "nop", AsmAddressingMode.NON, 2.0, "");
add(0xfb, "isc", AsmAddressingMode.ABY, 7.0, "Acvzn");
add(0xfc, "nop", AsmAddressingMode.ABX, 4.5, "");
add(0xfd, "sbc", AsmAddressingMode.ABX, 4.5, "Acvzn");
add(0xfe, "inc", AsmAddressingMode.ABX, 7.0, "zn");
add(0xff, "isc", AsmAddressingMode.ABX, 7.0, "Acvzn");
// 65c02 instructions
// TODO: create instruction set model that knows the different CPU's
add(0x1a, "inc", AsmAddressingMode.NON, 2.0, "Azn");
}
/**
* Add an instruction to the instruction set.
*
* @param opcode The numeric opcode
* @param mnemonic The lower case mnemonic
* @param addressingMode The addressing mode
* @param cycles The number of cycles
*/
private void add(int opcode, String mnemonic, AsmAddressingMode addressingMode, double cycles, String clobberString) {
AsmOpcode asmOpcode = new AsmOpcode(opcode, mnemonic, addressingMode, cycles, clobberString);
instructions.add(asmOpcode);
instructionsMap.put(mnemonic + "_" + addressingMode.getName(), asmOpcode);
}
/**
* Get a specific instruction opcode form the instruction set
*
* @param mnemonic The mnemonic
* @param addressingMode The addressing mode
* @return The opcode, if is exists. Null if the instruction set does not have the opcode.
*/
private AsmOpcode getOpcode(String mnemonic, AsmAddressingMode addressingMode) {
String key = mnemonic.toLowerCase() + "_" + addressingMode.getName();
return instructionsMap.get(key);
}
/**
* Get an opcode from the instruction set in either absolute or zeropage form.
* This will try to find a zeropage-based addressing mode if you indicate that you are interested in that.
*
* @param mnemonic The mnemonic
* @param addressingMode The addressing mode you want.
* @param isOperandZp Indicates whether the operand is <256 meaning the opcode could be zeropage-based.
* @return The opcode, if it exists. If you have requested an absolute addressing mode and pass isOperandZp as true the
* resulting opcode will have zeropage-based addressing if the instruction set offers that.
*/
public static AsmOpcode getOpcode(String mnemonic, AsmAddressingMode addressingMode, boolean isOperandZp) {
AsmOpcode asmOpcode = null;
if(AsmAddressingMode.ABS.equals(addressingMode) && isOperandZp) {
asmOpcode = set.getOpcode(mnemonic, AsmAddressingMode.ZP);
}
if(AsmAddressingMode.ABX.equals(addressingMode) && isOperandZp) {
asmOpcode = set.getOpcode(mnemonic, AsmAddressingMode.ZPX);
}
if(AsmAddressingMode.ABY.equals(addressingMode) && isOperandZp) {
asmOpcode = set.getOpcode(mnemonic, AsmAddressingMode.ZPY);
}
if(AsmAddressingMode.IND.equals(addressingMode) && isOperandZp) {
asmOpcode = set.getOpcode(mnemonic, AsmAddressingMode.INZ);
}
if(AsmAddressingMode.IAX.equals(addressingMode) && isOperandZp) {
asmOpcode = set.getOpcode(mnemonic, AsmAddressingMode.IZX);
}
if(asmOpcode == null) {
// If the ZP-form does not exist use the ABS-variation
asmOpcode = set.getOpcode(mnemonic, addressingMode);
}
if(asmOpcode == null && AsmAddressingMode.ABS.equals(addressingMode)) {
asmOpcode = set.getOpcode(mnemonic, AsmAddressingMode.REL);
}
return asmOpcode;
}
}

View File

@ -0,0 +1,108 @@
package dk.camelot64.cpufamily6502;
import java.util.*;
/**
* A 6502 family CPU. The CPU has an instruction set.
*/
public class Cpu65xx {
/** The CPU name. */
private final String name;
/** All opcodes in the instruction set. */
private final List<CpuOpcode> allOpcodes;
/** Maps mnemonic_addressingMode to the instruction opcode */
private final Map<String, CpuOpcode> opcodesByMnemonicAddrMode;
public Cpu65xx(String name) {
this.name = name;
this.allOpcodes = new ArrayList<>();
this.opcodesByMnemonicAddrMode = new LinkedHashMap<>();
}
public Cpu65xx(String name, Cpu65xx basedOn) {
this.name = name;
this.allOpcodes = new ArrayList<>();
this.opcodesByMnemonicAddrMode = new LinkedHashMap<>();
for(CpuOpcode opcode : basedOn.allOpcodes) {
addOpcode(opcode);
}
}
/**
* Add an instruction opcode to the instruction set.
*
* @param opcode The numeric opcode
* @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) {
CpuOpcode cpuOpcode = new CpuOpcode(opcode, mnemonic, addressingMode, cycles, clobberString);
addOpcode(cpuOpcode);
}
/**
* Add an instruction opcode to the instruction set.
*
* @param cpuOpcode The opcode to add
*/
private void addOpcode(CpuOpcode cpuOpcode) {
allOpcodes.add(cpuOpcode);
opcodesByMnemonicAddrMode.put(cpuOpcode.getMnemonic() + "_" + cpuOpcode.getAddressingMode().getName(), cpuOpcode);
}
/**
* Get a specific instruction opcode form the instruction set
*
* @param mnemonic The mnemonic
* @param addressingMode The addressing mode
* @return The opcode, if is exists. Null if the instruction set does not have the opcode.
*/
private CpuOpcode getOpcode(String mnemonic, CpuAddressingMode addressingMode) {
String key = mnemonic.toLowerCase() + "_" + addressingMode.getName();
return opcodesByMnemonicAddrMode.get(key);
}
/**
* Get an opcode from the instruction set in either absolute or zeropage form.
* This will try to find a zeropage-based addressing mode if you indicate that you are interested in that.
*
* @param mnemonic The mnemonic
* @param addressingMode The addressing mode you want.
* @param isOperandZp Indicates whether the operand is <256 meaning the opcode could be zeropage-based.
* @return The opcode, if it exists. If you have requested an absolute addressing mode and pass isOperandZp as true the
* resulting opcode will have zeropage-based addressing if the instruction set offers that.
*/
public CpuOpcode getOpcode(String mnemonic, CpuAddressingMode addressingMode, boolean isOperandZp) {
CpuOpcode cpuOpcode = null;
if(CpuAddressingMode.ABS.equals(addressingMode) && isOperandZp) {
cpuOpcode = getOpcode(mnemonic, CpuAddressingMode.ZP);
}
if(CpuAddressingMode.ABX.equals(addressingMode) && isOperandZp) {
cpuOpcode = getOpcode(mnemonic, CpuAddressingMode.ZPX);
}
if(CpuAddressingMode.ABY.equals(addressingMode) && isOperandZp) {
cpuOpcode = getOpcode(mnemonic, CpuAddressingMode.ZPY);
}
if(CpuAddressingMode.IND.equals(addressingMode) && isOperandZp) {
cpuOpcode = getOpcode(mnemonic, CpuAddressingMode.INZ);
}
if(CpuAddressingMode.IAX.equals(addressingMode) && isOperandZp) {
cpuOpcode = getOpcode(mnemonic, CpuAddressingMode.IZX);
}
if(cpuOpcode == null) {
// If the ZP-form does not exist use the ABS-variation
cpuOpcode = getOpcode(mnemonic, addressingMode);
}
if(cpuOpcode == null && CpuAddressingMode.ABS.equals(addressingMode)) {
// If the ABS-form does not exist try REL
cpuOpcode = getOpcode(mnemonic, CpuAddressingMode.REL);
}
return cpuOpcode;
}
}

View File

@ -1,7 +1,7 @@
package dk.camelot64.cpufamily6502;
/** 6502 Family Addressing Modes. */
public enum AsmAddressingMode {
public enum CpuAddressingMode {
/**
* None / Implied / Accumulator
@ -187,7 +187,7 @@ public enum AsmAddressingMode {
/** The number of bytes that an instruction takes up when using the addressing mode. This includes both opcode and operands. */
private int bytes;
AsmAddressingMode(String name, String template, int bytes) {
CpuAddressingMode(String name, String template, int bytes) {
this.bytes = bytes;
this.template = template;
this.name = name;

View File

@ -3,9 +3,9 @@ package dk.camelot64.cpufamily6502;
import java.io.Serializable;
/** Information about what registers/flags of the CPU an ASM instruction clobbers */
public class AsmClobber implements Serializable {
public class CpuClobber implements Serializable {
public static final AsmClobber CLOBBER_ALL = new AsmClobber(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);
final boolean registerA;
final boolean registerX;
@ -21,7 +21,7 @@ public class AsmClobber implements Serializable {
/** true if the stack pointer is modified.*/
final boolean registerSP;
public AsmClobber(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 flagC, boolean flagN, boolean flagZ, boolean flagV, boolean flagI, boolean flagD, boolean registerPC, boolean registerSP) {
this.registerA = registerA;
this.registerX = registerX;
this.registerY = registerY;
@ -35,7 +35,7 @@ public class AsmClobber implements Serializable {
this.registerSP = registerSP;
}
public AsmClobber() {
public CpuClobber() {
this(false, false, false, false, false, false, false, false, false, false, false);
}
@ -46,7 +46,7 @@ public class AsmClobber implements Serializable {
*
* @param clobberString The clobber string.
*/
public AsmClobber(String clobberString) {
public CpuClobber(String clobberString) {
this(
clobberString.contains("A"),
clobberString.contains("X"),
@ -68,7 +68,7 @@ public class AsmClobber implements Serializable {
* @param clobber1 One clobber
* @param clobber2 Another clobber
*/
public AsmClobber(AsmClobber clobber1, AsmClobber clobber2) {
public CpuClobber(CpuClobber clobber1, CpuClobber clobber2) {
this(
clobber1.registerA | clobber2.registerA,
clobber1.registerX | clobber2.registerX,

View File

@ -1,13 +1,13 @@
package dk.camelot64.cpufamily6502;
/** A specific opcode in the instruction set of a 6502 family CPU. */
public class AsmOpcode {
public class CpuOpcode {
/** The mnemonic of the instruction. */
private final String mnemonic;
/** The addressing mode of the instruction. */
private final AsmAddressingMode addressingMode;
private final CpuAddressingMode addressingMode;
/**
* The byte opcodes of the instruction.
@ -24,14 +24,14 @@ public class AsmOpcode {
private final double cycles;
/** Which registers/flags of the CPU are clobbered by the instruction. */
private final AsmClobber clobber;
private final CpuClobber clobber;
AsmOpcode(int opcode, String mnemonic, AsmAddressingMode addressingMode, double cycles, String clobberString) {
CpuOpcode(int opcode, String mnemonic, CpuAddressingMode addressingMode, double cycles, String clobberString) {
this.opcode = new int[]{opcode};
this.mnemonic = mnemonic;
this.addressingMode = addressingMode;
this.cycles = cycles;
this.clobber = new AsmClobber(clobberString);
this.clobber = new CpuClobber(clobberString);
}
/**
@ -48,7 +48,7 @@ public class AsmOpcode {
*
* @return The addressing mdoe
*/
public AsmAddressingMode getAddressingMode() {
public CpuAddressingMode getAddressingMode() {
return addressingMode;
}
@ -110,7 +110,7 @@ public class AsmOpcode {
*
* @return The clobber information
*/
public AsmClobber getClobber() {
public CpuClobber getClobber() {
return clobber;
}

View File

@ -0,0 +1,22 @@
package dk.camelot64.cpufamily6502.cpus;
import dk.camelot64.cpufamily6502.Cpu65xx;
/**
* The 45GS02 instruction set.
* https://github.com/MEGA65/mega65-user-guide/blob/master/MEGA65-Book_draft.pdf
*/
public class Cpu45GS02 extends Cpu65xx {
/** The 45GS02 CPU name. */
public final static String NAME = "45gs02";
/** The 45GS02 with illegal CPU. */
public final static Cpu45GS02 INSTANCE = new Cpu45GS02();
public Cpu45GS02() {
super(NAME, Cpu65CE02.INSTANCE);
// TODO: Add 45GS02 instructions
}
}

View File

@ -1,13 +1,13 @@
package dk.camelot64.cpufamily6502.cpus;
import dk.camelot64.cpufamily6502.AsmAddressingMode;
import dk.camelot64.cpufamily6502.AsmCpu;
import dk.camelot64.cpufamily6502.CpuAddressingMode;
import dk.camelot64.cpufamily6502.Cpu65xx;
/**
* The 6502 instruction set including illegal instructions.
* http://www.oxyron.de/html/opcodes02.html
*/
public class Cpu6502Illegal extends AsmCpu {
public class Cpu6502Illegal extends Cpu65xx {
/** The 6502 with illegal instructions CPU name. */
public final static String NAME = "6502x";
@ -17,72 +17,72 @@ public class Cpu6502Illegal extends AsmCpu {
public Cpu6502Illegal() {
super(NAME, Cpu6502Official.INSTANCE);
addOpcode(0x03, "slo", AsmAddressingMode.IZX, 8.0, "Aczn");
addOpcode(0x07, "slo", AsmAddressingMode.ZP, 5.0, "Aczn");
addOpcode(0x0b, "anc", AsmAddressingMode.IMM, 2.0, "Aczn");
addOpcode(0x0f, "slo", AsmAddressingMode.ABS, 6.0, "Aczn");
addOpcode(0x13, "slo", AsmAddressingMode.IZY, 8.0, "Aczn");
addOpcode(0x17, "slo", AsmAddressingMode.ZPX, 6.0, "Aczn");
addOpcode(0x1b, "slo", AsmAddressingMode.ABY, 7.0, "Aczn");
addOpcode(0x1f, "slo", AsmAddressingMode.ABX, 7.0, "Aczn");
addOpcode(0x23, "rla", AsmAddressingMode.IZX, 8.0, "Aczn");
addOpcode(0x27, "rla", AsmAddressingMode.ZP, 5.0, "Aczn");
addOpcode(0x2b, "anc", AsmAddressingMode.IMM, 2.0, "Aczn");
addOpcode(0x2f, "rla", AsmAddressingMode.ABS, 6.0, "Aczn");
addOpcode(0x33, "rla", AsmAddressingMode.IZY, 8.0, "Aczn");
addOpcode(0x37, "rla", AsmAddressingMode.ZPX, 6.0, "Aczn");
addOpcode(0x3b, "rla", AsmAddressingMode.ABY, 7.0, "Aczn");
addOpcode(0x3f, "rla", AsmAddressingMode.ABX, 7.0, "Aczn");
addOpcode(0x43, "sre", AsmAddressingMode.IZX, 8.0, "Aczn");
addOpcode(0x47, "sre", AsmAddressingMode.ZP, 5.0, "Aczn");
addOpcode(0x4b, "alr", AsmAddressingMode.IMM, 2.0, "Aczn");
addOpcode(0x4f, "sre", AsmAddressingMode.ABS, 6.0, "Aczn");
addOpcode(0x53, "sre", AsmAddressingMode.IZY, 8.0, "Aczn");
addOpcode(0x57, "sre", AsmAddressingMode.ZPX, 6.0, "Aczn");
addOpcode(0x5b, "sre", AsmAddressingMode.ABY, 7.0, "Aczn");
addOpcode(0x5f, "sre", AsmAddressingMode.ABX, 7.0, "Aczn");
addOpcode(0x63, "rra", AsmAddressingMode.IZX, 8.0, "Acvzn");
addOpcode(0x67, "rra", AsmAddressingMode.ZP, 5.0, "Acvzn");
addOpcode(0x6b, "arr", AsmAddressingMode.IMM, 2.0, "Acvzn");
addOpcode(0x6f, "rra", AsmAddressingMode.ABS, 6.0, "Acvzn");
addOpcode(0x73, "rra", AsmAddressingMode.IZY, 8.0, "Acvzn");
addOpcode(0x77, "rra", AsmAddressingMode.ZPX, 6.0, "Acvzn");
addOpcode(0x7b, "rra", AsmAddressingMode.ABY, 7.0, "Acvzn");
addOpcode(0x7f, "rra", AsmAddressingMode.ABX, 7.0, "Acvzn");
addOpcode(0x83, "sax", AsmAddressingMode.IZX, 6.0, "");
addOpcode(0x87, "sax", AsmAddressingMode.ZP, 3.0, "");
addOpcode(0x8b, "xaa", AsmAddressingMode.IMM, 2.0, "Azn");
addOpcode(0x8f, "sax", AsmAddressingMode.ABS, 4.0, "");
addOpcode(0x93, "ahx", AsmAddressingMode.IZY, 6.0, "");
addOpcode(0x97, "sax", AsmAddressingMode.ZPY, 4.0, "");
addOpcode(0x9b, "tas", AsmAddressingMode.ABY, 5.0, "");
addOpcode(0x9c, "shy", AsmAddressingMode.ABX, 5.0, "");
addOpcode(0x9e, "shx", AsmAddressingMode.ABY, 5.0, "");
addOpcode(0x9f, "ahx", AsmAddressingMode.ABY, 5.0, "");
addOpcode(0xa3, "lax", AsmAddressingMode.IZX, 6.0, "AXzn");
addOpcode(0xa7, "lax", AsmAddressingMode.ZP, 3.0, "AXzn");
addOpcode(0xab, "lax", AsmAddressingMode.IMM, 2.0, "AXzn");
addOpcode(0xaf, "lax", AsmAddressingMode.ABS, 4.0, "AXzn");
addOpcode(0xb3, "lax", AsmAddressingMode.IZY, 5.5, "AXzn");
addOpcode(0xb7, "lax", AsmAddressingMode.ZPY, 4.0, "AXzn");
addOpcode(0xbb, "las", AsmAddressingMode.ABY, 4.5, "AXzn");
addOpcode(0xbf, "lax", AsmAddressingMode.ABY, 4.5, "AXzn");
addOpcode(0xc3, "dcp", AsmAddressingMode.IZX, 8.0, "czn");
addOpcode(0xc7, "dcp", AsmAddressingMode.ZP, 5.0, "czn");
addOpcode(0xcb, "axs", AsmAddressingMode.IMM, 2.0, "Xczn");
addOpcode(0xcf, "dcp", AsmAddressingMode.ABS, 6.0, "czn");
addOpcode(0xd3, "dcp", AsmAddressingMode.IZY, 8.0, "czn");
addOpcode(0xd7, "dcp", AsmAddressingMode.ZPX, 6.0, "czn");
addOpcode(0xdb, "dcp", AsmAddressingMode.ABY, 7.0, "czn");
addOpcode(0xe2, "isc", AsmAddressingMode.IZX, 8.0, "Acvzn");
addOpcode(0xe6, "isc", AsmAddressingMode.ZP, 5.0, "Acvzn");
addOpcode(0xea, "sbc", AsmAddressingMode.IMM, 2.0, "Acvzn");
addOpcode(0xee, "isc", AsmAddressingMode.ABS, 6.0, "Acvzn");
addOpcode(0xef, "dcp", AsmAddressingMode.ABX, 7.0, "czn");
addOpcode(0xf3, "isc", AsmAddressingMode.IZY, 8.0, "Acvzn");
addOpcode(0xf7, "isc", AsmAddressingMode.ZPX, 6.0, "Acvzn");
addOpcode(0xfb, "isc", AsmAddressingMode.ABY, 7.0, "Acvzn");
addOpcode(0xff, "isc", AsmAddressingMode.ABX, 7.0, "Acvzn");
addOpcode(0x03, "slo", CpuAddressingMode.IZX, 8.0, "Aczn");
addOpcode(0x07, "slo", CpuAddressingMode.ZP, 5.0, "Aczn");
addOpcode(0x0b, "anc", CpuAddressingMode.IMM, 2.0, "Aczn");
addOpcode(0x0f, "slo", CpuAddressingMode.ABS, 6.0, "Aczn");
addOpcode(0x13, "slo", CpuAddressingMode.IZY, 8.0, "Aczn");
addOpcode(0x17, "slo", CpuAddressingMode.ZPX, 6.0, "Aczn");
addOpcode(0x1b, "slo", CpuAddressingMode.ABY, 7.0, "Aczn");
addOpcode(0x1f, "slo", CpuAddressingMode.ABX, 7.0, "Aczn");
addOpcode(0x23, "rla", CpuAddressingMode.IZX, 8.0, "Aczn");
addOpcode(0x27, "rla", CpuAddressingMode.ZP, 5.0, "Aczn");
addOpcode(0x2b, "anc", CpuAddressingMode.IMM, 2.0, "Aczn");
addOpcode(0x2f, "rla", CpuAddressingMode.ABS, 6.0, "Aczn");
addOpcode(0x33, "rla", CpuAddressingMode.IZY, 8.0, "Aczn");
addOpcode(0x37, "rla", CpuAddressingMode.ZPX, 6.0, "Aczn");
addOpcode(0x3b, "rla", CpuAddressingMode.ABY, 7.0, "Aczn");
addOpcode(0x3f, "rla", CpuAddressingMode.ABX, 7.0, "Aczn");
addOpcode(0x43, "sre", CpuAddressingMode.IZX, 8.0, "Aczn");
addOpcode(0x47, "sre", CpuAddressingMode.ZP, 5.0, "Aczn");
addOpcode(0x4b, "alr", CpuAddressingMode.IMM, 2.0, "Aczn");
addOpcode(0x4f, "sre", CpuAddressingMode.ABS, 6.0, "Aczn");
addOpcode(0x53, "sre", CpuAddressingMode.IZY, 8.0, "Aczn");
addOpcode(0x57, "sre", CpuAddressingMode.ZPX, 6.0, "Aczn");
addOpcode(0x5b, "sre", CpuAddressingMode.ABY, 7.0, "Aczn");
addOpcode(0x5f, "sre", CpuAddressingMode.ABX, 7.0, "Aczn");
addOpcode(0x63, "rra", CpuAddressingMode.IZX, 8.0, "Acvzn");
addOpcode(0x67, "rra", CpuAddressingMode.ZP, 5.0, "Acvzn");
addOpcode(0x6b, "arr", CpuAddressingMode.IMM, 2.0, "Acvzn");
addOpcode(0x6f, "rra", CpuAddressingMode.ABS, 6.0, "Acvzn");
addOpcode(0x73, "rra", CpuAddressingMode.IZY, 8.0, "Acvzn");
addOpcode(0x77, "rra", CpuAddressingMode.ZPX, 6.0, "Acvzn");
addOpcode(0x7b, "rra", CpuAddressingMode.ABY, 7.0, "Acvzn");
addOpcode(0x7f, "rra", CpuAddressingMode.ABX, 7.0, "Acvzn");
addOpcode(0x83, "sax", CpuAddressingMode.IZX, 6.0, "");
addOpcode(0x87, "sax", CpuAddressingMode.ZP, 3.0, "");
addOpcode(0x8b, "xaa", CpuAddressingMode.IMM, 2.0, "Azn");
addOpcode(0x8f, "sax", CpuAddressingMode.ABS, 4.0, "");
addOpcode(0x93, "ahx", CpuAddressingMode.IZY, 6.0, "");
addOpcode(0x97, "sax", CpuAddressingMode.ZPY, 4.0, "");
addOpcode(0x9b, "tas", CpuAddressingMode.ABY, 5.0, "");
addOpcode(0x9c, "shy", CpuAddressingMode.ABX, 5.0, "");
addOpcode(0x9e, "shx", CpuAddressingMode.ABY, 5.0, "");
addOpcode(0x9f, "ahx", CpuAddressingMode.ABY, 5.0, "");
addOpcode(0xa3, "lax", CpuAddressingMode.IZX, 6.0, "AXzn");
addOpcode(0xa7, "lax", CpuAddressingMode.ZP, 3.0, "AXzn");
addOpcode(0xab, "lax", CpuAddressingMode.IMM, 2.0, "AXzn");
addOpcode(0xaf, "lax", CpuAddressingMode.ABS, 4.0, "AXzn");
addOpcode(0xb3, "lax", CpuAddressingMode.IZY, 5.5, "AXzn");
addOpcode(0xb7, "lax", CpuAddressingMode.ZPY, 4.0, "AXzn");
addOpcode(0xbb, "las", CpuAddressingMode.ABY, 4.5, "AXzn");
addOpcode(0xbf, "lax", CpuAddressingMode.ABY, 4.5, "AXzn");
addOpcode(0xc3, "dcp", CpuAddressingMode.IZX, 8.0, "czn");
addOpcode(0xc7, "dcp", CpuAddressingMode.ZP, 5.0, "czn");
addOpcode(0xcb, "axs", CpuAddressingMode.IMM, 2.0, "Xczn");
addOpcode(0xcf, "dcp", CpuAddressingMode.ABS, 6.0, "czn");
addOpcode(0xd3, "dcp", CpuAddressingMode.IZY, 8.0, "czn");
addOpcode(0xd7, "dcp", CpuAddressingMode.ZPX, 6.0, "czn");
addOpcode(0xdb, "dcp", CpuAddressingMode.ABY, 7.0, "czn");
addOpcode(0xe2, "isc", CpuAddressingMode.IZX, 8.0, "Acvzn");
addOpcode(0xe6, "isc", CpuAddressingMode.ZP, 5.0, "Acvzn");
addOpcode(0xea, "sbc", CpuAddressingMode.IMM, 2.0, "Acvzn");
addOpcode(0xee, "isc", CpuAddressingMode.ABS, 6.0, "Acvzn");
addOpcode(0xef, "dcp", CpuAddressingMode.ABX, 7.0, "czn");
addOpcode(0xf3, "isc", CpuAddressingMode.IZY, 8.0, "Acvzn");
addOpcode(0xf7, "isc", CpuAddressingMode.ZPX, 6.0, "Acvzn");
addOpcode(0xfb, "isc", CpuAddressingMode.ABY, 7.0, "Acvzn");
addOpcode(0xff, "isc", CpuAddressingMode.ABX, 7.0, "Acvzn");
}
}

View File

@ -1,14 +1,14 @@
package dk.camelot64.cpufamily6502.cpus;
import dk.camelot64.cpufamily6502.AsmAddressingMode;
import dk.camelot64.cpufamily6502.AsmCpu;
import dk.camelot64.cpufamily6502.CpuAddressingMode;
import dk.camelot64.cpufamily6502.Cpu65xx;
/**
* The official 6502 instruction set (no illegal instructions).
* This is the basis for all other 6502 family CPU's and all opcodes are available in all other CPU's.
* http://archive.6502.org/datasheets/mos_6500_mpu_nov_1985.pdf
*/
public class Cpu6502Official extends AsmCpu {
public class Cpu6502Official extends Cpu65xx {
/** The 6502 official CPU name. */
public final static String NAME = "6502";
@ -18,157 +18,157 @@ public class Cpu6502Official extends AsmCpu {
public Cpu6502Official() {
super(NAME);
addOpcode(0x00, "brk", AsmAddressingMode.NON, 7.0, "");
addOpcode(0x01, "ora", AsmAddressingMode.IZX, 6.0, "Azn");
addOpcode(0x05, "ora", AsmAddressingMode.ZP, 3.0, "Azn");
addOpcode(0x06, "asl", AsmAddressingMode.ZP, 5.0, "czn");
addOpcode(0x08, "php", AsmAddressingMode.NON, 3.0, "S");
addOpcode(0x09, "ora", AsmAddressingMode.IMM, 2.0, "Azn");
addOpcode(0x0a, "asl", AsmAddressingMode.NON, 2.0, "Aczn");
addOpcode(0x0d, "ora", AsmAddressingMode.ABS, 4.0, "Azn");
addOpcode(0x0e, "asl", AsmAddressingMode.ABS, 6.0, "czn");
addOpcode(0x10, "bpl", AsmAddressingMode.REL, 2.5, "P");
addOpcode(0x11, "ora", AsmAddressingMode.IZY, 5.5, "Azn");
addOpcode(0x15, "ora", AsmAddressingMode.ZPX, 4.0, "Azn");
addOpcode(0x16, "asl", AsmAddressingMode.ZPX, 6.0, "czn");
addOpcode(0x18, "clc", AsmAddressingMode.NON, 2.0, "c");
addOpcode(0x19, "ora", AsmAddressingMode.ABY, 4.5, "Azn");
addOpcode(0x1d, "ora", AsmAddressingMode.ABX, 4.5, "Azn");
addOpcode(0x1e, "asl", AsmAddressingMode.ABX, 7.0, "czn");
addOpcode(0x20, "jsr", AsmAddressingMode.ABS, 6.0, "PS");
addOpcode(0x21, "and", AsmAddressingMode.IZX, 6.0, "Azn");
addOpcode(0x24, "bit", AsmAddressingMode.ZP, 3.0, "vzn");
addOpcode(0x25, "and", AsmAddressingMode.ZP, 3.0, "Azn");
addOpcode(0x26, "rol", AsmAddressingMode.ZP, 5.0, "czn");
addOpcode(0x28, "plp", AsmAddressingMode.NON, 4.0, "cvznS");
addOpcode(0x29, "and", AsmAddressingMode.IMM, 2.0, "Azn");
addOpcode(0x2a, "rol", AsmAddressingMode.NON, 2.0, "Aczn");
addOpcode(0x2c, "bit", AsmAddressingMode.ABS, 4.0, "vzn");
addOpcode(0x2d, "and", AsmAddressingMode.ABS, 4.0, "Azn");
addOpcode(0x2e, "rol", AsmAddressingMode.ABS, 6.0, "czn");
addOpcode(0x30, "bmi", AsmAddressingMode.REL, 2.5, "P");
addOpcode(0x31, "and", AsmAddressingMode.IZY, 5.5, "Azn");
addOpcode(0x35, "and", AsmAddressingMode.ZPX, 4.0, "Azn");
addOpcode(0x36, "rol", AsmAddressingMode.ZPX, 6.0, "czn");
addOpcode(0x38, "sec", AsmAddressingMode.NON, 2.0, "c");
addOpcode(0x39, "and", AsmAddressingMode.ABY, 4.5, "Azn");
addOpcode(0x3d, "and", AsmAddressingMode.ABX, 4.5, "Azn");
addOpcode(0x3e, "rol", AsmAddressingMode.ABX, 7.0, "czn");
addOpcode(0x40, "rti", AsmAddressingMode.NON, 6.0, "cvznPS");
addOpcode(0x41, "eor", AsmAddressingMode.IZX, 6.0, "Azn");
addOpcode(0x45, "eor", AsmAddressingMode.ZP, 3.0, "Azn");
addOpcode(0x46, "lsr", AsmAddressingMode.ZP, 5.0, "czn");
addOpcode(0x48, "pha", AsmAddressingMode.NON, 3.0, "S");
addOpcode(0x49, "eor", AsmAddressingMode.IMM, 2.0, "Azn");
addOpcode(0x4a, "lsr", AsmAddressingMode.NON, 2.0, "Aczn");
addOpcode(0x4c, "jmp", AsmAddressingMode.ABS, 3.0, "P");
addOpcode(0x4d, "eor", AsmAddressingMode.ABS, 4.0, "Azn");
addOpcode(0x4e, "lsr", AsmAddressingMode.ABS, 6.0, "czn");
addOpcode(0x50, "bvc", AsmAddressingMode.REL, 2.5, "P");
addOpcode(0x51, "eor", AsmAddressingMode.IZY, 5.5, "Azn");
addOpcode(0x55, "eor", AsmAddressingMode.ZPX, 4.0, "Azn");
addOpcode(0x56, "lsr", AsmAddressingMode.ZPX, 6.0, "czn");
addOpcode(0x58, "cli", AsmAddressingMode.NON, 2.0, "i");
addOpcode(0x59, "eor", AsmAddressingMode.ABY, 4.5, "Azn");
addOpcode(0x5d, "eor", AsmAddressingMode.ABX, 4.5, "Azn");
addOpcode(0x5e, "lsr", AsmAddressingMode.ABX, 7.0, "czn");
addOpcode(0x60, "rts", AsmAddressingMode.NON, 6.0, "PS");
addOpcode(0x61, "adc", AsmAddressingMode.IZX, 6.0, "Acvzn");
addOpcode(0x65, "adc", AsmAddressingMode.ZP, 3.0, "Acvzn");
addOpcode(0x66, "ror", AsmAddressingMode.ZP, 5.0, "czn");
addOpcode(0x68, "pla", AsmAddressingMode.NON, 4.0, "AznS");
addOpcode(0x69, "adc", AsmAddressingMode.IMM, 2.0, "Acvzn");
addOpcode(0x6a, "ror", AsmAddressingMode.NON, 2.0, "Aczn");
addOpcode(0x6c, "jmp", AsmAddressingMode.IND, 5.0, "P");
addOpcode(0x6d, "adc", AsmAddressingMode.ABS, 4.0, "Acvzn");
addOpcode(0x6e, "ror", AsmAddressingMode.ABS, 6.0, "czn");
addOpcode(0x70, "bvs", AsmAddressingMode.REL, 2.5, "P");
addOpcode(0x71, "adc", AsmAddressingMode.IZY, 5.5, "Acvzn");
addOpcode(0x75, "adc", AsmAddressingMode.ZPX, 4.0, "Acvzn");
addOpcode(0x76, "ror", AsmAddressingMode.ZPX, 6.0, "czn");
addOpcode(0x78, "sei", AsmAddressingMode.NON, 2.0, "i");
addOpcode(0x79, "adc", AsmAddressingMode.ABY, 4.5, "Acvzn");
addOpcode(0x7d, "adc", AsmAddressingMode.ABX, 4.5, "Acvzn");
addOpcode(0x7e, "ror", AsmAddressingMode.ABX, 7.0, "czn");
addOpcode(0x81, "sta", AsmAddressingMode.IZX, 6.0, "");
addOpcode(0x84, "sty", AsmAddressingMode.ZP, 3.0, "");
addOpcode(0x85, "sta", AsmAddressingMode.ZP, 3.0, "");
addOpcode(0x86, "stx", AsmAddressingMode.ZP, 3.0, "");
addOpcode(0x88, "dey", AsmAddressingMode.NON, 2.0, "Yzn");
addOpcode(0x8a, "txa", AsmAddressingMode.NON, 2.0, "Azn");
addOpcode(0x8c, "sty", AsmAddressingMode.ABS, 4.0, "");
addOpcode(0x8d, "sta", AsmAddressingMode.ABS, 4.0, "");
addOpcode(0x8e, "stx", AsmAddressingMode.ABS, 4.0, "");
addOpcode(0x90, "bcc", AsmAddressingMode.REL, 2.5, "P");
addOpcode(0x91, "sta", AsmAddressingMode.IZY, 6.0, "");
addOpcode(0x94, "sty", AsmAddressingMode.ZPX, 4.0, "");
addOpcode(0x95, "sta", AsmAddressingMode.ZPX, 4.0, "");
addOpcode(0x96, "stx", AsmAddressingMode.ZPY, 4.0, "");
addOpcode(0x98, "tya", AsmAddressingMode.NON, 2.0, "Azn");
addOpcode(0x99, "sta", AsmAddressingMode.ABY, 5.0, "");
addOpcode(0x9a, "txs", AsmAddressingMode.NON, 2.0, "S");
addOpcode(0x9d, "sta", AsmAddressingMode.ABX, 5.0, "");
addOpcode(0xa0, "ldy", AsmAddressingMode.IMM, 2.0, "Yzn");
addOpcode(0xa1, "lda", AsmAddressingMode.IZX, 6.0, "Azn");
addOpcode(0xa2, "ldx", AsmAddressingMode.IMM, 2.0, "Xzn");
addOpcode(0xa4, "ldy", AsmAddressingMode.ZP, 3.0, "Yzn");
addOpcode(0xa5, "lda", AsmAddressingMode.ZP, 3.0, "Azn");
addOpcode(0xa6, "ldx", AsmAddressingMode.ZP, 3.0, "Xzn");
addOpcode(0xa8, "tay", AsmAddressingMode.NON, 2.0, "Yzn");
addOpcode(0xa9, "lda", AsmAddressingMode.IMM, 2.0, "Azn");
addOpcode(0xaa, "tax", AsmAddressingMode.NON, 2.0, "Xzn");
addOpcode(0xac, "ldy", AsmAddressingMode.ABS, 4.0, "Yzn");
addOpcode(0xad, "lda", AsmAddressingMode.ABS, 4.0, "Azn");
addOpcode(0xae, "ldx", AsmAddressingMode.ABS, 4.0, "Xzn");
addOpcode(0xb0, "bcs", AsmAddressingMode.REL, 2.5, "P");
addOpcode(0xb1, "lda", AsmAddressingMode.IZY, 5.5, "Azn");
addOpcode(0xb4, "ldy", AsmAddressingMode.ZPX, 4.0, "Yzn");
addOpcode(0xb5, "lda", AsmAddressingMode.ZPX, 4.0, "Azn");
addOpcode(0xb6, "ldx", AsmAddressingMode.ZPY, 4.0, "Xzn");
addOpcode(0xb8, "clv", AsmAddressingMode.NON, 2.0, "v");
addOpcode(0xb9, "lda", AsmAddressingMode.ABY, 4.5, "Azn");
addOpcode(0xba, "tsx", AsmAddressingMode.NON, 2.0, "Xzn");
addOpcode(0xbc, "ldy", AsmAddressingMode.ABX, 4.5, "Yzn");
addOpcode(0xbd, "lda", AsmAddressingMode.ABX, 4.5, "Azn");
addOpcode(0xbe, "ldx", AsmAddressingMode.ABY, 4.5, "Xzn");
addOpcode(0xc0, "cpy", AsmAddressingMode.IMM, 2.0, "czn");
addOpcode(0xc1, "cmp", AsmAddressingMode.IZX, 6.0, "czn");
addOpcode(0xc4, "cpy", AsmAddressingMode.ZP, 3.0, "czn");
addOpcode(0xc5, "cmp", AsmAddressingMode.ZP, 3.0, "czn");
addOpcode(0xc6, "dec", AsmAddressingMode.ZP, 5.0, "zn");
addOpcode(0xc8, "iny", AsmAddressingMode.NON, 2.0, "Yzn");
addOpcode(0xc9, "cmp", AsmAddressingMode.IMM, 2.0, "czn");
addOpcode(0xca, "dex", AsmAddressingMode.NON, 2.0, "Xzn");
addOpcode(0xcc, "cpy", AsmAddressingMode.ABS, 4.0, "czn");
addOpcode(0xcd, "cmp", AsmAddressingMode.ABS, 4.0, "czn");
addOpcode(0xce, "dec", AsmAddressingMode.ABS, 6.0, "zn");
addOpcode(0xd0, "bne", AsmAddressingMode.REL, 2.5, "P");
addOpcode(0xd1, "cmp", AsmAddressingMode.IZY, 5.5, "czn");
addOpcode(0xd5, "cmp", AsmAddressingMode.ZPX, 4.0, "czn");
addOpcode(0xd6, "dec", AsmAddressingMode.ZPX, 6.0, "zn");
addOpcode(0xd8, "cld", AsmAddressingMode.NON, 2.0, "d");
addOpcode(0xd9, "cmp", AsmAddressingMode.ABY, 4.5, "czn");
addOpcode(0xdd, "cmp", AsmAddressingMode.ABX, 4.5, "czn");
addOpcode(0xde, "dec", AsmAddressingMode.ABX, 7.0, "zn");
addOpcode(0xe0, "cpx", AsmAddressingMode.IMM, 2.0, "czn");
addOpcode(0xe1, "sbc", AsmAddressingMode.IZX, 6.0, "Acvzn");
addOpcode(0xe4, "cpx", AsmAddressingMode.ZP, 3.0, "czn");
addOpcode(0xe5, "sbc", AsmAddressingMode.ZP, 3.0, "Acvzn");
addOpcode(0xe6, "inc", AsmAddressingMode.ZP, 5.0, "zn");
addOpcode(0xe8, "inx", AsmAddressingMode.NON, 2.0, "Xzn");
addOpcode(0xe9, "sbc", AsmAddressingMode.IMM, 2.0, "Acvzn");
addOpcode(0xea, "nop", AsmAddressingMode.NON, 2.0, "");
addOpcode(0xec, "cpx", AsmAddressingMode.ABS, 4.0, "czn");
addOpcode(0xed, "sbc", AsmAddressingMode.ABS, 4.0, "Acvzn");
addOpcode(0xee, "inc", AsmAddressingMode.ABS, 6.0, "zn");
addOpcode(0xf0, "beq", AsmAddressingMode.REL, 2.5, "P");
addOpcode(0xf1, "sbc", AsmAddressingMode.IZY, 5.5, "Acvzn");
addOpcode(0xf5, "sbc", AsmAddressingMode.ZPX, 4.0, "Acvzn");
addOpcode(0xf6, "inc", AsmAddressingMode.ZPX, 6.0, "zn");
addOpcode(0xf8, "sed", AsmAddressingMode.NON, 2.0, "d");
addOpcode(0xf9, "sbc", AsmAddressingMode.ABY, 4.5, "Acvzn");
addOpcode(0xfd, "sbc", AsmAddressingMode.ABX, 4.5, "Acvzn");
addOpcode(0xfe, "inc", AsmAddressingMode.ABX, 7.0, "zn");
addOpcode(0x00, "brk", CpuAddressingMode.NON, 7.0, "");
addOpcode(0x01, "ora", CpuAddressingMode.IZX, 6.0, "Azn");
addOpcode(0x05, "ora", CpuAddressingMode.ZP, 3.0, "Azn");
addOpcode(0x06, "asl", CpuAddressingMode.ZP, 5.0, "czn");
addOpcode(0x08, "php", CpuAddressingMode.NON, 3.0, "S");
addOpcode(0x09, "ora", CpuAddressingMode.IMM, 2.0, "Azn");
addOpcode(0x0a, "asl", CpuAddressingMode.NON, 2.0, "Aczn");
addOpcode(0x0d, "ora", CpuAddressingMode.ABS, 4.0, "Azn");
addOpcode(0x0e, "asl", CpuAddressingMode.ABS, 6.0, "czn");
addOpcode(0x10, "bpl", CpuAddressingMode.REL, 2.5, "P");
addOpcode(0x11, "ora", CpuAddressingMode.IZY, 5.5, "Azn");
addOpcode(0x15, "ora", CpuAddressingMode.ZPX, 4.0, "Azn");
addOpcode(0x16, "asl", CpuAddressingMode.ZPX, 6.0, "czn");
addOpcode(0x18, "clc", CpuAddressingMode.NON, 2.0, "c");
addOpcode(0x19, "ora", CpuAddressingMode.ABY, 4.5, "Azn");
addOpcode(0x1d, "ora", CpuAddressingMode.ABX, 4.5, "Azn");
addOpcode(0x1e, "asl", CpuAddressingMode.ABX, 7.0, "czn");
addOpcode(0x20, "jsr", CpuAddressingMode.ABS, 6.0, "PS");
addOpcode(0x21, "and", CpuAddressingMode.IZX, 6.0, "Azn");
addOpcode(0x24, "bit", CpuAddressingMode.ZP, 3.0, "vzn");
addOpcode(0x25, "and", CpuAddressingMode.ZP, 3.0, "Azn");
addOpcode(0x26, "rol", CpuAddressingMode.ZP, 5.0, "czn");
addOpcode(0x28, "plp", CpuAddressingMode.NON, 4.0, "cvznS");
addOpcode(0x29, "and", CpuAddressingMode.IMM, 2.0, "Azn");
addOpcode(0x2a, "rol", CpuAddressingMode.NON, 2.0, "Aczn");
addOpcode(0x2c, "bit", CpuAddressingMode.ABS, 4.0, "vzn");
addOpcode(0x2d, "and", CpuAddressingMode.ABS, 4.0, "Azn");
addOpcode(0x2e, "rol", CpuAddressingMode.ABS, 6.0, "czn");
addOpcode(0x30, "bmi", CpuAddressingMode.REL, 2.5, "P");
addOpcode(0x31, "and", CpuAddressingMode.IZY, 5.5, "Azn");
addOpcode(0x35, "and", CpuAddressingMode.ZPX, 4.0, "Azn");
addOpcode(0x36, "rol", CpuAddressingMode.ZPX, 6.0, "czn");
addOpcode(0x38, "sec", CpuAddressingMode.NON, 2.0, "c");
addOpcode(0x39, "and", CpuAddressingMode.ABY, 4.5, "Azn");
addOpcode(0x3d, "and", CpuAddressingMode.ABX, 4.5, "Azn");
addOpcode(0x3e, "rol", CpuAddressingMode.ABX, 7.0, "czn");
addOpcode(0x40, "rti", CpuAddressingMode.NON, 6.0, "cvznPS");
addOpcode(0x41, "eor", CpuAddressingMode.IZX, 6.0, "Azn");
addOpcode(0x45, "eor", CpuAddressingMode.ZP, 3.0, "Azn");
addOpcode(0x46, "lsr", CpuAddressingMode.ZP, 5.0, "czn");
addOpcode(0x48, "pha", CpuAddressingMode.NON, 3.0, "S");
addOpcode(0x49, "eor", CpuAddressingMode.IMM, 2.0, "Azn");
addOpcode(0x4a, "lsr", CpuAddressingMode.NON, 2.0, "Aczn");
addOpcode(0x4c, "jmp", CpuAddressingMode.ABS, 3.0, "P");
addOpcode(0x4d, "eor", CpuAddressingMode.ABS, 4.0, "Azn");
addOpcode(0x4e, "lsr", CpuAddressingMode.ABS, 6.0, "czn");
addOpcode(0x50, "bvc", CpuAddressingMode.REL, 2.5, "P");
addOpcode(0x51, "eor", CpuAddressingMode.IZY, 5.5, "Azn");
addOpcode(0x55, "eor", CpuAddressingMode.ZPX, 4.0, "Azn");
addOpcode(0x56, "lsr", CpuAddressingMode.ZPX, 6.0, "czn");
addOpcode(0x58, "cli", CpuAddressingMode.NON, 2.0, "i");
addOpcode(0x59, "eor", CpuAddressingMode.ABY, 4.5, "Azn");
addOpcode(0x5d, "eor", CpuAddressingMode.ABX, 4.5, "Azn");
addOpcode(0x5e, "lsr", CpuAddressingMode.ABX, 7.0, "czn");
addOpcode(0x60, "rts", CpuAddressingMode.NON, 6.0, "PS");
addOpcode(0x61, "adc", CpuAddressingMode.IZX, 6.0, "Acvzn");
addOpcode(0x65, "adc", CpuAddressingMode.ZP, 3.0, "Acvzn");
addOpcode(0x66, "ror", CpuAddressingMode.ZP, 5.0, "czn");
addOpcode(0x68, "pla", CpuAddressingMode.NON, 4.0, "AznS");
addOpcode(0x69, "adc", CpuAddressingMode.IMM, 2.0, "Acvzn");
addOpcode(0x6a, "ror", CpuAddressingMode.NON, 2.0, "Aczn");
addOpcode(0x6c, "jmp", CpuAddressingMode.IND, 5.0, "P");
addOpcode(0x6d, "adc", CpuAddressingMode.ABS, 4.0, "Acvzn");
addOpcode(0x6e, "ror", CpuAddressingMode.ABS, 6.0, "czn");
addOpcode(0x70, "bvs", CpuAddressingMode.REL, 2.5, "P");
addOpcode(0x71, "adc", CpuAddressingMode.IZY, 5.5, "Acvzn");
addOpcode(0x75, "adc", CpuAddressingMode.ZPX, 4.0, "Acvzn");
addOpcode(0x76, "ror", CpuAddressingMode.ZPX, 6.0, "czn");
addOpcode(0x78, "sei", CpuAddressingMode.NON, 2.0, "i");
addOpcode(0x79, "adc", CpuAddressingMode.ABY, 4.5, "Acvzn");
addOpcode(0x7d, "adc", CpuAddressingMode.ABX, 4.5, "Acvzn");
addOpcode(0x7e, "ror", CpuAddressingMode.ABX, 7.0, "czn");
addOpcode(0x81, "sta", CpuAddressingMode.IZX, 6.0, "");
addOpcode(0x84, "sty", CpuAddressingMode.ZP, 3.0, "");
addOpcode(0x85, "sta", CpuAddressingMode.ZP, 3.0, "");
addOpcode(0x86, "stx", CpuAddressingMode.ZP, 3.0, "");
addOpcode(0x88, "dey", CpuAddressingMode.NON, 2.0, "Yzn");
addOpcode(0x8a, "txa", CpuAddressingMode.NON, 2.0, "Azn");
addOpcode(0x8c, "sty", CpuAddressingMode.ABS, 4.0, "");
addOpcode(0x8d, "sta", CpuAddressingMode.ABS, 4.0, "");
addOpcode(0x8e, "stx", CpuAddressingMode.ABS, 4.0, "");
addOpcode(0x90, "bcc", CpuAddressingMode.REL, 2.5, "P");
addOpcode(0x91, "sta", CpuAddressingMode.IZY, 6.0, "");
addOpcode(0x94, "sty", CpuAddressingMode.ZPX, 4.0, "");
addOpcode(0x95, "sta", CpuAddressingMode.ZPX, 4.0, "");
addOpcode(0x96, "stx", CpuAddressingMode.ZPY, 4.0, "");
addOpcode(0x98, "tya", CpuAddressingMode.NON, 2.0, "Azn");
addOpcode(0x99, "sta", CpuAddressingMode.ABY, 5.0, "");
addOpcode(0x9a, "txs", CpuAddressingMode.NON, 2.0, "S");
addOpcode(0x9d, "sta", CpuAddressingMode.ABX, 5.0, "");
addOpcode(0xa0, "ldy", CpuAddressingMode.IMM, 2.0, "Yzn");
addOpcode(0xa1, "lda", CpuAddressingMode.IZX, 6.0, "Azn");
addOpcode(0xa2, "ldx", CpuAddressingMode.IMM, 2.0, "Xzn");
addOpcode(0xa4, "ldy", CpuAddressingMode.ZP, 3.0, "Yzn");
addOpcode(0xa5, "lda", CpuAddressingMode.ZP, 3.0, "Azn");
addOpcode(0xa6, "ldx", CpuAddressingMode.ZP, 3.0, "Xzn");
addOpcode(0xa8, "tay", CpuAddressingMode.NON, 2.0, "Yzn");
addOpcode(0xa9, "lda", CpuAddressingMode.IMM, 2.0, "Azn");
addOpcode(0xaa, "tax", CpuAddressingMode.NON, 2.0, "Xzn");
addOpcode(0xac, "ldy", CpuAddressingMode.ABS, 4.0, "Yzn");
addOpcode(0xad, "lda", CpuAddressingMode.ABS, 4.0, "Azn");
addOpcode(0xae, "ldx", CpuAddressingMode.ABS, 4.0, "Xzn");
addOpcode(0xb0, "bcs", CpuAddressingMode.REL, 2.5, "P");
addOpcode(0xb1, "lda", CpuAddressingMode.IZY, 5.5, "Azn");
addOpcode(0xb4, "ldy", CpuAddressingMode.ZPX, 4.0, "Yzn");
addOpcode(0xb5, "lda", CpuAddressingMode.ZPX, 4.0, "Azn");
addOpcode(0xb6, "ldx", CpuAddressingMode.ZPY, 4.0, "Xzn");
addOpcode(0xb8, "clv", CpuAddressingMode.NON, 2.0, "v");
addOpcode(0xb9, "lda", CpuAddressingMode.ABY, 4.5, "Azn");
addOpcode(0xba, "tsx", CpuAddressingMode.NON, 2.0, "Xzn");
addOpcode(0xbc, "ldy", CpuAddressingMode.ABX, 4.5, "Yzn");
addOpcode(0xbd, "lda", CpuAddressingMode.ABX, 4.5, "Azn");
addOpcode(0xbe, "ldx", CpuAddressingMode.ABY, 4.5, "Xzn");
addOpcode(0xc0, "cpy", CpuAddressingMode.IMM, 2.0, "czn");
addOpcode(0xc1, "cmp", CpuAddressingMode.IZX, 6.0, "czn");
addOpcode(0xc4, "cpy", CpuAddressingMode.ZP, 3.0, "czn");
addOpcode(0xc5, "cmp", CpuAddressingMode.ZP, 3.0, "czn");
addOpcode(0xc6, "dec", CpuAddressingMode.ZP, 5.0, "zn");
addOpcode(0xc8, "iny", CpuAddressingMode.NON, 2.0, "Yzn");
addOpcode(0xc9, "cmp", CpuAddressingMode.IMM, 2.0, "czn");
addOpcode(0xca, "dex", CpuAddressingMode.NON, 2.0, "Xzn");
addOpcode(0xcc, "cpy", CpuAddressingMode.ABS, 4.0, "czn");
addOpcode(0xcd, "cmp", CpuAddressingMode.ABS, 4.0, "czn");
addOpcode(0xce, "dec", CpuAddressingMode.ABS, 6.0, "zn");
addOpcode(0xd0, "bne", CpuAddressingMode.REL, 2.5, "P");
addOpcode(0xd1, "cmp", CpuAddressingMode.IZY, 5.5, "czn");
addOpcode(0xd5, "cmp", CpuAddressingMode.ZPX, 4.0, "czn");
addOpcode(0xd6, "dec", CpuAddressingMode.ZPX, 6.0, "zn");
addOpcode(0xd8, "cld", CpuAddressingMode.NON, 2.0, "d");
addOpcode(0xd9, "cmp", CpuAddressingMode.ABY, 4.5, "czn");
addOpcode(0xdd, "cmp", CpuAddressingMode.ABX, 4.5, "czn");
addOpcode(0xde, "dec", CpuAddressingMode.ABX, 7.0, "zn");
addOpcode(0xe0, "cpx", CpuAddressingMode.IMM, 2.0, "czn");
addOpcode(0xe1, "sbc", CpuAddressingMode.IZX, 6.0, "Acvzn");
addOpcode(0xe4, "cpx", CpuAddressingMode.ZP, 3.0, "czn");
addOpcode(0xe5, "sbc", CpuAddressingMode.ZP, 3.0, "Acvzn");
addOpcode(0xe6, "inc", CpuAddressingMode.ZP, 5.0, "zn");
addOpcode(0xe8, "inx", CpuAddressingMode.NON, 2.0, "Xzn");
addOpcode(0xe9, "sbc", CpuAddressingMode.IMM, 2.0, "Acvzn");
addOpcode(0xea, "nop", CpuAddressingMode.NON, 2.0, "");
addOpcode(0xec, "cpx", CpuAddressingMode.ABS, 4.0, "czn");
addOpcode(0xed, "sbc", CpuAddressingMode.ABS, 4.0, "Acvzn");
addOpcode(0xee, "inc", CpuAddressingMode.ABS, 6.0, "zn");
addOpcode(0xf0, "beq", CpuAddressingMode.REL, 2.5, "P");
addOpcode(0xf1, "sbc", CpuAddressingMode.IZY, 5.5, "Acvzn");
addOpcode(0xf5, "sbc", CpuAddressingMode.ZPX, 4.0, "Acvzn");
addOpcode(0xf6, "inc", CpuAddressingMode.ZPX, 6.0, "zn");
addOpcode(0xf8, "sed", CpuAddressingMode.NON, 2.0, "d");
addOpcode(0xf9, "sbc", CpuAddressingMode.ABY, 4.5, "Acvzn");
addOpcode(0xfd, "sbc", CpuAddressingMode.ABX, 4.5, "Acvzn");
addOpcode(0xfe, "inc", CpuAddressingMode.ABX, 7.0, "zn");
}
}

View File

@ -1,13 +1,13 @@
package dk.camelot64.cpufamily6502.cpus;
import dk.camelot64.cpufamily6502.AsmAddressingMode;
import dk.camelot64.cpufamily6502.AsmCpu;
import dk.camelot64.cpufamily6502.CpuAddressingMode;
import dk.camelot64.cpufamily6502.Cpu65xx;
/**
* The 65C02 instruction set.
* https://eater.net/datasheets/w65c02s.pdf
*/
public class Cpu65C02 extends AsmCpu {
public class Cpu65C02 extends Cpu65xx {
/** The 65C02 CPU name. */
public final static String NAME = "65c02";
@ -17,67 +17,67 @@ public class Cpu65C02 extends AsmCpu {
public Cpu65C02() {
super(NAME, Cpu6502Official.INSTANCE);
addOpcode(0x4,"tsb",AsmAddressingMode.ZP,5,"z");
addOpcode(0x7,"rmb0",AsmAddressingMode.ZP,5,"");
addOpcode(0xC,"tsb",AsmAddressingMode.ABS,6,"z");
addOpcode(0xF,"bbr0",AsmAddressingMode.REZ,5,"");
addOpcode(0x12,"ora",AsmAddressingMode.INZ,5,"Anz");
addOpcode(0x14,"trb",AsmAddressingMode.ZP,5,"z");
addOpcode(0x17,"rmb1",AsmAddressingMode.ZP,5,"");
addOpcode(0x1A,"inc",AsmAddressingMode.NON,2,"Anz");
addOpcode(0x1C,"trb",AsmAddressingMode.ABS,6,"z");
addOpcode(0x1F,"bbr1",AsmAddressingMode.REZ,5,"");
addOpcode(0x27,"rmb2",AsmAddressingMode.ZP,5,"");
addOpcode(0x2F,"bbr2",AsmAddressingMode.REZ,5,"");
addOpcode(0x32,"and",AsmAddressingMode.INZ,5,"Anz");
addOpcode(0x34,"bit",AsmAddressingMode.ZPX,4,"nvz");
addOpcode(0x37,"rmb3",AsmAddressingMode.ZP,5,"");
addOpcode(0x3A,"dec",AsmAddressingMode.NON,2,"Anz");
addOpcode(0x3C,"bit",AsmAddressingMode.ZPX,4.5,"nvz");
addOpcode(0x3F,"bbr3",AsmAddressingMode.REZ,5,"");
addOpcode(0x47,"rmb4",AsmAddressingMode.ZP,5,"");
addOpcode(0x4F,"bbr4",AsmAddressingMode.REZ,5,"");
addOpcode(0x52,"eor",AsmAddressingMode.INZ,5,"Anz");
addOpcode(0x57,"rmb5",AsmAddressingMode.ZP,5,"");
addOpcode(0x5A,"phy",AsmAddressingMode.NON,3,"");
addOpcode(0x5F,"bbr5",AsmAddressingMode.REZ,5,"");
addOpcode(0x64,"stz",AsmAddressingMode.ZP,3,"");
addOpcode(0x67,"rmb6",AsmAddressingMode.ZP,5,"");
addOpcode(0x6F,"bbr6",AsmAddressingMode.REZ,5,"");
addOpcode(0x72,"adc",AsmAddressingMode.INZ,5,"Acvnz");
addOpcode(0x74,"stz",AsmAddressingMode.ZPX,4,"");
addOpcode(0x77,"rmb7",AsmAddressingMode.ZP,5,"");
addOpcode(0x7A,"ply",AsmAddressingMode.NON,4,"Ynz");
addOpcode(0x7C,"jmp",AsmAddressingMode.IAX,6,"");
addOpcode(0x7F,"bbr7",AsmAddressingMode.REZ,5,"");
addOpcode(0x80,"bra",AsmAddressingMode.NON,3,"");
addOpcode(0x87,"smb0",AsmAddressingMode.ZP,5,"");
addOpcode(0x89,"bit",AsmAddressingMode.IAX,2,"z");
addOpcode(0x8F,"bbs0",AsmAddressingMode.REZ,5,"");
addOpcode(0x92,"sta",AsmAddressingMode.INZ,5,"");
addOpcode(0x97,"smb1",AsmAddressingMode.ZP,5,"");
addOpcode(0x9C,"stz",AsmAddressingMode.ABS,4,"");
addOpcode(0x9E,"stz",AsmAddressingMode.ZPX,5,"");
addOpcode(0x9F,"bbs1",AsmAddressingMode.REZ,5,"");
addOpcode(0xA7,"smb2",AsmAddressingMode.ZP,5,"");
addOpcode(0xAF,"bbs2",AsmAddressingMode.REZ,5,"");
addOpcode(0xB2,"lda",AsmAddressingMode.INZ,5,"Anz");
addOpcode(0xB7,"smb3",AsmAddressingMode.ZP,5,"");
addOpcode(0xBF,"bbs3",AsmAddressingMode.REZ,5,"");
addOpcode(0xC7,"smb4",AsmAddressingMode.ZP,5,"");
addOpcode(0xCB,"wai",AsmAddressingMode.NON,3,"");
addOpcode(0xCF,"bbs4",AsmAddressingMode.REZ,5,"");
addOpcode(0xD2,"cmp",AsmAddressingMode.INZ,5,"cnz");
addOpcode(0xD7,"smb5",AsmAddressingMode.ZP,5,"");
addOpcode(0xDA,"phx",AsmAddressingMode.NON,3,"");
addOpcode(0xDB,"stp",AsmAddressingMode.NON,3,"");
addOpcode(0xDF,"bbs5",AsmAddressingMode.REZ,5,"");
addOpcode(0xE7,"smb6",AsmAddressingMode.ZP,5,"");
addOpcode(0xEF,"bbs6",AsmAddressingMode.REZ,5,"");
addOpcode(0xF2,"sbc",AsmAddressingMode.INZ,5,"Acvnz");
addOpcode(0xF7,"smb7",AsmAddressingMode.ZP,5,"");
addOpcode(0xFA,"plx",AsmAddressingMode.NON,4,"Xnz");
addOpcode(0xFF,"bbs7",AsmAddressingMode.REZ,5,"");
addOpcode(0x4,"tsb", CpuAddressingMode.ZP,5,"z");
addOpcode(0x7,"rmb0", CpuAddressingMode.ZP,5,"");
addOpcode(0xC,"tsb", CpuAddressingMode.ABS,6,"z");
addOpcode(0xF,"bbr0", CpuAddressingMode.REZ,5,"");
addOpcode(0x12,"ora", CpuAddressingMode.INZ,5,"Anz");
addOpcode(0x14,"trb", CpuAddressingMode.ZP,5,"z");
addOpcode(0x17,"rmb1", CpuAddressingMode.ZP,5,"");
addOpcode(0x1A,"inc", CpuAddressingMode.NON,2,"Anz");
addOpcode(0x1C,"trb", CpuAddressingMode.ABS,6,"z");
addOpcode(0x1F,"bbr1", CpuAddressingMode.REZ,5,"");
addOpcode(0x27,"rmb2", CpuAddressingMode.ZP,5,"");
addOpcode(0x2F,"bbr2", CpuAddressingMode.REZ,5,"");
addOpcode(0x32,"and", CpuAddressingMode.INZ,5,"Anz");
addOpcode(0x34,"bit", CpuAddressingMode.ZPX,4,"nvz");
addOpcode(0x37,"rmb3", CpuAddressingMode.ZP,5,"");
addOpcode(0x3A,"dec", CpuAddressingMode.NON,2,"Anz");
addOpcode(0x3C,"bit", CpuAddressingMode.ZPX,4.5,"nvz");
addOpcode(0x3F,"bbr3", CpuAddressingMode.REZ,5,"");
addOpcode(0x47,"rmb4", CpuAddressingMode.ZP,5,"");
addOpcode(0x4F,"bbr4", CpuAddressingMode.REZ,5,"");
addOpcode(0x52,"eor", CpuAddressingMode.INZ,5,"Anz");
addOpcode(0x57,"rmb5", CpuAddressingMode.ZP,5,"");
addOpcode(0x5A,"phy", CpuAddressingMode.NON,3,"");
addOpcode(0x5F,"bbr5", CpuAddressingMode.REZ,5,"");
addOpcode(0x64,"stz", CpuAddressingMode.ZP,3,"");
addOpcode(0x67,"rmb6", CpuAddressingMode.ZP,5,"");
addOpcode(0x6F,"bbr6", CpuAddressingMode.REZ,5,"");
addOpcode(0x72,"adc", CpuAddressingMode.INZ,5,"Acvnz");
addOpcode(0x74,"stz", CpuAddressingMode.ZPX,4,"");
addOpcode(0x77,"rmb7", CpuAddressingMode.ZP,5,"");
addOpcode(0x7A,"ply", CpuAddressingMode.NON,4,"Ynz");
addOpcode(0x7C,"jmp", CpuAddressingMode.IAX,6,"");
addOpcode(0x7F,"bbr7", CpuAddressingMode.REZ,5,"");
addOpcode(0x80,"bra", CpuAddressingMode.NON,3,"");
addOpcode(0x87,"smb0", CpuAddressingMode.ZP,5,"");
addOpcode(0x89,"bit", CpuAddressingMode.IAX,2,"z");
addOpcode(0x8F,"bbs0", CpuAddressingMode.REZ,5,"");
addOpcode(0x92,"sta", CpuAddressingMode.INZ,5,"");
addOpcode(0x97,"smb1", CpuAddressingMode.ZP,5,"");
addOpcode(0x9C,"stz", CpuAddressingMode.ABS,4,"");
addOpcode(0x9E,"stz", CpuAddressingMode.ZPX,5,"");
addOpcode(0x9F,"bbs1", CpuAddressingMode.REZ,5,"");
addOpcode(0xA7,"smb2", CpuAddressingMode.ZP,5,"");
addOpcode(0xAF,"bbs2", CpuAddressingMode.REZ,5,"");
addOpcode(0xB2,"lda", CpuAddressingMode.INZ,5,"Anz");
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,"");
addOpcode(0xF2,"sbc", CpuAddressingMode.INZ,5,"Acvnz");
addOpcode(0xF7,"smb7", CpuAddressingMode.ZP,5,"");
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
}

View File

@ -0,0 +1,22 @@
package dk.camelot64.cpufamily6502.cpus;
import dk.camelot64.cpufamily6502.Cpu65xx;
/**
* The 65CE02 instruction set.
* http://archive.6502.org/datasheets/mos_65ce02_mpu.pdf
*/
public class Cpu65CE02 extends Cpu65xx {
/** The 65CE02 CPU name. */
public final static String NAME = "65ce02";
/** The 65CE02 with illegal CPU. */
public final static Cpu65CE02 INSTANCE = new Cpu65CE02();
public Cpu65CE02() {
super(NAME, Cpu65C02.INSTANCE);
// TODO: Add 65CE02 instructions
}
}

View File

@ -1,7 +1,7 @@
package dk.camelot64.kickc.asm;
import dk.camelot64.cpufamily6502.AsmClobber;
import dk.camelot64.cpufamily6502.AsmOpcode;
import dk.camelot64.cpufamily6502.CpuClobber;
import dk.camelot64.cpufamily6502.CpuOpcode;
import dk.camelot64.kickc.model.PhiTransitions;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.statements.Statement;
@ -56,7 +56,7 @@ public class AsmChunk {
private String scopeLabel;
/** If non-null this overwrites the clobber of the chunk that is calculated by examining the ASM instruction lines. */
private AsmClobber clobberOverwrite;
private CpuClobber clobberOverwrite;
public AsmChunk(int index, ScopeRef scope, Integer statementIdx, String source) {
this.lines = new ArrayList<>();
@ -74,11 +74,11 @@ public class AsmChunk {
lines.add(line);
}
public AsmClobber getClobberOverwrite() {
public CpuClobber getClobberOverwrite() {
return clobberOverwrite;
}
public void setClobberOverwrite(AsmClobber clobberOverwrite) {
public void setClobberOverwrite(CpuClobber clobberOverwrite) {
this.clobberOverwrite = clobberOverwrite;
}
@ -170,17 +170,17 @@ public class AsmChunk {
*
* @return The registers clobbered
*/
public AsmClobber getClobber() {
public CpuClobber getClobber() {
if(clobberOverwrite != null) {
return clobberOverwrite;
}
AsmClobber chunkClobber = new AsmClobber();
CpuClobber chunkClobber = new CpuClobber();
for(AsmLine line : lines) {
if(line instanceof AsmInstruction) {
AsmInstruction asmInstruction = (AsmInstruction) line;
AsmOpcode asmOpcode = asmInstruction.getAsmOpcode();
AsmClobber opcodeClobber = asmOpcode.getClobber();
chunkClobber = new AsmClobber(chunkClobber, opcodeClobber);
CpuOpcode cpuOpcode = asmInstruction.getCpuOpcode();
CpuClobber opcodeClobber = cpuOpcode.getClobber();
chunkClobber = new CpuClobber(chunkClobber, opcodeClobber);
}
}
return chunkClobber;

View File

@ -1,19 +1,19 @@
package dk.camelot64.kickc.asm;
import dk.camelot64.cpufamily6502.AsmAddressingMode;
import dk.camelot64.cpufamily6502.AsmOpcode;
import dk.camelot64.cpufamily6502.CpuAddressingMode;
import dk.camelot64.cpufamily6502.CpuOpcode;
import dk.camelot64.kickc.model.InternalError;
/** A specific assembler instruction line (opcode, addressing mode and specific parameter value) */
public class AsmInstruction implements AsmLine {
/** The instruction opcode. */
private AsmOpcode asmOpcode;
private CpuOpcode cpuOpcode;
/** The ASM opcode parameter. Null if the opcode addressing mode is Implied/A/None {@link AsmAddressingMode#NON} - eg. DEX */
/** The ASM opcode parameter. Null if the opcode addressing mode is Implied/A/None {@link CpuAddressingMode#NON} - eg. DEX */
private String operand1;
/** The second ASM opcode parameter. Null if not used. Only used for addressing mode Zeropage Test Relative {@link AsmAddressingMode#REZ} - eg. BBR0 $12,label */
/** The second ASM opcode parameter. Null if not used. Only used for addressing mode Zeropage Test Relative {@link CpuAddressingMode#REZ} - eg. BBR0 $12,label */
private String operand2;
/** The index of the instruction in the program. */
@ -22,20 +22,20 @@ public class AsmInstruction implements AsmLine {
/** If true the instruction will not be optimized away. */
private boolean dontOptimize;
public AsmInstruction(AsmOpcode asmOpcode) {
this.asmOpcode = asmOpcode;
public AsmInstruction(CpuOpcode cpuOpcode) {
this.cpuOpcode = cpuOpcode;
this.operand1 = null;
this.operand2 = null;
}
public AsmInstruction(AsmOpcode asmOpcode, String operand1) {
this.asmOpcode = asmOpcode;
public AsmInstruction(CpuOpcode cpuOpcode, String operand1) {
this.cpuOpcode = cpuOpcode;
this.operand1 = operand1;
this.operand2 = null;
}
public AsmInstruction(AsmOpcode asmOpcode, String operand1, String operand2) {
this.asmOpcode = asmOpcode;
public AsmInstruction(CpuOpcode cpuOpcode, String operand1, String operand2) {
this.cpuOpcode = cpuOpcode;
this.operand1 = operand1;
this.operand2 = operand2;
}
@ -56,27 +56,27 @@ public class AsmInstruction implements AsmLine {
this.operand2 = operand2;
}
public AsmOpcode getAsmOpcode() {
return asmOpcode;
public CpuOpcode getCpuOpcode() {
return cpuOpcode;
}
public void setAsmOpcode(AsmOpcode type) {
this.asmOpcode = type;
public void setCpuOpcode(CpuOpcode type) {
this.cpuOpcode = type;
}
@Override
public int getLineBytes() {
return asmOpcode.getBytes();
return cpuOpcode.getBytes();
}
@Override
public double getLineCycles() {
return asmOpcode.getCycles();
return cpuOpcode.getCycles();
}
@Override
public String getAsm() {
return asmOpcode.getAsm(operand1, operand2);
return cpuOpcode.getAsm(operand1, operand2);
}
@Override
@ -103,12 +103,12 @@ public class AsmInstruction implements AsmLine {
}
/***
* Get the operand value that represents a jump target (if the opcode is a jump as defined by {@link AsmOpcode#isJump()}
* Get the operand value that represents a jump target (if the opcode is a jump as defined by {@link CpuOpcode#isJump()}
* @return The jump target operand
*/
public String getOperandJumpTarget() {
if(asmOpcode.isJump()) {
if(AsmAddressingMode.REZ.equals(asmOpcode.getAddressingMode())) {
if(cpuOpcode.isJump()) {
if(CpuAddressingMode.REZ.equals(cpuOpcode.getAddressingMode())) {
// For addressing mode Zeropage Test Relative the jump target is operand2: bbr0 zp,rel
return operand2;
} else {
@ -121,12 +121,12 @@ public class AsmInstruction implements AsmLine {
}
/***
* Set the operand value that represents a jump target (if the opcode is a jump as defined by {@link AsmOpcode#isJump()}
* Set the operand value that represents a jump target (if the opcode is a jump as defined by {@link CpuOpcode#isJump()}
* @param operand The new jump target operand
*/
public void setOperandJumpTarget(String operand) {
if(asmOpcode.isJump()) {
if(AsmAddressingMode.REZ.equals(asmOpcode.getAddressingMode())) {
if(cpuOpcode.isJump()) {
if(CpuAddressingMode.REZ.equals(cpuOpcode.getAddressingMode())) {
// For addressing mode Zeropage Test Relative the jump target is operand2: bbr0 zp,rel
operand2 = operand;
} else {

View File

@ -1,11 +1,11 @@
package dk.camelot64.kickc.asm;
import dk.camelot64.cpufamily6502.AsmAddressingMode;
import dk.camelot64.cpufamily6502.AsmClobber;
import dk.camelot64.cpufamily6502.AsmInstructionSet;
import dk.camelot64.cpufamily6502.AsmOpcode;
import dk.camelot64.cpufamily6502.CpuAddressingMode;
import dk.camelot64.cpufamily6502.CpuClobber;
import dk.camelot64.cpufamily6502.CpuOpcode;
import dk.camelot64.kickc.model.CompileError;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.TargetCpu;
import dk.camelot64.kickc.model.values.ScopeRef;
import dk.camelot64.kickc.model.values.StringEncoding;
@ -19,6 +19,11 @@ import java.util.concurrent.atomic.AtomicInteger;
*/
public class AsmProgram {
/**
* The target CPU
*/
private TargetCpu targetCpu;
/**
* The chunks of the program. The chunks hold the ASM lines.
*/
@ -37,12 +42,17 @@ public class AsmProgram {
/** The current encoding used for printing strings. */
private StringEncoding currentEncoding = StringEncoding.SCREENCODE_MIXED;
public AsmProgram() {
public AsmProgram(TargetCpu targetCpu) {
this.targetCpu = targetCpu;
this.chunks = new ArrayList<>();
this.nextLineIndex = 0;
this.nextChunkIndex = 0;
}
public TargetCpu getTargetCpu() {
return targetCpu;
}
public Collection<AsmChunk> getChunks() {
return chunks;
}
@ -84,7 +94,6 @@ public class AsmProgram {
}
}
public void addComment(String comment, boolean isBlock) {
addLine(new AsmComment(comment, isBlock));
}
@ -103,9 +112,9 @@ public class AsmProgram {
addLine(new AsmScopeEnd());
}
public AsmInstruction addInstruction(String mnemonic, AsmAddressingMode addressingMode, String parameter, boolean zp) {
AsmOpcode asmOpcode = AsmInstructionSet.getOpcode(mnemonic, addressingMode, zp);
AsmInstruction asmInstruction = new AsmInstruction(asmOpcode, parameter);
public AsmInstruction addInstruction(String mnemonic, CpuAddressingMode addressingMode, String operand1, boolean isOperandZp) {
CpuOpcode cpuOpcode = targetCpu.getCpu65xx().getOpcode(mnemonic, addressingMode, isOperandZp);
AsmInstruction asmInstruction = new AsmInstruction(cpuOpcode, operand1);
addLine(asmInstruction);
return asmInstruction;
}
@ -125,7 +134,7 @@ public class AsmProgram {
}
/**
* Add a BYTE/WORD/DWORD data declaration tot the ASM
* Add a BYTE/WORD/DWORD data declaration to the ASM
*
* @param label The label of the data
* @param type The type of the data
@ -219,10 +228,10 @@ public class AsmProgram {
*
* @return The clobbered registers
*/
public AsmClobber getClobber() {
AsmClobber programClobber = new AsmClobber();
public CpuClobber getClobber() {
CpuClobber programClobber = new CpuClobber();
for(AsmChunk chunk : chunks) {
programClobber = new AsmClobber(programClobber, chunk.getClobber());
programClobber = new CpuClobber(programClobber, chunk.getClobber());
}
return programClobber;
}

View File

@ -1,8 +1,8 @@
package dk.camelot64.kickc.asm;
import dk.camelot64.cpufamily6502.AsmAddressingMode;
import dk.camelot64.cpufamily6502.AsmClobber;
import dk.camelot64.cpufamily6502.AsmOpcode;
import dk.camelot64.cpufamily6502.CpuAddressingMode;
import dk.camelot64.cpufamily6502.CpuClobber;
import dk.camelot64.cpufamily6502.CpuOpcode;
import java.util.LinkedHashMap;
import java.util.Map;
@ -87,38 +87,38 @@ public class AsmProgramStaticRegisterValues {
AsmInstruction instruction = (AsmInstruction) line;
values.put(instruction, current);
current = new AsmRegisterValues(current);
AsmOpcode asmOpcode = instruction.getAsmOpcode();
AsmClobber asmClobber = asmOpcode.getClobber();
if(instruction.getAsmOpcode().getMnemonic().equals("jsr")) {
asmClobber = AsmClobber.CLOBBER_ALL;
CpuOpcode cpuOpcode = instruction.getCpuOpcode();
CpuClobber cpuClobber = cpuOpcode.getClobber();
if(instruction.getCpuOpcode().getMnemonic().equals("jsr")) {
cpuClobber = CpuClobber.CLOBBER_ALL;
}
if(asmClobber.isRegisterA()) {
if(cpuClobber.isRegisterA()) {
current.setA(null);
current.setaMem(null);
}
if(asmClobber.isRegisterX()) {
if(cpuClobber.isRegisterX()) {
current.setX(null);
current.setxMem(null);
}
if(asmClobber.isRegisterY()) {
if(cpuClobber.isRegisterY()) {
current.setY(null);
current.setyMem(null);
}
if(asmClobber.isFlagC()) {
if(cpuClobber.isFlagC()) {
current.setC(null);
}
if(asmClobber.isFlagN()) {
if(cpuClobber.isFlagN()) {
current.setN(null);
}
if(asmClobber.isFlagV()) {
if(cpuClobber.isFlagV()) {
current.setV(null);
}
if(asmClobber.isFlagZ()) {
if(cpuClobber.isFlagZ()) {
current.setZ(null);
}
String mnemnonic = asmOpcode.getMnemonic();
AsmAddressingMode addressingMode = asmOpcode.getAddressingMode();
if((mnemnonic.equals("inc") || mnemnonic.equals("dec") || mnemnonic.equals("ror") || mnemnonic.equals("rol") || mnemnonic.equals("lsr") || mnemnonic.equals("asl")) && (addressingMode.equals(AsmAddressingMode.ZP) || addressingMode.equals(AsmAddressingMode.ABS))) {
String mnemnonic = cpuOpcode.getMnemonic();
CpuAddressingMode addressingMode = cpuOpcode.getAddressingMode();
if((mnemnonic.equals("inc") || mnemnonic.equals("dec") || mnemnonic.equals("ror") || mnemnonic.equals("rol") || mnemnonic.equals("lsr") || mnemnonic.equals("asl")) && (addressingMode.equals(CpuAddressingMode.ZP) || addressingMode.equals(CpuAddressingMode.ABS))) {
String modParam = instruction.getOperand1();
if(current.getaMem() != null && current.getaMem().equals(modParam)) {
current.setaMem(null);
@ -130,7 +130,7 @@ public class AsmProgramStaticRegisterValues {
current.setyMem(null);
}
}
if(mnemnonic.equals("lda") && addressingMode.equals(AsmAddressingMode.IMM)) {
if(mnemnonic.equals("lda") && addressingMode.equals(CpuAddressingMode.IMM)) {
current.setA(instruction.getOperand1());
current.setaMem(null);
Integer immValue = getImmValue(instruction.getOperand1());
@ -139,16 +139,16 @@ public class AsmProgramStaticRegisterValues {
current.setN(immValue > 127);
}
}
if(mnemnonic.equals("lda") && (addressingMode.equals(AsmAddressingMode.ZP) || addressingMode.equals(AsmAddressingMode.ABS))) {
if(mnemnonic.equals("lda") && (addressingMode.equals(CpuAddressingMode.ZP) || addressingMode.equals(CpuAddressingMode.ABS))) {
current.setaMem(instruction.getOperand1());
current.setA(null);
}
if(mnemnonic.equals("sta") && (addressingMode.equals(AsmAddressingMode.ZP) || addressingMode.equals(AsmAddressingMode.ABS))) {
if(mnemnonic.equals("sta") && (addressingMode.equals(CpuAddressingMode.ZP) || addressingMode.equals(CpuAddressingMode.ABS))) {
current.setaMem(instruction.getOperand1());
if(instruction.getOperand1().equals(current.getyMem())) current.setyMem(null);
if(instruction.getOperand1().equals(current.getxMem())) current.setxMem(null);
}
if(mnemnonic.equals("ldx") && addressingMode.equals(AsmAddressingMode.IMM)) {
if(mnemnonic.equals("ldx") && addressingMode.equals(CpuAddressingMode.IMM)) {
current.setX(instruction.getOperand1());
current.setxMem(null);
Integer immValue = getImmValue(instruction.getOperand1());
@ -157,16 +157,16 @@ public class AsmProgramStaticRegisterValues {
current.setN(immValue > 127);
}
}
if(mnemnonic.equals("ldx") && (addressingMode.equals(AsmAddressingMode.ZP) || addressingMode.equals(AsmAddressingMode.ABS))) {
if(mnemnonic.equals("ldx") && (addressingMode.equals(CpuAddressingMode.ZP) || addressingMode.equals(CpuAddressingMode.ABS))) {
current.setxMem(instruction.getOperand1());
current.setX(null);
}
if(mnemnonic.equals("stx") && (addressingMode.equals(AsmAddressingMode.ZP) || addressingMode.equals(AsmAddressingMode.ABS))) {
if(mnemnonic.equals("stx") && (addressingMode.equals(CpuAddressingMode.ZP) || addressingMode.equals(CpuAddressingMode.ABS))) {
current.setxMem(instruction.getOperand1());
if(instruction.getOperand1().equals(current.getyMem())) current.setyMem(null);
if(instruction.getOperand1().equals(current.getaMem())) current.setaMem(null);
}
if(mnemnonic.equals("ldy") && addressingMode.equals(AsmAddressingMode.IMM)) {
if(mnemnonic.equals("ldy") && addressingMode.equals(CpuAddressingMode.IMM)) {
current.setY(instruction.getOperand1());
current.setyMem(null);
Integer immValue = getImmValue(instruction.getOperand1());
@ -175,10 +175,10 @@ public class AsmProgramStaticRegisterValues {
current.setN(immValue > 127);
}
}
if(mnemnonic.equals("ldy") && (addressingMode.equals(AsmAddressingMode.ZP) || addressingMode.equals(AsmAddressingMode.ABS))) {
if(mnemnonic.equals("ldy") && (addressingMode.equals(CpuAddressingMode.ZP) || addressingMode.equals(CpuAddressingMode.ABS))) {
current.setyMem(instruction.getOperand1());
}
if(mnemnonic.equals("sty") && (addressingMode.equals(AsmAddressingMode.ZP) || addressingMode.equals(AsmAddressingMode.ABS))) {
if(mnemnonic.equals("sty") && (addressingMode.equals(CpuAddressingMode.ZP) || addressingMode.equals(CpuAddressingMode.ABS))) {
current.setyMem(instruction.getOperand1());
if(instruction.getOperand1().equals(current.getxMem())) current.setxMem(null);
if(instruction.getOperand1().equals(current.getaMem())) current.setaMem(null);

View File

@ -1,6 +1,6 @@
package dk.camelot64.kickc.fragment;
import dk.camelot64.cpufamily6502.AsmClobber;
import dk.camelot64.cpufamily6502.CpuClobber;
/** The clobber profile for a fragment template. Only distinguishes the 3 registers A/X/Y and not the flags. */
public class AsmFragmentClobber implements Comparable<AsmFragmentClobber> {
@ -15,7 +15,7 @@ public class AsmFragmentClobber implements Comparable<AsmFragmentClobber> {
this.clobberY = clobberY;
}
public AsmFragmentClobber(AsmClobber clobber) {
public AsmFragmentClobber(CpuClobber clobber) {
this(clobber.isRegisterA(), clobber.isRegisterX(), clobber.isRegisterY());
}

View File

@ -1,8 +1,7 @@
package dk.camelot64.kickc.fragment;
import dk.camelot64.cpufamily6502.AsmAddressingMode;
import dk.camelot64.cpufamily6502.AsmInstructionSet;
import dk.camelot64.cpufamily6502.AsmOpcode;
import dk.camelot64.cpufamily6502.CpuAddressingMode;
import dk.camelot64.cpufamily6502.CpuOpcode;
import dk.camelot64.kickc.NumberParser;
import dk.camelot64.kickc.asm.*;
import dk.camelot64.kickc.model.ConstantNotLiteral;
@ -23,19 +22,19 @@ import java.util.Map;
public class AsmFragmentInstance {
/** The symbol table. */
private Program program;
private final Program program;
/** The name of the fragment used in error messages. */
private String name;
private final String name;
/** The fragment template for the ASM code. */
private AsmFragmentTemplate fragmentTemplate;
private final AsmFragmentTemplate fragmentTemplate;
/** Binding of named values in the fragment to values (constants, variables, ...) . */
private Map<String, Value> bindings;
private final Map<String, Value> bindings;
/** The scope containing the fragment. Used when referencing symbols defined in other scopes. */
private ScopeRef codeScopeRef;
private final ScopeRef codeScopeRef;
public AsmFragmentInstance(
Program program,
@ -81,9 +80,9 @@ public class AsmFragmentInstance {
if(boundValue instanceof Variable && ((Variable) boundValue).isVariable()) {
Variable boundVar = (Variable) boundValue;
Registers.Register register = boundVar.getAllocation();
if(register != null && register instanceof Registers.RegisterZpMem) {
if(register instanceof Registers.RegisterZpMem) {
return new AsmParameter(AsmFormat.getAsmSymbolName(program, boundVar, codeScopeRef), true);
} else if(register != null && register instanceof Registers.RegisterMainMem) {
} else if(register instanceof Registers.RegisterMainMem) {
return new AsmParameter(AsmFormat.getAsmSymbolName(program, boundVar, codeScopeRef), false);
} else {
throw new RuntimeException("Register Type not implemented " + register);
@ -162,8 +161,8 @@ public class AsmFragmentInstance {
*/
public static class AsmParameter {
private String param;
private boolean zp;
private final String param;
private final boolean zp;
public AsmParameter(String param, boolean zp) {
this.param = param;
@ -181,13 +180,13 @@ public class AsmFragmentInstance {
private static class AsmSequenceGenerator extends KickCParserBaseVisitor {
private String name;
private AsmProgram program;
private AsmFragmentInstance bindings;
private final String name;
private final AsmProgram program;
private final AsmFragmentInstance fragmentInstance;
public AsmSequenceGenerator(String name, AsmFragmentInstance bindings, AsmProgram program) {
public AsmSequenceGenerator(String name, AsmFragmentInstance fragmentInstance, AsmProgram program) {
this.name = name;
this.bindings = bindings;
this.fragmentInstance = fragmentInstance;
this.program = program;
}
@ -227,7 +226,7 @@ public class AsmFragmentInstance {
KickCParser.AsmParamModeContext paramModeCtx = ctx.asmParamMode();
AsmInstruction instruction;
if(paramModeCtx == null) {
instruction = createAsmInstruction(ctx, null, null,AsmAddressingMode.NON);
instruction = createAsmInstruction(ctx, null, null, CpuAddressingMode.NON);
} else {
instruction = (AsmInstruction) this.visit(paramModeCtx);
}
@ -241,12 +240,12 @@ public class AsmFragmentInstance {
@Override
public Object visitAsmModeAbs(KickCParser.AsmModeAbsContext ctx) {
return createAsmInstruction(ctx, ctx.asmExpr(), null,AsmAddressingMode.ABS);
return createAsmInstruction(ctx, ctx.asmExpr(), null, CpuAddressingMode.ABS);
}
@Override
public Object visitAsmModeImm(KickCParser.AsmModeImmContext ctx) {
return createAsmInstruction(ctx, ctx.asmExpr(), null,AsmAddressingMode.IMM);
return createAsmInstruction(ctx, ctx.asmExpr(), null, CpuAddressingMode.IMM);
}
@Override
@ -255,25 +254,22 @@ public class AsmFragmentInstance {
if(indexCtx instanceof KickCParser.AsmExprLabelContext) {
final String xy = ((KickCParser.AsmExprLabelContext) indexCtx).ASM_NAME().getText();
if(xy.equals("x")) {
return createAsmInstruction(ctx, ctx.asmExpr(0), null,AsmAddressingMode.ABX);
return createAsmInstruction(ctx, ctx.asmExpr(0), null, CpuAddressingMode.ABX);
} else if(xy.equals("y")) {
return createAsmInstruction(ctx, ctx.asmExpr(0), null,AsmAddressingMode.ABY);
} else {
throw new RuntimeException("Unknown addressing mode " + ctx.getText());
return createAsmInstruction(ctx, ctx.asmExpr(0), null, CpuAddressingMode.ABY);
}
} else {
// Test Relative Addressing Mode (2 parameters)
return createAsmInstruction(ctx, ctx.asmExpr(0), ctx.asmExpr(1), AsmAddressingMode.REZ);
}
// Test Relative Addressing Mode (2 parameters)
return createAsmInstruction(ctx, ctx.asmExpr(0), ctx.asmExpr(1), CpuAddressingMode.REZ);
}
@Override
public Object visitAsmModeIndIdxXY(KickCParser.AsmModeIndIdxXYContext ctx) {
String xy = ctx.ASM_NAME().getText();
if(xy.equals("y")) {
return createAsmInstruction(ctx, ctx.asmExpr(), null,AsmAddressingMode.IZY);
return createAsmInstruction(ctx, ctx.asmExpr(), null, CpuAddressingMode.IZY);
} else if(xy.equals("z")) {
return createAsmInstruction(ctx, ctx.asmExpr(), null,AsmAddressingMode.IZZ);
return createAsmInstruction(ctx, ctx.asmExpr(), null, CpuAddressingMode.IZZ);
} else {
throw new RuntimeException("Unknown addressing mode " + ctx.getText());
}
@ -283,7 +279,7 @@ public class AsmFragmentInstance {
public Object visitAsmModeIndLongIdxXY(KickCParser.AsmModeIndLongIdxXYContext ctx) {
String xy = ctx.ASM_NAME().getText();
if(xy.equals("z")) {
return createAsmInstruction(ctx, ctx.asmExpr(), null,AsmAddressingMode.LIZ);
return createAsmInstruction(ctx, ctx.asmExpr(), null, CpuAddressingMode.LIZ);
} else {
throw new RuntimeException("Unknown addressing mode " + ctx.getText());
}
@ -293,7 +289,7 @@ public class AsmFragmentInstance {
public Object visitAsmModeIdxIndXY(KickCParser.AsmModeIdxIndXYContext ctx) {
String xy = ctx.ASM_NAME().getText();
if(xy.equals("x")) {
return createAsmInstruction(ctx, ctx.asmExpr(), null,AsmAddressingMode.IAX);
return createAsmInstruction(ctx, ctx.asmExpr(), null, CpuAddressingMode.IAX);
} else {
throw new RuntimeException("Unknown addressing mode " + ctx.getText());
}
@ -304,7 +300,7 @@ public class AsmFragmentInstance {
String sp = ctx.ASM_NAME(0).getText();
String y = ctx.ASM_NAME(1).getText();
if(sp.equals("sp") && y.equals("y")) {
return createAsmInstruction(ctx, ctx.asmExpr(), null,AsmAddressingMode.ISY);
return createAsmInstruction(ctx, ctx.asmExpr(), null, CpuAddressingMode.ISY);
} else {
throw new RuntimeException("Unknown addressing mode " + ctx.getText());
}
@ -312,19 +308,19 @@ public class AsmFragmentInstance {
@Override
public Object visitAsmModeInd(KickCParser.AsmModeIndContext ctx) {
return createAsmInstruction(ctx, ctx.asmExpr(), null, AsmAddressingMode.IND);
return createAsmInstruction(ctx, ctx.asmExpr(), null, CpuAddressingMode.IND);
}
@Override
public Object visitAsmModeIndLong(KickCParser.AsmModeIndLongContext ctx) {
return createAsmInstruction(ctx, ctx.asmExpr(), null, AsmAddressingMode.LIN);
return createAsmInstruction(ctx, ctx.asmExpr(), null, CpuAddressingMode.LIN);
}
private AsmInstruction createAsmInstruction(
KickCParser.AsmParamModeContext paramModeCtx,
KickCParser.AsmExprContext operand1Ctx,
KickCParser.AsmExprContext operand2Ctx,
AsmAddressingMode addressingMode) {
CpuAddressingMode addressingMode) {
return createAsmInstruction((KickCParser.AsmInstructionContext) paramModeCtx.getParent(), operand1Ctx, operand2Ctx, addressingMode);
}
@ -332,19 +328,19 @@ public class AsmFragmentInstance {
KickCParser.AsmInstructionContext instructionCtx,
KickCParser.AsmExprContext operand1Ctx,
KickCParser.AsmExprContext operand2Ctx,
AsmAddressingMode addressingMode) {
CpuAddressingMode addressingMode) {
String mnemonic = instructionCtx.ASM_MNEMONIC().getSymbol().getText();
AsmParameter param1 = operand1Ctx == null ? null : (AsmParameter) this.visit(operand1Ctx);
AsmParameter param2 = operand2Ctx == null ? null : (AsmParameter) this.visit(operand2Ctx);
// Convert to ZP-addressing mode if possible
boolean isZp = param1 != null && param1.isZp();
AsmOpcode asmOpcode = AsmInstructionSet.getOpcode(mnemonic, addressingMode, isZp);
CpuOpcode cpuOpcode = this.fragmentInstance.fragmentTemplate.getTargetCpu().getCpu65xx().getOpcode(mnemonic, addressingMode, isZp);
String operand1 = param1 == null ? null : param1.getParam();
String operand2 = param2 == null ? null : param2.getParam();
if(asmOpcode == null) {
if(cpuOpcode == null) {
throw new InternalError("Error in " + name + ".asm line " + instructionCtx.getStart().getLine() + " - Instruction type not supported " + addressingMode.getAsm(mnemonic, operand1, operand2));
}
return new AsmInstruction(asmOpcode, operand1, operand2);
return new AsmInstruction(cpuOpcode, operand1, operand2);
}
@Override
@ -410,7 +406,7 @@ public class AsmFragmentInstance {
@Override
public AsmParameter visitAsmExprReplace(KickCParser.AsmExprReplaceContext ctx) {
String replaceName = ctx.ASM_NAME().getSymbol().getText();
return bindings.getBoundValue(replaceName);
return fragmentInstance.getBoundValue(replaceName);
}
}

View File

@ -1,9 +1,10 @@
package dk.camelot64.kickc.fragment;
import dk.camelot64.cpufamily6502.AsmClobber;
import dk.camelot64.cpufamily6502.CpuClobber;
import dk.camelot64.kickc.asm.AsmProgram;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.Registers;
import dk.camelot64.kickc.model.TargetCpu;
import dk.camelot64.kickc.model.statements.StatementSource;
import dk.camelot64.kickc.model.symbols.Label;
import dk.camelot64.kickc.model.symbols.ProgramScope;
@ -28,14 +29,15 @@ public class AsmFragmentTemplate {
/** true if the fragment was loaded from the disk cache. */
private boolean cache;
/** The fragment template signature name. */
private String signature;
private final String signature;
/** The fragment template body */
private String body;
/** The synthesis that created the fragment. null if the fragment template was loaded. */
private AsmFragmentTemplateSynthesisRule synthesis;
/** The sub fragment template that the synthesis modified to create this. null if the fragment template was loaded. */
private AsmFragmentTemplate subFragment;
/** The target CPU. */
private final TargetCpu targetCpu;
/** The parsed ASM lines. Initially null. Will be non-null, is the template is ever used to generate ASM code. */
private KickCParser.AsmLinesContext bodyAsm;
/** The ASM clobber of the fragment. */
@ -43,9 +45,10 @@ public class AsmFragmentTemplate {
/** The cycles consumed by the ASM of the fragment. */
private Double cycles;
AsmFragmentTemplate(String signature, String body, boolean cache) {
AsmFragmentTemplate(String signature, String body, TargetCpu targetCpu, boolean cache) {
this.signature = signature;
this.body = body;
this.targetCpu = targetCpu;
this.file = true;
this.cache = cache;
}
@ -55,6 +58,7 @@ public class AsmFragmentTemplate {
this.body = body;
this.synthesis = synthesis;
this.subFragment = subFragment;
this.targetCpu = subFragment.targetCpu;
this.file = false;
this.cache = false;
}
@ -64,9 +68,10 @@ public class AsmFragmentTemplate {
*
* @param bodyLines Parsed ASM body
*/
public AsmFragmentTemplate(KickCParser.AsmLinesContext bodyLines) {
public AsmFragmentTemplate(KickCParser.AsmLinesContext bodyLines, TargetCpu targetCpu) {
this.signature = "--inline--";
this.bodyAsm = bodyLines;
this.targetCpu = targetCpu;
}
/**
@ -128,11 +133,11 @@ public class AsmFragmentTemplate {
if(signature.contains("la1")) bindings.put("la1", new Label("@1", scope, true));
AsmFragmentInstance fragmentInstance =
new AsmFragmentInstance(new Program(), signature, ScopeRef.ROOT, this, bindings);
AsmProgram asm = new AsmProgram();
AsmProgram asm = new AsmProgram(targetCpu);
asm.startChunk(ScopeRef.ROOT, null, signature);
fragmentInstance.generate(asm);
AsmClobber asmClobber = asm.getClobber();
this.clobber = new AsmFragmentClobber(asmClobber);
CpuClobber cpuClobber = asm.getClobber();
this.clobber = new AsmFragmentClobber(cpuClobber);
this.cycles = asm.getCycles();
}
@ -151,6 +156,10 @@ public class AsmFragmentTemplate {
return bodyAsm;
}
public TargetCpu getTargetCpu() {
return targetCpu;
}
public AsmFragmentClobber getClobber() {
if(clobber == null) {
initAsm();

View File

@ -41,7 +41,7 @@ public class AsmFragmentTemplateCache {
}
/** Special singleton representing that the fragment can not be synthesized or loaded. */
public static AsmFragmentTemplate NO_SYNTHESIS = new AsmFragmentTemplate("NO_SYNTHESIS", "NO_SYNTHESIS", false);
public static AsmFragmentTemplate NO_SYNTHESIS = new AsmFragmentTemplate("NO_SYNTHESIS", "NO_SYNTHESIS", null, false);
/** Prefix for the fragment hash file header. */
public static final String HASH_HEADER = "//KICKC FRAGMENT CACHE ";
@ -137,7 +137,7 @@ public class AsmFragmentTemplateCache {
if(cacheLine.startsWith(FRAGMENT_HEADER)) {
// New fragment - first put the current one into the cache
if(signature != null)
addFragment(cache, signature, body);
addFragment(cache, signature, body, cpu);
// Clear body and initialize signature
body = new StringBuilder();
signature = cacheLine.substring(FRAGMENT_HEADER.length());
@ -149,7 +149,7 @@ public class AsmFragmentTemplateCache {
}
// Put the last fragment into the cache
if(signature != null)
addFragment(cache, signature, body);
addFragment(cache, signature, body, cpu);
final Date after = new Date();
final long millis = after.getTime() - before.getTime();
if(log.isVerboseFragmentLog())
@ -162,13 +162,13 @@ public class AsmFragmentTemplateCache {
}
}
private static void addFragment(LinkedHashMap<String, AsmFragmentTemplate> cache, String signature, StringBuilder body) {
private static void addFragment(LinkedHashMap<String, AsmFragmentTemplate> cache, String signature, StringBuilder body, TargetCpu targetCpu) {
final String bodyString = body.toString();
if(bodyString.startsWith(NO_SYNTHESIS.getBody())) {
cache.put(signature, NO_SYNTHESIS);
} else {
CharStream fragmentCharStream = CharStreams.fromString(bodyString);
AsmFragmentTemplate template = new AsmFragmentTemplate(signature, AsmFragmentTemplateSynthesizer.fixNewlines(fragmentCharStream.toString()), true);
AsmFragmentTemplate template = new AsmFragmentTemplate(signature, AsmFragmentTemplateSynthesizer.fixNewlines(fragmentCharStream.toString()), targetCpu, true);
cache.put(signature, template);
}
}

View File

@ -116,6 +116,7 @@ class AsmFragmentTemplateSynthesisRule {
if(subDontClobber.contains("aa") && subTemplate.getClobber().isClobberA()) return null;
if(subDontClobber.contains("xx") && subTemplate.getClobber().isClobberX()) return null;
if(subDontClobber.contains("yy") && subTemplate.getClobber().isClobberY()) return null;
// TODO Z register: if(subDontClobber.contains("zz") && subTemplate.getClobber().isClobberZ()) return null;
}
StringBuilder newFragment = new StringBuilder();

View File

@ -26,22 +26,22 @@ import java.util.*;
public class AsmFragmentTemplateSynthesizer {
/** Create synthesizer. */
public AsmFragmentTemplateSynthesizer(TargetCpu cpu, Path baseFragmentFolder, boolean useFragmentCache, CompileLog log) {
public AsmFragmentTemplateSynthesizer(TargetCpu targetCpu, Path baseFragmentFolder, boolean useFragmentCache, CompileLog log) {
this.baseFragmentFolder = baseFragmentFolder;
this.cpu = cpu;
this.targetCpu = targetCpu;
this.synthesisGraph = new LinkedHashMap<>();
this.bestTemplateUpdate = new ArrayDeque<>();
if(useFragmentCache)
this.fragmentCache = AsmFragmentTemplateCache.load(cpu, baseFragmentFolder, log);
this.fragmentCache = AsmFragmentTemplateCache.load(targetCpu, baseFragmentFolder, log);
else
this.fragmentCache = AsmFragmentTemplateCache.memory(cpu);
this.fragmentCache = AsmFragmentTemplateCache.memory(targetCpu);
}
/** The folder containing fragment files. */
private Path baseFragmentFolder;
/** The Target CPU - used for obtaining CPU-specific fragment files. */
private TargetCpu cpu;
private TargetCpu targetCpu;
/** Cache for the best fragment templates. Maps signature to the best fragment template for the signature. */
private AsmFragmentTemplateCache fragmentCache;
@ -501,7 +501,7 @@ public class AsmFragmentTemplateSynthesizer {
*/
private List<AsmFragmentTemplate> loadFragmentTemplates(String signature) {
ArrayList<AsmFragmentTemplate> fileTemplates = new ArrayList<>();
List<TargetCpu.Feature> cpuFeatures = cpu.getFeatures();
List<TargetCpu.Feature> cpuFeatures = targetCpu.getFeatures();
for(TargetCpu.Feature cpuFeature : cpuFeatures) {
AsmFragmentTemplate fileFragment = loadFragmentTemplate(signature, baseFragmentFolder.resolve(cpuFeature.getName()));
if(fileFragment != null)
@ -532,7 +532,7 @@ public class AsmFragmentTemplateSynthesizer {
body = fixNewlines(fragmentCharStream.toString());
}
return new AsmFragmentTemplate(signature, body, false);
return new AsmFragmentTemplate(signature, body, targetCpu, false);
} catch(IOException e) {
throw new RuntimeException("Error loading fragment file " + signature, e);
} catch(StringIndexOutOfBoundsException e) {

View File

@ -1,5 +1,7 @@
package dk.camelot64.kickc.model;
import dk.camelot64.cpufamily6502.Cpu65xx;
import dk.camelot64.cpufamily6502.cpus.*;
import kickass._65xx.cpus.*;
import java.util.Arrays;
@ -12,19 +14,19 @@ import java.util.List;
* */
public enum TargetCpu {
/** Vanilla MOS 6502 CPU running in ROM - no illegal opcodes, no self-modifying code. */
ROM6502("rom6502", CPU_6502NoIllegals.name, Collections.singletonList(Feature.MOS6502_COMMON)),
ROM6502("rom6502", CPU_6502NoIllegals.name, Cpu6502Official.INSTANCE, Collections.singletonList(Feature.MOS6502_COMMON)),
/** MOS 6502 CPU running in ROM - allows illegal instructions, no self-modifying code. */
ROM6502X("rom6502x", CPU_6502WithIllegals.name, Arrays.asList(Feature.MOS6502_COMMON, Feature.MOS6502_UNODC)),
ROM6502X("rom6502x", CPU_6502WithIllegals.name, Cpu6502Illegal.INSTANCE, Arrays.asList(Feature.MOS6502_COMMON, Feature.MOS6502_UNODC)),
/** Vanilla MOS 6502 CPU - no illegal opcodes, allows self-modifying code. */
MOS6502("mos6502", CPU_6502NoIllegals.name, Arrays.asList(Feature.MOS6502_COMMON, Feature.MOS6502_SELFMOD)),
MOS6502("mos6502", CPU_6502NoIllegals.name, Cpu6502Official.INSTANCE, Arrays.asList(Feature.MOS6502_COMMON, Feature.MOS6502_SELFMOD)),
/** MOS 6502 CPU - allows illegal instructions, allows self-modifying code. */
MOS6502X("mos6502x", CPU_6502WithIllegals.name, Arrays.asList(Feature.MOS6502_COMMON, Feature.MOS6502_UNODC, Feature.MOS6502_SELFMOD)),
MOS6502X("mos6502x", CPU_6502WithIllegals.name, Cpu6502Illegal.INSTANCE, Arrays.asList(Feature.MOS6502_COMMON, Feature.MOS6502_UNODC, Feature.MOS6502_SELFMOD)),
/** WDC 65C02 CPU - More addressing modes and instructions, no self-modifying code. http://westerndesigncenter.com/wdc/documentation/w65c02s.pdf */
WDC65C02("wdc65c02", CPU_65C02.name, Arrays.asList(Feature.MOS6502_COMMON, Feature.WDC65C02_COMMON, Feature.WDC65C02_SPECIFIC)),
WDC65C02("wdc65c02", CPU_65C02.name, Cpu65C02.INSTANCE, Arrays.asList(Feature.MOS6502_COMMON, Feature.WDC65C02_COMMON, Feature.WDC65C02_SPECIFIC)),
/** CSG 65CE02 CPU - Even more addressing modes and instructions, no self-modifying code. http://www.zimmers.net/anonftp/pub/cbm/documents/chipdata/65ce02.txt */
CSG65CE02("csg65ce02", CPU_65CE02.name, Arrays.asList(Feature.MOS6502_COMMON, Feature.WDC65C02_COMMON, Feature.CSG65CE02_COMMON)),
CSG65CE02("csg65ce02", CPU_65CE02.name, Cpu65CE02.INSTANCE, Arrays.asList(Feature.MOS6502_COMMON, Feature.WDC65C02_COMMON, Feature.CSG65CE02_COMMON)),
/** 45GS02 CPU - Even more addressing modes and instructions, no self-modifying code. https://github.com/MEGA65/mega65-user-guide/blob/master/MEGA65-Book_draft.pdf */
MEGA45GS02("mega45gs02", CPU_45GS02.name, Arrays.asList(Feature.MOS6502_COMMON, Feature.WDC65C02_COMMON, Feature.CSG65CE02_COMMON, Feature.MEGA45GS02_COMMON)),
MEGA45GS02("mega45gs02", CPU_45GS02.name, Cpu45GS02.INSTANCE, Arrays.asList(Feature.MOS6502_COMMON, Feature.WDC65C02_COMMON, Feature.CSG65CE02_COMMON, Feature.MEGA45GS02_COMMON)),
///** 65C186 CPU - 16-bit instructions, 24-bit addressing modes and more instructions. http://www.westerndesigncenter.com/wdc/documentation/w65c816s.pdf */
//WDC65C186("65C186"),
;
@ -63,17 +65,21 @@ public enum TargetCpu {
}
/** The name of the CPU. */
private String name;
private final String name;
/** The CPU name used by KickAsm */
private String asmName;
private final String asmName;
/** The SM CPU knowing the instruction set. */
private final Cpu65xx cpu65xx;
/** Features of the CPU */
private List<Feature> features;
TargetCpu(String name, String asmName, List<Feature> features) {
TargetCpu(String name, String asmName, Cpu65xx cpu65xx, List<Feature> features) {
this.name = name;
this.asmName = asmName;
this.cpu65xx = cpu65xx;
this.features = features;
}
@ -81,6 +87,10 @@ public enum TargetCpu {
return name;
}
public Cpu65xx getCpu65xx() {
return cpu65xx;
}
/**
* Get the name used by KickAsm
* @return The CPU name used by KickAsm

View File

@ -1,6 +1,6 @@
package dk.camelot64.kickc.model.statements;
import dk.camelot64.cpufamily6502.AsmClobber;
import dk.camelot64.cpufamily6502.CpuClobber;
import dk.camelot64.kickc.model.Comment;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.values.SymbolRef;
@ -19,9 +19,9 @@ public class StatementAsm extends StatementBase {
private Map<String, SymbolRef> referenced;
/** Declared clobber for the inline ASM. */
private AsmClobber declaredClobber;
private CpuClobber declaredClobber;
public StatementAsm(KickCParser.AsmLinesContext asmBody, Map<String, SymbolRef> referenced, AsmClobber declaredClobber, StatementSource source, List<Comment> comments) {
public StatementAsm(KickCParser.AsmLinesContext asmBody, Map<String, SymbolRef> referenced, CpuClobber declaredClobber, StatementSource source, List<Comment> comments) {
super(source, comments);
this.asmLines = asmBody;
this.referenced = referenced;
@ -51,11 +51,11 @@ public class StatementAsm extends StatementBase {
return referenced;
}
public AsmClobber getDeclaredClobber() {
public CpuClobber getDeclaredClobber() {
return declaredClobber;
}
public void setDeclaredClobber(AsmClobber declaredClobber) {
public void setDeclaredClobber(CpuClobber declaredClobber) {
this.declaredClobber = declaredClobber;
}
}

View File

@ -1,6 +1,6 @@
package dk.camelot64.kickc.model.statements;
import dk.camelot64.cpufamily6502.AsmClobber;
import dk.camelot64.cpufamily6502.CpuClobber;
import dk.camelot64.kickc.model.Comment;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.values.RValue;
@ -25,7 +25,7 @@ public class StatementKickAsm extends StatementBase {
private List<SymbolRef> uses;
/** Declared clobber for the inline kick-assembler . */
private AsmClobber declaredClobber;
private CpuClobber declaredClobber;
public StatementKickAsm(String kickAsmCode, StatementSource source, List<Comment> comments) {
super(source, comments);
@ -33,7 +33,7 @@ public class StatementKickAsm extends StatementBase {
this.uses = new ArrayList<>();
}
public StatementKickAsm(String kickAsmCode, RValue bytes, RValue cycles, List<SymbolRef> uses, AsmClobber declaredClobber, StatementSource source, List<Comment> comments) {
public StatementKickAsm(String kickAsmCode, RValue bytes, RValue cycles, List<SymbolRef> uses, CpuClobber declaredClobber, StatementSource source, List<Comment> comments) {
super(source, comments);
this.kickAsmCode = kickAsmCode;
this.bytes = bytes;
@ -42,11 +42,11 @@ public class StatementKickAsm extends StatementBase {
this.declaredClobber = declaredClobber;
}
public AsmClobber getDeclaredClobber() {
public CpuClobber getDeclaredClobber() {
return declaredClobber;
}
public void setDeclaredClobber(AsmClobber declaredClobber) {
public void setDeclaredClobber(CpuClobber declaredClobber) {
this.declaredClobber = declaredClobber;
}

View File

@ -2,7 +2,7 @@ package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.NumberParser;
import dk.camelot64.kickc.SourceLoader;
import dk.camelot64.cpufamily6502.AsmClobber;
import dk.camelot64.cpufamily6502.CpuClobber;
import dk.camelot64.kickc.model.InternalError;
import dk.camelot64.kickc.model.*;
import dk.camelot64.kickc.model.operators.*;
@ -459,7 +459,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
/** The number of cycles used by the generated kick-assembler code. */
private RValue cycles;
/** Declared clobber for the inline kick-assembler . */
private AsmClobber declaredClobber;
private CpuClobber declaredClobber;
public KickAsm(String kickAsmCode) {
this.kickAsmCode = kickAsmCode;
@ -628,13 +628,13 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
/** ASM Directive specifying clobber registers. */
private static class AsmDirectiveClobber implements AsmDirective {
private AsmClobber clobber;
private CpuClobber clobber;
AsmDirectiveClobber(AsmClobber clobber) {
AsmDirectiveClobber(CpuClobber clobber) {
this.clobber = clobber;
}
public AsmClobber getClobber() {
public CpuClobber getClobber() {
return clobber;
}
@ -652,7 +652,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
if(!clobberString.matches("[AXY]*")) {
throw new CompileError("Error! Illegal clobber value " + clobberString, new StatementSource(ctx));
}
AsmClobber clobber = new AsmClobber(clobberString);
CpuClobber clobber = new CpuClobber(clobberString);
return new AsmDirectiveClobber(clobber);
}
@ -1700,7 +1700,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
Map<String, SymbolRef> referenced = getAsmReferencedSymbolVariables(ctx, definedLabels);
List<Comment> comments = ensureUnusedComments(getCommentsSymbol(ctx));
AsmClobber declaredClobber = null;
CpuClobber declaredClobber = null;
if(ctx.asmDirectives() != null) {
List<AsmDirective> asmDirectives = this.visitAsmDirectives(ctx.asmDirectives());
for(AsmDirective asmDirective : asmDirectives) {

View File

@ -1,7 +1,7 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.asm.AsmChunk;
import dk.camelot64.cpufamily6502.AsmClobber;
import dk.camelot64.cpufamily6502.CpuClobber;
import dk.camelot64.kickc.asm.AsmProgram;
import dk.camelot64.kickc.model.*;
import dk.camelot64.kickc.model.statements.*;
@ -29,7 +29,7 @@ public class Pass4AssertNoCpuClobber extends Pass2Base {
* @param clobber The clobber
* @return The clobbered CPU registers
*/
public static Collection<Registers.Register> getClobberRegisters(AsmClobber clobber) {
public static Collection<Registers.Register> getClobberRegisters(CpuClobber clobber) {
List<Registers.Register> clobberRegisters = new ArrayList<>();
if(clobber.isRegisterA()) {
clobberRegisters.add(Registers.getRegisterA());
@ -67,7 +67,7 @@ public class Pass4AssertNoCpuClobber extends Pass2Base {
int statementIdx = asmChunk.getStatementIdx();
Statement statement = getProgram().getStatementInfos().getStatement(statementIdx);
// Find the registered clobbered by the ASM asmChunk
AsmClobber asmChunkClobber = asmChunk.getClobber();
CpuClobber asmChunkClobber = asmChunk.getClobber();
Collection<Registers.Register> clobberRegisters = getClobberRegisters(asmChunkClobber);
// Find vars assigned to in the statement
Collection<VariableRef> assignedVars = Pass4RegisterUpliftPotentialRegisterAnalysis.getAssignedVars(statement);

View File

@ -1,7 +1,7 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.cpufamily6502.AsmAddressingMode;
import dk.camelot64.cpufamily6502.AsmClobber;
import dk.camelot64.cpufamily6502.CpuAddressingMode;
import dk.camelot64.cpufamily6502.CpuClobber;
import dk.camelot64.kickc.asm.*;
import dk.camelot64.kickc.fragment.*;
import dk.camelot64.kickc.model.InternalError;
@ -75,7 +75,7 @@ public class Pass4CodeGeneration {
}
public void generate() {
AsmProgram asm = new AsmProgram();
AsmProgram asm = new AsmProgram(program.getTargetCpu());
ScopeRef currentScope = ScopeRef.ROOT;
// Add file level comments
@ -156,14 +156,14 @@ public class Pass4CodeGeneration {
if(!transitionIsGenerated(transition)) {
genBlockPhiTransition(asm, block, defaultSuccessor, defaultSuccessor.getScope());
String label = AsmFormat.asmFix(defaultSuccessor.getLabel().getLocalName());
asm.addInstruction("JMP", AsmAddressingMode.ABS, label, false);
asm.addInstruction("JMP", CpuAddressingMode.ABS, label, false);
} else {
String label = AsmFormat.asmFix(defaultSuccessor.getLabel().getLocalName() + "_from_" + block.getLabel().getLocalName());
asm.addInstruction("JMP", AsmAddressingMode.ABS, label, false);
asm.addInstruction("JMP", CpuAddressingMode.ABS, label, false);
}
} else {
String label = AsmFormat.asmFix(defaultSuccessor.getLabel().getLocalName());
asm.addInstruction("JMP", AsmAddressingMode.ABS, label, false);
asm.addInstruction("JMP", CpuAddressingMode.ABS, label, false);
}
}
}
@ -215,7 +215,7 @@ public class Pass4CodeGeneration {
// Generate any indirect calls pending
for(String indirectCallAsmName : indirectCallAsmNames) {
asm.addLabel("bi_" + indirectCallAsmName);
asm.addInstruction("jmp", AsmAddressingMode.IND, indirectCallAsmName, false);
asm.addInstruction("jmp", CpuAddressingMode.IND, indirectCallAsmName, false);
}
indirectCallAsmNames = new ArrayList<>();
addData(asm, currentScope);
@ -233,7 +233,7 @@ public class Pass4CodeGeneration {
private void generateIndirectCall(AsmProgram asm, Variable procedureVariable, ScopeRef codeScopeRef) {
String varAsmName = AsmFormat.getAsmSymbolName(program, procedureVariable, codeScopeRef);
indirectCallAsmNames.add(varAsmName);
asm.addInstruction("jsr", AsmAddressingMode.ABS, "bi_" + varAsmName, false);
asm.addInstruction("jsr", CpuAddressingMode.ABS, "bi_" + varAsmName, false);
}
/**
@ -887,11 +887,11 @@ public class Pass4CodeGeneration {
}
}
}
asm.addInstruction("jsr", AsmAddressingMode.ABS, call.getProcedure().getFullName(), false);
asm.addInstruction("jsr", CpuAddressingMode.ABS, call.getProcedure().getFullName(), false);
} else if(statement instanceof StatementCallExecute) {
StatementCallExecute call = (StatementCallExecute) statement;
asm.getCurrentChunk().setFragment("jsr");
asm.addInstruction("jsr", AsmAddressingMode.ABS, call.getProcedure().getFullName(), false);
asm.addInstruction("jsr", CpuAddressingMode.ABS, call.getProcedure().getFullName(), false);
} else if(statement instanceof StatementExprSideEffect) {
AsmFragmentInstanceSpecFactory asmFragmentInstanceSpecFactory = new AsmFragmentInstanceSpecFactory((StatementExprSideEffect) statement, program);
ensureEncoding(asm, asmFragmentInstanceSpecFactory);
@ -903,14 +903,14 @@ public class Pass4CodeGeneration {
procedure = getScope().getProcedure((ProcedureRef) scope);
}
if(procedure == null || procedure.getInterruptType() == null) {
asm.addInstruction("rts", AsmAddressingMode.NON, null, false);
asm.addInstruction("rts", CpuAddressingMode.NON, null, false);
} else {
generateInterruptExit(asm, statement, procedure.getInterruptType());
}
} else if(statement instanceof StatementAsm) {
StatementAsm statementAsm = (StatementAsm) statement;
HashMap<String, Value> bindings = new HashMap<>();
AsmFragmentInstance asmFragmentInstance = new AsmFragmentInstance(program, "inline", block.getScope(), new AsmFragmentTemplate(statementAsm.getAsmLines()), bindings);
AsmFragmentInstance asmFragmentInstance = new AsmFragmentInstance(program, "inline", block.getScope(), new AsmFragmentTemplate(statementAsm.getAsmLines(), program.getTargetCpu()), bindings);
asmFragmentInstance.generate(asm);
AsmChunk currentChunk = asm.getCurrentChunk();
@ -920,8 +920,8 @@ public class Pass4CodeGeneration {
for(AsmLine asmLine : currentChunk.getLines()) {
if(asmLine instanceof AsmInstruction) {
AsmInstruction asmInstruction = (AsmInstruction) asmLine;
if(asmInstruction.getAsmOpcode().getMnemonic().equals("jsr")) {
currentChunk.setClobberOverwrite(AsmClobber.CLOBBER_ALL);
if(asmInstruction.getCpuOpcode().getMnemonic().equals("jsr")) {
currentChunk.setClobberOverwrite(CpuClobber.CLOBBER_ALL);
}
}
}
@ -940,7 +940,7 @@ public class Pass4CodeGeneration {
RValue pointer = ((PointerDereferenceSimple) procedure).getPointer();
if(pointer instanceof ConstantValue) {
ensureEncoding(asm, pointer);
asm.addInstruction("jsr", AsmAddressingMode.ABS, AsmFormat.getAsmConstant(program, (ConstantValue) pointer, 99, block.getScope()), false);
asm.addInstruction("jsr", CpuAddressingMode.ABS, AsmFormat.getAsmConstant(program, (ConstantValue) pointer, 99, block.getScope()), false);
supported = true;
} else if(pointer instanceof VariableRef) {
Variable variable = getScope().getVariable((VariableRef) pointer);
@ -966,13 +966,13 @@ public class Pass4CodeGeneration {
if(procedureVariableType instanceof SymbolTypePointer) {
if(((SymbolTypePointer) procedureVariableType).getElementType() instanceof SymbolTypeProcedure) {
String varAsmName = AsmFormat.getAsmSymbolName(program, procedureVariable, block.getScope());
asm.addInstruction("jsr", AsmAddressingMode.ABS, varAsmName, false);
asm.addInstruction("jsr", CpuAddressingMode.ABS, varAsmName, false);
supported = true;
}
}
}
if(supported) {
asm.getCurrentChunk().setClobberOverwrite(AsmClobber.CLOBBER_ALL);
asm.getCurrentChunk().setClobberOverwrite(CpuClobber.CLOBBER_ALL);
}
if(!supported) {
throw new InternalError("Call Pointer not supported " + statement);
@ -1030,21 +1030,21 @@ public class Pass4CodeGeneration {
} else if(Procedure.InterruptType.KERNEL_KEYBOARD.equals(interruptType)) {
// No entry ASM needed
} else if(Procedure.InterruptType.HARDWARE_ALL.equals(interruptType)) {
asm.addInstruction("sta", AsmAddressingMode.ABS, "rega+1", false).setDontOptimize(true);
asm.addInstruction("stx", AsmAddressingMode.ABS, "regx+1", false).setDontOptimize(true);
asm.addInstruction("sty", AsmAddressingMode.ABS, "regy+1", false).setDontOptimize(true);
asm.addInstruction("sta", CpuAddressingMode.ABS, "rega+1", false).setDontOptimize(true);
asm.addInstruction("stx", CpuAddressingMode.ABS, "regx+1", false).setDontOptimize(true);
asm.addInstruction("sty", CpuAddressingMode.ABS, "regy+1", false).setDontOptimize(true);
} else if(Procedure.InterruptType.HARDWARE_STACK.equals(interruptType)) {
asm.addInstruction("pha", AsmAddressingMode.NON, null, false).setDontOptimize(true);
asm.addInstruction("txa", AsmAddressingMode.NON, null, false).setDontOptimize(true);
asm.addInstruction("pha", AsmAddressingMode.NON, null, false).setDontOptimize(true);
asm.addInstruction("tya", AsmAddressingMode.NON, null, false).setDontOptimize(true);
asm.addInstruction("pha", AsmAddressingMode.NON, null, false).setDontOptimize(true);
asm.addInstruction("pha", CpuAddressingMode.NON, null, false).setDontOptimize(true);
asm.addInstruction("txa", CpuAddressingMode.NON, null, false).setDontOptimize(true);
asm.addInstruction("pha", CpuAddressingMode.NON, null, false).setDontOptimize(true);
asm.addInstruction("tya", CpuAddressingMode.NON, null, false).setDontOptimize(true);
asm.addInstruction("pha", CpuAddressingMode.NON, null, false).setDontOptimize(true);
} else if(Procedure.InterruptType.HARDWARE_NONE.equals(interruptType)) {
// No entry ASM needed
} else if(Procedure.InterruptType.HARDWARE_CLOBBER.equals(interruptType)) {
asm.addInstruction("sta", AsmAddressingMode.ABS, "rega+1", false).setDontOptimize(true);
asm.addInstruction("stx", AsmAddressingMode.ABS, "regx+1", false).setDontOptimize(true);
asm.addInstruction("sty", AsmAddressingMode.ABS, "regy+1", false).setDontOptimize(true);
asm.addInstruction("sta", CpuAddressingMode.ABS, "rega+1", false).setDontOptimize(true);
asm.addInstruction("stx", CpuAddressingMode.ABS, "regx+1", false).setDontOptimize(true);
asm.addInstruction("sty", CpuAddressingMode.ABS, "regy+1", false).setDontOptimize(true);
} else {
throw new RuntimeException("Interrupt Type not supported " + interruptType.name());
}
@ -1060,34 +1060,34 @@ public class Pass4CodeGeneration {
private void generateInterruptExit(AsmProgram asm, Statement statement, Procedure.InterruptType interruptType) {
asm.getCurrentChunk().setSource(asm.getCurrentChunk().getSource() + " - exit interrupt(" + interruptType.name() + ")");
if(Procedure.InterruptType.KERNEL_MIN.equals(interruptType)) {
asm.addInstruction("jmp", AsmAddressingMode.ABS, "$ea81", false);
asm.addInstruction("jmp", CpuAddressingMode.ABS, "$ea81", false);
} else if(Procedure.InterruptType.KERNEL_KEYBOARD.equals(interruptType)) {
asm.addInstruction("jmp", AsmAddressingMode.ABS, "$ea31", false);
asm.addInstruction("jmp", CpuAddressingMode.ABS, "$ea31", false);
} else if(Procedure.InterruptType.HARDWARE_ALL.equals(interruptType)) {
asm.addLabel("rega").setDontOptimize(true);
asm.addInstruction("lda", AsmAddressingMode.IMM, "00", false).setDontOptimize(true);
asm.addInstruction("lda", CpuAddressingMode.IMM, "00", false).setDontOptimize(true);
asm.addLabel("regx").setDontOptimize(true);
asm.addInstruction("ldx", AsmAddressingMode.IMM, "00", false).setDontOptimize(true);
asm.addInstruction("ldx", CpuAddressingMode.IMM, "00", false).setDontOptimize(true);
asm.addLabel("regy").setDontOptimize(true);
asm.addInstruction("ldy", AsmAddressingMode.IMM, "00", false).setDontOptimize(true);
asm.addInstruction("rti", AsmAddressingMode.NON, null, false);
asm.addInstruction("ldy", CpuAddressingMode.IMM, "00", false).setDontOptimize(true);
asm.addInstruction("rti", CpuAddressingMode.NON, null, false);
} else if(Procedure.InterruptType.HARDWARE_STACK.equals(interruptType)) {
asm.addInstruction("pla", AsmAddressingMode.NON, null, false).setDontOptimize(true);
asm.addInstruction("tay", AsmAddressingMode.NON, null, false).setDontOptimize(true);
asm.addInstruction("pla", AsmAddressingMode.NON, null, false).setDontOptimize(true);
asm.addInstruction("tax", AsmAddressingMode.NON, null, false).setDontOptimize(true);
asm.addInstruction("pla", AsmAddressingMode.NON, null, false).setDontOptimize(true);
asm.addInstruction("rti", AsmAddressingMode.NON, null, false);
asm.addInstruction("pla", CpuAddressingMode.NON, null, false).setDontOptimize(true);
asm.addInstruction("tay", CpuAddressingMode.NON, null, false).setDontOptimize(true);
asm.addInstruction("pla", CpuAddressingMode.NON, null, false).setDontOptimize(true);
asm.addInstruction("tax", CpuAddressingMode.NON, null, false).setDontOptimize(true);
asm.addInstruction("pla", CpuAddressingMode.NON, null, false).setDontOptimize(true);
asm.addInstruction("rti", CpuAddressingMode.NON, null, false);
} else if(Procedure.InterruptType.HARDWARE_NONE.equals(interruptType)) {
asm.addInstruction("rti", AsmAddressingMode.NON, null, false);
asm.addInstruction("rti", CpuAddressingMode.NON, null, false);
} else if(Procedure.InterruptType.HARDWARE_CLOBBER.equals(interruptType)) {
asm.addLabel("rega").setDontOptimize(true);
asm.addInstruction("lda", AsmAddressingMode.IMM, "00", false).setDontOptimize(true);
asm.addInstruction("lda", CpuAddressingMode.IMM, "00", false).setDontOptimize(true);
asm.addLabel("regx").setDontOptimize(true);
asm.addInstruction("ldx", AsmAddressingMode.IMM, "00", false).setDontOptimize(true);
asm.addInstruction("ldx", CpuAddressingMode.IMM, "00", false).setDontOptimize(true);
asm.addLabel("regy").setDontOptimize(true);
asm.addInstruction("ldy", AsmAddressingMode.IMM, "00", false).setDontOptimize(true);
asm.addInstruction("rti", AsmAddressingMode.NON, null, false);
asm.addInstruction("ldy", CpuAddressingMode.IMM, "00", false).setDontOptimize(true);
asm.addInstruction("rti", CpuAddressingMode.NON, null, false);
} else {
throw new RuntimeException("Interrupt Type not supported " + statement);
}
@ -1121,7 +1121,7 @@ public class Pass4CodeGeneration {
PhiTransitions.PhiTransition transition = transitions.getTransition(fromBlock);
if(!transitionIsGenerated(transition) && toBlock.getLabel().equals(fromBlock.getConditionalSuccessor())) {
genBlockPhiTransition(asm, fromBlock, toBlock, toBlock.getScope());
asm.addInstruction("JMP", AsmAddressingMode.ABS, AsmFormat.asmFix(toBlock.getLabel().getLocalName()), false);
asm.addInstruction("JMP", CpuAddressingMode.ABS, AsmFormat.asmFix(toBlock.getLabel().getLocalName()), false);
}
}
}

View File

@ -1,7 +1,7 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.asm.AsmChunk;
import dk.camelot64.cpufamily6502.AsmClobber;
import dk.camelot64.cpufamily6502.CpuClobber;
import dk.camelot64.kickc.asm.AsmLine;
import dk.camelot64.kickc.asm.AsmProgram;
import dk.camelot64.kickc.model.CallGraph;
@ -31,7 +31,7 @@ public class Pass4InterruptClobberFix extends Pass2Base {
if(Procedure.InterruptType.HARDWARE_CLOBBER.equals(procedure.getInterruptType())) {
// Find the interrupt routine clobber
AsmClobber procClobber = getProcedureClobber(procedure);
CpuClobber procClobber = getProcedureClobber(procedure);
getLog().append("Interrupt procedure "+procedure.getFullName()+" clobbers "+procClobber.toString());
// Find the entry/exit blocks for the interrupt
@ -68,17 +68,17 @@ public class Pass4InterruptClobberFix extends Pass2Base {
}
}
private AsmClobber getProcedureClobber(Procedure procedure) {
private CpuClobber getProcedureClobber(Procedure procedure) {
AsmProgram asm = getProgram().getAsm();
AsmClobber procClobber = new AsmClobber();
CpuClobber procClobber = new CpuClobber();
for(AsmChunk asmChunk : asm.getChunks()) {
if(procedure.getFullName().equals(asmChunk.getScopeLabel())) {
if(asmChunk.getSource().contains(Procedure.InterruptType.HARDWARE_CLOBBER.name())) {
// Do not count clobber in the entry/exit
continue;
}
AsmClobber chunkClobber = asmChunk.getClobber();
procClobber = new AsmClobber(procClobber, chunkClobber);
CpuClobber chunkClobber = asmChunk.getClobber();
procClobber = new CpuClobber(procClobber, chunkClobber);
}
}
@ -89,14 +89,14 @@ public class Pass4InterruptClobberFix extends Pass2Base {
ScopeRef calledProcLabel = call.getProcedure();
ProcedureRef calledProcRef = new ProcedureRef(calledProcLabel.getFullName());
Procedure calledProc = getProgram().getScope().getProcedure(calledProcRef);
AsmClobber calledClobber = getProcedureClobber(calledProc);
procClobber = new AsmClobber(procClobber, calledClobber);
CpuClobber calledClobber = getProcedureClobber(calledProc);
procClobber = new CpuClobber(procClobber, calledClobber);
}
return procClobber;
}
private List<String> getNonClobberedRegisterNames(AsmClobber procClobber) {
private List<String> getNonClobberedRegisterNames(CpuClobber procClobber) {
List<String> notClobberedRegisters = new ArrayList<>();
if(!procClobber.isRegisterA()) {
notClobberedRegisters.add("a");

View File

@ -1,6 +1,6 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.cpufamily6502.AsmClobber;
import dk.camelot64.cpufamily6502.CpuClobber;
import dk.camelot64.kickc.asm.AsmProgram;
import dk.camelot64.kickc.fragment.AsmFragmentInstance;
import dk.camelot64.kickc.fragment.AsmFragmentTemplateSynthesizer;
@ -167,7 +167,7 @@ public class Pass4RegisterUpliftPotentialRegisterAnalysis extends Pass2Base {
// Apply the combination
combination.allocate(getProgram());
// Generate ASM
AsmProgram asm = new AsmProgram();
AsmProgram asm = new AsmProgram(getProgram().getTargetCpu());
asm.startChunk(block.getScope(), statement.getIndex(), statement.toString(getProgram(), false));
Pass4CodeGeneration.AsmCodegenAluState aluState = new Pass4CodeGeneration.AsmCodegenAluState();
try {
@ -190,7 +190,7 @@ public class Pass4RegisterUpliftPotentialRegisterAnalysis extends Pass2Base {
}
continue;
}
AsmClobber clobber = asm.getClobber();
CpuClobber clobber = asm.getClobber();
Collection<Registers.Register> clobberRegisters = Pass4AssertNoCpuClobber.getClobberRegisters(clobber);
alwaysClobbered.removeIf(alwaysClobberRegister -> !clobberRegisters.contains(alwaysClobberRegister));
if(alwaysClobbered.isEmpty()) {

View File

@ -1,8 +1,9 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.cpufamily6502.AsmAddressingMode;
import dk.camelot64.cpufamily6502.AsmInstructionSet;
import dk.camelot64.kickc.asm.*;
import dk.camelot64.cpufamily6502.CpuAddressingMode;
import dk.camelot64.kickc.asm.AsmChunk;
import dk.camelot64.kickc.asm.AsmInstruction;
import dk.camelot64.kickc.asm.AsmLine;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.values.ScopeRef;
import dk.camelot64.kickc.model.values.SymbolRef;
@ -27,7 +28,7 @@ public class Pass5AddMainRts extends Pass5AsmOptimization {
AsmLine line = lineIterator.next();
if(line instanceof AsmInstruction) {
AsmInstruction instruction = (AsmInstruction) line;
if(instruction.getAsmOpcode().getMnemonic().equals("jsr")) {
if(instruction.getCpuOpcode().getMnemonic().equals("jsr")) {
if(instruction.getOperand1().equals(SymbolRef.MAIN_PROC_NAME)) {
// Add RTS if it is missing
if(!lineIterator.hasNext()) {
@ -40,7 +41,7 @@ public class Pass5AddMainRts extends Pass5AsmOptimization {
return true;
}
AsmInstruction nextInstruction = (AsmInstruction) nextLine;
if(!nextInstruction.getAsmOpcode().getMnemonic().equals("rts")) {
if(!nextInstruction.getCpuOpcode().getMnemonic().equals("rts")) {
addRts(lineIterator);
return true;
}
@ -54,7 +55,7 @@ public class Pass5AddMainRts extends Pass5AsmOptimization {
}
private void addRts(ListIterator<AsmLine> lineIterator) {
lineIterator.add(new AsmInstruction(AsmInstructionSet.getOpcode("rts", AsmAddressingMode.NON, false), null));
lineIterator.add(new AsmInstruction(getAsmProgram().getTargetCpu().getCpu65xx().getOpcode("rts", CpuAddressingMode.NON, false)));
getLog().append("Adding RTS to root block ");
}

View File

@ -1,8 +1,7 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.cpufamily6502.AsmAddressingMode;
import dk.camelot64.cpufamily6502.AsmInstructionSet;
import dk.camelot64.cpufamily6502.AsmOpcode;
import dk.camelot64.cpufamily6502.CpuAddressingMode;
import dk.camelot64.cpufamily6502.CpuOpcode;
import dk.camelot64.kickc.asm.*;
import dk.camelot64.kickc.model.Program;
@ -42,12 +41,12 @@ public class Pass5DoubleJumpElimination extends Pass5AsmOptimization {
} else if(line instanceof AsmInstruction) {
if(currentLabel != null) {
AsmInstruction asmInstruction = (AsmInstruction) line;
AsmOpcode jmpOpcode = AsmInstructionSet.getOpcode("jmp", AsmAddressingMode.ABS, false);
AsmOpcode rtsOpcode = AsmInstructionSet.getOpcode("rts", AsmAddressingMode.NON, false);
if(asmInstruction.getAsmOpcode().equals(jmpOpcode)) {
CpuOpcode jmpOpcode = getAsmProgram().getTargetCpu().getCpu65xx().getOpcode("jmp", CpuAddressingMode.ABS, false);
CpuOpcode rtsOpcode = getAsmProgram().getTargetCpu().getCpu65xx().getOpcode("rts", CpuAddressingMode.NON, false);
if(asmInstruction.getCpuOpcode().equals(jmpOpcode)) {
immediateJumps.put(currentScope + "::" + currentLabel, asmInstruction.getOperand1());
}
if(asmInstruction.getAsmOpcode().equals(rtsOpcode)) {
if(asmInstruction.getCpuOpcode().equals(rtsOpcode)) {
immediateJumps.put(currentScope + "::" + currentLabel, "rts");
}
}
@ -67,12 +66,12 @@ public class Pass5DoubleJumpElimination extends Pass5AsmOptimization {
currentScope = "";
} else if(line instanceof AsmInstruction) {
AsmInstruction asmInstruction = (AsmInstruction) line;
if(asmInstruction.getAsmOpcode().isJump()) {
if(asmInstruction.getCpuOpcode().isJump()) {
String jumpTarget = immediateJumps.get(currentScope + "::" + asmInstruction.getOperandJumpTarget());
if(jumpTarget == "rts" && asmInstruction.getAsmOpcode().getMnemonic() == "jmp") {
if(jumpTarget == "rts" && asmInstruction.getCpuOpcode().getMnemonic() == "jmp") {
getLog().append("Replacing jump to rts with rts in " + asmInstruction.toString());
AsmOpcode rtsOpcode = AsmInstructionSet.getOpcode("rts", AsmAddressingMode.NON, false);
asmInstruction.setAsmOpcode(rtsOpcode);
CpuOpcode rtsOpcode = getAsmProgram().getTargetCpu().getCpu65xx().getOpcode("rts", CpuAddressingMode.NON, false);
asmInstruction.setCpuOpcode(rtsOpcode);
asmInstruction.setOperand1(null);
asmInstruction.setOperand2(null);
optimized = true;

View File

@ -1,8 +1,7 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.cpufamily6502.AsmAddressingMode;
import dk.camelot64.cpufamily6502.AsmInstructionSet;
import dk.camelot64.cpufamily6502.AsmOpcode;
import dk.camelot64.cpufamily6502.CpuAddressingMode;
import dk.camelot64.cpufamily6502.CpuOpcode;
import dk.camelot64.kickc.asm.*;
import dk.camelot64.kickc.model.CompileError;
import dk.camelot64.kickc.model.Program;
@ -160,16 +159,16 @@ public class Pass5FixLongBranches extends Pass5AsmOptimization {
if(asmLine instanceof AsmInstruction) {
//getLog().append("Found ASM line "+asmLine);
AsmInstruction asmInstruction = (AsmInstruction) asmLine;
AsmOpcode asmOpcode = asmInstruction.getAsmOpcode();
AsmOpcode inverseAsmOpcode = invertBranch(asmOpcode);
if(inverseAsmOpcode != null) {
CpuOpcode cpuOpcode = asmInstruction.getCpuOpcode();
CpuOpcode inverseCpuOpcode = invertBranch(cpuOpcode);
if(inverseCpuOpcode != null) {
//getLog().append("Inversed branch instruction "+asmInstructionType.getMnemnonic()+" -> "+inverseType.getMnemnonic());
getLog().append("Fixing long branch [" + idx + "] " + asmLine.toString() + " to " + inverseAsmOpcode.getMnemonic());
getLog().append("Fixing long branch [" + idx + "] " + asmLine.toString() + " to " + inverseCpuOpcode.getMnemonic());
String branchDest = asmInstruction.getOperandJumpTarget();
asmInstruction.setAsmOpcode(inverseAsmOpcode);
asmInstruction.setCpuOpcode(inverseCpuOpcode);
String newLabel = AsmFormat.asmFix("!" + branchDest);
asmInstruction.setOperandJumpTarget(newLabel+"+");
AsmOpcode jmpOpcode = AsmInstructionSet.getOpcode("jmp", AsmAddressingMode.ABS, false);
CpuOpcode jmpOpcode = getAsmProgram().getTargetCpu().getCpu65xx().getOpcode("jmp", CpuAddressingMode.ABS, false);
AsmInstruction jmpInstruction = new AsmInstruction(jmpOpcode, branchDest);
asmChunk.addLineAfter(asmInstruction, jmpInstruction);
asmChunk.addLineAfter(jmpInstruction, new AsmLabel(newLabel));
@ -180,24 +179,24 @@ public class Pass5FixLongBranches extends Pass5AsmOptimization {
return false;
}
private AsmOpcode invertBranch(AsmOpcode asmOpcode) {
switch(asmOpcode.getMnemonic()) {
private CpuOpcode invertBranch(CpuOpcode cpuOpcode) {
switch(cpuOpcode.getMnemonic()) {
case "bcc":
return AsmInstructionSet.getOpcode("bcs", AsmAddressingMode.REL, false);
return getAsmProgram().getTargetCpu().getCpu65xx().getOpcode("bcs", CpuAddressingMode.REL, false);
case "bcs":
return AsmInstructionSet.getOpcode("bcc", AsmAddressingMode.REL, false);
return getAsmProgram().getTargetCpu().getCpu65xx().getOpcode("bcc", CpuAddressingMode.REL, false);
case "beq":
return AsmInstructionSet.getOpcode("bne", AsmAddressingMode.REL, false);
return getAsmProgram().getTargetCpu().getCpu65xx().getOpcode("bne", CpuAddressingMode.REL, false);
case "bne":
return AsmInstructionSet.getOpcode("beq", AsmAddressingMode.REL, false);
return getAsmProgram().getTargetCpu().getCpu65xx().getOpcode("beq", CpuAddressingMode.REL, false);
case "bpl":
return AsmInstructionSet.getOpcode("bmi", AsmAddressingMode.REL, false);
return getAsmProgram().getTargetCpu().getCpu65xx().getOpcode("bmi", CpuAddressingMode.REL, false);
case "bmi":
return AsmInstructionSet.getOpcode("bpl", AsmAddressingMode.REL, false);
return getAsmProgram().getTargetCpu().getCpu65xx().getOpcode("bpl", CpuAddressingMode.REL, false);
case "bvs":
return AsmInstructionSet.getOpcode("bvc", AsmAddressingMode.REL, false);
return getAsmProgram().getTargetCpu().getCpu65xx().getOpcode("bvc", CpuAddressingMode.REL, false);
case "bvc":
return AsmInstructionSet.getOpcode("bvs", AsmAddressingMode.REL, false);
return getAsmProgram().getTargetCpu().getCpu65xx().getOpcode("bvs", CpuAddressingMode.REL, false);
default:
return null;
}

View File

@ -33,7 +33,7 @@ public class Pass5NextJumpElimination extends Pass5AsmOptimization {
if(line instanceof AsmInstruction) {
candidate = null;
AsmInstruction instruction = (AsmInstruction) line;
if(instruction.getAsmOpcode().isJump() && !instruction.getAsmOpcode().getMnemonic().equals("jsr")) {
if(instruction.getCpuOpcode().isJump() && !instruction.getCpuOpcode().getMnemonic().equals("jsr")) {
candidate = instruction;
}
} else if(line instanceof AsmDataString || line instanceof AsmDataNumeric || line instanceof AsmDataZeroFill || line instanceof AsmInlineKickAsm ) {

View File

@ -38,7 +38,7 @@ public class Pass5RedundantLabelElimination extends Pass5AsmOptimization {
}
} else if(line instanceof AsmInstruction) {
AsmInstruction instruction = (AsmInstruction) line;
if(instruction.getAsmOpcode().isJump() && instruction.getOperandJumpTarget()!=null) {
if(instruction.getCpuOpcode().isJump() && instruction.getOperandJumpTarget()!=null) {
String labelStr = instruction.getOperandJumpTarget();
String labelReplacementStr = getLabelReplacement(redundantLabelSet, currentScope, labelStr);
if(labelReplacementStr!=null) {

View File

@ -95,7 +95,7 @@ public class Pass5RelabelLongLabels extends Pass5AsmOptimization {
}
} else if(asmLine instanceof AsmInstruction) {
AsmInstruction asmInstruction = (AsmInstruction) asmLine;
if(asmInstruction.getAsmOpcode().isJump()) {
if(asmInstruction.getCpuOpcode().isJump()) {
String parameter = asmInstruction.getOperandJumpTarget();
Map<String, String> scopeRelabels = relabels.get(currentScope);
if(scopeRelabels != null) {

View File

@ -41,7 +41,7 @@ public class Pass5SkipBegin extends Pass5AsmOptimization {
}
} else if(line instanceof AsmInstruction) {
AsmInstruction instruction = (AsmInstruction) line;
if(instruction.getAsmOpcode().getMnemonic().equals("jsr")) {
if(instruction.getCpuOpcode().getMnemonic().equals("jsr")) {
if(instruction.getOperandJumpTarget().equals(SymbolRef.MAIN_PROC_NAME)) {
lineIterator.remove();
optimized = true;

View File

@ -1,9 +1,11 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.cpufamily6502.AsmAddressingMode;
import dk.camelot64.cpufamily6502.AsmInstructionSet;
import dk.camelot64.cpufamily6502.AsmOpcode;
import dk.camelot64.kickc.asm.*;
import dk.camelot64.cpufamily6502.CpuAddressingMode;
import dk.camelot64.cpufamily6502.CpuOpcode;
import dk.camelot64.kickc.asm.AsmChunk;
import dk.camelot64.kickc.asm.AsmInstruction;
import dk.camelot64.kickc.asm.AsmLine;
import dk.camelot64.kickc.asm.AsmProgramStaticRegisterValues;
import dk.camelot64.kickc.model.Program;
import java.util.List;
@ -33,89 +35,89 @@ public class Pass5UnnecesaryLoadElimination extends Pass5AsmOptimization {
if(instruction.isDontOptimize()) {
continue;
}
AsmOpcode asmOpcode = instruction.getAsmOpcode();
CpuOpcode cpuOpcode = instruction.getCpuOpcode();
if(asmOpcode.getMnemonic().equals("lda") && asmOpcode.getAddressingMode().equals(AsmAddressingMode.IMM)) {
if(cpuOpcode.getMnemonic().equals("lda") && cpuOpcode.getAddressingMode().equals(CpuAddressingMode.IMM)) {
String immValue = instruction.getOperand1();
AsmProgramStaticRegisterValues.AsmRegisterValues instructionValues = staticValues.getValues(instruction);
if(AsmProgramStaticRegisterValues.matchImm(instructionValues.getA(), immValue)) {
modified = remove(lineIt);
} else if(AsmProgramStaticRegisterValues.matchImm(instructionValues.getX(), immValue)) {
getLog().append("Replacing instruction " + instruction + " with TXA");
instruction.setAsmOpcode(AsmInstructionSet.getOpcode("txa", AsmAddressingMode.NON, false));
instruction.setCpuOpcode(getAsmProgram().getTargetCpu().getCpu65xx().getOpcode("txa", CpuAddressingMode.NON, false));
instruction.setOperand1(null);
} else if(AsmProgramStaticRegisterValues.matchImm(instructionValues.getY(), immValue)) {
getLog().append("Replacing instruction " + instruction + " with TYA");
instruction.setAsmOpcode(AsmInstructionSet.getOpcode("tya", AsmAddressingMode.NON, false));
instruction.setCpuOpcode(getAsmProgram().getTargetCpu().getCpu65xx().getOpcode("tya", CpuAddressingMode.NON, false));
instruction.setOperand1(null);
}
}
if(asmOpcode.getMnemonic().equals("lda") && (asmOpcode.getAddressingMode().equals(AsmAddressingMode.ZP) || asmOpcode.getAddressingMode().equals(AsmAddressingMode.ABS))) {
if(cpuOpcode.getMnemonic().equals("lda") && (cpuOpcode.getAddressingMode().equals(CpuAddressingMode.ZP) || cpuOpcode.getAddressingMode().equals(CpuAddressingMode.ABS))) {
String memValue = instruction.getOperand1();
AsmProgramStaticRegisterValues.AsmRegisterValues instructionValues = staticValues.getValues(instruction);
if(instructionValues.getaMem() != null && instructionValues.getaMem().equals(memValue)) {
modified = remove(lineIt);
} else if(instructionValues.getxMem() != null && instructionValues.getxMem().equals(memValue)) {
getLog().append("Replacing instruction " + instruction + " with TXA");
instruction.setAsmOpcode(AsmInstructionSet.getOpcode("txa", AsmAddressingMode.NON, false));
instruction.setCpuOpcode(getAsmProgram().getTargetCpu().getCpu65xx().getOpcode("txa", CpuAddressingMode.NON, false));
instruction.setOperand1(null);
} else if(instructionValues.getyMem() != null && instructionValues.getyMem().equals(memValue)) {
getLog().append("Replacing instruction " + instruction + " with TYA");
instruction.setAsmOpcode(AsmInstructionSet.getOpcode("tya", AsmAddressingMode.NON, false));
instruction.setCpuOpcode(getAsmProgram().getTargetCpu().getCpu65xx().getOpcode("tya", CpuAddressingMode.NON, false));
instruction.setOperand1(null);
}
}
if(asmOpcode.getMnemonic().equals("ldx") && asmOpcode.getAddressingMode().equals(AsmAddressingMode.IMM)) {
if(cpuOpcode.getMnemonic().equals("ldx") && cpuOpcode.getAddressingMode().equals(CpuAddressingMode.IMM)) {
String immValue = instruction.getOperand1();
AsmProgramStaticRegisterValues.AsmRegisterValues instructionValues = staticValues.getValues(instruction);
if(AsmProgramStaticRegisterValues.matchImm(instructionValues.getX(), immValue)) {
modified = remove(lineIt);
} else if(AsmProgramStaticRegisterValues.matchImm(instructionValues.getA(), immValue)) {
getLog().append("Replacing instruction " + instruction + " with TAX");
instruction.setAsmOpcode(AsmInstructionSet.getOpcode("tax", AsmAddressingMode.NON, false));
instruction.setCpuOpcode(getAsmProgram().getTargetCpu().getCpu65xx().getOpcode("tax", CpuAddressingMode.NON, false));
instruction.setOperand1(null);
}
}
if(asmOpcode.getMnemonic().equals("ldx") && (asmOpcode.getAddressingMode().equals(AsmAddressingMode.ZP) || asmOpcode.getAddressingMode().equals(AsmAddressingMode.ABS))) {
if(cpuOpcode.getMnemonic().equals("ldx") && (cpuOpcode.getAddressingMode().equals(CpuAddressingMode.ZP) || cpuOpcode.getAddressingMode().equals(CpuAddressingMode.ABS))) {
String memValue = instruction.getOperand1();
AsmProgramStaticRegisterValues.AsmRegisterValues instructionValues = staticValues.getValues(instruction);
if(instructionValues.getxMem() != null && instructionValues.getxMem().equals(memValue)) {
modified = remove(lineIt);
} else if(instructionValues.getaMem() != null && instructionValues.getaMem().equals(memValue)) {
getLog().append("Replacing instruction " + instruction + " with TAX");
instruction.setAsmOpcode(AsmInstructionSet.getOpcode("tax", AsmAddressingMode.NON, false));
instruction.setCpuOpcode(getAsmProgram().getTargetCpu().getCpu65xx().getOpcode("tax", CpuAddressingMode.NON, false));
instruction.setOperand1(null);
}
}
if(asmOpcode.getMnemonic().equals("ldy") && asmOpcode.getAddressingMode().equals(AsmAddressingMode.IMM)) {
if(cpuOpcode.getMnemonic().equals("ldy") && cpuOpcode.getAddressingMode().equals(CpuAddressingMode.IMM)) {
String immValue = instruction.getOperand1();
AsmProgramStaticRegisterValues.AsmRegisterValues instructionValues = staticValues.getValues(instruction);
if(AsmProgramStaticRegisterValues.matchImm(instructionValues.getY(), immValue)) {
modified = remove(lineIt);
} else if(AsmProgramStaticRegisterValues.matchImm(instructionValues.getA(), immValue)) {
getLog().append("Replacing instruction " + instruction + " with TAY");
instruction.setAsmOpcode(AsmInstructionSet.getOpcode("tay", AsmAddressingMode.NON, false));
instruction.setCpuOpcode(getAsmProgram().getTargetCpu().getCpu65xx().getOpcode("tay", CpuAddressingMode.NON, false));
instruction.setOperand1(null);
}
}
if(asmOpcode.getMnemonic().equals("ldy") && (asmOpcode.getAddressingMode().equals(AsmAddressingMode.ZP) || asmOpcode.getAddressingMode().equals(AsmAddressingMode.ABS))) {
if(cpuOpcode.getMnemonic().equals("ldy") && (cpuOpcode.getAddressingMode().equals(CpuAddressingMode.ZP) || cpuOpcode.getAddressingMode().equals(CpuAddressingMode.ABS))) {
String memValue = instruction.getOperand1();
AsmProgramStaticRegisterValues.AsmRegisterValues instructionValues = staticValues.getValues(instruction);
if(instructionValues.getyMem() != null && instructionValues.getyMem().equals(memValue)) {
modified = remove(lineIt);
} else if(instructionValues.getaMem() != null && instructionValues.getaMem().equals(memValue)) {
getLog().append("Replacing instruction " + instruction + " with TAY");
instruction.setAsmOpcode(AsmInstructionSet.getOpcode("tay", AsmAddressingMode.NON, false));
instruction.setCpuOpcode(getAsmProgram().getTargetCpu().getCpu65xx().getOpcode("tay", CpuAddressingMode.NON, false));
instruction.setOperand1(null);
}
}
if(asmOpcode.getMnemonic().equals("clc")) {
if(cpuOpcode.getMnemonic().equals("clc")) {
AsmProgramStaticRegisterValues.AsmRegisterValues instructionValues = staticValues.getValues(instruction);
if(Boolean.FALSE.equals(instructionValues.getC())) {
modified = remove(lineIt);
}
}
if(asmOpcode.getMnemonic().equals("sec")) {
if(cpuOpcode.getMnemonic().equals("sec")) {
AsmProgramStaticRegisterValues.AsmRegisterValues instructionValues = staticValues.getValues(instruction);
if(Boolean.TRUE.equals(instructionValues.getC())) {
modified = remove(lineIt);

View File

@ -34,7 +34,7 @@ public class Pass5UnreachableCodeElimination extends Pass5AsmOptimization {
optimized = true;
} else {
AsmInstruction asmInstruction = (AsmInstruction) line;
if(asmInstruction.getAsmOpcode().getMnemonic().equals("rts") || asmInstruction.getAsmOpcode().getMnemonic().equals("jmp")) {
if(asmInstruction.getCpuOpcode().getMnemonic().equals("rts") || asmInstruction.getCpuOpcode().getMnemonic().equals("jmp")) {
afterExit = true;
}
}

View File

@ -41,7 +41,7 @@ public class Pass5UnusedLabelElimination extends Pass5AsmOptimization {
usedLabels.add(labelStr);
} else if(line instanceof AsmInstruction) {
AsmInstruction instruction = (AsmInstruction) line;
if(instruction.getAsmOpcode().isJump() && instruction.getOperandJumpTarget()!=null) {
if(instruction.getCpuOpcode().isJump() && instruction.getOperandJumpTarget()!=null) {
String labelStr = currentScope + "::" + instruction.getOperandJumpTarget();
usedLabels.add(labelStr);
}

View File

@ -43,8 +43,13 @@ public class TestPrograms {
}
@Test
public void testCpuAddressingModes() throws IOException, URISyntaxException {
compileAndCompare("cpu-addressing-modes.c");
public void testCpu65C02AddressingModes() throws IOException, URISyntaxException {
compileAndCompare("cpu-65c02-addressing-modes.c");
}
@Test
public void testCpu6502AddressingModes() throws IOException, URISyntaxException {
compileAndCompare("cpu-6502-addressing-modes.c");
}
@Test

View File

@ -0,0 +1,35 @@
// Tests the different ASM addressing modes
#pragma cpu(mos6502)
void main() {
asm {
// 6502:impl
inx
// 6502:im
lda #$12
// 6502:zp
lda $12
// 6502:zp,x
lda $12,x
// 6502:zp,y
ldx $12,y
// 6502:(zp,x)
lda ($12,x)
// 6502:(zp),y
lda ($12),y
// 6502:absolute
lda $1234
// 6502:abs,x
lda $1234,x
// 6502:abs,y
lda $1234,y
// 6502:relative
beq !+
// 6502:(abs))
jmp ($1234)
!:
}
}

View File

@ -0,0 +1,55 @@
// Tests the different ASM addressing modes
#pragma cpu(wdc65c02)
void main() {
asm {
// 6502:impl
inx
// 6502:imm
lda #$12
// 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
// 6502:absolute
lda $1234
// 6502:abs,x
lda $1234,x
// 6502:abs,y
lda $1234,y
// 6502:relative
beq lbl1
// 65C02: $12, rel
bbr0 $12,lbl2
lbl1:
// 6502:(abs)
jmp ($1234)
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))
}
}

View File

@ -1,33 +0,0 @@
// Tests the different ASM addressing modes
void main() {
asm {
// absolute indexed
lda $12,x
// Indirect
jmp ($1234)
// TODO Indirect Zeropage
// ora ($12)
// TODO: Indirect ABS,x
// jmp ($1234,x)
// TODO test relative
// lda $12, $1234
// 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

@ -0,0 +1,23 @@
// Tests the different ASM addressing modes
.cpu _6502NoIllegals
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
main: {
// asm
inx
lda #$12
lda.z $12
lda.z $12,x
ldx.z $12,y
lda ($12,x)
lda ($12),y
lda $1234
lda $1234,x
lda $1234,y
beq !+
jmp ($1234)
!:
// }
rts
}

View File

@ -1,7 +1,7 @@
(void()) main()
main: scope:[main] from
asm { lda$12,x jmp($1234) }
asm { inx lda#$12 lda$12 lda$12,x ldx$12,y lda($12,x) lda($12),y lda$1234 lda$1234,x lda$1234,y beq!+ jmp($1234) !: }
to:main::@return
main::@return: scope:[main] from main
[1] return

View File

@ -3,7 +3,7 @@ CONTROL FLOW GRAPH SSA
(void()) main()
main: scope:[main] from __start
asm { lda$12,x jmp($1234) }
asm { inx lda#$12 lda$12 lda$12,x ldx$12,y lda($12,x) lda($12),y lda$1234 lda$1234,x lda$1234,y beq!+ jmp($1234) !: }
to:main::@return
main::@return: scope:[main] from main
return
@ -40,7 +40,7 @@ FINAL CONTROL FLOW GRAPH
(void()) main()
main: scope:[main] from
asm { lda$12,x jmp($1234) }
asm { inx lda#$12 lda$12 lda$12,x ldx$12,y lda($12,x) lda($12),y lda$1234 lda$1234,x lda$1234,y beq!+ jmp($1234) !: }
to:main::@return
main::@return: scope:[main] from main
[1] return
@ -54,19 +54,31 @@ Initial phi equivalence classes
Complete equivalence classes
INITIAL ASM
Target platform is c64basic / MOS6502X
Target platform is c64basic / MOS6502
// File Comments
// Tests the different ASM addressing modes
// Upstart
.cpu _6502NoIllegals
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
// Global Constants & labels
// main
main: {
// asm { lda$12,x jmp($1234) }
// asm { inx lda#$12 lda$12 lda$12,x ldx$12,y lda($12,x) lda($12),y lda$1234 lda$1234,x lda$1234,y beq!+ jmp($1234) !: }
inx
lda #$12
lda.z $12
lda.z $12,x
ldx.z $12,y
lda ($12,x)
lda ($12),y
lda $1234
lda $1234,x
lda $1234,y
beq !+
jmp ($1234)
!:
jmp __breturn
// main::@return
__breturn:
@ -76,28 +88,40 @@ main: {
// File Data
REGISTER UPLIFT POTENTIAL REGISTERS
Statement asm { lda$12,x jmp($1234) } always clobbers reg byte a
Statement asm { inx lda#$12 lda$12 lda$12,x ldx$12,y lda($12,x) lda($12),y lda$1234 lda$1234,x lda$1234,y beq!+ jmp($1234) !: } always clobbers reg byte a reg byte x
REGISTER UPLIFT SCOPES
Uplift Scope [main]
Uplift Scope []
Uplifting [main] best 18 combination
Uplifting [] best 18 combination
Uplifting [main] best 56 combination
Uplifting [] best 56 combination
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
// Tests the different ASM addressing modes
// Upstart
.cpu _6502NoIllegals
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
// Global Constants & labels
// main
main: {
// asm { lda$12,x jmp($1234) }
// asm { inx lda#$12 lda$12 lda$12,x ldx$12,y lda($12,x) lda($12),y lda$1234 lda$1234,x lda$1234,y beq!+ jmp($1234) !: }
inx
lda #$12
lda.z $12
lda.z $12,x
ldx.z $12,y
lda ($12,x)
lda ($12),y
lda $1234
lda $1234,x
lda $1234,y
beq !+
jmp ($1234)
!:
jmp __breturn
// main::@return
__breturn:
@ -111,8 +135,6 @@ 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
(void()) main()
@ -121,11 +143,12 @@ FINAL SYMBOL TABLE
FINAL ASSEMBLER
Score: 9
Score: 53
// File Comments
// Tests the different ASM addressing modes
// Upstart
.cpu _6502NoIllegals
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
@ -133,12 +156,24 @@ Score: 9
// main
main: {
// asm
// asm { lda$12,x jmp($1234) }
// asm { inx lda#$12 lda$12 lda$12,x ldx$12,y lda($12,x) lda($12),y lda$1234 lda$1234,x lda$1234,y beq!+ jmp($1234) !: }
inx
lda #$12
lda.z $12
lda.z $12,x
ldx.z $12,y
lda ($12,x)
lda ($12),y
lda $1234
lda $1234,x
lda $1234,y
beq !+
jmp ($1234)
!:
// main::@return
// }
// [1] return
rts
}
// File Data

View File

@ -0,0 +1,26 @@
// Tests the different ASM addressing modes
.cpu _65c02
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
main: {
// asm
inx
lda #$12
lda.z $12
lda.z $12,x
ldx.z $12,y
ora.z ($12)
lda ($12,x)
lda ($12),y
lda $1234
lda $1234,x
lda $1234,y
beq lbl1
bbr0 $12,lbl2
lbl1:
jmp ($1234)
lbl2:
jmp ($1234,x)
// }
}

View File

@ -0,0 +1,8 @@
(void()) main()
main: scope:[main] from
asm { inx lda#$12 lda$12 lda$12,x ldx$12,y ora($12) lda($12,x) lda($12),y lda$1234 lda$1234,x lda$1234,y beqlbl1 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,192 @@
CONTROL FLOW GRAPH SSA
(void()) main()
main: scope:[main] from __start
asm { inx lda#$12 lda$12 lda$12,x ldx$12,y ora($12) lda($12,x) lda($12),y lda$1234 lda$1234,x lda$1234,y beqlbl1 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
(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 lda$12 lda$12,x ldx$12,y ora($12) lda($12,x) lda($12),y lda$1234 lda$1234,x lda$1234,y beqlbl1 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 / WDC65C02
// File Comments
// Tests the different ASM addressing modes
// Upstart
.cpu _65c02
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
// Global Constants & labels
// main
main: {
// asm { inx lda#$12 lda$12 lda$12,x ldx$12,y ora($12) lda($12,x) lda($12),y lda$1234 lda$1234,x lda$1234,y beqlbl1 bbr0$12,lbl2 lbl1: jmp($1234) lbl2: jmp($1234,x) }
inx
lda #$12
lda.z $12
lda.z $12,x
ldx.z $12,y
ora.z ($12)
lda ($12,x)
lda ($12),y
lda $1234
lda $1234,x
lda $1234,y
beq lbl1
bbr0 $12,lbl2
lbl1:
jmp ($1234)
lbl2:
jmp ($1234,x)
jmp __breturn
// main::@return
__breturn:
// [1] return
rts
}
// File Data
REGISTER UPLIFT POTENTIAL REGISTERS
Statement asm { inx lda#$12 lda$12 lda$12,x ldx$12,y ora($12) lda($12,x) lda($12),y lda$1234 lda$1234,x lda$1234,y beqlbl1 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 72 combination
Uplifting [] best 72 combination
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
// Tests the different ASM addressing modes
// Upstart
.cpu _65c02
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
// Global Constants & labels
// main
main: {
// asm { inx lda#$12 lda$12 lda$12,x ldx$12,y ora($12) lda($12,x) lda($12),y lda$1234 lda$1234,x lda$1234,y beqlbl1 bbr0$12,lbl2 lbl1: jmp($1234) lbl2: jmp($1234,x) }
inx
lda #$12
lda.z $12
lda.z $12,x
ldx.z $12,y
ora.z ($12)
lda ($12,x)
lda ($12),y
lda $1234
lda $1234,x
lda $1234,y
beq lbl1
bbr0 $12,lbl2
lbl1:
jmp ($1234)
lbl2:
jmp ($1234,x)
jmp __breturn
// main::@return
__breturn:
// [1] return
rts
}
// File Data
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
(void()) main()
(label) main::@return
FINAL ASSEMBLER
Score: 63
// File Comments
// Tests the different ASM addressing modes
// Upstart
.cpu _65c02
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
// Global Constants & labels
// main
main: {
// asm
// asm { inx lda#$12 lda$12 lda$12,x ldx$12,y ora($12) lda($12,x) lda($12),y lda$1234 lda$1234,x lda$1234,y beqlbl1 bbr0$12,lbl2 lbl1: jmp($1234) lbl2: jmp($1234,x) }
inx
lda #$12
lda.z $12
lda.z $12,x
ldx.z $12,y
ora.z ($12)
lda ($12,x)
lda ($12),y
lda $1234
lda $1234,x
lda $1234,y
beq lbl1
bbr0 $12,lbl2
lbl1:
jmp ($1234)
lbl2:
jmp ($1234,x)
// main::@return
// }
// [1] return
}
// File Data

View File

@ -0,0 +1,3 @@
(void()) main()
(label) main::@return

View File

@ -1,10 +0,0 @@
// Tests the different ASM addressing modes
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
main: {
// asm
lda.z $12,x
jmp ($1234)
// }
}