diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/ExpressionsAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/ExpressionsAsmGen.kt index 00620c050..1087a96a8 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/ExpressionsAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/ExpressionsAsmGen.kt @@ -747,9 +747,6 @@ internal class ExpressionsAsmGen(private val program: PtProgram, val elementDt = arrayExpr.type val arrayVarName = asmgen.asmVariableName(arrayExpr.variable) - if(arrayExpr.splitWords) - TODO("split words ${arrayExpr.position}") - if(arrayExpr.variable.type==DataType.UWORD) { // indexing a pointer var instead of a real array or string if(elementDt !in ByteDatatypes) @@ -767,6 +764,9 @@ internal class ExpressionsAsmGen(private val program: PtProgram, return } + if(arrayExpr.splitWords) + TODO("split words expression ${arrayExpr.position}") + val constIndexNum = arrayExpr.index.asConstInteger() if(constIndexNum!=null) { val indexValue = constIndexNum * program.memsizer.memorySize(elementDt) diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/ProgramAndVarsGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/ProgramAndVarsGen.kt index a4876a7ab..de1832c22 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/ProgramAndVarsGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/ProgramAndVarsGen.kt @@ -543,6 +543,11 @@ internal class ProgramAndVarsGen( DataType.UWORD -> asmgen.out("${variable.name}\t.word ?") DataType.WORD -> asmgen.out("${variable.name}\t.sint ?") DataType.FLOAT -> asmgen.out("${variable.name}\t.fill ${compTarget.machine.FLOAT_MEM_SIZE}") + in SplitWordArrayTypes -> { + val numbytesPerHalf = compTarget.memorySize(variable.dt, variable.length!!) / 2 + asmgen.out("${variable.name}_lsb\t.fill $numbytesPerHalf") + asmgen.out("${variable.name}_msb\t.fill $numbytesPerHalf") + } in ArrayDatatypes -> { val numbytes = compTarget.memorySize(variable.dt, variable.length!!) asmgen.out("${variable.name}\t.fill $numbytes") diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt index 0ffb4cd6d..4ae7e06c7 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt @@ -1896,6 +1896,8 @@ internal class AssignmentAsmGen(private val program: PtProgram, asmgen.out(" inx | lda P8ESTACK_LO,x | sta ${target.asmVarname},y") } DataType.UWORD, DataType.WORD -> { + if(target.array!!.splitWords) + TODO("assign into split words ${target.position}") asmgen.loadScaledArrayIndexIntoRegister(target.array, target.datatype, CpuRegister.Y) asmgen.out(""" inx @@ -2064,16 +2066,13 @@ internal class AssignmentAsmGen(private val program: PtProgram, lda $sourceName ldy $sourceName+1 sta ${target.asmVarname} - sty ${target.asmVarname}+1 - """) + sty ${target.asmVarname}+1""") } TargetStorageKind.MEMORY -> { throw AssemblyError("assign word to memory ${target.memory} should have gotten a typecast") } TargetStorageKind.ARRAY -> { target.array!! - if(target.array.splitWords) - TODO("assign var into split words ${target.position}") if(target.constArrayIndexValue!=null) { val scaledIdx = target.constArrayIndexValue!! * program.memsizer.memorySize(target.datatype).toUInt() when(target.datatype) { @@ -2081,12 +2080,18 @@ internal class AssignmentAsmGen(private val program: PtProgram, asmgen.out(" lda $sourceName | sta ${target.asmVarname}+$scaledIdx") } in WordDatatypes -> { - asmgen.out(""" - lda $sourceName - sta ${target.asmVarname}+$scaledIdx - lda $sourceName+1 - sta ${target.asmVarname}+$scaledIdx+1 - """) + if(target.array.splitWords) + asmgen.out(""" + lda $sourceName + sta ${target.asmVarname}_lsb+${target.constArrayIndexValue} + lda $sourceName+1 + sta ${target.asmVarname}_msb+${target.constArrayIndexValue}""") + else + asmgen.out(""" + lda $sourceName + sta ${target.asmVarname}+$scaledIdx + lda $sourceName+1 + sta ${target.asmVarname}+$scaledIdx+1""") } DataType.FLOAT -> { asmgen.out(""" @@ -2096,8 +2101,7 @@ internal class AssignmentAsmGen(private val program: PtProgram, sty P8ZP_SCRATCH_W1+1 lda #<(${target.asmVarname}+$scaledIdx) ldy #>(${target.asmVarname}+$scaledIdx) - jsr floats.copy_float - """) + jsr floats.copy_float""") } else -> throw AssemblyError("weird target variable type ${target.datatype}") } @@ -2111,12 +2115,18 @@ internal class AssignmentAsmGen(private val program: PtProgram, } DataType.UWORD, DataType.WORD -> { asmgen.loadScaledArrayIndexIntoRegister(target.array, target.datatype, CpuRegister.Y) - asmgen.out(""" - lda $sourceName - sta ${target.asmVarname},y - lda $sourceName+1 - sta ${target.asmVarname}+1,y - """) + if(target.array.splitWords) + asmgen.out(""" + lda $sourceName + sta ${target.asmVarname}_lsb,y + lda $sourceName+1 + sta ${target.asmVarname}_msb,y""") + else + asmgen.out(""" + lda $sourceName + sta ${target.asmVarname},y + lda $sourceName+1 + sta ${target.asmVarname}+1,y""") } DataType.FLOAT -> { asmgen.loadScaledArrayIndexIntoRegister(target.array, target.datatype, CpuRegister.A) @@ -2315,6 +2325,8 @@ internal class AssignmentAsmGen(private val program: PtProgram, } return } + if(target.array!!.splitWords) + TODO("assign into split words ${target.position}") if (target.constArrayIndexValue!=null) { val scaledIdx = target.constArrayIndexValue!! * program.memsizer.memorySize(target.datatype).toUInt() asmgen.out(" lda $sourceName | sta ${target.asmVarname}+$scaledIdx") @@ -2448,22 +2460,41 @@ internal class AssignmentAsmGen(private val program: PtProgram, asmgen.out(" lda #0 | sta ${wordtarget.asmVarname}+1") } TargetStorageKind.ARRAY -> { - if (wordtarget.constArrayIndexValue!=null) { - val scaledIdx = wordtarget.constArrayIndexValue!! * 2u - asmgen.out(" lda $sourceName | sta ${wordtarget.asmVarname}+$scaledIdx") - if(asmgen.isTargetCpu(CpuType.CPU65c02)) - asmgen.out(" stz ${wordtarget.asmVarname}+$scaledIdx+1") - else - asmgen.out(" lda #0 | sta ${wordtarget.asmVarname}+$scaledIdx+1") - } - else { - asmgen.loadScaledArrayIndexIntoRegister(wordtarget.array!!, wordtarget.datatype, CpuRegister.Y) - asmgen.out(""" - lda $sourceName - sta ${wordtarget.asmVarname},y - iny - lda #0 - sta ${wordtarget.asmVarname},y""") + if(wordtarget.array!!.splitWords) { + if (wordtarget.constArrayIndexValue!=null) { + val scaledIdx = wordtarget.constArrayIndexValue!! + asmgen.out(" lda $sourceName | sta ${wordtarget.asmVarname}_lsb+$scaledIdx") + if(asmgen.isTargetCpu(CpuType.CPU65c02)) + asmgen.out(" stz ${wordtarget.asmVarname}_msb+$scaledIdx") + else + asmgen.out(" lda #0 | sta ${wordtarget.asmVarname}_msb+$scaledIdx") + } + else { + asmgen.loadScaledArrayIndexIntoRegister(wordtarget.array, wordtarget.datatype, CpuRegister.Y) + asmgen.out(""" + lda $sourceName + sta ${wordtarget.asmVarname}_lsb,y + lda #0 + sta ${wordtarget.asmVarname}_msb,y""") + } + } else { + if (wordtarget.constArrayIndexValue!=null) { + val scaledIdx = wordtarget.constArrayIndexValue!! * 2u + asmgen.out(" lda $sourceName | sta ${wordtarget.asmVarname}+$scaledIdx") + if(asmgen.isTargetCpu(CpuType.CPU65c02)) + asmgen.out(" stz ${wordtarget.asmVarname}+$scaledIdx+1") + else + asmgen.out(" lda #0 | sta ${wordtarget.asmVarname}+$scaledIdx+1") + } + else { + asmgen.loadScaledArrayIndexIntoRegister(wordtarget.array, wordtarget.datatype, CpuRegister.Y) + asmgen.out(""" + lda $sourceName + sta ${wordtarget.asmVarname},y + iny + lda #0 + sta ${wordtarget.asmVarname},y""") + } } } TargetStorageKind.REGISTER -> { @@ -2720,49 +2751,93 @@ internal class AssignmentAsmGen(private val program: PtProgram, } } TargetStorageKind.ARRAY -> { - if(target.array!!.splitWords) - TODO("assign register pair into split words ${target.position}") - if (target.constArrayIndexValue!=null) { - val idx = target.constArrayIndexValue!! * 2u - when (regs) { - RegisterOrPair.AX -> asmgen.out(" sta ${target.asmVarname}+$idx | stx ${target.asmVarname}+$idx+1") - RegisterOrPair.AY -> asmgen.out(" sta ${target.asmVarname}+$idx | sty ${target.asmVarname}+$idx+1") - RegisterOrPair.XY -> asmgen.out(" stx ${target.asmVarname}+$idx | sty ${target.asmVarname}+$idx+1") - in Cx16VirtualRegisters -> { + if(target.array!!.splitWords) { + // assign to split lsb/msb word array + if (target.constArrayIndexValue!=null) { + val idx = target.constArrayIndexValue!! + when (regs) { + RegisterOrPair.AX -> asmgen.out(" sta ${target.asmVarname}_lsb+$idx | stx ${target.asmVarname}_msb+$idx") + RegisterOrPair.AY -> asmgen.out(" sta ${target.asmVarname}_lsb+$idx | sty ${target.asmVarname}_msb+$idx") + RegisterOrPair.XY -> asmgen.out(" stx ${target.asmVarname}_lsb+$idx | sty ${target.asmVarname}_msb+$idx") + in Cx16VirtualRegisters -> { + val srcReg = asmgen.asmSymbolName(regs) + asmgen.out(""" + lda $srcReg + sta ${target.asmVarname}_lsb+$idx + lda $srcReg+1 + sta ${target.asmVarname}_msb+$idx""") + } + else -> throw AssemblyError("expected reg pair or cx16 virtual 16-bit register") + } + } + else { + if (regs !in Cx16VirtualRegisters) { + when (regs) { + RegisterOrPair.AX -> asmgen.out(" pha | txa | pha") + RegisterOrPair.AY -> asmgen.out(" pha | tya | pha") + RegisterOrPair.XY -> asmgen.out(" txa | pha | tya | pha") + else -> throw AssemblyError("expected reg pair") + } + asmgen.loadScaledArrayIndexIntoRegister(target.array, DataType.UWORD, CpuRegister.Y, true) + asmgen.out(""" + pla + sta ${target.asmVarname}_lsb,y + pla + sta ${target.asmVarname}_msb,y""") + } else { val srcReg = asmgen.asmSymbolName(regs) + asmgen.loadScaledArrayIndexIntoRegister(target.array, DataType.UWORD, CpuRegister.Y, true) asmgen.out(""" lda $srcReg - sta ${target.asmVarname}+$idx + sta ${target.asmVarname}_lsb,y lda $srcReg+1 - sta ${target.asmVarname}+$idx+1""") + sta ${target.asmVarname}_msb,y""") } - else -> throw AssemblyError("expected reg pair or cx16 virtual 16-bit register") } - } - else { - if (regs !in Cx16VirtualRegisters) { + } else { + // assign to normal word array + if (target.constArrayIndexValue!=null) { + val idx = target.constArrayIndexValue!! * 2u when (regs) { - RegisterOrPair.AX -> asmgen.out(" pha | txa | pha") - RegisterOrPair.AY -> asmgen.out(" pha | tya | pha") - RegisterOrPair.XY -> asmgen.out(" txa | pha | tya | pha") - else -> throw AssemblyError("expected reg pair") + RegisterOrPair.AX -> asmgen.out(" sta ${target.asmVarname}+$idx | stx ${target.asmVarname}+$idx+1") + RegisterOrPair.AY -> asmgen.out(" sta ${target.asmVarname}+$idx | sty ${target.asmVarname}+$idx+1") + RegisterOrPair.XY -> asmgen.out(" stx ${target.asmVarname}+$idx | sty ${target.asmVarname}+$idx+1") + in Cx16VirtualRegisters -> { + val srcReg = asmgen.asmSymbolName(regs) + asmgen.out(""" + lda $srcReg + sta ${target.asmVarname}+$idx + lda $srcReg+1 + sta ${target.asmVarname}+$idx+1""") + } + else -> throw AssemblyError("expected reg pair or cx16 virtual 16-bit register") + } + } + else { + if (regs !in Cx16VirtualRegisters) { + when (regs) { + RegisterOrPair.AX -> asmgen.out(" pha | txa | pha") + RegisterOrPair.AY -> asmgen.out(" pha | tya | pha") + RegisterOrPair.XY -> asmgen.out(" txa | pha | tya | pha") + else -> throw AssemblyError("expected reg pair") + } + asmgen.loadScaledArrayIndexIntoRegister(target.array, DataType.UWORD, CpuRegister.Y, true) + asmgen.out(""" + pla + sta ${target.asmVarname},y + dey + pla + sta ${target.asmVarname},y""") + } else { + val srcReg = asmgen.asmSymbolName(regs) + asmgen.loadScaledArrayIndexIntoRegister(target.array!!, DataType.UWORD, CpuRegister.Y, true) + asmgen.out(""" + lda $srcReg+1 + sta ${target.asmVarname},y + dey + lda $srcReg + sta ${target.asmVarname},y""") } - asmgen.loadScaledArrayIndexIntoRegister(target.array, DataType.UWORD, CpuRegister.Y, true) - asmgen.out(""" - pla - sta ${target.asmVarname},y - dey - pla - sta ${target.asmVarname},y""") - } else { - val srcReg = asmgen.asmSymbolName(regs) - asmgen.loadScaledArrayIndexIntoRegister(target.array!!, DataType.UWORD, CpuRegister.Y, true) - asmgen.out(""" - lda $srcReg+1 - sta ${target.asmVarname},y - dey - lda $srcReg - sta ${target.asmVarname},y""") } } } @@ -2856,6 +2931,8 @@ internal class AssignmentAsmGen(private val program: PtProgram, throw AssemblyError("memory is bytes not words") } TargetStorageKind.ARRAY -> { + if(target.array!!.splitWords) + TODO("assign into split words ${target.position}") asmgen.loadScaledArrayIndexIntoRegister(target.array!!, DataType.UWORD, CpuRegister.Y) if(target.array.splitWords) asmgen.out(""" @@ -2913,6 +2990,8 @@ internal class AssignmentAsmGen(private val program: PtProgram, throw AssemblyError("assign word to memory ${target.memory} should have gotten a typecast") } TargetStorageKind.ARRAY -> { + if(target.array!!.splitWords) + TODO("assign into split words ${target.position}") asmgen.loadScaledArrayIndexIntoRegister(target.array!!, DataType.UWORD, CpuRegister.Y) if(target.array.splitWords) asmgen.out(""" @@ -2983,6 +3062,8 @@ internal class AssignmentAsmGen(private val program: PtProgram, } return } + if(target.array!!.splitWords) + TODO("assign into split words ${target.position}") if (target.constArrayIndexValue!=null) { val indexValue = target.constArrayIndexValue!! asmgen.out(" stz ${target.asmVarname}+$indexValue") @@ -3039,6 +3120,8 @@ internal class AssignmentAsmGen(private val program: PtProgram, } return } + if(target.array!!.splitWords) + TODO("assign into split words ${target.position}") if (target.constArrayIndexValue!=null) { val indexValue = target.constArrayIndexValue!! asmgen.out(" lda #${byte.toHex()} | sta ${target.asmVarname}+$indexValue") diff --git a/compiler/res/prog8lib/cx16/gfx2.p8 b/compiler/res/prog8lib/cx16/gfx2.p8 index d98f614cd..197fbdcd8 100644 --- a/compiler/res/prog8lib/cx16/gfx2.p8 +++ b/compiler/res/prog8lib/cx16/gfx2.p8 @@ -771,9 +771,9 @@ _done ; based loosely on code found here https://www.codeproject.com/Articles/6017/QuickFill-An-efficient-flood-fill-algorithm ; with the fixes applied to the seedfill_4 routine as mentioned in the comments. const ubyte MAXDEPTH = 48 - word[MAXDEPTH] @shared stack_xl - word[MAXDEPTH] @shared stack_xr - word[MAXDEPTH] @shared stack_y + word[MAXDEPTH] @split @shared stack_xl + word[MAXDEPTH] @split @shared stack_xr + word[MAXDEPTH] @split @shared stack_y byte[MAXDEPTH] @shared stack_dy cx16.r12L = 0 ; stack pointer word x1 @@ -791,21 +791,19 @@ _done ;; stack_dy[cx16.r12L] = sdy ;; cx16.r12L++ %asm {{ - lda cx16.r12L - asl a - tay + ldy cx16.r12L lda sxl - sta stack_xl,y + sta stack_xl_lsb,y lda sxl+1 - sta stack_xl+1,y + sta stack_xl_msb,y lda sxr - sta stack_xr,y + sta stack_xr_lsb,y lda sxr+1 - sta stack_xr+1,y + sta stack_xr_msb,y lda sy - sta stack_y,y + sta stack_y_lsb,y lda sy+1 - sta stack_y+1,y + sta stack_y_msb,y ldy cx16.r12L lda sdy sta stack_dy,y @@ -819,23 +817,20 @@ _done ;; x2 = stack_xr[cx16.r12L] ;; y = stack_y[cx16.r12L] ;; dy = stack_dy[cx16.r12L] -;; y += dy %asm {{ dec cx16.r12L - lda cx16.r12L - asl a - tay - lda stack_xl,y + ldy cx16.r12L + lda stack_xl_lsb,y sta x1 - lda stack_xl+1,y + lda stack_xl_msb,y sta x1+1 - lda stack_xr,y + lda stack_xr_lsb,y sta x2 - lda stack_xr+1,y + lda stack_xr_msb,y sta x2+1 - lda stack_y,y + lda stack_y_lsb,y sta y - lda stack_y+1,y + lda stack_y_msb,y sta y+1 ldy cx16.r12L lda stack_dy,y diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 203408fb9..0289105bb 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -20,7 +20,11 @@ For 9.0 major changes - [much work:] add special (u)word array type (or modifier such as @fast or @split? ) that puts the array into memory as 2 separate byte-arrays 1 for LSB 1 for MSB -> allows for word arrays of length 256 and faster indexing this is an enormous amout of work, if this type is to be treated equally as existing (u)word , because all expression / lookup / assignment routines need to know about the distinction.... So maybe only allow the bare essentials? (store, get, ++/--/+/-, bitwise operations?) + +- TODO: fix the remaining 'simple' split words TODO cases (expression assignments) +- TODO: change more library and examples to use more @split arrays - TODO: splitarrays unit tests + - [much work:] more support for (64tass) SEGMENTS ? - (What, how, isn't current BSS support enough?) - Add a mechanism to allocate variables into golden ram (or segments really) (see GoldenRam class) diff --git a/examples/cx16/circles.p8 b/examples/cx16/circles.p8 index bf9778377..0b42c0684 100644 --- a/examples/cx16/circles.p8 +++ b/examples/cx16/circles.p8 @@ -6,8 +6,8 @@ main { const ubyte MAX_NUM_CIRCLES = 80 const ubyte GROWTH_RATE = 2 - uword[MAX_NUM_CIRCLES] circle_x - uword[MAX_NUM_CIRCLES] circle_y + uword[MAX_NUM_CIRCLES] @split circle_x + uword[MAX_NUM_CIRCLES] @split circle_y ubyte[MAX_NUM_CIRCLES] circle_radius ubyte num_circles = 0 ubyte background_color diff --git a/examples/test.p8 b/examples/test.p8 index b5c22152e..468a3e7ce 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -5,6 +5,17 @@ main { sub start() { + uword[] @split split_uwords = [12345, 60000, 4096] + ubyte xx=1 + txt.print_ub(lsb(split_uwords[xx])) + txt.spc() + txt.print_ub(msb(split_uwords[xx])) + txt.spc() + split_uwords[1] = mkword($11, xx) ; TODO fix this in codegen + txt.print_uw(split_uwords[1]) + } + + sub start22() { uword[] @split split_uwords = [12345, 60000, 4096] word[] @split split_words = [-12345, -2222, 22222] uword[256] @split @shared split2 @@ -78,11 +89,30 @@ main { print_arrays() txt.nl() - split_uwords[1] |= 4095 - split_words[1] |= 127 +; split_uwords[1] |= 4095 ; TODO fix this in 6502 codegen +; split_words[1] |= 127 ; TODO fix this in 6502 codegen +; +; print_arrays() +; txt.nl() +; txt.nl() - print_arrays() + cx16.r0 = split_uwords[1] + cx16.r1s = split_words[1] + ww = 6655 + split_uwords[1] = xx + split_words[1] = xx as word + txt.print_uw(split_uwords[1]) + txt.spc() + txt.print_w(split_words[1]) txt.nl() + ww=7788 + split_uwords[xx] = ww + split_words[xx] = ww as word + txt.print_uw(split_uwords[1]) + txt.spc() + txt.print_w(split_words[1]) + txt.nl() + } }