diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AugmentableAssignmentAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AugmentableAssignmentAsmGen.kt index 399790a11..0867188f0 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AugmentableAssignmentAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AugmentableAssignmentAsmGen.kt @@ -208,10 +208,23 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram, TargetStorageKind.ARRAY -> { val indexNum = target.array!!.index as? PtNumber if (indexNum!=null) { - val targetVarName = if(target.array.splitWords) - "${target.asmVarname} + ${indexNum.number.toInt()}" - else - "${target.asmVarname} + ${indexNum.number.toInt()*program.memsizer.memorySize(target.datatype)}" + val index = indexNum.number.toInt() + if(target.array.splitWords) { + when(value.kind) { + SourceStorageKind.LITERALNUMBER -> inplacemodificationSplitWordWithLiteralval(target.asmVarname, index, operator, value.number!!.number.toInt()) + else -> { + // TODO: more optimized code for VARIABLE, REGISTER, MEMORY, ARRAY, EXPRESSION in the case of split-word arrays + val scope = target.origAstTarget?.definingSub() + val regTarget = AsmAssignTarget.fromRegisters(RegisterOrPair.R0, false, target.position, scope, asmgen) + val assignToReg = AsmAssignment(value, regTarget, program.memsizer, target.position) + assignmentAsmGen.translateNormalAssignment(assignToReg, scope) + inplacemodificationSplitWordWithR0(target.asmVarname, index, operator) + } + } + return + } + // normal array + val targetVarName = "${target.asmVarname} + ${index*program.memsizer.memorySize(target.datatype)}" when (target.datatype) { in ByteDatatypes -> { when(value.kind) { @@ -458,6 +471,91 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram, } } + private fun inplacemodificationSplitWordWithR0(arrayVar: String, index: Int, operator: String) { + when (operator) { + "+" -> { + asmgen.out(""" + lda ${arrayVar}_lsb+$index + clc + adc cx16.r0L + sta ${arrayVar}_lsb+$index + lda ${arrayVar}_msb+$index + adc cx16.r0H + sta ${arrayVar}_msb+$index""") + } + "-" -> { + asmgen.out(""" + lda ${arrayVar}_lsb+$index + sec + sbc cx16.r0L + sta ${arrayVar}_lsb+$index + lda ${arrayVar}_msb+$index + sbc cx16.r0H + sta ${arrayVar}_msb+$index""") + } + else -> TODO("in-place modify split-words array value for operator $operator") + } + } + + private fun inplacemodificationSplitWordWithLiteralval(arrayVar: String, index: Int, operator: String, value: Int) { + // note: this contains special optimized cases because we know the exact value. Don't replace this with another routine. + when (operator) { + "+" -> { + when { + value==0 -> {} + value in 1..0xff -> asmgen.out(""" + lda ${arrayVar}_lsb+$index + clc + adc #$value + sta ${arrayVar}_lsb+$index + bcc + + inc ${arrayVar}_msb+$index ++""") + value==0x0100 -> asmgen.out(" inc ${arrayVar}_msb+$index") + value==0x0200 -> asmgen.out(" inc ${arrayVar}_msb+$index | inc ${arrayVar}_msb+$index") + value==0x0300 -> asmgen.out(" inc ${arrayVar}_msb+$index | inc ${arrayVar}_msb+$index | inc ${arrayVar}_msb+$index") + value==0x0400 -> asmgen.out(" inc ${arrayVar}_msb+$index | inc ${arrayVar}_msb+$index | inc ${arrayVar}_msb+$index | inc ${arrayVar}_msb+$index") + value and 255==0 -> asmgen.out(" lda ${arrayVar}_msb+$index | clc | adc #>$value | sta ${arrayVar}_msb+$index") + else -> asmgen.out(""" + lda ${arrayVar}_lsb+$index + clc + adc #<$value + sta ${arrayVar}_lsb+$index + lda ${arrayVar}_msb+$index + adc #>$value + sta ${arrayVar}_msb+$index""") + } + } + "-" -> { + when { + value==0 -> {} + value in 1..0xff -> asmgen.out(""" + lda ${arrayVar}_lsb+$index + sec + sbc #$value + sta ${arrayVar}_lsb+$index + bcs + + dec ${arrayVar}_msb+$index ++""") + value==0x0100 -> asmgen.out(" dec ${arrayVar}_msb+$index") + value==0x0200 -> asmgen.out(" dec ${arrayVar}_msb+$index | dec ${arrayVar}_msb+$index") + value==0x0300 -> asmgen.out(" dec ${arrayVar}_msb+$index | dec ${arrayVar}_msb+$index | dec ${arrayVar}_msb+$index") + value==0x0400 -> asmgen.out(" dec ${arrayVar}_msb+$index | dec ${arrayVar}_msb+$index | dec ${arrayVar}_msb+$index | dec ${arrayVar}_msb+$index") + value and 255==0 -> asmgen.out(" lda ${arrayVar}_msb+$index | sec | sbc #>$value | sta ${arrayVar}_msb+$index") + else -> asmgen.out(""" + lda ${arrayVar}_lsb+$index + sec + sbc #<$value + sta ${arrayVar}_lsb+$index + lda ${arrayVar}_msb+$index + sbc #>$value + sta ${arrayVar}_msb+$index""") + } + } + else -> TODO("in-place modify split-words array value for operator $operator") + } + } + private fun inplacemodificationRegisterAXwithVariable(operator: String, variable: String, varDt: DataType): Boolean { when(operator) { "+" -> { diff --git a/examples/test.p8 b/examples/test.p8 index e70b2accd..5a3b1139f 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -5,16 +5,53 @@ main { sub start() { - ubyte @shared xx - uword[3] ubarr - bool[3] barr - float[3] flarr - bool @shared bb + ubyte @shared index = 1 - ubarr[1] = ubarr[1] < 2 - ubarr[1] = ubarr[1] <= 2 - ubarr[1] = ubarr[1] > 3 - ubarr[1] = ubarr[1] >= 3 +; @(2000) = 99 +; uword @shared ptr = 2000 +; txt.print_ub(@(2000)) +; txt.nl() +; @(2000) ++ +; @(2000) ++ +; @(2000) -- +; txt.print_ub(@(2000)) +; txt.nl() + + + uword[3] @split arr + + arr[1] = 9999 + txt.print_uw(arr[1]) + txt.nl() + arr[1] = arr[1]*5 + cx16.r0=2222 + arr[1] *= cx16.r0 + arr[1] -=5 + arr[1] -=index + txt.print_uw(arr[1]) + txt.nl() + +; arr[index] = 9999 +; txt.print_uw(arr[index]) +; txt.nl() +; arr[index] += 5 +; arr[index] += 5 +; arr[index] -= 5 +; txt.print_uw(arr[index]) +; txt.nl() + + +; +; ubyte @shared xx +; uword[3] ubarr +; bool[3] barr +; float[3] flarr +; bool @shared bb +; +; ubarr[1] = ubarr[1] < 2 +; ubarr[1] = ubarr[1] <= 2 +; ubarr[1] = ubarr[1] > 3 +; ubarr[1] = ubarr[1] >= 3 ; barr[1] = barr[0] and barr[2] ; barr[1] = barr[0] or barr[2]