Instructions

Instructions are encoded by opcodes. Each opcode is represented by a single byte, and is followed by the instruction’s immediate arguments, where present. The only exception are structured control instructions, which consist of several opcodes bracketing their nested instruction sequences.

Note

Gaps in the byte code ranges for encoding instructions are reserved for future extensions.

Control Instructions

Control instructions have varying encodings. For structured instructions, the instruction sequences forming nested blocks are terminated with explicit opcodes for end and else.

Block types are encoded in special compressed form, by either the byte 0x40 indicating the empty type, as a single value type, or as a type index encoded as a positive signed integer.

blocktype::=0x40ϵ|t:valtypet|x:s33x(ifx0)instr::=0x00unreachable|0x01nop|0x02  bt:blocktype  (in:instr)  0x0Bblock bt in end|0x03  bt:blocktype  (in:instr)  0x0Bloop bt in end|0x04  bt:blocktype  (in:instr)  0x0Bif bt in else ϵ end|0x04  bt:blocktype  (in1:instr)  0x05  (in2:instr)  0x0Bif bt in1 else in2 end|0x0C  l:labelidxbr l|0x0D  l:labelidxbr_if l|0x0E  l:vec(labelidx)  lN:labelidxbr_table l lN|0x0Freturn|0x10  x:funcidxcall x|0x11  y:typeidx  x:tableidxcall_indirect x y

Note

The else opcode 0x05 in the encoding of an if instruction can be omitted if the following instruction sequence is empty.

Unlike any other occurrence, the type index in a block type is encoded as a positive signed integer, so that its signed LEB128 bit pattern cannot collide with the encoding of value types or the special code 0x40, which correspond to the LEB128 encoding of negative integers. To avoid any loss in the range of allowed indices, it is treated as a 33 bit signed integer.

Reference Instructions

Reference instructions are represented by single byte codes.

instr::=|0xD0  t:reftyperef.null t|0xD1ref.is_null|0xD2  x:funcidxref.func x

Parametric Instructions

Parametric instructions are represented by single byte codes, possibly followed by a type annotation.

instr::=|0x1Adrop|0x1Bselect|0x1C  t:vec(valtype)select t

Variable Instructions

Variable instructions are represented by byte codes followed by the encoding of the respective index.

instr::=|0x20  x:localidxlocal.get x|0x21  x:localidxlocal.set x|0x22  x:localidxlocal.tee x|0x23  x:globalidxglobal.get x|0x24  x:globalidxglobal.set x

Table Instructions

Table instructions are represented either by a single byte or a one byte prefix followed by a variable-length unsigned integer.

instr::=|0x25  x:tableidxtable.get x|0x26  x:tableidxtable.set x|0xFC  12:u32  y:elemidx  x:tableidxtable.init x y|0xFC  13:u32  x:elemidxelem.drop x|0xFC  14:u32  x:tableidx  y:tableidxtable.copy x y|0xFC  15:u32  x:tableidxtable.grow x|0xFC  16:u32  x:tableidxtable.size x|0xFC  17:u32  x:tableidxtable.fill x

Memory Instructions

Each variant of memory instruction is encoded with a different byte code. Loads and stores are followed by the encoding of their memarg immediate.

memarg::=a:u32  o:u32{align a, offset o}instr::=|0x28  m:memargi32.load m|0x29  m:memargi64.load m|0x2A  m:memargf32.load m|0x2B  m:memargf64.load m|0x2C  m:memargi32.load8_s m|0x2D  m:memargi32.load8_u m|0x2E  m:memargi32.load16_s m|0x2F  m:memargi32.load16_u m|0x30  m:memargi64.load8_s m|0x31  m:memargi64.load8_u m|0x32  m:memargi64.load16_s m|0x33  m:memargi64.load16_u m|0x34  m:memargi64.load32_s m|0x35  m:memargi64.load32_u m|0x36  m:memargi32.store m|0x37  m:memargi64.store m|0x38  m:memargf32.store m|0x39  m:memargf64.store m|0x3A  m:memargi32.store8 m|0x3B  m:memargi32.store16 m|0x3C  m:memargi64.store8 m|0x3D  m:memargi64.store16 m|0x3E  m:memargi64.store32 m|0x3F  0x00memory.size|0x40  0x00memory.grow|0xFC  8:u32  x:dataidx 0x00memory.init x|0xFC  9:u32  x:dataidxdata.drop x|0xFC  10:u32  0x00  0x00memory.copy|0xFC  11:u32  0x00memory.fill

