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 の一覧 |
数値
整数
整数値の表記は
桁区切りとして _
が使用可能。
整数値の型
ビット幅 |
符号不問 |
符号あり |
符号なし |
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 |
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[𝑥]].elem
を TAB[𝑥]
-
S.mems[F.module.elemaddrs[𝑥]].elem
を ELEM[𝑥]
-
S.mems[F.module.memaddrs[0]].elem
を MEM
-
S.datas[F.module.dataaddrs[𝑥]].data
を DATA[𝑥]
とします。
以下に続く表は処理ブロック(後述)を除く単体の命令です。
表の最初の列 p
は必要な被演算子の数です。
被演算子は p1, p2, ...
と表記します。
結果は r
とします。結果がないものはスタックに値を積みません。
p
や r
などは必要に応じて 型
の添字を追加して p型
と r型
などと表記します。
p
の隣の列が「操作」の場合は、横の型一覧の一つから「型.操作」が命令になります。
定数
p |
命令 |
備考 |
0 |
i32.const i32 |
ri32 ← i32 |
0 |
i64.const i64 |
ri64 ← i64 |
0 |
f32.const f32 |
rf32 ← f32 |
0 |
f64.const f64 |
rf64 ← f64 |
0 |
v128.const i128 |
rv128 ← i128 |
破棄
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 𝑥 |
r ← p1 ; 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] ← ELEM[𝑦][p2i32 : p3i32] |
p |
命令 |
備考 |
0 |
elem.drop 𝑥 |
ELEM[𝑥] の要素を破棄 |
メモリ
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]i8 ← p2 |
2 |
store16 𝑚 |
○ |
○ |
|
|
|
MEM[𝑚 + p1i32]i16 ← p2 |
2 |
store32 𝑚 |
|
○ |
|
|
|
MEM[𝑚 + p1i32]i32 ← p2 |
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]i8 ← p2i8[u8] |
2 |
v128.store16_lane 𝑚 u8 |
MEM[𝑚 + p1i32]i16 ← p2i16[u8] |
2 |
v128.store32_lane 𝑚 u8 |
MEM[𝑚 + p1i32]i32 ← p2i32[u8] |
2 |
v128.store64_lane 𝑚 u8 |
MEM[𝑚 + p1i32]i64 ← p2i64[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 |
○ |
|
|
|
ri32 ← p1i64 & (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 |
○ |
○ |
○ |
r ← p1 & p2 |
2 |
andnot |
|
|
○ |
r ← p1 & (~p2) |
2 |
or |
○ |
○ |
○ |
r ← p1 | p2 |
2 |
xor |
○ |
○ |
○ |
r ← p1 ^ 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 |
○ |
○ |
r ← p1 << (p2i32 & m) |
2 |
shr_s |
○ |
○ |
r ← p1 >> (p2i32 & m) |
2 |
shr_u |
○ |
○ |
r ← p1 >>> (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 |
○ |
○ |
○ |
○ |
r ← p1 + p2 |
2 |
sub |
○ |
○ |
○ |
○ |
r ← p1 - p2 |
2 |
mul |
○ |
○ |
○ |
○ |
r ← p1 * p2 |
2 |
div |
|
|
○ |
○ |
r ← p1 / p2 |
2 |
div_s |
○ |
○ |
|
|
r ← trunc(p1 /± p2) |
2 |
div_u |
○ |
○ |
|
|
r ← trunc(p1 /+ p2) |
2 |
rem_s |
○ |
○ |
|
|
r ← trunc(p1 %± p2) |
2 |
rem_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 |
min_s |
○ |
○ |
○ |
|
|
|
r[n] ← min±(p1[n], p2[n]) |
2 |
min_u |
○ |
○ |
○ |
|
|
|
r[n] ← min+(p1[n], p2[n]) |
2 |
pmin |
|
|
|
|
○ |
○ |
r[n] ← pmin(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 |
r ← p3i32 ? p1 : p2 |
p |
操作 |
vb1 |
vb2 |
vb4 |
vb8 |
vfs |
vfd |
備考 |
1 |
replace_lane u8 |
○ |
○ |
○ |
○ |
○ |
○ |
r ← p1 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 |
rt ← nullt |
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 |
|