From e09f05405870378339e7b4d77341522248a1e7b0 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Mon, 23 May 2022 20:26:44 +0200 Subject: [PATCH] vm: implemented in-place bit rotate instructions --- .../src/prog8/codegen/virtual/CodeGen.kt | 1 - docs/source/todo.rst | 1 - virtualmachine/src/prog8/vm/Instructions.kt | 40 +++++++---- virtualmachine/src/prog8/vm/VirtualMachine.kt | 68 +++++++++++++++++++ 4 files changed, 95 insertions(+), 15 deletions(-) diff --git a/codeGenVirtual/src/prog8/codegen/virtual/CodeGen.kt b/codeGenVirtual/src/prog8/codegen/virtual/CodeGen.kt index ef2d65074..d714186f1 100644 --- a/codeGenVirtual/src/prog8/codegen/virtual/CodeGen.kt +++ b/codeGenVirtual/src/prog8/codegen/virtual/CodeGen.kt @@ -772,7 +772,6 @@ class CodeGen(internal val program: PtProgram, } private fun translate(sub: PtSub): VmCodeChunk { - // TODO actually inline subroutines marked as inline (but at this time only asmsub can be inline) val code = VmCodeChunk() code += VmCodeComment("SUB: ${sub.scopedName} -> ${sub.returntype}") code += VmCodeLabel(sub.scopedName) diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 8e33697e2..56aed5396 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -3,7 +3,6 @@ TODO For next release ^^^^^^^^^^^^^^^^ -- vm: implement the 4 rol/ror memory in-place instructions ... diff --git a/virtualmachine/src/prog8/vm/Instructions.kt b/virtualmachine/src/prog8/vm/Instructions.kt index ff5d43bdb..8e3ed64be 100644 --- a/virtualmachine/src/prog8/vm/Instructions.kt +++ b/virtualmachine/src/prog8/vm/Instructions.kt @@ -120,31 +120,33 @@ LOGICAL/BITWISE All have type b or w. and reg1, reg2 - reg1 = reg1 bitwise and reg2 -andm reg1 address - memory = memory bitwise and reg1 or reg1, reg2 - reg1 = reg1 bitwise or reg2 -orm reg1, address - memory = memory bitwise or reg1 xor reg1, reg2 - reg1 = reg1 bitwise xor reg2 -xorm reg1, address - memory = memory bitwise xor reg1 not reg1 - reg1 = boolean not of reg1 (0->1 , ~0 -> 0) -notm address - memory = boolean not of that memory (0->1 , ~0 -> 0) lsrn reg1, reg2 - reg1 = multi-shift reg1 right by reg2 bits + set Carry to shifted bit -lsrnm reg1, address - multi-shift memoryright by reg1 bits + set Carry to shifted bit asrn reg1, reg2 - reg1 = multi-shift reg1 right by reg2 bits (signed) + set Carry to shifted bit -asrnm reg1, address - multi-shift memory right by reg1 bits (signed) + set Carry to shifted bit lsln reg1, reg2 - reg1 = multi-shift reg1 left by reg2 bits + set Carry to shifted bit -lslnm reg1, address - multi-shift memory left by reg1 bits + set Carry to shifted bit lsr reg1 - shift reg1 right by 1 bits + set Carry to shifted bit -lsrm address - shift memory right by 1 bits + set Carry to shifted bit asr reg1 - shift reg1 right by 1 bits (signed) + set Carry to shifted bit -asrm address - shift memory right by 1 bits (signed) + set Carry to shifted bit lsl reg1 - shift reg1 left by 1 bits + set Carry to shifted bit -lslm address - shift memory left by 1 bits + set Carry to shifted bit ror reg1 - rotate reg1 right by 1 bits, not using carry + set Carry to shifted bit roxr reg1 - rotate reg1 right by 1 bits, using carry + set Carry to shifted bit rol reg1 - rotate reg1 left by 1 bits, not using carry + set Carry to shifted bit roxl reg1 - rotate reg1 left by 1 bits, using carry, + set Carry to shifted bit - -TODO: add memory-rotate instructions? +andm reg1 address - memory = memory bitwise and reg1 +orm reg1, address - memory = memory bitwise or reg1 +xorm reg1, address - memory = memory bitwise xor reg1 +notm address - memory = boolean not of that memory (0->1 , ~0 -> 0) +lsrnm reg1, address - multi-shift memoryright by reg1 bits + set Carry to shifted bit +asrnm reg1, address - multi-shift memory right by reg1 bits (signed) + set Carry to shifted bit +lslnm reg1, address - multi-shift memory left by reg1 bits + set Carry to shifted bit +lsrm address - shift memory right by 1 bits + set Carry to shifted bit +asrm address - shift memory right by 1 bits (signed) + set Carry to shifted bit +lslm address - shift memory left by 1 bits + set Carry to shifted bit +rorm address - rotate memory right by 1 bits, not using carry + set Carry to shifted bit +roxrm address - rotate memory right by 1 bits, using carry + set Carry to shifted bit +rolm address - rotate memory left by 1 bits, not using carry + set Carry to shifted bit +roxlm address - rotate memory left by 1 bits, using carry, + set Carry to shifted bit FLOATING POINT CONVERSIONS AND FUNCTIONS @@ -269,9 +271,13 @@ enum class Opcode { LSL, LSLM, ROR, + RORM, ROXR, + ROXRM, ROL, + ROLM, ROXL, + ROXLM, FFROMUB, FFROMSB, @@ -328,7 +334,11 @@ val OpcodesWithAddress = setOf( Opcode.LSLM, Opcode.LSLNM, Opcode.LSRNM, - Opcode.ASRNM + Opcode.ASRNM, + Opcode.ROLM, + Opcode.RORM, + Opcode.ROXLM, + Opcode.ROXRM ) @@ -554,9 +564,13 @@ val instructionFormats = mutableMapOf( Opcode.LSL to InstructionFormat.from("BW,r1"), Opcode.LSLM to InstructionFormat.from("BW,v"), Opcode.ROR to InstructionFormat.from("BW,r1"), + Opcode.RORM to InstructionFormat.from("BW,v"), Opcode.ROXR to InstructionFormat.from("BW,r1"), + Opcode.ROXRM to InstructionFormat.from("BW,v"), Opcode.ROL to InstructionFormat.from("BW,r1"), + Opcode.ROLM to InstructionFormat.from("BW,v"), Opcode.ROXL to InstructionFormat.from("BW,r1"), + Opcode.ROXLM to InstructionFormat.from("BW,v"), Opcode.FFROMUB to InstructionFormat.from("F,fr1,r1"), Opcode.FFROMSB to InstructionFormat.from("F,fr1,r1"), diff --git a/virtualmachine/src/prog8/vm/VirtualMachine.kt b/virtualmachine/src/prog8/vm/VirtualMachine.kt index 50b53b4b2..5e55f8679 100644 --- a/virtualmachine/src/prog8/vm/VirtualMachine.kt +++ b/virtualmachine/src/prog8/vm/VirtualMachine.kt @@ -175,9 +175,13 @@ class VirtualMachine(val memory: Memory, program: List) { Opcode.LSRM -> InsLSRM(ins) Opcode.LSLM -> InsLSLM(ins) Opcode.ROR -> InsROR(ins, false) + Opcode.RORM -> InsRORM(ins, false) Opcode.ROXR -> InsROR(ins, true) + Opcode.ROXRM -> InsRORM(ins, true) Opcode.ROL -> InsROL(ins, false) + Opcode.ROLM -> InsROLM(ins, false) Opcode.ROXL -> InsROL(ins, true) + Opcode.ROXLM -> InsROLM(ins, true) Opcode.MSIG -> InsMSIG(ins) Opcode.CONCAT -> InsCONCAT(ins) Opcode.PUSH -> InsPUSH(ins) @@ -1399,6 +1403,38 @@ class VirtualMachine(val memory: Memory, program: List) { statusCarry = newStatusCarry } + private fun InsRORM(i: Instruction, useCarry: Boolean) { + val newStatusCarry: Boolean + val address = i.value!! + when (i.type!!) { + VmDataType.BYTE -> { + val orig = memory.getUB(address) + newStatusCarry = (orig.toInt() and 1) != 0 + val rotated: UByte = if (useCarry) { + val carry = if (statusCarry) 0x80u else 0x00u + (orig.toUInt().rotateRight(1) or carry).toUByte() + } else + orig.rotateRight(1) + memory.setUB(address, rotated) + } + VmDataType.WORD -> { + val orig = memory.getUW(address) + newStatusCarry = (orig.toInt() and 1) != 0 + val rotated: UShort = if (useCarry) { + val carry = if (statusCarry) 0x8000u else 0x0000u + (orig.toUInt().rotateRight(1) or carry).toUShort() + } else + orig.rotateRight(1) + memory.setUW(address, rotated) + } + VmDataType.FLOAT -> { + throw IllegalArgumentException("can't ROR a float") + } + } + pc++ + statusCarry = newStatusCarry + } + private fun InsROL(i: Instruction, useCarry: Boolean) { val newStatusCarry: Boolean when (i.type!!) { @@ -1430,6 +1466,38 @@ class VirtualMachine(val memory: Memory, program: List) { statusCarry = newStatusCarry } + private fun InsROLM(i: Instruction, useCarry: Boolean) { + val address = i.value!! + val newStatusCarry: Boolean + when (i.type!!) { + VmDataType.BYTE -> { + val orig = memory.getUB(address) + newStatusCarry = (orig.toInt() and 0x80) != 0 + val rotated: UByte = if (useCarry) { + val carry = if (statusCarry) 1u else 0u + (orig.toUInt().rotateLeft(1) or carry).toUByte() + } else + orig.rotateLeft(1) + memory.setUB(address, rotated) + } + VmDataType.WORD -> { + val orig = memory.getUW(address) + newStatusCarry = (orig.toInt() and 0x8000) != 0 + val rotated: UShort = if (useCarry) { + val carry = if (statusCarry) 1u else 0u + (orig.toUInt().rotateLeft(1) or carry).toUShort() + } else + orig.rotateLeft(1) + memory.setUW(address, rotated) + } + VmDataType.FLOAT -> { + throw IllegalArgumentException("can't ROL a float") + } + } + pc++ + statusCarry = newStatusCarry + } + private fun InsMSIG(i: Instruction) { when(i.type!!) { VmDataType.BYTE -> {