sync: тут мелкие изменения, которые я делал в процессе дебага

История разработки превращается в кашу, но что поделать, этот репозиторий поддерживается на скорую руку
This commit is contained in:
ElectronixTM
2025-04-03 22:15:59 +03:00
parent 6a4a02ffb9
commit 7b6b3f73cd
2 changed files with 43 additions and 15 deletions

View File

@ -71,6 +71,8 @@ class Debugger:
"c": self._continue, "c": self._continue,
"breakpoint": self._breakpoint, "breakpoint": self._breakpoint,
"b": self._breakpoint, "b": self._breakpoint,
"clearbreakpoints": self._breakpointsclear,
"cbp": self._breakpointsclear,
"print": self._print, "print": self._print,
"p": self._print, "p": self._print,
"run": self._run, "run": self._run,
@ -119,9 +121,7 @@ class Debugger:
addr = -1 addr = -1
# находим за линейное время. Плохая практика, но так как # находим за линейное время. Плохая практика, но так как
# сходные коды вряд ли будут длиннее 1000 строк - приемлемо # сходные коды вряд ли будут длиннее 1000 строк - приемлемо
print(self._dbg_dict)
for addr, desc in self._dbg_dict["instructions"].items(): for addr, desc in self._dbg_dict["instructions"].items():
print("_______________", desc, "__________")
desc = cast(DbgInstrDesc, desc) desc = cast(DbgInstrDesc, desc)
if not desc["srcline"] == desired_addr: if not desc["srcline"] == desired_addr:
continue continue
@ -131,6 +131,11 @@ class Debugger:
return f"Couldn't place breakpoint on src line {desired_addr}" return f"Couldn't place breakpoint on src line {desired_addr}"
def _breakpointsclear(self, args: list[str]):
self._breakpoints.clear()
self._vm.breakpoints.clear()
return "Cleared all breakpoints"
def _print(self, args: list[str]) -> str: def _print(self, args: list[str]) -> str:
to_print = args[0] to_print = args[0]
if to_print == "pc": if to_print == "pc":
@ -178,6 +183,7 @@ class Debugger:
return ("You passed wrong offset parameter. It should be either " return ("You passed wrong offset parameter. It should be either "
"name of some label or explicit decimal or hexdecimal " "name of some label or explicit decimal or hexdecimal "
"number, in the second case it should start with 0x") "number, in the second case it should start with 0x")
offset = self._vm._to_raw_bytes_offset(offset)
try: try:
sym = self.UNPACK_SYMBOL_TABLE[size_arg] sym = self.UNPACK_SYMBOL_TABLE[size_arg]
@ -187,7 +193,7 @@ class Debugger:
"options as size: b/B - byte, h/H - 2 bytes, " "options as size: b/B - byte, h/H - 2 bytes, "
"w/W - 4 bytes. Big - unsigned, small - signed") "w/W - 4 bytes. Big - unsigned, small - signed")
contents = struct.unpack( contents = struct.unpack(
sym*amount, ">"+sym*amount,
self._vm.mem[offset:offset+size*amount] self._vm.mem[offset:offset+size*amount]
) )
return f"{mem_location}:" + " ".join(map(str, contents)) return f"{mem_location}:" + " ".join(map(str, contents))

View File

@ -262,6 +262,25 @@ class VM:
cond, disp cond, disp
) )
@staticmethod
def _perform_ariphmetic_operation(
lhs: int,
rhs: int,
op: Callable[[int, int], int]
) -> tuple[int, VMCC]:
cc = VMCC(0)
result = op(lhs, rhs)
if result < 0:
cc |= VMCC.NEGATIVE
elif result == 0:
cc |= VMCC.ZERO
# самая дорогая проверка на переполнение)
try:
struct.pack('i', result)
except struct.error:
cc |= VMCC.OVERFLOW
return result, cc
def _math_callback_gen( def _math_callback_gen(
self, self,
operation: Callable[[int, int], int] operation: Callable[[int, int], int]
@ -274,10 +293,16 @@ class VM:
def callback(self, r3: int, r1: int, r2: int): def callback(self, r3: int, r1: int, r2: int):
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)) result, cc = self._perform_ariphmetic_operation(
lhs,
rhs,
operation)
self.registers[r3] = c_int32(result)
self.cc = cc
return callback return callback
def _math_quick_callback_gen( def _math_quick_callback_gen(
self, self,
operation: Callable[[int, int], int] operation: Callable[[int, int], int]
@ -293,24 +318,21 @@ class VM:
def callback(self, r3: int, r1: int, i8: int) -> None: def callback(self, r3: int, r1: int, i8: int) -> None:
self.cc = VMCC(0) self.cc = VMCC(0)
lhs = self.registers[r1].value lhs = self.registers[r1].value
result = operation(lhs, i8) result, flags = self._perform_ariphmetic_operation(
if result < 0: lhs,
self.cc |= VMCC.NEGATIVE i8,
elif result == 0: operation)
self.cc |= VMCC.ZERO
# самая дорогая проверка на переполнение)
try:
struct.pack('i', result)
except struct.error:
self.cc |= VMCC.OVERFLOW
self.registers[r3] = c_int32(result) self.registers[r3] = c_int32(result)
self.cc = flags
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:
addr = self._to_raw_bytes_offset(self.registers[r1].value + disp) addr = self._to_raw_bytes_offset(self.registers[r1].value + disp)
raw_bytes = self.mem[addr:addr+WORD_SIZE]
self.registers[r3] = c_int32( self.registers[r3] = c_int32(
struct.unpack( struct.unpack(
">i", self.mem[addr:addr+WORD_SIZE])[0] ">i", raw_bytes
)[0]
) )
def _store_callback(self, r3: int, r1: int, disp: int) -> None: def _store_callback(self, r3: int, r1: int, disp: int) -> None: