Skip to main content

Opcode catalog

Every operation the wasm.<opcode>(...) escape hatch accepts: 199 of them, in catalog wastc-core-gc-0. Anything absent is a feature error, not a fallback to raw WAT.

Where this comes from

The opcode list is extracted from KNOWN_OPCODES in wastc-core -- the compiler decides what actually parses. Stack signatures, descriptions, and byte encodings come from vendor/wasm-ops/data/, last checked against the specification in July 2026. Immediate syntax is the WAST source form, which is not what the vendor data records (it describes binary immediates). Regenerate with mise run docs:opcodes.

Reading the tables

Stack is the WebAssembly stack effect: operands consumed on the left, results produced on the right. It is the instruction's contract, and it is why the escape hatch can type-check your call rather than pasting text.

In WAST the operands are ordinary expressions and the immediates go in <...>, so [i32 i32] → [i32] with no immediates reads as wasm.i32.add(a, b). t is a type the immediate supplies; field is a struct field or array element type.

wasm.i32.add(left, right)                      // [i32 i32] → [i32]
wasm.struct.get<Circle, radius>(circle)        // [(ref null $t)] → [field]
wasm.i32.store<Heap, offset=0, align=4>(a, v)  // [i32 i32] → []

A Const mark means the operation is valid in a global initializer. Only eight are: f32.const, f64.const, global.get, i32.const, i64.const, ref.func, ref.i31, ref.null (the last restricted to imported immutable globals).

Constants

No operands. Immediates do not accept a leading -; write the unsigned bit pattern instead (wasm.i32.const<4294967295> for -1).

OpcodeImmediatesStackDescriptionByte
i32.const<n>[] → [i32]Push a 32-bit integer value to the stack0x41
i64.const<n>[] → [i64]Push a 64-bit integer value to the stack0x42
f32.const<x.y>[] → [f32]Push a 32-bit float value to the stack0x43
f64.const<x.y>[] → [f64]Push a 64-bit float value to the stack0x44

i32 arithmetic, bitwise, and comparison

OpcodeImmediatesStackDescriptionByte
i32.addnone[i32 i32] → [i32]sign-agnostic addition0x6A
i32.subnone[i32 i32] → [i32]sign-agnostic subtraction0x6B
i32.mulnone[i32 i32] → [i32]sign-agnostic multiplication, modulo 2³²0x6C
i32.div_snone[i32 i32] → [i32]signed division (result is truncated toward zero)0x6D
i32.div_unone[i32 i32] → [i32]unsigned division (result is floored)0x6E
i32.rem_snone[i32 i32] → [i32]signed remainder (result has the sign of the dividend)0x6F
i32.rem_unone[i32 i32] → [i32]unsigned remainder0x70
i32.andnone[i32 i32] → [i32]sign-agnostic bitwise and. Return the bitwise conjunction of 𝑖1 and 𝑖20x71
i32.ornone[i32 i32] → [i32]sign-agnostic bitwise inclusive or. Return the bitwise disjunction of 𝑖1 and 𝑖20x72
i32.xornone[i32 i32] → [i32]sign-agnostic bitwise exclusive or. Return the bitwise exclusive disjunction of 𝑖1 and 𝑖20x73
i32.shlnone[i32 i32] → [i32]sign-agnostic shift left. Return the result of shifting i1 left by k bits, modulo 2³²0x74
i32.shr_snone[i32 i32] → [i32]sign-replicating (arithmetic) shift right. Return the result of shifting i1 right by k bits, extended with the most significant bit of the original value0x75
i32.shr_unone[i32 i32] → [i32]zero-replicating (logical) shift right. Return the result of shifting i1 right by k bits, extended with 0 bits0x76
i32.rotlnone[i32 i32] → [i32]sign-agnostic rotate left. Return the result of rotating i1 left by k bits0x77
i32.rotrnone[i32 i32] → [i32]sign-agnostic rotate right. Return the result of rotating i1 right by k bits0x78
i32.eqnone[i32 i32] → [i32]== sign-agnostic compare equal0x46
i32.nenone[i32 i32] → [i32] sign-agnostic compare unequal0x47
i32.lt_snone[i32 i32] → [i32]< signed less than0x48
i32.lt_unone[i32 i32] → [i32]< unsigned less than0x49
i32.gt_snone[i32 i32] → [i32]> signed greater than0x4A
i32.gt_unone[i32 i32] → [i32]> unsigned greater than0x4B
i32.le_snone[i32 i32] → [i32] signed less than or equal0x4C
i32.le_unone[i32 i32] → [i32] unsigned less than or equal0x4D
i32.ge_snone[i32 i32] → [i32] signed greater than or equal0x4E
i32.ge_unone[i32 i32] → [i32] unsigned greater than or equal0x4F
i32.clznone[i32] → [i32]sign-agnostic count leading zero bits. Return the count of leading zero bits in i. All zero bits are considered leading if the value is zero0x67
i32.ctznone[i32] → [i32]sign-agnostic count trailing zero bits. Return the count of trailing zero bits in i. All zero bits are considered trailing if the value is zero0x68
i32.popcntnone[i32] → [i32]sign-agnostic count number of one bits. Return the count of non-zero bits in i0x69
i32.eqznone[i32] → [i32]compare equal to zero. Return 1 if operand is zero, 0 otherwise0x45

