Appendix A: Instruction Reference

This appendix lists the instructions with their opcodes and their types. It covers every instruction in the core of WebAssembly 3.0 except the SIMD and atomic instructions, of which it shows a representative selection; the full lists are in the specification and the threads proposal.

The opcodes were not typed in by hand. scripts/opcodes.py assembles each instruction with the wat crate and reads its opcode back out of the binary, so the table agrees with the assembler. Prefixed opcodes show the prefix byte and the second opcode as it is encoded, in LEB128, so fd 85 02 is prefix fd followed by opcode 261.

Types are written as in the specification: what the instruction pops on the left, what it pushes on the right, with t standing for any value type and t* for any sequence of them. Instructions that end control flow, such as br and unreachable, have types with arbitrary t1* and t2*, since the stack after them is polymorphic (Chapter 6). The immediates column lists what follows the opcode in the binary, in order; a memarg is an alignment exponent and an offset (Chapter 13), and the memory instructions without a memarg take a memory index, which is 00 for memory 0.

#ControlA.1

Instruction Opcode Type Immediates and notes
unreachable 00 [t*] → [t*] trap
nop 01 [] → []
block bt 02 [t1*] → [t2*] block type; ends with end
loop bt 03 [t1*] → [t2*] block type
if bt 04 [t1* i32] → [t2*] block type
else 05 between the arms of an if
end 0b ends a block, loop, if, try_table or function
br l 0c [t* t1*] → [t2*] label depth
br_if l 0d [t* i32] → [t*] label depth
br_table l* l 0e [t1* t* i32] → [t2*] vector of depths, then default
return 0f [t1* t*] → [t2*]
call f 10 [t1*] → [t2*] function index
call_indirect t 11 [t1* i32] → [t2*] type index, table index
return_call f 12 [t1*] → [t2*] tail call
return_call_indirect t 13 [t1* i32] → [t2*] tail call
call_ref t 14 [t1* (ref null $t)] → [t2*] type index
return_call_ref t 15 [t1* (ref null $t)] → [t2*] type index
throw x 08 [t1* t*] → [t2*] tag index
throw_ref 0a [t1* exnref] → [t2*]
try_table bt c* 1f [t1*] → [t2*] block type, vector of catch clauses

#Parametric and variablesA.2

Instruction Opcode Type Immediates and notes
drop 1a [t] → []
select 1b [t t i32] → [t] numeric or vector operands
select t 1c [t t i32] → [t] typed form: vector of value types
local.get x 20 [] → [t] local index
local.set x 21 [t] → [] local index
local.tee x 22 [t] → [t] local index
global.get x 23 [] → [t] global index
global.set x 24 [t] → [] global index

#TablesA.3

Instruction Opcode Type Immediates and notes
table.get x 25 [i32] → [ref] table index
table.set x 26 [i32 ref] → [] table index
table.init fc 0c [i32 i32 i32] → [] element segment, table
elem.drop fc 0d [] → [] element segment
table.copy fc 0e [i32 i32 i32] → [] destination and source tables
table.grow x fc 0f [ref i32] → [i32] table index
table.size x fc 10 [] → [i32] table index
table.fill x fc 11 [i32 ref i32] → [] table index

#MemoryA.4

Instruction Opcode Type Immediates and notes
i32.load 28 [i32] → [i32] memarg
i64.load 29 [i32] → [i64] memarg
f32.load 2a [i32] → [f32] memarg
f64.load 2b [i32] → [f64] memarg
i32.load8_s 2c [i32] → [i32] memarg
i32.load8_u 2d [i32] → [i32] memarg
i32.load16_s 2e [i32] → [i32] memarg
i32.load16_u 2f [i32] → [i32] memarg
i64.load8_s 30 [i32] → [i64] memarg
i64.load8_u 31 [i32] → [i64] memarg
i64.load16_s 32 [i32] → [i64] memarg
i64.load16_u 33 [i32] → [i64] memarg
i64.load32_s 34 [i32] → [i64] memarg
i64.load32_u 35 [i32] → [i64] memarg
i32.store 36 [i32 i32] → [] memarg
i64.store 37 [i32 i64] → [] memarg
f32.store 38 [i32 f32] → [] memarg
f64.store 39 [i32 f64] → [] memarg
i32.store8 3a [i32 i32] → [] memarg
i32.store16 3b [i32 i32] → [] memarg
i64.store8 3c [i32 i64] → [] memarg
i64.store16 3d [i32 i64] → [] memarg
i64.store32 3e [i32 i64] → [] memarg
memory.size 3f [] → [i32] memory index
memory.grow 40 [i32] → [i32] memory index
memory.init fc 08 [i32 i32 i32] → [] data segment, memory
data.drop fc 09 [] → [] data segment
memory.copy fc 0a [i32 i32 i32] → [] destination and source memories
memory.fill fc 0b [i32 i32 i32] → [] memory index

