refactored and optimized load/store byte from pointervar

This commit is contained in:
Irmen de Jong 2020-08-25 00:18:33 +02:00
parent 4bb4eab3b2
commit 144199730f
5 changed files with 176 additions and 141 deletions

View File

@ -12,6 +12,7 @@ import prog8.compiler.target.IAssemblyGenerator
import prog8.compiler.target.IAssemblyProgram import prog8.compiler.target.IAssemblyProgram
import prog8.compiler.target.c64.AssemblyProgram import prog8.compiler.target.c64.AssemblyProgram
import prog8.compiler.target.c64.C64MachineDefinition import prog8.compiler.target.c64.C64MachineDefinition
import prog8.compiler.target.c64.C64MachineDefinition.C64Zeropage
import prog8.compiler.target.c64.C64MachineDefinition.ESTACK_HI_HEX import prog8.compiler.target.c64.C64MachineDefinition.ESTACK_HI_HEX
import prog8.compiler.target.c64.C64MachineDefinition.ESTACK_LO_HEX import prog8.compiler.target.c64.C64MachineDefinition.ESTACK_LO_HEX
import prog8.compiler.target.c64.Petscii import prog8.compiler.target.c64.Petscii
@ -516,17 +517,47 @@ internal class AsmGen(private val program: Program,
return fixNameSymbols(name) return fixNameSymbols(name)
} }
internal fun loadByteFromPointerIntoA(pointername: String) { internal fun loadByteFromPointerIntoA2(pointervar: IdentifierReference): Pair<Boolean, String> {
// TODO if pointer is already in the zeropage, we can omit the copy // returns if the pointer is already on the ZP itself or not (in which case SCRATCH_W1 is used as intermediary)
out(""" val sourceName = asmIdentifierName(pointervar)
lda $pointername val vardecl = pointervar.targetVarDecl(program.namespace)!!
ldy $pointername+1 val scopedName = vardecl.makeScopedName(vardecl.name)
sta ${C64MachineDefinition.C64Zeropage.SCRATCH_W1} if(scopedName in allocatedZeropageVariables) {
sty ${C64MachineDefinition.C64Zeropage.SCRATCH_W1 + 1} // pointervar is already in the zero page, no need to copy
ldy #0 out(" ldy #0 | lda ($sourceName),y")
lda (${C64MachineDefinition.C64Zeropage.SCRATCH_W1}),y""") return Pair(true, sourceName)
} else {
out("""
lda $sourceName
ldy $sourceName+1
sta ${C64Zeropage.SCRATCH_W1}
sty ${C64Zeropage.SCRATCH_W1 + 1}
ldy #0
lda (${C64Zeropage.SCRATCH_W1}),y""")
return Pair(false, sourceName)
}
} }
fun storeByteIntoPointer(pointervar: IdentifierReference, ldaInstructionArg: String?) {
val sourceName = asmIdentifierName(pointervar)
val vardecl = pointervar.targetVarDecl(program.namespace)!!
val scopedName = vardecl.makeScopedName(vardecl.name)
if(scopedName in allocatedZeropageVariables) {
// pointervar is already in the zero page, no need to copy
if(ldaInstructionArg!=null)
out(" lda $ldaInstructionArg")
out(" ldy #0 | sta ($sourceName),y")
} else {
out("""
ldy $sourceName
sty ${C64Zeropage.SCRATCH_W2}
ldy $sourceName+1
sty ${C64Zeropage.SCRATCH_W2 + 1}
${if(ldaInstructionArg==null) "" else "lda $ldaInstructionArg"}
ldy #0
sta (${C64Zeropage.SCRATCH_W2}),y""")
}
}
internal fun fixNameSymbols(name: String) = name.replace("<", "prog8_").replace(">", "") // take care of the autogenerated invalid (anon) label names internal fun fixNameSymbols(name: String) = name.replace("<", "prog8_").replace(">", "") // take care of the autogenerated invalid (anon) label names

View File

