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
translateIfElseBodies("beq", stmt)
}
"<" -> translateByteGreater(condition.right, condition.left, stmt, signed, jumpAfterIf)
"<" -> translateByteLess(stmt, signed, jumpAfterIf)
"<=" -> {
// X<=Y -> Y>=X (reverse of >=)
asmgen.assignExpressionToRegister(condition.right, RegisterOrPair.A, signed)
@ -150,7 +150,7 @@ internal class IfElseAsmGen(private val program: PtProgram,
translateIfElseBodies("bcc", stmt)
}
}
">" -> translateByteGreater(condition.left, condition.right, stmt, signed, jumpAfterIf)
">" -> translateByteGreater(stmt, signed, jumpAfterIf)
">=" -> {
asmgen.assignExpressionToRegister(condition.left, RegisterOrPair.A, signed)
cmpAwithByteValue(condition.right, false)
@ -323,7 +323,7 @@ internal class IfElseAsmGen(private val program: PtProgram,
if(constIndex!=null) {
val offset = constIndex * program.memsizer.memorySize(value.type)
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()
@ -337,7 +337,7 @@ internal class IfElseAsmGen(private val program: PtProgram,
}
}
is PtIdentifier -> {
asmgen.out(" $compare ${asmgen.asmVariableName(value.name)}")
asmgen.out(" $compare ${asmgen.asmVariableName(value)}")
}
is PtNumber -> {
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) {
// X>Y -> Y<X
asmgen.assignExpressionToRegister(rightOperand, RegisterOrPair.A, signed)
cmpAwithByteValue(leftOperand, true)
if(jumpAfterIf!=null)
translateJumpElseBodies("bmi", "bpl", jumpAfterIf, stmt.elseScope)
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) {
val (asmLabel, indirect) = asmgen.getJumpTarget(jumpAfterIf)
if(indirect) {
// X>Y -> Y<X
asmgen.out("""
bvc +
eor #128
+ bpl +
bcc +
beq +
jmp ($asmLabel)
+""")
} else {
asmgen.out("""
bvc +
eor #128
+ bmi $asmLabel""")
beq +
bcs $asmLabel
+""")
}
asmgen.translate(stmt.elseScope)
} else {
@ -376,33 +400,18 @@ internal class IfElseAsmGen(private val program: PtProgram,
if(stmt.hasElse()) {
// if and else blocks
val elseLabel = asmgen.makeLabel("else")
asmgen.out("""
bvc +
eor #128
+ bpl $elseLabel""")
asmgen.out(" bcc $elseLabel | beq $elseLabel")
asmgen.translate(stmt.ifScope)
asmgen.jmp(afterIfLabel, false)
asmgen.out(elseLabel)
asmgen.translate(stmt.elseScope)
} else {
// no else block
asmgen.out("""
bvc +
eor #128
+ bpl $afterIfLabel""")
asmgen.out(" bcc $afterIfLabel | beq $afterIfLabel")
asmgen.translate(stmt.ifScope)
}
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
====
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?)
uword >=
uword >
@ -12,7 +19,6 @@ word <=
word <
plasma is a bit larger
floatparse is a bit larger
testgfx2 is a bit larger
amiga is a bit larger

View File

@ -1,397 +1,48 @@
%import math
%import textio
%import floats
%import test_stack
%zeropage dontuse
%option no_sysinit
main {
ubyte success = 0
str datatype = "uword"
uword @shared comparison
sub start() {
txt.print("\ngreater-equal tests for: ")
txt.print(datatype)
txt.nl()
test_stack.test()
txt.print("\n>=number: ")
test_cmp_number()
/*
txt.print("\n>=var: ")
test_cmp_var()
txt.print("\n>=array[]: ")
test_cmp_array()
txt.print("\n>=expr: ")
test_cmp_expr()
*/
test_stack.test()
uword @shared wptr
str buffer=" "
; TODO: these generate LARGE code
while wptr!=&buffer
cx16.r0L++
while wptr==&buffer
cx16.r0L++
; ... these are fine:
while wptr!=cx16.r0
cx16.r0L++
while wptr==cx16.r0
cx16.r0L++
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) {
if success==expected {
txt.print_ub(success)
txt.print(" successes ok")
} else {
txt.print(" **failed** ")
txt.print_ub(success)
txt.print(" success, expected ")
txt.print_ub(expected)
}
sub ub() -> ubyte {
cx16.r0++
return cx16.r0L
}
sub fail_byte(uword idx) {
txt.print(" **fail#")
txt.print_uw(idx)
txt.print(" **")
sub sb() -> byte {
cx16.r0++
return cx16.r0sL
}
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)
}
*/
}