diff --git a/compiler/src/prog8/compiler/target/c64/codegen/AsmAssignment.kt b/compiler/src/prog8/compiler/target/c64/codegen/AsmAssignment.kt new file mode 100644 index 000000000..3a6fcd943 --- /dev/null +++ b/compiler/src/prog8/compiler/target/c64/codegen/AsmAssignment.kt @@ -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) { +} diff --git a/compiler/src/prog8/compiler/target/c64/codegen/AssignmentAsmGen.kt b/compiler/src/prog8/compiler/target/c64/codegen/AssignmentAsmGen.kt index b01b3df18..e1445f802 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen/AssignmentAsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/AssignmentAsmGen.kt @@ -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") diff --git a/compiler/src/prog8/compiler/target/c64/codegen/AugmentableAssignmentAsmGen.kt b/compiler/src/prog8/compiler/target/c64/codegen/AugmentableAssignmentAsmGen.kt index e9f3ba609..28922a1ec 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen/AugmentableAssignmentAsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/AugmentableAssignmentAsmGen.kt @@ -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 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 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 y) 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 x) 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 A) 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 (x 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 (A 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 (x 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") diff --git a/examples/test.p8 b/examples/test.p8 index 87876ff77..265697532 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -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