Note

In future versions of WebAssembly, the additional zero bytes occurring in the encoding of the memory.size, memory.grow, memory.copy, and memory.fill instructions may be used to index additional memories.

Numeric Instructions

All variants of numeric instructions are represented by separate byte codes.

The const instructions are followed by the respective literal.

instr::=|0x41  n:i32i32.const n|0x42  n:i64i64.const n|0x43  z:f32f32.const z|0x44  z:f64f64.const z

All other numeric instructions are plain opcodes without any immediates.

instr::=thisshouldbeenough|0x45i32.eqz|0x46i32.eq|0x47i32.ne|0x48i32.lt_s|0x49i32.lt_u|0x4Ai32.gt_s|0x4Bi32.gt_u|0x4Ci32.le_s|0x4Di32.le_u|0x4Ei32.ge_s|0x4Fi32.ge_u
instr::=thisshouldbeenough|0x50i64.eqz|0x51i64.eq|0x52i64.ne|0x53i64.lt_s|0x54i64.lt_u|0x55i64.gt_s|0x56i64.gt_u|0x57i64.le_s|0x58i64.le_u|0x59i64.ge_s|0x5Ai64.ge_u
instr::=thisshouldbeenough|0x5Bf32.eq|0x5Cf32.ne|0x5Df32.lt|0x5Ef32.gt|0x5Ff32.le|0x60f32.ge
instr::=thisshouldbeenough|0x61f64.eq|0x62f64.ne|0x63f64.lt|0x64f64.gt|0x65f64.le|0x66f64.ge
instr::=thisshouldbeenough|0x67i32.clz|0x68i32.ctz|0x69i32.popcnt|0x6Ai32.add|0x6Bi32.sub|0x6Ci32.mul|0x6Di32.div_s|0x6Ei32.div_u|0x6Fi32.rem_s|0x70i32.rem_u|0x71i32.and|0x72i32.or|0x73i32.xor|0x74i32.shl|0x75i32.shr_s|0x76i32.shr_u|0x77i32.rotl|0x78i32.rotr
instr::=thisshouldbeenough|0x79i64.clz|0x7Ai64.ctz|0x7Bi64.popcnt|0x7Ci64.add|0x7Di64.sub|0x7Ei64.mul|0x7Fi64.div_s|0x80i64.div_u|0x81i64.rem_s|0x82i64.rem_u|0x83i64.and|0x84i64.or|0x85i64.xor|0x86i64.shl|0x87i64.shr_s|0x88i64.shr_u|0x89i64.rotl|0x8Ai64.rotr
instr::=thisshouldbeenough|0x8Bf32.abs|0x8Cf32.neg|0x8Df32.ceil|0x8Ef32.floor|0x8Ff32.trunc|0x90f32.nearest|0x91f32.sqrt|0x92f32.add|0x93f32.sub|0x94f32.mul|0x95f32.div|0x96f32.min|0x97f32.max|0x98f32.copysign
instr::=thisshouldbeenough|0x99f64.abs|0x9Af64.neg|0x9Bf64.ceil|0x9Cf64.floor|0x9Df64.trunc|0x9Ef64.nearest|0x9Ff64.sqrt|0xA0f64.add|0xA1f64.sub|0xA2f64.mul|0xA3f64.div|0xA4f64.min|0xA5f64.max|0xA6f64.copysign
instr::=thisshouldbeenough|0xA7i32.wrap_i64|0xA8i32.trunc_f32_s|0xA9i32.trunc_f32_u|0xAAi32.trunc_f64_s|0xABi32.trunc_f64_u|0xACi64.extend_i32_s|0xADi64.extend_i32_u|0xAEi64.trunc_f32_s|0xAFi64.trunc_f32_u|0xB0i64.trunc_f64_s|0xB1i64.trunc_f64_u|0xB2f32.convert_i32_s|0xB3f32.convert_i32_u|0xB4f32.convert_i64_s|0xB5f32.convert_i64_u|0xB6f32.demote_f64|0xB7f64.convert_i32_s|0xB8f64.convert_i32_u|0xB9f64.convert_i64_s|0xBAf64.convert_i64_u|0xBBf64.promote_f32|0xBCi32.reinterpret_f32|0xBDi64.reinterpret_f64|0xBEf32.reinterpret_i32|0xBFf64.reinterpret_i64
instr::=thisshouldbeenough|0xC0i32.extend8_s|0xC1i32.extend16_s|0xC2i64.extend8_s|0xC3i64.extend16_s|0xC4i64.extend32_s

