mirror of
https://github.com/irmen/prog8.git
synced 2025-11-05 17:21:42 +00:00
implement inplace bitwise operations on long struct fields
This commit is contained in:
@@ -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
|
// 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)
|
if(target.dt.isByteOrBool) inplaceByteAnd(target, value)
|
||||||
else if(target.dt.isWord) inplaceWordAnd(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}")
|
else throw AssemblyError("weird dt ${target.dt} ${target.position}")
|
||||||
}
|
}
|
||||||
"|", "or" -> {
|
"|", "or" -> {
|
||||||
// byte targets are handled as direct memory access, not a pointer operation anymore however boolean targets are still to be handled here
|
// 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)
|
if(target.dt.isByteOrBool) inplaceByteOr(target, value)
|
||||||
else if(target.dt.isWord) inplaceWordOr(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}")
|
else throw AssemblyError("weird dt ${target.dt} ${target.position}")
|
||||||
}
|
}
|
||||||
"^", "xor" -> {
|
"^", "xor" -> {
|
||||||
// byte targets are handled as direct memory access, not a pointer operation anymore however boolean targets are still to be handled here
|
// 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)
|
if(target.dt.isByteOrBool) inplaceByteXor(target, value)
|
||||||
else if(target.dt.isWord) inplaceWordXor(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("weird dt ${target.dt} ${target.position}")
|
||||||
}
|
}
|
||||||
else -> throw AssemblyError("invalid operator for in-place modification $operator")
|
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}")
|
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")
|
// val ptrZp = AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, DataType.UWORD, target.scope, target.position, variableAsmName="P8ZP_SCRATCH_PTR")
|
||||||
// assignAddressOfIndexedPointer(ptrZp, arrayVarName, arrayDt, index)
|
// assignAddressOfIndexedPointer(ptrZp, arrayVarName, arrayDt, index)
|
||||||
|
|||||||
@@ -2,28 +2,31 @@
|
|||||||
%zeropage basicsafe
|
%zeropage basicsafe
|
||||||
|
|
||||||
main {
|
main {
|
||||||
struct Node {
|
struct element {
|
||||||
^^Node next
|
ubyte type
|
||||||
|
long l
|
||||||
}
|
}
|
||||||
|
|
||||||
sub start() {
|
sub start() {
|
||||||
^^Node node = 6000
|
^^element ptr = 5000
|
||||||
long @shared lvar = 999999
|
ptr^^.l = 123456789
|
||||||
^^long @shared lptr = 5000
|
txt.print_l(ptr^^.l)
|
||||||
^^bool bptr
|
txt.nl()
|
||||||
^^ubyte ubptr
|
|
||||||
pokel(5000, 11223344)
|
|
||||||
|
|
||||||
lptr^^ = 0
|
long @shared l1 = 1111110
|
||||||
lptr^^ = lvar
|
long @shared l2 = 2222220
|
||||||
lptr^^ = 82348234+lvar
|
long @shared l3 = 3333330
|
||||||
txt.print_l( lptr^^)
|
|
||||||
lvar = lptr^^+1111111
|
|
||||||
|
|
||||||
^^Node next = 8888
|
ptr.l &= l1+1
|
||||||
node.next = next
|
txt.print_l(ptr^^.l)
|
||||||
|
txt.nl()
|
||||||
|
|
||||||
bptr^^=false
|
ptr.l |= l2+2
|
||||||
ubptr^^=0
|
txt.print_l(ptr^^.l)
|
||||||
|
txt.nl()
|
||||||
|
|
||||||
|
ptr.l ^= l3+3
|
||||||
|
txt.print_l(ptr^^.l)
|
||||||
|
txt.nl()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user