mirror of
https://github.com/irmen/prog8.git
synced 2026-04-25 12:33:55 +00:00
add sgn(long) support, fix sgn() result type in IR
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -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
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user