fix some more long hex value comparisons

This commit is contained in:
Irmen de Jong
2025-10-12 04:00:47 +02:00
parent 32149d073a
commit dfc720557c
9 changed files with 78 additions and 70 deletions

View File

@@ -37,7 +37,7 @@ class FSignature(val pure: Boolean, // does it have side effects?
val returns: ReturnConvention = when (returnType) {
BaseDataType.UBYTE, BaseDataType.BYTE -> ReturnConvention(returnType, RegisterOrPair.A)
BaseDataType.UWORD, BaseDataType.WORD -> ReturnConvention(returnType, RegisterOrPair.AY)
BaseDataType.LONG -> ReturnConvention(returnType, RegisterOrPair.R0R1_32)
BaseDataType.LONG -> ReturnConvention(returnType, RegisterOrPair.R14R15_32)
BaseDataType.FLOAT -> ReturnConvention(returnType, RegisterOrPair.FAC1)
in IterableDatatypes -> ReturnConvention(returnType!!, RegisterOrPair.AY)
null -> ReturnConvention(null, null)
@@ -46,7 +46,7 @@ class FSignature(val pure: Boolean, // does it have side effects?
when (val paramType = actualParamTypes.first()) {
BaseDataType.UBYTE, BaseDataType.BYTE -> ReturnConvention(paramType, RegisterOrPair.A)
BaseDataType.UWORD, BaseDataType.WORD -> ReturnConvention(paramType, RegisterOrPair.AY)
BaseDataType.LONG -> ReturnConvention(returnType, RegisterOrPair.R0R1_32)
BaseDataType.LONG -> ReturnConvention(returnType, RegisterOrPair.R14R15_32)
BaseDataType.FLOAT -> ReturnConvention(paramType, RegisterOrPair.FAC1)
in IterableDatatypes -> ReturnConvention(paramType, RegisterOrPair.AY)
else -> ReturnConvention(paramType, null)
@@ -63,7 +63,7 @@ class FSignature(val pure: Boolean, // does it have side effects?
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.R0R1_32, false)
BaseDataType.LONG -> ParamConvention(paramType, RegisterOrPair.R14R15_32, false)
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)
@@ -95,7 +95,7 @@ val BuiltinFunctions: Map<String, FSignature> = mapOf(
"ror" to FSignature(false, null, FParam("item", BaseDataType.UBYTE, BaseDataType.UWORD, BaseDataType.LONG)),
"rol2" to FSignature(false, null, FParam("item", BaseDataType.UBYTE, BaseDataType.UWORD, BaseDataType.LONG)),
"ror2" to FSignature(false, null, FParam("item", BaseDataType.UBYTE, BaseDataType.UWORD, BaseDataType.LONG)),
"cmp" to FSignature(false, null, FParam("value1", *IntegerDatatypes), FParam("value2", *NumericDatatypes)), // cmp returns a status in the carry flag, but not a proper return value
"cmp" to FSignature(false, null, FParam("value1", *IntegerDatatypes), FParam("value2", *NumericDatatypes)), // cmp returns result in the cpu status flags, but not asa proper return value
"prog8_lib_stringcompare" to FSignature(true, BaseDataType.BYTE, FParam("str1", BaseDataType.STR), FParam("str2", BaseDataType.STR)),
"prog8_lib_square_byte" to FSignature(true, BaseDataType.UBYTE, FParam("value", BaseDataType.BYTE, BaseDataType.UBYTE)),
"prog8_lib_square_word" to FSignature(true, BaseDataType.UWORD, FParam("value", BaseDataType.WORD, BaseDataType.UWORD)),

View File

@@ -950,10 +950,12 @@ class AsmGen6502Internal (
}
} else throw AssemblyError("weird casted type")
} else {
TODO("assign typecasted expression $value to a long target ${target.position} - use simple expressions and temporary variables for now")
TODO("assign typecasted expression $value to a long target ${target.kind} at ${target.position} - use simple expressions and temporary variables for now")
}
} else if(target.kind == TargetStorageKind.REGISTER) {
assignExpressionToRegister(value, target.register!!, true)
} else {
TODO("assign long expression $value to a target ${target.position} - use simple expressions and temporary variables for now")
TODO("assign long expression $value to a target ${target.kind} at ${target.position} - use simple expressions and temporary variables for now")
}
}
target.datatype.isFloat -> {

View File

@@ -418,13 +418,13 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
asmgen.out("""
sec
lda $var1
sbc #${hex.substring(6, 8)}
sbc #$${hex.substring(6, 8)}
lda $var1+1
sbc #${hex.substring(4, 6)}
sbc #$${hex.substring(4, 6)}
lda $var1+2
sbc #${hex.substring(2, 4)}
sbc #$${hex.substring(2, 4)}
lda $var1+3
sbc #${hex.take(2)}""")
sbc #$${hex.take(2)}""")
} else if(arg1 is PtIdentifier && arg2 is PtIdentifier) {
val var1 = asmgen.asmVariableName(arg1)
val var2 = asmgen.asmVariableName(arg2)
@@ -439,18 +439,19 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
lda $var1+3
sbc $var2+3""")
} else {
assignAsmGen.assignExpressionToRegister(arg2, RegisterOrPair.R2R3_32, true)
assignAsmGen.assignExpressionToRegister(arg1, RegisterOrPair.R0R1_32, true)
// cmp() doesn't return a value and as such can't be used in an expression, so no need to save the temp registers' original values
assignAsmGen.assignExpressionToRegister(arg2, RegisterOrPair.R14R15_32, true)
assignAsmGen.assignExpressionToRegister(arg1, RegisterOrPair.R12R13_32, true)
asmgen.out("""
sec
lda cx16.r0
sbc cx16.r2
lda cx16.r0+1
sbc cx16.r2+1
lda cx16.r0+2
sbc cx16.r2+2
lda cx16.r0+3
sbc cx16.r2+3""")
lda cx16.r12
sbc cx16.r14
lda cx16.r12+1
sbc cx16.r14+1
lda cx16.r12+2
sbc cx16.r14+2
lda cx16.r12+3
sbc cx16.r14+3""")
}
} else
throw AssemblyError("args for cmp() should have same dt")

