# BEAM命令

> Source: https://www.ymotongpoo.com/works/beam-book-ja/appendix/ap_beam_instructions/


<a id="AP-Instructions"></a>

本章では、BEAM汎用命令セットの大半の命令を詳しく見ていきます。
次節では、コード内のドキュメント（`lib/compiler/src/genop.tab`を参照）から生成した簡単な説明とともに、すべての命令を一覧にしています。

## 関数とラベル

<a id="_functions_and_labels"></a>

### label Lbl

<a id="_label_lbl"></a>

汎用命令セットの命令番号1は、実のところ命令と呼べるようなものではありません。
コード中の現在位置に名前、というより番号を与えるだけの、モジュールローカルなラベルです。

各ラベルはジャンプの着地点になりうるため、ベーシックブロックの開始位置を示す場合があります。

### func_info Module Function Arity

<a id="_func_info_module_function_arity"></a>

各関数のコードは`func_info`命令から始まります。
この命令はfunction clauseエラーを生成するために使われ、関数の実際のコードはfunc_info命令の直後にあるラベルから実行が始まります。

ガード付きの関数を考えてみましょう。

``` erlang
id(I) when is_integer(I) -> I.
```

この関数に対応するBeamコードはおおむね次のようになります。

``` erlang
{function, id, 1, 4}.
  {label,3}.
    {func_info,{atom,test1},{atom,id},1}.
  {label,4}.
    {test,is_integer,{f,3},[{x,0}]}.
    return.
```

ここでメタ情報`{function, id, 1, 4}`は、id/1関数の実行がラベル4から始まることを示しています。
ラベル4ではx0に対して`is_integer`を行い、失敗するとfunc_info命令を指すラベル3（f3）へジャンプして*function clause*例外を生成します。
成功した場合はそのまま処理を続け、引数（x0）を返します。

{{< message >}}
func_info命令は、メモリ上の別の場所にある`Export`レコード（`erts/emulator/beam/export.h`で定義）を指しています。
このレコード内にあるいくつかの専用のメモリワードは、トレース機構がすべてのプロセスによる関数の呼び出し・返却のたびに発火する特別なトレース命令を配置するために使われます。
{{< /message >}}

## テスト命令

<a id="_test_instructions"></a>

### 型テスト

<a id="_type_tests"></a>

型テスト命令（`is_* Lbl Argument`）は、引数が指定した型かどうかを調べ、そうでなければラベルLblへジャンプします。
beamの逆アセンブラは、これらの命令をすべて`test`命令として包んで表示します。例えば次のようになります。

``` erlang
    {test,is_integer,{f,3},[{x,0}]}.
```

現在の型テスト命令には、`is_integer`、`is_float`、`is_number`、`is_atom`、`is_pid`、`is_reference`、`is_port`、`is_nil`、`is_binary`、`is_list`、`is_nonempty_list`、`is_function`、`is_function2`、`is_boolean`、`is_bitstr`、`is_tuple`があります。

さらに、アリティ3を取る型テスト命令が1つあります。`test_arity Lbl Arg Arity`です。
この命令は、引数（タプルであることを前提とします）のアリティが`Arity`であるかどうかを調べます。
通常、この命令の直前には`is_tuple`命令が置かれます。

### 比較

<a id="_comparisons"></a>

比較命令（`is_* Lbl Arg1 Arg2`）は、命令の指示に従って2つの引数を比較し、比較が成立しなければ`Lbl`へジャンプします。

比較命令には、`is_lt`、`is_ge`、`is_eq`、`is_ne`、`is_eq_exact`、`is_ne_exact`があります。

Erlangのすべての項は順序付けられているため、これらの命令はどんな2つの項でも比較できることを思い出してください。
たとえば、アトム`self`が`self()`の返すpidより小さいかどうかを調べることもできます（実際に小さいです）。

