mirror of
https://github.com/irmen/prog8.git
synced 2025-02-16 22:30:46 +00:00
start with yet another codegen restructure, this time to make the assignment of values even more explicit for the codegen
This commit is contained in:
parent
5075901830
commit
d9e3895c45
122
compiler/src/prog8/compiler/target/c64/codegen/AsmAssignment.kt
Normal file
122
compiler/src/prog8/compiler/target/c64/codegen/AsmAssignment.kt
Normal file
@ -0,0 +1,122 @@
|
||||
package prog8.compiler.target.c64.codegen
|
||||
|
||||
import prog8.ast.Program
|
||||
import prog8.ast.base.*
|
||||
import prog8.ast.expressions.*
|
||||
import prog8.ast.statements.AssignTarget
|
||||
import prog8.ast.statements.Assignment
|
||||
import prog8.ast.statements.DirectMemoryWrite
|
||||
import prog8.compiler.AssemblyError
|
||||
|
||||
|
||||
enum class AsmTargetStorageType {
|
||||
VARIABLE,
|
||||
ARRAY,
|
||||
MEMORY,
|
||||
REGISTER,
|
||||
STACK
|
||||
}
|
||||
|
||||
enum class AsmSourceStorageType {
|
||||
LITERALNUMBER,
|
||||
VARIABLE,
|
||||
ARRAY,
|
||||
MEMORY,
|
||||
REGISTER,
|
||||
STACK, // value is already present on stack
|
||||
EXPRESSION, // expression still to be evaluated
|
||||
}
|
||||
|
||||
internal class AsmAssignTarget(val type: AsmTargetStorageType,
|
||||
program: Program,
|
||||
asmgen: AsmGen,
|
||||
val datatype: DataType,
|
||||
val astVariable: IdentifierReference?,
|
||||
val astArray: ArrayIndexedExpression?,
|
||||
val astMemory: DirectMemoryWrite?,
|
||||
val register: RegisterOrPair?,
|
||||
val origAstTarget: AssignTarget?, // TODO get rid of this eventually?
|
||||
)
|
||||
{
|
||||
val constMemoryAddress by lazy { astMemory?.addressExpression?.constValue(program)?.number?.toInt() ?: 0}
|
||||
val constArrayIndexValue by lazy { astArray?.arrayspec?.size() ?: 0 }
|
||||
val vardecl by lazy { astVariable?.targetVarDecl(program.namespace)!! }
|
||||
val asmName by lazy {
|
||||
if(astVariable!=null)
|
||||
asmgen.asmIdentifierName(astVariable)
|
||||
else
|
||||
asmgen.asmIdentifierName(astArray!!.identifier)
|
||||
}
|
||||
|
||||
lateinit var origAssign: AsmAssignment
|
||||
|
||||
init {
|
||||
if(astVariable!=null && vardecl.type == VarDeclType.CONST)
|
||||
throw AssemblyError("can't assign to a constant")
|
||||
if(register!=null && datatype !in IntegerDatatypes)
|
||||
throw AssemblyError("register must be integer type")
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun fromAstAssignment(assign: Assignment, program: Program, asmgen: AsmGen): AsmAssignTarget = with(assign.target) {
|
||||
val dt = inferType(program, assign).typeOrElse(DataType.STRUCT)
|
||||
when {
|
||||
identifier != null -> AsmAssignTarget(AsmTargetStorageType.VARIABLE, program, asmgen, dt, identifier, null, null, null, this)
|
||||
arrayindexed != null -> AsmAssignTarget(AsmTargetStorageType.ARRAY, program, asmgen, dt, null, arrayindexed, null, null, this)
|
||||
memoryAddress != null -> AsmAssignTarget(AsmTargetStorageType.MEMORY, program, asmgen, dt, null, null, memoryAddress, null, this)
|
||||
else -> throw AssemblyError("weird target")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class AsmAssignSource(val type: AsmSourceStorageType,
|
||||
private val program: Program,
|
||||
val astVariable: IdentifierReference? = null,
|
||||
val astArray: ArrayIndexedExpression? = null,
|
||||
val astMemory: DirectMemoryRead? = null,
|
||||
val register: RegisterOrPair? = null,
|
||||
val numLitval: NumericLiteralValue? = null,
|
||||
val astExpression: Expression? = null
|
||||
)
|
||||
{
|
||||
val constMemoryAddress by lazy { astMemory?.addressExpression?.constValue(program)?.number?.toInt() ?: 0}
|
||||
val constArrayIndexValue by lazy { astArray?.arrayspec?.size() ?: 0 }
|
||||
val vardecl by lazy { astVariable?.targetVarDecl(program.namespace)!! }
|
||||
|
||||
companion object {
|
||||
fun fromAstSource(value: Expression, program: Program): AsmAssignSource {
|
||||
val cv = value.constValue(program)
|
||||
if(cv!=null)
|
||||
return AsmAssignSource(AsmSourceStorageType.LITERALNUMBER, program, numLitval = cv)
|
||||
|
||||
return when(value) {
|
||||
is NumericLiteralValue -> AsmAssignSource(AsmSourceStorageType.LITERALNUMBER, program, numLitval = cv)
|
||||
is StringLiteralValue -> throw AssemblyError("string literal value should not occur anymore for asm generation")
|
||||
is ArrayLiteralValue -> throw AssemblyError("array literal value should not occur anymore for asm generation")
|
||||
is IdentifierReference -> AsmAssignSource(AsmSourceStorageType.VARIABLE, program, astVariable = value)
|
||||
is DirectMemoryRead -> AsmAssignSource(AsmSourceStorageType.MEMORY, program, astMemory = value)
|
||||
is ArrayIndexedExpression -> AsmAssignSource(AsmSourceStorageType.ARRAY, program, astArray = value)
|
||||
else -> AsmAssignSource(AsmSourceStorageType.EXPRESSION, program, astExpression = value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getAstValue(): Expression = when(type) {
|
||||
AsmSourceStorageType.LITERALNUMBER -> numLitval!!
|
||||
AsmSourceStorageType.VARIABLE -> astVariable!!
|
||||
AsmSourceStorageType.ARRAY -> astArray!!
|
||||
AsmSourceStorageType.MEMORY -> astMemory!!
|
||||
AsmSourceStorageType.EXPRESSION -> astExpression!!
|
||||
AsmSourceStorageType.REGISTER -> TODO()
|
||||
AsmSourceStorageType.STACK -> TODO()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
internal class AsmAssignment(val source: AsmAssignSource,
|
||||
val target: AsmAssignTarget,
|
||||
val isAugmentable: Boolean,
|
||||
val position: Position) {
|
||||
}
|
@ -11,39 +11,21 @@ import prog8.compiler.target.c64.C64MachineDefinition.ESTACK_HI_HEX
|
||||
import prog8.compiler.target.c64.C64MachineDefinition.ESTACK_LO_HEX
|
||||
import prog8.compiler.toHex
|
||||
|
||||
// TODO optimize the array indexes where the index is a constant
|
||||
|
||||
enum class AsmAssignTargetType {
|
||||
VARIABLE,
|
||||
ARRAY,
|
||||
MEMORY,
|
||||
REGISTER,
|
||||
STACK
|
||||
}
|
||||
|
||||
internal sealed class AsmAssignTarget(type: AsmAssignTargetType,
|
||||
astVariable: IdentifierReference?,
|
||||
astArray: ArrayIndexedExpression?,
|
||||
astMemory: DirectMemoryWrite?,
|
||||
register: RegisterOrPair?,
|
||||
program: Program
|
||||
)
|
||||
{
|
||||
val constMemoryAddress by lazy { astMemory?.addressExpression.constValue(program) }
|
||||
val constArrayIndexValue by lazy { astArray?.arrayspec.index
|
||||
|
||||
init {
|
||||
astMemory!!.addressExpression.
|
||||
}
|
||||
}
|
||||
|
||||
internal class AssignmentAsmGen(private val program: Program, private val asmgen: AsmGen) {
|
||||
|
||||
private val augmentableAsmGen = AugmentableAssignmentAsmGen(program, this, asmgen)
|
||||
|
||||
internal fun translate(assign: Assignment) {
|
||||
internal fun translate(assignment: Assignment) {
|
||||
val source = AsmAssignSource.fromAstSource(assignment.value, program)
|
||||
val target = AsmAssignTarget.fromAstAssignment(assignment, program, asmgen)
|
||||
val assign = AsmAssignment(source, target, assignment.isAugmentable, assignment.position)
|
||||
|
||||
when {
|
||||
assign.value is NumericLiteralValue -> translateConstantValueAssignment(assign)
|
||||
assign.value is IdentifierReference -> translateVariableAssignment(assign)
|
||||
source.type==AsmSourceStorageType.LITERALNUMBER -> translateConstantValueAssignment(assign)
|
||||
source.type==AsmSourceStorageType.VARIABLE -> translateVariableAssignment(assign)
|
||||
assign.isAugmentable -> augmentableAsmGen.translate(assign)
|
||||
else -> translateOtherAssignment(assign)
|
||||
}
|
||||
@ -58,19 +40,19 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
||||
}
|
||||
}
|
||||
|
||||
private fun translateVariableAssignment(assign: Assignment) {
|
||||
val identifier = assign.value as IdentifierReference
|
||||
when (val type = assign.target.inferType(program, assign).typeOrElse(DataType.STRUCT)) {
|
||||
private fun translateVariableAssignment(assign: AsmAssignment) {
|
||||
val identifier = assign.source.astVariable!!
|
||||
when (assign.target.datatype) {
|
||||
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")
|
||||
else -> throw AssemblyError("unsupported assignment target type ${assign.target.datatype}")
|
||||
}
|
||||
}
|
||||
|
||||
private fun translateConstantValueAssignment(assign: Assignment) {
|
||||
val numVal = assign.value as NumericLiteralValue
|
||||
private fun translateConstantValueAssignment(assign: AsmAssignment) {
|
||||
val numVal = assign.source.numLitval!!
|
||||
when (numVal.type) {
|
||||
DataType.UBYTE, DataType.BYTE -> assignFromByteConstant(assign.target, numVal.number.toShort())
|
||||
DataType.UWORD, DataType.WORD -> assignFromWordConstant(assign.target, numVal.number.toInt())
|
||||
@ -79,44 +61,45 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
||||
}
|
||||
}
|
||||
|
||||
internal fun translateOtherAssignment(assign: Assignment) {
|
||||
when (assign.value) {
|
||||
internal fun translateOtherAssignment(assign: AsmAssignment) {
|
||||
// source: expression, register, stack (only expression implemented for now)
|
||||
|
||||
// TODO use source type enum
|
||||
val value=assign.source.getAstValue()
|
||||
when (value) {
|
||||
is AddressOf -> {
|
||||
val identifier = (assign.value as AddressOf).identifier
|
||||
assignFromAddressOf(assign.target, identifier)
|
||||
assignFromAddressOf(assign.target, value.identifier)
|
||||
}
|
||||
is DirectMemoryRead -> {
|
||||
val read = (assign.value as DirectMemoryRead)
|
||||
when (read.addressExpression) {
|
||||
when (value.addressExpression) {
|
||||
is NumericLiteralValue -> {
|
||||
val address = (read.addressExpression as NumericLiteralValue).number.toInt()
|
||||
val address = (value.addressExpression as NumericLiteralValue).number.toInt()
|
||||
assignFromMemoryByte(assign.target, address, null)
|
||||
}
|
||||
is IdentifierReference -> {
|
||||
assignFromMemoryByte(assign.target, null, read.addressExpression as IdentifierReference)
|
||||
assignFromMemoryByte(assign.target, null, value.addressExpression as IdentifierReference)
|
||||
}
|
||||
else -> {
|
||||
asmgen.translateExpression(read.addressExpression)
|
||||
asmgen.translateExpression(value.addressExpression)
|
||||
asmgen.out(" jsr prog8_lib.read_byte_from_address_on_stack | inx")
|
||||
assignFromRegister(assign.target, CpuRegister.A)
|
||||
}
|
||||
}
|
||||
}
|
||||
is PrefixExpression -> {
|
||||
asmgen.translateExpression(assign.value as PrefixExpression)
|
||||
asmgen.translateExpression(value)
|
||||
assignFromEvalResult(assign.target)
|
||||
}
|
||||
is BinaryExpression -> {
|
||||
asmgen.translateExpression(assign.value as BinaryExpression)
|
||||
asmgen.translateExpression(value)
|
||||
assignFromEvalResult(assign.target)
|
||||
}
|
||||
is ArrayIndexedExpression -> {
|
||||
val arrayExpr = assign.value as ArrayIndexedExpression
|
||||
val arrayDt = arrayExpr.identifier.inferType(program).typeOrElse(DataType.STRUCT)
|
||||
val index = arrayExpr.arrayspec.index
|
||||
val arrayDt = value.identifier.inferType(program).typeOrElse(DataType.STRUCT)
|
||||
val index = value.arrayspec.index
|
||||
if (index is NumericLiteralValue) {
|
||||
// constant array index value
|
||||
val arrayVarName = asmgen.asmIdentifierName(arrayExpr.identifier)
|
||||
val arrayVarName = asmgen.asmIdentifierName(value.identifier)
|
||||
val indexValue = index.number.toInt() * ArrayElementTypes.getValue(arrayDt).memorySize()
|
||||
when (arrayDt) {
|
||||
DataType.STR, DataType.ARRAY_UB, DataType.ARRAY_B ->
|
||||
@ -129,83 +112,79 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
||||
throw AssemblyError("weird array type")
|
||||
}
|
||||
} else {
|
||||
asmgen.translateArrayIndexIntoA(arrayExpr)
|
||||
asmgen.readAndPushArrayvalueWithIndexA(arrayDt, arrayExpr.identifier)
|
||||
asmgen.translateArrayIndexIntoA(value)
|
||||
asmgen.readAndPushArrayvalueWithIndexA(arrayDt, value.identifier)
|
||||
}
|
||||
assignFromEvalResult(assign.target)
|
||||
}
|
||||
is TypecastExpression -> {
|
||||
val cast = assign.value as TypecastExpression
|
||||
val sourceType = cast.expression.inferType(program)
|
||||
val sourceType = value.expression.inferType(program)
|
||||
if (sourceType.isKnown &&
|
||||
(sourceType.typeOrElse(DataType.STRUCT) in ByteDatatypes && cast.type in ByteDatatypes) ||
|
||||
(sourceType.typeOrElse(DataType.STRUCT) in WordDatatypes && cast.type in WordDatatypes)) {
|
||||
(sourceType.typeOrElse(DataType.STRUCT) in ByteDatatypes && value.type in ByteDatatypes) ||
|
||||
(sourceType.typeOrElse(DataType.STRUCT) in WordDatatypes && value.type in WordDatatypes)) {
|
||||
// no need for a type cast
|
||||
assign.value = cast.expression
|
||||
translate(assign)
|
||||
TODO("no typecast $value")
|
||||
// value = value.expression
|
||||
// val newAssign = AsmAssignment(assign.source, assign.target, assign.isAugmentable, assign.position)
|
||||
// translate(newAssign)
|
||||
} else {
|
||||
asmgen.translateExpression(assign.value as TypecastExpression)
|
||||
asmgen.translateExpression(value)
|
||||
assignFromEvalResult(assign.target)
|
||||
}
|
||||
}
|
||||
is FunctionCall -> {
|
||||
asmgen.translateExpression(assign.value as FunctionCall)
|
||||
asmgen.translateExpression(value)
|
||||
assignFromEvalResult(assign.target)
|
||||
}
|
||||
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}")
|
||||
else -> throw AssemblyError("assignment value type ${assign.value} should have been handled elsewhere")
|
||||
is RangeExpr -> throw AssemblyError("range expression should have been changed into array values ${value.position}")
|
||||
else -> throw AssemblyError("assignment value type $value should have been handled elsewhere")
|
||||
}
|
||||
}
|
||||
|
||||
private fun assignFromEvalResult(target: AssignTarget) {
|
||||
val targetIdent = target.identifier
|
||||
val targetArrayIdx = target.arrayindexed
|
||||
val targetMemory = target.memoryAddress
|
||||
when {
|
||||
targetIdent != null -> {
|
||||
val targetName = asmgen.asmIdentifierName(targetIdent)
|
||||
when (val targetDt = targetIdent.inferType(program).typeOrElse(DataType.STRUCT)) {
|
||||
private fun assignFromEvalResult(target: AsmAssignTarget) {
|
||||
when(target.type) {
|
||||
AsmTargetStorageType.VARIABLE -> {
|
||||
when (target.datatype) {
|
||||
DataType.UBYTE, DataType.BYTE -> {
|
||||
asmgen.out(" inx | lda $ESTACK_LO_HEX,x | sta $targetName")
|
||||
asmgen.out(" inx | lda $ESTACK_LO_HEX,x | sta ${target.asmName}")
|
||||
}
|
||||
DataType.UWORD, DataType.WORD -> {
|
||||
asmgen.out("""
|
||||
inx
|
||||
lda $ESTACK_LO_HEX,x
|
||||
sta $targetName
|
||||
sta ${target.asmName}
|
||||
lda $ESTACK_HI_HEX,x
|
||||
sta $targetName+1
|
||||
sta ${target.asmName}+1
|
||||
""")
|
||||
}
|
||||
DataType.FLOAT -> {
|
||||
asmgen.out("""
|
||||
lda #<$targetName
|
||||
ldy #>$targetName
|
||||
lda #<${target.asmName}
|
||||
ldy #>${target.asmName}
|
||||
jsr c64flt.pop_float
|
||||
""")
|
||||
}
|
||||
else -> throw AssemblyError("weird target variable type $targetDt")
|
||||
else -> throw AssemblyError("weird target variable type ${target.datatype}")
|
||||
}
|
||||
}
|
||||
targetMemory != null -> {
|
||||
AsmTargetStorageType.MEMORY -> {
|
||||
asmgen.out(" inx")
|
||||
storeByteViaRegisterAInMemoryAddress("$ESTACK_LO_HEX,x", targetMemory)
|
||||
storeByteViaRegisterAInMemoryAddress("$ESTACK_LO_HEX,x", target.astMemory!!)
|
||||
}
|
||||
targetArrayIdx != null -> {
|
||||
AsmTargetStorageType.ARRAY -> {
|
||||
val targetArrayIdx = target.astArray!!
|
||||
val arrayDt = targetArrayIdx.identifier.inferType(program).typeOrElse(DataType.STRUCT)
|
||||
val arrayVarName = asmgen.asmIdentifierName(targetArrayIdx.identifier)
|
||||
asmgen.translateExpression(targetArrayIdx.arrayspec.index)
|
||||
asmgen.out(" inx | lda $ESTACK_LO_HEX,x")
|
||||
popAndWriteArrayvalueWithIndexA(arrayDt, arrayVarName)
|
||||
popAndWriteArrayvalueWithIndexA(arrayDt, target.asmName)
|
||||
}
|
||||
else -> throw AssemblyError("weird assignment target $target")
|
||||
AsmTargetStorageType.REGISTER -> TODO()
|
||||
AsmTargetStorageType.STACK -> TODO()
|
||||
}
|
||||
}
|
||||
|
||||
private fun assignFromAddressOf(target: AssignTarget, name: IdentifierReference) {
|
||||
val targetIdent = target.identifier
|
||||
val targetArrayIdx = target.arrayindexed
|
||||
private fun assignFromAddressOf(target: AsmAssignTarget, name: IdentifierReference) {
|
||||
val struct = name.memberOfStruct(program.namespace)
|
||||
val sourceName = if (struct != null) {
|
||||
// take the address of the first struct member instead
|
||||
@ -219,81 +198,76 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
||||
asmgen.fixNameSymbols(name.nameInSource.joinToString("."))
|
||||
}
|
||||
|
||||
when {
|
||||
targetIdent != null -> {
|
||||
val targetName = asmgen.asmIdentifierName(targetIdent)
|
||||
when(target.type) {
|
||||
AsmTargetStorageType.VARIABLE -> {
|
||||
asmgen.out("""
|
||||
lda #<$sourceName
|
||||
ldy #>$sourceName
|
||||
sta $targetName
|
||||
sty $targetName+1
|
||||
sta ${target.asmName}
|
||||
sty ${target.asmName}+1
|
||||
""")
|
||||
}
|
||||
target.memoryAddress != null -> {
|
||||
AsmTargetStorageType.MEMORY -> {
|
||||
throw AssemblyError("no asm gen for assign address $sourceName to memory word $target")
|
||||
}
|
||||
targetArrayIdx != null -> {
|
||||
AsmTargetStorageType.ARRAY -> {
|
||||
val targetArrayIdx = target.astArray!!
|
||||
val index = targetArrayIdx.arrayspec.index
|
||||
val targetName = asmgen.asmIdentifierName(targetArrayIdx.identifier)
|
||||
throw AssemblyError("no asm gen for assign address $sourceName to array $targetName [ $index ]")
|
||||
throw AssemblyError("no asm gen for assign address $sourceName to array ${target.asmName} [ $index ]")
|
||||
}
|
||||
else -> throw AssemblyError("no asm gen for assign address $sourceName to $target")
|
||||
AsmTargetStorageType.REGISTER -> TODO()
|
||||
AsmTargetStorageType.STACK -> TODO()
|
||||
}
|
||||
}
|
||||
|
||||
private fun assignFromWordVariable(target: AssignTarget, variable: IdentifierReference) {
|
||||
private fun assignFromWordVariable(target: AsmAssignTarget, variable: IdentifierReference) {
|
||||
val sourceName = asmgen.asmIdentifierName(variable)
|
||||
val targetIdent = target.identifier
|
||||
val targetArrayIdx = target.arrayindexed
|
||||
when {
|
||||
targetIdent != null -> {
|
||||
val targetName = asmgen.asmIdentifierName(targetIdent)
|
||||
when(target.type) {
|
||||
AsmTargetStorageType.VARIABLE -> {
|
||||
asmgen.out("""
|
||||
lda $sourceName
|
||||
ldy $sourceName+1
|
||||
sta $targetName
|
||||
sty $targetName+1
|
||||
sta ${target.asmName}
|
||||
sty ${target.asmName}+1
|
||||
""")
|
||||
}
|
||||
target.memoryAddress != null -> {
|
||||
throw AssemblyError("no asm gen for assign wordvar $sourceName to memory ${target.memoryAddress}")
|
||||
AsmTargetStorageType.MEMORY -> {
|
||||
throw AssemblyError("no asm gen for assign wordvar $sourceName to memory ${target.astMemory}")
|
||||
}
|
||||
targetArrayIdx != null -> {
|
||||
AsmTargetStorageType.ARRAY -> {
|
||||
val targetArrayIdx = target.astArray!!
|
||||
val index = targetArrayIdx.arrayspec.index
|
||||
val targetName = asmgen.asmIdentifierName(targetArrayIdx.identifier)
|
||||
asmgen.out(" lda $sourceName | sta $ESTACK_LO_HEX,x | lda $sourceName+1 | sta $ESTACK_HI_HEX,x | dex")
|
||||
asmgen.translateExpression(index)
|
||||
asmgen.out(" inx | lda $ESTACK_LO_HEX,x")
|
||||
val arrayDt = targetArrayIdx.identifier.inferType(program).typeOrElse(DataType.STRUCT)
|
||||
popAndWriteArrayvalueWithIndexA(arrayDt, targetName)
|
||||
popAndWriteArrayvalueWithIndexA(arrayDt, target.asmName)
|
||||
}
|
||||
else -> throw AssemblyError("no asm gen for assign wordvar to $target")
|
||||
AsmTargetStorageType.REGISTER -> TODO()
|
||||
AsmTargetStorageType.STACK -> TODO()
|
||||
}
|
||||
}
|
||||
|
||||
private fun assignFromFloatVariable(target: AssignTarget, variable: IdentifierReference) {
|
||||
private fun assignFromFloatVariable(target: AsmAssignTarget, variable: IdentifierReference) {
|
||||
val sourceName = asmgen.asmIdentifierName(variable)
|
||||
val targetIdent = target.identifier
|
||||
val targetArrayIdx = target.arrayindexed
|
||||
when {
|
||||
targetIdent != null -> {
|
||||
val targetName = asmgen.asmIdentifierName(targetIdent)
|
||||
when(target.type) {
|
||||
AsmTargetStorageType.VARIABLE -> {
|
||||
asmgen.out("""
|
||||
lda $sourceName
|
||||
sta $targetName
|
||||
sta ${target.asmName}
|
||||
lda $sourceName+1
|
||||
sta $targetName+1
|
||||
sta ${target.asmName}+1
|
||||
lda $sourceName+2
|
||||
sta $targetName+2
|
||||
sta ${target.asmName}+2
|
||||
lda $sourceName+3
|
||||
sta $targetName+3
|
||||
sta ${target.asmName}+3
|
||||
lda $sourceName+4
|
||||
sta $targetName+4
|
||||
sta ${target.asmName}+4
|
||||
""")
|
||||
}
|
||||
targetArrayIdx != null -> {
|
||||
val index = targetArrayIdx.arrayspec.index
|
||||
val targetName = asmgen.asmIdentifierName(targetArrayIdx.identifier)
|
||||
AsmTargetStorageType.ARRAY -> {
|
||||
val index = target.astArray!!.arrayspec.index
|
||||
val targetName = asmgen.asmIdentifierName(target.astArray.identifier)
|
||||
asmgen.out(" lda #<$sourceName | ldy #>$sourceName | jsr c64flt.push_float")
|
||||
asmgen.translateExpression(index)
|
||||
asmgen.out(" lda #<$targetName | ldy #>$targetName | jsr c64flt.pop_float_to_indexed_var")
|
||||
@ -302,56 +276,50 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
||||
}
|
||||
}
|
||||
|
||||
private fun assignFromByteVariable(target: AssignTarget, variable: IdentifierReference) {
|
||||
private fun assignFromByteVariable(target: AsmAssignTarget, variable: IdentifierReference) {
|
||||
val sourceName = asmgen.asmIdentifierName(variable)
|
||||
val targetIdent = target.identifier
|
||||
val targetArrayIdx = target.arrayindexed
|
||||
val targetMemory = target.memoryAddress
|
||||
when {
|
||||
targetIdent != null -> {
|
||||
val targetName = asmgen.asmIdentifierName(targetIdent)
|
||||
when(target.type) {
|
||||
AsmTargetStorageType.VARIABLE -> {
|
||||
asmgen.out("""
|
||||
lda $sourceName
|
||||
sta $targetName
|
||||
sta ${target.asmName}
|
||||
""")
|
||||
}
|
||||
targetMemory != null -> {
|
||||
storeByteViaRegisterAInMemoryAddress(sourceName, targetMemory)
|
||||
AsmTargetStorageType.MEMORY -> {
|
||||
storeByteViaRegisterAInMemoryAddress(sourceName, target.astMemory!!)
|
||||
}
|
||||
targetArrayIdx != null -> {
|
||||
AsmTargetStorageType.ARRAY -> {
|
||||
val targetArrayIdx = target.astArray!!
|
||||
val index = targetArrayIdx.arrayspec.index
|
||||
val targetName = asmgen.asmIdentifierName(targetArrayIdx.identifier)
|
||||
val arrayDt = targetArrayIdx.identifier.inferType(program).typeOrElse(DataType.STRUCT)
|
||||
asmgen.out(" lda $sourceName | sta $ESTACK_LO_HEX,x | dex")
|
||||
asmgen.translateExpression(index)
|
||||
asmgen.out(" inx | lda $ESTACK_LO_HEX,x")
|
||||
popAndWriteArrayvalueWithIndexA(arrayDt, targetName)
|
||||
popAndWriteArrayvalueWithIndexA(arrayDt, target.asmName)
|
||||
}
|
||||
else -> throw AssemblyError("no asm gen for assign bytevar to $target")
|
||||
AsmTargetStorageType.REGISTER -> TODO()
|
||||
AsmTargetStorageType.STACK -> TODO()
|
||||
}
|
||||
}
|
||||
|
||||
private fun assignFromRegister(target: AssignTarget, register: CpuRegister) {
|
||||
val targetIdent = target.identifier
|
||||
val targetArrayIdx = target.arrayindexed
|
||||
when {
|
||||
targetIdent != null -> {
|
||||
val targetName = asmgen.asmIdentifierName(targetIdent)
|
||||
asmgen.out(" st${register.name.toLowerCase()} $targetName")
|
||||
private fun assignFromRegister(target: AsmAssignTarget, register: CpuRegister) {
|
||||
when(target.type) {
|
||||
AsmTargetStorageType.VARIABLE -> {
|
||||
asmgen.out(" st${register.name.toLowerCase()} ${target.asmName}")
|
||||
}
|
||||
target.memoryAddress != null -> {
|
||||
storeRegisterInMemoryAddress(register, target.memoryAddress)
|
||||
AsmTargetStorageType.MEMORY -> {
|
||||
storeRegisterInMemoryAddress(register, target.astMemory!!)
|
||||
}
|
||||
targetArrayIdx != null -> {
|
||||
AsmTargetStorageType.ARRAY -> {
|
||||
val targetArrayIdx = target.astArray!!
|
||||
val index = targetArrayIdx.arrayspec.index
|
||||
val targetName = asmgen.asmIdentifierName(targetArrayIdx.identifier)
|
||||
when (index) {
|
||||
is NumericLiteralValue -> {
|
||||
val memindex = index.number.toInt()
|
||||
when (register) {
|
||||
CpuRegister.A -> asmgen.out(" sta $targetName+$memindex")
|
||||
CpuRegister.X -> asmgen.out(" stx $targetName+$memindex")
|
||||
CpuRegister.Y -> asmgen.out(" sty $targetName+$memindex")
|
||||
CpuRegister.A -> asmgen.out(" sta ${target.asmName}+$memindex")
|
||||
CpuRegister.X -> asmgen.out(" stx ${target.asmName}+$memindex")
|
||||
CpuRegister.Y -> asmgen.out(" sty ${target.asmName}+$memindex")
|
||||
}
|
||||
}
|
||||
is IdentifierReference -> {
|
||||
@ -364,7 +332,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
||||
lda ${asmgen.asmIdentifierName(index)}
|
||||
tay
|
||||
lda ${C64Zeropage.SCRATCH_B1}
|
||||
sta $targetName,y
|
||||
sta ${target.asmName},y
|
||||
""")
|
||||
}
|
||||
else -> {
|
||||
@ -381,12 +349,13 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
||||
lda $ESTACK_LO_HEX,x
|
||||
tay
|
||||
lda ${C64Zeropage.SCRATCH_B1}
|
||||
sta $targetName,y
|
||||
sta ${target.asmName},y
|
||||
""")
|
||||
}
|
||||
}
|
||||
}
|
||||
else -> throw AssemblyError("no asm gen for assign register $register to $target")
|
||||
AsmTargetStorageType.REGISTER -> TODO()
|
||||
AsmTargetStorageType.STACK -> TODO()
|
||||
}
|
||||
}
|
||||
|
||||
@ -463,34 +432,31 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
||||
}
|
||||
}
|
||||
|
||||
private fun assignFromWordConstant(target: AssignTarget, word: Int) {
|
||||
val targetIdent = target.identifier
|
||||
val targetArrayIdx = target.arrayindexed
|
||||
when {
|
||||
targetIdent != null -> {
|
||||
val targetName = asmgen.asmIdentifierName(targetIdent)
|
||||
private fun assignFromWordConstant(target: AsmAssignTarget, word: Int) {
|
||||
when(target.type) {
|
||||
AsmTargetStorageType.VARIABLE -> {
|
||||
if (word ushr 8 == word and 255) {
|
||||
// lsb=msb
|
||||
asmgen.out("""
|
||||
lda #${(word and 255).toHex()}
|
||||
sta $targetName
|
||||
sta $targetName+1
|
||||
sta ${target.asmName}
|
||||
sta ${target.asmName}+1
|
||||
""")
|
||||
} else {
|
||||
asmgen.out("""
|
||||
lda #<${word.toHex()}
|
||||
ldy #>${word.toHex()}
|
||||
sta $targetName
|
||||
sty $targetName+1
|
||||
sta ${target.asmName}
|
||||
sty ${target.asmName}+1
|
||||
""")
|
||||
}
|
||||
}
|
||||
target.memoryAddress != null -> {
|
||||
throw AssemblyError("no asm gen for assign word $word to memory ${target.memoryAddress}")
|
||||
AsmTargetStorageType.MEMORY -> {
|
||||
throw AssemblyError("no asm gen for assign word $word to memory ${target.astMemory}")
|
||||
}
|
||||
targetArrayIdx != null -> {
|
||||
val index = targetArrayIdx.arrayspec.index
|
||||
val targetName = asmgen.asmIdentifierName(targetArrayIdx.identifier)
|
||||
AsmTargetStorageType.ARRAY -> {
|
||||
val index = target.astArray!!.arrayspec.index
|
||||
val targetName = asmgen.asmIdentifierName(target.astArray.identifier)
|
||||
asmgen.translateExpression(index)
|
||||
asmgen.out("""
|
||||
inx
|
||||
@ -503,25 +469,22 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
||||
sta $targetName+1,y
|
||||
""")
|
||||
}
|
||||
else -> throw AssemblyError("no asm gen for assign word $word to $target")
|
||||
AsmTargetStorageType.REGISTER -> TODO()
|
||||
AsmTargetStorageType.STACK -> TODO()
|
||||
}
|
||||
}
|
||||
|
||||
private fun assignFromByteConstant(target: AssignTarget, byte: Short) {
|
||||
val targetIdent = target.identifier
|
||||
val targetArrayIdx = target.arrayindexed
|
||||
val targetMemory = target.memoryAddress
|
||||
when {
|
||||
targetIdent != null -> {
|
||||
val targetName = asmgen.asmIdentifierName(targetIdent)
|
||||
asmgen.out(" lda #${byte.toHex()} | sta $targetName ")
|
||||
private fun assignFromByteConstant(target: AsmAssignTarget, byte: Short) {
|
||||
when(target.type) {
|
||||
AsmTargetStorageType.VARIABLE -> {
|
||||
asmgen.out(" lda #${byte.toHex()} | sta ${target.asmName} ")
|
||||
}
|
||||
targetMemory != null -> {
|
||||
storeByteViaRegisterAInMemoryAddress("#${byte.toHex()}", targetMemory)
|
||||
AsmTargetStorageType.MEMORY -> {
|
||||
storeByteViaRegisterAInMemoryAddress("#${byte.toHex()}", target.astMemory!!)
|
||||
}
|
||||
targetArrayIdx != null -> {
|
||||
val index = targetArrayIdx.arrayspec.index
|
||||
val targetName = asmgen.asmIdentifierName(targetArrayIdx.identifier)
|
||||
AsmTargetStorageType.ARRAY -> {
|
||||
val index = target.astArray!!.arrayspec.index
|
||||
val targetName = asmgen.asmIdentifierName(target.astArray.identifier)
|
||||
asmgen.translateExpression(index)
|
||||
asmgen.out("""
|
||||
inx
|
||||
@ -534,42 +497,38 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
||||
}
|
||||
}
|
||||
|
||||
private fun assignFromFloatConstant(target: AssignTarget, float: Double) {
|
||||
val targetIdent = target.identifier
|
||||
val targetArrayIdx = target.arrayindexed
|
||||
private fun assignFromFloatConstant(target: AsmAssignTarget, float: Double) {
|
||||
if (float == 0.0) {
|
||||
// optimized case for float zero
|
||||
when {
|
||||
targetIdent != null -> {
|
||||
val targetName = asmgen.asmIdentifierName(targetIdent)
|
||||
when(target.type) {
|
||||
AsmTargetStorageType.VARIABLE -> {
|
||||
asmgen.out("""
|
||||
lda #0
|
||||
sta $targetName
|
||||
sta $targetName+1
|
||||
sta $targetName+2
|
||||
sta $targetName+3
|
||||
sta $targetName+4
|
||||
sta ${target.asmName}
|
||||
sta ${target.asmName}+1
|
||||
sta ${target.asmName}+2
|
||||
sta ${target.asmName}+3
|
||||
sta ${target.asmName}+4
|
||||
""")
|
||||
}
|
||||
targetArrayIdx != null -> {
|
||||
val index = targetArrayIdx.arrayspec.index
|
||||
val targetName = asmgen.asmIdentifierName(targetArrayIdx.identifier)
|
||||
AsmTargetStorageType.ARRAY -> {
|
||||
val index = target.astArray!!.arrayspec.index
|
||||
if (index is NumericLiteralValue) {
|
||||
val indexValue = index.number.toInt() * C64MachineDefinition.FLOAT_MEM_SIZE
|
||||
asmgen.out("""
|
||||
lda #0
|
||||
sta $targetName+$indexValue
|
||||
sta $targetName+$indexValue+1
|
||||
sta $targetName+$indexValue+2
|
||||
sta $targetName+$indexValue+3
|
||||
sta $targetName+$indexValue+4
|
||||
sta ${target.asmName}+$indexValue
|
||||
sta ${target.asmName}+$indexValue+1
|
||||
sta ${target.asmName}+$indexValue+2
|
||||
sta ${target.asmName}+$indexValue+3
|
||||
sta ${target.asmName}+$indexValue+4
|
||||
""")
|
||||
} else {
|
||||
asmgen.translateExpression(index)
|
||||
asmgen.out("""
|
||||
lda #<${targetName}
|
||||
lda #<${target.asmName}
|
||||
sta ${C64Zeropage.SCRATCH_W1}
|
||||
lda #>${targetName}
|
||||
lda #>${target.asmName}
|
||||
sta ${C64Zeropage.SCRATCH_W1 + 1}
|
||||
jsr c64flt.set_0_array_float
|
||||
""")
|
||||
@ -580,25 +539,24 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
||||
} else {
|
||||
// non-zero value
|
||||
val constFloat = asmgen.getFloatConst(float)
|
||||
when {
|
||||
targetIdent != null -> {
|
||||
val targetName = asmgen.asmIdentifierName(targetIdent)
|
||||
when(target.type) {
|
||||
AsmTargetStorageType.VARIABLE -> {
|
||||
asmgen.out("""
|
||||
lda $constFloat
|
||||
sta $targetName
|
||||
sta ${target.asmName}
|
||||
lda $constFloat+1
|
||||
sta $targetName+1
|
||||
sta ${target.asmName}+1
|
||||
lda $constFloat+2
|
||||
sta $targetName+2
|
||||
sta ${target.asmName}+2
|
||||
lda $constFloat+3
|
||||
sta $targetName+3
|
||||
sta ${target.asmName}+3
|
||||
lda $constFloat+4
|
||||
sta $targetName+4
|
||||
sta ${target.asmName}+4
|
||||
""")
|
||||
}
|
||||
targetArrayIdx != null -> {
|
||||
val index = targetArrayIdx.arrayspec.index
|
||||
val arrayVarName = asmgen.asmIdentifierName(targetArrayIdx.identifier)
|
||||
AsmTargetStorageType.ARRAY -> {
|
||||
val index = target.astArray!!.arrayspec.index
|
||||
val arrayVarName = asmgen.asmIdentifierName(target.astArray.identifier)
|
||||
if (index is NumericLiteralValue) {
|
||||
val indexValue = index.number.toInt() * C64MachineDefinition.FLOAT_MEM_SIZE
|
||||
asmgen.out("""
|
||||
@ -633,34 +591,30 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
||||
}
|
||||
}
|
||||
|
||||
private fun assignFromMemoryByte(target: AssignTarget, address: Int?, identifier: IdentifierReference?) {
|
||||
val targetIdent = target.identifier
|
||||
val targetArrayIdx = target.arrayindexed
|
||||
val targetMemory = target.memoryAddress
|
||||
private fun assignFromMemoryByte(target: AsmAssignTarget, address: Int?, identifier: IdentifierReference?) {
|
||||
if (address != null) {
|
||||
when {
|
||||
targetIdent != null -> {
|
||||
val targetName = asmgen.asmIdentifierName(targetIdent)
|
||||
when(target.type) {
|
||||
AsmTargetStorageType.VARIABLE -> {
|
||||
asmgen.out("""
|
||||
lda ${address.toHex()}
|
||||
sta $targetName
|
||||
sta ${target.asmName}
|
||||
""")
|
||||
}
|
||||
targetMemory != null -> {
|
||||
storeByteViaRegisterAInMemoryAddress(address.toHex(), targetMemory)
|
||||
AsmTargetStorageType.MEMORY -> {
|
||||
storeByteViaRegisterAInMemoryAddress(address.toHex(), target.astMemory!!)
|
||||
}
|
||||
targetArrayIdx != null -> {
|
||||
val index = targetArrayIdx.arrayspec.index
|
||||
val targetName = asmgen.asmIdentifierName(targetArrayIdx.identifier)
|
||||
AsmTargetStorageType.ARRAY -> {
|
||||
val index = target.astArray!!.arrayspec.index
|
||||
val targetName = asmgen.asmIdentifierName(target.astArray.identifier)
|
||||
throw AssemblyError("no asm gen for assign memory byte at $address to array $targetName [ $index ]")
|
||||
}
|
||||
else -> throw AssemblyError("no asm gen for assign memory byte $target")
|
||||
AsmTargetStorageType.REGISTER -> TODO()
|
||||
AsmTargetStorageType.STACK -> TODO()
|
||||
}
|
||||
} else if (identifier != null) {
|
||||
val sourceName = asmgen.asmIdentifierName(identifier)
|
||||
when {
|
||||
targetIdent != null -> {
|
||||
val targetName = asmgen.asmIdentifierName(targetIdent)
|
||||
when(target.type) {
|
||||
AsmTargetStorageType.VARIABLE -> {
|
||||
asmgen.out("""
|
||||
lda $sourceName
|
||||
sta ${C64Zeropage.SCRATCH_W1}
|
||||
@ -668,14 +622,14 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
||||
sta ${C64Zeropage.SCRATCH_W1+1}
|
||||
ldy #0
|
||||
lda (${C64Zeropage.SCRATCH_W1}),y
|
||||
sta $targetName""")
|
||||
sta ${target.asmName}""")
|
||||
}
|
||||
targetMemory != null -> {
|
||||
storeByteViaRegisterAInMemoryAddress(sourceName, targetMemory)
|
||||
AsmTargetStorageType.MEMORY -> {
|
||||
storeByteViaRegisterAInMemoryAddress(sourceName, target.astMemory!!)
|
||||
}
|
||||
targetArrayIdx != null -> {
|
||||
val index = targetArrayIdx.arrayspec.index
|
||||
val targetName = asmgen.asmIdentifierName(targetArrayIdx.identifier)
|
||||
AsmTargetStorageType.ARRAY -> {
|
||||
val index = target.astArray!!.arrayspec.index
|
||||
val targetName = asmgen.asmIdentifierName(target.astArray.identifier)
|
||||
throw AssemblyError("no asm gen for assign memory byte $sourceName to array $targetName [ $index ]")
|
||||
}
|
||||
else -> throw AssemblyError("no asm gen for assign memory byte $target")
|
||||
|
@ -3,8 +3,6 @@ package prog8.compiler.target.c64.codegen
|
||||
import prog8.ast.Program
|
||||
import prog8.ast.base.*
|
||||
import prog8.ast.expressions.*
|
||||
import prog8.ast.statements.AssignTarget
|
||||
import prog8.ast.statements.Assignment
|
||||
import prog8.compiler.AssemblyError
|
||||
import prog8.compiler.target.c64.C64MachineDefinition.C64Zeropage
|
||||
import prog8.compiler.target.c64.C64MachineDefinition.ESTACK_HI_PLUS1_HEX
|
||||
@ -14,15 +12,16 @@ import prog8.compiler.toHex
|
||||
internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
private val assignmentAsmGen: AssignmentAsmGen,
|
||||
private val asmgen: AsmGen) {
|
||||
fun translate(assign: Assignment) {
|
||||
fun translate(assign: AsmAssignment) {
|
||||
require(assign.isAugmentable)
|
||||
require(assign.source.type==AsmSourceStorageType.EXPRESSION)
|
||||
|
||||
when (assign.value) {
|
||||
val value = assign.source.astExpression!!
|
||||
when (value) {
|
||||
is PrefixExpression -> {
|
||||
// A = -A , A = +A, A = ~A, A = not A
|
||||
val px = assign.value as PrefixExpression
|
||||
val type = px.inferType(program).typeOrElse(DataType.STRUCT)
|
||||
when (px.operator) {
|
||||
val type = value.inferType(program).typeOrElse(DataType.STRUCT)
|
||||
when (value.operator) {
|
||||
"+" -> {
|
||||
}
|
||||
"-" -> inplaceNegate(assign.target, type)
|
||||
@ -31,44 +30,45 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
else -> throw AssemblyError("invalid prefix operator")
|
||||
}
|
||||
}
|
||||
is TypecastExpression -> inplaceCast(assign.target, assign.value as TypecastExpression, assign)
|
||||
is BinaryExpression -> inplaceBinary(assign.target, assign.value as BinaryExpression, assign)
|
||||
is TypecastExpression -> inplaceCast(assign.target, value, assign.position)
|
||||
is BinaryExpression -> inplaceBinary(assign.target, value)
|
||||
else -> throw AssemblyError("invalid aug assign value type")
|
||||
}
|
||||
}
|
||||
|
||||
private fun inplaceBinary(target: AssignTarget, binExpr: BinaryExpression, assign: Assignment) {
|
||||
if (binExpr.left isSameAs target) {
|
||||
private fun inplaceBinary(target: AsmAssignTarget, binExpr: BinaryExpression) {
|
||||
val astTarget = target.origAstTarget!!
|
||||
if (binExpr.left isSameAs astTarget) {
|
||||
// A = A <operator> Something
|
||||
return inplaceModification(target, binExpr.operator, binExpr.right, assign)
|
||||
return inplaceModification(target, binExpr.operator, binExpr.right)
|
||||
}
|
||||
|
||||
if (binExpr.operator in associativeOperators) {
|
||||
if (binExpr.right isSameAs target) {
|
||||
if (binExpr.right isSameAs astTarget) {
|
||||
// A = 5 <operator> A
|
||||
return inplaceModification(target, binExpr.operator, binExpr.left, assign)
|
||||
return inplaceModification(target, binExpr.operator, binExpr.left)
|
||||
}
|
||||
|
||||
val leftBinExpr = binExpr.left as? BinaryExpression
|
||||
if (leftBinExpr?.operator == binExpr.operator) {
|
||||
// TODO better optimize the chained asm to avoid intermediate stores/loads?
|
||||
when {
|
||||
binExpr.right isSameAs target -> {
|
||||
binExpr.right isSameAs astTarget -> {
|
||||
// A = (x <associative-operator> y) <same-operator> A
|
||||
inplaceModification(target, binExpr.operator, leftBinExpr.left, assign)
|
||||
inplaceModification(target, binExpr.operator, leftBinExpr.right, assign)
|
||||
inplaceModification(target, binExpr.operator, leftBinExpr.left)
|
||||
inplaceModification(target, binExpr.operator, leftBinExpr.right)
|
||||
return
|
||||
}
|
||||
leftBinExpr.left isSameAs target -> {
|
||||
leftBinExpr.left isSameAs astTarget -> {
|
||||
// A = (A <associative-operator> x) <same-operator> y
|
||||
inplaceModification(target, binExpr.operator, leftBinExpr.right, assign)
|
||||
inplaceModification(target, binExpr.operator, binExpr.right, assign)
|
||||
inplaceModification(target, binExpr.operator, leftBinExpr.right)
|
||||
inplaceModification(target, binExpr.operator, binExpr.right)
|
||||
return
|
||||
}
|
||||
leftBinExpr.right isSameAs target -> {
|
||||
leftBinExpr.right isSameAs astTarget -> {
|
||||
// A = (x <associative-operator> A) <same-operator> y
|
||||
inplaceModification(target, binExpr.operator, leftBinExpr.left, assign)
|
||||
inplaceModification(target, binExpr.operator, binExpr.right, assign)
|
||||
inplaceModification(target, binExpr.operator, leftBinExpr.left)
|
||||
inplaceModification(target, binExpr.operator, binExpr.right)
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -76,59 +76,54 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
val rightBinExpr = binExpr.right as? BinaryExpression
|
||||
if (rightBinExpr?.operator == binExpr.operator) {
|
||||
when {
|
||||
binExpr.left isSameAs target -> {
|
||||
binExpr.left isSameAs astTarget -> {
|
||||
// A = A <associative-operator> (x <same-operator> y)
|
||||
inplaceModification(target, binExpr.operator, rightBinExpr.left, assign)
|
||||
inplaceModification(target, binExpr.operator, rightBinExpr.right, assign)
|
||||
inplaceModification(target, binExpr.operator, rightBinExpr.left)
|
||||
inplaceModification(target, binExpr.operator, rightBinExpr.right)
|
||||
return
|
||||
}
|
||||
rightBinExpr.left isSameAs target -> {
|
||||
rightBinExpr.left isSameAs astTarget -> {
|
||||
// A = y <associative-operator> (A <same-operator> x)
|
||||
inplaceModification(target, binExpr.operator, binExpr.left, assign)
|
||||
inplaceModification(target, binExpr.operator, rightBinExpr.right, assign)
|
||||
inplaceModification(target, binExpr.operator, binExpr.left)
|
||||
inplaceModification(target, binExpr.operator, rightBinExpr.right)
|
||||
return
|
||||
}
|
||||
rightBinExpr.right isSameAs target -> {
|
||||
rightBinExpr.right isSameAs astTarget -> {
|
||||
// A = y <associative-operator> (x <same-operator> y)
|
||||
inplaceModification(target, binExpr.operator, binExpr.left, assign)
|
||||
inplaceModification(target, binExpr.operator, rightBinExpr.left, assign)
|
||||
inplaceModification(target, binExpr.operator, binExpr.left)
|
||||
inplaceModification(target, binExpr.operator, rightBinExpr.left)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw FatalAstException("assignment should be augmentable $assign\nleft=${binExpr.left}\nright=${binExpr.right}")
|
||||
throw FatalAstException("assignment should be augmentable $binExpr")
|
||||
}
|
||||
|
||||
private fun inplaceModification(target: AssignTarget, operator: String, value: Expression, origAssign: Assignment) {
|
||||
val arrayIdx = target.arrayindexed
|
||||
val identifier = target.identifier
|
||||
val memory = target.memoryAddress
|
||||
private fun inplaceModification(target: AsmAssignTarget, operator: String, value: Expression) {
|
||||
val valueLv = (value as? NumericLiteralValue)?.number
|
||||
val ident = value as? IdentifierReference
|
||||
|
||||
when {
|
||||
identifier != null -> {
|
||||
val name = asmgen.asmIdentifierName(identifier)
|
||||
val dt = identifier.inferType(program).typeOrElse(DataType.STRUCT)
|
||||
when (dt) {
|
||||
when(target.type) {
|
||||
AsmTargetStorageType.VARIABLE -> {
|
||||
when (target.datatype) {
|
||||
in ByteDatatypes -> {
|
||||
when {
|
||||
valueLv != null -> inplaceModification_byte_litval_to_variable(name, dt, operator, valueLv.toInt())
|
||||
ident != null -> inplaceModification_byte_variable_to_variable(name, dt, operator, ident)
|
||||
valueLv != null -> inplaceModification_byte_litval_to_variable(target.asmName, target.datatype, operator, valueLv.toInt())
|
||||
ident != null -> inplaceModification_byte_variable_to_variable(target.asmName, target.datatype, operator, ident)
|
||||
// TODO more specialized code for types such as memory read etc.
|
||||
value is TypecastExpression -> {
|
||||
if (tryRemoveRedundantCast(value, target, operator, origAssign)) return
|
||||
inplaceModification_byte_value_to_variable(name, dt, operator, value)
|
||||
if (tryRemoveRedundantCast(value, target, operator)) return
|
||||
inplaceModification_byte_value_to_variable(target.asmName, target.datatype, operator, value)
|
||||
}
|
||||
else -> inplaceModification_byte_value_to_variable(name, dt, operator, value)
|
||||
else -> inplaceModification_byte_value_to_variable(target.asmName, target.datatype, operator, value)
|
||||
}
|
||||
}
|
||||
in WordDatatypes -> {
|
||||
when {
|
||||
valueLv != null -> inplaceModification_word_litval_to_variable(name, dt, operator, valueLv.toInt())
|
||||
ident != null -> inplaceModification_word_variable_to_variable(name, dt, operator, ident)
|
||||
valueLv != null -> inplaceModification_word_litval_to_variable(target.asmName, target.datatype, operator, valueLv.toInt())
|
||||
ident != null -> inplaceModification_word_variable_to_variable(target.asmName, target.datatype, operator, ident)
|
||||
// TODO more specialized code for types such as memory read etc.
|
||||
// value is DirectMemoryRead -> {
|
||||
// println("warning: slow stack evaluation used (8): $name $operator= ${value::class.simpleName} at ${value.position}") // TODO
|
||||
@ -143,28 +138,29 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
// // TODO
|
||||
// }
|
||||
value is TypecastExpression -> {
|
||||
if (tryRemoveRedundantCast(value, target, operator, origAssign)) return
|
||||
inplaceModification_word_value_to_variable(name, dt, operator, value)
|
||||
if (tryRemoveRedundantCast(value, target, operator)) return
|
||||
inplaceModification_word_value_to_variable(target.asmName, target.datatype, operator, value)
|
||||
}
|
||||
else -> inplaceModification_word_value_to_variable(name, dt, operator, value)
|
||||
else -> inplaceModification_word_value_to_variable(target.asmName, target.datatype, operator, value)
|
||||
}
|
||||
}
|
||||
DataType.FLOAT -> {
|
||||
when {
|
||||
valueLv != null -> inplaceModification_float_litval_to_variable(name, operator, valueLv.toDouble())
|
||||
ident != null -> inplaceModification_float_variable_to_variable(name, operator, ident)
|
||||
valueLv != null -> inplaceModification_float_litval_to_variable(target.asmName, operator, valueLv.toDouble())
|
||||
ident != null -> inplaceModification_float_variable_to_variable(target.asmName, operator, ident)
|
||||
// TODO more specialized code for types such as memory read etc.
|
||||
value is TypecastExpression -> {
|
||||
if (tryRemoveRedundantCast(value, target, operator, origAssign)) return
|
||||
inplaceModification_float_value_to_variable(name, operator, value)
|
||||
if (tryRemoveRedundantCast(value, target, operator)) return
|
||||
inplaceModification_float_value_to_variable(target.asmName, operator, value)
|
||||
}
|
||||
else -> inplaceModification_float_value_to_variable(name, operator, value)
|
||||
else -> inplaceModification_float_value_to_variable(target.asmName, operator, value)
|
||||
}
|
||||
}
|
||||
else -> throw AssemblyError("weird type to do in-place modification on $dt")
|
||||
else -> throw AssemblyError("weird type to do in-place modification on ${target.datatype}")
|
||||
}
|
||||
}
|
||||
memory != null -> {
|
||||
AsmTargetStorageType.MEMORY -> {
|
||||
val memory = target.astMemory!!
|
||||
when (memory.addressExpression) {
|
||||
is NumericLiteralValue -> {
|
||||
val addr = (memory.addressExpression as NumericLiteralValue).number.toInt()
|
||||
@ -174,7 +170,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
ident != null -> inplaceModification_byte_variable_to_variable(addr.toHex(), DataType.UBYTE, operator, ident)
|
||||
// TODO more specialized code for types such as memory read etc.
|
||||
value is TypecastExpression -> {
|
||||
if (tryRemoveRedundantCast(value, target, operator, origAssign)) return
|
||||
if (tryRemoveRedundantCast(value, target, operator)) return
|
||||
inplaceModification_byte_value_to_variable(addr.toHex(), DataType.UBYTE, operator, value)
|
||||
}
|
||||
else -> inplaceModification_byte_value_to_variable(addr.toHex(), DataType.UBYTE, operator, value)
|
||||
@ -187,7 +183,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
ident != null -> inplaceModification_byte_variable_to_memory(name, operator, ident)
|
||||
// TODO more specialized code for types such as memory read etc.
|
||||
value is TypecastExpression -> {
|
||||
if (tryRemoveRedundantCast(value, target, operator, origAssign)) return
|
||||
if (tryRemoveRedundantCast(value, target, operator)) return
|
||||
inplaceModification_byte_value_to_memory(name, operator, value)
|
||||
}
|
||||
else -> inplaceModification_byte_value_to_memory(name, operator, value)
|
||||
@ -203,7 +199,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
ident != null -> inplaceModification_byte_variable_to_variable(C64Zeropage.SCRATCH_B1.toHex(), DataType.UBYTE, operator, ident)
|
||||
// TODO more specialized code for types such as memory read etc.
|
||||
value is TypecastExpression -> {
|
||||
if (tryRemoveRedundantCast(value, target, operator, origAssign)) return
|
||||
if (tryRemoveRedundantCast(value, target, operator)) return
|
||||
inplaceModification_byte_value_to_variable(C64Zeropage.SCRATCH_B1.toHex(), DataType.UBYTE, operator, value)
|
||||
}
|
||||
else -> inplaceModification_byte_value_to_variable(C64Zeropage.SCRATCH_B1.toHex(), DataType.UBYTE, operator, value)
|
||||
@ -212,20 +208,21 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
}
|
||||
}
|
||||
}
|
||||
arrayIdx != null -> {
|
||||
println("*** TODO optimize simple inplace array assignment $arrayIdx $operator= $value")
|
||||
assignmentAsmGen.translateOtherAssignment(origAssign) // TODO get rid of this fallback for the most common cases here
|
||||
AsmTargetStorageType.ARRAY -> {
|
||||
println("*** TODO optimize simple inplace array assignment ${target.astArray} $operator= $value")
|
||||
assignmentAsmGen.translateOtherAssignment(target.origAssign) // TODO get rid of this fallback for the most common cases here
|
||||
}
|
||||
AsmTargetStorageType.REGISTER -> TODO()
|
||||
AsmTargetStorageType.STACK -> TODO()
|
||||
}
|
||||
}
|
||||
|
||||
private fun tryRemoveRedundantCast(value: TypecastExpression, target: AssignTarget, operator: String, origAssign: Assignment): Boolean {
|
||||
val targetDt = target.inferType(program, origAssign).typeOrElse(DataType.STRUCT)
|
||||
if (targetDt == value.type) {
|
||||
private fun tryRemoveRedundantCast(value: TypecastExpression, target: AsmAssignTarget, operator: String): Boolean {
|
||||
if (target.datatype == value.type) {
|
||||
val childDt = value.expression.inferType(program).typeOrElse(DataType.STRUCT)
|
||||
if (value.type.equalsSize(childDt) || value.type.largerThan(childDt)) {
|
||||
// this typecast is redundant here; the rest of the code knows how to deal with the uncasted value.
|
||||
inplaceModification(target, operator, value.expression, origAssign)
|
||||
inplaceModification(target, operator, value.expression)
|
||||
return true
|
||||
}
|
||||
}
|
||||
@ -1009,22 +1006,20 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
}
|
||||
}
|
||||
|
||||
private fun inplaceCast(target: AssignTarget, cast: TypecastExpression, assign: Assignment) {
|
||||
val targetDt = target.inferType(program, assign).typeOrElse(DataType.STRUCT)
|
||||
private fun inplaceCast(target: AsmAssignTarget, cast: TypecastExpression, position: Position) {
|
||||
val outerCastDt = cast.type
|
||||
val innerCastDt = (cast.expression as? TypecastExpression)?.type
|
||||
|
||||
if (innerCastDt == null) {
|
||||
// simple typecast where the value is the target
|
||||
when (targetDt) {
|
||||
when (target.datatype) {
|
||||
DataType.UBYTE, DataType.BYTE -> { /* byte target can't be casted to anything else at all */
|
||||
}
|
||||
DataType.UWORD, DataType.WORD -> {
|
||||
when (outerCastDt) {
|
||||
DataType.UBYTE, DataType.BYTE -> {
|
||||
if (target.identifier != null) {
|
||||
val name = asmgen.asmIdentifierName(target.identifier!!)
|
||||
asmgen.out(" lda #0 | sta $name+1")
|
||||
if(target.type==AsmTargetStorageType.VARIABLE) {
|
||||
asmgen.out(" lda #0 | sta ${target.asmName}+1")
|
||||
} else
|
||||
throw AssemblyError("weird value")
|
||||
}
|
||||
@ -1045,32 +1040,28 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
// calculate singular cast that is required
|
||||
val castDt = if (outerCastDt largerThan innerCastDt) innerCastDt else outerCastDt
|
||||
val value = (cast.expression as TypecastExpression).expression
|
||||
val resultingCast = TypecastExpression(value, castDt, false, assign.position)
|
||||
inplaceCast(target, resultingCast, assign)
|
||||
val resultingCast = TypecastExpression(value, castDt, false, position)
|
||||
inplaceCast(target, resultingCast, position)
|
||||
}
|
||||
}
|
||||
|
||||
private fun inplaceBooleanNot(target: AssignTarget, dt: DataType) {
|
||||
val arrayIdx = target.arrayindexed
|
||||
val identifier = target.identifier
|
||||
val memory = target.memoryAddress
|
||||
|
||||
private fun inplaceBooleanNot(target: AsmAssignTarget, dt: DataType) {
|
||||
when (dt) {
|
||||
DataType.UBYTE -> {
|
||||
when {
|
||||
identifier != null -> {
|
||||
val name = asmgen.asmIdentifierName(identifier)
|
||||
when(target.type) {
|
||||
AsmTargetStorageType.VARIABLE -> {
|
||||
asmgen.out("""
|
||||
lda $name
|
||||
lda ${target.asmName}
|
||||
beq +
|
||||
lda #1
|
||||
+ eor #1
|
||||
sta $name""")
|
||||
sta ${target.asmName}""")
|
||||
}
|
||||
memory != null -> {
|
||||
when (memory.addressExpression) {
|
||||
AsmTargetStorageType.MEMORY-> {
|
||||
val mem = target.astMemory!!
|
||||
when (mem.addressExpression) {
|
||||
is NumericLiteralValue -> {
|
||||
val addr = (memory.addressExpression as NumericLiteralValue).number.toHex()
|
||||
val addr = (mem.addressExpression as NumericLiteralValue).number.toHex()
|
||||
asmgen.out("""
|
||||
lda $addr
|
||||
beq +
|
||||
@ -1079,7 +1070,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
sta $addr""")
|
||||
}
|
||||
is IdentifierReference -> {
|
||||
val name = asmgen.asmIdentifierName(memory.addressExpression as IdentifierReference)
|
||||
val name = asmgen.asmIdentifierName(mem.addressExpression as IdentifierReference)
|
||||
asmgen.out("""
|
||||
lda $name
|
||||
sta ${C64Zeropage.SCRATCH_W1}
|
||||
@ -1093,8 +1084,8 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
sta (${C64Zeropage.SCRATCH_W1}),y""")
|
||||
}
|
||||
else -> {
|
||||
println("warning: slow stack evaluation used (6): ${memory.addressExpression::class.simpleName} at ${memory.addressExpression.position}") // TODO
|
||||
asmgen.translateExpression(memory.addressExpression)
|
||||
println("warning: slow stack evaluation used (6): ${mem.addressExpression::class.simpleName} at ${mem.addressExpression.position}") // TODO
|
||||
asmgen.translateExpression(mem.addressExpression)
|
||||
asmgen.out("""
|
||||
jsr prog8_lib.read_byte_from_address_on_stack
|
||||
beq +
|
||||
@ -1105,49 +1096,48 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
}
|
||||
}
|
||||
}
|
||||
arrayIdx != null -> {
|
||||
AsmTargetStorageType.ARRAY -> {
|
||||
TODO("in-place not of ubyte array")
|
||||
}
|
||||
AsmTargetStorageType.REGISTER -> TODO()
|
||||
AsmTargetStorageType.STACK -> TODO()
|
||||
}
|
||||
}
|
||||
DataType.UWORD -> {
|
||||
when {
|
||||
identifier != null -> {
|
||||
val name = asmgen.asmIdentifierName(identifier)
|
||||
when(target.type) {
|
||||
AsmTargetStorageType.VARIABLE -> {
|
||||
asmgen.out("""
|
||||
lda $name
|
||||
ora $name+1
|
||||
lda ${target.asmName}
|
||||
ora ${target.asmName}+1
|
||||
beq +
|
||||
lda #1
|
||||
+ eor #1
|
||||
sta $name
|
||||
sta ${target.asmName}
|
||||
lsr a
|
||||
sta $name+1""")
|
||||
sta ${target.asmName}+1""")
|
||||
}
|
||||
arrayIdx != null -> TODO("in-place not of uword array")
|
||||
memory != null -> throw AssemblyError("no asm gen for uword-memory not")
|
||||
AsmTargetStorageType.MEMORY -> throw AssemblyError("no asm gen for uword-memory not")
|
||||
AsmTargetStorageType.ARRAY -> TODO("in-place not of uword array")
|
||||
AsmTargetStorageType.REGISTER -> TODO()
|
||||
AsmTargetStorageType.STACK -> TODO()
|
||||
}
|
||||
}
|
||||
else -> throw AssemblyError("boolean-not of invalid type")
|
||||
}
|
||||
}
|
||||
|
||||
private fun inplaceInvert(target: AssignTarget, dt: DataType) {
|
||||
val arrayIdx = target.arrayindexed
|
||||
val identifier = target.identifier
|
||||
val memory = target.memoryAddress
|
||||
|
||||
private fun inplaceInvert(target: AsmAssignTarget, dt: DataType) {
|
||||
when (dt) {
|
||||
DataType.UBYTE -> {
|
||||
when {
|
||||
identifier != null -> {
|
||||
val name = asmgen.asmIdentifierName(identifier)
|
||||
when(target.type) {
|
||||
AsmTargetStorageType.VARIABLE -> {
|
||||
asmgen.out("""
|
||||
lda $name
|
||||
lda ${target.asmName}
|
||||
eor #255
|
||||
sta $name""")
|
||||
sta ${target.asmName}""")
|
||||
}
|
||||
memory != null -> {
|
||||
AsmTargetStorageType.MEMORY -> {
|
||||
val memory = target.astMemory!!
|
||||
when (memory.addressExpression) {
|
||||
is NumericLiteralValue -> {
|
||||
val addr = (memory.addressExpression as NumericLiteralValue).number.toHex()
|
||||
@ -1179,86 +1169,88 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
}
|
||||
}
|
||||
}
|
||||
arrayIdx != null -> {
|
||||
AsmTargetStorageType.ARRAY -> {
|
||||
TODO("in-place invert ubyte array")
|
||||
}
|
||||
AsmTargetStorageType.REGISTER -> TODO()
|
||||
AsmTargetStorageType.STACK -> TODO()
|
||||
}
|
||||
}
|
||||
DataType.UWORD -> {
|
||||
when {
|
||||
identifier != null -> {
|
||||
val name = asmgen.asmIdentifierName(identifier)
|
||||
when(target.type) {
|
||||
AsmTargetStorageType.VARIABLE -> {
|
||||
asmgen.out("""
|
||||
lda $name
|
||||
lda ${target.asmName}
|
||||
eor #255
|
||||
sta $name
|
||||
lda $name+1
|
||||
sta ${target.asmName}
|
||||
lda ${target.asmName}+1
|
||||
eor #255
|
||||
sta $name+1""")
|
||||
sta ${target.asmName}+1""")
|
||||
}
|
||||
arrayIdx != null -> TODO("in-place invert uword array")
|
||||
memory != null -> throw AssemblyError("no asm gen for uword-memory invert")
|
||||
AsmTargetStorageType.MEMORY -> throw AssemblyError("no asm gen for uword-memory invert")
|
||||
AsmTargetStorageType.ARRAY -> TODO("in-place invert uword array")
|
||||
AsmTargetStorageType.REGISTER -> TODO()
|
||||
AsmTargetStorageType.STACK -> TODO()
|
||||
}
|
||||
}
|
||||
else -> throw AssemblyError("invert of invalid type")
|
||||
}
|
||||
}
|
||||
|
||||
private fun inplaceNegate(target: AssignTarget, dt: DataType) {
|
||||
val arrayIdx = target.arrayindexed
|
||||
val identifier = target.identifier
|
||||
val memory = target.memoryAddress
|
||||
|
||||
private fun inplaceNegate(target: AsmAssignTarget, dt: DataType) {
|
||||
when (dt) {
|
||||
DataType.BYTE -> {
|
||||
when {
|
||||
identifier != null -> {
|
||||
val name = asmgen.asmIdentifierName(identifier)
|
||||
when (target.type) {
|
||||
AsmTargetStorageType.VARIABLE -> {
|
||||
asmgen.out("""
|
||||
lda #0
|
||||
sec
|
||||
sbc $name
|
||||
sta $name""")
|
||||
sbc ${target.asmName}
|
||||
sta ${target.asmName}""")
|
||||
}
|
||||
memory != null -> throw AssemblyError("can't in-place negate memory ubyte")
|
||||
arrayIdx != null -> TODO("in-place negate byte array")
|
||||
AsmTargetStorageType.MEMORY -> throw AssemblyError("can't in-place negate memory ubyte")
|
||||
AsmTargetStorageType.ARRAY -> TODO("in-place negate byte array")
|
||||
AsmTargetStorageType.REGISTER -> TODO()
|
||||
AsmTargetStorageType.STACK -> TODO()
|
||||
}
|
||||
}
|
||||
DataType.WORD -> {
|
||||
when {
|
||||
identifier != null -> {
|
||||
val name = asmgen.asmIdentifierName(identifier)
|
||||
when(target.type) {
|
||||
AsmTargetStorageType.VARIABLE -> {
|
||||
asmgen.out("""
|
||||
lda #0
|
||||
sec
|
||||
sbc $name
|
||||
sta $name
|
||||
sbc ${target.asmName}
|
||||
sta ${target.asmName}
|
||||
lda #0
|
||||
sbc $name+1
|
||||
sta $name+1""")
|
||||
sbc ${target.asmName}+1
|
||||
sta ${target.asmName}+1""")
|
||||
}
|
||||
arrayIdx != null -> TODO("in-place negate word array")
|
||||
memory != null -> throw AssemblyError("no asm gen for word memory negate")
|
||||
AsmTargetStorageType.ARRAY -> TODO("in-place negate word array")
|
||||
AsmTargetStorageType.MEMORY -> throw AssemblyError("no asm gen for word memory negate")
|
||||
AsmTargetStorageType.REGISTER -> TODO()
|
||||
AsmTargetStorageType.STACK -> TODO()
|
||||
}
|
||||
}
|
||||
DataType.FLOAT -> {
|
||||
when {
|
||||
identifier != null -> {
|
||||
val name = asmgen.asmIdentifierName(identifier)
|
||||
when(target.type) {
|
||||
AsmTargetStorageType.VARIABLE -> {
|
||||
asmgen.out("""
|
||||
stx ${C64Zeropage.SCRATCH_REG_X}
|
||||
lda #<$name
|
||||
ldy #>$name
|
||||
lda #<${target.asmName}
|
||||
ldy #>${target.asmName}
|
||||
jsr c64flt.MOVFM
|
||||
jsr c64flt.NEGOP
|
||||
ldx #<$name
|
||||
ldy #>$name
|
||||
ldx #<${target.asmName}
|
||||
ldy #>${target.asmName}
|
||||
jsr c64flt.MOVMF
|
||||
ldx ${C64Zeropage.SCRATCH_REG_X}
|
||||
""")
|
||||
}
|
||||
arrayIdx != null -> TODO("in-place negate float array")
|
||||
memory != null -> throw AssemblyError("no asm gen for float memory negate")
|
||||
AsmTargetStorageType.ARRAY -> TODO("in-place negate float array")
|
||||
AsmTargetStorageType.MEMORY -> throw AssemblyError("no asm gen for float memory negate")
|
||||
AsmTargetStorageType.REGISTER -> TODO()
|
||||
AsmTargetStorageType.STACK -> TODO()
|
||||
}
|
||||
}
|
||||
else -> throw AssemblyError("negate of invalid type")
|
||||
|
@ -11,9 +11,6 @@ main {
|
||||
ubyte[] array=[1,2,3]
|
||||
str string = "hello"
|
||||
|
||||
string = 3
|
||||
array = 5
|
||||
foo = $c100
|
||||
c64scr.print_uwhex(foo, 1)
|
||||
|
||||
foo[100]=10
|
||||
|
Loading…
x
Reference in New Issue
Block a user