#ConstantsA.5

Instruction Opcode Type Immediates and notes
i32.const 41 [] → [i32] signed LEB128
i64.const 42 [] → [i64] signed LEB128
f32.const 43 [] → [f32] 4 bytes
f64.const 44 [] → [f64] 8 bytes

#i32 operationsA.6

Instruction Opcode Type Immediates and notes
i32.eqz 45 [i32] → [i32]
i32.eq 46 [i32 i32] → [i32]
i32.ne 47 [i32 i32] → [i32]
i32.lt_s 48 [i32 i32] → [i32]
i32.lt_u 49 [i32 i32] → [i32]
i32.gt_s 4a [i32 i32] → [i32]
i32.gt_u 4b [i32 i32] → [i32]
i32.le_s 4c [i32 i32] → [i32]
i32.le_u 4d [i32 i32] → [i32]
i32.ge_s 4e [i32 i32] → [i32]
i32.ge_u 4f [i32 i32] → [i32]
i32.clz 67 [i32] → [i32]
i32.ctz 68 [i32] → [i32]
i32.popcnt 69 [i32] → [i32]
i32.add 6a [i32 i32] → [i32]
i32.sub 6b [i32 i32] → [i32]
i32.mul 6c [i32 i32] → [i32]
i32.div_s 6d [i32 i32] → [i32] traps on zero
i32.div_u 6e [i32 i32] → [i32] traps on zero
i32.rem_s 6f [i32 i32] → [i32] traps on zero
i32.rem_u 70 [i32 i32] → [i32] traps on zero
i32.and 71 [i32 i32] → [i32]
i32.or 72 [i32 i32] → [i32]
i32.xor 73 [i32 i32] → [i32]
i32.shl 74 [i32 i32] → [i32]
i32.shr_s 75 [i32 i32] → [i32]
i32.shr_u 76 [i32 i32] → [i32]
i32.rotl 77 [i32 i32] → [i32]
i32.rotr 78 [i32 i32] → [i32]

#i64 operationsA.7

Instruction Opcode Type Immediates and notes
i64.eqz 50 [i64] → [i32]
i64.eq 51 [i64 i64] → [i32]
i64.ne 52 [i64 i64] → [i32]
i64.lt_s 53 [i64 i64] → [i32]
i64.lt_u 54 [i64 i64] → [i32]
i64.gt_s 55 [i64 i64] → [i32]
i64.gt_u 56 [i64 i64] → [i32]
i64.le_s 57 [i64 i64] → [i32]
i64.le_u 58 [i64 i64] → [i32]
i64.ge_s 59 [i64 i64] → [i32]
i64.ge_u 5a [i64 i64] → [i32]
i64.clz 79 [i64] → [i64]
i64.ctz 7a [i64] → [i64]
i64.popcnt 7b [i64] → [i64]
i64.add 7c [i64 i64] → [i64]
i64.sub 7d [i64 i64] → [i64]
i64.mul 7e [i64 i64] → [i64]
i64.div_s 7f [i64 i64] → [i64] traps on zero
i64.div_u 80 [i64 i64] → [i64] traps on zero
i64.rem_s 81 [i64 i64] → [i64] traps on zero
i64.rem_u 82 [i64 i64] → [i64] traps on zero
i64.and 83 [i64 i64] → [i64]
i64.or 84 [i64 i64] → [i64]
i64.xor 85 [i64 i64] → [i64]
i64.shl 86 [i64 i64] → [i64]
i64.shr_s 87 [i64 i64] → [i64]
i64.shr_u 88 [i64 i64] → [i64]
i64.rotl 89 [i64 i64] → [i64]
i64.rotr 8a [i64 i64] → [i64]

#f32 operationsA.8

Instruction Opcode Type Immediates and notes
f32.eq 5b [f32 f32] → [i32]
f32.ne 5c [f32 f32] → [i32]
f32.lt 5d [f32 f32] → [i32]
f32.gt 5e [f32 f32] → [i32]
f32.le 5f [f32 f32] → [i32]
f32.ge 60 [f32 f32] → [i32]
f32.abs 8b [f32] → [f32]
f32.neg 8c [f32] → [f32]
f32.ceil 8d [f32] → [f32]
f32.floor 8e [f32] → [f32]
f32.trunc 8f [f32] → [f32]
f32.nearest 90 [f32] → [f32]
f32.sqrt 91 [f32] → [f32]
f32.add 92 [f32 f32] → [f32]
f32.sub 93 [f32 f32] → [f32]
f32.mul 94 [f32 f32] → [f32]
f32.div 95 [f32 f32] → [f32]
f32.min 96 [f32 f32] → [f32]
f32.max 97 [f32 f32] → [f32]
f32.copysign 98 [f32 f32] → [f32]

