mirror of
https://github.com/irmen/prog8.git
synced 2025-08-19 10:27:43 +00:00
ifelse more
This commit is contained in:
@@ -156,26 +156,8 @@ internal class IfElseAsmGen(private val program: PtProgram,
|
|||||||
translateIfElseBodies("bcs", stmt)
|
translateIfElseBodies("bcs", stmt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"<=" -> {
|
"<=" -> translateByteLessEqual(stmt, signed, jumpAfterIf)
|
||||||
fallbackTranslate(stmt, true)
|
">" -> translateByteGreater(stmt, signed, jumpAfterIf)
|
||||||
// asmgen.assignExpressionToRegister(condition.left, RegisterOrPair.A, signed)
|
|
||||||
// cmpAwithByteValue(condition.right)
|
|
||||||
// if(signed) {
|
|
||||||
// TODO("byte if <=")
|
|
||||||
// } else {
|
|
||||||
// TODO("ubyte if <=")
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
">" -> {
|
|
||||||
fallbackTranslate(stmt, true)
|
|
||||||
// asmgen.assignExpressionToRegister(condition.left, RegisterOrPair.A, signed)
|
|
||||||
// cmpAwithByteValue(condition.right)
|
|
||||||
// return if(signed) {
|
|
||||||
// TODO("byte if >")
|
|
||||||
// } else {
|
|
||||||
// TODO("ubyte if >")
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
">=" -> {
|
">=" -> {
|
||||||
asmgen.assignExpressionToRegister(condition.left, RegisterOrPair.A, signed)
|
asmgen.assignExpressionToRegister(condition.left, RegisterOrPair.A, signed)
|
||||||
cmpAwithByteValue(condition.right)
|
cmpAwithByteValue(condition.right)
|
||||||
@@ -240,66 +222,544 @@ 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
|
||||||
|
+""")
|
||||||
|
asmgen.translate(stmt.ifScope)
|
||||||
|
asmgen.jmp(afterIfLabel, false)
|
||||||
|
asmgen.out(elseLabel)
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(jumpAfterIf!=null) {
|
||||||
|
bodies("bcc" to "beq", "beq" to "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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun translateIfWord(stmt: PtIfElse, condition: PtBinaryExpression, jumpAfterIf: PtJump?) {
|
private fun translateIfWord(stmt: PtIfElse, condition: PtBinaryExpression, jumpAfterIf: PtJump?) {
|
||||||
val signed = condition.left.type in SignedDatatypes
|
val signed = condition.left.type in SignedDatatypes
|
||||||
val constValue = condition.right.asConstInteger()
|
val constValue = condition.right.asConstInteger()
|
||||||
if(constValue==0) {
|
if(constValue==0) {
|
||||||
if(condition.operator=="==") {
|
// optimized comparisons with zero
|
||||||
// if X==0
|
when (condition.operator) {
|
||||||
// TODO even more optimized code by comparing lsb and msb separately
|
"==" -> return wordEqualsZero(condition.left, false, signed, jumpAfterIf, stmt)
|
||||||
asmgen.assignExpressionToRegister(condition.left, RegisterOrPair.AY, signed)
|
"!=" -> return wordEqualsZero(condition.left, true, signed, jumpAfterIf, stmt)
|
||||||
asmgen.out(" sty P8ZP_SCRATCH_REG | ora P8ZP_SCRATCH_REG")
|
"<" -> return wordLessZero(condition.left, signed, jumpAfterIf, stmt)
|
||||||
return if(jumpAfterIf!=null)
|
"<=" -> return wordLessEqualsZero(condition.left, signed, jumpAfterIf, stmt)
|
||||||
translateJumpElseBodies("beq", "bne", jumpAfterIf, stmt.elseScope)
|
">" -> return wordGreaterZero(condition.left, signed, jumpAfterIf, stmt)
|
||||||
else
|
">=" -> return wordGreaterEqualsZero(condition.left, signed, jumpAfterIf, stmt)
|
||||||
translateIfElseBodies("bne", stmt)
|
|
||||||
} else if(condition.operator=="!=") {
|
|
||||||
// if X!=0
|
|
||||||
// TODO even more optimized code by comparing lsb and msb separately
|
|
||||||
asmgen.assignExpressionToRegister(condition.left, RegisterOrPair.AY, signed)
|
|
||||||
asmgen.out(" sty P8ZP_SCRATCH_REG | ora P8ZP_SCRATCH_REG")
|
|
||||||
return if(jumpAfterIf!=null)
|
|
||||||
translateJumpElseBodies("bne", "beq", jumpAfterIf, stmt.elseScope)
|
|
||||||
else
|
|
||||||
translateIfElseBodies("beq", stmt)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// non-zero comparisons
|
||||||
when(condition.operator) {
|
when(condition.operator) {
|
||||||
"==" -> {
|
"==" -> wordEqualsValue(condition.left, condition.right, false, signed, jumpAfterIf, stmt)
|
||||||
// TODO
|
"!=" -> wordEqualsValue(condition.left, condition.right, true, signed, jumpAfterIf, stmt)
|
||||||
println("word if ==")
|
"<" -> wordLessValue(condition.left, condition.right, signed, jumpAfterIf, stmt)
|
||||||
fallbackTranslate(stmt)
|
"<=" -> wordLessEqualsValue(condition.left, condition.right, signed, jumpAfterIf, stmt)
|
||||||
}
|
">" -> wordGreaterValue(condition.left, condition.right, signed, jumpAfterIf, stmt)
|
||||||
"!=" -> {
|
">=" -> wordGreaterEqualsValue(condition.left, condition.right, signed, jumpAfterIf, stmt)
|
||||||
// TODO
|
|
||||||
println("word if !=")
|
|
||||||
fallbackTranslate(stmt)
|
|
||||||
}
|
|
||||||
"<" -> {
|
|
||||||
// TODO()
|
|
||||||
println("word if <")
|
|
||||||
fallbackTranslate(stmt)
|
|
||||||
}
|
|
||||||
"<=" -> {
|
|
||||||
// TODO()
|
|
||||||
println("word if <=")
|
|
||||||
fallbackTranslate(stmt)
|
|
||||||
}
|
|
||||||
">" -> {
|
|
||||||
// TODO()
|
|
||||||
println("word if >")
|
|
||||||
fallbackTranslate(stmt)
|
|
||||||
}
|
|
||||||
">=" -> {
|
|
||||||
// TODO()
|
|
||||||
println("word if >=")
|
|
||||||
fallbackTranslate(stmt)
|
|
||||||
}
|
|
||||||
else -> fallbackTranslate(stmt, false)
|
else -> fallbackTranslate(stmt, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun wordGreaterEqualsZero(value: PtExpression, signed: Boolean, jump: PtJump?, stmt: PtIfElse) {
|
||||||
|
// special case for word>=0
|
||||||
|
if(signed) {
|
||||||
|
loadAndCmp0MSB(value)
|
||||||
|
if (jump != null)
|
||||||
|
translateJumpElseBodies("bpl", "bmi", jump, stmt.elseScope)
|
||||||
|
else
|
||||||
|
translateIfElseBodies("bmi", stmt)
|
||||||
|
} else {
|
||||||
|
asmgen.translate(stmt.ifScope)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun wordLessZero(value: PtExpression, signed: Boolean, jump: PtJump?, stmt: PtIfElse) {
|
||||||
|
if(signed) {
|
||||||
|
loadAndCmp0MSB(value)
|
||||||
|
if (jump != null)
|
||||||
|
translateJumpElseBodies("bmi", "bpl", jump, stmt.elseScope)
|
||||||
|
else
|
||||||
|
translateIfElseBodies("bpl", stmt)
|
||||||
|
} else {
|
||||||
|
asmgen.translate(stmt.elseScope)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun wordLessValue(left: PtExpression, right: PtExpression, signed: Boolean, jump: PtJump?, stmt: PtIfElse) {
|
||||||
|
println("word if <") // TODO
|
||||||
|
fallbackTranslate(stmt)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun wordGreaterValue(left: PtExpression, right: PtExpression, signed: Boolean, jump: PtJump?, stmt: PtIfElse) {
|
||||||
|
println("word if >") // TODO
|
||||||
|
fallbackTranslate(stmt)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun wordLessEqualsValue(left: PtExpression, right: PtExpression, signed: Boolean, jump: PtJump?, stmt: PtIfElse) {
|
||||||
|
println("word if <=") // TODO
|
||||||
|
fallbackTranslate(stmt)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun wordGreaterEqualsValue(left: PtExpression, right: PtExpression, signed: Boolean, jump: PtJump?, stmt: PtIfElse) {
|
||||||
|
println("word if >=") // TODO
|
||||||
|
fallbackTranslate(stmt)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun loadAndCmp0MSB(value: PtExpression) {
|
||||||
|
when(value) {
|
||||||
|
is PtArrayIndexer -> {
|
||||||
|
val varname = asmgen.asmVariableName(value.variable)
|
||||||
|
asmgen.loadScaledArrayIndexIntoRegister(value, CpuRegister.Y)
|
||||||
|
asmgen.out(" lda $varname+1,y")
|
||||||
|
}
|
||||||
|
is PtIdentifier -> {
|
||||||
|
val varname = asmgen.asmVariableName(value)
|
||||||
|
asmgen.out(" lda $varname+1")
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
asmgen.assignExpressionToRegister(value, RegisterOrPair.AY, true)
|
||||||
|
asmgen.out(" cmp #0")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun wordLessEqualsZero(value: PtExpression, signed: Boolean, jump: PtJump?, stmt: PtIfElse) {
|
||||||
|
return if(signed) {
|
||||||
|
asmgen.assignExpressionToRegister(value, RegisterOrPair.AY, true) // TODO optimize this even further by doing MSB/LSB separately
|
||||||
|
if(jump!=null) {
|
||||||
|
val (asmLabel, indirect) = asmgen.getJumpTarget(jump)
|
||||||
|
if(indirect) {
|
||||||
|
asmgen.out("""
|
||||||
|
cpy #0
|
||||||
|
bmi +
|
||||||
|
bne ++
|
||||||
|
cmp #0
|
||||||
|
bne ++
|
||||||
|
+ jmp ($asmLabel)
|
||||||
|
+""")
|
||||||
|
} else {
|
||||||
|
asmgen.out("""
|
||||||
|
cpy #0
|
||||||
|
bmi $asmLabel
|
||||||
|
bne +
|
||||||
|
cmp #0
|
||||||
|
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("""
|
||||||
|
cpy #0
|
||||||
|
bmi +
|
||||||
|
bne $elseLabel
|
||||||
|
cmp #0
|
||||||
|
bne $elseLabel
|
||||||
|
+""")
|
||||||
|
asmgen.translate(stmt.ifScope)
|
||||||
|
asmgen.jmp(afterIfLabel, false)
|
||||||
|
asmgen.out(elseLabel)
|
||||||
|
asmgen.translate(stmt.elseScope)
|
||||||
|
} else {
|
||||||
|
// no else block
|
||||||
|
asmgen.out("""
|
||||||
|
cpy #0
|
||||||
|
bmi +
|
||||||
|
bne $afterIfLabel
|
||||||
|
cmp #0
|
||||||
|
bne $afterIfLabel
|
||||||
|
+""")
|
||||||
|
asmgen.translate(stmt.ifScope)
|
||||||
|
}
|
||||||
|
asmgen.out(afterIfLabel)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
wordEqualsZero(value, true, false, jump, stmt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun wordGreaterZero(value: PtExpression, signed: Boolean, jump: PtJump?, stmt: PtIfElse) {
|
||||||
|
if(signed) {
|
||||||
|
asmgen.assignExpressionToRegister(value, RegisterOrPair.AY, true) // TODO optimize this even further by doing MSB/LSB separately
|
||||||
|
if(jump!=null) {
|
||||||
|
val (asmLabel, indirect) = asmgen.getJumpTarget(jump)
|
||||||
|
if(indirect) {
|
||||||
|
asmgen.out("""
|
||||||
|
cpy #0
|
||||||
|
bmi ++
|
||||||
|
bne +
|
||||||
|
cmp #0
|
||||||
|
beq ++
|
||||||
|
+ jmp ($asmLabel)
|
||||||
|
+""")
|
||||||
|
} else {
|
||||||
|
asmgen.out("""
|
||||||
|
cpy #0
|
||||||
|
bmi +
|
||||||
|
bne $asmLabel
|
||||||
|
cmp #0
|
||||||
|
bne $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("""
|
||||||
|
cpy #0
|
||||||
|
bmi $elseLabel
|
||||||
|
bne +
|
||||||
|
cmp #0
|
||||||
|
beq $elseLabel
|
||||||
|
+""")
|
||||||
|
asmgen.translate(stmt.ifScope)
|
||||||
|
asmgen.jmp(afterIfLabel, false)
|
||||||
|
asmgen.out(elseLabel)
|
||||||
|
asmgen.translate(stmt.elseScope)
|
||||||
|
} else {
|
||||||
|
// no else block
|
||||||
|
asmgen.out("""
|
||||||
|
cpy #0
|
||||||
|
bmi $afterIfLabel
|
||||||
|
bne +
|
||||||
|
cmp #0
|
||||||
|
beq $afterIfLabel
|
||||||
|
+""")
|
||||||
|
asmgen.translate(stmt.ifScope)
|
||||||
|
}
|
||||||
|
asmgen.out(afterIfLabel)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
wordEqualsZero(value, true, false, jump, stmt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun wordEqualsZero(value: PtExpression, notEquals: Boolean, signed: Boolean, jump: PtJump?, stmt: PtIfElse) {
|
||||||
|
|
||||||
|
fun viaScratchReg(branchInstr: String, falseBranch: String) {
|
||||||
|
asmgen.assignExpressionToRegister(value, RegisterOrPair.AY, signed)
|
||||||
|
asmgen.out(" sty P8ZP_SCRATCH_REG | ora P8ZP_SCRATCH_REG")
|
||||||
|
if(jump!=null)
|
||||||
|
translateJumpElseBodies(branchInstr, falseBranch, jump, stmt.elseScope)
|
||||||
|
else
|
||||||
|
translateIfElseBodies(falseBranch, stmt)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun translateLoadFromVar(variable: String, branch: String, falseBranch: String) {
|
||||||
|
asmgen.out(" lda $variable | ora $variable+1")
|
||||||
|
return if(jump!=null)
|
||||||
|
translateJumpElseBodies(branch, falseBranch, jump, stmt.elseScope)
|
||||||
|
else
|
||||||
|
translateIfElseBodies(falseBranch, stmt)
|
||||||
|
}
|
||||||
|
|
||||||
|
if(notEquals) {
|
||||||
|
when(value) {
|
||||||
|
is PtArrayIndexer -> {
|
||||||
|
val constIndex = value.index.asConstInteger()
|
||||||
|
if(constIndex!=null) {
|
||||||
|
val offset = constIndex * program.memsizer.memorySize(value.type)
|
||||||
|
if(offset<256) {
|
||||||
|
val varName = asmgen.asmVariableName(value.variable)
|
||||||
|
return translateLoadFromVar("$varName+$offset", "bne", "beq")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
viaScratchReg("bne", "beq")
|
||||||
|
}
|
||||||
|
is PtIdentifier -> {
|
||||||
|
return translateLoadFromVar(asmgen.asmVariableName(value), "bne", "beq")
|
||||||
|
}
|
||||||
|
else -> viaScratchReg("bne", "beq")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
when (value) {
|
||||||
|
is PtArrayIndexer -> {
|
||||||
|
val constIndex = value.index.asConstInteger()
|
||||||
|
if(constIndex!=null) {
|
||||||
|
val offset = constIndex * program.memsizer.memorySize(value.type)
|
||||||
|
if(offset<256) {
|
||||||
|
val varName = asmgen.asmVariableName(value.variable)
|
||||||
|
return translateLoadFromVar("$varName+$offset", "beq", "bne")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
viaScratchReg("beq", "bne")
|
||||||
|
}
|
||||||
|
is PtIdentifier -> {
|
||||||
|
return translateLoadFromVar(asmgen.asmVariableName(value), "beq", "bne")
|
||||||
|
}
|
||||||
|
else -> viaScratchReg("beq", "bne")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun wordEqualsValue(
|
||||||
|
left: PtExpression,
|
||||||
|
right: PtExpression,
|
||||||
|
notEquals: Boolean,
|
||||||
|
signed: Boolean,
|
||||||
|
jump: PtJump?,
|
||||||
|
stmt: PtIfElse
|
||||||
|
) {
|
||||||
|
|
||||||
|
fun translateLoadFromVarNotEquals(varname: String) {
|
||||||
|
if(jump!=null) {
|
||||||
|
val (asmLabel, indirect) = asmgen.getJumpTarget(jump)
|
||||||
|
if(indirect) {
|
||||||
|
asmgen.out("""
|
||||||
|
cmp $varname
|
||||||
|
bne +
|
||||||
|
cpy $varname+1
|
||||||
|
beq ++
|
||||||
|
+ jmp ($asmLabel)
|
||||||
|
+""")
|
||||||
|
} else {
|
||||||
|
asmgen.out("""
|
||||||
|
cmp $varname
|
||||||
|
bne $asmLabel
|
||||||
|
cpy $varname+1
|
||||||
|
bne $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("""
|
||||||
|
cmp $varname
|
||||||
|
bne +
|
||||||
|
cpy $varname+1
|
||||||
|
beq $elseLabel
|
||||||
|
+""")
|
||||||
|
asmgen.translate(stmt.ifScope)
|
||||||
|
asmgen.jmp(afterIfLabel, false)
|
||||||
|
asmgen.out(elseLabel)
|
||||||
|
asmgen.translate(stmt.elseScope)
|
||||||
|
} else {
|
||||||
|
// no else block
|
||||||
|
asmgen.out("""
|
||||||
|
cmp $varname
|
||||||
|
bne +
|
||||||
|
cpy $varname+1
|
||||||
|
beq $afterIfLabel
|
||||||
|
+""")
|
||||||
|
asmgen.translate(stmt.ifScope)
|
||||||
|
}
|
||||||
|
asmgen.out(afterIfLabel)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun translateLoadFromVarEquals(varname: String) {
|
||||||
|
return if(jump!=null) {
|
||||||
|
val (asmLabel, indirect) = asmgen.getJumpTarget(jump)
|
||||||
|
if(indirect) {
|
||||||
|
asmgen.out("""
|
||||||
|
cmp $varname
|
||||||
|
bne +
|
||||||
|
cpy $varname+1
|
||||||
|
bne +
|
||||||
|
jmp ($asmLabel)
|
||||||
|
+""")
|
||||||
|
} else {
|
||||||
|
asmgen.out("""
|
||||||
|
cmp $varname
|
||||||
|
bne +
|
||||||
|
cpy $varname+1
|
||||||
|
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("""
|
||||||
|
cmp $varname
|
||||||
|
bne $elseLabel
|
||||||
|
cpy $varname+1
|
||||||
|
bne $elseLabel""")
|
||||||
|
asmgen.translate(stmt.ifScope)
|
||||||
|
asmgen.jmp(afterIfLabel, false)
|
||||||
|
asmgen.out(elseLabel)
|
||||||
|
asmgen.translate(stmt.elseScope)
|
||||||
|
} else {
|
||||||
|
// no else block
|
||||||
|
asmgen.out("""
|
||||||
|
cmp $varname
|
||||||
|
bne $afterIfLabel
|
||||||
|
cpy $varname+1
|
||||||
|
bne $afterIfLabel""")
|
||||||
|
asmgen.translate(stmt.ifScope)
|
||||||
|
}
|
||||||
|
asmgen.out(afterIfLabel)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(notEquals) {
|
||||||
|
when(left) {
|
||||||
|
is PtArrayIndexer -> {
|
||||||
|
asmgen.assignExpressionToRegister(right, RegisterOrPair.AY, signed)
|
||||||
|
val constIndex = left.index.asConstInteger()
|
||||||
|
if(constIndex!=null) {
|
||||||
|
val offset = constIndex * program.memsizer.memorySize(left.type)
|
||||||
|
if(offset<256) {
|
||||||
|
val varName = asmgen.asmVariableName(left.variable)
|
||||||
|
return translateLoadFromVarNotEquals("$varName+$offset")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fallbackTranslate(stmt, false)
|
||||||
|
}
|
||||||
|
is PtIdentifier -> {
|
||||||
|
asmgen.assignExpressionToRegister(right, RegisterOrPair.AY, signed)
|
||||||
|
return translateLoadFromVarNotEquals(asmgen.asmVariableName(left))
|
||||||
|
}
|
||||||
|
else -> fallbackTranslate(stmt, false)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
when(left) {
|
||||||
|
is PtArrayIndexer -> {
|
||||||
|
asmgen.assignExpressionToRegister(right, RegisterOrPair.AY, signed)
|
||||||
|
val constIndex = left.index.asConstInteger()
|
||||||
|
if(constIndex!=null) {
|
||||||
|
val offset = constIndex * program.memsizer.memorySize(left.type)
|
||||||
|
if(offset<256) {
|
||||||
|
val varName = asmgen.asmVariableName(left.variable)
|
||||||
|
return translateLoadFromVarEquals("$varName+$offset")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fallbackTranslate(stmt, false)
|
||||||
|
}
|
||||||
|
is PtIdentifier -> {
|
||||||
|
asmgen.assignExpressionToRegister(right, RegisterOrPair.AY, signed)
|
||||||
|
return translateLoadFromVarEquals(asmgen.asmVariableName(left))
|
||||||
|
}
|
||||||
|
else -> fallbackTranslate(stmt, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun translateIfFloat(stmt: PtIfElse, condition: PtBinaryExpression, jumpAfterIf: PtJump?) {
|
private fun translateIfFloat(stmt: PtIfElse, condition: PtBinaryExpression, jumpAfterIf: PtJump?) {
|
||||||
val constValue = (condition.right as? PtNumber)?.number
|
val constValue = (condition.right as? PtNumber)?.number
|
||||||
if(constValue==0.0) {
|
if(constValue==0.0) {
|
||||||
|
@@ -2091,7 +2091,7 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
|||||||
throw AssemblyError("can't store word into memory byte")
|
throw AssemblyError("can't store word into memory byte")
|
||||||
}
|
}
|
||||||
TargetStorageKind.ARRAY -> {
|
TargetStorageKind.ARRAY -> {
|
||||||
asmgen.out(" lda #<$sourceName | ldy #>$sourceName")
|
asmgen.out(" lda #<$sourceName | ldy #>$sourceName")
|
||||||
assignRegisterpairWord(target, RegisterOrPair.AY)
|
assignRegisterpairWord(target, RegisterOrPair.AY)
|
||||||
}
|
}
|
||||||
TargetStorageKind.REGISTER -> {
|
TargetStorageKind.REGISTER -> {
|
||||||
|
@@ -1,6 +1,12 @@
|
|||||||
TODO
|
TODO
|
||||||
====
|
====
|
||||||
|
|
||||||
|
examples/primes is larger than on 10.1
|
||||||
|
examples/maze is larger than on 10.1
|
||||||
|
examples/textelite is larger than on 10.1
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
===== ====== =======
|
===== ====== =======
|
||||||
VM 6502 what
|
VM 6502 what
|
||||||
===== ====== =======
|
===== ====== =======
|
||||||
@@ -44,6 +50,9 @@ ok . check program sizes vs. master branch
|
|||||||
===== ====== =======
|
===== ====== =======
|
||||||
|
|
||||||
|
|
||||||
|
retest all comparisons in if statements (byte, word, signed and unsigned) + all comparison assignments. Against 0 and something else as 0.
|
||||||
|
with jump, indirect jump, no else block, and both if+else blocks.
|
||||||
|
|
||||||
check that the flood fill routine in gfx2 and paint still works.
|
check that the flood fill routine in gfx2 and paint still works.
|
||||||
re-allow typecast of const true/false back to ubytes 1 and 0.
|
re-allow typecast of const true/false back to ubytes 1 and 0.
|
||||||
re-allow typecast of const ubyte 0/1 to false/true boolean.
|
re-allow typecast of const ubyte 0/1 to false/true boolean.
|
||||||
|
110
examples/test.p8
110
examples/test.p8
@@ -6,8 +6,98 @@
|
|||||||
main {
|
main {
|
||||||
bool @shared staticbool1 = true
|
bool @shared staticbool1 = true
|
||||||
bool @shared staticbool2
|
bool @shared staticbool2
|
||||||
|
word[4] words
|
||||||
|
|
||||||
|
byte @shared sbb
|
||||||
|
|
||||||
sub start() {
|
sub start() {
|
||||||
|
|
||||||
|
while cx16.r0s < 1234
|
||||||
|
cx16.r0L++
|
||||||
|
loop:
|
||||||
|
if cx16.r0s >= 1234
|
||||||
|
goto skip
|
||||||
|
cx16.r0L++
|
||||||
|
goto loop
|
||||||
|
skip:
|
||||||
|
|
||||||
|
; TODO all this for uwords
|
||||||
|
|
||||||
|
; if sbb<0
|
||||||
|
; cx16.r0L++
|
||||||
|
; if sbb>0
|
||||||
|
; cx16.r0L++
|
||||||
|
; if sbb<=0
|
||||||
|
; cx16.r0L++
|
||||||
|
; if sbb>=0
|
||||||
|
; cx16.r0L++
|
||||||
|
; if cx16.r0s<0
|
||||||
|
; cx16.r0L++
|
||||||
|
; if cx16.r0s>0
|
||||||
|
; cx16.r0L++
|
||||||
|
; if cx16.r0s>0
|
||||||
|
; goto start
|
||||||
|
; if cx16.r0s>0
|
||||||
|
; goto cx16.r0
|
||||||
|
; if cx16.r0s<=0
|
||||||
|
; cx16.r0L++
|
||||||
|
; else
|
||||||
|
; cx16.r0L++
|
||||||
|
; if cx16.r0s>=0
|
||||||
|
; cx16.r0L++
|
||||||
|
; if words[2]<0
|
||||||
|
; cx16.r0L++
|
||||||
|
; if words[2]>0
|
||||||
|
; cx16.r0L++
|
||||||
|
; if words[2]<=0
|
||||||
|
; cx16.r0L++
|
||||||
|
; if words[2]>=0
|
||||||
|
; cx16.r0L++
|
||||||
|
; if words[cx16.r0L]<0
|
||||||
|
; cx16.r0L++
|
||||||
|
; if words[cx16.r0L]>0
|
||||||
|
; cx16.r0L++
|
||||||
|
; if words[cx16.r0L]<=0
|
||||||
|
; cx16.r0L++
|
||||||
|
; if words[cx16.r0L]>=0
|
||||||
|
; cx16.r0L++
|
||||||
|
|
||||||
|
; staticbool2 = sbb < 0
|
||||||
|
; staticbool2 = sbb > 0
|
||||||
|
; staticbool1 = sbb <= 0
|
||||||
|
; staticbool1 = sbb >= 0
|
||||||
|
; staticbool2 = cx16.r0s <0
|
||||||
|
; staticbool2 = cx16.r0s >0
|
||||||
|
; staticbool1 = cx16.r0s <=0
|
||||||
|
; staticbool1 = cx16.r0s >=0
|
||||||
|
; staticbool2 = words[2]<0
|
||||||
|
; staticbool2 = words[2]>0
|
||||||
|
; staticbool1 = words[2]<=0
|
||||||
|
; staticbool1 = words[2]>=0
|
||||||
|
; staticbool2 = words[cx16.r0L]<0
|
||||||
|
; staticbool2 = words[cx16.r0L]>0
|
||||||
|
; staticbool1 = words[cx16.r0L]<=0
|
||||||
|
; staticbool1 = words[cx16.r0L]>=0
|
||||||
|
|
||||||
|
|
||||||
|
; if cx16.r0 > 1234
|
||||||
|
; cx16.r0L++
|
||||||
|
; if cx16.r0s > 1234
|
||||||
|
; cx16.r0L++
|
||||||
|
; if cx16.r0 < 1234
|
||||||
|
; cx16.r0L++
|
||||||
|
; if cx16.r0s < 1234
|
||||||
|
; cx16.r0L++
|
||||||
|
; if cx16.r0 >= 1234
|
||||||
|
; cx16.r0L++
|
||||||
|
; if cx16.r0s >= 1234
|
||||||
|
; cx16.r0L++
|
||||||
|
; if cx16.r0 <= 1234
|
||||||
|
; cx16.r0L++
|
||||||
|
; if cx16.r0s <= 1234
|
||||||
|
; cx16.r0L++
|
||||||
|
|
||||||
|
|
||||||
; boolean_const_and_var(true)
|
; boolean_const_and_var(true)
|
||||||
; staticbool1 = boolean_arrays_and_return()
|
; staticbool1 = boolean_arrays_and_return()
|
||||||
; txt.print_ub(staticbool1 as ubyte)
|
; txt.print_ub(staticbool1 as ubyte)
|
||||||
@@ -27,7 +117,7 @@ main {
|
|||||||
; efficient_compare_99()
|
; efficient_compare_99()
|
||||||
; efficient_compare_var()
|
; efficient_compare_var()
|
||||||
; efficient_assign_cmp_0()
|
; efficient_assign_cmp_0()
|
||||||
efficient_assign_cmp_99()
|
; efficient_assign_cmp_99()
|
||||||
; efficient_assign_cmp_var()
|
; efficient_assign_cmp_var()
|
||||||
; if_gotos()
|
; if_gotos()
|
||||||
; if_code()
|
; if_code()
|
||||||
@@ -472,6 +562,7 @@ main {
|
|||||||
|
|
||||||
sub if_code() {
|
sub if_code() {
|
||||||
ubyte @shared ub
|
ubyte @shared ub
|
||||||
|
byte @shared sb
|
||||||
bool @shared bb
|
bool @shared bb
|
||||||
if ub==0
|
if ub==0
|
||||||
cx16.r0L++
|
cx16.r0L++
|
||||||
@@ -498,6 +589,23 @@ main {
|
|||||||
cx16.r0L++
|
cx16.r0L++
|
||||||
else
|
else
|
||||||
cx16.r0--
|
cx16.r0--
|
||||||
|
|
||||||
|
if ub>10
|
||||||
|
cx16.r0++
|
||||||
|
if ub>=10
|
||||||
|
cx16.r0++
|
||||||
|
if ub<10
|
||||||
|
cx16.r0++
|
||||||
|
if ub<=10
|
||||||
|
cx16.r0++
|
||||||
|
if sb>10
|
||||||
|
cx16.r0++
|
||||||
|
if sb>=10
|
||||||
|
cx16.r0++
|
||||||
|
if sb<10
|
||||||
|
cx16.r0++
|
||||||
|
if sb<=10
|
||||||
|
cx16.r0++
|
||||||
}
|
}
|
||||||
|
|
||||||
sub intfunc() -> ubyte {
|
sub intfunc() -> ubyte {
|
||||||
|
Reference in New Issue
Block a user