diff --git a/src/dk/camelot64/kickc/asm/AsmFragment.java b/src/dk/camelot64/kickc/asm/AsmFragment.java index 052a242a6..b1b2286a5 100644 --- a/src/dk/camelot64/kickc/asm/AsmFragment.java +++ b/src/dk/camelot64/kickc/asm/AsmFragment.java @@ -166,11 +166,22 @@ public class AsmFragment { public String bind(Value value) { if (value instanceof Variable) { value = symbols.getRegister((Variable) value); - } else if (value instanceof PointerDereferenceVariable) { - PointerDereferenceVariable deref = (PointerDereferenceVariable) value; - Variable pointer = deref.getPointer(); - RegisterAllocation.Register register = symbols.getRegister(pointer); - value = new PointerDereferenceRegisterZpByte((RegisterAllocation.RegisterZpPointerByte) register); + } else if (value instanceof PointerDereferenceSimple) { + PointerDereferenceSimple deref = (PointerDereferenceSimple) value; + RValue pointer = deref.getPointer(); + if(pointer instanceof Variable) { + Variable pointerVar = (Variable) pointer; + RegisterAllocation.Register register = symbols.getRegister(pointerVar); + value = new PointerDereferenceRegisterZpByte((RegisterAllocation.RegisterZpPointerByte) register); + } + } else if (value instanceof PointerDereferenceIndexed) { + PointerDereferenceIndexed deref = (PointerDereferenceIndexed) value; + String compositeName = + "ptr_" + + bind(deref.getPointer()) + + "_" + + bind(deref.getIndex()); + return compositeName; } // Find value if it is already bound @@ -201,6 +212,10 @@ public class AsmFragment { String name = "yby"; bindings.put(name, value); return name; + } else if (RegisterAllocation.RegisterType.REG_A_BYTE.equals(register.getType())) { + String name = "aby"; + bindings.put(name, value); + return name; } else if (RegisterAllocation.RegisterType.ZP_PTR_BYTE.equals(register.getType())) { String name = "zpptrby" + nextZpPtrIdx++; bindings.put(name, value); @@ -213,13 +228,16 @@ public class AsmFragment { bindings.put(name, value); return name; } - } else if (value instanceof PointerDereferenceConstant) { - PointerDereferenceConstant deref = (PointerDereferenceConstant) value; - Constant pointer = deref.getPointer(); - if (pointer instanceof ConstantInteger) { - String name = "coptr" + nextConstByteIdx++; - bindings.put(name, value); - return name; + } else if (value instanceof PointerDereferenceSimple) { + PointerDereferenceSimple deref = (PointerDereferenceSimple) value; + RValue pointer = deref.getPointer(); + if(pointer instanceof Constant) { + Constant pointerConst = (Constant) pointer; + if (pointerConst instanceof ConstantInteger) { + String name = "coptr" + nextConstByteIdx++; + bindings.put(name, value); + return name; + } } } else if (value instanceof ConstantInteger) { ConstantInteger intValue = (ConstantInteger) value; @@ -269,12 +287,17 @@ public class AsmFragment { PointerDereferenceRegisterZpByte deref = (PointerDereferenceRegisterZpByte) boundValue; RegisterAllocation.RegisterZpPointerByte register = deref.getPointerRegister(); bound = Integer.toString(register.getZp()); - } else if (boundValue instanceof PointerDereferenceConstant) { - PointerDereferenceConstant deref = (PointerDereferenceConstant) boundValue; - Constant pointer = deref.getPointer(); - if (pointer instanceof ConstantInteger) { - ConstantInteger intPointer = (ConstantInteger) pointer; - bound = Integer.toString(intPointer.getNumber()); + } else if (boundValue instanceof PointerDereferenceSimple) { + PointerDereferenceSimple deref = (PointerDereferenceSimple) boundValue; + RValue pointer = deref.getPointer(); + if(pointer instanceof Constant) { + Constant pointerConst = (Constant) pointer; + if (pointerConst instanceof ConstantInteger) { + ConstantInteger intPointer = (ConstantInteger) pointerConst; + bound = Integer.toString(intPointer.getNumber()); + } else { + throw new RuntimeException("Bound Value Type not implemented " + boundValue); + } } else { throw new RuntimeException("Bound Value Type not implemented " + boundValue); } diff --git a/src/dk/camelot64/kickc/asm/fragment/aby=aby_plus_coby1.asm b/src/dk/camelot64/kickc/asm/fragment/aby=aby_plus_coby1.asm new file mode 100644 index 000000000..6a2af41a3 --- /dev/null +++ b/src/dk/camelot64/kickc/asm/fragment/aby=aby_plus_coby1.asm @@ -0,0 +1,2 @@ +clc +adc #{coby1} \ No newline at end of file diff --git a/src/dk/camelot64/kickc/asm/fragment/aby=coby1.asm b/src/dk/camelot64/kickc/asm/fragment/aby=coby1.asm new file mode 100644 index 000000000..bd3d863e1 --- /dev/null +++ b/src/dk/camelot64/kickc/asm/fragment/aby=coby1.asm @@ -0,0 +1 @@ +lda #{coby1} \ No newline at end of file diff --git a/src/dk/camelot64/kickc/asm/fragment/aby=xby_ror_2.asm b/src/dk/camelot64/kickc/asm/fragment/aby=xby_ror_2.asm new file mode 100644 index 000000000..bebaf5f1e --- /dev/null +++ b/src/dk/camelot64/kickc/asm/fragment/aby=xby_ror_2.asm @@ -0,0 +1,3 @@ +txa +lsr +lsr \ No newline at end of file diff --git a/src/dk/camelot64/kickc/asm/fragment/ptr_cowo1_xby=aby.asm b/src/dk/camelot64/kickc/asm/fragment/ptr_cowo1_xby=aby.asm new file mode 100644 index 000000000..e1e06df1c --- /dev/null +++ b/src/dk/camelot64/kickc/asm/fragment/ptr_cowo1_xby=aby.asm @@ -0,0 +1 @@ +sta {cowo1},x \ No newline at end of file diff --git a/src/dk/camelot64/kickc/asm/fragment/ptr_cowo1_xby=zpby1.asm b/src/dk/camelot64/kickc/asm/fragment/ptr_cowo1_xby=zpby1.asm new file mode 100644 index 000000000..4179c4cb0 --- /dev/null +++ b/src/dk/camelot64/kickc/asm/fragment/ptr_cowo1_xby=zpby1.asm @@ -0,0 +1,2 @@ +lda {zpby1} +sta {cowo1},x \ No newline at end of file diff --git a/src/dk/camelot64/kickc/icl/Pass1GenerateSingleStaticAssignmentForm.java b/src/dk/camelot64/kickc/icl/Pass1GenerateSingleStaticAssignmentForm.java index b20ecfdbb..71953c2d7 100644 --- a/src/dk/camelot64/kickc/icl/Pass1GenerateSingleStaticAssignmentForm.java +++ b/src/dk/camelot64/kickc/icl/Pass1GenerateSingleStaticAssignmentForm.java @@ -73,12 +73,24 @@ public class Pass1GenerateSingleStaticAssignmentForm { if (lValue instanceof VariableVersion) { VariableVersion versioned = (VariableVersion) lValue; blockVersions.put(versioned.getVersionOf(), versioned); - } else if(lValue instanceof PointerDereferenceVariable) { - PointerDereferenceVariable deref = (PointerDereferenceVariable) lValue; - Variable pointer = deref.getPointer(); + } else if(lValue instanceof PointerDereferenceSimple) { + PointerDereferenceSimple deref = (PointerDereferenceSimple) lValue; + RValue pointer = deref.getPointer(); VariableVersion version = findOrCreateVersion(pointer, blockVersions, blockNewPhis); if (version != null) { - deref.setPointerVariable(version); + deref.setPointer(version); + } + } else if(lValue instanceof PointerDereferenceIndexed) { + PointerDereferenceIndexed deref = (PointerDereferenceIndexed) lValue; + RValue pointer = deref.getPointer(); + VariableVersion version = findOrCreateVersion(pointer, blockVersions, blockNewPhis); + if (version != null) { + deref.setPointer(version); + } + RValue index = deref.getIndex(); + VariableVersion iVersion = findOrCreateVersion(index, blockVersions, blockNewPhis); + if (iVersion != null) { + deref.setIndex(iVersion); } } } diff --git a/src/dk/camelot64/kickc/icl/Pass1GenerateStatementSequence.java b/src/dk/camelot64/kickc/icl/Pass1GenerateStatementSequence.java index 9d03ebe40..6d4699c21 100644 --- a/src/dk/camelot64/kickc/icl/Pass1GenerateStatementSequence.java +++ b/src/dk/camelot64/kickc/icl/Pass1GenerateStatementSequence.java @@ -156,7 +156,7 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor { public LValue visitLvaluePtr(KickCParser.LvaluePtrContext ctx) { LValue lval = (LValue) visit(ctx.lvalue()); if(lval instanceof Variable) { - return new PointerDereferenceVariable((Variable) lval); + return new PointerDereferenceSimple((Variable) lval); } else { throw new RuntimeException("Not implemented"); } @@ -166,11 +166,7 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor { public LValue visitLvalueArray(KickCParser.LvalueArrayContext ctx) { LValue lval = (LValue) visit(ctx.lvalue()); RValue index = (RValue) visit(ctx.expr()); - Operator operator = new Operator("+"); - VariableIntermediate tmpVar = symbolTable.newIntermediateAssignment(); - Statement stmt = new StatementAssignment(tmpVar, lval, operator, index); - sequence.addStatement(stmt); - return new PointerDereferenceVariable(tmpVar); + return new PointerDereferenceIndexed((Variable) lval, (Variable)index); } @Override diff --git a/src/dk/camelot64/kickc/icl/Pass2SsaOptimization.java b/src/dk/camelot64/kickc/icl/Pass2SsaOptimization.java index ff390bea8..da70dfc5c 100644 --- a/src/dk/camelot64/kickc/icl/Pass2SsaOptimization.java +++ b/src/dk/camelot64/kickc/icl/Pass2SsaOptimization.java @@ -66,18 +66,25 @@ public abstract class Pass2SsaOptimization { assignment.setRValue2(getAlias(aliases, assignment.getRValue2())); } // Handle pointer dereference in LValue - if (lValue instanceof PointerDereferenceVariable) { - PointerDereferenceVariable deref = (PointerDereferenceVariable) lValue; - Variable pointer = deref.getPointer(); + if (lValue instanceof PointerDereferenceSimple) { + PointerDereferenceSimple deref = (PointerDereferenceSimple) lValue; + RValue pointer = deref.getPointer(); if (getAlias(aliases, pointer) != null) { RValue alias = getAlias(aliases, pointer); - if (alias instanceof Variable) { - deref.setPointerVariable((Variable) alias); - } else if (alias instanceof Constant) { - assignment.setLValue(new PointerDereferenceConstant((Constant) alias)); - } else { - throw new RuntimeException("Error replacing LValue variable " + lValue + " with " + alias); - } + deref.setPointer(alias); + } + } + if (lValue instanceof PointerDereferenceIndexed) { + PointerDereferenceIndexed deref = (PointerDereferenceIndexed) lValue; + RValue pointer = deref.getPointer(); + if (getAlias(aliases, pointer) != null) { + RValue alias = getAlias(aliases, pointer); + deref.setPointer( alias); + } + RValue index = deref.getIndex(); + if (getAlias(aliases, index) != null) { + RValue alias = getAlias(aliases, index); + deref.setIndex(alias); } } return null; diff --git a/src/dk/camelot64/kickc/icl/Pass3RegisterAllocation.java b/src/dk/camelot64/kickc/icl/Pass3RegisterAllocation.java index d825d2fc1..2e1315299 100644 --- a/src/dk/camelot64/kickc/icl/Pass3RegisterAllocation.java +++ b/src/dk/camelot64/kickc/icl/Pass3RegisterAllocation.java @@ -58,11 +58,13 @@ public class Pass3RegisterAllocation { allocation.allocate(symbols.getVariable("ptr#1"), new RegisterAllocation.RegisterZpPointerByte(135)); allocation.allocate(symbols.getVariable("ptr#2"), new RegisterAllocation.RegisterZpPointerByte(135)); allocation.allocate(symbols.getVariable("ptr#3"), new RegisterAllocation.RegisterZpPointerByte(135)); - allocation.allocate(symbols.getVariable("v#1"), new RegisterAllocation.RegisterZpByte(137)); - allocation.allocate(symbols.getVariable("v#2"), new RegisterAllocation.RegisterZpByte(137)); - allocation.allocate(symbols.getVariable("v#3"), new RegisterAllocation.RegisterZpByte(137)); - allocation.allocate(symbols.getVariable("v#4"), new RegisterAllocation.RegisterZpByte(137)); - allocation.allocate(symbols.getVariable("v#5"), new RegisterAllocation.RegisterZpByte(137)); + allocation.allocate(symbols.getVariable("v#1"), new RegisterAllocation.RegisterAByte()); + allocation.allocate(symbols.getVariable("v#2"), new RegisterAllocation.RegisterAByte()); + allocation.allocate(symbols.getVariable("v#3"), new RegisterAllocation.RegisterAByte()); + allocation.allocate(symbols.getVariable("v#4"), new RegisterAllocation.RegisterAByte()); + allocation.allocate(symbols.getVariable("v#5"), new RegisterAllocation.RegisterAByte()); + allocation.allocate(symbols.getVariable("$0"), new RegisterAllocation.RegisterAByte()); + symbols.setAllocation(allocation); } diff --git a/src/dk/camelot64/kickc/icl/PointerDereferenceConstant.java b/src/dk/camelot64/kickc/icl/PointerDereferenceConstant.java deleted file mode 100644 index c6c266b09..000000000 --- a/src/dk/camelot64/kickc/icl/PointerDereferenceConstant.java +++ /dev/null @@ -1,24 +0,0 @@ -package dk.camelot64.kickc.icl; - -/** A dereferenced constant pointer */ -public class PointerDereferenceConstant implements PointerDereference { - - private Constant pointer; - - public PointerDereferenceConstant(Constant pointer) { - this.pointer = pointer; - } - - public Constant getPointer() { - return pointer; - } - - public Constant getPointerConstant() { - return pointer; - } - - @Override - public String toString() { - return "*(" + pointer + ')'; - } -} diff --git a/src/dk/camelot64/kickc/icl/PointerDereferenceIndexed.java b/src/dk/camelot64/kickc/icl/PointerDereferenceIndexed.java new file mode 100644 index 000000000..c7efbc4aa --- /dev/null +++ b/src/dk/camelot64/kickc/icl/PointerDereferenceIndexed.java @@ -0,0 +1,36 @@ +package dk.camelot64.kickc.icl; + +/** A dereferenced variable pointer plus an index (used for array writes)*/ +public class PointerDereferenceIndexed implements PointerDereference { + + private RValue pointer; + + private RValue index; + + public PointerDereferenceIndexed(RValue pointer, RValue index) { + this.pointer = pointer; + this.index = index; + } + + public RValue getPointer() { + return pointer; + } + + public void setPointer(RValue pointer) { + this.pointer = pointer; + } + + public RValue getIndex() { + return index; + } + + public void setIndex(RValue index) { + this.index = index; + } + + @Override + public String toString() { + return "*(" + pointer + " + " +index + ')'; + } + +} diff --git a/src/dk/camelot64/kickc/icl/PointerDereferenceSimple.java b/src/dk/camelot64/kickc/icl/PointerDereferenceSimple.java new file mode 100644 index 000000000..3e933a9aa --- /dev/null +++ b/src/dk/camelot64/kickc/icl/PointerDereferenceSimple.java @@ -0,0 +1,24 @@ +package dk.camelot64.kickc.icl; + +/** A dereferenced pointer (based on a variable or a constant pointer)*/ +public class PointerDereferenceSimple implements PointerDereference { + + private RValue pointer; + + public PointerDereferenceSimple(Variable pointer) { + this.pointer = pointer; + } + + public RValue getPointer() { + return pointer; + } + + @Override + public String toString() { + return "*(" + pointer + ')'; + } + + public void setPointer(RValue pointer) { + this.pointer = pointer; + } +} diff --git a/src/dk/camelot64/kickc/icl/PointerDereferenceVariable.java b/src/dk/camelot64/kickc/icl/PointerDereferenceVariable.java deleted file mode 100644 index e1148a10e..000000000 --- a/src/dk/camelot64/kickc/icl/PointerDereferenceVariable.java +++ /dev/null @@ -1,28 +0,0 @@ -package dk.camelot64.kickc.icl; - -/** A dereferenced variable pointer */ -public class PointerDereferenceVariable implements PointerDereference { - - private Variable pointer; - - public PointerDereferenceVariable(Variable pointer) { - this.pointer = pointer; - } - - public Variable getPointer() { - return pointer; - } - - public Variable getPointerVariable() { - return pointer; - } - - @Override - public String toString() { - return "*(" + pointer + ')'; - } - - public void setPointerVariable(Variable pointer) { - this.pointer = pointer; - } -} diff --git a/src/dk/camelot64/kickc/icl/RegisterAllocation.java b/src/dk/camelot64/kickc/icl/RegisterAllocation.java index c46e78861..6712e35ac 100644 --- a/src/dk/camelot64/kickc/icl/RegisterAllocation.java +++ b/src/dk/camelot64/kickc/icl/RegisterAllocation.java @@ -36,7 +36,7 @@ public class RegisterAllocation { /** The register type. */ public enum RegisterType { - ZP_BYTE, ZP_BOOL, REG_Y_BYTE, REG_X_BYTE, ZP_PTR_BYTE, ZP_WORD + ZP_BYTE, ZP_BOOL, REG_A_BYTE, REG_Y_BYTE, REG_X_BYTE, ZP_PTR_BYTE, ZP_WORD } /** A zero page address used as a register for a single byte variable. */ @@ -227,6 +227,26 @@ public class RegisterAllocation { } } + /** The A register. */ + public static class RegisterAByte implements Register { + @Override + public RegisterType getType() { + return RegisterType.REG_A_BYTE; + } + + @Override + public String toString() { + return "reg byte a"; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + return true; + } + } + public static Register getRegisterX() { return new RegisterXByte(); } @@ -235,6 +255,10 @@ public class RegisterAllocation { return new RegisterYByte(); } + public static Register getRegisterA() { + return new RegisterAByte(); + } + @Override public String toString() { StringBuffer out = new StringBuffer();