long equality comparisons

This commit is contained in:
Irmen de Jong
2025-09-27 22:46:33 +02:00
parent f1bfe619b2
commit 045c4909a8
7 changed files with 183 additions and 89 deletions

View File

@@ -1420,6 +1420,9 @@ $repeatLabel""")
sta $asmvar+2
sta $asmvar+3""")
}
BaseDataType.UWORD -> {
out(" lda #0 | sta $asmvar+2 | sta $asmvar+3")
}
BaseDataType.WORD -> {
out("""
lda $asmvar+1

View File

@@ -1263,7 +1263,23 @@ _jump jmp (${target.asmLabel})
}
private fun longEqualsZero(value: PtExpression, notEquals: Boolean, jump: PtJump?, stmt: PtIfElse) {
TODO("long == 0")
asmgen.assignExpressionToRegister(value, RegisterOrPair.R0R1_32, value.type.isSigned)
asmgen.out("""
lda cx16.r0
ora cx16.r0+1
ora cx16.r0+2
ora cx16.r0+3""")
if(notEquals) {
if (jump != null)
translateJumpElseBodies("bne", "beq", jump, stmt.elseScope)
else
translateIfElseBodies("bne", stmt)
} else {
if (jump != null)
translateJumpElseBodies("beq", "bne", jump, stmt.elseScope)
else
translateIfElseBodies("beq", stmt)
}
}
private fun longLessZero(value: PtExpression, lessEquals: Boolean, jump: PtJump?, stmt: PtIfElse) {
@@ -1374,7 +1390,72 @@ _jump jmp (${target.asmLabel})
jump: PtJump?,
stmt: PtIfElse
) {
TODO("long == value")
// TODO this can be optimized somewhat more when the left operand is a variable as well
// we only optimize for a const right value for now
val constRight = right.asConstInteger()
val variableRight = (right as? PtIdentifier)?.name
if(constRight!=null) {
asmgen.assignExpressionToRegister(left, RegisterOrPair.R0R1_32, left.type.isSigned)
val hex = constRight.toUInt().toString(16).padStart(8, '0')
asmgen.out("""
lda cx16.r0
cmp #$${hex.substring(6,8)}
bne +
lda cx16.r0+1
cmp #$${hex.substring(4, 6)}
bne +
lda cx16.r0+2
cmp #$${hex.substring(2, 4)}
bne +
lda cx16.r0+3
cmp #$${hex.take(2)}
+""")
} else if(variableRight!=null) {
require(right.type.isLong)
asmgen.assignExpressionToRegister(left, RegisterOrPair.R0R1_32, left.type.isSigned)
asmgen.out("""
lda cx16.r0
cmp $variableRight
bne +
lda cx16.r0+1
cmp $variableRight+1
bne +
lda cx16.r0+2
cmp $variableRight+2
bne +
lda cx16.r0+3
cmp $variableRight+3
+""")
} 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
+""")
}
if(notEquals) {
if (jump != null)
translateJumpElseBodies("bne", "beq", jump, stmt.elseScope)
else
translateIfElseBodies("bne", stmt)
} else {
if (jump != null)
translateJumpElseBodies("beq", "bne", jump, stmt.elseScope)
else
translateIfElseBodies("beq", stmt)
}
}
private fun wordEqualsValue(

View File

@@ -3171,7 +3171,24 @@ $endLabel""")
else -> throw AssemblyError("wrong dt ${target.position}")
}
}
TargetStorageKind.ARRAY -> TODO("assign long to array ${target.position}")
TargetStorageKind.ARRAY -> {
require(sourceDt.isLong)
val deref = target.array!!.pointerderef
if(deref!=null) {
pointergen.assignLongVar(IndexedPtrTarget(target), varName)
return
}
asmgen.loadScaledArrayIndexIntoRegister(target.array, CpuRegister.Y)
asmgen.out("""
lda $varName
sta ${target.asmVarname},y
lda $varName+1
sta ${target.asmVarname}+1,y
lda $varName+2
sta ${target.asmVarname}+2,y
lda $varName+3
sta ${target.asmVarname}+3,y""")
}
TargetStorageKind.MEMORY -> throw AssemblyError("memory is bytes not long ${target.position}")
TargetStorageKind.REGISTER -> {
require(target.register in combinedLongRegisters)
@@ -4231,7 +4248,7 @@ $endLabel""")
TargetStorageKind.ARRAY -> {
val deref = target.array!!.pointerderef
if(deref!=null) {
pointergen.assignWord(IndexedPtrTarget(target), long)
pointergen.assignLong(IndexedPtrTarget(target), long)
return
}
asmgen.loadScaledArrayIndexIntoRegister(target.array, CpuRegister.Y)
@@ -4247,7 +4264,20 @@ $endLabel""")
sta ${target.asmVarname}+3,y""")
}
TargetStorageKind.MEMORY -> throw AssemblyError("memory is bytes not long ${target.position}")
TargetStorageKind.REGISTER -> TODO("32 bits register assign? (we have no 32 bits registers right now) ${target.position}")
TargetStorageKind.REGISTER -> {
require(target.register in combinedLongRegisters)
val regstart = target.register!!.name.take(2).lowercase()
val hex = long.toUInt().toString(16).padStart(8, '0')
asmgen.out("""
lda #$${hex.substring(6,8)}
sta cx16.$regstart
lda #$${hex.substring(4,6)}
sta cx16.$regstart+1
lda #$${hex.substring(2,4)}
sta cx16.$regstart+2
lda #$${hex.take(2)}
sta cx16.$regstart+3""")
}
TargetStorageKind.POINTER -> throw AssemblyError("can't assign long to pointer, pointers are 16 bits ${target.position}")
TargetStorageKind.VOID -> { /* do nothing */ }
}

