diff --git a/src/optable.py b/src/optable.py index 8daa5dd..7c51de2 100644 --- a/src/optable.py +++ b/src/optable.py @@ -29,7 +29,7 @@ class OpcodeActions(Enum): LOAD = auto() STORE = auto() BRANCH = auto() - MEM_BRANCH = auto() + IND_BRANCH = auto() OpA = OpcodeActions diff --git a/src/vm.py b/src/vm.py index a8d4097..9794968 100644 --- a/src/vm.py +++ b/src/vm.py @@ -1,6 +1,6 @@ from dataclasses import dataclass, field -from typing import ClassVar, Callable, Any +from typing import ClassVar, Callable from ctypes import c_uint32, c_int32, c_uint8 import struct from optable import OPCODES, OpcodeDescription, OpL, OpA, OpF, OpD @@ -86,7 +86,7 @@ class VM: self._branch_callback, OpD(OpF.QUICK, OpL.BRANCH, OpA.BRANCH): self._branch_callback, - OpD(OpF(0), OpL.BRANCH, OpA.MEM_BRANCH): + OpD(OpF(0), OpL.BRANCH, OpA.IND_BRANCH): self._branch_indexed_callback } @@ -94,12 +94,16 @@ class VM: """ Make one step (only step into) """ + # По какой-то причине адрессация работает + # так, будто мы на 1 слово впереди опкода + if not VMFlags.AFTER_BRANCH: + self.pc = c_uint32(self.cc.value + 1) + # сбрасываем флаг AFTER_BRANCH + self._vm_flags &= ~(VMFlags.AFTER_BRANCH) opcode = self.mem[self.pc.value] opdesc = self._fetch_opcode_desc(opcode) args = self._parse_arguments(opdesc) - if not VMFlags.AFTER_BRANCH: - self.pc = c_uint32(self.cc.value + 1) - self._vm_flags &= ~(VMFlags.AFTER_BRANCH) + self._run_callback(opdesc, args) def continue_(self) -> None: """ @@ -142,7 +146,39 @@ class VM: self.instr_callbacks[opdesc]( r3, r1, r2_or_i8 ) - if opdesc.layout == OpL.MEM + if opdesc.layout == OpL.MEM: + if OpF.QUICK in opdesc.flags: + assert len(args) == 4 + _, r3, r1, i8 = args + self.instr_callbacks[opdesc]( + r3, r1, i8 + ) + else: + assert len(args) == 5 + _, r3, r1, _, disp = args + self.instr_callbacks[opdesc]( + r3, r1, disp + ) + + if opdesc.layout == OpL.BRANCH: + if OpF.QUICK in opdesc.flags: + assert len(args) == 4 + _, cond, _, i8 = args + self.instr_callbacks[opdesc]( + cond, i8 + ) + elif opdesc.action == OpA.IND_BRANCH: + assert len(args) == 5 + _, cond, r1, _, disp = args + self.instr_callbacks[opdesc]( + cond, r1, disp + ) + else: + assert len(args) == 5 + _, cond, _, _, disp = args + self.instr_callbacks[opdesc]( + cond, disp + ) def _math_callback_gen( self, @@ -200,3 +236,4 @@ class VM: self._vm_flags |= VMFlags.AFTER_BRANCH addr = self.registers[r1].value + disp self.pc = c_uint32(addr) +