From d028aebe59d4ea380b669894837878524c02a217 Mon Sep 17 00:00:00 2001 From: rs <> Date: Sun, 12 Oct 2025 21:45:46 -0500 Subject: [PATCH] Add breakpoints and memory dumps to emulator --- projects/cpu_0/asm/emu.py | 77 ++++++++++++++++++++++++++++++++++----- 1 file changed, 67 insertions(+), 10 deletions(-) diff --git a/projects/cpu_0/asm/emu.py b/projects/cpu_0/asm/emu.py index ffff076..473d393 100755 --- a/projects/cpu_0/asm/emu.py +++ b/projects/cpu_0/asm/emu.py @@ -3,6 +3,8 @@ from __future__ import annotations from typing import * +import hexdump + # ------------------------------------------------------------------------------ @@ -24,6 +26,7 @@ class Cpu0(object): self._return_stack = list() self._regions = dict() self._syms = list() + self._breakpoints = list() def load_bin(self, data: bytes, offset: int = 0): for i, b in enumerate(data): @@ -36,6 +39,11 @@ class Cpu0(object): addr = int(saddr, 0) self._syms.append((addr, symbol.strip())) + def bp(self, address: int | str) -> None: + if isinstance(address, str): + address = self.symbol_to_addr(address) + self._breakpoints.append(address) + def addr_to_symbol(self, address: int) -> str: # Assumes symbols are sorted found_symbol = '' @@ -116,7 +124,7 @@ class Cpu0(object): while self.pc != addr: self.step() - def step(self) -> None: + def step(self) -> Optional[int]: instr = self.ld8(self.pc) self.pc += 1 if instr == 0x01: # #8 @@ -168,7 +176,8 @@ class Cpu0(object): elif instr == 0x0f: # JP addr = self.ld32(self.pc) self.pc += 4 - if self.p_pop() > 0: + x = self.p_pop() + if x > 0 and x & 0x8000000 == 0: self.pc = addr elif instr == 0x10: # + self.p_push(self.p_pop() + self.p_pop()) @@ -202,13 +211,23 @@ class Cpu0(object): self.p_push(val << 1) else: # NOP pass + for i, addr in enumerate(self._breakpoints): + if self.pc == addr: + return i + return None def dump(self) -> None: print('-'*80) print(f'0x{self.pc:08x} {self.addr_to_symbol(self.pc)}') instr = self.ld8(self.pc) sinstr = self.INSTRS[instr] if instr in self.INSTRS else '???' - print(f' (0x{instr:02x} {sinstr})') + if sinstr == '#8': + imm = self.ld8(self.pc + 1) + sinstr += f' 0x{imm:02x}/{imm}' + elif sinstr in ['#32', 'JMP', 'JN', 'JZ', 'JP', 'CALL']: + imm = self.ld32(self.pc + 1) + sinstr += f' 0x{imm:08x}/{imm} - {self.addr_to_symbol(imm)}' + print(f' 0x{instr:02x} {sinstr}') print() print('Data stack:') for x in reversed(self._param_stack): @@ -233,15 +252,53 @@ def main() -> int: emu.load_bin(data) emu.load_map(mapfile) + emu.p_push(0) + emu.pc = 0 emu.dump() - emu.r_push(0xdeadbeef) - emu.p_push(0x1234) - emu.p_push(0x41) - emu.pc = 'div_uu' - emu.dump() - - emu.run_until(0xdeadbeef) + emu.run_until('vga_console_putc') emu.dump() + i = '' + while True: + p = i + i = input('> ') + if not i: + i = p + c = i.split() + + if c[0] == 'q': + break + elif c[0] == 'b': + if len(c) == 1: + for i, addr in enumerate(emu._breakpoints): + print(f'{i}: 0x{addr:08x} ({emu.addr_to_symbol(addr)})') + print() + elif c[1][0].isdigit(): + emu.bp(int(c[1], 0)) + else: + emu.bp(c[1]) + elif c[0] == 'c': + try: + while True: + bp = emu.step() + if bp is not None: + print(f'Halted at breakpoint {bp}') + break + except KeyboardInterrupt: + print('Halted') + emu.dump() + elif c[0] == 'd': + a = c[1] + l = c[2] + l = int(l, 0) + if a[0].isdigit(): + a = int(a, 0) + else: + a = emu.symbol_to_addr(a) + d = bytes(emu.ld8(addr) for addr in range(a, a+l)) + hexdump.hexdump(d) + elif c[0] == 's': + emu.step() + emu.dump() return 0 -- 2.43.0