WebAssembly Opcodes

  _0 _1 _2 _3 _4 _5 _6 _7 _8 _9 _A _B _C _D _E _F
0_ unreachable nop block loop if else *try *catch *throw *rethrow *br_on_exn end br br_if br_table return
1_ call call_indirect *return_call *return_call_indirect             drop select *select t      
2_ local.get local.set local.tee global.get global.set *table.get *table.set   i32.load i64.load f32.load f64.load i32.load8_s i32.load8_u i32.load16_s i32.load16_u
3_ i64.load8_s i64.load8_u i64.load16_s i64.load16_u i64.load32_s i64.load32_u i32.store i64.store f32.store f64.store i32.store8 i32.store16 i64.store8 i64.store16 i64.store32 memory.size
4_ memory.grow i32.const i64.const f32.const f64.const i32.eqz i32.eq i32.ne i32.lt_s i32.lt_u i32.gt_s i32.gt_u i32.le_s i32.le_u i32.ge_s i32.ge_u
5_ i64.eqz i64.eq i64.ne i64.lt_s i64.lt_u i64.gt_s i64.gt_u i64.le_s i64.le_u i64.ge_s i64.ge_u f32.eq f32.ne f32.lt f32.gt f32.le
6_ f32.ge f64.eq f64.ne f64.lt f64.gt f64.le f64.ge i32.clz i32.ctz i32.popcnt i32.add i32.sub i32.mul i32.div_s i32.div_u i32.rem_s
7_ i32.rem_u i32.and i32.or i32.xor i32.shl i32.shr_s i32.shr_u i32.rotl i32.rotr i64.clz i64.ctz i64.popcnt i64.add i64.sub i64.mul i64.div_s
8_ i64.div_u i64.rem_s i64.rem_u i64.and i64.or i64.xor i64.shl i64.shr_s i64.shr_u i64.rotl i64.rotr f32.abs f32.neg f32.ceil f32.floor f32.trunc
9_ f32.nearest f32.sqrt f32.add f32.sub f32.mul f32.div f32.min f32.max f32.copysign f64.abs f64.neg f64.ceil f64.floor f64.trunc f64.nearest f64.sqrt
A_ f64.add f64.sub f64.mul f64.div f64.min f64.max f64.copysign i32.wrap_i64 i32.trunc_f32_s i32.trunc_f32_u i32.trunc_f64_s i32.trunc_f64_u i64.extend_i32_s i64.extend_i32_u i64.trunc_f32_s i64.trunc_f32_u
B_ i64.trunc_f64_s i64.trunc_f64_u f32.convert_i32_s f32.convert_i32_u f32.convert_i64_s f32.convert_i64_u f32.demote_f64 f64.convert_i32_s f64.convert_i32_u f64.convert_i64_s f64.convert_i64_u f64.promote_f32 i32.reinterpret_f32 i64.reinterpret_f64 f32.reinterpret_i32 f64.reinterpret_i64
C_ *i32.extend8_s *i32.extend16_s *i64.extend8_s *i64.extend16_s *i64.extend32_s                      
D_ *ref.null *ref.is_null *ref.func                          
E_                                
F_                         *** *SIMD    


** 0xFC proposals

  _0 _1 _2 _3 _4 _5 _6 _7 _8 _9 _A _B _C _D _E _F
FC 0_ i32.trunc_sat_f32_s i32.trunc_sat_f32_u i32.trunc_sat_f64_s i32.trunc_sat_f64_u i64.trunc_sat_f32_s i64.trunc_sat_f32_u i64.trunc_sat_f64_s i64.trunc_sat_f64_u memory.init data.drop memory.copy memory.fill table.init elem.drop table.copy table.grow
FC 1_ table.size table.fill                            

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 caught.

Followed by:

Note: Any instructions following must be valid.

Stack:

[t1] → [t2]

stack-polymorphic: performs an unconditional control transfer.

The nop instruction does nothing.

Stack:

[] → []

[t?]

the beginning of a block construct, a sequence of instructions with a label at the end.

Followed by:

  1. i8 rt : blocktype — 0x40 = [], 0x7F = [i32], 0x7E = [i64], 0x7D = [f32], 0x7C = [f64]
  2. instructions
  3. 0x0B — end

Stack:

[] → [t]

The result type of the instructions must match the blocktype.

The block, loop and if instructions are structured instructions. They bracket nested sequences of instructions, called blocks, terminated with, or separated by, end or else pseudo-instructions. They must be well-nested.

[t?]