View File

@@ -1437,22 +1437,7 @@ _jump jmp (${target.asmLabel})
+""")
}
} else {
asmgen.assignExpressionToRegister(left, RegisterOrPair.R2R3_32, left.type.isSigned)
asmgen.assignExpressionToRegister(right, RegisterOrPair.R0R1_32, right.type.isSigned)
asmgen.out("""
lda cx16.r0
cmp cx16.r2
bne +
lda cx16.r0+1
cmp cx16.r2+1
bne +
lda cx16.r0+2
cmp cx16.r2+2
bne +
lda cx16.r0+3
cmp cx16.r2+3
+""")
TODO("long == value expression ${right.position}")
}
if(notEquals) {
@@ -1475,24 +1460,25 @@ _jump jmp (${target.asmLabel})
jump: PtJump?,
stmt: PtIfElse
) {
// this comparison is not part of an expression but part of an if statement, there's no need to save the previous values of the temp registers
if(operator=="<" || operator ==">=") {
assignmentAsmGen.assignExpressionToRegister(right, RegisterOrPair.R2R3_32, left.type.isSigned)
assignmentAsmGen.assignExpressionToRegister(left, RegisterOrPair.R0R1_32, left.type.isSigned)
assignmentAsmGen.assignExpressionToRegister(right, RegisterOrPair.R14R15_32, left.type.isSigned)
assignmentAsmGen.assignExpressionToRegister(left, RegisterOrPair.R12R13_32, left.type.isSigned)
} else {
// flip operands
assignmentAsmGen.assignExpressionToRegister(left, RegisterOrPair.R2R3_32, left.type.isSigned)
assignmentAsmGen.assignExpressionToRegister(right, RegisterOrPair.R0R1_32, left.type.isSigned)
assignmentAsmGen.assignExpressionToRegister(left, RegisterOrPair.R14R15_32, left.type.isSigned)
assignmentAsmGen.assignExpressionToRegister(right, RegisterOrPair.R12R13_32, left.type.isSigned)
}
asmgen.out("""
sec
lda cx16.r0
sbc cx16.r2
lda cx16.r0+1
sbc cx16.r2+1
lda cx16.r0+2
sbc cx16.r2+2
lda cx16.r0+3
sbc cx16.r2+3""")
lda cx16.r12
sbc cx16.r14
lda cx16.r12+1
sbc cx16.r14+1
lda cx16.r12+2
sbc cx16.r14+2
lda cx16.r12+3
sbc cx16.r14+3""")
when(operator) {
"<", ">" -> {
if (jump != null)

View File

@@ -386,31 +386,31 @@ internal class IfExpressionAsmGen(private val asmgen: AsmGen6502Internal, privat
val varname = asmgen.asmVariableName(expr)
asmgen.out("""
lda $varname
cmp #${hex.substring(6, 8)}
cmp #$${hex.substring(6, 8)}
bne $falseLabel
lda $varname+1
cmp #${hex.substring(4, 6)}
cmp #$${hex.substring(4, 6)}
bne $falseLabel
lda $varname+2
cmp #${hex.substring(2, 4)}
cmp #$${hex.substring(2, 4)}
bne $falseLabel
lda $varname+3
cmp #${hex.take(2)}
cmp #$${hex.take(2)}
bne $falseLabel""")
} else {
asmgen.assignExpressionToRegister(expr, RegisterOrPair.R0R1_32)
asmgen.out("""
lda cx16.r0
cmp #${hex.substring(6, 8)}
cmp #$${hex.substring(6, 8)}
bne $falseLabel
lda cx16.r0+1
cmp #${hex.substring(4, 6)}
cmp #$${hex.substring(4, 6)}
bne $falseLabel
lda cx16.r0+2
cmp #${hex.substring(2, 4)}
cmp #$${hex.substring(2, 4)}
bne $falseLabel
lda cx16.r0+3
cmp #${hex.take(2)}
cmp #$${hex.take(2)}
bne $falseLabel""")
}
}

View File

@@ -1753,8 +1753,27 @@ internal class AssignmentAsmGen(
asmgen.out(" jsr prog8_lib.long_sub_inplace")
}
return true
} else if(target.kind == TargetStorageKind.REGISTER) {
val startreg = target.register!!.startregname()
asmgen.assignExpressionTo(left, target)
val rightsym = asmgen.asmVariableName(right)
asmgen.out(
"""
lda #<$rightsym
ldy #>$rightsym
sta P8ZP_SCRATCH_W1
sty P8ZP_SCRATCH_W1+1
lda #<cx16.$startreg
ldy #>cx16.$startreg"""
)
if (expr.operator == "+") {
asmgen.out(" jsr prog8_lib.long_add_inplace")
} else {
asmgen.out(" jsr prog8_lib.long_sub_inplace")
}
return true
} else {
TODO("add/subtract long ${target.position} - use simple expressions and temporary variables for now")
TODO("add/subtract long into ${target.kind} at ${target.position} - use simple expressions and temporary variables for now")
}
}
is PtNumber -> {
@@ -1794,7 +1813,7 @@ internal class AssignmentAsmGen(
}
return true
} else {
TODO("add/subtract long ${target.position} - use simple expressions and temporary variables for now")
TODO("add/subtract long into ${target.kind} ${target.position} - use simple expressions and temporary variables for now")
}
}
else -> {

View File

@@ -129,8 +129,8 @@ All elements in scoped names such as ``main.routine.var1`` are prefixed so this
}}
Subroutine Calling Convention
-----------------------------
Subroutine Calling Conventions
------------------------------
Calling a subroutine requires three steps:

View File

@@ -2,12 +2,13 @@ TODO
====
- use R12-R15 as temp registers with longs instead of R0-R3 (much less chance on clobbering)
update the warning in the docs about this
check usages of R0R1_32, because all usages of R2R3_32 have already been corrected
update/remove the warning in the docs about this
maybe reduce problem even further by storing/retrieveing the previous value of those registers? we NEED this anyway because expressions can be nested...
- (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)
- (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))
- fix crash for txt.print_l(conv.str_l(0)) and: txt.print_l(cx16.r0)
STRUCTS and TYPED POINTERS

View File

@@ -3,18 +3,17 @@
main {
sub start() {
long lv1, lv2, lv3
long @shared lv1, lv2, lv3
;txt.print_l(cx16.r0) ; TODO fix crash
;txt.print_l(conv.str_l(0)) ; TODO fix crash
lv1 = 999999
lv2 = 555555
lv3 = 222222
txt.print_l(lv3 | $2222)
txt.nl()
txt.print_bool(lv1 >= lv2+4*lv3)
lv1 = lv2-(lv3 | $2222)
txt.print_l(lv1)
txt.spc()
txt.print_ulhex(lv1, true)
txt.nl()
}
}