implement more long operations on struct fields

This commit is contained in:
Irmen de Jong
2025-10-17 01:55:11 +02:00
parent de2f3f0d0d
commit c7158fd968
9 changed files with 125 additions and 26 deletions
@@ -866,7 +866,7 @@ class AsmGen6502Internal (
}
target.datatype.isLong -> {
if(value is PtNumber) {
val hex = value.asConstInteger()!!.toString(16).padStart(8, '0')
val hex = value.asConstInteger()!!.toLongHex()
when(target.kind) {
TargetStorageKind.VARIABLE -> {
out("""
@@ -2109,6 +2109,22 @@ $repeatLabel""")
}
}
internal fun loadIndirectLongIntoR14R15(zpPtrVar: String, offset: UByte) {
out("""
ldy #$offset
lda ($zpPtrVar),y
sta cx16.r14
iny
lda ($zpPtrVar),y
sta cx16.r14+1
iny
lda ($zpPtrVar),y
sta cx16.r14+2
iny
lda ($zpPtrVar),y
sta cx16.r14+3""")
}
internal fun storeIndirectByte(byte: Int, zpPtrVar: String, offset: UByte) {
if (offset > 0u) {
out(" lda #$byte | ldy #$offset | sta ($zpPtrVar),y")
@@ -2497,4 +2513,8 @@ internal class SubroutineExtraAsmInfo {
var usedFloatEvalResultVar2 = false
val extraVars = mutableListOf<Triple<BaseDataType, String, UInt?>>()
}
}
internal fun Double.toLongHex(): String = this.toUInt().toString(16).padStart(8, '0')
internal fun Int.toLongHex(): String = this.toUInt().toString(16).padStart(8, '0')
@@ -416,7 +416,7 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
if(arg2.type.isLong) {
if(arg1 is PtIdentifier && arg2 is PtNumber) {
val var1 = asmgen.asmVariableName(arg1)
val hex = arg2.number.toUInt().toString(16).padStart(8, '0')
val hex = arg2.number.toLongHex()
asmgen.out("""
sec
lda $var1
@@ -1406,7 +1406,7 @@ _jump jmp (${target.asmLabel})
if(left is PtIdentifier) {
val leftvar = asmgen.asmVariableName(left)
if(constRight!=null) {
val hex = constRight.toUInt().toString(16).padStart(8, '0')
val hex = constRight.toLongHex()
asmgen.out("""
lda $leftvar
cmp #$${hex.substring(6,8)}
@@ -1437,7 +1437,7 @@ _jump jmp (${target.asmLabel})
// TODO cannot easily preserve R14:R15 on stack because we need the status flags of the comparison in between...
asmgen.assignExpressionToRegister(left, RegisterOrPair.R14R15_32, left.type.isSigned)
if(constRight!=null) {
val hex = constRight.toUInt().toString(16).padStart(8, '0')
val hex = constRight.toLongHex()
asmgen.out("""
lda cx16.r14
cmp #$${hex.substring(6,8)}
@@ -2113,4 +2113,5 @@ _jump jmp (${target.asmLabel})
else -> throw AssemblyError("expected comparison operator")
}
}
}
}
@@ -368,7 +368,7 @@ internal class IfExpressionAsmGen(private val asmgen: AsmGen6502Internal, privat
private fun translateLongExprEqualsNumber(expr: PtExpression, number: Int, falseLabel: String) {
// if L==number
// TODO reuse code from ifElse?
val hex = number.toUInt().toString(16).padStart(8, '0')
val hex = number.toLongHex()
if(expr is PtIdentifier) {
val varname = asmgen.asmVariableName(expr)
asmgen.out("""
@@ -1044,7 +1044,7 @@ internal class ProgramAndVarsGen(
}
dt.isLongArray -> array.map {
val number = it.number!!.toInt()
val hexnum = number.absoluteValue.toString(16).padStart(8, '0')
val hexnum = number.absoluteValue.toLongHex()
if(number>=0)
"$$hexnum"
else
@@ -5,6 +5,7 @@ import prog8.code.ast.*
import prog8.code.core.*
import prog8.codegen.cpu6502.AsmGen6502Internal
import prog8.codegen.cpu6502.VariableAllocator
import prog8.codegen.cpu6502.toLongHex
import kotlin.math.log2
@@ -1783,7 +1784,7 @@ internal class AssignmentAsmGen(
}
is PtNumber -> {
asmgen.assignExpressionTo(left, target)
val hex = right.number.toInt().toString(16).padStart(8, '0')
val hex = right.number.toLongHex()
if (target.kind == TargetStorageKind.VARIABLE) {
if (expr.operator == "+") {
asmgen.out("""
@@ -4514,7 +4515,7 @@ $endLabel""")
asmgen.out(" lda #$$hexbyte | sta ${target.asmVarname}+$offset")
}
}
val hex = long.toUInt().toString(16).padStart(8, '0')
val hex = long.toLongHex()
store(hex.substring(6,8), 0)
store(hex.substring(4,6), 1)
store(hex.substring(2,4), 2)
@@ -4527,7 +4528,7 @@ $endLabel""")
return
}
asmgen.loadScaledArrayIndexIntoRegister(target.array, CpuRegister.Y)
val hex = long.toUInt().toString(16).padStart(8, '0')
val hex = long.toLongHex()
asmgen.out("""
lda #$${hex.substring(6,8)}
sta ${target.asmVarname},y
@@ -4542,7 +4543,7 @@ $endLabel""")
TargetStorageKind.REGISTER -> {
require(target.register in combinedLongRegisters)
val regstart = target.register!!.startregname()
val hex = long.toUInt().toString(16).padStart(8, '0')
val hex = long.toLongHex()
asmgen.out("""
lda #$${hex.substring(6,8)}
sta cx16.$regstart
@@ -4553,7 +4554,7 @@ $endLabel""")
lda #$${hex.take(2)}
sta cx16.$regstart+3""")
}
TargetStorageKind.POINTER -> TODO("assign long to pointer ${target.position}")
TargetStorageKind.POINTER -> pointergen.assignLong(target.pointer!!, long)
TargetStorageKind.VOID -> { /* do nothing */ }
}
}
@@ -4,6 +4,7 @@ import prog8.code.ast.*
import prog8.code.core.*
import prog8.codegen.cpu6502.AsmGen6502Internal
import prog8.codegen.cpu6502.VariableAllocator
import prog8.codegen.cpu6502.toLongHex
internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
@@ -859,7 +860,7 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
inc $variable+3
+""")
} else {
val hex = value.toUInt().toString(16).padStart(8, '0')
val hex = value.toLongHex()
asmgen.out("""
clc
lda $variable
@@ -921,7 +922,7 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
dec $variable+3
+""")
} else {
val hex = value.toUInt().toString(16).padStart(8, '0')
val hex = value.toLongHex()
asmgen.out("""
sec
lda $variable
@@ -943,7 +944,7 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
"<<" -> if (value > 0) inplaceLongShiftLeft()
">>" -> if (value > 0) inplaceLongShiftRight()
"|" -> {
val hex = value.toUInt().toString(16).padStart(8, '0')
val hex = value.toLongHex()
asmgen.out("""
lda $variable
ora #$${hex.substring(6,8)}
@@ -959,7 +960,7 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
sta $variable+3""")
}
"&" -> {
val hex = value.toUInt().toString(16).padStart(8, '0')
val hex = value.toLongHex()
asmgen.out("""
lda $variable
and #$${hex.substring(6,8)}
@@ -975,7 +976,7 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
sta $variable+3""")
}
"^" -> {
val hex = value.toUInt().toString(16).padStart(8, '0')
val hex = value.toLongHex()
asmgen.out("""
lda $variable
eor #$${hex.substring(6,8)}
@@ -5,6 +5,7 @@ import prog8.code.ast.*
import prog8.code.core.*
import prog8.codegen.cpu6502.AsmGen6502Internal
import prog8.codegen.cpu6502.VariableAllocator
import prog8.codegen.cpu6502.toLongHex
import kotlin.math.log2
@@ -248,8 +249,10 @@ internal class PointerAssignmentsGen(private val asmgen: AsmGen6502Internal, pri
asmgen.loadIndirectFloat(zpPtrVar, offset)
asmgen.assignRegister(RegisterOrPair.FAC1, target)
}
else if(value.type.isLong)
TODO("load long ${value.position}")
else if(value.type.isLong) {
asmgen.loadIndirectLongIntoR14R15(zpPtrVar, offset)
asmgen.assignRegister(RegisterOrPair.R14R15_32, target)
}
else
throw AssemblyError("weird dt ${value.type} in pointer deref assignment ${target.position}")
}
@@ -459,6 +462,25 @@ internal class PointerAssignmentsGen(private val asmgen: AsmGen6502Internal, pri
TODO("array ptr assign long var ${target.position}")
}
fun assignLong(pointer: PtPointerDeref, long: Int) {
val (ptrVar, offset) = deref(pointer)
val hex = long.toLongHex()
asmgen.out("""
ldy #$offset
lda #$${hex.substring(6,8)}
sta ($ptrVar),y
iny
lda #$${hex.substring(4, 6)}
sta ($ptrVar),y
iny
lda #$${hex.substring(2, 4)}
sta ($ptrVar),y
iny
lda #$${hex.take(2)}
sta ($ptrVar),y""")
}
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
@@ -953,18 +975,64 @@ internal class PointerAssignmentsGen(private val asmgen: AsmGen6502Internal, pri
}
private fun inplaceLongAdd(target: PtrTarget, value: AsmAssignSource) {
val (zpPtrVar, offset) = deref(target.pointer)
when(value.kind) {
SourceStorageKind.LITERALNUMBER -> TODO("inplace long add with ${value.number} ${target.position}")
SourceStorageKind.VARIABLE -> TODO("inplace long add with ${value.asmVarname} ${target.position}")
SourceStorageKind.LITERALNUMBER -> {
val hex = value.number!!.number.toLongHex()
asmgen.out("""
ldy #$offset
clc
lda ($zpPtrVar),y
adc #$${hex.substring(6, 8)}
sta ($zpPtrVar),y
iny
lda ($zpPtrVar),y
adc #$${hex.substring(4, 6)}
sta ($zpPtrVar),y
iny
lda ($zpPtrVar),y
adc #$${hex.substring(2, 4)}
sta ($zpPtrVar),y
iny
lda ($zpPtrVar),y
adc #$${hex.take(2)}
sta ($zpPtrVar),y""")
}
SourceStorageKind.VARIABLE -> {
TODO("inplace long add with ${value.asmVarname} ${target.position}")
}
SourceStorageKind.EXPRESSION -> TODO("inplace long add with ${value.expression} ${target.position}")
else -> TODO("inplace long add with ${value.kind} ${target.position}")
}
}
private fun inplaceLongSub(target: PtrTarget, value: AsmAssignSource) {
val (zpPtrVar, offset) = deref(target.pointer)
when(value.kind) {
SourceStorageKind.LITERALNUMBER -> TODO("inplace long sub with ${value.number} ${target.position}")
SourceStorageKind.VARIABLE -> TODO("inplace long sub with ${value.asmVarname} ${target.position}")
SourceStorageKind.LITERALNUMBER -> {
val hex = value.number!!.number.toLongHex()
asmgen.out("""
ldy #$offset
sec
lda ($zpPtrVar),y
sbc #$${hex.substring(6, 8)}
sta ($zpPtrVar),y
iny
lda ($zpPtrVar),y
sbc #$${hex.substring(4, 6)}
sta ($zpPtrVar),y
iny
lda ($zpPtrVar),y
sbc #$${hex.substring(2, 4)}
sta ($zpPtrVar),y
iny
lda ($zpPtrVar),y
sbc #$${hex.take(2)}
sta ($zpPtrVar),y""")
}
SourceStorageKind.VARIABLE -> {
TODO("inplace long sub with ${value.asmVarname} ${target.position}")
}
SourceStorageKind.EXPRESSION -> TODO("inplace long sub with ${value.expression} ${target.position}")
else -> TODO("inplace long sub with ${value.kind} ${target.position}")
}
+10 -2
View File
@@ -1,3 +1,6 @@
%import textio
%zeropage basicsafe
main {
struct element {
ubyte type
@@ -6,7 +9,12 @@ main {
}
sub start() {
^^element myElement
myElement.y += 1
^^element myElement = $6000
myElement.y = $44444444
long @shared lv
myElement.y -= lv
txt.print_ulhex(myElement.y, true)
}
}