This project is a simple, educational 16-bit virtual machine (VM) written in Rust. It is designed to help you understand how CPUs and low-level computer architecture work by simulating a basic computer system from scratch.
- Learn the fundamentals of CPU and VM design
- Explore instruction sets, registers, memory, and program execution
- Provide a clear, well-documented codebase for experimentation and learning
- 16-bit word size for all operations and memory
- General-purpose and special-purpose registers (PC, SP, FLAGS, etc.)
- Simple instruction set (arithmetic, logic, memory access, control flow)
- Memory-mapped I/O and bus abstraction
- Halt and error handling for safe execution
The VM consists of:
- Registers: 6 registers (R0–R3 general-purpose, RPC program counter RIR)
- Memory: Linear address space, 16-bit words
- Instruction Set: Each instruction is 16 bits, with 4 bits for the opcode and the rest for operands
- Execution Loop: Fetch-decode-execute cycle, halts on errors or HALT instruction
Each instruction is 16 bits, divided as follows:
In my implementation, each register’s value can hold either actual data from memory or a memory address, depending on the OPCODE being used.
| Bits | Field | Description |
|---|---|---|
| 15–12 (4) | Opcode | Operation to perform |
| 11–8 (4) | Register 1 | Destination register |
| 7–4 (4) | Register 2 | Source register |
| 3–0 (4) | Imm/Offset | Immediate value or offset (opcode-dependent) |
┌───────┬────────────┬────────────┬────────────┐
│Opcode │ Register 1 │ Register 2 │ Imm/Offset │
└───────┴────────────┴────────────┴────────────┘
4 bits 4 bits 4 bits 4 bits
- The meaning of the last 4 bits (Imm/Ofs) depends on the opcode: it can be a small constant or an offset.
Build the project:
cargo buildRun the VM (example, see main.rs for entry point):
cargo runRight now, my 16-bit Rust VM is a pure-interpreter. It reads my VM instructions (Read, decode, executes, one instruction at a time) in the software on the host CPU. Nothing gets translated to native instructions.
- The host CPU executes Rust code that implements the operations, not the ADD itself.
- VM registers live in Rust memory, not in actual CPU registers.
Adding a runtime with JIT will allow me:
- Translate my 16-bit VM into host CPU instructions (ARM64)
- Execute them natively instead of interpreting them one by one
- Get much higher performance for “heavy work”
- Keep safety and control over execution because the VM still manages correctness
The goal is to make my VM run eBPF programs with runtime + JIT:
- Define a mapping from eBPF instructions to your VM structures (Implement the eBPF Interpreter), adding verifier is optional (probably will not implement)
- Add a eBPF VM runtime -> program execution manager
- Implement JIT Compilation -> translate eBPF instructions to host CPU instructions at runtime
This project is for learning and experimentation. Contributions and questions are welcome!
