Compare commits
5 Commits
922670be47
...
82eb4e96ff
| Author | SHA1 | Date | |
|---|---|---|---|
| 82eb4e96ff | |||
| eae2846925 | |||
| a9bedc18cf | |||
| 90040c9823 | |||
| 69234aac2d |
@ -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,
|
||||||
|
|||||||
@ -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}"
|
||||||
|
|
||||||
|
|||||||
29
src/vm.py
29
src/vm.py
@ -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:
|
||||||
"""
|
"""
|
||||||
|
|||||||
Reference in New Issue
Block a user