ifelse more

This commit is contained in:
Irmen de Jong 2024-02-20 00:35:13 +01:00
parent e1a133c2c0
commit 7868e672e0
4 changed files with 557 additions and 44 deletions

View File

@ -402,25 +402,538 @@ internal class IfElseAsmGen(private val program: PtProgram,
}
private fun wordLessValue(left: PtExpression, right: PtExpression, signed: Boolean, jump: PtJump?, stmt: PtIfElse) {
println("word if <") // TODO
fallbackTranslate(stmt)
fun code(valueLsb: String, valueMsb: String) {
if(signed) {
if(jump!=null) {
val (asmLabel, indirect) = asmgen.getJumpTarget(jump)
if(indirect) {
asmgen.out("""
cmp $valueLsb
tya
sbc $valueMsb
bvs +
eor #128
+ bpl +
jmp ($asmLabel)
+""")
} else {
asmgen.out("""
cmp $valueLsb
tya
sbc $valueMsb
bvc +
eor #128
+ bmi $asmLabel""")
}
} else {
val afterIfLabel = asmgen.makeLabel("afterif")
if(stmt.hasElse()) {
// if and else blocks
val elseLabel = asmgen.makeLabel("else")
asmgen.out("""
cmp $valueLsb
tya
sbc $valueMsb
bvs +
eor #128
+ bmi $elseLabel""")
asmgen.translate(stmt.ifScope)
asmgen.jmp(afterIfLabel, false)
asmgen.out(elseLabel)
asmgen.translate(stmt.elseScope)
} else {
// no else block
asmgen.out("""
cmp $valueLsb
tya
sbc $valueMsb
bvs +
eor #128
+ bmi $afterIfLabel""")
asmgen.translate(stmt.ifScope)
}
asmgen.out(afterIfLabel)
}
} else {
if(jump!=null) {
val (asmLabel, indirect) = asmgen.getJumpTarget(jump)
if(indirect) {
asmgen.out("""
cmp $valueLsb
tya
sbc $valueMsb
bcc +
jmp ($asmLabel)
+""")
} else {
asmgen.out("""
cmp $valueLsb
tya
sbc $valueMsb
bcc $asmLabel""")
}
} else {
val afterIfLabel = asmgen.makeLabel("afterif")
if(stmt.hasElse()) {
// if and else blocks
val elseLabel = asmgen.makeLabel("else")
asmgen.out("""
cmp $valueLsb
tya
sbc $valueMsb
bcs $elseLabel""")
asmgen.translate(stmt.ifScope)
asmgen.jmp(afterIfLabel, false)
asmgen.out(elseLabel)
asmgen.translate(stmt.elseScope)
} else {
// no else block
asmgen.out("""
cmp $valueLsb
tya
sbc $valueMsb
bcs $afterIfLabel""")
asmgen.translate(stmt.ifScope)
}
asmgen.out(afterIfLabel)
}
}
}
if(right is PtNumber) {
asmgen.assignExpressionToRegister(left, RegisterOrPair.AY, signed)
val number = right.number.toHex()
return code("#<$number", "#>$number")
}
if(right is PtIdentifier) {
asmgen.assignExpressionToRegister(left, RegisterOrPair.AY, signed)
val variable = asmgen.asmVariableName(right)
return code("#<$variable", "#>$variable")
}
// TODO optimize for simple array value
// generic case via scratch register
asmgen.assignWordOperandsToAYAndVar(left, right, "P8ZP_SCRATCH_W2")
code("P8ZP_SCRATCH_W2", "P8ZP_SCRATCH_W2+1")
}
private fun wordGreaterValue(left: PtExpression, right: PtExpression, signed: Boolean, jump: PtJump?, stmt: PtIfElse) {
println("word if >") // TODO
fallbackTranslate(stmt)
fun code(valueLsb: String, valueMsb: String) {
if(signed) {
if(jump!=null) {
val (asmLabel, indirect) = asmgen.getJumpTarget(jump)
if(indirect) {
asmgen.out("""
sta P8ZP_SCRATCH_W1
sty P8ZP_SCRATCH_W1+1
ldy $valueLsb
lda $valueMsb
cpy P8ZP_SCRATCH_W1
sbc P8ZP_SCRATCH_W1+1
bvc +
eor #128
+ bmi +
jmp ($asmLabel)
+""")
} else {
asmgen.out("""
sta P8ZP_SCRATCH_W1
sty P8ZP_SCRATCH_W1+1
ldy $valueLsb
lda $valueMsb
cpy P8ZP_SCRATCH_W1
sbc P8ZP_SCRATCH_W1+1
bvc +
eor #128
+ bpl $asmLabel""")
}
} else {
val afterIfLabel = asmgen.makeLabel("afterif")
if(stmt.hasElse()) {
// if and else blocks
val elseLabel = asmgen.makeLabel("else")
asmgen.out("""
sta P8ZP_SCRATCH_W1
sty P8ZP_SCRATCH_W1+1
ldy $valueLsb
lda $valueMsb
cpy P8ZP_SCRATCH_W1
sbc P8ZP_SCRATCH_W1+1
bvc +
eor #128
+ bmi $elseLabel""")
asmgen.translate(stmt.ifScope)
asmgen.jmp(afterIfLabel, false)
asmgen.out(elseLabel)
asmgen.translate(stmt.elseScope)
} else {
// no else block
asmgen.out("""
sta P8ZP_SCRATCH_W1
sty P8ZP_SCRATCH_W1+1
ldy $valueLsb
lda $valueMsb
cpy P8ZP_SCRATCH_W1
sbc P8ZP_SCRATCH_W1+1
bvc +
eor #128
+ bmi $afterIfLabel""")
asmgen.translate(stmt.ifScope)
}
asmgen.out(afterIfLabel)
}
} else {
if(jump!=null) {
val (asmLabel, indirect) = asmgen.getJumpTarget(jump)
if(indirect) {
asmgen.out("""
cpy $valueMsb
beq +
bcc _gt
bcs _not
+ cmp $valueLsb
bcc _gt
bne _not
_gt jmp ($asmLabel)
_not""")
} else {
asmgen.out("""
sec
sbc $valueLsb
sta P8ZP_SCRATCH_REG
tya
sbc $valueMsb
ora P8ZP_SCRATCH_REG
beq +
bcs $asmLabel
+""")
}
} else {
val afterIfLabel = asmgen.makeLabel("afterif")
if(stmt.hasElse()) {
// if and else blocks
val elseLabel = asmgen.makeLabel("else")
asmgen.out("""
cpy $valueMsb
beq +
bcc _gt
bcs $elseLabel
+ cmp $valueLsb
bcc _gt
bne $elseLabel
_gt""")
asmgen.translate(stmt.ifScope)
asmgen.jmp(afterIfLabel, false)
asmgen.out(elseLabel)
asmgen.translate(stmt.elseScope)
} else {
// no else block
asmgen.out("""
cpy $valueMsb
beq +
bcc _gt
bcs $afterIfLabel
+ cmp $valueLsb
bcc _gt
bne $afterIfLabel
_gt""")
asmgen.translate(stmt.ifScope)
}
asmgen.out(afterIfLabel)
}
}
}
if(right is PtNumber) {
asmgen.assignExpressionToRegister(left, RegisterOrPair.AY, signed)
val number = right.number.toHex()
return code("#<$number", "#>$number")
}
if(right is PtIdentifier) {
asmgen.assignExpressionToRegister(left, RegisterOrPair.AY, signed)
val variable = asmgen.asmVariableName(right)
return code("#<$variable", "#>$variable")
}
// TODO optimize for simple array value
// generic case via scratch register
asmgen.assignWordOperandsToAYAndVar(left, right, "P8ZP_SCRATCH_W2")
code("P8ZP_SCRATCH_W2", "P8ZP_SCRATCH_W2+1")
}
private fun wordLessEqualsValue(left: PtExpression, right: PtExpression, signed: Boolean, jump: PtJump?, stmt: PtIfElse) {
println("word if <=") // TODO
fallbackTranslate(stmt)
fun code(valueLsb: String, valueMsb: String) {
if(signed) {
if(jump!=null) {
val (asmLabel, indirect) = asmgen.getJumpTarget(jump)
if(indirect) {
asmgen.out("""
sta P8ZP_SCRATCH_W1
sty P8ZP_SCRATCH_W1+1
ldy $valueLsb
lda $valueMsb
cpy P8ZP_SCRATCH_W1
sbc P8ZP_SCRATCH_W1+1
bvc +
eor #128
+ bmi +
jmp ($asmLabel)
+""")
} else {
asmgen.out("""
sta P8ZP_SCRATCH_W1
sty P8ZP_SCRATCH_W1+1
ldy $valueLsb
lda $valueMsb
cpy P8ZP_SCRATCH_W1
sbc P8ZP_SCRATCH_W1+1
bvc +
eor #128
+ bpl $asmLabel""")
}
} else {
val afterIfLabel = asmgen.makeLabel("afterif")
if(stmt.hasElse()) {
// if and else blocks
val elseLabel = asmgen.makeLabel("else")
asmgen.out("""
sta P8ZP_SCRATCH_W1
sty P8ZP_SCRATCH_W1+1
ldy $valueLsb
lda $valueMsb
cpy P8ZP_SCRATCH_W1
sbc P8ZP_SCRATCH_W1+1
bvc +
eor #128
+ bmi $elseLabel""")
asmgen.translate(stmt.ifScope)
asmgen.jmp(afterIfLabel, false)
asmgen.out(elseLabel)
asmgen.translate(stmt.elseScope)
} else {
// no else block
asmgen.out("""
sta P8ZP_SCRATCH_W1
sty P8ZP_SCRATCH_W1+1
ldy $valueLsb
lda $valueMsb
cpy P8ZP_SCRATCH_W1
sbc P8ZP_SCRATCH_W1+1
bvc +
eor #128
+ bmi $afterIfLabel""")
asmgen.translate(stmt.ifScope)
}
asmgen.out(afterIfLabel)
}
} else {
if(jump!=null) {
val (asmLabel, indirect) = asmgen.getJumpTarget(jump)
if(indirect) {
asmgen.out("""
sec
sbc $valueLsb
sta P8ZP_SCRATCH_REG
tya
sbc $valueMsb
ora P8ZP_SCRATCH_REG
beq +
bcc +
jmp $(asmLabel)
+""")
} else {
asmgen.out("""
sec
sbc $valueLsb
sta P8ZP_SCRATCH_REG
tya
sbc $valueMsb
ora P8ZP_SCRATCH_REG
beq +
bcs $asmLabel
+""")
}
} else {
val afterIfLabel = asmgen.makeLabel("afterif")
if(stmt.hasElse()) {
// if and else blocks
val elseLabel = asmgen.makeLabel("else")
asmgen.out("""
sec
sbc $valueLsb
sta P8ZP_SCRATCH_REG
tya
sbc $valueMsb
ora P8ZP_SCRATCH_REG
beq +
bcc $elseLabel
+""")
asmgen.translate(stmt.ifScope)
asmgen.jmp(afterIfLabel, false)
asmgen.out(elseLabel)
asmgen.translate(stmt.elseScope)
} else {
// no else block
asmgen.out("""
sec
sbc $valueLsb
sta P8ZP_SCRATCH_REG
tya
sbc $valueMsb
ora P8ZP_SCRATCH_REG
beq +
bcc $afterIfLabel
+""")
asmgen.translate(stmt.ifScope)
}
asmgen.out(afterIfLabel)
}
}
}
if(right is PtNumber) {
asmgen.assignExpressionToRegister(left, RegisterOrPair.AY, signed)
val number = right.number.toHex()
return code("#<$number", "#>$number")
}
if(right is PtIdentifier) {
asmgen.assignExpressionToRegister(left, RegisterOrPair.AY, signed)
val variable = asmgen.asmVariableName(right)
return code("#<$variable", "#>$variable")
}
// TODO optimize for simple array value
// generic case via scratch register
asmgen.assignWordOperandsToAYAndVar(left, right, "P8ZP_SCRATCH_W2")
code("P8ZP_SCRATCH_W2", "P8ZP_SCRATCH_W2+1")
}
private fun wordGreaterEqualsValue(left: PtExpression, right: PtExpression, signed: Boolean, jump: PtJump?, stmt: PtIfElse) {
println("word if >=") // TODO
fallbackTranslate(stmt)
fun code(valueLsb: String, valueMsb: String) {
if(signed) {
if(jump!=null) {
val (asmLabel, indirect) = asmgen.getJumpTarget(jump)
if(indirect) {
asmgen.out("""
cmp $valueLsb
tya
sbc $valueMsb
bvc +
eor #128
+ bpl +
jmp ($asmLabel)
+""")
} else {
asmgen.out("""
cmp $valueLsb
tya
sbc $valueMsb
bvs +
eor #128
+ bmi $asmLabel""")
}
} else {
val afterIfLabel = asmgen.makeLabel("afterif")
if(stmt.hasElse()) {
// if and else blocks
val elseLabel = asmgen.makeLabel("else")
asmgen.out("""
cmp $valueLsb
tya
sbc $valueMsb
bvc +
eor #128
+ bmi $elseLabel""")
asmgen.translate(stmt.ifScope)
asmgen.jmp(afterIfLabel, false)
asmgen.out(elseLabel)
asmgen.translate(stmt.elseScope)
} else {
// no else block
asmgen.out("""
cmp $valueLsb
tya
sbc $valueMsb
bvc +
eor #128
+ bmi $afterIfLabel""")
asmgen.translate(stmt.ifScope)
}
asmgen.out(afterIfLabel)
}
} else {
if(jump!=null) {
val (asmLabel, indirect) = asmgen.getJumpTarget(jump)
if(indirect) {
asmgen.out("""
cmp $valueLsb
tya
sbc $valueMsb
bcs +
jmp ($asmLabel)
+""")
} else {
asmgen.out("""
cmp $valueLsb
tya
sbc $valueMsb
bcs $asmLabel""")
}
} else {
val afterIfLabel = asmgen.makeLabel("afterif")
if(stmt.hasElse()) {
// if and else blocks
val elseLabel = asmgen.makeLabel("else")
asmgen.out("""
cmp $valueLsb
tya
sbc $valueMsb
bcc $elseLabel""")
asmgen.translate(stmt.ifScope)
asmgen.jmp(afterIfLabel, false)
asmgen.out(elseLabel)
asmgen.translate(stmt.elseScope)
} else {
// no else block
asmgen.out("""
cmp $valueLsb
tya
sbc $valueMsb
bcc $afterIfLabel""")
asmgen.translate(stmt.ifScope)
}
asmgen.out(afterIfLabel)
}
}
}
if(right is PtNumber) {
asmgen.assignExpressionToRegister(left, RegisterOrPair.AY, signed)
val number = right.number.toHex()
return code("#<$number", "#>$number")
}
if(right is PtIdentifier) {
asmgen.assignExpressionToRegister(left, RegisterOrPair.AY, signed)
val variable = asmgen.asmVariableName(right)
return code("#<$variable", "#>$variable")
}
// TODO optimize for simple array value
// generic case via scratch register
asmgen.assignWordOperandsToAYAndVar(left, right, "P8ZP_SCRATCH_W2")
code("P8ZP_SCRATCH_W2", "P8ZP_SCRATCH_W2+1")
}
private fun loadAndCmp0MSB(value: PtExpression) {
when(value) {
is PtArrayIndexer -> {

View File

@ -1,9 +1,18 @@
TODO
====
examples/primes is larger than on 10.1
efficient code for assignment float comparisons against a value (it now copies the floats around too many times) 10.1 created efficient code.
examples/maze is larger than on 10.1
examples/textelite is larger than on 10.1
rockrunner is a lot bigger still than on 10.1
paint is bigger than on 10.1
cx16/testmonogfx is broken
assembler is broken
imageviewer is broken
paint flood fill is broken
rockrunner load caveset list is broken
medemo and dsdemo are broken
@ -29,23 +38,23 @@ ok ok while not <integervar> should give type error
ok ok while not <integer functioncall> should give type error
ok ok while not cx16.mouse_pos() should give condition type error
ok ok efficient code for manipulating bools in an array (normal and agumented assigns)
ok WIP efficient code for if with only a goto in it
ok . efficient code for if byte comparisons against 0 (== and !=)
ok . efficient code for if word comparisons against 0 (== and !=)
ok . efficient code for if float comparisons against 0 (== and !=)
ok . efficient code for if byte comparisons against a value
ok . efficient code for if word comparisons against a value
ok . efficient code for if float comparisons against a value
ok ok efficient code for if with only a goto in it
ok ok efficient code for if byte comparisons against 0 (== and !=)
ok ok efficient code for if word comparisons against 0 (== and !=)
ok ok efficient code for if float comparisons against 0 (== and !=)
ok ok efficient code for if byte comparisons against a value
ok ok efficient code for if word comparisons against a value
ok ok efficient code for if float comparisons against a value
ok ok efficient code for assignment byte comparisons against 0 (== and !=)
ok . efficient code for assignment word comparisons against 0 (== and !=)
ok . efficient code for assignment float comparisons against 0 (== and !=)
ok FAIL efficient code for assignment byte comparisons against a value ("float if ==" and "float if !=")
ok . efficient code for assignment word comparisons against a value
ok . efficient code for assignment float comparisons against a value
ok ok efficient code for assignment word comparisons against 0 (== and !=)
ok ok efficient code for assignment float comparisons against 0 (== and !=)
ok ok efficient code for assignment byte comparisons against a value
ok ok efficient code for assignment word comparisons against a value
ok FAIL efficient code for assignment float comparisons against a value
ok ok efficient code for if_cc conditional expressions
ok FAIL while boolean should produce identical code as while integer!=0 and code should be efficient
ok . while not boolvar -> can we get rid of the cmp? (6502 only?)
ok . testmonogfx works
ok ok while boolean should produce identical code as while integer!=0 and code should be efficient
ok ok while not boolvar -> can we get rid of the cmp? (6502 only?)
ok FAIL testmonogfx works
ok . check program sizes vs. master branch
===== ====== =======
@ -54,18 +63,10 @@ retest all comparisons in if statements (byte, word, signed and unsigned) + all
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.
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?
boolean trick to go from a compare >= value, to a bool
cmp #value
rol a
and #1
Already broken in 10.0: textelite on c64, info on diso -> jams the cpu after printing
IR: add TEST instruction to test memory content and set N/Z flags, without affecting any register.
replace all LOADM+CMPI #0 / LOAD #0+LOADM+CMP+BRANCH by this instruction

View File

@ -37,8 +37,8 @@ main {
angley+=217
anglez+=452
sys.waitvsync()
sys.waitvsync()
;sys.waitvsync()
;sys.waitvsync()
}
}

View File

@ -9,17 +9,16 @@ main {
word[4] words
byte @shared sbb
float @shared fl=3.3
float @shared fl2=4.3
sub start() {
while cx16.r0s < 1234
while not staticbool2
cx16.r0L++
while cx16.r0L==0
cx16.r0L++
loop:
if cx16.r0s >= 1234
goto skip
cx16.r0L++
goto loop
skip:
; TODO all this for uwords