mirror of
https://github.com/irmen/prog8.git
synced 2025-11-02 13:16:07 +00:00
fix some more long hex value comparisons
This commit is contained in:
@@ -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)),
|
||||
|
||||
@@ -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 -> {
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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""")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 -> {
|
||||
|
||||
@@ -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:
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user