mirror of
https://github.com/irmen/prog8.git
synced 2025-11-01 22:16:16 +00:00
long equality comparisons
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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 */ }
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
"+" -> {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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?
|
||||
|
||||
131
examples/test.p8
131
examples/test.p8
@@ -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]--
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user