fix some split array issues in 6502 codegen

This commit is contained in:
Irmen de Jong 2023-05-28 14:53:53 +02:00
parent d61283a8bc
commit 82898f7bba
7 changed files with 216 additions and 99 deletions

View File

@ -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)

View File

@ -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")

View File

@ -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")

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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()
}
}