diff --git a/codeGenVirtual/src/prog8/codegen/virtual/BuiltinFuncGen.kt b/codeGenVirtual/src/prog8/codegen/virtual/BuiltinFuncGen.kt index 3d99b760f..ce196b856 100644 --- a/codeGenVirtual/src/prog8/codegen/virtual/BuiltinFuncGen.kt +++ b/codeGenVirtual/src/prog8/codegen/virtual/BuiltinFuncGen.kt @@ -18,11 +18,11 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen: "msb" -> funcMsb(call, resultRegister) "lsb" -> funcLsb(call, resultRegister) "memory" -> funcMemory(call, resultRegister) - "rnd" -> funcRnd(call, resultRegister) + "rnd" -> funcRnd(resultRegister) "peek" -> funcPeek(call, resultRegister) "peekw" -> funcPeekW(call, resultRegister) - "poke" -> funcPoke(call, resultRegister) - "pokew" -> funcPokeW(call, resultRegister) + "poke" -> funcPoke(call) + "pokew" -> funcPokeW(call) "pokemon" -> VmCodeChunk() "mkword" -> funcMkword(call, resultRegister) "sin8u" -> funcSin8u(call, resultRegister) @@ -136,47 +136,65 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen: return code } - private fun funcPokeW(call: PtBuiltinFunctionCall, resultRegister: Int): VmCodeChunk { - val addressReg = codeGen.vmRegisters.nextFree() - val valueReg = codeGen.vmRegisters.nextFree() + private fun funcPokeW(call: PtBuiltinFunctionCall): VmCodeChunk { val code = VmCodeChunk() - code += exprGen.translateExpression(call.args[0], addressReg) - code += exprGen.translateExpression(call.args[1], valueReg) - // TODO use STOREM if constant address - code += VmCodeInstruction(Opcode.STOREI, VmDataType.WORD, reg1 = valueReg, reg2=addressReg) + val valueReg = codeGen.vmRegisters.nextFree() + if(call.args[0] is PtNumber) { + val address = (call.args[0] as PtNumber).number.toInt() + code += exprGen.translateExpression(call.args[1], valueReg) + code += VmCodeInstruction(Opcode.STOREM, VmDataType.WORD, reg1 = valueReg, value=address) + } else { + val addressReg = codeGen.vmRegisters.nextFree() + code += exprGen.translateExpression(call.args[0], addressReg) + code += exprGen.translateExpression(call.args[1], valueReg) + code += VmCodeInstruction(Opcode.STOREI, VmDataType.WORD, reg1 = valueReg, reg2 = addressReg) + } return code } - private fun funcPoke(call: PtBuiltinFunctionCall, resultRegister: Int): VmCodeChunk { - val addressReg = codeGen.vmRegisters.nextFree() - val valueReg = codeGen.vmRegisters.nextFree() + private fun funcPoke(call: PtBuiltinFunctionCall): VmCodeChunk { val code = VmCodeChunk() - code += exprGen.translateExpression(call.args[0], addressReg) - code += exprGen.translateExpression(call.args[1], valueReg) - // TODO use STOREM if constant address - code += VmCodeInstruction(Opcode.STOREI, VmDataType.BYTE, reg1 = valueReg, reg2=addressReg) + val valueReg = codeGen.vmRegisters.nextFree() + if(call.args[0] is PtNumber) { + val address = (call.args[0] as PtNumber).number.toInt() + code += exprGen.translateExpression(call.args[1], valueReg) + code += VmCodeInstruction(Opcode.STOREM, VmDataType.BYTE, reg1 = valueReg, value=address) + } else { + val addressReg = codeGen.vmRegisters.nextFree() + code += exprGen.translateExpression(call.args[0], addressReg) + code += exprGen.translateExpression(call.args[1], valueReg) + code += VmCodeInstruction(Opcode.STOREI, VmDataType.BYTE, reg1 = valueReg, reg2 = addressReg) + } return code } private fun funcPeekW(call: PtBuiltinFunctionCall, resultRegister: Int): VmCodeChunk { - val addressReg = codeGen.vmRegisters.nextFree() val code = VmCodeChunk() - code += exprGen.translateExpression(call.args.single(), addressReg) - // TODO use LOADM if constant address - code += VmCodeInstruction(Opcode.LOADI, VmDataType.WORD, reg1 = resultRegister, reg2=addressReg) + if(call.args[0] is PtNumber) { + val address = (call.args[0] as PtNumber).number.toInt() + code += VmCodeInstruction(Opcode.LOADM, VmDataType.WORD, reg1 = resultRegister, value = address) + } else { + val addressReg = codeGen.vmRegisters.nextFree() + code += exprGen.translateExpression(call.args.single(), addressReg) + code += VmCodeInstruction(Opcode.LOADI, VmDataType.WORD, reg1 = resultRegister, reg2 = addressReg) + } return code } private fun funcPeek(call: PtBuiltinFunctionCall, resultRegister: Int): VmCodeChunk { val code = VmCodeChunk() - val addressReg = codeGen.vmRegisters.nextFree() - code += exprGen.translateExpression(call.args.single(), addressReg) - // TODO use LOADM if constant address - code += VmCodeInstruction(Opcode.LOADI, VmDataType.BYTE, reg1 = resultRegister, reg2=addressReg) + if(call.args[0] is PtNumber) { + val address = (call.args[0] as PtNumber).number.toInt() + code += VmCodeInstruction(Opcode.LOADM, VmDataType.BYTE, reg1 = resultRegister, value = address) + } else { + val addressReg = codeGen.vmRegisters.nextFree() + code += exprGen.translateExpression(call.args.single(), addressReg) + code += VmCodeInstruction(Opcode.LOADI, VmDataType.BYTE, reg1 = resultRegister, reg2 = addressReg) + } return code } - private fun funcRnd(call: PtBuiltinFunctionCall, resultRegister: Int): VmCodeChunk { + private fun funcRnd(resultRegister: Int): VmCodeChunk { val code = VmCodeChunk() code += VmCodeInstruction(Opcode.SYSCALL, value= Syscall.RND.ordinal) if(resultRegister!=0) @@ -203,7 +221,6 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen: } private fun funcLsb(call: PtBuiltinFunctionCall, resultRegister: Int): VmCodeChunk { - // TODO optimized code gen val code = VmCodeChunk() code += exprGen.translateExpression(call.args.single(), resultRegister) // note: if a word result is needed, the upper byte is cleared by the typecast that follows. No need to do it here. @@ -211,7 +228,6 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen: } private fun funcMsb(call: PtBuiltinFunctionCall, resultRegister: Int): VmCodeChunk { - // TODO optimized code gen val code = VmCodeChunk() code += exprGen.translateExpression(call.args.single(), resultRegister) code += VmCodeInstruction(Opcode.MSIG, VmDataType.BYTE, reg1 = resultRegister, reg2=resultRegister) diff --git a/codeGenVirtual/src/prog8/codegen/virtual/CodeGen.kt b/codeGenVirtual/src/prog8/codegen/virtual/CodeGen.kt index 3a9eb38cd..dd15c6384 100644 --- a/codeGenVirtual/src/prog8/codegen/virtual/CodeGen.kt +++ b/codeGenVirtual/src/prog8/codegen/virtual/CodeGen.kt @@ -459,12 +459,18 @@ class CodeGen(internal val program: PtProgram, code += VmCodeInstruction(operation, vmDt, reg1=resultReg) code += VmCodeInstruction(Opcode.STOREM, vmDt, reg1=resultReg, value = address) } else if(memory!=null) { - val addressReg = vmRegisters.nextFree() - code += expressionEval.translateExpression(memory.address, addressReg) - // TODO use LOADM/STOREM if address is constant - code += VmCodeInstruction(Opcode.LOADI, vmDt, reg1=resultReg, reg2=addressReg) - code += VmCodeInstruction(operation, vmDt, reg1=resultReg) - code += VmCodeInstruction(Opcode.STOREI, vmDt, reg1=resultReg, reg2=addressReg) + if(memory.address is PtNumber) { + val address = (memory.address as PtNumber).number.toInt() + code += VmCodeInstruction(Opcode.LOADM, vmDt, reg1 = resultReg, value = address) + code += VmCodeInstruction(operation, vmDt, reg1 = resultReg) + code += VmCodeInstruction(Opcode.STOREM, vmDt, reg1 = resultReg, value=address) + } else { + val addressReg = vmRegisters.nextFree() + code += expressionEval.translateExpression(memory.address, addressReg) + code += VmCodeInstruction(Opcode.LOADI, vmDt, reg1 = resultReg, reg2 = addressReg) + code += VmCodeInstruction(operation, vmDt, reg1 = resultReg) + code += VmCodeInstruction(Opcode.STOREI, vmDt, reg1 = resultReg, reg2 = addressReg) + } } else if (array!=null) { val variable = array.variable.targetName var variableAddr = allocations.get(variable) diff --git a/codeGenVirtual/src/prog8/codegen/virtual/ExpressionGen.kt b/codeGenVirtual/src/prog8/codegen/virtual/ExpressionGen.kt index cdc8ba16e..9f9f08a90 100644 --- a/codeGenVirtual/src/prog8/codegen/virtual/ExpressionGen.kt +++ b/codeGenVirtual/src/prog8/codegen/virtual/ExpressionGen.kt @@ -44,10 +44,14 @@ internal class ExpressionGen(private val codeGen: CodeGen) { code += VmCodeInstruction(Opcode.LOAD, vmDt, reg1=resultRegister, value=mem) } is PtMemoryByte -> { - val addressRegister = codeGen.vmRegisters.nextFree() - code += translateExpression(expr.address, addressRegister) - // TODO use LOADM if adress is constant - code += VmCodeInstruction(Opcode.LOADI, VmDataType.BYTE, reg1=resultRegister, reg2=addressRegister) + if(expr.address is PtNumber) { + val address = (expr.address as PtNumber).number.toInt() + code += VmCodeInstruction(Opcode.LOADM, VmDataType.BYTE, reg1=resultRegister, value = address) + } else { + val addressRegister = codeGen.vmRegisters.nextFree() + code += translateExpression(expr.address, addressRegister) + code += VmCodeInstruction(Opcode.LOADI, VmDataType.BYTE, reg1=resultRegister, reg2=addressRegister) + } } is PtTypeCast -> code += translate(expr, resultRegister) is PtPrefix -> code += translate(expr, resultRegister) diff --git a/compiler/res/prog8lib/virtual/math.p8 b/compiler/res/prog8lib/virtual/math.p8 index 4c0128f06..12942459e 100644 --- a/compiler/res/prog8lib/virtual/math.p8 +++ b/compiler/res/prog8lib/virtual/math.p8 @@ -3,5 +3,5 @@ ; Written by Irmen de Jong (irmen@razorvine.net) - license: GNU GPL 3.0 math { - ; TODO + ; required by the compiler, but the vm implements all math operations as instructions. } diff --git a/examples/test.p8 b/examples/test.p8 index c3e7e3f41..099105acf 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -7,45 +7,52 @@ main { sub start() { - uword other = $fe4a - uword value = $ea31 - uword[] warray = [$aa44, $bb55, $cc66] - ubyte upperb = msb(value) - ubyte lowerb = lsb(value) - txt.print_ubhex(upperb, true) - txt.print_ubhex(lowerb, false) - txt.nl() - value = mkword(upperb, lowerb) - txt.print_uwhex(value, true) - txt.nl() - upperb = msb(warray[1]) - lowerb = lsb(warray[1]) - txt.print_ubhex(upperb, true) - txt.print_ubhex(lowerb, false) - txt.nl() - ubyte index=1 - upperb = msb(warray[index]) - lowerb = lsb(warray[index]) - txt.print_ubhex(upperb, true) - txt.print_ubhex(lowerb, false) - txt.nl() - swap(other, value) - txt.print_uwhex(value,true) + pokew($1000, $ea31) + poke($1001, $44) + txt.print_uwhex(peekw($1000), true) txt.nl() + txt.print_ubhex(peek($1001), true) txt.nl() - pokew($1000, $ab98) - txt.print_ubhex(@($1000),true) - txt.print_ubhex(@($1001),false) - txt.nl() - txt.print_uwhex(peekw($1000),true) - txt.nl() - swap(@($1000), @($1001)) - txt.print_uwhex(peekw($1000),true) - txt.nl() - swap(warray[0], warray[1]) - txt.print_uwhex(warray[1],true) - txt.nl() +; uword other = $fe4a +; uword value = $ea31 +; uword[] warray = [$aa44, $bb55, $cc66] +; ubyte upperb = msb(value) +; ubyte lowerb = lsb(value) +; txt.print_ubhex(upperb, true) +; txt.print_ubhex(lowerb, false) +; txt.nl() +; value = mkword(upperb, lowerb) +; txt.print_uwhex(value, true) +; txt.nl() +; upperb = msb(warray[1]) +; lowerb = lsb(warray[1]) +; txt.print_ubhex(upperb, true) +; txt.print_ubhex(lowerb, false) +; txt.nl() +; ubyte index=1 +; upperb = msb(warray[index]) +; lowerb = lsb(warray[index]) +; txt.print_ubhex(upperb, true) +; txt.print_ubhex(lowerb, false) +; txt.nl() +; swap(other, value) +; txt.print_uwhex(value,true) +; txt.nl() +; txt.nl() +; +; pokew($1000, $ab98) +; txt.print_ubhex(@($1000),true) +; txt.print_ubhex(@($1001),false) +; txt.nl() +; txt.print_uwhex(peekw($1000),true) +; txt.nl() +; swap(@($1000), @($1001)) +; txt.print_uwhex(peekw($1000),true) +; txt.nl() +; swap(warray[0], warray[1]) +; txt.print_uwhex(warray[1],true) +; txt.nl() ; ; a "pixelshader": ; void syscall1(8, 0) ; enable lo res creen