> ## Documentation Index
> Fetch the complete documentation index at: https://docs.stoffelmpc.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Instructions and Types

> Stoffel VM instruction, register, value, function, and bytecode format reference.

Stoffel VM bytecode is register-based. Instructions operate on absolute frame registers, call functions by name before resolution, and are serialized into `.stflb` bytecode by `stoffel-vm-types`.

<img src="https://mintcdn.com/stoffellabs/WsJVEVCX73RSUEma/images/diagrams/vm-execution-model.svg?fit=max&auto=format&n=WsJVEVCX73RSUEma&q=85&s=3904911081be82c388b652e51f6e8ea5" alt="Stoffel VM execution model showing bytecode flowing into the instruction dispatcher, clear and secret register spaces, runtime stores, builtins, and MPC protocol hooks." width="1200" height="675" data-path="images/diagrams/vm-execution-model.svg" />

## Architecture Overview

The VM uses two related instruction forms:

| Form                  | Purpose                                                                                                                                   |
| --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| `Instruction`         | Symbolic representation with labels, function names, and embedded immediate `Value`s. Used by compiler output and direct VM construction. |
| `ResolvedInstruction` | Execution-oriented representation with label targets, constants, and call targets resolved to numeric indices.                            |

During function registration and bytecode loading, labels are resolved, immediates are interned into a per-function constant table, and `CALL("name")` becomes a numeric call-target index plus a call-target name table.

The runtime then lowers resolved instructions into packed runtime instructions for dispatch. The packed runtime opcode mapping is an internal optimization and is not the same thing as the serialized opcode values shown below.

## Registers

Bytecode register operands are absolute frame indices. The default layout uses register `16` as the secret-register boundary:

| Range     | Default bank     |
| --------- | ---------------- |
| `r0..r15` | clear registers  |
| `r16..`   | secret registers |

Important details:

* `r0` is the return register.
* The secret boundary is a layout convention, not a hard 32-register maximum.
* Each `VMFunction` has a frame register count. Registration normalizes the count so it is large enough for parameters, the return register, and every referenced register.
* The register file stores clear and secret banks separately even though bytecode operands are absolute indices.
* Moving clear values into secret registers creates or carries share values. Moving secret values back to clear registers becomes a reveal/open operation.
* Pending reveals are stored as register-slot state until the async MPC operation completes.

## Frame memory

Each activation frame contains:

* function name and local variable map;
* register file;
* captured upvalues;
* a volatile argument stack for `PUSHARG`, `LD`, and calls;
* a dedicated spill vector for `STS` / `LDS`;
* a compare flag;
* an instruction pointer;
* optional closure metadata.

`LD` reads from the current frame's argument stack. Offset `0` resolves to the top argument; negative offsets read below the top.

`STS` and `LDS` do not use that argument stack. They access a stable per-frame spill area used by register allocation, so spilled values survive between call argument pushes without being confused with function-call arguments.

## Value types

The VM value enum includes:

| Variant family        | Runtime shape                                                                       |
| --------------------- | ----------------------------------------------------------------------------------- |
| Signed integers       | `I64`, `I32`, `I16`, `I8`                                                           |
| Unsigned integers     | `U64`, `U32`, `U16`, `U8`                                                           |
| Other scalars         | `Float(F64)`, `Bool`, `String`, `Unit`                                              |
| VM-managed references | `Object(ObjectRef)`, `Array(ArrayRef)`, `Foreign(ForeignObjectRef)`, `Closure(...)` |
| Shares                | `Share(ShareType, ShareData)`                                                       |

Object, array, and foreign values are typed handles into VM-managed stores. They are not serialized as constants in `.stflb` files.

Share type metadata is shape-oriented:

```rust theme={null}
ShareType::SecretInt { bit_length }
ShareType::SecretUInt { bit_length }
ShareType::SecretFixedPoint { precision }
```

Useful defaults:

* secret int: 64 bits;
* secret bool: one-bit secret int;
* fixed point: 64 total bits, 16 fractional bits.

## Instruction set

### Loading and movement

| Instruction | Operands             | Effect                                                                |
| ----------- | -------------------- | --------------------------------------------------------------------- |
| `NOP`       | —                    | No operation.                                                         |
| `LD`        | `dest, stack_offset` | Load from current frame's argument stack.                             |
| `LDI`       | `dest, value`        | Load an immediate value; serialized bytecode stores a constant index. |
| `MOV`       | `dest, src`          | Move/copy a register value, including clear/secret bank transitions.  |
| `PUSHARG`   | `src`                | Push a register value onto the call argument stack.                   |
| `STS`       | `slot, src`          | Store a raw value into the frame spill area.                          |
| `LDS`       | `dest, slot`         | Load a raw value from the frame spill area.                           |

### Arithmetic and bitwise operations

