LoginSignup
0
0

WebAssembly 命令の一覧

Last updated at Posted at 2024-04-28

WebAssembly Specification の主に命令関係を大雑把にまとめたものです。詳細は仕様書を参照してください。数も多いので間違いもあると思います。

この記事での表記

ある程度プログラムを組んだ人なら理解できると思われる、JavaScript 等の馴染みのある表記を使用しているつもりです。

以下の機能を予め定義しておきます。

機能 処理 内容
ceil(𝑥) 𝑥 を整数にする 切り上げ
floor(𝑥) 𝑥 を整数にする 切り捨て
trunc(𝑥) 𝑥 を整数にする 0 方向丸め
nearest(𝑥) 𝑥 を整数にする 四捨五入
abs(𝑥) 𝑥 < 0 ? -𝑥 : 𝑥 絶対値
sqrt(𝑥) 𝑥 平方根
min(𝑥, 𝑦) 𝑥 < 𝑦 ? 𝑥 : 𝑦 最小値を選択
max(𝑥, 𝑦) 𝑥 > 𝑦 ? 𝑥 : 𝑦 最大値を選択
clamp(𝑙, 𝑥, 𝑚) max(𝑙, min(𝑥, 𝑚)) 範囲外を範囲内にする
avgr(𝑥, 𝑦) trunc((𝑥 + 𝑦 + 1) / 2) 平均値(四捨五入)
popcnt(𝑥) 𝑥 の 2 進数表記で 1 の数 1 のビット数
memset(𝑑, 𝑠, 𝑛) 𝑑から𝑛バイトを𝑠で埋める メモリの初期化
memcpy(𝑑, 𝑠, 𝑛) 𝑠から𝑛バイトを𝑑ヘ複写 メモリ内容複写(領域重複注意)
memmove(𝑑, 𝑠, 𝑛) 𝑠から𝑛バイトを𝑑ヘ複写 メモリ内容複写(領域重複可)

min,max と非数・無限の挙動が違う pmin,pmax があります。

WASM モジュール (module)

モジュールの中身は以下の通り。

種類 内容
types functype の一覧
funcs func の一覧
tables table の一覧
mems mem の一覧
globals global の一覧
elems elem の一覧
datas data の一覧
start 開始関数(func)
imports import の一覧
exports export の一覧

数値

  • 整数
  • 浮動小数点数
  • ベクトル

整数

整数値の表記は

  • 10進数
  • 16進数:前置文字列 0x

桁区切りとして _ が使用可能。

整数値の型

ビット幅 符号不問 符号あり 符号なし
8 i8 s8 u8
16 i16 s16 u16
32 i32 s32 u32
64 i64 s64 u64
128 i128 s128 u128
𝑁 i𝑁 s𝑁 u𝑁

符号不問はビット列の扱いを利用側に委ねる(既定は符号なし)。

添字による符号の明示

符号を明示するための添字記号を定義しておきます。

符号 記号 例(比較の添字)
あり ± 符号あり比較 (𝑎 <± 𝑏)
なし + 符号なし比較 (𝑎 <+ 𝑏)

ビット拡張

𝑁 ビット整数を、より大きいビット数の整数に変換する機能表現を定義しておきます。

ビット幅 符号あり 符号なし
8 ext8s ext8u
16 ext16s ext16u
32 ext32s ext32u
64 ext64s ext64u
𝑁 ext𝑁s ext𝑁u

ext𝑁s(𝑥)ext𝑁u(𝑥) の処理内容は以下の通り。

機能 内容
ext𝑁s(𝑥) (𝑥 & (2𝑁-1 - 1)) | (0 - (𝑥 & 2𝑁-1))
ext𝑁u(𝑥) (𝑥 & (2𝑁 - 1))

飽和処理

数値を 𝑁 ビットで表現できるように範囲外の値を範囲内に変更する機能表現を定義しておきます。

