From 1605791f1b10fc24d99feae672553c0917782c1b Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Sat, 6 Nov 2021 03:28:42 +0100 Subject: [PATCH] float swap() no longer uses evaluation stack but a single temp var instead + FAC1 --- .../compiler/target/cpu6502/codegen/AsmGen.kt | 2 +- .../cpu6502/codegen/BuiltinFunctionsAsmGen.kt | 25 ++++++++++--------- .../cpu6502/codegen/ExpressionsAsmGen.kt | 6 ++--- .../cpu6502/codegen/FunctionCallAsmGen.kt | 2 +- .../codegen/assignment/AssignmentAsmGen.kt | 8 ++---- compiler/res/prog8lib/c64/floats.p8 | 1 + compiler/res/prog8lib/cx16/floats.p8 | 3 ++- compiler/res/prog8lib/prog8_lib.p8 | 1 + .../astprocessing/StatementReorderer.kt | 1 + examples/test.p8 | 24 ++++++++++++------ 10 files changed, 42 insertions(+), 31 deletions(-) diff --git a/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/AsmGen.kt b/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/AsmGen.kt index de6e6c1d6..28cdbf59d 100644 --- a/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/AsmGen.kt +++ b/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/AsmGen.kt @@ -870,7 +870,7 @@ class AsmGen(private val program: Program, RegisterOrPair.XY, in Cx16VirtualRegisters -> assignmentAsmGen.assignRegisterpairWord(target, reg) RegisterOrPair.FAC1 -> assignmentAsmGen.assignFAC1float(target) - RegisterOrPair.FAC2 -> throw AssemblyError("no support yet to assign FAC2 directly to something") + RegisterOrPair.FAC2 -> TODO("no support yet to assign FAC2 directly to something") else -> throw AssemblyError("invalid register") } } diff --git a/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/BuiltinFunctionsAsmGen.kt b/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/BuiltinFunctionsAsmGen.kt index 4019b87e1..70810863f 100644 --- a/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/BuiltinFunctionsAsmGen.kt +++ b/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/BuiltinFunctionsAsmGen.kt @@ -875,22 +875,23 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val asmgen.translateNormalAssignment(assignSecond) } DataType.FLOAT -> { - // via evaluation stack - // TODO use 2 temporary variables instead - asmgen.translateExpression(first) - asmgen.translateExpression(second) - val assignFirst = AsmAssignment( - AsmAssignSource(SourceStorageKind.STACK, program, asmgen, DataType.FLOAT), + // via temp variable and FAC1 + asmgen.assignExpressionTo(first, AsmAssignTarget(TargetStorageKind.VARIABLE, program, asmgen, DataType.FLOAT, first.definingSubroutine, "floats.tempvar_swap_float")) + asmgen.assignExpressionTo(second, AsmAssignTarget(TargetStorageKind.REGISTER, program, asmgen, DataType.FLOAT, null, register=RegisterOrPair.FAC1)) + asmgen.translateNormalAssignment( + AsmAssignment( + AsmAssignSource(SourceStorageKind.REGISTER, program, asmgen, datatype, register = RegisterOrPair.FAC1), targetFromExpr(first, datatype), - false, program.memsizer, first.position + true, program.memsizer, first.position + ) ) - val assignSecond = AsmAssignment( - AsmAssignSource(SourceStorageKind.STACK, program, asmgen, DataType.FLOAT), + asmgen.translateNormalAssignment( + AsmAssignment( + AsmAssignSource(SourceStorageKind.VARIABLE, program, asmgen, datatype, "floats.tempvar_swap_float"), targetFromExpr(second, datatype), - false, program.memsizer, second.position + true, program.memsizer, second.position + ) ) - asmgen.translateNormalAssignment(assignFirst) - asmgen.translateNormalAssignment(assignSecond) } else -> throw AssemblyError("weird swap dt") } diff --git a/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/ExpressionsAsmGen.kt b/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/ExpressionsAsmGen.kt index 3a07f6b25..2d2d4e329 100644 --- a/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/ExpressionsAsmGen.kt +++ b/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/ExpressionsAsmGen.kt @@ -1847,7 +1847,8 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge } private fun translateExpression(expr: BinaryExpression) { - // TODO needs to use optimized assembly generation like the assignment instructions. But avoid code duplication.... rewrite all expressions into assignment form? + // Uses evalstack to evaluate the given expression. + // TODO we're slowly reducing the number of places where this is called and instead replace that by more efficient assignment-form code (using temp var or register for instance). val leftIDt = expr.left.inferType(program) val rightIDt = expr.right.inferType(program) if(!leftIDt.isKnown || !rightIDt.isKnown) @@ -1856,7 +1857,6 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge val leftDt = leftIDt.getOr(DataType.UNDEFINED) val rightDt = rightIDt.getOr(DataType.UNDEFINED) // see if we can apply some optimized routines - // TODO avoid using evaluation on stack everywhere when(expr.operator) { "+" -> { if(leftDt in IntegerDatatypes && rightDt in IntegerDatatypes) { @@ -2147,7 +2147,7 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge translateCompareStrings(expr.left, expr.operator, expr.right) } else { - // the general, non-optimized cases TODO optimize more cases.... + // the general, non-optimized cases TODO optimize more cases.... (or one day just don't use the evalstack at all anymore) translateExpressionInternal(expr.left) translateExpressionInternal(expr.right) when (leftDt) { diff --git a/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/FunctionCallAsmGen.kt b/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/FunctionCallAsmGen.kt index ad20ef3eb..75ec7b42d 100644 --- a/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/FunctionCallAsmGen.kt +++ b/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/FunctionCallAsmGen.kt @@ -147,7 +147,7 @@ internal class FunctionCallAsmGen(private val program: Program, private val asmg if(arg.isSimple) { // TODO FOR ALL ARG TYPES? // note this stuff below is needed to (eventually) avoid calling asmgen.translateExpression() // TODO but This STILL requires the translateNormalAssignment() to be fixed to avoid stack eval for expressions... - println("*** ALT PARAM PASSING FOR ASMSUB $stmt $arg") // TODO DEBUG + // println("*** ALT PARAM PASSING FOR ASMSUB $stmt $arg") // TODO DEBUG val dt = arg.inferType(program).getOr(DataType.UNDEFINED) val target = AsmAssignTarget(TargetStorageKind.STACK, program, asmgen, dt, sub) asmgen.assignExpressionTo(arg, target) diff --git a/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/assignment/AssignmentAsmGen.kt b/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/assignment/AssignmentAsmGen.kt index 7c9d1cbbd..9783f4625 100644 --- a/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/assignment/AssignmentAsmGen.kt +++ b/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/assignment/AssignmentAsmGen.kt @@ -254,7 +254,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen // (we can't use the assignment helper functions (assignExpressionTo...) to do it via registers here, // because the code here is the implementation of exactly that...) // TODO FIX THIS... by using a temp var? so that it becomes augmentable assignment expression? - exprAsmgen.translateExpression(value) + asmgen.translateExpression(value) if (assign.target.datatype in WordDatatypes && assign.source.datatype in ByteDatatypes) asmgen.signExtendStackLsb(assign.source.datatype) assignStackValue(assign.target) @@ -262,11 +262,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen } } SourceStorageKind.REGISTER -> { - when(assign.source.datatype) { - DataType.UBYTE, DataType.BYTE -> assignRegisterByte(assign.target, assign.source.register!!.asCpuRegister()) - DataType.UWORD, DataType.WORD, in PassByReferenceDatatypes -> assignRegisterpairWord(assign.target, assign.source.register!!) - else -> throw AssemblyError("invalid register dt ${assign.source.datatype}") - } + asmgen.assignRegister(assign.source.register!!, assign.target) } SourceStorageKind.STACK -> { assignStackValue(assign.target) diff --git a/compiler/res/prog8lib/c64/floats.p8 b/compiler/res/prog8lib/c64/floats.p8 index 417e9faf5..da8770ab5 100644 --- a/compiler/res/prog8lib/c64/floats.p8 +++ b/compiler/res/prog8lib/c64/floats.p8 @@ -12,6 +12,7 @@ floats { const float PI = 3.141592653589793 const float TWOPI = 6.283185307179586 + ubyte[5] tempvar_swap_float ; used for some swap() operations ; ---- C64 basic and kernal ROM float constants and functions ---- diff --git a/compiler/res/prog8lib/cx16/floats.p8 b/compiler/res/prog8lib/cx16/floats.p8 index a9a0df938..e5488ab9e 100644 --- a/compiler/res/prog8lib/cx16/floats.p8 +++ b/compiler/res/prog8lib/cx16/floats.p8 @@ -10,10 +10,11 @@ floats { ; ---- this block contains C-64 compatible floating point related functions ---- ; the addresses are from cx16 V39 emulator and roms! they won't work on older versions. - const float PI = 3.141592653589793 const float TWOPI = 6.283185307179586 + ubyte[5] tempvar_swap_float ; used for some swap() operations + ; ---- ROM float functions ---- diff --git a/compiler/res/prog8lib/prog8_lib.p8 b/compiler/res/prog8lib/prog8_lib.p8 index d4927b6ff..980a5d39d 100644 --- a/compiler/res/prog8lib/prog8_lib.p8 +++ b/compiler/res/prog8lib/prog8_lib.p8 @@ -6,6 +6,7 @@ prog8_lib { %asminclude "library:prog8_lib.asm" %asminclude "library:prog8_funcs.asm" + ; TODO these retval variables are no longer used??? uword @zp retval_interm_uw ; to store intermediary expression results for return values (hopefully allocated on ZP to reduce code size) word @zp retval_interm_w ; to store intermediary expression results for return values (hopefully allocated on ZP to reduce code size) ubyte @zp retval_interm_ub ; to store intermediary expression results for return values (hopefully allocated on ZP to reduce code size) diff --git a/compiler/src/prog8/compiler/astprocessing/StatementReorderer.kt b/compiler/src/prog8/compiler/astprocessing/StatementReorderer.kt index 5c4e84dc6..b5025ebca 100644 --- a/compiler/src/prog8/compiler/astprocessing/StatementReorderer.kt +++ b/compiler/src/prog8/compiler/astprocessing/StatementReorderer.kt @@ -53,6 +53,7 @@ internal class StatementReorderer(val program: Program, val errors: IErrorReport decl.value = null if(decl.name.startsWith("retval_interm_") && decl.definingScope.name=="prog8_lib") { // no need to zero out the special internal returnvalue intermediates. + // TODO these variables are no longer used??? return noModifications } val nextStmt = decl.nextSibling() diff --git a/examples/test.p8 b/examples/test.p8 index ce7422646..25383b5cc 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -1,15 +1,25 @@ %import textio +%import floats %zeropage basicsafe main { sub start() { - uword xx=$2000 - ubyte yy=$30 - ubyte zz=9 - ; sys.memset(xx+200, yy*2, zz+yy) +; uword xx=$2000 +; ubyte yy=$30 +; ubyte zz=9 +; ; sys.memset(xx+200, yy*2, zz+yy) +; +; @($c030) = 10 +; @($c000+yy) *= 2 +; txt.print_ub(@($c030)) - @($c030) = 10 - @($c000+yy) *= 2 - txt.print_ub(@($c030)) + float f1 = 1111.11 + float f2 = 2222.22 + float[] fa = [2222.22, 3333.33] + + swap(f1, fa[1]) + floats.print_f(f1) + txt.nl() + floats.print_f(fa[1]) } }