optimize msb(lsw(longvar)) into @(&longvar+1)

This commit is contained in:
Irmen de Jong
2026-01-06 22:58:45 +01:00
parent bc4470aeda
commit 3a0add60fd
4 changed files with 41 additions and 29 deletions
@@ -2617,15 +2617,15 @@ $endLabel""")
}
valueDt.isByte -> {
assignExpressionToRegister(value, RegisterOrPair.A, valueDt.isSigned)
assignTypeCastedRegisters(target.asmVarname, targetDt.base, RegisterOrPair.A, valueDt.base)
assignTypeCastedRegisters(target.asmVarname, targetDt.base, RegisterOrPair.A, valueDt.base, target.position)
}
valueDt.isLong -> {
assignExpressionToRegister(value, RegisterOrPair.R14R15_32, valueDt.isSigned)
assignTypeCastedRegisters(target.asmVarname, targetDt.base, RegisterOrPair.R14R15_32, valueDt.base)
assignTypeCastedRegisters(target.asmVarname, targetDt.base, RegisterOrPair.R14R15_32, valueDt.base, target.position)
}
valueDt.isWord || valueDt.isPointer -> {
assignExpressionToRegister(value, RegisterOrPair.AY, valueDt.isSigned)
assignTypeCastedRegisters(target.asmVarname, targetDt.base, RegisterOrPair.AY, valueDt.base)
assignTypeCastedRegisters(target.asmVarname, targetDt.base, RegisterOrPair.AY, valueDt.base, target.position)
}
valueDt.isFloat -> {
assignExpressionToRegister(value, RegisterOrPair.FAC1, true)
@@ -3129,7 +3129,7 @@ $endLabel""")
private fun assignTypeCastedRegisters(targetAsmVarName: String, targetDt: BaseDataType,
regs: RegisterOrPair, sourceDt: BaseDataType) {
regs: RegisterOrPair, sourceDt: BaseDataType, position: Position) {
if(sourceDt == targetDt)
throw AssemblyError("typecast to identical type")
@@ -3158,7 +3158,7 @@ $endLabel""")
else
asmgen.out(" st${regs.toString().lowercase()} $targetAsmVarName | lda #0 | sta $targetAsmVarName+1")
}
BaseDataType.POINTER -> TODO("cast to pointer")
BaseDataType.POINTER -> TODO("cast to pointer $position")
BaseDataType.LONG -> {
asmgen.out("""
st${regs.toString().lowercase()} $targetAsmVarName
@@ -3186,7 +3186,7 @@ $endLabel""")
}
BaseDataType.BYTE -> {
when(targetDt) {
BaseDataType.BOOL -> TODO("assign byte to bool")
BaseDataType.BOOL -> TODO("assign byte to bool $position")
BaseDataType.UBYTE -> {
asmgen.out(" st${regs.toString().lowercase()} $targetAsmVarName")
}
@@ -3206,7 +3206,7 @@ $endLabel""")
asmgen.signExtendAYlsb(sourceDt)
asmgen.out(" sta $targetAsmVarName | sty $targetAsmVarName+1")
}
BaseDataType.POINTER -> TODO("cast to pointer")
BaseDataType.POINTER -> TODO("assign to pointer cast $position")
BaseDataType.LONG -> {
asmgen.out(" st${regs.toString().lowercase()} $targetAsmVarName")
asmgen.signExtendLongVariable(targetAsmVarName, sourceDt)
@@ -3230,7 +3230,7 @@ $endLabel""")
}
BaseDataType.UWORD -> {
when(targetDt) {
BaseDataType.BOOL -> TODO("assign uword to bool")
BaseDataType.BOOL -> TODO("assign uword to bool $position")
BaseDataType.BYTE, BaseDataType.UBYTE -> {
asmgen.out(" st${regs.toString().lowercase().first()} $targetAsmVarName")
}
@@ -3242,7 +3242,7 @@ $endLabel""")
else -> throw AssemblyError("non-word regs")
}
}
BaseDataType.POINTER -> TODO("cast to pointer")
BaseDataType.POINTER -> TODO("assign to pointer cast $position")
BaseDataType.LONG -> {
when(regs) {
RegisterOrPair.AX -> asmgen.out(" sta $targetAsmVarName | stx $targetAsmVarName+1")
@@ -3269,7 +3269,7 @@ $endLabel""")
}
BaseDataType.WORD -> {
when(targetDt) {
BaseDataType.BOOL -> TODO("assign word to bool")
BaseDataType.BOOL -> TODO("assign word to bool $position")
BaseDataType.BYTE, BaseDataType.UBYTE -> {
asmgen.out(" st${regs.toString().lowercase().first()} $targetAsmVarName")
}
@@ -3281,7 +3281,7 @@ $endLabel""")
else -> throw AssemblyError("non-word regs")
}
}
BaseDataType.POINTER -> TODO("cast to pointer")
BaseDataType.POINTER -> TODO("assign to pointer cast $position")
BaseDataType.LONG -> {
when(regs) {
RegisterOrPair.AX -> asmgen.out(" sta $targetAsmVarName | stx $targetAsmVarName+1")
@@ -616,7 +616,7 @@ class ExpressionSimplifier(private val program: Program, private val errors: IEr
return listOf(IAstModification.ReplaceNode(functionCallExpr, cast, parent))
}
} else if(arg is FunctionCallExpression && arg.target.nameInSource == listOf("msw")) {
// lsb(msb(longvar)) --> @(&longvar+2) ; get the bank byte from a long variable
// lsb(msw(longvar)) --> @(&longvar+2) ; get the bank byte from a long variable
val longvar = arg.args[0] as? IdentifierReference
if(longvar!=null && longvar.inferType(program).isLong) {
val address = AddressOf(longvar, null, null, false, false, functionCallExpr.position)
@@ -656,6 +656,15 @@ class ExpressionSimplifier(private val program: Program, private val errors: IEr
NumericLiteral(valueDt.getOr(DataType.UBYTE).base, 0.0, arg.expression.position),
parent))
}
} else if(arg is FunctionCallExpression && arg.target.nameInSource == listOf("lsw")) {
// msb(lsw(longvar)) --> @(&longvar+1) ; get the second byte from a long variable
val longvar = arg.args[0] as? IdentifierReference
if(longvar!=null && longvar.inferType(program).isLong) {
val address = AddressOf(longvar, null, null, false, false, functionCallExpr.position)
val plus2 = BinaryExpression(address, "+", NumericLiteral(BaseDataType.UWORD, 1.0, functionCallExpr.position), functionCallExpr.position)
val memread = DirectMemoryRead(plus2, functionCallExpr.position)
return listOf(IAstModification.ReplaceNode(functionCallExpr, memread, parent))
}
} else {
if(arg is IdentifierReference && arg.nameInSource.size==2
&& arg.nameInSource[0]=="cx16" && arg.nameInSource[1].uppercase() in RegisterOrPair.names) {
+4 -1
View File
@@ -1,6 +1,9 @@
TODO
====
- fix TODO pointer cast , for example: @(&lv as ^^ubyte + 1) = 0
Weird Heisenbug
^^^^^^^^^^^^^^^
- BUG: examples/cube3d-float crashes with div by zero error on C64 (works on cx16. ALready broken in v11, v10 still worked)
@@ -11,7 +14,7 @@ Future Things and Ideas
^^^^^^^^^^^^^^^^^^^^^^^
- implement msb(a+b), lsb(a+b), msw(a+b), lsw(a+b)
- make divmod() return the 2 results rather than accepting 2 extra variables as arguments
- introduce lmh(longvalue) builtin function that returns the low, mid, hi (bank) bytes of a long.
- introduce lmh(longvalue) -or whatever sensible name- builtin function that returns the low, mid, hi (bank) bytes of a long.
- add a -profile option that instruments the start of every prog8 subroutine with code that dumps to the emulator debug console: name of sub, stack pointer (for call depth!), emudbg cycle count. Start of program must set cycle count to zero.
- when implementing unsigned longs: remove the (multiple) "TODO "hack" to allow unsigned long constants to be used as values for signed longs, without needing a cast"
- structs: properly fix the symbol name prefix hack in StStruct.sameas(), see github issue 198
+16 -16
View File
@@ -5,7 +5,7 @@ main {
sub start() {
long @shared lv = $aabbccdd
@(&lv as ^^ubyte + 1) = 0
; TODO fix : @(&lv as ^^ubyte + 1) = 0
txt.print_ubhex(lsb(msw($11223344)), true)
txt.nl()
@@ -21,20 +21,20 @@ main {
;setbsb(lv, $99)
setlsb(lv, $44)
setmsb(lv, $11)
txt.print_ulhex(lv, true)
txt.nl()
setlsb(lv, 0)
setmsb(lv, 0)
txt.print_ulhex(lv, true)
txt.nl()
long[32] longs
longs[3]=$aabbccdd
setmsb(longs[3], $11)
setlsb(longs[3], $44)
txt.print_ulhex(longs[3], true)
txt.nl()
; setlsb(lv, $44)
; setmsb(lv, $11)
; txt.print_ulhex(lv, true)
; txt.nl()
; setlsb(lv, 0)
; setmsb(lv, 0)
; txt.print_ulhex(lv, true)
; txt.nl()
;
; long[32] longs
; longs[3]=$aabbccdd
; setmsb(longs[3], $11)
; setlsb(longs[3], $44)
; txt.print_ulhex(longs[3], true)
; txt.nl()
}
}