@ -4,7 +4,6 @@ import prog8.ast.Program
import prog8.ast.base.* import prog8.ast.base.*
import prog8.ast.expressions.* import prog8.ast.expressions.*
import prog8.compiler.AssemblyError import prog8.compiler.AssemblyError
import prog8.compiler.target.c64.C64MachineDefinition
import prog8.compiler.target.c64.C64MachineDefinition.C64Zeropage import prog8.compiler.target.c64.C64MachineDefinition.C64Zeropage
import prog8.compiler.target.c64.C64MachineDefinition.ESTACK_HI_HEX import prog8.compiler.target.c64.C64MachineDefinition.ESTACK_HI_HEX
import prog8.compiler.target.c64.C64MachineDefinition.ESTACK_HI_PLUS1_HEX import prog8.compiler.target.c64.C64MachineDefinition.ESTACK_HI_PLUS1_HEX
@ -146,8 +145,7 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge
} }
is IdentifierReference -> { is IdentifierReference -> {
// the identifier is a pointer variable, so read the value from the address in it // the identifier is a pointer variable, so read the value from the address in it
val sourceName = asmgen.asmIdentifierName(expr.addressExpression as IdentifierReference) asmgen.loadByteFromPointerIntoA2(expr.addressExpression as IdentifierReference)
asmgen.loadByteFromPointerIntoA(sourceName)
asmgen.out(" sta $ESTACK_LO_HEX,x | dex") asmgen.out(" sta $ESTACK_LO_HEX,x | dex")
} }
else -> { else -> {
@ -226,8 +224,8 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge
if (amount <= 2) if (amount <= 2)
repeat(amount) { asmgen.out(" lda $ESTACK_LO_PLUS1_HEX,x | asl a | ror $ESTACK_LO_PLUS1_HEX,x") } repeat(amount) { asmgen.out(" lda $ESTACK_LO_PLUS1_HEX,x | asl a | ror $ESTACK_LO_PLUS1_HEX,x") }
else { else {
asmgen.out(" lda $ESTACK_LO_PLUS1_HEX,x | sta ${C64MachineDefinition.C64Zeropage.SCRATCH_B1}") asmgen.out(" lda $ESTACK_LO_PLUS1_HEX,x | sta ${C64Zeropage.SCRATCH_B1}")
repeat(amount) { asmgen.out(" asl a | ror ${C64MachineDefinition.C64Zeropage.SCRATCH_B1} | lda ${C64MachineDefinition.C64Zeropage.SCRATCH_B1}") } repeat(amount) { asmgen.out(" asl a | ror ${C64Zeropage.SCRATCH_B1} | lda ${C64Zeropage.SCRATCH_B1}") }
asmgen.out(" sta $ESTACK_LO_PLUS1_HEX,x") asmgen.out(" sta $ESTACK_LO_PLUS1_HEX,x")
} }
} }

View File