a block with a label at the beginning which may be used to form loops

Followed by:

  1. i8 rt : blocktype — 0x40 = [], 0x7F = [i32], 0x7E = [i64], 0x7D = [f32], 0x7C = [f64]
  2. instructions
  3. 0x0B — end

Stack:

[] → [t]

[t?]

the beginning of an if construct with an implicit then block

Followed by:

  1. i8 rt : blocktype — 0x40 = [], 0x7F = [i32], 0x7E = [i64], 0x7D = [f32], 0x7C = [f64]
  2. instructions1
  3. 0x0B — end
or
  1. i8 rt : blocktype
  2. instructions1
  3. 0x05 — else
  4. instructions2
  5. 0x0B — end

Stack:

[i32] → [t]
i32 c → [t]
if c is non-zero, enter block instructions1, else enter block instructions2

Marks the else block of an if.

Marks the end of a block, loop, if, or function.

l

Branch to a given label in an enclosing construct.

Performs an unconditional branch.

Followed by:

u32 l : labelidx

Label 0 refers to the innermost structured control instruction enclosing the referring branch instruction, while increasing indices refer to those farther out.

Stack:

[t1 t?] → [t2]

A branch targeting a block or if behaves like a break statement in most C-like languages, while a branch targeting a loop behaves like a continue statement.

stack-polymorphic: performs an unconditional control transfer.

l

Performs a conditional branch, branching if i32 c is non-zero.

Conditionally branch to a given label in an enclosing construct.

Followed by:

u32 l : labelidx

Stack:

[t? i32] → [t?]

l* l

A jump table which jumps to a label in an enclosing construct.

Performs an indirect branch through an operand indexing into the label vector that is an immediate to the instruction, or to a default target if the operand is out of bounds.

Followed by:

  1. u32 l* : vec( labelidx )
  2. u32 l : labelidx

Stack:

[t1 t? i32] → [t2]

stack-polymorphic: performs an unconditional control transfer.

return zero or more values from this function.

The return instruction is a shortcut for an unconditional branch to the outermost block, which implicitly is the body of the current function.

Stack:

[t1 t?] → [t2]

stack-polymorphic: performs an unconditional control transfer.

x

The call instruction invokes another function, consuming the necessary arguments from the stack and returning the result values of the call.

Followed by:

u32 x : funcidx

Stack:

[t1] → [t2]

x

The call_indirect instruction calls a function indirectly through an operand indexing into a table.

Followed by:

  1. u32 x : typeidx
  2. 0x00 — zero byte

Stack:

[t? i32] → [t?]

In future versions of WebAssembly, the zero byte may be used to index additional tables.

The drop instruction simply throws away a single operand.

Stack:

[t] → [] (value-polymorphic)

The select instruction selects one of its first two operands based on whether its third operand is zero or not.

Stack:

[t t i32] → [t] (value-polymorphic)

x

This instruction gets the value of a variable.

Followed by:

u32 x : localidx

Stack:

[] → [t]

The index space for locals is only accessible inside a function and includes the parameters of that function, which precede the local variables.

The locals context refers to the list of locals declared in the current function (including parameters), represented by their value type.

x

This instruction sets the value of a variable.

Followed by:

u32 x : localidx

Stack:

[t] → []

The index space for locals is only accessible inside a function and includes the parameters of that function, which precede the local variables.

x

The local.tee instruction is like local.set but also returns its argument.

Followed by:

u32 x : localidx

Stack:

[t] → [t]

The index space for locals is only accessible inside a function and includes the parameters of that function, which precede the local variables.

x

This instruction gets the value of a variable.

Followed by:

u32 x : globalidx

Stack:

[] → [t]

The globals context is the list of globals declared in the current module, represented by their global type.

x

This instruction sets the value of a variable

Followed by:

u32 x : globalidx

Stack:

[t] → []

m

load 4 bytes as i32.

Followed by:

m : memarg { u32 offset, u32 align }

Stack:

[i32] → [i32]
i : address-operand → c : result

Memory is accessed with load and store instructions for the different value types. They all take a memory immediate memarg that contains an address offset and the expected alignment.

The immediate value memarg.align is an alignment hint about the effective-address. It is a power-of 2 encoded as log2(memarg.align). In practice, its value may be: 0 (8-bit), 1 (16-bit), 2 (32-bit), or (64-bit; used only with wasm64).

effective-address = address-operand + memarg.offset

If memarg.align is incorrect it is considered "misaligned". Misaligned access still has the same behavior as aligned access, only possibly much slower.

