mirror of
https://github.com/irmen/prog8.git
synced 2024-11-27 03:50:27 +00:00
refactoring assignments codegen
This commit is contained in:
parent
c144d4e501
commit
6f3b2749b0
@ -328,7 +328,7 @@ open class Assignment(var target: AssignTarget, var value: Expression, override
|
|||||||
return("Assignment(target: $target, value: $value, pos=$position)")
|
return("Assignment(target: $target, value: $value, pos=$position)")
|
||||||
}
|
}
|
||||||
|
|
||||||
val isInplace: Boolean
|
val isAugmentable: Boolean
|
||||||
get() {
|
get() {
|
||||||
val binExpr = value as? BinaryExpression
|
val binExpr = value as? BinaryExpression
|
||||||
if(binExpr!=null) {
|
if(binExpr!=null) {
|
||||||
|
@ -1025,36 +1025,6 @@ $counterVar .byte 0""")
|
|||||||
internal fun translateFunctionCall(functionCall: FunctionCall) =
|
internal fun translateFunctionCall(functionCall: FunctionCall) =
|
||||||
functioncallAsmGen.translateFunctionCall(functionCall)
|
functioncallAsmGen.translateFunctionCall(functionCall)
|
||||||
|
|
||||||
internal fun assignFromEvalResult(target: AssignTarget) =
|
internal fun assignToRegister(reg: CpuRegister, value: Short?, identifier: IdentifierReference?) =
|
||||||
assignmentAsmGen.assignFromEvalResult(target)
|
|
||||||
|
|
||||||
fun assignFromByteConstant(target: AssignTarget, value: Short) =
|
|
||||||
assignmentAsmGen.assignFromByteConstant(target, value)
|
|
||||||
|
|
||||||
fun assignFromWordConstant(target: AssignTarget, value: Int) =
|
|
||||||
assignmentAsmGen.assignFromWordConstant(target, value)
|
|
||||||
|
|
||||||
fun assignFromFloatConstant(target: AssignTarget, value: Double) =
|
|
||||||
assignmentAsmGen.assignFromFloatConstant(target, value)
|
|
||||||
|
|
||||||
fun assignFromByteVariable(target: AssignTarget, variable: IdentifierReference) =
|
|
||||||
assignmentAsmGen.assignFromByteVariable(target, variable)
|
|
||||||
|
|
||||||
fun assignFromWordVariable(target: AssignTarget, variable: IdentifierReference) =
|
|
||||||
assignmentAsmGen.assignFromWordVariable(target, variable)
|
|
||||||
|
|
||||||
fun assignFromAddressOf(target: AssignTarget, variable: IdentifierReference) =
|
|
||||||
assignmentAsmGen.assignFromAddressOf(target, variable)
|
|
||||||
|
|
||||||
fun assignFromFloatVariable(target: AssignTarget, variable: IdentifierReference) =
|
|
||||||
assignmentAsmGen.assignFromFloatVariable(target, variable)
|
|
||||||
|
|
||||||
fun assignFromRegister(target: AssignTarget, register: CpuRegister) =
|
|
||||||
assignmentAsmGen.assignFromRegister(target, register)
|
|
||||||
|
|
||||||
fun assignFromMemoryByte(target: AssignTarget, address: Int?, identifier: IdentifierReference?) =
|
|
||||||
assignmentAsmGen.assignFromMemoryByte(target, address, identifier)
|
|
||||||
|
|
||||||
fun assignToRegister(reg: CpuRegister, value: Short?, identifier: IdentifierReference?) =
|
|
||||||
assignmentAsmGen.assignToRegister(reg, value, identifier)
|
assignmentAsmGen.assignToRegister(reg, value, identifier)
|
||||||
}
|
}
|
||||||
|
@ -3,10 +3,7 @@ package prog8.compiler.target.c64.codegen
|
|||||||
import prog8.ast.Program
|
import prog8.ast.Program
|
||||||
import prog8.ast.base.*
|
import prog8.ast.base.*
|
||||||
import prog8.ast.expressions.*
|
import prog8.ast.expressions.*
|
||||||
import prog8.ast.statements.AssignTarget
|
import prog8.ast.statements.*
|
||||||
import prog8.ast.statements.Assignment
|
|
||||||
import prog8.ast.statements.DirectMemoryWrite
|
|
||||||
import prog8.ast.statements.VarDecl
|
|
||||||
import prog8.compiler.AssemblyError
|
import prog8.compiler.AssemblyError
|
||||||
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.C64Zeropage
|
||||||
@ -18,33 +15,49 @@ import prog8.compiler.toHex
|
|||||||
internal class AssignmentAsmGen(private val program: Program, private val asmgen: AsmGen) {
|
internal class AssignmentAsmGen(private val program: Program, private val asmgen: AsmGen) {
|
||||||
|
|
||||||
internal fun translate(assign: Assignment) {
|
internal fun translate(assign: Assignment) {
|
||||||
if(assign.isInplace)
|
when {
|
||||||
translateNormalAssignment(assign) // TODO generate better code here for in-place assignments
|
assign.value is NumericLiteralValue -> translateConstantValueAssignment(assign)
|
||||||
else
|
assign.value is IdentifierReference -> translateVariableAssignment(assign)
|
||||||
translateNormalAssignment(assign)
|
assign.isAugmentable -> {
|
||||||
|
println("TODO: optimize augmentable assignment ${assign.position}") // TODO
|
||||||
|
translateOtherAssignment(assign) // TODO generate better code here for augmentable assignments
|
||||||
|
}
|
||||||
|
else -> translateOtherAssignment(assign)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// old code-generation below:
|
internal fun assignToRegister(reg: CpuRegister, value: Short?, identifier: IdentifierReference?) {
|
||||||
// eventually, all of this should have been replaced by newer more optimized code.
|
if(value!=null) {
|
||||||
private fun translateNormalAssignment(assign: Assignment) {
|
asmgen.out(" ld${reg.toString().toLowerCase()} #${value.toHex()}")
|
||||||
|
} else if(identifier!=null) {
|
||||||
|
val name = asmgen.asmIdentifierName(identifier)
|
||||||
|
asmgen.out(" ld${reg.toString().toLowerCase()} $name")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun translateVariableAssignment(assign: Assignment) {
|
||||||
|
val identifier = assign.value as IdentifierReference
|
||||||
|
when (val type = assign.target.inferType(program, assign).typeOrElse(DataType.STRUCT)) {
|
||||||
|
DataType.UBYTE, DataType.BYTE -> assignFromByteVariable(assign.target, identifier)
|
||||||
|
DataType.UWORD, DataType.WORD -> assignFromWordVariable(assign.target, identifier)
|
||||||
|
DataType.FLOAT -> assignFromFloatVariable(assign.target, identifier)
|
||||||
|
in PassByReferenceDatatypes -> assignFromAddressOf(assign.target, identifier)
|
||||||
|
else -> throw AssemblyError("unsupported assignment target type $type")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun translateConstantValueAssignment(assign: Assignment) {
|
||||||
|
val numVal = assign.value as NumericLiteralValue
|
||||||
|
when (numVal.type) {
|
||||||
|
DataType.UBYTE, DataType.BYTE -> assignFromByteConstant(assign.target, numVal.number.toShort())
|
||||||
|
DataType.UWORD, DataType.WORD -> assignFromWordConstant(assign.target, numVal.number.toInt())
|
||||||
|
DataType.FLOAT -> assignFromFloatConstant(assign.target, numVal.number.toDouble())
|
||||||
|
else -> throw AssemblyError("weird numval type")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun translateOtherAssignment(assign: Assignment) {
|
||||||
when (assign.value) {
|
when (assign.value) {
|
||||||
is NumericLiteralValue -> {
|
|
||||||
val numVal = assign.value as NumericLiteralValue
|
|
||||||
when (numVal.type) {
|
|
||||||
DataType.UBYTE, DataType.BYTE -> assignFromByteConstant(assign.target, numVal.number.toShort())
|
|
||||||
DataType.UWORD, DataType.WORD -> assignFromWordConstant(assign.target, numVal.number.toInt())
|
|
||||||
DataType.FLOAT -> assignFromFloatConstant(assign.target, numVal.number.toDouble())
|
|
||||||
else -> throw AssemblyError("weird numval type")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
is IdentifierReference -> {
|
|
||||||
when (val type = assign.target.inferType(program, assign).typeOrElse(DataType.STRUCT)) {
|
|
||||||
DataType.UBYTE, DataType.BYTE -> assignFromByteVariable(assign.target, assign.value as IdentifierReference)
|
|
||||||
DataType.UWORD, DataType.WORD -> assignFromWordVariable(assign.target, assign.value as IdentifierReference)
|
|
||||||
DataType.FLOAT -> assignFromFloatVariable(assign.target, assign.value as IdentifierReference)
|
|
||||||
else -> throw AssemblyError("unsupported assignment target type $type")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
is AddressOf -> {
|
is AddressOf -> {
|
||||||
val identifier = (assign.value as AddressOf).identifier
|
val identifier = (assign.value as AddressOf).identifier
|
||||||
assignFromAddressOf(assign.target, identifier)
|
assignFromAddressOf(assign.target, identifier)
|
||||||
@ -60,7 +73,9 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
|||||||
assignFromMemoryByte(assign.target, null, read.addressExpression as IdentifierReference)
|
assignFromMemoryByte(assign.target, null, read.addressExpression as IdentifierReference)
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
throw AssemblyError("missing asm gen for memread assignment into ${assign.target}")
|
asmgen.translateExpression(read.addressExpression)
|
||||||
|
asmgen.out(" jsr prog8_lib.read_byte_from_address | inx")
|
||||||
|
assignFromRegister(assign.target, CpuRegister.A)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -120,10 +135,11 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
|||||||
}
|
}
|
||||||
is ArrayLiteralValue, is StringLiteralValue -> throw AssemblyError("no asm gen for string/array assignment $assign")
|
is ArrayLiteralValue, is StringLiteralValue -> throw AssemblyError("no asm gen for string/array assignment $assign")
|
||||||
is RangeExpr -> throw AssemblyError("range expression should have been changed into array values ${assign.value.position}")
|
is RangeExpr -> throw AssemblyError("range expression should have been changed into array values ${assign.value.position}")
|
||||||
|
else -> throw AssemblyError("assignment value type should have been handled elsewhere")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun assignFromEvalResult(target: AssignTarget) {
|
private fun assignFromEvalResult(target: AssignTarget) {
|
||||||
val targetIdent = target.identifier
|
val targetIdent = target.identifier
|
||||||
when {
|
when {
|
||||||
targetIdent != null -> {
|
targetIdent != null -> {
|
||||||
@ -152,8 +168,8 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
target.memoryAddress != null -> {
|
target.memoryAddress != null -> {
|
||||||
asmgen.out(" inx | ldy $ESTACK_LO_HEX,x")
|
asmgen.out(" inx")
|
||||||
storeRegisterInMemoryAddress(CpuRegister.Y, target.memoryAddress)
|
storeByteViaRegisterAInMemoryAddress("$ESTACK_LO_HEX,x", target.memoryAddress)
|
||||||
}
|
}
|
||||||
target.arrayindexed != null -> {
|
target.arrayindexed != null -> {
|
||||||
val arrayDt = target.arrayindexed!!.identifier.inferType(program).typeOrElse(DataType.STRUCT)
|
val arrayDt = target.arrayindexed!!.identifier.inferType(program).typeOrElse(DataType.STRUCT)
|
||||||
@ -166,7 +182,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun assignFromAddressOf(target: AssignTarget, name: IdentifierReference) {
|
private fun assignFromAddressOf(target: AssignTarget, name: IdentifierReference) {
|
||||||
val targetIdent = target.identifier
|
val targetIdent = target.identifier
|
||||||
val targetArrayIdx = target.arrayindexed
|
val targetArrayIdx = target.arrayindexed
|
||||||
val struct = name.memberOfStruct(program.namespace)
|
val struct = name.memberOfStruct(program.namespace)
|
||||||
@ -204,7 +220,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun assignFromWordVariable(target: AssignTarget, variable: IdentifierReference) {
|
private fun assignFromWordVariable(target: AssignTarget, variable: IdentifierReference) {
|
||||||
val sourceName = asmgen.asmIdentifierName(variable)
|
val sourceName = asmgen.asmIdentifierName(variable)
|
||||||
val targetIdent = target.identifier
|
val targetIdent = target.identifier
|
||||||
val targetArrayIdx = target.arrayindexed
|
val targetArrayIdx = target.arrayindexed
|
||||||
@ -234,7 +250,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun assignFromFloatVariable(target: AssignTarget, variable: IdentifierReference) {
|
private fun assignFromFloatVariable(target: AssignTarget, variable: IdentifierReference) {
|
||||||
val sourceName = asmgen.asmIdentifierName(variable)
|
val sourceName = asmgen.asmIdentifierName(variable)
|
||||||
val targetIdent = target.identifier
|
val targetIdent = target.identifier
|
||||||
val targetArrayIdx = target.arrayindexed
|
val targetArrayIdx = target.arrayindexed
|
||||||
@ -265,7 +281,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun assignFromByteVariable(target: AssignTarget, variable: IdentifierReference) {
|
private fun assignFromByteVariable(target: AssignTarget, variable: IdentifierReference) {
|
||||||
val sourceName = asmgen.asmIdentifierName(variable)
|
val sourceName = asmgen.asmIdentifierName(variable)
|
||||||
val targetIdent = target.identifier
|
val targetIdent = target.identifier
|
||||||
val targetArrayIdx = target.arrayindexed
|
val targetArrayIdx = target.arrayindexed
|
||||||
@ -296,16 +312,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
|||||||
asmgen.out(" lda $sourceName | sta $targetName")
|
asmgen.out(" lda $sourceName | sta $targetName")
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
asmgen.translateExpression(addressExpr)
|
storeByteViaRegisterAInMemoryAddress(sourceName, target.memoryAddress)
|
||||||
asmgen.out("""
|
|
||||||
inx
|
|
||||||
lda $ESTACK_LO_HEX,x
|
|
||||||
ldy $ESTACK_HI_HEX,x
|
|
||||||
sta (+) +1
|
|
||||||
sty (+) +2
|
|
||||||
lda $sourceName
|
|
||||||
+ sta ${'$'}ffff ; modified
|
|
||||||
""")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -313,7 +320,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun assignFromRegister(target: AssignTarget, register: CpuRegister) {
|
private fun assignFromRegister(target: AssignTarget, register: CpuRegister) {
|
||||||
val targetIdent = target.identifier
|
val targetIdent = target.identifier
|
||||||
val targetArrayIdx = target.arrayindexed
|
val targetArrayIdx = target.arrayindexed
|
||||||
when {
|
when {
|
||||||
@ -372,7 +379,39 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun storeByteViaRegisterAInMemoryAddress(ldaInstructionArg: String, memoryAddress: DirectMemoryWrite) {
|
||||||
|
val addressExpr = memoryAddress.addressExpression
|
||||||
|
val addressLv = addressExpr as? NumericLiteralValue
|
||||||
|
when {
|
||||||
|
addressLv != null -> asmgen.out(" lda $ldaInstructionArg | sta ${addressLv.number.toHex()}")
|
||||||
|
addressExpr is IdentifierReference -> {
|
||||||
|
val targetName = asmgen.asmIdentifierName(addressExpr)
|
||||||
|
asmgen.out("""
|
||||||
|
lda $targetName
|
||||||
|
sta ${C64Zeropage.SCRATCH_W1}
|
||||||
|
lda $targetName+1
|
||||||
|
sta ${C64Zeropage.SCRATCH_W1+1}
|
||||||
|
lda $ldaInstructionArg
|
||||||
|
ldy #0
|
||||||
|
sta (${C64Zeropage.SCRATCH_W1}),y""")
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
asmgen.translateExpression(addressExpr)
|
||||||
|
asmgen.out("""
|
||||||
|
inx
|
||||||
|
lda $ESTACK_LO_HEX,x
|
||||||
|
sta ${C64Zeropage.SCRATCH_W1}
|
||||||
|
lda $ESTACK_HI_HEX,x
|
||||||
|
sta ${C64Zeropage.SCRATCH_W1+1}
|
||||||
|
lda $ldaInstructionArg
|
||||||
|
ldy #0
|
||||||
|
sta (${C64Zeropage.SCRATCH_W1}),y""")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun storeRegisterInMemoryAddress(register: CpuRegister, memoryAddress: DirectMemoryWrite) {
|
private fun storeRegisterInMemoryAddress(register: CpuRegister, memoryAddress: DirectMemoryWrite) {
|
||||||
|
// this is optimized for register A.
|
||||||
val addressExpr = memoryAddress.addressExpression
|
val addressExpr = memoryAddress.addressExpression
|
||||||
val addressLv = addressExpr as? NumericLiteralValue
|
val addressLv = addressExpr as? NumericLiteralValue
|
||||||
val registerName = register.name.toLowerCase()
|
val registerName = register.name.toLowerCase()
|
||||||
@ -381,48 +420,35 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
|||||||
addressExpr is IdentifierReference -> {
|
addressExpr is IdentifierReference -> {
|
||||||
val targetName = asmgen.asmIdentifierName(addressExpr)
|
val targetName = asmgen.asmIdentifierName(addressExpr)
|
||||||
when (register) {
|
when (register) {
|
||||||
CpuRegister.A -> asmgen.out("""
|
CpuRegister.A -> {}
|
||||||
ldy $targetName
|
CpuRegister.X -> asmgen.out(" txa")
|
||||||
sty (+) +1
|
CpuRegister.Y -> asmgen.out(" tya")
|
||||||
ldy $targetName+1
|
|
||||||
sty (+) +2
|
|
||||||
+ sta ${'$'}ffff ; modified""")
|
|
||||||
CpuRegister.X -> asmgen.out("""
|
|
||||||
ldy $targetName
|
|
||||||
sty (+) +1
|
|
||||||
ldy $targetName+1
|
|
||||||
sty (+) +2
|
|
||||||
+ stx ${'$'}ffff ; modified""")
|
|
||||||
CpuRegister.Y -> asmgen.out("""
|
|
||||||
lda $targetName
|
|
||||||
sta (+) +1
|
|
||||||
lda $targetName+1
|
|
||||||
sta (+) +2
|
|
||||||
+ sty ${'$'}ffff ; modified""")
|
|
||||||
}
|
}
|
||||||
|
asmgen.out("""
|
||||||
|
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)
|
||||||
asmgen.translateExpression(addressExpr)
|
asmgen.translateExpression(addressExpr)
|
||||||
asmgen.restoreRegister(register)
|
asmgen.restoreRegister(CpuRegister.A)
|
||||||
when (register) {
|
|
||||||
CpuRegister.A -> asmgen.out(" tay")
|
|
||||||
CpuRegister.X -> throw AssemblyError("can't use X register here")
|
|
||||||
CpuRegister.Y -> {}
|
|
||||||
}
|
|
||||||
asmgen.out("""
|
asmgen.out("""
|
||||||
inx
|
inx
|
||||||
lda $ESTACK_LO_HEX,x
|
ldy $ESTACK_LO_HEX,x
|
||||||
sta (+) +1
|
sty ${C64Zeropage.SCRATCH_W1}
|
||||||
lda $ESTACK_HI_HEX,x
|
ldy $ESTACK_HI_HEX,x
|
||||||
sta (+) +2
|
sty ${C64Zeropage.SCRATCH_W1+1}
|
||||||
+ sty ${'$'}ffff ; modified
|
ldy #0
|
||||||
""")
|
sta (${C64Zeropage.SCRATCH_W1}),y""")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun assignFromWordConstant(target: AssignTarget, word: Int) {
|
private fun assignFromWordConstant(target: AssignTarget, word: Int) {
|
||||||
val targetIdent = target.identifier
|
val targetIdent = target.identifier
|
||||||
val targetArrayIdx = target.arrayindexed
|
val targetArrayIdx = target.arrayindexed
|
||||||
when {
|
when {
|
||||||
@ -467,17 +493,17 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun assignFromByteConstant(target: AssignTarget, byte: Short) {
|
private fun assignFromByteConstant(target: AssignTarget, byte: Short) {
|
||||||
val targetIdent = target.identifier
|
val targetIdent = target.identifier
|
||||||
val targetArrayIdx = target.arrayindexed
|
val targetArrayIdx = target.arrayindexed
|
||||||
|
val targetMemory = target.memoryAddress
|
||||||
when {
|
when {
|
||||||
targetIdent != null -> {
|
targetIdent != null -> {
|
||||||
val targetName = asmgen.asmIdentifierName(targetIdent)
|
val targetName = asmgen.asmIdentifierName(targetIdent)
|
||||||
asmgen.out(" lda #${byte.toHex()} | sta $targetName ")
|
asmgen.out(" lda #${byte.toHex()} | sta $targetName ")
|
||||||
}
|
}
|
||||||
target.memoryAddress != null -> {
|
targetMemory != null -> {
|
||||||
asmgen.out(" ldy #${byte.toHex()}")
|
storeByteViaRegisterAInMemoryAddress("#${byte.toHex()}", targetMemory)
|
||||||
storeRegisterInMemoryAddress(CpuRegister.Y, target.memoryAddress)
|
|
||||||
}
|
}
|
||||||
targetArrayIdx != null -> {
|
targetArrayIdx != null -> {
|
||||||
val index = targetArrayIdx.arrayspec.index
|
val index = targetArrayIdx.arrayspec.index
|
||||||
@ -495,7 +521,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun assignFromFloatConstant(target: AssignTarget, float: Double) {
|
private fun assignFromFloatConstant(target: AssignTarget, float: Double) {
|
||||||
val targetIdent = target.identifier
|
val targetIdent = target.identifier
|
||||||
val targetArrayIdx = target.arrayindexed
|
val targetArrayIdx = target.arrayindexed
|
||||||
if (float == 0.0) {
|
if (float == 0.0) {
|
||||||
@ -594,7 +620,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun assignFromMemoryByte(target: AssignTarget, address: Int?, identifier: IdentifierReference?) {
|
private fun assignFromMemoryByte(target: AssignTarget, address: Int?, identifier: IdentifierReference?) {
|
||||||
val targetIdent = target.identifier
|
val targetIdent = target.identifier
|
||||||
val targetArrayIdx = target.arrayindexed
|
val targetArrayIdx = target.arrayindexed
|
||||||
if (address != null) {
|
if (address != null) {
|
||||||
@ -607,8 +633,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
|||||||
""")
|
""")
|
||||||
}
|
}
|
||||||
target.memoryAddress != null -> {
|
target.memoryAddress != null -> {
|
||||||
asmgen.out(" ldy ${address.toHex()}")
|
storeByteViaRegisterAInMemoryAddress(address.toHex(), target.memoryAddress)
|
||||||
storeRegisterInMemoryAddress(CpuRegister.Y, target.memoryAddress)
|
|
||||||
}
|
}
|
||||||
targetArrayIdx != null -> {
|
targetArrayIdx != null -> {
|
||||||
val index = targetArrayIdx.arrayspec.index
|
val index = targetArrayIdx.arrayspec.index
|
||||||
@ -631,8 +656,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
|||||||
sta $targetName""")
|
sta $targetName""")
|
||||||
}
|
}
|
||||||
target.memoryAddress != null -> {
|
target.memoryAddress != null -> {
|
||||||
asmgen.out(" ldy $sourceName")
|
storeByteViaRegisterAInMemoryAddress(sourceName, target.memoryAddress)
|
||||||
storeRegisterInMemoryAddress(CpuRegister.Y, target.memoryAddress)
|
|
||||||
}
|
}
|
||||||
targetArrayIdx != null -> {
|
targetArrayIdx != null -> {
|
||||||
val index = targetArrayIdx.arrayspec.index
|
val index = targetArrayIdx.arrayspec.index
|
||||||
@ -663,13 +687,4 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
|||||||
throw AssemblyError("weird array type")
|
throw AssemblyError("weird array type")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun assignToRegister(reg: CpuRegister, value: Short?, identifier: IdentifierReference?) {
|
|
||||||
if(value!=null) {
|
|
||||||
asmgen.out(" ld${reg.toString().toLowerCase()} #${value.toHex()}")
|
|
||||||
} else if(identifier!=null) {
|
|
||||||
val name = asmgen.asmIdentifierName(identifier)
|
|
||||||
asmgen.out(" ld${reg.toString().toLowerCase()} $name")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -140,10 +140,11 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge
|
|||||||
val sourceName = asmgen.asmIdentifierName(expr.addressExpression as IdentifierReference)
|
val sourceName = asmgen.asmIdentifierName(expr.addressExpression as IdentifierReference)
|
||||||
asmgen.out("""
|
asmgen.out("""
|
||||||
lda $sourceName
|
lda $sourceName
|
||||||
sta (+) +1
|
sta ${C64MachineDefinition.C64Zeropage.SCRATCH_W1}
|
||||||
lda $sourceName+1
|
lda $sourceName+1
|
||||||
sta (+) +2
|
sta ${C64MachineDefinition.C64Zeropage.SCRATCH_W1+1}
|
||||||
+ lda ${'$'}ffff ; modified
|
ldy #0
|
||||||
|
lda (${C64MachineDefinition.C64Zeropage.SCRATCH_W1}),y
|
||||||
sta $ESTACK_LO_HEX,x
|
sta $ESTACK_LO_HEX,x
|
||||||
dex""")
|
dex""")
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import prog8.ast.Program
|
|||||||
import prog8.ast.base.*
|
import prog8.ast.base.*
|
||||||
import prog8.ast.expressions.*
|
import prog8.ast.expressions.*
|
||||||
import prog8.ast.statements.AssignTarget
|
import prog8.ast.statements.AssignTarget
|
||||||
|
import prog8.ast.statements.Assignment
|
||||||
import prog8.ast.statements.Subroutine
|
import prog8.ast.statements.Subroutine
|
||||||
import prog8.ast.statements.SubroutineParameter
|
import prog8.ast.statements.SubroutineParameter
|
||||||
import prog8.compiler.AssemblyError
|
import prog8.compiler.AssemblyError
|
||||||
@ -107,48 +108,9 @@ internal class FunctionCallAsmGen(private val program: Program, private val asmg
|
|||||||
val paramVar = parameter.value
|
val paramVar = parameter.value
|
||||||
val scopedParamVar = (sub.scopedname+"."+paramVar.name).split(".")
|
val scopedParamVar = (sub.scopedname+"."+paramVar.name).split(".")
|
||||||
val target = AssignTarget(IdentifierReference(scopedParamVar, sub.position), null, null, sub.position)
|
val target = AssignTarget(IdentifierReference(scopedParamVar, sub.position), null, null, sub.position)
|
||||||
target.linkParents(value.parent)
|
val assign = Assignment(target, value, value.position)
|
||||||
when (value) {
|
assign.linkParents(value.parent)
|
||||||
is NumericLiteralValue -> {
|
asmgen.translate(assign)
|
||||||
// optimize when the argument is a constant literal
|
|
||||||
when(parameter.value.type) {
|
|
||||||
in ByteDatatypes -> asmgen.assignFromByteConstant(target, value.number.toShort())
|
|
||||||
in WordDatatypes -> asmgen.assignFromWordConstant(target, value.number.toInt())
|
|
||||||
DataType.FLOAT -> asmgen.assignFromFloatConstant(target, value.number.toDouble())
|
|
||||||
else -> throw AssemblyError("weird parameter datatype")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
is IdentifierReference -> {
|
|
||||||
// optimize when the argument is a variable
|
|
||||||
when (parameter.value.type) {
|
|
||||||
in ByteDatatypes -> asmgen.assignFromByteVariable(target, value)
|
|
||||||
in WordDatatypes -> asmgen.assignFromWordVariable(target, value)
|
|
||||||
DataType.FLOAT -> asmgen.assignFromFloatVariable(target, value)
|
|
||||||
in PassByReferenceDatatypes -> asmgen.assignFromAddressOf(target, value)
|
|
||||||
else -> throw AssemblyError("weird parameter datatype")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
is DirectMemoryRead -> {
|
|
||||||
when(value.addressExpression) {
|
|
||||||
is NumericLiteralValue -> {
|
|
||||||
val address = (value.addressExpression as NumericLiteralValue).number.toInt()
|
|
||||||
asmgen.assignFromMemoryByte(target, address, null)
|
|
||||||
}
|
|
||||||
is IdentifierReference -> {
|
|
||||||
asmgen.assignFromMemoryByte(target, null, value.addressExpression as IdentifierReference)
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
asmgen.translateExpression(value.addressExpression)
|
|
||||||
asmgen.out(" jsr prog8_lib.read_byte_from_address | inx")
|
|
||||||
asmgen.assignFromRegister(target, CpuRegister.A)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
asmgen.translateExpression(value)
|
|
||||||
asmgen.assignFromEvalResult(target)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun argumentViaRegister(sub: Subroutine, parameter: IndexedValue<SubroutineParameter>, value: Expression) {
|
private fun argumentViaRegister(sub: Subroutine, parameter: IndexedValue<SubroutineParameter>, value: Expression) {
|
||||||
|
@ -7,21 +7,10 @@ main {
|
|||||||
|
|
||||||
sub start() {
|
sub start() {
|
||||||
|
|
||||||
c64scr.print_ub(5)
|
ubyte A=5
|
||||||
c64.CHROUT('\n')
|
uword clr = $d020
|
||||||
return
|
@(clr+1) = A
|
||||||
|
|
||||||
c64scr.print_ub(5)
|
; uword xx = @(clr+1)
|
||||||
c64.CHROUT('\n')
|
|
||||||
|
|
||||||
goto start
|
|
||||||
|
|
||||||
c64scr.print_ub(5)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
|
|
||||||
exit(11)
|
|
||||||
|
|
||||||
c64scr.print_ub(5)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user