ContentsInstruction reference

Instruction reference

On this page
  1. Control
  2. Parametric and variables
  3. Memory
  4. Constants, tests and comparisons
  5. Arithmetic and bits
  6. Conversions
  7. Wide arithmetic
  8. Traps
  9. Everything else

The 115 accepted instructions, by opcode byte. "Stack" shows what an instruction pops and pushes, bottom to top, with [t] for a value that depends on the label or function. Every instruction except else and end costs its price from the price list before it executes (exact metering). Values are i32 and i64. The definitions are those of the dated WebAssembly Core 1.0 text, plus the sign-extension operators and the two bulk memory operations of Release 2.0, and the four instructions of the wide-arithmetic proposal (the execution profile); the reference interpreter in src/vm/interp.rs implements them directly. The rules on this page are normative; where they are silent, the dated texts decide.

Control#

ByteInstructionImmediatesStackMeaning
00unreachableTraps.
01nopDoes nothing.
02blockblock typeOpens a region; a branch to it continues after its end.
03loopblock typeOpens a region; a branch to it continues at its first instruction.
04ifblock typei32 →Opens a region and runs the then-branch for a non-zero condition, otherwise the else-branch or nothing.
05elseSeparates the branches of an if; free.
0bendCloses a region, or the function; free.
0cbrdepth[t] →Branches to the depth-th enclosing label, carrying its value if it has one.
0dbr_ifdepth[t] i32 → [t]Branches when the condition is non-zero; otherwise leaves the value in place.
0ebr_tabledepths, default[t] i32 →Branches to the label at the unsigned index, or to the default when the index is out of range.
0freturn[t] →Leaves the function with its result, if any.
10callfunctionparams → [result]Calls a function; a host import runs its host rule.
11call_indirecttype, 00params i32 → [result]Calls the entry of table 0 at the unsigned index; traps on an index outside the table, a null entry, or an entry whose type differs structurally (in its parameter and result types, not its type index) from the expected type. Otherwise exactly like call.

Parametric and variables#

ByteInstructionImmediatesStackMeaning
1adropt →Discards a value.
1bselectt t i32 → tKeeps the first value when the condition is non-zero, the second otherwise; all three are evaluated.
20local.getlocal→ tReads a parameter or local.
21local.setlocalt →Writes a parameter or local.
22local.teelocalt → tWrites and keeps the value.
23global.getglobal→ tReads a global.
24global.setglobalt →Writes a mutable global.

Memory#

Memory is a byte array of 64 KiB pages. Each access computes its effective address as the unsigned 32-bit address plus the unsigned 32-bit offset, in unbounded arithmetic, and traps when the address plus the access width exceeds the current memory size: an address never wraps around into valid memory, and a store that traps writes nothing. Bytes are little-endian. Narrow signed loads sign-extend, narrow unsigned loads zero-extend, and narrow stores keep the low bytes. Alignment immediates are hints and never change behaviour.

ByteInstructionStackMeaning
28i32.loadi32 → i324 bytes.
29i64.loadi32 → i648 bytes.
2ci32.load8_si32 → i321 byte, sign-extended.
2di32.load8_ui32 → i321 byte, zero-extended.
2ei32.load16_si32 → i322 bytes, sign-extended.
2fi32.load16_ui32 → i322 bytes, zero-extended.
30i64.load8_si32 → i641 byte, sign-extended.
31i64.load8_ui32 → i641 byte, zero-extended.
32i64.load16_si32 → i642 bytes, sign-extended.
33i64.load16_ui32 → i642 bytes, zero-extended.
34i64.load32_si32 → i644 bytes, sign-extended.
35i64.load32_ui32 → i644 bytes, zero-extended.
36i32.storei32 i32 →4 bytes.
37i64.storei32 i64 →8 bytes.
3ai32.store8i32 i32 →The low byte.
3bi32.store16i32 i32 →The low 2 bytes.
3ci64.store8i32 i64 →The low byte.
3di64.store16i32 i64 →The low 2 bytes.
3ei64.store32i32 i64 →The low 4 bytes.
3fmemory.size→ i32The current size in pages.
40memory.growi32 → i32Appends that many zeroed pages and yields the previous size, or yields −1 with no effect when the new size would exceed the declared maximum. Growth by zero pages succeeds and yields the current size. Charges 40,000 C per new page; running out of compute there fails the invocation rather than yielding −1.
fc 0amemory.copyi32 i32 i32 →Destination, source, length n: moves n bytes as if the source were first copied aside, so overlapping ranges move correctly. Charges bytes(n), then traps before writing anything if any part of either range lies outside memory.
fc 0bmemory.filli32 i32 i32 →Destination, value, length n: writes the low byte of the value n times. Same charging and bounds rule.

