17. ベクトル並べ替え命令

ベクトル要素間でデータを並べ替えるための並べ替え命令が定義されている。

17.1. 整数スカラ移動命令

整数スカラ読み書き命令は、スカラの整数レジスタxと、ベクトルレジスタの要素0の値を移動するための命令である。この命令はLMULとベクトルレジスタグループの設定を無視する。

vmv.x.s rd, vs2  # rd = vs2[0] (rs1=0)
vmv.s.x vd, rs1  # vd[0] = rs1 (vs2=0)

vmv.x.s命令はベクトルレジスタの要素0から1つのSEW長の要素をコピーして、整数レジスタに書き込む。SEW > XLENであれば、XLENビットの最下位ビットが書き込まれ、SEW-XLENビットの上位ビットは無視される。SEW < XLENであれば、その値はXLENビットまでゼロ拡張されてコピーされる。

vmv.s.x命令は、スカラ整数レジスタの値を書き込みベクトルレジスタの要素0にコピーする。SEW < XLENであれば、SEWビット幅の下位ビットがコピーされ、XLEN-SEWビットの上位ビットは無視される。SEW > XLENであれば、値はSEWビットまでゼロ拡張される。書き込みベクトルレジスタの他の要素(0 < index < VLEN/SEW)はゼロが設定される。 vstartvl の場合、書き込みベクトルレジスタに対する操作は行われない。

結果とし、vl=0の場合、vstartの値に関わらず書き込みベクトルレジスタグループに対するデータの更新は行われない。

エンコーディングでは、vmv.x.s and vmv.s.x のマスクされたバリエーション(vm=0)の命令は予約されている。

17.2. 浮動小数点スカラ移動命令

浮動小数点スカラ読み書き命令は、スカラの浮動小数点レジスタfと、ベクトルレジスタの要素0の値を移動するための命令であるうこの命令はLMULとベクトルレジスタグループの設定を無視する。

vfmv.f.s rd, vs2  # rd = vs2[0] (rs1=0)
vfmv.s.f vd, rs1  # vd[0] = rs1 (vs2=0)

vfmv.f.s命令はベクトルレジスタの要素0から1つのSEW長の要素をコピーして、浮動小数点レジスタに書き込む。SEW > FLENであれば、FLENビットの最下位ビットが書き込まれ、SEW-FLENビットの上位ビットは無視される。SEW < FLENであれば、その値はFLENビットにNaN Boxing(1拡張)される。

vfmv.s.f命令は、スカラ浮動小数点レジスタの値を書き込みベクトルレジスタの要素0にコピーする。SEW < FLENであれば、SEWビット幅の下位ビットがコピーされ、FLEN-SEWビットの上位ビットは無視される。SEW > FLENであれば、値はSEWビットまでNaN-Boxing(1拡張)される。書き込みベクトルレジスタの他の要素(0 < index < VLEN/SEW)はゼロが設定される。 vstartvl の場合、書き込みベクトルレジスタに対する操作は行われない。

結果とし、vl=0の場合、vstartの値に関わらず書き込みベクトルレジスタグループに対するデータの更新は行われない。

エンコーディングでは、vfmv.f.s and vfmv.s.f のマスクされたバリエーション(vm=0)の命令は予約されている。

17.3. ベクトルスライド命令

ベクトルの要素の位置を変更するための命令が定義されている。

レジスタのギャザー命令を使用するより、スライド操作はより効率的に実装することができる。実装ではvslideupvslidedown命令のための特定のOFFSET値に最適化することができる。特に、オフセットの値が2の累乗である場合は他のオフセットよりも全体的に高速な実装を実現できる。

vslideup, vslidedown, vslide1up, vslide1down命令のすべてでは、vstartvlであれば、命令は何も実行せず、書き込みベクトルレジスタの値は更新されない。

結果として、vl=0であれば、vstartの値に関わらず書き込みベクトルレジスタグループは更新されない。

マスク要素\(i\)が書き込み要素\(i\)を制御しているスライド命令はマスクされる。

17.3.1. ベクトルスライドアップ命令

vslideup.vx vd, vs2, rs1, vm        # vd[i+rs1] = vs2[i]
vslideup.vi vd, vs2, uimm[4:0], vm  # vd[i+uimm] = vs2[i]

vslideup命令では、vlの値は書き込まれるベクトルの最大要素の数を示している。書き込みレジスタの開始インデックス(OFFSET)は符号なし整数として整数xレジスタに格納しておき、rs1として参照するか、5ビットのサイズまでであれば即値命令を使用して指定できる。

XLEN > SEWであるならば、SEWビットは切り取られない。マスクされておらず、かつOFFSET < vlならばOFFSETからvl-1までの要素は書き込まれる。

 vslideup命令での書き込みベクトル要素の動作

 OFFSETはスライドアップの量であり、xレジスタもしくは5ビットの即値で与えられる。
                  0 <  i < max(vstart, OFFSET)  変化なし
