fix abs(long), mklong(), mklong2(), peekl(), pokel()

This commit is contained in:
Irmen de Jong
2025-10-12 14:06:21 +02:00
parent 6db3611d93
commit d69eead6d8
4 changed files with 59 additions and 78 deletions

View File

@@ -887,8 +887,8 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
assignAsmGen.assignRegisterpairWord(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.AY, false, fcall.position, scope, asmgen), RegisterOrPair.AY)
}
BaseDataType.LONG -> {
asmgen.out(" jsr prog8_lib.abs_l_into_R0R1")
assignAsmGen.assignRegisterLong(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.R0R1_32, true, fcall.position, scope, asmgen), RegisterOrPair.R0R1_32)
asmgen.out(" jsr prog8_lib.abs_l_into_R14R15")
assignAsmGen.assignRegisterLong(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.R14R15_32, true, fcall.position, scope, asmgen), RegisterOrPair.R14R15_32)
}
BaseDataType.FLOAT -> {
asmgen.out(" jsr floats.func_abs_f_into_FAC1")
@@ -1059,7 +1059,8 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
asmgen.assignExpressionToRegister(fcall.args[0], RegisterOrPair.AY)
asmgen.saveRegisterStack(CpuRegister.A, false)
asmgen.saveRegisterStack(CpuRegister.Y, false)
asmgen.assignExpressionToRegister(fcall.args[1], RegisterOrPair.R0R1_32, true)
// it's a statement so no need to preserve R14:R15
asmgen.assignExpressionToRegister(fcall.args[1], RegisterOrPair.R14R15_32, true)
asmgen.restoreRegisterStack(CpuRegister.Y, false)
asmgen.restoreRegisterStack(CpuRegister.A, false)
asmgen.out(" jsr prog8_lib.func_pokel")
@@ -1190,8 +1191,8 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
// TODO optimize for the simple cases
asmgen.assignExpressionToRegister(fcall.args[0], RegisterOrPair.AY)
asmgen.out(" jsr prog8_lib.func_peekl")
val targetReg = AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.R0R1_32, true, fcall.position, fcall.definingISub(), asmgen)
assignAsmGen.assignRegisterLong(targetReg, RegisterOrPair.R0R1_32)
val targetReg = AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.R14R15_32, true, fcall.position, fcall.definingISub(), asmgen)
assignAsmGen.assignRegisterLong(targetReg, RegisterOrPair.R14R15_32)
}
@@ -1357,7 +1358,7 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
}
private fun funcMklong(fcall: PtBuiltinFunctionCall) {
// result long in R0:R1 (r0=lsw, r1=msw)
// result long in R14:R15 (r14=lsw, r15=msw)
fun isArgRegister(expression: PtExpression, reg: RegisterOrPair): Boolean {
if(expression !is PtIdentifier)
@@ -1367,25 +1368,25 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
if(fcall.args.size==2) {
// mklong2(msw, lsw)
if(isArgRegister(fcall.args[0], RegisterOrPair.R0) || isArgRegister(fcall.args[0], RegisterOrPair.R1) ||
isArgRegister(fcall.args[1], RegisterOrPair.R0) || isArgRegister(fcall.args[1], RegisterOrPair.R1)) {
error("cannot use R0 and/or R1 as arguments for mklong2 because the result should go into R0:R1 ${fcall.position}")
if(isArgRegister(fcall.args[0], RegisterOrPair.R14) || isArgRegister(fcall.args[0], RegisterOrPair.R15) ||
isArgRegister(fcall.args[1], RegisterOrPair.R14) || isArgRegister(fcall.args[1], RegisterOrPair.R15)) {
error("cannot use R14 and/or R15 as arguments for mklong2 because the result should go into R0:R1 ${fcall.position}")
} else {
assignAsmGen.assignExpressionToVariable(fcall.args[0], "cx16.r1", DataType.UWORD)
assignAsmGen.assignExpressionToVariable(fcall.args[1], "cx16.r0", DataType.UWORD)
assignAsmGen.assignExpressionToVariable(fcall.args[0], "cx16.r15", DataType.UWORD)
assignAsmGen.assignExpressionToVariable(fcall.args[1], "cx16.r14", DataType.UWORD)
}
} else {
// mklong(msb, b2, b1, lsb)
if(isArgRegister(fcall.args[0], RegisterOrPair.R0) || isArgRegister(fcall.args[0], RegisterOrPair.R1) ||
isArgRegister(fcall.args[1], RegisterOrPair.R0) || isArgRegister(fcall.args[1], RegisterOrPair.R1) ||
isArgRegister(fcall.args[2], RegisterOrPair.R0) || isArgRegister(fcall.args[2], RegisterOrPair.R1) ||
isArgRegister(fcall.args[3], RegisterOrPair.R0) || isArgRegister(fcall.args[3], RegisterOrPair.R1)) {
error("cannot use R0 and/or R1 as arguments for mklong because the result should go into R0:R1 ${fcall.position}")
if(isArgRegister(fcall.args[0], RegisterOrPair.R14) || isArgRegister(fcall.args[0], RegisterOrPair.R15) ||
isArgRegister(fcall.args[1], RegisterOrPair.R14) || isArgRegister(fcall.args[1], RegisterOrPair.R15) ||
isArgRegister(fcall.args[2], RegisterOrPair.R14) || isArgRegister(fcall.args[2], RegisterOrPair.R15) ||
isArgRegister(fcall.args[3], RegisterOrPair.R14) || isArgRegister(fcall.args[3], RegisterOrPair.R15)) {
error("cannot use R14 and/or R15 as arguments for mklong because the result should go into R14:R15 ${fcall.position}")
} else {
assignAsmGen.assignExpressionToVariable(fcall.args[0], "cx16.r1H", DataType.UBYTE)
assignAsmGen.assignExpressionToVariable(fcall.args[1], "cx16.r1L", DataType.UBYTE)
assignAsmGen.assignExpressionToVariable(fcall.args[2], "cx16.r0H", DataType.UBYTE)
assignAsmGen.assignExpressionToVariable(fcall.args[3], "cx16.r0L", DataType.UBYTE)
assignAsmGen.assignExpressionToVariable(fcall.args[0], "cx16.r15H", DataType.UBYTE)
assignAsmGen.assignExpressionToVariable(fcall.args[1], "cx16.r15L", DataType.UBYTE)
assignAsmGen.assignExpressionToVariable(fcall.args[2], "cx16.r14H", DataType.UBYTE)
assignAsmGen.assignExpressionToVariable(fcall.args[3], "cx16.r14L", DataType.UBYTE)
}
}
}

View File

@@ -655,8 +655,8 @@ internal class AssignmentAsmGen(
}
}
returnDt== BaseDataType.LONG -> {
// longs are in R0:R1 (r0=lsw, r1=msw)
assignRegisterLong(target, RegisterOrPair.R0R1_32)
// longs are in R14:R15 (r14=lsw, r15=msw)
assignRegisterLong(target, RegisterOrPair.R14R15_32)
}
returnDt==BaseDataType.FLOAT -> {
// float result from function sits in FAC1
@@ -3923,7 +3923,7 @@ $endLabel""")
else throw AssemblyError("only combined vreg allowed as long target ${target.position}")
}
TargetStorageKind.ARRAY -> {
TODO("assign 32 bits int in R0:R1 into array ${target.position}")
TODO("assign 32 bits int into array ${target.position}")
}
TargetStorageKind.MEMORY -> throw AssemblyError("memory is bytes not long ${target.position}")
TargetStorageKind.REGISTER -> {

View File

@@ -29,33 +29,33 @@ abs_w_into_AY .proc
+ rts
.pend
abs_l_into_R0R1 .proc
; -- R0:R1 = abs(R0:R1)
lda cx16.r1H
abs_l_into_R14R15 .proc
; -- R14:R15 = abs(R14:R15)
lda cx16.r15H
bmi + ; Negative if high bit of highest byte is set
rts
+
; Invert all four bytes
lda cx16.r0L
lda cx16.r14L
eor #$FF
sta cx16.r0L
lda cx16.r0H
sta cx16.r14L
lda cx16.r14H
eor #$FF
sta cx16.r0H
lda cx16.r1L
sta cx16.r14H
lda cx16.r15L
eor #$FF
sta cx16.r1L
lda cx16.r1H
sta cx16.r15L
lda cx16.r15H
eor #$FF
sta cx16.r1H
sta cx16.r15H
; Add 1 to whole 32-bit value
inc cx16.r0L
inc cx16.r14L
bne +
inc cx16.r0H
inc cx16.r14H
bne +
inc cx16.r1L
inc cx16.r15L
bne +
inc cx16.r1H
inc cx16.r15H
+ rts
.pend
@@ -479,22 +479,22 @@ from_scratchW1
.pend
func_peekl .proc
; -- read the ;pmg value on the address in AY, into R0:R1
; -- read the ;pmg value on the address in AY, into R14:R15
sta P8ZP_SCRATCH_W1
sty P8ZP_SCRATCH_W1+1
from_scratchW1
ldy #0
lda (P8ZP_SCRATCH_W1),y
sta cx16.r0
sta cx16.r14
iny
lda (P8ZP_SCRATCH_W1),y
sta cx16.r0+1
sta cx16.r14+1
iny
lda (P8ZP_SCRATCH_W1),y
sta cx16.r0+2
sta cx16.r14+2
iny
lda (P8ZP_SCRATCH_W1),y
sta cx16.r0+3
sta cx16.r14+3
rts
.pend
@@ -522,20 +522,20 @@ func_pokew_scratchW2 .proc
.pend
func_pokel .proc
; -- store the long value in R0:R1 in the address in AY
; -- store the long value in R14:R15 in the address in AY
sta P8ZP_SCRATCH_W1
sty P8ZP_SCRATCH_W1+1
ldy #0
lda cx16.r0
lda cx16.r14
sta (P8ZP_SCRATCH_W1),y
iny
lda cx16.r0+1
lda cx16.r14+1
sta (P8ZP_SCRATCH_W1),y
iny
lda cx16.r0+2
lda cx16.r14+2
sta (P8ZP_SCRATCH_W1),y
iny
lda cx16.r0+3
lda cx16.r14+3
sta (P8ZP_SCRATCH_W1),y
rts
.pend

View File

@@ -3,42 +3,22 @@
main {
sub start() {
long @shared lv1, lv2, lv3
long @shared lv1 = -123456
cx16.r0 = 12345
txt.print_l(cx16.r0)
txt.print_l(abs(lv1))
txt.spc()
cx16.r0s = -9999
txt.print_l(cx16.r0)
lv1 = -99999
lv1 = abs(lv1)
txt.print_l(abs(lv1))
txt.nl()
txt.print("sgns:\n")
word @shared w1, w2, w3
w1 = $1100
w2 = $ff00 as word
w3 = $0000
txt.print_b(sgn(w1))
cx16.r4 = $1122
cx16.r5 = $abcd
txt.print_ulhex(mklong(cx16.r5H,cx16.r5L,cx16.r4H,cx16.r4L), true)
txt.spc()
txt.print_b(sgn(w2))
txt.spc()
txt.print_b(sgn(w3))
txt.print_ulhex(mklong2(cx16.r5,cx16.r4), true)
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()
lv2 = 555555
lv3 = 222222
txt.print_bool(lv1 >= lv2+4*lv3)
txt.nl()
}
}