ビット幅 符号あり 符号なし
8 sat8s sat8u
16 sat16s sat16u
32 sat32s sat32u
64 sat64s sat64u
𝑁 sat𝑁s sat𝑁u

sat𝑁s(𝑥)sat𝑁u(𝑥) の処理内容は以下の通り。

機能 内容
sat𝑁s(𝑥) clamp(-2𝑁-1, 𝑥, 2𝑁-1-1);
sat𝑁u(𝑥) clamp(0, 𝑥, 2𝑁-1)

浮動小数点数

浮動小数点数は浮動小数点数は IEEE 754 形式が使用されています。

ビット幅 表記 内容
32 f32 単精度浮動小数点数
64 f64 倍精度浮動小数点数

整値の表記は

  • 10進数
  • 16進数:前置文字列 0x

桁区切りとして _ が使用可能。

指数表記

基数 後置記号 備考
10 E または e 1.2e-3 = 0.0012
16 p または p 指数部は10進数のビット数(基数 2)
0x1.fp12 = 0x1f00

ベクトル

ベクトルは 128 ビット データです。

表の幅を短くするため、この記事独自の別名を定義しておきます。
プログラム記述では、別名は使用できないので、元の型を使用してください。

要素型 要素数 別名
i8x16 i8 16 vb1
i16x8 i16 8 vb2
i32x4 i32 4 vb4
i64x2 i64 2 vb8
f32x4 f32 4 vfs
f64x2 f64 2 vfd
v128 i128 1 vt

v128 以外の型では配列表記も使用します。

  • 要素型[要素数]
  • 変数[要素数]
  • 変数要素型[要素数]

スタック マシン

スタック上には以下の 3 種類が含まれる。

  • 被演算子(operand)
  • ラベル(br)
  • フレーム(call)

スタックの先頭を右端として表記し、スタックの状況を

..., s2,s1

とすると比較命令(lt)は以下のような動作になります。

実行イメージ
s1 = stack.pop();
s2 = stack.pop();
r = s2 < s1 ? 1 : 0;
stack.push(r);

このままではやや不便なので、順番は必要な数の逆順にして

..., p1, p2

とすると、以下のようになります。

実行イメージ
p2 = stack.pop(); // s1
p1 = stack.pop(); // s2
r = p1 < p2 ? 1 : 0;
stack.push(r);

命令表

仕様書の

  • S.tables[F.module.tableaddrs[𝑥]].elemTAB[𝑥]
  • S.mems[F.module.memaddrs[0]].elemMEM
  • S.datas[F.module.dataaddrs[𝑥]].dataDATA[𝑥]

とします。

以下に続く表は処理ブロック(後述)を除く単体の命令です。

表の最初の列 p は必要な被演算子の数です。

被演算子は p1, p2, ... と表記します。

結果は r とします。結果がないものはスタックに値を積みません。

pr などは必要に応じて の添字を追加して pr などと表記します。

p の隣の列が「操作」の場合は、横の型一覧の一つから「型.操作」が命令になります。

定数

p 命令 備考
0 i32.const i32 ri32i32
0 i64.const i64 ri64i64
0 f32.const f32 rf32f32
0 f64.const f64 rf64f64
0 v128.const i128 rv128i128

破棄

p 命令 備考
1 drop p1 を破棄
1 data.drop 𝑥 DATA[𝑥] を破棄

グローバル変数

p 命令 備考
0 global.get 𝑥 r ← globals[𝑥]
1 global.set 𝑥 globals[𝑥] ← p1

ローカル変数

p 命令 備考
0 local.get 𝑥 r ← locals[𝑥]
1 local.set 𝑥 locals[𝑥] ← p1
1 local.tee 𝑥 rp1 ; locals[𝑥] ← p1

テーブル