数値については、比較がErlangの*number*型に基づいて行われることに注意してください（詳しくは[型システムの章](../../understanding_erts/type_system/#CH-TypeSystem)を参照してください）。
つまり、floatとintegerが混在する比較では、精度の低い方の数値がもう一方の型に変換されてから比較されます。
たとえば私の環境では、1と1.0は等しいと比較され、9999999999999999と1.0e16も同様です。
浮動小数点数の比較には常にリスクが伴うため避けるべきであり、結果は基盤となるハードウェアによって変わることがあります。

整数の1と浮動小数点数の1.0を確実に区別して比較したい場合は、is_eq_exactとis_ne_exactを使います。
これはErlangの演算子`=:=`と`=/=`に対応します。

## 関数呼び出し

<a id="_function_calls"></a>

本章では、さまざまな呼び出し命令が何を行うのかを概観します。
関数呼び出しの仕組みについての詳しい説明は、[呼び出しの章](../../understanding_erts/calls/#CH-Calls)を参照してください。

### call Arity Label

<a id="_call_arity_label"></a>

同一モジュール内、ラベル`Label`にあるアリティ`Arity`の関数を呼び出します。
まずリダクションカウントを減らし、必要であればコンテキストスイッチを行います。
呼び出し後の現在のコードアドレスはCPに保存されます。

ローカル呼び出しでは、指定するラベルは常にそのコードが開始する関数の2番目のラベルです。
コンテキストスイッチが必要になった際にMFAを取得できるよう、そのラベルの直前の命令は`func_info`であることが前提とされています。

### call_only Arity Label

<a id="_call_only_arity_label"></a>

同一モジュール内、ラベル`Label`にあるアリティ`Arity`の関数へ末尾再帰呼び出しを行います。
まずリダクションカウントを減らし、必要であればコンテキストスイッチを行います。
CPは戻りアドレスで更新されません。

### call_last Arity Label Deallocate

<a id="_call_last_arity_label_deallocate"></a>

スタックを`Deallocate`ワード分解放したうえで、同一モジュール内、ラベル`Label`にあるアリティ`Arity`の関数へ末尾再帰呼び出しを行います。
まずリダクションカウントを減らし、必要であればコンテキストスイッチを行います。
CPは戻りアドレスで更新されません。

### call_ext Arity Destination

<a id="_call_ext_arity_destination"></a>

Destinationで指定される、アリティ`Arity`の関数へ外部呼び出しを行います。
アセンブリ上でDestinationは通常`{extfunc, Module, Function, Arity}`のように書かれ、これはモジュールのimportsセクションに追加されます。
まずリダクションカウントを減らし、必要であればコンテキストスイッチを行います。
CPは戻りアドレスで更新されます。

### call_ext_only Arity Destination

<a id="_call_ext_only_arity_destination"></a>

Destinationで指定される、アリティ`Arity`の関数へ末尾再帰的な外部呼び出しを行います。
アセンブリ上でDestinationは通常`{extfunc, Module, Function, Arity}`のように書かれます。
まずリダクションカウントを減らし、必要であればコンテキストスイッチを行います。
CPは戻りアドレスで更新されません。

### call_ext_last Arity Destination Deallocate

<a id="_call_ext_last_arity_destination_deallocate"></a>

スタックを`Deallocate`ワード分解放したうえで、Destinationで指定される、アリティ`Arity`の関数へ末尾再帰的な外部呼び出しを行います。
アセンブリ上でDestinationは通常`{extfunc, Module, Function, Arity}`のように書かれます。
まずリダクションカウントを減らし、必要であればコンテキストスイッチを行います。
CPは戻りアドレスで更新されません。

### bif0 Bif Reg, bif\[1,2\] Lbl Bif \[Arg,…​\] Reg

<a id="_bif0_bif_reg_bif12_lbl_bif_arg_reg"></a>

与えられた引数でbif`Bif`を呼び出し、結果を`Reg`に格納します。
bifが失敗した場合は`Lbl`へジャンプします。
アリティ0のbifは失敗しえないため、`bif0`には失敗時のラベルがありません。

{{< message >}}
これらの命令で呼び出されるbifは、ヒープ上への確保やガベージコレクションの引き金を引くことはできません。
それらが必要な場合は`gc_bif`を参照してください。
{{< /message >}}

### gc_bif\[1-3\] Lbl Live Bif \[Arg, …​\] Reg

<a id="_gc_bif1_3_lbl_live_bif_arg_reg"></a>

与えられた引数でbif`Bif`を呼び出し、結果を`Reg`に格納します。
bifが失敗した場合は`Lbl`へジャンプします。
引数は`x(Live)`、`x(Live+1)`、`x(Live+2)`に格納されます。

{{< message >}}
この命令は引数`Live`を持つため、ガベージコレクションを起動するのに十分な情報が得られます。
{{< /message >}}

### call_fun Arity

<a id="_call_fun_arity"></a>

`call_fun`命令は、引数が先頭の`Arity`個の引数レジスタに置かれ、fun（クロージャへのポインタ）が最後の引数の次のレジスタ`x[Arity+1]`に置かれていることを前提とします。

つまり、アリティ0の呼び出しではクロージャは`x[0]`に置かれます。
アリティ1の呼び出しでは`x[0]`に引数が、`x[1]`にクロージャが入ります。以下同様です。

{{< message >}}
アリティが関数オブジェクトと一致しない場合は`badarity`を送出します。
関数でない値が渡された場合は`badfun`を送出します。
{{< /message >}}

### apply Arity

<a id="_apply_arity"></a>

X registersに格納された`Arity`個の引数で関数呼び出しをapplyします。
モジュールを表すアトムは`x[Arity]`に、関数を表すアトムは`x[Arity+1]`に格納されます。
モジュールはタプルで表現されることもあります。

### apply_last Arity Dealloc

<a id="_apply_last_arity_dealloc"></a>

CPをポップし、要素を解放してからCPを再びプッシュするという手順で、スタック上の`Dealloc`個の要素を解放します。
続いて、新しい場所へジャンプすることで、X registersに格納された`Arity`個の引数を使って末尾再帰呼び出しを行います。
モジュールと関数を表すアトムは、それぞれ`x[Arity]`と`x[Arity+1]`に格納されます。
モジュールはタプルで表現されることもあります。

## スタックとヒープの管理

<a id="_stack_and_heap_management_2"></a>

BeamにおけるErlangプロセスのスタックとヒープは同じメモリ領域を共有しています（詳しい説明は[プロセスの章](../../understanding_erts/processes/#CH-Processes)と[メモリの章](../../understanding_erts/memory/#CH-Memory)を参照してください）。
スタックはアドレスの低い方向へ、ヒープはアドレスの高い方向へ伸びていきます。
スタックかヒープのどちらかで利用可能な量を超える空間が必要になると、Beamはガベージコレクションを行います。

- **リーフ関数**：他の関数を一切呼び出さない関数のことです。
- **非リーフ関数**：他の関数を呼び出す可能性がある関数のことです。

これらの命令は、非リーフ関数が現在のスタックフレームを構築・解体するためにも使われます。
つまり、関数に入るときに*継続ポインタ*（CP）がスタックに保存され、抜けるときにスタックから読み戻されます。

リーフ関数の骨格は次のようになります。

```
{function, Name, Arity, StartLabel}.
  {label,L1}.
    {func_info,{atom,Module},{atom,Name},Arity}.
  {label,L2}.
    ...
    return.
```

非リーフ関数の骨格は次のようになります。

```
{function, Name, Arity, StartLabel}.
  {label,L1}.
    {func_info,{atom,Module},{atom,Name},Arity}.
  {label,L2}.
    {allocate,Need,Live}.

    ...
    call ...
    ...

    {deallocate,Need}.
    return.
```

### allocate StackNeed Live

<a id="_allocate_stackneed_live"></a>

継続ポインタ（CP）を保存し、スタック上に`StackNeed`ワード分の領域を追加で確保します。
確保の途中でメモリが尽きた場合はGCを呼び出し、先頭の`Live`個のxレジスタがルートセットの一部を構成します。
たとえば`Live`が2であれば、GCはレジスタX0とX1を保存し、残りは未使用として解放されます。

スタック上に確保する際は、スタックポインタ（E）が減少します。

**allocateの実行例（Allocate 1 0）**

```
       Before           After
         | xxx |            | xxx |
    E -> | xxx |            | xxx |
         |     |            | ??? | caller save slot
           ...         E -> | CP  |
           ...                ...
 HTOP -> |     |    HTOP -> |     |
         | xxx |            | xxx |
```

### allocate_heap StackNeed HeapNeed Live

<a id="_allocate_heap_stackneed_heapneed_live"></a>

継続ポインタ（CP）を保存し、スタック上に`StackNeed`ワード分の領域を追加で確保します。
さらに、ヒープ上にも`HeapNeed`ワード分の空きがあることを保証します。
確保の途中でメモリが尽きた場合は、保持すべきXレジスタの数を`Live`としてGCを呼び出します。

{{< message >}}
ヒープポインタ（HTOP）は、実際にヒープの確保が行われるまで変更されません。
{{< /message >}}

### allocate_zero StackNeed Live

<a id="_allocate_zero_stackneed_live"></a>

この命令はallocateと同様に動作しますが、確保したスタックスロットを`NIL`でクリアする点が異なります。

**allocate_zeroの実行例（allocate_zero 1 0）**

```
       Before           After
         | xxx |            | xxx |
    E -> | xxx |            | xxx |
         |     |            | NIL | caller save slot
           ...         E -> | CP  |
           ...                ...
 HTOP -> |     |    HTOP -> |     |
         | xxx |            | xxx |
```

### allocate_heap_zero StackNeed HeapNeed Live

<a id="_allocate_heap_zero_stackneed_heapneed_live"></a>

allocate_heap_zero命令は`allocate_heap`命令と同様に動作しますが、確保したスタックスロットを`NIL`でクリアする点が異なります。

### test_heap HeapNeed Live

<a id="_test_heap_heapneed_live"></a>

test_heap命令は、ヒープ上に`HeapNeed`ワード分の空きがあることを保証します。
確保の途中でメモリが尽きた場合は、保持すべきXレジスタの数を`Live`としてGCを呼び出します。

### init N

<a id="_init_n"></a>

init命令は、CPポインタより上のNワード分のスタックに`NIL`を書き込んでクリアします。

### deallocate N

<a id="_deallocate_n"></a>

`deallocate`命令は`allocate`の逆の操作を行います。
CP（継続ポインタ）を復元し、`N+1`ワード分のスタックを解放します。

### return

<a id="_return"></a>

return命令は、継続ポインタ（CP）に入っているアドレスへジャンプします。
CPの値はC言語における`0`にあたる値に設定されます。

### trim N Remaining

<a id="_trim_n_remaining"></a>

CPを一時変数へポップし、スタックの`N`ワード分を解放してから、CPをスタックの先頭に戻します。
（引数`Remaining`は、私が知るかぎり使われていません。）

**trimの実行例（Trim 2）**

```
       Before           After
         | ??? |            | ??? |
         | xxx |       E -> | CP  |
         | xxx |            | ... |
    E -> | CP  |            | ... |
         |     |            | ... |
           ...                ...
 HTOP -> |     |    HTOP -> |     |
         | xxx |            | xxx |
```

## データの移動、抽出、書き換え

<a id="_moving_extracting_modifying_data"></a>

### move Source Destination

<a id="_move_source_destination"></a>

移動元`Source`（リテラルまたはレジスタ）の値を、移動先レジスタ`Destination`へ移動します。

### get_list Source Head Tail

<a id="_get_list_source_head_tail"></a>

リストセルを分解する操作です。
`Source`で指定されたリスト（consセル）のheadとtail（car部とcdr部）を取り出し、レジスタ`Head`と`Tail`に格納します。

### get_tuple_element Source Element Destination

<a id="_get_tuple_element_source_element_destination"></a>

配列の添字読み出し操作です。
`Source`タプルの位置`Element`にある要素を取り出し、レジスタ`Destination`に格納します。

### set_tuple_element NewElement Tuple Position

<a id="_set_tuple_element_newelement_tuple_position"></a>

配列の添字を使った破壊的更新操作です。
`Tuple`の`Position`にある要素を、新しい値`NewElement`で更新します。

## 項の構築

<a id="_building_terms"></a>

### put_list Head Tail Destination

<a id="_put_list_head_tail_destination"></a>

ヒープ上に新しいリスト（cons）セルを構築し（2ワード）、そのアドレスをレジスタ`Destination`に格納します。
リストセルの第1要素には`Head`の値が、第2要素には`Tail`の値が設定されます。

### put_tuple Size Destination

<a id="_put_tuple_size_destination"></a>

ヒープ上に空のタプルを構築し（`Size+1`ワード）、そのアドレスをレジスタ`Destination`に格納します。
この時点では要素は設定されません。
`put_tuple`命令の後には必ず複数の`put`命令が続き、要素を1つずつ破壊的に設定していきます。

### put Value

<a id="_put_value"></a>

直前の`put_tuple`命令で作られたタプルの次の要素へ、`Value`を破壊的に格納します。
書き込みアドレスはVM内部で保持・インクリメントされます。
新しいタプルの内容を設定するには、複数の`put`命令が使われます。

### make_fun2 LambdaIndex

<a id="_make_fun2_lambdaindex"></a>

モジュールのLambdaテーブル上のインデックスによって定義される関数オブジェクトを生成します。
Lambdaテーブルは、エントリポイント（ラベルまたはexportエントリ）、アリティ、そしてfrozen変数をいくつ取るかを定義します。
frozen変数の値は現在の実行コンテキスト（Xレジスタ）からコピーされ、関数オブジェクトに格納されます。

個々のBEAM命令の詳細な一覧は本翻訳の対象外です。
原文オンライン版（<https://blog.stenmans.org/theBeamBook/#AP-Instructions>）を参照してください。

## 個別の命令

<a id="_specific_instructions"></a>

引数の型は次のとおりです。

| 型 | 説明 |
|------|------|
| a | 即値のアトム。例: `'foo'` |
| c | 即値の定数値（アトム、nil、small int）。Pid?かもしれない |
| d | レジスタまたはスタックスロットのいずれか |
| e | exportテーブルエントリへの参照 |
| f | ラベル、すなわちコードアドレス |
| I | 整数。例: `42` |
| j | 省略可能なコードラベル |
| l | 浮動小数点レジスタ |
| P | 正の（符号なし）整数リテラル |
| r | レジスタR0（`x[0]`） |
| s | リテラル、レジスタ、スタックスロットのいずれか |
| t | 項。例: `[{foo, bar}]` |
| x | レジスタ。例: `{x, 5}`に対する`5` |
| y | スタックスロット。例: `{y, 1}`に対する`1` |

### すべてのBEAM命令の一覧

<a id="_list_of_all_beam_instructions"></a>

| 命令 | 引数 | 説明 |
|----|----|----|
| allocate | t t | スタック上にいくつかのワードを確保する |
| allocate_heap | t I t | ヒープ上にいくつかのワードを確保する |
| allocate_heap_zero | t I t | ヒープを確保し、ワードをNILに設定する |
| allocate_init | t I y |  |
| allocate_zero | t t | スタックを確保し、ワードを0に設定する？ |
| apply | I | `x[Arity]`のモジュールと`x[Arity+1]`の関数に対して、`x[0..Arity-1]`の引数を適用する |
| apply_last | I P | `apply`と同様だが、CPを保存せず`P`ワードを解放する |
| badarg | j | `badarg`エラーを生成する |
| badmatch | rxy | `badmatch`エラーを生成する |
| bif1 | f b s d | 1引数でbifを呼び出し、失敗した場合は`f`へジャンプする |
| bif1_body | b s d |  |
| bs_context_to_binary | rxy |  |
| bs_put_string | I I |  |
| bs_test_tail_imm2 | f rx I |  |
| bs_test_unit | f rx I |  |
| bs_test_unit8 | f rx |  |
| bs_test_zero_tail2 | f rx |  |
| call_bif0 | e |  |
| call_bif1 | e |  |
| call_bif2 | e |  |
| call_bif3 | e |  |
| case_end | rxy | `case_clause`エラーを生成する |
| catch | y f |  |
| catch_end | y |  |
| deallocate | I | スタックからいくつかのワードを解放し、CPをポップする |
| deallocate_return | Q | `deallocate`と`return`を組み合わせる |
| extract_next_element | xy |  |
| extract_next_element2 | xy |  |
| extract_next_element3 | xy |  |
| fclearerror |  |  |
| fconv | d l |  |
| fmove | qdl ld |  |
| get_list | rxy rxy rxy | リストセルをheadとtailに分解する |
| i_apply |  | 引数`x2`で関数`x0:x1`のコードを呼び出し、CPを保存する |
| i_apply_fun |  | 引数`x1`で関数オブジェクト`x0`のコードを呼び出し、CPを保存する |
| i_apply_fun_last | P | 引数`x1`で関数オブジェクト`x0`のコードへジャンプし、CPを復元して`P`個のスタックセルを解放する |
| i_apply_fun_only |  | 引数`x1`で関数オブジェクト`x0`のコードへジャンプする |
| i_apply_last | P | 引数`x2`で関数`x0:x1`のコードへジャンプする |
| i_apply_only |  | 引数`x2`で関数`x0:x1`のコードへジャンプする |
| i_band | j I d |  |
| i_bif2 | f b d |  |
| i_bif2_body | b d |  |
| i_bor | j I d |  |
| i_bs_add | j I d |  |
| i_bs_append | j I I I d |  |
| i_bs_get_binary2 | f rx I s I d |  |
| i_bs_get_binary_all2 | f rx I I d |  |
| i_bs_get_binary_all_reuse | rx f I |  |
| i_bs_get_binary_imm2 | f rx I I I d |  |
| i_bs_get_float2 | f rx I s I d |  |
| i_bs_get_integer | f I I d |  |
| i_bs_get_integer_16 | rx f d |  |
| i_bs_get_integer_32 | rx f I d |  |
| i_bs_get_integer_8 | rx f d |  |
| i_bs_get_integer_imm | rx I I f I d |  |
| i_bs_get_integer_small_imm | rx I f I d |  |
| i_bs_get_utf16 | rx f I d |  |
| i_bs_get_utf8 | rx f d |  |
| i_bs_init | I I d |  |
| i_bs_init_bits | I I d |  |
| i_bs_init_bits_fail | rxy j I d |  |
| i_bs_init_bits_fail_heap | I j I d |  |
| i_bs_init_bits_heap | I I I d |  |
| i_bs_init_fail | rxy j I d |  |
| i_bs_init_fail_heap | I j I d |  |
| i_bs_init_heap | I I I d |  |
| i_bs_init_heap_bin | I I d |  |
| i_bs_init_heap_bin_heap | I I I d |  |
| i_bs_init_writable |  |  |
| i_bs_match_string | rx f I I |  |
| i_bs_private_append | j I d |  |
| i_bs_put_utf16 | j I s |  |
| i_bs_put_utf8 | j s |  |
| i_bs_restore2 | rx I |  |
| i_bs_save2 | rx I |  |
| i_bs_skip_bits2 | f rx rxy I |  |
| i_bs_skip_bits2_imm2 | f rx I |  |
| i_bs_skip_bits_all2 | f rx I |  |
| i_bs_start_match2 | rxy f I I d |  |
| i_bs_utf16_size | s d |  |
| i_bs_utf8_size | s d |  |
| i_bs_validate_unicode | j s |  |
| i_bs_validate_unicode_retract | j |  |
| i_bsl | j I d |  |
| i_bsr | j I d |  |
| i_bxor | j I d |  |
| i_call | f |  |
| i_call_ext | e |  |
| i_call_ext_last | e P |  |
| i_call_ext_only | e |  |
| i_call_fun | I |  |
| i_call_fun_last | I P |  |
| i_call_last | f P |  |
| i_call_only | f |  |
| i_element | rxy j s d |  |
| i_fadd | l l l |  |
| i_fast_element | rxy j I d |  |
| i_fcheckerror |  |  |
| i_fdiv | l l l |  |
| i_fetch | s s |  |
| i_fmul | l l l |  |
| i_fnegate | l l l |  |
| i_fsub | l l l |  |
| i_func_info | I a a I | `function_clause`エラーを生成する |
| i_gc_bif1 | j I s I d |  |
| i_gc_bif2 | j I I d |  |
| i_gc_bif3 | j I s I d |  |
| i_get | s d |  |
| i_get_tuple_element | rxy P rxy |  |
| i_hibernate |  |  |
| i_increment | rxy I I d |  |
| i_int_bnot | j s I d |  |
| i_int_div | j I d |  |
| i_is_eq | f |  |
| i_is_eq_exact | f |  |
| i_is_eq_exact_immed | f rxy c |  |
| i_is_eq_exact_literal | f rxy c |  |
| i_is_ge | f |  |
| i_is_lt | f |  |
| i_is_ne | f |  |
| i_is_ne_exact | f |  |
| i_is_ne_exact_immed | f rxy c |  |
| i_is_ne_exact_literal | f rxy c |  |
| i_jump_on_val | rxy f I I |  |
| i_jump_on_val_zero | rxy f I |  |
| i_loop_rec | f r |  |
| i_m_div | j I d |  |
| i_make_fun | I t |  |
| i_minus | j I d |  |
| i_move_call | c r f |  |
| i_move_call_ext | c r e |  |
| i_move_call_ext_last | e P c r |  |
| i_move_call_ext_only | e c r |  |
| i_move_call_last | f P c r |  |
| i_move_call_only | f c r |  |
| i_new_bs_put_binary | j s I s |  |
| i_new_bs_put_binary_all | j s I |  |
| i_new_bs_put_binary_imm | j I s |  |
| i_new_bs_put_float | j s I s |  |
| i_new_bs_put_float_imm | j I I s |  |
| i_new_bs_put_integer | j s I s |  |
| i_new_bs_put_integer_imm | j I I s |  |
| i_plus | j I d |  |
| i_put_tuple | rxy I | アリティ`I`のタプルを生成し、結果を`rxy`に格納する。要素は続く`put`命令で設定する |
| i_recv_set | f |  |
| i_rem | j I d |  |
| i_select_tuple_arity | r f I |  |
| i_select_tuple_arity | x f I |  |
| i_select_tuple_arity | y f I |  |
| i_select_tuple_arity2 | r f A f A f |  |
| i_select_tuple_arity2 | x f A f A f |  |
| i_select_tuple_arity2 | y f A f A f |  |
| i_select_val | r f I | 値を`{Value, Label}`のペアのリストと比較し、一致すればジャンプする。一致しなければ`f`へジャンプする |
| i_select_val | x f I | 上と同様だがxレジスタの場合 |
| i_select_val | y f I | 上と同様だがyレジスタの場合 |
| i_select_val2 | r f c f c f | 値を`{c1, f1}`または`{c2, f2}`の2つのペアと比較してジャンプする。失敗した場合は`f`へジャンプする |
| i_select_val2 | x f c f c f | 上と同様だがxレジスタの場合 |
| i_select_val2 | y f c f c f | 上と同様だがyレジスタの場合 |
| i_times | j I d |  |
| i_trim | I | スタックを`I`要素分切り詰め、先頭のCPは保持する |
| i_wait_error |  |  |
| i_wait_error_locked |  |  |
| i_wait_timeout | f I |  |
| i_wait_timeout | f s |  |
| i_wait_timeout_locked | f I |  |
| i_wait_timeout_locked | f s |  |
| if_end |  | `if_clause`エラーを生成する |
| init | y | スタック上の1ワードを`NIL`（`[]`）に設定する |
| init2 | y y | スタック上の2ワードを`NIL`（`[]`）に設定する |
| init3 | y y y | スタック上の3ワードを`NIL`（`[]`）に設定する |
| int_code_end |  | プログラムの終端（スタックなしのreturnと同じ） |
| is_atom | f rxy | 値がアトムかどうかを調べ、そうでなければジャンプする |
| is_bitstring | f rxy | 値がビット列かどうかを調べ、そうでなければジャンプする |
| is_boolean | f rxy | 値がアトム`true`または`false`かどうかを調べ、そうでなければジャンプする |
| is_float | f rxy | 値が浮動小数点数かどうかを調べ、そうでなければジャンプする |
| is_function | f rxy | 値が関数かどうかを調べ、そうでなければジャンプする |
| is_function2 | f s s | 値が関数かどうかを調べ、そうでなければジャンプする |
| is_integer | f rxy | 値がbig integerまたはsmall integerかどうかを調べ、そうでなければジャンプする |
| is_integer_allocate | f rx I I |  |
| is_list | f rxy | 値がリストまたは`NIL`かどうかを調べ、そうでなければジャンプする |
| is_nil | f rxy | 値が空リスト`[]`かどうかを調べ、そうでなければジャンプする |
| is_nonempty_list | f rxy | 値が空でないリスト（consポインタ）かどうかを調べ、そうでなければジャンプする |
| is_nonempty_list_allocate | f rx I t |  |
| is_nonempty_list_test_heap | f r I t |  |
| is_number | f rxy | 値がbig integer、small integer、floatのいずれかかどうかを調べ、そうでなければジャンプする |
| is_pid | f rxy | 値がpidかどうかを調べ、そうでなければジャンプする |
| is_port | f rxy | 値がportかどうかを調べ、そうでなければジャンプする |
| is_reference | f rxy | 値がreferenceかどうかを調べ、そうでなければジャンプする |
| is_tuple | f rxy | 値がタプルかどうかを調べ、そうでなければジャンプする |
| is_tuple_of_arity | f rxy A | 値がアリティ`A`のタプルかどうかを調べ、そうでなければジャンプする |
| jump | f | 位置（ラベル）`f`へジャンプする |
| label | L | コード中の位置を示すマーカーで、ロード時に取り除かれる |
| line | I | ソースファイル中の位置を示すマーカーで、ロード時に取り除かれる |
| loop_rec_end | f | プロセスのreceiveポインタを進め、`loop_rec`命令へジャンプする |
| move | rxync rxy | 値またはレジスタを別のレジスタへ移動する |
| move2 | x x x x | 値のペアを移動先のペアへ移動する |
| move2 | x y x y | 値のペアを移動先のペアへ移動する |
| move2 | y x y x | 値のペアを移動先のペアへ移動する |
| move_call | xy r f |  |
| move_call_last | xy r f Q |  |
| move_call_only | x r f |  |
| move_deallocate_return | xycn r Q |  |
| move_jump | f ncxy |  |
| move_return | xcn r |  |
| move_x1 | c | 値を`x1`に格納する |
| move_x2 | c | 値を`x2`に格納する |
| node | rxy | `rxy`を現在のノード名を表すアトムにする |
| put | rxy | この命令の並びは`i_put_tuple`の後に置かれ、タプルの要素を（0番目から）初期化するために使われる |
| put_list | s s d | headとtailからリストセルを構築し、consポインタを移動先`d`に格納する |
| raise | s s | 指定した型の例外を送出する。互換性維持の都合上、例外の型は第2引数のスタックトレースから取り出す必要がある |
| recv_mark | f | メッセージ取得の再開位置として既知の位置に印を付ける（参照の最適化） |
| remove_message |  | プロセスのinboxから現在のメッセージを取り除く（受信済みとする） |
| return |  | CPにあるアドレスへジャンプし、CPを0に設定する |
| self | rxy | `rxy`を現在のプロセスのpidに設定する |
| send |  | メッセージ`x1`をプロセス`x0`のinboxへ送信する。プロセスが存在しなくてもエラーにはならない |
| set_tuple_element | s d P | 添字を使ってタプルの要素を破壊的に更新する |
| system_limit | j |  |
| test_arity | f rxy A | `rxy`にある関数オブジェクト（クロージャまたはexport）がアリティ`A`かどうかを調べ、そうでなければ`f`へジャンプする |
| test_heap | I t | ヒープの空き容量を確認する |
| test_heap_1_put_list | I y |  |
| timeout |  | タイマーを設定し、メッセージの到着かタイマーイベントのどちらか早い方を待ってプロセスの実行を明け渡す |
| timeout_locked |  |  |
| try | y f | スタックセル`y`に特別なcatch値を書き込み、tryブロックが有効であることを示す。例外が発生するとVMはラベル`f`へジャンプする。これ以降実行されるコードは例外から保護される |
| try_case | y | `try_end`と同様に保護区間の終わりを示し、スタック上のcatch値をクリアして例外マッチングのコード区間を開始する |
| try_case_end | s |  |
| try_end | y | スタックセル`y`からcatch値をクリアし、保護区間の終わりを示す |
| wait | f | メッセージの到着を待ってプロセスをスケジュールアウトする（明け渡す） |
| wait_locked | f |  |
| wait_unlocked | f |  |

