diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/IfElseAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/IfElseAsmGen.kt index 8f140fbb5..3e915249d 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/IfElseAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/IfElseAsmGen.kt @@ -402,25 +402,538 @@ internal class IfElseAsmGen(private val program: PtProgram, } private fun wordLessValue(left: PtExpression, right: PtExpression, signed: Boolean, jump: PtJump?, stmt: PtIfElse) { - println("word if <") // TODO - fallbackTranslate(stmt) + fun code(valueLsb: String, valueMsb: String) { + if(signed) { + if(jump!=null) { + val (asmLabel, indirect) = asmgen.getJumpTarget(jump) + if(indirect) { + asmgen.out(""" + cmp $valueLsb + tya + sbc $valueMsb + bvs + + eor #128 ++ bpl + + jmp ($asmLabel) ++""") + } else { + asmgen.out(""" + cmp $valueLsb + tya + sbc $valueMsb + bvc + + eor #128 ++ bmi $asmLabel""") + } + } else { + val afterIfLabel = asmgen.makeLabel("afterif") + if(stmt.hasElse()) { + // if and else blocks + val elseLabel = asmgen.makeLabel("else") + asmgen.out(""" + cmp $valueLsb + tya + sbc $valueMsb + bvs + + eor #128 ++ bmi $elseLabel""") + asmgen.translate(stmt.ifScope) + asmgen.jmp(afterIfLabel, false) + asmgen.out(elseLabel) + asmgen.translate(stmt.elseScope) + } else { + // no else block + asmgen.out(""" + cmp $valueLsb + tya + sbc $valueMsb + bvs + + eor #128 ++ bmi $afterIfLabel""") + asmgen.translate(stmt.ifScope) + } + asmgen.out(afterIfLabel) + } + } else { + if(jump!=null) { + val (asmLabel, indirect) = asmgen.getJumpTarget(jump) + if(indirect) { + asmgen.out(""" + cmp $valueLsb + tya + sbc $valueMsb + bcc + + jmp ($asmLabel) ++""") + } else { + asmgen.out(""" + cmp $valueLsb + tya + sbc $valueMsb + bcc $asmLabel""") + } + } else { + val afterIfLabel = asmgen.makeLabel("afterif") + if(stmt.hasElse()) { + // if and else blocks + val elseLabel = asmgen.makeLabel("else") + asmgen.out(""" + cmp $valueLsb + tya + sbc $valueMsb + bcs $elseLabel""") + asmgen.translate(stmt.ifScope) + asmgen.jmp(afterIfLabel, false) + asmgen.out(elseLabel) + asmgen.translate(stmt.elseScope) + } else { + // no else block + asmgen.out(""" + cmp $valueLsb + tya + sbc $valueMsb + bcs $afterIfLabel""") + asmgen.translate(stmt.ifScope) + } + asmgen.out(afterIfLabel) + } + } + } + + if(right is PtNumber) { + asmgen.assignExpressionToRegister(left, RegisterOrPair.AY, signed) + val number = right.number.toHex() + return code("#<$number", "#>$number") + } + + if(right is PtIdentifier) { + asmgen.assignExpressionToRegister(left, RegisterOrPair.AY, signed) + val variable = asmgen.asmVariableName(right) + return code("#<$variable", "#>$variable") + } + + // TODO optimize for simple array value + + // generic case via scratch register + asmgen.assignWordOperandsToAYAndVar(left, right, "P8ZP_SCRATCH_W2") + code("P8ZP_SCRATCH_W2", "P8ZP_SCRATCH_W2+1") } private fun wordGreaterValue(left: PtExpression, right: PtExpression, signed: Boolean, jump: PtJump?, stmt: PtIfElse) { - println("word if >") // TODO - fallbackTranslate(stmt) + fun code(valueLsb: String, valueMsb: String) { + if(signed) { + if(jump!=null) { + val (asmLabel, indirect) = asmgen.getJumpTarget(jump) + if(indirect) { + asmgen.out(""" + sta P8ZP_SCRATCH_W1 + sty P8ZP_SCRATCH_W1+1 + ldy $valueLsb + lda $valueMsb + cpy P8ZP_SCRATCH_W1 + sbc P8ZP_SCRATCH_W1+1 + bvc + + eor #128 ++ bmi + + jmp ($asmLabel) ++""") + } else { + asmgen.out(""" + sta P8ZP_SCRATCH_W1 + sty P8ZP_SCRATCH_W1+1 + ldy $valueLsb + lda $valueMsb + cpy P8ZP_SCRATCH_W1 + sbc P8ZP_SCRATCH_W1+1 + bvc + + eor #128 ++ bpl $asmLabel""") + } + } else { + val afterIfLabel = asmgen.makeLabel("afterif") + if(stmt.hasElse()) { + // if and else blocks + val elseLabel = asmgen.makeLabel("else") + asmgen.out(""" + sta P8ZP_SCRATCH_W1 + sty P8ZP_SCRATCH_W1+1 + ldy $valueLsb + lda $valueMsb + cpy P8ZP_SCRATCH_W1 + sbc P8ZP_SCRATCH_W1+1 + bvc + + eor #128 ++ bmi $elseLabel""") + asmgen.translate(stmt.ifScope) + asmgen.jmp(afterIfLabel, false) + asmgen.out(elseLabel) + asmgen.translate(stmt.elseScope) + } else { + // no else block + asmgen.out(""" + sta P8ZP_SCRATCH_W1 + sty P8ZP_SCRATCH_W1+1 + ldy $valueLsb + lda $valueMsb + cpy P8ZP_SCRATCH_W1 + sbc P8ZP_SCRATCH_W1+1 + bvc + + eor #128 ++ bmi $afterIfLabel""") + asmgen.translate(stmt.ifScope) + } + asmgen.out(afterIfLabel) + } + } else { + if(jump!=null) { + val (asmLabel, indirect) = asmgen.getJumpTarget(jump) + if(indirect) { + asmgen.out(""" + cpy $valueMsb + beq + + bcc _gt + bcs _not ++ cmp $valueLsb + bcc _gt + bne _not +_gt jmp ($asmLabel) +_not""") + } else { + asmgen.out(""" + sec + sbc $valueLsb + sta P8ZP_SCRATCH_REG + tya + sbc $valueMsb + ora P8ZP_SCRATCH_REG + beq + + bcs $asmLabel ++""") + } + } else { + val afterIfLabel = asmgen.makeLabel("afterif") + if(stmt.hasElse()) { + // if and else blocks + val elseLabel = asmgen.makeLabel("else") + asmgen.out(""" + cpy $valueMsb + beq + + bcc _gt + bcs $elseLabel ++ cmp $valueLsb + bcc _gt + bne $elseLabel +_gt""") + asmgen.translate(stmt.ifScope) + asmgen.jmp(afterIfLabel, false) + asmgen.out(elseLabel) + asmgen.translate(stmt.elseScope) + } else { + // no else block + asmgen.out(""" + cpy $valueMsb + beq + + bcc _gt + bcs $afterIfLabel ++ cmp $valueLsb + bcc _gt + bne $afterIfLabel +_gt""") + asmgen.translate(stmt.ifScope) + } + asmgen.out(afterIfLabel) + } + } + } + + if(right is PtNumber) { + asmgen.assignExpressionToRegister(left, RegisterOrPair.AY, signed) + val number = right.number.toHex() + return code("#<$number", "#>$number") + } + + if(right is PtIdentifier) { + asmgen.assignExpressionToRegister(left, RegisterOrPair.AY, signed) + val variable = asmgen.asmVariableName(right) + return code("#<$variable", "#>$variable") + } + + // TODO optimize for simple array value + + // generic case via scratch register + asmgen.assignWordOperandsToAYAndVar(left, right, "P8ZP_SCRATCH_W2") + code("P8ZP_SCRATCH_W2", "P8ZP_SCRATCH_W2+1") } private fun wordLessEqualsValue(left: PtExpression, right: PtExpression, signed: Boolean, jump: PtJump?, stmt: PtIfElse) { - println("word if <=") // TODO - fallbackTranslate(stmt) + fun code(valueLsb: String, valueMsb: String) { + if(signed) { + if(jump!=null) { + val (asmLabel, indirect) = asmgen.getJumpTarget(jump) + if(indirect) { + asmgen.out(""" + sta P8ZP_SCRATCH_W1 + sty P8ZP_SCRATCH_W1+1 + ldy $valueLsb + lda $valueMsb + cpy P8ZP_SCRATCH_W1 + sbc P8ZP_SCRATCH_W1+1 + bvc + + eor #128 ++ bmi + + jmp ($asmLabel) ++""") + } else { + asmgen.out(""" + sta P8ZP_SCRATCH_W1 + sty P8ZP_SCRATCH_W1+1 + ldy $valueLsb + lda $valueMsb + cpy P8ZP_SCRATCH_W1 + sbc P8ZP_SCRATCH_W1+1 + bvc + + eor #128 ++ bpl $asmLabel""") + } + } else { + val afterIfLabel = asmgen.makeLabel("afterif") + if(stmt.hasElse()) { + // if and else blocks + val elseLabel = asmgen.makeLabel("else") + asmgen.out(""" + sta P8ZP_SCRATCH_W1 + sty P8ZP_SCRATCH_W1+1 + ldy $valueLsb + lda $valueMsb + cpy P8ZP_SCRATCH_W1 + sbc P8ZP_SCRATCH_W1+1 + bvc + + eor #128 ++ bmi $elseLabel""") + asmgen.translate(stmt.ifScope) + asmgen.jmp(afterIfLabel, false) + asmgen.out(elseLabel) + asmgen.translate(stmt.elseScope) + } else { + // no else block + asmgen.out(""" + sta P8ZP_SCRATCH_W1 + sty P8ZP_SCRATCH_W1+1 + ldy $valueLsb + lda $valueMsb + cpy P8ZP_SCRATCH_W1 + sbc P8ZP_SCRATCH_W1+1 + bvc + + eor #128 ++ bmi $afterIfLabel""") + asmgen.translate(stmt.ifScope) + } + asmgen.out(afterIfLabel) + } + } else { + if(jump!=null) { + val (asmLabel, indirect) = asmgen.getJumpTarget(jump) + if(indirect) { + asmgen.out(""" + sec + sbc $valueLsb + sta P8ZP_SCRATCH_REG + tya + sbc $valueMsb + ora P8ZP_SCRATCH_REG + beq + + bcc + + jmp $(asmLabel) ++""") + } else { + asmgen.out(""" + sec + sbc $valueLsb + sta P8ZP_SCRATCH_REG + tya + sbc $valueMsb + ora P8ZP_SCRATCH_REG + beq + + bcs $asmLabel ++""") + } + } else { + val afterIfLabel = asmgen.makeLabel("afterif") + if(stmt.hasElse()) { + // if and else blocks + val elseLabel = asmgen.makeLabel("else") + asmgen.out(""" + sec + sbc $valueLsb + sta P8ZP_SCRATCH_REG + tya + sbc $valueMsb + ora P8ZP_SCRATCH_REG + beq + + bcc $elseLabel ++""") + asmgen.translate(stmt.ifScope) + asmgen.jmp(afterIfLabel, false) + asmgen.out(elseLabel) + asmgen.translate(stmt.elseScope) + } else { + // no else block + asmgen.out(""" + sec + sbc $valueLsb + sta P8ZP_SCRATCH_REG + tya + sbc $valueMsb + ora P8ZP_SCRATCH_REG + beq + + bcc $afterIfLabel ++""") + asmgen.translate(stmt.ifScope) + } + asmgen.out(afterIfLabel) + } + } + } + + if(right is PtNumber) { + asmgen.assignExpressionToRegister(left, RegisterOrPair.AY, signed) + val number = right.number.toHex() + return code("#<$number", "#>$number") + } + + if(right is PtIdentifier) { + asmgen.assignExpressionToRegister(left, RegisterOrPair.AY, signed) + val variable = asmgen.asmVariableName(right) + return code("#<$variable", "#>$variable") + } + + // TODO optimize for simple array value + + // generic case via scratch register + asmgen.assignWordOperandsToAYAndVar(left, right, "P8ZP_SCRATCH_W2") + code("P8ZP_SCRATCH_W2", "P8ZP_SCRATCH_W2+1") } private fun wordGreaterEqualsValue(left: PtExpression, right: PtExpression, signed: Boolean, jump: PtJump?, stmt: PtIfElse) { - println("word if >=") // TODO - fallbackTranslate(stmt) + + fun code(valueLsb: String, valueMsb: String) { + if(signed) { + if(jump!=null) { + val (asmLabel, indirect) = asmgen.getJumpTarget(jump) + if(indirect) { + asmgen.out(""" + cmp $valueLsb + tya + sbc $valueMsb + bvc + + eor #128 ++ bpl + + jmp ($asmLabel) ++""") + } else { + asmgen.out(""" + cmp $valueLsb + tya + sbc $valueMsb + bvs + + eor #128 ++ bmi $asmLabel""") + } + } else { + val afterIfLabel = asmgen.makeLabel("afterif") + if(stmt.hasElse()) { + // if and else blocks + val elseLabel = asmgen.makeLabel("else") + asmgen.out(""" + cmp $valueLsb + tya + sbc $valueMsb + bvc + + eor #128 ++ bmi $elseLabel""") + asmgen.translate(stmt.ifScope) + asmgen.jmp(afterIfLabel, false) + asmgen.out(elseLabel) + asmgen.translate(stmt.elseScope) + } else { + // no else block + asmgen.out(""" + cmp $valueLsb + tya + sbc $valueMsb + bvc + + eor #128 ++ bmi $afterIfLabel""") + asmgen.translate(stmt.ifScope) + } + asmgen.out(afterIfLabel) + } + } else { + if(jump!=null) { + val (asmLabel, indirect) = asmgen.getJumpTarget(jump) + if(indirect) { + asmgen.out(""" + cmp $valueLsb + tya + sbc $valueMsb + bcs + + jmp ($asmLabel) ++""") + } else { + asmgen.out(""" + cmp $valueLsb + tya + sbc $valueMsb + bcs $asmLabel""") + } + } else { + val afterIfLabel = asmgen.makeLabel("afterif") + if(stmt.hasElse()) { + // if and else blocks + val elseLabel = asmgen.makeLabel("else") + asmgen.out(""" + cmp $valueLsb + tya + sbc $valueMsb + bcc $elseLabel""") + asmgen.translate(stmt.ifScope) + asmgen.jmp(afterIfLabel, false) + asmgen.out(elseLabel) + asmgen.translate(stmt.elseScope) + } else { + // no else block + asmgen.out(""" + cmp $valueLsb + tya + sbc $valueMsb + bcc $afterIfLabel""") + asmgen.translate(stmt.ifScope) + } + asmgen.out(afterIfLabel) + } + } + } + + if(right is PtNumber) { + asmgen.assignExpressionToRegister(left, RegisterOrPair.AY, signed) + val number = right.number.toHex() + return code("#<$number", "#>$number") + } + + if(right is PtIdentifier) { + asmgen.assignExpressionToRegister(left, RegisterOrPair.AY, signed) + val variable = asmgen.asmVariableName(right) + return code("#<$variable", "#>$variable") + } + + // TODO optimize for simple array value + + // generic case via scratch register + asmgen.assignWordOperandsToAYAndVar(left, right, "P8ZP_SCRATCH_W2") + code("P8ZP_SCRATCH_W2", "P8ZP_SCRATCH_W2+1") } + private fun loadAndCmp0MSB(value: PtExpression) { when(value) { is PtArrayIndexer -> { diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 4427770d5..d103123a7 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -1,9 +1,18 @@ TODO ==== -examples/primes is larger than on 10.1 +efficient code for assignment float comparisons against a value (it now copies the floats around too many times) 10.1 created efficient code. + examples/maze is larger than on 10.1 -examples/textelite is larger than on 10.1 +rockrunner is a lot bigger still than on 10.1 +paint is bigger than on 10.1 + +cx16/testmonogfx is broken +assembler is broken +imageviewer is broken +paint flood fill is broken +rockrunner load caveset list is broken +medemo and dsdemo are broken @@ -29,23 +38,23 @@ ok ok while not should give type error ok ok while not should give type error ok ok while not cx16.mouse_pos() should give condition type error ok ok efficient code for manipulating bools in an array (normal and agumented assigns) -ok WIP efficient code for if with only a goto in it -ok . efficient code for if byte comparisons against 0 (== and !=) -ok . efficient code for if word comparisons against 0 (== and !=) -ok . efficient code for if float comparisons against 0 (== and !=) -ok . efficient code for if byte comparisons against a value -ok . efficient code for if word comparisons against a value -ok . efficient code for if float comparisons against a value +ok ok efficient code for if with only a goto in it +ok ok efficient code for if byte comparisons against 0 (== and !=) +ok ok efficient code for if word comparisons against 0 (== and !=) +ok ok efficient code for if float comparisons against 0 (== and !=) +ok ok efficient code for if byte comparisons against a value +ok ok efficient code for if word comparisons against a value +ok ok efficient code for if float comparisons against a value ok ok efficient code for assignment byte comparisons against 0 (== and !=) -ok . efficient code for assignment word comparisons against 0 (== and !=) -ok . efficient code for assignment float comparisons against 0 (== and !=) -ok FAIL efficient code for assignment byte comparisons against a value ("float if ==" and "float if !=") -ok . efficient code for assignment word comparisons against a value -ok . efficient code for assignment float comparisons against a value +ok ok efficient code for assignment word comparisons against 0 (== and !=) +ok ok efficient code for assignment float comparisons against 0 (== and !=) +ok ok efficient code for assignment byte comparisons against a value +ok ok efficient code for assignment word comparisons against a value +ok FAIL efficient code for assignment float comparisons against a value ok ok efficient code for if_cc conditional expressions -ok FAIL while boolean should produce identical code as while integer!=0 and code should be efficient -ok . while not boolvar -> can we get rid of the cmp? (6502 only?) -ok . testmonogfx works +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 . check program sizes vs. master branch ===== ====== ======= @@ -54,18 +63,10 @@ retest all comparisons in if statements (byte, word, signed and unsigned) + all with jump, indirect jump, no else block, and both if+else blocks. 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 ubyte 0/1 to false/true boolean. +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? -boolean trick to go from a compare >= value, to a bool - cmp #value - rol a - and #1 - - -Already broken in 10.0: textelite on c64, info on diso -> jams the cpu after printing - IR: add TEST instruction to test memory content and set N/Z flags, without affecting any register. replace all LOADM+CMPI #0 / LOAD #0+LOADM+CMP+BRANCH by this instruction diff --git a/examples/cube3d-gfx.p8 b/examples/cube3d-gfx.p8 index 62518e51a..ecedf3553 100644 --- a/examples/cube3d-gfx.p8 +++ b/examples/cube3d-gfx.p8 @@ -37,8 +37,8 @@ main { angley+=217 anglez+=452 - sys.waitvsync() - sys.waitvsync() + ;sys.waitvsync() + ;sys.waitvsync() } } diff --git a/examples/test.p8 b/examples/test.p8 index cc95b4a60..5991e4bc8 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -9,17 +9,16 @@ main { word[4] words byte @shared sbb + float @shared fl=3.3 + float @shared fl2=4.3 sub start() { - while cx16.r0s < 1234 + while not staticbool2 + cx16.r0L++ + + while cx16.r0L==0 cx16.r0L++ -loop: - if cx16.r0s >= 1234 - goto skip - cx16.r0L++ - goto loop -skip: ; TODO all this for uwords