diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt index f5e7511cb..ac3c97fa0 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt @@ -1027,9 +1027,10 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram, } private fun funcPokeL(fcall: PtBuiltinFunctionCall) { - val addrExpr = fcall.args[0] - val value = fcall.args[1] - TODO("pokel $addrExpr, $value") + // TODO optimize for the simple cases + asmgen.assignExpressionToRegister(fcall.args[1], RegisterOrPair.R0R1_32, true) + asmgen.assignExpressionToRegister(fcall.args[0], RegisterOrPair.AY) + asmgen.out(" jsr prog8_lib.func_pokel") } private fun funcPeekF(fcall: PtBuiltinFunctionCall, resultRegister: RegisterOrPair?) { @@ -1129,9 +1130,11 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram, } private fun funcPeekL(fcall: PtBuiltinFunctionCall, resultRegister: RegisterOrPair?) { - val addrExpr = fcall.args[0] - val value = fcall.args[1] - TODO("peekl $addrExpr, $value") + // TODO optimize for the simple cases + asmgen.assignExpressionToRegister(fcall.args[0], RegisterOrPair.AY) + asmgen.out(" jsr prog8_lib.func_peekl") + val targetReg = AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.R0R1_32, true, fcall.position, fcall.definingISub(), asmgen) + assignAsmGen.assignRegisterLong(targetReg, RegisterOrPair.R0R1_32) } @@ -1419,6 +1422,9 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram, else asmgen.out(" lda $sourceName+1 | sta cx16.$regname | lda #0 | sta cx16.$regname+1") } + in combinedLongRegisters -> { + TODO("msb into long register ${fcall.position}") + } else -> throw AssemblyError("invalid reg") } } else { @@ -1495,6 +1501,9 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram, asmgen.assignExpressionToRegister(arg, RegisterOrPair.AY) asmgen.out(" sty ${reg}L | lda #0 | sta ${reg}H | lda ${reg}L") } + in combinedLongRegisters -> { + TODO("msb into long register ${fcall.position}") + } else -> throw AssemblyError("invalid reg") } } @@ -1523,6 +1532,9 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram, else asmgen.out(" lda $sourceName | sta cx16.$regname | lda #0 | sta cx16.$regname+1") } + in combinedLongRegisters -> { + TODO("lsb into long register ${fcall.position}") + } else -> throw AssemblyError("invalid reg") } } else { @@ -1581,6 +1593,9 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram, asmgen.assignExpressionToRegister(arg, RegisterOrPair.AY) asmgen.out(" sta ${reg}L | ldy #0 | sty ${reg}H | cmp #0") } + in combinedLongRegisters -> { + TODO("lsb into long register ${fcall.position}") + } else -> throw AssemblyError("invalid reg") } } diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/PointerAssignmentsGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/PointerAssignmentsGen.kt index 2325e03c6..026263181 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/PointerAssignmentsGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/PointerAssignmentsGen.kt @@ -1669,6 +1669,9 @@ internal class PointerAssignmentsGen(private val asmgen: AsmGen6502Internal, pri lda $regname+1 pha""") } + in combinedLongRegisters -> { + TODO("save on stack long register pair") + } else -> asmgen.saveRegisterStack(regs.asCpuRegister(), false) } } @@ -1701,6 +1704,9 @@ internal class PointerAssignmentsGen(private val asmgen: AsmGen6502Internal, pri pla sta $regname""") } + in combinedLongRegisters -> { + TODO("restore from stack long register") + } else -> asmgen.restoreRegisterStack(regs.asCpuRegister(), false) } } diff --git a/compiler/res/prog8lib/prog8_funcs.asm b/compiler/res/prog8lib/prog8_funcs.asm index d8e8fd7ff..909a1e875 100644 --- a/compiler/res/prog8lib/prog8_funcs.asm +++ b/compiler/res/prog8lib/prog8_funcs.asm @@ -454,6 +454,25 @@ func_peekw .proc rts .pend +func_peekl .proc + ; -- read the ;pmg value on the address in AY, into R0:R1 + sta P8ZP_SCRATCH_W1 + sty P8ZP_SCRATCH_W1+1 + ldy #0 + lda (P8ZP_SCRATCH_W1),y + sta cx16.r0 + iny + lda (P8ZP_SCRATCH_W1),y + sta cx16.r0+1 + iny + lda (P8ZP_SCRATCH_W1),y + sta cx16.r0+2 + iny + lda (P8ZP_SCRATCH_W1),y + sta cx16.r0+3 + rts + .pend + func_pokew .proc ; -- store the word value in AY in the address in P8ZP_SCRATCH_W1 @@ -466,6 +485,22 @@ func_pokew .proc rts .pend +func_pokel .proc + ; -- store the long value in R0:R1 in the address in AY + ldy #0 + lda cx16.r0 + sta (P8ZP_SCRATCH_W1),y + iny + lda cx16.r0+1 + sta (P8ZP_SCRATCH_W1),y + iny + lda cx16.r0+2 + sta (P8ZP_SCRATCH_W1),y + iny + lda cx16.r0+3 + sta (P8ZP_SCRATCH_W1),y + rts + .pend func_clamp_byte .proc ; signed value in A, result in A diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 46fe060bb..d3de5b5ae 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -165,6 +165,7 @@ Optimizations - optimize longEqualsValue() for const and variable operands to not assign needlessly to R0-R3. - optimize optimizedBitwiseExpr() for const and variable operands to not assign needlessly to R0-R3. - optimize inplacemodificationLongWithLiteralval() for more shift values such as 8, 16, 24 etc but take sign bit into account! +- optimize simple cases in funcPeekL and funcPokeL - Port benchmarks from https://thred.github.io/c-bench-64/ to prog8 and see how it stacks up. - Since fixing the missing zp-var initialization, programs grew in size again because STZ's reappeared. Can we add more intelligent (and correct!) optimizations to remove those STZs that might be redundant again? - in Identifier: use typedarray of strings instead of listOf? Other places? diff --git a/examples/test.p8 b/examples/test.p8 index 4f70b0bd5..e7c4d91d6 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -3,136 +3,19 @@ main { sub start() { - long lv1 - long lv2 + long lv1 = 12345678 - txt.print("<\n") - lv1 = $77777777 - lv2 = $55555555 - txt.print_bool(lv1 < lv2) + txt.print_l(lv1) txt.spc() - if lv1 < lv2 - txt.print("error1 ") - else - txt.print("ok1 ") + txt.print_uw(&lv1) + txt.spc() + txt.print_l(peekl(&lv1)) txt.nl() - lv1 = $55555555 - lv2 = $55555555 - txt.print_bool(lv1 < lv2) - txt.spc() - if lv1 < lv2 - txt.print("error2 ") - else - txt.print("ok2 ") - txt.nl() + pokel(&lv1, -6666666) + sys.pushl(lv1) - lv1 = $44444444 - lv2 = $55555555 - txt.print_bool(lv1 < lv2) - txt.spc() - if lv1 < lv2 - txt.print("ok3 ") - else - txt.print("error3 ") - txt.nl() - - - - - txt.print("<=\n") - lv1 = $77777777 - lv2 = $55555555 - txt.print_bool(lv1 <= lv2) - txt.spc() - if lv1 <= lv2 - txt.print("error1 ") - else - txt.print("ok1 ") - txt.nl() - - lv1 = $55555555 - lv2 = $55555555 - txt.print_bool(lv1 <= lv2) - txt.spc() - if lv1 <= lv2 - txt.print("ok2 ") - else - txt.print("error2 ") - txt.nl() - - lv1 = $44444444 - lv2 = $55555555 - txt.print_bool(lv1 <= lv2) - txt.spc() - if lv1 <= lv2 - txt.print("ok3 ") - else - txt.print("error3 ") - txt.nl() - - - txt.print(">\n") - lv1 = $77777777 - lv2 = $55555555 - txt.print_bool(lv1 > lv2) - txt.spc() - if lv1 > lv2 - txt.print("ok1 ") - else - txt.print("error1 ") - txt.nl() - - lv1 = $55555555 - lv2 = $55555555 - txt.print_bool(lv1 > lv2) - txt.spc() - if lv1 > lv2 - txt.print("error2 ") - else - txt.print("ok2 ") - txt.nl() - - lv1 = $44444444 - lv2 = $55555555 - txt.print_bool(lv1 > lv2) - txt.spc() - if lv1 > lv2 - txt.print("error3 ") - else - txt.print("ok3 ") - txt.nl() - - - txt.print(">=\n") - lv1 = $77777777 - lv2 = $55555555 - txt.print_bool(lv1 >= lv2) - txt.spc() - if lv1 >= lv2 - txt.print("ok1 ") - else - txt.print("error1 ") - txt.nl() - - lv1 = $55555555 - lv2 = $55555555 - txt.print_bool(lv1 >= lv2) - txt.spc() - if lv1 >= lv2 - txt.print("ok2 ") - else - txt.print("error2 ") - txt.nl() - - lv1 = $44444444 - lv2 = $55555555 - txt.print_bool(lv1 >= lv2) - txt.spc() - if lv1 >= lv2 - txt.print("error3 ") - else - txt.print("ok3 ") - txt.nl() + long lv2 = sys.popl() + txt.print_l(lv2) } }