diff --git a/src/main/fragment/pwuc1_derefidx_vbuxx=pwuc1_derefidx_vbuxx_plus_vwuc2.asm b/src/main/fragment/pwuc1_derefidx_vbuxx=pwuc1_derefidx_vbuxx_plus_vwuc2.asm new file mode 100644 index 000000000..6d2451a41 --- /dev/null +++ b/src/main/fragment/pwuc1_derefidx_vbuxx=pwuc1_derefidx_vbuxx_plus_vwuc2.asm @@ -0,0 +1,7 @@ +clc +lda {c1},x +adc #<{c2} +sta {c1},x +lda {c1}+1,x +adc #>{c2} +sta {c1}+1,x diff --git a/src/main/fragment/pwuc1_derefidx_vbuyy=pwuc1_derefidx_vbuyy_plus_vwuc2.asm b/src/main/fragment/pwuc1_derefidx_vbuyy=pwuc1_derefidx_vbuyy_plus_vwuc2.asm new file mode 100644 index 000000000..3d1bb4033 --- /dev/null +++ b/src/main/fragment/pwuc1_derefidx_vbuyy=pwuc1_derefidx_vbuyy_plus_vwuc2.asm @@ -0,0 +1,7 @@ +clc +lda {c1},y +adc #<{c2} +sta {c1},y +lda {c1}+1,y +adc #>{c2} +sta {c1}+1,y diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java index 2df185b12..866a73214 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java @@ -1162,11 +1162,26 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor { String op = ((TerminalNode) ctx.getChild(1)).getSymbol().getText(); Operator operator = Operators.getBinaryCompound(op); // Assignment with operator - Statement stmt = new StatementAssignment(lValue, lValue, operator, rValue, new StatementSource(ctx), ensureUnusedComments(getCommentsSymbol(ctx))); + LValue rValue1 = copyLValue(lValue); + Statement stmt = new StatementAssignment(lValue, rValue1, operator, rValue, new StatementSource(ctx), ensureUnusedComments(getCommentsSymbol(ctx))); sequence.addStatement(stmt); return lValue; } + private LValue copyLValue(LValue lValue) { + if(lValue instanceof VariableRef) { + return new VariableRef(((VariableRef) lValue).getFullName()); + } else if(lValue instanceof LvalueIntermediate) { + return new LvalueIntermediate((VariableRef) copyLValue(((LvalueIntermediate) lValue).getVariable())); + } else if(lValue instanceof PointerDereferenceSimple) { + return new PointerDereferenceSimple(((PointerDereferenceSimple) lValue).getPointer()); + } else if(lValue instanceof PointerDereferenceIndexed) { + return new PointerDereferenceIndexed(((PointerDereferenceIndexed) lValue).getPointer(), ((PointerDereferenceIndexed) lValue).getIndex()); + } else { + throw new CompileError("Unknown LValue type "+lValue); + } + } + @Override public RValue visitExprCast(KickCParser.ExprCastContext ctx) { RValue child = (RValue) this.visit(ctx.expr()); diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass1PointerSizeofFix.java b/src/main/java/dk/camelot64/kickc/passes/Pass1PointerSizeofFix.java index df234d431..ebef5d865 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass1PointerSizeofFix.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass1PointerSizeofFix.java @@ -14,9 +14,10 @@ import dk.camelot64.kickc.model.types.SymbolType; import dk.camelot64.kickc.model.types.SymbolTypePointer; import dk.camelot64.kickc.model.values.ConstantRef; import dk.camelot64.kickc.model.values.PointerDereferenceIndexed; +import dk.camelot64.kickc.model.values.RValue; import dk.camelot64.kickc.model.values.VariableRef; -import java.util.ListIterator; +import java.util.*; /** * Fixes pointer math to use sizeof(type) @@ -44,6 +45,9 @@ public class Pass1PointerSizeofFix extends Pass1Base { } } + // For each statement maps RValues used as index to the new *2 variable created + Map> handled = new LinkedHashMap<>(); + ProgramValueIterator.execute(getProgram(), (programValue, currentStmt, stmtIt, currentBlock) -> { if(programValue.get() instanceof PointerDereferenceIndexed) { PointerDereferenceIndexed deref = (PointerDereferenceIndexed) programValue.get(); @@ -54,13 +58,20 @@ public class Pass1PointerSizeofFix extends Pass1Base { if(pointerType.getElementType().getSizeBytes() > 1) { // Array-indexing into a non-byte pointer - multiply by sizeof() getLog().append("Fixing pointer array-indexing " + deref.toString(getProgram())); - VariableIntermediate tmpVar = getScope().getScope(currentBlock.getScope()).addVariableIntermediate(); - tmpVar.setType(SymbolType.BYTE); - stmtIt.remove(); - ConstantRef sizeOfTargetType = OperatorSizeOf.getSizeOfConstantVar(getProgram().getScope(), pointerType.getElementType()); - stmtIt.add(new StatementAssignment(tmpVar.getRef(), deref.getIndex(), Operators.MULTIPLY, sizeOfTargetType, currentStmt.getSource(), Comment.NO_COMMENTS)); - stmtIt.add(currentStmt); - deref.setIndex(tmpVar.getRef()); + VariableRef idx2VarRef = handled.getOrDefault(currentStmt, new LinkedHashMap<>()).get(deref.getIndex()); + if(idx2VarRef==null) { + VariableIntermediate idx2Var = getScope().getScope(currentBlock.getScope()).addVariableIntermediate(); + idx2Var.setType(SymbolType.BYTE); + ConstantRef sizeOfTargetType = OperatorSizeOf.getSizeOfConstantVar(getProgram().getScope(), pointerType.getElementType()); + StatementAssignment idx2 = new StatementAssignment(idx2Var.getRef(), deref.getIndex(), Operators.MULTIPLY, sizeOfTargetType, currentStmt.getSource(), Comment.NO_COMMENTS); + stmtIt.previous(); + stmtIt.add(idx2); + stmtIt.next(); + idx2VarRef = idx2Var.getRef(); + handled.putIfAbsent(currentStmt, new LinkedHashMap<>()); + handled.get(currentStmt).put(deref.getIndex(), idx2VarRef); + } + deref.setIndex(idx2VarRef); } } } diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index 3e85fbc2f..32d31856e 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -37,6 +37,11 @@ public class TestPrograms { // compileAndCompare("pointer-cast-3"); //} + @Test + public void testWordPointerCompound() throws IOException, URISyntaxException { + compileAndCompare("word-pointer-compound"); + } + @Test public void testWordPointerMath() throws IOException, URISyntaxException { compileAndCompare("word-pointer-math"); diff --git a/src/test/kc/word-pointer-compound.kc b/src/test/kc/word-pointer-compound.kc new file mode 100644 index 000000000..741ed04b7 --- /dev/null +++ b/src/test/kc/word-pointer-compound.kc @@ -0,0 +1,22 @@ +// Test word pointer compound assignment + +void main() { + word[] words = { $3031, $3233, $3435 }; + + for( byte i: 0..2) { + words[i] += $0101; + } + + const byte* SCREEN = $0400; + + SCREEN[0] = >words[0]; + SCREEN[1] = words[1]; + SCREEN[3] = words[2]; + SCREEN[5] =