version 0.1

Architecture specification

Complete enough that a second, independent emulator could be built from this page alone. Everything here is what the playground actually executes.

Number system

A trit holds one of three values, written - for -1, 0 for 0, and + for +1. Trits are written most significant first, so the digit at position i from the right carries weight 3i.

  • Zero is all-zero trits and has exactly one representation.
  • Negation is trit-wise inversion; there is no sign trit and no two's-complement rule.
  • The sign of a value is the sign of its most significant non-zero trit.
  • Arithmetic that leaves the word range wraps within 729 states and sets the overflow flag.
DecimalBalanced ternary word
100000+
-100000-
8000+0-
-8000-0+
1210+++++
364++++++
-364------

word dial

set each switch to - 0 +
243
81
27
9
3
1
reads000----9 -3 -1 =-13

Machine word

trits per word6 (one "tryte")
distinct values729
integer range-364 .. 364
register width6 trits
memory unit1 word
instruction width3 words (18 trits)
overflowwrap-around, OVF flag set

Registers

8 general-purpose registers plus three special registers. R0 is hardwired to zero: writes to it are discarded.

R0constant 0, immutable
R1 .. R7general purpose, reset to 0
PCprogram counter, reset to 0, advances by 3
SPstack pointer, reset to 364, grows downward
FLAGSSIGN (-, 0, +), OVF, HALT

SIGN is a single trit rather than a set of boolean condition bits: arithmetic sets it to the sign of the result, and CMP sets it to the sign of the difference. Conditional branches read it directly — JLT on -, JEQ on 0, JGT on +.

Memory

size729 words
addresses-364 .. 364 (balanced, like any word)
reset stateevery word is 0
program originaddress 0, growing upward
stackfrom 364 downward
out-of-range accessexecution error, machine halts

Instruction encoding

Fixed width: every instruction is exactly 3 words.

WordContents
PC + 0opcode
PC + 1operand A — register number, immediate, or address
PC + 2operand B — register number, immediate, or address

The opcode fixes the operand kinds, so ADD Rd, Rs and ADD Rd, value are separate opcodes. Unused operand words are 0. An opcode with no definition raises an invalid-instruction error and halts the machine.

Assembly syntax

comment; to end of line
labelNAME: at the start of a line
registerR0 .. R7
decimal literal42, -17
ternary literal+0- or 0t+0-
memory reference[100], [LABEL], [R2]

The assembler reports unknown instructions, invalid registers, malformed literals, wrong operand counts, invalid operand types, duplicate labels, unresolved labels, and out-of-range values — each with its source line.

Instruction set

Machine control

SyntaxOpcodeEncodedEffect
NOP0000000No state change. PC += 3.
HALT100000+Sets HALT flag; execution stops.

Data movement

SyntaxOpcodeEncodedEffect
MOV Rd, Rs20000+-Rd <- Rs. Updates SIGN.
MOV Rd, value30000+0Rd <- immediate. Updates SIGN.

Memory access

SyntaxOpcodeEncodedEffect
LOAD Rd, [addr]40000++Rd <- mem[addr]. Updates SIGN.
LOAD Rd, [Rs]5000+--Rd <- mem[Rs]. Updates SIGN.
STORE [addr], Rs6000+-0mem[addr] <- Rs.
STORE [Rd], Rs7000+-+mem[Rd] <- Rs.

Arithmetic

SyntaxOpcodeEncodedEffect
ADD Rd, Rs8000+0-Rd <- Rd + Rs. Updates SIGN, OVF.
ADD Rd, value9000+00Rd <- Rd + immediate. Updates SIGN, OVF.
SUB Rd, Rs10000+0+Rd <- Rd - Rs. Updates SIGN, OVF.
SUB Rd, value11000++-Rd <- Rd - immediate. Updates SIGN, OVF.
MUL Rd, Rs12000++0Rd <- Rd * Rs. Updates SIGN, OVF.
MUL Rd, value13000+++Rd <- Rd * immediate. Updates SIGN, OVF.
NEG Rd1400+---Rd <- -Rd (trit-wise inversion). Updates SIGN.

Comparison

SyntaxOpcodeEncodedEffect
CMP Rd, Rs1500+--0SIGN <- sign(Rd - Rs). Registers unchanged.
CMP Rd, value1600+--+SIGN <- sign(Rd - immediate).

Control flow

SyntaxOpcodeEncodedEffect
JMP label1700+-0-PC <- addr.
JEQ label1800+-00PC <- addr if SIGN = 0.
JNE label1900+-0+PC <- addr if SIGN /= 0.
JLT label2000+-+-PC <- addr if SIGN = -.
JGT label2100+-+0PC <- addr if SIGN = +.
CALL label2200+-++Push return address, PC <- addr.
RET2300+0--Pop return address into PC.

Stack

SyntaxOpcodeEncodedEffect
PUSH Rs2400+0-0mem[SP] <- Rs, SP -= 1.
POP Rd2500+0-+SP += 1, Rd <- mem[SP].