A computer architecture
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

208 lines
8.8 KiB

Thingamajig v2.0
Thingamajig v2.0 is a RISC/MISC homebrew computer architecture. Its git
9 months ago
repository can be found at
Included Software
The repository includes an emulator implementation of Thingamajig with
device control programs, and an assembler and a disassembler, all
written in FreePascal. It also includes couple of simple example
programs for Thingamajig written in assembly.
Registers and Memory
* 24-bit instruction register IR
* 16-bit instruction and return pointers IP and RP
* 8-bit general-purpose registers R0-R3
* 8-bit memory locations 0-FFFF
Multi-byte values are big-endian. Memory locations 0-FFEF are used for
RAM while FFF0-FFFF are reserved for memory mapped devices.
Input and output are mapped to address FFFF, while arbitrary devices can
be mapped to the other reserved addresses. When interacting with memory
mapped devices Thingamajig will stop processing to wait for the device
to be ready if needed.
Instructions without an immediate or address argument are 8-bit, those
with an immediate one 16-bit, and those with an address one 24-bit. The
instruction pointer is incremented before being accessed or modified.
1 RET IP = *RP; RP += 2
2 SHL RX, N RX <<= N (logical) Shifts of 1-4 steps,
3 SHR RX, N RX >>= N (logical) with 4 encoded as 0
4 ROL RX, N RX <<= N (rotating) in machine code.
5 ROR RX, N RX >>= N (rotating)
6 NAND RX, RY RX = ~(RX & RY)
8 OR RX, RY RX |= RY
A LOAD RX, ~0, IMM RX = IMM Written as "LOAD RX, #IMM"
0, ADDR RX = *ADDR Written as "LOAD RX, ADDR"
E CLEQ RX, RY, ADDR if (RX == RY) {RP -= 2; *RP = IP; IP = ADDR}
F CLNEQ RX, RY, ADDR if (RX != RY) {RP -= 2; *RP = IP; IP = ADDR}
Assembly Language
Lines of assembly are of the following form:
The language is case-insensitive and uses hexadecimal numbers. A label
can consist of any alphanumeric characters as long as it is not
interpretable as a hexadecimal number. The label, instruction, and
comment elements are all optional, as is spacing between the arguments.
For the arguments of each instruction see the previous section.
Address arguments can be either absolute addresses or references to or
relative to a label. Relative references are of the form LABEL +/- N;
the spacing is optional.
In addition to the true instructions there are three
pseudo-instructions. ORG sets the location of the following code and
data; as it has no direct equivalent in machine code it cannot have a
label. The default starting address of 0 does not need to be indicated
with ORG. DATA introduces a byte of data. ADDR introduces two bytes of
data containing the address of a reference to or relative to a label.
At boot the initial program loader (IPL) loads a program to RAM starting
at address 0 after which is cedes control to the CPU. If an
implementation has a front panel the IPL is optional. The instruction
and return pointers are initialised as 0 and the first address after RAM
respectively, while other registers and RAM are uninitialised.
Emulator and Device Control Programs
* emulator (-v) program (2> verbose_output)
* tapectl (-r tape) (-p tape)
* floppyctl (-0 disc) (-1 disc)
* modemctl -o/[-a address:port]/[-d address:port]/-h
By default the emulator runs at roughly 500 KIPS and has 2 KiB of RAM.
The arguments -dRAM4, -dRAM8, -dRAM16, -dRAM32, and -dRAM64 can be used
to compile the emulator with 4, 8, 16, 32, or 64 KiB (minus the reserved
addresses) of RAM respectively instead and the speed limitations can be
removed with the argument -dfast. When run with the argument -v the
current state of the registers is output to stderr before each
Input and output are handled by an emulated roughly 1000 CPS
ASCII-compatible glass teletype terminal with local echo on by default.
Of the control characters bell (^G), backspace (^H), line feed (^J),
carriage return (^M), and device control characters two (^R) and four
(^T) are used by the terminal: the device control characters are used to
turn the local echo on and off respectively while the rest have their
standard uses. The backspace and delete keys input their respective
characters and non-character keys null.
In Linux the emulator can be compiled with support for a character
printer, an emulated high speed 8-bit paper tape reader and punch, an
emulated two-drive 8" floppy disc system, a modem, and an input status
register with the arguments -dprinter, -dtape, -dfloppy, -dmodem, and
-dstatus respectively. Full 64 KiB of RAM and all of these options can
also be enabled with the argument -dfull. The printer is mapped to
address FFFE, the tape reader and punch to FFFD, the disc system to FFFB
and FFFC, the modem to FFF9 and FFFA, and the input status register to
The printer prints into /dev/usb/lp0. The tape files read from and
punched to are (re)set using the program tapectl with the arguments -r
and -p respectively and the disc files in drives 0 and 1 using the
program floppyctl with the arguments -0 and -1 respectively. The disc
system uses hard sectored single-sided discs with 77 tracks of 32
sectors of 137 bytes, or 337568 bytes in total: the disc files must be
of this size. The modem is controlled by the program modemctl: the
options -o and -a are used to set the originate and answer modes, the
latter with the address and port to be listened; -d to dial an address
and port to be called; and -h to hang. Dialing when in answer mode
automatically switches the modem to originate mode. The modem hangs
automatically if the connection is lost or hanged from the other side,
if another address and port are dialed, if a mode change command is
given, or if the emulator is halted.
The floppy disc system uses two ports: command at FFFB and data at FFFC.
Only the low nibble of the command port is used, consisting of a
three-bit command followed by a one-bit drive number used as an argument
by instructions 1 and 4-7. The track or sector to be accessed is input
to and the buffer accessed sequentially through the data port after the
relevant command is input to the command port. New commands other than
resetting the system are ignored until the current command is fully
executed. Note that each sector begins with a synchronisation bit that
must always be set.
The commands for the disc system are:
0: Reset the system.
1: Format a disc.
2: Read a sector from the buffer to the computer.
3: Write a sector from the computer to the buffer.
4: Set the track to be accessed.
5: Set the sector to be accessed.
6: Read a sector from a disc to the buffer.
7: Write a sector from the buffer to a disc.
The modem also uses two ports: status at FFF9 and data at FFFA. Only the
least significant bit of the status port is used, indicating whether
the modem is connected or not. Unsetting the bit hangs the modem while
setting it in answer mode hangs any current call and listens for an
incoming call to answer. Setting the bit in originate mode is ignored.
The input status register can be used to check if a device is ready to
be read from. The reserved addresses FFF8-FFFF are mapped to the bits
7-0: a set bit means either that the device is ready or that no input
device is mapped to the address in question.
The IPL loads the program specified as an argument when running the
Assembler and Disassembler
* assembler program (< input)
* disassembler program (> output)
Both the assembler and the disassembler are run with a program as their
sole argument: they take their input from and print their output to
stdin and stdout respectively.
An initial gap created with ORG is not included in an assembled program.
All possible interpretations of a disassembled program are included in
its listing, resulting in overlapping information.
* Added the ability to shift a register multiple steps in one
* Changed the register argument of STORE from RX to RY
* Added support for an emulated floppy disc system and modem and an
input status register to the emulator
* Added the ability to use ORG non-initially to the assembler
* Changed tapectl so that it uses arguments for input
* Initial release