float swap() no longer uses evaluation stack but a single temp var instead + FAC1

This commit is contained in:
Irmen de Jong 2021-11-06 03:28:42 +01:00
parent 37a46aa2cf
commit 1605791f1b
10 changed files with 42 additions and 31 deletions

View File

@ -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")
}
}

View File

@ -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")
}

View File

@ -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) {

View File

@ -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)

View File

@ -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)

View File

@ -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 ----

View File

@ -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 ----

View File

@ -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)

View File

@ -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()

View File

@ -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])
}
}