From d69eead6d87afc487daf5bd53fb06a9b250cc124 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Sun, 12 Oct 2025 14:06:21 +0200 Subject: [PATCH] fix abs(long), mklong(), mklong2(), peekl(), pokel() --- .../codegen/cpu6502/BuiltinFunctionsAsmGen.kt | 41 +++++++-------- .../cpu6502/assignment/AssignmentAsmGen.kt | 6 +-- compiler/res/prog8lib/prog8_funcs.asm | 50 +++++++++---------- examples/test.p8 | 40 ++++----------- 4 files changed, 59 insertions(+), 78 deletions(-) diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt index 514c02747..4a78f4090 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt @@ -887,8 +887,8 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram, assignAsmGen.assignRegisterpairWord(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.AY, false, fcall.position, scope, asmgen), RegisterOrPair.AY) } BaseDataType.LONG -> { - asmgen.out(" jsr prog8_lib.abs_l_into_R0R1") - assignAsmGen.assignRegisterLong(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.R0R1_32, true, fcall.position, scope, asmgen), RegisterOrPair.R0R1_32) + asmgen.out(" jsr prog8_lib.abs_l_into_R14R15") + assignAsmGen.assignRegisterLong(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.R14R15_32, true, fcall.position, scope, asmgen), RegisterOrPair.R14R15_32) } BaseDataType.FLOAT -> { asmgen.out(" jsr floats.func_abs_f_into_FAC1") @@ -1059,7 +1059,8 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram, asmgen.assignExpressionToRegister(fcall.args[0], RegisterOrPair.AY) asmgen.saveRegisterStack(CpuRegister.A, false) asmgen.saveRegisterStack(CpuRegister.Y, false) - asmgen.assignExpressionToRegister(fcall.args[1], RegisterOrPair.R0R1_32, true) + // it's a statement so no need to preserve R14:R15 + asmgen.assignExpressionToRegister(fcall.args[1], RegisterOrPair.R14R15_32, true) asmgen.restoreRegisterStack(CpuRegister.Y, false) asmgen.restoreRegisterStack(CpuRegister.A, false) asmgen.out(" jsr prog8_lib.func_pokel") @@ -1190,8 +1191,8 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram, // 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) + val targetReg = AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.R14R15_32, true, fcall.position, fcall.definingISub(), asmgen) + assignAsmGen.assignRegisterLong(targetReg, RegisterOrPair.R14R15_32) } @@ -1357,7 +1358,7 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram, } private fun funcMklong(fcall: PtBuiltinFunctionCall) { - // result long in R0:R1 (r0=lsw, r1=msw) + // result long in R14:R15 (r14=lsw, r15=msw) fun isArgRegister(expression: PtExpression, reg: RegisterOrPair): Boolean { if(expression !is PtIdentifier) @@ -1367,25 +1368,25 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram, if(fcall.args.size==2) { // mklong2(msw, lsw) - if(isArgRegister(fcall.args[0], RegisterOrPair.R0) || isArgRegister(fcall.args[0], RegisterOrPair.R1) || - isArgRegister(fcall.args[1], RegisterOrPair.R0) || isArgRegister(fcall.args[1], RegisterOrPair.R1)) { - error("cannot use R0 and/or R1 as arguments for mklong2 because the result should go into R0:R1 ${fcall.position}") + if(isArgRegister(fcall.args[0], RegisterOrPair.R14) || isArgRegister(fcall.args[0], RegisterOrPair.R15) || + isArgRegister(fcall.args[1], RegisterOrPair.R14) || isArgRegister(fcall.args[1], RegisterOrPair.R15)) { + error("cannot use R14 and/or R15 as arguments for mklong2 because the result should go into R0:R1 ${fcall.position}") } else { - assignAsmGen.assignExpressionToVariable(fcall.args[0], "cx16.r1", DataType.UWORD) - assignAsmGen.assignExpressionToVariable(fcall.args[1], "cx16.r0", DataType.UWORD) + assignAsmGen.assignExpressionToVariable(fcall.args[0], "cx16.r15", DataType.UWORD) + assignAsmGen.assignExpressionToVariable(fcall.args[1], "cx16.r14", DataType.UWORD) } } else { // mklong(msb, b2, b1, lsb) - if(isArgRegister(fcall.args[0], RegisterOrPair.R0) || isArgRegister(fcall.args[0], RegisterOrPair.R1) || - isArgRegister(fcall.args[1], RegisterOrPair.R0) || isArgRegister(fcall.args[1], RegisterOrPair.R1) || - isArgRegister(fcall.args[2], RegisterOrPair.R0) || isArgRegister(fcall.args[2], RegisterOrPair.R1) || - isArgRegister(fcall.args[3], RegisterOrPair.R0) || isArgRegister(fcall.args[3], RegisterOrPair.R1)) { - error("cannot use R0 and/or R1 as arguments for mklong because the result should go into R0:R1 ${fcall.position}") + if(isArgRegister(fcall.args[0], RegisterOrPair.R14) || isArgRegister(fcall.args[0], RegisterOrPair.R15) || + isArgRegister(fcall.args[1], RegisterOrPair.R14) || isArgRegister(fcall.args[1], RegisterOrPair.R15) || + isArgRegister(fcall.args[2], RegisterOrPair.R14) || isArgRegister(fcall.args[2], RegisterOrPair.R15) || + isArgRegister(fcall.args[3], RegisterOrPair.R14) || isArgRegister(fcall.args[3], RegisterOrPair.R15)) { + error("cannot use R14 and/or R15 as arguments for mklong because the result should go into R14:R15 ${fcall.position}") } else { - assignAsmGen.assignExpressionToVariable(fcall.args[0], "cx16.r1H", DataType.UBYTE) - assignAsmGen.assignExpressionToVariable(fcall.args[1], "cx16.r1L", DataType.UBYTE) - assignAsmGen.assignExpressionToVariable(fcall.args[2], "cx16.r0H", DataType.UBYTE) - assignAsmGen.assignExpressionToVariable(fcall.args[3], "cx16.r0L", DataType.UBYTE) + assignAsmGen.assignExpressionToVariable(fcall.args[0], "cx16.r15H", DataType.UBYTE) + assignAsmGen.assignExpressionToVariable(fcall.args[1], "cx16.r15L", DataType.UBYTE) + assignAsmGen.assignExpressionToVariable(fcall.args[2], "cx16.r14H", DataType.UBYTE) + assignAsmGen.assignExpressionToVariable(fcall.args[3], "cx16.r14L", DataType.UBYTE) } } } diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt index a83af52cc..cd8733393 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt @@ -655,8 +655,8 @@ internal class AssignmentAsmGen( } } returnDt== BaseDataType.LONG -> { - // longs are in R0:R1 (r0=lsw, r1=msw) - assignRegisterLong(target, RegisterOrPair.R0R1_32) + // longs are in R14:R15 (r14=lsw, r15=msw) + assignRegisterLong(target, RegisterOrPair.R14R15_32) } returnDt==BaseDataType.FLOAT -> { // float result from function sits in FAC1 @@ -3923,7 +3923,7 @@ $endLabel""") else throw AssemblyError("only combined vreg allowed as long target ${target.position}") } TargetStorageKind.ARRAY -> { - TODO("assign 32 bits int in R0:R1 into array ${target.position}") + TODO("assign 32 bits int into array ${target.position}") } TargetStorageKind.MEMORY -> throw AssemblyError("memory is bytes not long ${target.position}") TargetStorageKind.REGISTER -> { diff --git a/compiler/res/prog8lib/prog8_funcs.asm b/compiler/res/prog8lib/prog8_funcs.asm index b0fe5c4c5..2634e1835 100644 --- a/compiler/res/prog8lib/prog8_funcs.asm +++ b/compiler/res/prog8lib/prog8_funcs.asm @@ -29,33 +29,33 @@ abs_w_into_AY .proc + rts .pend -abs_l_into_R0R1 .proc - ; -- R0:R1 = abs(R0:R1) - lda cx16.r1H +abs_l_into_R14R15 .proc + ; -- R14:R15 = abs(R14:R15) + lda cx16.r15H bmi + ; Negative if high bit of highest byte is set rts + ; Invert all four bytes - lda cx16.r0L + lda cx16.r14L eor #$FF - sta cx16.r0L - lda cx16.r0H + sta cx16.r14L + lda cx16.r14H eor #$FF - sta cx16.r0H - lda cx16.r1L + sta cx16.r14H + lda cx16.r15L eor #$FF - sta cx16.r1L - lda cx16.r1H + sta cx16.r15L + lda cx16.r15H eor #$FF - sta cx16.r1H + sta cx16.r15H ; Add 1 to whole 32-bit value - inc cx16.r0L + inc cx16.r14L bne + - inc cx16.r0H + inc cx16.r14H bne + - inc cx16.r1L + inc cx16.r15L bne + - inc cx16.r1H + inc cx16.r15H + rts .pend @@ -479,22 +479,22 @@ from_scratchW1 .pend func_peekl .proc - ; -- read the ;pmg value on the address in AY, into R0:R1 + ; -- read the ;pmg value on the address in AY, into R14:R15 sta P8ZP_SCRATCH_W1 sty P8ZP_SCRATCH_W1+1 from_scratchW1 ldy #0 lda (P8ZP_SCRATCH_W1),y - sta cx16.r0 + sta cx16.r14 iny lda (P8ZP_SCRATCH_W1),y - sta cx16.r0+1 + sta cx16.r14+1 iny lda (P8ZP_SCRATCH_W1),y - sta cx16.r0+2 + sta cx16.r14+2 iny lda (P8ZP_SCRATCH_W1),y - sta cx16.r0+3 + sta cx16.r14+3 rts .pend @@ -522,20 +522,20 @@ func_pokew_scratchW2 .proc .pend func_pokel .proc - ; -- store the long value in R0:R1 in the address in AY + ; -- store the long value in R14:R15 in the address in AY sta P8ZP_SCRATCH_W1 sty P8ZP_SCRATCH_W1+1 ldy #0 - lda cx16.r0 + lda cx16.r14 sta (P8ZP_SCRATCH_W1),y iny - lda cx16.r0+1 + lda cx16.r14+1 sta (P8ZP_SCRATCH_W1),y iny - lda cx16.r0+2 + lda cx16.r14+2 sta (P8ZP_SCRATCH_W1),y iny - lda cx16.r0+3 + lda cx16.r14+3 sta (P8ZP_SCRATCH_W1),y rts .pend diff --git a/examples/test.p8 b/examples/test.p8 index 2ea660193..f281f056c 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -3,42 +3,22 @@ main { sub start() { - long @shared lv1, lv2, lv3 + long @shared lv1 = -123456 - cx16.r0 = 12345 - txt.print_l(cx16.r0) + txt.print_l(abs(lv1)) txt.spc() - cx16.r0s = -9999 - txt.print_l(cx16.r0) + + lv1 = -99999 + lv1 = abs(lv1) + txt.print_l(abs(lv1)) txt.nl() - txt.print("sgns:\n") - word @shared w1, w2, w3 - w1 = $1100 - w2 = $ff00 as word - w3 = $0000 - txt.print_b(sgn(w1)) + cx16.r4 = $1122 + cx16.r5 = $abcd + txt.print_ulhex(mklong(cx16.r5H,cx16.r5L,cx16.r4H,cx16.r4L), true) txt.spc() - txt.print_b(sgn(w2)) - txt.spc() - txt.print_b(sgn(w3)) + txt.print_ulhex(mklong2(cx16.r5,cx16.r4), true) txt.nl() - lv1= 333333 - lv2 = -22222 - lv3 = 0 - txt.print_b(sgn(lv1)) - txt.spc() - txt.print_b(sgn(lv2)) - txt.spc() - txt.print_b(sgn(lv3)) - txt.nl() - - - lv2 = 555555 - lv3 = 222222 - txt.print_bool(lv1 >= lv2+4*lv3) - - txt.nl() } }