mirror of
https://github.com/irmen/prog8.git
synced 2024-12-27 05:29:38 +00:00
refactored and optimized load/store byte from pointervar
This commit is contained in:
parent
4bb4eab3b2
commit
144199730f
@ -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
|
||||||
|
|
||||||
|
@ -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")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user