Compare commits

...

5 Commits

3 changed files with 67 additions and 15 deletions

View File

@ -1,4 +1,5 @@
from dpdebugger import Debugger from dpdebugger import Debugger
from vm import VMException, VMExceptionType, VMStatus
from dataclasses import dataclass from dataclasses import dataclass
from typing import cast from typing import cast
import math import math
@ -86,13 +87,41 @@ class DebuggerUI:
user_input = self.commands_history[0] user_input = self.commands_history[0]
self.history_index = 0 self.history_index = 0
self.commands_history.appendleft("") self.commands_history.appendleft("")
try:
dbg_output = self.dbg.do_command(user_input.split()) dbg_output = self.dbg.do_command(user_input.split())
self.terminal_panel.write(dbg_output) 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._display_source_lines()
self.commands_history[0] = user_input 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): def _display_source_lines(self):
if self.dbg._vm.status == VMStatus.FINISHED:
return
try:
active_line = self.dbg.get_current_source_line_number() 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( lines = _get_source_lines(
srcline=active_line, srcline=active_line,
lines=self.srclines, lines=self.srclines,

View File

@ -75,7 +75,8 @@ class Debugger:
"run": self._run, "run": self._run,
"r": self._run, "r": self._run,
"inspect": self._inspect, "inspect": self._inspect,
"i": self._inspect "i": self._inspect,
"reset": self._reset
} }
def do_command(self, command: list[str]) -> str: def do_command(self, command: list[str]) -> str:
@ -84,6 +85,13 @@ class Debugger:
return "Unknown command" return "Unknown command"
return self._callbacks_table[callback_name](command[1:]) 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: def _step(self, args: list[str]) -> str:
try: try:
self._vm.step() self._vm.step()
@ -93,9 +101,6 @@ class Debugger:
return f"Virtual machine exception: {e.message}" return f"Virtual machine exception: {e.message}"
return "" 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: def _continue(self, args: list[str]) -> str:
try: try:
self._vm.continue_() self._vm.continue_()
@ -134,7 +139,10 @@ class Debugger:
f"z: {flags.z}\n" 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:]) index = int(to_print[1:])
return f"{to_print}: {self._vm.registers[index].value}" return f"{to_print}: {self._vm.registers[index].value}"

View File

@ -25,6 +25,11 @@ class VMCC(IntFlag):
NEGATIVE = 1 << 1 NEGATIVE = 1 << 1
ZERO = 1 << 0 ZERO = 1 << 0
class VMStatus(Enum):
RUNNING = auto()
INITED = auto()
FINISHED = auto()
@dataclass @dataclass
class Breakpoint(Exception): class Breakpoint(Exception):
address: int address: int
@ -48,15 +53,12 @@ class VM:
registers: list[c_int32] registers: list[c_int32]
breakpoints: set[int] breakpoints: set[int]
_vm_flags: VMFlags _vm_flags: VMFlags
status: VMStatus
def __init__(self, mem: bytearray): def __init__(self, mem: bytearray):
self.mem: bytearray = mem self._initial_mem = 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.__init_callbacks__() self.__init_callbacks__()
self.reset()
def __init_callbacks__(self): def __init_callbacks__(self):
VM.instr_callbacks = { VM.instr_callbacks = {
@ -119,16 +121,27 @@ class VM:
self._branch_indexed_callback 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: def step(self) -> None:
""" """
Make one step (only step into) Make one step (only step into)
""" """
if self._to_raw_bytes_offset(self.pc) > len(self.mem) - WORD_SIZE: if self._to_raw_bytes_offset(self.pc) > len(self.mem) - WORD_SIZE:
self.status = VMStatus.FINISHED
raise VMException( raise VMException(
VMExceptionType.END_OF_MEM, VMExceptionType.END_OF_MEM,
self.pc.value, self.pc.value,
"couldn't perform step because end of memory occured" "couldn't perform step because end of memory occured"
) )
self.status = VMStatus.RUNNING
opcode, *_ = instr = self._fetch_instr() opcode, *_ = instr = self._fetch_instr()
opdesc = self._get_opcode_desc(opcode) opdesc = self._get_opcode_desc(opcode)
args: tuple[int, ...] = self._parse_instr_fields(bytes(instr)) args: tuple[int, ...] = self._parse_instr_fields(bytes(instr))
@ -148,14 +161,16 @@ class VM:
if self.pc.value in self.breakpoints: if self.pc.value in self.breakpoints:
raise Breakpoint(self.pc.value) raise Breakpoint(self.pc.value)
self.step() self.step()
self.status = VMStatus.FINISHED
def run(self) -> None: def run(self) -> None:
""" """
Run from very beginning Run from very beginning
""" """
self.pc = c_uint32(0) self.reset()
while (self._to_raw_bytes_offset(self.pc.value) < len(self.mem)): while (self._to_raw_bytes_offset(self.pc.value) < len(self.mem)):
self.continue_() self.continue_()
self.status = VMStatus.FINISHED
def _fetch_instr(self) -> bytearray: def _fetch_instr(self) -> bytearray:
""" """