#f64 operationsA.9

Instruction Opcode Type Immediates and notes
f64.eq 61 [f64 f64] → [i32]
f64.ne 62 [f64 f64] → [i32]
f64.lt 63 [f64 f64] → [i32]
f64.gt 64 [f64 f64] → [i32]
f64.le 65 [f64 f64] → [i32]
f64.ge 66 [f64 f64] → [i32]
f64.abs 99 [f64] → [f64]
f64.neg 9a [f64] → [f64]
f64.ceil 9b [f64] → [f64]
f64.floor 9c [f64] → [f64]
f64.trunc 9d [f64] → [f64]
f64.nearest 9e [f64] → [f64]
f64.sqrt 9f [f64] → [f64]
f64.add a0 [f64 f64] → [f64]
f64.sub a1 [f64 f64] → [f64]
f64.mul a2 [f64 f64] → [f64]
f64.div a3 [f64 f64] → [f64]
f64.min a4 [f64 f64] → [f64]
f64.max a5 [f64 f64] → [f64]
f64.copysign a6 [f64 f64] → [f64]

#ConversionsA.10

Instruction Opcode Type Immediates and notes
i32.wrap_i64 a7 [i64] → [i32]
i32.trunc_f32_s a8 [f32] → [i32] traps if out of range or NaN
i32.trunc_f32_u a9 [f32] → [i32] traps if out of range or NaN
i32.trunc_f64_s aa [f64] → [i32] traps if out of range or NaN
i32.trunc_f64_u ab [f64] → [i32] traps if out of range or NaN
i64.extend_i32_s ac [i32] → [i64]
i64.extend_i32_u ad [i32] → [i64]
i64.trunc_f32_s ae [f32] → [i64] traps if out of range or NaN
i64.trunc_f32_u af [f32] → [i64] traps if out of range or NaN
i64.trunc_f64_s b0 [f64] → [i64] traps if out of range or NaN
i64.trunc_f64_u b1 [f64] → [i64] traps if out of range or NaN
f32.convert_i32_s b2 [i32] → [f32]
f32.convert_i32_u b3 [i32] → [f32]
f32.convert_i64_s b4 [i64] → [f32]
f32.convert_i64_u b5 [i64] → [f32]
f32.demote_f64 b6 [f64] → [f32]
f64.convert_i32_s b7 [i32] → [f64]
f64.convert_i32_u b8 [i32] → [f64]
f64.convert_i64_s b9 [i64] → [f64]
f64.convert_i64_u ba [i64] → [f64]
f64.promote_f32 bb [f32] → [f64]
i32.reinterpret_f32 bc [f32] → [i32]
i64.reinterpret_f64 bd [f64] → [i64]
f32.reinterpret_i32 be [i32] → [f32]
f64.reinterpret_i64 bf [i64] → [f64]
i32.extend8_s c0 [i32] → [i32]
i32.extend16_s c1 [i32] → [i32]
i64.extend8_s c2 [i64] → [i64]
i64.extend16_s c3 [i64] → [i64]
i64.extend32_s c4 [i64] → [i64]
i32.trunc_sat_f32_s fc 00 [f32] → [i32] saturates
i32.trunc_sat_f32_u fc 01 [f32] → [i32] saturates
i32.trunc_sat_f64_s fc 02 [f64] → [i32] saturates
i32.trunc_sat_f64_u fc 03 [f64] → [i32] saturates
i64.trunc_sat_f32_s fc 04 [f32] → [i64] saturates
i64.trunc_sat_f32_u fc 05 [f32] → [i64] saturates
i64.trunc_sat_f64_s fc 06 [f64] → [i64] saturates
i64.trunc_sat_f64_u fc 07 [f64] → [i64] saturates

#ReferencesA.11

Instruction Opcode Type Immediates and notes
ref.null ht d0 [] → [(ref null ht)] heap type
ref.is_null d1 [ref] → [i32]
ref.func f d2 [] → [(ref $t)] function index
ref.eq d3 [eqref eqref] → [i32]
ref.as_non_null d4 [(ref null ht)] → [(ref ht)] traps on null
br_on_null l d5 [t* (ref null ht)] → [t* (ref ht)] label depth
br_on_non_null l d6 [t* (ref null ht)] → [t*] label depth

