mirror of
https://github.com/irmen/prog8.git
synced 2026-03-11 05:41:42 +00:00
long args call convention is to pass via parameter variable not R14R15
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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() {
|
||||
|
||||
Reference in New Issue
Block a user