mirror of
https://gitlab.com/camelot/kickc.git
synced 2024-11-25 20:32:25 +00:00
Moved 6502 family instruction set to separate java package.
This commit is contained in:
parent
f221865593
commit
676df5fc02
@ -1,4 +1,4 @@
|
||||
//KICKC FRAGMENT CACHE 161ce03ba6
|
||||
//KICKC FRAGMENT CACHE 15c356fca7
|
||||
//FRAGMENT vbuz1=vbuc1
|
||||
lda #{c1}
|
||||
sta {z1}
|
||||
|
140
src/main/java/dk/camelot64/cpufamily6502/AsmAddressingMode.java
Normal file
140
src/main/java/dk/camelot64/cpufamily6502/AsmAddressingMode.java
Normal file
@ -0,0 +1,140 @@
|
||||
package dk.camelot64.cpufamily6502;
|
||||
|
||||
/** 6502 Family Addressing Modes. */
|
||||
public enum AsmAddressingMode {
|
||||
|
||||
/**
|
||||
* None / Implied / Accumulator
|
||||
* IMPLIED ADDRESSING — In the implied addressing mode, the address containing the operand is implicitly stated in
|
||||
* the operation code of the instruction.
|
||||
* ACCUMULATOR ADDRESSING — This form of addressing is represented with a one byte instruction, implying an operation
|
||||
* on the accumulator"
|
||||
*/
|
||||
NON("", "%i", 1),
|
||||
/**
|
||||
* Immediate
|
||||
* IMMEDIATE ADDRESSING — In immediate addressing, the operand is contained in the second byte of the instruction,
|
||||
* with no further memory addressing required.
|
||||
*/
|
||||
IMM("#imm", "%i #%p", 2),
|
||||
/**
|
||||
* Zeropage
|
||||
* ZERO PAGE ADDRESSING — The zero page instructions allow for shorter code and execution times by only fetching the
|
||||
* second byte of the instruction and assuming a zero high address byte. Careful use of the zero page can result in
|
||||
* significant increase in code efficiency.
|
||||
*/
|
||||
ZP("zp", "%i.z %p", 2),
|
||||
/**
|
||||
* X Indexed Zeropage
|
||||
* INDEXED ZERO PAGE ADDRESSING - (X, Y indexing) — This form of addressing is used in conjunction with the index
|
||||
* register and is referred to as “Zero Page, X" or "Zero Page, Y.” The effective address is calculated by adding the
|
||||
* second byte to the contents of the index register. Since this is a form of "Zero Page" addressing, the content of
|
||||
* the second byte references a location in page zero. Additionally, due to the “Zero Page" addressing nature of this
|
||||
* mode, no carry is added to the high order 8 bits of memory and crossing of page boundaries does not occur.
|
||||
*/
|
||||
ZPX("zp,x", "%i.z %p,x", 2),
|
||||
/**
|
||||
* Y Indexed Zeropage
|
||||
* INDEXED ZERO PAGE ADDRESSING - (X, Y indexing) — This form of addressing is used in coniunction with the index
|
||||
* register and is referred to as “Zero Page, X" or "Zero Page, Y.” The effective address is calculated by adding
|
||||
* the second byte to the contents of the index register. Since this is a form of "Zero Page" addressing, the content
|
||||
* of the second byte references a location in page zero. Additionally, due to the “Zero Page" addressing nature of
|
||||
* this mode, no carry is added to the high order 8 bits of memory and crossing of page boundaries does not occur.
|
||||
*/
|
||||
ZPY("zp,y", "%i.z %p,y", 2),
|
||||
/**
|
||||
* Absolute
|
||||
* ABSOLUTE ADDRESSING — In absolute addressing, the second byte of the instruction specifies the eight low order
|
||||
* bits of the effective address while the third byte specifies the eight high order bits. Thus, the absolute
|
||||
* addressing mode allows access to the entire 65 K bytes of addressable memory.
|
||||
*/
|
||||
ABS("abs", "%i %p", 3),
|
||||
/**
|
||||
* Absolute X
|
||||
* INDEX ABSOLUTE ADDRESSING — (X, Y indexing) — This form of addressing is used in conjunction with X and Y index
|
||||
* register and is referred to as "Absolute. X," and “Absolute. Y." The effective address is formed by adding the
|
||||
* contents of X and Y to the address contained in the second and third bytes of the instruction. This mode allows
|
||||
* the index register to contain the index or count value and the instruction to contain the base address. This type
|
||||
* of indexing allows any location referencing and the index to modify multiple fields resulting in reduced coding
|
||||
* and execution time.
|
||||
*/
|
||||
ABX("abs,x", "%i %p,x", 3),
|
||||
/**
|
||||
* Absolute Y
|
||||
* INDEX ABSOLUTE ADDRESSING — (X, Y indexing) — This form of addressing is used in conjunction with X and Y index
|
||||
* register and is referred to as "Absolute. X," and “Absolute. Y." The effective address is formed by adding the
|
||||
* contents of X and Y to the address contained in the second and third bytes of the instruction. This mode allows the
|
||||
* index register to contain the index or count value and the instruction to contain the base address. This type of
|
||||
* indexing allows any location referencing and the index to modify multiple fields resulting in reduced coding and
|
||||
* execution time.
|
||||
*/
|
||||
ABY("abs,y", "%i %p,y", 4),
|
||||
/**
|
||||
* Indirect Zeropage X
|
||||
* INDEXED INDIRECT ADDRESSING - In indexed indirect addressing (referred to as [Indirect, X]), the second byte of
|
||||
* the instruction is added to the contents of the.X index register, discarding the carry. The result of this
|
||||
* addition points to a memory
|
||||
* location on page zero whose contents is the low order eight bits of the effective address. The next memory
|
||||
* location in page zero contains the high order eight bits of the effective address. Both memory locations
|
||||
* specifying the high and low order bytes of the effective address must be in page zero."
|
||||
*/
|
||||
IZX("(zp,x)", "%i (%p,x)", 2),
|
||||
/**
|
||||
* Indirect Zeropage Y
|
||||
* INDIRECT INDEXED ADDRESSING — In indirect indexed addressing (referred to as (Indirect, Y]), the second byte of
|
||||
* the instruction points to a memory location in page zero. The contents of this memory location is added to the
|
||||
* contents of the Y index register, the result being the low order eight bits of the effective
|
||||
* address. The carry from this addition is added to the contents of the next page zero memory location, the result
|
||||
* being the high order eight bits of the effective address."
|
||||
*/
|
||||
IZY("(zp),y", "%i (%p),y", 2),
|
||||
/**
|
||||
* Relative
|
||||
* RELATIVE ADDRESSING — Relative addressing is used only with branch instructions and establishes a destination for
|
||||
* the conditional branch. The second byte of-the instruction becomes the operand which is an “Offset"" added to the
|
||||
* contents of the lower eight bits of the program counter when the counter is set at the next instruction. The range
|
||||
* of the offset is — 128 to + 127 bytes from the next instruction."
|
||||
*/
|
||||
REL("rel", "%i %p", 2),
|
||||
/**
|
||||
* Indirect Absolute
|
||||
* ABSOLUTE INDIRECT — The second byte of the instruction contains the low order eight bits of a memory location.
|
||||
* The high order eight bits of that memory location is contained in the third byte of the instruction.
|
||||
* The contents of the fully specified memory location is the low order byte of the effective address.
|
||||
* The next memory location contains the high order byte of the effective address which is loaded into the sixteen
|
||||
* bits of the program counter.
|
||||
*/
|
||||
IND("(ind)", "%i (%p)", 3);
|
||||
|
||||
/** The short name of the addressing mode. */
|
||||
private String name;
|
||||
|
||||
/** The template for an instruction using the addressing mode. */
|
||||
private String template;
|
||||
|
||||
/** 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) {
|
||||
this.bytes = bytes;
|
||||
this.template = template;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getBytes() {
|
||||
return bytes;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getAsm(String mnemnonic, String parameter) {
|
||||
String replaced = template.replace("%i", mnemnonic);
|
||||
if(parameter != null) {
|
||||
replaced = replaced.replace("%p", parameter);
|
||||
}
|
||||
return replaced;
|
||||
}
|
||||
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package dk.camelot64.kickc.asm;
|
||||
package dk.camelot64.cpufamily6502;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
396
src/main/java/dk/camelot64/cpufamily6502/AsmInstructionSet.java
Normal file
396
src/main/java/dk/camelot64/cpufamily6502/AsmInstructionSet.java
Normal file
@ -0,0 +1,396 @@
|
||||
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);
|
||||
add(0x01, "ora", AsmAddressingMode.IZX, 6.0);
|
||||
add(0x02, "kil", AsmAddressingMode.NON, 0.0);
|
||||
add(0x03, "slo", AsmAddressingMode.IZX, 8.0);
|
||||
add(0x04, "nop", AsmAddressingMode.ZP, 3.0);
|
||||
add(0x05, "ora", AsmAddressingMode.ZP, 3.0);
|
||||
add(0x06, "asl", AsmAddressingMode.ZP, 5.0);
|
||||
add(0x07, "slo", AsmAddressingMode.ZP, 5.0);
|
||||
add(0x08, "php", AsmAddressingMode.NON, 3.0);
|
||||
add(0x09, "ora", AsmAddressingMode.IMM, 2.0);
|
||||
add(0x0a, "asl", AsmAddressingMode.NON, 2.0);
|
||||
add(0x0b, "anc", AsmAddressingMode.IMM, 2.0);
|
||||
add(0x0c, "nop", AsmAddressingMode.ABS, 4.0);
|
||||
add(0x0d, "ora", AsmAddressingMode.ABS, 4.0);
|
||||
add(0x0e, "asl", AsmAddressingMode.ABS, 6.0);
|
||||
add(0x0f, "slo", AsmAddressingMode.ABS, 6.0);
|
||||
add(0x10, "bpl", AsmAddressingMode.REL, 2.5);
|
||||
add(0x11, "ora", AsmAddressingMode.IZY, 5.5);
|
||||
add(0x12, "kil", AsmAddressingMode.NON, 0.0);
|
||||
add(0x13, "slo", AsmAddressingMode.IZY, 8.0);
|
||||
add(0x14, "nop", AsmAddressingMode.ZPX, 4.0);
|
||||
add(0x15, "ora", AsmAddressingMode.ZPX, 4.0);
|
||||
add(0x16, "asl", AsmAddressingMode.ZPX, 6.0);
|
||||
add(0x17, "slo", AsmAddressingMode.ZPX, 6.0);
|
||||
add(0x18, "clc", AsmAddressingMode.NON, 2.0);
|
||||
add(0x19, "ora", AsmAddressingMode.ABY, 4.5);
|
||||
add(0x1a, "nop", AsmAddressingMode.NON, 2.0);
|
||||
add(0x1b, "slo", AsmAddressingMode.ABY, 7.0);
|
||||
add(0x1c, "nop", AsmAddressingMode.ABX, 4.5);
|
||||
add(0x1d, "ora", AsmAddressingMode.ABX, 4.5);
|
||||
add(0x1e, "asl", AsmAddressingMode.ABX, 7.0);
|
||||
add(0x1f, "slo", AsmAddressingMode.ABX, 7.0);
|
||||
add(0x20, "jsr", AsmAddressingMode.ABS, 6.0);
|
||||
add(0x21, "and", AsmAddressingMode.IZX, 6.0);
|
||||
add(0x22, "kil", AsmAddressingMode.NON, 0.0);
|
||||
add(0x23, "rla", AsmAddressingMode.IZX, 8.0);
|
||||
add(0x24, "bit", AsmAddressingMode.ZP, 3.0);
|
||||
add(0x25, "and", AsmAddressingMode.ZP, 3.0);
|
||||
add(0x26, "rol", AsmAddressingMode.ZP, 5.0);
|
||||
add(0x27, "rla", AsmAddressingMode.ZP, 5.0);
|
||||
add(0x28, "plp", AsmAddressingMode.NON, 4.0);
|
||||
add(0x29, "and", AsmAddressingMode.IMM, 2.0);
|
||||
add(0x2a, "rol", AsmAddressingMode.NON, 2.0);
|
||||
add(0x2b, "anc", AsmAddressingMode.IMM, 2.0);
|
||||
add(0x2c, "bit", AsmAddressingMode.ABS, 4.0);
|
||||
add(0x2d, "and", AsmAddressingMode.ABS, 4.0);
|
||||
add(0x2e, "rol", AsmAddressingMode.ABS, 6.0);
|
||||
add(0x2f, "rla", AsmAddressingMode.ABS, 6.0);
|
||||
add(0x30, "bmi", AsmAddressingMode.REL, 2.5);
|
||||
add(0x31, "and", AsmAddressingMode.IZY, 5.5);
|
||||
add(0x32, "kil", AsmAddressingMode.NON, 0.0);
|
||||
add(0x33, "rla", AsmAddressingMode.IZY, 8.0);
|
||||
add(0x34, "nop", AsmAddressingMode.ZPX, 4.0);
|
||||
add(0x35, "and", AsmAddressingMode.ZPX, 4.0);
|
||||
add(0x36, "rol", AsmAddressingMode.ZPX, 6.0);
|
||||
add(0x37, "rla", AsmAddressingMode.ZPX, 6.0);
|
||||
add(0x38, "sec", AsmAddressingMode.NON, 2.0);
|
||||
add(0x39, "and", AsmAddressingMode.ABY, 4.5);
|
||||
add(0x3a, "nop", AsmAddressingMode.NON, 2.0);
|
||||
add(0x3b, "rla", AsmAddressingMode.ABY, 7.0);
|
||||
add(0x3c, "nop", AsmAddressingMode.ABX, 4.5);
|
||||
add(0x3d, "and", AsmAddressingMode.ABX, 4.5);
|
||||
add(0x3e, "rol", AsmAddressingMode.ABX, 7.0);
|
||||
add(0x3f, "rla", AsmAddressingMode.ABX, 7.0);
|
||||
add(0x40, "rti", AsmAddressingMode.NON, 6.0);
|
||||
add(0x41, "eor", AsmAddressingMode.IZX, 6.0);
|
||||
add(0x42, "kil", AsmAddressingMode.NON, 0.0);
|
||||
add(0x43, "sre", AsmAddressingMode.IZX, 8.0);
|
||||
add(0x44, "nop", AsmAddressingMode.ZP, 3.0);
|
||||
add(0x45, "eor", AsmAddressingMode.ZP, 3.0);
|
||||
add(0x46, "lsr", AsmAddressingMode.ZP, 5.0);
|
||||
add(0x47, "sre", AsmAddressingMode.ZP, 5.0);
|
||||
add(0x48, "pha", AsmAddressingMode.NON, 3.0);
|
||||
add(0x49, "eor", AsmAddressingMode.IMM, 2.0);
|
||||
add(0x4a, "lsr", AsmAddressingMode.NON, 2.0);
|
||||
add(0x4b, "alr", AsmAddressingMode.IMM, 2.0);
|
||||
add(0x4c, "jmp", AsmAddressingMode.ABS, 3.0);
|
||||
add(0x4d, "eor", AsmAddressingMode.ABS, 4.0);
|
||||
add(0x4e, "lsr", AsmAddressingMode.ABS, 6.0);
|
||||
add(0x4f, "sre", AsmAddressingMode.ABS, 6.0);
|
||||
add(0x50, "bvc", AsmAddressingMode.REL, 2.5);
|
||||
add(0x51, "eor", AsmAddressingMode.IZY, 5.5);
|
||||
add(0x52, "kil", AsmAddressingMode.NON, 0.0);
|
||||
add(0x53, "sre", AsmAddressingMode.IZY, 8.0);
|
||||
add(0x54, "nop", AsmAddressingMode.ZPX, 4.0);
|
||||
add(0x55, "eor", AsmAddressingMode.ZPX, 4.0);
|
||||
add(0x56, "lsr", AsmAddressingMode.ZPX, 6.0);
|
||||
add(0x57, "sre", AsmAddressingMode.ZPX, 6.0);
|
||||
add(0x58, "cli", AsmAddressingMode.NON, 2.0);
|
||||
add(0x59, "eor", AsmAddressingMode.ABY, 4.5);
|
||||
add(0x5a, "nop", AsmAddressingMode.NON, 2.0);
|
||||
add(0x5b, "sre", AsmAddressingMode.ABY, 7.0);
|
||||
add(0x5c, "nop", AsmAddressingMode.ABX, 4.5);
|
||||
add(0x5d, "eor", AsmAddressingMode.ABX, 4.5);
|
||||
add(0x5e, "lsr", AsmAddressingMode.ABX, 7.0);
|
||||
add(0x5f, "sre", AsmAddressingMode.ABX, 7.0);
|
||||
add(0x60, "rts", AsmAddressingMode.NON, 6.0);
|
||||
add(0x61, "adc", AsmAddressingMode.IZX, 6.0);
|
||||
add(0x62, "kil", AsmAddressingMode.NON, 0.0);
|
||||
add(0x63, "rra", AsmAddressingMode.IZX, 8.0);
|
||||
add(0x64, "nop", AsmAddressingMode.ZP, 3.0);
|
||||
add(0x65, "adc", AsmAddressingMode.ZP, 3.0);
|
||||
add(0x66, "ror", AsmAddressingMode.ZP, 5.0);
|
||||
add(0x67, "rra", AsmAddressingMode.ZP, 5.0);
|
||||
add(0x68, "pla", AsmAddressingMode.NON, 4.0);
|
||||
add(0x69, "adc", AsmAddressingMode.IMM, 2.0);
|
||||
add(0x6a, "ror", AsmAddressingMode.NON, 2.0);
|
||||
add(0x6b, "arr", AsmAddressingMode.IMM, 2.0);
|
||||
add(0x6c, "jmp", AsmAddressingMode.IND, 5.0);
|
||||
add(0x6d, "adc", AsmAddressingMode.ABS, 4.0);
|
||||
add(0x6e, "ror", AsmAddressingMode.ABS, 6.0);
|
||||
add(0x6f, "rra", AsmAddressingMode.ABS, 6.0);
|
||||
add(0x70, "bvs", AsmAddressingMode.REL, 2.5);
|
||||
add(0x71, "adc", AsmAddressingMode.IZY, 5.5);
|
||||
add(0x72, "kil", AsmAddressingMode.NON, 0.0);
|
||||
add(0x73, "rra", AsmAddressingMode.IZY, 8.0);
|
||||
add(0x74, "nop", AsmAddressingMode.ZPX, 4.0);
|
||||
add(0x75, "adc", AsmAddressingMode.ZPX, 4.0);
|
||||
add(0x76, "ror", AsmAddressingMode.ZPX, 6.0);
|
||||
add(0x77, "rra", AsmAddressingMode.ZPX, 6.0);
|
||||
add(0x78, "sei", AsmAddressingMode.NON, 2.0);
|
||||
add(0x79, "adc", AsmAddressingMode.ABY, 4.5);
|
||||
add(0x7a, "nop", AsmAddressingMode.NON, 2.0);
|
||||
add(0x7b, "rra", AsmAddressingMode.ABY, 7.0);
|
||||
add(0x7c, "nop", AsmAddressingMode.ABX, 4.5);
|
||||
add(0x7d, "adc", AsmAddressingMode.ABX, 4.5);
|
||||
add(0x7e, "ror", AsmAddressingMode.ABX, 7.0);
|
||||
add(0x7f, "rra", AsmAddressingMode.ABX, 7.0);
|
||||
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);
|
||||
add(0x89, "nop", AsmAddressingMode.IMM, 2.0);
|
||||
add(0x8a, "txa", AsmAddressingMode.NON, 2.0);
|
||||
add(0x8b, "xaa", AsmAddressingMode.IMM, 2.0);
|
||||
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);
|
||||
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);
|
||||
add(0x99, "sta", AsmAddressingMode.ABY, 5.0);
|
||||
add(0x9a, "txs", AsmAddressingMode.NON, 2.0);
|
||||
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);
|
||||
add(0xa1, "lda", AsmAddressingMode.IZX, 6.0);
|
||||
add(0xa2, "ldx", AsmAddressingMode.IMM, 2.0);
|
||||
add(0xa3, "lax", AsmAddressingMode.IZX, 6.0);
|
||||
add(0xa4, "ldy", AsmAddressingMode.ZP, 3.0);
|
||||
add(0xa5, "lda", AsmAddressingMode.ZP, 3.0);
|
||||
add(0xa6, "ldx", AsmAddressingMode.ZP, 3.0);
|
||||
add(0xa7, "lax", AsmAddressingMode.ZP, 3.0);
|
||||
add(0xa8, "tay", AsmAddressingMode.NON, 2.0);
|
||||
add(0xa9, "lda", AsmAddressingMode.IMM, 2.0);
|
||||
add(0xaa, "tax", AsmAddressingMode.NON, 2.0);
|
||||
add(0xab, "lax", AsmAddressingMode.IMM, 2.0);
|
||||
add(0xac, "ldy", AsmAddressingMode.ABS, 4.0);
|
||||
add(0xad, "lda", AsmAddressingMode.ABS, 4.0);
|
||||
add(0xae, "ldx", AsmAddressingMode.ABS, 4.0);
|
||||
add(0xaf, "lax", AsmAddressingMode.ABS, 4.0);
|
||||
add(0xb0, "bcs", AsmAddressingMode.REL, 2.5);
|
||||
add(0xb1, "lda", AsmAddressingMode.IZY, 5.5);
|
||||
add(0xb2, "kil", AsmAddressingMode.NON, 0.0);
|
||||
add(0xb3, "lax", AsmAddressingMode.IZY, 5.5);
|
||||
add(0xb4, "ldy", AsmAddressingMode.ZPX, 4.0);
|
||||
add(0xb5, "lda", AsmAddressingMode.ZPX, 4.0);
|
||||
add(0xb6, "ldx", AsmAddressingMode.ZPY, 4.0);
|
||||
add(0xb7, "lax", AsmAddressingMode.ZPY, 4.0);
|
||||
add(0xb8, "clv", AsmAddressingMode.NON, 2.0);
|
||||
add(0xb9, "lda", AsmAddressingMode.ABY, 4.5);
|
||||
add(0xba, "tsx", AsmAddressingMode.NON, 2.0);
|
||||
add(0xbb, "las", AsmAddressingMode.ABY, 4.5);
|
||||
add(0xbc, "ldy", AsmAddressingMode.ABX, 4.5);
|
||||
add(0xbd, "lda", AsmAddressingMode.ABX, 4.5);
|
||||
add(0xbe, "ldx", AsmAddressingMode.ABY, 4.5);
|
||||
add(0xbf, "lax", AsmAddressingMode.ABY, 4.5);
|
||||
add(0xc0, "cpy", AsmAddressingMode.IMM, 2.0);
|
||||
add(0xc1, "cmp", AsmAddressingMode.IZX, 6.0);
|
||||
add(0xc2, "nop", AsmAddressingMode.IMM, 2.0);
|
||||
add(0xc3, "dcp", AsmAddressingMode.IZX, 8.0);
|
||||
add(0xc4, "cpy", AsmAddressingMode.ZP, 3.0);
|
||||
add(0xc5, "cmp", AsmAddressingMode.ZP, 3.0);
|
||||
add(0xc6, "dec", AsmAddressingMode.ZP, 5.0);
|
||||
add(0xc7, "dcp", AsmAddressingMode.ZP, 5.0);
|
||||
add(0xc8, "iny", AsmAddressingMode.NON, 2.0);
|
||||
add(0xc9, "cmp", AsmAddressingMode.IMM, 2.0);
|
||||
add(0xca, "dex", AsmAddressingMode.NON, 2.0);
|
||||
add(0xcb, "axs", AsmAddressingMode.IMM, 2.0);
|
||||
add(0xcc, "cpy", AsmAddressingMode.ABS, 4.0);
|
||||
add(0xcd, "cmp", AsmAddressingMode.ABS, 4.0);
|
||||
add(0xce, "dec", AsmAddressingMode.ABS, 6.0);
|
||||
add(0xcf, "dcp", AsmAddressingMode.ABS, 6.0);
|
||||
add(0xd0, "bne", AsmAddressingMode.REL, 2.5);
|
||||
add(0xd1, "cmp", AsmAddressingMode.IZY, 5.5);
|
||||
add(0xd2, "kil", AsmAddressingMode.NON, 0.0);
|
||||
add(0xd3, "dcp", AsmAddressingMode.IZY, 8.0);
|
||||
add(0xd4, "nop", AsmAddressingMode.ZPX, 4.0);
|
||||
add(0xd5, "cmp", AsmAddressingMode.ZPX, 4.0);
|
||||
add(0xd6, "dec", AsmAddressingMode.ZPX, 6.0);
|
||||
add(0xd7, "dcp", AsmAddressingMode.ZPX, 6.0);
|
||||
add(0xd8, "cld", AsmAddressingMode.NON, 2.0);
|
||||
add(0xd9, "cmp", AsmAddressingMode.ABY, 4.5);
|
||||
add(0xda, "nop", AsmAddressingMode.NON, 2.0);
|
||||
add(0xdb, "dcp", AsmAddressingMode.ABY, 7.0);
|
||||
add(0xdc, "nop", AsmAddressingMode.ABX, 4.5);
|
||||
add(0xdd, "cmp", AsmAddressingMode.ABX, 4.5);
|
||||
add(0xde, "dec", AsmAddressingMode.ABX, 7.0);
|
||||
add(0xef, "cpx", AsmAddressingMode.IMM, 2.0);
|
||||
add(0xe0, "sbc", AsmAddressingMode.IZX, 6.0);
|
||||
add(0xe1, "nop", AsmAddressingMode.IMM, 2.0);
|
||||
add(0xe2, "isc", AsmAddressingMode.IZX, 8.0);
|
||||
add(0xe3, "cpx", AsmAddressingMode.ZP, 3.0);
|
||||
add(0xe4, "sbc", AsmAddressingMode.ZP, 3.0);
|
||||
add(0xe5, "inc", AsmAddressingMode.ZP, 5.0);
|
||||
add(0xe6, "isc", AsmAddressingMode.ZP, 5.0);
|
||||
add(0xe7, "inx", AsmAddressingMode.NON, 2.0);
|
||||
add(0xe8, "sbc", AsmAddressingMode.IMM, 2.0);
|
||||
add(0xe9, "nop", AsmAddressingMode.NON, 2.0);
|
||||
add(0xea, "sbc", AsmAddressingMode.IMM, 2.0);
|
||||
add(0xeb, "cpx", AsmAddressingMode.ABS, 4.0);
|
||||
add(0xec, "sbc", AsmAddressingMode.ABS, 4.0);
|
||||
add(0xed, "inc", AsmAddressingMode.ABS, 6.0);
|
||||
add(0xee, "isc", AsmAddressingMode.ABS, 6.0);
|
||||
add(0xef, "dcp", AsmAddressingMode.ABX, 7.0);
|
||||
add(0xf0, "beq", AsmAddressingMode.REL, 2.5);
|
||||
add(0xf1, "sbc", AsmAddressingMode.IZY, 5.5);
|
||||
add(0xf2, "kil", AsmAddressingMode.NON, 0.0);
|
||||
add(0xf3, "isc", AsmAddressingMode.IZY, 8.0);
|
||||
add(0xf4, "nop", AsmAddressingMode.ZPX, 4.0);
|
||||
add(0xf5, "sbc", AsmAddressingMode.ZPX, 4.0);
|
||||
add(0xf6, "inc", AsmAddressingMode.ZPX, 6.0);
|
||||
add(0xf7, "isc", AsmAddressingMode.ZPX, 6.0);
|
||||
add(0xf8, "sed", AsmAddressingMode.NON, 2.0);
|
||||
add(0xf9, "sbc", AsmAddressingMode.ABY, 4.5);
|
||||
add(0xfa, "nop", AsmAddressingMode.NON, 2.0);
|
||||
add(0xfb, "isc", AsmAddressingMode.ABY, 7.0);
|
||||
add(0xfc, "nop", AsmAddressingMode.ABX, 4.5);
|
||||
add(0xfd, "sbc", AsmAddressingMode.ABX, 4.5);
|
||||
add(0xfe, "inc", AsmAddressingMode.ABX, 7.0);
|
||||
add(0xff, "isc", AsmAddressingMode.ABX, 7.0);
|
||||
|
||||
// 65c02 instructions
|
||||
// TODO: create instruction set model that knows the different CPU's
|
||||
add(0x1a, "inc", AsmAddressingMode.NON, 2.0);
|
||||
|
||||
List<String> jumps = Arrays.asList("jmp", "beq", "bne", "bcc", "bcs", "bvs", "bvc", "bmi", "bpl", "jsr");
|
||||
for(AsmOpcode instruction : instructions) {
|
||||
if(jumps.contains(instruction.getMnemnonic())) {
|
||||
instruction.setJump(true);
|
||||
}
|
||||
}
|
||||
List<String> cxs = Arrays.asList("dex", "inx", "ldx", "tax", "tsx", "las", "lax", "axs");
|
||||
for(AsmOpcode instruction : instructions) {
|
||||
if(cxs.contains(instruction.getMnemnonic())) {
|
||||
instruction.getClobber().setClobberX(true);
|
||||
}
|
||||
}
|
||||
List<String> cys = Arrays.asList("dey", "iny", "ldy", "tay");
|
||||
for(AsmOpcode instruction : instructions) {
|
||||
if(cys.contains(instruction.getMnemnonic())) {
|
||||
instruction.getClobber().setClobberY(true);
|
||||
}
|
||||
}
|
||||
List<String> cas = Arrays.asList("ora", "and", "eor", "adc", "sbc", "lda", "txa", "tya", "pla", "slo", "rla", "sre", "rra", "isc", "anc", "alr", "arr", "xaa", "lax", "las");
|
||||
for(AsmOpcode instruction : instructions) {
|
||||
if(cas.contains(instruction.getMnemnonic())) {
|
||||
instruction.getClobber().setClobberA(true);
|
||||
} else if(instruction.getOpcode()==0x0a) {
|
||||
// Special handling of ASL A
|
||||
instruction.getClobber().setClobberA(true);
|
||||
} else if(instruction.getOpcode()==0x2a) {
|
||||
// Special handling of ROL A
|
||||
instruction.getClobber().setClobberA(true);
|
||||
} else if(instruction.getOpcode()==0x4a) {
|
||||
// Special handling of LSR A
|
||||
instruction.getClobber().setClobberA(true);
|
||||
} else if(instruction.getOpcode()==0x6a) {
|
||||
// Special handling of ROR A
|
||||
instruction.getClobber().setClobberA(true);
|
||||
}
|
||||
|
||||
}
|
||||
List<String> ccs = Arrays.asList("adc", "sbc", "cmp", "cpx", "cpy", "asl", "rol", "lsr", "ror", "plp", "rti", "clc", "sec", "slo", "rla", "sre", "rra", "dcp", "isc", "anc", "alr", "arr", "axs");
|
||||
for(AsmOpcode instruction : instructions) {
|
||||
if(ccs.contains(instruction.getMnemnonic())) {
|
||||
instruction.getClobber().setClobberC(true);
|
||||
}
|
||||
}
|
||||
List<String> cvs = Arrays.asList("adc", "sbc", "plp", "rti", "bit", "rra", "isc", "arr");
|
||||
for(AsmOpcode instruction : instructions) {
|
||||
if(cvs.contains(instruction.getMnemnonic())) {
|
||||
instruction.getClobber().setClobberV(true);
|
||||
}
|
||||
}
|
||||
List<String> czs = Arrays.asList("ora", "and", "eor", "adc", "sbc", "cmp", "cpx", "cpy", "dec", "dex", "dey", "inc", "inx", "iny", "asl", "rol", "lsr", "ror", "lda", "ldx", "ldy", "tax", "txa", "tay", "tya", "tsx", "txs", "pla", "plp", "rti", "bit", "slo", "rla", "sre", "rra", "lax", "dcp", "isc", "anc", "alr", "arr", "xaa", "lax", "axs", "las");
|
||||
for(AsmOpcode instruction : instructions) {
|
||||
if(czs.contains(instruction.getMnemnonic())) {
|
||||
instruction.getClobber().setClobberZ(true);
|
||||
instruction.getClobber().setClobberN(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add an instruction to the instruction set.
|
||||
* @param opcode The numeric opcode
|
||||
* @param mnemonic The lower case mnemonic
|
||||
* @param addressingmMode The addressing mode
|
||||
* @param cycles The number of cycles
|
||||
*/
|
||||
private void add(int opcode, String mnemonic, AsmAddressingMode addressingmMode, double cycles) {
|
||||
AsmOpcode instructionType = new AsmOpcode(opcode, mnemonic, addressingmMode, cycles);
|
||||
instructions.add(instructionType);
|
||||
instructionsMap.put(mnemonic + "_" + addressingmMode.getName(), instructionType);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
public 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 mode The addressing mode you want.
|
||||
* @param isZp Indicates whether you are interested in a zeropage-based opcode.
|
||||
* @return The opcode, if it exists. If you have requested an absolute addressing mode passed isZp as true the resulting opcode will have zeropage-based addressing the instruction set offers that.
|
||||
*/
|
||||
public static AsmOpcode getOpcode(String mnemonic, AsmAddressingMode mode, boolean isZp) {
|
||||
AsmOpcode type = null;
|
||||
if(AsmAddressingMode.ABS.equals(mode) && isZp) {
|
||||
type = set.getOpcode(mnemonic, AsmAddressingMode.ZP);
|
||||
}
|
||||
if(AsmAddressingMode.ABX.equals(mode) && isZp) {
|
||||
type = set.getOpcode(mnemonic, AsmAddressingMode.ZPX);
|
||||
}
|
||||
if(AsmAddressingMode.ABY.equals(mode) && isZp) {
|
||||
type = set.getOpcode(mnemonic, AsmAddressingMode.ZPY);
|
||||
}
|
||||
if(type == null) {
|
||||
type = set.getOpcode(mnemonic, mode);
|
||||
}
|
||||
if(type == null && AsmAddressingMode.ABS.equals(mode)) {
|
||||
type = set.getOpcode(mnemonic, AsmAddressingMode.REL);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
81
src/main/java/dk/camelot64/cpufamily6502/AsmOpcode.java
Normal file
81
src/main/java/dk/camelot64/cpufamily6502/AsmOpcode.java
Normal file
@ -0,0 +1,81 @@
|
||||
package dk.camelot64.cpufamily6502;
|
||||
|
||||
/** A specific opcode in the instruction set of a 6502 family CPU. */
|
||||
public class AsmOpcode {
|
||||
|
||||
/** The opcode of the instruction. */
|
||||
private final int opcode;
|
||||
|
||||
/** The mnemonic of the instruction. */
|
||||
private final String mnemnonic;
|
||||
|
||||
/** The addressing mode of the instruction. */
|
||||
private final AsmAddressingMode addressingMode;
|
||||
|
||||
/**
|
||||
* The number of cycles that executing the instruction takes.
|
||||
* Some instructions use different number of cycles under different calling conditions, in that case this is an
|
||||
* estimate of the average cycles cost.
|
||||
*/
|
||||
private final double cycles;
|
||||
|
||||
/**
|
||||
* True if the instruction is a jump or a branch.
|
||||
* A jump is any instruction that can modify the program counter in a way that is not just incrementing it to the
|
||||
* next instruction in memory. This includes JSR and RTS.
|
||||
*/
|
||||
private boolean jump;
|
||||
|
||||
/** Which registers/flags of the CPU are clobbered by the instruction. */
|
||||
private final AsmClobber clobber;
|
||||
|
||||
public AsmOpcode(int opcode, String mnemnonic, AsmAddressingMode addressingMode, double cycles) {
|
||||
this.opcode = opcode;
|
||||
this.mnemnonic = mnemnonic;
|
||||
this.addressingMode = addressingMode;
|
||||
this.cycles = cycles;
|
||||
this.clobber = new AsmClobber();
|
||||
}
|
||||
|
||||
public String getMnemnonic() {
|
||||
return mnemnonic;
|
||||
}
|
||||
|
||||
public AsmAddressingMode getAddressingMode() {
|
||||
return addressingMode;
|
||||
}
|
||||
|
||||
public double getCycles() {
|
||||
return cycles;
|
||||
}
|
||||
|
||||
public int getBytes() {
|
||||
return addressingMode.getBytes();
|
||||
}
|
||||
|
||||
public int getOpcode() {
|
||||
return opcode;
|
||||
}
|
||||
|
||||
public String getAsm(String parameter) {
|
||||
return addressingMode.getAsm(mnemnonic, parameter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells if the instruction is a jump or a branch
|
||||
*
|
||||
* @return true if the instruction is a jump/branch
|
||||
*/
|
||||
public boolean isJump() {
|
||||
return jump;
|
||||
}
|
||||
|
||||
void setJump(boolean jump) {
|
||||
this.jump = jump;
|
||||
}
|
||||
|
||||
public AsmClobber getClobber() {
|
||||
return clobber;
|
||||
}
|
||||
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
package dk.camelot64.kickc.asm;
|
||||
|
||||
/** 6502 Assembler Instruction Addressing Modes. */
|
||||
public enum AsmAddressingMode {
|
||||
NON("", "%i", 1),
|
||||
IMM("#imm", "%i #%p", 2),
|
||||
ZP("zp", "%i.z %p", 2),
|
||||
ZPX("zp,x", "%i.z %p,x", 2),
|
||||
ZPY("zp,y", "%i.z %p,y", 2),
|
||||
ABS("abs", "%i %p", 3),
|
||||
ABX("abs,x", "%i %p,x", 3),
|
||||
ABY("abs,y", "%i %p,y", 4),
|
||||
IZX("(zp,x)", "%i (%p,x)", 2),
|
||||
IZY("(zp),y", "%i (%p),y", 2),
|
||||
REL("rel", "%i %p", 2),
|
||||
IND("(ind)", "%i (%p)", 3);
|
||||
|
||||
|
||||
private String name;
|
||||
|
||||
private String template;
|
||||
|
||||
private int bytes;
|
||||
|
||||
AsmAddressingMode(String name, String template, int bytes) {
|
||||
this.bytes = bytes;
|
||||
this.template = template;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getBytes() {
|
||||
return bytes;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getAsm(String mnemnonic, String parameter) {
|
||||
String replaced = template.replace("%i", mnemnonic);
|
||||
if(parameter != null) {
|
||||
replaced = replaced.replace("%p", parameter);
|
||||
}
|
||||
return replaced;
|
||||
}
|
||||
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
package dk.camelot64.kickc.asm;
|
||||
|
||||
import dk.camelot64.cpufamily6502.AsmClobber;
|
||||
import dk.camelot64.cpufamily6502.AsmOpcode;
|
||||
import dk.camelot64.kickc.model.PhiTransitions;
|
||||
import dk.camelot64.kickc.model.Program;
|
||||
import dk.camelot64.kickc.model.statements.Statement;
|
||||
@ -176,8 +178,8 @@ public class AsmChunk {
|
||||
for(AsmLine line : lines) {
|
||||
if(line instanceof AsmInstruction) {
|
||||
AsmInstruction asmInstruction = (AsmInstruction) line;
|
||||
AsmInstructionType asmInstructionType = asmInstruction.getType();
|
||||
AsmClobber asmClobber = asmInstructionType.getClobber();
|
||||
AsmOpcode asmOpcode = asmInstruction.getAsmOpcode();
|
||||
AsmClobber asmClobber = asmOpcode.getClobber();
|
||||
clobber.add(asmClobber);
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,11 @@
|
||||
package dk.camelot64.kickc.asm;
|
||||
|
||||
/** An assembler instruction */
|
||||
import dk.camelot64.cpufamily6502.AsmOpcode;
|
||||
|
||||
/** A specific assembler instruction line (opcode, addressing mode and specific parameter value)*/
|
||||
public class AsmInstruction implements AsmLine {
|
||||
|
||||
private AsmInstructionType type;
|
||||
private AsmOpcode asmOpcode;
|
||||
|
||||
private String parameter;
|
||||
|
||||
@ -11,8 +13,8 @@ public class AsmInstruction implements AsmLine {
|
||||
|
||||
private boolean dontOptimize;
|
||||
|
||||
public AsmInstruction(AsmInstructionType type, String parameter) {
|
||||
this.type = type;
|
||||
public AsmInstruction(AsmOpcode asmOpcode, String parameter) {
|
||||
this.asmOpcode = asmOpcode;
|
||||
this.parameter = parameter;
|
||||
}
|
||||
|
||||
@ -24,27 +26,27 @@ public class AsmInstruction implements AsmLine {
|
||||
this.parameter = parameter;
|
||||
}
|
||||
|
||||
public AsmInstructionType getType() {
|
||||
return type;
|
||||
public AsmOpcode getAsmOpcode() {
|
||||
return asmOpcode;
|
||||
}
|
||||
|
||||
public void setType(AsmInstructionType type) {
|
||||
this.type = type;
|
||||
public void setAsmOpcode(AsmOpcode type) {
|
||||
this.asmOpcode = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLineBytes() {
|
||||
return type.getBytes();
|
||||
return asmOpcode.getBytes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getLineCycles() {
|
||||
return type.getCycles();
|
||||
return asmOpcode.getCycles();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAsm() {
|
||||
return type.getAsm(parameter);
|
||||
return asmOpcode.getAsm(parameter);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,381 +0,0 @@
|
||||
package dk.camelot64.kickc.asm;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* The set of all 6502 assembler instructions
|
||||
*/
|
||||
public class AsmInstructionSet {
|
||||
|
||||
private static AsmInstructionSet set = new AsmInstructionSet();
|
||||
private List<AsmInstructionType> instructions;
|
||||
/** Maps mnemonic_addressingmMode to the instruction type */
|
||||
private Map<String, AsmInstructionType> instructionsMap;
|
||||
|
||||
public AsmInstructionSet() {
|
||||
this.instructions = new ArrayList<>();
|
||||
this.instructionsMap = new HashMap<>();
|
||||
AsmAddressingMode non = AsmAddressingMode.NON;
|
||||
AsmAddressingMode zp = AsmAddressingMode.ZP;
|
||||
AsmAddressingMode zpx = AsmAddressingMode.ZPX;
|
||||
AsmAddressingMode zpy = AsmAddressingMode.ZPY;
|
||||
AsmAddressingMode imm = AsmAddressingMode.IMM;
|
||||
AsmAddressingMode abs = AsmAddressingMode.ABS;
|
||||
AsmAddressingMode abx = AsmAddressingMode.ABX;
|
||||
AsmAddressingMode aby = AsmAddressingMode.ABY;
|
||||
AsmAddressingMode izx = AsmAddressingMode.IZX;
|
||||
AsmAddressingMode izy = AsmAddressingMode.IZY;
|
||||
AsmAddressingMode rel = AsmAddressingMode.REL;
|
||||
AsmAddressingMode ind = AsmAddressingMode.IND;
|
||||
add(0x00, "brk", non, 7.0);
|
||||
add(0x01, "ora", izx, 6.0);
|
||||
add(0x01, "ora", izx, 6.0);
|
||||
add(0x02, "kil", non, 0.0);
|
||||
add(0x03, "slo", izx, 8.0);
|
||||
add(0x04, "nop", zp, 3.0);
|
||||
add(0x05, "ora", zp, 3.0);
|
||||
add(0x06, "asl", zp, 5.0);
|
||||
add(0x07, "slo", zp, 5.0);
|
||||
add(0x08, "php", non, 3.0);
|
||||
add(0x09, "ora", imm, 2.0);
|
||||
add(0x0a, "asl", non, 2.0);
|
||||
add(0x0b, "anc", imm, 2.0);
|
||||
add(0x0c, "nop", abs, 4.0);
|
||||
add(0x0d, "ora", abs, 4.0);
|
||||
add(0x0e, "asl", abs, 6.0);
|
||||
add(0x0f, "slo", abs, 6.0);
|
||||
add(0x10, "bpl", rel, 2.5);
|
||||
add(0x11, "ora", izy, 5.5);
|
||||
add(0x12, "kil", non, 0.0);
|
||||
add(0x13, "slo", izy, 8.0);
|
||||
add(0x14, "nop", zpx, 4.0);
|
||||
add(0x15, "ora", zpx, 4.0);
|
||||
add(0x16, "asl", zpx, 6.0);
|
||||
add(0x17, "slo", zpx, 6.0);
|
||||
add(0x18, "clc", non, 2.0);
|
||||
add(0x19, "ora", aby, 4.5);
|
||||
add(0x1a, "nop", non, 2.0);
|
||||
add(0x1b, "slo", aby, 7.0);
|
||||
add(0x1c, "nop", abx, 4.5);
|
||||
add(0x1d, "ora", abx, 4.5);
|
||||
add(0x1e, "asl", abx, 7.0);
|
||||
add(0x1f, "slo", abx, 7.0);
|
||||
add(0x20, "jsr", abs, 6.0);
|
||||
add(0x21, "and", izx, 6.0);
|
||||
add(0x22, "kil", non, 0.0);
|
||||
add(0x23, "rla", izx, 8.0);
|
||||
add(0x24, "bit", zp, 3.0);
|
||||
add(0x25, "and", zp, 3.0);
|
||||
add(0x26, "rol", zp, 5.0);
|
||||
add(0x27, "rla", zp, 5.0);
|
||||
add(0x28, "plp", non, 4.0);
|
||||
add(0x29, "and", imm, 2.0);
|
||||
add(0x2a, "rol", non, 2.0);
|
||||
add(0x2b, "anc", imm, 2.0);
|
||||
add(0x2c, "bit", abs, 4.0);
|
||||
add(0x2d, "and", abs, 4.0);
|
||||
add(0x2e, "rol", abs, 6.0);
|
||||
add(0x2f, "rla", abs, 6.0);
|
||||
add(0x30, "bmi", rel, 2.5);
|
||||
add(0x31, "and", izy, 5.5);
|
||||
add(0x32, "kil", non, 0.0);
|
||||
add(0x33, "rla", izy, 8.0);
|
||||
add(0x34, "nop", zpx, 4.0);
|
||||
add(0x35, "and", zpx, 4.0);
|
||||
add(0x36, "rol", zpx, 6.0);
|
||||
add(0x37, "rla", zpx, 6.0);
|
||||
add(0x38, "sec", non, 2.0);
|
||||
add(0x39, "and", aby, 4.5);
|
||||
add(0x3a, "nop", non, 2.0);
|
||||
add(0x3b, "rla", aby, 7.0);
|
||||
add(0x3c, "nop", abx, 4.5);
|
||||
add(0x3d, "and", abx, 4.5);
|
||||
add(0x3e, "rol", abx, 7.0);
|
||||
add(0x3f, "rla", abx, 7.0);
|
||||
add(0x40, "rti", non, 6.0);
|
||||
add(0x41, "eor", izx, 6.0);
|
||||
add(0x42, "kil", non, 0.0);
|
||||
add(0x43, "sre", izx, 8.0);
|
||||
add(0x44, "nop", zp, 3.0);
|
||||
add(0x45, "eor", zp, 3.0);
|
||||
add(0x46, "lsr", zp, 5.0);
|
||||
add(0x47, "sre", zp, 5.0);
|
||||
add(0x48, "pha", non, 3.0);
|
||||
add(0x49, "eor", imm, 2.0);
|
||||
add(0x4a, "lsr", non, 2.0);
|
||||
add(0x4b, "alr", imm, 2.0);
|
||||
add(0x4c, "jmp", abs, 3.0);
|
||||
add(0x4d, "eor", abs, 4.0);
|
||||
add(0x4e, "lsr", abs, 6.0);
|
||||
add(0x4f, "sre", abs, 6.0);
|
||||
add(0x50, "bvc", rel, 2.5);
|
||||
add(0x51, "eor", izy, 5.5);
|
||||
add(0x52, "kil", non, 0.0);
|
||||
add(0x53, "sre", izy, 8.0);
|
||||
add(0x54, "nop", zpx, 4.0);
|
||||
add(0x55, "eor", zpx, 4.0);
|
||||
add(0x56, "lsr", zpx, 6.0);
|
||||
add(0x57, "sre", zpx, 6.0);
|
||||
add(0x58, "cli", non, 2.0);
|
||||
add(0x59, "eor", aby, 4.5);
|
||||
add(0x5a, "nop", non, 2.0);
|
||||
add(0x5b, "sre", aby, 7.0);
|
||||
add(0x5c, "nop", abx, 4.5);
|
||||
add(0x5d, "eor", abx, 4.5);
|
||||
add(0x5e, "lsr", abx, 7.0);
|
||||
add(0x5f, "sre", abx, 7.0);
|
||||
add(0x60, "rts", non, 6.0);
|
||||
add(0x61, "adc", izx, 6.0);
|
||||
add(0x62, "kil", non, 0.0);
|
||||
add(0x63, "rra", izx, 8.0);
|
||||
add(0x64, "nop", zp, 3.0);
|
||||
add(0x65, "adc", zp, 3.0);
|
||||
add(0x66, "ror", zp, 5.0);
|
||||
add(0x67, "rra", zp, 5.0);
|
||||
add(0x68, "pla", non, 4.0);
|
||||
add(0x69, "adc", imm, 2.0);
|
||||
add(0x6a, "ror", non, 2.0);
|
||||
add(0x6b, "arr", imm, 2.0);
|
||||
add(0x6c, "jmp", ind, 5.0);
|
||||
add(0x6d, "adc", abs, 4.0);
|
||||
add(0x6e, "ror", abs, 6.0);
|
||||
add(0x6f, "rra", abs, 6.0);
|
||||
add(0x70, "bvs", rel, 2.5);
|
||||
add(0x71, "adc", izy, 5.5);
|
||||
add(0x72, "kil", non, 0.0);
|
||||
add(0x73, "rra", izy, 8.0);
|
||||
add(0x74, "nop", zpx, 4.0);
|
||||
add(0x75, "adc", zpx, 4.0);
|
||||
add(0x76, "ror", zpx, 6.0);
|
||||
add(0x77, "rra", zpx, 6.0);
|
||||
add(0x78, "sei", non, 2.0);
|
||||
add(0x79, "adc", aby, 4.5);
|
||||
add(0x7a, "nop", non, 2.0);
|
||||
add(0x7b, "rra", aby, 7.0);
|
||||
add(0x7c, "nop", abx, 4.5);
|
||||
add(0x7d, "adc", abx, 4.5);
|
||||
add(0x7e, "ror", abx, 7.0);
|
||||
add(0x7f, "rra", abx, 7.0);
|
||||
add(0x80, "nop", imm, 2.0);
|
||||
add(0x81, "sta", izx, 6.0);
|
||||
add(0x82, "nop", imm, 2.0);
|
||||
add(0x83, "sax", izx, 6.0);
|
||||
add(0x84, "sty", zp, 3.0);
|
||||
add(0x85, "sta", zp, 3.0);
|
||||
add(0x86, "stx", zp, 3.0);
|
||||
add(0x87, "sax", zp, 3.0);
|
||||
add(0x88, "dey", non, 2.0);
|
||||
add(0x89, "nop", imm, 2.0);
|
||||
add(0x8a, "txa", non, 2.0);
|
||||
add(0x8b, "xaa", imm, 2.0);
|
||||
add(0x8c, "sty", abs, 4.0);
|
||||
add(0x8d, "sta", abs, 4.0);
|
||||
add(0x8e, "stx", abs, 4.0);
|
||||
add(0x8f, "sax", abs, 4.0);
|
||||
add(0x90, "bcc", rel, 2.5);
|
||||
add(0x91, "sta", izy, 6.0);
|
||||
add(0x92, "kil", non, 0.0);
|
||||
add(0x93, "ahx", izy, 6.0);
|
||||
add(0x94, "sty", zpx, 4.0);
|
||||
add(0x95, "sta", zpx, 4.0);
|
||||
add(0x96, "stx", zpy, 4.0);
|
||||
add(0x97, "sax", zpy, 4.0);
|
||||
add(0x98, "tya", non, 2.0);
|
||||
add(0x99, "sta", aby, 5.0);
|
||||
add(0x9a, "txs", non, 2.0);
|
||||
add(0x9b, "tas", aby, 5.0);
|
||||
add(0x9c, "shy", abx, 5.0);
|
||||
add(0x9d, "sta", abx, 5.0);
|
||||
add(0x9e, "shx", aby, 5.0);
|
||||
add(0x9f, "ahx", aby, 5.0);
|
||||
add(0xa0, "ldy", imm, 2.0);
|
||||
add(0xa1, "lda", izx, 6.0);
|
||||
add(0xa2, "ldx", imm, 2.0);
|
||||
add(0xa3, "lax", izx, 6.0);
|
||||
add(0xa4, "ldy", zp, 3.0);
|
||||
add(0xa5, "lda", zp, 3.0);
|
||||
add(0xa6, "ldx", zp, 3.0);
|
||||
add(0xa7, "lax", zp, 3.0);
|
||||
add(0xa8, "tay", non, 2.0);
|
||||
add(0xa9, "lda", imm, 2.0);
|
||||
add(0xaa, "tax", non, 2.0);
|
||||
add(0xab, "lax", imm, 2.0);
|
||||
add(0xac, "ldy", abs, 4.0);
|
||||
add(0xad, "lda", abs, 4.0);
|
||||
add(0xae, "ldx", abs, 4.0);
|
||||
add(0xaf, "lax", abs, 4.0);
|
||||
add(0xb0, "bcs", rel, 2.5);
|
||||
add(0xb1, "lda", izy, 5.5);
|
||||
add(0xb2, "kil", non, 0.0);
|
||||
add(0xb3, "lax", izy, 5.5);
|
||||
add(0xb4, "ldy", zpx, 4.0);
|
||||
add(0xb5, "lda", zpx, 4.0);
|
||||
add(0xb6, "ldx", zpy, 4.0);
|
||||
add(0xb7, "lax", zpy, 4.0);
|
||||
add(0xb8, "clv", non, 2.0);
|
||||
add(0xb9, "lda", aby, 4.5);
|
||||
add(0xba, "tsx", non, 2.0);
|
||||
add(0xbb, "las", aby, 4.5);
|
||||
add(0xbc, "ldy", abx, 4.5);
|
||||
add(0xbd, "lda", abx, 4.5);
|
||||
add(0xbe, "ldx", aby, 4.5);
|
||||
add(0xbf, "lax", aby, 4.5);
|
||||
add(0xc0, "cpy", imm, 2.0);
|
||||
add(0xc1, "cmp", izx, 6.0);
|
||||
add(0xc2, "nop", imm, 2.0);
|
||||
add(0xc3, "dcp", izx, 8.0);
|
||||
add(0xc4, "cpy", zp, 3.0);
|
||||
add(0xc5, "cmp", zp, 3.0);
|
||||
add(0xc6, "dec", zp, 5.0);
|
||||
add(0xc7, "dcp", zp, 5.0);
|
||||
add(0xc8, "iny", non, 2.0);
|
||||
add(0xc9, "cmp", imm, 2.0);
|
||||
add(0xca, "dex", non, 2.0);
|
||||
add(0xcb, "axs", imm, 2.0);
|
||||
add(0xcc, "cpy", abs, 4.0);
|
||||
add(0xcd, "cmp", abs, 4.0);
|
||||
add(0xce, "dec", abs, 6.0);
|
||||
add(0xcf, "dcp", abs, 6.0);
|
||||
add(0xd0, "bne", rel, 2.5);
|
||||
add(0xd1, "cmp", izy, 5.5);
|
||||
add(0xd2, "kil", non, 0.0);
|
||||
add(0xd3, "dcp", izy, 8.0);
|
||||
add(0xd4, "nop", zpx, 4.0);
|
||||
add(0xd5, "cmp", zpx, 4.0);
|
||||
add(0xd6, "dec", zpx, 6.0);
|
||||
add(0xd7, "dcp", zpx, 6.0);
|
||||
add(0xd8, "cld", non, 2.0);
|
||||
add(0xd9, "cmp", aby, 4.5);
|
||||
add(0xda, "nop", non, 2.0);
|
||||
add(0xdb, "dcp", aby, 7.0);
|
||||
add(0xdc, "nop", abx, 4.5);
|
||||
add(0xdd, "cmp", abx, 4.5);
|
||||
add(0xde, "dec", abx, 7.0);
|
||||
add(0xef, "cpx", imm, 2.0);
|
||||
add(0xe0, "sbc", izx, 6.0);
|
||||
add(0xe1, "nop", imm, 2.0);
|
||||
add(0xe2, "isc", izx, 8.0);
|
||||
add(0xe3, "cpx", zp, 3.0);
|
||||
add(0xe4, "sbc", zp, 3.0);
|
||||
add(0xe5, "inc", zp, 5.0);
|
||||
add(0xe6, "isc", zp, 5.0);
|
||||
add(0xe7, "inx", non, 2.0);
|
||||
add(0xe8, "sbc", imm, 2.0);
|
||||
add(0xe9, "nop", non, 2.0);
|
||||
add(0xea, "sbc", imm, 2.0);
|
||||
add(0xeb, "cpx", abs, 4.0);
|
||||
add(0xec, "sbc", abs, 4.0);
|
||||
add(0xed, "inc", abs, 6.0);
|
||||
add(0xee, "isc", abs, 6.0);
|
||||
add(0xef, "dcp", abx, 7.0);
|
||||
add(0xf0, "beq", rel, 2.5);
|
||||
add(0xf1, "sbc", izy, 5.5);
|
||||
add(0xf2, "kil", non, 0.0);
|
||||
add(0xf3, "isc", izy, 8.0);
|
||||
add(0xf4, "nop", zpx, 4.0);
|
||||
add(0xf5, "sbc", zpx, 4.0);
|
||||
add(0xf6, "inc", zpx, 6.0);
|
||||
add(0xf7, "isc", zpx, 6.0);
|
||||
add(0xf8, "sed", non, 2.0);
|
||||
add(0xf9, "sbc", aby, 4.5);
|
||||
add(0xfa, "nop", non, 2.0);
|
||||
add(0xfb, "isc", aby, 7.0);
|
||||
add(0xfc, "nop", abx, 4.5);
|
||||
add(0xfd, "sbc", abx, 4.5);
|
||||
add(0xfe, "inc", abx, 7.0);
|
||||
add(0xff, "isc", abx, 7.0);
|
||||
|
||||
// 65c02 instructions
|
||||
// TODO: create instruction set model that knows the different CPU's
|
||||
add(0x1a, "inc", non, 2.0);
|
||||
|
||||
List<String> jumps = Arrays.asList("jmp", "beq", "bne", "bcc", "bcs", "bvs", "bvc", "bmi", "bpl", "jsr");
|
||||
for(AsmInstructionType instruction : instructions) {
|
||||
if(jumps.contains(instruction.getMnemnonic())) {
|
||||
instruction.setJump(true);
|
||||
}
|
||||
}
|
||||
List<String> cxs = Arrays.asList("dex", "inx", "ldx", "tax", "tsx", "las", "lax", "axs");
|
||||
for(AsmInstructionType instruction : instructions) {
|
||||
if(cxs.contains(instruction.getMnemnonic())) {
|
||||
instruction.getClobber().setClobberX(true);
|
||||
}
|
||||
}
|
||||
List<String> cys = Arrays.asList("dey", "iny", "ldy", "tay");
|
||||
for(AsmInstructionType instruction : instructions) {
|
||||
if(cys.contains(instruction.getMnemnonic())) {
|
||||
instruction.getClobber().setClobberY(true);
|
||||
}
|
||||
}
|
||||
List<String> cas = Arrays.asList("ora", "and", "eor", "adc", "sbc", "lda", "txa", "tya", "pla", "slo", "rla", "sre", "rra", "isc", "anc", "alr", "arr", "xaa", "lax", "las");
|
||||
for(AsmInstructionType instruction : instructions) {
|
||||
if(cas.contains(instruction.getMnemnonic())) {
|
||||
instruction.getClobber().setClobberA(true);
|
||||
} else if(instruction.getOpcode()==0x0a) {
|
||||
// Special handling of ASL A
|
||||
instruction.getClobber().setClobberA(true);
|
||||
} else if(instruction.getOpcode()==0x2a) {
|
||||
// Special handling of ROL A
|
||||
instruction.getClobber().setClobberA(true);
|
||||
} else if(instruction.getOpcode()==0x4a) {
|
||||
// Special handling of LSR A
|
||||
instruction.getClobber().setClobberA(true);
|
||||
} else if(instruction.getOpcode()==0x6a) {
|
||||
// Special handling of ROR A
|
||||
instruction.getClobber().setClobberA(true);
|
||||
}
|
||||
|
||||
}
|
||||
List<String> ccs = Arrays.asList("adc", "sbc", "cmp", "cpx", "cpy", "asl", "rol", "lsr", "ror", "plp", "rti", "clc", "sec", "slo", "rla", "sre", "rra", "dcp", "isc", "anc", "alr", "arr", "axs");
|
||||
for(AsmInstructionType instruction : instructions) {
|
||||
if(ccs.contains(instruction.getMnemnonic())) {
|
||||
instruction.getClobber().setClobberC(true);
|
||||
}
|
||||
}
|
||||
List<String> cvs = Arrays.asList("adc", "sbc", "plp", "rti", "bit", "rra", "isc", "arr");
|
||||
for(AsmInstructionType instruction : instructions) {
|
||||
if(cvs.contains(instruction.getMnemnonic())) {
|
||||
instruction.getClobber().setClobberV(true);
|
||||
}
|
||||
}
|
||||
List<String> czs = Arrays.asList("ora", "and", "eor", "adc", "sbc", "cmp", "cpx", "cpy", "dec", "dex", "dey", "inc", "inx", "iny", "asl", "rol", "lsr", "ror", "lda", "ldx", "ldy", "tax", "txa", "tay", "tya", "tsx", "txs", "pla", "plp", "rti", "bit", "slo", "rla", "sre", "rra", "lax", "dcp", "isc", "anc", "alr", "arr", "xaa", "lax", "axs", "las");
|
||||
for(AsmInstructionType instruction : instructions) {
|
||||
if(czs.contains(instruction.getMnemnonic())) {
|
||||
instruction.getClobber().setClobberZ(true);
|
||||
instruction.getClobber().setClobberN(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static AsmInstructionType getInstructionType(String mnemonic, AsmAddressingMode mode, boolean isZp) {
|
||||
AsmInstructionType type = null;
|
||||
if(AsmAddressingMode.ABS.equals(mode) && isZp) {
|
||||
type = set.getType(mnemonic, AsmAddressingMode.ZP);
|
||||
}
|
||||
if(AsmAddressingMode.ABX.equals(mode) && isZp) {
|
||||
type = set.getType(mnemonic, AsmAddressingMode.ZPX);
|
||||
}
|
||||
if(AsmAddressingMode.ABY.equals(mode) && isZp) {
|
||||
type = set.getType(mnemonic, AsmAddressingMode.ZPY);
|
||||
}
|
||||
if(type == null) {
|
||||
type = set.getType(mnemonic, mode);
|
||||
}
|
||||
if(type == null && AsmAddressingMode.ABS.equals(mode)) {
|
||||
type = set.getType(mnemonic, AsmAddressingMode.REL);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
private void add(int opcode, String mnemonic, AsmAddressingMode addressingmMode, double cycles) {
|
||||
AsmInstructionType instructionType = new AsmInstructionType(opcode, mnemonic, addressingmMode, cycles);
|
||||
instructions.add(instructionType);
|
||||
instructionsMap.put(mnemonic + "_" + addressingmMode.getName(), instructionType);
|
||||
}
|
||||
|
||||
public AsmInstructionType getType(String mnemonic, AsmAddressingMode addressingMode) {
|
||||
String key = mnemonic.toLowerCase() + "_" + addressingMode.getName();
|
||||
return instructionsMap.get(key);
|
||||
}
|
||||
|
||||
}
|
@ -1,66 +0,0 @@
|
||||
package dk.camelot64.kickc.asm;
|
||||
|
||||
/** The instructions of the 6502 assembler instruction set */
|
||||
public class AsmInstructionType {
|
||||
|
||||
private int opcode;
|
||||
|
||||
private String mnemnonic;
|
||||
|
||||
private AsmAddressingMode addressingMode;
|
||||
|
||||
private double cycles;
|
||||
|
||||
private boolean jump;
|
||||
|
||||
private AsmClobber clobber;
|
||||
|
||||
public AsmInstructionType(int opcode, String mnemnonic, AsmAddressingMode addressingMode, double cycles) {
|
||||
this.opcode = opcode;
|
||||
this.mnemnonic = mnemnonic;
|
||||
this.addressingMode = addressingMode;
|
||||
this.cycles = cycles;
|
||||
this.clobber = new AsmClobber();
|
||||
}
|
||||
|
||||
public String getMnemnonic() {
|
||||
return mnemnonic;
|
||||
}
|
||||
|
||||
public AsmAddressingMode getAddressingMode() {
|
||||
return addressingMode;
|
||||
}
|
||||
|
||||
public double getCycles() {
|
||||
return cycles;
|
||||
}
|
||||
|
||||
public int getBytes() {
|
||||
return addressingMode.getBytes();
|
||||
}
|
||||
|
||||
public int getOpcode() {
|
||||
return opcode;
|
||||
}
|
||||
|
||||
public String getAsm(String parameter) {
|
||||
return addressingMode.getAsm(mnemnonic, parameter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells if the instruction is a jump or a branch (and the parameter is therefore a label or destination address).
|
||||
*
|
||||
* @return true if the instruction is a jump/branch
|
||||
*/
|
||||
public boolean isJump() {
|
||||
return jump;
|
||||
}
|
||||
|
||||
void setJump(boolean jump) {
|
||||
this.jump = jump;
|
||||
}
|
||||
|
||||
public AsmClobber getClobber() {
|
||||
return clobber;
|
||||
}
|
||||
}
|
@ -1,5 +1,9 @@
|
||||
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.kickc.model.CompileError;
|
||||
import dk.camelot64.kickc.model.Program;
|
||||
import dk.camelot64.kickc.model.values.ScopeRef;
|
||||
@ -100,10 +104,10 @@ public class AsmProgram {
|
||||
}
|
||||
|
||||
public AsmInstruction addInstruction(String mnemonic, AsmAddressingMode addressingMode, String parameter, boolean zp) {
|
||||
AsmInstructionType instructionType = AsmInstructionSet.getInstructionType(mnemonic, addressingMode, zp);
|
||||
AsmInstruction instruction = new AsmInstruction(instructionType, parameter);
|
||||
addLine(instruction);
|
||||
return instruction;
|
||||
AsmOpcode asmOpcode = AsmInstructionSet.getOpcode(mnemonic, addressingMode, zp);
|
||||
AsmInstruction asmInstruction = new AsmInstruction(asmOpcode, parameter);
|
||||
addLine(asmInstruction);
|
||||
return asmInstruction;
|
||||
}
|
||||
|
||||
public void addLabelDecl(String name, String value) {
|
||||
|
@ -1,5 +1,9 @@
|
||||
package dk.camelot64.kickc.asm;
|
||||
|
||||
import dk.camelot64.cpufamily6502.AsmAddressingMode;
|
||||
import dk.camelot64.cpufamily6502.AsmClobber;
|
||||
import dk.camelot64.cpufamily6502.AsmOpcode;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@ -83,37 +87,37 @@ public class AsmProgramStaticRegisterValues {
|
||||
AsmInstruction instruction = (AsmInstruction) line;
|
||||
values.put(instruction, current);
|
||||
current = new AsmRegisterValues(current);
|
||||
AsmInstructionType instructionType = instruction.getType();
|
||||
AsmClobber clobber = instructionType.getClobber();
|
||||
if(instruction.getType().getMnemnonic().equals("jsr")) {
|
||||
clobber = AsmClobber.CLOBBER_ALL;
|
||||
AsmOpcode asmOpcode = instruction.getAsmOpcode();
|
||||
AsmClobber asmClobber = asmOpcode.getClobber();
|
||||
if(instruction.getAsmOpcode().getMnemnonic().equals("jsr")) {
|
||||
asmClobber = AsmClobber.CLOBBER_ALL;
|
||||
}
|
||||
if(clobber.isClobberA()) {
|
||||
if(asmClobber.isClobberA()) {
|
||||
current.setA(null);
|
||||
current.setaMem(null);
|
||||
}
|
||||
if(clobber.isClobberX()) {
|
||||
if(asmClobber.isClobberX()) {
|
||||
current.setX(null);
|
||||
current.setxMem(null);
|
||||
}
|
||||
if(clobber.isClobberY()) {
|
||||
if(asmClobber.isClobberY()) {
|
||||
current.setY(null);
|
||||
current.setyMem(null);
|
||||
}
|
||||
if(clobber.isClobberC()) {
|
||||
if(asmClobber.isClobberC()) {
|
||||
current.setC(null);
|
||||
}
|
||||
if(clobber.isClobberN()) {
|
||||
if(asmClobber.isClobberN()) {
|
||||
current.setN(null);
|
||||
}
|
||||
if(clobber.isClobberV()) {
|
||||
if(asmClobber.isClobberV()) {
|
||||
current.setV(null);
|
||||
}
|
||||
if(clobber.isClobberZ()) {
|
||||
if(asmClobber.isClobberZ()) {
|
||||
current.setZ(null);
|
||||
}
|
||||
String mnemnonic = instructionType.getMnemnonic();
|
||||
AsmAddressingMode addressingMode = instructionType.getAddressingMode();
|
||||
String mnemnonic = asmOpcode.getMnemnonic();
|
||||
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 modParam = instruction.getParameter();
|
||||
if(current.getaMem() != null && current.getaMem().equals(modParam)) {
|
||||
|
@ -1,6 +1,6 @@
|
||||
package dk.camelot64.kickc.fragment;
|
||||
|
||||
import dk.camelot64.kickc.asm.AsmClobber;
|
||||
import dk.camelot64.cpufamily6502.AsmClobber;
|
||||
|
||||
/** 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> {
|
||||
|
@ -1,5 +1,8 @@
|
||||
package dk.camelot64.kickc.fragment;
|
||||
|
||||
import dk.camelot64.cpufamily6502.AsmAddressingMode;
|
||||
import dk.camelot64.cpufamily6502.AsmInstructionSet;
|
||||
import dk.camelot64.cpufamily6502.AsmOpcode;
|
||||
import dk.camelot64.kickc.NumberParser;
|
||||
import dk.camelot64.kickc.asm.*;
|
||||
import dk.camelot64.kickc.model.ConstantNotLiteral;
|
||||
@ -109,6 +112,7 @@ public class AsmFragmentInstance {
|
||||
|
||||
/**
|
||||
* Determine whether a constant value representing an address in memory is located on zeropage.
|
||||
*
|
||||
* @param boundConst The constant value
|
||||
* @return true if the address represented by the constant is 0<=val<=255
|
||||
*/
|
||||
@ -224,14 +228,11 @@ public class AsmFragmentInstance {
|
||||
AsmInstruction instruction;
|
||||
if(paramModeCtx == null) {
|
||||
final String mnemonic = ctx.ASM_MNEMONIC().getText();
|
||||
AsmInstructionType type = AsmInstructionSet.getInstructionType(
|
||||
mnemonic,
|
||||
AsmAddressingMode.NON,
|
||||
false);
|
||||
if(type == null) {
|
||||
AsmOpcode asmOpcode = AsmInstructionSet.getOpcode(mnemonic, AsmAddressingMode.NON, false);
|
||||
if(asmOpcode == null) {
|
||||
throw new InternalError("Error in " + name + ".asm line " + ctx.getStart().getLine() + " - Instruction type unknown " + mnemonic + " " + AsmAddressingMode.NON);
|
||||
}
|
||||
instruction = new AsmInstruction(type, null);
|
||||
instruction = new AsmInstruction(asmOpcode, null);
|
||||
} else {
|
||||
instruction = (AsmInstruction) this.visit(paramModeCtx);
|
||||
}
|
||||
@ -297,14 +298,11 @@ public class AsmFragmentInstance {
|
||||
KickCParser.AsmInstructionContext instructionCtx = (KickCParser.AsmInstructionContext) ctx.getParent();
|
||||
AsmParameter parameter = (AsmParameter) this.visit(exprCtx);
|
||||
String mnemonic = instructionCtx.ASM_MNEMONIC().getSymbol().getText();
|
||||
AsmInstructionType type = AsmInstructionSet.getInstructionType(
|
||||
mnemonic,
|
||||
addressingMode,
|
||||
parameter.isZp());
|
||||
if(type == null) {
|
||||
AsmOpcode asmOpcode = AsmInstructionSet.getOpcode(mnemonic, addressingMode, parameter.isZp());
|
||||
if(asmOpcode == null) {
|
||||
throw new InternalError("Error in " + name + ".asm line " + instructionCtx.getStart().getLine() + " - Instruction type unknown " + mnemonic + " " + addressingMode + " " + parameter);
|
||||
}
|
||||
return new AsmInstruction(type, parameter.getParam());
|
||||
return new AsmInstruction(asmOpcode, parameter.getParam());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,6 +1,6 @@
|
||||
package dk.camelot64.kickc.fragment;
|
||||
|
||||
import dk.camelot64.kickc.asm.AsmClobber;
|
||||
import dk.camelot64.cpufamily6502.AsmClobber;
|
||||
import dk.camelot64.kickc.asm.AsmProgram;
|
||||
import dk.camelot64.kickc.model.Program;
|
||||
import dk.camelot64.kickc.model.Registers;
|
||||
|
@ -1,6 +1,6 @@
|
||||
package dk.camelot64.kickc.model.statements;
|
||||
|
||||
import dk.camelot64.kickc.asm.AsmClobber;
|
||||
import dk.camelot64.cpufamily6502.AsmClobber;
|
||||
import dk.camelot64.kickc.model.Comment;
|
||||
import dk.camelot64.kickc.model.Program;
|
||||
import dk.camelot64.kickc.model.values.SymbolRef;
|
||||
|
@ -1,6 +1,6 @@
|
||||
package dk.camelot64.kickc.model.statements;
|
||||
|
||||
import dk.camelot64.kickc.asm.AsmClobber;
|
||||
import dk.camelot64.cpufamily6502.AsmClobber;
|
||||
import dk.camelot64.kickc.model.Comment;
|
||||
import dk.camelot64.kickc.model.Program;
|
||||
import dk.camelot64.kickc.model.values.RValue;
|
||||
|
@ -2,7 +2,7 @@ package dk.camelot64.kickc.passes;
|
||||
|
||||
import dk.camelot64.kickc.NumberParser;
|
||||
import dk.camelot64.kickc.SourceLoader;
|
||||
import dk.camelot64.kickc.asm.AsmClobber;
|
||||
import dk.camelot64.cpufamily6502.AsmClobber;
|
||||
import dk.camelot64.kickc.model.InternalError;
|
||||
import dk.camelot64.kickc.model.*;
|
||||
import dk.camelot64.kickc.model.operators.*;
|
||||
|
@ -1,7 +1,7 @@
|
||||
package dk.camelot64.kickc.passes;
|
||||
|
||||
import dk.camelot64.kickc.asm.AsmChunk;
|
||||
import dk.camelot64.kickc.asm.AsmClobber;
|
||||
import dk.camelot64.cpufamily6502.AsmClobber;
|
||||
import dk.camelot64.kickc.asm.AsmProgram;
|
||||
import dk.camelot64.kickc.model.*;
|
||||
import dk.camelot64.kickc.model.statements.*;
|
||||
|
@ -1,5 +1,7 @@
|
||||
package dk.camelot64.kickc.passes;
|
||||
|
||||
import dk.camelot64.cpufamily6502.AsmAddressingMode;
|
||||
import dk.camelot64.cpufamily6502.AsmClobber;
|
||||
import dk.camelot64.kickc.asm.*;
|
||||
import dk.camelot64.kickc.fragment.*;
|
||||
import dk.camelot64.kickc.model.InternalError;
|
||||
@ -914,7 +916,7 @@ public class Pass4CodeGeneration {
|
||||
for(AsmLine asmLine : currentChunk.getLines()) {
|
||||
if(asmLine instanceof AsmInstruction) {
|
||||
AsmInstruction asmInstruction = (AsmInstruction) asmLine;
|
||||
if(asmInstruction.getType().getMnemnonic().equals("jsr")) {
|
||||
if(asmInstruction.getAsmOpcode().getMnemnonic().equals("jsr")) {
|
||||
currentChunk.setClobberOverwrite(AsmClobber.CLOBBER_ALL);
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
package dk.camelot64.kickc.passes;
|
||||
|
||||
import dk.camelot64.kickc.asm.AsmChunk;
|
||||
import dk.camelot64.kickc.asm.AsmClobber;
|
||||
import dk.camelot64.cpufamily6502.AsmClobber;
|
||||
import dk.camelot64.kickc.asm.AsmLine;
|
||||
import dk.camelot64.kickc.asm.AsmProgram;
|
||||
import dk.camelot64.kickc.model.CallGraph;
|
||||
|
@ -1,6 +1,6 @@
|
||||
package dk.camelot64.kickc.passes;
|
||||
|
||||
import dk.camelot64.kickc.asm.AsmClobber;
|
||||
import dk.camelot64.cpufamily6502.AsmClobber;
|
||||
import dk.camelot64.kickc.asm.AsmProgram;
|
||||
import dk.camelot64.kickc.fragment.AsmFragmentInstance;
|
||||
import dk.camelot64.kickc.fragment.AsmFragmentTemplateSynthesizer;
|
||||
|
@ -1,5 +1,7 @@
|
||||
package dk.camelot64.kickc.passes;
|
||||
|
||||
import dk.camelot64.cpufamily6502.AsmAddressingMode;
|
||||
import dk.camelot64.cpufamily6502.AsmInstructionSet;
|
||||
import dk.camelot64.kickc.asm.*;
|
||||
import dk.camelot64.kickc.model.Program;
|
||||
import dk.camelot64.kickc.model.values.ScopeRef;
|
||||
@ -25,7 +27,7 @@ public class Pass5AddMainRts extends Pass5AsmOptimization {
|
||||
AsmLine line = lineIterator.next();
|
||||
if(line instanceof AsmInstruction) {
|
||||
AsmInstruction instruction = (AsmInstruction) line;
|
||||
if(instruction.getType().getMnemnonic().equals("jsr")) {
|
||||
if(instruction.getAsmOpcode().getMnemnonic().equals("jsr")) {
|
||||
if(instruction.getParameter().equals(SymbolRef.MAIN_PROC_NAME)) {
|
||||
// Add RTS if it is missing
|
||||
if(!lineIterator.hasNext()) {
|
||||
@ -38,7 +40,7 @@ public class Pass5AddMainRts extends Pass5AsmOptimization {
|
||||
return true;
|
||||
}
|
||||
AsmInstruction nextInstruction = (AsmInstruction) nextLine;
|
||||
if(!nextInstruction.getType().getMnemnonic().equals("rts")) {
|
||||
if(!nextInstruction.getAsmOpcode().getMnemnonic().equals("rts")) {
|
||||
addRts(lineIterator);
|
||||
return true;
|
||||
}
|
||||
@ -52,7 +54,7 @@ public class Pass5AddMainRts extends Pass5AsmOptimization {
|
||||
}
|
||||
|
||||
private void addRts(ListIterator<AsmLine> lineIterator) {
|
||||
lineIterator.add(new AsmInstruction(AsmInstructionSet.getInstructionType("rts", AsmAddressingMode.NON, false), null));
|
||||
lineIterator.add(new AsmInstruction(AsmInstructionSet.getOpcode("rts", AsmAddressingMode.NON, false), null));
|
||||
getLog().append("Adding RTS to root block ");
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,8 @@
|
||||
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.kickc.model.Program;
|
||||
|
||||
@ -39,12 +42,12 @@ public class Pass5DoubleJumpElimination extends Pass5AsmOptimization {
|
||||
} else if(line instanceof AsmInstruction) {
|
||||
if(currentLabel != null) {
|
||||
AsmInstruction asmInstruction = (AsmInstruction) line;
|
||||
AsmInstructionType jmpType = AsmInstructionSet.getInstructionType("jmp", AsmAddressingMode.ABS, false);
|
||||
AsmInstructionType rtsType = AsmInstructionSet.getInstructionType("rts", AsmAddressingMode.NON, false);
|
||||
if(asmInstruction.getType().equals(jmpType)) {
|
||||
AsmOpcode jmpOpcode = AsmInstructionSet.getOpcode("jmp", AsmAddressingMode.ABS, false);
|
||||
AsmOpcode rtsOpcode = AsmInstructionSet.getOpcode("rts", AsmAddressingMode.NON, false);
|
||||
if(asmInstruction.getAsmOpcode().equals(jmpOpcode)) {
|
||||
immediateJumps.put(currentScope + "::" + currentLabel, asmInstruction.getParameter());
|
||||
}
|
||||
if(asmInstruction.getType().equals(rtsType)) {
|
||||
if(asmInstruction.getAsmOpcode().equals(rtsOpcode)) {
|
||||
immediateJumps.put(currentScope + "::" + currentLabel, "rts");
|
||||
}
|
||||
}
|
||||
@ -64,12 +67,12 @@ public class Pass5DoubleJumpElimination extends Pass5AsmOptimization {
|
||||
currentScope = "";
|
||||
} else if(line instanceof AsmInstruction) {
|
||||
AsmInstruction asmInstruction = (AsmInstruction) line;
|
||||
if(asmInstruction.getType().isJump()) {
|
||||
if(asmInstruction.getAsmOpcode().isJump()) {
|
||||
String immediateJmpTarget = immediateJumps.get(currentScope + "::" + asmInstruction.getParameter());
|
||||
if(immediateJmpTarget == "rts" && asmInstruction.getType().getMnemnonic() == "jmp") {
|
||||
if(immediateJmpTarget == "rts" && asmInstruction.getAsmOpcode().getMnemnonic() == "jmp") {
|
||||
getLog().append("Replacing jump to rts with rts in " + asmInstruction.toString());
|
||||
AsmInstructionType rtsType = AsmInstructionSet.getInstructionType("rts", AsmAddressingMode.NON, false);
|
||||
asmInstruction.setType(rtsType);
|
||||
AsmOpcode rtsOpcode = AsmInstructionSet.getOpcode("rts", AsmAddressingMode.NON, false);
|
||||
asmInstruction.setAsmOpcode(rtsOpcode);
|
||||
optimized = true;
|
||||
} else if(immediateJmpTarget != null && immediateJmpTarget != "rts" && !immediateJmpTarget.equals(asmInstruction.getParameter())) {
|
||||
getLog().append("Skipping double jump to " + immediateJmpTarget + " in " + asmInstruction.toString());
|
||||
|
@ -1,5 +1,8 @@
|
||||
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.kickc.model.CompileError;
|
||||
import dk.camelot64.kickc.model.Program;
|
||||
@ -157,17 +160,17 @@ public class Pass5FixLongBranches extends Pass5AsmOptimization {
|
||||
if(asmLine != null && asmLine instanceof AsmInstruction) {
|
||||
//getLog().append("Found ASM line "+asmLine);
|
||||
AsmInstruction asmInstruction = (AsmInstruction) asmLine;
|
||||
AsmInstructionType asmInstructionType = asmInstruction.getType();
|
||||
AsmInstructionType inverseType = invertBranch(asmInstructionType);
|
||||
if(inverseType != null) {
|
||||
AsmOpcode asmOpcode = asmInstruction.getAsmOpcode();
|
||||
AsmOpcode inverseAsmOpcode = invertBranch(asmOpcode);
|
||||
if(inverseAsmOpcode != null) {
|
||||
//getLog().append("Inversed branch instruction "+asmInstructionType.getMnemnonic()+" -> "+inverseType.getMnemnonic());
|
||||
getLog().append("Fixing long branch [" + idx + "] " + asmLine.toString() + " to " + inverseType.getMnemnonic());
|
||||
getLog().append("Fixing long branch [" + idx + "] " + asmLine.toString() + " to " + inverseAsmOpcode.getMnemnonic());
|
||||
String branchDest = asmInstruction.getParameter();
|
||||
asmInstruction.setType(inverseType);
|
||||
asmInstruction.setAsmOpcode(inverseAsmOpcode);
|
||||
String newLabel = AsmFormat.asmFix("!" + branchDest);
|
||||
asmInstruction.setParameter(newLabel+"+");
|
||||
AsmInstructionType jmpType = AsmInstructionSet.getInstructionType("jmp", AsmAddressingMode.ABS, false);
|
||||
AsmInstruction jmpInstruction = new AsmInstruction(jmpType, branchDest);
|
||||
AsmOpcode jmpOpcode = AsmInstructionSet.getOpcode("jmp", AsmAddressingMode.ABS, false);
|
||||
AsmInstruction jmpInstruction = new AsmInstruction(jmpOpcode, branchDest);
|
||||
asmChunk.addLineAfter(asmInstruction, jmpInstruction);
|
||||
asmChunk.addLineAfter(jmpInstruction, new AsmLabel(newLabel));
|
||||
return true;
|
||||
@ -177,24 +180,24 @@ public class Pass5FixLongBranches extends Pass5AsmOptimization {
|
||||
return false;
|
||||
}
|
||||
|
||||
private AsmInstructionType invertBranch(AsmInstructionType type) {
|
||||
switch(type.getMnemnonic()) {
|
||||
private AsmOpcode invertBranch(AsmOpcode asmOpcode) {
|
||||
switch(asmOpcode.getMnemnonic()) {
|
||||
case "bcc":
|
||||
return AsmInstructionSet.getInstructionType("bcs", AsmAddressingMode.REL, false);
|
||||
return AsmInstructionSet.getOpcode("bcs", AsmAddressingMode.REL, false);
|
||||
case "bcs":
|
||||
return AsmInstructionSet.getInstructionType("bcc", AsmAddressingMode.REL, false);
|
||||
return AsmInstructionSet.getOpcode("bcc", AsmAddressingMode.REL, false);
|
||||
case "beq":
|
||||
return AsmInstructionSet.getInstructionType("bne", AsmAddressingMode.REL, false);
|
||||
return AsmInstructionSet.getOpcode("bne", AsmAddressingMode.REL, false);
|
||||
case "bne":
|
||||
return AsmInstructionSet.getInstructionType("beq", AsmAddressingMode.REL, false);
|
||||
return AsmInstructionSet.getOpcode("beq", AsmAddressingMode.REL, false);
|
||||
case "bpl":
|
||||
return AsmInstructionSet.getInstructionType("bmi", AsmAddressingMode.REL, false);
|
||||
return AsmInstructionSet.getOpcode("bmi", AsmAddressingMode.REL, false);
|
||||
case "bmi":
|
||||
return AsmInstructionSet.getInstructionType("bpl", AsmAddressingMode.REL, false);
|
||||
return AsmInstructionSet.getOpcode("bpl", AsmAddressingMode.REL, false);
|
||||
case "bvs":
|
||||
return AsmInstructionSet.getInstructionType("bvc", AsmAddressingMode.REL, false);
|
||||
return AsmInstructionSet.getOpcode("bvc", AsmAddressingMode.REL, false);
|
||||
case "bvc":
|
||||
return AsmInstructionSet.getInstructionType("bvs", AsmAddressingMode.REL, false);
|
||||
return AsmInstructionSet.getOpcode("bvs", AsmAddressingMode.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.getType().isJump() && !instruction.getType().getMnemnonic().equals("jsr")) {
|
||||
if(instruction.getAsmOpcode().isJump() && !instruction.getAsmOpcode().getMnemnonic().equals("jsr")) {
|
||||
candidate = instruction;
|
||||
}
|
||||
} else if(line instanceof AsmDataString || line instanceof AsmDataNumeric || line instanceof AsmDataFill || line instanceof AsmInlineKickAsm ) {
|
||||
|
@ -38,7 +38,7 @@ public class Pass5RedundantLabelElimination extends Pass5AsmOptimization {
|
||||
}
|
||||
} else if(line instanceof AsmInstruction) {
|
||||
AsmInstruction instruction = (AsmInstruction) line;
|
||||
if(instruction.getType().isJump()) {
|
||||
if(instruction.getAsmOpcode().isJump()) {
|
||||
String labelStr = instruction.getParameter();
|
||||
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.getType().isJump()) {
|
||||
if(asmInstruction.getAsmOpcode().isJump()) {
|
||||
String parameter = asmInstruction.getParameter();
|
||||
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.getType().getMnemnonic().equals("jsr")) {
|
||||
if(instruction.getAsmOpcode().getMnemnonic().equals("jsr")) {
|
||||
if(instruction.getParameter().equals(SymbolRef.MAIN_PROC_NAME)) {
|
||||
lineIterator.remove();
|
||||
optimized = true;
|
||||
|
@ -1,5 +1,8 @@
|
||||
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.kickc.model.Program;
|
||||
|
||||
@ -30,89 +33,89 @@ public class Pass5UnnecesaryLoadElimination extends Pass5AsmOptimization {
|
||||
if(instruction.isDontOptimize()) {
|
||||
continue;
|
||||
}
|
||||
AsmInstructionType instructionType = instruction.getType();
|
||||
AsmOpcode asmOpcode = instruction.getAsmOpcode();
|
||||
|
||||
if(instructionType.getMnemnonic().equals("lda") && instructionType.getAddressingMode().equals(AsmAddressingMode.IMM)) {
|
||||
if(asmOpcode.getMnemnonic().equals("lda") && asmOpcode.getAddressingMode().equals(AsmAddressingMode.IMM)) {
|
||||
String immValue = instruction.getParameter();
|
||||
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.setType(AsmInstructionSet.getInstructionType("txa", AsmAddressingMode.NON, false));
|
||||
instruction.setAsmOpcode(AsmInstructionSet.getOpcode("txa", AsmAddressingMode.NON, false));
|
||||
instruction.setParameter(null);
|
||||
} else if(AsmProgramStaticRegisterValues.matchImm(instructionValues.getY(), immValue)) {
|
||||
getLog().append("Replacing instruction " + instruction + " with TYA");
|
||||
instruction.setType(AsmInstructionSet.getInstructionType("tya", AsmAddressingMode.NON, false));
|
||||
instruction.setAsmOpcode(AsmInstructionSet.getOpcode("tya", AsmAddressingMode.NON, false));
|
||||
instruction.setParameter(null);
|
||||
}
|
||||
}
|
||||
if(instructionType.getMnemnonic().equals("lda") && (instructionType.getAddressingMode().equals(AsmAddressingMode.ZP) || instructionType.getAddressingMode().equals(AsmAddressingMode.ABS))) {
|
||||
if(asmOpcode.getMnemnonic().equals("lda") && (asmOpcode.getAddressingMode().equals(AsmAddressingMode.ZP) || asmOpcode.getAddressingMode().equals(AsmAddressingMode.ABS))) {
|
||||
String memValue = instruction.getParameter();
|
||||
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.setType(AsmInstructionSet.getInstructionType("txa", AsmAddressingMode.NON, false));
|
||||
instruction.setAsmOpcode(AsmInstructionSet.getOpcode("txa", AsmAddressingMode.NON, false));
|
||||
instruction.setParameter(null);
|
||||
} else if(instructionValues.getyMem() != null && instructionValues.getyMem().equals(memValue)) {
|
||||
getLog().append("Replacing instruction " + instruction + " with TYA");
|
||||
instruction.setType(AsmInstructionSet.getInstructionType("tya", AsmAddressingMode.NON, false));
|
||||
instruction.setAsmOpcode(AsmInstructionSet.getOpcode("tya", AsmAddressingMode.NON, false));
|
||||
instruction.setParameter(null);
|
||||
}
|
||||
}
|
||||
if(instructionType.getMnemnonic().equals("ldx") && instructionType.getAddressingMode().equals(AsmAddressingMode.IMM)) {
|
||||
if(asmOpcode.getMnemnonic().equals("ldx") && asmOpcode.getAddressingMode().equals(AsmAddressingMode.IMM)) {
|
||||
String immValue = instruction.getParameter();
|
||||
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.setType(AsmInstructionSet.getInstructionType("tax", AsmAddressingMode.NON, false));
|
||||
instruction.setAsmOpcode(AsmInstructionSet.getOpcode("tax", AsmAddressingMode.NON, false));
|
||||
instruction.setParameter(null);
|
||||
}
|
||||
}
|
||||
if(instructionType.getMnemnonic().equals("ldx") && (instructionType.getAddressingMode().equals(AsmAddressingMode.ZP) || instructionType.getAddressingMode().equals(AsmAddressingMode.ABS))) {
|
||||
if(asmOpcode.getMnemnonic().equals("ldx") && (asmOpcode.getAddressingMode().equals(AsmAddressingMode.ZP) || asmOpcode.getAddressingMode().equals(AsmAddressingMode.ABS))) {
|
||||
String memValue = instruction.getParameter();
|
||||
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.setType(AsmInstructionSet.getInstructionType("tax", AsmAddressingMode.NON, false));
|
||||
instruction.setAsmOpcode(AsmInstructionSet.getOpcode("tax", AsmAddressingMode.NON, false));
|
||||
instruction.setParameter(null);
|
||||
}
|
||||
}
|
||||
if(instructionType.getMnemnonic().equals("ldy") && instructionType.getAddressingMode().equals(AsmAddressingMode.IMM)) {
|
||||
if(asmOpcode.getMnemnonic().equals("ldy") && asmOpcode.getAddressingMode().equals(AsmAddressingMode.IMM)) {
|
||||
String immValue = instruction.getParameter();
|
||||
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.setType(AsmInstructionSet.getInstructionType("tay", AsmAddressingMode.NON, false));
|
||||
instruction.setAsmOpcode(AsmInstructionSet.getOpcode("tay", AsmAddressingMode.NON, false));
|
||||
instruction.setParameter(null);
|
||||
}
|
||||
}
|
||||
if(instructionType.getMnemnonic().equals("ldy") && (instructionType.getAddressingMode().equals(AsmAddressingMode.ZP) || instructionType.getAddressingMode().equals(AsmAddressingMode.ABS))) {
|
||||
if(asmOpcode.getMnemnonic().equals("ldy") && (asmOpcode.getAddressingMode().equals(AsmAddressingMode.ZP) || asmOpcode.getAddressingMode().equals(AsmAddressingMode.ABS))) {
|
||||
String memValue = instruction.getParameter();
|
||||
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.setType(AsmInstructionSet.getInstructionType("tay", AsmAddressingMode.NON, false));
|
||||
instruction.setAsmOpcode(AsmInstructionSet.getOpcode("tay", AsmAddressingMode.NON, false));
|
||||
instruction.setParameter(null);
|
||||
}
|
||||
}
|
||||
if(instructionType.getMnemnonic().equals("clc")) {
|
||||
if(asmOpcode.getMnemnonic().equals("clc")) {
|
||||
AsmProgramStaticRegisterValues.AsmRegisterValues instructionValues = staticValues.getValues(instruction);
|
||||
if(Boolean.FALSE.equals(instructionValues.getC())) {
|
||||
modified = remove(lineIt);
|
||||
}
|
||||
}
|
||||
if(instructionType.getMnemnonic().equals("sec")) {
|
||||
if(asmOpcode.getMnemnonic().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.getType().getMnemnonic().equals("rts") || asmInstruction.getType().getMnemnonic().equals("jmp")) {
|
||||
if(asmInstruction.getAsmOpcode().getMnemnonic().equals("rts") || asmInstruction.getAsmOpcode().getMnemnonic().equals("jmp")) {
|
||||
afterExit = true;
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,9 @@
|
||||
package dk.camelot64.kickc.passes;
|
||||
|
||||
import dk.camelot64.kickc.asm.*;
|
||||
import dk.camelot64.kickc.model.ControlFlowBlock;
|
||||
import dk.camelot64.kickc.model.Program;
|
||||
import dk.camelot64.kickc.model.statements.Statement;
|
||||
import dk.camelot64.kickc.model.statements.StatementAsm;
|
||||
import dk.camelot64.kickc.model.values.LabelRef;
|
||||
import dk.camelot64.kickc.model.values.SymbolRef;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashSet;
|
||||
@ -44,7 +41,7 @@ public class Pass5UnusedLabelElimination extends Pass5AsmOptimization {
|
||||
usedLabels.add(labelStr);
|
||||
} else if(line instanceof AsmInstruction) {
|
||||
AsmInstruction instruction = (AsmInstruction) line;
|
||||
if(instruction.getType().isJump()) {
|
||||
if(instruction.getAsmOpcode().isJump()) {
|
||||
String labelStr = currentScope + "::" + instruction.getParameter();
|
||||
usedLabels.add(labelStr);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user