From 34061c5a63669017e9cf928265bf6db71fdbec9a Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Tue, 28 Oct 2025 23:44:34 +0100 Subject: [PATCH] implement inplace bitwise operations on long struct fields --- .../assignment/PointerAssignmentsGen.kt | 221 +++++++++++++++++- examples/test.p8 | 37 +-- 2 files changed, 237 insertions(+), 21 deletions(-) diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/PointerAssignmentsGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/PointerAssignmentsGen.kt index 05e9ef76f..6d936e166 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/PointerAssignmentsGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/PointerAssignmentsGen.kt @@ -314,21 +314,21 @@ internal class PointerAssignmentsGen(private val asmgen: AsmGen6502Internal, pri // byte targets are handled as direct memory access, not a pointer operation anymore however boolean targets are still to be handled here if(target.dt.isByteOrBool) inplaceByteAnd(target, value) else if(target.dt.isWord) inplaceWordAnd(target, value) - else if(target.dt.isLong) TODO("inplace long and ${target.position}") + else if(target.dt.isLong) inplaceLongAnd(target, value) else throw AssemblyError("weird dt ${target.dt} ${target.position}") } "|", "or" -> { // byte targets are handled as direct memory access, not a pointer operation anymore however boolean targets are still to be handled here if(target.dt.isByteOrBool) inplaceByteOr(target, value) else if(target.dt.isWord) inplaceWordOr(target, value) - else if(target.dt.isLong) TODO("inplace long or ${target.position}") + else if(target.dt.isLong) inplaceLongOr(target, value) else throw AssemblyError("weird dt ${target.dt} ${target.position}") } "^", "xor" -> { // byte targets are handled as direct memory access, not a pointer operation anymore however boolean targets are still to be handled here if(target.dt.isByteOrBool) inplaceByteXor(target, value) else if(target.dt.isWord) inplaceWordXor(target, value) - else if(target.dt.isLong) TODO("inplace long xor ${target.position}") + else if(target.dt.isLong) inplaceLongXor(target, value) else throw AssemblyError("weird dt ${target.dt} ${target.position}") } else -> throw AssemblyError("invalid operator for in-place modification $operator") @@ -1787,7 +1787,220 @@ internal class PointerAssignmentsGen(private val asmgen: AsmGen6502Internal, pri } } - fun assignIndexedPointer(target: AsmAssignTarget, arrayVarName: String, index: PtExpression, arrayDt: DataType) { + private fun inplaceLongAnd(target: PtrTarget, value: AsmAssignSource) { + val (zpPtrVar, offset) = deref(target.pointer) + when(value.kind) { + SourceStorageKind.LITERALNUMBER -> { + val number = value.number!!.number.toLongHex() + asmgen.out(""" + ldy #$offset + lda ($zpPtrVar),y + and #$${number.substring(6,8)} + sta ($zpPtrVar),y + iny + lda ($zpPtrVar),y + and #$${number.substring(4, 6)} + sta ($zpPtrVar),y + iny + lda ($zpPtrVar),y + and #$${number.substring(2, 4)} + sta ($zpPtrVar),y + iny + lda ($zpPtrVar),y + and #$${number.take(2)} + sta ($zpPtrVar),y""") + } + SourceStorageKind.VARIABLE -> { + require(value.datatype.isLong) + val varname = value.asmVarname + asmgen.out(""" + ldy #$offset + lda ($zpPtrVar),y + and $varname + sta ($zpPtrVar),y + iny + lda ($zpPtrVar),y + and $varname+1 + sta ($zpPtrVar),y + iny + lda ($zpPtrVar),y + and $varname+2 + sta ($zpPtrVar),y + iny + lda ($zpPtrVar),y + and $varname+3 + sta ($zpPtrVar),y""") + } + SourceStorageKind.EXPRESSION -> { + require(value.datatype.isLong) + // not an expression so no need to preserve R14/R15 + asmgen.assignExpressionToRegister(value.expression!!, RegisterOrPair.R14R15_32, target.dt.isSigned) + asmgen.out(""" + ldy #$offset + lda ($zpPtrVar),y + and cx16.r14 + sta ($zpPtrVar),y + iny + lda ($zpPtrVar),y + and cx16.r14+1 + sta ($zpPtrVar),y + iny + lda ($zpPtrVar),y + and cx16.r14+2 + sta ($zpPtrVar),y + iny + lda ($zpPtrVar),y + and cx16.r14+3 + sta ($zpPtrVar),y""") + } + SourceStorageKind.REGISTER -> TODO("inplace long &= register ${target.position}") + else -> throw AssemblyError("weird source value $value") + } + } + + private fun inplaceLongOr(target: PtrTarget, value: AsmAssignSource) { + val (zpPtrVar, offset) = deref(target.pointer) + when(value.kind) { + SourceStorageKind.LITERALNUMBER -> { + val number = value.number!!.number.toLongHex() + asmgen.out(""" + ldy #$offset + lda ($zpPtrVar),y + ora #$${number.substring(6,8)} + sta ($zpPtrVar),y + iny + lda ($zpPtrVar),y + ora #$${number.substring(4, 6)} + sta ($zpPtrVar),y + iny + lda ($zpPtrVar),y + ora #$${number.substring(2, 4)} + sta ($zpPtrVar),y + iny + lda ($zpPtrVar),y + ora #$${number.take(2)} + sta ($zpPtrVar),y""") + } + SourceStorageKind.VARIABLE -> { + require(value.datatype.isLong) + val varname = value.asmVarname + asmgen.out(""" + ldy #$offset + lda ($zpPtrVar),y + ora $varname + sta ($zpPtrVar),y + iny + lda ($zpPtrVar),y + ora $varname+1 + sta ($zpPtrVar),y + iny + lda ($zpPtrVar),y + ora $varname+2 + sta ($zpPtrVar),y + iny + lda ($zpPtrVar),y + ora $varname+3 + sta ($zpPtrVar),y""") + } + SourceStorageKind.EXPRESSION -> { + require(value.datatype.isLong) + // not an expression so no need to preserve R14/R15 + asmgen.assignExpressionToRegister(value.expression!!, RegisterOrPair.R14R15_32, target.dt.isSigned) + asmgen.out(""" + ldy #$offset + lda ($zpPtrVar),y + ora cx16.r14 + sta ($zpPtrVar),y + iny + lda ($zpPtrVar),y + ora cx16.r14+1 + sta ($zpPtrVar),y + iny + lda ($zpPtrVar),y + ora cx16.r14+2 + sta ($zpPtrVar),y + iny + lda ($zpPtrVar),y + ora cx16.r14+3 + sta ($zpPtrVar),y""") + } + SourceStorageKind.REGISTER -> TODO("inplace long |= register ${target.position}") + else -> throw AssemblyError("weird source value $value") + } + } + + private fun inplaceLongXor(target: PtrTarget, value: AsmAssignSource) { + val (zpPtrVar, offset) = deref(target.pointer) + when(value.kind) { + SourceStorageKind.LITERALNUMBER -> { + val number = value.number!!.number.toLongHex() + asmgen.out(""" + ldy #$offset + lda ($zpPtrVar),y + eor #$${number.substring(6,8)} + sta ($zpPtrVar),y + iny + lda ($zpPtrVar),y + eor #$${number.substring(4, 6)} + sta ($zpPtrVar),y + iny + lda ($zpPtrVar),y + eor #$${number.substring(2, 4)} + sta ($zpPtrVar),y + iny + lda ($zpPtrVar),y + eor #$${number.take(2)} + sta ($zpPtrVar),y""") + } + SourceStorageKind.VARIABLE -> { + require(value.datatype.isLong) + val varname = value.asmVarname + asmgen.out(""" + ldy #$offset + lda ($zpPtrVar),y + eor $varname + sta ($zpPtrVar),y + iny + lda ($zpPtrVar),y + eor $varname+1 + sta ($zpPtrVar),y + iny + lda ($zpPtrVar),y + eor $varname+2 + sta ($zpPtrVar),y + iny + lda ($zpPtrVar),y + eor $varname+3 + sta ($zpPtrVar),y""") + } + SourceStorageKind.EXPRESSION -> { + require(value.datatype.isLong) + // not an expression so no need to preserve R14/R15 + asmgen.assignExpressionToRegister(value.expression!!, RegisterOrPair.R14R15_32, target.dt.isSigned) + asmgen.out(""" + ldy #$offset + lda ($zpPtrVar),y + eor cx16.r14 + sta ($zpPtrVar),y + iny + lda ($zpPtrVar),y + eor cx16.r14+1 + sta ($zpPtrVar),y + iny + lda ($zpPtrVar),y + eor cx16.r14+2 + sta ($zpPtrVar),y + iny + lda ($zpPtrVar),y + eor cx16.r14+3 + sta ($zpPtrVar),y""") + } + SourceStorageKind.REGISTER -> TODO("inplace long ^= register ${target.position}") + else -> throw AssemblyError("weird source value $value") + } + } + + internal fun assignIndexedPointer(target: AsmAssignTarget, arrayVarName: String, index: PtExpression, arrayDt: DataType) { TODO("assign indexed pointer from array $arrayVarName at ${target.position}") // val ptrZp = AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, DataType.UWORD, target.scope, target.position, variableAsmName="P8ZP_SCRATCH_PTR") // assignAddressOfIndexedPointer(ptrZp, arrayVarName, arrayDt, index) diff --git a/examples/test.p8 b/examples/test.p8 index ca37babb5..7ceadd977 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -2,28 +2,31 @@ %zeropage basicsafe main { - struct Node { - ^^Node next + struct element { + ubyte type + long l } sub start() { - ^^Node node = 6000 - long @shared lvar = 999999 - ^^long @shared lptr = 5000 - ^^bool bptr - ^^ubyte ubptr - pokel(5000, 11223344) + ^^element ptr = 5000 + ptr^^.l = 123456789 + txt.print_l(ptr^^.l) + txt.nl() - lptr^^ = 0 - lptr^^ = lvar - lptr^^ = 82348234+lvar - txt.print_l( lptr^^) - lvar = lptr^^+1111111 + long @shared l1 = 1111110 + long @shared l2 = 2222220 + long @shared l3 = 3333330 - ^^Node next = 8888 - node.next = next + ptr.l &= l1+1 + txt.print_l(ptr^^.l) + txt.nl() - bptr^^=false - ubptr^^=0 + ptr.l |= l2+2 + txt.print_l(ptr^^.l) + txt.nl() + + ptr.l ^= l3+3 + txt.print_l(ptr^^.l) + txt.nl() } }