5. ベクトル命令フォーマット

ベクトル拡張命令は既存の4つの命令オペコード(LOAD-FP, STORE-FP, AMO)および新しいメジャーオペコード(OP-V)を使用している。

ベクトルロードとストア命令は浮動小数点巣からロードストアのメジャーオペコード(LOAD-FP/STORE-FP)でエンコーディングされている。ベクトルロードとストアは標準的なスカラの浮動小数点ロードストア命令の12ビットの即値フィールドを使って、より多くの命令エンコーディングを提供している。ビット25は標準的なベクトルマスクビットを示している(マスクエンコーディングの章を参照のこと)。

LOAD-FPメジャーオペコードを使用したベクトルロード命令のフォーマット
31 29 28 26  25  24      20 19       15 14   12 11      7 6     0
 nf  | mop | vm |  lumop   |    rs1    | width |    vd   |0000111| VL*  unit-stride
 nf  | mop | vm |   rs2    |    rs1    | width |    vd   |0000111| VLS* strided
 nf  | mop | vm |   vs2    |    rs1    | width |    vd   |0000111| VLX* indexed
  3     3     1      5           5         3         5       7

STORE-FPメジャーオペコードを使用を使用したベクトルストア命令のフォーマット
31 29 28 26  25  24      20 19       15 14   12 11      7 6     0
 nf  | mop | vm |  sumop   |    rs1    | width |   vs3   |0100111| VS*  unit-stride
 nf  | mop | vm |   rs2    |    rs1    | width |   vs3   |0100111| VSS* strided
 nf  | mop | vm |   vs2    |    rs1    | width |   vs3   |0100111| VSX* indexed
  3     3     1      5           5         3         5        7
AMOメジャーオペコードを使用したベクトルAMO命令のフォーマット
31    27 26  25  24      20 19       15 14   12 11      7 6     0
 amoop  |wd| vm |   vs2    |    rs1    | width | vs3/vd  |0101111| VAMO*
   5      1   1      5           5         3        5        7
OP-Vメジャーオペコードを使用したベクトル算術演算のフォーマット

31       26  25   24      20 19      15 14   12 11      7 6     0
  funct6   | vm  |   vs2    |    vs1   | 0 0 0 |    vd   |1010111| OP-V (OPIVV)
  funct6   | vm  |   vs2    |    vs1   | 0 0 1 |  vd/rd  |1010111| OP-V (OPFVV)
  funct6   | vm  |   vs2    |    vs1   | 0 1 0 |  vd/rd  |1010111| OP-V (OPMVV)
  funct6   | vm  |   vs2    |   simm5  | 0 1 1 |    vd   |1010111| OP-V (OPIVI)
  funct6   | vm  |   vs2    |    rs1   | 1 0 0 |    vd   |1010111| OP-V (OPIVX)
  funct6   | vm  |   vs2    |    rs1   | 1 0 1 |    vd   |1010111| OP-V (OPFVF)
  funct6   | vm  |   vs2    |    rs1   | 1 1 0 |  vd/rd  |1010111| OP-V (OPMVX)
     6        1        5          5        3        5        7
OP-Vメジャーオペコードを使用したベクトルコンフィグレーションのフォーマット

 31 30         25 24      20 19      15 14   12 11      7 6     0
 0 |        zimm[10:0]      |    rs1   | 1 1 1 |    rd   |1010111| vsetvli
 1 |   000000    |   rs2    |    rs1   | 1 1 1 |    rd   |1010111| vsetvl
 1        6            5          5        3        5        7

ベクトル命令はスカラオペランドとベクトルソースオペランドを持つことができ、スカラとベクトルの両方の結果を出力することができる。ほとんどのベクトル命令は無条件で動作するか、マスクに基づいて条件的に動作する。

ベクトルロードストア命令はレジスタ要素とメモリの間でビットパタンを移動する。ベクトル算術演算はベクトルレジスタ要素の値を演算する。

5.1. スカラオペランド

スカラオペランドは、即値、X整数レジスタ、f浮動小数点レジスタ、ベクトルの要素0レジスタを取ることができる。スカラの結果はX, f, もしくはベクトルレジスタの要素0番目に書き込まれる。LMULのセッティングに関係なく、どのようなベクトルレジスタもスカラの値を保持することができる。

0.6からの仕様変更として、浮動小数点レジスタはベクトルレジスタとオーバレイしなくなった点と、スカラの要素嘘として整数と浮動小数点レジスタを取ることができるということが挙げられる。fレジスタとのオーバレイの仕様を削除したことにより、ベクトルレジスタのレジスタプレッシャの問題を削減し、標準的な呼び出し規約での相互干渉を避けることができる。また、高性能スカラ浮動小数点演算命令において実装を簡単化する。また、Zfinx ISAとの互換性をサポートする。fレジスタをvレジスタとオーバレイすることのメリットはいくつかの実装で状態ビットの数を削減することができるが、高性能な設計では実装が複雑化し、Zfinxオプションでの処理が複雑化する。

5.2. ベクトルオペランド

ベクトルオペランド・ベクトル演算結果はLMULに基づいて1つ以上のベクトルレジスタを使用するが、常にグループ内の最小ベクトルレジスタアドレスを使用する。最小ベクトルレジスタアドレス以外を使用すると、不定命令例外を発生する。

