fix long if-expressions temp register usage

This commit is contained in:
Irmen de Jong
2025-10-14 02:15:15 +02:00
parent a8fd66cfdb
commit ee5d33a230
4 changed files with 68 additions and 75 deletions

View File

@@ -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 -> {
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)
}
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 -> {
} 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 -> throw AssemblyError("weird dt")
} 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")
}
}

View File

@@ -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

View File

@@ -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

View File

@@ -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
;