This guide provides an overview of the TISC instruction set and the T81 Virtual Machine (VM) that executes it.
Last Updated: February 17, 2026
Companion Documents:
spec/tisc-spec.md, spec/t81vm-spec.mdinclude/t81/isa/opcodes.hpp: The Opcode enum.core/vm/vm.cpp: The VM implementation.tests/cpp/t81_vm_*_test.cpp, tests/cpp/e2e_*_test.cppThe TISC (Ternary Instruction Set Computer) is the low-level, stable assembly language of the T81 ecosystem. The T81 Virtual Machine (VM) is the interpreter that executes TISC bytecode.
.t81 source files into TISC.BinaryEmitter encodes TISC into a compact binary format.This separation ensures that the compiler and the VM are decoupled, connected only by the stable TISC specification.
r0 is often used for return values._pc, tracks the address of the next instruction to be executed.The following TISC opcodes are defined in opcodes.hpp and implemented in the VM.
| Category | Opcodes |
|---|---|
| Control Flow | Halt, Nop, Jump, JumpIfZero, JumpIfNotZero, JumpIfNegative, JumpIfPositive, Call, Ret, Trap |
| Memory | LoadImm, Load, Store, Mov, Push, Pop |
| Integer Arithmetic | Add, Sub, Mul, Div, Mod, Inc, Dec, Cmp, Neg |
| Ternary Logic | TNot, TAnd, TOr, TXor |
| Float Arithmetic | FAdd, FSub, FMul, FDiv |
| Fraction Arithmetic | FracAdd, FracSub, FracMul, FracDiv |
| Type Conversion | I2F, F2I, I2Frac, Frac2I |
| Comparison Boolean | Less, LessEqual, Greater, GreaterEqual, Equal, NotEqual |
| Tensor Operations | TVecAdd, TMatMul, TTenDot, ChkShape, TNorm, TLoadHash |
| Option/Result Types | MakeOptionSome, MakeOptionNone, OptionIsSome, OptionUnwrap, MakeResultOk, MakeResultErr, ResultIsOk, ResultUnwrapOk, ResultUnwrapErr |
| Axion Interface | AxRead, AxSet, AxVerify, AxCheck, AxSign, AxLineage, AxCanon, AxReport |
| Allocator / Metadata | StackAlloc, StackFree, HeapAlloc, HeapFree, WeightsLoad |
| Assertion / Debug | Assert, AxHalt |
| Memory (Advanced) | Canon, MemZero, Copy |
| Cognitive (Symbolic) | SymLoad, SymRewrite, SymConfluence, SymCanon, SymBind |
| Cognitive (Reflective) | ReflCap, ReflJustify, ReflCheck, ReflTrace, ReflSeal |
| Cognitive (Recursive) | Recurse, Contract, Entropy, Depth, Terminate |
| Cognitive (Distributed) | Merge, Gossip, TickSync, Coherence, DistSeal |
| Cognitive (Infinite) | InfSeed, InfExpand, InfCollapse, InfConverge, InfSignature |
StackAlloc, StackFree, HeapAlloc, HeapFree encode the deterministic allocator model described in spec/t81vm-spec.md. Every stack allocation is bounded by the current stack limit (Axion policy layers may adjust the limit via hints) and must pair StackAlloc with a matching StackFree within the same lexical scope; missing frees raise deterministic traps rather than silently overflow. Heap allocations obey the same Axion-guided guards—VM state keeps per-program counters and faults when any request would exceed the configured heap cap.+∞ / -∞ invariants. The VM also uses them when lowering loop/match constructs that require temporary buffers or when the new weights.load builtin materializes handles.StackAlloc/StackFree for all short-lived temporaries so the Axion trace can track stack depth precisely. Heap paths (HeapAlloc/HeapFree) are reserved for long-lived state such as tensors stored across invocations or weights handles; the VM tracks these with the same deterministic telemetry used by Axion’s policy text and loop metadata.To demonstrate how allocator ops and Axion policy text interplay, consider a simple loop in T81Lang:
loop {
let n = 0;
if (n > 10) break;
n = n + 1;
}
When the frontend lowers this loop, it emits StackAlloc/StackFree around any temporary n values and annotates the loop with a loop hint (file/line/column). The HanoiVM produces an Axion policy block such as:
(policy
(tier 1)
(loop
(id 0)
(file examples/demo.t81)
(line 12)
(column 5)
(annotated true)
(depth 0)
(bound infinite)))
This policy text is emitted whenever ./build/t81 code run executes the TISC program, giving downstream consumers deterministic diagnostics (file:line:column) and exposing Axion’s loop-tracking hooks. If the loop tries to grow the stack beyond the configured limit, the VM traps before Axion ever allows a +∞ overflow; the Axion log entry and the policy text show the same metadata used by diagnostics, closing the trace from source to runtime. For a concrete CLI command/output pair you can copy into logs or release notes, see the Axion CLI Trace Example in the demo gallery guide.
The comparison boolean opcodes produce canonical 0/1 values, so a simple relational expression such as:
let cmp = 1 < 2;
produces the following TISC sequence (after lowering):
LOADI r1 1
LOADI r2 2
Less r0 r1 r2 ; emits 1 if r1 < r2, 0 otherwise
The frontend IR generator attaches a ComparisonRelation to the CMP instruction and marks it as a boolean result, allowing the binary emitter to lower it directly to the appropriate HanoiVM opcode instead of relying on flag-based CMP + conditional jumps.
This section provides a conceptual walkthrough for adding a new instruction to the TISC and the VM. We will use the example of adding a hypothetical MOD (modulo) instruction.
include/t81/isa/opcodes.hpp and add your new opcode to the Opcode enum.spec/tisc-spec.md. This includes assigning a binary encoding and defining the precise semantics.In core/vm/vm.cpp, find the main switch statement in the execute or run method and add a new case for your opcode. The logic should:
// in VM::execute() in core/vm/vm.cpp
switch (instruction.opcode) {
// ...
case Opcode::MOD: {
auto dest = instruction.operands[0].as_register();
auto src_a = instruction.operands[1].as_register();
auto src_b = instruction.operands[2].as_register();
auto val_a = _state.registers[src_a.index];
auto val_b = _state.registers[src_b.index];
if (val_b.is_zero()) {
// This should trigger a spec-compliant VM fault.
trap(TrapCode::DivisionByZero);
break;
}
_state.registers[dest.index] = val_a % val_b;
break;
}
// ...
}
tests/cpp/, such as vm_my_opcode_test.cpp.tisc::Program with your new instruction, set up the initial VM state (registers), execute the program, and assert that the final state is correct. See tests/cpp/t81_vm_divmod_test.cpp for a good example.CMakeLists.txt.