m

load 8 bytes as i64.

Followed by:

m : memarg { u32 offset, u32 align }

Stack:

[i32] → [i64]

The static address offset is added to the dynamic address operand, yielding a 33 bit effective address that is the zero-based index at which the memory is accessed. All values are read and written in little endian byte order. A trap results if any of the accessed memory bytes lies outside the address range implied by the memory’s current size.

m

load 4 bytes as f32.

Stack:

[i32] → [f32]

Note: When a number is stored into memory, it is converted into a sequence of bytes in little endian byte order.

m

load 8 bytes as f64.

Stack:

[i32] → [f64]

m

load 1 byte and sign-extend i8 to i32.

Stack:

[i32] → [i32]

Integer loads and stores can optionally specify a storage size that is smaller than the bit width of the respective value type. In the case of loads, a sign extension mode sx (s|u) is then required to select appropriate behavior.

m

load 1 byte and zero-extend i8 to i32

Stack:

[i32] → [i32]

m

load 2 bytes and sign-extend i16 to i32

Stack:

[i32] → [i32]

m

load 2 bytes and zero-extend i16 to i32

Stack:

[i32] → [i32]

m

load 1 byte and sign-extend i8 to i64

Stack:

[i32] → [i64]

m

load 1 byte and zero-extend i8 to i64

Stack:

[i32] → [i64]

m

load 2 bytes and sign-extend i16 to i64

Stack:

[i32] → [i64]

m

load 2 bytes and zero-extend i16 to i64

Stack:

[i32] → [i64]

m

load 4 bytes and sign-extend i16 to i64

Stack:

[i32] → [i64]

m

load 4 bytes and zero-extend i16 to i64

Stack:

[i32] → [i64]

m

store 4 bytes (no conversion)

Stack:

[i32 i32] → []

m

store 8 bytes (no conversion)

Stack:

[i32 i64] → []

m

store 4 bytes (no conversion)

Stack:

[i32 f32] → []

m

store 8 bytes (no conversion)

Stack:

[i32 f64] → []

m

wrap i32 to i8 and store 1 byte

Stack:

[i32 i32] → []

m

wrap i32 to i16 and store 2 bytes

Stack:

[i32 i32] → []

m

wrap i64 to i8 and store 1 byte

Stack:

[i32 i64] → []

m

wrap i64 to i16 and store 2 bytes

Stack:

[i32 i64] → []

m

wrap i64 to i32 and store 4 bytes

Stack:

[i32 i64] → []

The memory.size instruction returns the current size of a memory.

Operates in units of page size. Each page is 65,536 bytes (64KB).

Stack:

[] → [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).

Stack:

[i32] → [i32]

n

Push a 32-bit integer value to the stack.

Followed by:

n : i32

Stack:

[] → [i32]

n

Push a 64-bit integer value to the stack.

Followed by:

n : i64

Stack:

[] → [i64]

z

Push a 32-bit float value to the stack.

Followed by:

z : f32

Stack:

[] → [f32]

Push a 64-bit float value to the stack.

z

Followed by:

z : f64

Stack:

[] → [f64]

compare equal to zero.

Return 1 if operand is zero, 0 otherwise.

Stack:

[i32] → [i32]

compare equal to zero.

Return 1 if operand is zero, 0 otherwise.

Stack:

[i64] → [i32]

==

sign-agnostic compare equal

Stack:

[i32 i32] → [i32]

==

sign-agnostic compare equal

Stack:

[i64 i64] → [i32]

sign-agnostic compare unequal

Stack:

[i32 i32] → [i32]

sign-agnostic compare unequal

Stack:

[i64 i64] → [i32]

<

signed less than

Stack:

[i32 i32] → [i32]

<

signed less than

Stack:

[i64 i64] → [i32]

<

unsigned less than

Stack:

[i32 i32] → [i32]

<

unsigned less than

Stack:

[i64 i64] → [i32]

>

signed greater than

Stack:

[i32 i32] → [i32]

>

signed greater than

Stack:

[i64 i64] → [i32]

>

unsigned greater than

Stack:

[i32 i32] → [i32]

>

unsigned greater than

Stack:

[i64 i64] → [i32]

signed less than or equal

Stack:

[i32 i32] → [i32]

signed less than or equal

Stack:

[i64 i64] → [i32]

unsigned less than or equal

Stack:

[i32 i32] → [i32]

unsigned less than or equal

Stack:

[i64 i64] → [i32]

signed greater than or equal

Stack:

[i32 i32] → [i32]

