improved asm generation for conditions that compare ubyte/uword to zero

This commit is contained in:
Irmen de Jong 2021-10-31 01:39:37 +02:00
parent 2df0c9503c
commit 2388359a99
2 changed files with 72 additions and 99 deletions

View File

@ -59,7 +59,7 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge
} }
if (rightConstVal!=null && rightConstVal.number.toDouble() == 0.0) if (rightConstVal!=null && rightConstVal.number.toDouble() == 0.0)
jumpIfZeroOrNot(left, operator, right, jumpIfFalseLabel, leftConstVal, rightConstVal) jumpIfZeroOrNot(left, operator, jumpIfFalseLabel)
else else
jumpIfComparison(left, operator, right, jumpIfFalseLabel, leftConstVal, rightConstVal) jumpIfComparison(left, operator, right, jumpIfFalseLabel, leftConstVal, rightConstVal)
} }
@ -67,71 +67,46 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge
private fun jumpIfZeroOrNot( private fun jumpIfZeroOrNot(
left: Expression, left: Expression,
operator: String, operator: String,
right: Expression, jumpIfFalseLabel: String
jumpIfFalseLabel: String,
leftConstVal: NumericLiteralValue?,
rightConstVal: NumericLiteralValue?
) { ) {
when(left.inferType(program).getOr(DataType.UNDEFINED)) { when(val dt = left.inferType(program).getOr(DataType.UNDEFINED)) {
DataType.UBYTE, DataType.BYTE -> { DataType.UBYTE, DataType.UWORD -> {
asmgen.assignExpressionToRegister(left, RegisterOrPair.A) if(operator=="<") {
if (left is FunctionCall && !left.isSimple) asmgen.out(" jmp $jumpIfFalseLabel")
asmgen.out(" cmp #0") return
} else if(operator==">=") {
return
}
if(dt==DataType.UBYTE) {
asmgen.assignExpressionToRegister(left, RegisterOrPair.A)
if (left is FunctionCall && !left.isSimple)
asmgen.out(" cmp #0")
} else {
asmgen.assignExpressionToRegister(left, RegisterOrPair.AY)
asmgen.out(" sty P8ZP_SCRATCH_B1 | ora P8ZP_SCRATCH_B1")
}
when (operator) { when (operator) {
"==" -> { "==" -> asmgen.out(" bne $jumpIfFalseLabel")
asmgen.out(" bne $jumpIfFalseLabel") "!=" -> asmgen.out(" beq $jumpIfFalseLabel")
} ">" -> asmgen.out(" beq $jumpIfFalseLabel")
"!=" -> { "<=" -> asmgen.out(" bne $jumpIfFalseLabel")
asmgen.out(" beq $jumpIfFalseLabel") else -> throw AssemblyError("invalid comparison operator $operator")
}
else -> {
// TODO optimize byte other operators
jumpIfComparison(left, operator, right, jumpIfFalseLabel, leftConstVal, rightConstVal)
}
} }
} }
DataType.UWORD, DataType.WORD -> { DataType.BYTE, DataType.WORD -> {
asmgen.assignExpressionToRegister(left, RegisterOrPair.AY) TODO("signed BYTE/UWORD comparison $operator")
asmgen.out(" sty P8ZP_SCRATCH_B1 | ora P8ZP_SCRATCH_B1")
when (operator) {
"==" -> {
asmgen.out(" bne $jumpIfFalseLabel")
}
"!=" -> {
asmgen.out(" beq $jumpIfFalseLabel")
}
else -> {
// TODO optimize word other operators
jumpIfComparison(left, operator, right, jumpIfFalseLabel, leftConstVal, rightConstVal)
}
}
} }
DataType.FLOAT -> { DataType.FLOAT -> {
asmgen.assignExpressionToRegister(left, RegisterOrPair.FAC1) asmgen.assignExpressionToRegister(left, RegisterOrPair.FAC1)
asmgen.out(" jsr floats.SIGN") asmgen.out(" jsr floats.SIGN") // SIGN(fac1) to A, $ff, $0, $1 for negative, zero, positive
when (operator) { when (operator) {
"==" -> { "==" -> asmgen.out(" bne $jumpIfFalseLabel")
// SIGN(fac1) to A, $ff, $0, $1 for negative, zero, positive "!=" -> asmgen.out(" beq $jumpIfFalseLabel")
asmgen.out(" bne $jumpIfFalseLabel") ">" -> asmgen.out(" bmi $jumpIfFalseLabel | beq $jumpIfFalseLabel")
} "<" -> asmgen.out(" bpl $jumpIfFalseLabel")
"!=" -> { ">=" -> asmgen.out(" bmi $jumpIfFalseLabel")
asmgen.out(" beq $jumpIfFalseLabel") "<=" -> asmgen.out(" cmp #1 | beq $jumpIfFalseLabel")
} else -> throw AssemblyError("invalid comparison operator $operator")
">" -> {
asmgen.out(" bmi $jumpIfFalseLabel | beq $jumpIfFalseLabel")
}
"<" -> {
asmgen.out(" bpl $jumpIfFalseLabel")
}
">=" -> {
asmgen.out(" bmi $jumpIfFalseLabel")
}
"<=" -> {
asmgen.out(" cmp #1 | beq $jumpIfFalseLabel")
}
else -> {
throw AssemblyError("invalid comparison operator $operator")
}
} }
} }
else -> { else -> {

View File

@ -1,4 +1,3 @@
%import floats
%import textio %import textio
%zeropage basicsafe %zeropage basicsafe
@ -6,76 +5,75 @@ main {
sub start() { sub start() {
ubyte xx ubyte xx
float ff
ff=0 xx=0
if ff>=0 { if xx>=0 {
txt.print("ff>=0\n") txt.print("xx>=0\n")
} else { } else {
txt.print("error1\n") txt.print("error1\n")
} }
if ff<=0 { if xx<=0 {
txt.print("ff<=0\n") txt.print("xx<=0\n")
} else { } else {
txt.print("error1\n") txt.print("error1\n")
} }
if ff>0 { if xx>0 {
txt.print("ff>0 error\n") txt.print("xx>0 error\n")
} else { } else {
txt.print("ok1\n") txt.print("ok1\n")
} }
if ff<0 { if xx<0 {
txt.print("ff<0 error\n") txt.print("xx<0 error\n")
} else { } else {
txt.print("ok1\n") txt.print("ok1\n")
} }
txt.nl() txt.nl()
ff=0.22 xx=22
if ff>=0 { if xx>=0 {
txt.print("ff>=0\n") txt.print("xx>=0\n")
} else { } else {
txt.print("error2\n") txt.print("error2\n")
} }
if ff<=0 { if xx<=0 {
txt.print("ff<=0 error\n") txt.print("xx<=0 error\n")
} else { } else {
txt.print("ok2\n") txt.print("ok2\n")
} }
if ff>0 { if xx>0 {
txt.print("ff>0\n") txt.print("xx>0\n")
} else { } else {
txt.print("error2\n") txt.print("error2\n")
} }
if ff<0 { if xx<0 {
txt.print("ff<0 error\n") txt.print("xx<0 error\n")
} else { } else {
txt.print("ok2\n") txt.print("ok2\n")
} }
txt.nl() txt.nl()
ff=-1.11 ; xx=-11
if ff>=0 { ; if xx>=0 {
txt.print("ff>=0 error\n") ; txt.print("xx>=0 error\n")
} else { ; } else {
txt.print("ok3\n") ; txt.print("ok3\n")
} ; }
if ff<=0 { ; if xx<=0 {
txt.print("ff<=0\n") ; txt.print("xx<=0\n")
} else { ; } else {
txt.print("error3\n") ; txt.print("error3\n")
} ; }
if ff>0 { ; if xx>0 {
txt.print("ff>0 error\n") ; txt.print("xx>0 error\n")
} else { ; } else {
txt.print("ok3\n") ; txt.print("ok3\n")
} ; }
if ff<0 { ; if xx<0 {
txt.print("ff<0\n") ; txt.print("xx<0\n")
} else { ; } else {
txt.print("error3\n") ; txt.print("error3\n")
} ; }