mirror of
https://github.com/irmen/prog8.git
synced 2025-02-19 11:31:07 +00:00
improved codegen for some pointer+index expressions
This commit is contained in:
parent
9046fe8d3a
commit
d18f2a7bfd
@ -314,18 +314,100 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun assignByteFromAddressExpression(address: PtExpression, target: AsmAssignTarget) {
|
private fun assignByteFromAddressExpression(address: PtExpression, target: AsmAssignTarget) {
|
||||||
// TODO optimize this into more efficient code, using indexed register ,Y instead of explicitly calculating the full pointer value, or use self=modifying code and just use absolute addressing.
|
if(address is PtBinaryExpression) {
|
||||||
// see: https://discord.com/channels/547559626024157184/629863245934755860/1262873088782110750
|
if(address.operator=="+" && address.right.type==DataType.UWORD) {
|
||||||
|
if (address.left is PtIdentifier) {
|
||||||
|
// use (zp),Y instead of explicitly calculating the full zp pointer value
|
||||||
|
val pointer = (address.left as PtIdentifier).name
|
||||||
|
when(val index=address.right) {
|
||||||
|
is PtIdentifier -> {
|
||||||
|
val indexName = index.name
|
||||||
|
asmgen.out("""
|
||||||
|
lda $pointer
|
||||||
|
sta P8ZP_SCRATCH_W2
|
||||||
|
lda $pointer+1
|
||||||
|
clc
|
||||||
|
adc $indexName+1
|
||||||
|
sta P8ZP_SCRATCH_W2+1
|
||||||
|
ldy $indexName
|
||||||
|
lda (P8ZP_SCRATCH_W2),y""")
|
||||||
|
assignRegisterByte(target, CpuRegister.A, false, true)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
is PtNumber -> {
|
||||||
|
val indexValue = index.number.toString()
|
||||||
|
asmgen.out("""
|
||||||
|
lda $pointer
|
||||||
|
sta P8ZP_SCRATCH_W2
|
||||||
|
lda $pointer+1
|
||||||
|
clc
|
||||||
|
adc #>$indexValue
|
||||||
|
sta P8ZP_SCRATCH_W2+1
|
||||||
|
ldy #<$indexValue
|
||||||
|
lda (P8ZP_SCRATCH_W2),y""")
|
||||||
|
assignRegisterByte(target, CpuRegister.A, false, true)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// else if(address.operator=="-") {
|
||||||
|
// // does this ever occur? we could optimize it too, but it seems like a pathological case
|
||||||
|
// }
|
||||||
|
}
|
||||||
assignExpressionToVariable(address, "P8ZP_SCRATCH_W2", DataType.UWORD)
|
assignExpressionToVariable(address, "P8ZP_SCRATCH_W2", DataType.UWORD)
|
||||||
asmgen.loadAFromZpPointerVar("P8ZP_SCRATCH_W2", false)
|
asmgen.loadAFromZpPointerVar("P8ZP_SCRATCH_W2", false)
|
||||||
assignRegisterByte(target, CpuRegister.A, false, true)
|
assignRegisterByte(target, CpuRegister.A, false, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun storeByteInAToAddressExpression(addressExpr: PtExpression, saveA: Boolean) {
|
private fun storeByteInAToAddressExpression(address: PtExpression, saveA: Boolean) {
|
||||||
// TODO optimize this into more efficient code, using indexed register ,Y instead of explicitly calculating the full pointer value, or use self=modifying code and just use absolute addressing.
|
if(address is PtBinaryExpression) {
|
||||||
// see: https://discord.com/channels/547559626024157184/629863245934755860/1262873088782110750
|
if(address.operator=="+") {
|
||||||
|
if (address.left is PtIdentifier && address.right.type==DataType.UWORD) {
|
||||||
|
// use (zp),Y instead of explicitly calculating the full zp pointer value
|
||||||
|
val pointer = (address.left as PtIdentifier).name
|
||||||
|
when(val index=address.right) {
|
||||||
|
is PtIdentifier -> {
|
||||||
|
val indexName = index.name
|
||||||
|
asmgen.out("""
|
||||||
|
tax
|
||||||
|
lda $pointer
|
||||||
|
sta P8ZP_SCRATCH_W2
|
||||||
|
lda $pointer+1
|
||||||
|
clc
|
||||||
|
adc $indexName+1
|
||||||
|
sta P8ZP_SCRATCH_W2+1
|
||||||
|
ldy $indexName
|
||||||
|
txa
|
||||||
|
sta (P8ZP_SCRATCH_W2),y""")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
is PtNumber -> {
|
||||||
|
val indexValue = index.number.toString()
|
||||||
|
asmgen.out("""
|
||||||
|
tax
|
||||||
|
lda $pointer
|
||||||
|
sta P8ZP_SCRATCH_W2
|
||||||
|
lda $pointer+1
|
||||||
|
clc
|
||||||
|
adc #>$indexValue
|
||||||
|
sta P8ZP_SCRATCH_W2+1
|
||||||
|
ldy #<$indexValue
|
||||||
|
txa
|
||||||
|
sta (P8ZP_SCRATCH_W2),y""")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// else if(address.operator=="-") {
|
||||||
|
// // does this ever occur? we could optimize it too, but it seems like a pathological case
|
||||||
|
// }
|
||||||
|
}
|
||||||
if(saveA) asmgen.out(" pha")
|
if(saveA) asmgen.out(" pha")
|
||||||
assignExpressionToVariable(addressExpr, "P8ZP_SCRATCH_W2", DataType.UWORD)
|
assignExpressionToVariable(address, "P8ZP_SCRATCH_W2", DataType.UWORD)
|
||||||
if(saveA) asmgen.out(" pla")
|
if(saveA) asmgen.out(" pla")
|
||||||
asmgen.storeAIntoZpPointerVar("P8ZP_SCRATCH_W2", false)
|
asmgen.storeAIntoZpPointerVar("P8ZP_SCRATCH_W2", false)
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,10 @@ TODO
|
|||||||
|
|
||||||
See open issues on github.
|
See open issues on github.
|
||||||
|
|
||||||
Optimize code in assignByteFromAddressExpression() and storeByteInAToAddressExpression()
|
Generate proper index out of bounds error for array[-11] if the array is only size 10. (only array[-1]..array[-10] are valid)
|
||||||
|
|
||||||
|
Putting a signed variable as an array index should be a compiler error. (using it for a pointer indexing is fine - but weird).
|
||||||
|
Add some more explanation about this to the "array indexing" paragraph in the docs.
|
||||||
|
|
||||||
Re-generate the skeletons doc files.
|
Re-generate the skeletons doc files.
|
||||||
|
|
||||||
|
@ -8,10 +8,47 @@ main {
|
|||||||
uword @shared ptr = $2000
|
uword @shared ptr = $2000
|
||||||
uword @shared index = 1000
|
uword @shared index = 1000
|
||||||
|
|
||||||
|
@($2000+1000) = 123
|
||||||
|
@($2000+1001) = 124
|
||||||
|
|
||||||
cx16.r0L = @(ptr+index)
|
cx16.r0L = @(ptr+index)
|
||||||
cx16.r1L = ptr[index]
|
cx16.r1L = @(ptr+1001)
|
||||||
|
|
||||||
|
txt.print_ub(cx16.r0L)
|
||||||
|
txt.spc()
|
||||||
|
txt.print_ub(cx16.r1L)
|
||||||
|
txt.spc()
|
||||||
|
|
||||||
|
cx16.r2L = ptr[index]
|
||||||
|
cx16.r3L = ptr[1001]
|
||||||
|
|
||||||
|
txt.print_ub(cx16.r2L)
|
||||||
|
txt.spc()
|
||||||
|
txt.print_ub(cx16.r3L)
|
||||||
|
txt.spc()
|
||||||
|
|
||||||
|
cx16.r0L = 200
|
||||||
|
cx16.r1L = 201
|
||||||
|
|
||||||
@(ptr+index) = cx16.r0L
|
@(ptr+index) = cx16.r0L
|
||||||
ptr[index] = cx16.r1L
|
@(ptr+1001) = cx16.r1L
|
||||||
|
|
||||||
|
txt.print_ub(@($2000+1000))
|
||||||
|
txt.spc()
|
||||||
|
txt.print_ub(@($2000+1001))
|
||||||
|
txt.spc()
|
||||||
|
|
||||||
|
cx16.r0L = 203
|
||||||
|
cx16.r1L = 204
|
||||||
|
|
||||||
|
ptr[index] = cx16.r0L
|
||||||
|
ptr[1001] = cx16.r1L
|
||||||
|
|
||||||
|
txt.print_ub(@($2000+1000))
|
||||||
|
txt.spc()
|
||||||
|
txt.print_ub(@($2000+1001))
|
||||||
|
txt.spc()
|
||||||
|
|
||||||
; txt.print_ub(ptr[index])
|
; txt.print_ub(ptr[index])
|
||||||
; txt.nl()
|
; txt.nl()
|
||||||
; ptr[index] = 123
|
; ptr[index] = 123
|
||||||
|
Loading…
x
Reference in New Issue
Block a user