p 命令 備考
0 table.size 𝑥 ri32 ← (TAB[𝑥] のサイズ)
2 table.grow 𝑥 ri32 ← (TAB[𝑥] のサイズ)
TAB[𝑥] をサイズ p2i32 に変更(内容は p1)
1 table.get 𝑥 r ← TAB[𝑥][p1i32]
2 table.set 𝑥 TAB[𝑥][p1i32] ← p2
3 table.fill 𝑥 TAB[𝑥][p1i32 : p3i32] ← p2
3 table.copy 𝑥 𝑦 TAB[𝑥][p1i32 : p3i32] ← TAB[𝑦][p2i32 : p3i32]
3 table.init 𝑥 𝑦 TAB[𝑥][p1i32 : p3i32] ← TAB[𝑦][p2i32 : p3i32]
p 命令 備考
0 elem.drop 𝑥 TAB[𝑥] の要素を破棄

メモリ

p 命令 備考
0 memory.size ri32 ← (MEM のページ サイズ)
1 memory.grow ri32 ← (MEM のページ サイズ)
MEM のページをサイズ p1i32 に変更
3 memory.fill memset( &MEM[p1i32], p2i32, p3i32)
3 memory.copy memmove( &MEM[p1i32], &MEM[p2i32], p3i32)
3 memory.init 𝑥 memcpy( &MEM[p1i32], &DATA[𝑥][p2i32], p3i32)
p 操作 i32 i64 f32 f64 v128 備考
1 load 𝑚 r ← MEM[𝑚 + p1i32]
1 load8_s 𝑚 r ← ext8s(MEM[𝑚 + p1i32]i8)
1 load8_u 𝑚 r ← ext8u(MEM[𝑚 + p1i32]i8)
1 load16_s 𝑚 r ← ext16s(MEM𝑚 + p1i32]i16)
1 load16_u 𝑚 r ← ext16u(MEM𝑚 + p1i32]i16)
1 load32_s 𝑚 r ← ext32s(MEM[𝑚 + p1i32]i32)
1 load32_u 𝑚 r ← ext32u(MEM[𝑚 + p1i32]i32)
2 store 𝑚 MEM[𝑚 + p1i32] ← p2
2 store8 𝑚 MEM[𝑚 + p1i32]i8p2
2 store16 𝑚 MEM[𝑚 + p1i32]i16p2
2 store32 𝑚 MEM[𝑚 + p1i32]i32p2
p 命令 備考
1 v128.load8x8_s 𝑚 ri16[n] ← ext8s(MEM[𝑚 + p1i32 + n]i8)
1 v128.load8x8_u 𝑚 ri16[n] ← ext8u(MEM[𝑚 + p1i32 + n]i8)
1 v128.load16x4_s 𝑚 ri32[n] ← ext16s(MEM[𝑚 + p1i32 + 2*n]i16)
1 v128.load16x4_u 𝑚 ri32[n] ← ext16u(MEM[𝑚 + p1i32 + 2*n]i16)
1 v128.load32x2_s 𝑚 ri64[n] ← ext32s(MEM[𝑚 + p1i32 + 4*n]i32)
1 v128.load32x2_u 𝑚 ri64[n] ← ext32u(MEM[𝑚 + p1i32 + 4*n]i32)
1 v128.load32_zero 𝑚 ri128 ← ext32u(MEM[𝑚 + p1i32]i32)
1 v128.load64_zero 𝑚 ri128 ← ext64u(MEM[𝑚 + p1i32]i64)
1 v128.load8_splat 𝑚 ri8[n] ← MEM[𝑚 + p1i32]i8
1 v128.load16_splat 𝑚 ri16[n] ← MEM[𝑚 + p1i32]i16
1 v128.load32_splat 𝑚 ri32[n] ← MEM[𝑚 + p1i32]i32
1 v128.load64_splat 𝑚 ri64[n] ← MEM[𝑚 + p1i32]i64
2 v128.load8_lane 𝑚 u8 r ← p2 ; ri8[u8] ← MEM[𝑚 + p1i32]i8
2 v128.load16_lane 𝑚 u8 r ← p2 ; ri16[u8] ← MEM[𝑚 + p1i32]i16
2 v128.load32_lane 𝑚 u8 r ← p2 ; ri32[u8] ← MEM[𝑚 + p1i32]i32
2 v128.load64_lane 𝑚 u8 r ← p2 ; ri64[u8] ← MEM[𝑚 + p1i32]i64
2 v128.store8_lane 𝑚 u8 MEM[𝑚 + p1i32]i8p2i8[u8]
2 v128.store16_lane 𝑚 u8 MEM[𝑚 + p1i32]i16p2i16[u8]
2 v128.store32_lane 𝑚 u8 MEM[𝑚 + p1i32]i32p2i32[u8]
2 v128.store64_lane 𝑚 u8 MEM[𝑚 + p1i32]i64p2i64[u8]