A zero-length copy or fill whose addresses are at or below the end of memory is in bounds.

Constants, tests and comparisons#

ByteInstructionImmediatesStack
41i32.constsigned LEB128→ i32
42i64.constsigned LEB128→ i64
45i32.eqzi32 → i32
46–4fi32.eq, ne, lt_s, lt_u, gt_s, gt_u, le_s, le_u, ge_s, ge_ui32 i32 → i32
50i64.eqzi64 → i32
51–5ai64.eq, ne, lt_s, lt_u, gt_s, gt_u, le_s, le_u, ge_s, ge_ui64 i64 → i32

Results are 1 or 0. _s compares two's-complement signed values, _u unsigned. eqz tests for zero.

Arithmetic and bits#

i32i64InstructionMeaning
6779clzLeading zero bits; the width for zero.
687actzTrailing zero bits; the width for zero.
697bpopcntSet bits.
6a7caddWrapping.
6b7dsubWrapping.
6c7emulWrapping, the low bits of the product.
6d7fdiv_sSigned, truncating toward zero; traps on a zero divisor and on the minimum value divided by −1.
6e80div_uUnsigned; traps on a zero divisor.
6f81rem_sSigned remainder with the dividend's sign; traps on a zero divisor; the minimum value by −1 is 0.
7082rem_uUnsigned; traps on a zero divisor.
7183andBitwise.
7284orBitwise.
7385xorBitwise.
7486shlShift left by the count modulo the width.
7587shr_sArithmetic shift right by the count modulo the width.
7688shr_uLogical shift right by the count modulo the width.
7789rotlRotate left by the count modulo the width.
788arotrRotate right by the count modulo the width.

Binary operators take the left operand first: a b sub is a − b, and the shift or rotation count is the second operand. Shifts and rotations use only the low 5 bits of the count for i32 and the low 6 bits for i64. Unsigned division and remainder are the ordinary unsigned operations.

Conversions#

ByteInstructionStackMeaning
a7i32.wrap_i64i64 → i32The low 32 bits.
aci64.extend_i32_si32 → i64Sign-extended.
adi64.extend_i32_ui32 → i64Zero-extended.
c0i32.extend8_si32 → i32The low 8 bits, sign-extended.
c1i32.extend16_si32 → i32The low 16 bits, sign-extended.
c2i64.extend8_si64 → i64The low 8 bits, sign-extended.
c3i64.extend16_si64 → i64The low 16 bits, sign-extended.
c4i64.extend32_si64 → i64The low 32 bits, sign-extended.

Wide arithmetic#

Four instructions compute with 128-bit integers held as two i64 values, the low half below the high half on the stack. They are the four instructions of the WebAssembly wide-arithmetic proposal, with its opcodes and meaning.

BytesInstructionStackMeaning
fc 13i64.add128i64 i64 i64 i64 → i64 i64Left low, left high, right low, right high: the low and high halves of the sum modulo 2^128.
fc 14i64.sub128i64 i64 i64 i64 → i64 i64The same operands: the halves of left minus right modulo 2^128.
fc 15i64.mul_wide_si64 i64 → i64 i64The low and high halves of the full 128-bit product of two signed values.
fc 16i64.mul_wide_ui64 i64 → i64 i64The same for two unsigned values.

None of them traps. Each pushes two values, so it counts twice toward a function's maximum operand height.

Traps#

A trap is a deterministic guest outcome: it ends the invocation with status 2 and no result, after the instruction's own dispatch charge and any byte charge it made. The causes are unreachable, a zero divisor, the signed-division overflow, an out-of-bounds memory access, a bulk operation out of bounds, and a bad indirect call. Host rules add their own causes (host interface). All traps are the same status; nothing distinguishes them in a receipt.

Everything else#

No other opcode byte and no other fc sub-opcode is accepted. That excludes floating point, SIMD, typed select, reference types, table instructions, memory.init and data.drop, saturating truncation, exceptions, threads and every other proposal.