mirror of
https://gitlab.com/camelot/kickc.git
synced 2025-04-21 11:42:30 +00:00
Added support for all new addressing modes used in CPU's 65C02, 65CE02 and 45GS02.
This commit is contained in:
parent
a8b5929adf
commit
a454ee2cdd
@ -11,21 +11,24 @@ public enum AsmAddressingMode {
|
||||
* on the accumulator"
|
||||
*/
|
||||
NON("", "%i", 1),
|
||||
|
||||
/**
|
||||
* Immediate
|
||||
* #imm Immediate <br>
|
||||
* 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
|
||||
* zp Zeropage <br>
|
||||
* 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
|
||||
* zp,x X Indexed Zeropage <br>
|
||||
* 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
|
||||
@ -33,8 +36,9 @@ public enum AsmAddressingMode {
|
||||
* 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
|
||||
* zp,y Y Indexed Zeropage <br>
|
||||
* 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
|
||||
@ -42,15 +46,17 @@ public enum AsmAddressingMode {
|
||||
* 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
|
||||
* abs Absolute <br>
|
||||
* 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
|
||||
* abs,x Absolute X <br>
|
||||
* 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
|
||||
@ -59,8 +65,9 @@ public enum AsmAddressingMode {
|
||||
* and execution time.
|
||||
*/
|
||||
ABX("abs,x", "%i %p,x", 3),
|
||||
|
||||
/**
|
||||
* Absolute Y
|
||||
* abs,y Absolute Y <br>
|
||||
* 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
|
||||
@ -69,9 +76,10 @@ public enum AsmAddressingMode {
|
||||
* 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
|
||||
* (zp,x) Indirect Zeropage X <br>
|
||||
* INDEXED INDIRECT ZEROPAGE 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
|
||||
@ -79,32 +87,96 @@ public enum AsmAddressingMode {
|
||||
* 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
|
||||
* (abs,x) Indirect Absolute X <br>
|
||||
* "ABSOLUTE INDEXED INDIRECT
|
||||
* With the Absolute Indexed Indirect addressing mode, the X Index Register is added to the second and third bytes of
|
||||
* the instruction to form an address to a pointer. This address mode is only used with the JMP/JSR instruction and the
|
||||
* program Counter is loaded with the first and second bytes at this pointer."
|
||||
*/
|
||||
IAX("(abs,x)", "%i (%p,x)", 3),
|
||||
|
||||
/**
|
||||
* (zp),y 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."
|
||||
* (zp),z Indirect Zeropage Z <br>
|
||||
* INDIRECT INDEXED ADDRESSING — In indirect indexed addressing (referred to as (Indirect),Z ), 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."
|
||||
*/
|
||||
REL("rel", "%i %p", 2),
|
||||
IZZ("(zp),z", "%i.z (%p),z", 2),
|
||||
|
||||
/**
|
||||
* Indirect Absolute
|
||||
* (abs) Indirect Absolute <br>
|
||||
* 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);
|
||||
IND("(abs)", "%i (%p)", 3),
|
||||
|
||||
/**
|
||||
* (zp) Indirect Zeropage <br>
|
||||
* ZEROPAGE INDIRECT
|
||||
* The second byte of the instruction contains address of a zeropage memory location.
|
||||
*/
|
||||
INZ("(zp)", "%i.z (%p)", 2),
|
||||
|
||||
/**
|
||||
* ((zp)) 32-bit Indirect Zeropage <br>
|
||||
* 32BIT ZEROPAGE INDIRECT ADDRESSING
|
||||
* In indirect addressing the second byte of the instruction points to a memory location in page zero. This mode is
|
||||
* formed by preceding a Base Page Indirect Mode instruction with NEG NEG NOP instructions.
|
||||
*/
|
||||
LIN("((zp))", "%i.z ((%p))", 2),
|
||||
|
||||
/**
|
||||
* ((zp)),z 32-bit Indirect Zeropage Z <br>
|
||||
* 32BIT INDIRECT INDEXED ADDRESSING
|
||||
* In indirect indexed addressing the second byte of the instruction points to a memory location in page zero. This
|
||||
* mode is formed by preceding a Base Page Indirect Z-Indexed Mode instruction with the NOP instruction (opcode $EA).
|
||||
*/
|
||||
LIZ("((zp)),z", "%i.z ((%p)),z", 2),
|
||||
|
||||
/**
|
||||
* (zp,sp),y Stack Pointer Indirect Indexed <br>
|
||||
* STACK POINTER INDIRECT INDEXED - This new mode is similar to indirect indexed addressing. The Stack replaces
|
||||
* the Base Page and the second instruction byte specifies the displacement from the current stack pointer location
|
||||
* rather than the location within Base Page. The contents of this displaced stack location are added to the contents
|
||||
* of the Y index register, the result becomes the low order eight bits ot the effective address. The carry from this
|
||||
* addition is added to the contents of the next (D -1) stack location the result being the high order eight bits of
|
||||
* the effective address." STA ($12,SP),Y
|
||||
*/
|
||||
ISY("(zp,sp),y", "%i.z (%p,sp),y", 2),
|
||||
|
||||
/**
|
||||
* Relative <br>
|
||||
* 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),
|
||||
|
||||
/**
|
||||
* zp,rel Zeropage Test Relative
|
||||
* ZEROPAGE TEST RELATIVE. It needs two one-byte operands, one for the zero page address that is used for the bit
|
||||
* test, and one indicating the signed relative PC offset if the branch is taken. This makes BBRi and BBSi the single
|
||||
* instructions with two explicit operands.
|
||||
*/
|
||||
REZ("zp,rel", "%i %p,%q", 3);
|
||||
|
||||
/** The short name of the addressing mode. */
|
||||
private String name;
|
||||
@ -129,10 +201,22 @@ public enum AsmAddressingMode {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getAsm(String mnemnonic, String parameter) {
|
||||
/**
|
||||
* Get the printed ASM code for the instruction with an operand value.
|
||||
* This prints to the syntax that KickAssembler expects.
|
||||
*
|
||||
* @param mnemnonic The opcode mnemonic
|
||||
* @param operand The operand value. Null if addressing mode is Implied/A/None
|
||||
* @param operand2 The second operand value (only used for addressing mode Zeropage Test Relative)
|
||||
* @return The printed ASM code for the instruction
|
||||
*/
|
||||
public String getAsm(String mnemnonic, String operand, String operand2) {
|
||||
String replaced = template.replace("%i", mnemnonic);
|
||||
if(parameter != null) {
|
||||
replaced = replaced.replace("%p", parameter);
|
||||
if(operand != null) {
|
||||
replaced = replaced.replace("%p", operand);
|
||||
}
|
||||
if(operand2 != null) {
|
||||
replaced = replaced.replace("%q", operand2);
|
||||
}
|
||||
return replaced;
|
||||
}
|
||||
|
@ -329,7 +329,14 @@ public class AsmInstructionSet {
|
||||
if(AsmAddressingMode.ABY.equals(mode) && isZp) {
|
||||
asmOpcode = set.getOpcode(mnemonic, AsmAddressingMode.ZPY);
|
||||
}
|
||||
if(AsmAddressingMode.IND.equals(mode) && isZp) {
|
||||
asmOpcode = set.getOpcode(mnemonic, AsmAddressingMode.INZ);
|
||||
}
|
||||
if(AsmAddressingMode.IAX.equals(mode) && isZp) {
|
||||
asmOpcode = set.getOpcode(mnemonic, AsmAddressingMode.IZX);
|
||||
}
|
||||
if(asmOpcode == null) {
|
||||
// If the ZP-variation does not exist use the ABS-variation
|
||||
asmOpcode = set.getOpcode(mnemonic, mode);
|
||||
}
|
||||
if(asmOpcode == null && AsmAddressingMode.ABS.equals(mode)) {
|
||||
|
@ -24,7 +24,7 @@ public class AsmOpcode {
|
||||
private final double cycles;
|
||||
|
||||
/** Which registers/flags of the CPU are clobbered by the instruction. */
|
||||
private AsmClobber clobber;
|
||||
private final AsmClobber clobber;
|
||||
|
||||
AsmOpcode(int opcode, String mnemonic, AsmAddressingMode addressingMode, double cycles, String clobberString) {
|
||||
this.opcode = new int[]{opcode};
|
||||
@ -85,22 +85,24 @@ public class AsmOpcode {
|
||||
|
||||
/**
|
||||
* Determines if this instruction has a specific single byte opcode
|
||||
*
|
||||
* @param opcode The byte opcode to check
|
||||
* @return true if this instruction has a 1-byte opcode that matches the passed value.
|
||||
*/
|
||||
public boolean hasOpcode(int opcode) {
|
||||
return this.opcode.length==1 && this.opcode[0]==(byte)opcode;
|
||||
return this.opcode.length == 1 && this.opcode[0] == (byte) opcode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the printed ASM code for the instruction with an operand value.
|
||||
* This prints to the syntax that KickAssembler expects.
|
||||
*
|
||||
* @param operand The operand value
|
||||
* @param operand The operand value. Null if addressing mode is Implied/A/None
|
||||
* @param operand2 The second operand value (only used for addressing mode Zeropage Test Relative)
|
||||
* @return The printed ASM code for the instruction
|
||||
*/
|
||||
public String getAsm(String operand) {
|
||||
return addressingMode.getAsm(mnemonic, operand);
|
||||
public String getAsm(String operand, String operand2) {
|
||||
return addressingMode.getAsm(mnemonic, operand, operand2);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -123,13 +125,4 @@ public class AsmOpcode {
|
||||
return clobber.isRegisterPC();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the clobber information of the opcode.
|
||||
* TODO: Remove this setter and initialize using the constructor instead.
|
||||
* @param asmClobber The new clobber information
|
||||
*/
|
||||
public void setClobber(AsmClobber asmClobber) {
|
||||
this.clobber = asmClobber;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -7,29 +7,53 @@ 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 String parameter;
|
||||
/** The ASM opcode parameter. Null if the opcode addressing mode is Implied/A/None {@link AsmAddressingMode#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 */
|
||||
private String operand2;
|
||||
|
||||
/** The index of the instruction in the program. */
|
||||
private int index;
|
||||
|
||||
/** If true the instruction will not be optimized away. */
|
||||
private boolean dontOptimize;
|
||||
|
||||
public AsmInstruction(AsmOpcode asmOpcode, String parameter) {
|
||||
public AsmInstruction(AsmOpcode asmOpcode) {
|
||||
this.asmOpcode = asmOpcode;
|
||||
this.parameter = parameter;
|
||||
if(AsmAddressingMode.NON.equals(asmOpcode.getAddressingMode()) && parameter != null)
|
||||
throw new InternalError("Opcode with NON paramter cannot have a parameter");
|
||||
this.operand1 = null;
|
||||
this.operand2 = null;
|
||||
}
|
||||
|
||||
public String getParameter() {
|
||||
return parameter;
|
||||
public AsmInstruction(AsmOpcode asmOpcode, String operand1) {
|
||||
this.asmOpcode = asmOpcode;
|
||||
this.operand1 = operand1;
|
||||
this.operand2 = null;
|
||||
}
|
||||
|
||||
public void setParameter(String parameter) {
|
||||
if(AsmAddressingMode.NON.equals(asmOpcode.getAddressingMode()) && parameter != null)
|
||||
throw new InternalError("Opcode with NON paramter cannot have a parameter");
|
||||
this.parameter = parameter;
|
||||
public AsmInstruction(AsmOpcode asmOpcode, String operand1, String operand2) {
|
||||
this.asmOpcode = asmOpcode;
|
||||
this.operand1 = operand1;
|
||||
this.operand2 = operand2;
|
||||
}
|
||||
|
||||
public String getOperand1() {
|
||||
return operand1;
|
||||
}
|
||||
|
||||
public void setOperand1(String operand1) {
|
||||
this.operand1 = operand1;
|
||||
}
|
||||
|
||||
public String getOperand2() {
|
||||
return operand2;
|
||||
}
|
||||
|
||||
public void setOperand2(String operand2) {
|
||||
this.operand2 = operand2;
|
||||
}
|
||||
|
||||
public AsmOpcode getAsmOpcode() {
|
||||
@ -52,7 +76,7 @@ public class AsmInstruction implements AsmLine {
|
||||
|
||||
@Override
|
||||
public String getAsm() {
|
||||
return asmOpcode.getAsm(parameter);
|
||||
return asmOpcode.getAsm(operand1, operand2);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -77,4 +101,44 @@ public class AsmInstruction implements AsmLine {
|
||||
public void setDontOptimize(boolean dontOptimize) {
|
||||
this.dontOptimize = dontOptimize;
|
||||
}
|
||||
}
|
||||
|
||||
/***
|
||||
* Get the operand value that represents a jump target (if the opcode is a jump as defined by {@link AsmOpcode#isJump()}
|
||||
* @return The jump target operand
|
||||
*/
|
||||
public String getOperandJumpTarget() {
|
||||
if(asmOpcode.isJump()) {
|
||||
if(AsmAddressingMode.REZ.equals(asmOpcode.getAddressingMode())) {
|
||||
// For addressing mode Zeropage Test Relative the jump target is operand2: bbr0 zp,rel
|
||||
return operand2;
|
||||
} else {
|
||||
// For all other jump addressing modes jump target is operand1
|
||||
return operand1;
|
||||
}
|
||||
} else
|
||||
// Not a jump
|
||||
return null;
|
||||
}
|
||||
|
||||
/***
|
||||
* Set the operand value that represents a jump target (if the opcode is a jump as defined by {@link AsmOpcode#isJump()}
|
||||
* @param operand The new jump target operand
|
||||
*/
|
||||
public void setOperandJumpTarget(String operand) {
|
||||
if(asmOpcode.isJump()) {
|
||||
if(AsmAddressingMode.REZ.equals(asmOpcode.getAddressingMode())) {
|
||||
// For addressing mode Zeropage Test Relative the jump target is operand2: bbr0 zp,rel
|
||||
operand2 = operand;
|
||||
} else {
|
||||
// For all other jump addressing modes jump target is operand1
|
||||
operand1 = operand;
|
||||
}
|
||||
} else {
|
||||
throw new InternalError("Error! Instruction is not a jump "+getAsm());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@ -119,7 +119,7 @@ public class AsmProgramStaticRegisterValues {
|
||||
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 modParam = instruction.getParameter();
|
||||
String modParam = instruction.getOperand1();
|
||||
if(current.getaMem() != null && current.getaMem().equals(modParam)) {
|
||||
current.setaMem(null);
|
||||
}
|
||||
@ -131,57 +131,57 @@ public class AsmProgramStaticRegisterValues {
|
||||
}
|
||||
}
|
||||
if(mnemnonic.equals("lda") && addressingMode.equals(AsmAddressingMode.IMM)) {
|
||||
current.setA(instruction.getParameter());
|
||||
current.setA(instruction.getOperand1());
|
||||
current.setaMem(null);
|
||||
Integer immValue = getImmValue(instruction.getParameter());
|
||||
Integer immValue = getImmValue(instruction.getOperand1());
|
||||
if(immValue != null) {
|
||||
current.setZ(immValue == 0);
|
||||
current.setN(immValue > 127);
|
||||
}
|
||||
}
|
||||
if(mnemnonic.equals("lda") && (addressingMode.equals(AsmAddressingMode.ZP) || addressingMode.equals(AsmAddressingMode.ABS))) {
|
||||
current.setaMem(instruction.getParameter());
|
||||
current.setaMem(instruction.getOperand1());
|
||||
current.setA(null);
|
||||
}
|
||||
if(mnemnonic.equals("sta") && (addressingMode.equals(AsmAddressingMode.ZP) || addressingMode.equals(AsmAddressingMode.ABS))) {
|
||||
current.setaMem(instruction.getParameter());
|
||||
if(instruction.getParameter().equals(current.getyMem())) current.setyMem(null);
|
||||
if(instruction.getParameter().equals(current.getxMem())) current.setxMem(null);
|
||||
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)) {
|
||||
current.setX(instruction.getParameter());
|
||||
current.setX(instruction.getOperand1());
|
||||
current.setxMem(null);
|
||||
Integer immValue = getImmValue(instruction.getParameter());
|
||||
Integer immValue = getImmValue(instruction.getOperand1());
|
||||
if(immValue != null) {
|
||||
current.setZ(immValue == 0);
|
||||
current.setN(immValue > 127);
|
||||
}
|
||||
}
|
||||
if(mnemnonic.equals("ldx") && (addressingMode.equals(AsmAddressingMode.ZP) || addressingMode.equals(AsmAddressingMode.ABS))) {
|
||||
current.setxMem(instruction.getParameter());
|
||||
current.setxMem(instruction.getOperand1());
|
||||
current.setX(null);
|
||||
}
|
||||
if(mnemnonic.equals("stx") && (addressingMode.equals(AsmAddressingMode.ZP) || addressingMode.equals(AsmAddressingMode.ABS))) {
|
||||
current.setxMem(instruction.getParameter());
|
||||
if(instruction.getParameter().equals(current.getyMem())) current.setyMem(null);
|
||||
if(instruction.getParameter().equals(current.getaMem())) current.setaMem(null);
|
||||
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)) {
|
||||
current.setY(instruction.getParameter());
|
||||
current.setY(instruction.getOperand1());
|
||||
current.setyMem(null);
|
||||
Integer immValue = getImmValue(instruction.getParameter());
|
||||
Integer immValue = getImmValue(instruction.getOperand1());
|
||||
if(immValue != null) {
|
||||
current.setZ(immValue == 0);
|
||||
current.setN(immValue > 127);
|
||||
}
|
||||
}
|
||||
if(mnemnonic.equals("ldy") && (addressingMode.equals(AsmAddressingMode.ZP) || addressingMode.equals(AsmAddressingMode.ABS))) {
|
||||
current.setyMem(instruction.getParameter());
|
||||
current.setyMem(instruction.getOperand1());
|
||||
}
|
||||
if(mnemnonic.equals("sty") && (addressingMode.equals(AsmAddressingMode.ZP) || addressingMode.equals(AsmAddressingMode.ABS))) {
|
||||
current.setyMem(instruction.getParameter());
|
||||
if(instruction.getParameter().equals(current.getxMem())) current.setxMem(null);
|
||||
if(instruction.getParameter().equals(current.getaMem())) current.setaMem(null);
|
||||
current.setyMem(instruction.getOperand1());
|
||||
if(instruction.getOperand1().equals(current.getxMem())) current.setxMem(null);
|
||||
if(instruction.getOperand1().equals(current.getaMem())) current.setaMem(null);
|
||||
}
|
||||
if(mnemnonic.equals("txa")) {
|
||||
current.setA(current.getX());
|
||||
|
@ -227,50 +227,63 @@ public class AsmFragmentInstance {
|
||||
KickCParser.AsmParamModeContext paramModeCtx = ctx.asmParamMode();
|
||||
AsmInstruction instruction;
|
||||
if(paramModeCtx == null) {
|
||||
final String mnemonic = ctx.ASM_MNEMONIC().getText();
|
||||
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(asmOpcode, null);
|
||||
instruction = createAsmInstruction(ctx, null, null,AsmAddressingMode.NON);
|
||||
} else {
|
||||
instruction = (AsmInstruction) this.visit(paramModeCtx);
|
||||
}
|
||||
if(instruction != null) {
|
||||
program.addLine(instruction);
|
||||
} else {
|
||||
throw new RuntimeException("Error parsing ASM fragment line in dk/camelot64/kickc/fragment/asm/" + name + ".asm\n - Line: " + ctx.getText());
|
||||
throw new RuntimeException("Error parsing ASM fragment line " + name + ".asm\n - Line: " + ctx.getText());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitAsmModeAbs(KickCParser.AsmModeAbsContext ctx) {
|
||||
return createAsmInstruction(ctx, ctx.asmExpr(), AsmAddressingMode.ABS);
|
||||
return createAsmInstruction(ctx, ctx.asmExpr(), null,AsmAddressingMode.ABS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitAsmModeImm(KickCParser.AsmModeImmContext ctx) {
|
||||
return createAsmInstruction(ctx, ctx.asmExpr(), AsmAddressingMode.IMM);
|
||||
return createAsmInstruction(ctx, ctx.asmExpr(), null,AsmAddressingMode.IMM);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitAsmModeAbsXY(KickCParser.AsmModeAbsXYContext ctx) {
|
||||
String xy = ctx.getChild(ctx.getChildCount() - 1).getText();
|
||||
if(xy.equals("x")) {
|
||||
return createAsmInstruction(ctx, ctx.asmExpr(), AsmAddressingMode.ABX);
|
||||
} else if(xy.equals("y")) {
|
||||
return createAsmInstruction(ctx, ctx.asmExpr(), AsmAddressingMode.ABY);
|
||||
final KickCParser.AsmExprContext indexCtx = ctx.asmExpr(1);
|
||||
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);
|
||||
} else if(xy.equals("y")) {
|
||||
return createAsmInstruction(ctx, ctx.asmExpr(0), null,AsmAddressingMode.ABY);
|
||||
} else {
|
||||
throw new RuntimeException("Unknown addressing mode " + ctx.getText());
|
||||
}
|
||||
} else {
|
||||
// Test Relative Addressing Mode (2 parameters)
|
||||
return createAsmInstruction(ctx, ctx.asmExpr(0), ctx.asmExpr(1), AsmAddressingMode.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);
|
||||
} else if(xy.equals("z")) {
|
||||
return createAsmInstruction(ctx, ctx.asmExpr(), null,AsmAddressingMode.IZZ);
|
||||
} else {
|
||||
throw new RuntimeException("Unknown addressing mode " + ctx.getText());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitAsmModeIndIdxXY(KickCParser.AsmModeIndIdxXYContext ctx) {
|
||||
String xy = ctx.getChild(ctx.getChildCount() - 1).getText();
|
||||
if(xy.equals("y")) {
|
||||
return createAsmInstruction(ctx, ctx.asmExpr(), AsmAddressingMode.IZY);
|
||||
public Object visitAsmModeIndLongIdxXY(KickCParser.AsmModeIndLongIdxXYContext ctx) {
|
||||
String xy = ctx.ASM_NAME().getText();
|
||||
if(xy.equals("z")) {
|
||||
return createAsmInstruction(ctx, ctx.asmExpr(), null,AsmAddressingMode.LIZ);
|
||||
} else {
|
||||
throw new RuntimeException("Unknown addressing mode " + ctx.getText());
|
||||
}
|
||||
@ -278,9 +291,20 @@ public class AsmFragmentInstance {
|
||||
|
||||
@Override
|
||||
public Object visitAsmModeIdxIndXY(KickCParser.AsmModeIdxIndXYContext ctx) {
|
||||
String xy = ctx.getChild(ctx.getChildCount() - 1).getText();
|
||||
String xy = ctx.ASM_NAME().getText();
|
||||
if(xy.equals("x")) {
|
||||
return createAsmInstruction(ctx, ctx.asmExpr(), AsmAddressingMode.IZX);
|
||||
return createAsmInstruction(ctx, ctx.asmExpr(), null,AsmAddressingMode.IAX);
|
||||
} else {
|
||||
throw new RuntimeException("Unknown addressing mode " + ctx.getText());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitAsmModeSPIndIdx(KickCParser.AsmModeSPIndIdxContext ctx) {
|
||||
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);
|
||||
} else {
|
||||
throw new RuntimeException("Unknown addressing mode " + ctx.getText());
|
||||
}
|
||||
@ -288,21 +312,39 @@ public class AsmFragmentInstance {
|
||||
|
||||
@Override
|
||||
public Object visitAsmModeInd(KickCParser.AsmModeIndContext ctx) {
|
||||
return createAsmInstruction(ctx, ctx.asmExpr(), AsmAddressingMode.IND);
|
||||
return createAsmInstruction(ctx, ctx.asmExpr(), null, AsmAddressingMode.IND);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitAsmModeIndLong(KickCParser.AsmModeIndLongContext ctx) {
|
||||
return createAsmInstruction(ctx, ctx.asmExpr(), null, AsmAddressingMode.LIN);
|
||||
}
|
||||
|
||||
private AsmInstruction createAsmInstruction(
|
||||
KickCParser.AsmParamModeContext ctx,
|
||||
KickCParser.AsmExprContext exprCtx,
|
||||
KickCParser.AsmParamModeContext paramModeCtx,
|
||||
KickCParser.AsmExprContext operand1Ctx,
|
||||
KickCParser.AsmExprContext operand2Ctx,
|
||||
AsmAddressingMode addressingMode) {
|
||||
return createAsmInstruction((KickCParser.AsmInstructionContext) paramModeCtx.getParent(), operand1Ctx, operand2Ctx, addressingMode);
|
||||
}
|
||||
|
||||
private AsmInstruction createAsmInstruction(
|
||||
KickCParser.AsmInstructionContext instructionCtx,
|
||||
KickCParser.AsmExprContext operand1Ctx,
|
||||
KickCParser.AsmExprContext operand2Ctx,
|
||||
AsmAddressingMode addressingMode) {
|
||||
KickCParser.AsmInstructionContext instructionCtx = (KickCParser.AsmInstructionContext) ctx.getParent();
|
||||
AsmParameter parameter = (AsmParameter) this.visit(exprCtx);
|
||||
String mnemonic = instructionCtx.ASM_MNEMONIC().getSymbol().getText();
|
||||
AsmOpcode asmOpcode = AsmInstructionSet.getOpcode(mnemonic, addressingMode, parameter.isZp());
|
||||
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);
|
||||
String operand1 = param1 == null ? null : param1.getParam();
|
||||
String operand2 = param2 == null ? null : param2.getParam();
|
||||
if(asmOpcode == null) {
|
||||
throw new InternalError("Error in " + name + ".asm line " + instructionCtx.getStart().getLine() + " - Instruction type unknown " + mnemonic + " " + addressingMode + " " + parameter);
|
||||
throw new InternalError("Error in " + name + ".asm line " + instructionCtx.getStart().getLine() + " - Instruction type not supported " + addressingMode.getAsm(mnemonic, operand1, operand2));
|
||||
}
|
||||
return new AsmInstruction(asmOpcode, parameter.getParam());
|
||||
return new AsmInstruction(asmOpcode, operand1, operand2);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -301,10 +301,13 @@ asmBytes
|
||||
asmParamMode
|
||||
: asmExpr #asmModeAbs
|
||||
| ASM_IMM asmExpr #asmModeImm
|
||||
| asmExpr ASM_COMMA ASM_NAME #asmModeAbsXY
|
||||
| asmExpr ASM_COMMA asmExpr #asmModeAbsXY
|
||||
| ASM_PAR_BEGIN asmExpr ASM_PAR_END ASM_COMMA ASM_NAME #asmModeIndIdxXY
|
||||
| ASM_PAR_BEGIN ASM_PAR_BEGIN asmExpr ASM_PAR_END ASM_PAR_END ASM_COMMA ASM_NAME #asmModeIndLongIdxXY
|
||||
| ASM_PAR_BEGIN asmExpr ASM_COMMA ASM_NAME ASM_PAR_END ASM_COMMA ASM_NAME #asmModeSPIndIdx
|
||||
| ASM_PAR_BEGIN asmExpr ASM_COMMA ASM_NAME ASM_PAR_END #asmModeIdxIndXY
|
||||
| ASM_PAR_BEGIN asmExpr ASM_PAR_END #asmModeInd
|
||||
| ASM_PAR_BEGIN ASM_PAR_BEGIN asmExpr ASM_PAR_END ASM_PAR_END #asmModeIndLong
|
||||
;
|
||||
|
||||
asmExpr
|
||||
|
File diff suppressed because one or more lines are too long
@ -6719,12 +6719,70 @@ public class KickCParser extends Parser {
|
||||
else return visitor.visitChildren(this);
|
||||
}
|
||||
}
|
||||
public static class AsmModeAbsXYContext extends AsmParamModeContext {
|
||||
public static class AsmModeSPIndIdxContext extends AsmParamModeContext {
|
||||
public TerminalNode ASM_PAR_BEGIN() { return getToken(KickCParser.ASM_PAR_BEGIN, 0); }
|
||||
public AsmExprContext asmExpr() {
|
||||
return getRuleContext(AsmExprContext.class,0);
|
||||
}
|
||||
public List<TerminalNode> ASM_COMMA() { return getTokens(KickCParser.ASM_COMMA); }
|
||||
public TerminalNode ASM_COMMA(int i) {
|
||||
return getToken(KickCParser.ASM_COMMA, i);
|
||||
}
|
||||
public List<TerminalNode> ASM_NAME() { return getTokens(KickCParser.ASM_NAME); }
|
||||
public TerminalNode ASM_NAME(int i) {
|
||||
return getToken(KickCParser.ASM_NAME, i);
|
||||
}
|
||||
public TerminalNode ASM_PAR_END() { return getToken(KickCParser.ASM_PAR_END, 0); }
|
||||
public AsmModeSPIndIdxContext(AsmParamModeContext ctx) { copyFrom(ctx); }
|
||||
@Override
|
||||
public void enterRule(ParseTreeListener listener) {
|
||||
if ( listener instanceof KickCParserListener ) ((KickCParserListener)listener).enterAsmModeSPIndIdx(this);
|
||||
}
|
||||
@Override
|
||||
public void exitRule(ParseTreeListener listener) {
|
||||
if ( listener instanceof KickCParserListener ) ((KickCParserListener)listener).exitAsmModeSPIndIdx(this);
|
||||
}
|
||||
@Override
|
||||
public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
|
||||
if ( visitor instanceof KickCParserVisitor ) return ((KickCParserVisitor<? extends T>)visitor).visitAsmModeSPIndIdx(this);
|
||||
else return visitor.visitChildren(this);
|
||||
}
|
||||
}
|
||||
public static class AsmModeIndLongContext extends AsmParamModeContext {
|
||||
public List<TerminalNode> ASM_PAR_BEGIN() { return getTokens(KickCParser.ASM_PAR_BEGIN); }
|
||||
public TerminalNode ASM_PAR_BEGIN(int i) {
|
||||
return getToken(KickCParser.ASM_PAR_BEGIN, i);
|
||||
}
|
||||
public AsmExprContext asmExpr() {
|
||||
return getRuleContext(AsmExprContext.class,0);
|
||||
}
|
||||
public List<TerminalNode> ASM_PAR_END() { return getTokens(KickCParser.ASM_PAR_END); }
|
||||
public TerminalNode ASM_PAR_END(int i) {
|
||||
return getToken(KickCParser.ASM_PAR_END, i);
|
||||
}
|
||||
public AsmModeIndLongContext(AsmParamModeContext ctx) { copyFrom(ctx); }
|
||||
@Override
|
||||
public void enterRule(ParseTreeListener listener) {
|
||||
if ( listener instanceof KickCParserListener ) ((KickCParserListener)listener).enterAsmModeIndLong(this);
|
||||
}
|
||||
@Override
|
||||
public void exitRule(ParseTreeListener listener) {
|
||||
if ( listener instanceof KickCParserListener ) ((KickCParserListener)listener).exitAsmModeIndLong(this);
|
||||
}
|
||||
@Override
|
||||
public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
|
||||
if ( visitor instanceof KickCParserVisitor ) return ((KickCParserVisitor<? extends T>)visitor).visitAsmModeIndLong(this);
|
||||
else return visitor.visitChildren(this);
|
||||
}
|
||||
}
|
||||
public static class AsmModeAbsXYContext extends AsmParamModeContext {
|
||||
public List<AsmExprContext> asmExpr() {
|
||||
return getRuleContexts(AsmExprContext.class);
|
||||
}
|
||||
public AsmExprContext asmExpr(int i) {
|
||||
return getRuleContext(AsmExprContext.class,i);
|
||||
}
|
||||
public TerminalNode ASM_COMMA() { return getToken(KickCParser.ASM_COMMA, 0); }
|
||||
public TerminalNode ASM_NAME() { return getToken(KickCParser.ASM_NAME, 0); }
|
||||
public AsmModeAbsXYContext(AsmParamModeContext ctx) { copyFrom(ctx); }
|
||||
@Override
|
||||
public void enterRule(ParseTreeListener listener) {
|
||||
@ -6740,6 +6798,35 @@ public class KickCParser extends Parser {
|
||||
else return visitor.visitChildren(this);
|
||||
}
|
||||
}
|
||||
public static class AsmModeIndLongIdxXYContext extends AsmParamModeContext {
|
||||
public List<TerminalNode> ASM_PAR_BEGIN() { return getTokens(KickCParser.ASM_PAR_BEGIN); }
|
||||
public TerminalNode ASM_PAR_BEGIN(int i) {
|
||||
return getToken(KickCParser.ASM_PAR_BEGIN, i);
|
||||
}
|
||||
public AsmExprContext asmExpr() {
|
||||
return getRuleContext(AsmExprContext.class,0);
|
||||
}
|
||||
public List<TerminalNode> ASM_PAR_END() { return getTokens(KickCParser.ASM_PAR_END); }
|
||||
public TerminalNode ASM_PAR_END(int i) {
|
||||
return getToken(KickCParser.ASM_PAR_END, i);
|
||||
}
|
||||
public TerminalNode ASM_COMMA() { return getToken(KickCParser.ASM_COMMA, 0); }
|
||||
public TerminalNode ASM_NAME() { return getToken(KickCParser.ASM_NAME, 0); }
|
||||
public AsmModeIndLongIdxXYContext(AsmParamModeContext ctx) { copyFrom(ctx); }
|
||||
@Override
|
||||
public void enterRule(ParseTreeListener listener) {
|
||||
if ( listener instanceof KickCParserListener ) ((KickCParserListener)listener).enterAsmModeIndLongIdxXY(this);
|
||||
}
|
||||
@Override
|
||||
public void exitRule(ParseTreeListener listener) {
|
||||
if ( listener instanceof KickCParserListener ) ((KickCParserListener)listener).exitAsmModeIndLongIdxXY(this);
|
||||
}
|
||||
@Override
|
||||
public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
|
||||
if ( visitor instanceof KickCParserVisitor ) return ((KickCParserVisitor<? extends T>)visitor).visitAsmModeIndLongIdxXY(this);
|
||||
else return visitor.visitChildren(this);
|
||||
}
|
||||
}
|
||||
public static class AsmModeIdxIndXYContext extends AsmParamModeContext {
|
||||
public TerminalNode ASM_PAR_BEGIN() { return getToken(KickCParser.ASM_PAR_BEGIN, 0); }
|
||||
public AsmExprContext asmExpr() {
|
||||
@ -6831,7 +6918,7 @@ public class KickCParser extends Parser {
|
||||
AsmParamModeContext _localctx = new AsmParamModeContext(_ctx, getState());
|
||||
enterRule(_localctx, 90, RULE_asmParamMode);
|
||||
try {
|
||||
setState(864);
|
||||
setState(886);
|
||||
_errHandler.sync(this);
|
||||
switch ( getInterpreter().adaptivePredict(_input,84,_ctx) ) {
|
||||
case 1:
|
||||
@ -6861,7 +6948,7 @@ public class KickCParser extends Parser {
|
||||
setState(845);
|
||||
match(ASM_COMMA);
|
||||
setState(846);
|
||||
match(ASM_NAME);
|
||||
asmExpr(0);
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
@ -6881,30 +6968,86 @@ public class KickCParser extends Parser {
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
_localctx = new AsmModeIdxIndXYContext(_localctx);
|
||||
_localctx = new AsmModeIndLongIdxXYContext(_localctx);
|
||||
enterOuterAlt(_localctx, 5);
|
||||
{
|
||||
setState(854);
|
||||
match(ASM_PAR_BEGIN);
|
||||
setState(855);
|
||||
asmExpr(0);
|
||||
match(ASM_PAR_BEGIN);
|
||||
setState(856);
|
||||
match(ASM_COMMA);
|
||||
asmExpr(0);
|
||||
setState(857);
|
||||
match(ASM_NAME);
|
||||
match(ASM_PAR_END);
|
||||
setState(858);
|
||||
match(ASM_PAR_END);
|
||||
setState(859);
|
||||
match(ASM_COMMA);
|
||||
setState(860);
|
||||
match(ASM_NAME);
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
_localctx = new AsmModeIndContext(_localctx);
|
||||
_localctx = new AsmModeSPIndIdxContext(_localctx);
|
||||
enterOuterAlt(_localctx, 6);
|
||||
{
|
||||
setState(860);
|
||||
match(ASM_PAR_BEGIN);
|
||||
setState(861);
|
||||
asmExpr(0);
|
||||
setState(862);
|
||||
match(ASM_PAR_BEGIN);
|
||||
setState(863);
|
||||
asmExpr(0);
|
||||
setState(864);
|
||||
match(ASM_COMMA);
|
||||
setState(865);
|
||||
match(ASM_NAME);
|
||||
setState(866);
|
||||
match(ASM_PAR_END);
|
||||
setState(867);
|
||||
match(ASM_COMMA);
|
||||
setState(868);
|
||||
match(ASM_NAME);
|
||||
}
|
||||
break;
|
||||
case 7:
|
||||
_localctx = new AsmModeIdxIndXYContext(_localctx);
|
||||
enterOuterAlt(_localctx, 7);
|
||||
{
|
||||
setState(870);
|
||||
match(ASM_PAR_BEGIN);
|
||||
setState(871);
|
||||
asmExpr(0);
|
||||
setState(872);
|
||||
match(ASM_COMMA);
|
||||
setState(873);
|
||||
match(ASM_NAME);
|
||||
setState(874);
|
||||
match(ASM_PAR_END);
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
_localctx = new AsmModeIndContext(_localctx);
|
||||
enterOuterAlt(_localctx, 8);
|
||||
{
|
||||
setState(876);
|
||||
match(ASM_PAR_BEGIN);
|
||||
setState(877);
|
||||
asmExpr(0);
|
||||
setState(878);
|
||||
match(ASM_PAR_END);
|
||||
}
|
||||
break;
|
||||
case 9:
|
||||
_localctx = new AsmModeIndLongContext(_localctx);
|
||||
enterOuterAlt(_localctx, 9);
|
||||
{
|
||||
setState(880);
|
||||
match(ASM_PAR_BEGIN);
|
||||
setState(881);
|
||||
match(ASM_PAR_BEGIN);
|
||||
setState(882);
|
||||
asmExpr(0);
|
||||
setState(883);
|
||||
match(ASM_PAR_END);
|
||||
setState(884);
|
||||
match(ASM_PAR_END);
|
||||
}
|
||||
break;
|
||||
@ -7109,7 +7252,7 @@ public class KickCParser extends Parser {
|
||||
int _alt;
|
||||
enterOuterAlt(_localctx, 1);
|
||||
{
|
||||
setState(880);
|
||||
setState(902);
|
||||
_errHandler.sync(this);
|
||||
switch (_input.LA(1)) {
|
||||
case ASM_BRACKET_BEGIN:
|
||||
@ -7118,11 +7261,11 @@ public class KickCParser extends Parser {
|
||||
_ctx = _localctx;
|
||||
_prevctx = _localctx;
|
||||
|
||||
setState(867);
|
||||
setState(889);
|
||||
match(ASM_BRACKET_BEGIN);
|
||||
setState(868);
|
||||
setState(890);
|
||||
asmExpr(0);
|
||||
setState(869);
|
||||
setState(891);
|
||||
match(ASM_BRACKET_END);
|
||||
}
|
||||
break;
|
||||
@ -7134,7 +7277,7 @@ public class KickCParser extends Parser {
|
||||
_localctx = new AsmExprUnaryContext(_localctx);
|
||||
_ctx = _localctx;
|
||||
_prevctx = _localctx;
|
||||
setState(871);
|
||||
setState(893);
|
||||
_la = _input.LA(1);
|
||||
if ( !(((((_la - 137)) & ~0x3f) == 0 && ((1L << (_la - 137)) & ((1L << (ASM_PLUS - 137)) | (1L << (ASM_MINUS - 137)) | (1L << (ASM_LESS_THAN - 137)) | (1L << (ASM_GREATER_THAN - 137)))) != 0)) ) {
|
||||
_errHandler.recoverInline(this);
|
||||
@ -7144,7 +7287,7 @@ public class KickCParser extends Parser {
|
||||
_errHandler.reportMatch(this);
|
||||
consume();
|
||||
}
|
||||
setState(872);
|
||||
setState(894);
|
||||
asmExpr(8);
|
||||
}
|
||||
break;
|
||||
@ -7153,7 +7296,7 @@ public class KickCParser extends Parser {
|
||||
_localctx = new AsmExprLabelContext(_localctx);
|
||||
_ctx = _localctx;
|
||||
_prevctx = _localctx;
|
||||
setState(873);
|
||||
setState(895);
|
||||
match(ASM_NAME);
|
||||
}
|
||||
break;
|
||||
@ -7162,7 +7305,7 @@ public class KickCParser extends Parser {
|
||||
_localctx = new AsmExprLabelRelContext(_localctx);
|
||||
_ctx = _localctx;
|
||||
_prevctx = _localctx;
|
||||
setState(874);
|
||||
setState(896);
|
||||
match(ASM_MULTI_REL);
|
||||
}
|
||||
break;
|
||||
@ -7171,11 +7314,11 @@ public class KickCParser extends Parser {
|
||||
_localctx = new AsmExprReplaceContext(_localctx);
|
||||
_ctx = _localctx;
|
||||
_prevctx = _localctx;
|
||||
setState(875);
|
||||
setState(897);
|
||||
match(ASM_CURLY_BEGIN);
|
||||
setState(876);
|
||||
setState(898);
|
||||
match(ASM_NAME);
|
||||
setState(877);
|
||||
setState(899);
|
||||
match(ASM_CURLY_END);
|
||||
}
|
||||
break;
|
||||
@ -7184,7 +7327,7 @@ public class KickCParser extends Parser {
|
||||
_localctx = new AsmExprIntContext(_localctx);
|
||||
_ctx = _localctx;
|
||||
_prevctx = _localctx;
|
||||
setState(878);
|
||||
setState(900);
|
||||
match(ASM_NUMBER);
|
||||
}
|
||||
break;
|
||||
@ -7193,7 +7336,7 @@ public class KickCParser extends Parser {
|
||||
_localctx = new AsmExprCharContext(_localctx);
|
||||
_ctx = _localctx;
|
||||
_prevctx = _localctx;
|
||||
setState(879);
|
||||
setState(901);
|
||||
match(ASM_CHAR);
|
||||
}
|
||||
break;
|
||||
@ -7201,7 +7344,7 @@ public class KickCParser extends Parser {
|
||||
throw new NoViableAltException(this);
|
||||
}
|
||||
_ctx.stop = _input.LT(-1);
|
||||
setState(896);
|
||||
setState(918);
|
||||
_errHandler.sync(this);
|
||||
_alt = getInterpreter().adaptivePredict(_input,87,_ctx);
|
||||
while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) {
|
||||
@ -7209,20 +7352,20 @@ public class KickCParser extends Parser {
|
||||
if ( _parseListeners!=null ) triggerExitRuleEvent();
|
||||
_prevctx = _localctx;
|
||||
{
|
||||
setState(894);
|
||||
setState(916);
|
||||
_errHandler.sync(this);
|
||||
switch ( getInterpreter().adaptivePredict(_input,86,_ctx) ) {
|
||||
case 1:
|
||||
{
|
||||
_localctx = new AsmExprBinaryContext(new AsmExprContext(_parentctx, _parentState));
|
||||
pushNewRecursionContext(_localctx, _startState, RULE_asmExpr);
|
||||
setState(882);
|
||||
setState(904);
|
||||
if (!(precpred(_ctx, 10))) throw new FailedPredicateException(this, "precpred(_ctx, 10)");
|
||||
{
|
||||
setState(883);
|
||||
setState(905);
|
||||
match(ASM_DOT);
|
||||
}
|
||||
setState(884);
|
||||
setState(906);
|
||||
asmExpr(11);
|
||||
}
|
||||
break;
|
||||
@ -7230,9 +7373,9 @@ public class KickCParser extends Parser {
|
||||
{
|
||||
_localctx = new AsmExprBinaryContext(new AsmExprContext(_parentctx, _parentState));
|
||||
pushNewRecursionContext(_localctx, _startState, RULE_asmExpr);
|
||||
setState(885);
|
||||
setState(907);
|
||||
if (!(precpred(_ctx, 9))) throw new FailedPredicateException(this, "precpred(_ctx, 9)");
|
||||
setState(886);
|
||||
setState(908);
|
||||
_la = _input.LA(1);
|
||||
if ( !(_la==ASM_SHIFT_LEFT || _la==ASM_SHIFT_RIGHT) ) {
|
||||
_errHandler.recoverInline(this);
|
||||
@ -7242,7 +7385,7 @@ public class KickCParser extends Parser {
|
||||
_errHandler.reportMatch(this);
|
||||
consume();
|
||||
}
|
||||
setState(887);
|
||||
setState(909);
|
||||
asmExpr(10);
|
||||
}
|
||||
break;
|
||||
@ -7250,9 +7393,9 @@ public class KickCParser extends Parser {
|
||||
{
|
||||
_localctx = new AsmExprBinaryContext(new AsmExprContext(_parentctx, _parentState));
|
||||
pushNewRecursionContext(_localctx, _startState, RULE_asmExpr);
|
||||
setState(888);
|
||||
setState(910);
|
||||
if (!(precpred(_ctx, 7))) throw new FailedPredicateException(this, "precpred(_ctx, 7)");
|
||||
setState(889);
|
||||
setState(911);
|
||||
_la = _input.LA(1);
|
||||
if ( !(_la==ASM_MULTIPLY || _la==ASM_DIVIDE) ) {
|
||||
_errHandler.recoverInline(this);
|
||||
@ -7262,7 +7405,7 @@ public class KickCParser extends Parser {
|
||||
_errHandler.reportMatch(this);
|
||||
consume();
|
||||
}
|
||||
setState(890);
|
||||
setState(912);
|
||||
asmExpr(8);
|
||||
}
|
||||
break;
|
||||
@ -7270,9 +7413,9 @@ public class KickCParser extends Parser {
|
||||
{
|
||||
_localctx = new AsmExprBinaryContext(new AsmExprContext(_parentctx, _parentState));
|
||||
pushNewRecursionContext(_localctx, _startState, RULE_asmExpr);
|
||||
setState(891);
|
||||
setState(913);
|
||||
if (!(precpred(_ctx, 6))) throw new FailedPredicateException(this, "precpred(_ctx, 6)");
|
||||
setState(892);
|
||||
setState(914);
|
||||
_la = _input.LA(1);
|
||||
if ( !(_la==ASM_PLUS || _la==ASM_MINUS) ) {
|
||||
_errHandler.recoverInline(this);
|
||||
@ -7282,14 +7425,14 @@ public class KickCParser extends Parser {
|
||||
_errHandler.reportMatch(this);
|
||||
consume();
|
||||
}
|
||||
setState(893);
|
||||
setState(915);
|
||||
asmExpr(7);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
setState(898);
|
||||
setState(920);
|
||||
_errHandler.sync(this);
|
||||
_alt = getInterpreter().adaptivePredict(_input,87,_ctx);
|
||||
}
|
||||
@ -7418,7 +7561,7 @@ public class KickCParser extends Parser {
|
||||
}
|
||||
|
||||
public static final String _serializedATN =
|
||||
"\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3\u00a7\u0386\4\2\t"+
|
||||
"\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3\u00a7\u039c\4\2\t"+
|
||||
"\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13"+
|
||||
"\t\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22"+
|
||||
"\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\4\31\t\31"+
|
||||
@ -7480,24 +7623,25 @@ public class KickCParser extends Parser {
|
||||
"\n(\f(\16(\u031e\13(\3(\3(\3)\3)\3)\3)\3)\3)\3)\3)\3)\3)\5)\u032c\n)\3"+
|
||||
"*\7*\u032f\n*\f*\16*\u0332\13*\3+\3+\3+\5+\u0337\n+\3,\3,\3,\3,\5,\u033d"+
|
||||
"\n,\3-\3-\5-\u0341\n-\3.\3.\3.\3.\7.\u0347\n.\f.\16.\u034a\13.\3/\3/\3"+
|
||||
"/\3/\3/\3/\3/\3/\3/\3/\3/\3/\3/\3/\3/\3/\3/\3/\3/\3/\3/\3/\3/\5/\u0363"+
|
||||
"\n/\3\60\3\60\3\60\3\60\3\60\3\60\3\60\3\60\3\60\3\60\3\60\3\60\3\60\3"+
|
||||
"\60\5\60\u0373\n\60\3\60\3\60\3\60\3\60\3\60\3\60\3\60\3\60\3\60\3\60"+
|
||||
"\3\60\3\60\7\60\u0381\n\60\f\60\16\60\u0384\13\60\3\60\2\t\f\30\32&FH"+
|
||||
"^\61\2\4\6\b\n\f\16\20\22\24\26\30\32\34\36 \"$&(*,.\60\62\64\668:<>@"+
|
||||
"BDFHJLNPRTVXZ\\^\2\r\3\2\27\30\5\2\22\23\31\32^^\4\2!!$$\3\2\35\36\3\2"+
|
||||
"\24\26\3\2\22\23\3\2\37$\3\2\u008b\u008e\3\2\u0089\u008a\3\2\u008f\u0090"+
|
||||
"\3\2\u008b\u008c\2\u0409\2`\3\2\2\2\4c\3\2\2\2\6i\3\2\2\2\bz\3\2\2\2\n"+
|
||||
"|\3\2\2\2\f\177\3\2\2\2\16\u0096\3\2\2\2\20\u00bb\3\2\2\2\22\u00c0\3\2"+
|
||||
"\2\2\24\u00ca\3\2\2\2\26\u00d1\3\2\2\2\30\u00d7\3\2\2\2\32\u00f6\3\2\2"+
|
||||
"\2\34\u0106\3\2\2\2\36\u0109\3\2\2\2 \u0115\3\2\2\2\"\u0118\3\2\2\2$\u011b"+
|
||||
"/\3/\3/\3/\3/\3/\3/\3/\3/\3/\3/\3/\3/\3/\3/\3/\3/\3/\3/\3/\3/\3/\3/\3"+
|
||||
"/\3/\3/\3/\3/\3/\3/\3/\3/\3/\3/\3/\3/\3/\3/\3/\3/\3/\3/\3/\5/\u0379\n"+
|
||||
"/\3\60\3\60\3\60\3\60\3\60\3\60\3\60\3\60\3\60\3\60\3\60\3\60\3\60\3\60"+
|
||||
"\5\60\u0389\n\60\3\60\3\60\3\60\3\60\3\60\3\60\3\60\3\60\3\60\3\60\3\60"+
|
||||
"\3\60\7\60\u0397\n\60\f\60\16\60\u039a\13\60\3\60\2\t\f\30\32&FH^\61\2"+
|
||||
"\4\6\b\n\f\16\20\22\24\26\30\32\34\36 \"$&(*,.\60\62\64\668:<>@BDFHJL"+
|
||||
"NPRTVXZ\\^\2\r\3\2\27\30\5\2\22\23\31\32^^\4\2!!$$\3\2\35\36\3\2\24\26"+
|
||||
"\3\2\22\23\3\2\37$\3\2\u008b\u008e\3\2\u0089\u008a\3\2\u008f\u0090\3\2"+
|
||||
"\u008b\u008c\2\u0422\2`\3\2\2\2\4c\3\2\2\2\6i\3\2\2\2\bz\3\2\2\2\n|\3"+
|
||||
"\2\2\2\f\177\3\2\2\2\16\u0096\3\2\2\2\20\u00bb\3\2\2\2\22\u00c0\3\2\2"+
|
||||
"\2\24\u00ca\3\2\2\2\26\u00d1\3\2\2\2\30\u00d7\3\2\2\2\32\u00f6\3\2\2\2"+
|
||||
"\34\u0106\3\2\2\2\36\u0109\3\2\2\2 \u0115\3\2\2\2\"\u0118\3\2\2\2$\u011b"+
|
||||
"\3\2\2\2&\u0123\3\2\2\2(\u012e\3\2\2\2*\u0133\3\2\2\2,\u0144\3\2\2\2."+
|
||||
"\u014a\3\2\2\2\60\u015d\3\2\2\2\62\u01b6\3\2\2\2\64\u01b8\3\2\2\2\66\u01e9"+
|
||||
"\3\2\2\28\u01ec\3\2\2\2:\u0245\3\2\2\2<\u0248\3\2\2\2>\u0253\3\2\2\2@"+
|
||||
"\u0271\3\2\2\2B\u0277\3\2\2\2D\u0279\3\2\2\2F\u027b\3\2\2\2H\u02c7\3\2"+
|
||||
"\2\2J\u0308\3\2\2\2L\u0310\3\2\2\2N\u0316\3\2\2\2P\u032b\3\2\2\2R\u0330"+
|
||||
"\3\2\2\2T\u0336\3\2\2\2V\u033c\3\2\2\2X\u033e\3\2\2\2Z\u0342\3\2\2\2\\"+
|
||||
"\u0362\3\2\2\2^\u0372\3\2\2\2`a\5\6\4\2ab\7\2\2\3b\3\3\2\2\2cd\5R*\2d"+
|
||||
"\u0378\3\2\2\2^\u0388\3\2\2\2`a\5\6\4\2ab\7\2\2\3b\3\3\2\2\2cd\5R*\2d"+
|
||||
"e\7\2\2\3e\5\3\2\2\2fh\5\b\5\2gf\3\2\2\2hk\3\2\2\2ig\3\2\2\2ij\3\2\2\2"+
|
||||
"j\7\3\2\2\2ki\3\2\2\2lm\5\n\6\2mn\7\n\2\2n{\3\2\2\2op\5\36\20\2pq\7\n"+
|
||||
"\2\2q{\3\2\2\2rs\5$\23\2st\7\n\2\2t{\3\2\2\2u{\5*\26\2v{\5\62\32\2wx\5"+
|
||||
@ -7745,36 +7889,44 @@ public class KickCParser extends Parser {
|
||||
"\u033f\3\2\2\2\u0340\u0341\3\2\2\2\u0341Y\3\2\2\2\u0342\u0343\7\177\2"+
|
||||
"\2\u0343\u0348\5^\60\2\u0344\u0345\7\u0083\2\2\u0345\u0347\5^\60\2\u0346"+
|
||||
"\u0344\3\2\2\2\u0347\u034a\3\2\2\2\u0348\u0346\3\2\2\2\u0348\u0349\3\2"+
|
||||
"\2\2\u0349[\3\2\2\2\u034a\u0348\3\2\2\2\u034b\u0363\5^\60\2\u034c\u034d"+
|
||||
"\7\u0081\2\2\u034d\u0363\5^\60\2\u034e\u034f\5^\60\2\u034f\u0350\7\u0083"+
|
||||
"\2\2\u0350\u0351\7\u009f\2\2\u0351\u0363\3\2\2\2\u0352\u0353\7\u0084\2"+
|
||||
"\2\u0353\u0354\5^\60\2\u0354\u0355\7\u0085\2\2\u0355\u0356\7\u0083\2\2"+
|
||||
"\u0356\u0357\7\u009f\2\2\u0357\u0363\3\2\2\2\u0358\u0359\7\u0084\2\2\u0359"+
|
||||
"\u035a\5^\60\2\u035a\u035b\7\u0083\2\2\u035b\u035c\7\u009f\2\2\u035c\u035d"+
|
||||
"\7\u0085\2\2\u035d\u0363\3\2\2\2\u035e\u035f\7\u0084\2\2\u035f\u0360\5"+
|
||||
"^\60\2\u0360\u0361\7\u0085\2\2\u0361\u0363\3\2\2\2\u0362\u034b\3\2\2\2"+
|
||||
"\u0362\u034c\3\2\2\2\u0362\u034e\3\2\2\2\u0362\u0352\3\2\2\2\u0362\u0358"+
|
||||
"\3\2\2\2\u0362\u035e\3\2\2\2\u0363]\3\2\2\2\u0364\u0365\b\60\1\2\u0365"+
|
||||
"\u0366\7\u0086\2\2\u0366\u0367\5^\60\2\u0367\u0368\7\u0087\2\2\u0368\u0373"+
|
||||
"\3\2\2\2\u0369\u036a\t\t\2\2\u036a\u0373\5^\60\n\u036b\u0373\7\u009f\2"+
|
||||
"\2\u036c\u0373\7\u009d\2\2\u036d\u036e\7\u0091\2\2\u036e\u036f\7\u009f"+
|
||||
"\2\2\u036f\u0373\7\u0092\2\2\u0370\u0373\7\u0093\2\2\u0371\u0373\7\u009c"+
|
||||
"\2\2\u0372\u0364\3\2\2\2\u0372\u0369\3\2\2\2\u0372\u036b\3\2\2\2\u0372"+
|
||||
"\u036c\3\2\2\2\u0372\u036d\3\2\2\2\u0372\u0370\3\2\2\2\u0372\u0371\3\2"+
|
||||
"\2\2\u0373\u0382\3\2\2\2\u0374\u0375\f\f\2\2\u0375\u0376\7\u0088\2\2\u0376"+
|
||||
"\u0381\5^\60\r\u0377\u0378\f\13\2\2\u0378\u0379\t\n\2\2\u0379\u0381\5"+
|
||||
"^\60\f\u037a\u037b\f\t\2\2\u037b\u037c\t\13\2\2\u037c\u0381\5^\60\n\u037d"+
|
||||
"\u037e\f\b\2\2\u037e\u037f\t\f\2\2\u037f\u0381\5^\60\t\u0380\u0374\3\2"+
|
||||
"\2\2\u0380\u0377\3\2\2\2\u0380\u037a\3\2\2\2\u0380\u037d\3\2\2\2\u0381"+
|
||||
"\u0384\3\2\2\2\u0382\u0380\3\2\2\2\u0382\u0383\3\2\2\2\u0383_\3\2\2\2"+
|
||||
"\u0384\u0382\3\2\2\2Ziz\u0083\u008d\u0093\u009b\u00a2\u00ab\u00b0\u00b6"+
|
||||
"\u00bb\u00c0\u00c7\u00ce\u00d3\u00df\u00e2\u00e4\u00ef\u00f6\u00fb\u0101"+
|
||||
"\u0103\u010b\u0111\u011d\u012b\u0131\u0137\u013d\u0142\u0146\u014f\u0156"+
|
||||
"\u015d\u0186\u01b2\u01b6\u01bb\u01c6\u01da\u01e3\u01e9\u01ee\u01f5\u0202"+
|
||||
"\u0207\u0213\u0221\u0234\u023d\u0245\u024a\u024f\u0251\u0257\u025c\u0260"+
|
||||
"\u0266\u0269\u0271\u0274\u0277\u0283\u028f\u0297\u029d\u02a1\u02b6\u02ba"+
|
||||
"\u02c3\u02c7\u02f9\u0303\u0305\u030d\u0312\u031c\u032b\u0330\u0336\u033c"+
|
||||
"\u0340\u0348\u0362\u0372\u0380\u0382";
|
||||
"\2\2\u0349[\3\2\2\2\u034a\u0348\3\2\2\2\u034b\u0379\5^\60\2\u034c\u034d"+
|
||||
"\7\u0081\2\2\u034d\u0379\5^\60\2\u034e\u034f\5^\60\2\u034f\u0350\7\u0083"+
|
||||
"\2\2\u0350\u0351\5^\60\2\u0351\u0379\3\2\2\2\u0352\u0353\7\u0084\2\2\u0353"+
|
||||
"\u0354\5^\60\2\u0354\u0355\7\u0085\2\2\u0355\u0356\7\u0083\2\2\u0356\u0357"+
|
||||
"\7\u009f\2\2\u0357\u0379\3\2\2\2\u0358\u0359\7\u0084\2\2\u0359\u035a\7"+
|
||||
"\u0084\2\2\u035a\u035b\5^\60\2\u035b\u035c\7\u0085\2\2\u035c\u035d\7\u0085"+
|
||||
"\2\2\u035d\u035e\7\u0083\2\2\u035e\u035f\7\u009f\2\2\u035f\u0379\3\2\2"+
|
||||
"\2\u0360\u0361\7\u0084\2\2\u0361\u0362\5^\60\2\u0362\u0363\7\u0083\2\2"+
|
||||
"\u0363\u0364\7\u009f\2\2\u0364\u0365\7\u0085\2\2\u0365\u0366\7\u0083\2"+
|
||||
"\2\u0366\u0367\7\u009f\2\2\u0367\u0379\3\2\2\2\u0368\u0369\7\u0084\2\2"+
|
||||
"\u0369\u036a\5^\60\2\u036a\u036b\7\u0083\2\2\u036b\u036c\7\u009f\2\2\u036c"+
|
||||
"\u036d\7\u0085\2\2\u036d\u0379\3\2\2\2\u036e\u036f\7\u0084\2\2\u036f\u0370"+
|
||||
"\5^\60\2\u0370\u0371\7\u0085\2\2\u0371\u0379\3\2\2\2\u0372\u0373\7\u0084"+
|
||||
"\2\2\u0373\u0374\7\u0084\2\2\u0374\u0375\5^\60\2\u0375\u0376\7\u0085\2"+
|
||||
"\2\u0376\u0377\7\u0085\2\2\u0377\u0379\3\2\2\2\u0378\u034b\3\2\2\2\u0378"+
|
||||
"\u034c\3\2\2\2\u0378\u034e\3\2\2\2\u0378\u0352\3\2\2\2\u0378\u0358\3\2"+
|
||||
"\2\2\u0378\u0360\3\2\2\2\u0378\u0368\3\2\2\2\u0378\u036e\3\2\2\2\u0378"+
|
||||
"\u0372\3\2\2\2\u0379]\3\2\2\2\u037a\u037b\b\60\1\2\u037b\u037c\7\u0086"+
|
||||
"\2\2\u037c\u037d\5^\60\2\u037d\u037e\7\u0087\2\2\u037e\u0389\3\2\2\2\u037f"+
|
||||
"\u0380\t\t\2\2\u0380\u0389\5^\60\n\u0381\u0389\7\u009f\2\2\u0382\u0389"+
|
||||
"\7\u009d\2\2\u0383\u0384\7\u0091\2\2\u0384\u0385\7\u009f\2\2\u0385\u0389"+
|
||||
"\7\u0092\2\2\u0386\u0389\7\u0093\2\2\u0387\u0389\7\u009c\2\2\u0388\u037a"+
|
||||
"\3\2\2\2\u0388\u037f\3\2\2\2\u0388\u0381\3\2\2\2\u0388\u0382\3\2\2\2\u0388"+
|
||||
"\u0383\3\2\2\2\u0388\u0386\3\2\2\2\u0388\u0387\3\2\2\2\u0389\u0398\3\2"+
|
||||
"\2\2\u038a\u038b\f\f\2\2\u038b\u038c\7\u0088\2\2\u038c\u0397\5^\60\r\u038d"+
|
||||
"\u038e\f\13\2\2\u038e\u038f\t\n\2\2\u038f\u0397\5^\60\f\u0390\u0391\f"+
|
||||
"\t\2\2\u0391\u0392\t\13\2\2\u0392\u0397\5^\60\n\u0393\u0394\f\b\2\2\u0394"+
|
||||
"\u0395\t\f\2\2\u0395\u0397\5^\60\t\u0396\u038a\3\2\2\2\u0396\u038d\3\2"+
|
||||
"\2\2\u0396\u0390\3\2\2\2\u0396\u0393\3\2\2\2\u0397\u039a\3\2\2\2\u0398"+
|
||||
"\u0396\3\2\2\2\u0398\u0399\3\2\2\2\u0399_\3\2\2\2\u039a\u0398\3\2\2\2"+
|
||||
"Ziz\u0083\u008d\u0093\u009b\u00a2\u00ab\u00b0\u00b6\u00bb\u00c0\u00c7"+
|
||||
"\u00ce\u00d3\u00df\u00e2\u00e4\u00ef\u00f6\u00fb\u0101\u0103\u010b\u0111"+
|
||||
"\u011d\u012b\u0131\u0137\u013d\u0142\u0146\u014f\u0156\u015d\u0186\u01b2"+
|
||||
"\u01b6\u01bb\u01c6\u01da\u01e3\u01e9\u01ee\u01f5\u0202\u0207\u0213\u0221"+
|
||||
"\u0234\u023d\u0245\u024a\u024f\u0251\u0257\u025c\u0260\u0266\u0269\u0271"+
|
||||
"\u0274\u0277\u0283\u028f\u0297\u029d\u02a1\u02b6\u02ba\u02c3\u02c7\u02f9"+
|
||||
"\u0303\u0305\u030d\u0312\u031c\u032b\u0330\u0336\u033c\u0340\u0348\u0378"+
|
||||
"\u0388\u0396\u0398";
|
||||
public static final ATN _ATN =
|
||||
new ATNDeserializer().deserialize(_serializedATN.toCharArray());
|
||||
static {
|
||||
|
@ -1609,6 +1609,30 @@ public class KickCParserBaseListener implements KickCParserListener {
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitAsmModeIndIdxXY(KickCParser.AsmModeIndIdxXYContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterAsmModeIndLongIdxXY(KickCParser.AsmModeIndLongIdxXYContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitAsmModeIndLongIdxXY(KickCParser.AsmModeIndLongIdxXYContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterAsmModeSPIndIdx(KickCParser.AsmModeSPIndIdxContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitAsmModeSPIndIdx(KickCParser.AsmModeSPIndIdxContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
@ -1633,6 +1657,18 @@ public class KickCParserBaseListener implements KickCParserListener {
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitAsmModeInd(KickCParser.AsmModeIndContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterAsmModeIndLong(KickCParser.AsmModeIndLongContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitAsmModeIndLong(KickCParser.AsmModeIndLongContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
|
@ -944,6 +944,20 @@ public class KickCParserBaseVisitor<T> extends AbstractParseTreeVisitor<T> imple
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitAsmModeIndIdxXY(KickCParser.AsmModeIndIdxXYContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitAsmModeIndLongIdxXY(KickCParser.AsmModeIndLongIdxXYContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitAsmModeSPIndIdx(KickCParser.AsmModeSPIndIdxContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
@ -958,6 +972,13 @@ public class KickCParserBaseVisitor<T> extends AbstractParseTreeVisitor<T> imple
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitAsmModeInd(KickCParser.AsmModeIndContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitAsmModeIndLong(KickCParser.AsmModeIndLongContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
|
@ -1541,6 +1541,30 @@ public interface KickCParserListener extends ParseTreeListener {
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitAsmModeIndIdxXY(KickCParser.AsmModeIndIdxXYContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by the {@code asmModeIndLongIdxXY}
|
||||
* labeled alternative in {@link KickCParser#asmParamMode}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterAsmModeIndLongIdxXY(KickCParser.AsmModeIndLongIdxXYContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by the {@code asmModeIndLongIdxXY}
|
||||
* labeled alternative in {@link KickCParser#asmParamMode}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitAsmModeIndLongIdxXY(KickCParser.AsmModeIndLongIdxXYContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by the {@code asmModeSPIndIdx}
|
||||
* labeled alternative in {@link KickCParser#asmParamMode}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterAsmModeSPIndIdx(KickCParser.AsmModeSPIndIdxContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by the {@code asmModeSPIndIdx}
|
||||
* labeled alternative in {@link KickCParser#asmParamMode}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitAsmModeSPIndIdx(KickCParser.AsmModeSPIndIdxContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by the {@code asmModeIdxIndXY}
|
||||
* labeled alternative in {@link KickCParser#asmParamMode}.
|
||||
@ -1565,6 +1589,18 @@ public interface KickCParserListener extends ParseTreeListener {
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitAsmModeInd(KickCParser.AsmModeIndContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by the {@code asmModeIndLong}
|
||||
* labeled alternative in {@link KickCParser#asmParamMode}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterAsmModeIndLong(KickCParser.AsmModeIndLongContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by the {@code asmModeIndLong}
|
||||
* labeled alternative in {@link KickCParser#asmParamMode}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitAsmModeIndLong(KickCParser.AsmModeIndLongContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by the {@code asmExprReplace}
|
||||
* labeled alternative in {@link KickCParser#asmExpr}.
|
||||
|
@ -911,6 +911,20 @@ public interface KickCParserVisitor<T> extends ParseTreeVisitor<T> {
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitAsmModeIndIdxXY(KickCParser.AsmModeIndIdxXYContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code asmModeIndLongIdxXY}
|
||||
* labeled alternative in {@link KickCParser#asmParamMode}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitAsmModeIndLongIdxXY(KickCParser.AsmModeIndLongIdxXYContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code asmModeSPIndIdx}
|
||||
* labeled alternative in {@link KickCParser#asmParamMode}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitAsmModeSPIndIdx(KickCParser.AsmModeSPIndIdxContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code asmModeIdxIndXY}
|
||||
* labeled alternative in {@link KickCParser#asmParamMode}.
|
||||
@ -925,6 +939,13 @@ public interface KickCParserVisitor<T> extends ParseTreeVisitor<T> {
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitAsmModeInd(KickCParser.AsmModeIndContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code asmModeIndLong}
|
||||
* labeled alternative in {@link KickCParser#asmParamMode}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitAsmModeIndLong(KickCParser.AsmModeIndLongContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code asmExprReplace}
|
||||
* labeled alternative in {@link KickCParser#asmExpr}.
|
||||
|
@ -1743,6 +1743,9 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
||||
@Override
|
||||
public Void visitAsmExprLabel(KickCParser.AsmExprLabelContext ctxLabel) {
|
||||
String label = ctxLabel.ASM_NAME().toString();
|
||||
if(label.equalsIgnoreCase("x") || label.equalsIgnoreCase("y") || label.equalsIgnoreCase("z")|| label.equalsIgnoreCase("sp"))
|
||||
// Skip registers
|
||||
return super.visitAsmExprLabel(ctxLabel);
|
||||
if(!definedLabels.contains(label)) {
|
||||
// Look for the symbol
|
||||
Symbol symbol = getCurrentScope().findSymbol(ctxLabel.ASM_NAME().getText());
|
||||
|
@ -28,7 +28,7 @@ public class Pass5AddMainRts extends Pass5AsmOptimization {
|
||||
if(line instanceof AsmInstruction) {
|
||||
AsmInstruction instruction = (AsmInstruction) line;
|
||||
if(instruction.getAsmOpcode().getMnemonic().equals("jsr")) {
|
||||
if(instruction.getParameter().equals(SymbolRef.MAIN_PROC_NAME)) {
|
||||
if(instruction.getOperand1().equals(SymbolRef.MAIN_PROC_NAME)) {
|
||||
// Add RTS if it is missing
|
||||
if(!lineIterator.hasNext()) {
|
||||
addRts(lineIterator);
|
||||
|
@ -45,7 +45,7 @@ public class Pass5DoubleJumpElimination extends Pass5AsmOptimization {
|
||||
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());
|
||||
immediateJumps.put(currentScope + "::" + currentLabel, asmInstruction.getOperand1());
|
||||
}
|
||||
if(asmInstruction.getAsmOpcode().equals(rtsOpcode)) {
|
||||
immediateJumps.put(currentScope + "::" + currentLabel, "rts");
|
||||
@ -68,16 +68,17 @@ public class Pass5DoubleJumpElimination extends Pass5AsmOptimization {
|
||||
} else if(line instanceof AsmInstruction) {
|
||||
AsmInstruction asmInstruction = (AsmInstruction) line;
|
||||
if(asmInstruction.getAsmOpcode().isJump()) {
|
||||
String immediateJmpTarget = immediateJumps.get(currentScope + "::" + asmInstruction.getParameter());
|
||||
if(immediateJmpTarget == "rts" && asmInstruction.getAsmOpcode().getMnemonic() == "jmp") {
|
||||
String jumpTarget = immediateJumps.get(currentScope + "::" + asmInstruction.getOperandJumpTarget());
|
||||
if(jumpTarget == "rts" && asmInstruction.getAsmOpcode().getMnemonic() == "jmp") {
|
||||
getLog().append("Replacing jump to rts with rts in " + asmInstruction.toString());
|
||||
AsmOpcode rtsOpcode = AsmInstructionSet.getOpcode("rts", AsmAddressingMode.NON, false);
|
||||
asmInstruction.setAsmOpcode(rtsOpcode);
|
||||
asmInstruction.setParameter(null);
|
||||
asmInstruction.setOperand1(null);
|
||||
asmInstruction.setOperand2(null);
|
||||
optimized = true;
|
||||
} else if(immediateJmpTarget != null && immediateJmpTarget != "rts" && !immediateJmpTarget.equals(asmInstruction.getParameter())) {
|
||||
getLog().append("Skipping double jump to " + immediateJmpTarget + " in " + asmInstruction.toString());
|
||||
asmInstruction.setParameter(immediateJmpTarget);
|
||||
} else if(jumpTarget != null && jumpTarget != "rts" && !jumpTarget.equals(asmInstruction.getOperandJumpTarget())) {
|
||||
getLog().append("Skipping double jump to " + jumpTarget + " in " + asmInstruction.toString());
|
||||
asmInstruction.setOperandJumpTarget(jumpTarget);
|
||||
optimized = true;
|
||||
}
|
||||
}
|
||||
|
@ -157,7 +157,7 @@ public class Pass5FixLongBranches extends Pass5AsmOptimization {
|
||||
if(asmChunk != null) {
|
||||
//getLog().append("Found ASM chunk "+asmChunk);
|
||||
AsmLine asmLine = asmChunk.getAsmLine(idx);
|
||||
if(asmLine != null && asmLine instanceof AsmInstruction) {
|
||||
if(asmLine instanceof AsmInstruction) {
|
||||
//getLog().append("Found ASM line "+asmLine);
|
||||
AsmInstruction asmInstruction = (AsmInstruction) asmLine;
|
||||
AsmOpcode asmOpcode = asmInstruction.getAsmOpcode();
|
||||
@ -165,10 +165,10 @@ public class Pass5FixLongBranches extends Pass5AsmOptimization {
|
||||
if(inverseAsmOpcode != null) {
|
||||
//getLog().append("Inversed branch instruction "+asmInstructionType.getMnemnonic()+" -> "+inverseType.getMnemnonic());
|
||||
getLog().append("Fixing long branch [" + idx + "] " + asmLine.toString() + " to " + inverseAsmOpcode.getMnemonic());
|
||||
String branchDest = asmInstruction.getParameter();
|
||||
String branchDest = asmInstruction.getOperandJumpTarget();
|
||||
asmInstruction.setAsmOpcode(inverseAsmOpcode);
|
||||
String newLabel = AsmFormat.asmFix("!" + branchDest);
|
||||
asmInstruction.setParameter(newLabel+"+");
|
||||
asmInstruction.setOperandJumpTarget(newLabel+"+");
|
||||
AsmOpcode jmpOpcode = AsmInstructionSet.getOpcode("jmp", AsmAddressingMode.ABS, false);
|
||||
AsmInstruction jmpInstruction = new AsmInstruction(jmpOpcode, branchDest);
|
||||
asmChunk.addLineAfter(asmInstruction, jmpInstruction);
|
||||
|
@ -25,7 +25,7 @@ public class Pass5NextJumpElimination extends Pass5AsmOptimization {
|
||||
}
|
||||
if(candidate != null) {
|
||||
if(line instanceof AsmLabel) {
|
||||
if(((AsmLabel) line).getLabel().equals(candidate.getParameter())) {
|
||||
if(((AsmLabel) line).getLabel().equals(candidate.getOperandJumpTarget())) {
|
||||
removeLines.add(candidate);
|
||||
}
|
||||
}
|
||||
|
@ -38,12 +38,12 @@ public class Pass5RedundantLabelElimination extends Pass5AsmOptimization {
|
||||
}
|
||||
} else if(line instanceof AsmInstruction) {
|
||||
AsmInstruction instruction = (AsmInstruction) line;
|
||||
if(instruction.getAsmOpcode().isJump() && instruction.getParameter()!=null) {
|
||||
String labelStr = instruction.getParameter();
|
||||
if(instruction.getAsmOpcode().isJump() && instruction.getOperandJumpTarget()!=null) {
|
||||
String labelStr = instruction.getOperandJumpTarget();
|
||||
String labelReplacementStr = getLabelReplacement(redundantLabelSet, currentScope, labelStr);
|
||||
if(labelReplacementStr!=null) {
|
||||
getLog().append("Replacing label " + labelStr + " with " + labelReplacementStr);
|
||||
instruction.setParameter(labelReplacementStr);
|
||||
instruction.setOperandJumpTarget(labelReplacementStr);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -96,12 +96,12 @@ public class Pass5RelabelLongLabels extends Pass5AsmOptimization {
|
||||
} else if(asmLine instanceof AsmInstruction) {
|
||||
AsmInstruction asmInstruction = (AsmInstruction) asmLine;
|
||||
if(asmInstruction.getAsmOpcode().isJump()) {
|
||||
String parameter = asmInstruction.getParameter();
|
||||
String parameter = asmInstruction.getOperandJumpTarget();
|
||||
Map<String, String> scopeRelabels = relabels.get(currentScope);
|
||||
if(scopeRelabels != null) {
|
||||
String newLabel = scopeRelabels.get(parameter);
|
||||
if(newLabel != null) {
|
||||
asmInstruction.setParameter(newLabel);
|
||||
asmInstruction.setOperandJumpTarget(newLabel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ public class Pass5SkipBegin extends Pass5AsmOptimization {
|
||||
} else if(line instanceof AsmInstruction) {
|
||||
AsmInstruction instruction = (AsmInstruction) line;
|
||||
if(instruction.getAsmOpcode().getMnemonic().equals("jsr")) {
|
||||
if(instruction.getParameter().equals(SymbolRef.MAIN_PROC_NAME)) {
|
||||
if(instruction.getOperandJumpTarget().equals(SymbolRef.MAIN_PROC_NAME)) {
|
||||
lineIterator.remove();
|
||||
optimized = true;
|
||||
getLog().append("Removing instruction " + line.getAsm());
|
||||
|
@ -36,77 +36,77 @@ public class Pass5UnnecesaryLoadElimination extends Pass5AsmOptimization {
|
||||
AsmOpcode asmOpcode = instruction.getAsmOpcode();
|
||||
|
||||
if(asmOpcode.getMnemonic().equals("lda") && asmOpcode.getAddressingMode().equals(AsmAddressingMode.IMM)) {
|
||||
String immValue = instruction.getParameter();
|
||||
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.setParameter(null);
|
||||
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.setParameter(null);
|
||||
instruction.setOperand1(null);
|
||||
}
|
||||
}
|
||||
if(asmOpcode.getMnemonic().equals("lda") && (asmOpcode.getAddressingMode().equals(AsmAddressingMode.ZP) || asmOpcode.getAddressingMode().equals(AsmAddressingMode.ABS))) {
|
||||
String memValue = instruction.getParameter();
|
||||
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.setParameter(null);
|
||||
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.setParameter(null);
|
||||
instruction.setOperand1(null);
|
||||
}
|
||||
}
|
||||
if(asmOpcode.getMnemonic().equals("ldx") && asmOpcode.getAddressingMode().equals(AsmAddressingMode.IMM)) {
|
||||
String immValue = instruction.getParameter();
|
||||
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.setParameter(null);
|
||||
instruction.setOperand1(null);
|
||||
}
|
||||
}
|
||||
if(asmOpcode.getMnemonic().equals("ldx") && (asmOpcode.getAddressingMode().equals(AsmAddressingMode.ZP) || asmOpcode.getAddressingMode().equals(AsmAddressingMode.ABS))) {
|
||||
String memValue = instruction.getParameter();
|
||||
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.setParameter(null);
|
||||
instruction.setOperand1(null);
|
||||
}
|
||||
}
|
||||
if(asmOpcode.getMnemonic().equals("ldy") && asmOpcode.getAddressingMode().equals(AsmAddressingMode.IMM)) {
|
||||
String immValue = instruction.getParameter();
|
||||
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.setParameter(null);
|
||||
instruction.setOperand1(null);
|
||||
}
|
||||
}
|
||||
if(asmOpcode.getMnemonic().equals("ldy") && (asmOpcode.getAddressingMode().equals(AsmAddressingMode.ZP) || asmOpcode.getAddressingMode().equals(AsmAddressingMode.ABS))) {
|
||||
String memValue = instruction.getParameter();
|
||||
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.setParameter(null);
|
||||
instruction.setOperand1(null);
|
||||
}
|
||||
}
|
||||
if(asmOpcode.getMnemonic().equals("clc")) {
|
||||
|
@ -41,8 +41,8 @@ public class Pass5UnusedLabelElimination extends Pass5AsmOptimization {
|
||||
usedLabels.add(labelStr);
|
||||
} else if(line instanceof AsmInstruction) {
|
||||
AsmInstruction instruction = (AsmInstruction) line;
|
||||
if(instruction.getAsmOpcode().isJump() && instruction.getParameter()!=null) {
|
||||
String labelStr = currentScope + "::" + instruction.getParameter();
|
||||
if(instruction.getAsmOpcode().isJump() && instruction.getOperandJumpTarget()!=null) {
|
||||
String labelStr = currentScope + "::" + instruction.getOperandJumpTarget();
|
||||
usedLabels.add(labelStr);
|
||||
}
|
||||
}
|
||||
|
@ -42,6 +42,11 @@ public class TestPrograms {
|
||||
public TestPrograms() {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAsmAddressingModes() throws IOException, URISyntaxException {
|
||||
compileAndCompare("asm-addressing-modes.c");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCastingNegative() throws IOException, URISyntaxException {
|
||||
compileAndCompare("casting-negative.c");
|
||||
|
33
src/test/kc/asm-addressing-modes.c
Normal file
33
src/test/kc/asm-addressing-modes.c
Normal file
@ -0,0 +1,33 @@
|
||||
// Tests the different ASM addressing modes
|
||||
|
||||
void main() {
|
||||
|
||||
asm {
|
||||
// absolute indexed
|
||||
lda $12,x
|
||||
// Indirect
|
||||
jmp ($1234)
|
||||
|
||||
// TODO: Indirect ABS,x
|
||||
// jmp ($1234,x)
|
||||
|
||||
// TODO Indirect Zeropage
|
||||
//jmp ($12)
|
||||
|
||||
// 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))
|
||||
}
|
||||
|
||||
}
|
10
src/test/ref/asm-addressing-modes.asm
Normal file
10
src/test/ref/asm-addressing-modes.asm
Normal file
@ -0,0 +1,10 @@
|
||||
// Tests the different ASM addressing modes
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
main: {
|
||||
// asm
|
||||
lda.z $12,x
|
||||
jmp ($1234)
|
||||
// }
|
||||
}
|
8
src/test/ref/asm-addressing-modes.cfg
Normal file
8
src/test/ref/asm-addressing-modes.cfg
Normal file
@ -0,0 +1,8 @@
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from
|
||||
asm { lda$12,x jmp($1234) }
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
[1] return
|
||||
to:@return
|
144
src/test/ref/asm-addressing-modes.log
Normal file
144
src/test/ref/asm-addressing-modes.log
Normal file
@ -0,0 +1,144 @@
|
||||
|
||||
CONTROL FLOW GRAPH SSA
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from __start
|
||||
asm { lda$12,x jmp($1234) }
|
||||
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 { lda$12,x jmp($1234) }
|
||||
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 / MOS6502X
|
||||
// File Comments
|
||||
// Tests the different ASM addressing modes
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
// main
|
||||
main: {
|
||||
// asm { lda$12,x jmp($1234) }
|
||||
lda.z $12,x
|
||||
jmp ($1234)
|
||||
jmp __breturn
|
||||
// main::@return
|
||||
__breturn:
|
||||
// [1] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Statement asm { lda$12,x jmp($1234) } always clobbers reg byte a
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
Uplift Scope [main]
|
||||
Uplift Scope []
|
||||
|
||||
Uplifting [main] best 18 combination
|
||||
Uplifting [] best 18 combination
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
// Tests the different ASM addressing modes
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
// main
|
||||
main: {
|
||||
// asm { lda$12,x jmp($1234) }
|
||||
lda.z $12,x
|
||||
jmp ($1234)
|
||||
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: 9
|
||||
|
||||
// File Comments
|
||||
// Tests the different ASM addressing modes
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
// main
|
||||
main: {
|
||||
// asm
|
||||
// asm { lda$12,x jmp($1234) }
|
||||
lda.z $12,x
|
||||
jmp ($1234)
|
||||
// main::@return
|
||||
// }
|
||||
// [1] return
|
||||
}
|
||||
// File Data
|
||||
|
3
src/test/ref/asm-addressing-modes.sym
Normal file
3
src/test/ref/asm-addressing-modes.sym
Normal file
@ -0,0 +1,3 @@
|
||||
(void()) main()
|
||||
(label) main::@return
|
||||
|
Loading…
x
Reference in New Issue
Block a user