max(vstart, OFFSET) <= i < vl                   マスクが有効ならばvd[i] = vs2[i-OFFSET]
                                                 そうでなければ変化なし
                 vl <= i < VLMAX                テール要素。変更なし。

vslideupの書き込みベクトルレジスタグループとソースベクトルレジスタグループとオーバラップすることはできなない。操作がマスクされてベクトルマスクレジスタとオーバラップしないならば良いが、そうでなければ不正命令例外が発生する。

オーバラップしない条件は、入力ベクトルに対するWARハザードの発生を抑止する目的と、非ゼロのvstartから再開するためである。

17.3.2. ベクトルストライドダウン命令

vslidedown.vx vd, vs2, rs1, vm       # vd[i] = vs2[i+rs1]
vslidedown.vi vd, vs2, uimm[4:0], vm # vd[i] = vs2[i+uimm]

vslidedown命令では、vlの値はいくつの書き込み先要素に書き込みが行われるかを示す。

vslidedownの要素iのソース要素の動作
                 0 <= i+OFFSET < VLMAX   vs2[i+OFFSET]を読み出す。
             VLMAX <= i+OFFSET           0として読みだされる。

vslidedownの要素iの書き込み要素の動作
                 0 <  i < vstart         変更なし。
            vstart <= i < vl             マスクが有効ならばアップデートされる。そうでなければアップデートされない。
                vl <= i < VLMAX          変更なし。

17.3.3. ベクトルSlide1up命令

ベクトルのスライド命令に対するバリエーションとして、要素1つ分のみベクトルをスライド可能だが、空いた要素に対してスカラの整数を挿入可能な命令を定義する。

vslide1up.vx vd, vs2, rs1, vm        # vd[0]=x[rs1], vd[i+1] = vs2[i]

vslide1up命令はxレジスタ引数を取り、書き込みベクトルレジスタの要素0番がアクティブであればその値を挿入し、そうでなければその書き込み要素は変化しない。XLEN < SEWであれば、値はSEWビットまで符号拡張される。XLEN > SEWであれば、SEWビット分の値がコピーされ、SEW-XLENビット分の値は無視される。

残っているアクティブなvl-1個の要素はソースベクトルレジスタのインデックスiから書き込みベクトルレジスタグループのi+1要素にコピーされる。

vlレジスタは書き込みベクトルレジスタ要素のうちいくつの要素に書き込みが行われるかを示しており、テールの要素はゼロが設定される。

 vslide1upの動作

                  i < vstart  変化なし
              0 = i = vstart  マスクが有効ならば vd[i] = x[rs1]、そうでなければ変化なし。
max(vstart, 1) <= i < vl      マスクが有効ならば vd[i] = vs2[i-1]、そうでなければ変化なし。
            vl <= i < VLMAX   テール要素。 変更なし。

vslide1up命令は、マスクレジスタがマスクされており、書き込み先ベクトルレジスタとオーバラップしてはならない。そうでなければ、不正命令例外が発生する。

17.3.4. ベクトルSlide1down命令

vslide1down命令はアクティブなベクトル要素のうち最初のvl-1個のアクティブの要素をi+1のソースベクトルレジスタインデックスから書き込みベクトルレジスタグループのiのインデックスにコピーする。

vlレジスタは書き込みベクトルレジスタ要素のうちいくつの要素に書き込みが行われるかを示しており、テールの要素の値は変更されない。

vslide1down.vx vd, vs2, rs1, vm      # vd[i] = vs2[i+1], vd[vl-1]=x[rs1]

vslide1down命令はxレジスタ引数を取り、書き込みベクトルレジスタの要素vl-1番がアクティブであればその値を挿入し、そうでなければその書き込み要素は変化しない。XLEN < SEWであれば、値はSEWビットまでゼロ拡張される。XLEN > SEWであれば、SEWビット分の値がコピーされ、SEW-XLENビット分の値は無視される。

vslide1downの動作

                    i < vstart  変化しない
          vstart <= i < vl-1    マスクが有効ならばvd[i] = vs2[i+1]。そうでなければ変化なし。
          vstart <= i = vl-1    マスクが有効ならばvd[vl-1] = x[rs1]。そうでなければ変化なし。
              vl <= i < VLMAX   テール要素。変更なし。
vslide1down命令はメモリを使用せずに、他のベクトルレジスタを汚すことなく値をベクトルレジスタにロードすることができる。これはデバッガがベクトルレジスタの値をデバッグするときに使用でるが、非常に低速であり、またvslide1down命令を何度も発行する必要がある。

17.4. ベクトルレジスタギャザー命令

