]> git.the-white-hart.net Git - vhdl/commitdiff
Add breakpoints and memory dumps to emulator
authorrs <>
Mon, 13 Oct 2025 02:45:46 +0000 (21:45 -0500)
committerrs <>
Mon, 13 Oct 2025 02:45:46 +0000 (21:45 -0500)
projects/cpu_0/asm/emu.py

index ffff076ce6bd3cead9bae1b9d287b1231b746051..473d3931a6ad0bfcb73788f41fd873d9708f7f7d 100755 (executable)
@@ -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