Compare commits
5 Commits
922670be47
...
82eb4e96ff
| Author | SHA1 | Date | |
|---|---|---|---|
| 82eb4e96ff | |||
| eae2846925 | |||
| a9bedc18cf | |||
| 90040c9823 | |||
| 69234aac2d |
@ -1,4 +1,5 @@
|
||||
from dpdebugger import Debugger
|
||||
from vm import VMException, VMExceptionType, VMStatus
|
||||
from dataclasses import dataclass
|
||||
from typing import cast
|
||||
import math
|
||||
@ -86,13 +87,41 @@ class DebuggerUI:
|
||||
user_input = self.commands_history[0]
|
||||
self.history_index = 0
|
||||
self.commands_history.appendleft("")
|
||||
dbg_output = self.dbg.do_command(user_input.split())
|
||||
self.terminal_panel.write(dbg_output)
|
||||
|
||||
try:
|
||||
dbg_output = self.dbg.do_command(user_input.split())
|
||||
except VMException as vme:
|
||||
self._terminal_append(
|
||||
"VM Exception: " + vme.message
|
||||
)
|
||||
return
|
||||
|
||||
# self._terminal_append(dbg_output)
|
||||
self._terminal_append(dbg_output)
|
||||
self._display_source_lines()
|
||||
self.commands_history[0] = user_input
|
||||
|
||||
def _terminal_append(self, text: str):
|
||||
self.terminal_panel.write(text)
|
||||
viewport_height = self.terminal_panel.get_viewport_height()
|
||||
contents = self.terminal_panel.get().split('\n')[-viewport_height:]
|
||||
self.terminal_panel.set_text("\n".join(contents))
|
||||
|
||||
def _display_source_lines(self):
|
||||
active_line = self.dbg.get_current_source_line_number()
|
||||
if self.dbg._vm.status == VMStatus.FINISHED:
|
||||
return
|
||||
try:
|
||||
active_line = self.dbg.get_current_source_line_number()
|
||||
except KeyError:
|
||||
self._terminal_append(
|
||||
"Cant find source line your are on. "
|
||||
"May be you reached end of program. "
|
||||
)
|
||||
self._terminal_append(
|
||||
"Please type \"reset\" to reset vm "
|
||||
"it's initial state"
|
||||
)
|
||||
return
|
||||
lines = _get_source_lines(
|
||||
srcline=active_line,
|
||||
lines=self.srclines,
|
||||
|
||||
@ -75,7 +75,8 @@ class Debugger:
|
||||
"run": self._run,
|
||||
"r": self._run,
|
||||
"inspect": self._inspect,
|
||||
"i": self._inspect
|
||||
"i": self._inspect,
|
||||
"reset": self._reset
|
||||
}
|
||||
|
||||
def do_command(self, command: list[str]) -> str:
|
||||
@ -84,6 +85,13 @@ class Debugger:
|
||||
return "Unknown command"
|
||||
return self._callbacks_table[callback_name](command[1:])
|
||||
|
||||
def get_current_source_line_number(self) -> int:
|
||||
return self._dbg_dict["instructions"][self._vm.pc.value]['srcline']
|
||||
|
||||
def _reset(self, args: list[str]) -> str:
|
||||
self._vm.reset()
|
||||
return "VM reseted"
|
||||
|
||||
def _step(self, args: list[str]) -> str:
|
||||
try:
|
||||
self._vm.step()
|
||||
@ -93,9 +101,6 @@ class Debugger:
|
||||
return f"Virtual machine exception: {e.message}"
|
||||
return ""
|
||||
|
||||
def get_current_source_line_number(self) -> int:
|
||||
return self._dbg_dict["instructions"][self._vm.pc.value]['srcline']
|
||||
|
||||
def _continue(self, args: list[str]) -> str:
|
||||
try:
|
||||
self._vm.continue_()
|
||||
@ -134,7 +139,10 @@ class Debugger:
|
||||
f"z: {flags.z}\n"
|
||||
)
|
||||
|
||||
elif re.fullmatch(r'r\d+', to_print):
|
||||
elif re.fullmatch(
|
||||
# r0-r255
|
||||
r'r(0|[1-9][0-9]|1[0-9][0-9]|2[1-4][1-9]|25[1-5])',
|
||||
to_print):
|
||||
index = int(to_print[1:])
|
||||
return f"{to_print}: {self._vm.registers[index].value}"
|
||||
|
||||
|
||||
29
src/vm.py
29
src/vm.py
@ -25,6 +25,11 @@ class VMCC(IntFlag):
|
||||
NEGATIVE = 1 << 1
|
||||
ZERO = 1 << 0
|
||||
|
||||
class VMStatus(Enum):
|
||||
RUNNING = auto()
|
||||
INITED = auto()
|
||||
FINISHED = auto()
|
||||
|
||||
@dataclass
|
||||
class Breakpoint(Exception):
|
||||
address: int
|
||||
@ -48,15 +53,12 @@ class VM:
|
||||
registers: list[c_int32]
|
||||
breakpoints: set[int]
|
||||
_vm_flags: VMFlags
|
||||
status: VMStatus
|
||||
|
||||
def __init__(self, mem: bytearray):
|
||||
self.mem: bytearray = mem
|
||||
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] = set()
|
||||
self._vm_flags: VMFlags = VMFlags(0)
|
||||
self._initial_mem = mem.copy()
|
||||
self.__init_callbacks__()
|
||||
self.reset()
|
||||
|
||||
def __init_callbacks__(self):
|
||||
VM.instr_callbacks = {
|
||||
@ -119,16 +121,27 @@ class VM:
|
||||
self._branch_indexed_callback
|
||||
}
|
||||
|
||||
def reset(self):
|
||||
self.mem: bytearray = self._initial_mem.copy()
|
||||
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] = set()
|
||||
self._vm_flags: VMFlags = VMFlags(0)
|
||||
self.status = VMStatus.INITED
|
||||
|
||||
def step(self) -> None:
|
||||
"""
|
||||
Make one step (only step into)
|
||||
"""
|
||||
if self._to_raw_bytes_offset(self.pc) > len(self.mem) - WORD_SIZE:
|
||||
self.status = VMStatus.FINISHED
|
||||
raise VMException(
|
||||
VMExceptionType.END_OF_MEM,
|
||||
self.pc.value,
|
||||
"couldn't perform step because end of memory occured"
|
||||
)
|
||||
self.status = VMStatus.RUNNING
|
||||
opcode, *_ = instr = self._fetch_instr()
|
||||
opdesc = self._get_opcode_desc(opcode)
|
||||
args: tuple[int, ...] = self._parse_instr_fields(bytes(instr))
|
||||
@ -148,14 +161,16 @@ class VM:
|
||||
if self.pc.value in self.breakpoints:
|
||||
raise Breakpoint(self.pc.value)
|
||||
self.step()
|
||||
self.status = VMStatus.FINISHED
|
||||
|
||||
def run(self) -> None:
|
||||
"""
|
||||
Run from very beginning
|
||||
"""
|
||||
self.pc = c_uint32(0)
|
||||
self.reset()
|
||||
while (self._to_raw_bytes_offset(self.pc.value) < len(self.mem)):
|
||||
self.continue_()
|
||||
self.status = VMStatus.FINISHED
|
||||
|
||||
def _fetch_instr(self) -> bytearray:
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user