This commit is contained in:
Irmen de Jong 2020-08-24 23:18:46 +02:00
parent cf9151f669
commit 4bb4eab3b2
5 changed files with 98 additions and 108 deletions

View File

@ -507,14 +507,6 @@ internal class AsmGen(private val program: Program,
}
}
internal fun signExtendAtoMsb(destination: String) =
"""
ora #$7f
bmi +
lda #0
+ sta $destination
"""
internal fun asmIdentifierName(identifier: IdentifierReference): String {
val name = if(identifier.memberOfStruct(program.namespace)!=null) {
identifier.targetVarDecl(program.namespace)!!.name
@ -524,6 +516,18 @@ internal class AsmGen(private val program: Program,
return fixNameSymbols(name)
}
internal fun loadByteFromPointerIntoA(pointername: String) {
// TODO if pointer is already in the zeropage, we can omit the copy
out("""
lda $pointername
ldy $pointername+1
sta ${C64MachineDefinition.C64Zeropage.SCRATCH_W1}
sty ${C64MachineDefinition.C64Zeropage.SCRATCH_W1 + 1}
ldy #0
lda (${C64MachineDefinition.C64Zeropage.SCRATCH_W1}),y""")
}
internal fun fixNameSymbols(name: String) = name.replace("<", "prog8_").replace(">", "") // take care of the autogenerated invalid (anon) label names
internal fun saveRegister(register: CpuRegister) {

View File

@ -5,6 +5,7 @@ import prog8.ast.base.*
import prog8.ast.expressions.*
import prog8.compiler.AssemblyError
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_PLUS1_HEX
import prog8.compiler.target.c64.C64MachineDefinition.ESTACK_LO_HEX
@ -84,7 +85,15 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge
DataType.BYTE -> {
when(expr.type) {
DataType.UBYTE, DataType.BYTE -> {}
DataType.UWORD, DataType.WORD -> asmgen.out(" lda $ESTACK_LO_PLUS1_HEX,x | ${asmgen.signExtendAtoMsb("$ESTACK_HI_PLUS1_HEX,x")}")
DataType.UWORD, DataType.WORD -> {
// sign extend
asmgen.out("""
lda $ESTACK_LO_PLUS1_HEX,x
ora #$7f
bmi +
lda #0
+ sta $ESTACK_HI_PLUS1_HEX,x""")
}
DataType.FLOAT -> asmgen.out(" jsr c64flt.stack_b2float")
in PassByReferenceDatatypes -> throw AssemblyError("cannot cast to a pass-by-reference datatype")
else -> throw AssemblyError("weird type")
@ -138,15 +147,8 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge
is IdentifierReference -> {
// the identifier is a pointer variable, so read the value from the address in it
val sourceName = asmgen.asmIdentifierName(expr.addressExpression as IdentifierReference)
asmgen.out("""
lda $sourceName
sta ${C64MachineDefinition.C64Zeropage.SCRATCH_W1}
lda $sourceName+1
sta ${C64MachineDefinition.C64Zeropage.SCRATCH_W1+1}
ldy #0
lda (${C64MachineDefinition.C64Zeropage.SCRATCH_W1}),y
sta $ESTACK_LO_HEX,x
dex""")
asmgen.loadByteFromPointerIntoA(sourceName)
asmgen.out(" sta $ESTACK_LO_HEX,x | dex")
}
else -> {
translateExpression(expr.addressExpression)

View File

@ -804,14 +804,8 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
val sourceName = asmgen.asmIdentifierName(identifier)
when(target.kind) {
TargetStorageKind.VARIABLE -> {
asmgen.out("""
lda $sourceName
sta ${C64Zeropage.SCRATCH_W1}
lda $sourceName+1
sta ${C64Zeropage.SCRATCH_W1+1}
ldy #0
lda (${C64Zeropage.SCRATCH_W1}),y
sta ${target.asmVarname}""")
asmgen.loadByteFromPointerIntoA(sourceName)
asmgen.out(" sta ${target.asmVarname}")
}
TargetStorageKind.MEMORY -> {
storeByteViaRegisterAInMemoryAddress(sourceName, target.memory!!)
@ -820,13 +814,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
throw AssemblyError("no asm gen for assign memory byte $sourceName to array ${target.asmVarname} ")
}
TargetStorageKind.REGISTER -> {
asmgen.out("""
lda $sourceName
sta ${C64Zeropage.SCRATCH_W1}
lda $sourceName+1
sta ${C64Zeropage.SCRATCH_W1+1}
ldy #0
lda (${C64Zeropage.SCRATCH_W1}),y""")
asmgen.loadByteFromPointerIntoA(sourceName)
when(target.register!!) {
RegisterOrPair.A -> {}
RegisterOrPair.X -> asmgen.out(" tax")

View File

@ -365,23 +365,14 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
private fun inplaceModification_byte_value_to_memory(pointername: String, operator: String, value: Expression) {
println("warning: slow stack evaluation used (3): @($pointername) $operator= ${value::class.simpleName} at ${value.position}") // TODO
asmgen.translateExpression(value)
fun loadByteFromPointerIntoA() {
asmgen.out("""
lda $pointername
ldy $pointername+1
sta ${C64Zeropage.SCRATCH_W1}
sty ${C64Zeropage.SCRATCH_W1 + 1}
ldy #0
lda (${C64Zeropage.SCRATCH_W1}),y""")
}
when (operator) {
// note: ** (power) operator requires floats.
"+" -> {
loadByteFromPointerIntoA()
asmgen.loadByteFromPointerIntoA(pointername)
asmgen.out(" clc | adc $ESTACK_LO_PLUS1_HEX,x | sta (${C64Zeropage.SCRATCH_W1}),y")
}
"-" -> {
loadByteFromPointerIntoA()
asmgen.loadByteFromPointerIntoA(pointername)
asmgen.out(" sec | sbc $ESTACK_LO_PLUS1_HEX,x | sta (${C64Zeropage.SCRATCH_W1}),y")
}
"*" -> TODO("mul")// asmgen.out(" jsr prog8_lib.mul_byte") // the optimized routines should have been checked earlier
@ -395,15 +386,15 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
"<<" -> TODO("ubyte asl")
">>" -> TODO("ubyte lsr")
"&" -> {
loadByteFromPointerIntoA()
asmgen.loadByteFromPointerIntoA(pointername)
asmgen.out(" and $ESTACK_LO_PLUS1_HEX,x | sta (${C64Zeropage.SCRATCH_W1}),y")
}
"^" -> {
loadByteFromPointerIntoA()
asmgen.loadByteFromPointerIntoA(pointername)
asmgen.out(" xor $ESTACK_LO_PLUS1_HEX,x | sta (${C64Zeropage.SCRATCH_W1}),y")
}
"|" -> {
loadByteFromPointerIntoA()
asmgen.loadByteFromPointerIntoA(pointername)
asmgen.out(" ora $ESTACK_LO_PLUS1_HEX,x | sta (${C64Zeropage.SCRATCH_W1}),y")
}
else -> throw AssemblyError("invalid operator for in-place modification $operator")
@ -413,23 +404,14 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
private fun inplaceModification_byte_variable_to_memory(pointername: String, operator: String, ident: IdentifierReference) {
val otherName = asmgen.asmIdentifierName(ident)
fun loadByteFromPointerIntoA() {
asmgen.out("""
lda $pointername
ldy $pointername+1
sta ${C64Zeropage.SCRATCH_W1}
sty ${C64Zeropage.SCRATCH_W1 + 1}
ldy #0
lda (${C64Zeropage.SCRATCH_W1}),y""")
}
when (operator) {
// note: ** (power) operator requires floats.
"+" -> {
loadByteFromPointerIntoA()
asmgen.loadByteFromPointerIntoA(pointername)
asmgen.out(" clc | adc $otherName | sta (${C64Zeropage.SCRATCH_W1}),y")
}
"-" -> {
loadByteFromPointerIntoA()
asmgen.loadByteFromPointerIntoA(pointername)
asmgen.out(" sec | sbc $otherName | sta (${C64Zeropage.SCRATCH_W1}),y")
}
"*" -> TODO("mul")// asmgen.out(" jsr prog8_lib.mul_byte") // the optimized routines should have been checked earlier
@ -443,15 +425,15 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
"<<" -> TODO("ubyte asl")
">>" -> TODO("ubyte lsr")
"&" -> {
loadByteFromPointerIntoA()
asmgen.loadByteFromPointerIntoA(pointername)
asmgen.out(" and $otherName | sta (${C64Zeropage.SCRATCH_W1}),y")
}
"^" -> {
loadByteFromPointerIntoA()
asmgen.loadByteFromPointerIntoA(pointername)
asmgen.out(" xor $otherName | sta (${C64Zeropage.SCRATCH_W1}),y")
}
"|" -> {
loadByteFromPointerIntoA()
asmgen.loadByteFromPointerIntoA(pointername)
asmgen.out(" ora $otherName | sta (${C64Zeropage.SCRATCH_W1}),y")
}
else -> throw AssemblyError("invalid operator for in-place modification $operator")
@ -459,23 +441,14 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
}
private fun inplaceModification_byte_litval_to_memory(pointername: String, operator: String, value: Int) {
fun loadByteFromPointerInA() {
asmgen.out("""
lda $pointername
ldy $pointername+1
sta ${C64Zeropage.SCRATCH_W1}
sty ${C64Zeropage.SCRATCH_W1 + 1}
ldy #0
lda (${C64Zeropage.SCRATCH_W1}),y""")
}
when (operator) {
// note: ** (power) operator requires floats.
"+" -> {
loadByteFromPointerInA()
asmgen.loadByteFromPointerIntoA(pointername)
asmgen.out(" clc | adc #$value | sta (${C64Zeropage.SCRATCH_W1}),y")
}
"-" -> {
loadByteFromPointerInA()
asmgen.loadByteFromPointerIntoA(pointername)
asmgen.out(" sec | sbc #$value | sta (${C64Zeropage.SCRATCH_W1}),y")
}
"*" -> TODO("mul")// asmgen.out(" jsr prog8_lib.mul_byte") // the optimized routines should have been checked earlier
@ -495,28 +468,28 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
}
"<<" -> {
if (value > 0) {
loadByteFromPointerInA()
asmgen.loadByteFromPointerIntoA(pointername)
repeat(value) { asmgen.out(" asl a") }
asmgen.out(" sta (${C64Zeropage.SCRATCH_W1}),y")
}
}
">>" -> {
if (value > 0) {
loadByteFromPointerInA()
asmgen.loadByteFromPointerIntoA(pointername)
repeat(value) { asmgen.out(" lsr a") }
asmgen.out(" sta (${C64Zeropage.SCRATCH_W1}),y")
}
}
"&" -> {
loadByteFromPointerInA()
asmgen.loadByteFromPointerIntoA(pointername)
asmgen.out(" and #$value | sta (${C64Zeropage.SCRATCH_W1}),y")
}
"^" -> {
loadByteFromPointerInA()
asmgen.loadByteFromPointerIntoA(pointername)
asmgen.out(" xor #$value | sta (${C64Zeropage.SCRATCH_W1}),y")
}
"|" -> {
loadByteFromPointerInA()
asmgen.loadByteFromPointerIntoA(pointername)
asmgen.out(" ora #$value | sta (${C64Zeropage.SCRATCH_W1}),y")
}
else -> throw AssemblyError("invalid operator for in-place modification $operator")
@ -1075,13 +1048,8 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
}
is IdentifierReference -> {
val name = asmgen.asmIdentifierName(mem.addressExpression as IdentifierReference)
asmgen.loadByteFromPointerIntoA(name)
asmgen.out("""
lda $name
sta ${C64Zeropage.SCRATCH_W1}
lda $name+1
sta ${C64Zeropage.SCRATCH_W1 + 1}
ldy #0
lda (${C64Zeropage.SCRATCH_W1}),y
beq +
lda #1
+ eor #1
@ -1152,13 +1120,8 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
}
is IdentifierReference -> {
val name = asmgen.asmIdentifierName(memory.addressExpression as IdentifierReference)
asmgen.loadByteFromPointerIntoA(name)
asmgen.out("""
lda $name
sta ${C64Zeropage.SCRATCH_W1}
lda $name+1
sta ${C64Zeropage.SCRATCH_W1 + 1}
ldy #0
lda (${C64Zeropage.SCRATCH_W1}),y
eor #255
sta (${C64Zeropage.SCRATCH_W1}),y""")
}

View File

@ -1,27 +1,60 @@
%import c64utils
%zeropage basicsafe
main {
uword glob=11222
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() {
uword lines = 1
uword score = $1000
ubyte x
ubyte y
c64scr.print_uw(lines)
c64.CHROUT('\n')
lines=glob
c64scr.print_uw(lines)
c64.CHROUT('\n')
lines = mkword(x, y)
c64scr.print_uw(lines)
c64.CHROUT('\n')
c64scr.print_uw(score)
c64.CHROUT('\n')
benchcommon.begin()
ubyte i
for i in 0 to 5 {
c64scr.print_uw(sumrom())
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)
}
}