mirror of
https://github.com/irmen/prog8.git
synced 2024-12-27 05:29:38 +00:00
comparisonjump tweak
This commit is contained in:
parent
03ac9b6956
commit
61fa3bc77c
@ -982,7 +982,7 @@ class AsmGen(private val program: Program,
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun translate(stmt: IfStatement) {
|
private fun translate(stmt: IfStatement) {
|
||||||
checkBooleanExpression(stmt.condition) // we require the condition to be of the form 'x <comparison> <value>'
|
requireComparisonExpression(stmt.condition) // IfStatement: condition must be of form 'x <comparison> <value>'
|
||||||
val booleanCondition = stmt.condition as BinaryExpression
|
val booleanCondition = stmt.condition as BinaryExpression
|
||||||
|
|
||||||
// DISABLED FOR NOW:
|
// DISABLED FOR NOW:
|
||||||
@ -1008,9 +1008,9 @@ class AsmGen(private val program: Program,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkBooleanExpression(condition: Expression) {
|
private fun requireComparisonExpression(condition: Expression) {
|
||||||
if(condition !is BinaryExpression || condition.operator !in comparisonOperators)
|
if(condition !is BinaryExpression || condition.operator !in comparisonOperators)
|
||||||
throw AssemblyError("expected boolean expression $condition")
|
throw AssemblyError("expected boolean comparison expression $condition")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun translate(stmt: RepeatLoop) {
|
private fun translate(stmt: RepeatLoop) {
|
||||||
@ -1161,7 +1161,7 @@ $repeatLabel lda $counterVar
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun translate(stmt: WhileLoop) {
|
private fun translate(stmt: WhileLoop) {
|
||||||
checkBooleanExpression(stmt.condition) // we require the condition to be of the form 'x <comparison> <value>'
|
requireComparisonExpression(stmt.condition) // WhileLoop: condition must be of form 'x <comparison> <value>'
|
||||||
val booleanCondition = stmt.condition as BinaryExpression
|
val booleanCondition = stmt.condition as BinaryExpression
|
||||||
val whileLabel = makeLabel("while")
|
val whileLabel = makeLabel("while")
|
||||||
val endLabel = makeLabel("whileend")
|
val endLabel = makeLabel("whileend")
|
||||||
@ -1175,7 +1175,7 @@ $repeatLabel lda $counterVar
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun translate(stmt: UntilLoop) {
|
private fun translate(stmt: UntilLoop) {
|
||||||
checkBooleanExpression(stmt.condition) // we require the condition to be of the form 'x <comparison> <value>'
|
requireComparisonExpression(stmt.condition) // UntilLoop: condition must be of form 'x <comparison> <value>'
|
||||||
val booleanCondition = stmt.condition as BinaryExpression
|
val booleanCondition = stmt.condition as BinaryExpression
|
||||||
val repeatLabel = makeLabel("repeat")
|
val repeatLabel = makeLabel("repeat")
|
||||||
val endLabel = makeLabel("repeatend")
|
val endLabel = makeLabel("repeatend")
|
||||||
|
@ -33,13 +33,16 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal fun translateComparisonExpressionWithJumpIfFalse(expr: BinaryExpression, jumpIfFalseLabel: String) {
|
internal fun translateComparisonExpressionWithJumpIfFalse(expr: BinaryExpression, jumpIfFalseLabel: String) {
|
||||||
// This is a helper routine called from while, do-util, and if expressions to generate optimized conditional branching code.
|
// This is a helper routine called from while, do-util, and if expressions to generate optimized conditional branching code.
|
||||||
// First, if it is of the form: <constvalue> <comparison> X , then flip the expression so the constant is always the right operand.
|
// First, if it is of the form: <constvalue> <comparison> X , then flip the expression so the constant is always the right operand.
|
||||||
|
|
||||||
var left = expr.left
|
var left = expr.left
|
||||||
var right = expr.right
|
var right = expr.right
|
||||||
var operator = expr.operator
|
var operator = expr.operator
|
||||||
var leftConstVal = left.constValue(program)
|
var leftConstVal = left.constValue(program)
|
||||||
var rightConstVal = right.constValue(program)
|
var rightConstVal = right.constValue(program)
|
||||||
|
|
||||||
|
// make sure the constant value is on the right of the comparison expression
|
||||||
if(leftConstVal!=null) {
|
if(leftConstVal!=null) {
|
||||||
val tmp = left
|
val tmp = left
|
||||||
left = right
|
left = right
|
||||||
@ -55,32 +58,90 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val idt = left.inferType(program)
|
if (rightConstVal!=null && rightConstVal.number.toDouble() == 0.0)
|
||||||
if(!idt.isKnown)
|
jumpIfZeroOrNot(left, operator, right, jumpIfFalseLabel, leftConstVal, rightConstVal)
|
||||||
throw AssemblyError("unknown dt")
|
else
|
||||||
val dt = idt.getOr(DataType.UNDEFINED)
|
jumpIfComparison(left, operator, right, jumpIfFalseLabel, leftConstVal, rightConstVal)
|
||||||
when (operator) {
|
}
|
||||||
"==" -> {
|
|
||||||
// if the left operand is an expression, and the right is 0, we can just evaluate that expression,
|
private fun jumpIfZeroOrNot(
|
||||||
// and use the result value directly to determine the boolean result. Shortcut only for integers.
|
left: Expression,
|
||||||
if(rightConstVal?.number?.toDouble() == 0.0) {
|
operator: String,
|
||||||
if(dt in ByteDatatypes) {
|
right: Expression,
|
||||||
asmgen.assignExpressionToRegister(left, RegisterOrPair.A)
|
jumpIfFalseLabel: String,
|
||||||
if(left is FunctionCall && !left.isSimple)
|
leftConstVal: NumericLiteralValue?,
|
||||||
|
rightConstVal: NumericLiteralValue?
|
||||||
|
) {
|
||||||
|
val dt = left.inferType(program).getOrElse { throw AssemblyError("unknown dt") }
|
||||||
|
when(dt) {
|
||||||
|
DataType.UBYTE, DataType.BYTE -> {
|
||||||
|
asmgen.assignExpressionToRegister(left, RegisterOrPair.A)
|
||||||
|
when (operator) {
|
||||||
|
"==", "!=" -> {
|
||||||
|
// simple zero (in)equality check
|
||||||
|
if (left is FunctionCall && !left.isSimple)
|
||||||
asmgen.out(" cmp #0")
|
asmgen.out(" cmp #0")
|
||||||
asmgen.out(" bne $jumpIfFalseLabel")
|
if (operator == "==")
|
||||||
return
|
asmgen.out(" bne $jumpIfFalseLabel")
|
||||||
|
else
|
||||||
|
asmgen.out(" beq $jumpIfFalseLabel")
|
||||||
}
|
}
|
||||||
else if(dt in WordDatatypes) {
|
else -> {
|
||||||
asmgen.assignExpressionToRegister(left, RegisterOrPair.AY)
|
// TODO optimize byte other operators
|
||||||
asmgen.out("""
|
jumpIfComparison(left, operator, right, jumpIfFalseLabel, leftConstVal, rightConstVal)
|
||||||
sty P8ZP_SCRATCH_B1
|
|
||||||
ora P8ZP_SCRATCH_B1
|
|
||||||
bne $jumpIfFalseLabel""")
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
DataType.UWORD, DataType.WORD -> {
|
||||||
|
asmgen.assignExpressionToRegister(left, RegisterOrPair.AY)
|
||||||
|
when (operator) {
|
||||||
|
"==" -> {
|
||||||
|
asmgen.out(" sty P8ZP_SCRATCH_B1 | ora P8ZP_SCRATCH_B1 | bne $jumpIfFalseLabel")
|
||||||
|
}
|
||||||
|
"!=" -> {
|
||||||
|
asmgen.out(" sty P8ZP_SCRATCH_B1 | ora P8ZP_SCRATCH_B1 | beq $jumpIfFalseLabel")
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
// TODO optimize word other operators
|
||||||
|
jumpIfComparison(left, operator, right, jumpIfFalseLabel, leftConstVal, rightConstVal)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DataType.FLOAT -> {
|
||||||
|
asmgen.assignExpressionToRegister(left, RegisterOrPair.FAC1)
|
||||||
|
when (operator) {
|
||||||
|
"==" -> {
|
||||||
|
asmgen.out(" jsr floats.SIGN") // SIGN(fac1) to A, $ff, $0, $1 for negative, zero, positive
|
||||||
|
asmgen.out(" bne $jumpIfFalseLabel")
|
||||||
|
}
|
||||||
|
"!=" -> {
|
||||||
|
asmgen.out(" jsr floats.SIGN") // SIGN(fac1) to A, $ff, $0, $1 for negative, zero, positive
|
||||||
|
asmgen.out(" beq $jumpIfFalseLabel")
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
// TODO optimize float other operators?
|
||||||
|
jumpIfComparison(left, operator, right, jumpIfFalseLabel, leftConstVal, rightConstVal)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
throw AssemblyError("invalid dt")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun jumpIfComparison(
|
||||||
|
left: Expression,
|
||||||
|
operator: String,
|
||||||
|
right: Expression,
|
||||||
|
jumpIfFalseLabel: String,
|
||||||
|
leftConstVal: NumericLiteralValue?,
|
||||||
|
rightConstVal: NumericLiteralValue?
|
||||||
|
) {
|
||||||
|
val dt = left.inferType(program).getOrElse { throw AssemblyError("unknown dt") }
|
||||||
|
|
||||||
|
when (operator) {
|
||||||
|
"==" -> {
|
||||||
when (dt) {
|
when (dt) {
|
||||||
in ByteDatatypes -> translateByteEqualsJump(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel)
|
in ByteDatatypes -> translateByteEqualsJump(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel)
|
||||||
in WordDatatypes -> translateWordEqualsJump(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel)
|
in WordDatatypes -> translateWordEqualsJump(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel)
|
||||||
@ -90,26 +151,6 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
"!=" -> {
|
"!=" -> {
|
||||||
// if the left operand is an expression, and the right is 0, we can just evaluate that expression,
|
|
||||||
// and use the result value directly to determine the boolean result. Shortcut only for integers.
|
|
||||||
if(rightConstVal?.number?.toDouble() == 0.0) {
|
|
||||||
if(dt in ByteDatatypes) {
|
|
||||||
asmgen.assignExpressionToRegister(left, RegisterOrPair.A)
|
|
||||||
if(left is FunctionCall && !left.isSimple)
|
|
||||||
asmgen.out(" cmp #0")
|
|
||||||
asmgen.out(" beq $jumpIfFalseLabel")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
else if(dt in WordDatatypes) {
|
|
||||||
asmgen.assignExpressionToRegister(left, RegisterOrPair.AY)
|
|
||||||
asmgen.out("""
|
|
||||||
sty P8ZP_SCRATCH_B1
|
|
||||||
ora P8ZP_SCRATCH_B1
|
|
||||||
beq $jumpIfFalseLabel""")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
when (dt) {
|
when (dt) {
|
||||||
in ByteDatatypes -> translateByteNotEqualsJump(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel)
|
in ByteDatatypes -> translateByteNotEqualsJump(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel)
|
||||||
in WordDatatypes -> translateWordNotEqualsJump(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel)
|
in WordDatatypes -> translateWordNotEqualsJump(left, right, leftConstVal, rightConstVal, jumpIfFalseLabel)
|
||||||
|
@ -1,41 +1,55 @@
|
|||||||
%import string
|
%import floats
|
||||||
%import textio
|
%import textio
|
||||||
%zeropage basicsafe
|
%zeropage basicsafe
|
||||||
|
|
||||||
main {
|
main {
|
||||||
|
|
||||||
sub start() {
|
sub start() {
|
||||||
uword[] values = [1111,2222,3333,4444]
|
ubyte xx
|
||||||
|
float ff
|
||||||
|
|
||||||
@($2000) = 'a'
|
ff=0
|
||||||
@($2001) = 'b'
|
|
||||||
@($2002) = 'c'
|
|
||||||
@($2003) = 0
|
|
||||||
|
|
||||||
asmfunc([999,888,777])
|
if ff==0 {
|
||||||
asmfunc(values)
|
txt.print("ff=0\n")
|
||||||
asmfunc($2000)
|
}
|
||||||
txt.nl()
|
if ff!=0 {
|
||||||
func([999,888,777])
|
txt.print("ff!=0 (error!)\n")
|
||||||
func(values)
|
}
|
||||||
func($2000)
|
ff=-0.22
|
||||||
}
|
if ff==0 {
|
||||||
|
txt.print("ff=0 (error!)\n")
|
||||||
|
}
|
||||||
|
if ff!=0 {
|
||||||
|
txt.print("ff!=0\n")
|
||||||
|
}
|
||||||
|
|
||||||
asmsub asmfunc(uword[] thing @AY) {
|
|
||||||
%asm {{
|
|
||||||
sta func.thing
|
|
||||||
sty func.thing+1
|
|
||||||
jmp func
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub func(uword[] thing) {
|
if xx { ; doesn't use stack...
|
||||||
uword t2 = thing as uword
|
xx++
|
||||||
ubyte length = string.length(thing)
|
}
|
||||||
txt.print_uwhex(thing, true)
|
|
||||||
txt.nl()
|
xx = xx+1 ; doesn't use stack...
|
||||||
txt.print_ub(length)
|
|
||||||
txt.nl()
|
if 8<xx {
|
||||||
txt.print(thing)
|
}
|
||||||
txt.nl()
|
|
||||||
|
if xx+1 { ; TODO why does this use stack?
|
||||||
|
xx++
|
||||||
|
}
|
||||||
|
|
||||||
|
xx = xx & %0001 ; doesn't use stack...
|
||||||
|
|
||||||
|
if xx & %0001 { ; TODO why does this use stack?
|
||||||
|
xx--
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
xx++
|
||||||
|
} until xx+1
|
||||||
|
|
||||||
|
while xx+1 {
|
||||||
|
xx++
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user