i64 arithmetic, bitwise, and comparison

OpcodeImmediatesStackDescriptionByte
i64.addnone[i64 i64] → [i64]sign-agnostic addition0x7C
i64.subnone[i64 i64] → [i64]sign-agnostic subtraction0x7D
i64.mulnone[i64 i64] → [i64]sign-agnostic multiplication, modulo 2⁶⁴0x7E
i64.div_snone[i64 i64] → [i64]signed division (result is truncated toward zero)0x7F
i64.div_unone[i64 i64] → [i64]unsigned division (result is floored)0x80
i64.rem_snone[i64 i64] → [i64]signed remainder (result has the sign of the dividend)0x81
i64.rem_unone[i64 i64] → [i64]unsigned remainder0x82
i64.andnone[i64 i64] → [i64]sign-agnostic bitwise and. Return the bitwise conjunction of 𝑖1 and 𝑖20x83
i64.ornone[i64 i64] → [i64]sign-agnostic bitwise inclusive or. Return the bitwise disjunction of 𝑖1 and 𝑖20x84
i64.xornone[i64 i64] → [i64]sign-agnostic bitwise exclusive or. Return the bitwise exclusive disjunction of 𝑖1 and 𝑖20x85
i64.shlnone[i64 i64] → [i64]sign-agnostic shift left. Return the result of shifting i1 left by k bits, modulo 2⁶⁴0x86
i64.shr_snone[i64 i64] → [i64]sign-replicating (arithmetic) shift right. Return the result of shifting i1 right by k bits, extended with the most significant bit of the original value0x87
i64.shr_unone[i64 i64] → [i64]zero-replicating (logical) shift right. Return the result of shifting i1 right by k bits, extended with 0 bits0x88
i64.rotlnone[i64 i64] → [i64]sign-agnostic rotate left. Return the result of rotating i1 left by k bits0x89
i64.rotrnone[i64 i64] → [i64]sign-agnostic rotate right. Return the result of rotating i1 right by k bits0x8A
i64.eqnone[i64 i64] → [i32]== sign-agnostic compare equal0x51
i64.nenone[i64 i64] → [i32] sign-agnostic compare unequal0x52
i64.lt_snone[i64 i64] → [i32]< signed less than0x53
i64.lt_unone[i64 i64] → [i32]< unsigned less than0x54
i64.gt_snone[i64 i64] → [i32]> signed greater than0x55
i64.gt_unone[i64 i64] → [i32]> unsigned greater than0x56
i64.le_snone[i64 i64] → [i32] signed less than or equal0x57
i64.le_unone[i64 i64] → [i32] unsigned less than or equal0x58
i64.ge_snone[i64 i64] → [i32] signed greater than or equal0x59
i64.ge_unone[i64 i64] → [i32] unsigned greater than or equal0x5A
i64.clznone[i64] → [i64]sign-agnostic count leading zero bits. Return the count of leading zero bits in i. All zero bits are considered leading if the value is zero0x79
i64.ctznone[i64] → [i64]sign-agnostic count trailing zero bits. Return the count of trailing zero bits in i. All zero bits are considered trailing if the value is zero0x7A
i64.popcntnone[i64] → [i64]sign-agnostic count number of one bits. Return the count of non-zero bits in i0x7B
i64.eqznone[i64] → [i32]compare equal to zero. Return 1 if operand is zero, 0 otherwise0x50

f32 arithmetic and comparison

