diff --git a/codeCore/src/prog8/code/core/BuiltinFunctions.kt b/codeCore/src/prog8/code/core/BuiltinFunctions.kt index 266dce014..a3cd4b2a2 100644 --- a/codeCore/src/prog8/code/core/BuiltinFunctions.kt +++ b/codeCore/src/prog8/code/core/BuiltinFunctions.kt @@ -57,13 +57,13 @@ class FSignature(val pure: Boolean, // does it have side effects? return when { actualParamTypes.isEmpty() -> CallConvention(emptyList(), returns) actualParamTypes.size==1 -> { - // One parameter goes via register/registerpair. + // One parameter goes via register/registerpair (except longs) // this avoids repeated code for every caller to store the value in the subroutine's argument variable. // (that store is still done, but only coded once at the start at the subroutine itself rather than at every call site). val paramConv = when(val paramType = actualParamTypes[0]) { BaseDataType.UBYTE, BaseDataType.BYTE -> ParamConvention(paramType, RegisterOrPair.A, false) BaseDataType.UWORD, BaseDataType.WORD -> ParamConvention(paramType, RegisterOrPair.AY, false) - BaseDataType.LONG -> ParamConvention(paramType, RegisterOrPair.R14R15, false) // TODO longs should not be passed in R14R15 but via parameter variable + BaseDataType.LONG -> ParamConvention(paramType, null, true) BaseDataType.FLOAT -> ParamConvention(paramType, RegisterOrPair.AY, false) // NOTE: for builtin functions, floating point arguments are passed by reference (so you get a pointer in AY) in IterableDatatypes -> ParamConvention(paramType, RegisterOrPair.AY, false) else -> ParamConvention(paramType, null, false) diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt index d14491463..1d436a249 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt @@ -511,12 +511,12 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram, private fun funcSqrt(fcall: PtBuiltinFunctionCall, resultRegister: RegisterOrPair?, scope: IPtSubroutine?) { when(fcall.args[0].type.base) { BaseDataType.UBYTE -> { - translateArguments(fcall, scope) + translateArguments(fcall, null, scope) asmgen.out(" ldy #0 | jsr prog8_lib.func_sqrt16_into_A") assignAsmGen.assignRegisterByte(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.A, false, fcall.position, scope, asmgen), CpuRegister.A, false, false) } BaseDataType.UWORD -> { - translateArguments(fcall, scope) + translateArguments(fcall, null, scope) asmgen.out(" jsr prog8_lib.func_sqrt16_into_A") assignAsmGen.assignRegisterByte(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.A, false, fcall.position, scope, asmgen), CpuRegister.A, false, false) } @@ -527,7 +527,7 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram, assignAsmGen.assignRegisterpairWord(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.AY, false, fcall.position, scope, asmgen),RegisterOrPair.AY) } BaseDataType.FLOAT -> { - translateArguments(fcall, scope) + translateArguments(fcall, null, scope) asmgen.out(" jsr floats.func_sqrt_into_FAC1") assignAsmGen.assignFAC1float(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.FAC1, true, fcall.position, scope, asmgen)) } @@ -967,14 +967,31 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram, } private fun funcSgn(fcall: PtBuiltinFunctionCall, resultRegister: RegisterOrPair?, scope: IPtSubroutine?) { - translateArguments(fcall, scope) when (val dt = fcall.args.single().type.base) { - BaseDataType.UBYTE -> asmgen.out(" jsr prog8_lib.func_sign_ub_into_A") - BaseDataType.BYTE -> asmgen.out(" jsr prog8_lib.func_sign_b_into_A") - BaseDataType.UWORD -> asmgen.out(" jsr prog8_lib.func_sign_uw_into_A") - BaseDataType.WORD -> asmgen.out(" jsr prog8_lib.func_sign_w_into_A") - BaseDataType.LONG -> asmgen.out(" jsr prog8_lib.func_sign_l_r14r15_into_A") // note: long arg is stored in R14:R15 - BaseDataType.FLOAT -> asmgen.out(" jsr floats.func_sign_f_into_A") + BaseDataType.UBYTE -> { + translateArguments(fcall, null, scope) + asmgen.out(" jsr prog8_lib.func_sign_ub_into_A") + } + BaseDataType.BYTE -> { + translateArguments(fcall, null, scope) + asmgen.out(" jsr prog8_lib.func_sign_b_into_A") + } + BaseDataType.UWORD -> { + translateArguments(fcall, null, scope) + asmgen.out(" jsr prog8_lib.func_sign_uw_into_A") + } + BaseDataType.WORD -> { + translateArguments(fcall, null, scope) + asmgen.out(" jsr prog8_lib.func_sign_w_into_A") + } + BaseDataType.LONG -> { + translateArguments(fcall, funcname="func_sign_l_into_A", scope) + asmgen.out(" jsr prog8_lib.func_sign_l_into_A") + } + BaseDataType.FLOAT -> { + translateArguments(fcall, null, scope) + asmgen.out(" jsr floats.func_sign_f_into_A") + } else -> throw AssemblyError("weird type $dt") } assignAsmGen.assignRegisterByte(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.A, false, fcall.position, scope, asmgen), CpuRegister.A, true, true) @@ -1463,7 +1480,7 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram, } private fun funcAbs(fcall: PtBuiltinFunctionCall, resultRegister: RegisterOrPair?, scope: IPtSubroutine?) { - translateArguments(fcall, scope) + translateArguments(fcall, null, scope) val dt = fcall.args.single().type.base when (dt) { BaseDataType.BYTE -> { @@ -2712,7 +2729,7 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram, } - private fun translateArguments(call: PtBuiltinFunctionCall, scope: IPtSubroutine?) { + private fun translateArguments(call: PtBuiltinFunctionCall, funcname: String?, scope: IPtSubroutine?) { val signature = BuiltinFunctions.getValue(call.name) val callConv = signature.callConvention(call.args.map { require(it.type.isNumericOrBool) @@ -2756,13 +2773,15 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram, } } + val libfuncname = funcname ?: "func_${call.name}" + call.args.zip(callConv.params).zip(signature.parameters).forEach { val paramName = it.second.name val conv = it.first.second val value = it.first.first when { conv.variable -> { - val varname = "prog8_lib.func_${call.name}._arg_${paramName}" + val varname = "prog8_lib.${libfuncname}._arg_${paramName}" val src = when { conv.dt==BaseDataType.FLOAT -> getSourceForFloat(value) conv.dt==BaseDataType.LONG -> getSourceForLong(value) diff --git a/compiler/res/prog8lib/prog8_funcs.asm b/compiler/res/prog8lib/prog8_funcs.asm index 2634e1835..bf5a727f2 100644 --- a/compiler/res/prog8lib/prog8_funcs.asm +++ b/compiler/res/prog8lib/prog8_funcs.asm @@ -99,15 +99,16 @@ _negative lda #-1 rts .pend -func_sign_l_r14r15_into_A .proc - lda cx16.r14+3 ; msb +func_sign_l_into_A .proc + ; NOTE: takes long argument in _arg_value + lda _arg_value+3 ; msb bmi _negative bne _positive - lda cx16.r14+2 + lda _arg_value+2 bne _positive - lda cx16.r14+1 + lda _arg_value+1 bne _positive - lda cx16.r14 + lda _arg_value beq _zero lda #1 _zero @@ -119,6 +120,8 @@ _positive lda #1 rts +_arg_value .byte 0,0,0,0 + .pend diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 3dbd32f27..741bc5179 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -1,11 +1,6 @@ TODO ==== -- FSignature.callConvention should not pass long via R14R15 -- func_sign_l_r14r15_into_A should not take the long in r14r15 but in regular parameter like sqrt_long - - - Known bugs: - fix chained aliasing errors see test "chained aliasing" - fix crash in ir loader/vm for deeply nested symbol reference, see test "deeply scoped variable references" diff --git a/examples/test.p8 b/examples/test.p8 index dd0c72e07..9a942371f 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -12,8 +12,29 @@ main { long @shared l1 = -1000000 cx16.r0sL = sgn(b1) + txt.print_b(cx16.r0sL) + txt.spc() cx16.r1sL = sgn(w1) + txt.print_b(cx16.r1sL) + txt.spc() cx16.r2sL = sgn(l1) + txt.print_b(cx16.r2sL) + txt.nl() + + b1 = 100 + w1 = 1000 + l1 = 1000000 + + cx16.r0sL = sgn(b1) + txt.print_b(cx16.r0sL) + txt.spc() + cx16.r1sL = sgn(w1) + txt.print_b(cx16.r1sL) + txt.spc() + cx16.r2sL = sgn(l1) + txt.print_b(cx16.r2sL) + txt.nl() + } sub start() {