A high-performance, cycle-accurate emulator of the original IBM PC with Intel 8088 processor, implemented in Rust. The emulator features a three-tier execution system (cold/warm/hot paths) designed for progressive optimization as code executes, aiming to achieve both accuracy and performance through direct dispatch, decode caching, and compiled basic blocks.
While the original goal was to build an insanely efficient PC emulator, the actual goal became to see if Claude Code could write the entire thing, end to end. Every single line of code in this repository was generated by Claude (Anthropic's AI assistant). I haven't written any code myself—I've architected the design, provided prompts and direction, reviewed the output, and guided the implementation, but 100% of the actual code was AI-generated.
This project serves as an exploration of what's possible with AI-assisted development in 2025, particularly for complex systems programming tasks like emulator development.
The emulator now successfully POSTs and boots IBM Cassette BASIC! 🎉
The CPU core and essential peripherals are functional, allowing real IBM PC BIOS to execute.
- Data Transfer: MOV, XCHG, LEA, LDS, LES, XLAT, PUSH, POP (registers and segments)
- Arithmetic: ADD, ADC, SUB, SBB, INC, DEC, CMP, NEG, MUL, IMUL, DIV, IDIV, AAA, AAS, AAM, AAD, DAA, DAS, CBW, CWD
- Logic: AND, OR, XOR, TEST, NOT
- Shift/Rotate: SHL, SHR, SAR, ROL, ROR, RCL, RCR
- Control Flow: JMP, CALL, RET (near/far), INT, IRET, conditional jumps (Jcc), LOOP family
- String Operations: MOVS, STOS, LODS, CMPS, SCAS (byte/word with REP/REPE/REPNE)
- Flag Manipulation: CLC, STC, CMC, CLI, STI, CLD, STD, PUSHF, POPF, SAHF, LAHF
- I/O: IN, OUT (immediate and DX port)
- Prefixes: Segment overrides (ES, CS, SS, DS), REP, REPE, REPNE
- System: HLT, NOP
- 8088 CPU: Full instruction set with lazy flag evaluation
- MDA (Monochrome Display Adapter): 80x25 text mode with 720x350 graphical output
- 8259 PIC (Programmable Interrupt Controller): Edge-triggered interrupts, priority handling, masking
- 8253 PIT (Programmable Interval Timer): Timer channel 0 with IRQ0 generation
- 8255 PPI (Programmable Peripheral Interface): Keyboard input, DIP switches, reset control
- Memory: 64KB RAM, 64KB ROM/BIOS, MDA VRAM at 0xB0000
- Lazy flag evaluation for performance
- ModR/M decoding with all addressing modes
- Segment:offset memory addressing
- Hardware interrupt handling via PIC
- REP prefix support with conditional termination
- GDB remote debugging over Unix socket
- Comprehensive test suite (479+ tests)
The emulator is designed around three execution tiers:
- Tier 1 (Cold Path): Direct dispatch using function pointers for first-time instruction execution
- Tier 2 (Warm Path): Decode cache for frequently executed instructions
- Tier 3 (Hot Path): Compiled basic blocks for the hottest code paths
Currently, Tier 1 is implemented and functional. See ARCH.md for detailed architecture and implementation plan.
# Build the project
cargo build
# Run tests
cargo test
# Run in release mode (for benchmarking)
cargo build --releaseThe emulator includes built-in support for GDB remote debugging over a Unix socket. This allows you to inspect CPU state, set breakpoints, single-step through code, and examine memory while the emulator runs.
- Start the emulator with GDB enabled:
cargo run --release -- --gdb /tmp/ezpc.sock bios.rom- In another terminal, connect with GDB:
gdb
(gdb) set architecture i8086
(gdb) target remote /tmp/ezpc.sockOnce connected, you can use standard GDB commands:
# View registers
(gdb) info registers
# Read memory (segmented addressing)
(gdb) x/16xb 0xf000:0xfff0
# Set a breakpoint at a specific address
(gdb) break *0xf000:0xe000
# Single-step instructions
(gdb) stepi
# Continue execution
(gdb) continue
# Read/write registers
(gdb) print $eip
(gdb) set $ax = 0x1234- ✅ Register read/write (AX, BX, CX, DX, SI, DI, SP, BP, IP, FLAGS, CS, SS, DS, ES)
- ✅ Memory read/write (linear addressing)
- ✅ Breakpoints (software breakpoints at any address)
- ✅ Single-step execution (
stepi) - ✅ Continue execution (
continue) - ✅ Halt reason reporting (SIGTRAP on break/step)
The GDB integration uses non-blocking I/O to avoid impacting emulation performance:
- Socket I/O runs in a separate thread
- Commands are queued and processed each frame
- Emulation never blocks waiting for GDB
- Zero performance overhead when debugger not connected
# View all command-line options
cargo run -- --helpsrc/cpu/- CPU emulation corestate.rs- CPU registers, flags, and state managementdecode/- Instruction decoding (ModR/M, operands)execute/- Instruction handlers by categorytier1/- Direct dispatch implementation
src/debugger/- GDB remote debugging supportprotocol.rs- GDB Remote Serial Protocol packet handlingsocket.rs- Non-blocking Unix socket I/O threadcommands.rs- GDB command handlers (g, m, s, c, Z, etc.)mod.rs- Debugger core and state management
src/components/- Hardware componentsmda.rs- Monochrome Display Adapter with font ROMpic.rs- 8259 Programmable Interrupt Controllerpit.rs- 8253 Programmable Interval Timerppi.rs- 8255 Programmable Peripheral Interfacekeyboard.rs- XT keyboard with scancode generationdma.rs- 8237 DMA Controller (stub)
src/emulator/- Emulator state and coordinationgraphics.rs- WGPU-based framebuffer renderingscancode.rs- PC XT scancode translation
src/memory.rs- Memory bus with RAM/ROM/VRAMtests/- Comprehensive test suite organized by instruction type
This project follows a strict incremental development methodology:
- Small, atomic commits representing single logical changes
- Test-driven development with tests written alongside implementations
- Continuous verification (cargo check, cargo test, cargo fmt before each commit)
- Architecture-guided implementation following the phases in ARCH.md
Every commit represents a complete, working state of the emulator with all tests passing.
MIT License - See LICENSE file for details.
Note: This is an active experiment in AI-generated code. The human's role has been purely architectural and directorial—the implementation is entirely Claude's work.