RCA COSMAC CDP180219768-bit3 MHzno stack · no multiply · no divide

Four programs.
One chip from 1976.
Every byte written by hand.

STELLAR is a multitasking virtual machine for the RCA 1802, written straight in hex with no assembler. The four screens below are running on STELLAR's real firmware, on an emulated 1802, right now in your browser. It isn't a video and it isn't a re-implementation. The picture beside them is the chip's memory, lit up as it works.

clock
The die 32 KB of RAM · one pixel per byte
hover the die · click to enlarge

Every pixel is one byte of RAM. Colour: the chip running code there, for VM1 VM2 VM3 VM4 or the scheduler. White: a byte just changed. What each block is ↓

CIDP$2F00
time on a real Elf2K
0:00
1802 instructions
0
STELLAR opcodes
0
1802 instructions per opcode
—
running now
—
who has the CPU the scheduler's hand-offs · newest on the right · width = time

One detail the browser changes. A real Elf2K has one serial port, so these four programs would share one terminal and draw over each other. Here each byte is sorted by the VM that sent it, and each key you type goes only to the screen you clicked. Everything else, including the scheduling, the timing and every instruction, is the real firmware. Click Invaders and press a key to play.

01

Reading the die

The die is the machine's whole memory, all 32 KB of it, drawn as a picture: one pixel per byte, 128 bytes to a row, from $0000 at the top left to $7FFF at the bottom right. Each byte glows faintly by its value, so code and tables have a texture and empty memory is black. On top of that, every instruction the 1802 fetches lights its byte in the colour of the VM it is working for, and every byte that changes flashes white. Both fade within a few frames, so the picture shows where the chip is working right now. Hover to read any byte; click the die to enlarge it.

The coloured light is almost all in the firmware, because that is the code the 1802 actually runs. A program's own STELLAR bytecode, down in its VM block, is data to the chip: the firmware reads it one opcode at a time and runs the handler for it. So the program blocks light up white, where programs write their variables and screens, and the firmware lights up in colour, showing which handlers each program is keeping busy.

kernel$0000–$07FF · 2 KB Start-up, the scheduler that hands the chip from VM to VM every few opcodes, the call-and-return routines, and the error handling. It lights in every VM's colour in turn.
dispatch$0800–$09FF · 512 B The opcode table: for each of the 256 possible STELLAR opcodes, the two-byte address of the code that carries it out. Looked up once per opcode.
opcode handlers$0A00–$2EFF · 9.3 KB The 1802 code for every STELLAR command: moves, maths, tests, branches, printing, I/O. Each bright streak is a handler at work; its colour says which program asked for it.
CIDP$2F00–$2FFF · 256 B The Common Interchange Data Page, shared by everything: one 16-byte entry per VM (its pages, state and command count), the scheduler's own state at $2F50 (which VM has the chip, how many there are, multitasking on or off), and the 1802's hardware stack at the top. Only 2 pixels tall on the die, so beside the die it has its own block just above VM1, joined by a dashed line to its real place, and it is shown byte by byte in the CIDP table under the die: each VM's row in its colour, the running VM's row lit, changes flashing. Hover a byte there to see what it is.
cores$3000–$3FFF · 4 × 1 KB Each VM's core: its 16 registers, the accumulators, flags, the settings its program has chosen (ports, memory mode), its stacks and labels. They flash white constantly, because every opcode changes a register.
VM1$4000–$4FFF · 4 KB VM1's program block: the program's bytecode at the start, then its strings, tables and variables. VM2 $5000, VM3 $6000 and VM4 $7000 are laid out the same way. A block that stays dark is code being read, not written; white is the program updating its data, like Mandelbrot's picture or Invaders' positions.
02

Fair by opcode, not by time

Watch the timeline while Invaders waits at press any key. STELLAR's scheduler gives every VM the same turn, three opcodes, and then moves on. That's fair by count. But opcodes aren't equal. While it waits, Invaders keeps calling $C3 RAND to stir its random seed, and a single RAND costs thousands of 1802 instructions. So its three opcodes take far longer than anyone else's, and the pink VM ends up with most of the chip.

Press a key in Invaders and watch its share fall. The program's own listing says it plainly:

; D 400B C3             RAND                   Stir the generator while we wait
; D 400C CC             SERST                  A key yet?
; D 400D A1 00 0B       IFFALSEI SEED
; D 4010 CB             SERIN                  Take it and discard it
03

One opcode, all the way down

Choose a VM and follow its most recent instruction through every layer: from the STELLAR bytecode it was written in, to the 1802 machine code the firmware runs to carry it out, to the bytes of RAM that change as a result. Freeze the machine to read one, and Step to move on by exactly one opcode.

A STELLAR bytecode what the programmer wrote
B The opcode one instruction of the virtual machine
C 1802 machine code what the chip actually ran for it
D Bytes in RAM this VM's 256-byte core
04

There is no assembler

STELLAR's firmware lives in a Word document with two columns: notes on the left and hex on the right. Every instruction of the 1802 code you just watched was worked out by hand, typed as bytes and tested on a real Elf2K. The firmware image this page runs is extracted straight from that document.

Programs are delivered the same way, as D-lines that the Elf2K's monitor loads byte by byte. The tools on this site (the disassembler, this emulator, the opcode table) came later, and were written to check the hand work, not to replace it.

The workbench

The rest of the site covers the same machine one piece at a time.