View File

@@ -111,7 +111,7 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
SourceStorageKind.LITERALBOOLEAN -> inplacemodificationLongWithLiteralval(target.asmVarname, operator, value.boolean!!.asInt())
SourceStorageKind.LITERALNUMBER -> inplacemodificationLongWithLiteralval(target.asmVarname, operator, value.number!!.number.toInt())
SourceStorageKind.VARIABLE -> inplacemodificationLongWithVariable(target.asmVarname, operator, value.asmVarname)
SourceStorageKind.EXPRESSION -> TODO("inplace modify long with expression ${target.position}")
SourceStorageKind.EXPRESSION -> inplacemodificationLongWithExpression(target.asmVarname, operator, value.expression!!)
SourceStorageKind.REGISTER -> TODO("32 bits register inplace modification? ${target.position}")
SourceStorageKind.ARRAY -> TODO("inplace modify long with array ${target.position}")
SourceStorageKind.MEMORY -> TODO("memread into long ${target.position}")
@@ -553,6 +553,11 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
}
}
internal fun inplacemodificationLongWithExpression(targetVar: String, operator: String, value: PtExpression) {
assignmentAsmGen.assignExpressionToRegister(value, RegisterOrPair.R0R1_32, value.type.isSigned)
inplacemodificationLongWithVariable(targetVar, operator, "cx16.r0")
}
internal fun inplacemodificationLongWithVariable(targetVar: String, operator: String, sourceVar: String) {
when(operator) {
"+" -> {

View File

@@ -446,6 +446,10 @@ internal class PointerAssignmentsGen(private val asmgen: AsmGen6502Internal, pri
TODO("array ptr assign word var ${target.position}")
}
internal fun assignLongVar(target: IndexedPtrTarget, varName: String) {
TODO("array ptr assign long var ${target.position}")
}
internal fun operatorDereference(binExpr: PtBinaryExpression): Triple<String, UByte, DataType> {
// the only case we support here is: a.b.c[i] . value
// returns the ZP var to use as a pointer, and a Y register offset (which can be zero), and finally the datatype of the field

View File

@@ -1,11 +1,14 @@
TODO
====
CHECK THAT >> and << work correctly for negative longs
implement the bitwise & | ^ operations as expressions on longs (all types args)
LONG TYPE
---------
- call convention: return long -> return it in R0+R1.... because AY is only 16 bits...
- call convention: long param -> passed as regular variable NOT via R0:R1? asmsubs don't have syntax for this so use explicit separate msw() and lsw() arguments... Or introduce new syntax for R0+R1 combo's?
- implement the bitwise & | ^ operations as expressions on longs (all types args)
- make sure == and != work with longs against byte and words as well signed and unsigned
- how hard is it to also implement the other comparison operators on longs?
- implement rol() and ror() on longs (also roxl and roxr)
@@ -173,6 +176,7 @@ Optimizations
-------------
- more optimized operator handling of different types, for example uword a ^ byte b now does a type cast of b to word first
- optimize longEqualsValue() for const and variable operands to not assign needlessly to R0-R3.
- Port benchmarks from https://thred.github.io/c-bench-64/ to prog8 and see how it stacks up.
- Since fixing the missing zp-var initialization, programs grew in size again because STZ's reappeared. Can we add more intelligent (and correct!) optimizations to remove those STZs that might be redundant again?
- in Identifier: use typedarray of strings instead of listOf? Other places?

View File

@@ -9,6 +9,37 @@ main {
lv1 = $11223344
lv2 = $33883388
txt.print_bool(lv1==0)
txt.spc()
txt.print_bool(lv1==1)
txt.spc()
txt.print_bool(lv1==$11000000)
txt.spc()
txt.print_bool(lv1==$11223344)
txt.nl()
txt.print_bool(lv1==lv2)
txt.spc()
lv2 = lv1
txt.print_bool(lv1==lv2)
txt.nl()
lv2 = $33883388
txt.print_bool(lv1!=0)
txt.spc()
txt.print_bool(lv1!=1)
txt.spc()
txt.print_bool(lv1!=$11000000)
txt.spc()
txt.print_bool(lv1!=$11223344)
txt.nl()
txt.print_bool(lv1!=lv2)
txt.spc()
lv2 = lv1
txt.print_bool(lv1!=lv2)
txt.nl()
txt.print_ulhex(lv1, false)
txt.nl()
lv1 = ~lv1
@@ -59,11 +90,7 @@ main {
b1 = lv1 != cx16.r0
b2 = lv2 != cx16.r0s
b1 = lv1 != lv2
}
}
/*
sub start2() {
txt.print_l(mklong2($a000,$bbbb))
txt.spc()
txt.print_ulhex(mklong2($a000,$bbbb), true)
@@ -88,16 +115,16 @@ main {
txt.nl()
long @shared lv = 111111111
long @shared lv2 = 1000000
lv2 = 1000000
word @shared ww = 1000
byte @shared bb = 1
long @shared result = lv + lv2
txt.print_l(result)
txt.spc()
result = lv + (ww as long) ; TODO automatic cast
result = lv + ww
txt.print_l(result)
txt.spc()
result = lv + (bb as long) ; TODO automatic cast
result = lv + bb
txt.print_l(result)
txt.nl()
txt.print_l(lv)
@@ -109,79 +136,19 @@ main {
txt.print_l(lv + 1000000)
txt.nl()
; long[] array = [-1999888777, -999, 42, 0, 77, 123456, 999999999]
; long xx
; for xx in array {
; txt.print_uw(msw(xx))
; txt.spc()
; txt.print_uw(lsw(xx))
; txt.nl()
; }
; txt.nl()
; array[2] = 0
; array[3] = 222222222
; array[4] = bignum
; array[5]++
; array[6]--
;
; txt.print_l(-1999888777)
; txt.spc()
; txt.print_l(-999)
; txt.spc()
; txt.print_l(-42)
; txt.spc()
; txt.print_l(0)
; txt.spc()
; txt.print_l(bignum)
; txt.nl()
; txt.print_l(bignum2)
; txt.nl()
; txt.print_l(-bignum2)
; txt.nl()
; bignum2 = -bignum2
; bignum2++
; bignum2++
; txt.print_l(bignum2)
; txt.nl()
; bignum2--
; bignum2--
; txt.print_l(bignum2)
; txt.spc()
; txt.print_l(bignum)
; txt.nl()
; txt.nl()
; bignum2 += bignum
; txt.print_l(bignum2)
; txt.nl()
; bignum2 -= bignum
; txt.print_l(bignum2)
; txt.nl()
; ^^Node test = []
;
; bignum++
; bignum2--
; txt.print_l(bignum)
; txt.spc()
; txt.print_l(bignum2)
; txt.nl()
;
; str output = "...................."
; txt.print_l(bignum)
; txt.spc()
; txt.print(conv.str_l(bignum))
; txt.nl()
;
; bignum = 999999
; bignum-- ; TODO this works in the current VM...
; bignum = -888888
;
; test.counter = 0
; test.counter ++ ; TODO ... why doesn't this? (requires plusMinusMultAnyLong routine)
; test.counter = bignum2
; test.counter --
long[] array = [-1999888777, -999, 42, 0, 77, 123456, 999999999]
long xx
for xx in array {
txt.print_uw(msw(xx))
txt.spc()
txt.print_uw(lsw(xx))
txt.nl()
}
*/
;}
txt.nl()
array[2] = 0
array[3] = 222222222
array[4] = lv1
array[5]++
array[6]--
}
}