diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java index 0656ff35a..d852f2416 100644 --- a/src/main/java/dk/camelot64/kickc/Compiler.java +++ b/src/main/java/dk/camelot64/kickc/Compiler.java @@ -145,7 +145,6 @@ public class Compiler { log.append(program.getScope().getSymbolTableContents(Variable.class)); new Pass3RegistersFinalize(program, log).allocate(); - new Pass3AssertNoCpuClobber(program, log).check(); new Pass3RegisterUplifting(program, log).uplift(); @@ -156,7 +155,7 @@ public class Compiler { new Pass3ZeroPageCoalesce(program, log).allocate(); new Pass3AssertNoCpuClobber(program, log).check(); - //new Pass3CustomRegisters(program).allocate(); + //new Pass3CustomRegisters(program).setRegister(); //new Pass3AssertNoCpuClobber(program, log).check(); } diff --git a/src/main/java/dk/camelot64/kickc/asm/fragment/_star_cowo1=yby.asm b/src/main/java/dk/camelot64/kickc/asm/fragment/_star_cowo1=yby.asm new file mode 100644 index 000000000..d9d8ac70e --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/asm/fragment/_star_cowo1=yby.asm @@ -0,0 +1 @@ +sty {cowo1} \ No newline at end of file diff --git a/src/main/java/dk/camelot64/kickc/asm/fragment/aby=_inc_aby.asm b/src/main/java/dk/camelot64/kickc/asm/fragment/aby=_inc_aby.asm new file mode 100644 index 000000000..46f7e9c4b --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/asm/fragment/aby=_inc_aby.asm @@ -0,0 +1,2 @@ +clc +adc #1 \ No newline at end of file diff --git a/src/main/java/dk/camelot64/kickc/asm/fragment/aby=aby_minus_coby1.asm b/src/main/java/dk/camelot64/kickc/asm/fragment/aby=aby_minus_coby1.asm new file mode 100644 index 000000000..fe317bfa7 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/asm/fragment/aby=aby_minus_coby1.asm @@ -0,0 +1,2 @@ +sec +sbc #{coby1} \ No newline at end of file diff --git a/src/main/java/dk/camelot64/kickc/asm/fragment/coby1_lt_aby_then_la1.asm b/src/main/java/dk/camelot64/kickc/asm/fragment/coby1_lt_aby_then_la1.asm new file mode 100644 index 000000000..f3b60d1c6 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/asm/fragment/coby1_lt_aby_then_la1.asm @@ -0,0 +1,2 @@ +cmp #{coby1} +bcs {la1} \ No newline at end of file diff --git a/src/main/java/dk/camelot64/kickc/asm/fragment/coby1_lt_xby_then_la1.asm b/src/main/java/dk/camelot64/kickc/asm/fragment/coby1_lt_xby_then_la1.asm new file mode 100644 index 000000000..eee87de96 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/asm/fragment/coby1_lt_xby_then_la1.asm @@ -0,0 +1,2 @@ +cpx #{coby1} +bcs {la1} \ No newline at end of file diff --git a/src/main/java/dk/camelot64/kickc/asm/fragment/cowo1_staridx_aby=zpby1.asm b/src/main/java/dk/camelot64/kickc/asm/fragment/cowo1_staridx_aby=zpby1.asm new file mode 100644 index 000000000..1d4ceb929 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/asm/fragment/cowo1_staridx_aby=zpby1.asm @@ -0,0 +1,3 @@ +tax +lda {zpby1} +sta {cowo1},x \ No newline at end of file diff --git a/src/main/java/dk/camelot64/kickc/asm/fragment/cowo1_staridx_zpby1=xby.asm b/src/main/java/dk/camelot64/kickc/asm/fragment/cowo1_staridx_zpby1=xby.asm new file mode 100644 index 000000000..c1cdf8a55 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/asm/fragment/cowo1_staridx_zpby1=xby.asm @@ -0,0 +1,3 @@ +txa +ldx {zpby1} +sta {cowo1},x \ No newline at end of file diff --git a/src/main/java/dk/camelot64/kickc/asm/fragment/cowo1_staridx_zpby1=yby.asm b/src/main/java/dk/camelot64/kickc/asm/fragment/cowo1_staridx_zpby1=yby.asm new file mode 100644 index 000000000..c96484a92 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/asm/fragment/cowo1_staridx_zpby1=yby.asm @@ -0,0 +1,3 @@ +tya +ldy {zpby1} +sta {cowo1},y \ No newline at end of file diff --git a/src/main/java/dk/camelot64/kickc/asm/fragment/xby=cowo1_staridx_xby.asm b/src/main/java/dk/camelot64/kickc/asm/fragment/xby=cowo1_staridx_xby.asm new file mode 100644 index 000000000..b6edc1f5c --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/asm/fragment/xby=cowo1_staridx_xby.asm @@ -0,0 +1,2 @@ +lda {cowo1},x +tax \ No newline at end of file diff --git a/src/main/java/dk/camelot64/kickc/asm/fragment/xby=cowo1_staridx_zpby1.asm b/src/main/java/dk/camelot64/kickc/asm/fragment/xby=cowo1_staridx_zpby1.asm new file mode 100644 index 000000000..73af4ba1d --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/asm/fragment/xby=cowo1_staridx_zpby1.asm @@ -0,0 +1,3 @@ +ldx {zpby1} +lda {cowo1},x +tax \ No newline at end of file diff --git a/src/main/java/dk/camelot64/kickc/asm/fragment/xby=xby_plus_coby1.asm b/src/main/java/dk/camelot64/kickc/asm/fragment/xby=xby_plus_coby1.asm new file mode 100644 index 000000000..0d08d0c44 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/asm/fragment/xby=xby_plus_coby1.asm @@ -0,0 +1,4 @@ +txa +clc +adc #{coby1} +tax \ No newline at end of file diff --git a/src/main/java/dk/camelot64/kickc/asm/fragment/xby=xby_plus_zpby1.asm b/src/main/java/dk/camelot64/kickc/asm/fragment/xby=xby_plus_zpby1.asm new file mode 100644 index 000000000..7edd87e89 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/asm/fragment/xby=xby_plus_zpby1.asm @@ -0,0 +1,4 @@ +txa +clc +adc {zpby1} +tax \ No newline at end of file diff --git a/src/main/java/dk/camelot64/kickc/asm/fragment/yby=cowo1_staridx_yby.asm b/src/main/java/dk/camelot64/kickc/asm/fragment/yby=cowo1_staridx_yby.asm new file mode 100644 index 000000000..9ebb2ca7a --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/asm/fragment/yby=cowo1_staridx_yby.asm @@ -0,0 +1,2 @@ +lda {cowo1},y +tay \ No newline at end of file diff --git a/src/main/java/dk/camelot64/kickc/asm/fragment/yby=cowo1_staridx_zpby1.asm b/src/main/java/dk/camelot64/kickc/asm/fragment/yby=cowo1_staridx_zpby1.asm new file mode 100644 index 000000000..6d11b55c1 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/asm/fragment/yby=cowo1_staridx_zpby1.asm @@ -0,0 +1,3 @@ +ldy {zpby1} +lda {cowo1},y +tay \ No newline at end of file diff --git a/src/main/java/dk/camelot64/kickc/asm/fragment/yby=yby_plus_zpby1.asm b/src/main/java/dk/camelot64/kickc/asm/fragment/yby=yby_plus_zpby1.asm new file mode 100644 index 000000000..2bead6ed0 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/asm/fragment/yby=yby_plus_zpby1.asm @@ -0,0 +1,4 @@ +tya +clc +adc {zpby1} +tay \ No newline at end of file diff --git a/src/main/java/dk/camelot64/kickc/asm/fragment/zpby1=xby_plus_coby1.asm b/src/main/java/dk/camelot64/kickc/asm/fragment/zpby1=xby_plus_coby1.asm new file mode 100644 index 000000000..cd2f9882e --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/asm/fragment/zpby1=xby_plus_coby1.asm @@ -0,0 +1,4 @@ +txa +clc +adc #{coby1} +sta {zpby1} \ No newline at end of file diff --git a/src/main/java/dk/camelot64/kickc/asm/fragment/zpby1=yby_plus_coby1.asm b/src/main/java/dk/camelot64/kickc/asm/fragment/zpby1=yby_plus_coby1.asm new file mode 100644 index 000000000..eb6a52c43 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/asm/fragment/zpby1=yby_plus_coby1.asm @@ -0,0 +1,4 @@ +tya +clc +adc #{coby1} +sta {zpby1} \ No newline at end of file diff --git a/src/main/java/dk/camelot64/kickc/asm/fragment/zpptrby1_staridx_aby=zpby1.asm b/src/main/java/dk/camelot64/kickc/asm/fragment/zpptrby1_staridx_aby=zpby1.asm new file mode 100644 index 000000000..c07b6fa73 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/asm/fragment/zpptrby1_staridx_aby=zpby1.asm @@ -0,0 +1,3 @@ +tay +lda {zpby1} +sta ({zpptrby1}),y \ No newline at end of file diff --git a/src/main/java/dk/camelot64/kickc/asm/fragment/zpptrby1_staridx_xby=zpby1.asm b/src/main/java/dk/camelot64/kickc/asm/fragment/zpptrby1_staridx_xby=zpby1.asm new file mode 100644 index 000000000..2ed06e644 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/asm/fragment/zpptrby1_staridx_xby=zpby1.asm @@ -0,0 +1,4 @@ +txa +tay +lda {zpby1} +sta ({zpptrby1}),y \ No newline at end of file diff --git a/src/main/java/dk/camelot64/kickc/asm/fragment/zpptrby1_staridx_yby=zpby1.asm b/src/main/java/dk/camelot64/kickc/asm/fragment/zpptrby1_staridx_yby=zpby1.asm new file mode 100644 index 000000000..0ff47809d --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/asm/fragment/zpptrby1_staridx_yby=zpby1.asm @@ -0,0 +1,2 @@ +lda {zpby1} +sta ({zpptrby1}),y \ No newline at end of file diff --git a/src/main/java/dk/camelot64/kickc/icl/LiveRangeEquivalenceClassSet.java b/src/main/java/dk/camelot64/kickc/icl/LiveRangeEquivalenceClassSet.java index fbe5b595c..f0857a7a8 100644 --- a/src/main/java/dk/camelot64/kickc/icl/LiveRangeEquivalenceClassSet.java +++ b/src/main/java/dk/camelot64/kickc/icl/LiveRangeEquivalenceClassSet.java @@ -61,4 +61,16 @@ public class LiveRangeEquivalenceClassSet { equivalenceClasses.remove(equivalenceClass); } + public RegisterAllocation createRegisterAllocation() { + RegisterAllocation allocation = new RegisterAllocation(); + for (LiveRangeEquivalenceClass equivalenceClass : getEquivalenceClasses()) { + RegisterAllocation.Register register = equivalenceClass.getRegister(); + for (VariableRef variable : equivalenceClass.getVariables()) { + allocation.setRegister(variable, register); + } + } + return allocation; + } + + } diff --git a/src/main/java/dk/camelot64/kickc/icl/RegisterAllocation.java b/src/main/java/dk/camelot64/kickc/icl/RegisterAllocation.java index 450a1bd4b..958d2db61 100644 --- a/src/main/java/dk/camelot64/kickc/icl/RegisterAllocation.java +++ b/src/main/java/dk/camelot64/kickc/icl/RegisterAllocation.java @@ -24,7 +24,7 @@ public class RegisterAllocation { } - public void allocate(VariableRef variable, Register register) { + public void setRegister(VariableRef variable, Register register) { if(variable!=null) { allocation.put(variable, register); } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass3AssertNoCpuClobber.java b/src/main/java/dk/camelot64/kickc/passes/Pass3AssertNoCpuClobber.java index b05a9a679..49c59b795 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass3AssertNoCpuClobber.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass3AssertNoCpuClobber.java @@ -30,11 +30,19 @@ public class Pass3AssertNoCpuClobber { /** Check that no statement clobbers a CPU register used by an alive variable */ public void check() { - LiveRangeVariables liveRangeVariables = program.getScope().getLiveRangeVariables(); + if(hasClobberProblem()) { + throw new RuntimeException("CLOBBER ERROR! See log for more info."); + } + } + + /** + * Determines whether any statement in the program clobbers a CPU register used by an alive variable + * @return true if there is a clobber problem in the program + */ + public boolean hasClobberProblem() { RegisterAllocation allocation = program.getScope().getAllocation(); - + LiveRangeVariables liveRangeVariables = program.getScope().getLiveRangeVariables(); boolean error = false; - for (ControlFlowBlock block : program.getGraph().getAllBlocks()) { for (Statement statement : block.getStatements()) { @@ -66,11 +74,7 @@ public class Pass3AssertNoCpuClobber { } } } - - if(error) { - throw new RuntimeException("CLOBBER ERROR! See log for more info."); - } - + return error; } @@ -133,5 +137,4 @@ public class Pass3AssertNoCpuClobber { return asm; } - } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass3CustomRegisters.java b/src/main/java/dk/camelot64/kickc/passes/Pass3CustomRegisters.java index 986814d08..0014463e2 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass3CustomRegisters.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass3CustomRegisters.java @@ -18,96 +18,96 @@ public class Pass3CustomRegisters { RegisterAllocation allocation = program.getScope().getAllocation(); // Register allocation for loopnest.kc - allocation.allocate(new VariableRef("nest2::j#2"), RegisterAllocation.getRegisterX()); - allocation.allocate(new VariableRef("nest2::j#1"), RegisterAllocation.getRegisterX()); - allocation.allocate(new VariableRef("nest2::i#2"), RegisterAllocation.getRegisterY()); - allocation.allocate(new VariableRef("nest2::i#1"), RegisterAllocation.getRegisterY()); + allocation.setRegister(new VariableRef("nest2::j#2"), RegisterAllocation.getRegisterX()); + allocation.setRegister(new VariableRef("nest2::j#1"), RegisterAllocation.getRegisterX()); + allocation.setRegister(new VariableRef("nest2::i#2"), RegisterAllocation.getRegisterY()); + allocation.setRegister(new VariableRef("nest2::i#1"), RegisterAllocation.getRegisterY()); // Register allocation for fibmem.kc /* - allocation.allocate(new VariableRef("i#1"), RegisterAllocation.getRegisterX()); - allocation.allocate(new VariableRef("i#2"), RegisterAllocation.getRegisterX()); - allocation.allocate(new VariableRef("$1"), new RegisterAllocation.RegisterAByte()); - allocation.allocate(new VariableRef("$3"), new RegisterAllocation.RegisterALUByte()); - allocation.allocate(new VariableRef("$4"), new RegisterAllocation.RegisterAByte()); + allocation.setRegister(new VariableRef("i#1"), RegisterAllocation.getRegisterX()); + allocation.setRegister(new VariableRef("i#2"), RegisterAllocation.getRegisterX()); + allocation.setRegister(new VariableRef("$1"), new RegisterAllocation.RegisterAByte()); + allocation.setRegister(new VariableRef("$3"), new RegisterAllocation.RegisterALUByte()); + allocation.setRegister(new VariableRef("$4"), new RegisterAllocation.RegisterAByte()); */ // Registers for postinc.kc /* - allocation.allocate(new VariableRef("c#0"), RegisterAllocation.getRegisterA()); - allocation.allocate(new VariableRef("c#1"), RegisterAllocation.getRegisterA()); - allocation.allocate(new VariableRef("c#2"), RegisterAllocation.getRegisterA()); - allocation.allocate(new VariableRef("b#0"), new RegisterAllocation.RegisterZpByte(102)); - allocation.allocate(new VariableRef("b#1"), new RegisterAllocation.RegisterZpByte(102)); - allocation.allocate(new VariableRef("b#2"), new RegisterAllocation.RegisterZpByte(102)); - allocation.allocate(new VariableRef("$1"), new RegisterAllocation.RegisterZpByte(101)); - allocation.allocate(new VariableRef("a#0"), new RegisterAllocation.RegisterZpByte(103)); - allocation.allocate(new VariableRef("a#1"), new RegisterAllocation.RegisterZpByte(103)); - allocation.allocate(new VariableRef("a#2"), new RegisterAllocation.RegisterZpByte(103)); - allocation.allocate(new VariableRef("$0"), RegisterAllocation.getRegisterA()); - allocation.allocate(new VariableRef("i#0"), RegisterAllocation.getRegisterX()); - allocation.allocate(new VariableRef("i#1"), RegisterAllocation.getRegisterX()); - allocation.allocate(new VariableRef("i#2"), RegisterAllocation.getRegisterX()); + allocation.setRegister(new VariableRef("c#0"), RegisterAllocation.getRegisterA()); + allocation.setRegister(new VariableRef("c#1"), RegisterAllocation.getRegisterA()); + allocation.setRegister(new VariableRef("c#2"), RegisterAllocation.getRegisterA()); + allocation.setRegister(new VariableRef("b#0"), new RegisterAllocation.RegisterZpByte(102)); + allocation.setRegister(new VariableRef("b#1"), new RegisterAllocation.RegisterZpByte(102)); + allocation.setRegister(new VariableRef("b#2"), new RegisterAllocation.RegisterZpByte(102)); + allocation.setRegister(new VariableRef("$1"), new RegisterAllocation.RegisterZpByte(101)); + allocation.setRegister(new VariableRef("a#0"), new RegisterAllocation.RegisterZpByte(103)); + allocation.setRegister(new VariableRef("a#1"), new RegisterAllocation.RegisterZpByte(103)); + allocation.setRegister(new VariableRef("a#2"), new RegisterAllocation.RegisterZpByte(103)); + allocation.setRegister(new VariableRef("$0"), RegisterAllocation.getRegisterA()); + allocation.setRegister(new VariableRef("i#0"), RegisterAllocation.getRegisterX()); + allocation.setRegister(new VariableRef("i#1"), RegisterAllocation.getRegisterX()); + allocation.setRegister(new VariableRef("i#2"), RegisterAllocation.getRegisterX()); */ // Optimal Registers for flipper-rex2.kc /* - allocation.allocate(new VariableRef("plot::i#0"), RegisterAllocation.getRegisterX()); - allocation.allocate(new VariableRef("plot::i#1"), RegisterAllocation.getRegisterX()); - allocation.allocate(new VariableRef("plot::i#2"), RegisterAllocation.getRegisterX()); - allocation.allocate(new VariableRef("plot::i#3"), RegisterAllocation.getRegisterX()); - allocation.allocate(new VariableRef("plot::i#4"), RegisterAllocation.getRegisterX()); - allocation.allocate(new VariableRef("plot::x#0"), RegisterAllocation.getRegisterY()); - allocation.allocate(new VariableRef("plot::x#1"), RegisterAllocation.getRegisterY()); - allocation.allocate(new VariableRef("plot::x#2"), RegisterAllocation.getRegisterY()); - allocation.allocate(new VariableRef("plot::y#0"), new RegisterAllocation.RegisterZpByte(100)); - allocation.allocate(new VariableRef("plot::y#1"), new RegisterAllocation.RegisterZpByte(100)); - allocation.allocate(new VariableRef("plot::y#2"), new RegisterAllocation.RegisterZpByte(100)); - allocation.allocate(new VariableRef("plot::y#3"), new RegisterAllocation.RegisterZpByte(100)); - allocation.allocate(new VariableRef("plot::y#4"), new RegisterAllocation.RegisterZpByte(100)); - allocation.allocate(new VariableRef("plot::line#0"), new RegisterAllocation.RegisterZpPointerByte(101)); - allocation.allocate(new VariableRef("plot::line#1"), new RegisterAllocation.RegisterZpPointerByte(101)); - allocation.allocate(new VariableRef("plot::line#2"), new RegisterAllocation.RegisterZpPointerByte(101)); - allocation.allocate(new VariableRef("plot::line#3"), new RegisterAllocation.RegisterZpPointerByte(101)); - allocation.allocate(new VariableRef("plot::line#4"), new RegisterAllocation.RegisterZpPointerByte(101)); - allocation.allocate(new VariableRef("plot::$3"), RegisterAllocation.getRegisterA()); - allocation.allocate(new VariableRef("prepare::i#0"), RegisterAllocation.getRegisterX()); - allocation.allocate(new VariableRef("prepare::i#1"), RegisterAllocation.getRegisterX()); - allocation.allocate(new VariableRef("prepare::i#2"), RegisterAllocation.getRegisterX()); - allocation.allocate(new VariableRef("flip::srcIdx#0"), RegisterAllocation.getRegisterX()); - allocation.allocate(new VariableRef("flip::srcIdx#0"), RegisterAllocation.getRegisterX()); - allocation.allocate(new VariableRef("flip::srcIdx#1"), RegisterAllocation.getRegisterX()); - allocation.allocate(new VariableRef("flip::srcIdx#2"), RegisterAllocation.getRegisterX()); - allocation.allocate(new VariableRef("flip::srcIdx#3"), RegisterAllocation.getRegisterX()); - allocation.allocate(new VariableRef("flip::srcIdx#4"), RegisterAllocation.getRegisterX()); - allocation.allocate(new VariableRef("flip::dstIdx#0"), RegisterAllocation.getRegisterY()); - allocation.allocate(new VariableRef("flip::dstIdx#1"), RegisterAllocation.getRegisterY()); - allocation.allocate(new VariableRef("flip::dstIdx#2"), RegisterAllocation.getRegisterY()); - allocation.allocate(new VariableRef("flip::dstIdx#3"), RegisterAllocation.getRegisterY()); - allocation.allocate(new VariableRef("flip::dstIdx#4"), RegisterAllocation.getRegisterY()); - allocation.allocate(new VariableRef("flip::dstIdx#5"), RegisterAllocation.getRegisterY()); - allocation.allocate(new VariableRef("flip::c#0"), new RegisterAllocation.RegisterZpByte(103)); - allocation.allocate(new VariableRef("flip::c#1"), new RegisterAllocation.RegisterZpByte(103)); - allocation.allocate(new VariableRef("flip::c#2"), new RegisterAllocation.RegisterZpByte(103)); - allocation.allocate(new VariableRef("flip::r#0"), new RegisterAllocation.RegisterZpByte(104)); - allocation.allocate(new VariableRef("flip::r#1"), new RegisterAllocation.RegisterZpByte(104)); - allocation.allocate(new VariableRef("flip::r#2"), new RegisterAllocation.RegisterZpByte(104)); - allocation.allocate(new VariableRef("flip::r#3"), new RegisterAllocation.RegisterZpByte(104)); - allocation.allocate(new VariableRef("flip::r#4"), new RegisterAllocation.RegisterZpByte(104)); - allocation.allocate(new VariableRef("flip::i#0"), RegisterAllocation.getRegisterX()); - allocation.allocate(new VariableRef("flip::i#1"), RegisterAllocation.getRegisterX()); - allocation.allocate(new VariableRef("flip::i#2"), RegisterAllocation.getRegisterX()); - allocation.allocate(new VariableRef("flip::$0"), RegisterAllocation.getRegisterA()); - allocation.allocate(new VariableRef("flip::$8"), RegisterAllocation.getRegisterA()); - allocation.allocate(new VariableRef("flip::$4"), RegisterAllocation.getRegisterA()); - allocation.allocate(new VariableRef("main::$1"), RegisterAllocation.getRegisterA()); - allocation.allocate(new VariableRef("main::$3"), RegisterAllocation.getRegisterA()); - allocation.allocate(new VariableRef("main::c#0"), RegisterAllocation.getRegisterX()); - allocation.allocate(new VariableRef("main::c#1"), RegisterAllocation.getRegisterX()); - allocation.allocate(new VariableRef("main::c#2"), RegisterAllocation.getRegisterX()); - allocation.allocate(new VariableRef("main::c#3"), RegisterAllocation.getRegisterX()); - allocation.allocate(new VariableRef("main::c#4"), RegisterAllocation.getRegisterX()); + allocation.setRegister(new VariableRef("plot::i#0"), RegisterAllocation.getRegisterX()); + allocation.setRegister(new VariableRef("plot::i#1"), RegisterAllocation.getRegisterX()); + allocation.setRegister(new VariableRef("plot::i#2"), RegisterAllocation.getRegisterX()); + allocation.setRegister(new VariableRef("plot::i#3"), RegisterAllocation.getRegisterX()); + allocation.setRegister(new VariableRef("plot::i#4"), RegisterAllocation.getRegisterX()); + allocation.setRegister(new VariableRef("plot::x#0"), RegisterAllocation.getRegisterY()); + allocation.setRegister(new VariableRef("plot::x#1"), RegisterAllocation.getRegisterY()); + allocation.setRegister(new VariableRef("plot::x#2"), RegisterAllocation.getRegisterY()); + allocation.setRegister(new VariableRef("plot::y#0"), new RegisterAllocation.RegisterZpByte(100)); + allocation.setRegister(new VariableRef("plot::y#1"), new RegisterAllocation.RegisterZpByte(100)); + allocation.setRegister(new VariableRef("plot::y#2"), new RegisterAllocation.RegisterZpByte(100)); + allocation.setRegister(new VariableRef("plot::y#3"), new RegisterAllocation.RegisterZpByte(100)); + allocation.setRegister(new VariableRef("plot::y#4"), new RegisterAllocation.RegisterZpByte(100)); + allocation.setRegister(new VariableRef("plot::line#0"), new RegisterAllocation.RegisterZpPointerByte(101)); + allocation.setRegister(new VariableRef("plot::line#1"), new RegisterAllocation.RegisterZpPointerByte(101)); + allocation.setRegister(new VariableRef("plot::line#2"), new RegisterAllocation.RegisterZpPointerByte(101)); + allocation.setRegister(new VariableRef("plot::line#3"), new RegisterAllocation.RegisterZpPointerByte(101)); + allocation.setRegister(new VariableRef("plot::line#4"), new RegisterAllocation.RegisterZpPointerByte(101)); + allocation.setRegister(new VariableRef("plot::$3"), RegisterAllocation.getRegisterA()); + allocation.setRegister(new VariableRef("prepare::i#0"), RegisterAllocation.getRegisterX()); + allocation.setRegister(new VariableRef("prepare::i#1"), RegisterAllocation.getRegisterX()); + allocation.setRegister(new VariableRef("prepare::i#2"), RegisterAllocation.getRegisterX()); + allocation.setRegister(new VariableRef("flip::srcIdx#0"), RegisterAllocation.getRegisterX()); + allocation.setRegister(new VariableRef("flip::srcIdx#0"), RegisterAllocation.getRegisterX()); + allocation.setRegister(new VariableRef("flip::srcIdx#1"), RegisterAllocation.getRegisterX()); + allocation.setRegister(new VariableRef("flip::srcIdx#2"), RegisterAllocation.getRegisterX()); + allocation.setRegister(new VariableRef("flip::srcIdx#3"), RegisterAllocation.getRegisterX()); + allocation.setRegister(new VariableRef("flip::srcIdx#4"), RegisterAllocation.getRegisterX()); + allocation.setRegister(new VariableRef("flip::dstIdx#0"), RegisterAllocation.getRegisterY()); + allocation.setRegister(new VariableRef("flip::dstIdx#1"), RegisterAllocation.getRegisterY()); + allocation.setRegister(new VariableRef("flip::dstIdx#2"), RegisterAllocation.getRegisterY()); + allocation.setRegister(new VariableRef("flip::dstIdx#3"), RegisterAllocation.getRegisterY()); + allocation.setRegister(new VariableRef("flip::dstIdx#4"), RegisterAllocation.getRegisterY()); + allocation.setRegister(new VariableRef("flip::dstIdx#5"), RegisterAllocation.getRegisterY()); + allocation.setRegister(new VariableRef("flip::c#0"), new RegisterAllocation.RegisterZpByte(103)); + allocation.setRegister(new VariableRef("flip::c#1"), new RegisterAllocation.RegisterZpByte(103)); + allocation.setRegister(new VariableRef("flip::c#2"), new RegisterAllocation.RegisterZpByte(103)); + allocation.setRegister(new VariableRef("flip::r#0"), new RegisterAllocation.RegisterZpByte(104)); + allocation.setRegister(new VariableRef("flip::r#1"), new RegisterAllocation.RegisterZpByte(104)); + allocation.setRegister(new VariableRef("flip::r#2"), new RegisterAllocation.RegisterZpByte(104)); + allocation.setRegister(new VariableRef("flip::r#3"), new RegisterAllocation.RegisterZpByte(104)); + allocation.setRegister(new VariableRef("flip::r#4"), new RegisterAllocation.RegisterZpByte(104)); + allocation.setRegister(new VariableRef("flip::i#0"), RegisterAllocation.getRegisterX()); + allocation.setRegister(new VariableRef("flip::i#1"), RegisterAllocation.getRegisterX()); + allocation.setRegister(new VariableRef("flip::i#2"), RegisterAllocation.getRegisterX()); + allocation.setRegister(new VariableRef("flip::$0"), RegisterAllocation.getRegisterA()); + allocation.setRegister(new VariableRef("flip::$8"), RegisterAllocation.getRegisterA()); + allocation.setRegister(new VariableRef("flip::$4"), RegisterAllocation.getRegisterA()); + allocation.setRegister(new VariableRef("main::$1"), RegisterAllocation.getRegisterA()); + allocation.setRegister(new VariableRef("main::$3"), RegisterAllocation.getRegisterA()); + allocation.setRegister(new VariableRef("main::c#0"), RegisterAllocation.getRegisterX()); + allocation.setRegister(new VariableRef("main::c#1"), RegisterAllocation.getRegisterX()); + allocation.setRegister(new VariableRef("main::c#2"), RegisterAllocation.getRegisterX()); + allocation.setRegister(new VariableRef("main::c#3"), RegisterAllocation.getRegisterX()); + allocation.setRegister(new VariableRef("main::c#4"), RegisterAllocation.getRegisterX()); */ @@ -121,16 +121,16 @@ public class Pass3CustomRegisters { } else if (symbol instanceof VariableIntermediate || symbol instanceof VariableVersion) { Variable var = (Variable) symbol; if (symbol.getType().equals(SymbolTypeBasic.BYTE)) { - allocation.allocate(var.getRef(), new RegisterAllocation.RegisterZpByte(currentZp++)); + allocation.setRegister(var.getRef(), new RegisterAllocation.RegisterZpByte(currentZp++)); } else if (symbol.getType().equals(SymbolTypeBasic.WORD)) { - allocation.allocate(var.getRef(), new RegisterAllocation.RegisterZpWord(currentZp)); + allocation.setRegister(var.getRef(), new RegisterAllocation.RegisterZpWord(currentZp)); currentZp = currentZp + 2; } else if (symbol.getType().equals(SymbolTypeBasic.BOOLEAN)) { - allocation.allocate(var.getRef(), new RegisterAllocation.RegisterZpBool(currentZp++)); + allocation.setRegister(var.getRef(), new RegisterAllocation.RegisterZpBool(currentZp++)); } else if (symbol.getType().equals(SymbolTypeBasic.VOID)) { - // No need to allocate register for VOID value + // No need to setRegister register for VOID value } else if (symbol.getType() instanceof SymbolTypePointer) { - allocation.allocate(var.getRef(), new RegisterAllocation.RegisterZpPointerByte(currentZp)); + allocation.setRegister(var.getRef(), new RegisterAllocation.RegisterZpPointerByte(currentZp)); currentZp = currentZp + 2; } else { throw new RuntimeException("Unhandled variable type " + symbol); diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass3RegisterUplifting.java b/src/main/java/dk/camelot64/kickc/passes/Pass3RegisterUplifting.java index 80a6ac1d5..a16bb7505 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass3RegisterUplifting.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass3RegisterUplifting.java @@ -5,7 +5,10 @@ import dk.camelot64.kickc.asm.AsmProgram; import dk.camelot64.kickc.asm.parser.AsmClobber; import dk.camelot64.kickc.icl.*; +import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; +import java.util.List; /*** Uplift one variable into the A register - and check if the program still works */ public class Pass3RegisterUplifting { @@ -30,31 +33,56 @@ public class Pass3RegisterUplifting { * Uplift one variable */ public void uplift() { - VariableRegisterWeights variableRegisterWeights = program.getScope().getVariableRegisterWeights(); + LiveRangeEquivalenceClassSet equivalenceClassSet = program.getScope().getLiveRangeEquivalenceClassSet(); double maxWeight = 0.0; - Variable maxVar = null; + LiveRangeEquivalenceClass maxEquivalenceClass = null; - Collection allVars = program.getScope().getAllVariables(true); - RegisterAllocation allocation = program.getScope().getAllocation(); - - for (Variable variable : allVars) { - RegisterAllocation.Register currentRegister = allocation.getRegister(variable.getRef()); - if (currentRegister!=null && currentRegister.isZp()) { - Double w = variableRegisterWeights.getWeight(variable.getRef()); - if (w != null && w > maxWeight) { - maxWeight = w; - maxVar = variable; - } + // Find the live range equivalence class with the highest total weight + for (LiveRangeEquivalenceClass equivalenceClass : equivalenceClassSet.getEquivalenceClasses()) { + double totalWeight = 0.0; + List vars = equivalenceClass.getVariables(); + for (VariableRef var : vars) { + Double varWeight = variableRegisterWeights.getWeight(var); + totalWeight += varWeight; + } + if (maxWeight < totalWeight) { + maxEquivalenceClass = equivalenceClass; + maxWeight = totalWeight; } } - // Found max variable! - if(maxVar!=null) { - log.append("Uplifting of variable " + maxVar + " to A"); - allocation.allocate(maxVar.getRef(), new RegisterAllocation.RegisterAByte()); + + if (maxEquivalenceClass != null) { + log.append("Uplifting max weight " + maxWeight + " live range equivalence class " + maxEquivalenceClass); + // Try the A register first + List registers = + Arrays.asList( + RegisterAllocation.getRegisterA(), + RegisterAllocation.getRegisterX(), + RegisterAllocation.getRegisterY()); + for (RegisterAllocation.Register register : registers) { + attemptUplift(maxEquivalenceClass, register); + } } + RegisterAllocation allocation = program.getScope().getLiveRangeEquivalenceClassSet().createRegisterAllocation(); + program.getScope().setAllocation(allocation); + + } + + private void attemptUplift(LiveRangeEquivalenceClass equivalenceClass, RegisterAllocation.Register register) { + RegisterAllocation allocation = program.getScope().getLiveRangeEquivalenceClassSet().createRegisterAllocation(); + for (VariableRef var : equivalenceClass.getVariables()) { + allocation.setRegister(var, register); + } + program.getScope().setAllocation(allocation); + Pass3AssertNoCpuClobber clobber = new Pass3AssertNoCpuClobber(program, log); + if (clobber.hasClobberProblem()) { + log.append("Uplift to " + register + " resulted in clobber."); + } else { + log.append("Uplift to " + register + " succesfull."); + } } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass3RegistersFinalize.java b/src/main/java/dk/camelot64/kickc/passes/Pass3RegistersFinalize.java index b271fc7ee..cd0747c4a 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass3RegistersFinalize.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass3RegistersFinalize.java @@ -19,8 +19,17 @@ public class Pass3RegistersFinalize { public void allocate() { LiveRangeEquivalenceClassSet liveRangeEquivalenceClassSet = program.getScope().getLiveRangeEquivalenceClassSet(); + reallocateZp(liveRangeEquivalenceClassSet); + RegisterAllocation allocation = liveRangeEquivalenceClassSet.createRegisterAllocation(); + program.getScope().setAllocation(allocation); + } - RegisterAllocation allocation = new RegisterAllocation(); + /** + * Reallocate all ZP registers to minimize ZP usage + * + * @param liveRangeEquivalenceClassSet The + */ + private void reallocateZp(LiveRangeEquivalenceClassSet liveRangeEquivalenceClassSet) { for (LiveRangeEquivalenceClass equivalenceClass : liveRangeEquivalenceClassSet.getEquivalenceClasses()) { RegisterAllocation.Register register = equivalenceClass.getRegister(); if(register.isZp()) { @@ -28,14 +37,12 @@ public class Pass3RegistersFinalize { VariableRef variable = equivalenceClass.getVariables().get(0); Variable symbol = program.getScope().getVariable(variable); register = allocateNewRegisterZp(symbol.getType()); - log.append("Re-allocated ZP register from "+before+" to "+register.toString()); - } - for (VariableRef variable : equivalenceClass.getVariables()) { - allocation.allocate(variable, register); + equivalenceClass.setRegister(register); + if(!before.equals(register.toString())) { + log.append("Re-allocated ZP register from " + before + " to " + register.toString()); + } } } - program.getScope().setAllocation(allocation); - } /** @@ -61,7 +68,7 @@ public class Pass3RegistersFinalize { } else if (varType.equals(SymbolTypeBasic.BOOLEAN)) { return new RegisterAllocation.RegisterZpBool(currentZp++); } else if (varType.equals(SymbolTypeBasic.VOID)) { - // No need to allocate register for VOID value + // No need to setRegister register for VOID value return null; } else if (varType instanceof SymbolTypePointer) { RegisterAllocation.RegisterZpPointerByte registerZpPointerByte = diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass3ZeroPageAllocation.java b/src/main/java/dk/camelot64/kickc/passes/Pass3ZeroPageAllocation.java index c4e3caef2..5ab680c1f 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass3ZeroPageAllocation.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass3ZeroPageAllocation.java @@ -178,7 +178,7 @@ public class Pass3ZeroPageAllocation { } else if (varType.equals(SymbolTypeBasic.BOOLEAN)) { return new RegisterAllocation.RegisterZpBool(currentZp++); } else if (varType.equals(SymbolTypeBasic.VOID)) { - // No need to allocate register for VOID value + // No need to setRegister register for VOID value return null; } else if (varType instanceof SymbolTypePointer) { RegisterAllocation.RegisterZpPointerByte registerZpPointerByte = diff --git a/src/main/java/dk/camelot64/kickc/test/TestCompilationOutput.java b/src/main/java/dk/camelot64/kickc/test/TestCompilationOutput.java index a6c4e4d70..4e3a11f28 100644 --- a/src/main/java/dk/camelot64/kickc/test/TestCompilationOutput.java +++ b/src/main/java/dk/camelot64/kickc/test/TestCompilationOutput.java @@ -23,56 +23,63 @@ public class TestCompilationOutput extends TestCase { } public void testFlipper() throws IOException, URISyntaxException { - TestCompilationOutput tester = new TestCompilationOutput(); - tester.testFile("flipper-rex2"); + compileAndCompare("flipper-rex2"); } public void testBresenham() throws IOException, URISyntaxException { - TestCompilationOutput tester = new TestCompilationOutput(); - tester.testFile("bresenham"); + compileAndCompare("bresenham"); } public void testMinus() throws IOException, URISyntaxException { - TestCompilationOutput tester = new TestCompilationOutput(); - tester.testFile("minus"); + compileAndCompare("minus"); } public void testLoopMin() throws IOException, URISyntaxException { - TestCompilationOutput tester = new TestCompilationOutput(); - tester.testFile("loopmin"); + compileAndCompare("loopmin"); } public void testSumMin() throws IOException, URISyntaxException { - TestCompilationOutput tester = new TestCompilationOutput(); - tester.testFile("summin"); + compileAndCompare("summin"); } public void testLoopSplit() throws IOException, URISyntaxException { - TestCompilationOutput tester = new TestCompilationOutput(); - tester.testFile("loopsplit"); + compileAndCompare("loopsplit"); } public void testLoopNest() throws IOException, URISyntaxException { - TestCompilationOutput tester = new TestCompilationOutput(); - tester.testFile("loopnest"); + compileAndCompare("loopnest"); } public void testLoopNest2() throws IOException, URISyntaxException { - TestCompilationOutput tester = new TestCompilationOutput(); - tester.testFile("loopnest2"); + compileAndCompare("loopnest2"); } public void testFibMem() throws IOException, URISyntaxException { - TestCompilationOutput tester = new TestCompilationOutput(); - tester.testFile("fibmem"); + compileAndCompare("fibmem"); } public void testPtrTest() throws IOException, URISyntaxException { - TestCompilationOutput tester = new TestCompilationOutput(); - tester.testFile("ptrtest"); + compileAndCompare("ptrtest"); + } + + public void testUseGlobal() throws IOException, URISyntaxException { + compileAndCompare("useglobal"); + } + + public void testUseUninitialized() throws IOException, URISyntaxException { + String filename = "useuninitialized"; + compileAndCompare(filename); + } + + public void testUseUndeclared() throws IOException, URISyntaxException { + compileAndCompare("useundeclared"); } + private void compileAndCompare(String filename) throws IOException, URISyntaxException { + TestCompilationOutput tester = new TestCompilationOutput(); + tester.testFile(filename); + } private void testFile(String fileName) throws IOException, URISyntaxException { String inputPath = testPath + fileName + ".kc"; diff --git a/src/main/java/dk/camelot64/kickc/test/useglobal.kc b/src/main/java/dk/camelot64/kickc/test/useglobal.kc new file mode 100644 index 000000000..30e1f5f1e --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/test/useglobal.kc @@ -0,0 +1,6 @@ +// Tests procedures using global variables (should not fail) +byte* SCREEN = $0400; +main(); +void main() { + *SCREEN = 1; +} \ No newline at end of file diff --git a/src/main/java/dk/camelot64/kickc/test/useundeclared.kc b/src/main/java/dk/camelot64/kickc/test/useundeclared.kc new file mode 100644 index 000000000..9a6c970ef --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/test/useundeclared.kc @@ -0,0 +1,5 @@ +// Uses an undeclared variable - should fail gracefully +main(); +void main() { + byte s = b+1; +} \ No newline at end of file diff --git a/src/main/java/dk/camelot64/kickc/test/useuninitialized.kc b/src/main/java/dk/camelot64/kickc/test/useuninitialized.kc new file mode 100644 index 000000000..f442348df --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/test/useuninitialized.kc @@ -0,0 +1,7 @@ +// Use an uninitialized variable - should fail gracefully! + +main(); +void main() { + byte b; + byte s=b+1; +} \ No newline at end of file