An emulator for the RX82 fantasy retro computer system, including the R8 8-bit CPU.
ADRIC: What do these numbers and letters mean?
DOCTOR: It's an early version. Instructions have to be punched in by machine code.
ADRIC: Oh, how boring.
DOCTOR: Boring?
—Doctor Who, Logopolis
cargo install --locked rx82This is an emulator for the RX82 architecture, an imagined home computer system similar to those of the early 1980s, such as the Sinclair ZX81 and Spectrum, the BBC Micro, or the Commodore 64.
The RX82's design is intended not only to evoke fond memories in those of a certain age, but also to help teach the fundamentals of computer systems architecture and computer engineering. It's simpler than historic systems such as the ZX81, because no cost or design compromises are required, but also realistic enough to be useful for learning purposes.
Its central processor is the R8, a fan-fiction CPU design comparable to the Zilog Z80 or the MOS 6502, but again, somewhat simplified for educational purposes.
This crate provides a reference implementation of the RX82 and R8 architectures, and an assembler / disassembler for use with R8 assembly language programs. However, it is intended to be modular, so that you can pick and choose components to build your own systems.
For example, you could use the R8 CPU as part of your own emulator that replaces the RX82 system with something else. Equally, you could use the RX82 system components but replace the CPU with a design of your own, or an emulated real machine such as a 6502.
Prepare your program in a text file (see R8 Assembly Language below), and run:
rx82 asm my_prog.asmIf the program assembles correctly, this will produce a my_prog.bin file you can run with the monitor.
To start the monitor in debug (single-step) mode:
rx82 mon(C) 1982 RX Computers Ltd.
0xBF00 bytes free. Ready.You can also optionally load and run a binary file (such as one produced by the assembler, for example):
rx82 mon my_prog.binTo run the binary in single-step mode, use the --step switch:
rx82 mon --step my_prog.binThe monitor displays the current CPU registers and the next instruction in memory, then prompts for a command. Type H for help:
RMON v1.0 (C) 1977 Solid State Technologies, Inc.
PC SP A B C D E F G H ZC | NEXT
C022 BFFF 02 00 BF FF 00 00 00 00 00 | halt
> h
Commands:
G [<address>] = Go (run till halted)
H = Help
M [<address>] = Memory dump
S [<address>] = Single step
Q = Quit
Enter = Repeat last command
>To dump memory, use the M command. This will print a block of memory starting at the current value of pc:
> m
0000: 10 06 19 FF FF 49 B2 FD 40 B2 F7 00 00 00 00 00
0010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
...Press Enter to dump the next block:
>
0080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
...To dump memory from a specific address, enter the address in hex:
> m fff0
FFF0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 C0
0000: 10 06 19 FF FF 49 B2 FD 40 B2 F7 00 00 00 00 00
...Run:
rx82 dis my_prog.binThis will print the disassembled listing.
The RX82 is a single-board computer with one R8 CPU clocked at 4Mhz, 64KiB of static RAM, an 8-bit data bus, and a 16-bit address bus.
| Address | Contents |
|---|---|
| 0x0000 | Trap/interrupt table |
| 0x0080 | System data area |
| 0x0100 | User RAM |
| 0xC000 | ROM |
| 0xFF00 | System I/O area |
| 0xFFFE | Reset vector |
At power on, the CPU loads the reset vector at 0xFFFE, which in the RX82 system holds the ROM entry point, 0xC000. Execution begins here and a simple RAM test is performed to find the highest writable address in memory. The stack pointer is initialised to this address.
The trap table is initialised, and all undefined traps are vectored to a single 'undefined trap' handler.
Finally, the interactive monitor is invoked.
The following general-purpose traps are defined:
| Code | Name | Purpose | Inputs |
|---|---|---|---|
| 0x20 | PUTCHAR | Print character to terminal | A = ASCII code of character |
| -0 | -1 | -2 | -3 | -4 | -5 | -6 | -7 | -8 | -9 | -A | -B | -C | -D | -E | -F | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0- | halt | nop | sec | clc | ret | rti | ||||||||||
| 1- | ld a, N | ld b, N | ld c, N | ld d, N | ld e, N | ld f, N | ld g, N | ld h, N | ld ab, NN | ld cd, NN | ld ef, NN | ld gh, NN | ld sp, NN | ld R, (RR) | ld R, R | |
| 2- | ld NN, a | ld NN, b | ld NN, c | ld NN, d | ld NN, e | ld NN, f | ld NN, g | ld NN, h | ld (RR), R | |||||||
| 3- | inc a | inc b | inc c | inc d | inc e | inc f | inc g | inc h | inc ab | inc cd | inc ef | inc gh | inc sp | inc (RR) | inc (NN) | |
| 4- | dec a | dec b | dec c | dec d | dec e | dec f | dec g | dec h | dec ab | dec cd | dec ef | dec gh | dec sp | dec (RR) | dec (NN) | |
| 5- | add a, N | add b, N | add c, N | add d, N | add e, N | add f, N | add g, N | add h, N | ||||||||
| 6- | sub a, N | sub b, N | sub c, N | sub d, N | sub e, N | sub f, N | sub g, N | sub h, N | ||||||||
| 7- | cmp a, N | cmp b, N | cmp c, N | cmp d, N | cmp e, N | cmp f, N | cmp g, N | cmp h, N | cmp ab, N | cmp cd, N | cmp ef, N | cmp gh, N | ||||
| 8- | and a, N | and b, N | and c, N | and d, N | and e, N | and f, N | and g, N | and h, N | ||||||||
| 9- | ||||||||||||||||
| A- | lsr a, S | lsr b, S | lsr c, S | lsr d, S | lsr e, S | lsr f, S | lsr g, S | lsr h, S | ||||||||
| B- | ||||||||||||||||
| C- | ||||||||||||||||
| D- | push a | push b | push c | push d | push e | push f | push g | push h | push ab | push cd | push ef | push gh | ||||
| E- | pop a | pop b | pop c | pop d | pop e | pop f | pop g | pop h | pop ab | pop cd | pop ef | pop gh | ||||
| F- | bra D | beq D | bne D | bcs D | bcc D | jmp | call NN | trap T |
This is a cycle-stepped emulator (sometimes called a “low-level” emulator) that models the whole computer system, including the CPU, devices, bus, and so forth. Unlike a “high-level”, or instruction-stepped emulator, where the CPU “owns” all the resources, such as memory, and can manipulate them directly, in a low-level emulator the CPU must read and write signals to the bus like any other device.
This makes it more complicated, since the emulator must model the CPU's internal state (fetch, decode, execute, and so on), the bus signalling, and all the devices, but it's also more realistic and interesting.
If you're interested in writing an emulator, though, it's much easier to get started with a high-level one. You can read a tutorial series on writing a high-level R8 emulator here:
- 0.5.0 —
organddatadirectives, traps implemented,trap,rti,call,ret,ld (RR), R,ld R, R,push,pop,inc/dec (RR),inc/dec (NN),brainstructions, reset vector, stack pointer, ROM binary, forward labels - 0.4.0 —
beq,bne,inc,dec, andcmpinstructions; zero and carry flags; backward labels, comments - 0.3.0 — all registers, load immediate and store direct instructions
- 0.2.0 — monitor improvements, add
haltinstruction, add assembler - 0.1.0 — first release