いくつかのベクトル命令はより幅の長い要素を読み込むか書き込みを行い、vlmulで指定されたレジスタグループよりもより多くのベクトルレジスタグループを使用することがある。最大のベクトルレジスタグループは8を超える事は無く、もしベクトル命令が8よりも大きなレジスタグループを必要とするならば、その命令は不定命令例外が発生する。例えば、LMUL=8でより幅の広いレジスタを使用する命令を実行した場合、不定命令例外が発生する。幅を広げられるスカラの値、例えば幅広いリダクション演算の結果などはベクトルレジスタの最初の要素に格納され、LMUL=1のようにして取り扱われる。

5.3 ベクトルマスク

多くのベクトル命令ではマスクイングをサポートしている。マスクされた要素に対する演算は、書き込みレジスタ要素の値を更新せず、例外も発生しない。

ベースレジスタ拡張では、マスクの値はマスク付きベクトル命令によって使用され、マスクの値は常にベクトルレジスタv0から与えられる。各要素の再開ビットが制御命令のマスクベクタとして使用される。

将来のベクトル拡張では、マスクレジスタとしてすべての空間を利用できるような長い命令エンコーディングを提供する予定である。

マスク付きベクトル命令の書き込みレジスタグループは、LMUL=1の時のみオーバラップすることができる。それ以外の場合は不定命令例外が発生する。

この制約では、非ゼロのvstart値による再開がサポートされる。

他のベクトルレジスタは計算中のマスクを保持することができ、プレディケートの計算のためにベクトル論理演算などを適用できる。

5.3.1. マスクのエンコーディング

マスクが使用可能な場合、命令中のinst[25]に配置されているvm1ビットとしてエンコードされる。

vm 説明
0 vector result, only where v0[i].LSB = 1
1 unmasked
初期の仕様では、vmは2ビットでありvm[1:0]とし、スカラ命令と同様にv0を使用して双方とも1もしくは排他的なマスクをサポートしていた。

ベクトルのマスクはアセンブラコードでは追加のベクトルオペランドとして表現される。.tv0[i].LSBが1である場合に演算が発生する。マスクが指定されていないと、マスク無しベクトル命令(vm=1)として演算が実行される。

vop.v*    v1, v2, v3, v0.t  # enabled where v0[i].LSB=1, m=0
vop.v*    v1, v2, v3        # unmasked vector operation, m=1
v0によるTrueの形のプレディケーションをベクトルマスクレジスタをサポートしているにも関わらず、アセンブリの構文ではマスクレジスタの指定としてすべてのベクトルレジスタを指定でき、Both Trueと排他的なマスクをサポートできるように設計している。.tはマスクの仕様を視覚的にエンコードすることを助ける。

5.4 プリスタート・アクティブ・インアクティブ・ボディー・テールの要素定義

ベクトル命令を実行中に、演算が適用される要素は以下の4つの別々の状態に分類される。

  • プリスタート(prestart) 要素は、その要素のインデックがvstartに格納されている初期値よりも小さいものを指す。プリスタート状態の要素は例外を発生させず、書き込みレジスタに指定されても要素のアップデートは行われない。
  • アクティブ(active)要素は現在のベクトル長の設定に含まれているベクトル要素であり、現在のマスク設定により有効化されている要素である。アクティブな要素は例外を発生する可能性があり、書き込みベクトルレジスタグループにより書き込みが発生する可能性がある。
  • インアクティブ(inactive)な要素は現在のベクトル長の設定に含まれているベクトル要素であるが、現在のマスクそっていにより有効化されていないベクトル要素である。インアクティブな要素は例外を発生させず、書き込みレジスタに指定されても書き込みが行われない。
  • テール(tail)要素はベクトル命令の実行中に、現在のベクトル長の設定よりも後ろのベクトル要素である。テールのベクトル要素は例外を発生させないが、ベクトルレジスタグループにおいて書き込み時はゼロが書き込まれる。
  • 加えて、他の要素としてボディー(body)要素は、アクティブ要素とインアクティブ要素の両方を示したものである。つまり、プリスタート以降で、テール以前の要素を指す。
ベクトル要素のインデックス xについて、
プリスタート     = (0 <= x < vstart)
mask(x)        = unmasked || v0[x].LSB == 1
アクティブ(x)    = (vstart <= x < vl) && mask(x)
インアクティブ(x) = (vstart <= x < vl) && !mask(x)
ボディー(x)      = active(x) || inactive(x)
テール(x)        = (vl <= x < VLMAX)

インアクティブ及びテール要素のアップデートのルールは、ベクトル操作において参加されることのない書き込み要素について値の変化なしとしている。前回のバージョン(v0.7)では、テール要素にゼロを書き込むことでレジスタリネーミングの実装における複雑性を除去していた。バージョン0.8では、テールの要素は値を変化させないように変更となっている。これによりレジスタリネーミングを行わないシンプルな実装において複雑にならないようにしており、またいくつかの共通シーケンスにおいてソフトウェアの複雑性が発生しないようにしている。関連する仕様については以下の仕様を参考にすること。

インアクティブおよびテール要素の「変更なし」と「ゼロ設定」に関する議論