型変換

p 操作 i32 i64 f32 f64 備考
1 extend8_s r ← ext8s(p1)
1 extend16_s r ← ext16s(p1)
1 extend32_s ri64 ← ext32s(p1i64)
1 extend_i32_s ri64 ← ext64s(p1i32)
1 extend_i32_u ri64 ← ext64u(p1i32)
1 wrap_i64 ri32p1i64 & (232-1)
1 trunc_f32_s r ← trunc(p1f32)
1 trunc_f32_u r ← trunc(p1f32)
1 trunc_f64_s r ← trunc(p1f64)
1 trunc_f64_u r ← trunc(p1f64)
1 trunc_sat_f32_s r ← satNs(trunc(p1f32))
1 trunc_sat_f32_u r ← satNu(trunc(p1f32))
1 trunc_sat_f64_s r ← satNs(trunc(p1f64))
1 trunc_sat_f64_u r ← satNu(trunc(p1f64))
1 demote_f64 rf32 ← f32(p1f64)
1 promote_f64 rf64 ← f64(p1f32)
1 convert_i32_s r ← 型(p1s32)
1 convert_i32_u r ← 型(p1u32)
1 convert_i64_s r ← 型(p1s64)
1 convert_i64_u r ← 型(p1u64)
1 reinterpret_f32 ri32 ← ビット複写(p1f32)
1 reinterpret_f64 ri64 ← ビット複写(p1f64)
1 reinterpret_i32 rf32 ← ビット複写(p1i32)
1 reinterpret_i64 rf64 ← ビット複写(p1i64)
p 操作 vb1 vb2 vb4 vb8 vfs vfd 備考
1 splat r[全要素] ← p1要素型
1 extract_lane u8 r要素型p1[u8]
1 extract_lane_s u8 ri32 ← extNs(p1[u8])
1 extract_lane_u u8 ri32 ← extNu(p1[u8])
p 命令 備考
1 i32x4.trunc_sat_f32x4_s r[n] ← sat32s(trunc(p1f32[n]))
1 i32x4.trunc_sat_f32x4_u r[n] ← sat32u(trunc(p1f32[n]))
1 i32x4.trunc_sat_f64x2_s_zero r[n] ← sat32s(trunc(p1f64[n] ?? 0))
1 i32x4.trunc_sat_f64x2_u_zero r[n] ← sat32u(trunc(p1f64[n] ?? 0))
1 f32x4.convert_i32x4_s r[n] ← f32(p1s32[n])
1 f32x4.convert_i32x4_u r[n] ← f32(p1u32[n])
1 f32x4.demote_f64x2_zero_s r[n] ← f32(p1f64[n])
1 f64x2.convert_low_i32x4_s r[n] ← f64(p1s32[2*n])
1 f64x2.convert_low_i32x4_u r[n] ← f64(p1u32[2*n])
1 f64x2.promote_low_f32x4 r[n] ← f64(p1f32[2*n])
p 命令 備考
1 i16x8.extend_low_i8x16_s r[n] ← ext8s(p1s8[2*n])
1 i16x8.extend_low_i8x16_u r[n] ← ext8u(p1u8[2*n])
1 i16x8.extend_high_i8x16_s r[n] ← ext8s(p1s8[2*n+1])
1 i16x8.extend_high_i8x16_u r[n] ← ext8u(p1u8[2*n+1])
1 i32x4.extend_low_i16x8_s r[n] ← ext16s(p1s16[2*n])
1 i32x4.extend_low_i16x8_u r[n] ← ext16u(p1u16[2*n])
1 i32x4.extend_high_i16x8_s r[n] ← ext16s(p1s16[2*n+1])
1 i32x4.extend_high_i16x8_u r[n] ← ext16u(p1u16[2*n+1])
1 i64x2.extend_low_i32x4_s r[n] ← ext32s(p1s32[2*n])
1 i64x2.extend_low_i32x4_u r[n] ← ext32u(p1u32[2*n])
1 i64x2.extend_high_i32x4_s r[n] ← ext32s(p1s32[2*n+1])
1 i64x2.extend_high_i32x4_u r[n] ← ext32u(p1u32[2*n+1])
2 i8x16.narrow_i16x8_s r[n] ← sat8s(((n&1)?p2:p1)s16[n>>1])
2 i8x16.narrow_i16x8_u r[n] ← sat8u(((n&1)?p2:p1)u16[n>>1])
2 i16x8.narrow_i32x4_s r[n] ← sat16s(((n&1)?p2:p1)s32[n>>1])
2 i16x8.narrow_i32x4_u r[n] ← sat16u(((n&1)?p2:p1)u32[n>>1])

