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:
parent
ba9f99059a
commit
1881fb17d0
@ -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);
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
108
src/main/java/dk/camelot64/cpufamily6502/Cpu65xx.java
Normal file
108
src/main/java/dk/camelot64/cpufamily6502/Cpu65xx.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
@ -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,
|
@ -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;
|
||||
}
|
||||
|
22
src/main/java/dk/camelot64/cpufamily6502/cpus/Cpu45GS02.java
Normal file
22
src/main/java/dk/camelot64/cpufamily6502/cpus/Cpu45GS02.java
Normal 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
|
||||
}
|
||||
|
||||
}
|
@ -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");
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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");
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
22
src/main/java/dk/camelot64/cpufamily6502/cpus/Cpu65CE02.java
Normal file
22
src/main/java/dk/camelot64/cpufamily6502/cpus/Cpu65CE02.java
Normal 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
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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");
|
||||
|
@ -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()) {
|
||||
|
@ -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 ");
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 ) {
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
35
src/test/kc/cpu-6502-addressing-modes.c
Normal file
35
src/test/kc/cpu-6502-addressing-modes.c
Normal 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)
|
||||
!:
|
||||
}
|
||||
|
||||
}
|
55
src/test/kc/cpu-65c02-addressing-modes.c
Normal file
55
src/test/kc/cpu-65c02-addressing-modes.c
Normal 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))
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -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))
|
||||
}
|
||||
|
||||
}
|
23
src/test/ref/cpu-6502-addressing-modes.asm
Normal file
23
src/test/ref/cpu-6502-addressing-modes.asm
Normal 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
|
||||
}
|
@ -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
|
@ -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
|
||||
|
26
src/test/ref/cpu-65c02-addressing-modes.asm
Normal file
26
src/test/ref/cpu-65c02-addressing-modes.asm
Normal 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)
|
||||
// }
|
||||
}
|
8
src/test/ref/cpu-65c02-addressing-modes.cfg
Normal file
8
src/test/ref/cpu-65c02-addressing-modes.cfg
Normal 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
|
192
src/test/ref/cpu-65c02-addressing-modes.log
Normal file
192
src/test/ref/cpu-65c02-addressing-modes.log
Normal 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
|
||||
|
3
src/test/ref/cpu-65c02-addressing-modes.sym
Normal file
3
src/test/ref/cpu-65c02-addressing-modes.sym
Normal file
@ -0,0 +1,3 @@
|
||||
(void()) main()
|
||||
(label) main::@return
|
||||
|
@ -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)
|
||||
// }
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user