#Garbage collectionA.12

Instruction Opcode Type Immediates and notes
struct.new s fb 00 [t*] → [(ref $s)] type
struct.new_default s fb 01 [] → [(ref $s)] type
struct.get s i fb 02 [(ref null $s)] → [t] type, field
struct.get_s s i fb 03 [(ref null $s)] → [i32] packed field
struct.get_u s i fb 04 [(ref null $s)] → [i32] packed field
struct.set s i fb 05 [(ref null $s) t] → [] type, field
array.new a fb 06 [t i32] → [(ref $a)] type
array.new_default a fb 07 [i32] → [(ref $a)] type
array.new_fixed a n fb 08 [t^n] → [(ref $a)] type, count
array.new_data a d fb 09 [i32 i32] → [(ref $a)] type, data segment
array.new_elem a e fb 0a [i32 i32] → [(ref $a)] type, element segment
array.get a fb 0b [(ref null $a) i32] → [t] type
array.get_s a fb 0c [(ref null $a) i32] → [i32] packed
array.get_u a fb 0d [(ref null $a) i32] → [i32] packed
array.set a fb 0e [(ref null $a) i32 t] → [] type
array.len fb 0f [(ref null array)] → [i32]
array.fill a fb 10 [(ref null $a) i32 t i32] → [] type
array.copy a b fb 11 [(ref null $a) i32 (ref null $b) i32 i32] → [] two types
array.init_data a d fb 12 [(ref null $a) i32 i32 i32] → [] type, data segment
ref.test rt fb 14 [ref] → [i32] reference type
ref.cast rt fb 16 [ref] → [rt] traps if the cast fails
br_on_cast l rt1 rt2 fb 18 [t* rt1] → [t* rt1'] flags, label, two types
br_on_cast_fail l rt1 rt2 fb 19 [t* rt1] → [t* rt2] flags, label, two types
any.convert_extern fb 1a [externref] → [anyref]
extern.convert_any fb 1b [anyref] → [externref]
ref.i31 fb 1c [i32] → [(ref i31)]
i31.get_s fb 1d [i31ref] → [i32]
i31.get_u fb 1e [i31ref] → [i32]

#SIMD (a selection)A.13

Instruction Opcode Type Immediates and notes
v128.load fd 00 [i32] → [v128] memarg
v128.store fd 0b [i32 v128] → [] memarg
v128.const fd 0c [] → [v128] 16 bytes
i8x16.shuffle fd 0d [v128 v128] → [v128] 16 lane indices
i8x16.swizzle fd 0e [v128 v128] → [v128]
i32x4.splat fd 11 [i32] → [v128]
f32x4.splat fd 13 [f32] → [v128]
i32x4.extract_lane fd 1b [v128] → [i32] lane index
f32x4.extract_lane fd 1f [v128] → [f32] lane index
i32x4.replace_lane fd 1c [v128 i32] → [v128] lane index
v128.and fd 4e [v128 v128] → [v128]
v128.bitselect fd 52 [v128 v128 v128] → [v128]
v128.any_true fd 53 [v128] → [i32]
i32x4.all_true fd a3 01 [v128] → [i32]
i32x4.add fd ae 01 [v128 v128] → [v128]
i32x4.mul fd b5 01 [v128 v128] → [v128]
f32x4.add fd e4 01 [v128 v128] → [v128]
f32x4.mul fd e6 01 [v128 v128] → [v128]
f32x4.div fd e7 01 [v128 v128] → [v128]
f32x4.sqrt fd e3 01 [v128] → [v128]
f32x4.lt fd 43 [v128 v128] → [v128] lane masks
v128.load32_splat fd 09 [i32] → [v128] memarg
f32x4.relaxed_madd fd 85 02 [v128 v128 v128] → [v128] relaxed

#Threads (a selection)A.14

Instruction Opcode Type Immediates and notes
memory.atomic.notify fe 00 [i32 i32] → [i32] memarg
memory.atomic.wait32 fe 01 [i32 i32 i64] → [i32] memarg
atomic.fence fe 03 [] → []
i32.atomic.load fe 10 [i32] → [i32] memarg
i32.atomic.store fe 17 [i32 i32] → [] memarg
i32.atomic.rmw.add fe 1e [i32 i32] → [i32] memarg
i32.atomic.rmw.cmpxchg fe 48 [i32 i32 i32] → [i32] memarg