signed greater than or equal

Stack:

[i64 i64] → [i32]

unsigned greater than or equal

Stack:

[i32 i32] → [i32]

unsigned greater than or equal

Stack:

[i64 i64] → [i32]

==

compare equal

Stack:

[f32 f32] → [i32]

==

compare equal

Stack:

[f64 f64] → [i32]

compare unordered or unequal

Stack:

[f32 f32] → [i32]

compare unordered or unequal

Stack:

[f64 f64] → [i32]

<

less than

Stack:

[f32 f32] → [i32]

<

less than

Stack:

[f64 f64] → [i32]

>

greater than

Stack:

[f32 f32] → [i32]

>

greater than

Stack:

[f64 f64] → [i32]

less than or equal

Stack:

[f32 f32] → [i32]

less than or equal

Stack:

[f64 f64] → [i32]

greater than or equal

Stack:

[f32 f32] → [i32]

greater than or equal

Stack:

[f64 f64] → [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 zero.

Stack:

[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 zero.

Stack:

[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 zero.

Stack:

[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 zero.

Stack:

[i64] → [i64]

sign-agnostic count number of one bits

Return the count of non-zero bits in i.

Stack:

[i32] → [i32]

sign-agnostic count number of one bits

Return the count of non-zero bits in i.

Stack:

[i64] → [i64]

sign-agnostic addition

Stack:

[i32 i32] → [i32]

sign-agnostic addition

Stack:

[i64 i64] → [i64]

sign-agnostic subtraction

Stack:

[i32 i32] → [i32]

sign-agnostic subtraction

Stack:

[i64 i64] → [i64]

sign-agnostic multiplication, modulo 232

Stack:

[i32 i32] → [i32]

sign-agnostic multiplication, modulo 264

Stack:

[i64 i64] → [i64]

signed division (result is truncated toward zero)

Stack:

[i32 i32] → [i32]

signed division (result is truncated toward zero)

Stack:

[i64 i64] → [i64]

unsigned division (result is floored)

Stack:

[i32 i32] → [i32]

unsigned division (result is floored)

Stack:

[i64 i64] → [i64]

signed remainder (result has the sign of the dividend)

Stack:

[i32 i32] → [i32]

signed remainder (result has the sign of the dividend)

Stack:

[i64 i64] → [i64]

unsigned remainder

Stack:

[i32 i32] → [i32]

unsigned remainder

Stack:

[i64 i64] → [i64]

sign-agnostic bitwise and.

Return the bitwise conjunction of 𝑖1 and 𝑖2.

Stack:

[i32 i32] → [i32]

sign-agnostic bitwise and.

Return the bitwise conjunction of 𝑖1 and 𝑖2.

Stack:

[i64 i64] → [i64]

sign-agnostic bitwise inclusive or.

Return the bitwise disjunction of 𝑖1 and 𝑖2.

Stack:

[i32 i32] → [i32]

sign-agnostic bitwise inclusive or.

Return the bitwise disjunction of 𝑖1 and 𝑖2.

Stack:

[i64 i64] → [i64]

sign-agnostic bitwise exclusive or.

Return the bitwise exclusive disjunction of 𝑖1 and 𝑖2.

Stack:

[i32 i32] → [i32]

sign-agnostic bitwise exclusive or.

Return the bitwise exclusive disjunction of 𝑖1 and 𝑖2.

Stack:

[i64 i64] → [i64]

sign-agnostic shift left

Return the result of shifting i1 left by k bits, modulo 232

Stack:

[i32 i32] → [i32]

sign-agnostic shift left

Return the result of shifting i1 left by k bits, modulo 264

Stack:

[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 value.

Stack:

[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 value.

Stack:

[i64 i64] → [i64]

zero-replicating (logical) shift right

Return the result of shifting i1 right by k bits, extended with 0 bits.

Stack:

[i32 i32] → [i32]

zero-replicating (logical) shift right

Return the result of shifting i1 right by k bits, extended with 0 bits.

Stack:

[i64 i64] → [i64]

sign-agnostic rotate left

Return the result of rotating i1 left by k bits.

Stack:

[i32 i32] → [i32]

sign-agnostic rotate left

Return the result of rotating i1 left by k bits.

Stack:

[i64 i64] → [i64]

sign-agnostic rotate right

Return the result of rotating i1 right by k bits.

Stack:

[i32 i32] → [i32]

sign-agnostic rotate right

Return the result of rotating i1 right by k bits.

Stack:

[i64 i64] → [i64]

absolute value

Stack:

[f32] → [f32]

absolute value

Stack:

[f64] → [f64]

negation

Stack:

[f32] → [f32]

negation

Stack:

[f64] → [f64]

ceiling operator

Stack:

[f32] → [f32]

ceiling operator

Stack:

[f64] → [f64]

floor operator

Stack:

[f32] → [f32]

floor operator

Stack:

[f64] → [f64]

round to nearest integer towards zero

Stack:

[f32] → [f32]

round to nearest integer towards zero

Stack:

[f64] → [f64]

round to nearest integer, ties to even

Stack:

[f32] → [f32]

round to nearest integer, ties to even

Stack:

[f64] → [f64]

square root

Stack:

[f32] → [f32]

square root

Stack:

[f64] → [f64]

addition

Stack:

[f32 f32] → [f32]

addition

Stack:

[f64 f64] → [f64]

subtraction

Stack:

[f32 f32] → [f32]

subtraction

Stack:

[f64 f64] → [f64]

multiplication

Stack:

[f32 f32] → [f32]

multiplication

Stack:

[f64 f64] → [f64]

division

partial function: division by 0 is undefined

Stack:

[f32 f32] → [f32]

division

partial function: division by 0 is undefined

Stack:

[f64 f64] → [f64]

minimum (binary operator); if either operand is NaN, returns NaN

Stack:

[f32 f32] → [f32]

minimum (binary operator); if either operand is NaN, returns NaN

Stack:

[f64 f64] → [f64]

maximum (binary operator); if either operand is NaN, returns NaN

Stack:

[f32 f32] → [f32]

maximum (binary operator); if either operand is NaN, returns NaN

Stack:

[f64 f64] → [f64]

If z1 and z2 have the same sign, then return z1. Else return z1 with negated sign.

Stack:

[f32 f32] → [f32]

If z1 and z2 have the same sign, then return z1. Else return z1 with negated sign.

Stack:

[f64 f64] → [f64]

wrap a 64-bit integer to a 32-bit integer.

Return i modulo 232.

Stack:

[i64] → [i32]

truncate a 32-bit float to a signed 32-bit integer

Stack:

[f32] → [i32]

truncate a 32-bit float to an unsigned 32-bit integer

Stack:

[f32] → [i32]

truncate a 64-bit float to a signed 32-bit integer

Stack:

[f64] → [i32]

truncate a 64-bit float to an unsigned 32-bit integer

Stack:

[f64] → [i32]

extend a signed 32-bit integer to a 64-bit integer.

Stack:

[i32] → [i64]

extend an unsigned 32-bit integer to a 64-bit integer.

Stack:

[i32] → [i64]

truncate a 32-bit float to a signed 64-bit integer.

Stack:

[f32] → [i64]

truncate a 32-bit float to an unsigned 64-bit integer.

Stack:

[f32] → [i64]

truncate a 64-bit float to a signed 64-bit integer.

Stack:

[f64] → [i64]

truncate a 64-bit float to an unsigned 64-bit integer.

Stack:

[f64] → [i64]

convert a signed 32-bit integer to a 32-bit float.

Stack:

[i32] → [f32]

convert an unsigned 32-bit integer to a 32-bit float.

Stack:

[i32] → [f32]

convert a signed 64-bit integer to a 32-bit float.

Stack:

[i64] → [f32]

convert an unsigned 64-bit integer to a 32-bit float.

Stack:

[i64] → [f32]

demote a 64-bit float to a 32-bit float

Stack:

[f64] → [f32]

convert a signed 32-bit integer to a 64-bit float.

Stack:

[i32] → [f64]

convert an unsigned 32-bit integer to a 64-bit float.

Stack:

[i32] → [f64]

convert a signed 64-bit integer to a 64-bit float.

Stack:

[i64] → [f64]

convert an unsigned 64-bit integer to a 64-bit float.

Stack:

[i64] → [f64]

promote a 32-bit float to a 64-bit float

Stack:

[f32] → [f64]

reinterpret the bits of a 32-bit float as a 32-bit integer

Stack:

[f32] → [i32]

reinterpret the bits of a 64-bit float as a 64-bit integer

Stack:

[f64] → [i64]

reinterpret the bits of a 32-bit integer as a 32-bit float

Stack:

[i32] → [f32]

reinterpret the bits of a 64-bit integer as a 64-bit float

Stack:

[i64] → [f64]

Stack: [i32][i32]
4.3.2.20.
  • Return the count of non-zero bits in .
 

Further reading


View on GitHub