Compare commits
5 Commits
a072d50ca1
...
320f876f97
| Author | SHA1 | Date | |
|---|---|---|---|
| 320f876f97 | |||
| 5dea5b81db | |||
| b73f92ef88 | |||
| 0f5ac310e8 | |||
| 86a3d307b2 |
6
main.py
6
main.py
@ -1,6 +0,0 @@
|
|||||||
def main():
|
|
||||||
print("Hello from dp32-proto!")
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
||||||
@ -29,7 +29,7 @@ class OpcodeActions(Enum):
|
|||||||
LOAD = auto()
|
LOAD = auto()
|
||||||
STORE = auto()
|
STORE = auto()
|
||||||
BRANCH = auto()
|
BRANCH = auto()
|
||||||
MEM_BRANCH = auto()
|
IND_BRANCH = auto()
|
||||||
|
|
||||||
OpA = OpcodeActions
|
OpA = OpcodeActions
|
||||||
|
|
||||||
|
|||||||
70
src/vm.py
70
src/vm.py
@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
from dataclasses import dataclass, field
|
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
|
from ctypes import c_uint32, c_int32, c_uint8
|
||||||
import struct
|
import struct
|
||||||
from optable import OPCODES, OpcodeDescription, OpL, OpA, OpF, OpD
|
from optable import OPCODES, OpcodeDescription, OpL, OpA, OpF, OpD
|
||||||
@ -16,13 +16,18 @@ class Condition:
|
|||||||
self.n: bool = bool(cond & (1 << 1))
|
self.n: bool = bool(cond & (1 << 1))
|
||||||
self.z: bool = bool(cond & (1 << 0))
|
self.z: bool = bool(cond & (1 << 0))
|
||||||
|
|
||||||
|
class VMCC(IntFlag):
|
||||||
|
OVERFLOW = 1 << 2
|
||||||
|
NEGATIVE = 1 << 1
|
||||||
|
ZERO = 1 << 0
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class VM:
|
class VM:
|
||||||
instr_callbacks: ClassVar[dict[OpcodeDescription, Callable]]
|
instr_callbacks: ClassVar[dict[OpcodeDescription, Callable]]
|
||||||
|
|
||||||
def __init__(self, mem):
|
def __init__(self, mem):
|
||||||
self.mem: bytearray = 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.pc: c_uint32 = c_uint32(0)
|
||||||
self.registers: list[c_int32] = [c_int32(0) for _ in range(256)]
|
self.registers: list[c_int32] = [c_int32(0) for _ in range(256)]
|
||||||
self.breakpoints: set[int] = field(default_factory=set)
|
self.breakpoints: set[int] = field(default_factory=set)
|
||||||
@ -86,7 +91,7 @@ class VM:
|
|||||||
self._branch_callback,
|
self._branch_callback,
|
||||||
OpD(OpF.QUICK, OpL.BRANCH, OpA.BRANCH):
|
OpD(OpF.QUICK, OpL.BRANCH, OpA.BRANCH):
|
||||||
self._branch_callback,
|
self._branch_callback,
|
||||||
OpD(OpF(0), OpL.BRANCH, OpA.MEM_BRANCH):
|
OpD(OpF(0), OpL.BRANCH, OpA.IND_BRANCH):
|
||||||
self._branch_indexed_callback
|
self._branch_indexed_callback
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,12 +99,16 @@ class VM:
|
|||||||
"""
|
"""
|
||||||
Make one step (only step into)
|
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]
|
opcode = self.mem[self.pc.value]
|
||||||
opdesc = self._fetch_opcode_desc(opcode)
|
opdesc = self._fetch_opcode_desc(opcode)
|
||||||
args = self._parse_arguments(opdesc)
|
args = self._parse_arguments(opdesc)
|
||||||
if not VMFlags.AFTER_BRANCH:
|
self._run_callback(opdesc, args)
|
||||||
self.pc = c_uint32(self.cc.value + 1)
|
|
||||||
self._vm_flags &= ~(VMFlags.AFTER_BRANCH)
|
|
||||||
|
|
||||||
def continue_(self) -> None:
|
def continue_(self) -> None:
|
||||||
"""
|
"""
|
||||||
@ -142,7 +151,39 @@ class VM:
|
|||||||
self.instr_callbacks[opdesc](
|
self.instr_callbacks[opdesc](
|
||||||
r3, r1, r2_or_i8
|
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(
|
def _math_callback_gen(
|
||||||
self,
|
self,
|
||||||
@ -157,6 +198,7 @@ class VM:
|
|||||||
lhs = self.registers[r1].value
|
lhs = self.registers[r1].value
|
||||||
rhs = self.registers[r2].value
|
rhs = self.registers[r2].value
|
||||||
self.registers[r3] = c_int32(operation(lhs, rhs))
|
self.registers[r3] = c_int32(operation(lhs, rhs))
|
||||||
|
|
||||||
return callback
|
return callback
|
||||||
|
|
||||||
def _math_quick_callback_gen(
|
def _math_quick_callback_gen(
|
||||||
@ -172,8 +214,19 @@ class VM:
|
|||||||
операций с пометкой QUICK
|
операций с пометкой QUICK
|
||||||
"""
|
"""
|
||||||
def callback(self, r3: int, r1: int, i8: int) -> None:
|
def callback(self, r3: int, r1: int, i8: int) -> None:
|
||||||
|
self.cc = VMCC(0)
|
||||||
lhs = self.registers[r1].value
|
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
|
return callback
|
||||||
|
|
||||||
def _load_callback(self, r3: int, r1: int, disp: int) -> None:
|
def _load_callback(self, r3: int, r1: int, disp: int) -> None:
|
||||||
@ -200,3 +253,4 @@ class VM:
|
|||||||
self._vm_flags |= VMFlags.AFTER_BRANCH
|
self._vm_flags |= VMFlags.AFTER_BRANCH
|
||||||
addr = self.registers[r1].value + disp
|
addr = self.registers[r1].value + disp
|
||||||
self.pc = c_uint32(addr)
|
self.pc = c_uint32(addr)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user