Function bodies, offsets and initialisers are expressions: instructions ending with
0B (end). Each instruction is an opcode byte, or a prefix
byte (FB, FC, FD) followed by a u32 sub-opcode
in LEB128, then its immediates. This page lists every opcode of
WebAssembly
3.0. Value encodings (u32, s33 and so on) are on the
module page and type codes on
types.
Memory arguments
Loads and stores take a memarg: a u32 alignment field, then a u64
offset. The alignment is a power of two, log₂ of the bytes. If bit 6
of the alignment field is set (3.0, multiple memories), a memory index follows it and
the alignment is the field minus 64; otherwise the memory is 0. Example:
28 02 08 is i32.load offset=8 align=4.
Control, reference, parametric and variable
| Byte | Instruction | Immediates | Since |
|---|---|---|---|
00 | unreachable | — | 1.0 |
01 | nop | — | 1.0 |
02 | block | blocktype, instructions, 0B | 1.0 |
03 | loop | blocktype, instructions, 0B | 1.0 |
04 | if | blocktype, instructions, optional 05 and instructions, 0B | 1.0 |
05 | else | — | 1.0 |
08 | throw | tagidx | 3.0 |
0A | throw_ref | — | 3.0 |
0B | end | — | 1.0 |
0C | br | labelidx | 1.0 |
0D | br_if | labelidx | 1.0 |
0E | br_table | vec(labelidx), default labelidx | 1.0 |
0F | return | — | 1.0 |
10 | call | funcidx | 1.0 |
11 | call_indirect | typeidx, tableidx | 1.0 |
12 | return_call | funcidx | 3.0 |
13 | return_call_indirect | typeidx, tableidx | 3.0 |
14 | call_ref | typeidx | 3.0 |
15 | return_call_ref | typeidx | 3.0 |
1A | drop | — | 1.0 |
1B | select | — | 1.0 |
1C | select t* | vec(valtype) | 2.0 |
1F | try_table | blocktype, vec(catch), instructions, 0B | 3.0 |
20 | local.get | localidx | 1.0 |
21 | local.set | localidx | 1.0 |
22 | local.tee | localidx | 1.0 |
23 | global.get | globalidx | 1.0 |
24 | global.set | globalidx | 1.0 |
25 | table.get | tableidx | 2.0 |
26 | table.set | tableidx | 2.0 |
D0 | ref.null | heaptype | 2.0 |
D1 | ref.is_null | — | 2.0 |
D2 | ref.func | funcidx | 2.0 |
D3 | ref.eq | — | 3.0 |
D4 | ref.as_non_null | — | 3.0 |
D5 | br_on_null | labelidx | 3.0 |
D6 | br_on_non_null | labelidx | 3.0 |
Bytes 06, 07, 09, 16–19,
1D, 1E, 27, C5–CF,
D7–FA and FE are not used by release 3.0, and
FF is reserved.
try_table catch clauses
| Byte | Clause | Immediates |
|---|---|---|
00 | catch | tagidx, labelidx |
01 | catch_ref | tagidx, labelidx |
02 | catch_all | labelidx |
03 | catch_all_ref | labelidx |
Memory
| Byte | Instruction | Byte | Instruction |
|---|---|---|---|
28 | i32.load | 34 | i64.load32_s |
29 | i64.load | 35 | i64.load32_u |
2A | f32.load | 36 | i32.store |
2B | f64.load | 37 | i64.store |
2C | i32.load8_s | 38 | f32.store |
2D | i32.load8_u | 39 | f64.store |
2E | i32.load16_s | 3A | i32.store8 |
2F | i32.load16_u | 3B | i32.store16 |
30 | i64.load8_s | 3C | i64.store8 |
31 | i64.load8_u | 3D | i64.store16 |
32 | i64.load16_s | 3E | i64.store32 |
33 | i64.load16_u |
All of these take a memarg. 3F memory.size and
40 memory.grow take a memory index.
Numeric
41 i32.const (an s32), 42
i64.const (an s64), 43 f32.const (4 bytes) and
44 f64.const (8 bytes). All other numeric instructions have no
immediates.
| Byte | Instruction | Byte | Instruction | Byte | Instruction |
|---|---|---|---|---|---|
45 | i32.eqz | 72 | i32.or | 9F | f64.sqrt |
46 | i32.eq | 73 | i32.xor | A0 | f64.add |
47 | i32.ne | 74 | i32.shl | A1 | f64.sub |
48 | i32.lt_s | 75 | i32.shr_s | A2 | f64.mul |
49 | i32.lt_u | 76 | i32.shr_u | A3 | f64.div |
4A | i32.gt_s | 77 | i32.rotl | A4 | f64.min |
4B | i32.gt_u | 78 | i32.rotr | A5 | f64.max |
4C | i32.le_s | 79 | i64.clz | A6 | f64.copysign |
4D | i32.le_u | 7A | i64.ctz | A7 | i32.wrap_i64 |
4E | i32.ge_s | 7B | i64.popcnt | A8 | i32.trunc_f32_s |
4F | i32.ge_u | 7C | i64.add | A9 | i32.trunc_f32_u |
50 | i64.eqz | 7D | i64.sub | AA | i32.trunc_f64_s |
51 | i64.eq | 7E | i64.mul | AB | i32.trunc_f64_u |
52 | i64.ne | 7F | i64.div_s | AC | i64.extend_i32_s |
53 | i64.lt_s | 80 | i64.div_u | AD | i64.extend_i32_u |
54 | i64.lt_u | 81 | i64.rem_s | AE | i64.trunc_f32_s |
55 | i64.gt_s | 82 | i64.rem_u | AF | i64.trunc_f32_u |
56 | i64.gt_u | 83 | i64.and | B0 | i64.trunc_f64_s |
57 | i64.le_s | 84 | i64.or | B1 | i64.trunc_f64_u |
58 | i64.le_u | 85 | i64.xor | B2 | f32.convert_i32_s |
59 | i64.ge_s | 86 | i64.shl | B3 | f32.convert_i32_u |
5A | i64.ge_u | 87 | i64.shr_s | B4 | f32.convert_i64_s |
5B | f32.eq | 88 | i64.shr_u | B5 | f32.convert_i64_u |
5C | f32.ne | 89 | i64.rotl | B6 | f32.demote_f64 |
5D | f32.lt | 8A | i64.rotr | B7 | f64.convert_i32_s |
5E | f32.gt | 8B | f32.abs | B8 | f64.convert_i32_u |
5F | f32.le | 8C | f32.neg | B9 | f64.convert_i64_s |
60 | f32.ge | 8D | f32.ceil | BA | f64.convert_i64_u |
61 | f64.eq | 8E | f32.floor | BB | f64.promote_f32 |
62 | f64.ne | 8F | f32.trunc | BC | i32.reinterpret_f32 |
63 | f64.lt | 90 | f32.nearest | BD | i64.reinterpret_f64 |
64 | f64.gt | 91 | f32.sqrt | BE | f32.reinterpret_i32 |
65 | f64.le | 92 | f32.add | BF | f64.reinterpret_i64 |
66 | f64.ge | 93 | f32.sub | C0 | i32.extend8_s (2.0) |
67 | i32.clz | 94 | f32.mul | C1 | i32.extend16_s (2.0) |
68 | i32.ctz | 95 | f32.div | C2 | i64.extend8_s (2.0) |
69 | i32.popcnt | 96 | f32.min | C3 | i64.extend16_s (2.0) |
6A | i32.add | 97 | f32.max | C4 | i64.extend32_s (2.0) |
6B | i32.sub | 98 | f32.copysign | ||
6C | i32.mul | 99 | f64.abs | ||
6D | i32.div_s | 9A | f64.neg | ||
6E | i32.div_u | 9B | f64.ceil | ||
6F | i32.rem_s | 9C | f64.floor | ||
70 | i32.rem_u | 9D | f64.trunc | ||
71 | i32.and | 9E | f64.nearest |
Prefix FB: aggregate and reference types (3.0)
| Sub | Instruction | Immediates |
|---|---|---|
| 0 | struct.new | typeidx |
| 1 | struct.new_default | typeidx |
| 2 | struct.get | typeidx, fieldidx |
| 3 | struct.get_s | typeidx, fieldidx |
| 4 | struct.get_u | typeidx, fieldidx |
| 5 | struct.set | typeidx, fieldidx |
| 6 | array.new | typeidx |
| 7 | array.new_default | typeidx |
| 8 | array.new_fixed | typeidx, u32 count |
| 9 | array.new_data | typeidx, dataidx |
| 10 | array.new_elem | typeidx, elemidx |
| 11 | array.get | typeidx |
| 12 | array.get_s | typeidx |
| 13 | array.get_u | typeidx |
| 14 | array.set | typeidx |
| 15 | array.len | — |
| 16 | array.fill | typeidx |
| 17 | array.copy | typeidx (destination), typeidx (source) |
| 18 | array.init_data | typeidx, dataidx |
| 19 | array.init_elem | typeidx, elemidx |
| 20 | ref.test (non-null) | heaptype |
| 21 | ref.test (nullable) | heaptype |
| 22 | ref.cast (non-null) | heaptype |
| 23 | ref.cast (nullable) | heaptype |
| 24 | br_on_cast | castflags, labelidx, heaptype, heaptype |
| 25 | br_on_cast_fail | castflags, labelidx, heaptype, heaptype |
| 26 | any.convert_extern | — |
| 27 | extern.convert_any | — |
| 28 | ref.i31 | — |
| 29 | i31.get_s | — |
| 30 | i31.get_u | — |
castflags: bit 0 set means the source type is nullable, bit 1 the target type
(00 to 03).
Prefix FC
| Sub | Instruction | Immediates | Since |
|---|---|---|---|
| 0 | i32.trunc_sat_f32_s | — | 2.0 |
| 1 | i32.trunc_sat_f32_u | — | 2.0 |
| 2 | i32.trunc_sat_f64_s | — | 2.0 |
| 3 | i32.trunc_sat_f64_u | — | 2.0 |
| 4 | i64.trunc_sat_f32_s | — | 2.0 |
| 5 | i64.trunc_sat_f32_u | — | 2.0 |
| 6 | i64.trunc_sat_f64_s | — | 2.0 |
| 7 | i64.trunc_sat_f64_u | — | 2.0 |
| 8 | memory.init | dataidx, memidx | 2.0 |
| 9 | data.drop | dataidx | 2.0 |
| 10 | memory.copy | memidx (destination), memidx (source) | 2.0 |
| 11 | memory.fill | memidx | 2.0 |
| 12 | table.init | elemidx, tableidx | 2.0 |
| 13 | elem.drop | elemidx | 2.0 |
| 14 | table.copy | tableidx (destination), tableidx (source) | 2.0 |
| 15 | table.grow | tableidx | 2.0 |
| 16 | table.size | tableidx | 2.0 |
| 17 | table.fill | tableidx | 2.0 |
Prefix FD: vector (2.0)
Loads and stores take a memarg; lane instructions take a lane index byte;
v128.const takes 16 bytes (little-endian) and i8x16.shuffle
16 lane index bytes. Sub-opcodes 256 and up (relaxed SIMD) are 3.0.
| Sub | Instruction | Sub | Instruction | Sub | Instruction |
|---|---|---|---|---|---|
| 0 | v128.load | 92 | v128.load32_zero | 184 | i32x4.max_s |
| 1 | v128.load8x8_s | 93 | v128.load64_zero | 185 | i32x4.max_u |
| 2 | v128.load8x8_u | 94 | f32x4.demote_f64x2_zero | 186 | i32x4.dot_i16x8_s |
| 3 | v128.load16x4_s | 95 | f64x2.promote_low_f32x4 | 188 | i32x4.extmul_low_i16x8_s |
| 4 | v128.load16x4_u | 96 | i8x16.abs | 189 | i32x4.extmul_high_i16x8_s |
| 5 | v128.load32x2_s | 97 | i8x16.neg | 190 | i32x4.extmul_low_i16x8_u |
| 6 | v128.load32x2_u | 98 | i8x16.popcnt | 191 | i32x4.extmul_high_i16x8_u |
| 7 | v128.load8_splat | 99 | i8x16.all_true | 192 | i64x2.abs |
| 8 | v128.load16_splat | 100 | i8x16.bitmask | 193 | i64x2.neg |
| 9 | v128.load32_splat | 101 | i8x16.narrow_i16x8_s | 195 | i64x2.all_true |
| 10 | v128.load64_splat | 102 | i8x16.narrow_i16x8_u | 196 | i64x2.bitmask |
| 11 | v128.store | 103 | f32x4.ceil | 199 | i64x2.extend_low_i32x4_s |
| 12 | v128.const | 104 | f32x4.floor | 200 | i64x2.extend_high_i32x4_s |
| 13 | i8x16.shuffle | 105 | f32x4.trunc | 201 | i64x2.extend_low_i32x4_u |
| 14 | i8x16.swizzle | 106 | f32x4.nearest | 202 | i64x2.extend_high_i32x4_u |
| 15 | i8x16.splat | 107 | i8x16.shl | 203 | i64x2.shl |
| 16 | i16x8.splat | 108 | i8x16.shr_s | 204 | i64x2.shr_s |
| 17 | i32x4.splat | 109 | i8x16.shr_u | 205 | i64x2.shr_u |
| 18 | i64x2.splat | 110 | i8x16.add | 206 | i64x2.add |
| 19 | f32x4.splat | 111 | i8x16.add_sat_s | 209 | i64x2.sub |
| 20 | f64x2.splat | 112 | i8x16.add_sat_u | 213 | i64x2.mul |
| 21 | i8x16.extract_lane_s | 113 | i8x16.sub | 214 | i64x2.eq |
| 22 | i8x16.extract_lane_u | 114 | i8x16.sub_sat_s | 215 | i64x2.ne |
| 23 | i8x16.replace_lane | 115 | i8x16.sub_sat_u | 216 | i64x2.lt_s |
| 24 | i16x8.extract_lane_s | 116 | f64x2.ceil | 217 | i64x2.gt_s |
| 25 | i16x8.extract_lane_u | 117 | f64x2.floor | 218 | i64x2.le_s |
| 26 | i16x8.replace_lane | 118 | i8x16.min_s | 219 | i64x2.ge_s |
| 27 | i32x4.extract_lane | 119 | i8x16.min_u | 220 | i64x2.extmul_low_i32x4_s |
| 28 | i32x4.replace_lane | 120 | i8x16.max_s | 221 | i64x2.extmul_high_i32x4_s |
| 29 | i64x2.extract_lane | 121 | i8x16.max_u | 222 | i64x2.extmul_low_i32x4_u |
| 30 | i64x2.replace_lane | 122 | f64x2.trunc | 223 | i64x2.extmul_high_i32x4_u |
| 31 | f32x4.extract_lane | 123 | i8x16.avgr_u | 224 | f32x4.abs |
| 32 | f32x4.replace_lane | 124 | i16x8.extadd_pairwise_i8x16_s | 225 | f32x4.neg |
| 33 | f64x2.extract_lane | 125 | i16x8.extadd_pairwise_i8x16_u | 227 | f32x4.sqrt |
| 34 | f64x2.replace_lane | 126 | i32x4.extadd_pairwise_i16x8_s | 228 | f32x4.add |
| 35 | i8x16.eq | 127 | i32x4.extadd_pairwise_i16x8_u | 229 | f32x4.sub |
| 36 | i8x16.ne | 128 | i16x8.abs | 230 | f32x4.mul |
| 37 | i8x16.lt_s | 129 | i16x8.neg | 231 | f32x4.div |
| 38 | i8x16.lt_u | 130 | i16x8.q15mulr_sat_s | 232 | f32x4.min |
| 39 | i8x16.gt_s | 131 | i16x8.all_true | 233 | f32x4.max |
| 40 | i8x16.gt_u | 132 | i16x8.bitmask | 234 | f32x4.pmin |
| 41 | i8x16.le_s | 133 | i16x8.narrow_i32x4_s | 235 | f32x4.pmax |
| 42 | i8x16.le_u | 134 | i16x8.narrow_i32x4_u | 236 | f64x2.abs |
| 43 | i8x16.ge_s | 135 | i16x8.extend_low_i8x16_s | 237 | f64x2.neg |
| 44 | i8x16.ge_u | 136 | i16x8.extend_high_i8x16_s | 239 | f64x2.sqrt |
| 45 | i16x8.eq | 137 | i16x8.extend_low_i8x16_u | 240 | f64x2.add |
| 46 | i16x8.ne | 138 | i16x8.extend_high_i8x16_u | 241 | f64x2.sub |
| 47 | i16x8.lt_s | 139 | i16x8.shl | 242 | f64x2.mul |
| 48 | i16x8.lt_u | 140 | i16x8.shr_s | 243 | f64x2.div |
| 49 | i16x8.gt_s | 141 | i16x8.shr_u | 244 | f64x2.min |
| 50 | i16x8.gt_u | 142 | i16x8.add | 245 | f64x2.max |
| 51 | i16x8.le_s | 143 | i16x8.add_sat_s | 246 | f64x2.pmin |
| 52 | i16x8.le_u | 144 | i16x8.add_sat_u | 247 | f64x2.pmax |
| 53 | i16x8.ge_s | 145 | i16x8.sub | 248 | i32x4.trunc_sat_f32x4_s |
| 54 | i16x8.ge_u | 146 | i16x8.sub_sat_s | 249 | i32x4.trunc_sat_f32x4_u |
| 55 | i32x4.eq | 147 | i16x8.sub_sat_u | 250 | f32x4.convert_i32x4_s |
| 56 | i32x4.ne | 148 | f64x2.nearest | 251 | f32x4.convert_i32x4_u |
| 57 | i32x4.lt_s | 149 | i16x8.mul | 252 | i32x4.trunc_sat_f64x2_s_zero |
| 58 | i32x4.lt_u | 150 | i16x8.min_s | 253 | i32x4.trunc_sat_f64x2_u_zero |
| 59 | i32x4.gt_s | 151 | i16x8.min_u | 254 | f64x2.convert_low_i32x4_s |
| 60 | i32x4.gt_u | 152 | i16x8.max_s | 255 | f64x2.convert_low_i32x4_u |
| 61 | i32x4.le_s | 153 | i16x8.max_u | 256 | i8x16.relaxed_swizzle |
| 62 | i32x4.le_u | 155 | i16x8.avgr_u | 257 | i32x4.relaxed_trunc_f32x4_s |
| 63 | i32x4.ge_s | 156 | i16x8.extmul_low_i8x16_s | 258 | i32x4.relaxed_trunc_f32x4_u |
| 64 | i32x4.ge_u | 157 | i16x8.extmul_high_i8x16_s | 259 | i32x4.relaxed_trunc_f64x2_s_zero |
| 65 | f32x4.eq | 158 | i16x8.extmul_low_i8x16_u | 260 | i32x4.relaxed_trunc_f64x2_u_zero |
| 66 | f32x4.ne | 159 | i16x8.extmul_high_i8x16_u | 261 | f32x4.relaxed_madd |
| 67 | f32x4.lt | 160 | i32x4.abs | 262 | f32x4.relaxed_nmadd |
| 68 | f32x4.gt | 161 | i32x4.neg | 263 | f64x2.relaxed_madd |
| 69 | f32x4.le | 163 | i32x4.all_true | 264 | f64x2.relaxed_nmadd |
| 70 | f32x4.ge | 164 | i32x4.bitmask | 265 | i8x16.relaxed_laneselect |
| 71 | f64x2.eq | 167 | i32x4.extend_low_i16x8_s | 266 | i16x8.relaxed_laneselect |
| 72 | f64x2.ne | 168 | i32x4.extend_high_i16x8_s | 267 | i32x4.relaxed_laneselect |
| 73 | f64x2.lt | 169 | i32x4.extend_low_i16x8_u | 268 | i64x2.relaxed_laneselect |
| 74 | f64x2.gt | 170 | i32x4.extend_high_i16x8_u | 269 | f32x4.relaxed_min |
| 75 | f64x2.le | 171 | i32x4.shl | 270 | f32x4.relaxed_max |
| 76 | f64x2.ge | 172 | i32x4.shr_s | 271 | f64x2.relaxed_min |
| 77 | v128.not | 173 | i32x4.shr_u | 272 | f64x2.relaxed_max |
| 78 | v128.and | 174 | i32x4.add | 273 | i16x8.relaxed_q15mulr_s |
| 79 | v128.andnot | 177 | i32x4.sub | 274 | i16x8.relaxed_dot_i8x16_i7x16_s |
| 80 | v128.or | 181 | i32x4.mul | 275 | i32x4.relaxed_dot_i8x16_i7x16_add_s |
| 81 | v128.xor | 182 | i32x4.min_s | ||
| 82 | v128.bitselect | 183 | i32x4.min_u | ||
| 83 | v128.any_true | ||||
| 84 | v128.load8_lane | ||||
| 85 | v128.load16_lane | ||||
| 86 | v128.load32_lane | ||||
| 87 | v128.load64_lane | ||||
| 88 | v128.store8_lane | ||||
| 89 | v128.store16_lane | ||||
| 90 | v128.store32_lane | ||||
| 91 | v128.store64_lane |
Unused vector sub-opcodes: 154, 162, 165, 166, 175, 176, 178–180, 187, 194, 197, 198, 207, 208, 210–212, 226 and 238.
Example
20 00 local.get 0
20 01 local.get 1
6A i32.add
0B end
FC 0A 00 00 memory.copy 0 0
FD 0C 16 bytes v128.const
FB 01 05 struct.new_default type 5
Sources
The WebAssembly
core specification, release 3.0, binary format chapter “Instructions”: control,
reference, parametric, variable, table, memory (with memarg), numeric,
aggregate (FB), FC and vector (FD) instructions
and expressions; appendix “Change History” for the release that added each
instruction. Unused opcode numbers are those missing from the chapter’s tables.