Arithmetic instructions use `dest, left, right` operands:

| Instruction | Meaning               |
| ----------- | --------------------- |
| `ADD`       | `dest = left + right` |
| `SUB`       | `dest = left - right` |
| `MUL`       | `dest = left * right` |
| `DIV`       | `dest = left / right` |
| `MOD`       | `dest = left % right` |

Bitwise instructions:

| Instruction | Meaning                                             |
| ----------- | --------------------------------------------------- |
| `AND`       | `dest = left & right`                               |
| `OR`        | `dest = left \| right`                              |
| `XOR`       | `dest = left ^ right`                               |
| `NOT`       | `dest = !src` / bitwise not depending on value type |
| `SHL`       | `dest = value << amount_register`                   |
| `SHR`       | `dest = value >> amount_register`                   |

`SHL` and `SHR` take the shift amount from a register, not an immediate literal operand.

### Comparisons and jumps

`CMP left, right` sets a typed compare flag:

* `Less`
* `Equal`
* `Greater`

Conditional jumps read that flag:

| Instruction | Jumps when                  |
| ----------- | --------------------------- |
| `JMPEQ`     | comparison was equal        |
| `JMPNEQ`    | comparison was not equal    |
| `JMPLT`     | comparison was less than    |
| `JMPGT`     | comparison was greater than |

`JMP` jumps unconditionally to a label in symbolic form or instruction index in resolved form.

### Calls and returns

| Instruction | Purpose                                                                        |
| ----------- | ------------------------------------------------------------------------------ |
| `CALL name` | Call a VM or foreign function. Arguments must have been pushed with `PUSHARG`. |
| `RET src`   | Return a register value to the caller.                                         |

At the end of a VM function, the runtime also treats `r0` as the return register for fallthrough-style completion.

## Serialized opcode values

The opcode values used by serialized bytecode are:

| Hex    | Instruction |
| ------ | ----------- |
| `0x00` | `LD`        |
| `0x01` | `LDI`       |
| `0x02` | `MOV`       |
| `0x03` | `ADD`       |
| `0x04` | `SUB`       |
| `0x05` | `MUL`       |
| `0x06` | `DIV`       |
| `0x07` | `MOD`       |
| `0x08` | `AND`       |
| `0x09` | `OR`        |
| `0x0A` | `XOR`       |
| `0x0B` | `NOT`       |
| `0x0C` | `SHL`       |
| `0x0D` | `SHR`       |
| `0x0E` | `JMP`       |
| `0x0F` | `JMPEQ`     |
| `0x10` | `JMPNEQ`    |
| `0x11` | `CALL`      |
| `0x12` | `RET`       |
| `0x13` | `PUSHARG`   |
| `0x14` | `CMP`       |
| `0x15` | `JMPLT`     |
| `0x16` | `JMPGT`     |
| `0x17` | `NOP`       |
| `0x18` | `LDS`       |
| `0x19` | `STS`       |

## Bytecode format

Compiled bytecode is stored in `.stflb` files. The format is defined by `stoffel-vm-types::compiled_binary`.

Current format facts:

* magic bytes: `STFL`;
* format version: `9`;
* version 9 added `LDS` / `STS` spill-slot instructions;
* generic collection guardrail: 1,000,000 items;
* per-function instruction guardrail: 8,000,000 instructions;
* string/blob guardrail: 16 MiB.

Top-level serialized layout:

```text theme={null}
magic bytes:       4 bytes  "STFL"
format version:    u16
constant count:    u32
constants:         scalar constants only
function count:    u32
functions:         compiled function records
client IO manifest versioned fields, when present
```

### Constants

The constant pool supports scalar constants:

* `Unit`
* signed and unsigned integer values
* `Float`
* `Bool`
* `String`

Complex runtime values such as objects, arrays, foreign objects, closures, and shares are created at runtime and are not serialized as constants.

### Function records

A compiled function stores:

* name;
* parameters;
* parameter types;
* return type;
* upvalues;
* optional parent function name;
* frame register count;
* labels;
* instructions.

Function names, parameter names, upvalues, and labels are length-prefixed strings. Register counts and many counts are bounded integer fields; instruction and label offsets use wider fields for large generated programs.

### Client and MPC manifest

The bytecode manifest carries MPC-facing metadata used by the CLI and SDK:

* selected MPC backend, such as HoneyBadger or AVSS;
* selected curve/field configuration;
* client input/output schemas by client slot;
* static preprocessing demand estimate.

The preprocessing estimate includes counts for Beaver triples, random shares, PRandBits, PRandInts, and a `dynamic` flag for cases where runtime demand may exceed the static estimate.

## See also

* [Virtual Machine Overview](./overview)
* [Stoffel VM Implementation](./implementation)
* [Built-in Functions](./builtins)
