From 3e28ed4fe4a9d2e1d3fbd921ccd5ca3add18d8de Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Wed, 28 Oct 2020 22:56:13 +0100 Subject: [PATCH] mader versions of abs() and sgn() returning value in register --- compiler/res/prog8lib/math.asm | 38 +++++++++ compiler/res/prog8lib/prog8_lib.asm | 32 ++++++++ .../prog8/ast/expressions/AstExpressions.kt | 2 +- .../c64/codegen/BuiltinFunctionsAsmGen.kt | 82 ++++++++++++------- .../codegen/assignment/AssignmentAsmGen.kt | 13 +-- .../src/prog8/functions/BuiltinFunctions.kt | 8 +- examples/line-circle-txt.p8 | 2 - examples/test.p8 | 59 +++++++++++++ 8 files changed, 196 insertions(+), 40 deletions(-) diff --git a/compiler/res/prog8lib/math.asm b/compiler/res/prog8lib/math.asm index c24c18336..2f719e1ae 100644 --- a/compiler/res/prog8lib/math.asm +++ b/compiler/res/prog8lib/math.asm @@ -1282,6 +1282,44 @@ _sign_possibly_zero lda P8ESTACK_LO+1,x .pend +sign_b_into_A .proc + ; -- A = sgn(pop stack byte) + inx + lda P8ESTACK_LO,x + beq _sign_zero + bmi _sign_neg +_sign_pos lda #1 + rts +_sign_neg lda #-1 +_sign_zero rts + .pend + +sign_ub_into_A .proc + ; -- A = sgn(pop stack ubyte) + lda P8ESTACK_LO+1,x + bne sign_b._sign_pos + rts + .pend + +sign_w_into_A .proc + ; -- A = sgn(pop stack word) + lda P8ESTACK_HI+1,x + bmi sign_b._sign_neg + bne sign_b._sign_pos + rts + .pend + +sign_uw_into_A .proc + ; -- A = sgn(pop stack uword) + lda P8ESTACK_HI+1,x + beq _sign_possibly_zero +_sign_pos lda #1 + rts +_sign_possibly_zero lda P8ESTACK_LO+1,x + bne _sign_pos + rts + .pend + ; bit shifts. ; anything below 3 is done inline. anything above 7 is done via other optimizations. diff --git a/compiler/res/prog8lib/prog8_lib.asm b/compiler/res/prog8lib/prog8_lib.asm index c796e9a5a..29802bb58 100644 --- a/compiler/res/prog8lib/prog8_lib.asm +++ b/compiler/res/prog8lib/prog8_lib.asm @@ -259,6 +259,38 @@ abs_w .proc rts .pend +abs_b_into_A .proc + ; -- A = abs(pop stack byte) + inx + lda P8ESTACK_LO,x + bmi + + rts ++ eor #$ff + clc + adc #1 + rts + .pend + +abs_w_into_AY .proc + ; -- AY = abs(pop stack word) + inx + lda P8ESTACK_LO,x + ldy P8ESTACK_HI,x + bmi + + rts ++ eor #$ff + pha + tya + eor #$ff + tay + pla + clc + adc #1 + bcc + + iny ++ rts + .pend + add_w .proc ; -- push word+word / uword+uword inx diff --git a/compiler/src/prog8/ast/expressions/AstExpressions.kt b/compiler/src/prog8/ast/expressions/AstExpressions.kt index 5411594d4..8a1df2e17 100644 --- a/compiler/src/prog8/ast/expressions/AstExpressions.kt +++ b/compiler/src/prog8/ast/expressions/AstExpressions.kt @@ -821,7 +821,7 @@ class FunctionCall(override var target: IdentifierReference, val exprfunc = func.constExpressionFunc if(exprfunc!=null) resultValue = exprfunc(args, position, program) - else if(func.returntype==null) + else if(func.known_returntype==null) throw ExpressionError("builtin function ${target.nameInSource[0]} can't be used here because it doesn't return a value", position) } diff --git a/compiler/src/prog8/compiler/target/c64/codegen/BuiltinFunctionsAsmGen.kt b/compiler/src/prog8/compiler/target/c64/codegen/BuiltinFunctionsAsmGen.kt index 3a8f3ca78..103fb1225 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen/BuiltinFunctionsAsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/BuiltinFunctionsAsmGen.kt @@ -36,17 +36,18 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val when (functionName) { "msb" -> funcMsb(fcall, resultToStack) "lsb" -> funcLsb(fcall, resultToStack) - "mkword" -> funcMkword(fcall, func) // TODO resultToStack - "abs" -> funcAbs(fcall, func) // TODO resultToStack + // TODO THE OTHERS +// "mkword" -> funcMkword(fcall, func) // TODO resultToStack + "abs" -> funcAbs(fcall, func, resultToStack) "swap" -> funcSwap(fcall) - "strlen" -> funcStrlen(fcall) // TODO resultToStack - "min", "max", "sum" -> funcMinMaxSum(fcall, functionName) // TODO resultToStack - "any", "all" -> funcAnyAll(fcall, functionName) // TODO resultToStack - "sgn" -> funcSgn(fcall, func) // TODO resultToStack +// "strlen" -> funcStrlen(fcall) // TODO resultToStack +// "min", "max", "sum" -> funcMinMaxSum(fcall, functionName) // TODO resultToStack +// "any", "all" -> funcAnyAll(fcall, functionName) // TODO resultToStack + "sgn" -> funcSgn(fcall, func, resultToStack) "sin", "cos", "tan", "atan", "ln", "log2", "sqrt", "rad", "deg", "round", "floor", "ceil", - "rdnf" -> funcVariousFloatFuncs(fcall, func, functionName) // TODO resultToStack +// "rdnf" -> funcVariousFloatFuncs(fcall, func, functionName) // TODO resultToStack "rol" -> funcRol(fcall) "rol2" -> funcRol2(fcall) "ror" -> funcRor(fcall) @@ -67,8 +68,13 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val "clear_irqd" -> asmgen.out(" cli") "set_irqd" -> asmgen.out(" sei") else -> { - translateFunctionArguments(fcall.args, func) - asmgen.out(" jsr prog8_lib.func_$functionName") // TODO resultToStack + translateArguments(fcall.args, func) + if(resultToStack) { + asmgen.out(" jsr prog8_lib.func_$functionName") + } else { + TODO("builtin function $fcall") + // TODO call function that puts result in registers, not on stack + } } } } @@ -346,20 +352,31 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val } private fun funcVariousFloatFuncs(fcall: IFunctionCall, func: FSignature, functionName: String) { - translateFunctionArguments(fcall.args, func) + translateArguments(fcall.args, func) asmgen.out(" jsr floats.func_$functionName") } - private fun funcSgn(fcall: IFunctionCall, func: FSignature) { - translateFunctionArguments(fcall.args, func) + private fun funcSgn(fcall: IFunctionCall, func: FSignature, resultToStack: Boolean) { + translateArguments(fcall.args, func) val dt = fcall.args.single().inferType(program) - when (dt.typeOrElse(DataType.STRUCT)) { - DataType.UBYTE -> asmgen.out(" jsr math.sign_ub") - DataType.BYTE -> asmgen.out(" jsr math.sign_b") - DataType.UWORD -> asmgen.out(" jsr math.sign_uw") - DataType.WORD -> asmgen.out(" jsr math.sign_w") - DataType.FLOAT -> asmgen.out(" jsr floats.sign_f") - else -> throw AssemblyError("weird type $dt") + if(resultToStack) { + when (dt.typeOrElse(DataType.STRUCT)) { + DataType.UBYTE -> asmgen.out(" jsr math.sign_ub") + DataType.BYTE -> asmgen.out(" jsr math.sign_b") + DataType.UWORD -> asmgen.out(" jsr math.sign_uw") + DataType.WORD -> asmgen.out(" jsr math.sign_w") + DataType.FLOAT -> asmgen.out(" jsr floats.sign_f") + else -> throw AssemblyError("weird type $dt") + } + } else { + when (dt.typeOrElse(DataType.STRUCT)) { + DataType.UBYTE -> asmgen.out(" jsr math.sign_ub_into_A") + DataType.BYTE -> asmgen.out(" jsr math.sign_b_into_A") + DataType.UWORD -> asmgen.out(" jsr math.sign_uw_into_A") + DataType.WORD -> asmgen.out(" jsr math.sign_w_into_A") + DataType.FLOAT -> TODO("sign float using registers") + else -> throw AssemblyError("weird type $dt") + } } } @@ -758,14 +775,23 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val } } - private fun funcAbs(fcall: IFunctionCall, func: FSignature) { - translateFunctionArguments(fcall.args, func) + private fun funcAbs(fcall: IFunctionCall, func: FSignature, resultToStack: Boolean) { + translateArguments(fcall.args, func) val dt = fcall.args.single().inferType(program) - when (dt.typeOrElse(DataType.STRUCT)) { - in ByteDatatypes -> asmgen.out(" jsr prog8_lib.abs_b") - in WordDatatypes -> asmgen.out(" jsr prog8_lib.abs_w") - DataType.FLOAT -> asmgen.out(" jsr floats.abs_f") - else -> throw AssemblyError("weird type") + if(resultToStack) { + when (dt.typeOrElse(DataType.STRUCT)) { + in ByteDatatypes -> asmgen.out(" jsr prog8_lib.abs_b") + in WordDatatypes -> asmgen.out(" jsr prog8_lib.abs_w") + DataType.FLOAT -> asmgen.out(" jsr floats.abs_f") + else -> throw AssemblyError("weird type") + } + } else { + when (dt.typeOrElse(DataType.STRUCT)) { + in ByteDatatypes -> asmgen.out(" jsr prog8_lib.abs_b_into_A") + in WordDatatypes -> asmgen.out(" jsr prog8_lib.abs_w_into_AY") + DataType.FLOAT -> TODO("abs(float) via registers") + else -> throw AssemblyError("weird type") + } } } @@ -828,9 +854,9 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val """) } - private fun translateFunctionArguments(args: MutableList, signature: FSignature) { + private fun translateArguments(args: MutableList, signature: FSignature) { args.forEach { - asmgen.translateExpression(it) + asmgen.translateExpression(it) // TODO if possible, function args via 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 0d2ba9dd8..9e69f1026 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen/assignment/AssignmentAsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/assignment/AssignmentAsmGen.kt @@ -11,6 +11,7 @@ import prog8.compiler.target.c64.codegen.AsmGen import prog8.compiler.target.c64.codegen.ExpressionsAsmGen import prog8.compiler.toHex import prog8.functions.BuiltinFunctions +import prog8.functions.builtinFunctionReturnType internal class AssignmentAsmGen(private val program: Program, private val asmgen: AsmGen, private val exprAsmgen: ExpressionsAsmGen) { @@ -144,12 +145,14 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen is BuiltinFunctionStatementPlaceholder -> { val signature = BuiltinFunctions.getValue(sub.name) asmgen.translateBuiltinFunctionCallExpression(value, signature, false) - when(signature.returntype) { - in ByteDatatypes -> assignRegisterByte(assign.target, CpuRegister.A) - in WordDatatypes -> assignRegisterpairWord(assign.target, RegisterOrPair.AY) + val returntype = builtinFunctionReturnType(sub.name, value.args, program) + if(returntype.isUnknown) + throw AssemblyError("weird result type") + when(returntype.typeOrElse(DataType.STRUCT)) { + in ByteDatatypes -> assignRegisterByte(assign.target, CpuRegister.A) // function's byte result is in A + in WordDatatypes -> assignRegisterpairWord(assign.target, RegisterOrPair.AY) // function's word result is in AY DataType.FLOAT -> TODO("assign float result from ${sub.name}") - null -> {} - else -> throw AssemblyError("weird result type ${signature.returntype}") + else -> throw AssemblyError("weird result type") } } else -> { diff --git a/compiler/src/prog8/functions/BuiltinFunctions.kt b/compiler/src/prog8/functions/BuiltinFunctions.kt index f7748b901..8a85c03b3 100644 --- a/compiler/src/prog8/functions/BuiltinFunctions.kt +++ b/compiler/src/prog8/functions/BuiltinFunctions.kt @@ -17,7 +17,7 @@ typealias ConstExpressionCaller = (args: List, position: Position, p class FSignature(val pure: Boolean, // does it have side effects? val parameters: List, - val returntype: DataType?, + val known_returntype: DataType?, // specify return type if fixed, otherwise null if it depends on the arguments val constExpressionFunc: ConstExpressionCaller? = null) @@ -144,10 +144,10 @@ fun builtinFunctionReturnType(function: String, args: List, program: } val func = BuiltinFunctions.getValue(function) - if(func.returntype!=null) - return InferredTypes.knownFor(func.returntype) - // function has return values, but the return type depends on the arguments + if(func.known_returntype!=null) + return InferredTypes.knownFor(func.known_returntype) + // function has return values, but the return type depends on the arguments return when (function) { "abs" -> { val dt = args.single().inferType(program) diff --git a/examples/line-circle-txt.p8 b/examples/line-circle-txt.p8 index b919913ea..2783562d6 100644 --- a/examples/line-circle-txt.p8 +++ b/examples/line-circle-txt.p8 @@ -4,8 +4,6 @@ ; Note: this program is compatible with C64 and CX16. -; TODO the LINES are all wrong... - main { sub start() { diff --git a/examples/test.p8 b/examples/test.p8 index ecb138cba..d49f9129a 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -1,9 +1,67 @@ %import textio %import floats +%import syslib %option enable_floats ; TODO remove this option, only import floats is requires %zeropage basicsafe + +; Note: this program is compatible with C64 and CX16. + +; TODO fix abs() and the other builtin funcs + main { + sub start() { + byte bb + word ww + + bb = 0 + bb = sgn(bb) + txt.print_b(bb) + txt.chrout('\n') + bb = 127 + bb = sgn(bb) + txt.print_b(bb) + txt.chrout('\n') + bb = -1 + bb = sgn(bb) + txt.print_b(bb) + txt.chrout('\n') + bb = -127 + bb = sgn(bb) + txt.print_b(bb) + txt.chrout('\n') + bb = -128 + bb = sgn(bb) + txt.print_b(bb) + txt.chrout('\n') + txt.chrout('\n') + + ww = 0 + ww = sgn(ww) + txt.print_w(ww) + txt.chrout('\n') + ww = 32767 + ww = sgn(ww) + txt.print_w(ww) + txt.chrout('\n') + ww = -1 + ww = sgn(ww) + txt.print_w(ww) + txt.chrout('\n') + ww = -32767 + ww = sgn(ww) + txt.print_w(ww) + txt.chrout('\n') + ww = -32768 + ww = sgn(ww) + txt.print_w(ww) + txt.chrout('\n') + + main22.testX() + } +} + +main22 { sub start() { ubyte char @@ -13,6 +71,7 @@ main { ;char = 1+(lsb(ssss) * 2) ;fl = 2.0*(abs(fl) + 1.0) + char = abs(char) char = lsb(ssss) char++ char = msb(ssss)