OpcodeImmediatesStackDescriptionByte
f32.addnone[f32 f32] → [f32]addition0x92
f32.subnone[f32 f32] → [f32]subtraction0x93
f32.mulnone[f32 f32] → [f32]multiplication0x94
f32.divnone[f32 f32] → [f32]division. partial function: division by 0 is undefined0x95
f32.minnone[f32 f32] → [f32]minimum (binary operator); if either operand is NaN, returns NaN0x96
f32.maxnone[f32 f32] → [f32]maximum (binary operator); if either operand is NaN, returns NaN0x97
f32.copysignnone[f32 f32] → [f32]If z1 and z2 have the same sign, then return z1. Else return z1 with negated sign0x98
f32.eqnone[f32 f32] → [i32]== compare equal0x5B
f32.nenone[f32 f32] → [i32] compare unordered or unequal0x5C
f32.ltnone[f32 f32] → [i32]< less than0x5D
f32.gtnone[f32 f32] → [i32]> greater than0x5E
f32.lenone[f32 f32] → [i32] less than or equal0x5F
f32.genone[f32 f32] → [i32] greater than or equal0x60
f32.negnone[f32] → [f32]negation0x8C
f32.absnone[f32] → [f32]absolute value0x8B
f32.sqrtnone[f32] → [f32]square root0x91
f32.ceilnone[f32] → [f32]ceiling operator0x8D
f32.floornone[f32] → [f32]floor operator0x8E
f32.truncnone[f32] → [f32]round to nearest integer towards zero0x8F
f32.nearestnone[f32] → [f32]round to nearest integer, ties to even0x90

f64 arithmetic and comparison

OpcodeImmediatesStackDescriptionByte
f64.addnone[f64 f64] → [f64]addition0xA0
f64.subnone[f64 f64] → [f64]subtraction0xA1
f64.mulnone[f64 f64] → [f64]multiplication0xA2
f64.divnone[f64 f64] → [f64]division. partial function: division by 0 is undefined0xA3
f64.minnone[f64 f64] → [f64]minimum (binary operator); if either operand is NaN, returns NaN0xA4
f64.maxnone[f64 f64] → [f64]maximum (binary operator); if either operand is NaN, returns NaN0xA5
f64.copysignnone[f64 f64] → [f64]If z1 and z2 have the same sign, then return z1. Else return z1 with negated sign0xA6
f64.eqnone[f64 f64] → [i32]== compare equal0x61
f64.nenone[f64 f64] → [i32] compare unordered or unequal0x62
f64.ltnone[f64 f64] → [i32]< less than0x63
f64.gtnone[f64 f64] → [i32]> greater than0x64
f64.lenone[f64 f64] → [i32] less than or equal0x65
f64.genone[f64 f64] → [i32] greater than or equal0x66
f64.negnone[f64] → [f64]negation0x9A
f64.absnone[f64] → [f64]absolute value0x99
f64.sqrtnone[f64] → [f64]square root0x9F
f64.ceilnone[f64] → [f64]ceiling operator0x9B
f64.floornone[f64] → [f64]floor operator0x9C
f64.truncnone[f64] → [f64]round to nearest integer towards zero0x9D
f64.nearestnone[f64] → [f64]round to nearest integer, ties to even0x9E

Conversions

No saturating (_sat_) truncation: a float-to-int conversion traps when the value is out of range or NaN.

