From 80095f49629ab350599e478759af0537fef82bda Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Mon, 15 Jan 2024 23:51:19 +0100 Subject: [PATCH] added support for any() on split word arrays --- .../codegen/cpu6502/BuiltinFunctionsAsmGen.kt | 59 ++++++++++-- .../codegen/intermediate/BuiltinFuncGen.kt | 26 ++++- docs/source/todo.rst | 6 +- examples/test.p8 | 96 ++++++++++++------- 4 files changed, 142 insertions(+), 45 deletions(-) diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt index 461207503..51083d61f 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt @@ -713,13 +713,57 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram, } private fun funcAnyAll(fcall: PtBuiltinFunctionCall, resultRegister: RegisterOrPair?, scope: IPtSubroutine?) { - outputAddressAndLenghtOfArray(fcall.args[0]) val dt = fcall.args.single().type + val array = fcall.args[0] as PtIdentifier when (dt) { - DataType.ARRAY_B, DataType.ARRAY_UB, DataType.STR -> asmgen.out(" jsr prog8_lib.func_${fcall.name}_b_into_A | ldy #0") - DataType.ARRAY_UW, DataType.ARRAY_W -> asmgen.out(" jsr prog8_lib.func_${fcall.name}_w_into_A | ldy #0") - DataType.ARRAY_F -> asmgen.out(" jsr floats.func_${fcall.name}_f_into_A | ldy #0") - in SplitWordArrayTypes -> TODO("split word any/all") + DataType.ARRAY_B, DataType.ARRAY_UB, DataType.STR -> { + outputAddressAndLengthOfArray(array) + asmgen.out(" jsr prog8_lib.func_${fcall.name}_b_into_A") + } + DataType.ARRAY_UW, DataType.ARRAY_W -> { + outputAddressAndLengthOfArray(array) + asmgen.out(" jsr prog8_lib.func_${fcall.name}_w_into_A") + } + DataType.ARRAY_F -> { + outputAddressAndLengthOfArray(array) + asmgen.out(" jsr floats.func_${fcall.name}_f_into_A") + } + in SplitWordArrayTypes -> { + val numElements = (asmgen.symbolTable.lookup(array.name) as StStaticVariable).length + when(fcall.name) { + "any" -> { + // any(lsb-array) or any(msb-array) + val arrayName = asmgen.asmVariableName(array) + asmgen.out(""" + lda #<${arrayName}_lsb + ldy #>${arrayName}_lsb + sta P8ZP_SCRATCH_W1 + sty P8ZP_SCRATCH_W1+1 + lda #$numElements + """) + asmgen.out(" jsr prog8_lib.func_${fcall.name}_b_into_A") + asmgen.out(" bne +") // shortcircuit + asmgen.out(""" + pha + lda #<${arrayName}_msb + ldy #>${arrayName}_msb + sta P8ZP_SCRATCH_W1 + sty P8ZP_SCRATCH_W1+1 + lda #$numElements + """) + asmgen.out(" jsr prog8_lib.func_${fcall.name}_b_into_A") + asmgen.out(""" + sta P8ZP_SCRATCH_REG + pla + ora P8ZP_SCRATCH_REG ++""") + } + "all" -> { + TODO("split words all") + } + else -> throw AssemblyError("weird call") + } + } else -> throw AssemblyError("weird type $dt") } assignAsmGen.assignRegisterByte(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.A, false, fcall.position, scope, asmgen), CpuRegister.A, dt in SignedDatatypes, true) @@ -1226,9 +1270,8 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram, } } - private fun outputAddressAndLenghtOfArray(arg: PtExpression) { - // address in P8ZP_SCRATCH_W1, number of elements in A - arg as PtIdentifier + private fun outputAddressAndLengthOfArray(arg: PtIdentifier) { + // address goes in P8ZP_SCRATCH_W1, number of elements in A val symbol = asmgen.symbolTable.lookup(arg.name) val numElements = when(symbol) { is StStaticVariable -> symbol.length!! diff --git a/codeGenIntermediate/src/prog8/codegen/intermediate/BuiltinFuncGen.kt b/codeGenIntermediate/src/prog8/codegen/intermediate/BuiltinFuncGen.kt index 850f26f1d..3b205fdab 100644 --- a/codeGenIntermediate/src/prog8/codegen/intermediate/BuiltinFuncGen.kt +++ b/codeGenIntermediate/src/prog8/codegen/intermediate/BuiltinFuncGen.kt @@ -148,9 +148,29 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe private fun funcAny(call: PtBuiltinFunctionCall): ExpressionCodeResult { val arrayName = call.args[0] as PtIdentifier val arrayLength = codeGen.symbolTable.getLength(arrayName.name) + val result = mutableListOf() if(arrayName.type in SplitWordArrayTypes) { - TODO("any(split words) array=$arrayName length=$arrayLength") + // any(lsb-array) or any(msb-array) + val lengthReg = codeGen.registers.nextFree() + addInstr(result, IRInstruction(Opcode.PREPARECALL, immediate = 2), null) + val trLsb = exprGen.translateExpression(PtIdentifier(arrayName.name+"_lsb", DataType.ARRAY_UB, call.position)) + addToResult(result, trLsb, trLsb.resultReg, -1) + addInstr(result, IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1 = lengthReg, immediate = arrayLength), null) + result += codeGen.makeSyscall(IMSyscall.ANY_BYTE, listOf(IRDataType.WORD to trLsb.resultReg, IRDataType.BYTE to lengthReg), IRDataType.BYTE to trLsb.resultReg) + val shortcircuitLabel = codeGen.createLabelName() + result += IRCodeChunk(null, null).also { + it += IRInstruction(Opcode.CMPI, IRDataType.BYTE, reg1 = trLsb.resultReg, immediate = 0) + it += IRInstruction(Opcode.BSTNE, labelSymbol = shortcircuitLabel) + it += IRInstruction(Opcode.PREPARECALL, immediate = 2) + } + val trMsb = exprGen.translateExpression(PtIdentifier(arrayName.name+"_msb", DataType.ARRAY_UB, call.position)) + addToResult(result, trMsb, trMsb.resultReg, -1) + addInstr(result, IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1 = lengthReg, immediate = arrayLength), null) + result += codeGen.makeSyscall(IMSyscall.ANY_BYTE, listOf(IRDataType.WORD to trMsb.resultReg, IRDataType.BYTE to lengthReg), IRDataType.BYTE to trMsb.resultReg) + addInstr(result, IRInstruction(Opcode.ORR, IRDataType.BYTE, reg1=trLsb.resultReg, reg2=trMsb.resultReg), null) + result += IRCodeChunk(shortcircuitLabel, null) + return ExpressionCodeResult(result, IRDataType.BYTE, trLsb.resultReg, -1) } val syscall = @@ -162,7 +182,6 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe DataType.ARRAY_F -> IMSyscall.ANY_FLOAT else -> throw IllegalArgumentException("weird type") } - val result = mutableListOf() addInstr(result, IRInstruction(Opcode.PREPARECALL, immediate = 2), null) val tr = exprGen.translateExpression(call.args[0]) addToResult(result, tr, tr.resultReg, -1) @@ -177,7 +196,8 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe val arrayLength = codeGen.symbolTable.getLength(arrayName.name) if(arrayName.type in SplitWordArrayTypes) { - TODO("all(split words) array=$arrayName length=$arrayLength") + // this is a bit complicated to calculate.... have to check all recombined (lsb,msb) words for $0000 + TODO("all(split words $arrayName)") } val syscall = diff --git a/docs/source/todo.rst b/docs/source/todo.rst index f7f7f477f..38025f756 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -3,8 +3,7 @@ TODO funcRor()/funcRol(): save carry flag before calculating array index otherwise it gets clobbered -split words sort and reverse -split words any and all +- split words arrays reverse() Mark had a compiler crash FatalAstException: invalid dt @@ -50,6 +49,9 @@ Compiler: - Zig-like try-based error handling where the V flag could indicate error condition? and/or BRK to jump into monitor on failure? (has to set BRK vector for that) But the V flag is also set on certain normal instructions - generate WASM to eventually run prog8 on a browser canvas? Use binaryen toolkit and/or my binaryen kotlin library? - add Vic20 target? +- split words arrays all() +- split words arrays sort() + Libraries: diff --git a/examples/test.p8 b/examples/test.p8 index 1bc1c6ed5..875f53900 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -4,10 +4,8 @@ main { sub start() { -/* - mem() - bytes() -*/ +; mem() +; bytes() words() } @@ -31,6 +29,11 @@ main { sub bytes() { ubyte[] wa = [$1a, $2b, $3c] + txt.print_ub(all(wa)) + txt.spc() + txt.print_ub(any(wa)) + txt.nl() + txt.print_ubbin(wa[2], true) txt.nl() rol(wa[2]) @@ -51,37 +54,66 @@ main { sub words() { uword[] wa = [$11aa, $22bb, $33cc] uword[] @split swa = [$11aa, $22bb, $33cc] + uword[] waone = [$0000, $3300, $0000] + uword[] wazero = [$0000, $0000, $0000] + uword[] @split swaone = [$0000, $3300, $0000] + uword[] @split swazero = [$0000, $0000, $0000] - 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.print_ub(all(wa)) ; 1 +; txt.spc() +; txt.print_ub(any(wa)) ; 1 +; txt.nl() +; txt.print_ub(all(waone)) ; 0 +; txt.spc() +; txt.print_ub(any(waone)) ; 1 +; txt.nl() +;; txt.print_ub(all(swaone)) ; 0 +;; txt.spc() + txt.print_ub(any(swaone)) ; 1 txt.nl() +;; txt.print_ub(all(swa)) ; 1 +;; txt.spc() +; txt.print_ub(any(swa)) ; 1 +; txt.nl() +; txt.print_ub(all(wazero)) ; 0 +; txt.spc() +; txt.print_ub(any(wazero)) ; 0 +; txt.nl() +;; txt.print_ub(all(swazero)) ; 0 +;; txt.spc() + txt.print_ub(any(swazero)) ; 0 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() +; 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() } }