mirror of
https://gitlab.com/camelot/kickc.git
synced 2025-08-05 07:28:18 +00:00
Added fallback to ZP-addressing if inline ASM instruction does not support absolute addressing. Closes #673
This commit is contained in:
@@ -4,10 +4,8 @@ import dk.camelot64.cpufamily6502.CpuAddressingMode;
|
||||
import dk.camelot64.cpufamily6502.CpuOpcode;
|
||||
import dk.camelot64.kickc.NumberParser;
|
||||
import dk.camelot64.kickc.asm.*;
|
||||
import dk.camelot64.kickc.model.ConstantNotLiteral;
|
||||
import dk.camelot64.kickc.model.*;
|
||||
import dk.camelot64.kickc.model.InternalError;
|
||||
import dk.camelot64.kickc.model.Program;
|
||||
import dk.camelot64.kickc.model.Registers;
|
||||
import dk.camelot64.kickc.model.symbols.Label;
|
||||
import dk.camelot64.kickc.model.symbols.Variable;
|
||||
import dk.camelot64.kickc.model.types.SymbolType;
|
||||
@@ -345,10 +343,14 @@ public class AsmFragmentInstance {
|
||||
// Convert to ZP-addressing mode if possible
|
||||
boolean isZp = param1 != null && param1.isZp();
|
||||
CpuOpcode cpuOpcode = this.getAsmProgram().getTargetCpu().getCpu65xx().getOpcode(mnemonic, addressingMode, isZp);
|
||||
if(!isZp && cpuOpcode==null) {
|
||||
// Fallback to ZP-addressing
|
||||
cpuOpcode = this.getAsmProgram().getTargetCpu().getCpu65xx().getOpcode(mnemonic, addressingMode, true);
|
||||
}
|
||||
String operand1 = param1 == null ? null : param1.getParam();
|
||||
String operand2 = param2 == null ? null : param2.getParam();
|
||||
if(cpuOpcode == null) {
|
||||
throw new InternalError("Error in " + name + ".asm line " + instructionCtx.getStart().getLine() + " - Instruction type not supported " + addressingMode.getAsm(mnemonic, operand1, operand2) + " by CPU " + this.fragmentInstance.fragmentTemplate.getTargetCpu().getName());
|
||||
throw new CompileError("Error in " + name + ".asm line " + instructionCtx.getStart().getLine() + " - Instruction type not supported " + addressingMode.getAsm(mnemonic, operand1, operand2) + " by CPU " + this.fragmentInstance.fragmentTemplate.getTargetCpu().getName());
|
||||
}
|
||||
return new AsmInstruction(cpuOpcode, operand1, operand2);
|
||||
}
|
||||
|
@@ -9,6 +9,11 @@ import java.io.IOException;
|
||||
*/
|
||||
public class TestProgramsFast extends TestPrograms {
|
||||
|
||||
@Test
|
||||
public void testMissingInstruction() throws IOException {
|
||||
compileAndCompare("missing-instruction.c", log());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNpeProblem0() throws IOException {
|
||||
compileAndCompare("npe-problem-0.c");
|
||||
|
7
src/test/kc/missing-instruction.c
Normal file
7
src/test/kc/missing-instruction.c
Normal file
@@ -0,0 +1,7 @@
|
||||
void main()
|
||||
{
|
||||
volatile unsigned char test;
|
||||
asm {
|
||||
sty test,x
|
||||
}
|
||||
}
|
19
src/test/ref/missing-instruction.asm
Normal file
19
src/test/ref/missing-instruction.asm
Normal file
@@ -0,0 +1,19 @@
|
||||
// Commodore 64 PRG executable file
|
||||
.file [name="missing-instruction.prg", type="prg", segments="Program"]
|
||||
.segmentdef Program [segments="Basic, Code, Data"]
|
||||
.segmentdef Basic [start=$0801]
|
||||
.segmentdef Code [start=$80d]
|
||||
.segmentdef Data [startAfter="Code"]
|
||||
.segment Basic
|
||||
:BasicUpstart(main)
|
||||
.segment Code
|
||||
main: {
|
||||
.label test = 2
|
||||
// volatile unsigned char test
|
||||
lda #0
|
||||
sta.z test
|
||||
// asm
|
||||
sty.z test,x
|
||||
// }
|
||||
rts
|
||||
}
|
9
src/test/ref/missing-instruction.cfg
Normal file
9
src/test/ref/missing-instruction.cfg
Normal file
@@ -0,0 +1,9 @@
|
||||
|
||||
void main()
|
||||
main: scope:[main] from
|
||||
[0] main::test = 0
|
||||
asm { stytest,x }
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
[2] return
|
||||
to:@return
|
145
src/test/ref/missing-instruction.log
Normal file
145
src/test/ref/missing-instruction.log
Normal file
@@ -0,0 +1,145 @@
|
||||
|
||||
CONTROL FLOW GRAPH SSA
|
||||
|
||||
void main()
|
||||
main: scope:[main] from __start
|
||||
main::test = 0
|
||||
asm { stytest,x }
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
return
|
||||
to:@return
|
||||
|
||||
void __start()
|
||||
__start: scope:[__start] from
|
||||
call main
|
||||
to:__start::@1
|
||||
__start::@1: scope:[__start] from __start
|
||||
to:__start::@return
|
||||
__start::@return: scope:[__start] from __start::@1
|
||||
return
|
||||
to:@return
|
||||
|
||||
SYMBOL TABLE SSA
|
||||
void __start()
|
||||
void main()
|
||||
volatile byte main::test loadstore
|
||||
|
||||
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
|
||||
[0] main::test = 0
|
||||
asm { stytest,x }
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
[2] return
|
||||
to:@return
|
||||
|
||||
|
||||
VARIABLE REGISTER WEIGHTS
|
||||
void main()
|
||||
volatile byte main::test loadstore 2.0
|
||||
|
||||
Initial phi equivalence classes
|
||||
Added variable main::test to live range equivalence class [ main::test ]
|
||||
Complete equivalence classes
|
||||
[ main::test ]
|
||||
Allocated zp[1]:2 [ main::test ]
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Statement [0] main::test = 0 [ main::test ] ( [ main::test ] { } ) always clobbers reg byte a
|
||||
Potential registers zp[1]:2 [ main::test ] : zp[1]:2 ,
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
Uplift Scope [main] 2: zp[1]:2 [ main::test ]
|
||||
Uplift Scope []
|
||||
|
||||
Uplifting [main] best 18 combination zp[1]:2 [ main::test ]
|
||||
Uplifting [] best 18 combination
|
||||
Attempting to uplift remaining variables inzp[1]:2 [ main::test ]
|
||||
Uplifting [main] best 18 combination zp[1]:2 [ main::test ]
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
// Upstart
|
||||
// Commodore 64 PRG executable file
|
||||
.file [name="missing-instruction.prg", type="prg", segments="Program"]
|
||||
.segmentdef Program [segments="Basic, Code, Data"]
|
||||
.segmentdef Basic [start=$0801]
|
||||
.segmentdef Code [start=$80d]
|
||||
.segmentdef Data [startAfter="Code"]
|
||||
.segment Basic
|
||||
:BasicUpstart(main)
|
||||
// Global Constants & labels
|
||||
.segment Code
|
||||
// main
|
||||
main: {
|
||||
.label test = 2
|
||||
// [0] main::test = 0 -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta.z test
|
||||
// asm { stytest,x }
|
||||
sty.z test,x
|
||||
jmp __breturn
|
||||
// main::@return
|
||||
__breturn:
|
||||
// [2] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
|
||||
ASSEMBLER OPTIMIZATIONS
|
||||
Removing instruction jmp __breturn
|
||||
Succesful ASM optimization Pass5NextJumpElimination
|
||||
Removing instruction __breturn:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
|
||||
FINAL SYMBOL TABLE
|
||||
void main()
|
||||
volatile byte main::test loadstore zp[1]:2 2.0
|
||||
|
||||
zp[1]:2 [ main::test ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 15
|
||||
|
||||
// File Comments
|
||||
// Upstart
|
||||
// Commodore 64 PRG executable file
|
||||
.file [name="missing-instruction.prg", type="prg", segments="Program"]
|
||||
.segmentdef Program [segments="Basic, Code, Data"]
|
||||
.segmentdef Basic [start=$0801]
|
||||
.segmentdef Code [start=$80d]
|
||||
.segmentdef Data [startAfter="Code"]
|
||||
.segment Basic
|
||||
:BasicUpstart(main)
|
||||
// Global Constants & labels
|
||||
.segment Code
|
||||
// main
|
||||
main: {
|
||||
.label test = 2
|
||||
// volatile unsigned char test
|
||||
// [0] main::test = 0 -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta.z test
|
||||
// asm
|
||||
// asm { stytest,x }
|
||||
sty.z test,x
|
||||
// main::@return
|
||||
// }
|
||||
// [2] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
|
4
src/test/ref/missing-instruction.sym
Normal file
4
src/test/ref/missing-instruction.sym
Normal file
@@ -0,0 +1,4 @@
|
||||
void main()
|
||||
volatile byte main::test loadstore zp[1]:2 2.0
|
||||
|
||||
zp[1]:2 [ main::test ]
|
Reference in New Issue
Block a user