OpcodeImmediatesStackDescriptionByte
i32.wrap_i64none[i64] → [i32]wrap a 64-bit integer to a 32-bit integer. Return i modulo 2³²0xA7
i64.extend_i32_snone[i32] → [i64]extend a signed 32-bit integer to a 64-bit integer0xAC
i64.extend_i32_unone[i32] → [i64]extend an unsigned 32-bit integer to a 64-bit integer0xAD
i32.extend8_snone[i32] → [i32]extend a signed 8-bit integer to a 32-bit integer. Sign-extension operators extension0xC0
i32.extend16_snone[i32] → [i32]extend a signed 16-bit integer to a 32-bit integer. Sign-extension operators extension0xC1
i64.extend8_snone[i64] → [i64]extend a signed 8-bit integer to a 64-bit integer. Sign-extension operators extension0xC2
i64.extend16_snone[i64] → [i64]extend a signed 16-bit integer to a 64-bit integer. Sign-extension operators extension0xC3
i64.extend32_snone[i64] → [i64]extend a signed 32-bit integer to a 64-bit integer. Sign-extension operators extension0xC4
f32.convert_i32_snone[i32] → [f32]convert a signed 32-bit integer to a 32-bit float0xB2
f32.convert_i32_unone[i32] → [f32]convert an unsigned 32-bit integer to a 32-bit float0xB3
f32.convert_i64_snone[i64] → [f32]convert a signed 64-bit integer to a 32-bit float0xB4
f32.convert_i64_unone[i64] → [f32]convert an unsigned 64-bit integer to a 32-bit float0xB5
f64.convert_i32_snone[i32] → [f64]convert a signed 32-bit integer to a 64-bit float0xB7
f64.convert_i32_unone[i32] → [f64]convert an unsigned 32-bit integer to a 64-bit float0xB8
f64.convert_i64_snone[i64] → [f64]convert a signed 64-bit integer to a 64-bit float0xB9
f64.convert_i64_unone[i64] → [f64]convert an unsigned 64-bit integer to a 64-bit float0xBA
i32.trunc_f32_snone[f32] → [i32]truncate a 32-bit float to a signed 32-bit integer0xA8
i32.trunc_f32_unone[f32] → [i32]truncate a 32-bit float to an unsigned 32-bit integer0xA9
i32.trunc_f64_snone[f64] → [i32]truncate a 64-bit float to a signed 32-bit integer0xAA
i32.trunc_f64_unone[f64] → [i32]truncate a 64-bit float to an unsigned 32-bit integer0xAB
i64.trunc_f32_snone[f32] → [i64]truncate a 32-bit float to a signed 64-bit integer0xAE
i64.trunc_f32_unone[f32] → [i64]truncate a 32-bit float to an unsigned 64-bit integer0xAF
i64.trunc_f64_snone[f64] → [i64]truncate a 64-bit float to a signed 64-bit integer0xB0
i64.trunc_f64_unone[f64] → [i64]truncate a 64-bit float to an unsigned 64-bit integer0xB1
f32.demote_f64none[f64] → [f32]demote a 64-bit float to a 32-bit float0xB6
f64.promote_f32none[f32] → [f64]promote a 32-bit float to a 64-bit float0xBB
i32.reinterpret_f32none[f32] → [i32]reinterpret the bits of a 32-bit float as a 32-bit integer0xBC
f32.reinterpret_i32none[i32] → [f32]reinterpret the bits of a 32-bit integer as a 32-bit float0xBE
i64.reinterpret_f64none[f64] → [i64]reinterpret the bits of a 64-bit float as a 64-bit integer0xBD
f64.reinterpret_i64none[i64] → [f64]reinterpret the bits of a 64-bit integer as a 64-bit float0xBF

Linear memory

Every access names its memory -- there is no default memory. align is a byte count, must be a power of two, and must not exceed the natural alignment of the access. Addresses are always i32.

OpcodeImmediatesStackDescriptionByte
i32.load<Memory[, offset=N][, align=N]>[i32] → [i32]load 4 bytes as i320x28
i64.load<Memory[, offset=N][, align=N]>[i32] → [i64]load 8 bytes as i640x29
f32.load<Memory[, offset=N][, align=N]>[i32] → [f32]load 4 bytes as f320x2A
f64.load<Memory[, offset=N][, align=N]>[i32] → [f64]load 8 bytes as f640x2B
i32.load8_s<Memory[, offset=N][, align=N]>[i32] → [i32]load 1 byte and sign-extend i8 to i320x2C
i32.load8_u<Memory[, offset=N][, align=N]>[i32] → [i32]load 1 byte and zero-extend i8 to i320x2D
i32.load16_s<Memory[, offset=N][, align=N]>[i32] → [i32]load 2 bytes and sign-extend i16 to i320x2E
i32.load16_u<Memory[, offset=N][, align=N]>[i32] → [i32]load 2 bytes and zero-extend i16 to i320x2F
i64.load8_s<Memory[, offset=N][, align=N]>[i32] → [i64]load 1 byte and sign-extend i8 to i640x30
i64.load8_u<Memory[, offset=N][, align=N]>[i32] → [i64]load 1 byte and zero-extend i8 to i640x31
i64.load16_s<Memory[, offset=N][, align=N]>[i32] → [i64]load 2 bytes and sign-extend i16 to i640x32
i64.load16_u<Memory[, offset=N][, align=N]>[i32] → [i64]load 2 bytes and zero-extend i16 to i640x33
i64.load32_s<Memory[, offset=N][, align=N]>[i32] → [i64]load 4 bytes and sign-extend i32 to i640x34
i64.load32_u<Memory[, offset=N][, align=N]>[i32] → [i64]load 4 bytes and zero-extend i32 to i640x35
i32.store<Memory[, offset=N][, align=N]>[i32 i32] → []store 4 bytes (no conversion)0x36
i64.store<Memory[, offset=N][, align=N]>[i32 i64] → []store 8 bytes (no conversion)0x37
f32.store<Memory[, offset=N][, align=N]>[i32 f32] → []store 4 bytes (no conversion)0x38
f64.store<Memory[, offset=N][, align=N]>[i32 f64] → []store 8 bytes (no conversion)0x39
i32.store8<Memory[, offset=N][, align=N]>[i32 i32] → []wrap i32 to i8 and store 1 byte0x3A
i32.store16<Memory[, offset=N][, align=N]>[i32 i32] → []wrap i32 to i16 and store 2 bytes0x3B
i64.store8<Memory[, offset=N][, align=N]>[i32 i64] → []wrap i64 to i8 and store 1 byte0x3C
i64.store16<Memory[, offset=N][, align=N]>[i32 i64] → []wrap i64 to i16 and store 2 bytes0x3D
i64.store32<Memory[, offset=N][, align=N]>[i32 i64] → []wrap i64 to i32 and store 4 bytes0x3E
memory.size<Memory>[] → [i32]The memory.size instruction returns the current size of a memory. Operates in units of page size. Each page is 65,536 bytes (64KB)0x3F
memory.grow<Memory>[i32] → [i32]The memory.grow instruction grows memory by a given delta and returns the previous size, or −1 if enough memory cannot be allocated. Operates in units of page size. Each page is 65,536 bytes (64KB)0x40

