mirror of
				https://github.com/irmen/prog8.git
				synced 2025-11-04 10:16:13 +00:00 
			
		
		
		
	refactoring assignments codegen
This commit is contained in:
		@@ -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,17 +15,38 @@ 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()}")
 | 
				
			||||||
        when (assign.value) {
 | 
					        } else if(identifier!=null) {
 | 
				
			||||||
            is NumericLiteralValue -> {
 | 
					            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
 | 
					        val numVal = assign.value as NumericLiteralValue
 | 
				
			||||||
        when (numVal.type) {
 | 
					        when (numVal.type) {
 | 
				
			||||||
            DataType.UBYTE, DataType.BYTE -> assignFromByteConstant(assign.target, numVal.number.toShort())
 | 
					            DataType.UBYTE, DataType.BYTE -> assignFromByteConstant(assign.target, numVal.number.toShort())
 | 
				
			||||||
@@ -37,14 +55,9 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
 | 
				
			|||||||
            else -> throw AssemblyError("weird numval type")
 | 
					            else -> throw AssemblyError("weird numval type")
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
            is IdentifierReference -> {
 | 
					
 | 
				
			||||||
                when (val type = assign.target.inferType(program, assign).typeOrElse(DataType.STRUCT)) {
 | 
					    private fun translateOtherAssignment(assign: Assignment) {
 | 
				
			||||||
                    DataType.UBYTE, DataType.BYTE -> assignFromByteVariable(assign.target, assign.value as IdentifierReference)
 | 
					        when (assign.value) {
 | 
				
			||||||
                    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')
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user