From 7de665d1e445d7aa5a13000e8ba3958325860ed4 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Sun, 14 Jan 2024 19:03:49 +0100 Subject: [PATCH] support for split wordarrays rol/ror and rol2/ror2 optimized rol and ror codegen optimize/fix ror/ror2/rol/rol2 on word arrays --- .../src/prog8/codegen/cpu6502/AsmGen.kt | 1 + .../codegen/cpu6502/BuiltinFunctionsAsmGen.kt | 69 ++++---- compiler/res/prog8lib/prog8_lib.asm | 164 ------------------ docs/source/todo.rst | 6 +- examples/test.p8 | 82 ++++++++- 5 files changed, 116 insertions(+), 206 deletions(-) diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt index 92a11ed33..d08b9eabf 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt @@ -527,6 +527,7 @@ class AsmGen6502Internal ( elementDt: DataType, register: CpuRegister ) { + require(elementDt==expr.type) // TODO remove this if it is ok val reg = register.toString().lowercase() val indexnum = expr.index.asConstInteger() if (indexnum != null) { diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt index 234a62530..39ba001bd 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt @@ -409,8 +409,9 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram, DataType.UBYTE -> { when (what) { is PtArrayIndexer -> { - translateRolRorArrayArgs(what.variable, what, "ror2", 'b') - asmgen.out(" jsr prog8_lib.ror2_array_ub") + asmgen.loadScaledArrayIndexIntoRegister(what, what.type, CpuRegister.X) + val varname = asmgen.asmVariableName(what.variable) + asmgen.out(" lda ${varname},x | lsr a | bcc + | ora #\$80 |+ | sta ${varname},x") } is PtMemoryByte -> { if (what.address is PtNumber) { @@ -431,10 +432,12 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram, DataType.UWORD -> { when (what) { is PtArrayIndexer -> { + asmgen.loadScaledArrayIndexIntoRegister(what, what.type, CpuRegister.X) + val varname = asmgen.asmVariableName(what.variable) if(what.splitWords) - TODO("ror2 split words ${what.position}") - translateRolRorArrayArgs(what.variable, what, "ror2", 'w') - asmgen.out(" jsr prog8_lib.ror2_array_uw") + asmgen.out(" lsr ${varname}_msb,x | ror ${varname}_lsb,x | bcc + | lda ${varname}_msb,x | ora #\$80 | sta ${varname}_msb,x |+ ") + else + asmgen.out(" lsr ${varname}+1,x | ror ${varname},x | bcc + | lda ${varname}+1,x | ora #\$80 | sta ${varname}+1,x |+ ") } is PtIdentifier -> { val variable = asmgen.asmVariableName(what) @@ -453,8 +456,9 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram, DataType.UBYTE -> { when (what) { is PtArrayIndexer -> { - translateRolRorArrayArgs(what.variable, what, "ror", 'b') - asmgen.out(" jsr prog8_lib.ror_array_ub") + asmgen.loadScaledArrayIndexIntoRegister(what, what.type, CpuRegister.X) + val varname = asmgen.asmVariableName(what.variable) + asmgen.out(" ror ${varname},x") } is PtMemoryByte -> { if (what.address is PtNumber) { @@ -489,10 +493,12 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram, DataType.UWORD -> { when (what) { is PtArrayIndexer -> { + asmgen.loadScaledArrayIndexIntoRegister(what, what.type, CpuRegister.X) + val varname = asmgen.asmVariableName(what.variable) if(what.splitWords) - TODO("ror split words ${what.position}") - translateRolRorArrayArgs(what.variable, what, "ror", 'w') - asmgen.out(" jsr prog8_lib.ror_array_uw") + asmgen.out(" ror ${varname}_msb,x | ror ${varname}_lsb,x") + else + asmgen.out(" ror ${varname}+1,x | ror ${varname},x") } is PtIdentifier -> { val variable = asmgen.asmVariableName(what) @@ -511,8 +517,9 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram, DataType.UBYTE -> { when (what) { is PtArrayIndexer -> { - translateRolRorArrayArgs(what.variable, what, "rol2", 'b') - asmgen.out(" jsr prog8_lib.rol2_array_ub") + asmgen.loadScaledArrayIndexIntoRegister(what, what.type, CpuRegister.X) + val varname = asmgen.asmVariableName(what.variable) + asmgen.out(" lda ${varname},x | cmp #\$80 | rol a | sta ${varname},x") } is PtMemoryByte -> { if (what.address is PtNumber) { @@ -533,10 +540,12 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram, DataType.UWORD -> { when (what) { is PtArrayIndexer -> { + asmgen.loadScaledArrayIndexIntoRegister(what, what.type, CpuRegister.X) + val varname = asmgen.asmVariableName(what.variable) if(what.splitWords) - TODO("rol2 split words ${what.position}") - translateRolRorArrayArgs(what.variable, what, "rol2", 'w') - asmgen.out(" jsr prog8_lib.rol2_array_uw") + asmgen.out(" asl ${varname}_lsb,x | rol ${varname}_msb,x | bcc + | inc ${varname}_lsb |+") + else + asmgen.out(" asl ${varname},x | rol ${varname}+1,x | bcc + | inc ${varname},x |+ ") } is PtIdentifier -> { val variable = asmgen.asmVariableName(what) @@ -555,8 +564,9 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram, DataType.UBYTE -> { when (what) { is PtArrayIndexer -> { - translateRolRorArrayArgs(what.variable, what, "rol", 'b') - asmgen.out(" jsr prog8_lib.rol_array_ub") + asmgen.loadScaledArrayIndexIntoRegister(what, what.type, CpuRegister.X) + val varname = asmgen.asmVariableName(what.variable) + asmgen.out(" rol ${varname},x") } is PtMemoryByte -> { if (what.address is PtNumber) { @@ -591,10 +601,12 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram, DataType.UWORD -> { when (what) { is PtArrayIndexer -> { + asmgen.loadScaledArrayIndexIntoRegister(what, what.type, CpuRegister.X) + val varname = asmgen.asmVariableName(what.variable) if(what.splitWords) - TODO("rol split words ${what.position}") - translateRolRorArrayArgs(what.variable, what, "rol", 'w') - asmgen.out(" jsr prog8_lib.rol_array_uw") + asmgen.out(" rol ${varname}_lsb,x | rol ${varname}_msb,x") + else + asmgen.out(" rol ${varname},x | rol ${varname}+1,x") } is PtIdentifier -> { val variable = asmgen.asmVariableName(what) @@ -607,23 +619,6 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram, } } - private fun translateRolRorArrayArgs(arrayvar: PtIdentifier, indexer: PtArrayIndexer, operation: String, dt: Char) { - if(indexer.splitWords) - TODO("rol/ror split words access ${indexer.position}") - if(arrayvar.type==DataType.UWORD) { - if(dt!='b') - throw AssemblyError("non-array var indexing requires bytes dt") - asmgen.assignExpressionToVariable(arrayvar, "prog8_lib.${operation}_array_u${dt}._arg_target", DataType.UWORD) - } else { - val p = arrayvar.parent - val addressOf = PtAddressOf(arrayvar.position) - addressOf.add(arrayvar) - addressOf.parent = p - asmgen.assignExpressionToVariable(addressOf, "prog8_lib.${operation}_array_u${dt}._arg_target", DataType.UWORD) - } - asmgen.assignExpressionToVariable(indexer.index, "prog8_lib.${operation}_array_u${dt}._arg_index", DataType.UBYTE) - } - private fun funcSetLsbMsb(fcall: PtBuiltinFunctionCall, msb: Boolean) { val target: AsmAssignTarget when(fcall.args[0]) { diff --git a/compiler/res/prog8lib/prog8_lib.asm b/compiler/res/prog8lib/prog8_lib.asm index 1ff557cd0..37a2bdb4b 100644 --- a/compiler/res/prog8lib/prog8_lib.asm +++ b/compiler/res/prog8lib/prog8_lib.asm @@ -218,170 +218,6 @@ rol2_mem_ub .proc rts .pend -rol_array_ub .proc - ; -- rol a ubyte in an array - lda _arg_target - ldy _arg_target+1 - sta P8ZP_SCRATCH_W1 - sty P8ZP_SCRATCH_W1+1 - ldy _arg_index - lda (P8ZP_SCRATCH_W1),y - rol a - sta (P8ZP_SCRATCH_W1),y - rts -_arg_target .word 0 -_arg_index .byte 0 - .pend - - -ror_array_ub .proc - ; -- ror a ubyte in an array - lda _arg_target - ldy _arg_target+1 - sta P8ZP_SCRATCH_W1 - sty P8ZP_SCRATCH_W1+1 - ldy _arg_index - lda (P8ZP_SCRATCH_W1),y - ror a - sta (P8ZP_SCRATCH_W1),y - rts -_arg_target .word 0 -_arg_index .byte 0 - .pend - -ror2_array_ub .proc - ; -- ror2 (8-bit ror) a ubyte in an array - lda _arg_target - ldy _arg_target+1 - sta P8ZP_SCRATCH_W1 - sty P8ZP_SCRATCH_W1+1 - ldy _arg_index - lda (P8ZP_SCRATCH_W1),y - lsr a - bcc + - ora #$80 -+ sta (P8ZP_SCRATCH_W1),y - rts -_arg_target .word 0 -_arg_index .byte 0 - .pend - -rol2_array_ub .proc - ; -- rol2 (8-bit rol) a ubyte in an array - lda _arg_target - ldy _arg_target+1 - sta P8ZP_SCRATCH_W1 - sty P8ZP_SCRATCH_W1+1 - ldy _arg_index - lda (P8ZP_SCRATCH_W1),y - cmp #$80 - rol a - sta (P8ZP_SCRATCH_W1),y - rts -_arg_target .word 0 -_arg_index .byte 0 - .pend - -ror_array_uw .proc - ; -- ror a uword in an array - php - lda _arg_target - ldy _arg_target+1 - sta P8ZP_SCRATCH_W1 - sty P8ZP_SCRATCH_W1+1 - lda _arg_index - asl a - tay - iny - lda (P8ZP_SCRATCH_W1),y - plp - ror a - sta (P8ZP_SCRATCH_W1),y - dey - lda (P8ZP_SCRATCH_W1),y - ror a - sta (P8ZP_SCRATCH_W1),y - rts -_arg_target .word 0 -_arg_index .byte 0 - .pend - -rol_array_uw .proc - ; -- rol a uword in an array - php - lda _arg_target - ldy _arg_target+1 - sta P8ZP_SCRATCH_W1 - sty P8ZP_SCRATCH_W1+1 - lda _arg_index - asl a - tay - lda (P8ZP_SCRATCH_W1),y - plp - rol a - sta (P8ZP_SCRATCH_W1),y - iny - lda (P8ZP_SCRATCH_W1),y - rol a - sta (P8ZP_SCRATCH_W1),y - rts -_arg_target .word 0 -_arg_index .byte 0 - .pend - -rol2_array_uw .proc - ; -- rol2 (16-bit rol) a uword in an array - lda _arg_target - ldy _arg_target+1 - sta P8ZP_SCRATCH_W1 - sty P8ZP_SCRATCH_W1+1 - lda _arg_index - asl a - tay - lda (P8ZP_SCRATCH_W1),y - asl a - sta (P8ZP_SCRATCH_W1),y - iny - lda (P8ZP_SCRATCH_W1),y - rol a - sta (P8ZP_SCRATCH_W1),y - bcc + - dey - lda (P8ZP_SCRATCH_W1),y - adc #0 - sta (P8ZP_SCRATCH_W1),y -+ rts -_arg_target .word 0 -_arg_index .byte 0 - .pend - -ror2_array_uw .proc - ; -- ror2 (16-bit ror) a uword in an array - lda _arg_target - ldy _arg_target+1 - sta P8ZP_SCRATCH_W1 - sty P8ZP_SCRATCH_W1+1 - lda _arg_index - asl a - tay - iny - lda (P8ZP_SCRATCH_W1),y - lsr a - sta (P8ZP_SCRATCH_W1),y - dey - lda (P8ZP_SCRATCH_W1),y - ror a - sta (P8ZP_SCRATCH_W1),y - bcc + - iny - lda (P8ZP_SCRATCH_W1),y - ora #$80 - sta (P8ZP_SCRATCH_W1),y -+ rts -_arg_target .word 0 -_arg_index .byte 0 - .pend - strcpy .proc ; copy a string (must be 0-terminated) from A/Y to (P8ZP_SCRATCH_W1) diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 8869348ee..4edcc4eb9 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -1,10 +1,14 @@ TODO ==== +funcRor()/funcRol(): save carry flag before calculating array index otherwise it gets clobbered +rol/ror a membyte through a uword ptr + split words sort and reverse -split words rol and ror and rol2/ror2 split words any and all +loadScaledArrayIndexIntoRegister(): the type arg can be removed? + Mark had a compiler crash FatalAstException: invalid dt ... diff --git a/examples/test.p8 b/examples/test.p8 index 85f90a601..1bc1c6ed5 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -1,13 +1,87 @@ %import textio -%import floats %zeropage basicsafe %option no_sysinit main { sub start() { - float[] fa = [1.1, 2.2, 3.3] - float @shared fl = 2.2 +/* + mem() + bytes() +*/ + words() + } - txt.print_ub(fl in fa) + sub mem() { + @($2000) = $7a + rol(@($2000)) + txt.print_ubbin(@($2000), true) + txt.nl() + rol2(@($2000)) + txt.print_ubbin(@($2000), true) + txt.nl() + ror(@($2000)) + txt.print_ubbin(@($2000), true) + txt.nl() + ror2(@($2000)) + txt.print_ubbin(@($2000), true) + txt.nl() + txt.nl() + } + + sub bytes() { + ubyte[] wa = [$1a, $2b, $3c] + + txt.print_ubbin(wa[2], true) + txt.nl() + rol(wa[2]) + txt.print_ubbin(wa[2], true) + txt.nl() + rol2(wa[2]) + txt.print_ubbin(wa[2], true) + txt.nl() + ror(wa[2]) + txt.print_ubbin(wa[2], true) + txt.nl() + ror2(wa[2]) + txt.print_ubbin(wa[2], true) + txt.nl() + txt.nl() + } + + sub words() { + uword[] wa = [$11aa, $22bb, $33cc] + uword[] @split swa = [$11aa, $22bb, $33cc] + + txt.print_uwbin(wa[2], true) + txt.nl() + rol(wa[2]) + txt.print_uwbin(wa[2], true) + txt.nl() + rol2(wa[2]) + txt.print_uwbin(wa[2], true) + txt.nl() + ror(wa[2]) + txt.print_uwbin(wa[2], true) + txt.nl() + ror2(wa[2]) + txt.print_uwbin(wa[2], true) + txt.nl() + txt.nl() + + txt.print_uwbin(swa[2], true) + txt.nl() + rol(swa[2]) + txt.print_uwbin(swa[2], true) + txt.nl() + rol2(swa[2]) + txt.print_uwbin(swa[2], true) + txt.nl() + ror(swa[2]) + txt.print_uwbin(swa[2], true) + txt.nl() + ror2(swa[2]) + txt.print_uwbin(swa[2], true) + txt.nl() + txt.nl() } }