@ -10,7 +10,6 @@ import prog8.compiler.target.c64.C64MachineDefinition.ESTACK_HI_HEX
import prog8.compiler.target.c64.C64MachineDefinition.ESTACK_LO_HEX import prog8.compiler.target.c64.C64MachineDefinition.ESTACK_LO_HEX
import prog8.compiler.target.c64.codegen.AsmGen import prog8.compiler.target.c64.codegen.AsmGen
import prog8.compiler.toHex import prog8.compiler.toHex
import prog8.functions.BuiltinFunctions
internal class AssignmentAsmGen(private val program: Program, private val asmgen: AsmGen) { internal class AssignmentAsmGen(private val program: Program, private val asmgen: AsmGen) {
@ -801,20 +800,20 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
TargetStorageKind.STACK -> TODO() TargetStorageKind.STACK -> TODO()
} }
} else if (identifier != null) { } else if (identifier != null) {
val sourceName = asmgen.asmIdentifierName(identifier)
when(target.kind) { when(target.kind) {
TargetStorageKind.VARIABLE -> { TargetStorageKind.VARIABLE -> {
asmgen.loadByteFromPointerIntoA(sourceName) asmgen.loadByteFromPointerIntoA2(identifier)
asmgen.out(" sta ${target.asmVarname}") asmgen.out(" sta ${target.asmVarname}")
} }
TargetStorageKind.MEMORY -> { TargetStorageKind.MEMORY -> {
val sourceName = asmgen.asmIdentifierName(identifier)
storeByteViaRegisterAInMemoryAddress(sourceName, target.memory!!) storeByteViaRegisterAInMemoryAddress(sourceName, target.memory!!)
} }
TargetStorageKind.ARRAY -> { TargetStorageKind.ARRAY -> {
throw AssemblyError("no asm gen for assign memory byte $sourceName to array ${target.asmVarname} ") throw AssemblyError("no asm gen for assign memory byte $identifier to array ${target.asmVarname} ")
} }
TargetStorageKind.REGISTER -> { TargetStorageKind.REGISTER -> {
asmgen.loadByteFromPointerIntoA(sourceName) asmgen.loadByteFromPointerIntoA2(identifier)
when(target.register!!) { when(target.register!!) {
RegisterOrPair.A -> {} RegisterOrPair.A -> {}
RegisterOrPair.X -> asmgen.out(" tax") RegisterOrPair.X -> asmgen.out(" tax")
@ -835,15 +834,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
asmgen.out(" lda $ldaInstructionArg | sta ${addressLv.number.toHex()}") asmgen.out(" lda $ldaInstructionArg | sta ${addressLv.number.toHex()}")
} }
addressExpr is IdentifierReference -> { addressExpr is IdentifierReference -> {
val pointerVarName = asmgen.asmIdentifierName(addressExpr) asmgen.storeByteIntoPointer(addressExpr, ldaInstructionArg)
asmgen.out("""
lda $pointerVarName
sta ${C64Zeropage.SCRATCH_W2}
lda $pointerVarName+1
sta ${C64Zeropage.SCRATCH_W2+1}
lda $ldaInstructionArg
ldy #0
sta (${C64Zeropage.SCRATCH_W2}),y""")
} }
else -> { else -> {
asmgen.translateExpression(addressExpr) asmgen.translateExpression(addressExpr)
@ -870,19 +861,12 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
asmgen.out(" st$registerName ${addressLv.number.toHex()}") asmgen.out(" st$registerName ${addressLv.number.toHex()}")
} }
addressExpr is IdentifierReference -> { addressExpr is IdentifierReference -> {
val targetName = asmgen.asmIdentifierName(addressExpr)
when (register) { when (register) {
CpuRegister.A -> {} CpuRegister.A -> {}
CpuRegister.X -> asmgen.out(" txa") CpuRegister.X -> asmgen.out(" txa")
CpuRegister.Y -> asmgen.out(" tya") CpuRegister.Y -> asmgen.out(" tya")
} }
asmgen.out(""" asmgen.storeByteIntoPointer(addressExpr, null)
ldy $targetName
sty ${C64Zeropage.SCRATCH_W1}
ldy $targetName+1
sty ${C64Zeropage.SCRATCH_W1+1}
ldy #0
sta (${C64Zeropage.SCRATCH_W1}),y""")
} }
else -> { else -> {
asmgen.saveRegister(register) asmgen.saveRegister(register)

View File

@ -178,16 +178,16 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
} }
} }
is IdentifierReference -> { is IdentifierReference -> {
val name = asmgen.asmIdentifierName(memory.addressExpression as IdentifierReference) val pointer = memory.addressExpression as IdentifierReference
when { when {
valueLv != null -> inplaceModification_byte_litval_to_memory(name, operator, valueLv.toInt()) valueLv != null -> inplaceModification_byte_litval_to_memory(pointer, operator, valueLv.toInt())
ident != null -> inplaceModification_byte_variable_to_memory(name, operator, ident) ident != null -> inplaceModification_byte_variable_to_memory(pointer, operator, ident)
// TODO more specialized code for types such as memory read etc. // TODO more specialized code for types such as memory read etc.
value is TypecastExpression -> { value is TypecastExpression -> {
if (tryRemoveRedundantCast(value, target, operator)) return if (tryRemoveRedundantCast(value, target, operator)) return
inplaceModification_byte_value_to_memory(name, operator, value) inplaceModification_byte_value_to_memory(pointer, operator, value)
} }
else -> inplaceModification_byte_value_to_memory(name, operator, value) else -> inplaceModification_byte_value_to_memory(pointer, operator, value)
} }
} }
else -> { else -> {
@ -362,18 +362,26 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
} }
} }
private fun inplaceModification_byte_value_to_memory(pointername: String, operator: String, value: Expression) { private fun inplaceModification_byte_value_to_memory(pointervar: IdentifierReference, operator: String, value: Expression) {
println("warning: slow stack evaluation used (3): @($pointername) $operator= ${value::class.simpleName} at ${value.position}") // TODO println("warning: slow stack evaluation used (3): @(${pointervar.nameInSource.last()}) $operator= ${value::class.simpleName} at ${value.position}") // TODO
asmgen.translateExpression(value) asmgen.translateExpression(value)
when (operator) { when (operator) {
// note: ** (power) operator requires floats. // note: ** (power) operator requires floats.
"+" -> { "+" -> {
asmgen.loadByteFromPointerIntoA(pointername) val (ptrOnZp, sourceName) = asmgen.loadByteFromPointerIntoA2(pointervar)
asmgen.out(" clc | adc $ESTACK_LO_PLUS1_HEX,x | sta (${C64Zeropage.SCRATCH_W1}),y") asmgen.out(" clc | adc $ESTACK_LO_PLUS1_HEX,x")
if(ptrOnZp)
asmgen.out(" sta ($sourceName),y")
else
asmgen.out(" sta (${C64Zeropage.SCRATCH_W1}),y")
} }
"-" -> { "-" -> {
asmgen.loadByteFromPointerIntoA(pointername) val (ptrOnZp, sourceName) = asmgen.loadByteFromPointerIntoA2(pointervar)
asmgen.out(" sec | sbc $ESTACK_LO_PLUS1_HEX,x | sta (${C64Zeropage.SCRATCH_W1}),y") asmgen.out(" sec | sbc $ESTACK_LO_PLUS1_HEX,x")
if(ptrOnZp)
asmgen.out(" sta ($sourceName),y")
else
asmgen.out(" sta (${C64Zeropage.SCRATCH_W1}),y")
} }
"*" -> TODO("mul")// asmgen.out(" jsr prog8_lib.mul_byte") // the optimized routines should have been checked earlier "*" -> TODO("mul")// asmgen.out(" jsr prog8_lib.mul_byte") // the optimized routines should have been checked earlier
"/" -> TODO("div")// asmgen.out(if(types==DataType.UBYTE) " jsr prog8_lib.idiv_ub" else " jsr prog8_lib.idiv_b") "/" -> TODO("div")// asmgen.out(if(types==DataType.UBYTE) " jsr prog8_lib.idiv_ub" else " jsr prog8_lib.idiv_b")
@ -386,33 +394,53 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
"<<" -> TODO("ubyte asl") "<<" -> TODO("ubyte asl")
">>" -> TODO("ubyte lsr") ">>" -> TODO("ubyte lsr")
"&" -> { "&" -> {
asmgen.loadByteFromPointerIntoA(pointername) val (ptrOnZp, sourceName) = asmgen.loadByteFromPointerIntoA2(pointervar)
asmgen.out(" and $ESTACK_LO_PLUS1_HEX,x | sta (${C64Zeropage.SCRATCH_W1}),y") asmgen.out(" and $ESTACK_LO_PLUS1_HEX,x")
if(ptrOnZp)
asmgen.out(" sta ($sourceName),y")
else
asmgen.out(" sta (${C64Zeropage.SCRATCH_W1}),y")
} }
"^" -> { "^" -> {
asmgen.loadByteFromPointerIntoA(pointername) val (ptrOnZp, sourceName) = asmgen.loadByteFromPointerIntoA2(pointervar)
asmgen.out(" xor $ESTACK_LO_PLUS1_HEX,x | sta (${C64Zeropage.SCRATCH_W1}),y") asmgen.out(" xor $ESTACK_LO_PLUS1_HEX,x")
if(ptrOnZp)
asmgen.out(" sta ($sourceName),y")
else
asmgen.out(" sta (${C64Zeropage.SCRATCH_W1}),y")
} }
"|" -> { "|" -> {
asmgen.loadByteFromPointerIntoA(pointername) val (ptrOnZp, sourceName) = asmgen.loadByteFromPointerIntoA2(pointervar)
asmgen.out(" ora $ESTACK_LO_PLUS1_HEX,x | sta (${C64Zeropage.SCRATCH_W1}),y") asmgen.out(" ora $ESTACK_LO_PLUS1_HEX,x")
if(ptrOnZp)
asmgen.out(" sta ($sourceName),y")
else
asmgen.out(" sta (${C64Zeropage.SCRATCH_W1}),y")
} }
else -> throw AssemblyError("invalid operator for in-place modification $operator") else -> throw AssemblyError("invalid operator for in-place modification $operator")
} }
asmgen.out(" inx") asmgen.out(" inx")
} }
private fun inplaceModification_byte_variable_to_memory(pointername: String, operator: String, ident: IdentifierReference) { private fun inplaceModification_byte_variable_to_memory(pointervar: IdentifierReference, operator: String, value: IdentifierReference) {
val otherName = asmgen.asmIdentifierName(ident) val otherName = asmgen.asmIdentifierName(value)
when (operator) { when (operator) {
// note: ** (power) operator requires floats. // note: ** (power) operator requires floats.
"+" -> { "+" -> {
asmgen.loadByteFromPointerIntoA(pointername) val (ptrOnZp, sourceName) = asmgen.loadByteFromPointerIntoA2(pointervar)
asmgen.out(" clc | adc $otherName | sta (${C64Zeropage.SCRATCH_W1}),y") asmgen.out(" clc | adc $otherName")
if(ptrOnZp)
asmgen.out(" sta ($sourceName),y")
else
asmgen.out(" sta (${C64Zeropage.SCRATCH_W1}),y")
} }
"-" -> { "-" -> {
asmgen.loadByteFromPointerIntoA(pointername) val (ptrOnZp, sourceName) = asmgen.loadByteFromPointerIntoA2(pointervar)
asmgen.out(" sec | sbc $otherName | sta (${C64Zeropage.SCRATCH_W1}),y") asmgen.out(" sec | sbc $otherName")
if(ptrOnZp)
asmgen.out(" sta ($sourceName),y")
else
asmgen.out(" sta (${C64Zeropage.SCRATCH_W1}),y")
} }
"*" -> TODO("mul")// asmgen.out(" jsr prog8_lib.mul_byte") // the optimized routines should have been checked earlier "*" -> TODO("mul")// asmgen.out(" jsr prog8_lib.mul_byte") // the optimized routines should have been checked earlier
"/" -> TODO("div")// asmgen.out(if(types==DataType.UBYTE) " jsr prog8_lib.idiv_ub" else " jsr prog8_lib.idiv_b") "/" -> TODO("div")// asmgen.out(if(types==DataType.UBYTE) " jsr prog8_lib.idiv_ub" else " jsr prog8_lib.idiv_b")
@ -425,31 +453,51 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
"<<" -> TODO("ubyte asl") "<<" -> TODO("ubyte asl")
">>" -> TODO("ubyte lsr") ">>" -> TODO("ubyte lsr")
"&" -> { "&" -> {
asmgen.loadByteFromPointerIntoA(pointername) val (ptrOnZp, sourceName) = asmgen.loadByteFromPointerIntoA2(pointervar)
asmgen.out(" and $otherName | sta (${C64Zeropage.SCRATCH_W1}),y") asmgen.out(" and $otherName")
if(ptrOnZp)
asmgen.out(" sta ($sourceName),y")
else
asmgen.out(" sta (${C64Zeropage.SCRATCH_W1}),y")
} }
"^" -> { "^" -> {
asmgen.loadByteFromPointerIntoA(pointername) val (ptrOnZp, sourceName) = asmgen.loadByteFromPointerIntoA2(pointervar)
asmgen.out(" xor $otherName | sta (${C64Zeropage.SCRATCH_W1}),y") asmgen.out(" xor $otherName")
if(ptrOnZp)
asmgen.out(" sta ($sourceName),y")
else
asmgen.out(" sta (${C64Zeropage.SCRATCH_W1}),y")
} }
"|" -> { "|" -> {
asmgen.loadByteFromPointerIntoA(pointername) val (ptrOnZp, sourceName) = asmgen.loadByteFromPointerIntoA2(pointervar)
asmgen.out(" ora $otherName | sta (${C64Zeropage.SCRATCH_W1}),y") asmgen.out(" ora $otherName")
if(ptrOnZp)
asmgen.out(" sta ($sourceName),y")
else
asmgen.out(" sta (${C64Zeropage.SCRATCH_W1}),y")
} }
else -> throw AssemblyError("invalid operator for in-place modification $operator") else -> throw AssemblyError("invalid operator for in-place modification $operator")
} }
} }
private fun inplaceModification_byte_litval_to_memory(pointername: String, operator: String, value: Int) { private fun inplaceModification_byte_litval_to_memory(pointervar: IdentifierReference, operator: String, value: Int) {
when (operator) { when (operator) {
// note: ** (power) operator requires floats. // note: ** (power) operator requires floats.
"+" -> { "+" -> {
asmgen.loadByteFromPointerIntoA(pointername) val (ptrOnZp, sourceName) = asmgen.loadByteFromPointerIntoA2(pointervar)
asmgen.out(" clc | adc #$value | sta (${C64Zeropage.SCRATCH_W1}),y") asmgen.out(" clc | adc #$value")
if(ptrOnZp)
asmgen.out(" sta ($sourceName),y")
else
asmgen.out(" sta (${C64Zeropage.SCRATCH_W1}),y")
} }
"-" -> { "-" -> {
asmgen.loadByteFromPointerIntoA(pointername) val (ptrOnZp, sourceName) = asmgen.loadByteFromPointerIntoA2(pointervar)
asmgen.out(" sec | sbc #$value | sta (${C64Zeropage.SCRATCH_W1}),y") asmgen.out(" sec | sbc #$value")
if(ptrOnZp)
asmgen.out(" sta ($sourceName),y")
else
asmgen.out(" sta (${C64Zeropage.SCRATCH_W1}),y")
} }
"*" -> TODO("mul")// asmgen.out(" jsr prog8_lib.mul_byte") // the optimized routines should have been checked earlier "*" -> TODO("mul")// asmgen.out(" jsr prog8_lib.mul_byte") // the optimized routines should have been checked earlier
"/" -> { "/" -> {
@ -468,29 +516,47 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
} }
"<<" -> { "<<" -> {
if (value > 0) { if (value > 0) {
asmgen.loadByteFromPointerIntoA(pointername) val (ptrOnZp, sourceName) = asmgen.loadByteFromPointerIntoA2(pointervar)
repeat(value) { asmgen.out(" asl a") } repeat(value) { asmgen.out(" asl a") }
asmgen.out(" sta (${C64Zeropage.SCRATCH_W1}),y") if(ptrOnZp)
asmgen.out(" sta ($sourceName),y")
else
asmgen.out(" sta (${C64Zeropage.SCRATCH_W1}),y")
} }
} }
">>" -> { ">>" -> {
if (value > 0) { if (value > 0) {
asmgen.loadByteFromPointerIntoA(pointername) val (ptrOnZp, sourceName) = asmgen.loadByteFromPointerIntoA2(pointervar)
repeat(value) { asmgen.out(" lsr a") } repeat(value) { asmgen.out(" lsr a") }
asmgen.out(" sta (${C64Zeropage.SCRATCH_W1}),y") if(ptrOnZp)
asmgen.out(" sta ($sourceName),y")
else
asmgen.out(" sta (${C64Zeropage.SCRATCH_W1}),y")
} }
} }
"&" -> { "&" -> {
asmgen.loadByteFromPointerIntoA(pointername) val (ptrOnZp, sourceName) = asmgen.loadByteFromPointerIntoA2(pointervar)
asmgen.out(" and #$value | sta (${C64Zeropage.SCRATCH_W1}),y") asmgen.out(" and #$value")
if(ptrOnZp)
asmgen.out(" sta ($sourceName),y")
else
asmgen.out(" sta (${C64Zeropage.SCRATCH_W1}),y")
} }
"^" -> { "^" -> {
asmgen.loadByteFromPointerIntoA(pointername) val (ptrOnZp, sourceName) = asmgen.loadByteFromPointerIntoA2(pointervar)
asmgen.out(" xor #$value | sta (${C64Zeropage.SCRATCH_W1}),y") asmgen.out(" xor #$value")
if(ptrOnZp)
asmgen.out(" sta ($sourceName),y")
else
asmgen.out(" sta (${C64Zeropage.SCRATCH_W1}),y")
} }
"|" -> { "|" -> {
asmgen.loadByteFromPointerIntoA(pointername) val (ptrOnZp, sourceName) = asmgen.loadByteFromPointerIntoA2(pointervar)
asmgen.out(" ora #$value | sta (${C64Zeropage.SCRATCH_W1}),y") asmgen.out(" ora #$value")
if(ptrOnZp)
asmgen.out(" sta ($sourceName),y")
else
asmgen.out(" sta (${C64Zeropage.SCRATCH_W1}),y")
} }
else -> throw AssemblyError("invalid operator for in-place modification $operator") else -> throw AssemblyError("invalid operator for in-place modification $operator")
} }
@ -1047,13 +1113,15 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
sta $addr""") sta $addr""")
} }
is IdentifierReference -> { is IdentifierReference -> {
val name = asmgen.asmIdentifierName(mem.addressExpression as IdentifierReference) val (ptrOnZp, sourceName) = asmgen.loadByteFromPointerIntoA2(mem.addressExpression as IdentifierReference)
asmgen.loadByteFromPointerIntoA(name)
asmgen.out(""" asmgen.out("""
beq + beq +
lda #1 lda #1
+ eor #1 + eor #1""")
sta (${C64Zeropage.SCRATCH_W1}),y""") if(ptrOnZp)
asmgen.out(" sta ($sourceName),y")
else
asmgen.out(" sta (${C64Zeropage.SCRATCH_W1}),y")
} }
else -> { else -> {
println("warning: slow stack evaluation used (6): ${mem.addressExpression::class.simpleName} at ${mem.addressExpression.position}") // TODO println("warning: slow stack evaluation used (6): ${mem.addressExpression::class.simpleName} at ${mem.addressExpression.position}") // TODO
@ -1119,11 +1187,12 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
sta $addr""") sta $addr""")
} }
is IdentifierReference -> { is IdentifierReference -> {
val name = asmgen.asmIdentifierName(memory.addressExpression as IdentifierReference) val (ptrOnZp, sourceName) = asmgen.loadByteFromPointerIntoA2(memory.addressExpression as IdentifierReference)
asmgen.loadByteFromPointerIntoA(name) asmgen.out(" eor #255")
asmgen.out(""" if(ptrOnZp)
eor #255 asmgen.out(" sta ($sourceName),y")
sta (${C64Zeropage.SCRATCH_W1}),y""") else
asmgen.out(" sta (${C64Zeropage.SCRATCH_W1}),y")
} }
else -> { else -> {
println("warning: slow stack evaluation used (7): ${memory.addressExpression::class.simpleName} at ${memory.addressExpression.position}") // TODO println("warning: slow stack evaluation used (7): ${memory.addressExpression::class.simpleName} at ${memory.addressExpression.position}") // TODO

View File

@ -1,60 +1,13 @@
%import c64utils %import c64utils
%zeropage basicsafe
main { main {
const uword rom = $e000
sub sumrom() -> uword {
uword p = rom
uword s = 0
ubyte i
repeat $20 {
repeat $100 {
s += @(p)
p++
}
}
return s
}
sub start() { sub start() {
benchcommon.begin() ubyte bb = 1
ubyte i uword addr=$d020
for i in 0 to 5 { @(addr) = bb
c64scr.print_uw(sumrom()) bb = @(addr)
c64.CHROUT('\n')
}
benchcommon.end()
}
}
benchcommon {
uword last_time = 0
uword time_start = 0
asmsub read_time () clobbers(A,X,Y) {
%asm {{
jsr $FFDE
sta last_time
stx last_time+1
rts
}}
}
sub begin() {
benchcommon.read_time()
benchcommon.time_start = benchcommon.last_time
}
sub end() {
benchcommon.read_time()
c64scr.print_uwhex(benchcommon.last_time-benchcommon.time_start, false)
c64.CHROUT('\n')
void c64scr.input_chars($c000)
} }
} }