mirror of
https://github.com/irmen/prog8.git
synced 2024-06-11 11:29:31 +00:00
fix codegen error for comparisons
This commit is contained in:
parent
004048e5a7
commit
2a1fec2ed2
|
@ -26,7 +26,7 @@ internal class IfElseAsmGen(private val program: PtProgram,
|
|||
val compareCond = stmt.condition as? PtBinaryExpression
|
||||
if(compareCond!=null) {
|
||||
return when(compareCond.right.type) {
|
||||
in ByteDatatypesWithBoolean -> translateIfByte(stmt, compareCond, jumpAfterIf)
|
||||
in ByteDatatypesWithBoolean -> translateIfByte(stmt, jumpAfterIf)
|
||||
in WordDatatypes -> translateIfWord(stmt, compareCond, jumpAfterIf)
|
||||
DataType.FLOAT -> translateIfFloat(stmt, compareCond, jumpAfterIf)
|
||||
else -> throw AssemblyError("weird dt")
|
||||
|
@ -106,32 +106,19 @@ internal class IfElseAsmGen(private val program: PtProgram,
|
|||
asmgen.translate(elseBlock)
|
||||
}
|
||||
|
||||
private fun translateIfByte(stmt: PtIfElse, condition: PtBinaryExpression, jumpAfterIf: PtJump?) {
|
||||
private fun translateIfByte(stmt: PtIfElse, jumpAfterIf: PtJump?) {
|
||||
val condition = stmt.condition as PtBinaryExpression
|
||||
val signed = condition.left.type in SignedDatatypes
|
||||
val constValue = condition.right.asConstInteger()
|
||||
if(constValue==0) {
|
||||
if(condition.operator=="==") {
|
||||
// if X==0
|
||||
assignConditionValueToRegisterAndTest(condition.left)
|
||||
return if(jumpAfterIf!=null)
|
||||
translateJumpElseBodies("beq", "bne", jumpAfterIf, stmt.elseScope)
|
||||
else
|
||||
translateIfElseBodies("bne", stmt)
|
||||
} else if(condition.operator=="!=") {
|
||||
// if X!=0
|
||||
assignConditionValueToRegisterAndTest(condition.left)
|
||||
return if(jumpAfterIf!=null)
|
||||
translateJumpElseBodies("bne", "beq", jumpAfterIf, stmt.elseScope)
|
||||
else
|
||||
translateIfElseBodies("beq", stmt)
|
||||
}
|
||||
return translateIfCompareWithZeroByte(stmt, signed, jumpAfterIf)
|
||||
}
|
||||
|
||||
when (condition.operator) {
|
||||
"==" -> {
|
||||
// if X==value
|
||||
asmgen.assignExpressionToRegister(condition.left, RegisterOrPair.A, signed)
|
||||
cmpAwithByteValue(condition.right)
|
||||
cmpAwithByteValue(condition.right, false)
|
||||
return if(jumpAfterIf!=null)
|
||||
translateJumpElseBodies("beq", "bne", jumpAfterIf, stmt.elseScope)
|
||||
else
|
||||
|
@ -140,32 +127,33 @@ internal class IfElseAsmGen(private val program: PtProgram,
|
|||
"!=" -> {
|
||||
// if X!=value
|
||||
asmgen.assignExpressionToRegister(condition.left, RegisterOrPair.A, signed)
|
||||
cmpAwithByteValue(condition.right)
|
||||
cmpAwithByteValue(condition.right, false)
|
||||
return if(jumpAfterIf!=null)
|
||||
translateJumpElseBodies("bne", "beq", jumpAfterIf, stmt.elseScope)
|
||||
else
|
||||
translateIfElseBodies("beq", stmt)
|
||||
}
|
||||
"<" -> {
|
||||
asmgen.assignExpressionToRegister(condition.left, RegisterOrPair.A, signed)
|
||||
cmpAwithByteValue(condition.right)
|
||||
"<" -> translateByteGreater(condition.right, condition.left, stmt, signed, jumpAfterIf)
|
||||
"<=" -> {
|
||||
// X<=Y -> Y>=X (reverse of >=)
|
||||
asmgen.assignExpressionToRegister(condition.right, RegisterOrPair.A, signed)
|
||||
cmpAwithByteValue(condition.left, false)
|
||||
return if(signed) {
|
||||
if(jumpAfterIf!=null)
|
||||
translateJumpElseBodies("bmi", "bpl", jumpAfterIf, stmt.elseScope)
|
||||
translateJumpElseBodies("bpl", "bmi", jumpAfterIf, stmt.elseScope)
|
||||
else
|
||||
translateIfElseBodies("bpl", stmt)
|
||||
translateIfElseBodies("bmi", stmt)
|
||||
} else {
|
||||
if(jumpAfterIf!=null)
|
||||
translateJumpElseBodies("bcc", "bcs", jumpAfterIf, stmt.elseScope)
|
||||
translateJumpElseBodies("bcs", "bcc", jumpAfterIf, stmt.elseScope)
|
||||
else
|
||||
translateIfElseBodies("bcs", stmt)
|
||||
translateIfElseBodies("bcc", stmt)
|
||||
}
|
||||
}
|
||||
"<=" -> translateByteLessEqual(stmt, signed, jumpAfterIf)
|
||||
">" -> translateByteGreater(stmt, signed, jumpAfterIf)
|
||||
">" -> translateByteGreater(condition.left, condition.right, stmt, signed, jumpAfterIf)
|
||||
">=" -> {
|
||||
asmgen.assignExpressionToRegister(condition.left, RegisterOrPair.A, signed)
|
||||
cmpAwithByteValue(condition.right)
|
||||
cmpAwithByteValue(condition.right, false)
|
||||
return if(signed) {
|
||||
if(jumpAfterIf!=null)
|
||||
translateJumpElseBodies("bpl", "bmi", jumpAfterIf, stmt.elseScope)
|
||||
|
@ -182,7 +170,141 @@ internal class IfElseAsmGen(private val program: PtProgram,
|
|||
}
|
||||
}
|
||||
|
||||
private fun cmpAwithByteValue(value: PtExpression) {
|
||||
private fun translateIfCompareWithZeroByte(stmt: PtIfElse, signed: Boolean, jumpAfterIf: PtJump?) {
|
||||
// optimized code for byte comparisons with 0
|
||||
val condition = stmt.condition as PtBinaryExpression
|
||||
assignConditionValueToRegisterAndTest(condition.left)
|
||||
when (condition.operator) {
|
||||
"==" -> {
|
||||
return if(jumpAfterIf!=null)
|
||||
translateJumpElseBodies("beq", "bne", jumpAfterIf, stmt.elseScope)
|
||||
else
|
||||
translateIfElseBodies("bne", stmt)
|
||||
}
|
||||
"!=" -> {
|
||||
return if(jumpAfterIf!=null)
|
||||
translateJumpElseBodies("bne", "beq", jumpAfterIf, stmt.elseScope)
|
||||
else
|
||||
translateIfElseBodies("beq", stmt)
|
||||
}
|
||||
">" -> {
|
||||
if(signed) {
|
||||
return if (jumpAfterIf != null) {
|
||||
val (asmLabel, indirect) = asmgen.getJumpTarget(jumpAfterIf)
|
||||
if(indirect) {
|
||||
asmgen.out("""
|
||||
bmi +
|
||||
beq +
|
||||
jmp ($asmLabel)
|
||||
+""")
|
||||
} else {
|
||||
asmgen.out("""
|
||||
beq +
|
||||
bpl $asmLabel
|
||||
+""")
|
||||
}
|
||||
asmgen.translate(stmt.elseScope)
|
||||
}
|
||||
else {
|
||||
val afterIfLabel = asmgen.makeLabel("afterif")
|
||||
if(stmt.hasElse()) {
|
||||
// if and else blocks
|
||||
val elseLabel = asmgen.makeLabel("else")
|
||||
asmgen.out(" bmi $elseLabel | beq $elseLabel")
|
||||
asmgen.translate(stmt.ifScope)
|
||||
asmgen.jmp(afterIfLabel, false)
|
||||
asmgen.out(elseLabel)
|
||||
asmgen.translate(stmt.elseScope)
|
||||
} else {
|
||||
// no else block
|
||||
asmgen.out(" bmi $afterIfLabel | beq $afterIfLabel")
|
||||
asmgen.translate(stmt.ifScope)
|
||||
}
|
||||
asmgen.out(afterIfLabel)
|
||||
}
|
||||
} else {
|
||||
return if (jumpAfterIf != null)
|
||||
translateJumpElseBodies("bne", "beq", jumpAfterIf, stmt.elseScope)
|
||||
else
|
||||
translateIfElseBodies("beq", stmt)
|
||||
}
|
||||
}
|
||||
">=" -> {
|
||||
if(signed) {
|
||||
return if (jumpAfterIf != null)
|
||||
translateJumpElseBodies("bpl", "bmi", jumpAfterIf, stmt.elseScope)
|
||||
else
|
||||
translateIfElseBodies("bmi", stmt)
|
||||
} else {
|
||||
// always true for unsigned
|
||||
asmgen.translate(stmt.ifScope)
|
||||
}
|
||||
}
|
||||
"<" -> {
|
||||
if(signed) {
|
||||
return if (jumpAfterIf != null)
|
||||
translateJumpElseBodies("bmi", "bpl", jumpAfterIf, stmt.elseScope)
|
||||
else
|
||||
translateIfElseBodies("bpl", stmt)
|
||||
} else {
|
||||
// always false for unsigned
|
||||
asmgen.translate(stmt.elseScope)
|
||||
}
|
||||
}
|
||||
"<=" -> {
|
||||
if(signed) {
|
||||
// inverted '>'
|
||||
return if (jumpAfterIf != null) {
|
||||
val (asmLabel, indirect) = asmgen.getJumpTarget(jumpAfterIf)
|
||||
if(indirect) {
|
||||
asmgen.out("""
|
||||
bmi +
|
||||
bne ++
|
||||
+ jmp ($asmLabel)
|
||||
+""")
|
||||
} else {
|
||||
asmgen.out("""
|
||||
bmi $asmLabel
|
||||
beq $asmLabel""")
|
||||
}
|
||||
asmgen.translate(stmt.elseScope)
|
||||
}
|
||||
else {
|
||||
val afterIfLabel = asmgen.makeLabel("afterif")
|
||||
if(stmt.hasElse()) {
|
||||
// if and else blocks
|
||||
val elseLabel = asmgen.makeLabel("else")
|
||||
asmgen.out("""
|
||||
beq +
|
||||
bpl $elseLabel
|
||||
+""")
|
||||
asmgen.translate(stmt.ifScope)
|
||||
asmgen.jmp(afterIfLabel, false)
|
||||
asmgen.out(elseLabel)
|
||||
asmgen.translate(stmt.elseScope)
|
||||
} else {
|
||||
// no else block
|
||||
asmgen.out("""
|
||||
beq +
|
||||
bpl $afterIfLabel
|
||||
+""")
|
||||
asmgen.translate(stmt.ifScope)
|
||||
}
|
||||
asmgen.out(afterIfLabel)
|
||||
}
|
||||
} else {
|
||||
return if(jumpAfterIf!=null)
|
||||
translateJumpElseBodies("beq", "bne", jumpAfterIf, stmt.elseScope)
|
||||
else
|
||||
translateIfElseBodies("bne", stmt)
|
||||
}
|
||||
}
|
||||
else -> throw AssemblyError("weird operator")
|
||||
}
|
||||
}
|
||||
|
||||
private fun cmpAwithByteValue(value: PtExpression, useSbc: Boolean) {
|
||||
val compare = if(useSbc) "sec | sbc" else "cmp"
|
||||
fun cmpViaScratch() {
|
||||
if(assignmentAsmGen.directIntoY(value)) {
|
||||
asmgen.assignExpressionToRegister(value, RegisterOrPair.Y, false)
|
||||
|
@ -192,7 +314,7 @@ internal class IfElseAsmGen(private val program: PtProgram,
|
|||
asmgen.assignExpressionToVariable(value, "P8ZP_SCRATCH_REG", value.type)
|
||||
asmgen.out(" pla")
|
||||
}
|
||||
asmgen.out(" cmp P8ZP_SCRATCH_REG")
|
||||
asmgen.out(" $compare P8ZP_SCRATCH_REG")
|
||||
}
|
||||
|
||||
when(value) {
|
||||
|
@ -201,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 | cmp ${asmgen.asmVariableName(value.variable.name)},y")
|
||||
return asmgen.out(" ldy #$offset | $compare ${asmgen.asmVariableName(value.variable.name)},y")
|
||||
}
|
||||
}
|
||||
cmpViaScratch()
|
||||
|
@ -209,17 +331,17 @@ internal class IfElseAsmGen(private val program: PtProgram,
|
|||
is PtMemoryByte -> {
|
||||
val constAddr = value.address.asConstInteger()
|
||||
if(constAddr!=null) {
|
||||
asmgen.out(" cmp ${constAddr.toHex()}")
|
||||
asmgen.out(" $compare ${constAddr.toHex()}")
|
||||
} else {
|
||||
cmpViaScratch()
|
||||
}
|
||||
}
|
||||
is PtIdentifier -> {
|
||||
asmgen.out(" cmp ${asmgen.asmVariableName(value.name)}")
|
||||
asmgen.out(" $compare ${asmgen.asmVariableName(value.name)}")
|
||||
}
|
||||
is PtNumber -> {
|
||||
if(value.number!=0.0)
|
||||
asmgen.out(" cmp #${value.number.toInt()}")
|
||||
asmgen.out(" $compare #${value.number.toInt()}")
|
||||
}
|
||||
else -> {
|
||||
cmpViaScratch()
|
||||
|
@ -227,129 +349,59 @@ internal class IfElseAsmGen(private val program: PtProgram,
|
|||
}
|
||||
}
|
||||
|
||||
private fun translateByteLessEqual(stmt: PtIfElse, signed: Boolean, jumpAfterIf: PtJump?) {
|
||||
|
||||
fun bodies(greaterBranches: Pair<String, String>, stmt: PtIfElse) {
|
||||
// comparison value is already in A
|
||||
val afterIfLabel = asmgen.makeLabel("afterif")
|
||||
if(stmt.hasElse()) {
|
||||
// if and else blocks
|
||||
val elseLabel = asmgen.makeLabel("else")
|
||||
asmgen.out("""
|
||||
${greaterBranches.first} +
|
||||
${greaterBranches.second} $elseLabel
|
||||
private fun translateByteGreater(leftOperand: PtExpression, rightOperand: PtExpression, stmt: PtIfElse, signed: Boolean, jumpAfterIf: PtJump?) {
|
||||
if(signed) {
|
||||
// X>Y -> Y<X
|
||||
asmgen.assignExpressionToRegister(rightOperand, RegisterOrPair.A, signed)
|
||||
cmpAwithByteValue(leftOperand, true)
|
||||
if(jumpAfterIf!=null) {
|
||||
val (asmLabel, indirect) = asmgen.getJumpTarget(jumpAfterIf)
|
||||
if(indirect) {
|
||||
// X>Y -> Y<X
|
||||
asmgen.out("""
|
||||
bvc +
|
||||
eor #128
|
||||
+ bpl +
|
||||
jmp ($asmLabel)
|
||||
+""")
|
||||
asmgen.translate(stmt.ifScope)
|
||||
asmgen.jmp(afterIfLabel, false)
|
||||
asmgen.out(elseLabel)
|
||||
} else {
|
||||
asmgen.out("""
|
||||
bvc +
|
||||
eor #128
|
||||
+ bmi $asmLabel""")
|
||||
}
|
||||
asmgen.translate(stmt.elseScope)
|
||||
} else {
|
||||
// no else block
|
||||
asmgen.out("""
|
||||
${greaterBranches.first} +
|
||||
${greaterBranches.second} $afterIfLabel
|
||||
+""")
|
||||
asmgen.translate(stmt.ifScope)
|
||||
}
|
||||
asmgen.out(afterIfLabel)
|
||||
}
|
||||
|
||||
fun bodies(
|
||||
branches: Pair<String, String>,
|
||||
greaterBranches: Pair<String, String>,
|
||||
jump: PtJump,
|
||||
elseBlock: PtNodeGroup
|
||||
) {
|
||||
// comparison value is already in A
|
||||
val (asmLabel, indirect) = asmgen.getJumpTarget(jump)
|
||||
if(indirect) {
|
||||
asmgen.out("""
|
||||
${greaterBranches.first} +
|
||||
${greaterBranches.second} ++
|
||||
+ jmp ($asmLabel)
|
||||
+""")
|
||||
} else {
|
||||
asmgen.out(" ${branches.first} $asmLabel | ${branches.second} $asmLabel")
|
||||
}
|
||||
asmgen.translate(elseBlock)
|
||||
}
|
||||
|
||||
val condition = stmt.condition as PtBinaryExpression
|
||||
asmgen.assignExpressionToRegister(condition.left, RegisterOrPair.A, signed)
|
||||
cmpAwithByteValue(condition.right)
|
||||
if(signed) {
|
||||
if(jumpAfterIf!=null) {
|
||||
bodies("bmi" to "beq", "beq" to "bpl", jumpAfterIf, stmt.elseScope)
|
||||
} else {
|
||||
bodies("beq" to "bpl", stmt)
|
||||
val afterIfLabel = asmgen.makeLabel("afterif")
|
||||
if(stmt.hasElse()) {
|
||||
// if and else blocks
|
||||
val elseLabel = asmgen.makeLabel("else")
|
||||
asmgen.out("""
|
||||
bvc +
|
||||
eor #128
|
||||
+ bpl $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.translate(stmt.ifScope)
|
||||
}
|
||||
asmgen.out(afterIfLabel)
|
||||
}
|
||||
} else {
|
||||
// X>Y -> Y<X
|
||||
asmgen.assignExpressionToRegister(rightOperand, RegisterOrPair.A, signed)
|
||||
cmpAwithByteValue(leftOperand, false)
|
||||
if(jumpAfterIf!=null) {
|
||||
bodies("bcc" to "beq", "beq" to "bcs", jumpAfterIf, stmt.elseScope)
|
||||
translateJumpElseBodies("bcc", "bcs", jumpAfterIf, stmt.elseScope)
|
||||
} else {
|
||||
bodies("beq" to "bcs", stmt)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun translateByteGreater(stmt: PtIfElse, signed: Boolean, jumpAfterIf: PtJump?) {
|
||||
|
||||
fun bodies(lessEqBranches: Pair<String, String>, stmt: PtIfElse) {
|
||||
// comparison value is already in A
|
||||
val afterIfLabel = asmgen.makeLabel("afterif")
|
||||
if(stmt.hasElse()) {
|
||||
// if and else blocks
|
||||
val elseLabel = asmgen.makeLabel("else")
|
||||
asmgen.out(" ${lessEqBranches.first} $elseLabel | ${lessEqBranches.second} $elseLabel")
|
||||
asmgen.translate(stmt.ifScope)
|
||||
asmgen.jmp(afterIfLabel, false)
|
||||
asmgen.out(elseLabel)
|
||||
asmgen.translate(stmt.elseScope)
|
||||
} else {
|
||||
// no else block
|
||||
asmgen.out(" ${lessEqBranches.first} $afterIfLabel | ${lessEqBranches.second} $afterIfLabel")
|
||||
asmgen.translate(stmt.ifScope)
|
||||
}
|
||||
asmgen.out(afterIfLabel)
|
||||
}
|
||||
|
||||
fun bodies(
|
||||
branches: Pair<String, String>,
|
||||
lessEqBranches: Pair<String, String>,
|
||||
jump: PtJump,
|
||||
elseBlock: PtNodeGroup
|
||||
) {
|
||||
// comparison value is already in A
|
||||
val (asmLabel, indirect) = asmgen.getJumpTarget(jump)
|
||||
if(indirect) {
|
||||
asmgen.out("""
|
||||
${lessEqBranches.first} +
|
||||
${lessEqBranches.second} +
|
||||
jmp ($asmLabel)
|
||||
+""")
|
||||
} else {
|
||||
asmgen.out("""
|
||||
${branches.first} +
|
||||
${branches.second} $asmLabel
|
||||
+""")
|
||||
}
|
||||
asmgen.translate(elseBlock)
|
||||
}
|
||||
|
||||
val condition = stmt.condition as PtBinaryExpression
|
||||
asmgen.assignExpressionToRegister(condition.left, RegisterOrPair.A, signed)
|
||||
cmpAwithByteValue(condition.right)
|
||||
if(signed) {
|
||||
if(jumpAfterIf!=null) {
|
||||
bodies("beq" to "bpl", "bmi" to "beq", jumpAfterIf, stmt.elseScope)
|
||||
} else {
|
||||
bodies("bmi" to "beq", stmt)
|
||||
}
|
||||
} else {
|
||||
if(jumpAfterIf!=null) {
|
||||
bodies("beq" to "bcs", "bcc" to "beq", jumpAfterIf, stmt.elseScope)
|
||||
} else {
|
||||
bodies("bcc" to "beq", stmt)
|
||||
translateIfElseBodies("bcs", stmt)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -520,7 +572,7 @@ _jump jmp ($asmLabel)
|
|||
if(right is PtIdentifier) {
|
||||
asmgen.assignExpressionToRegister(left, RegisterOrPair.AY, signed)
|
||||
val variable = asmgen.asmVariableName(right)
|
||||
return code("#<$variable", "#>$variable")
|
||||
return code(variable, variable+"+1")
|
||||
}
|
||||
|
||||
// TODO optimize for simple array value
|
||||
|
@ -665,7 +717,7 @@ _jump jmp ($asmLabel)
|
|||
if(right is PtIdentifier) {
|
||||
asmgen.assignExpressionToRegister(left, RegisterOrPair.AY, signed)
|
||||
val variable = asmgen.asmVariableName(right)
|
||||
return code("#<$variable", "#>$variable")
|
||||
return code(variable, variable+"+1")
|
||||
}
|
||||
|
||||
// TODO optimize for simple array value
|
||||
|
@ -754,8 +806,8 @@ _jump jmp ($asmLabel)
|
|||
sbc $valueMsb
|
||||
ora P8ZP_SCRATCH_REG
|
||||
beq +
|
||||
bcc +
|
||||
jmp ($asmLabel)
|
||||
bcs ++
|
||||
+ jmp ($asmLabel)
|
||||
+""")
|
||||
} else {
|
||||
asmgen.out("""
|
||||
|
@ -765,9 +817,8 @@ _jump jmp ($asmLabel)
|
|||
tya
|
||||
sbc $valueMsb
|
||||
ora P8ZP_SCRATCH_REG
|
||||
beq +
|
||||
bcs $asmLabel
|
||||
+""")
|
||||
beq $asmLabel
|
||||
bcc $asmLabel""")
|
||||
}
|
||||
} else {
|
||||
val afterIfLabel = asmgen.makeLabel("afterif")
|
||||
|
@ -782,7 +833,7 @@ _jump jmp ($asmLabel)
|
|||
sbc $valueMsb
|
||||
ora P8ZP_SCRATCH_REG
|
||||
beq +
|
||||
bcc $elseLabel
|
||||
bcs $elseLabel
|
||||
+""")
|
||||
asmgen.translate(stmt.ifScope)
|
||||
asmgen.jmp(afterIfLabel, false)
|
||||
|
@ -798,7 +849,7 @@ _jump jmp ($asmLabel)
|
|||
sbc $valueMsb
|
||||
ora P8ZP_SCRATCH_REG
|
||||
beq +
|
||||
bcc $afterIfLabel
|
||||
bcs $afterIfLabel
|
||||
+""")
|
||||
asmgen.translate(stmt.ifScope)
|
||||
}
|
||||
|
@ -816,7 +867,7 @@ _jump jmp ($asmLabel)
|
|||
if(right is PtIdentifier) {
|
||||
asmgen.assignExpressionToRegister(left, RegisterOrPair.AY, signed)
|
||||
val variable = asmgen.asmVariableName(right)
|
||||
return code("#<$variable", "#>$variable")
|
||||
return code(variable, variable+"+1")
|
||||
}
|
||||
|
||||
// TODO optimize for simple array value
|
||||
|
@ -838,7 +889,7 @@ _jump jmp ($asmLabel)
|
|||
cmp $valueLsb
|
||||
tya
|
||||
sbc $valueMsb
|
||||
bvc +
|
||||
bvs +
|
||||
eor #128
|
||||
+ bpl +
|
||||
jmp ($asmLabel)
|
||||
|
@ -890,7 +941,7 @@ _jump jmp ($asmLabel)
|
|||
cmp $valueLsb
|
||||
tya
|
||||
sbc $valueMsb
|
||||
bcs +
|
||||
bcc +
|
||||
jmp ($asmLabel)
|
||||
+""")
|
||||
} else {
|
||||
|
@ -937,7 +988,7 @@ _jump jmp ($asmLabel)
|
|||
if(right is PtIdentifier) {
|
||||
asmgen.assignExpressionToRegister(left, RegisterOrPair.AY, signed)
|
||||
val variable = asmgen.asmVariableName(right)
|
||||
return code("#<$variable", "#>$variable")
|
||||
return code(variable, variable+"+1")
|
||||
}
|
||||
|
||||
// TODO optimize for simple array value
|
||||
|
|
|
@ -6,10 +6,10 @@ package prog8.buildversion
|
|||
const val MAVEN_GROUP = "prog8"
|
||||
const val MAVEN_NAME = "compiler"
|
||||
const val VERSION = "10.2-BOOLEANS"
|
||||
const val GIT_REVISION = 4485
|
||||
const val GIT_SHA = "eddf97191959f87119c746d8833b71a247db661d"
|
||||
const val GIT_DATE = "2024-02-15T23:58:56Z"
|
||||
const val GIT_REVISION = 4512
|
||||
const val GIT_SHA = "a977e3402faab7f2b63af7127fd628cbbdb8a7ad"
|
||||
const val GIT_DATE = "2024-02-25T15:41:16Z"
|
||||
const val GIT_BRANCH = "booleans"
|
||||
const val BUILD_DATE = "2024-02-16T00:19:00Z"
|
||||
const val BUILD_UNIX_TIME = 1708042740125L
|
||||
const val BUILD_DATE = "2024-02-25T16:07:25Z"
|
||||
const val BUILD_UNIX_TIME = 1708877245670L
|
||||
const val DIRTY = 1
|
||||
|
|
|
@ -153,6 +153,11 @@ internal class AstChecker(private val program: Program,
|
|||
if(!ifElse.condition.inferType(program).isBool)
|
||||
errors.err("condition should be a boolean", ifElse.condition.position)
|
||||
|
||||
val constvalue = ifElse.condition.constValue(program)
|
||||
if(constvalue!=null) {
|
||||
errors.warn("condition is always ${constvalue.asBooleanValue}", ifElse.condition.position)
|
||||
}
|
||||
|
||||
super.visit(ifElse)
|
||||
}
|
||||
|
||||
|
|
|
@ -54,53 +54,33 @@ main {{
|
|||
}}
|
||||
}}
|
||||
|
||||
sub fail_byte(uword idx, byte v1, byte v2) {{
|
||||
sub fail_byte(uword idx) {{
|
||||
txt.print(" **fail#")
|
||||
txt.print_uw(idx)
|
||||
txt.chrout(':')
|
||||
txt.print_b(v1)
|
||||
txt.chrout(',')
|
||||
txt.print_b(v2)
|
||||
txt.print(" **")
|
||||
}}
|
||||
|
||||
sub fail_ubyte(uword idx, ubyte v1, ubyte v2) {{
|
||||
sub fail_ubyte(uword idx) {{
|
||||
txt.print(" **fail#")
|
||||
txt.print_uw(idx)
|
||||
txt.chrout(':')
|
||||
txt.print_ub(v1)
|
||||
txt.chrout(',')
|
||||
txt.print_ub(v2)
|
||||
txt.print(" **")
|
||||
}}
|
||||
|
||||
sub fail_word(uword idx, word v1, word v2) {{
|
||||
sub fail_word(uword idx) {{
|
||||
txt.print(" **fail#")
|
||||
txt.print_uw(idx)
|
||||
txt.chrout(':')
|
||||
txt.print_w(v1)
|
||||
txt.chrout(',')
|
||||
txt.print_w(v2)
|
||||
txt.print(" **")
|
||||
}}
|
||||
|
||||
sub fail_uword(uword idx, uword v1, uword v2) {{
|
||||
sub fail_uword(uword idx) {{
|
||||
txt.print(" **fail#")
|
||||
txt.print_uw(idx)
|
||||
txt.chrout(':')
|
||||
txt.print_uw(v1)
|
||||
txt.chrout(',')
|
||||
txt.print_uw(v2)
|
||||
txt.print(" **")
|
||||
}}
|
||||
|
||||
sub fail_float(uword idx, float v1, float v2) {{
|
||||
sub fail_float(uword idx) {{
|
||||
txt.print(" **fail#")
|
||||
txt.print_uw(idx)
|
||||
txt.chrout(':')
|
||||
floats.print(v1)
|
||||
txt.chrout(',')
|
||||
floats.print(v2)
|
||||
txt.print(" **")
|
||||
}}
|
||||
|
||||
|
@ -115,9 +95,9 @@ def tc(value):
|
|||
|
||||
|
||||
testnumbers = {
|
||||
"byte": [-100, 0, 100],
|
||||
"byte": [-1, 0, 1],
|
||||
"ubyte": [0, 1, 255],
|
||||
"word": [tc(0xaabb), 0, 0x00aa, 0x7700, 0x7fff],
|
||||
"word": [tc(0xaabb), -1, 0, 1, 0x00aa, 0x7700, 0x7fff],
|
||||
"uword": [0, 1, 0x7700, 0xffff],
|
||||
"float": [0.0, 1234.56]
|
||||
}
|
||||
|
@ -143,15 +123,18 @@ def make_test_number(datatype, comparison: C):
|
|||
true_action2 = "success++"
|
||||
true_action3 = "success++"
|
||||
true_action4 = "success++"
|
||||
fail_action4 = "cx16.r0L++"
|
||||
else:
|
||||
fail_index += 1
|
||||
true_action1 = f"fail_{datatype}({fail_index},x,{value})"
|
||||
true_action1 = f"fail_{datatype}({fail_index})"
|
||||
fail_index += 1
|
||||
true_action2 = f"fail_{datatype}({fail_index},x,{value})"
|
||||
true_action2 = f"fail_{datatype}({fail_index})"
|
||||
fail_index += 1
|
||||
true_action3 = f"fail_{datatype}({fail_index},x,{value})"
|
||||
true_action3 = f"fail_{datatype}({fail_index})"
|
||||
fail_index += 1
|
||||
true_action4 = f"fail_{datatype}({fail_index},x,{value})"
|
||||
true_action4 = f"fail_{datatype}({fail_index})"
|
||||
fail_action4 = "success++"
|
||||
expected += 1
|
||||
print(f""" ; direct jump
|
||||
if x{comp}{value}
|
||||
goto lbl{test_index}a
|
||||
|
@ -173,7 +156,7 @@ skip{test_index}b:
|
|||
if x{comp}{value}
|
||||
{true_action4}
|
||||
else
|
||||
cx16.r0L++
|
||||
{fail_action4}
|
||||
""")
|
||||
print(f" verify_success({expected})\n}}")
|
||||
|
||||
|
@ -189,8 +172,6 @@ def make_test_var(datatype, comparison: C):
|
|||
for x in numbers:
|
||||
print(f" x={x}")
|
||||
for value in numbers:
|
||||
if value == 0:
|
||||
continue # 0 already tested separately
|
||||
print(f" value={value}")
|
||||
result = comparison.compare(x, value)
|
||||
comp = comparison.operator
|
||||
|
@ -201,15 +182,18 @@ def make_test_var(datatype, comparison: C):
|
|||
true_action2 = "success++"
|
||||
true_action3 = "success++"
|
||||
true_action4 = "success++"
|
||||
fail_action4 = "cx16.r0L++"
|
||||
else:
|
||||
fail_index += 1
|
||||
true_action1 = f"fail_{datatype}({fail_index},x,value)"
|
||||
true_action1 = f"fail_{datatype}({fail_index})"
|
||||
fail_index += 1
|
||||
true_action2 = f"fail_{datatype}({fail_index},x,value)"
|
||||
true_action2 = f"fail_{datatype}({fail_index})"
|
||||
fail_index += 1
|
||||
true_action3 = f"fail_{datatype}({fail_index},x,value)"
|
||||
true_action3 = f"fail_{datatype}({fail_index})"
|
||||
fail_index += 1
|
||||
true_action4 = f"fail_{datatype}({fail_index},x,value)"
|
||||
true_action4 = f"fail_{datatype}({fail_index})"
|
||||
fail_action4 = "success++"
|
||||
expected += 1
|
||||
print(f""" ; direct jump
|
||||
if x{comp}value
|
||||
goto lbl{test_index}a
|
||||
|
@ -231,7 +215,7 @@ skip{test_index}b:
|
|||
if x{comp}value
|
||||
{true_action4}
|
||||
else
|
||||
cx16.r0L++
|
||||
{fail_action4}
|
||||
""")
|
||||
print(f" verify_success({expected})\n}}")
|
||||
|
||||
|
@ -248,8 +232,6 @@ def make_test_array(datatype, comparison: C):
|
|||
for x in numbers:
|
||||
print(f" x={x}")
|
||||
for value in numbers:
|
||||
if value == 0:
|
||||
continue # 0 already tested separately
|
||||
print(f" values[1]={value}")
|
||||
result = comparison.compare(x, value)
|
||||
comp = comparison.operator
|
||||
|
@ -260,15 +242,18 @@ def make_test_array(datatype, comparison: C):
|
|||
true_action2 = "success++"
|
||||
true_action3 = "success++"
|
||||
true_action4 = "success++"
|
||||
fail_action4 = "cx16.r0L++"
|
||||
else:
|
||||
fail_index += 1
|
||||
true_action1 = f"fail_{datatype}({fail_index},x,{value})"
|
||||
true_action1 = f"fail_{datatype}({fail_index})"
|
||||
fail_index += 1
|
||||
true_action2 = f"fail_{datatype}({fail_index},x,{value})"
|
||||
true_action2 = f"fail_{datatype}({fail_index})"
|
||||
fail_index += 1
|
||||
true_action3 = f"fail_{datatype}({fail_index},x,{value})"
|
||||
true_action3 = f"fail_{datatype}({fail_index})"
|
||||
fail_index += 1
|
||||
true_action4 = f"fail_{datatype}({fail_index},x,{value})"
|
||||
true_action4 = f"fail_{datatype}({fail_index})"
|
||||
fail_action4 = "success++"
|
||||
expected += 1
|
||||
print(f""" ; direct jump
|
||||
if x{comp}values[1]
|
||||
goto lbl{test_index}a
|
||||
|
@ -290,7 +275,7 @@ skip{test_index}b:
|
|||
if x{comp}values[1]
|
||||
{true_action4}
|
||||
else
|
||||
cx16.r0L++
|
||||
{fail_action4}
|
||||
""")
|
||||
print(f" verify_success({expected})\n}}")
|
||||
|
||||
|
@ -310,8 +295,6 @@ def make_test_expr(datatype, comparison: C):
|
|||
for x in numbers:
|
||||
print(f" x={x}")
|
||||
for value in numbers:
|
||||
if value == 0:
|
||||
continue # 0 already tested separately
|
||||
if datatype=="byte":
|
||||
expr = f"cx16.r4sL+{value}-cx16.r5sL"
|
||||
elif datatype=="ubyte":
|
||||
|
@ -331,15 +314,18 @@ def make_test_expr(datatype, comparison: C):
|
|||
true_action2 = "success++"
|
||||
true_action3 = "success++"
|
||||
true_action4 = "success++"
|
||||
fail_action4 = "cx16.r0L++"
|
||||
else:
|
||||
fail_index += 1
|
||||
true_action1 = f"fail_{datatype}({fail_index},x,{value})"
|
||||
true_action1 = f"fail_{datatype}({fail_index})"
|
||||
fail_index += 1
|
||||
true_action2 = f"fail_{datatype}({fail_index},x,{value})"
|
||||
true_action2 = f"fail_{datatype}({fail_index})"
|
||||
fail_index += 1
|
||||
true_action3 = f"fail_{datatype}({fail_index},x,{value})"
|
||||
true_action3 = f"fail_{datatype}({fail_index})"
|
||||
fail_index += 1
|
||||
true_action4 = f"fail_{datatype}({fail_index},x,{value})"
|
||||
true_action4 = f"fail_{datatype}({fail_index})"
|
||||
fail_action4 = "success++"
|
||||
expected += 1
|
||||
print(f""" ; direct jump
|
||||
if x{comp}{expr}
|
||||
goto lbl{test_index}a
|
||||
|
@ -361,7 +347,7 @@ skip{test_index}b:
|
|||
if x{comp}{expr}
|
||||
{true_action4}
|
||||
else
|
||||
cx16.r0L++
|
||||
{fail_action4}
|
||||
""")
|
||||
print(f" verify_success({expected})\n}}")
|
||||
|
||||
|
|
|
@ -1,36 +1,32 @@
|
|||
TODO
|
||||
====
|
||||
|
||||
add tests for comparison that do an assignment rather than an if.
|
||||
|
||||
fix ifelse codegens:
|
||||
byte >= (all 4 paths)
|
||||
byte > (all 4 paths)
|
||||
byte <= (all 4 paths)
|
||||
byte < (all 4 paths)
|
||||
uword >= (all 4 paths)
|
||||
uword > (var and array)
|
||||
uword <= (all 4 paths)
|
||||
uword < (var)
|
||||
word >= (all 4 paths)
|
||||
word > (var, array)
|
||||
word <= (var)
|
||||
word < (var)
|
||||
verify ifelse codegens to be shortest code: (some are using too many scratch vars?)
|
||||
uword >=
|
||||
uword >
|
||||
uword <=
|
||||
uword <
|
||||
word >=
|
||||
word >
|
||||
word <=
|
||||
word <
|
||||
|
||||
|
||||
improve code size for "wordGreaterValue" et al.
|
||||
plasma is a bit larger
|
||||
floatparse is a bit larger
|
||||
testgfx2 is a bit larger
|
||||
amiga is a bit larger
|
||||
halloween is 1 byte larger
|
||||
rockrunner is bigger than on 10.1
|
||||
paint is slightly bigger than on 10.1
|
||||
chess is bigger than on 10.1
|
||||
imageviewer is a lot bigger
|
||||
shell is a couple of bytes bigger
|
||||
|
||||
|
||||
rockrunner is a lot bigger still than on 10.1
|
||||
paint is bigger than on 10.1
|
||||
|
||||
cx16/testmonogfx is broken
|
||||
cx16/amiga is broken
|
||||
assembler is broken
|
||||
imageviewer is broken
|
||||
paint flood fill is broken
|
||||
rockrunner load caveset list is broken
|
||||
medemo and dsdemo are broken
|
||||
add tests for comparison that do an assignment rather than an if
|
||||
assign to variable, and barray[indexvar], test if they're both correct
|
||||
(bb = value > -100 --> contains a beq +++ that shouldn't be there??)
|
||||
|
||||
|
||||
|
||||
|
@ -72,7 +68,7 @@ ok ok efficient code for assignment float comparisons against a value
|
|||
ok ok efficient code for if_cc conditional expressions
|
||||
ok ok while boolean should produce identical code as while integer!=0 and code should be efficient
|
||||
ok ok while not boolvar -> can we get rid of the cmp? (6502 only?)
|
||||
ok FAIL testmonogfx works
|
||||
ok ok testmonogfx works
|
||||
ok . check program sizes vs. master branch
|
||||
===== ====== =======
|
||||
|
||||
|
|
2013
examples/test.p8
2013
examples/test.p8
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user