VRILの命令
ここでは、VRILの命令の一覧や仕様などを掲載しています。
- 各種命令の仕様
- 算術演算命令
(ADD, SUB, MUL, DIV, REM, NEG) - 比較演算命令
(EQ, NEQ, GT, LT, GEQ, LEQ) - 論理演算命令
(ANDM, ORM, NOT) - 転送命令
(MOV, REF, POP, MOVPOP, REFPOP, MOVELM, REFELM, CAST, REORD, FILL) - メモリ管理命令
(ALLOC, ALLOCR, ALLOCP, ALLOCT, FREE) - 制御命令
(JMP, JMPN, CALL, CALLX, RET, ENDFUN, ENDPRM, END, NOP, LABEL) - 拡張命令
(EX)
各種命令の仕様
下記は、VRIL で定義されている各種命令コード(オペレーションコード、オペコード)の一覧と仕様です。
算術演算命令
命令コード | ADD |
---|---|
種類 | SIMD算術演算命令 |
構文 | ADD type output inputA inputB; |
説明 |
加算を行う命令です。 この命令の実行により、「 inputA + inputB 」の計算が行われ、結果が output に格納されます。 全オペランドのデータ型は揃っている必要があり、そのデータ型の名称を type に指定します。 また、全オペランドの配列要素数も同一に揃っている必要があります。 |
命令コード | SUB |
---|---|
種類 | SIMD算術演算命令 |
構文 | SUB type output inputA inputB; |
説明 |
減算を行う命令です。 この命令の実行により、「 inputA - inputB 」の計算が行われ、結果が output に格納されます。 全オペランドのデータ型は揃っている必要があり、そのデータ型の名称を type に指定します。 また、全オペランドの配列要素数も同一に揃っている必要があります。 |
命令コード | MUL |
---|---|
種類 | SIMD算術演算命令 |
構文 | MUL type output inputA inputB; |
説明 |
乗算を行う命令です。 この命令の実行により、「 inputA * inputB 」の計算が行われ、結果が output に格納されます。 全オペランドのデータ型は揃っている必要があり、そのデータ型の名称を type に指定します。 また、全オペランドの配列要素数も同一に揃っている必要があります。 |
命令コード | DIV |
---|---|
種類 | SIMD算術演算命令 |
構文 | DIV type output inputA inputB; |
説明 |
除算を行う命令です。 この命令の実行により、「 inputA / inputB 」の計算が行われ、結果が output に格納されます。 全オペランドのデータ型は揃っている必要があり、そのデータ型の名称を type に指定します。 また、全オペランドの配列要素数も同一に揃っている必要があります。 |
命令コード | REM |
---|---|
種類 | SIMD算術演算命令 |
構文 | REM type output inputA inputB; |
説明 |
剰余演算を行う命令です。 この命令の実行により、「 inputA % inputB 」の計算が行われ、結果が output に格納されます。 全オペランドのデータ型は揃っている必要があり、そのデータ型の名称を type に指定します。 また、全オペランドの配列要素数も同一に揃っている必要があります。 |
命令コード | NEG |
---|---|
種類 | SIMD算術演算命令 |
構文 | NEG type output input; |
説明 |
符号反転演算を行う命令です。 この命令の実行により、「 -input 」の計算が行われ、結果が output に格納されます。 全オペランドのデータ型は揃っている必要があり、そのデータ型の名称を type に指定します。 また、全オペランドの配列要素数も同一に揃っている必要があります。 |
比較演算命令
命令コード | EQ |
---|---|
種類 | SIMD比較演算命令 |
構文 | EQ type output inputA inputB; |
説明 |
等値比較演算を行う命令です。 この命令の実行により、「 inputA == inputB 」の比較演算が行われ、結果が output に格納されます。 inputA と inputB のデータ型は揃っている必要があり、そのデータ型の名称を type に指定します。 加えて、output のデータ型は bool 型である必要があります. また、全オペランドの配列要素数も同一に揃っている必要があります。 |
命令コード | NEQ |
---|---|
種類 | SIMD比較演算命令 |
構文 | NEQ type output inputA inputB; |
説明 |
非等値比較演算を行う命令です。 この命令の実行により、「 inputA != inputB 」の比較演算が行われ、結果が output に格納されます。 inputA と inputB のデータ型は揃っている必要があり、そのデータ型の名称を type に指定します。 加えて、output のデータ型は bool 型である必要があります. また、全オペランドの配列要素数も同一に揃っている必要があります。 |
命令コード | GT |
---|---|
種類 | SIMD比較演算命令 |
構文 | GT type output inputA inputB; |
説明 |
大なり比較演算を行う命令です。 この命令の実行により、「 inputA > inputB 」の比較演算が行われ、結果が output に格納されます。 inputA と inputB のデータ型は揃っている必要があり、そのデータ型の名称を type に指定します。 加えて、output のデータ型は bool 型である必要があります. また、全オペランドの配列要素数も同一に揃っている必要があります。 |
命令コード | LT |
---|---|
種類 | SIMD比較演算命令 |
構文 | LT type output inputA inputB; |
説明 |
小なり比較演算を行う命令です。 この命令の実行により、「 inputA < inputB 」の比較演算が行われ、結果が output に格納されます。 inputA と inputB のデータ型は揃っている必要があり、そのデータ型の名称を type に指定します。 加えて、output のデータ型は bool 型である必要があります. また、全オペランドの配列要素数も同一に揃っている必要があります。 |
命令コード | GEQ |
---|---|
種類 | SIMD比較演算命令 |
構文 | GEQ type output inputA inputB; |
説明 |
大なり等値(以上)比較演算を行う命令です。 この命令の実行により、「 inputA >= inputB 」の比較演算が行われ、結果が output に格納されます。 inputA と inputB のデータ型は揃っている必要があり、そのデータ型の名称を type に指定します。 加えて、output のデータ型は bool 型である必要があります. また、全オペランドの配列要素数も同一に揃っている必要があります。 |
命令コード | LEQ |
---|---|
種類 | SIMD比較演算命令 |
構文 | LEQ type output inputA inputB; |
説明 |
小なり等値(以下)比較演算を行う命令です。 この命令の実行により、「 inputA <= inputB 」の比較演算が行われ、結果が output に格納されます。 inputA と inputB のデータ型は揃っている必要があり、そのデータ型の名称を type に指定します。 加えて、output のデータ型は bool 型である必要があります. また、全オペランドの配列要素数も同一に揃っている必要があります。 |
論理演算命令
命令コード | ANDM |
---|---|
種類 | SIMD論理演算命令 |
構文 | ANDM type output inputA inputB; |
説明 |
論理積演算を行う命令です。 この命令の実行により、「 inputA && inputB 」の論理演算が行われ、結果が output に格納されます。 全てのオペランドのデータ型は bool 型に揃っている必要があり、type にも bool を指定します。 この命令は、「 && 」演算子の短絡評価に対応する生成コードを簡潔にするため、 inputA の値だけから結果が確定可能な場合には、inputB にアクセスしません。 そのため, そのような場合は、inputB は未初期化の状態である事が許容されます。 具体的には、オペランドがスカラなら inputA が false の場合、 ベクトルなら inputA の全要素が false の場合に、inputB へのアクセスがスキップされます。 |
命令コード | ORM |
---|---|
種類 | SIMD論理演算命令 |
構文 | ANDM type output inputA inputB; |
説明 |
論理和演算を行う命令です。 この命令の実行により、「 inputA || inputB 」の論理演算が行われ、結果が output に格納されます。 全てのオペランドのデータ型は bool 型に揃っている必要があり、type にも bool を指定します。 この命令は、「 || 」演算子の短絡評価に対応する生成コードを簡潔にするため、 inputA の値だけから結果が確定可能な場合には、inputB にアクセスしません。 そのため, そのような場合は、inputB は未初期化の状態である事が許容されます。 具体的には、オペランドがスカラなら inputA が true の場合、 ベクトルなら inputA の全要素が true の場合に、inputB へのアクセスがスキップされます。 |
命令コード | NOT |
---|---|
種類 | SIMD論理演算命令 |
構文 | NOT type output input; |
説明 |
論理否定演算を行う命令です。 この命令の実行により、「 ! inputA 」の論理演算が行われ、結果が output に格納されます。 全てのオペランドのデータ型は bool 型に揃っている必要があり、type にも bool を指定します。 |
転送命令
命令コード | MOV |
---|---|
種類 | SIMD転送命令 |
構文 | MOV type output input; |
説明 |
コピー代入演算を行う命令です。 この命令の実行により、input のデータがコピーされ、output に格納されます。 全オペランドのデータ型は揃っている必要があり、そのデータ型の名称を type に指定します。 |
命令コード | REF |
---|---|
種類 | SIMD転送命令 |
構文 | REF type output input; |
説明 |
参照代入演算を行う命令です。 この命令の実行により, output が、input と同一のデータを参照するようになります。 全オペランドのデータ型は揃っている必要があり、そのデータ型の名称を type に指定します。 |
命令コード | POP |
---|---|
種類 | SIMD転送命令 |
構文 | POP -; |
説明 | スタックからデータを取り出しつつ, どこにも格納しない命令です。 |
命令コード | MOVPOP |
---|---|
種類 | SIMD転送命令 |
構文 | MOVPOP type output; |
説明 |
スタックからデータを取り出してコピー代入演算を行う命令です。 この命令の実行により、スタックから取りだされたデータがコピーされ、output に格納されます。 output のデータ型の名称を type に指定します。 |
命令コード | REFPOP |
---|---|
種類 | SIMD転送命令 |
構文 | MOVPOP type output; |
説明 |
スタックからデータを取り出して参照代入演算を行う命令です。 この命令の実行により、output が、スタックから取りだされたデータを参照するようになります。 output のデータ型の名称を type に指定します。 |
命令コード | MOVELM |
---|---|
種類 | スカラ転送命令 |
構文 | MOVELM type output input index1 index2 index3 ... indexN ; (可変長) |
説明 |
配列要素をコピーする命令です。 この命令の実行により、配列 input の要素 [index1][index2][index3]...[indexN] がコピーされ、output に格納されます。 全オペランドのデータ型は揃っている必要があり、そのデータ型の名称を type に指定します。 |
命令コード | REFELM |
---|---|
種類 | スカラ転送命令 |
構文 | REFELM type output input index1 index2 index3 ... indexN ; (可変長) |
説明 |
配列要素を参照する命令です。 この命令の実行により、output のデータの参照が、配列 input の要素 [index1][index2][index3]...[indexN] を指すようになります。 全オペランドのデータ型は揃っている必要があり、そのデータ型の名称を type に指定します。 |
命令コード | CAST |
---|---|
種類 | SIMD転送命令 |
構文 | CAST toType:fromType output input; |
説明 |
型変換命令を行いつつ、値をコピーする命令です。 この命令の実行により、データ型が fromType 型である input のデータが、toType 型に変換された上で、output に代入されます。 |
命令コード | REORD |
---|---|
種類 | SIMD転送命令 |
構文 | REORD type output input; |
説明 |
次元ごとの要素数が異なる多次元配列間で、要素の位置を自動調整しつつ代入を行う命令です。 この命令の実行により、input の各要素の値が、output における同じ配列インデックスの位置に代入されます。 全オペランドのデータ型は揃っている必要があり、そのデータ型の名称を type に指定します。 |
命令コード | FILL |
---|---|
種類 | SIMD転送命令 |
構文 | FILL type output input; |
説明 |
配列データの全要素に、同一の値を代入する命令です。 この命令の実行により、スカラ値 input が、配列 output の全要素に代入されます。 全オペランドのデータ型は揃っている必要があり、そのデータ型の名称を type に指定します。 |
メモリー管理命令
命令コード | ALLOC |
---|---|
種類 | メモリー管理命令 |
構文 | ALLOC type target len1 len2 len3 ... lenN; (可変長) |
説明 |
メモリー確保命令です。 この命令の実行により、target が type 型のデータを格納できるように、仮想メモリー内にデータコンテナが確保されます。 len1 ... lenN オペランドには、格納するデータの配列要素数を、次元ごとに指定します。 例えば [R0][R1][R2] の長さの配列を格納するには、R0 R1 R2 を指定します。 スカラデータは0次元配列として扱われるため、格納するデータがスカラの場合には、len1 ... lenN には何も指定しません。 |
命令コード | ALLOCR |
---|---|
種類 | メモリー管理命令 |
構文 | ALLOCR type target sample; |
説明 |
他のデータと同サイズのメモリ領域を確保するための、ALLOC 命令の派生命令です。 この命令の実行により、target が、type 型で sample と同サイズのデータを格納できるように、仮想メモリー内にデータコンテナが確保されます。 命令名の末尾に "-R" が付いている通り、 この命令は主に、ベクトル演算の結果を格納するレジスタを確保するために用いられます。 ただし、レジスタ領域専用というわけではなく、他の領域の確保にも使用できます。 |
命令コード | ALLOCP |
---|---|
種類 | メモリー管理命令 |
構文 | ALLOCP type target; |
説明 |
スタック先頭にあるデータと同サイズのメモリ領域を確保するための、ALLOC 命令の派生命令です。 この命令の実行により、target が、スタック先頭のデータと同サイズかつ type 型のデータを格納できるように、 仮想メモリー内にデータコンテナが確保されます。 |
命令コード | ALLOCT |
---|---|
種類 | メモリー管理命令 |
構文 | ALLOCT type target len1 len2 len3 ... lenN; |
説明 |
コードの可読性と最適化性のため、データ型や配列次元/要素数の宣言だけを行いつつ、実際のメモリ領域の確保は行わない、ALLOC 命令の派生命令です。 この命令は、例えばスタックからデータを取り出している箇所などで使用されます。 スタックを介するデータのやり取りは、実行時の処理フローに依存する動作であるため、 その型情報(配列次元数含む)をコードから静的に読み取る/推測する事は容易ではありません。 そこで、取り出すデータの格納先に対して、この命令で型情報を明示的に宣言しておく事で、 コードの可読性や最適化の容易さが向上します。 (コード生成を行うコンパイラは、スタックから取り出す値の型情報を知っており、従ってそれが可能です。) |
命令コード | FREE |
---|---|
種類 | メモリー管理命令 |
構文 | FREE type target; |
説明 |
メモリー解放命令です。 この命令の実行により, 仮想メモリー内に確保されていた、target のデータを格納するためのデータコンテナが解放されます。 |
制御命令
命令コード | JMP |
---|---|
種類 | 制御命令 |
構文 | JMP bool - label condition; |
説明 |
条件が真の場合に飛ぶ分岐命令です。 この命令の実行により、condition に指定された値(配列の場合は全要素)が true の場合に、 label に指定されたラベル(または命令アドレスを格納する、定数領域のアドレス)の次の位置にある命令に処理が飛びます。 condition のデータ型は bool 型である必要があります。 |
命令コード | JMPN |
---|---|
種類 | 制御命令 |
構文 | JMPN bool - label condition; |
説明 |
条件が偽の場合に飛ぶ分岐命令です。 この命令の実行により、condition に指定された値(配列の場合は全要素)が false の場合に、 label に指定されたラベル(または命令アドレスを格納する、定数領域のアドレス)の次の位置にある命令に処理が飛びます。 condition のデータ型は bool 型である必要があります。 |
命令コード | CALL |
---|---|
種類 | 制御命令 |
構文 | CALL returnType - signature arg1 arg2 arg3 ... argN; (可変長) |
説明 |
内部関数呼び出し命令です。 この命令の実行により、signature に指定されたシグネチャ(または関数先頭の命令アドレスを格納する、定数領域のアドレス)の内部関数が、[arg1, arg2, arg3, ..., argN] を引数として呼び出されます。 具体的には、まずこの命令の次の命令アドレス(戻り先アドレス)がスタックに積まれ、続いて全ての引数が、左から順にスタックに積まれます。 そして、signature と同じ文字列で宣言されているラベル(=関数先頭)の次の命令に処理が飛びます。 returnType には、戻り値としてスタックに積まれるデータの型名を指定します。 内部関数の実行が終了すると、RET 命令によって、戻り値がスタックの先頭に積まれた状態で、戻り先アドレスの位置の命令に処理が戻されます。 従って、この命令の後方で、スタックから戻り値を取り出す必要があります。 |
命令コード | CALLX |
---|---|
種類 | 制御命令 |
構文 | CALLX returnType returnValue identifier arg1 arg2 arg3 ... argN; (可変長) |
説明 |
外部関数呼び出し命令です。 この命令の実行により、identifier に指定された(名前修飾済みの)識別子の外部関数が、 [arg1, arg2, arg3, ..., argN] を引数として呼び出され、戻り値が returnValue に格納されます。 戻り値のデータ型名を returnType に指定します。 |
命令コード | RET |
---|---|
種類 | 制御命令 |
構文 | RET type returnData; |
説明 |
内部関数から戻るための命令です。 returnData には、関数の戻り値に相当する値があればそれを指定し、無ければ省略します。 type にはその値のデータ型名を指定しますが、値が無い場合にはプレースホルダ「 - 」を指定します。 この命令が実行されると、スタック先頭に積まれている命令アドレス(戻り先アドレス)が取り出され、代わりに戻り値がスタックの先頭に積まれます。 戻り値が無い場合でも、空のデータコンテナがスタックに積まれます。 そして、取り出された命令アドレスの位置に処理が飛びます。 |
命令コード | ENDFUN |
---|---|
種類 | 制御命令 |
構文 | ENDFUN type functionName; |
説明 |
関数終端に置かれる特別な命令です。 functionName には, 実行対象の関数の名称を指定します。type には string を指定します。 スクリプトが正しく記述されていた場合、実行フローはこの命令の実行に達する前に RET 命令によって呼び出し元に戻るため、この命令が実行される事はありません。 この命令が実行されるのは, スクリプトの内容が誤っており、戻り値を返すべき関数が、 戻り値を返さずに終端に達した場合です。 従って、この命令が実行されると、上述の件を通知するエラーが発生します。 |
命令コード | ENDPRM |
---|---|
種類 | 制御命令 |
構文 | ENDPRM type functionName; |
説明 |
関数における実引数-仮引数間の転送部の終端に置かれる特別な命令です。 functionName には、実行対象の関数の名称を指定します。type には string を指定します。 この命令は、実行されても何も起こりませんが、最適化を補助する情報として有用です。 また、VRILコードの可読性の向上にも若干貢献します。 |
命令コード | END |
---|---|
種類 | 制御命令 |
構文 | END type result; |
説明 |
コード終端に置かれる特別な命令です。 result には、コードの評価値に相当する値があればそれを指定し、無ければ省略します。 type にはその値のデータ型名を指定しますが、値が無い場合にはプレースホルダ「 - 」を指定します。 例えば、アプリ内組み込み用のスクリプト実行エンジン(Vnano等)では、 スクリプトの実行結果として、何らかの値(最終行の式文の値など)をアプリ側に返す必要があります。 そのような実行結果の値が、このEND命令の result として指定され、アプリ側に返されます。 |
命令コード | NOP |
---|---|
種類 | 制御命令 |
構文 | NOP -; |
説明 |
最適化によって削除されない事が保証された、何も行わない命令です。 処理系を一定サイクル空回しさせたい場合などに、適当に無意味な処理を記述すると、最適化によって削除される可能性があります。 そのような場合に、このNOP命令を使用します。 |
命令コード | LABEL |
---|---|
種類 | 制御命令 |
構文 | LABEL -; |
説明 |
NOP と同様に何もしない命令ですが、最適化によって削除される場合があります。 VRILのアセンブリコード内での分岐先ラベルは、この命令に変換されます。 これは、最適化による命令の並び替えなどの最中に、分岐の着地点が変化してしまわないように、 「それが着地点になっていると分かる命令」が置かれていると便利なためです。 一方で、実行時には何もしない命令であり、ループ等のオーバーヘッドになってしまうため、 大半は最適化の最後に除去されます。 |
拡張命令
命令コード | EX |
---|---|
種類 | 拡張命令 |
構文 | (処理系依存) |
説明 |
拡張命令を作成するためのオペレーションコードです。 この命令は、VRILの基本的な(非拡張の)命令に基づいた処理系の上に、 拡張的な挙動を行う処理系をかぶせて動作させる際に、 その拡張層で処理する命令を表すために使用します。 拡張命令のオペレーションコードなどは、別途処理系依存の命令オブジェクト内に、拡張情報などの形で保持します。 例として、Vnanoのスクリプト処理系のVM層では、単純なVRILマシンである「 Processor 」と、 その上層に重なる高速実装である「 Accelerator 」が存在しますが、後者でこの拡張命令が使用されます。 具体的には、最適化によって複数の算術演算命令を連続させて、1つにまとめて処理する際に、 そのような拡張命令に変換されます。 |