数値比較

p 操作 i32 i64 f32 f64 備考
1 eqz ri32 ← (p1 == 0)
2 eq ri32 ← (p1 == p2)
2 ne ri32 ← (p1 != p2)
2 lt ri32 ← (p1 < p2)
2 lt_s ri32 ← (p1 <± p2)
2 lt_u ri32 ← (p1 <+ p2)
2 gt ri32 ← (p1 > p2)
2 gt_s ri32 ← (p1 >± p2)
2 gt_u ri32 ← (p1 >+ p2)
2 le ri32 ← (p1 <= p2)
2 le_s ri32 ← (p1 <=± p2)
2 le_u ri32 ← (p1 <=+ p2)
2 ge ri32 ← (p1 >= p2)
2 ge_s ri32 ← (p1 >=± p2)
2 ge_u ri32 ← (p1 >=+ p2)
p 操作 vb1 vb2 vb4 vb8 vfs vfd 備考
2 eq r[n] ← (p1[n] == p2[n])
2 ne r[n] ← (p1[n] != p2[n])
2 lt r[n] ← (p1[n] < p2[n])
2 lt_s r[n] ← (p1[n] <± p2[n])
2 lt_u r[n] ← (p1[n] <+ p2[n])
2 gt r[n] ← (p1[n] > p2[n])
2 gt_s r[n] ← (p1[n] >± p2[n])
2 gt_u r[n] ← (p1[n] >+ p2[n])
2 le r[n] ← (p1[n] <= p2[n])
2 le_s r[n] ← (p1[n] <=± p2[n])
2 le_u r[n] ← (p1[n] <=+ p2[n])
2 ge r[n] ← (p1[n] >= p2[n])
2 ge_s r[n] ← (p1[n] >=± p2[n])
2 ge_u r[n] ← (p1[n] >=+ p2[n])
p 操作 vb1 vb2 vb4 vb8 vt 備考
1 any_true ri32 ← (p1i128 != 0)
1 all_true ri32 ← (p1 の全要素が非 0 で真)

ビット演算

