From 76c09da96188f52186cdf1704d86844f62f9d476 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Thu, 9 Nov 2023 22:32:20 +0100 Subject: [PATCH] make pokemon() be like poke, but also return the old value in the memory location. --- .../src/prog8/code/core/BuiltinFunctions.kt | 2 +- .../src/prog8/codegen/cpu6502/AsmGen.kt | 28 ++++++++++ .../codegen/cpu6502/BuiltinFunctionsAsmGen.kt | 11 +++- .../codegen/intermediate/BuiltinFuncGen.kt | 55 ++++++++++++++++++- docs/source/programming.rst | 3 +- examples/test.p8 | 29 +++++++--- 6 files changed, 117 insertions(+), 11 deletions(-) diff --git a/codeCore/src/prog8/code/core/BuiltinFunctions.kt b/codeCore/src/prog8/code/core/BuiltinFunctions.kt index 80271044c..878eb4c1d 100644 --- a/codeCore/src/prog8/code/core/BuiltinFunctions.kt +++ b/codeCore/src/prog8/code/core/BuiltinFunctions.kt @@ -121,8 +121,8 @@ val BuiltinFunctions: Map = mapOf( "peek" to FSignature(true, listOf(FParam("address", arrayOf(DataType.UWORD))), DataType.UBYTE), "peekw" to FSignature(true, listOf(FParam("address", arrayOf(DataType.UWORD))), DataType.UWORD), "poke" to FSignature(false, listOf(FParam("address", arrayOf(DataType.UWORD)), FParam("value", arrayOf(DataType.UBYTE))), null), - "pokemon" to FSignature(false, listOf(FParam("address", arrayOf(DataType.UWORD)), FParam("value", arrayOf(DataType.UBYTE))), null), "pokew" to FSignature(false, listOf(FParam("address", arrayOf(DataType.UWORD)), FParam("value", arrayOf(DataType.UWORD))), null), + "pokemon" to FSignature(false, listOf(FParam("address", arrayOf(DataType.UWORD)), FParam("value", arrayOf(DataType.UBYTE))), DataType.UBYTE), "pop" to FSignature(false, listOf(FParam("target", ByteDatatypes)), null), "popw" to FSignature(false, listOf(FParam("target", WordDatatypes)), null), "push" to FSignature(false, listOf(FParam("value", ByteDatatypes)), null), diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt index f296857aa..d67fbf49b 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt @@ -577,6 +577,34 @@ class AsmGen6502Internal ( internal fun assignExpressionTo(value: PtExpression, target: AsmAssignTarget) { when (target.datatype) { in ByteDatatypes -> { + if (value.asConstInteger()==0) { + when(target.kind) { + TargetStorageKind.VARIABLE -> { + if (isTargetCpu(CpuType.CPU6502)) + out("lda #0 | sta ${target.asmVarname}") + else + out("stz ${target.asmVarname}") + } + TargetStorageKind.MEMORY -> { + val address = target.memory!!.address.asConstInteger() + if(address!=null) { + if (isTargetCpu(CpuType.CPU6502)) + out("lda #0 | sta ${address.toHex()}") + else + out(" stz ${address.toHex()}") + return + } + } + TargetStorageKind.REGISTER -> { + val zero = PtNumber(DataType.UBYTE, 0.0, value.position) + zero.parent = value + assignExpressionToRegister(zero, target.register!!, false) + return + } + else -> { } + } + } + assignExpressionToRegister(value, RegisterOrPair.A) assignRegister(RegisterOrPair.A, target) } diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt index 6524689b7..97c48232f 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt @@ -49,7 +49,16 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram, "peekw" -> funcPeekW(fcall, resultRegister) "peek" -> throw AssemblyError("peek() should have been replaced by @()") "pokew" -> funcPokeW(fcall) - "pokemon" -> { /* meme function */ } + "pokemon" -> { + val memread = PtMemoryByte(fcall.position) + memread.add(fcall.args[0]) + memread.parent = fcall + asmgen.assignExpressionToRegister(memread, RegisterOrPair.A, false) + asmgen.out(" pha") + val memtarget = AsmAssignTarget(TargetStorageKind.MEMORY, asmgen, DataType.UBYTE, fcall.definingISub(), fcall.position, memory=memread) + asmgen.assignExpressionTo(fcall.args[1], memtarget) + asmgen.out(" pla") + } "poke" -> throw AssemblyError("poke() should have been replaced by @()") "push" -> asmgen.pushCpuStack(DataType.UBYTE, fcall.args[0]) "pushw" -> asmgen.pushCpuStack(DataType.UWORD, fcall.args[0]) diff --git a/codeGenIntermediate/src/prog8/codegen/intermediate/BuiltinFuncGen.kt b/codeGenIntermediate/src/prog8/codegen/intermediate/BuiltinFuncGen.kt index cf8294ba1..13b67fbfa 100644 --- a/codeGenIntermediate/src/prog8/codegen/intermediate/BuiltinFuncGen.kt +++ b/codeGenIntermediate/src/prog8/codegen/intermediate/BuiltinFuncGen.kt @@ -33,7 +33,7 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe "peekw" -> funcPeekW(call) "poke" -> funcPoke(call) "pokew" -> funcPokeW(call) - "pokemon" -> ExpressionCodeResult.EMPTY // easter egg function + "pokemon" -> funcPokemon(call) "mkword" -> funcMkword(call) "clamp__byte", "clamp__ubyte", "clamp__word", "clamp__uword" -> funcClamp(call) "min__byte", "min__ubyte", "min__word", "min__uword" -> funcMin(call) @@ -552,6 +552,59 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe } } + private fun funcPokemon(call: PtBuiltinFunctionCall): ExpressionCodeResult { + val result = mutableListOf() + val address = call.args[0] + + fun pokeM(result: MutableList, address: Int, value: PtExpression) { + if(codeGen.isZero(value)) { + result += IRCodeChunk(null, null).also { + it += IRInstruction(Opcode.STOREZM, IRDataType.BYTE, address = address) + } + } else { + val tr = exprGen.translateExpression(value) + addToResult(result, tr, tr.resultReg, -1) + result += IRCodeChunk(null, null).also { + it += IRInstruction(Opcode.STOREM, IRDataType.BYTE, reg1 = tr.resultReg, address = address) + } + } + } + + fun pokeI(result: MutableList, register: Int, value: PtExpression) { + if(codeGen.isZero(value)) { + result += IRCodeChunk(null, null).also { + it += IRInstruction(Opcode.STOREZI, IRDataType.BYTE, reg1 = register) + } + } else { + val valueTr = exprGen.translateExpression(value) + addToResult(result, valueTr, valueTr.resultReg, -1) + result += IRCodeChunk(null, null).also { + it += IRInstruction(Opcode.STOREI, IRDataType.BYTE, reg1 = valueTr.resultReg, reg2 = register) + } + } + } + + return if(address is PtNumber) { + val resultRegister = codeGen.registers.nextFree() + val addressNum = address.number.toInt() + result += IRCodeChunk(null, null).also { + it += IRInstruction(Opcode.LOADM, IRDataType.BYTE, reg1 = resultRegister, address = addressNum) + } + pokeM(result, addressNum, call.args[1]) + ExpressionCodeResult(result, IRDataType.BYTE, resultRegister, -1) + } else { + val addressTr = exprGen.translateExpression(address) + addToResult(result, addressTr, addressTr.resultReg, -1) + val resultReg = codeGen.registers.nextFree() + result += IRCodeChunk(null, null).also { + it += IRInstruction(Opcode.LOADI, IRDataType.BYTE, reg1 = resultReg, reg2 = addressTr.resultReg) + } + pokeI(result, addressTr.resultReg, call.args[1]) + ExpressionCodeResult(result, IRDataType.BYTE, resultReg, -1) + } + } + + private fun funcMemory(call: PtBuiltinFunctionCall): ExpressionCodeResult { val name = (call.args[0] as PtString).value val code = IRCodeChunk(null, null) diff --git a/docs/source/programming.rst b/docs/source/programming.rst index cec47bb7f..27fafeabd 100644 --- a/docs/source/programming.rst +++ b/docs/source/programming.rst @@ -865,7 +865,8 @@ pokew (address, value) writes the word value at the given address in memory, in usual little-endian lsb/msb byte order. pokemon (address, value) - Doesn't do anything useful. Also doesn't have anything to do with a certain video game. + Like poke(), but also returns the previous value in the given address. + Also doesn't have anything to do with a certain video game. push (value) pushes a byte value on the CPU hardware stack. Low-level function that should normally not be used. diff --git a/examples/test.p8 b/examples/test.p8 index a0b8af249..eaf27a469 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -1,14 +1,29 @@ -%zeropage basicsafe -%option no_sysinit %import textio -%import verafx +%zeropage basicsafe main { sub start() { - uword lower16 = verafx.mult(11111,9988) - uword upper16 = cx16.r0 - txt.print_uwhex(upper16, true) ; $069d5e9c = 110976668 - txt.print_uwhex(lower16, false) + uword address = 1000 + + poke(1000, 99) + ubyte prev = pokemon(1000,123) + txt.print_ub(prev) + txt.nl() + prev = pokemon(1000,0) + txt.print_ub(prev) + txt.nl() + txt.print_ub(@(1000)) + txt.nl() + txt.nl() + + poke(address+3, 99) + prev = pokemon(address+3,123) + txt.print_ub(prev) + txt.nl() + prev = pokemon(address+3,0) + txt.print_ub(prev) + txt.nl() + txt.print_ub(@(address+3)) txt.nl() } }