add sgn(long) support, fix sgn() result type in IR

This commit is contained in:
Irmen de Jong
2025-10-12 11:58:34 +02:00
parent dfc720557c
commit a84320c7e2
8 changed files with 133 additions and 22 deletions
@@ -501,7 +501,7 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
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)
}
BaseDataType.LONG -> TODO("sqrt LONG")
BaseDataType.LONG -> TODO("sqrt LONG ${fcall.position}")
BaseDataType.FLOAT -> {
asmgen.out(" jsr floats.func_sqrt_into_FAC1")
assignAsmGen.assignFAC1float(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.FAC1, true, fcall.position, scope, asmgen))
@@ -867,7 +867,7 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
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 -> TODO("sgn LONG")
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")
else -> throw AssemblyError("weird type $dt")
}
@@ -1769,7 +1769,7 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
val varname = "prog8_lib.func_${call.name}._arg_${paramName}"
val src = when {
conv.dt==BaseDataType.FLOAT -> getSourceForFloat(value)
conv.dt==BaseDataType.LONG -> TODO("LONG argument for builtin func")
conv.dt==BaseDataType.LONG -> TODO("LONG argument for builtin func ${call.position}")
conv.dt.isPassByRef -> {
// put the address of the argument in AY
val addr = PtAddressOf(DataType.forDt(conv.dt).typeForAddressOf(false), false, value.position)
@@ -2867,7 +2867,16 @@ $endLabel""")
BaseDataType.WORD -> {
asmgen.out(" lda $sourceAsmVarName | sta $targetAsmVarName | lda $sourceAsmVarName+1 | sta $targetAsmVarName+1")
}
BaseDataType.LONG -> TODO("assign typecasted to LONG")
BaseDataType.LONG -> {
asmgen.out("""
lda $sourceAsmVarName
sta $targetAsmVarName
lda $sourceAsmVarName+1
sta $targetAsmVarName+1
lda #0
sta $targetAsmVarName+2
sta $targetAsmVarName+3""")
}
BaseDataType.FLOAT -> {
asmgen.out("""
lda #<$targetAsmVarName
@@ -2965,7 +2974,14 @@ $endLabel""")
else
asmgen.out(" st${regs.toString().lowercase()} $targetAsmVarName | lda #0 | sta $targetAsmVarName+1")
}
BaseDataType.LONG -> TODO("assign typecasted to LONG")
BaseDataType.LONG -> {
asmgen.out("""
st${regs.toString().lowercase()} $targetAsmVarName
lda #0
sta $targetAsmVarName+1
sta $targetAsmVarName+2
sta $targetAsmVarName+3""")
}
BaseDataType.FLOAT -> {
when(regs) {
RegisterOrPair.A -> asmgen.out(" tay")
@@ -3005,7 +3021,10 @@ $endLabel""")
asmgen.signExtendAYlsb(sourceDt)
asmgen.out(" sta $targetAsmVarName | sty $targetAsmVarName+1")
}
BaseDataType.LONG -> TODO("assign typecasted to LONG")
BaseDataType.LONG -> {
asmgen.out(" st${regs.toString().lowercase()} $targetAsmVarName")
asmgen.signExtendLongVariable(targetAsmVarName, sourceDt)
}
BaseDataType.FLOAT -> {
when(regs) {
RegisterOrPair.A -> {}
@@ -3037,7 +3056,15 @@ $endLabel""")
else -> throw AssemblyError("non-word regs")
}
}
BaseDataType.LONG -> TODO("assign typecasted to LONG")
BaseDataType.LONG -> {
when(regs) {
RegisterOrPair.AX -> asmgen.out(" sta $targetAsmVarName | stx $targetAsmVarName+1")
RegisterOrPair.AY -> asmgen.out(" sta $targetAsmVarName | sty $targetAsmVarName+1")
RegisterOrPair.XY -> asmgen.out(" stx $targetAsmVarName | sty $targetAsmVarName+1")
else -> throw AssemblyError("non-word regs")
}
asmgen.out(" lda #0 | sta $targetAsmVarName+2 | sta $targetAsmVarName+3")
}
BaseDataType.FLOAT -> {
if(regs!=RegisterOrPair.AY)
throw AssemblyError("only supports AY here")
@@ -230,7 +230,7 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
private fun funcSgn(call: PtBuiltinFunctionCall): ExpressionCodeResult {
val result = mutableListOf<IRCodeChunkBase>()
val tr = exprGen.translateExpression(call.args.single())
val resultReg = codeGen.registers.next(tr.dt)
val resultReg = codeGen.registers.next(IRDataType.BYTE)
if(tr.dt==IRDataType.FLOAT) {
addToResult(result, tr, -1, tr.resultFpReg)
@@ -267,7 +267,14 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
}
return ExpressionCodeResult(result, IRDataType.BYTE, resultReg, -1)
}
BaseDataType.LONG -> TODO("SQRT LONG")
BaseDataType.LONG -> {
addToResult(result, tr, tr.resultReg, -1)
val resultReg = codeGen.registers.next(IRDataType.WORD) // sqrt of a long still produces just a word result
result += IRCodeChunk(null, null).also {
it += IRInstruction(Opcode.SQRT, IRDataType.LONG, reg1=resultReg, reg2=tr.resultReg)
}
return ExpressionCodeResult(result, IRDataType.WORD, resultReg, -1)
}
BaseDataType.FLOAT -> {
addToResult(result, tr, -1, tr.resultFpReg)
val resultFpReg = codeGen.registers.next(IRDataType.FLOAT)
+30 -8
View File
@@ -89,17 +89,39 @@ _possibly_zero cmp #0
func_sign_w_into_A .proc
cpy #0
beq _possibly_zero
bmi _neg
_pos lda #1
rts
_neg lda #-1
rts
_possibly_zero cmp #0
bne _pos
bmi _negative
bne _positive
cmp #0
beq _zero
_positive lda #1
_zero rts
_negative lda #-1
rts
.pend
func_sign_l_r14r15_into_A .proc
lda cx16.r14+3 ; msb
bmi _negative
bne _positive
lda cx16.r14+2
bne _positive
lda cx16.r14+1
bne _positive
lda cx16.r14
beq _zero
lda #1
_zero
rts
_negative
lda #-1
rts
_positive
lda #1
rts
.pend
func_sqrt16_into_A .proc
; integer square root
+18
View File
@@ -184,5 +184,23 @@ main {
compileText(Cx16Target(), false, src, outputDir, writeAssembly = true) shouldNotBe null
compileText(C64Target(), false, src, outputDir, writeAssembly = true) shouldNotBe null
}
test("sgn") {
val src="""
main {
sub start() {
byte @shared b1 = -100
word @shared w1 = -1000
long @shared l1 = -1000000
cx16.r0sL = sgn(b1)
cx16.r1sL = sgn(w1)
cx16.r2sL = sgn(l1)
}
}"""
compileText(Cx16Target(), false, src, outputDir, writeAssembly = true) shouldNotBe null
compileText(C64Target(), false, src, outputDir, writeAssembly = true) shouldNotBe null
compileText(VMTarget(), false, src, outputDir, writeAssembly = true) shouldNotBe null
}
})
+1 -1
View File
@@ -8,7 +8,7 @@ TODO
- (not needed anymore if everything is saved on the stack?:) can the compiler give a warning if you use R0/R1 (or whatever the temp storage is) in expressions and/or statements together with long integers? (because R0/R1 are likely to be clobbered as temporary storage)
- fix crash for txt.print_l(conv.str_l(0)) and: txt.print_l(cx16.r0)
- fix crash for txt.print_l(conv.str_l(0))
STRUCTS and TYPED POINTERS
+33 -2
View File
@@ -5,8 +5,39 @@ main {
sub start() {
long @shared lv1, lv2, lv3
;txt.print_l(cx16.r0) ; TODO fix crash
;txt.print_l(conv.str_l(0)) ; TODO fix crash
cx16.r0 = 12345
txt.print_l(cx16.r0)
txt.spc()
cx16.r0s = -9999
txt.print_l(cx16.r0)
txt.nl()
txt.print("sgns:\n")
word @shared w1, w2, w3
w1 = $1100
w2 = $ff00 as word
w3 = $0000
txt.print_b(sgn(w1))
txt.spc()
txt.print_b(sgn(w2))
txt.spc()
txt.print_b(sgn(w3))
txt.nl()
lv1= 333333
lv2 = -22222
lv3 = 0
txt.print_b(sgn(lv1))
txt.spc()
txt.print_b(sgn(lv2))
txt.spc()
txt.print_b(sgn(lv3))
txt.nl()
; txt.print_l(conv.str_l(0)) ; TODO fix crash
; txt.print_l(conv.str_l(987654)) ; TODO fix crash
; txt.print_l(conv.str_l(-12345)) ; TODO fix crash
lv1 = 999999
lv2 = 555555
@@ -1086,11 +1086,17 @@ data class IRInstruction(
if(type==IRDataType.WORD) {
// some word instructions have byte reg1
return when (opcode) {
Opcode.STOREZX, Opcode.SQRT -> IRDataType.BYTE
Opcode.SGN, Opcode.STOREZX, Opcode.SQRT -> IRDataType.BYTE
Opcode.EXT, Opcode.EXTS, Opcode.CONCAT -> IRDataType.LONG
else -> IRDataType.WORD
else -> type
}
}
if(type==IRDataType.LONG) {
return if(opcode==Opcode.SGN)
IRDataType.BYTE
else
type
}
if(opcode==Opcode.JUMPI || opcode==Opcode.CALLI || opcode==Opcode.STOREZI)
return IRDataType.WORD
if(opcode==Opcode.EXT || opcode==Opcode.EXTS)