From c14f6cfc2b2f64ffdb14ca2f706e38a97dc7ce11 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Tue, 22 Oct 2024 22:58:32 +0200 Subject: [PATCH] more optimal if expression code --- README.md | 1 + .../cpu6502/assignment/AssignmentAsmGen.kt | 17 +++--- .../codegen/intermediate/ExpressionGen.kt | 2 +- docs/source/index.rst | 3 +- docs/source/todo.rst | 2 +- examples/test.p8 | 54 +++++-------------- 6 files changed, 23 insertions(+), 56 deletions(-) diff --git a/README.md b/README.md index 488560a45..9777c9f3a 100644 --- a/README.md +++ b/README.md @@ -66,6 +66,7 @@ What does Prog8 provide? - conditional branches that map 1:1 to cpu status flags - ``when`` statement to provide a concise jump table alternative to if/elseif chains - ``in`` expression for concise and efficient multi-value/containment check +- ``defer`` statement to help write concise and robust subroutine cleanup logic - several specialized built-in functions such as ``lsb``, ``msb``, ``min``, ``max``, ``rol``, ``ror`` - various powerful built-in libraries to do I/O, number conversions, graphics and more - inline assembly allows you to have full control when every cycle or byte matters diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt index 48cfd5479..eef92c5fb 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt @@ -645,7 +645,7 @@ internal class AssignmentAsmGen( } private fun assignIfExpression(target: AsmAssignTarget, expr: PtIfExpression) { - // TODO dont store condition as expression result but just use the flags, like a normal PtIfElse translation does + // TODO don't store condition as expression result but just use the flags, like a normal PtIfElse translation does require(target.datatype==expr.type) val falseLabel = asmgen.makeLabel("ifexpr_false") val endLabel = asmgen.makeLabel("ifexpr_end") @@ -654,32 +654,27 @@ internal class AssignmentAsmGen( when(expr.type) { in ByteDatatypesWithBoolean -> { assignExpressionToRegister(expr.truevalue, RegisterOrPair.A, false) - assignRegisterByte(target, CpuRegister.A, false, false) asmgen.jmp(endLabel) asmgen.out(falseLabel) assignExpressionToRegister(expr.falsevalue, RegisterOrPair.A, false) - assignRegisterByte(target, CpuRegister.A, false, false) asmgen.out(endLabel) + assignRegisterByte(target, CpuRegister.A, false, false) } in WordDatatypes -> { assignExpressionToRegister(expr.truevalue, RegisterOrPair.AY, false) - assignRegisterpairWord(target, RegisterOrPair.AY) asmgen.jmp(endLabel) asmgen.out(falseLabel) assignExpressionToRegister(expr.falsevalue, RegisterOrPair.AY, false) - assignRegisterpairWord(target, RegisterOrPair.AY) asmgen.out(endLabel) + assignRegisterpairWord(target, RegisterOrPair.AY) } DataType.FLOAT -> { - val trueSrc = AsmAssignSource.fromAstSource(expr.truevalue, program, asmgen) - val assignTrue = AsmAssignment(trueSrc, target, program.memsizer, expr.position) - translateNormalAssignment(assignTrue, expr.definingISub()) + assignExpressionToRegister(expr.truevalue, RegisterOrPair.FAC1, true) asmgen.jmp(endLabel) asmgen.out(falseLabel) - val falseSrc = AsmAssignSource.fromAstSource(expr.falsevalue, program, asmgen) - val assignFalse = AsmAssignment(falseSrc, target, program.memsizer, expr.position) - translateNormalAssignment(assignFalse, expr.definingISub()) + assignExpressionToRegister(expr.falsevalue, RegisterOrPair.FAC1, true) asmgen.out(endLabel) + asmgen.assignRegister(RegisterOrPair.FAC1, target) } else -> throw AssemblyError("weird dt") } diff --git a/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt b/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt index 05c6865f8..13f0aaa75 100644 --- a/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt +++ b/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt @@ -91,7 +91,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { } private fun translate(ifExpr: PtIfExpression): ExpressionCodeResult { - // TODO dont store condition as expression result but just use the flags, like a normal PtIfElse translation does + // TODO don't store condition as expression result but just use the flags, like a normal PtIfElse translation does val condTr = translateExpression(ifExpr.condition) val trueTr = translateExpression(ifExpr.truevalue) val falseTr = translateExpression(ifExpr.falsevalue) diff --git a/docs/source/index.rst b/docs/source/index.rst index e310afbd7..99ee9b8bb 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -93,11 +93,12 @@ Features still able to directly use memory addresses and ROM subroutines, and inline assembly to have full control when every register, cycle or byte matters - Variables are all allocated statically, no memory allocation overhead +- Variable data types include signed and unsigned bytes and words, arrays, strings. - Conditional branches for status flags that map 1:1 to processor branch instructions for optimal efficiency - ``when`` statement to avoid if-else chains - ``in`` expression for concise and efficient multi-value/containment test +- ``defer`` statement to help write concise and robust subroutine cleanup logic - Several specialized built-in functions, such as ``lsb``, ``msb``, ``min``, ``max``, ``rol``, ``ror`` -- Variable data types include signed and unsigned bytes and words, arrays, strings. - Various powerful built-in libraries to do I/O, number conversions, graphics and more - Floating point math is supported on certain compiler targets. - Easy and highly efficient integration with external subroutines and ROM routines on the target systems. diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 1baa49a2e..4f258d9d3 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -1,7 +1,7 @@ TODO ==== -- Optimize the IfExpression code generation to be more like regular if-else code. (both 6502 and IR) +- Optimize the IfExpression code generation to be more like regular if-else code. (both 6502 and IR) (assignIfExpression / translate(ifExpr: PtIfExpression)) Improve register load order in subroutine call args assignments: diff --git a/examples/test.p8 b/examples/test.p8 index 9a6e1cac6..af05876d9 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -1,54 +1,24 @@ -%import textio %import floats +%import textio %option no_sysinit %zeropage basicsafe main { sub start() { - uword res1 = allocate(111) - defer deallocate(res1) - uword res2 = allocate(222) - if res2==0 - return - defer deallocate(res2) + ubyte[4] values + uword[4] wvalues + float[4] fvalues + cx16.r0L = 0 + cx16.r1L = 3 + values[cx16.r0L+2] = if cx16.r1L>2 99 else 111 + wvalues[cx16.r0L+2] = if cx16.r1L>2 9999 else 1111 + fvalues[cx16.r0L+2] = if cx16.r1L>2 9.99 else 1.111 - if not process1(res1, res2) - return - if not process2(res1, res2) - return - } - - sub allocate(uword arg) -> uword { -; if arg==222 -; return 0 - txt.print("allocate ") - txt.print_uw(4000+arg) + txt.print_ub(values[2]) txt.nl() - return 4000+arg - } - - sub deallocate(uword arg) { - txt.print("dealloc ") - txt.print_uw(arg) + txt.print_uw(wvalues[2]) txt.nl() - } - - sub process1(uword arg1, uword arg2) -> bool { - txt.print("process1 ") - txt.print_uw(arg1) - txt.spc() - txt.print_uw(arg2) - txt.nl() - return true - } - - sub process2(uword arg1, uword arg2) -> bool { - txt.print("process2 ") - txt.print_uw(arg1) - txt.spc() - txt.print_uw(arg2) - txt.nl() - return true + floats.print(fvalues[2]) } }