fix 6502 casting uword and float to bool

This commit is contained in:
Irmen de Jong 2024-02-24 15:07:22 +01:00
parent f5e332daf7
commit 37b346740b
6 changed files with 96 additions and 19 deletions

View File

@ -56,8 +56,8 @@ internal class IfElseAsmGen(private val program: PtProgram,
is PtPrefix,
is PtBinaryExpression -> { /* no cmp necessary the lda has been done just prior */ }
is PtTypeCast -> {
if(condition.value.type !in ByteDatatypes)
asmgen.out(" cmp #0") // maybe can be eliminated altogether? depends on how the actual type cast is done...
if(condition.value.type !in ByteDatatypes && condition.value.type !in WordDatatypes)
asmgen.out(" cmp #0")
}
else -> asmgen.out(" cmp #0")
}

View File

@ -1550,6 +1550,8 @@ internal class AssignmentAsmGen(private val program: PtProgram,
if(targetDt in ByteDatatypes && valueDt in WordDatatypes) {
// just assign the lsb from the array value
return assignCastViaLsbFunc(value, target)
} else if(targetDt==DataType.BOOL && valueDt in WordDatatypes) {
return assignWordToBool(value, target)
}
}
else -> {}
@ -1629,9 +1631,12 @@ internal class AssignmentAsmGen(private val program: PtProgram,
RegisterOrPair.A,
RegisterOrPair.X,
RegisterOrPair.Y -> {
// cast an uword to a byte register, do this via lsb(value)
// generate code for lsb(value) here instead of the ubyte typecast
return assignCastViaLsbFunc(value, target)
return if(targetDt==DataType.BOOL)
assignWordToBool(value, target)
else
// cast an uword to a byte register, do this via lsb(value)
// generate code for lsb(value) here instead of the ubyte typecast
assignCastViaLsbFunc(value, target)
}
RegisterOrPair.AX,
RegisterOrPair.AY,
@ -1647,15 +1652,18 @@ internal class AssignmentAsmGen(private val program: PtProgram,
if(target.kind==TargetStorageKind.REGISTER) {
if(valueDt==DataType.FLOAT && target.datatype!=DataType.FLOAT) {
// have to typecast the float number on the fly down to an integer
assignExpressionToRegister(value, RegisterOrPair.FAC1, target.datatype in SignedDatatypes)
assignTypeCastedFloatFAC1("P8ZP_SCRATCH_W1", target.datatype)
assignVariableToRegister("P8ZP_SCRATCH_W1", target.register!!, target.datatype in SignedDatatypes, origTypeCastExpression.definingISub(), target.position)
assignExpressionToRegister(value, RegisterOrPair.FAC1, targetDt in SignedDatatypes)
assignTypeCastedFloatFAC1("P8ZP_SCRATCH_W1", targetDt)
assignVariableToRegister("P8ZP_SCRATCH_W1", target.register!!, targetDt in SignedDatatypes, origTypeCastExpression.definingISub(), target.position)
return
} else {
if(!(valueDt isAssignableTo targetDt)) {
return if(valueDt in WordDatatypes && targetDt in ByteDatatypes) {
// word to byte, just take the lsb
assignCastViaLsbFunc(value, target)
} else if(valueDt in WordDatatypes && targetDt==DataType.BOOL) {
// word to bool
assignWordToBool(value, target)
} else if(valueDt in WordDatatypes && targetDt in WordDatatypes) {
// word to word, just assign
assignExpressionToRegister(value, target.register!!, valueDt in SignedDatatypes)
@ -1742,12 +1750,24 @@ internal class AssignmentAsmGen(private val program: PtProgram,
translateNormalAssignment(assign, value.definingISub())
}
private fun assignWordToBool(value: PtExpression, target: AsmAssignTarget) {
assignExpressionToRegister(value, RegisterOrPair.AY, false)
asmgen.out("""
sty P8ZP_SCRATCH_REG
ora P8ZP_SCRATCH_REG
beq +
lda #1
+""")
assignRegisterByte(target, CpuRegister.A, false, false)
}
private fun assignTypeCastedFloatFAC1(targetAsmVarName: String, targetDt: DataType) {
if(targetDt==DataType.FLOAT)
throw AssemblyError("typecast to identical type")
when(targetDt) {
DataType.BOOL -> asmgen.out(" jsr floats.cast_FAC1_as_bool_into_a | sta $targetAsmVarName")
DataType.UBYTE -> asmgen.out(" jsr floats.cast_FAC1_as_uw_into_ya | sty $targetAsmVarName")
DataType.BYTE -> asmgen.out(" jsr floats.cast_FAC1_as_w_into_ay | sta $targetAsmVarName")
DataType.UWORD -> asmgen.out(" jsr floats.cast_FAC1_as_uw_into_ya | sty $targetAsmVarName | sta $targetAsmVarName+1")
@ -1796,7 +1816,7 @@ internal class AssignmentAsmGen(private val program: PtProgram,
}
DataType.BYTE -> {
when(targetDt) {
DataType.UBYTE -> {
DataType.UBYTE, DataType.BOOL -> {
asmgen.out(" lda $sourceAsmVarName | sta $targetAsmVarName")
}
DataType.UWORD -> {
@ -1823,6 +1843,14 @@ internal class AssignmentAsmGen(private val program: PtProgram,
}
DataType.UWORD -> {
when(targetDt) {
DataType.BOOL -> {
asmgen.out("""
lda $sourceAsmVarName
ora $sourceAsmVarName+1
beq +
lda #1
+ sta $targetAsmVarName""")
}
DataType.BYTE, DataType.UBYTE -> {
asmgen.out(" lda $sourceAsmVarName | sta $targetAsmVarName")
}
@ -1844,6 +1872,14 @@ internal class AssignmentAsmGen(private val program: PtProgram,
}
DataType.WORD -> {
when(targetDt) {
DataType.BOOL -> {
asmgen.out("""
lda $sourceAsmVarName
ora $sourceAsmVarName+1
beq +
lda #1
+ sta $targetAsmVarName""")
}
DataType.BYTE, DataType.UBYTE -> {
asmgen.out(" lda $sourceAsmVarName | sta $targetAsmVarName")
}
@ -1866,6 +1902,7 @@ internal class AssignmentAsmGen(private val program: PtProgram,
DataType.FLOAT -> {
asmgen.out(" lda #<$sourceAsmVarName | ldy #>$sourceAsmVarName")
when(targetDt) {
DataType.BOOL -> asmgen.out(" jsr floats.cast_as_bool_into_a | sta $targetAsmVarName")
DataType.UBYTE -> asmgen.out(" jsr floats.cast_as_uw_into_ya | sty $targetAsmVarName")
DataType.BYTE -> asmgen.out(" jsr floats.cast_as_w_into_ay | sta $targetAsmVarName")
DataType.UWORD -> asmgen.out(" jsr floats.cast_as_uw_into_ya | sty $targetAsmVarName | sta $targetAsmVarName+1")

View File

@ -98,6 +98,21 @@ cast_as_w_into_ay .proc ; also used for float 2 b
jmp cast_FAC1_as_w_into_ay
.pend
cast_as_bool_into_a .proc
; -- cast float at A/Y to bool into A
; clobbers X
jsr MOVFM
jmp cast_FAC1_as_bool_into_a
.pend
cast_FAC1_as_bool_into_a .proc
; -- cast fac1 to bool into A
; clobbers X
jsr SIGN
and #1
rts
.pend
cast_FAC1_as_uw_into_ya .proc ; also used for float 2 ub
; -- cast fac1 to uword into Y/A
; clobbers X

View File

@ -1,4 +1,5 @@
# generates various Prog8 files with a huge amount of number equality tests.
# generates various Prog8 files with a large amount of number equality tests,
# using various forms of the if statement (because these forms have their own code gen paths)
import sys

View File

@ -1,7 +1,8 @@
TODO
====
fix 6502 casting uword to bool (don't take only the lsb!)
retest all comparisons in if statements (byte, word, signed and unsigned) + all comparison assignments. Against 0 and something else as 0.
with jump, indirect jump, no else block, and both if+else blocks.
fix "wordGreaterValue"
@ -64,9 +65,6 @@ ok . check program sizes vs. master branch
===== ====== =======
retest all comparisons in if statements (byte, word, signed and unsigned) + all comparison assignments. Against 0 and something else as 0.
with jump, indirect jump, no else block, and both if+else blocks.
check that the flood fill routine in gfx2 and paint still works.
re-allow typecast of const true/false back to ubytes 1 and 0?
re-allow typecast of const ubyte 0/1 to false/true boolean?

View File

@ -6,15 +6,41 @@
main {
sub start() {
cx16.r0 = $2200
float @shared fl = 1123.56
if cx16.r0L as bool
cx16.r0L++
if fl as bool
txt.print("yep ")
else
txt.print("nope ")
bool @shared qq = fl as bool
if qq
txt.print("yep ")
else
txt.print("nope ")
if cx16.r0 as bool
cx16.r0L++
txt.print("yep ")
else
txt.print("nope ")
if @(cx16.r0) as bool
cx16.r0L++
qq = cx16.r0 as bool
if qq
txt.print("yep ")
else
txt.print("nope ")
if cx16.r0s as bool
txt.print("yep ")
else
txt.print("nope ")
qq = cx16.r0s as bool
if qq
txt.print("yep ")
else
txt.print("nope ")
; test_stack.test()
; broken_word_gt()