mirror of
https://github.com/irmen/prog8.git
synced 2025-04-19 05:38:28 +00:00
optimize comparison against zero
This commit is contained in:
parent
cfea8b3745
commit
09a7a4bbe5
@ -416,7 +416,6 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
||||
val translatedOk = when (expr.operator) {
|
||||
in ComparisonOperators -> optimizedComparison(expr, assign)
|
||||
in setOf("&", "|", "^", "and", "or", "xor") -> optimizedLogicalOrBitwiseExpr(expr, assign.target)
|
||||
"==", "!=" -> optimizedEqualityExpr(expr, assign.target)
|
||||
"+", "-" -> optimizedPlusMinExpr(expr, assign.target)
|
||||
"<<", ">>" -> optimizedBitshiftExpr(expr, assign.target)
|
||||
"*" -> optimizedMultiplyExpr(expr, assign.target)
|
||||
@ -888,63 +887,6 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
||||
return false
|
||||
}
|
||||
|
||||
private fun optimizedEqualityExpr(expr: PtBinaryExpression, target: AsmAssignTarget): Boolean {
|
||||
// expression datatype is BOOL (ubyte) but operands can be anything
|
||||
if(expr.left.type in ByteDatatypes && expr.right.type in ByteDatatypes &&
|
||||
expr.left.isSimple() && expr.right.isSimple()) {
|
||||
assignExpressionToRegister(expr.left, RegisterOrPair.A, false)
|
||||
asmgen.saveRegisterStack(CpuRegister.A, false)
|
||||
assignExpressionToVariable(expr.right, "P8ZP_SCRATCH_B1", DataType.UBYTE)
|
||||
asmgen.restoreRegisterStack(CpuRegister.A, false)
|
||||
if(expr.operator=="==") {
|
||||
asmgen.out("""
|
||||
cmp P8ZP_SCRATCH_B1
|
||||
bne +
|
||||
lda #1
|
||||
bne ++
|
||||
+ lda #0
|
||||
+""")
|
||||
} else {
|
||||
asmgen.out("""
|
||||
cmp P8ZP_SCRATCH_B1
|
||||
beq +
|
||||
lda #1
|
||||
bne ++
|
||||
+ lda #0
|
||||
+""")
|
||||
}
|
||||
assignRegisterByte(target, CpuRegister.A, false)
|
||||
return true
|
||||
} else if(expr.left.type in WordDatatypes && expr.right.type in WordDatatypes &&
|
||||
expr.left.isSimple() && expr.right.isSimple()) {
|
||||
asmgen.assignWordOperandsToAYAndVar(expr.left, expr.right, "P8ZP_SCRATCH_W1")
|
||||
if(expr.operator=="==") {
|
||||
asmgen.out("""
|
||||
cmp P8ZP_SCRATCH_W1
|
||||
bne +
|
||||
cpy P8ZP_SCRATCH_W1+1
|
||||
bne +
|
||||
lda #1
|
||||
bne ++
|
||||
+ lda #0
|
||||
+""")
|
||||
} else {
|
||||
asmgen.out("""
|
||||
cmp P8ZP_SCRATCH_W1
|
||||
bne +
|
||||
cpy P8ZP_SCRATCH_W1+1
|
||||
bne +
|
||||
lda #0
|
||||
beq ++
|
||||
+ lda #1
|
||||
+""")
|
||||
}
|
||||
assignRegisterByte(target, CpuRegister.A, false)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun optimizedLogicalOrBitwiseExpr(expr: PtBinaryExpression, target: AsmAssignTarget): Boolean {
|
||||
if (expr.left.type in ByteDatatypes && expr.right.type in ByteDatatypes) {
|
||||
if (expr.right.isSimple()) {
|
||||
@ -1085,7 +1027,6 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
||||
}
|
||||
}
|
||||
|
||||
// checked OK:
|
||||
private fun byteLess(expr: PtBinaryExpression, signed: Boolean) {
|
||||
// note: this is the inverse of byteGreaterEqual
|
||||
when(expr.right) {
|
||||
@ -1232,78 +1173,6 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
||||
}
|
||||
}
|
||||
|
||||
private fun byteLessEqualsWRONG(expr: PtBinaryExpression, signed: Boolean) {
|
||||
// note: this is the inverse of byteGreater
|
||||
when(expr.right) {
|
||||
is PtNumber -> {
|
||||
// TODO verify if this is correct code on all corner cases
|
||||
val number = (expr.right as PtNumber).number.toInt()
|
||||
asmgen.assignExpressionToRegister(expr.left, RegisterOrPair.A, signed)
|
||||
if(signed)
|
||||
asmgen.out("""
|
||||
sec
|
||||
sbc #$number
|
||||
bvc +
|
||||
eor #$80
|
||||
+ bmi +
|
||||
lda #0
|
||||
beq ++
|
||||
+ lda #1
|
||||
+""")
|
||||
else
|
||||
asmgen.out("""
|
||||
cmp #$number
|
||||
lda #0
|
||||
rol a
|
||||
eor #1""")
|
||||
}
|
||||
is PtIdentifier -> {
|
||||
// TODO verify if this is correct code on all corner cases
|
||||
val varname = (expr.right as PtIdentifier).name
|
||||
asmgen.assignExpressionToRegister(expr.left, RegisterOrPair.A, signed)
|
||||
if(signed)
|
||||
asmgen.out("""
|
||||
sec
|
||||
sbc $varname
|
||||
bvc +
|
||||
eor #$80
|
||||
+ bmi +
|
||||
lda #0
|
||||
beq ++
|
||||
+ lda #1
|
||||
+""")
|
||||
else
|
||||
asmgen.out("""
|
||||
cmp $varname
|
||||
lda #0
|
||||
rol a
|
||||
eor #1""")
|
||||
}
|
||||
else -> {
|
||||
// TODO verify if this is correct code on all corner cases
|
||||
// note: left and right operands get reversed here to reduce code size
|
||||
asmgen.assignByteOperandsToAAndVar(expr.right, expr.left, "P8ZP_SCRATCH_B1")
|
||||
if(signed)
|
||||
asmgen.out("""
|
||||
sec
|
||||
sbc P8ZP_SCRATCH_B1
|
||||
bvc +
|
||||
eor #$80
|
||||
+ bmi +
|
||||
lda #1
|
||||
bne ++
|
||||
+ lda #0
|
||||
+""")
|
||||
else
|
||||
asmgen.out("""
|
||||
cmp P8ZP_SCRATCH_B1
|
||||
lda #0
|
||||
rol a""")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// checked OK:
|
||||
private fun byteGreater(expr: PtBinaryExpression, signed: Boolean) {
|
||||
// note: this is the inverse of byteLessEqual
|
||||
when(expr.right) {
|
||||
@ -1381,7 +1250,6 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
||||
}
|
||||
}
|
||||
|
||||
// checked OK:
|
||||
private fun byteGreaterEquals(expr: PtBinaryExpression, signed: Boolean) {
|
||||
// note: this is the inverse of byteLess
|
||||
when(expr.right) {
|
||||
@ -1649,10 +1517,8 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
||||
assignExpressionToRegister(expr.left, RegisterOrPair.A, dt==DataType.BYTE)
|
||||
asmgen.out("""
|
||||
beq +
|
||||
lda #0
|
||||
beq ++
|
||||
+ lda #1
|
||||
+""")
|
||||
lda #1
|
||||
+ eor #1""")
|
||||
assignRegisterByte(assign.target, CpuRegister.A, false)
|
||||
return true
|
||||
}
|
||||
@ -1662,10 +1528,8 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
||||
sty P8ZP_SCRATCH_B1
|
||||
ora P8ZP_SCRATCH_B1
|
||||
beq +
|
||||
lda #0
|
||||
beq ++
|
||||
+ lda #1
|
||||
+""")
|
||||
lda #1
|
||||
+ eor #1""")
|
||||
assignRegisterByte(assign.target, CpuRegister.A, false)
|
||||
return true
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
TODO
|
||||
====
|
||||
- optimize assembly output for if word1 & word2 ... (no need for stack pushes)
|
||||
- optimize assembly output for ( word1 & word2 ==0) ... (no need for stack pushes)
|
||||
|
||||
- prefix prog8 subroutines with p8s_ instead of p8_ to not let them clash with variables in the asm?
|
||||
|
||||
|
@ -1,13 +1,45 @@
|
||||
%import textio
|
||||
%import math
|
||||
%zeropage basicsafe
|
||||
|
||||
main {
|
||||
sub start() {
|
||||
thing()
|
||||
}
|
||||
sub thing() {
|
||||
ubyte start=22
|
||||
txt.print_ub(start)
|
||||
txt.print_uw(&main.start)
|
||||
uword w1
|
||||
uword w2
|
||||
|
||||
ubyte b1
|
||||
ubyte b2
|
||||
|
||||
b1 = 255
|
||||
b2 = 1
|
||||
txt.print_ub(b1&b2!=0) ; true
|
||||
txt.spc()
|
||||
txt.print_ub(b1&b2==0) ; false
|
||||
txt.nl()
|
||||
|
||||
b1 = 255
|
||||
b2 = 0
|
||||
txt.print_ub(b1&b2!=0) ; false
|
||||
txt.spc()
|
||||
txt.print_ub(b1&b2==0) ; true
|
||||
txt.nl()
|
||||
|
||||
w1 = $ff0f
|
||||
w2 = $0101
|
||||
txt.print_ub(w1&w2!=0) ; true
|
||||
txt.spc()
|
||||
txt.print_ub(w1&w2==0) ; false
|
||||
txt.nl()
|
||||
|
||||
w1 = $ff0f
|
||||
w2 = $00f0
|
||||
txt.print_ub(w1&w2!=0) ; false
|
||||
txt.spc()
|
||||
txt.print_ub(w1&w2==0) ; true
|
||||
txt.nl()
|
||||
|
||||
|
||||
; if w1 & w2
|
||||
; cx16.r0++
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user