p 操作 i32 i64 v128 備考
1 not r ← ~p1
2 and rp1 & p2
2 andnot rp1 & (~p2)
2 or rp1 | p2
2 xor rp1 ^ p2
3 bitselect r ← (p1 & p3) | (p2 & ~p3)
1 clz r ← clz(p1) : 最上位ビットから 0 を数える
1 clt r ← ctz(p1) : 最下位ビットから 0 を数える
1 popcnt r ← popcnt(p1)
p 操作 i32
m=31
i64
m=63
備考
2 shl rp1 << (p2i32 & m)
2 shr_s rp1 >> (p2i32 & m)
2 shr_u rp1 >>> (p2i32 & m)
2 rotl r ← (p1 << (p2i32 & m)) | (p1 >>> (-p2i32 & m))
2 rotr r ← (p1 >>> (p2i32 & m)) | (p1 << (-p2i32 & m))
p 操作 vb1
m=7
vb2
m=15
vb4
m=31
vb8
m=63
備考
2 shl r[n] ← p1[n] << (p2i32 & m)
2 shr_s r[n] ← p1[n] >> (p2i32 & m)
2 shr_u r[n] ← p1[n] >>> (p2i32 & m)
p 操作 vb1 vb2 vb4 vb8 備考
1 popcnt r[n] ← popcnt(p1[n])
1 bitmask ri32 ← 0
ri32 |= (p1[n] <± 0) << n

数値演算

p 操作 i32 i64 f32 f64 備考
1 ceil r ← ceil(p1)
1 floor r ← floor(p1)
1 trunc r ← trunc(p1)
1 nearest r ← nearest(p1)
1 abs r ← abs(p1)
1 neg r ← -p1
1 sqrt r ← sqrt(p1)
2 add rp1 + p2
2 sub rp1 - p2
2 mul rp1 * p2
2 div rp1 / p2
2 div_s r ← trunc(p1 /± p2)
2 div_u r ← trunc(p1 /+ p2)
2 min r ← min(p1, p2)
2 max r ← max(p1, p2)
2 copysign r ← abs(p1) * (p2 / abs(p2))
p 操作 vb1 vb2 vb4 vb8 vfs vfd 備考
1 floor r[n] ← floor(p1[n])
1 trunc r[n] ← trunc(p1[n])
1 nearest r[n] ← nearest(p1[n])
1 abs r[n] ← abs(p1[n])
1 neg r[n] ← -p1[n]
1 sqrt r[n] ← sqrt(p1[n])
1 ceil r[n] ← ceil(p1[n])
2 add r[n] ← p1[n] + p2[n]
2 add_sat_s r[n] ← satNs(p1[n] + p2[n])
2 add_sat_u r[n] ← satNu(p1[n] + p2[n])
2 avgr_u r[n] ← avgr+(p1[n], p2[n])
2 sub r[n] ← p1[n] - p2[n]
2 sub_sat_s r[n] ← satNs(p1[n] - p2[n])
2 sub_sat_u r[n] ← satNu(p1[n] - p2[n])
2 mul r[n] ← p1[n] * p2[n]
2 div r[n] ← p1[n] / p2[n]
2 min r[n] ← min(p1[n], p2[n])
2 pmin r[n] ← pmin(p1[n], p2[n])
2 min_s r[n] ← min±(p1[n], p2[n])
2 min_u r[n] ← min+(p1[n], p2[n])
2 max r[n] ← max(p1[n], p2[n])
2 max_s r[n] ← max±(p1[n], p2[n])
2 max_u r[n] ← max+(p1[n], p2[n])
2 pmax r[n] ← pmax(p1[n], p2[n])
p 命令 備考
1 i16x8.extadd_pairwise_i8x16_s r[n] ← p1s8[2*n] + p1s8[2*n+1]
1 i16x8.extadd_pairwise_i8x16_u r[n] ← p1u8[2*n] + p1u8[2*n+1]
1 i32x4.extadd_pairwise_i16x8_s r[n] ← p1s16[2*n] + p1s16[2*n+1]
1 i32x4.extadd_pairwise_i16x8_u r[n] ← p1u16[2*n] + p1u16[2*n+1]
2 i16x8.extmul_low_i8x16_s r[n] ← p1s8[2*n] * p2s8[2*n]
2 i16x8.extmul_low_i8x16_u r[n] ← p1u8[2*n] * p2u8[2*n]
2 i16x8.extmul_hight_i8x16_s r[n] ← p1s8[2*n+1] * p2s8[2*n+1]
2 i16x8.extmul_hight_i8x16_u r[n] ← p1u8[2*n+1] * p2u8[2*n+1]
2 i32x4.extmul_low_i16x8_s r[n] ← p1s16[2*n] * p2s16[2*n]
2 i32x4.extmul_low_i16x8_u r[n] ← p1u16[2*n] * p2u16[2*n]
2 i32x4.extmul_hight_i16x8_s r[n] ← p1s16[2*n+1] * p2s16[2*n+1]
2 i32x4.extmul_hight_i16x8_u r[n] ← p1u16[2*n+1] * p2u16[2*n+1]
2 i64x2.extmul_low_i32x4_s r[n] ← p1s32[2*n] * p2s32[2*n]
2 i64x2.extmul_low_i32x4_u r[n] ← p1u32[2*n] * p2u32[2*n]
2 i64x2.extmul_hight_i32x4_s r[n] ← p1s32[2*n+1] * p2s32[2*n+1]
2 i64x2.extmul_hight_i32x4_u r[n] ← p1u32[2*n+1] * p2u32[2*n+1]
2 i16x8.q15mulr_sat_s r[n] ← sat16s(
      (p1s16[n] * p2s16[n] + 214) >> 15)
