tweak to byte compares

This commit is contained in:
Irmen de Jong
2024-02-27 00:02:42 +01:00
parent 2a1fec2ed2
commit bc2ede76bf
3 changed files with 83 additions and 417 deletions

View File

@@ -133,7 +133,7 @@ internal class IfElseAsmGen(private val program: PtProgram,
else else
translateIfElseBodies("beq", stmt) translateIfElseBodies("beq", stmt)
} }
"<" -> translateByteGreater(condition.right, condition.left, stmt, signed, jumpAfterIf) "<" -> translateByteLess(stmt, signed, jumpAfterIf)
"<=" -> { "<=" -> {
// X<=Y -> Y>=X (reverse of >=) // X<=Y -> Y>=X (reverse of >=)
asmgen.assignExpressionToRegister(condition.right, RegisterOrPair.A, signed) asmgen.assignExpressionToRegister(condition.right, RegisterOrPair.A, signed)
@@ -150,7 +150,7 @@ internal class IfElseAsmGen(private val program: PtProgram,
translateIfElseBodies("bcc", stmt) translateIfElseBodies("bcc", stmt)
} }
} }
">" -> translateByteGreater(condition.left, condition.right, stmt, signed, jumpAfterIf) ">" -> translateByteGreater(stmt, signed, jumpAfterIf)
">=" -> { ">=" -> {
asmgen.assignExpressionToRegister(condition.left, RegisterOrPair.A, signed) asmgen.assignExpressionToRegister(condition.left, RegisterOrPair.A, signed)
cmpAwithByteValue(condition.right, false) cmpAwithByteValue(condition.right, false)
@@ -323,7 +323,7 @@ internal class IfElseAsmGen(private val program: PtProgram,
if(constIndex!=null) { if(constIndex!=null) {
val offset = constIndex * program.memsizer.memorySize(value.type) val offset = constIndex * program.memsizer.memorySize(value.type)
if(offset<256) { if(offset<256) {
return asmgen.out(" ldy #$offset | $compare ${asmgen.asmVariableName(value.variable.name)},y") return asmgen.out(" ldy #$offset | $compare ${asmgen.asmVariableName(value.variable)},y")
} }
} }
cmpViaScratch() cmpViaScratch()
@@ -337,7 +337,7 @@ internal class IfElseAsmGen(private val program: PtProgram,
} }
} }
is PtIdentifier -> { is PtIdentifier -> {
asmgen.out(" $compare ${asmgen.asmVariableName(value.name)}") asmgen.out(" $compare ${asmgen.asmVariableName(value)}")
} }
is PtNumber -> { is PtNumber -> {
if(value.number!=0.0) if(value.number!=0.0)
@@ -349,26 +349,50 @@ internal class IfElseAsmGen(private val program: PtProgram,
} }
} }
private fun translateByteGreater(leftOperand: PtExpression, rightOperand: PtExpression, stmt: PtIfElse, signed: Boolean, jumpAfterIf: PtJump?) { private fun translateByteLess(stmt: PtIfElse, signed: Boolean, jumpAfterIf: PtJump?) {
val condition = stmt.condition as PtBinaryExpression
asmgen.assignExpressionToRegister(condition.left, RegisterOrPair.A, signed)
cmpAwithByteValue(condition.right, false)
if(signed) { if(signed) {
// X>Y -> Y<X if(jumpAfterIf!=null)
asmgen.assignExpressionToRegister(rightOperand, RegisterOrPair.A, signed) translateJumpElseBodies("bmi", "bpl", jumpAfterIf, stmt.elseScope)
cmpAwithByteValue(leftOperand, true) else
translateIfElseBodies("bpl", stmt)
} else {
if(jumpAfterIf!=null)
translateJumpElseBodies("bcc", "bcs", jumpAfterIf, stmt.elseScope)
else
translateIfElseBodies("bcs", stmt)
}
}
private fun translateByteGreater(stmt: PtIfElse, signed: Boolean, jumpAfterIf: PtJump?) {
val condition = stmt.condition as PtBinaryExpression
if(signed) {
// TODO if compared to a number, a more optimized routine is possible (X>=Y+1)
// X>Y --> Y<X
asmgen.assignExpressionToRegister(condition.right, RegisterOrPair.A, signed)
cmpAwithByteValue(condition.left, true)
if (jumpAfterIf != null)
translateJumpElseBodies("bmi", "bpl", jumpAfterIf, stmt.elseScope)
else
translateIfElseBodies("bpl", stmt)
} else {
asmgen.assignExpressionToRegister(condition.left, RegisterOrPair.A, signed)
cmpAwithByteValue(condition.right, false)
if(jumpAfterIf!=null) { if(jumpAfterIf!=null) {
val (asmLabel, indirect) = asmgen.getJumpTarget(jumpAfterIf) val (asmLabel, indirect) = asmgen.getJumpTarget(jumpAfterIf)
if(indirect) { if(indirect) {
// X>Y -> Y<X
asmgen.out(""" asmgen.out("""
bvc + bcc +
eor #128 beq +
+ bpl +
jmp ($asmLabel) jmp ($asmLabel)
+""") +""")
} else { } else {
asmgen.out(""" asmgen.out("""
bvc + beq +
eor #128 bcs $asmLabel
+ bmi $asmLabel""") +""")
} }
asmgen.translate(stmt.elseScope) asmgen.translate(stmt.elseScope)
} else { } else {
@@ -376,33 +400,18 @@ internal class IfElseAsmGen(private val program: PtProgram,
if(stmt.hasElse()) { if(stmt.hasElse()) {
// if and else blocks // if and else blocks
val elseLabel = asmgen.makeLabel("else") val elseLabel = asmgen.makeLabel("else")
asmgen.out(""" asmgen.out(" bcc $elseLabel | beq $elseLabel")
bvc +
eor #128
+ bpl $elseLabel""")
asmgen.translate(stmt.ifScope) asmgen.translate(stmt.ifScope)
asmgen.jmp(afterIfLabel, false) asmgen.jmp(afterIfLabel, false)
asmgen.out(elseLabel) asmgen.out(elseLabel)
asmgen.translate(stmt.elseScope) asmgen.translate(stmt.elseScope)
} else { } else {
// no else block // no else block
asmgen.out(""" asmgen.out(" bcc $afterIfLabel | beq $afterIfLabel")
bvc +
eor #128
+ bpl $afterIfLabel""")
asmgen.translate(stmt.ifScope) asmgen.translate(stmt.ifScope)
} }
asmgen.out(afterIfLabel) asmgen.out(afterIfLabel)
} }
} else {
// X>Y -> Y<X
asmgen.assignExpressionToRegister(rightOperand, RegisterOrPair.A, signed)
cmpAwithByteValue(leftOperand, false)
if(jumpAfterIf!=null) {
translateJumpElseBodies("bcc", "bcs", jumpAfterIf, stmt.elseScope)
} else {
translateIfElseBodies("bcs", stmt)
}
} }
} }

View File

@@ -1,6 +1,13 @@
TODO TODO
==== ====
fix large code for while wptr!=&buffer
explore possible optimizations when comparing to a constant number:
X < N --> X<=N-1
X > N --> X>=N+1 etc etc some yield shorter code!!
verify ifelse codegens to be shortest code: (some are using too many scratch vars?) verify ifelse codegens to be shortest code: (some are using too many scratch vars?)
uword >= uword >=
uword > uword >
@@ -12,7 +19,6 @@ word <=
word < word <
plasma is a bit larger
floatparse is a bit larger floatparse is a bit larger
testgfx2 is a bit larger testgfx2 is a bit larger
amiga is a bit larger amiga is a bit larger

View File

@@ -1,397 +1,48 @@
%import math
%import textio %import textio
%import floats
%import test_stack
%zeropage dontuse %zeropage dontuse
%option no_sysinit %option no_sysinit
main { main {
ubyte success = 0
str datatype = "uword"
uword @shared comparison
sub start() { sub start() {
txt.print("\ngreater-equal tests for: ") uword @shared wptr
txt.print(datatype) str buffer=" "
txt.nl()
test_stack.test() ; TODO: these generate LARGE code
txt.print("\n>=number: ") while wptr!=&buffer
test_cmp_number() cx16.r0L++
/* while wptr==&buffer
txt.print("\n>=var: ") cx16.r0L++
test_cmp_var()
txt.print("\n>=array[]: ") ; ... these are fine:
test_cmp_array() while wptr!=cx16.r0
txt.print("\n>=expr: ") cx16.r0L++
test_cmp_expr() while wptr==cx16.r0
*/ cx16.r0L++
test_stack.test()
if ub() > 5
cx16.r0L++
if ub() < 5
cx16.r0L++
if sb() > 5
cx16.r0L++
if sb() < 5
cx16.r0L++
} }
sub verify_success(ubyte expected) { sub ub() -> ubyte {
if success==expected { cx16.r0++
txt.print_ub(success) return cx16.r0L
txt.print(" successes ok")
} else {
txt.print(" **failed** ")
txt.print_ub(success)
txt.print(" success, expected ")
txt.print_ub(expected)
}
} }
sub fail_byte(uword idx) { sub sb() -> byte {
txt.print(" **fail#") cx16.r0++
txt.print_uw(idx) return cx16.r0sL
txt.print(" **")
} }
sub fail_ubyte(uword idx) {
txt.print(" **fail#")
txt.print_uw(idx)
txt.print(" **")
}
sub fail_word(uword idx) {
txt.print(" **fail#")
txt.print_uw(idx)
txt.print(" **")
}
sub fail_uword(uword idx) {
txt.print(" **fail#")
txt.print_uw(idx)
txt.print(" **")
}
sub fail_float(uword idx) {
txt.print(" **fail#")
txt.print_uw(idx)
txt.print(" **")
}
sub test_cmp_number() {
uword @shared x = 65500
if x>=65500
goto lbl4a
goto skip4a
lbl4a: txt.print("should see this!\n")
skip4a:
}
/*
sub test_cmp_var() {
uword @shared x, value
success = 0
x=0
value=0
; direct jump
if x>=value
goto lbl1a
goto skip1a
lbl1a: success++
skip1a:
; indirect jump
cx16.r3 = &lbl1b
if x>=value
goto cx16.r3
goto skip1b
lbl1b: success++
skip1b:
; no else
if x>=value
success++
; with else
if x>=value
success++
else
cx16.r0L++
value=65535
; direct jump
if x>=value
goto lbl2a
goto skip2a
lbl2a: fail_uword(5)
skip2a:
; indirect jump
cx16.r3 = &lbl2b
if x>=value
goto cx16.r3
goto skip2b
lbl2b: fail_uword(6)
skip2b:
; no else
if x>=value
fail_uword(7)
; with else
if x>=value
fail_uword(8)
else
success++
x=65535
value=0
; direct jump
if x>=value
goto lbl3a
goto skip3a
lbl3a: success++
skip3a:
; indirect jump
cx16.r3 = &lbl3b
if x>=value
goto cx16.r3
goto skip3b
lbl3b: success++
skip3b:
; no else
if x>=value
success++
; with else
if x>=value
success++
else
cx16.r0L++
value=65535
; direct jump
if x>=value
goto lbl4a
goto skip4a
lbl4a: success++
skip4a:
; indirect jump
cx16.r3 = &lbl4b
if x>=value
goto cx16.r3
goto skip4b
lbl4b: success++
skip4b:
; no else
if x>=value
success++
; with else
if x>=value
success++
else
cx16.r0L++
verify_success(13)
}
sub test_cmp_array() {
uword @shared x
uword[] values = [0, 0]
success = 0
x=0
values[1]=0
; direct jump
if x>=values[1]
goto lbl1a
goto skip1a
lbl1a: success++
skip1a:
; indirect jump
cx16.r3 = &lbl1b
if x>=values[1]
goto cx16.r3
goto skip1b
lbl1b: success++
skip1b:
; no else
if x>=values[1]
success++
; with else
if x>=values[1]
success++
else
cx16.r0L++
values[1]=65535
; direct jump
if x>=values[1]
goto lbl2a
goto skip2a
lbl2a: fail_uword(9)
skip2a:
; indirect jump
cx16.r3 = &lbl2b
if x>=values[1]
goto cx16.r3
goto skip2b
lbl2b: fail_uword(10)
skip2b:
; no else
if x>=values[1]
fail_uword(11)
; with else
if x>=values[1]
fail_uword(12)
else
success++
x=65535
values[1]=0
; direct jump
if x>=values[1]
goto lbl3a
goto skip3a
lbl3a: success++
skip3a:
; indirect jump
cx16.r3 = &lbl3b
if x>=values[1]
goto cx16.r3
goto skip3b
lbl3b: success++
skip3b:
; no else
if x>=values[1]
success++
; with else
if x>=values[1]
success++
else
cx16.r0L++
values[1]=65535
; direct jump
if x>=values[1]
goto lbl4a
goto skip4a
lbl4a: success++
skip4a:
; indirect jump
cx16.r3 = &lbl4b
if x>=values[1]
goto cx16.r3
goto skip4b
lbl4b: success++
skip4b:
; no else
if x>=values[1]
success++
; with else
if x>=values[1]
success++
else
cx16.r0L++
verify_success(13)
}
sub test_cmp_expr() {
uword @shared x
cx16.r4 = 1
cx16.r5 = 1
float @shared f4 = 1.0
float @shared f5 = 1.0
success = 0
x=0
; direct jump
if x>=cx16.r4+0-cx16.r5
goto lbl1a
goto skip1a
lbl1a: success++
skip1a:
; indirect jump
cx16.r3 = &lbl1b
if x>=cx16.r4+0-cx16.r5
goto cx16.r3
goto skip1b
lbl1b: success++
skip1b:
; no else
if x>=cx16.r4+0-cx16.r5
success++
; with else
if x>=cx16.r4+0-cx16.r5
success++
else
cx16.r0L++
; direct jump
if x>=cx16.r4+65535-cx16.r5
goto lbl2a
goto skip2a
lbl2a: fail_uword(13)
skip2a:
; indirect jump
cx16.r3 = &lbl2b
if x>=cx16.r4+65535-cx16.r5
goto cx16.r3
goto skip2b
lbl2b: fail_uword(14)
skip2b:
; no else
if x>=cx16.r4+65535-cx16.r5
fail_uword(15)
; with else
if x>=cx16.r4+65535-cx16.r5
fail_uword(16)
else
success++
x=65535
; direct jump
if x>=cx16.r4+0-cx16.r5
goto lbl3a
goto skip3a
lbl3a: success++
skip3a:
; indirect jump
cx16.r3 = &lbl3b
if x>=cx16.r4+0-cx16.r5
goto cx16.r3
goto skip3b
lbl3b: success++
skip3b:
; no else
if x>=cx16.r4+0-cx16.r5
success++
; with else
if x>=cx16.r4+0-cx16.r5
success++
else
cx16.r0L++
; direct jump
if x>=cx16.r4+65535-cx16.r5
goto lbl4a
goto skip4a
lbl4a: success++
skip4a:
; indirect jump
cx16.r3 = &lbl4b
if x>=cx16.r4+65535-cx16.r5
goto cx16.r3
goto skip4b
lbl4b: success++
skip4b:
; no else
if x>=cx16.r4+65535-cx16.r5
success++
; with else
if x>=cx16.r4+65535-cx16.r5
success++
else
cx16.r0L++
verify_success(13)
}
*/
} }