diff --git a/compiler/src/prog8/compiler/target/c64/codegen/assignment/AssignmentAsmGen.kt b/compiler/src/prog8/compiler/target/c64/codegen/assignment/AssignmentAsmGen.kt index 793dbc5b3..522e65fea 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen/assignment/AssignmentAsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/assignment/AssignmentAsmGen.kt @@ -878,7 +878,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen } } - private fun assignFAC1float(target: AsmAssignTarget) { + internal fun assignFAC1float(target: AsmAssignTarget) { when(target.kind) { TargetStorageKind.VARIABLE -> { asmgen.out(""" @@ -1143,7 +1143,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen } } - private fun assignRegisterByte(target: AsmAssignTarget, register: CpuRegister) { + internal fun assignRegisterByte(target: AsmAssignTarget, register: CpuRegister) { require(target.datatype in ByteDatatypes) when(target.kind) { TargetStorageKind.VARIABLE -> { @@ -1212,7 +1212,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen } } - private fun assignRegisterpairWord(target: AsmAssignTarget, regs: RegisterOrPair) { + internal fun assignRegisterpairWord(target: AsmAssignTarget, regs: RegisterOrPair) { require(target.datatype in NumericDatatypes) if(target.datatype==DataType.FLOAT) throw AssemblyError("float value should be from FAC1 not from registerpair memory pointer") diff --git a/compiler/src/prog8/compiler/target/c64/codegen/assignment/AugmentableAssignmentAsmGen.kt b/compiler/src/prog8/compiler/target/c64/codegen/assignment/AugmentableAssignmentAsmGen.kt index 1104e8977..e1969d748 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen/assignment/AugmentableAssignmentAsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/assignment/AugmentableAssignmentAsmGen.kt @@ -160,7 +160,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, when { valueLv != null -> inplaceModification_byte_litval_to_variable(addr.toHex(), DataType.UBYTE, operator, valueLv.toInt()) ident != null -> inplaceModification_byte_variable_to_variable(addr.toHex(), DataType.UBYTE, operator, ident) - // TODO more specialized code for types such as memory read etc. + // TODO more specialized code for types such as memory read etc. -> inplaceModification_byte_memread_to_variable() value is TypecastExpression -> { if (tryRemoveRedundantCast(value, target, operator)) return inplaceModification_byte_value_to_variable(addr.toHex(), DataType.UBYTE, operator, value) @@ -173,7 +173,6 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, when { valueLv != null -> inplaceModification_byte_litval_to_pointer(pointer, operator, valueLv.toInt()) ident != null -> inplaceModification_byte_variable_to_pointer(pointer, operator, ident) - // TODO more specialized code for types such as memory read etc. value is TypecastExpression -> { if (tryRemoveRedundantCast(value, target, operator)) return inplaceModification_byte_value_to_pointer(pointer, operator, value) @@ -199,9 +198,75 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, } } TargetStorageKind.ARRAY -> { - if(asmgen.options.slowCodegenWarnings) - println("*** TODO optimize simple inplace array assignment ${target.array} $operator= $value") - assignmentAsmGen.translateNormalAssignment(target.origAssign) // TODO get rid of this fallback for the most common cases here + with(target.array!!.indexer) { + when { + indexNum!=null -> { + val targetVarName = "${target.asmVarname} + ${indexNum!!.number.toInt()*target.datatype.memorySize()}" + when(target.datatype) { + in ByteDatatypes -> { + when { + valueLv != null -> inplaceModification_byte_litval_to_variable(targetVarName, target.datatype, operator, valueLv.toInt()) + ident != null -> inplaceModification_byte_variable_to_variable(targetVarName, target.datatype, operator, ident) + memread != null -> inplaceModification_byte_memread_to_variable(targetVarName, target.datatype, operator, memread) + value is TypecastExpression -> { + if (tryRemoveRedundantCast(value, target, operator)) return + inplaceModification_byte_value_to_variable(targetVarName, target.datatype, operator, value) + } + else -> inplaceModification_byte_value_to_variable(targetVarName, target.datatype, operator, value) + } + } + in WordDatatypes -> { + when { + valueLv != null -> inplaceModification_word_litval_to_variable(targetVarName, target.datatype, operator, valueLv.toInt()) + ident != null -> inplaceModification_word_variable_to_variable(targetVarName, target.datatype, operator, ident) + memread != null -> inplaceModification_word_memread_to_variable(targetVarName, target.datatype, operator, memread) + value is TypecastExpression -> { + if (tryRemoveRedundantCast(value, target, operator)) return + inplaceModification_word_value_to_variable(targetVarName, target.datatype, operator, value) + } + else -> inplaceModification_word_value_to_variable(targetVarName, target.datatype, operator, value) + } + } + DataType.FLOAT -> { + when { + valueLv != null -> inplaceModification_float_litval_to_variable(targetVarName, operator, valueLv.toDouble(), target.scope!!) + ident != null -> inplaceModification_float_variable_to_variable(targetVarName, operator, ident, target.scope!!) + value is TypecastExpression -> { + if (tryRemoveRedundantCast(value, target, operator)) return + inplaceModification_float_value_to_variable(targetVarName, operator, value, target.scope!!) + } + else -> inplaceModification_float_value_to_variable(targetVarName, operator, value, target.scope!!) + } + } + else -> throw AssemblyError("weird type to do in-place modification on ${target.datatype}") + } + } + indexVar!=null -> { + when(target.datatype) { + in ByteDatatypes -> { + val tgt = AsmAssignTarget.fromRegisters(RegisterOrPair.A, null, program, asmgen) + val assign = AsmAssignment(target.origAssign.source, tgt, false, value.position) + assignmentAsmGen.translateNormalAssignment(assign) + assignmentAsmGen.assignRegisterByte(target, CpuRegister.A) + } + in WordDatatypes -> { + val tgt = AsmAssignTarget.fromRegisters(RegisterOrPair.AY, null, program, asmgen) + val assign = AsmAssignment(target.origAssign.source, tgt, false, value.position) + assignmentAsmGen.translateNormalAssignment(assign) + assignmentAsmGen.assignRegisterpairWord(target, RegisterOrPair.AY) + } + DataType.FLOAT -> { + val tgt = AsmAssignTarget.fromRegisters(RegisterOrPair.FAC1, null, program, asmgen) + val assign = AsmAssignment(target.origAssign.source, tgt, false, value.position) + assignmentAsmGen.translateNormalAssignment(assign) + assignmentAsmGen.assignFAC1float(target) + } + else -> throw AssemblyError("weird type to do in-place modification on ${target.datatype}") + } + } + else -> throw AssemblyError("indexer expression should have been replaced by auto indexer var") + } + } } TargetStorageKind.REGISTER -> TODO("reg in-place modification") TargetStorageKind.STACK -> TODO("stack in-place modification") diff --git a/examples/test.p8 b/examples/test.p8 index 8ab03fa92..bee9d4f25 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -8,15 +8,24 @@ main { sub start() { ubyte[] ubarray = [100,200] + uword[] uwarray = [1000, 2000] ubyte index = 0 ubarray[index+1] += 13 ubarray[index+1] += 13 ubarray[index+1] += 13 - ubarray[index+2] += 13 + ; ubarray[index+2] += 13 txt.print_ub(ubarray[1]) txt.chrout('\n') + + uwarray[index+1] += 13 + uwarray[index+1] += 13 + uwarray[index+1] += 13 + ; uwarray[index+2] += 13 + + txt.print_uw(uwarray[1]) + txt.chrout('\n') } ; sub start222() {