diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/IfExpressionAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/IfExpressionAsmGen.kt index 2538d2c0c..05cc8428c 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/IfExpressionAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/IfExpressionAsmGen.kt @@ -15,40 +15,27 @@ internal class IfExpressionAsmGen(private val asmgen: AsmGen6502Internal, privat val falseLabel = asmgen.makeLabel("ifexpr_false") val endLabel = asmgen.makeLabel("ifexpr_end") evalIfExpressionConditonAndBranchWhenFalse(expr.condition, falseLabel) - when { - expr.type.isByteOrBool -> { - asmgen.assignExpressionToRegister(expr.truevalue, RegisterOrPair.A) - asmgen.jmp(endLabel) - asmgen.out(falseLabel) - asmgen.assignExpressionToRegister(expr.falsevalue, RegisterOrPair.A) - asmgen.out(endLabel) - assignmentAsmGen.assignRegisterByte(target, CpuRegister.A, false, false) - } - expr.type.isWord || expr.type.isString -> { - asmgen.assignExpressionToRegister(expr.truevalue, RegisterOrPair.AY) - asmgen.jmp(endLabel) - asmgen.out(falseLabel) - asmgen.assignExpressionToRegister(expr.falsevalue, RegisterOrPair.AY) - asmgen.out(endLabel) - assignmentAsmGen.assignRegisterpairWord(target, RegisterOrPair.AY) - } - expr.type.isLong -> { - asmgen.assignExpressionToRegister(expr.truevalue, RegisterOrPair.R0R1_32, true) - asmgen.jmp(endLabel) - asmgen.out(falseLabel) - asmgen.assignExpressionToRegister(expr.falsevalue, RegisterOrPair.R0R1_32, true) - asmgen.out(endLabel) - assignmentAsmGen.assignRegisterLong(target, RegisterOrPair.R0R1_32) - } - expr.type.isFloat -> { - asmgen.assignExpressionToRegister(expr.truevalue, RegisterOrPair.FAC1, true) - asmgen.jmp(endLabel) - asmgen.out(falseLabel) - asmgen.assignExpressionToRegister(expr.falsevalue, RegisterOrPair.FAC1, true) - asmgen.out(endLabel) - asmgen.assignRegister(RegisterOrPair.FAC1, target) - } - else -> throw AssemblyError("weird dt") + + if(expr.type.isByteOrBool) { + asmgen.assignExpressionToRegister(expr.truevalue, RegisterOrPair.A) + asmgen.jmp(endLabel) + asmgen.out(falseLabel) + asmgen.assignExpressionToRegister(expr.falsevalue, RegisterOrPair.A) + asmgen.out(endLabel) + assignmentAsmGen.assignRegisterByte(target, CpuRegister.A, false, false) + } else if(expr.type.isFloat) { + asmgen.assignExpressionToRegister(expr.truevalue, RegisterOrPair.FAC1, true) + asmgen.jmp(endLabel) + asmgen.out(falseLabel) + asmgen.assignExpressionToRegister(expr.falsevalue, RegisterOrPair.FAC1, true) + asmgen.out(endLabel) + asmgen.assignRegister(RegisterOrPair.FAC1, target) + } else { + asmgen.assignExpressionTo(expr.truevalue, target) + asmgen.jmp(endLabel) + asmgen.out(falseLabel) + asmgen.assignExpressionTo(expr.falsevalue, target) + asmgen.out(endLabel) } } @@ -398,18 +385,19 @@ internal class IfExpressionAsmGen(private val asmgen: AsmGen6502Internal, privat cmp #$${hex.take(2)} bne $falseLabel""") } else { - asmgen.assignExpressionToRegister(expr, RegisterOrPair.R0R1_32) + // TODO cannot easily preserve R14:R15 on stack because we need the status flags of the comparison in between... + asmgen.assignExpressionToRegister(expr, RegisterOrPair.R14R15_32) asmgen.out(""" - lda cx16.r0 + lda cx16.r14 cmp #$${hex.substring(6, 8)} bne $falseLabel - lda cx16.r0+1 + lda cx16.r14+1 cmp #$${hex.substring(4, 6)} bne $falseLabel - lda cx16.r0+2 + lda cx16.r14+2 cmp #$${hex.substring(2, 4)} bne $falseLabel - lda cx16.r0+3 + lda cx16.r14+3 cmp #$${hex.take(2)} bne $falseLabel""") } @@ -435,18 +423,19 @@ internal class IfExpressionAsmGen(private val asmgen: AsmGen6502Internal, privat cmp $varname2+3 bne $falseLabel""") } else { - asmgen.assignExpressionToRegister(expr, RegisterOrPair.R0R1_32) + // TODO cannot easily preserve R14:R15 on stack because we need the status flags of the comparison in between... + asmgen.assignExpressionToRegister(expr, RegisterOrPair.R14R15_32) asmgen.out(""" - lda cx16.r0 + lda cx16.r14 cmp $varname2 bne $falseLabel - lda cx16.r0+1 + lda cx16.r14+1 cmp $varname2+1 bne $falseLabel - lda cx16.r0+2 + lda cx16.r14+2 cmp $varname2+2 bne $falseLabel - lda cx16.r0+3 + lda cx16.r14+3 cmp $varname2+3 bne $falseLabel""") } @@ -503,13 +492,16 @@ internal class IfExpressionAsmGen(private val asmgen: AsmGen6502Internal, privat ora $varname+3 bne $falseLabel""") } else { - asmgen.assignExpressionToRegister(expr, RegisterOrPair.R0R1_32) + asmgen.pushLongRegisters(RegisterOrPair.R14R15_32, 1) + asmgen.assignExpressionToRegister(expr, RegisterOrPair.R14R15_32) asmgen.out(""" - lda cx16.r0 - ora cx16.r0+1 - ora cx16.r0+2 - ora cx16.r0+3 - bne $falseLabel""") + lda cx16.r14 + ora cx16.r14+1 + ora cx16.r14+2 + ora cx16.r14+3 + sta P8ZP_SCRATCH_REG""") + asmgen.popLongRegisters(RegisterOrPair.R14R15_32, 1) + asmgen.out(" lda P8ZP_SCRATCH_REG | bne $falseLabel") } } @@ -525,13 +517,16 @@ internal class IfExpressionAsmGen(private val asmgen: AsmGen6502Internal, privat ora $varname+3 beq $falseLabel""") } else { - asmgen.assignExpressionToRegister(expr, RegisterOrPair.R0R1_32) + asmgen.pushLongRegisters(RegisterOrPair.R14R15_32, 1) + asmgen.assignExpressionToRegister(expr, RegisterOrPair.R14R15_32) asmgen.out(""" - lda cx16.r0 - ora cx16.r0+1 - ora cx16.r0+2 - ora cx16.r0+3 - beq $falseLabel""") + lda cx16.r14 + ora cx16.r14+1 + ora cx16.r14+2 + ora cx16.r14+3 + sta P8ZP_SCRATCH_REG""") + asmgen.popLongRegisters(RegisterOrPair.R14R15_32, 1) + asmgen.out(" lda P8ZP_SCRATCH_REG | beq $falseLabel") } } diff --git a/docs/source/todo.rst b/docs/source/todo.rst index e04da84e1..b6e8ea49a 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -2,14 +2,6 @@ TODO ==== - optimizedBitwiseExpr(): use R14:R15 instead to save copying/stack manipulation? - -- use R12-R15 as temp registers with longs instead of R0-R3 (much less chance on clobbering) - check usages of R0R1_32, because all usages of R2R3_32 have already been corrected - update/remove the warning in the docs about this - maybe reduce problem even further by storing/retrieveing the previous value of those registers? we NEED this anyway because expressions can be nested... - -- (not needed anymore if everything is saved on the stack?:) can the compiler give a warning if you use R0/R1 (or whatever the temp storage is) in expressions and/or statements together with long integers? (because R0/R1 are likely to be clobbered as temporary storage) - - implement inplaceLongAdd/Sub in PointerAssignmentGen diff --git a/docs/source/variables.rst b/docs/source/variables.rst index 52bd2f851..d6eabf1d4 100644 --- a/docs/source/variables.rst +++ b/docs/source/variables.rst @@ -250,13 +250,12 @@ to be done on word values, and don't want to explicitly have to cast everything a lot will be much slower than when you restrict yourself to 8 or 16 bit values. Use long values sparingly. .. danger:: - **longs and cx16.R0,R1,R2,R3**: - **Many operations on long values require the use of the R0 and R1 virtual register as temporary storage** - and several even R2 and R3 as well. So if you are working with long values, you should assume that the contents of R0 and R1 - (and probably R2 and R3 as well) are destroyed. - **Using R0,R1,R2,R3 in expressions that work with longs, will probably give a corrupted result, without - a warning of the compiler!** It is strongly advised to *not* use R0,R1,R2,R3 at all when dealing with longs. - *Note: this may change in the future to maybe R12-R15 instead, to reduce the chance of overwriting registers that are already used* + **longs and cx16.R12,R13,R14,R15**: + **Some operations on long values require the use of the R12-R15 virtual register as temporary storage** + So if you are working with long values, you should assume that the contents of R12-R15 could be destroyed. + ()Many operations preserve the values, but not all because of reasons) + **Using R12,R13,R14,R15 in expressions that work with longs, will sometimes give a corrupted result, without + a warning of the compiler!** It is strongly advised to *not* use R12-R15 at all when dealing with longs. Booleans diff --git a/examples/test.p8 b/examples/test.p8 index 0fa990e30..9f2eb1542 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -7,11 +7,18 @@ main { sub start() { long @shared lv, lv2 - if lv==lv2+2 - cx16.r0++ + cx16.r0L = if lv==9999 then 99 else 42 + txt.print_ub(cx16.r0L) + txt.nl() + + lv2 = if lv==9999 then 999999 else 424242 + txt.print_l(lv2) + txt.nl() + lv=9999 + lv2 = if lv==9999 then 999999 else 424242 + txt.print_l(lv2) + txt.nl() - if lv!=lv2+2 - cx16.r0++ ; long @shared lv1 = $12345678 ;