Compare commits

...

5 Commits

3 changed files with 63 additions and 15 deletions

View File

@ -1,6 +0,0 @@
def main():
print("Hello from dp32-proto!")
if __name__ == "__main__":
main()

View File

@ -29,7 +29,7 @@ class OpcodeActions(Enum):
LOAD = auto()
STORE = auto()
BRANCH = auto()
MEM_BRANCH = auto()
IND_BRANCH = auto()
OpA = OpcodeActions

View File

@ -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
@ -16,13 +16,18 @@ class Condition:
self.n: bool = bool(cond & (1 << 1))
self.z: bool = bool(cond & (1 << 0))
class VMCC(IntFlag):
OVERFLOW = 1 << 2
NEGATIVE = 1 << 1
ZERO = 1 << 0
@dataclass
class VM:
instr_callbacks: ClassVar[dict[OpcodeDescription, Callable]]
def __init__(self, mem):
self.mem: bytearray = mem
self.cc: c_uint8 = c_uint8(0)
self.cc: VMCC = VMCC(0)
self.pc: c_uint32 = c_uint32(0)
self.registers: list[c_int32] = [c_int32(0) for _ in range(256)]
self.breakpoints: set[int] = field(default_factory=set)
@ -86,7 +91,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 +99,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 +151,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,
@ -157,6 +198,7 @@ class VM:
lhs = self.registers[r1].value
rhs = self.registers[r2].value
self.registers[r3] = c_int32(operation(lhs, rhs))
return callback
def _math_quick_callback_gen(
@ -172,8 +214,19 @@ class VM:
операций с пометкой QUICK
"""
def callback(self, r3: int, r1: int, i8: int) -> None:
self.cc = VMCC(0)
lhs = self.registers[r1].value
self.registers[r3] = c_int32(operation(lhs, i8))
result = operation(lhs, i8)
if result < 0:
self.cc |= VMCC.NEGATIVE
elif result == 0:
self.cc |= VMCC.ZERO
# самая дорогая проверка на переполнение)
try:
struct.pack('i', result)
except struct.error:
self.cc |= VMCC.OVERFLOW
self.registers[r3] = c_int32(result)
return callback
def _load_callback(self, r3: int, r1: int, disp: int) -> None:
@ -200,3 +253,4 @@ class VM:
self._vm_flags |= VMFlags.AFTER_BRANCH
addr = self.registers[r1].value + disp
self.pc = c_uint32(addr)