The saturating truncation instructions all have a one byte prefix, whereas the actual opcode is encoded by a variable-length unsigned integer.

instr::=thisshouldbeenough|0xFC  0:u32i32.trunc_sat_f32_s|0xFC  1:u32i32.trunc_sat_f32_u|0xFC  2:u32i32.trunc_sat_f64_s|0xFC  3:u32i32.trunc_sat_f64_u|0xFC  4:u32i64.trunc_sat_f32_s|0xFC  5:u32i64.trunc_sat_f32_u|0xFC  6:u32i64.trunc_sat_f64_s|0xFC  7:u32i64.trunc_sat_f64_u

Vector Instructions

All variants of vector instructions are represented by separate byte codes. They all have a one byte prefix, whereas the actual opcode is encoded by a variable-length unsigned integer.

Vector loads and stores are followed by the encoding of their memarg immediate.

laneidx::=l:bytelinstr::=|0xFD  0:u32  m:memargv128.load m|0xFD  1:u32  m:memargv128.load8x8_s m|0xFD  2:u32  m:memargv128.load8x8_u m|0xFD  3:u32  m:memargv128.load16x4_s m|0xFD  4:u32  m:memargv128.load16x4_u m|0xFD  5:u32  m:memargv128.load32x2_s m|0xFD  6:u32  m:memargv128.load32x2_u m|0xFD  7:u32  m:memargv128.load8_splat m|0xFD  8:u32  m:memargv128.load16_splat m|0xFD  9:u32  m:memargv128.load32_splat m|0xFD  10:u32  m:memargv128.load64_splat m|0xFD  92:u32  m:memargv128.load32_zero m|0xFD  93:u32  m:memargv128.load64_zero m|0xFD  11:u32  m:memargv128.store m|0xFD  84:u32  m:memarg l:laneidxv128.load8_lane m l|0xFD  85:u32  m:memarg l:laneidxv128.load16_lane m l|0xFD  86:u32  m:memarg l:laneidxv128.load32_lane m l|0xFD  87:u32  m:memarg l:laneidxv128.load64_lane m l|0xFD  88:u32  m:memarg l:laneidxv128.store8_lane m l|0xFD  89:u32  m:memarg l:laneidxv128.store16_lane m l|0xFD  90:u32  m:memarg l:laneidxv128.store32_lane m l|0xFD  91:u32  m:memarg l:laneidxv128.store64_lane m l

The const instruction is followed by 16 immediate bytes, which are converted into a i128 in littleendian byte order:

instr::=|0xFD  12:u32  (b:byte)16v128.const bytesi1281(b0  b15)

The shuffle instruction is also followed by the encoding of 16 laneidx immediates.

instr::=|0xFD  13:u32  (l:laneidx)16i8x16.shuffle l16

