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)
if (expr.left.type in WordDatatypes && expr.right.type in WordDatatypes) {
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) {
require(expr.operator in ComparisonOperators)
return assignFloatBinExpr(expr, assign)
}
TODO("weird expr operand types")
throw AssemblyError("weird expr operand types: ${expr.left.type} and {${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 {
val signed = expr.left.type == DataType.WORD || expr.right.type == DataType.WORD
when(expr.operator) {
"==" -> {
asmgen.assignWordOperandsToAYAndVar(expr.right, expr.left, "P8ZP_SCRATCH_W1")
asmgen.out("""
if(expr.left is PtIdentifier) {
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
bne +
cpy P8ZP_SCRATCH_W1+1
@ -1426,10 +1440,24 @@ internal class AssignmentAsmGen(private val program: PtProgram,
bne ++
+ lda #0
+""")
}
}
"!=" -> {
asmgen.assignWordOperandsToAYAndVar(expr.right, expr.left, "P8ZP_SCRATCH_W1")
asmgen.out("""
if(expr.left is PtIdentifier) {
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
bne +
cpy P8ZP_SCRATCH_W1+1
@ -1438,11 +1466,39 @@ internal class AssignmentAsmGen(private val program: PtProgram,
beq ++
+ lda #1
+""")
}
}
"<" -> {
if(signed) {
asmgen.assignWordOperandsToAYAndVar(expr.left, expr.right, "P8ZP_SCRATCH_W1")
asmgen.out("""
if(expr.right is PtIdentifier) {
val varName = asmgen.asmVariableName(expr.right as PtIdentifier)
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
tya
sbc P8ZP_SCRATCH_W1+1
@ -1453,10 +1509,10 @@ internal class AssignmentAsmGen(private val program: PtProgram,
bne ++
+ lda #0
+""")
}
else {
asmgen.assignWordOperandsToAYAndVar(expr.left, expr.right, "P8ZP_SCRATCH_W1")
asmgen.out("""
}
else {
asmgen.assignWordOperandsToAYAndVar(expr.left, expr.right, "P8ZP_SCRATCH_W1")
asmgen.out("""
cpy P8ZP_SCRATCH_W1+1
bcc +
bne ++
@ -1466,12 +1522,40 @@ internal class AssignmentAsmGen(private val program: PtProgram,
bne ++
+ lda #0
+""")
}
}
}
"<=" -> {
if(signed) {
asmgen.assignWordOperandsToAYAndVar(expr.right, expr.left, "P8ZP_SCRATCH_W1")
asmgen.out("""
if(expr.left is PtIdentifier) {
val varName = asmgen.asmVariableName(expr.left as PtIdentifier)
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
tya
sbc P8ZP_SCRATCH_W1+1
@ -1482,10 +1566,10 @@ internal class AssignmentAsmGen(private val program: PtProgram,
bne ++
+ lda #0
+""")
}
else {
asmgen.assignWordOperandsToAYAndVar(expr.right, expr.left, "P8ZP_SCRATCH_W1")
asmgen.out("""
}
else {
asmgen.assignWordOperandsToAYAndVar(expr.right, expr.left, "P8ZP_SCRATCH_W1")
asmgen.out("""
cpy P8ZP_SCRATCH_W1+1
bcc ++
bne +
@ -1495,12 +1579,40 @@ internal class AssignmentAsmGen(private val program: PtProgram,
bne ++
+ lda #0
+""")
}
}
}
">" -> {
if(signed) {
asmgen.assignWordOperandsToAYAndVar(expr.right, expr.left, "P8ZP_SCRATCH_W1")
asmgen.out("""
if(expr.left is PtIdentifier) {
val varName = asmgen.asmVariableName(expr.left as PtIdentifier)
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
tya
sbc P8ZP_SCRATCH_W1+1
@ -1511,10 +1623,10 @@ internal class AssignmentAsmGen(private val program: PtProgram,
bne ++
+ lda #0
+""")
}
else {
asmgen.assignWordOperandsToAYAndVar(expr.right, expr.left, "P8ZP_SCRATCH_W1")
asmgen.out("""
}
else {
asmgen.assignWordOperandsToAYAndVar(expr.right, expr.left, "P8ZP_SCRATCH_W1")
asmgen.out("""
cpy P8ZP_SCRATCH_W1+1
bcc +
bne ++
@ -1524,12 +1636,40 @@ internal class AssignmentAsmGen(private val program: PtProgram,
bne ++
+ lda #0
+""")
}
}
}
">=" -> {
if(signed) {
asmgen.assignWordOperandsToAYAndVar(expr.left, expr.right, "P8ZP_SCRATCH_W1")
asmgen.out("""
if(expr.right is PtIdentifier) {
val varName = asmgen.asmVariableName(expr.right as PtIdentifier)
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
tya
sbc P8ZP_SCRATCH_W1+1
@ -1540,10 +1680,10 @@ internal class AssignmentAsmGen(private val program: PtProgram,
bne ++
+ lda #0
+""")
}
else {
asmgen.assignWordOperandsToAYAndVar(expr.left, expr.right, "P8ZP_SCRATCH_W1")
asmgen.out("""
}
else {
asmgen.assignWordOperandsToAYAndVar(expr.left, expr.right, "P8ZP_SCRATCH_W1")
asmgen.out("""
cpy P8ZP_SCRATCH_W1+1
bcc ++
bne +
@ -1553,6 +1693,7 @@ internal class AssignmentAsmGen(private val program: PtProgram,
bne ++
+ lda #0
+""")
}
}
}
else -> return false

View File

@ -1,8 +1,6 @@
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: 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!

View File

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