2 i32x4.dot_i16x8_s r[n] ← (p1s16[2*n] * p2s16[2*n]
      + p1s16[2*n+1] * p2s16[2*n+1])

選択・混成

p 命令 備考
3 select rp3i32 ? p1 : p2
p 操作 vb1 vb2 vb4 vb8 vfs vfd 備考
1 replace_lane u8 rp1
r[u8] ← p2要素型
p 命令 備考
2 i8x16.shuffle u80 u81 ... u815 r[n] ← [...p1 , ...p2][u8n]
2 i8x16.swizzle r[n] ← p1[p2[n]] ?? 0

ref 命令

p 命令 備考
0 ref.func 𝑥 rfunc ← funcs[𝑥]
0 ref.null t rtnullt
1 ref.is_null ri32 ← (p1 == null)

制御命令

p 命令 備考
0 nop 何もしない
0 unreachable 不到達用(trap発生)
? br l ブロックの入れ子 l 番目のラベルへジャンプ
(脱出するブロック分のスタック処理が行われる)
1+? br_if l if (p1i32) "br l"
1+? br_table l0 l1 ... lN "br lmin(N, p1i32)"
0 call 𝑥 関数 funcs[𝑥] の呼び出し
1 call_indirect 𝑥 𝑦 関数 TAB[𝑥][p1i32] の呼び出し
関数は types[𝑦] 型であること
? return 関数から戻る (関数型に応じたスタック処理が行われる)

処理ブロック

以下の表は、命令表ではなく処理順を表します。

block 〜 end

p コード 備考
? block t ブロックの開始 (t に応じたスタック処理が行われる)
? 𝑖𝑛𝑠𝑡𝑟... ブロック内のコード
? end ブロックの終了 (t に応じたスタック処理が行われる)
(なし) ラベルの位置

loop 〜 end

p コード 備考
(なし) ラベルの位置
? loop t ブロックの開始 (t に応じたスタック処理が行われる)
? 𝑖𝑛𝑠𝑡𝑟... ブロック内のコード
? end ブロックの終了 (t に応じたスタック処理が行われる)

if 〜 else 〜 end

p コード 備考
1 if t p1i32 が偽なら else の次へジャンプ
- 𝑖𝑛𝑠𝑡𝑟... block t 𝑖𝑛𝑠𝑡𝑟... end 相当
0 else end へジャンプ
- 𝑖𝑛𝑠𝑡𝑟... block t 𝑖𝑛𝑠𝑡𝑟... end 相当
0 end
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0