fix and optimize storing A into pointervar

This commit is contained in:
Irmen de Jong 2021-12-04 04:43:58 +01:00
parent b867d8f731
commit e545ea9504
6 changed files with 107 additions and 74 deletions

View File

@ -604,6 +604,45 @@ class AsmGen(private val program: Program,
} }
} }
internal fun storeAIntoPointerVar(pointervar: IdentifierReference) {
val sourceName = asmVariableName(pointervar)
val vardecl = pointervar.targetVarDecl(program)!!
val scopedName = vardecl.scopedName.joinToString(".")
if (isTargetCpu(CpuType.CPU65c02)) {
if (isZpVar(scopedName)) {
// pointervar is already in the zero page, no need to copy
out(" sta ($sourceName)")
} else {
out("""
ldy $sourceName
sty P8ZP_SCRATCH_W2
ldy $sourceName+1
sty P8ZP_SCRATCH_W2+1
sta (P8ZP_SCRATCH_W2)""")
}
} else {
if (isZpVar(scopedName)) {
// pointervar is already in the zero page, no need to copy
out(" ldy #0 | sta ($sourceName),y")
} else {
out("""
ldy $sourceName
sty P8ZP_SCRATCH_W2
ldy $sourceName+1
sty P8ZP_SCRATCH_W2+1
ldy #0
sta (P8ZP_SCRATCH_W2),y""")
}
}
}
internal fun storeAIntoZpPointerVar(zpPointerVar: String) {
if (isTargetCpu(CpuType.CPU65c02))
out(" sta ($zpPointerVar)")
else
out(" ldy #0 | sta ($zpPointerVar),y")
}
private fun fixNameSymbols(name: String): String { private fun fixNameSymbols(name: String): String {
val name2 = name.replace("<", "prog8_").replace(">", "") // take care of the autogenerated invalid (anon) label names val name2 = name.replace("<", "prog8_").replace(">", "") // take care of the autogenerated invalid (anon) label names
return name2.replace("prog8_lib.P8ZP_SCRATCH_", "P8ZP_SCRATCH_") // take care of the 'hooks' to the temp vars return name2.replace("prog8_lib.P8ZP_SCRATCH_", "P8ZP_SCRATCH_") // take care of the 'hooks' to the temp vars

View File

@ -2140,52 +2140,14 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
when(addressExpr) { when(addressExpr) {
is NumericLiteralValue, is IdentifierReference -> { is NumericLiteralValue, is IdentifierReference -> {
assignExpressionToVariable(addressExpr, "P8ZP_SCRATCH_W2", DataType.UWORD, null) assignExpressionToVariable(addressExpr, "P8ZP_SCRATCH_W2", DataType.UWORD, null)
if (asmgen.isTargetCpu(CpuType.CPU65c02)) asmgen.storeAIntoZpPointerVar("P8ZP_SCRATCH_W2")
asmgen.out(" sta (P8ZP_SCRATCH_W2)")
else
asmgen.out(" ldy #0 | sta (P8ZP_SCRATCH_W2),y")
} }
else -> { else -> {
// same as above but we need to save the A register // same as above but we need to save the A register
asmgen.out(" pha") asmgen.out(" pha")
assignExpressionToVariable(addressExpr, "P8ZP_SCRATCH_W2", DataType.UWORD, null) assignExpressionToVariable(addressExpr, "P8ZP_SCRATCH_W2", DataType.UWORD, null)
asmgen.out(" pla") asmgen.out(" pla")
if (asmgen.isTargetCpu(CpuType.CPU65c02)) asmgen.storeAIntoZpPointerVar("P8ZP_SCRATCH_W2")
asmgen.out(" sta (P8ZP_SCRATCH_W2)")
else
asmgen.out(" ldy #0 | sta (P8ZP_SCRATCH_W2),y")
}
}
}
fun storeAIntoPointerVar(pointervar: IdentifierReference) {
val sourceName = asmgen.asmVariableName(pointervar)
val vardecl = pointervar.targetVarDecl(program)!!
val scopedName = vardecl.scopedName.joinToString(".")
if (asmgen.isTargetCpu(CpuType.CPU65c02)) {
if (asmgen.isZpVar(scopedName)) {
// pointervar is already in the zero page, no need to copy
asmgen.out(" sta ($sourceName)")
} else {
asmgen.out("""
ldy $sourceName
sty P8ZP_SCRATCH_W2
ldy $sourceName+1
sty P8ZP_SCRATCH_W2+1
sta (P8ZP_SCRATCH_W2)""")
}
} else {
if (asmgen.isZpVar(scopedName)) {
// pointervar is already in the zero page, no need to copy
asmgen.out(" ldy #0 | sta ($sourceName),y")
} else {
asmgen.out("""
ldy $sourceName
sty P8ZP_SCRATCH_W2
ldy $sourceName+1
sty P8ZP_SCRATCH_W2+1
ldy #0
sta (P8ZP_SCRATCH_W2),y""")
} }
} }
} }
@ -2195,7 +2157,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
asmgen.out(" sta ${addressLv.number.toHex()}") asmgen.out(" sta ${addressLv.number.toHex()}")
} }
addressExpr is IdentifierReference -> { addressExpr is IdentifierReference -> {
storeAIntoPointerVar(addressExpr) asmgen.storeAIntoPointerVar(addressExpr)
} }
addressExpr is BinaryExpression -> { addressExpr is BinaryExpression -> {
if(!asmgen.tryOptimizedPointerAccessWithA(addressExpr, true)) if(!asmgen.tryOptimizedPointerAccessWithA(addressExpr, true))

View File

@ -372,9 +372,9 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
// note: ** (power) operator requires floats. // note: ** (power) operator requires floats.
"+" -> asmgen.out(" clc | adc P8ZP_SCRATCH_B1") "+" -> asmgen.out(" clc | adc P8ZP_SCRATCH_B1")
"-" -> asmgen.out(" sec | sbc P8ZP_SCRATCH_B1") "-" -> asmgen.out(" sec | sbc P8ZP_SCRATCH_B1")
"*" -> asmgen.out(" ldy P8ZP_SCRATCH_B1 | jsr math.multiply_bytes | ldy #0") "*" -> asmgen.out(" ldy P8ZP_SCRATCH_B1 | jsr math.multiply_bytes")
"/" -> asmgen.out(" ldy P8ZP_SCRATCH_B1 | jsr math.divmod_ub_asm | tya | ldy #0") "/" -> asmgen.out(" ldy P8ZP_SCRATCH_B1 | jsr math.divmod_ub_asm | tya")
"%" -> asmgen.out(" ldy P8ZP_SCRATCH_B1 | jsr math.divmod_ub_asm | ldy #0") "%" -> asmgen.out(" ldy P8ZP_SCRATCH_B1 | jsr math.divmod_ub_asm")
"<<" -> { "<<" -> {
asmgen.out(""" asmgen.out("""
ldy P8ZP_SCRATCH_B1 ldy P8ZP_SCRATCH_B1
@ -398,8 +398,9 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
"^", "xor" -> asmgen.out(" eor P8ZP_SCRATCH_B1") "^", "xor" -> asmgen.out(" eor P8ZP_SCRATCH_B1")
else -> throw AssemblyError("invalid operator for in-place modification $operator") else -> throw AssemblyError("invalid operator for in-place modification $operator")
} }
// TODO THIS IS WRONG:????
val sourceName = asmgen.loadByteFromPointerIntoA(pointervar) val sourceName = asmgen.loadByteFromPointerIntoA(pointervar)
asmgen.out(" sta ($sourceName),y") asmgen.storeAIntoZpPointerVar(sourceName)
} }
private fun inplaceModification_byte_variable_to_pointer(pointervar: IdentifierReference, operator: String, value: IdentifierReference) { private fun inplaceModification_byte_variable_to_pointer(pointervar: IdentifierReference, operator: String, value: IdentifierReference) {
@ -410,9 +411,9 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
// note: ** (power) operator requires floats. // note: ** (power) operator requires floats.
"+" -> asmgen.out(" clc | adc $otherName") "+" -> asmgen.out(" clc | adc $otherName")
"-" -> asmgen.out(" sec | sbc $otherName") "-" -> asmgen.out(" sec | sbc $otherName")
"*" -> asmgen.out(" ldy $otherName | jsr math.multiply_bytes | ldy #0") "*" -> asmgen.out(" ldy $otherName | jsr math.multiply_bytes")
"/" -> asmgen.out(" ldy $otherName | jsr math.divmod_ub_asm | tya | ldy #0") "/" -> asmgen.out(" ldy $otherName | jsr math.divmod_ub_asm | tya")
"%" -> asmgen.out(" ldy $otherName | jsr math.divmod_ub_asm | ldy #0") "%" -> asmgen.out(" ldy $otherName | jsr math.divmod_ub_asm")
"<<" -> { "<<" -> {
asmgen.out(""" asmgen.out("""
ldy $otherName ldy $otherName
@ -436,7 +437,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
"^", "xor" -> asmgen.out(" eor $otherName") "^", "xor" -> asmgen.out(" eor $otherName")
else -> throw AssemblyError("invalid operator for in-place modification $operator") else -> throw AssemblyError("invalid operator for in-place modification $operator")
} }
asmgen.out(" sta ($sourceName),y") asmgen.storeAIntoZpPointerVar(sourceName)
} }
private fun inplaceModification_byte_litval_to_pointer(pointervar: IdentifierReference, operator: String, value: Int) { private fun inplaceModification_byte_litval_to_pointer(pointervar: IdentifierReference, operator: String, value: Int) {
@ -445,63 +446,63 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
"+" -> { "+" -> {
val sourceName = asmgen.loadByteFromPointerIntoA(pointervar) val sourceName = asmgen.loadByteFromPointerIntoA(pointervar)
asmgen.out(" clc | adc #$value") asmgen.out(" clc | adc #$value")
asmgen.out(" sta ($sourceName),y") asmgen.storeAIntoZpPointerVar(sourceName)
} }
"-" -> { "-" -> {
val sourceName = asmgen.loadByteFromPointerIntoA(pointervar) val sourceName = asmgen.loadByteFromPointerIntoA(pointervar)
asmgen.out(" sec | sbc #$value") asmgen.out(" sec | sbc #$value")
asmgen.out(" sta ($sourceName),y") asmgen.storeAIntoZpPointerVar(sourceName)
} }
"*" -> { "*" -> {
val sourceName = asmgen.loadByteFromPointerIntoA(pointervar) val sourceName = asmgen.loadByteFromPointerIntoA(pointervar)
if(value in asmgen.optimizedByteMultiplications) if(value in asmgen.optimizedByteMultiplications)
asmgen.out(" jsr math.mul_byte_${value}") asmgen.out(" jsr math.mul_byte_${value}")
else else
asmgen.out(" ldy #$value | jsr math.multiply_bytes | ldy #0") asmgen.out(" ldy #$value | jsr math.multiply_bytes")
asmgen.out(" sta ($sourceName),y") asmgen.storeAIntoZpPointerVar(sourceName)
} }
"/" -> { "/" -> {
val sourceName = asmgen.loadByteFromPointerIntoA(pointervar) val sourceName = asmgen.loadByteFromPointerIntoA(pointervar)
if(value==0) if(value==0)
throw AssemblyError("division by zero") throw AssemblyError("division by zero")
asmgen.out(" ldy #$value | jsr math.divmod_ub_asm | tya | ldy #0") asmgen.out(" ldy #$value | jsr math.divmod_ub_asm | tya")
asmgen.out(" sta ($sourceName),y") asmgen.storeAIntoZpPointerVar(sourceName)
} }
"%" -> { "%" -> {
val sourceName = asmgen.loadByteFromPointerIntoA(pointervar) val sourceName = asmgen.loadByteFromPointerIntoA(pointervar)
if(value==0) if(value==0)
throw AssemblyError("division by zero") throw AssemblyError("division by zero")
asmgen.out(" ldy #$value | jsr math.divmod_ub_asm | ldy #0") asmgen.out(" ldy #$value | jsr math.divmod_ub_asm")
asmgen.out(" sta ($sourceName),y") asmgen.storeAIntoZpPointerVar(sourceName)
} }
"<<" -> { "<<" -> {
if (value > 0) { if (value > 0) {
val sourceName = asmgen.loadByteFromPointerIntoA(pointervar) val sourceName = asmgen.loadByteFromPointerIntoA(pointervar)
repeat(value) { asmgen.out(" asl a") } repeat(value) { asmgen.out(" asl a") }
asmgen.out(" sta ($sourceName),y") asmgen.storeAIntoZpPointerVar(sourceName)
} }
} }
">>" -> { ">>" -> {
if (value > 0) { if (value > 0) {
val sourceName = asmgen.loadByteFromPointerIntoA(pointervar) val sourceName = asmgen.loadByteFromPointerIntoA(pointervar)
repeat(value) { asmgen.out(" lsr a") } repeat(value) { asmgen.out(" lsr a") }
asmgen.out(" sta ($sourceName),y") asmgen.storeAIntoZpPointerVar(sourceName)
} }
} }
"&", "and" -> { "&", "and" -> {
val sourceName = asmgen.loadByteFromPointerIntoA(pointervar) val sourceName = asmgen.loadByteFromPointerIntoA(pointervar)
asmgen.out(" and #$value") asmgen.out(" and #$value")
asmgen.out(" sta ($sourceName),y") asmgen.storeAIntoZpPointerVar(sourceName)
} }
"|", "or" -> { "|", "or" -> {
val sourceName = asmgen.loadByteFromPointerIntoA(pointervar) val sourceName = asmgen.loadByteFromPointerIntoA(pointervar)
asmgen.out(" ora #$value") asmgen.out(" ora #$value")
asmgen.out(" sta ($sourceName),y") asmgen.storeAIntoZpPointerVar(sourceName)
} }
"^", "xor" -> { "^", "xor" -> {
val sourceName = asmgen.loadByteFromPointerIntoA(pointervar) val sourceName = asmgen.loadByteFromPointerIntoA(pointervar)
asmgen.out(" eor #$value") asmgen.out(" eor #$value")
asmgen.out(" sta ($sourceName),y") asmgen.storeAIntoZpPointerVar(sourceName)
} }
else -> throw AssemblyError("invalid operator for in-place modification $operator") else -> throw AssemblyError("invalid operator for in-place modification $operator")
} }
@ -1811,7 +1812,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
beq + beq +
lda #1 lda #1
+ eor #1""") + eor #1""")
asmgen.out(" sta ($sourceName),y") asmgen.storeAIntoZpPointerVar(sourceName)
} }
else -> { else -> {
asmgen.assignExpressionToVariable(mem.addressExpression, "P8ZP_SCRATCH_W2", DataType.UWORD, target.scope) asmgen.assignExpressionToVariable(mem.addressExpression, "P8ZP_SCRATCH_W2", DataType.UWORD, target.scope)
@ -1820,8 +1821,8 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
lda (P8ZP_SCRATCH_W2),y lda (P8ZP_SCRATCH_W2),y
beq + beq +
lda #1 lda #1
+ eor #1 + eor #1""")
sta (P8ZP_SCRATCH_W2),y""") asmgen.storeAIntoZpPointerVar("P8ZP_SCRATCH_W2")
} }
} }
} }
@ -1942,8 +1943,8 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
asmgen.out(""" asmgen.out("""
ldy #0 ldy #0
lda (P8ZP_SCRATCH_W2),y lda (P8ZP_SCRATCH_W2),y
eor #255 eor #255""")
sta (P8ZP_SCRATCH_W2),y""") asmgen.storeAIntoZpPointerVar("P8ZP_SCRATCH_W2")
} }
} }
} }

View File

@ -73,6 +73,7 @@ X = BinExpr X = LeftExpr
// ) // )
} }
// TODO breaks imageviewer EHB palette
if(binExpr.right.isSimple) { if(binExpr.right.isSimple) {
val firstAssign = Assignment(assignment.target.copy(), binExpr.left, binExpr.left.position) val firstAssign = Assignment(assignment.target.copy(), binExpr.left, binExpr.left.position)
val targetExpr = assignment.target.toExpression() val targetExpr = assignment.target.toExpression()

View File

@ -3,6 +3,10 @@ TODO
For next compiler release (7.5) For next compiler release (7.5)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
BUG: imageviewer.p8 iff loader: winterqueen.iff (EHB image) is not displayed correctly!
--> make_ehb_palette() is wrong with optimizations, ok without.
--> caused by splitBinaryExpressions()
... ...

View File

@ -3,15 +3,41 @@
main { main {
ubyte[64*3] palette
sub start() { sub start() {
uword scrpos = $0400 ubyte i
repeat 256 { for i in 0 to len(palette)-1 {
@(scrpos) = 81 palette[i] = 15
scrpos++
} }
txt.print_uw(scrpos) for i in 0 to len(palette)-1 {
txt.print_ubhex(palette[i], false)
}
txt.nl()
make_ehb_palette()
for i in 0 to len(palette)-1 {
txt.print_ubhex(palette[i], false)
}
txt.nl() txt.nl()
} }
sub make_ehb_palette() {
; generate 32 additional Extra-Halfbrite colors in the cmap
uword palletteptr = &palette
uword ehbptr = palletteptr + 32*3
repeat 32 {
@(ehbptr) = @(palletteptr)>>1
ehbptr++
palletteptr++
@(ehbptr) = @(palletteptr)>>1
ehbptr++
palletteptr++
@(ehbptr) = @(palletteptr)>>1
ehbptr++
palletteptr++
}
}
} }