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) { private fun wordLessValue(left: PtExpression, right: PtExpression, signed: Boolean, jump: PtJump?, stmt: PtIfElse) {
println("word if <") // TODO fun code(valueLsb: String, valueMsb: String) {
fallbackTranslate(stmt) 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) { private fun wordGreaterValue(left: PtExpression, right: PtExpression, signed: Boolean, jump: PtJump?, stmt: PtIfElse) {
println("word if >") // TODO fun code(valueLsb: String, valueMsb: String) {
fallbackTranslate(stmt) 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) { private fun wordLessEqualsValue(left: PtExpression, right: PtExpression, signed: Boolean, jump: PtJump?, stmt: PtIfElse) {
println("word if <=") // TODO fun code(valueLsb: String, valueMsb: String) {
fallbackTranslate(stmt) 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) { 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) { private fun loadAndCmp0MSB(value: PtExpression) {
when(value) { when(value) {
is PtArrayIndexer -> { is PtArrayIndexer -> {

View File

@ -1,9 +1,18 @@
TODO 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/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 <integer functioncall> should give type error
ok ok while not cx16.mouse_pos() should give condition 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 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 ok efficient code for if with only a goto in it
ok . efficient code for if byte comparisons against 0 (== and !=) ok ok efficient code for if byte comparisons against 0 (== and !=)
ok . efficient code for if word comparisons against 0 (== and !=) ok ok efficient code for if word comparisons against 0 (== and !=)
ok . efficient code for if float comparisons against 0 (== and !=) ok ok efficient code for if float comparisons against 0 (== and !=)
ok . efficient code for if byte comparisons against a value ok ok efficient code for if byte comparisons against a value
ok . efficient code for if word comparisons against a value ok 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 float comparisons against a value
ok ok efficient code for assignment byte comparisons against 0 (== and !=) ok ok efficient code for assignment byte comparisons against 0 (== and !=)
ok . efficient code for assignment word comparisons against 0 (== and !=) ok ok efficient code for assignment word comparisons against 0 (== and !=)
ok . efficient code for assignment float comparisons against 0 (== and !=) ok 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 ok efficient code for assignment byte comparisons against a value
ok . efficient code for assignment word comparisons against a value ok ok efficient code for assignment word comparisons against a value
ok . efficient code for assignment float 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 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 ok 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 ok while not boolvar -> can we get rid of the cmp? (6502 only?)
ok . testmonogfx works ok FAIL testmonogfx works
ok . check program sizes vs. master branch 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. with jump, indirect jump, no else block, and both if+else blocks.
check that the flood fill routine in gfx2 and paint still works. 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 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 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. 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 replace all LOADM+CMPI #0 / LOAD #0+LOADM+CMP+BRANCH by this instruction

View File

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

View File

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