ベクトルレジスタギャザー命令は最初のソースベクトルレジスタグループから2番目のソースベクトルレジスタグループが示す場所のデータを読み込む。2番目のベクトルに入っているインデックス値は符号なし整数として扱われる。ソースベクトルは、vlの値に関わらず、index < VLMAXの範囲で読み込むことができる。書き込むことのできるレジスタ数はvlで与えられ、vl以降の書き込みベクトルレジスタの値は変更されない。この演算はマスクされることができる。

vrgather.vv vd, vs2, vs1, vm # vd[i] = (vs1[i] >= VLMAX) ? 0 : vs2[vs1[i]];

指定したインデックスが範囲外である場合(vs1[i] > VLMAX)、要素の値としてゼロが返される。

ベクトル - スカラおよびベクトル - 即値の形式をとることができる。これらの命令では、ソースベクトルレジスタからインデックスを読み込み、ベクトルレジスタの最初の位置からvlこの要素を書き込む。スカラレジスタに格納されているインデックスの値および即値の値は符号なし整数として扱われる。

この命令の形式は、任意のベクトル要素を、すべてのベクトルに対して展開するために使用できる。

vrgather.vx vd, vs2, rs1, vm # vd[i] = (x[rs1] >= VLMAX) ? 0 : vs2[x[rs1]]
vrgather.vi vd, vs2, uimm, vm # vd[i] = (uimm >= VLMAX) ? 0 : vs2[uimm]

任意のvrgather命令では、書き込みベクトルレジスタぐルールはマスクレジスタを含めて書き込みベクトルレジスタとオーバラップしてはならない。そうでなければ、不定命令例外が発生する。

SEW=8の場合、vgather.vv命令はベクトル要素0-255のみが参照可能である。

17.5. ベクトル圧縮命令

ベクトル圧縮命令はソースベクトルレジスタグループからベクトルマスクレジスタにより選択された要素を、書き込みベクトルレジスタグループの先頭から連続した要素に並べ替える。

vcompress.vm vd, vs2, vs1  # vs1が有効なマスクであるvs2の要素を圧縮してvd2に書き込む。

vs1により指定されるベクトルマスクレジスタは、最初のvlこの要素を使用してvs2ベクトルの要素を抽出し連続する要素にパックし、vdの先頭から書き込む。任意の残されたvdの値は変更されない。

vcompress命令の使用例

    1 1 0 1 0 0 1 0 1   v0
    8 7 6 5 4 3 2 1 0   v1
    1 2 3 4 5 6 7 8 9   v2

                            vcompress.vm v2, v1, v0
    1 2 3 4 8 7 5 2 0   v2

vcompressはマスクされない命令(vm=1)としてエンコードされる。マスクされる命令(vm=0)のエンコードは予約である。

書き込みベクトルレジスタグループは、ソースベクトルレジスタ及びソースベクトルマスクレジスタとオーバラップしてはならないという制約がある。そうでなければ、不正命令例外が発生する。

vcompress命令の例外は、常にvstartが0であるとして通知される。vstart非ゼロのままでvcompress命令を実行すると、不正命令例外が発生する。

不可能ではないものの、vcompress命令はvstartがゼロでないとして最も再開が難しい命令の非辰である。つまり、実装はそのような動作はしないものとして実装するか、その代わりに要素0から再開するものとして実装する。これは、vstart書き込みレジスタの要素はすでにアップデートされているものと仮定していることを意味する。

17.6 全体ベクトルレジスタ移動命令

vmv<nf>r.v命令は現在のvlおよびvtypeレジスタの設定を無視してすべてのベクトルレジスタ(例えば、すべてのVLENビット)をコピーする。すべてのベクトルレジスタをコピーすることも可能である。

この命令はコンパイラがベクトルレジスタをvlおよびvtypeを使用せずにシャッフルすることを助けるための命令である。

この命令はOPIVI命令としてエンコードされる。コピーされるベクトルレジスタの数はsimmフィールドの最下位ビットとしてエンコードされ、メモリアクセス命令のnfフィールドと同様である。simmフィールドの上位ビットはゼロを設定しなければならず、他のエンコーディングは予約されている。nfの値は1, 2, 4, 8レジスタのどれかを指定しなければならない。

将来の拡張では移動することのできるレジスタの数を上記以外でもサポートする予定である。しかし、現在ではnfが3, 5, 6, 7の場合のエンコーディングは予約されている。
この命令はvsmul命令と同様のエンコーディングをfunct6で使用しているが、即値オペランドを持っており、アンマスクされたバージョンしか定義されていない(vm=1)。エンコーディングは関連したvmergeのエンコーディングと近いものを選択しており、vsmul命令と違い即値の形式の利点を活用している。

ソースレジスタと書き込みレジスタはベクトルレジスタグループサイズにアラインしたアドレスでなければならない。

将来の拡張では、このアラインの制約を除去する予定である。
vdvs2と同じである場合、この命令はNOPである。