Locals and globals

local.set/local.tee require a var binding; global.set requires a mut global.

OpcodeImmediatesStackDescriptionByte
local.get<local>[] → [t]This instruction gets the value of a variable0x20
local.set<local>[t] → []This instruction sets the value of a variable0x21
local.tee<local>[t] → [t]The local.tee instruction is like local.set but also returns its argument0x22
global.get<Global>[] → [t]This instruction gets the value of a variable0x23
global.set<Global>[t] → []This instruction sets the value of a variable0x24

References and casts

ref.test/ref.cast only ever downcast: the immediate's heap type must be a subtype of the operand's. A bare heap keyword is not a type immediate -- write <&struct>, never <struct>.

OpcodeImmediatesStackDescriptionByte
ref.null<?T>[] → [(ref null t)]evaluates to the null reference constant0xD0
ref.is_nullnone[(ref null t)] → [i32]checks for null0xD1
ref.eqnone[eqref eqref] → [i32][eqref eqref] -> [i32]0xD3
ref.func<func>[] → [(ref f)]creates a reference to a given function0xD2
ref.test<&T> / <?T>[(ref null t)] → [i32]checks whether a reference has a given heap type0xFB.20
ref.cast<&T> / <?T>[(ref null t₁)] → [(ref t₂)]tries to convert to a given heap type0xFB.22

i31

Note the asymmetry: ref.i31 produces a non-null &i31, but both accessors take a nullable ?i31.

OpcodeImmediatesStackDescriptionByte
ref.i31none[i32] → [(ref i31)]creates an i31ref from a 32 bit value, truncating high bit0xFB.28
i31.get_snone[i31ref] → [i32]extracts the value, sign-extending0xFB.29
i31.get_unone[i31ref] → [i32]extracts the value, zero-extending0xFB.30

GC structs

The immediate names the field; the emitted WAT uses its flattened parent-first index. A packed (i8/i16) field requires _s/_u, and a non-packed field rejects them.

OpcodeImmediatesStackDescriptionByte
struct.new<Struct>[field*] → [(ref $t)]allocates a structure with canonical RTT (runtime type) and initialises its fields with given values0xFB.0
struct.get<Struct, field>[(ref null $t)] → [field]reads field i from a structure0xFB.2
struct.get_s<Struct, field>[(ref null $t)] → [i32]--0xFB.3
struct.get_u<Struct, field>[(ref null $t)] → [i32]--0xFB.4
struct.set<Struct, field>[(ref null $t) field] → []writes field i of a structure0xFB.5
struct.new_default<Struct>[] → [(ref $t)]allocates a structure of type $t with canonical RTT (runtime type) and initialises its fields with default values0xFB.1

GC arrays

array.copy takes the destination type first and requires both arrays to agree on packedness.

