diff --git a/compiler/src/prog8/ast/base/Base.kt b/compiler/src/prog8/ast/base/Base.kt index d5733d49d..3ee5c821b 100644 --- a/compiler/src/prog8/ast/base/Base.kt +++ b/compiler/src/prog8/ast/base/Base.kt @@ -80,7 +80,9 @@ enum class RegisterOrPair { Y, AX, AY, - XY; + XY, + FAC1, + FAC2; companion object { val names by lazy { values().map { it.toString()} } diff --git a/compiler/src/prog8/ast/processing/AstChecker.kt b/compiler/src/prog8/ast/processing/AstChecker.kt index f92aa2b44..bd82085c7 100644 --- a/compiler/src/prog8/ast/processing/AstChecker.kt +++ b/compiler/src/prog8/ast/processing/AstChecker.kt @@ -288,6 +288,7 @@ internal class AstChecker(private val program: Program, regCounts[CpuRegister.X]=regCounts.getValue(CpuRegister.X)+1 regCounts[CpuRegister.Y]=regCounts.getValue(CpuRegister.Y)+1 } + RegisterOrPair.FAC1, RegisterOrPair.FAC2 -> { /* no sensible way to count this */ } null -> if(p.statusflag!=null) statusflagCounts[p.statusflag] = statusflagCounts.getValue(p.statusflag) + 1 diff --git a/compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt b/compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt index caadf8f53..dd8288f19 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt @@ -1174,18 +1174,7 @@ $label nop""") } DataType.FLOAT -> { // return the float value via FAC1 - when (returnvalue) { - is NumericLiteralValue -> throw AssemblyError("float literal should have been changed to auto var") - is IdentifierReference -> { - val asmVar = asmVariableName(returnvalue) - out(" lda #<${asmVar} | ldy #>${asmVar} | jsr floats.MOVFM") - } - else -> { - // todo evaluate directly into fac1 instead of via stack intermediate (add RegisterOrPair.FAC1/FAC2 ??) - translateExpression(returnvalue) - out(" jsr floats.pop_float_fac1") - } - } + assignExpressionToRegister(returnvalue, RegisterOrPair.FAC1) } else -> { // all else take its address and assign that also to AY register pair diff --git a/compiler/src/prog8/compiler/target/c64/codegen/ExpressionsAsmGen.kt b/compiler/src/prog8/compiler/target/c64/codegen/ExpressionsAsmGen.kt index 97bfd298c..003d0303e 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen/ExpressionsAsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/ExpressionsAsmGen.kt @@ -1339,6 +1339,8 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge asmgen.out(" lda #0 | sta P8ESTACK_LO,x") asmgen.out(" tya | sta P8ESTACK_HI,x | dex") } + RegisterOrPair.FAC1 -> asmgen.out(" jsr floats.push_fac1") + RegisterOrPair.FAC2 -> asmgen.out(" jsr floats.push_fac2") } } else if(reg.statusflag!=null) { diff --git a/compiler/src/prog8/compiler/target/c64/codegen/assignment/AsmAssignment.kt b/compiler/src/prog8/compiler/target/c64/codegen/assignment/AsmAssignment.kt index 48a0a9f79..dae8684c3 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen/assignment/AsmAssignment.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/assignment/AsmAssignment.kt @@ -49,8 +49,8 @@ internal class AsmAssignTarget(val kind: TargetStorageKind, lateinit var origAssign: AsmAssignment init { - if(register!=null && datatype !in IntegerDatatypes) - throw AssemblyError("register must be integer type") + if(register!=null && datatype !in NumericDatatypes) + throw AssemblyError("register must be integer or float type") } companion object { @@ -75,6 +75,8 @@ internal class AsmAssignTarget(val kind: TargetStorageKind, RegisterOrPair.AX, RegisterOrPair.AY, RegisterOrPair.XY -> AsmAssignTarget(TargetStorageKind.REGISTER, program, asmgen, DataType.UWORD, scope, register = registers) + RegisterOrPair.FAC1, + RegisterOrPair.FAC2 -> AsmAssignTarget(TargetStorageKind.REGISTER, program, asmgen, DataType.FLOAT, scope, register = registers) } } } diff --git a/compiler/src/prog8/compiler/target/c64/codegen/assignment/AssignmentAsmGen.kt b/compiler/src/prog8/compiler/target/c64/codegen/assignment/AssignmentAsmGen.kt index 16d1b9e93..117a4c0a0 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen/assignment/AssignmentAsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/assignment/AssignmentAsmGen.kt @@ -527,6 +527,14 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen else -> throw AssemblyError("can't assign word to single byte register") } } + DataType.FLOAT -> { + when(target.register!!) { + RegisterOrPair.FAC1 -> asmgen.out(" jsr floats.pop_float_fac1") + RegisterOrPair.FAC2 -> asmgen.out(" jsr floats.pop_float_fac2") + else -> throw AssemblyError("can only assign float to Fac1 or 2") + } + } + else -> throw AssemblyError("weird dt") } } @@ -729,7 +737,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen asmgen.out(" jsr floats.set_array_float_from_fac1") } TargetStorageKind.MEMORY -> throw AssemblyError("can't assign float to mem byte") - TargetStorageKind.REGISTER -> throw AssemblyError("can't assign float to register") + TargetStorageKind.REGISTER -> throw AssemblyError("can't assign Fac1 float to another fac register") TargetStorageKind.STACK -> asmgen.out(" jsr floats.push_fac1") } } @@ -762,7 +770,13 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen asmgen.out(" jsr floats.set_array_float") } TargetStorageKind.MEMORY -> throw AssemblyError("can't assign float to mem byte") - TargetStorageKind.REGISTER -> throw AssemblyError("can't assign float to register") + TargetStorageKind.REGISTER -> { + when(target.register!!) { + RegisterOrPair.FAC1 -> asmgen.out(" jsr floats.MOVFM") + RegisterOrPair.FAC2 -> asmgen.out(" jsr floats.CONUPK") + else -> throw AssemblyError("can only assign float to Fac1 or 2") + } + } TargetStorageKind.STACK -> asmgen.out(" jsr floats.push_float") } } @@ -803,7 +817,13 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen asmgen.out(" jsr floats.set_array_float") } TargetStorageKind.MEMORY -> throw AssemblyError("can't assign float to mem byte") - TargetStorageKind.REGISTER -> throw AssemblyError("can't assign float to register") + TargetStorageKind.REGISTER -> { + when(target.register!!) { + RegisterOrPair.FAC1 -> asmgen.out(" lda #<$sourceName | ldy #>$sourceName | jsr floats.MOVFM") + RegisterOrPair.FAC2 -> asmgen.out(" lda #<$sourceName | ldy #>$sourceName | jsr floats.CONUPK") + else -> throw AssemblyError("can only assign float to Fac1 or 2") + } + } TargetStorageKind.STACK -> asmgen.out(" lda #<$sourceName | ldy #>$sourceName | jsr floats.push_float") } } @@ -837,6 +857,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen RegisterOrPair.AX -> asmgen.out(" lda $sourceName | ldx #0") RegisterOrPair.AY -> asmgen.out(" lda $sourceName | ldy #0") RegisterOrPair.XY -> asmgen.out(" ldx $sourceName | ldy #0") + RegisterOrPair.FAC1, RegisterOrPair.FAC2 -> throw AssemblyError("expected typecasted byte to float") } } TargetStorageKind.STACK -> { @@ -988,6 +1009,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen RegisterOrPair.AY -> { asmgen.out(" ldy #0") } RegisterOrPair.AX -> { asmgen.out(" ldx #0") } RegisterOrPair.XY -> { asmgen.out(" tax | ldy #0") } + RegisterOrPair.FAC1, RegisterOrPair.FAC2 -> throw AssemblyError("expected type cast to float") } CpuRegister.X -> when(target.register!!) { RegisterOrPair.A -> { asmgen.out(" txa") } @@ -996,6 +1018,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen RegisterOrPair.AY -> { asmgen.out(" txa | ldy #0") } RegisterOrPair.AX -> { asmgen.out(" txa | ldx #0") } RegisterOrPair.XY -> { asmgen.out(" ldy #0") } + RegisterOrPair.FAC1, RegisterOrPair.FAC2 -> throw AssemblyError("expected type cast to float") } CpuRegister.Y -> when(target.register!!) { RegisterOrPair.A -> { asmgen.out(" tya") } @@ -1004,6 +1027,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen RegisterOrPair.AY -> { asmgen.out(" tya | ldy #0") } RegisterOrPair.AX -> { asmgen.out(" tya | ldx #0") } RegisterOrPair.XY -> { asmgen.out(" tya | tax | ldy #0") } + RegisterOrPair.FAC1, RegisterOrPair.FAC2 -> throw AssemblyError("expected type cast to float") } } } @@ -1156,6 +1180,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen RegisterOrPair.AX -> asmgen.out(" lda #${byte.toHex()} | ldx #0") RegisterOrPair.AY -> asmgen.out(" lda #${byte.toHex()} | ldy #0") RegisterOrPair.XY -> asmgen.out(" ldx #${byte.toHex()} | ldy #0") + RegisterOrPair.FAC1, RegisterOrPair.FAC2 -> throw AssemblyError("expected typecasted byte to float") } TargetStorageKind.STACK -> { asmgen.out(""" @@ -1213,7 +1238,14 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen } } TargetStorageKind.MEMORY -> throw AssemblyError("can't assign float to memory byte") - TargetStorageKind.REGISTER -> throw AssemblyError("can't assign float to register") + TargetStorageKind.REGISTER -> { + val floatConst = asmgen.getFloatAsmConst(float) + when(target.register!!) { + RegisterOrPair.FAC1 -> asmgen.out(" lda #<$floatConst | ldy #>$floatConst | jsr floats.MOVFM") + RegisterOrPair.FAC2 -> asmgen.out(" lda #<$floatConst | ldy #>$floatConst | jsr floats.CONUPK") + else -> throw AssemblyError("can only assign float to Fac1 or 2") + } + } TargetStorageKind.STACK -> { val floatConst = asmgen.getFloatAsmConst(float) asmgen.out(" lda #<$floatConst | ldy #>$floatConst | jsr floats.push_float") @@ -1270,7 +1302,14 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen } } TargetStorageKind.MEMORY -> throw AssemblyError("can't assign float to memory byte") - TargetStorageKind.REGISTER -> throw AssemblyError("can't assign float to register") + TargetStorageKind.REGISTER -> { + val floatConst = asmgen.getFloatAsmConst(float) + when(target.register!!) { + RegisterOrPair.FAC1 -> asmgen.out(" lda #<$floatConst | ldy #>$floatConst | jsr floats.MOVFM") + RegisterOrPair.FAC2 -> asmgen.out(" lda #<$floatConst | ldy #>$floatConst | jsr floats.CONUPK") + else -> throw AssemblyError("can only assign float to Fac1 or 2") + } + } TargetStorageKind.STACK -> { val floatConst = asmgen.getFloatAsmConst(float) asmgen.out(" lda #<$floatConst | ldy #>$floatConst | jsr floats.push_float") @@ -1301,6 +1340,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen RegisterOrPair.AX -> asmgen.out(" lda ${address.toHex()} | ldx #0") RegisterOrPair.AY -> asmgen.out(" lda ${address.toHex()} | ldy #0") RegisterOrPair.XY -> asmgen.out(" ldy ${address.toHex()} | ldy #0") + RegisterOrPair.FAC1, RegisterOrPair.FAC2 -> throw AssemblyError("expected typecasted byte to float") } TargetStorageKind.STACK -> { asmgen.out(""" @@ -1331,6 +1371,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen RegisterOrPair.AX -> asmgen.out(" ldx #0") RegisterOrPair.AY -> asmgen.out(" ldy #0") RegisterOrPair.XY -> asmgen.out(" tax | ldy #0") + RegisterOrPair.FAC1, RegisterOrPair.FAC2 -> throw AssemblyError("expected typecasted byte to float") } } TargetStorageKind.STACK -> { diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 804ef77ff..e7bd1c408 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -3,7 +3,6 @@ TODO ==== - check the various math routines that are marked TODO in prog8_lib.asm for correctness... -- translate(ret: Return) optimize returning of float directly via FAC1 - make it possible to use cpu opcodes such as 'nop' as variable names by prefixing all asm vars with something such as '_' - option to load the built-in library files from a directory instead of the embedded ones (for easier library development/debugging) - see if we can group some errors together for instance the (now single) errors about unidentified symbols diff --git a/examples/test.p8 b/examples/test.p8 index ff30856c9..e6510372f 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -19,6 +19,11 @@ main { word ww float fl + + fl = func(33) + floats.print_f(fl) + txt.chrout('\n') + const ubyte i = 2 const ubyte j = 3 @@ -45,4 +50,9 @@ main { test_stack.test() txt.chrout('\n') } + + sub func(ubyte w) -> float { + w = w*99 + return 3344.55 + } }