From 5fe6aa2800fb32000198984f17568cc698be3da7 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Fri, 3 Jun 2022 23:13:35 +0200 Subject: [PATCH] fix swap() code for pointervars --- .../codegen/cpu6502/BuiltinFunctionsAsmGen.kt | 91 ++++++++++++++++--- examples/test.p8 | 85 +++++++++++++---- 2 files changed, 145 insertions(+), 31 deletions(-) diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt index e9508ee27..5abf3b414 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt @@ -710,6 +710,11 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, val first = fcall.args[0] val second = fcall.args[1] + val arrayVarDecl1 = (first as? ArrayIndexedExpression)?.arrayvar?.targetVarDecl(program) + val arrayVarDecl2 = (second as? ArrayIndexedExpression)?.arrayvar?.targetVarDecl(program) + if((arrayVarDecl1!=null && !arrayVarDecl1.isArray) || (arrayVarDecl2!=null && !arrayVarDecl2.isArray)) + throw AssemblyError("no asm gen for swapping bytes to and/or from indexed pointer var ${fcall.position}") + // optimized simple case: swap two variables if(first is IdentifierReference && second is IdentifierReference) { val firstName = asmgen.asmVariableName(first) @@ -787,11 +792,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, ) { if(firstOffset is NumericLiteral && secondOffset is NumericLiteral) { if(firstOffset!=secondOffset) { - swapArrayValues( - DataType.UBYTE, - asmgen.asmVariableName(pointerVariable), firstOffset, - asmgen.asmVariableName(pointerVariable), secondOffset - ) + swapArrayBytesViaPointers(pointerVariable, firstOffset, pointerVariable, secondOffset) return } } else if(firstOffset is TypecastExpression && secondOffset is TypecastExpression) { @@ -800,11 +801,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, val secondOffsetVar = secondOffset.expression as? IdentifierReference if(firstOffsetVar!=null && secondOffsetVar!=null) { if(firstOffsetVar!=secondOffsetVar) { - swapArrayValues( - DataType.UBYTE, - asmgen.asmVariableName(pointerVariable), firstOffsetVar, - asmgen.asmVariableName(pointerVariable), secondOffsetVar - ) + swapArrayBytesViaPointers(pointerVariable, firstOffsetVar, pointerVariable, secondOffsetVar) return } } @@ -829,16 +826,16 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, val secondNum = second.indexer.indexExpr as? NumericLiteral val secondVar = second.indexer.indexExpr as? IdentifierReference - if(firstNum!=null && secondNum!=null) { + if (firstNum != null && secondNum != null) { swapArrayValues(elementDt, arrayVarName1, firstNum, arrayVarName2, secondNum) return - } else if(firstVar!=null && secondVar!=null) { + } else if (firstVar != null && secondVar != null) { swapArrayValues(elementDt, arrayVarName1, firstVar, arrayVarName2, secondVar) return - } else if(firstNum!=null && secondVar!=null) { + } else if (firstNum != null && secondVar != null) { swapArrayValues(elementDt, arrayVarName1, firstNum, arrayVarName2, secondVar) return - } else if(firstVar!=null && secondNum!=null) { + } else if (firstVar != null && secondNum != null) { swapArrayValues(elementDt, arrayVarName1, firstVar, arrayVarName2, secondNum) return } @@ -895,6 +892,72 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, } } + private fun swapArrayBytesViaPointers( + firstZpPtr: IdentifierReference, + firstOffset: NumericLiteral, + secondZpPtr: IdentifierReference, + secondOffset: NumericLiteral + ) { + var firstZpPtrName = asmgen.asmSymbolName(firstZpPtr) + if(!asmgen.isZpVar(firstZpPtr)) { + asmgen.out(" lda $firstZpPtrName | sta P8ZP_SCRATCH_W1") + asmgen.out(" lda $firstZpPtrName+1 | sta P8ZP_SCRATCH_W1+1") + firstZpPtrName = "P8ZP_SCRATCH_W1" + } + var secondZpPtrName = asmgen.asmSymbolName(secondZpPtr) + if(!asmgen.isZpVar(secondZpPtr)) { + asmgen.out(" lda $secondZpPtrName | sta P8ZP_SCRATCH_W2") + asmgen.out(" lda $secondZpPtrName+1 | sta P8ZP_SCRATCH_W2+1") + secondZpPtrName = "P8ZP_SCRATCH_W2" + } + asmgen.out(""" + ldy #${firstOffset.number.toInt()} + lda ($firstZpPtrName),y + pha + ldy #${secondOffset.number.toInt()} + lda ($secondZpPtrName),y + ldy #${firstOffset.number.toInt()} + sta ($firstZpPtrName),y + pla + ldy #${secondOffset.number.toInt()} + sta ($secondZpPtrName),y + """) + } + + private fun swapArrayBytesViaPointers( + firstZpPtr: IdentifierReference, + index1Var: IdentifierReference, + secondZpPtr: IdentifierReference, + index2Var: IdentifierReference + ) { + var firstZpPtrName = asmgen.asmSymbolName(firstZpPtr) + if(!asmgen.isZpVar(firstZpPtr)) { + asmgen.out(" lda $firstZpPtrName | sta P8ZP_SCRATCH_W1") + asmgen.out(" lda $firstZpPtrName+1 | sta P8ZP_SCRATCH_W1+1") + firstZpPtrName = "P8ZP_SCRATCH_W1" + } + var secondZpPtrName = asmgen.asmSymbolName(secondZpPtr) + if(!asmgen.isZpVar(secondZpPtr)) { + asmgen.out(" lda $secondZpPtrName | sta P8ZP_SCRATCH_W2") + asmgen.out(" lda $secondZpPtrName+1 | sta P8ZP_SCRATCH_W2+1") + secondZpPtrName = "P8ZP_SCRATCH_W2" + } + val index1Name = asmgen.asmVariableName(index1Var) + val index2Name = asmgen.asmVariableName(index2Var) + asmgen.out(""" + ldy $index1Name + lda ($firstZpPtrName),y + pha + ldy $index2Name + lda ($secondZpPtrName),y + ldy $index1Name + sta ($firstZpPtrName),y + pla + ldy $index2Name + sta ($secondZpPtrName),y + """) + } + private fun swapArrayValues(elementDt: DataType, arrayVarName1: String, indexValue1: NumericLiteral, arrayVarName2: String, indexValue2: NumericLiteral) { val index1 = indexValue1.number.toInt() * program.memsizer.memorySize(elementDt) val index2 = indexValue2.number.toInt() * program.memsizer.memorySize(elementDt) diff --git a/examples/test.p8 b/examples/test.p8 index 366dd1cef..761c02fa6 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -1,5 +1,5 @@ %import textio -%zeropage basicsafe +%zeropage dontuse ; NOTE: meant to test to virtual machine output target (use -target vitual) @@ -31,27 +31,78 @@ main { sub start() { ; mcCarthy() - ubyte[20] sieve - uword count=0 - if count < 256 - txt.print("<256 ok! 1\n") - if count > 256 - txt.print(">256 nok! 2\n") - count=257 - if count < 256 - txt.print("<256 nok! 3\n") - if count > 256 - txt.print(">256 ok! 4\n") - count=256 + ubyte value = 0 + ubyte size = 9 + ubyte[10] data = [11,22,33,4,5,6,7,8,9,10] + uword bitmapbuf = &data - count=0 - while count < 256 { ; TODO fix this while loop - txt.print_uw(count) +; ; 11 22 33 +; txt.print_ub(bitmapbuf[0]) +; txt.spc() +; txt.print_ub(bitmapbuf[1]) +; txt.spc() +; txt.print_ub(bitmapbuf[2]) +; txt.nl() +; rol(bitmapbuf[0]) +; rol(bitmapbuf[0]) +; txt.print_ub(bitmapbuf[0]) ; 44 +; txt.spc() +; ror(bitmapbuf[0]) +; ror(bitmapbuf[0]) +; txt.print_ub(bitmapbuf[0]) ; 11 +; txt.nl() +; +; ; 22 44 66 +; txt.print_ub(bitmapbuf[0]*2) +; txt.spc() +; txt.print_ub(bitmapbuf[1]*2) +; txt.spc() +; txt.print_ub(bitmapbuf[2]*2) +; txt.nl() + + ubyte one = 1 + + bitmapbuf[0] = one + bitmapbuf[1] = one+one + bitmapbuf[2] = one+one+one + bitmapbuf[2] += 4 + bitmapbuf[2] -= 2 + bitmapbuf[2] -= 2 + swap(bitmapbuf[0], bitmapbuf[1]) + + ; 1 2 3 + txt.print_ub(bitmapbuf[0]) + txt.spc() + txt.print_ub(bitmapbuf[1]) + txt.spc() + txt.print_ub(bitmapbuf[2]) + txt.nl() + + for value in data { + txt.print_ub(value) txt.spc() - count += 10 } txt.nl() + ; TODO why is this loop much larger in code than the one below. + value = 0 + ubyte xx + for xx in 0 to size-1 { + value += bitmapbuf[xx] + } + txt.print_ub(value) ; 45 + txt.nl() + + ; TODO this one is much more compact + value = 0 + uword srcptr = bitmapbuf + repeat size { + value += @(srcptr) + srcptr++ + } + txt.print_ub(value) ; 45 + txt.nl() + ; ; a "pixelshader": ; sys.gfx_enable(0) ; enable lo res screen ; ubyte shifter