OpcodeImmediatesStackDescriptionByte
array.new_fixed<Array>[field^n] → [(ref $t)]allocates an array with canonical RTT (runtime type) of fixed size and initialises it from operands0xFB.8
array.get<Array>[(ref null $t) i32] → [field]reads an element from an array0xFB.11
array.get_s<Array>[(ref null $t) i32] → [i32]--0xFB.12
array.get_u<Array>[(ref null $t) i32] → [i32]--0xFB.13
array.set<Array>[(ref null $t) i32 field] → []writes an element to an array0xFB.14
array.lennone[arrayref] → [i32]inquires the length of an array0xFB.15
array.new<Array>[field i32] → [(ref $t)]allocates an array with canonical RTT (runtime type)0xFB.6
array.new_default<Array>[i32] → [(ref $t)]allocates an array with canonical RTT (runtime type) and initialises its fields with the default value0xFB.7
array.fill<Array>[(ref null $t) i32 field i32] → []--0xFB.16
array.copy<Dest, Src>[(ref null $t₁) i32 (ref null $t₂) i32 i32] → []--0xFB.17

Tables

table.grow takes the fill value first, then the delta.

OpcodeImmediatesStackDescriptionByte
table.get<Table>[i32] → [t]Access tables0x25
table.set<Table>[i32 t] → []Access tables0x26
table.size<Table>[] → [i32]current number of elements in the table--
table.grow<Table>[t i32] → [i32]grow the table by n elements, returning the previous size or -1--

Host reference bridge

OpcodeImmediatesStackDescriptionByte
any.convert_externnone[externref] → [anyref]converts an external value into the internal representation0xFB.26
extern.convert_anynone[anyref] → [externref]converts an internal value into the external representation0xFB.27

Calls

call_indirect takes the table index as its last argument, after the call arguments.

OpcodeImmediatesStackDescriptionByte
call<func>[t∗_1] → [t∗_2]The call instruction invokes another function, consuming the necessary arguments from the stack and returning the result values of the call0x10
call_indirect<Table, FuncType>[t? i32] → [t?]The call_indirect instruction calls a function indirectly through an operand indexing into a table0x11

Stack and control

unreachable is polymorphic and marks the path diverging. select emits an explicit result annotation only when the result is a reference.

OpcodeImmediatesStackDescriptionByte
dropnone[t] → []The drop instruction simply throws away a single operand. Arguably the only stack manipulation instruction WebAssembly has. There is no dup, swap or rot, and no way to reach past the top of the stack: select consumes three operands and computes with them, and local.tee does the work dup would by going out to a local and back. See WebAssembly is not quite a stack machine, by purplesyringa0x1A
selectnone (rejects any)[t t i32] → [t]The select instruction selects one of its first two operands based on whether its third operand is zero or not0x1B
nopnone[] → []The nop instruction does nothing0x01
unreachablenone[t∗_1] → [t∗_2]The unreachable instruction causes an unconditional trap. A trap immediately aborts execution. Traps cannot be handled by WebAssembly code, but are reported to the outside environment, where they typically can be caught0x00

Not in the catalog

These are absent on purpose. Reaching for one is a feature error:

feature error at L:C: 'memory.copy' is not available in the selected
target's instruction catalog (wastc-core-gc-0)
ExcludedWhy
br, br_if, br_table, block, loop, if, return, br_on_null, br_on_castThe escape hatch's grammar is an expression producing a value; a branch is a control-flow edge and has no such shape. The language's own structured control flow covers these, and always will.
return_call, return_call_ref, raw call_refTail calls are a compiler output mode (--tail-calls) applied to your own return, never source syntax.
memory.init, data.drop, memory.copy, memory.fillBulk memory is outside the target feature set. A passive data segment currently has no way to be used from source as a result.
table.copy, table.fill, table.init, elem.dropSame.
array.new_data, array.new_elemDepend on the segment operations above.
i32.trunc_sat_*, i64.trunc_sat_*The fc proposal is out of scope, so out-of-range float-to-int conversion traps rather than saturating.
SIMD, threads/atomics, exception handling, stringref, memory64Outside the target feature set entirely -- see limitations.

Two behaviours that will surprise you

Numeric opcodes ignore their immediates. wasm.i32.add<Nonsense>(a, b) type-checks and silently discards the immediate. It is unchecked, not rejected. select is the only opcode that errors on a stray immediate.

A typo reads as a missing feature. The unknown-opcode arm is the same one that reports out-of-scope instructions, so wasm.i32.addd(...) claims the catalog doesn't have it rather than telling you it isn't a real opcode.

See also