extract_lane and replace_lane instructions are followed by the encoding of a laneidx immediate.

instr::=|0xFD  21:u32  l:laneidxi8x16.extract_lane_s l|0xFD  22:u32  l:laneidxi8x16.extract_lane_u l|0xFD  23:u32  l:laneidxi8x16.replace_lane l|0xFD  24:u32  l:laneidxi16x8.extract_lane_s l|0xFD  25:u32  l:laneidxi16x8.extract_lane_u l|0xFD  26:u32  l:laneidxi16x8.replace_lane l|0xFD  27:u32  l:laneidxi32x4.extract_lane l|0xFD  28:u32  l:laneidxi32x4.replace_lane l|0xFD  29:u32  l:laneidxi64x2.extract_lane l|0xFD  30:u32  l:laneidxi64x2.replace_lane l|0xFD  31:u32  l:laneidxf32x4.extract_lane l|0xFD  32:u32  l:laneidxf32x4.replace_lane l|0xFD  33:u32  l:laneidxf64x2.extract_lane l|0xFD  34:u32  l:laneidxf64x2.replace_lane l

All other vector instructions are plain opcodes without any immediates.

instr::=vechaslongerinstructionnames|0xFD  14:u32i8x16.swizzle|0xFD  15:u32i8x16.splat|0xFD  16:u32i16x8.splat|0xFD  17:u32i32x4.splat|0xFD  18:u32i64x2.splat|0xFD  19:u32f32x4.splat|0xFD  20:u32f64x2.splat
instr::=vechaslongerinstructionnames|0xFD  35:u32i8x16.eq|0xFD  36:u32i8x16.ne|0xFD  37:u32i8x16.lt_s|0xFD  38:u32i8x16.lt_u|0xFD  39:u32i8x16.gt_s|0xFD  40:u32i8x16.gt_u|0xFD  41:u32i8x16.le_s|0xFD  42:u32i8x16.le_u|0xFD  43:u32i8x16.ge_s|0xFD  44:u32i8x16.ge_u
instr::=vechaslongerinstructionnames|0xFD  45:u32i16x8.eq|0xFD  46:u32i16x8.ne|0xFD  47:u32i16x8.lt_s|0xFD  48:u32i16x8.lt_u|0xFD  49:u32i16x8.gt_s|0xFD  50:u32i16x8.gt_u|0xFD  51:u32i16x8.le_s|0xFD  52:u32i16x8.le_u|0xFD  53:u32i16x8.ge_s|0xFD  54:u32i16x8.ge_u
instr::=vechaslongerinstructionnames|0xFD  55:u32i32x4.eq|0xFD  56:u32i32x4.ne|0xFD  57:u32i32x4.lt_s|0xFD  58:u32i32x4.lt_u|0xFD  59:u32i32x4.gt_s|0xFD  60:u32i32x4.gt_u|0xFD  61:u32i32x4.le_s|0xFD  62:u32i32x4.le_u|0xFD  63:u32i32x4.ge_s|0xFD  64:u32i32x4.ge_u
instr::=vechaslongerinstructionnames|0xFD  214:u32i64x2.eq|0xFD  215:u32i64x2.ne|0xFD  216:u32i64x2.lt_s|0xFD  217:u32i64x2.gt_s|0xFD  218:u32i64x2.le_s|0xFD  219:u32i64x2.ge_s|
instr::=vechaslongerinstructionnames|0xFD  65:u32f32x4.eq|0xFD  66:u32f32x4.ne|0xFD  67:u32f32x4.lt|0xFD  68:u32f32x4.gt|0xFD  69:u32f32x4.le|0xFD  70:u32f32x4.ge
instr::=vechaslongerinstructionnames|0xFD  71:u32f64x2.eq|0xFD  72:u32f64x2.ne|0xFD  73:u32f64x2.lt|0xFD  74:u32f64x2.gt|0xFD  75:u32f64x2.le|0xFD  76:u32f64x2.ge
instr::=vechaslongerinstructionnames|0xFD  77:u32v128.not|0xFD  78:u32v128.and|0xFD  79:u32v128.andnot|0xFD  80:u32v128.or|0xFD  81:u32v128.xor|0xFD  82:u32v128.bitselect|0xFD  83:u32v128.any_true
instr::=vechaslongerinstructionnames|0xFD  96:u32i8x16.abs|0xFD  97:u32i8x16.neg|0xFD  98:u32i8x16.popcnt|0xFD  99:u32i8x16.all_true|0xFD  100:u32i8x16.bitmask|0xFD  101:u32i8x16.narrow_i16x8_s|0xFD  102:u32i8x16.narrow_i16x8_u|0xFD  107:u32i8x16.shl|0xFD  108:u32i8x16.shr_s|0xFD  109:u32i8x16.shr_u|0xFD  110:u32i8x16.add|0xFD  111:u32i8x16.add_sat_s|0xFD  112:u32i8x16.add_sat_u|0xFD  113:u32i8x16.sub|0xFD  114:u32i8x16.sub_sat_s|0xFD  115:u32i8x16.sub_sat_u|0xFD  118:u32i8x16.min_s|0xFD  119:u32i8x16.min_u|0xFD  120:u32i8x16.max_s|0xFD  121:u32i8x16.max_u|0xFD  123:u32i8x16.avgr_u
instr::=vechaslongerinstructionnames|0xFD  124:u32i16x8.extadd_pairwise_i8x16_s|0xFD  125:u32i16x8.extadd_pairwise_i8x16_u|0xFD  128:u32i16x8.abs|0xFD  129:u32i16x8.neg|0xFD  130:u32i16x8.q15mulr_sat_s|0xFD  131:u32i16x8.all_true|0xFD  132:u32i16x8.bitmask|0xFD  133:u32i16x8.narrow_i32x4_s|0xFD  134:u32i16x8.narrow_i32x4_u|0xFD  135:u32i16x8.extend_low_i8x16_s|0xFD  136:u32i16x8.extend_high_i8x16_s|0xFD  137:u32i16x8.extend_low_i8x16_u|0xFD  138:u32i16x8.extend_high_i8x16_u|0xFD  139:u32i16x8.shl|0xFD  140:u32i16x8.shr_s|0xFD  141:u32i16x8.shr_u|0xFD  142:u32i16x8.add|0xFD  143:u32i16x8.add_sat_s|0xFD  144:u32i16x8.add_sat_u|0xFD  145:u32i16x8.sub|0xFD  146:u32i16x8.sub_sat_s|0xFD  147:u32i16x8.sub_sat_u|0xFD  149:u32i16x8.mul|0xFD  150:u32i16x8.min_s|0xFD  151:u32i16x8.min_u|0xFD  152:u32i16x8.max_s|0xFD  153:u32i16x8.max_u|0xFD  155:u32i16x8.avgr_u|0xFD  156:u32i16x8.extmul_low_i8x16_s|0xFD  157:u32i16x8.extmul_high_i8x16_s|0xFD  158:u32i16x8.extmul_low_i8x16_u|0xFD  159:u32i16x8.extmul_high_i8x16_u
instr::=vechaslongerinstructionnames|0xFD  126:u32i32x4.extadd_pairwise_i16x8_s|0xFD  127:u32i32x4.extadd_pairwise_i16x8_u|0xFD  160:u32i32x4.abs|0xFD  161:u32i32x4.neg|0xFD  163:u32i32x4.all_true|0xFD  164:u32i32x4.bitmask|0xFD  167:u32i32x4.extend_low_i16x8_s|0xFD  168:u32i32x4.extend_high_i16x8_s|0xFD  169:u32i32x4.extend_low_i16x8_u|0xFD  170:u32i32x4.extend_high_i16x8_u|0xFD  171:u32i32x4.shl|0xFD  172:u32i32x4.shr_s|0xFD  173:u32i32x4.shr_u|0xFD  174:u32i32x4.add|0xFD  177:u32i32x4.sub|0xFD  181:u32i32x4.mul|0xFD  182:u32i32x4.min_s|0xFD  183:u32i32x4.min_u|0xFD  184:u32i32x4.max_s|0xFD  185:u32i32x4.max_u|0xFD  186:u32i32x4.dot_i16x8_s|0xFD  188:u32i32x4.extmul_low_i16x8_s|0xFD  189:u32i32x4.extmul_high_i16x8_s|0xFD  190:u32i32x4.extmul_low_i16x8_u|0xFD  191:u32i32x4.extmul_high_i16x8_u
instr::=vechaslongerinstructionnames|0xFD  192:u32i64x2.abs|0xFD  193:u32i64x2.neg|0xFD  195:u32i64x2.all_true|0xFD  196:u32i64x2.bitmask|0xFD  199:u32i64x2.extend_low_i32x4_s|0xFD  200:u32i64x2.extend_high_i32x4_s|0xFD  201:u32i64x2.extend_low_i32x4_u|0xFD  202:u32i64x2.extend_high_i32x4_u|0xFD  203:u32i64x2.shl|0xFD  204:u32i64x2.shr_s|0xFD  205:u32i64x2.shr_u|0xFD  206:u32i64x2.add|0xFD  209:u32i64x2.sub|0xFD  213:u32i64x2.mul|0xFD  220:u32i64x2.extmul_low_i32x4_s|0xFD  221:u32i64x2.extmul_high_i32x4_s|0xFD  222:u32i64x2.extmul_low_i32x4_u|0xFD  223:u32i64x2.extmul_high_i32x4_u
instr::=vechaslongerinstructionnames|0xFD  103:u32f32x4.ceil|0xFD  104:u32f32x4.floor|0xFD  105:u32f32x4.trunc|0xFD  106:u32f32x4.nearest|0xFD  224:u32f32x4.abs|0xFD  225:u32f32x4.neg|0xFD  227:u32f32x4.sqrt|0xFD  228:u32f32x4.add|0xFD  229:u32f32x4.sub|0xFD  230:u32f32x4.mul|0xFD  231:u32f32x4.div|0xFD  232:u32f32x4.min|0xFD  233:u32f32x4.max|0xFD  234:u32f32x4.pmin|0xFD  235:u32f32x4.pmax
instr::=vechaslongerinstructionnames|0xFD  116:u32f64x2.ceil|0xFD  117:u32f64x2.floor|0xFD  122:u32f64x2.trunc|0xFD  148:u32f64x2.nearest|0xFD  236:u32f64x2.abs|0xFD  237:u32f64x2.neg|0xFD  239:u32f64x2.sqrt|0xFD  240:u32f64x2.add|0xFD  241:u32f64x2.sub|0xFD  242:u32f64x2.mul|0xFD  243:u32f64x2.div|0xFD  244:u32f64x2.min|0xFD  245:u32f64x2.max|0xFD  246:u32f64x2.pmin|0xFD  247:u32f64x2.pmax
instr::=vechaslongerinstructionnames|0xFD  248:u32i32x4.trunc_sat_f32x4_s|0xFD  249:u32i32x4.trunc_sat_f32x4_u|0xFD  250:u32f32x4.convert_i32x4_s|0xFD  251:u32f32x4.convert_i32x4_u|0xFD  252:u32i32x4.trunc_sat_f64x2_s_zero|0xFD  253:u32i32x4.trunc_sat_f64x2_u_zero|0xFD  254:u32f64x2.convert_low_i32x4_s|0xFD  255:u32f64x2.convert_low_i32x4_u|0xFD  94:u32f32x4.demote_f64x2_zero|0xFD  95:u32f64x2.promote_low_f32x4

Expressions

Expressions are encoded by their instruction sequence terminated with an explicit 0x0B opcode for end.

expr::=(in:instr)  0x0Bin end