diff --git a/codeGenVirtual/src/prog8/codegen/virtual/BuiltinFuncGen.kt b/codeGenVirtual/src/prog8/codegen/virtual/BuiltinFuncGen.kt index cf5fc594a..f56bb268e 100644 --- a/codeGenVirtual/src/prog8/codegen/virtual/BuiltinFuncGen.kt +++ b/codeGenVirtual/src/prog8/codegen/virtual/BuiltinFuncGen.kt @@ -2,7 +2,6 @@ package prog8.codegen.virtual import prog8.code.StStaticVariable import prog8.code.ast.* -import prog8.code.core.ArrayToElementTypes import prog8.code.core.AssemblyError import prog8.code.core.DataType import prog8.vm.Opcode @@ -241,32 +240,54 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen: private fun funcPokeW(call: PtBuiltinFunctionCall): VmCodeChunk { val code = VmCodeChunk() - 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, -1) - code += VmCodeInstruction(Opcode.STOREM, VmDataType.WORD, reg1 = valueReg, value=address) + if(codeGen.isZero(call.args[1])) { + if (call.args[0] is PtNumber) { + val address = (call.args[0] as PtNumber).number.toInt() + code += VmCodeInstruction(Opcode.STOREZM, VmDataType.WORD, value = address) + } else { + val addressReg = codeGen.vmRegisters.nextFree() + code += exprGen.translateExpression(call.args[0], addressReg, -1) + code += VmCodeInstruction(Opcode.STOREZI, VmDataType.WORD, reg2 = addressReg) + } } else { - val addressReg = codeGen.vmRegisters.nextFree() - code += exprGen.translateExpression(call.args[0], addressReg, -1) - code += exprGen.translateExpression(call.args[1], valueReg, -1) - 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, -1) + code += VmCodeInstruction(Opcode.STOREM, VmDataType.WORD, reg1 = valueReg, value = address) + } else { + val addressReg = codeGen.vmRegisters.nextFree() + code += exprGen.translateExpression(call.args[0], addressReg, -1) + code += exprGen.translateExpression(call.args[1], valueReg, -1) + code += VmCodeInstruction(Opcode.STOREI, VmDataType.WORD, reg1 = valueReg, reg2 = addressReg) + } } return code } private fun funcPoke(call: PtBuiltinFunctionCall): VmCodeChunk { val code = VmCodeChunk() - 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, -1) - code += VmCodeInstruction(Opcode.STOREM, VmDataType.BYTE, reg1 = valueReg, value=address) + if(codeGen.isZero(call.args[1])) { + if (call.args[0] is PtNumber) { + val address = (call.args[0] as PtNumber).number.toInt() + code += VmCodeInstruction(Opcode.STOREZM, VmDataType.BYTE, value = address) + } else { + val addressReg = codeGen.vmRegisters.nextFree() + code += exprGen.translateExpression(call.args[0], addressReg, -1) + code += VmCodeInstruction(Opcode.STOREZI, VmDataType.BYTE, reg2 = addressReg) + } } else { - val addressReg = codeGen.vmRegisters.nextFree() - code += exprGen.translateExpression(call.args[0], addressReg, -1) - code += exprGen.translateExpression(call.args[1], valueReg, -1) - 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, -1) + code += VmCodeInstruction(Opcode.STOREM, VmDataType.BYTE, reg1 = valueReg, value = address) + } else { + val addressReg = codeGen.vmRegisters.nextFree() + code += exprGen.translateExpression(call.args[0], addressReg, -1) + code += exprGen.translateExpression(call.args[1], valueReg, -1) + code += VmCodeInstruction(Opcode.STOREI, VmDataType.BYTE, reg1 = valueReg, reg2 = addressReg) + } } return code } @@ -361,5 +382,4 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen: code += codeGen.translateNode(assignment) return code } - } diff --git a/codeGenVirtual/src/prog8/codegen/virtual/CodeGen.kt b/codeGenVirtual/src/prog8/codegen/virtual/CodeGen.kt index 3f3ec3eb2..e83e6e97c 100644 --- a/codeGenVirtual/src/prog8/codegen/virtual/CodeGen.kt +++ b/codeGenVirtual/src/prog8/codegen/virtual/CodeGen.kt @@ -6,7 +6,6 @@ import prog8.code.ast.* import prog8.code.core.* import prog8.vm.Opcode import prog8.vm.VmDataType -import java.nio.file.Path import kotlin.math.pow @@ -410,7 +409,7 @@ class CodeGen(internal val program: PtProgram, // just shift multiple bits val pow2reg = vmRegisters.nextFree() code += VmCodeInstruction(Opcode.LOAD, dt, reg1=pow2reg, value=pow2) - code += VmCodeInstruction(Opcode.LSLX, dt, reg1=reg, reg2=reg, reg3=pow2reg) + code += VmCodeInstruction(Opcode.LSLN, dt, reg1=reg, reg2=reg, reg3=pow2reg) } else { if (factor == 0) { code += VmCodeInstruction(Opcode.LOAD, dt, reg1=reg, value=0) @@ -451,7 +450,7 @@ class CodeGen(internal val program: PtProgram, // just shift multiple bits val pow2reg = vmRegisters.nextFree() code += VmCodeInstruction(Opcode.LOAD, dt, reg1=pow2reg, value=pow2) - code += VmCodeInstruction(Opcode.LSRX, dt, reg1=reg, reg2=reg, reg3=pow2reg) + code += VmCodeInstruction(Opcode.LSRN, dt, reg1=reg, reg2=reg, reg3=pow2reg) } else { if (factor == 0) { code += VmCodeInstruction(Opcode.LOAD, dt, reg1=reg, value=0xffff) @@ -615,24 +614,32 @@ class CodeGen(internal val program: PtProgram, val vmDt = vmType(assignment.value.type) var resultRegister = -1 var resultFpRegister = -1 - if(vmDt==VmDataType.FLOAT) { - resultFpRegister = vmRegisters.nextFreeFloat() - code += expressionEval.translateExpression(assignment.value, -1, resultFpRegister) - } else { - resultRegister = if (assignment.value is PtMachineRegister) { - (assignment.value as PtMachineRegister).register + val zero = isZero(assignment.value) + if(!zero) { + // calculate the assignment value + if (vmDt == VmDataType.FLOAT) { + resultFpRegister = vmRegisters.nextFreeFloat() + code += expressionEval.translateExpression(assignment.value, -1, resultFpRegister) } else { - val reg = vmRegisters.nextFree() - code += expressionEval.translateExpression(assignment.value, reg, -1) - reg + resultRegister = if (assignment.value is PtMachineRegister) { + (assignment.value as PtMachineRegister).register + } else { + val reg = vmRegisters.nextFree() + code += expressionEval.translateExpression(assignment.value, reg, -1) + reg + } } } if(ident!=null) { val address = allocations.get(ident.targetName) - code += if(vmDt==VmDataType.FLOAT) - VmCodeInstruction(Opcode.STOREM, vmDt, fpReg1=resultFpRegister, value=address) - else - VmCodeInstruction(Opcode.STOREM, vmDt, reg1=resultRegister, value=address) + code += if(zero) { + VmCodeInstruction(Opcode.STOREZM, vmDt, value = address) + } else { + if (vmDt == VmDataType.FLOAT) + VmCodeInstruction(Opcode.STOREM, vmDt, fpReg1 = resultFpRegister, value = address) + else + VmCodeInstruction(Opcode.STOREM, vmDt, reg1 = resultRegister, value = address) + } } else if(array!=null) { val variable = array.variable.targetName @@ -640,23 +647,45 @@ class CodeGen(internal val program: PtProgram, val itemsize = program.memsizer.memorySize(array.type) val fixedIndex = constIntValue(array.index) val vmDtArrayIdx = vmType(array.type) - if(fixedIndex!=null) { - variableAddr += fixedIndex*itemsize - code += VmCodeInstruction(Opcode.STOREM, vmDtArrayIdx, reg1 = resultRegister, value=variableAddr) + // TODO floating point array incorrect? + if(zero) { + if(fixedIndex!=null) { + variableAddr += fixedIndex*itemsize + code += VmCodeInstruction(Opcode.STOREZM, vmDtArrayIdx, value=variableAddr) + } else { + val indexReg = vmRegisters.nextFree() + code += expressionEval.translateExpression(array.index, indexReg, -1) + code += VmCodeInstruction(Opcode.STOREZX, vmDtArrayIdx, reg1=indexReg, value=variableAddr) + } } else { - val indexReg = vmRegisters.nextFree() - code += expressionEval.translateExpression(array.index, indexReg, -1) - code += VmCodeInstruction(Opcode.STOREX, vmDtArrayIdx, reg1 = resultRegister, reg2=indexReg, value=variableAddr) + if(fixedIndex!=null) { + variableAddr += fixedIndex*itemsize + code += VmCodeInstruction(Opcode.STOREM, vmDtArrayIdx, reg1 = resultRegister, value=variableAddr) + } else { + val indexReg = vmRegisters.nextFree() + code += expressionEval.translateExpression(array.index, indexReg, -1) + code += VmCodeInstruction(Opcode.STOREX, vmDtArrayIdx, reg1 = resultRegister, reg2=indexReg, value=variableAddr) + } } } else if(memory!=null) { require(vmDt==VmDataType.BYTE) - if(memory.address is PtNumber) { - code += VmCodeInstruction(Opcode.STOREM, vmDt, reg1=resultRegister, value=(memory.address as PtNumber).number.toInt()) + if(zero) { + if(memory.address is PtNumber) { + code += VmCodeInstruction(Opcode.STOREZM, vmDt, value=(memory.address as PtNumber).number.toInt()) + } else { + val addressReg = vmRegisters.nextFree() + code += expressionEval.translateExpression(memory.address, addressReg, -1) + code += VmCodeInstruction(Opcode.STOREZI, vmDt, reg1=addressReg) + } } else { - val addressReg = vmRegisters.nextFree() - code += expressionEval.translateExpression(memory.address, addressReg, -1) - code += VmCodeInstruction(Opcode.STOREI, vmDt, reg1=resultRegister, reg2=addressReg) + if(memory.address is PtNumber) { + code += VmCodeInstruction(Opcode.STOREM, vmDt, reg1=resultRegister, value=(memory.address as PtNumber).number.toInt()) + } else { + val addressReg = vmRegisters.nextFree() + code += expressionEval.translateExpression(memory.address, addressReg, -1) + code += VmCodeInstruction(Opcode.STOREI, vmDt, reg1=resultRegister, reg2=addressReg) + } } } else @@ -722,4 +751,6 @@ class CodeGen(internal val program: PtProgram, internal fun translateBuiltinFunc(call: PtBuiltinFunctionCall, resultRegister: Int): VmCodeChunk = builtinFuncGen.translate(call, resultRegister) + + internal fun isZero(expression: PtExpression): Boolean = expression is PtNumber && expression.number==0.0 } diff --git a/codeGenVirtual/src/prog8/codegen/virtual/ExpressionGen.kt b/codeGenVirtual/src/prog8/codegen/virtual/ExpressionGen.kt index 4d55977d2..660113ebf 100644 --- a/codeGenVirtual/src/prog8/codegen/virtual/ExpressionGen.kt +++ b/codeGenVirtual/src/prog8/codegen/virtual/ExpressionGen.kt @@ -9,7 +9,6 @@ import prog8.code.core.PassByValueDatatypes import prog8.code.core.SignedDatatypes import prog8.vm.Opcode import prog8.vm.VmDataType -import java.nio.channels.FileLock internal class ExpressionGen(private val codeGen: CodeGen) { @@ -174,6 +173,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) { private fun translate(expr: PtPrefix, resultRegister: Int): VmCodeChunk { val code = VmCodeChunk() + // TODO if the value is a variable or memory read, use memory-versions of the opcodes instead of using intermediary register code += translateExpression(expr.value, resultRegister, -1) val vmDt = codeGen.vmType(expr.type) when(expr.operator) { @@ -363,22 +363,24 @@ internal class ExpressionGen(private val codeGen: CodeGen) { private fun operatorShiftRight(binExpr: PtBinaryExpression, vmDt: VmDataType, resultRegister: Int, signed: Boolean): VmCodeChunk { val code = VmCodeChunk() + // TODO if shift is 1, use ASR/LSR instruction instead of multishift val leftResultReg = codeGen.vmRegisters.nextFree() val rightResultReg = codeGen.vmRegisters.nextFree() code += translateExpression(binExpr.left, leftResultReg, -1) code += translateExpression(binExpr.right, rightResultReg, -1) - val opc = if(signed) Opcode.ASRX else Opcode.LSRX + val opc = if(signed) Opcode.ASRN else Opcode.LSRN code += VmCodeInstruction(opc, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg) return code } private fun operatorShiftLeft(binExpr: PtBinaryExpression, vmDt: VmDataType, resultRegister: Int): VmCodeChunk { val code = VmCodeChunk() + // TODO if shift is 1, use LSL instruction instead of multishift val leftResultReg = codeGen.vmRegisters.nextFree() val rightResultReg = codeGen.vmRegisters.nextFree() code += translateExpression(binExpr.left, leftResultReg, -1) code += translateExpression(binExpr.right, rightResultReg, -1) - code += VmCodeInstruction(Opcode.LSLX, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg) + code += VmCodeInstruction(Opcode.LSLN, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg) return code } @@ -568,16 +570,26 @@ internal class ExpressionGen(private val codeGen: CodeGen) { val code = VmCodeChunk() for ((arg, parameter) in fcall.args.zip(subroutine.parameters)) { val paramDt = codeGen.vmType(parameter.type) - if(paramDt==VmDataType.FLOAT) { - val argFpReg = codeGen.vmRegisters.nextFreeFloat() - code += translateExpression(arg, -1, argFpReg) - val mem = codeGen.allocations.get(fcall.functionName + parameter.name) - code += VmCodeInstruction(Opcode.STOREM, paramDt, fpReg1 = argFpReg, value = mem) + if(codeGen.isZero(arg)) { + if (paramDt == VmDataType.FLOAT) { + val mem = codeGen.allocations.get(fcall.functionName + parameter.name) + code += VmCodeInstruction(Opcode.STOREZM, paramDt, value = mem) + } else { + val mem = codeGen.allocations.get(fcall.functionName + parameter.name) + code += VmCodeInstruction(Opcode.STOREZM, paramDt, value = mem) + } } else { - val argReg = codeGen.vmRegisters.nextFree() - code += translateExpression(arg, argReg, -1) - val mem = codeGen.allocations.get(fcall.functionName + parameter.name) - code += VmCodeInstruction(Opcode.STOREM, paramDt, reg1 = argReg, value = mem) + if (paramDt == VmDataType.FLOAT) { + val argFpReg = codeGen.vmRegisters.nextFreeFloat() + code += translateExpression(arg, -1, argFpReg) + val mem = codeGen.allocations.get(fcall.functionName + parameter.name) + code += VmCodeInstruction(Opcode.STOREM, paramDt, fpReg1 = argFpReg, value = mem) + } else { + val argReg = codeGen.vmRegisters.nextFree() + code += translateExpression(arg, argReg, -1) + val mem = codeGen.allocations.get(fcall.functionName + parameter.name) + code += VmCodeInstruction(Opcode.STOREM, paramDt, reg1 = argReg, value = mem) + } } } code += VmCodeInstruction(Opcode.CALL, symbol=fcall.functionName) diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 261fb5e3d..7ef07ffff 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -3,7 +3,11 @@ TODO For next release ^^^^^^^^^^^^^^^^ -- vm: add way more instructions operating directly on memory instead of only registers +- vm: assignment to float array is not correct? also zero? +- vm: use more instructions in codegen: shift one +- vm: use more instructions in codegen: branching +- vm: add more instructions operating directly on memory instead of only registers? +- in-place modifiying functions (rol, ror, ..) don't accept a memory address but require a memory-read expression. that is weird. - complete the Inliner - add McCarthy evaluation to shortcircuit and/or expressions. First do ifs by splitting them up? Then do expressions that compute a value? diff --git a/examples/test.p8 b/examples/test.p8 index 44f44744f..d464d4436 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -6,21 +6,57 @@ ; NOTE: meant to test to virtual machine output target (use -target vitual) main { - ubyte value = 42 +; ubyte value = 42 +; +; sub inline_candidate() -> ubyte { +; return math.sin8u(value) +; } +; +; sub add(ubyte first, ubyte second) -> ubyte { +; return first + second +; } +; +; sub mul(ubyte first, ubyte second) -> ubyte { +; return first * second +; } - sub derp() -> ubyte { - return math.sin8u(value) + sub ding(uword arg) { + arg++ + txt.print_uw(arg) } sub start() { - ubyte value = derp() - txt.print_ub(value) + ding(0) txt.nl() - txt.print_ub(derp()) + ding(2) txt.nl() - ; TODO: test with builtin function using multiple args (such as mkword) -; ubyte value = add(3,4) |> add(10) |> mul(2) |> math.sin8u() ; TODO should not work yet on vm codegen, but it compiles.... :/ +; ubyte value = inline_candidate() +; byte svalue = 99 +; svalue = -svalue +; @($5000) = not @($5000) +; rol(value) +; rol(@($5000)) +; ror(value) +; ror(@($5000)) +; rol2(value) +; rol2(@($5000)) +; ror2(value) +; ror2(@($5000)) +; @($5000) <<= 1 +; @($5000) >>= 1 +; value <<= 1 +; value >>= 1 +; @($5000) <<= 3 +; @($5000) >>= 3 +; value <<= 3 +; value >>= 3 +; txt.print_ub(value) +; txt.nl() +; txt.print_ub(inline_candidate()) +; txt.nl() + +; ubyte value = add(3,4) |> add(10) |> mul(2) |> math.sin8u() ; txt.print_ub(value) ; txt.nl() ; uword wvalue = add(3,4) |> add($30) |> mkword($ea) diff --git a/virtualmachine/src/prog8/vm/Instructions.kt b/virtualmachine/src/prog8/vm/Instructions.kt index 119352cfc..337bad923 100644 --- a/virtualmachine/src/prog8/vm/Instructions.kt +++ b/virtualmachine/src/prog8/vm/Instructions.kt @@ -31,7 +31,7 @@ loadr reg1, reg2 - load reg1 with value at register reg2 storem reg1, address - store reg1 at memory address storei reg1, reg2 - store reg1 at memory indirect, memory pointed to by reg2 storex reg1, reg2, address - store reg1 at memory address, indexed by value in reg2 -storez address - store zero at memory address +storezm address - store zero at memory address storezi reg1 - store zero at memory pointed to by reg1 storezx reg1, address - store zero at memory address, indexed by value in reg @@ -89,8 +89,8 @@ ARITHMETIC ---------- All have type b or w or f. Note: result types are the same as operand types! E.g. byte*byte->byte. -ext reg1 - reg1 = unsigned extension of reg1 (which in practice just means clearing the MSB / MSW) (latter not yet implemented as we don't have longs yet) -exts reg1 - reg1 = signed extension of reg1 (byte to word, or word to long) (note: latter ext.w, not yet implemented as we don't have longs yet) +ext reg1 - reg1 = unsigned extension of reg1 (which in practice just means clearing the MSB / MSW) (ext.w not yet implemented as we don't have longs yet) +exts reg1 - reg1 = signed extension of reg1 (byte to word, or word to long) (note: ext.w is not yet implemented as we don't have longs yet) inc reg1 - reg1 = reg1+1 incm address - memory at address += 1 dec reg1 - reg1 = reg1-1 @@ -116,9 +116,9 @@ All have type b or w. and reg1, reg2, reg3 - reg1 = reg2 bitwise and reg3 or reg1, reg2, reg3 - reg1 = reg2 bitwise or reg3 xor reg1, reg2, reg3 - reg1 = reg2 bitwise xor reg3 -lsrx reg1, reg2, reg3 - reg1 = multi-shift reg2 right by reg3 bits + set Carry to shifted bit -asrx reg1, reg2, reg3 - reg1 = multi-shift reg2 right by reg3 bits (signed) + set Carry to shifted bit -lslx reg1, reg2, reg3 - reg1 = multi-shift reg2 left by reg3 bits + set Carry to shifted bit +lsrn reg1, reg2, reg3 - reg1 = multi-shift reg2 right by reg3 bits + set Carry to shifted bit +asrn reg1, reg2, reg3 - reg1 = multi-shift reg2 right by reg3 bits (signed) + set Carry to shifted bit +lsln reg1, reg2, reg3 - reg1 = multi-shift reg2 left by reg3 bits + set Carry to shifted bit lsr reg1 - shift reg1 right by 1 bits + set Carry to shifted bit asr reg1 - shift reg1 right by 1 bits (signed) + set Carry to shifted bit lsl reg1 - shift reg1 left by 1 bits + set Carry to shifted bit @@ -149,10 +149,7 @@ clc - clear Carry status bit sec - set Carry status bit nop - do nothing breakpoint - trigger a breakpoint -copy reg1, reg2, length - copy memory from ptrs in reg1 to reg3, length bytes -copyz reg1, reg2 - copy memory from ptrs in reg1 to reg3, stop after first 0-byte msig [b, w] reg1, reg2 - reg1 becomes the most significant byte (or word) of the word (or int) in reg2 (.w not yet implemented; requires 32 bits regs) -swapreg reg1, reg2 - swap values in reg1 and reg2 concat [b, w] reg1, reg2, reg3 - reg1 = concatenated lsb/lsw of reg2 and lsb/lsw of reg3 into new word or int (int not yet implemented; requires 32bits regs) push [b, w] reg1 - push value in reg1 on the stack pop [b, w] reg1 - pop value from stack into reg1 @@ -169,14 +166,12 @@ enum class Opcode { STOREM, STOREI, STOREX, - STOREZ, + STOREZM, STOREZI, STOREZX, JUMP, - JUMPI, CALL, - CALLI, SYSCALL, RETURN, @@ -190,14 +185,14 @@ enum class Opcode { BNZ, BEQ, BNE, - BLT, - BLTS, - BGT, - BGTS, - BLE, - BLES, - BGE, - BGES, + BLT, // TODO not used in codegen??? < + BLTS, // TODO not used in codegen??? < + BGT, // TODO not used in codegen??? > + BGTS, // TODO not used in codegen??? > + BLE, // TODO should be used in codegen conditional branch too + BLES, // TODO should be used in codegen conditional branch too + BGE, // TODO not used in codegen??? >= + BGES, // TODO not used in codegen??? >= SEQ, SNE, SLT, @@ -229,12 +224,12 @@ enum class Opcode { AND, OR, XOR, - ASRX, - LSRX, - LSLX, - ASR, - LSR, - LSL, + ASRN, + LSRN, + LSLN, + ASR, // TODO not used in codegen of shift 1 + LSR, // TODO not used in codegen of shift 1 + LSL, // TODO not used in codegen of shift 1 ROR, ROXR, ROL, @@ -266,7 +261,6 @@ enum class Opcode { PUSH, POP, MSIG, - SWAPREG, CONCAT, BREAKPOINT } @@ -276,7 +270,7 @@ val OpcodesWithAddress = setOf( Opcode.LOADX, Opcode.STOREM, Opcode.STOREX, - Opcode.STOREZ, + Opcode.STOREZM, Opcode.STOREZX ) @@ -443,17 +437,14 @@ val instructionFormats = mutableMapOf( Opcode.LOADI to InstructionFormat.from("BW,r1,r2 | F,fr1,r1"), Opcode.LOADX to InstructionFormat.from("BW,r1,r2,v | F,fr1,r1,v"), Opcode.LOADR to InstructionFormat.from("BW,r1,r2 | F,fr1,fr2"), - Opcode.SWAPREG to InstructionFormat.from("BW,r1,r2 | F,fr1,fr2"), Opcode.STOREM to InstructionFormat.from("BW,r1,v | F,fr1,v"), Opcode.STOREI to InstructionFormat.from("BW,r1,r2 | F,fr1,r1"), Opcode.STOREX to InstructionFormat.from("BW,r1,r2,v | F,fr1,r1,v"), - Opcode.STOREZ to InstructionFormat.from("BW,v | F,v"), + Opcode.STOREZM to InstructionFormat.from("BW,v | F,v"), Opcode.STOREZI to InstructionFormat.from("BW,r1 | F,r1"), Opcode.STOREZX to InstructionFormat.from("BW,r1,v | F,r1,v"), Opcode.JUMP to InstructionFormat.from("N,v"), - Opcode.JUMPI to InstructionFormat.from("N,r1"), Opcode.CALL to InstructionFormat.from("N,v"), - Opcode.CALLI to InstructionFormat.from("N,r1"), Opcode.SYSCALL to InstructionFormat.from("N,v"), Opcode.RETURN to InstructionFormat.from("N"), Opcode.BSTCC to InstructionFormat.from("N,v"), @@ -503,9 +494,9 @@ val instructionFormats = mutableMapOf( Opcode.AND to InstructionFormat.from("BW,r1,r2,r3"), Opcode.OR to InstructionFormat.from("BW,r1,r2,r3"), Opcode.XOR to InstructionFormat.from("BW,r1,r2,r3"), - Opcode.ASRX to InstructionFormat.from("BW,r1,r2,r3"), - Opcode.LSRX to InstructionFormat.from("BW,r1,r2,r3"), - Opcode.LSLX to InstructionFormat.from("BW,r1,r2,r3"), + Opcode.ASRN to InstructionFormat.from("BW,r1,r2,r3"), + Opcode.LSRN to InstructionFormat.from("BW,r1,r2,r3"), + Opcode.LSLN to InstructionFormat.from("BW,r1,r2,r3"), Opcode.ASR to InstructionFormat.from("BW,r1"), Opcode.LSR to InstructionFormat.from("BW,r1"), Opcode.LSL to InstructionFormat.from("BW,r1"), diff --git a/virtualmachine/src/prog8/vm/VirtualMachine.kt b/virtualmachine/src/prog8/vm/VirtualMachine.kt index 0bae365da..8495455df 100644 --- a/virtualmachine/src/prog8/vm/VirtualMachine.kt +++ b/virtualmachine/src/prog8/vm/VirtualMachine.kt @@ -92,17 +92,14 @@ class VirtualMachine(val memory: Memory, program: List) { Opcode.LOADX -> InsLOADX(ins) Opcode.LOADI -> InsLOADI(ins) Opcode.LOADR -> InsLOADR(ins) - Opcode.SWAPREG -> InsSWAPREG(ins) Opcode.STOREM -> InsSTOREM(ins) Opcode.STOREX -> InsSTOREX(ins) Opcode.STOREI -> InsSTOREI(ins) - Opcode.STOREZ -> InsSTOREZ(ins) + Opcode.STOREZM -> InsSTOREZ(ins) Opcode.STOREZX -> InsSTOREZX(ins) Opcode.STOREZI -> InsSTOREZI(ins) Opcode.JUMP -> InsJUMP(ins) - Opcode.JUMPI -> InsJUMPI(ins) Opcode.CALL -> InsCALL(ins) - Opcode.CALLI -> InsCALLI(ins) Opcode.SYSCALL -> InsSYSCALL(ins) Opcode.RETURN -> InsRETURN() Opcode.BSTCC -> InsBSTCC(ins) @@ -153,9 +150,9 @@ class VirtualMachine(val memory: Memory, program: List) { Opcode.AND -> InsAND(ins) Opcode.OR -> InsOR(ins) Opcode.XOR -> InsXOR(ins) - Opcode.ASRX -> InsASRM(ins) - Opcode.LSRX -> InsLSRM(ins) - Opcode.LSLX -> InsLSLM(ins) + Opcode.ASRN -> InsASRM(ins) + Opcode.LSRN -> InsLSRM(ins) + Opcode.LSLN -> InsLSLM(ins) Opcode.ASR -> InsASR(ins) Opcode.LSR -> InsLSR(ins) Opcode.LSL -> InsLSL(ins) @@ -297,27 +294,6 @@ class VirtualMachine(val memory: Memory, program: List) { pc++ } - private fun InsSWAPREG(i: Instruction) { - when(i.type!!) { - VmDataType.BYTE -> { - val oldR2 = registers.getUB(i.reg2!!) - registers.setUB(i.reg2, registers.getUB(i.reg1!!)) - registers.setUB(i.reg1, oldR2) - } - VmDataType.WORD -> { - val oldR2 = registers.getUW(i.reg2!!) - registers.setUW(i.reg2, registers.getUW(i.reg1!!)) - registers.setUW(i.reg1, oldR2) - } - VmDataType.FLOAT -> { - val oldR2 = registers.getFloat(i.fpReg2!!) - registers.setFloat(i.fpReg2, registers.getFloat(i.fpReg1!!)) - registers.setFloat(i.fpReg1, oldR2) - } - } - pc++ - } - private fun InsSTOREM(i: Instruction) { when(i.type!!) { VmDataType.BYTE -> memory.setUB(i.value!!, registers.getUB(i.reg1!!)) @@ -351,6 +327,7 @@ class VirtualMachine(val memory: Memory, program: List) { VmDataType.WORD -> memory.setUW(i.value!!, 0u) VmDataType.FLOAT -> memory.setFloat(i.value!!, 0f) } + pc++ } private fun InsSTOREZI(i: Instruction) { @@ -375,20 +352,11 @@ class VirtualMachine(val memory: Memory, program: List) { pc = i.value!! } - private fun InsJUMPI(i: Instruction) { - pc = registers.getUW(i.reg1!!).toInt() - } - private fun InsCALL(i: Instruction) { callStack.push(pc+1) pc = i.value!! } - private fun InsCALLI(i: Instruction) { - callStack.push(pc+1) - pc = registers.getUW(i.reg1!!).toInt() - } - private fun InsRETURN() { if(callStack.isEmpty()) exit()