optimized comparison with word variables

This commit is contained in:
Irmen de Jong 2023-11-05 00:20:12 +01:00
parent d5f35bb3fb
commit e7178ee496
4 changed files with 190 additions and 59 deletions

View File

@ -23,13 +23,13 @@ internal class AnyExprAsmGen(
return assignByteBinExpr(expr, assign) return assignByteBinExpr(expr, assign)
if (expr.left.type in WordDatatypes && expr.right.type in WordDatatypes) { if (expr.left.type in WordDatatypes && expr.right.type in WordDatatypes) {
require(expr.operator in ComparisonOperators) require(expr.operator in ComparisonOperators)
TODO("words operands comparison -> byte") throw AssemblyError("words operands comparison -> byte, should have been handled by assignOptimizedComparisonWords()")
} }
if (expr.left.type==DataType.FLOAT && expr.right.type==DataType.FLOAT) { if (expr.left.type==DataType.FLOAT && expr.right.type==DataType.FLOAT) {
require(expr.operator in ComparisonOperators) require(expr.operator in ComparisonOperators)
return assignFloatBinExpr(expr, assign) return assignFloatBinExpr(expr, assign)
} }
TODO("weird expr operand types") throw AssemblyError("weird expr operand types: ${expr.left.type} and {${expr.right.type}")
} }
in WordDatatypes -> { in WordDatatypes -> {
require(expr.left.type in WordDatatypes && expr.right.type in WordDatatypes) { require(expr.left.type in WordDatatypes && expr.right.type in WordDatatypes) {

View File

@ -1414,10 +1414,24 @@ internal class AssignmentAsmGen(private val program: PtProgram,
private fun assignOptimizedComparisonWords(expr: PtBinaryExpression, assign: AsmAssignment): Boolean { private fun assignOptimizedComparisonWords(expr: PtBinaryExpression, assign: AsmAssignment): Boolean {
val signed = expr.left.type == DataType.WORD || expr.right.type == DataType.WORD val signed = expr.left.type == DataType.WORD || expr.right.type == DataType.WORD
when(expr.operator) { when(expr.operator) {
"==" -> { "==" -> {
asmgen.assignWordOperandsToAYAndVar(expr.right, expr.left, "P8ZP_SCRATCH_W1") if(expr.left is PtIdentifier) {
asmgen.out(""" val varName = asmgen.asmVariableName(expr.left as PtIdentifier)
asmgen.assignExpressionToRegister(expr.right, RegisterOrPair.AY)
asmgen.out("""
cmp $varName
bne +
cpy $varName+1
bne +
lda #1
bne ++
+ lda #0
+""")
} else {
asmgen.assignWordOperandsToAYAndVar(expr.right, expr.left, "P8ZP_SCRATCH_W1")
asmgen.out("""
cmp P8ZP_SCRATCH_W1 cmp P8ZP_SCRATCH_W1
bne + bne +
cpy P8ZP_SCRATCH_W1+1 cpy P8ZP_SCRATCH_W1+1
@ -1426,10 +1440,24 @@ internal class AssignmentAsmGen(private val program: PtProgram,
bne ++ bne ++
+ lda #0 + lda #0
+""") +""")
}
} }
"!=" -> { "!=" -> {
asmgen.assignWordOperandsToAYAndVar(expr.right, expr.left, "P8ZP_SCRATCH_W1") if(expr.left is PtIdentifier) {
asmgen.out(""" val varName = asmgen.asmVariableName(expr.left as PtIdentifier)
asmgen.assignExpressionToRegister(expr.right, RegisterOrPair.AY)
asmgen.out("""
cmp $varName
bne +
cpy $varName+1
bne +
lda #0
beq ++
+ lda #1
+""")
} else {
asmgen.assignWordOperandsToAYAndVar(expr.right, expr.left, "P8ZP_SCRATCH_W1")
asmgen.out("""
cmp P8ZP_SCRATCH_W1 cmp P8ZP_SCRATCH_W1
bne + bne +
cpy P8ZP_SCRATCH_W1+1 cpy P8ZP_SCRATCH_W1+1
@ -1438,11 +1466,39 @@ internal class AssignmentAsmGen(private val program: PtProgram,
beq ++ beq ++
+ lda #1 + lda #1
+""") +""")
}
} }
"<" -> { "<" -> {
if(signed) { if(expr.right is PtIdentifier) {
asmgen.assignWordOperandsToAYAndVar(expr.left, expr.right, "P8ZP_SCRATCH_W1") val varName = asmgen.asmVariableName(expr.right as PtIdentifier)
asmgen.out(""" asmgen.assignExpressionToRegister(expr.left, RegisterOrPair.AY)
if(signed)
asmgen.out("""
cmp $varName
tya
sbc $varName+1
bvc +
eor #${'$'}80
+ bpl ++
+ lda #1
bne ++
+ lda #0
+""")
else
asmgen.out("""
cpy $varName+1
bcc +
bne ++
cmp $varName
bcs ++
+ lda #1
bne ++
+ lda #0
+""")
} else {
if(signed) {
asmgen.assignWordOperandsToAYAndVar(expr.left, expr.right, "P8ZP_SCRATCH_W1")
asmgen.out("""
cmp P8ZP_SCRATCH_W1 cmp P8ZP_SCRATCH_W1
tya tya
sbc P8ZP_SCRATCH_W1+1 sbc P8ZP_SCRATCH_W1+1
@ -1453,10 +1509,10 @@ internal class AssignmentAsmGen(private val program: PtProgram,
bne ++ bne ++
+ lda #0 + lda #0
+""") +""")
} }
else { else {
asmgen.assignWordOperandsToAYAndVar(expr.left, expr.right, "P8ZP_SCRATCH_W1") asmgen.assignWordOperandsToAYAndVar(expr.left, expr.right, "P8ZP_SCRATCH_W1")
asmgen.out(""" asmgen.out("""
cpy P8ZP_SCRATCH_W1+1 cpy P8ZP_SCRATCH_W1+1
bcc + bcc +
bne ++ bne ++
@ -1466,12 +1522,40 @@ internal class AssignmentAsmGen(private val program: PtProgram,
bne ++ bne ++
+ lda #0 + lda #0
+""") +""")
}
} }
} }
"<=" -> { "<=" -> {
if(signed) { if(expr.left is PtIdentifier) {
asmgen.assignWordOperandsToAYAndVar(expr.right, expr.left, "P8ZP_SCRATCH_W1") val varName = asmgen.asmVariableName(expr.left as PtIdentifier)
asmgen.out(""" asmgen.assignExpressionToRegister(expr.right, RegisterOrPair.AY)
if(signed)
asmgen.out("""
cmp $varName
tya
sbc $varName+1
bvc +
eor #${'$'}80
+ bmi +
lda #1
bne ++
+ lda #0
+""")
else
asmgen.out("""
cpy $varName+1
bcc ++
bne +
cmp $varName
bcc ++
+ lda #1
bne ++
+ lda #0
+""")
} else {
if(signed) {
asmgen.assignWordOperandsToAYAndVar(expr.right, expr.left, "P8ZP_SCRATCH_W1")
asmgen.out("""
cmp P8ZP_SCRATCH_W1 cmp P8ZP_SCRATCH_W1
tya tya
sbc P8ZP_SCRATCH_W1+1 sbc P8ZP_SCRATCH_W1+1
@ -1482,10 +1566,10 @@ internal class AssignmentAsmGen(private val program: PtProgram,
bne ++ bne ++
+ lda #0 + lda #0
+""") +""")
} }
else { else {
asmgen.assignWordOperandsToAYAndVar(expr.right, expr.left, "P8ZP_SCRATCH_W1") asmgen.assignWordOperandsToAYAndVar(expr.right, expr.left, "P8ZP_SCRATCH_W1")
asmgen.out(""" asmgen.out("""
cpy P8ZP_SCRATCH_W1+1 cpy P8ZP_SCRATCH_W1+1
bcc ++ bcc ++
bne + bne +
@ -1495,12 +1579,40 @@ internal class AssignmentAsmGen(private val program: PtProgram,
bne ++ bne ++
+ lda #0 + lda #0
+""") +""")
}
} }
} }
">" -> { ">" -> {
if(signed) { if(expr.left is PtIdentifier) {
asmgen.assignWordOperandsToAYAndVar(expr.right, expr.left, "P8ZP_SCRATCH_W1") val varName = asmgen.asmVariableName(expr.left as PtIdentifier)
asmgen.out(""" asmgen.assignExpressionToRegister(expr.right, RegisterOrPair.AY)
if(signed)
asmgen.out("""
cmp $varName
tya
sbc $varName+1
bvc +
eor #${'$'}80
+ bpl ++
+ lda #1
bne ++
+ lda #0
+""")
else
asmgen.out("""
cpy $varName+1
bcc +
bne ++
cmp $varName
bcs ++
+ lda #1
bne ++
+ lda #0
+""")
} else {
if(signed) {
asmgen.assignWordOperandsToAYAndVar(expr.right, expr.left, "P8ZP_SCRATCH_W1")
asmgen.out("""
cmp P8ZP_SCRATCH_W1 cmp P8ZP_SCRATCH_W1
tya tya
sbc P8ZP_SCRATCH_W1+1 sbc P8ZP_SCRATCH_W1+1
@ -1511,10 +1623,10 @@ internal class AssignmentAsmGen(private val program: PtProgram,
bne ++ bne ++
+ lda #0 + lda #0
+""") +""")
} }
else { else {
asmgen.assignWordOperandsToAYAndVar(expr.right, expr.left, "P8ZP_SCRATCH_W1") asmgen.assignWordOperandsToAYAndVar(expr.right, expr.left, "P8ZP_SCRATCH_W1")
asmgen.out(""" asmgen.out("""
cpy P8ZP_SCRATCH_W1+1 cpy P8ZP_SCRATCH_W1+1
bcc + bcc +
bne ++ bne ++
@ -1524,12 +1636,40 @@ internal class AssignmentAsmGen(private val program: PtProgram,
bne ++ bne ++
+ lda #0 + lda #0
+""") +""")
}
} }
} }
">=" -> { ">=" -> {
if(signed) { if(expr.right is PtIdentifier) {
asmgen.assignWordOperandsToAYAndVar(expr.left, expr.right, "P8ZP_SCRATCH_W1") val varName = asmgen.asmVariableName(expr.right as PtIdentifier)
asmgen.out(""" asmgen.assignExpressionToRegister(expr.left, RegisterOrPair.AY)
if(signed)
asmgen.out("""
cmp $varName
tya
sbc $varName+1
bvc +
eor #${'$'}80
+ bmi +
lda #1
bne ++
+ lda #0
+""")
else
asmgen.out("""
cpy $varName+1
bcc ++
bne +
cmp $varName
bcc ++
+ lda #1
bne ++
+ lda #0
+""")
} else {
if(signed) {
asmgen.assignWordOperandsToAYAndVar(expr.left, expr.right, "P8ZP_SCRATCH_W1")
asmgen.out("""
cmp P8ZP_SCRATCH_W1 cmp P8ZP_SCRATCH_W1
tya tya
sbc P8ZP_SCRATCH_W1+1 sbc P8ZP_SCRATCH_W1+1
@ -1540,10 +1680,10 @@ internal class AssignmentAsmGen(private val program: PtProgram,
bne ++ bne ++
+ lda #0 + lda #0
+""") +""")
} }
else { else {
asmgen.assignWordOperandsToAYAndVar(expr.left, expr.right, "P8ZP_SCRATCH_W1") asmgen.assignWordOperandsToAYAndVar(expr.left, expr.right, "P8ZP_SCRATCH_W1")
asmgen.out(""" asmgen.out("""
cpy P8ZP_SCRATCH_W1+1 cpy P8ZP_SCRATCH_W1+1
bcc ++ bcc ++
bne + bne +
@ -1553,6 +1693,7 @@ internal class AssignmentAsmGen(private val program: PtProgram,
bne ++ bne ++
+ lda #0 + lda #0
+""") +""")
}
} }
} }
else -> return false else -> return false

View File

@ -1,8 +1,6 @@
TODO TODO
==== ====
- what makes while xx <= x2 and pget(xx as uword, yy as uword) == cx16.r11L so large
- [on branch: shortcircuit] investigate McCarthy evaluation again? this may also reduce code size perhaps for things like if a>4 or a<2 .... - [on branch: shortcircuit] investigate McCarthy evaluation again? this may also reduce code size perhaps for things like if a>4 or a<2 ....
- [on branch: ir-less-branch-opcodes] IR: reduce the number of branch instructions such as BEQ, BEQR, etc (gradually), replace with CMP(I) + status branch instruction - [on branch: ir-less-branch-opcodes] IR: reduce the number of branch instructions such as BEQ, BEQR, etc (gradually), replace with CMP(I) + status branch instruction
- IR: reduce amount of CMP/CMPI after instructions that set the status bits correctly (LOADs? INC? Bitwise operations, etc), but only after setting the status bits is verified! - IR: reduce amount of CMP/CMPI after instructions that set the status bits correctly (LOADs? INC? Bitwise operations, etc), but only after setting the status bits is verified!

View File

@ -1,30 +1,22 @@
%import syslib
%import textio
%zeropage basicsafe %zeropage basicsafe
main { main {
sub start() {
uword[] wordarray = [0,1,2,3,4,5,6,7,8,9] sub pget(uword x, uword y) -> ubyte {
ubyte n = 5 return lsb(x+y)
n = lsb(wordarray[n])
n = wordarray[n] as ubyte
test(wordarray[n] as ubyte,wordarray[n] as ubyte,0)
test(lsb(wordarray[n]), lsb(wordarray[n]),0)
} }
asmsub test(ubyte a1 @A, ubyte a2 @X, ubyte a3 @Y) { sub start() {
%asm {{
phy word xx
phx word x2
jsr txt.print_ub word yy
jsr txt.spc
pla if xx <= x2 and pget(xx as uword, yy as uword) == cx16.r11L
jsr txt.print_ub xx++
jsr txt.spc
pla ; if xx <= x2
jsr txt.print_ub ; if pget(xx as uword, yy as uword) == cx16.r11L
jsr txt.nl ; xx++
rts
}}
} }
} }