Version 1.0-rc2-draft :doctype: article :encoding: utf-8 :lang: en :toc: left :numbered: :stem: latexmath :le: ≤ :ge: ≥ :ne: ≠ :approx: ≈ :inf: ∞

Contributors include: Alon Amid, Krste Asanovic, Allen Baum, Alex Bradbury, Tony Brewer, Chris Celio, Aliaksei Chapyzhenka, Silviu Chiricescu, Ken Dockser, Bob Dreyer, Roger Espasa, Sean Halle, John Hauser, David Horner, Bruce Hoult, Bill Huffman, Nicholas Knight, Constantine Korikov, Ben Korpan, Hanna Kruppe, Yunsup Lee, Guy Lemieux, Grigorios Magklis, Filip Moc, Rich Newell, Albert Ou, David Patterson, Colin Schmidt, Alex Solomatnikov, Steve Wallach, Andrew Waterman, Jim Wilson.

sectnums!

v1.0-rc1からの変更点

現在まで変更なし。

sectnums

イントロダクション

このドキュメントは、RISC-Vベクトル拡張のバージョン1.0の第2リリース候補のドラフトであり、 パブリックレビューのためのものです。

これはパブリックレビュー用の1.0の凍結版ではありません。

注釈

パブリックレビューのために送り出されることを意図しています。 また、バージョン1.0は、上流のソフトウェアプロジェクトを含め、ツールチェイン、機能シミュレータ、 初期実装の開発を開始するのに十分な安定性があると考えられており、 批准中に重大な問題が発見された場合を除き、 大きな機能変更はないと予想されています。批准されると、仕様書のバージョンは2.0になります。

本仕様書ドラフトには、現在定義されているベクトル命令の全セットが含まれています。 標準ベクトル拡張 セクションには、標準的なベクトル拡張機能と、 それぞれの拡張機能でサポートされる命令および要素幅が記載されています。

実装により定義される定数パラメータ

ベクトル拡張をサポートする各hartには、2つのパラメータが定義されています。

  • 任意の演算で生成または消費できるベクトル要素の最大サイズ(ビット) ELEN {ge} 8 で、これは2の累乗でなければなりません。

  • 1つのベクトルレジスタのビット数 VLEN 、これは2の累乗でなければならず、2の累乗であり、2^16^以上であってはなりません。

標準的なベクトル拡張(標準ベクトル拡張 セクション)とアーキテクチャプロファイルは、 ELENVLEN にさらなる制約を設定することができます。

注釈

(LMUL=8およびSEW=8でVLEN=65,536の場合、最大のVLMAXは65,536になります)。 将来的にクトルレジスタあたり64Kib以上に拡張する場合は、 新しいコンフィグレーション命令が必要になりますが、 従来のコンフィグレーション命令を使用しているソフトウェアでは、 ベクトルの長さが大きくなることはありません。

ISAは、特定の制約の下で、VLENパラメータの値が異なるhart上でバイナリコードが実行されるポータブルな記述をサポートしていますが、 両方のhartが必要な要素型をサポートしていることが条件となります。

注釈

VLENまたはELENパラメータに違いのあるhart間で実行中にコンテキストを移動するとはできません。

ベクトル拡張のプログラミングモデル

ベクトル拡張はRISC-VのベーススカラISAに対して、 32本のベクトルレジスタと7つの非特権CSR(vstart, vxsat, vxrm, vcsr, vl, vlenb)が追加されます。

アドレス

特権

名前

説明

0x008

URW

vstart

ベクトル操作開始位置

0x009

URW

vxsat

固定小数点飽和フラグ

0x00A

URW

vxrm

固定小数点丸めモード

0x00F

URW

vcsr

ベクトル制御・ステータスレジスタ

0xC20

URO

vl

ベクトル長

0xC21

URO

vtype

ベクトルデータ型レジスタ

0xC22

URO

vlenb

VLEN/8 (バイト単位でのベクトルレジスタ長)

ベクトルレジスタ

ベクトル拡張により、RISC-VベーススカラISAに対して 32本のアーキテクチャベクトルレジスタ v0-v31 が追加されます。

各ベクトルレジスタのサイズは固定長でVLENビットです。

注釈

整数レジスタファイル上で実行する新しいISAオプションです。 Vector 1.0拡張はZfinxに対して互換性があります。

mstatus 内のベクトルコンテキストステータス

ベクトルコンテキストステータスフィールド VS は、 mstatus[10:9] に追加され、 sstatus[10:9] でシャドウイングされます。 これは、浮動小数点コンテキストステータスフィールドである FS と同様に定義されます。

VS フィールドがOFFに設定されている場合は、 ベクトル命令を実行しようとしたり、ベクトルCSRにアクセスしようとすると、 不正命令例外が発生します。

VS フィールドがInitialまたはCleanに設定されている場合、 ベクトルCSRを含むベクトルの状態を変更する命令を実行すると、VS がDirtyに変更されます。 また、実装では、ベクトルの状態が変化していなくても、 いつでも VS フィールドをInitialまたはCleanからDirtyに変更することができます。

注釈

ソフトウェアは通常、コンテキストスワップのオーバーヘッドを減らすためにVSを使用します。

実装では、書き込み可能な misa.v フィールドを持つことができます。 浮動小数点演算ユニットの処理方法と同様に、 misa.v がクリアされていても mstatus.vs フィールドが存在する場合があります。

注釈

ベクトル操作のエミュレーションが可能になり、書き込み可能な misa.v を持つシステムでの mstatus.vs の処理が簡単になります。

ベクトル型レジスタ vtype

読み取り専用のXLEN幅を持つ ベクトル CSR (vtype)は、 ベクトルレジスタファイルの内容を解釈するために使用されるデフォルトの型を提供し、 vset{i}vl{i} 命令によってのみ更新することができます。 ベクトル型は、各ベクトルレジスタの要素の構成や、複数のベクトルレジスタをどのようにグループ化するかを決定します。

注釈

vtype レジスタの状態の維持が容易になります。

vtype レジスタには、 villvmavtavsew[2:0]vlmul[2:0] の5つのフィールドがあります。

include::vtype-format.adoc[]

注釈

mata に 2 ビット、vsew[1:0] に 2 ビット、 vlmul[2:0] に 3 ビットです。 vill で表される不正な値は、vsew[1:0] の不正な64ビットの組み合わせを使って内部的にエンコードすることができ、 vill を保持するための追加のストレージビットを必要としません。

注釈

より多様なデータ型がサポートされるようになります。

注釈

これらのフィールドを命令エンコーディング内で静的に指定できるようになることが予想されます。

ベクトル選択要素幅 vsew[2:0]

vsew の値は、動的な 選択要素幅 (SEW)を設定します。 デフォルトでは、ベクトルレジスタは、 VLEN/SEW要素に分割されているとみなされます。

vsew[2:0]

SEW

0

0

0

8

0

0

1

16

0

1

0

32

0

1

1

64

1

0

0

128

予約

1

0

1

256

予約

1

1

0

512

予約

1

1

1

1024

予約

注釈

より大きな vsew[2:0] エンコーディング (100-111) が使用されることが予想されますが、 このエンコーディングは、現時点では正式には 予約 です。

SEW

ベクトルレジスタあたりの要素数

64

2

32

4

16

8

8

16

サポートされる要素の幅はLMULによって異なりますが、 プロファイルはLMUL=1でサポートされなければならない最小のSEWを義務付けている場合があります。

注釈

大きなSEWをサポートする場合があります。 大きなSEWに依存しているソフトウェアは、コードを実行できる実装の数を増やすために、 最大のLMULを使用し、したがって最小のベクトルレジスタグループを使用するようにしてください。 また、vtype を設定した後に、vtypevill ビットをチェックして、 その構成がサポートされているかどうかを確認し、 サポートされていない場合には、代替のコードパスを提供する必要があります。 また、プロファイルでは、各LMULの設定で最小のSEWを義務付けることもできます。

ベクトルレジスタのグループ化(vlmul[2:0])

複数のベクトルレジスタをグループ化することで、1つのベクトル命令で複数のベクトルレジスタを操作することができます。 本仕様書では、ベクトル命令の単一オペランドとして使用される1つまたは複数のベクトルレジスタを指すために ベクトルレジスタグループ という用語を使用しています。 ベクトルレジスタグループは、2倍以上の幅の要素を、選択された幅の要素と同じベクトル長で操作することを可能にします。 また、ベクトルレジスタグループは、長いアプリケーションベクトルの実行効率を高めます。

ベクトル長 の倍数 LMUL が1より大きい場合は、ベクトルレジスタグループ形成するために 結合されるベクトルレジスタのデフォルト数を表します。 実装では、LMULは整数値1,2,4,8をサポートする必要があります。

LMUL は、ベクトルレジスタで使用されるビット数を減らすために、小数値を取ることもできます。 LMUL は、1/2、1/4、1/8 の分数値を持つことができます。 小数点以下のLMULは、幅の広いベクトルが複数のベクトルレジスタを使用する必要がないため、 幅の異なる値を操作する際に使用可能なアーキテクチャーレジスタの数を増やすために使用されます。 その代わり、幅の広い値は1つのベクトルレジスタを占有し、 幅の狭い値はベクトルレジスタの端数を占有することができます。

実装では、LMUL {ge} SEW~LMUL1MIN~/SEW~LMUL1MAX~ の小数の LMUL 設定をサポートする必要があります。 SEW~LMUL1MIN~ はLMUL=1でサポートされる最も狭いSEW値で、 SEW~LMUL1MAX~ はLMUL=1でサポートされる最も広いSEW値です。 サポートされていないSEWとLMULの設定を行おうとすると、 vtypevill ビットが設定されます。

サポートされている小数のLMUL設定に対して、 実装はSEW~LMUL1MIN~ とLMUL * SEW~LMUL1MAX~ の間のSEW設定をサポートしなければなりません。

注釈

幅の広い要素を保持するために1つのベクトルレジスタのみを使用し、幅の狭い要素を保持するために小数のLMULを使用することができます。 LMUL < SEW~LMUL1MIN~/SEW~LMUL1MAX~ の場合、VLEN=SEW~LMUL1MAX~ が有効な実装選択であるため、 少なくとも1つの要素を格納するのに十分なビットが小数ベクトル・レジスタにあるという保証はありません。

注釈

この制約はELENではなくSEW~LMUL1MAX~ を使用して記述されています。 このような場合には、コードがより狭い幅の演算も実行しているときに、単一のベクトルレジスタに保持できる最も広くサポートされた要素を保持するために、 単一のベクトルレジスタ以上のものが必要とされないように、制約が保証されることに注意してください。

LMUL < SEW~LMUL1MIN~/SEW~LMUL1MAX~ での vtype エンコーディングの使用は**予約**ですが、 実装はこれらの構成をサポートしていない場合、 vill を設定することができます。

注釈

将来的に拡張機能でこのケースを使用することができなくなるため、 LMUL<SEW~LMUL1MIN~/SEW~LMUL1MAX~ の動作を将来的に定義できるように、 このケースの使用は 予約 であると考えます。

注釈

エラーではなく警告を出すことを推奨します。

LMULは、vtype の符号付き vlmul フィールドで設定されます (LMUL = 2^`vlmul[2:0]`^)。

VLMAX = LMUL*VLEN/SEW の導出値は、以下の表に示すように、 現在のSEWとLMULの設定があれば、1つのベクト命令で操作できる要素の最大数を表します。

vlmul[2:0]

LMUL

#groups

VLMAX

Registers grouped with register n

1

0

0

reserved

1

0

1

1/8

32

VLEN/SEW/8

v n (single register in group)

1

1

0

1/4

32

VLEN/SEW/4

v n (single register in group)

1

1

1

1/2

32

VLEN/SEW/2

v n (single register in group)

0

0

0

1

32

VLEN/SEW

v n (single register in group)

0

0

1

2

16

2*VLEN/SEW

v n, v n+1

0

1

0

4

8

4*VLEN/SEW

v n, …, v n+3

0

1

1

8

4

8*VLEN/SEW

v n, …, v n+7

LMUL=2の場合、ベクトレジスタグループには、ベクトレジスタ v **n**とベクトレジスタ v **n**+1が含まれ、 ビット単位で2倍のベクト長になります。 LMUL=2のベクトレジスタグループで、奇数番号のベクトレジスタを指定する命令は予約されています。

LMUL=4 の場合、ベクトレジスタグループには 4 個のベクトレジスタが含まれ、 4 の倍数ではないベクトレジスタ番号を使用して LMUL=4 のベクトレジスタグループを指定する命令は予約されます。

LMUL=8 の場合、ベクトレジスタグループには 8 個のベクトレジスタが含まれ、 8 の倍数ではないレジスタ番号を使用して LMUL=8 ベクトレジスタグループを指定する命令は予約されています。

マスクレジスタは、LMULにかかわらず、常に1つのベクトレジスタとして取り扱われます。

Tail Agnostic とVector Mask Agnostic vtavma

これらの2つのビットは、ベクトル命令の実行中に、書き込みレジスタのTail要素および 書き込みレジスタの非アクティブなマスクオフされた要素の動作をそれぞれ変更します。 Tailセットと非アクティブセットには、プリスタート、アクティブ、非アクティブ、ボディ、末尾要素の定義 項で定義されているように、 ベクトル演算中に新しい結果を受け取らない要素の位置を含んでいます。

すべてのシステムは、4つのオプションすべてをサポートしなければなりません。

vta

vma

末尾要素

非アクティブ要素

0

0

undisturbed

undisturbed

0

1

undisturbed

agnostic

1

0

agnostic

undisturbed

1

1

agnostic

agnostic

セットがundisturbedに設定されている場合、ベクトルレジスタグループ内の対応するセットの書き込み要素は、 以前の値を保持します。 マスクの書き込み値は、vta の設定にかかわらず、 常にTail Agnosticとして扱われます。

セットがAgnosticとして設定されている場合、任意のベクトル書き込みオペランドの要素における対応するセットは、 以前保持していた値か、1で上書きされるかのいずれかになります。 1つのベクトル命令の中で、各書き込み要素は、任意の組み合わせで、値を保持したり、1で上書きしたりすることができ、 同じ入力で命令を実行したときに、値を保持するか1で上書きしたりするパタンは、常に決定している必要はありません。 また、マスクロード命令を除き、マスク結果の末尾にある任意の要素には、 マスク生成演算が `vl`=VLMAX で計算したであろう値を書き込むこともできます。

注釈

深い一時的なベクトルレジスタを持つマシンに対応するために追加されました。 Agnosticなポリシでは、新しい物理書き込みベクトルレジスタにコピーするために、 すべての要素を古い物理書き込みベクトルレジスタから読み込まなければなりません。 これは、これらの非アクティブまたは末尾の要素値が後続の計算に必要でない場合、効率が悪くなります。

注釈

マスクレジスタ値のTail Undisturbedをサポートするソフトウェアの必要性はほとんどないと思われます。 マスクを生成する命令が命令の結果を書き戻すことを許可すると、末尾をマスクアウトするロジックの必要性がなくなります。 ただし、マスクロードは、ソフトウェアの意図を超えてメモリにアクセスすることになるため、 宛先のマスクテールにメモリ値を書き込むことはできません。

注釈

ソフトウェア開発者が書き込まれた値に依存しないようにするためです。

注釈

互換性とスレッドの移行をサポートするために、vtavma のステートビットは vtype で提供されなければなりません。

注釈

tail-agnostic + mask-agnostic を tail-agnostic + mask-undisturbed を使って実装することを選択できます。

注釈

レジスタリネーミングのある大きなアウトオブオーダコア上のhart(おそらくagnostic要素を1で上書きする)の間でアプリケーションスレッドを 移行することに対応するため、緩く残されています。 途中で再起動する必要があるかもしれないので、1つのベクトル命令の中で、Agnosticなポリシを任意に混在させることができます。 このようなポリシの混在を許容することで、 例えば、アクティブに操作されている要素内ではundisturbedを使用し、テールの要素ではすべて1にリネームするなど、 ベクトルレジスタの異なる要素に対してポリシを変更するような実装も可能になります。

アセンブリ構文では、 vsetvli 命令に2つのフラグが追加されています。

ta   # Tail agnostic
tu   # Tail undisturbed
ma   # Mask agnostic
mu   # Mask undisturbed

vsetvli t0, a0, e32, m4, ta, ma   # Tail agnostic, mask agnostic
vsetvli t0, a0, e32, m4, tu, ma   # Tail undisturbed, mask agnostic
vsetvli t0, a0, e32, m4, ta, mu   # Tail agnostic, mask undisturbed
vsetvli t0, a0, e32, m4, tu, mu   # Tail undisturbed, mask undisturbed

注釈

デフォルトで mask-undisturbed/tail-undisturbed とすべきです。 しかし、これらのフラグを持たない vsetvli の使用は非推奨とし、 フラグ設定の指定が必須となるようにします。 どちらかというと、デフォルトはtail-agnostic/mask-agnosticにすべきなので、 ソフトウェアは非アクティブ要素を気にするタイミングを指定する必要がありますが、 これらのフラグが導入される前の命令の歴史的な意味を考えると、 将来のアセンブリコードでは常にフラグを要求するのが最も安全です。

不正ベクトル型 vill

vill ビットは、過去の vset{i}vl{i} 命令がサポートされていない値を vtype に書き込もうとしたことをエンコードするために使用されます。

注釈

符号を検査する分岐命令で不正な値をチェックできます。

vill ビットがセットされている場合、vtype に依存するベクトル命令を実行しようとすると、 不正命令例外が発生します。

vill ビットがセットされているときは、 vtype の他のXLEN-1ビットはゼロでなければなりません。

ベクトル長レジスタ vl

XLEN ビット幅の読み込み専用 vl CSRは、vset{i}vl{i} 命令と、 fault-only-first ベクトルロード命令によってのみ更新することができます。

vl レジスタは、セクション プリスタート、アクティブ、非アクティブ、ボディ、末尾要素の定義 で詳しく説明されているように、 ベクトル命令の結果で更新される要素数を指定する符号なし整数を保持します。

注釈

VLEN=32 で SEW=8 をサポートする最小のベクトル実装では、0~32 の値を保持するために、 vl に少なくとも 6 ビットが必要になります (VLEN=32 で LMUL=8 と SEW=8 を使用すると、VLMAX=32 になります)。

ベクトルバイト長 vlenb

XLEN ビット幅の読み取り専用CSR vlenb は、値VLEN/8、すなわち、 バイト単位でのベクトルレジスタの長さを保持します。

注釈

コードは現在の vlvtype の設定を乱す必要があり、 それらを保存したり復元したりする必要があります。

ベクトルスタートインデックスCSR vstart

読み書き可能なCSRである vstart は、 プリスタート、アクティブ、非アクティブ、ボディ、末尾要素の定義 項で説明したように、 ベクトル命令で実行される最初の要素のインデックスを指定します。

通常、vstart はベクトル命令の例外発生時にハードウェアによってのみ書き込まれ、 vstart の値は例外発生した要素 (同期例外または非同期割り込み) を表し、 再開可能な例外が処理された後に実行が再開されるべき要素を表します。

すべてのベクトル命令は、 vstart CSR で指定された要素インデックスから実行を開始し、 書き込みベクトル内の以前の要素には影響を与えず、実行終了時には vstart CSR をゼロにリセットするように定義されています。

vstart は、不正命令例外を発生させるベクトル命令によって変更されません。

vstart CSR は、最大の要素インデックスを保持するのに十分な書き込み可能なビットのみを持つように定義されます (最大 VLMAX より 1 つ少ない)。

注釈

例えば、VLEN=256の場合、vstart は、0から255までのインデックスを表す8ビットを持つことになります。

現在のSEW設定の最大要素インデックスよりも大きい vstart 値の使用は予約されています。

注釈

上位の vstart ビットの将来的な使用法として、 不正確な例外情報を保存することが考えられるため、 例外を発生させることは必須ではありません。

vstart CSR は非特権コードによって書き込み可能ですが、 非ゼロの vstart 値はいくつかの実装でベクトル命令の実行速度を大幅に低下させる可能性があるため、 vstart はアプリケーション・プログラマーが使用すべきではありません。 いくつかのベクトル命令は、非ゼロの vstart 値では実行できず、 以下に定義するような不正な命令例外を発生させます。

注釈

ユーザレベルのスレッディングライブラリをサポートします。

実装は、同じ vtype 設定で同じ命令を実行した場合でも、 実装が決して生成できない vstart の値を持つベクトル命令を実行しようとした場合、 不正命令例外を発生させることが許可されています。

注釈

命令が完了するまで待って割り込みを受け取ります。 そのような実装では、 vstart が0でないときにベクトル演算命令を実行しようとすると、 不正な命令例外を発生させることができます。

注釈

vstart 値は新しい hart のマイクロアーキテクチャーではサポートされていない可能性があります。 その場合、受信側の hart のランタイムは、サポートされている vstart 要素の位置への命令実行をエミュレートしなければならないかもしれません。 あるいは、移行イベントは、相互にサポートされる vstart 位置でのみ発生するように制約することもできます。

ベクトル固定小数点丸めモードレジスタ vxrm

ベクトル固定小数点丸めモード・レジスタは、2ビットの読み書き可能な丸め込みモード・フィールドを保持します。 ベクトル固定小数点丸め込みモードは、独立してアクセスできるように、 別のCSRアドレスが与えられていますが、 vcsr のフィールドとしても反映されています。

固定小数点丸めのアルゴリズムは以下のように規定されています。 丸め前の結果を v とし、その結果の d ビットを丸めるとします。 このとき、丸められた結果は (v >> d) + r となり、 r は次の表にあるように丸めモードに依存します。

vxrm[1:0]

Abbreviation

Rounding Mode

Rounding increment, r

0

0

rnu

round-to-nearest-up (add +0.5 LSB)

v[d-1]

0

1

rne

round-to-nearest-even

v[d-1] & (v[d-2:0]≠0 | v[d])

1

0

rdn

round-down (truncate)

0

1

1

rod

round-to-odd (OR bits into LSB, aka "jam")

!v[d] & v[d-1:0]≠0

以下の命令の説明では、丸め関数を表すために以下の操作が使用されています。

roundoff*unsigned(v, d) = (unsigned(v) >> d) + r
roundoff*signed(v, d) = (signed(v) >> d) + r

vxrm[XLEN-1:2] はゼロが書き込まれるべきです。

注釈

新しい丸め込みモードを設定することができます。

ベクトル固定小数点飽和フラグ vxsat

vxsat CSRは読み書き可能な1ビットを保持しており、 固定小数点命令が出力値を出力先のフォーマットに収めるために飽和させる必要があったかどうかを示します。

vxsat ビットは vcsr のミラーです。

Vector 制御・ステータスレジスタ vcsr

vxrmvxsat CSRは、ベクトル制御・ステータスCSRである vcsr のフィールドを介してアクセスすることもできます。

Bits

Name

Description

2:1

vxrm[1:0]

Fixed-point rounding mode

0

vxsat

Fixed-point accrued saturation flag

リセット時のベクトル拡張の状態

ベクトル拡張は、リセット時に一貫した状態を持っている必要があります。 特に、vtypevl は、1つの vsetvl 命令で読み取ってから復元できる値を持っていなければなりません。

vstart, vxrm, vxsat CSR は、リセット時に任意の値を持つことができます。

注釈

これにより vstart がリセットされます。 vxrmvxsat フィールドは、使用前にソフトウェアで明示的にリセットする必要があります。

ベクトルレジスタはリセット時に任意の値を持つことができます。

ベクトルレジスタ状態へのベクトル要素のマッピング

以下の図は、現在のSEWおよびLMULの設定と、実装のVLENに応じて、 異なる幅の要素がどのようにベクトルレジスタのバイトに詰め込まれるかを示しています。 要素は、最下位バイトが最下位ビットになるように各ベクトルレジスタに詰め込まれます。

LMUL = 1 時のマッピング

LMUL=1の場合、要素はベクトルレジスタの最下位ビットから最上位ビットの順に単純にパックされます。

注釈

バイトアドレスが右から左に向かって増加するように並べられています。 要素内のビットはリトルエンディアン形式で番号付けされており、 右から左へのビットインデックスの増加は大きさの増加に対応します。

// LMUL=1 examples.
LMUL=1の例

The element index is given in hexadecimal and is shown placed at the
least-significant byte of the stored element.

要素のインデックスは16進数で与えられ、
格納された要素の最下位バイトに配置されて表示されます。

 VLEN=32b

 Byte         3 2 1 0

 SEW=8b       3 2 1 0
 SEW=16b        1   0
 SEW=32b            0

 VLEN=64b

 Byte        7 6 5 4 3 2 1 0

 SEW=8b      7 6 5 4 3 2 1 0
 SEW=16b       3   2   1   0
 SEW=32b           1       0
 SEW=64b                   0

 VLEN=128b

 Byte        F E D C B A 9 8 7 6 5 4 3 2 1 0

 SEW=8b      F E D C B A 9 8 7 6 5 4 3 2 1 0
 SEW=16b       7   6   5   4   3   2   1   0
 SEW=32b           3       2       1       0
 SEW=64b                   1               0
 SEW=128b                                  0

 VLEN=256b

 Byte     1F1E1D1C1B1A19181716151413121110 F E D C B A 9 8 7 6 5 4 3 2 1 0

 SEW=8b   1F1E1D1C1B1A19181716151413121110 F E D C B A 9 8 7 6 5 4 3 2 1 0
 SEW=16b     F   E   D   C   B   A   9   8   7   6   5   4   3   2   1   0
 SEW=32b         7       6       5       4       3       2       1       0
 SEW=64b                 3               2               1               0
 SEW=128b                                1                               0

LMUL < 1の場合のマッピング

LMUL < 1 の場合、ベクトルレジスタの最初の LMUL*VLEN/SEW 要素のみが使用される。 ベクトルレジスタ内の残りのスペースはテールの一部として扱われるため、 vtaの設定に従わなければなりません。

// Example, VLEN=128b, LMUL=1/4
VLEN=128b, LMUL=1/4の例

Byte        F E D C B A 9 8 7 6 5 4 3 2 1 0

SEW=8b      - - - - - - - - - - - - 3 2 1 0
SEW=16b       -   -   -   -   -   -   1   0
SEW=32b           -       -       -       0

LMUL > 1 のマッピング

ベクトルレジスタがグループ化されると、ベクトルレジスタグループの要素は、構成するベクトルレジスタ間でストライプされます。 要素は、グループ内の各ベクトルレジスタに要素順に連続して詰められ、 各ベクトルレジスタが満たされると、グループ内の次の最高番号(訳注:ここが上手く訳せない)のベクトルレジスタに移動します。

// LMUL > 1 examples

LMUL > 1の例

 VLEN=32b, SEW=8b, LMUL=2

 Byte         3 2 1 0
 v2*n         3 2 1 0
 v2*n+1       7 6 5 4

 VLEN=32b, SEW=16b, LMUL=2

 Byte         3 2 1 0
 v2*n           1   0
 v2*n+1         3   2

 VLEN=32b, SEW=16b, LMUL=4

 Byte         3 2 1 0
 v4*n           1   0
 v4*n+1         3   2
 v4*n+2         5   4
 v4*n+3         7   6

 VLEN=32b, SEW=32b, LMUL=4

 Byte         3 2 1 0
 v4*n               0
 v4*n+1             1
 v4*n+2             2
 v4*n+3             3

 VLEN=64b, SEW=32b, LMUL=2

 Byte         7 6 5 4 3 2 1 0
 v2*n               1       0
 v2*n+1             3       2

 VLEN=64b, SEW=32b, LMUL=4

 Byte         7 6 5 4 3 2 1 0
 v4*n               1       0
 v4*n+1             3       2
 v4*n+2             5       4
 v4*n+3             7       6

 VLEN=128b, SEW=32b, LMUL=2

 Byte        F E D C B A 9 8 7 6 5 4 3 2 1 0
 v2*n              3       2       1       0
 v2*n+1            7       6       5       4

 VLEN=128b, SEW=32b, LMUL=4

 Byte          F E D C B A 9 8 7 6 5 4 3 2 1 0
 v4*n                3       2       1       0
 v4*n+1              7       6       5       4
 v4*n+2              B       A       9       8
 v4*n+3              F       E       D       C

混合幅演算でのマッピングについて

ベクトルISAは、明示的な追加再配置命令を必要とせずに、混合幅の演算をサポートするように設計されています。 異なる精度のベクトルを操作する場合、推奨されるソフトウェア戦略は、vtype を動的に変更して、 SEW/LMULを一定に保つことです(したがって、VLMAXも一定になります)。

次の例では、VLEN=128bの実装において、4つの異なるパックエレメント幅(8b、16b、32b、64b)を示しています。 ベクトルレジスタのグループ化係数(LMUL)は、各グループが同じ数のベクトル要素(この例ではVLMAX=8)を保持できるように、 相対的な要素サイズによって増加し、ストリップマイニングコードを簡素化します。

Example VLEN=128b, with SEW/LMUL=16

Byte      F E D C B A 9 8 7 6 5 4 3 2 1 0
vn        - - - - - - - - 7 6 5 4 3 2 1 0  SEW=8b, LMUL=1/2

vn          7   6   5   4   3   2   1   0  SEW=16b, LMUL=1

v2*n            3       2       1       0  SEW=32b, LMUL=2
v2*n+1          7       6       5       4

v4*n                    1               0  SEW=64b, LMUL=4
v4*n+1                  3               2
v4*n+2                  5               4
v4*n+3                  7               6

次の表は、幅が混在しているループで考えられる一定のSEW/LMULの動作点を示しています。 各列は一定のSEW/LMUL動作点を表しています。 表のエントリは、その行のデータ幅に対して、その列のSEW/LMUL値をもたらすLMUL値です。 各列のデータ幅のLMUL設定は、同じ列のLMUL設定を持つ他のデータ幅と、すべてが同じVLMAXになるように整列できることを示しています。

SEW/LMUL

1

2

4

8

16

32

64

128

256

512

1024

2048

4096

8192

SEW= 8

8

4

2

1

1/2

1/4

1/8

SEW= 16

8

4

2

1

1/2

1/4

1/8

SEW= 32

8

4

2

1

1/2

1/4

1/8

SEW= 64

8

4

2

1

1/2

1/4

1/8

SEW= 128

8

4

2

1

1/2

1/4

1/8

SEW= 256

8

4

2

1

1/2

1/4

1/8

SEW= 512

8

4

2

1

1/2

1/4

1/8

SEW=1024

8

4

2

1

1/2

1/4

1/8

LMULの設定を大きくすると、単純にベクトルの長さを長くして命令のフェッチとディスパッチのオーバーヘッドを減らすことができ、 ベクトルレジスタグループの数が少なくて済む場合にも使用できます。

注釈

より多くのアーキテクチャレジスタを有効にしていないため、有用な動作ポイントを追加していません。

LMUL > 1 かつ ELEN > VLEN のマッピング

より大きなSEWをサポートするためにベクトルレジスタがグループ化され、ELEN > VLENとなった場合、 グループ内のベクトルレジスタは連結されて1つのバイト配列となり、 グループ内で最も番号の低いレジスタが、メモリレイアウトから最も低いアドレスのバイトを保持します。

LMUL > 1 ELEN>VLEN, examples

VLEN=32b, SEW=64b, LMUL=2

Byte         3 2 1 0
v2*n               0
v2*n+1

VLEN=32b, SEW=64b, LMUL=4

Byte         3 2 1 0
v4*n               0
v4*n+1
v4*n+2             1
v4*n+3

VLEN=32b, SEW=64b, LMUL=8

Byte         3 2 1 0
v8*n               0
v8*n+1
v8*n+2             1
v8*n+3
v8*n+4             2
v8*n+5
v8*n+6             3
v8*n+7

マスクレジスタのレイアウト

ベクトルマスクは、SEWやLMULに関係なく、1つのベクトルレジスタのみを占有します。 各要素には、マスクベクトルレジスタに1つのマスクビットが割り当てられます。

注釈

0.9デザインでは、MLEN=1です。

マスク要素の場所

要素 i のマスクビットは、SEWやLMULとは関係なく、マスクレジスタのビット i に配置されます。

VLEN=32b

         Byte    3   2   1   0
LMUL=1,SEW=8b
                 3   2   1   0  Element
               [03][02][01][00] Mask bit position in decimal

LMUL=2,SEW=16b
                     1       0
                   [01]    [00]
                     3       2
                   [03]    [02]

LMUL=4,SEW=32b               0
                           [00]
                             1
                           [01]
                             2
                           [02]
                             3
                           [03]
LMUL=2,SEW=8b
                 3   2   1   0
               [03][02][01][00]
                 7   6   5   4
               [07][06][05][04]

LMUL=8,SEW=32b
                             0
                           [00]
                             1
                           [01]
                             2
                           [02]
                             3
                           [03]
                             4
                           [04]
                             5
                           [05]
                             6
                           [06]
                             7
                           [07]

LMUL=8,SEW=8b
                 3   2   1   0
               [03][02][01][00]
                 7   6   5   4
               [07][06][05][04]
                 B   A   9   8
               [11][10][09][08]
                 F   E   D   C
               [15][14][13][12]
                13  12  11  10
               [19][18][17][16]
                17  16  15  14
               [23][22][21][20]
                1B  1A  19  18
               [27][26][25][24]
                1F  1E  1D  1C
               [31][30][29][28]

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

ベクトル拡張の命令は、既存の2つのメジャーオペコード(LOAD-FP、STORE-FP)と1つの新しいメジャーオペコード(OP-V)に当てはまります。

ベクトルのロードとストアは、スカラ浮動小数点のロードとストアのメジャーオペコード(LOAD-FP/STORE-FP)の中にエンコードされます。 ベクトルロード/ストアのエンコーディングは、標準的なスカラ浮動小数点ロード/ストアの12ビット即値フィールドの一部を再利用して、 さらにベクトル命令のエンコーディングを行い、ビット25には標準的なベクトルマスクビット ( マスクエンコーディング を参照)を格納します。

include::vmem-format.adoc[]

include::valu-format.adoc[]

include::vcfg-format.adoc[]

ベクトル命令は、スカラまたはベクトルのソースオペランドを持ち、 スカラまたはベクトルの結果を生成することができ、 ほとんどのベクトル命令は、無条件またはマスクの下で条件付きで実行することができます。

ベクトルのロードとストアは、ベクトルのレジスタ要素とメモリの間でビットパタンを移動させます。 ベクトル演算命令は、ベクトルレジスタ要素に保持された値を演算します。

スカラオペランド

スカラオペランドは即値、または x レジスタ、f レジスタ、またはベクトルレジスタの要素 0 から取得することができます。 スカラの結果は x または f レジスタ、またはベクトルレジスタの要素 0 に書き込まれます。 現在の LMUL の設定に関わらず、どのベクトルレジスタもスカラを保持するために使用できます。

注釈

f レジスタをオーバーレイしないことで、ベクトルレジスタが圧迫させないようにし、 標準的な呼び出し規則との相互作用を避け、高性能なスカラ浮動小数点の設計を簡素化し、Zfinx ISA オプションとの互換性を実現します。 fv を重ねると、実装によってはステート・ビット数を減らせるというメリットがありますが、 高性能な設計が複雑になり、Zfinx ISAオプションとの互換性もなくなります。

ベクトルオペランド

各ベクトルオペランドは、ベクトルレジスタグループ内のすべての要素のサイズと位置を決定するために使用される effective element width (EEW) と effective LMUL (EMUL)を持っています。 デフォルトでは、ほとんどの命令のほとんどのオペランドで、EEW=SEW、EMUL=LMULとなります。

ベクトル命令の中には、ソースと書き込みベクトルオペランドの要素数が同じでも幅が異なるものがあり、 その場合、EEWとEMULはそれぞれSEWとLMULと異なりますが、EEW/EMUL = SEW/LMULとなります。 例えば、Widening演算命令の多くは、ソースグループがEEW=SEW、EMUL=LMULで、 書き込みグループがEEW=2*SEW、EMUL=2*LMULとなっています。 Narrowing命令は、ソースオペランドはEEW=2*SEW、EMUL=2*LMULですが、 書き込みレジスタはEEW=SEW、EMUL=LMULです。

ベクトルオペランドまたは演算結果は、EMULに応じて1つまたは複数のベクトルレジスタを占めることがありますが、 常にグループ内で最も低い番号のベクトルレジスタを使用して指定されます。 ベクトルレジスタグループの指定に最下位のベクトルレジスタ以外を使用するエンコーディングは予約されています。

書き込みベクトルレジスタグループは、次のいずれかが成立する場合に限り、 ソースベクトルレジスタグループとオーバーラップすることができます。

  • 書き込みレジスタのEEWとソースのEEWが等しい。

  • 書き込みレジスタのEEWがソースのEEWよりも小さく、オーバーラップする部分がソースのレジスタグループの最も低い番号の部分である(例えば、LMUL=1の場合、 vnsrl.wi v0, v0, 3 は合法だが、v1 の書き込みは合法ではない)。

  • 書き込みレジスタのEEWがソースのEEWよりも大きく、ソースのEMULが少なくとも1であり、オーバーラップが書き込みレジスタグループの最も高い番号の部分にある場合(例えば、LMUL=8の場合、 vzext.vf4 v0, v6 は合法ですが、ソースの v0v2v4 は合法ではない)。

レジスタグループのオーバーラップ制約のために、マスク要素はEEW=1となります。

ある命令で使用される最大のベクトルレジスタグループは、8個以上のベクトル・レジスタであってはならず(すなわち、EMUL{le}8)、 ベクトル命令が8個以上のベクトルレジスタグループを必要とする場合には、その命令エンコーディングは予約されます。 例えば、LMUL=8のときにWideringされたベクトルレジスタ群の結果を得るWidening演算は、EMUL=16の結果を意味するため、予約されます。

Wideningされたスカラ値(Wideningリダクション演算の結果など)は、 ベクトルレジスタの最初の要素に保持され、EMUL=1となる。

注釈

暗黙のうちにEMULが1となるため、wide スカラリダクションの結果を保持するためにベクトルレジスタグループを使用することはできません。 この場合、スカラリダクション要素のEMULを指定する独立したパラメータが必要になります。

ベクトルマスキング

マスキングは多くのベクトル命令でサポートされています。 マスクオフされた(非アクティブな)要素の操作は、例外を発生させません。 マスクオフされた要素に対応する書き込みベクトルレジスタの要素は、vtypevma ビットの 設定に応じて、mask-undisturbedまたはmask-agnosticのいずれかのポリシで処理されます(セクション Tail Agnostic とVector Mask Agnostic vta と vma )。

マスクされたベクトル命令の実行を制御するために使用されるマスク値は、 常にベクトルレジスタ v0 によって提供されます。

注釈

より長い命令エンコーディングを提供するかもしれません。

マスクド・ベクトル命令の書き込みベクトルレジスタグループは、書き込みベクトルレジスタにマスク値(比較など)やリダクションのスカラ結果が書き込まれていない限り、 ソースマスクレジスタ(v0)とオーバーラップすることはできません。 これらの命令エンコーディングは予約済みです。

注釈

例えば、 vadd.vv v0, v1, v2, v0.m は、以前は LMUL=1 の場合には合法でしたが、現在は常に違法です。

作業用マスクの値を保持するために他のベクトルレジスタを使用することができ、 述語計算を行うためのマスクベクトル論理演算が提供されています。 .. _sec-mask-vector-logical:を参照してください。

Tail Agnostic とVector Mask Agnostic vta と vma で規定されているように、マスクの書き込み値は vta の設定にかかわらず、 常に tail-agnostic として扱われます。

マスクエンコーディング

マスキングが可能な場合は、命令内の1ビットの vm フィールドにエンコードされます( inst[25] )。

vm

説明

0

ベクトル演算の結果は v0.mask[i]=1の領域にのみ書き込まれる

1

マスクされない

注釈

v0 を使った真と補填マスキングと、スカラ演算の符号化を行っていました。

ベクトルのマスキングはアセンブラのコードでは別のベクトルオペランドとして表現され、.tv0.mask[i]1 のときに演算が行われるかどうかを示します。 マスキングオペランドが指定されていない場合は、ベクトル実行はマスクされていない(vm=1)とされます。

vop.v*    v1, v2, v3, v0.t  # マスク有効、v0.mask[i]=1の部分がマスクされる
vop.v*    v1, v2, v3        # マスク無効

注釈

アセンブリ構文では、マスクレジスタ指定子を追加し、真のマスキングと負のマスキングの両方をサポートする可能性のある将来の拡張と互換性を持たせるために、完全な文法を書き出します。 マスキングオペランドの接尾辞 .t は、マスクの使用を視覚的に符号化するのにも役立ちます。

注釈

v0.mask[i] のように文章中にマスクベクトルに添え字として使用されるだけです。

プリスタート、アクティブ、非アクティブ、ボディ、末尾要素の定義

ベクトル命令の実行時に操作される出力要素のインデックスは、3つのサブセットに分けられます。

  • プリスタート 要素は、要素のインデックスが vstart レジスタの初期値よりも小さいものです。

プリスタート要素は、例外を発生させず、書き込みベクトルレジスタも更新しません。

  • ボディ 要素は、要素のインデックスが vstart レジスタの初期値以上で、

vl の現在のベクトル長設定よりも小さいものです。ボディは2つの分離したサブセットに分割することができます。

** ベクトル命令の実行中の アクティブ 要素は、ボディ内の要素で、 その要素位置で現在のマスクが有効になっているところです。 アクティブな要素は、例外を発生させたり、書き込みベクトルレジスタグループを更新することができます。

** 非アクティブ 要素は、ボディ内の要素で、その要素の位置で現在のマスクが無効になっている要素です。 非アクティブな要素は、 masked agnostic が指定されていない限り (`vtype.vma`=1)、 例外を発生させず、書き込みベクトルレジスタグループを更新しません。 この場合、非アクティブな要素は 1 で上書きされる可能性があります。

  • ベクトル命令実行中の 末尾 要素は、vl で指定された現在のベクトル長設定を超えた要素です。

末尾要素は例外を発生させず、Tail Agunostics指定されていない限り (`vtype.vta`=1)、 書き込みベクトルレジスタグループを更新しません。 この場合、末尾要素は 1 で上書きされるか、マスクロードを除くマスク生成命令の場合は命令の結果で上書きされる可能性があります。 LMUL < 1の場合、末尾には同じベクトルレジスタに保持されているVLMAX以降の要素が含まれます。

for element index x
prestart(x) = (0 <= x < vstart)
body(x)     = (vstart <= x < vl)
tail(x)     = (vl <= x < max(VLMAX,VLEN/SEW))
mask(x)     = unmasked || v0.mask[x] == 1
active(x)   = body(x) && mask(x)
inactive(x) = body(x) && !mask(x)

vstart {ge} vl のとき、ボディの要素はなく、どの書き込みベクトルレジスタグループの要素も更新されず、 これは末尾要素がagnosticな値で更新されないことも含みます。

注釈

書き込みベクトルレジスタグループはAgnosticな要素を含めて、いかなる要素も更新されません。

x レジスタや f レジスタを書き込む命令は、 vl =0のときも含めて、vstart {ge} vl のときにも実行されます。

注釈

vl または VLMAX を超えるインデックスを読み取ることがあります。 一般的なポリシは、インデックスがソースベクトルレジスタグループのVLMAXよりも大きい場合、値0を返します。

コンフィグレーション設定命令 (vsetvli/vsetivl/vsetvl)

多数の要素を処理するための一般的なアプローチの一つに、ループの各イタレーションでいくつかの要素を処理し、 すべての要素が処理されるまでイタレーションを続ける"ストリップマイニング"があります。 RISC-Vのベクトル仕様では、この手法を直接かつポータブルにサポートしています。 アプリケーションは、処理する要素の総数(アプリケーションベクトル長、AVL)を vl の候補値として指定し、 ハードウェアは、マイクロアーキテクチャの実装と vtype の設定に基づいて、 ハードウェアが反復ごとに処理する要素数( vl に格納されている) を、汎用レジスタを介して応答します。 example-stripmin-sew に示されている簡単なループ構造は、コードが残りの要素数とハードウェアが処理する1回あたりの量を簡単に追跡していることを示しています。

アプリケーションのニーズに合わせて vlvtype の値を迅速に設定できるように、一連の命令が提供されています。 vset{i}vl{i} 命令は、その引数に基づいて、vtypevl の CSR を設定し、rdvl の新しい値を書き込みます。

vsetvli rd, rs1, vtypei   # rd = new vl, rs1 = AVL, vtypei = new vtype setting
vsetivli rd, uimm, vtypei # rd = new vl, uimm = AVL, vtypei = new vtype setting
vsetvl  rd, rs1, rs2      # rd = new vl, rs1 = AVL, rs2 = new vtype value

include::vcfg-format.adoc[]

vtype エンコーディング

include::vtype-format.adoc[]

新しい vtype の設定は、 vsetvlivsetivli の即時フィールド、および vsetvlrs2 レジスタにエンコードされます。

 vset{i}vli の即値vtipeiで提案されるアセンブラ名

 e8    # SEW=8b
 e16   # SEW=16b
 e32   # SEW=32b
 e64   # SEW=64b
 e128  # SEW=128b
 e256  # SEW=256b
 e512  # SEW=512b
 e1024 # SEW=1024b

 mf8  # LMUL=1/8
 mf4  # LMUL=1/4
 mf2  # LMUL=1/2
 m1   # LMUL=1, mの設定を省略した場合
 m2   # LMUL=2
 m4   # LMUL=4
 m8   # LMUL=8

:
    vsetvli t0, a0, e8          # SEW= 8, LMUL=1
    vsetvli t0, a0, e8, m2      # SEW= 8, LMUL=2
    vsetvli t0, a0, e32, mf2    # SEW=32, LMUL=1/2

vsetvl の動作は、rs2 から vtype の値を受け取ることと、 コンテキストの復元に使えることを除いて、vsetvli と同様になります。

vtype の設定が実装でサポートされていない場合には、vtypevill ビットが設定され、 vtype の残りのビットは 0 に設定され、vl レジスタも 0 に設定されます。

注釈

しかし、これはISAへのCSRの書き込み時に最初のデータ依存の例外を追加することになりました。 実装では、 vill を設定する代わりに、 vtype に不正な値が書き込まれたときに例外することを選択して、 エミュレーションで新しい構成をサポートできるようにして、将来の互換性を確保することができます。 現在のスキームは、ある設定に対して vill がクリアされているかどうかをチェックすることで、 サポートされているベクトルユニットの設定をランタイムに軽く照会することをサポートしています。

AVLのエンコーディング

新しいベクトル長の設定はAVLに基づいており、 vsetvlivsetvl では、 rs1rd のフィールドに以下のようにエンコードされます。

rd

rs1

AVL値

vl を更新する

!x0

x[rs1] の値

通常のストリップマイニング

!x0

x0

~0

vl を VLMAXに設定する

x0

x0

vl レジスタの値

vl をキープする(もちろん、 vtype は変更される)

rs1x0 でない場合、AVL は rs1 で指定された x レジスタに保持される符号なし整数となり、 新しい vl 値も rd で指定された x レジスタに書き込まれます。

rs1=x0 であるが、 rd!=x0 のときは、符号なし整数の最大値 (~0) が AVL として使用され、 結果として VLMAX が vl に書き込まれ、 rd で指定された x レジスタにも書き込まれます。

rs1=x0 かつ rd=x0 の場合、この命令は vl の現在のベクトル長をAVLとして使用し、 結果の値は vl に書き込まれますが、書き込みレジスタには書き込まれません。 この形式はVLMAXの場合にのみ使用でき、したがって vl は新しいSEW/LMUL比によって実際には変更されません。 VLMAXの変更をもたらすような新しいSEW/LMUL比率の命令の使用は予約済みです。 この場合、実装では vill を設定することができます。

注釈

この設計は、現在の vtype 設定に対して vl が常に正当な値を保持するように選択されました。 現在の vl 値は vl CSR から読み取ることができます。 新しいSEW/LMUL比率によってVLMAXが縮小する場合、この命令によって vl 値が減少する可能性がありますが、 これが一般的に有用な動作であることは明らかではないため、このケースは留保されています。 また、実装は、マイクロアーキテクチャを最適化するために、この命令によって vl が変更されないと仮定することができます。

vsetivli 命令では、AVLは rs1 フィールドの 5ビットのゼロ拡張即時値(0~31)としてエンコードされます。

vsetivli 命令は、ベクトルサイズが小さく、ベクトルレジスタ内に収まることがわかっているため、 ストリップマイニングのオーバーヘッドが不要な場合に、よりコンパクトなコードを提供します。

vl 設定の制約

vset{i}vl{i} 命令は、まず引数の vtype にしたがってVLMAXを設定し、 次に以下の制約にしたがって vl を設定します。

  • AVL {le} VLMAX のときは vl = AVL

  • AVL W (2 * VLMAX) のときは ceil(AVL / ) {le} vl {le} VLMAX

  • AVL {ge} (2 * VLMAX) のときは vl = VLMAX

  • 同一の入力AVLおよびVLMAX値に対して、任意の実装で決定される

  • これらの具体的な特性は、事前のルールから導かれます。

  • AVL = 0 なら vl = 0

  • AVL > 0 なら vl > 0

  • vl {le} VLMAX

  • vl {le} AVL

  • vl から読み込んだ値を vset{i}vl{i} の AVL 引数として使用すると、vl 内の同じ値になります。 ただし、結果として得られる VLMAX が vl が読み込まれた時点での VLMAX の値と同じであることが条件です。

[NOTE] -- vl の設定ルールは、AVL {le} VLMAX では、レジスタの流出やコンテキストの入れ替えがあっても vl の動作を維持できるよう、 十分に厳密に設計されています。しかし、 AVL > VLMAX の場合は、ベクトルレーンの使用率を向上させることができる柔軟性を備えています。 例えば、 VLMAX < AVL < 2*VLMAX の場合、vl = ceil(AVL / 2) と設定することで、ストリップマイニングループの最後の2回の反復に作業を均等に分散させることができます。 要件2は、 AVL < 2*VLMAX の場合であっても、リダクションループの最初のストリップミン反復では、 すべての反復の中で最大のベクトル長を使用することを保証する。 これにより、ソフトウェアは、ストリップマイニングループで観測されたベクトル長の実行最大値を明示的に計算する必要がなくなります。 また、要件2では、 VLMAX < AVL < 2*VLMAX の場合、vlをVLMAXに設定することができます。

--

ストリップマイニングとSEW変更の例

SEWとLMULの設定を動的に変更することで、1つのループで幅が混在するオペレーションでも高い処理能力を発揮します。 ..

# Example: Load 16-bit values, widen multiply to 32b, shift 32b result # right by 3, store 32b values. # On entry: # a0 holds the total number of elements to process # a1 holds the address of the source array # a2 holds the address of the destination array

loop:
vsetvli a3, a0, e16, m4, ta, ma # vtype = 16-bit integer vectors;

# also update a3 with vl (# of elements this iteration)

vle16.v v4, (a1) # Get 16b vector slli t1, a3, 1 # Multiply # elements this iteration by 2 bytes/source element add a1, a1, t1 # Bump pointer vwmul.vx v8, v4, x10 # Widening multiply into 32b in <v8--v15>

vsetvli x0, x0, e32, m8, ta, ma # Operate on 32b values vsrl.vi v8, v8, 3 vse32.v v8, (a2) # Store vector of 32b elements slli t1, a3, 2 # Multiply # elements this iteration by 4 bytes/destination element add a2, a2, t1 # Bump pointer sub a0, a0, a3 # Decrement count by vl bnez a0, loop # Any more?

# 例: 16ビットの値をロードし、32ビットに拡張し乗算を行い、
# 結果の32ビットを3ビット右にシフトし、結果の32ビットをストアする
# プログラムの先頭では:
#  a0は処理を行う全体の要素数を保持している
#  a1はソース配列のアドレスを保持している
#  a2は書き込み配列のアドレスを保持している
loop:
    vsetvli a3, a0, e16, m4, ta, ma  # vtype = 16-bit 整数ベクトル
                                     # a3をvlに更新する(個のイタレーションにおける要素の個数)
    vle16.v v4, (a1)        # 16ビットのベクトルを取得する
    slli t1, a3, 1          # このイタレーションで処理する要素の個数から要素の2バイト数を計算する
    add a1, a1, t1          # ポインタを進める
    vwmul.vx v8, v4, x10    # v4の値を32ビットに拡張して<v8--v15>に格納する

    vsetvli x0, x0, e32, m8, ta, ma  # 32ビット操作に変更する
    vsrl.vi v8, v8, 3
    vse32.v v8, (a2)        # 32ビットの値をベクトルにストアする
    slli t1, a3, 2          # このイタレーションで処理する要素の個数から要素の4バイト数を計算する
    add a2, a2, t1          # ポインタを進める
    sub a0, a0, a3          # vlだけカウンタを減少させる
    bnez a0, loop           # これ以上処理する?

ベクトルロード・ストア命令

ベクトルのロードとストアは、ベクトルレジスタとメモリの間で値を移動させます。 ベクトルロードとストアはマスクされ、非アクティブな要素で例外を発生させません。 マスク付きベクトルロード命令は、マスク付きAgnostics (vtype.vma`=1) が指定されていない限り、 書き込みベクトルレジスタグループの非アクティブな要素を更新しません。 マスク付きベクトルストアは、アクティブなメモリ要素のみを更新します。 すべてのベクトルロードとストアは、ゼロではない `vstart 値を生成して受け入れることができます。

ベクトルロードストア命令のエンコーディング

include::vmem-format.adoc[]

ベクトルメモリユニットストライドおよびコンスタントストライド操作では、転送するデータのEEWを命令内で直接静的にエンコードすることで、 幅が混在するルーチンでメモリをアクセスする際の vtype の変更回数を減らすことができます。 インデックス付き演算では、命令内の明示的なEEWエンコーディングにより、 使用するインデックスのサイズを設定し、SEW/LMULによりデータ幅を指定します。

ベクトルロードストアアドレッシングモード

ベクトル拡張は、ユニットストライド、ストライド、インデックス(スキャッター/ギャザー)のアドレッシングモードをサポートしています。 ベクトルのロード/ストアベースレジスタとストライドは、GPRの x レジスタから取得されます。

すべてのベクトルアクセスのベースとなる実効アドレスは、 rs1 で指定された x レジスタの内容で与えられます。

ベクトルのユニットストライド演算は、ベース有効アドレスからメモリ内に連続して格納されている要素をアクセスします。

ベクトルの定数ストライド演算では、ベース実効アドレスで最初のメモリ要素をアクセスし、 その後、 rs2 で指定される x レジスタに含まれるバイトオフセットで与えられるアドレス増分で後続の要素をアクセスします。

ベクトルインデックス演算では、 vs2 で指定されたベクトルオフセットオペランドの各要素の内容をベース実効アドレスに加算し、 各要素の実効アドレスを得ることができます。 データベクトルレジスタ群は、EEW=SEW、EMUL=LMUL、オフセットベクトルレジスタ群は、 命令内でEEW符号化、EMUL=(EEW/SEW)*LMULとなります。

ベクトル・オフセット・オペランドは、バイトアドレス・オフセットのベクトルとして扱われます。

注釈

この場合、vs2 ベクトルはオブジェクトのベースへのポインタを保持し、スカラ x レジスタは各オブジェクト内のメンバ・フィールドのオフセットを保持します。 このケースをサポートすることが、要素のインデックスをデータEEWでスケーリングするインデックス付き演算が定義されなかった理由です。

ベクトルオフセットの要素がXLENより狭い場合は、ベースの実効アドレスに追加する前にXLENまでゼロ拡張されます。 ベクトルオフセット要素の幅がXLENよりも広い場合は、アドレスの計算に最下位のXLENビットが使用されます。 EEWがオフセット要素に対してサポートされていない場合、実装は不正な命令例外を発生させることができます。

ベクトルアドレッシングモードは、2ビットの mop[1:0] フィールドを使ってエンコードされます。

ベクトルのユニットストライドおよびコンスタントストライドのメモリアクセスでは、個々の要素のアクセス間の順序付けは保証されません。 ベクトルのインデックス付きロードおよびストアのメモリ操作には、順序付きと非順序付きの2つの形式があります。 indexed-ordered の場合は、メモリアクセス時の要素の順序を保持します。

順序なしの命令(mop!=11)では、要素アクセスの順序は保証されません。 強く順序付けられたIO領域へのアクセスの場合、要素のアクセスはどのような順序でも開始できます。

注釈

順序付けられたインデックス付き命令を使用する必要があります。

精密なベクトル例外を備えた実装では、 インデックス付きの非順序型ストアの例外も精密でなければなりません。

追加のユニットストライドベクトルアドレッシングモードは、 ユニットストライドロード命令およびストア命令のエンコーディングにおいて、 それぞれ5ビットの lumop および sumop フィールドにエンコードされます。

nf[2:0] フィールドは、各セグメントのフィールドの数をエンコードします。 通常のベクトルロード/ストアでは、 nf`=0で、各要素の位置でベクトルレジスタグループとメモリーの間で1つの値が移動することを示します。 より大きな値の `nf フィールドは、後述の ベクトルロードストアセグメント命令 項で説明するように、 セグメント内の複数の連続したフィールドにアクセスするために使用されます。

注釈

アドレスオフセットフィールドのための同じビットの使用に取って代わりました。 セグメントロード/ストアは、メモリとの間でアイテムを移動するためのより強力なプリミティブを追加する一方で、 オフセットは単一のスカラ整数の計算で置き換えることができます。

また、 nf[2:0] フィールドは、全体ベクトルレジスタの ロード/ストア命令で転送する全体ベクトルレジスタの数をエンコードします。

ベクトルロードストア幅のエンコーディング

ベクトルのロードとストアは、命令に直接EEWがエンコードされています。 対応するEMULはEMUL = (EEW/SEW)*LMULとして計算されます。 EMULが範囲外(EMUL>8またはEMUL<1/8)になる場合は、命令のエンコーディングは予約されます。 ベクトルレジスタグループには、選択されたEMULに対応する正当なレジスタ指定子がなければならず、 それ以外の命令エンコーディングは予約済みとみなされます。

ベクトルユニットストライドおよび定数ストライドでは、データ値に命令でエンコードされたEEW/EMULを使用し、 ベクトルインデックスロードおよびストアでは、インデックス値に命令でエンコードされたEEW/EMULを使用し、 データ値に vtype でエンコードされたSEW/LMULを使用します。

ベクトルのロード・ストアは、標準的なスカラ浮動小数点の ロード・ストアが明示していない幅の値を使ってエンコードされます。

mew ビット(inst[28])は、128ビット以上の拡張メモリサイズをエンコードするために使用されることが期待されますが、 これらのエンコードは現時点では 予約 です。

サポートされているすべてのSEW設定のEEWのベクトルロード/ストアは、実装で提供されなければなりません。 サポートされていないEEW幅のベクトルロード・ストアエンコーディングは予約済みです。

Mem bits は、メモリにアクセスされる各要素のサイズです。

Data reg bits は、レジスタにアクセスされる各データ要素のサイズです。

Index bits は、レジスタにアクセスされる各インデックスのサイズです。

64b以上のデータおよびインデックスビットのEEWエンコーディングは現在予約済みです。

ベクトルユニットストライド命令

# ベクトルユニットストライドロードストア命令

# vd は書き込みレジスタ, rs1 はベースアドレス, vm はマスクエンコーディング (v0.t or <missing>)
vle8.v    vd, (rs1), vm  #    8-bit ユニットストライドロード
vle16.v   vd, (rs1), vm  #   16-bit ユニットストライドロード
vle32.v   vd, (rs1), vm  #   32-bit ユニットストライドロード
vle64.v   vd, (rs1), vm  #   64-bit ユニットストライドロード
# vle128.v  vd, (rs1), vm  #  128-bit ユニットストライドロード、予約済み
# vle256.v  vd, (rs1), vm  #  256-bit ユニットストライドロード、予約済み
# vle512.v  vd, (rs1), vm  #  512-bit ユニットストライドロード、予約済み
# vle1024.v vd, (rs1), vm  # 1024-bit ユニットストライドロード、予約済み

# vs3はストアデータ, rs1はベースアドレス, vmはマスクエンコーディング (v0.t or <missing>)
vse8.v    vs3, (rs1), vm  #    8-bit ユニットストライドストア
vse16.v   vs3, (rs1), vm  #   16-bit ユニットストライドストア
vse32.v   vs3, (rs1), vm  #   32-bit ユニットストライドストア
vse64.v   vs3, (rs1), vm  #   64-bit ユニットストライドストア
# vse128.v  vs3, (rs1), vm  #  128-bit ユニットストライドストア、予約済み
# vse256.v  vs3, (rs1), vm  #  256-bit ユニットストライドストア、予約済み
# vse512.v  vs3, (rs1), vm  #  512-bit ユニットストライドストア、予約済み
# vse1024.v vs3, (rs1), vm  # 1024-bit ユニットストライドストア、予約済み

マスク値をメモリとの間で転送するために、ユニットストライドのロード/ストアが追加されました。 これは、実効ベクトル長が evl``=ceil(``vl/8) (つまりEMUL=1)であることと、 転送先のレジスタが常にテールアグノスティックポリシで書き込まれることを除けば、 マスクなしのバイトロード/ストア(EEW=8)と同じ動作をします。

# ベクトルユニットストライドマスクロード命令
vlm.v vd, (rs1)   #  ceil(vl/8)バイト長だけバイトデータをロードする

# ベクトルユニットストライドマスクストア命令
vsm.v vs3, (rs1)  #  ceil(vl/8)バイト長だけバイトデータをストアする

vlm.vvsm.v は、vle8.vvse8.v と同様に width[2:0]`=0 でエンコードされますが、 `lumopsumop のエンコードが異なることで区別されます。 vlm.vvsm.v はバイトロードとストアとして動作するので、 これらの命令では vstart はバイト単位になります。

注釈

これらの命令と他の要素のロード/ストア命令で長さの扱いが異なるため、混乱を招きました。 ソフトウェアの混乱を避けるために、これらの古いアセンブラニーモニックはエイリアスとして残されています。

注釈

データパス間の配線を減らすためにデータを内部で再配置するマシンをサポートすることです。 また、 vl を変更する必要がないため、マスクのスピル/フィルのコストを削減することができます。

ベクトルストライド命令

# ベクトルストライドロードストア命令

# vdは書き込みレジスタ, rs1はベースレジスタ, rs2はバイトストライド
vlse8.v    vd, (rs1), rs2, vm  #    8-bit ストライドロード命令
vlse16.v   vd, (rs1), rs2, vm  #   16-bit ストライドロード命令
vlse32.v   vd, (rs1), rs2, vm  #   32-bit ストライドロード命令
vlse64.v   vd, (rs1), rs2, vm  #   64-bit ストライドロード命令
# vlse128.v  vd, (rs1), rs2, vm  #  128-bit ストライドロード命令、予約済み
# vlse256.v  vd, (rs1), rs2, vm  #  256-bit ストライドロード命令、予約済み
# vlse512.v  vd, (rs1), rs2, vm  #  512-bit ストライドロード命令、予約済み
# vlse1024.v vd, (rs1), rs2, vm  # 1024-bit ストライドロード命令、予約済み

# vs3 store data, rs1 base address, rs2 byte stride
vsse8.v    vs3, (rs1), rs2, vm  #    8-bit ストライドストア命令
vsse16.v   vs3, (rs1), rs2, vm  #   16-bit ストライドストア命令
vsse32.v   vs3, (rs1), rs2, vm  #   32-bit ストライドストア命令
vsse64.v   vs3, (rs1), rs2, vm  #   64-bit ストライドストア命令
# vsse128.v  vs3, (rs1), rs2, vm  #  128-bit ストライドストア命令、予約済み
# vsse256.v  vs3, (rs1), rs2, vm  #  256-bit ストライドストア命令、予約済み
# vsse512.v  vs3, (rs1), rs2, vm  #  512-bit ストライドストア命令、予約済み
# vsse1024.v vs3, (rs1), rs2, vm  # 1024-bit ストライドストア命令、予約済み

負の数のストライドとゼロストライドに対応しています。

ストライド命令内の要素アクセスは、互いに順序付けられていません。

rs2`=`x0 の場合、実装はアクティブな要素の数よりも少ないメモリ操作を実行することが許されますが、必須ではありません。 また、同じ静的に同じ命令の異なる動的な実行において、異なる数のメモリ操作を実行することができます。

注釈

即時ストライドが 0 のときに rs2 に x0 形式を使用しないように、 コンパイラーは注意しなければなりません。

rs2!=x0x[rs2]=0 の場合、実装はアクティブな要素ごとに1回のメモリアクセスを 行わなければなりません(ただし、これらのアクセスは順序付けられません)。

注釈

順序付きインデックス操作を使用することができます。

ベクトルインデックス命令

# ベクトルインデックスロードストア命令

# ベクトル順序無しインデックスロード命令
# vdは書き込みベクトルレジスタ, rs1はベースアドレス, vs2はインデックス
vluxei8.v    vd, (rs1), vs2, vm  # unordered  8-bit SEWデータのインデックスロード命令
vluxei16.v   vd, (rs1), vs2, vm  # unordered 16-bit SEWデータのインデックスロード命令
vluxei32.v   vd, (rs1), vs2, vm  # unordered 32-bit SEWデータのインデックスロード命令
vluxei64.v   vd, (rs1), vs2, vm  # unordered 64-bit SEWデータのインデックスロード命令

# ベクトル順序付きインデックスロード命令
# vdは書き込みベクトルレジスタ, rs1はベースアドレス, vs2はインデックス
vloxei8.v    vd, (rs1), vs2, vm  # ordered  8-bit SEWデータのインデックスロード命令
vloxei16.v   vd, (rs1), vs2, vm  # ordered 16-bit SEWデータのインデックスロード命令
vloxei32.v   vd, (rs1), vs2, vm  # ordered 32-bit SEWデータのインデックスロード命令
vloxei64.v   vd, (rs1), vs2, vm  # ordered 64-bit SEWデータのインデックスロード命令

# ベクトル順序無しインデックスストア命令
# vs3はストアデータ, rs1はベースアドレス, vs2はインデックス
vsuxei8.v   vs3, (rs1), vs2, vm # unordered  8-bit SEWデータのインデックスストア命令
vsuxei16.v  vs3, (rs1), vs2, vm # unordered 16-bit SEWデータのインデックスストア命令
vsuxei32.v  vs3, (rs1), vs2, vm # unordered 32-bit SEWデータのインデックスストア命令
vsuxei64.v  vs3, (rs1), vs2, vm # unordered 64-bit SEWデータのインデックスストア命令

# ベクトル順序付きインデックスストア命令
# vs3はストアデータ, rs1はベースアドレス, vs2はインデックス
vsoxei8.v    vs3, (rs1), vs2, vm  # ordered  8-bit SEWデータのインデックスストア命令
vsoxei16.v   vs3, (rs1), vs2, vm  # ordered 16-bit SEWデータのインデックスストア命令
vsoxei32.v   vs3, (rs1), vs2, vm  # ordered 32-bit SEWデータのインデックスストア命令
vsoxei64.v   vs3, (rs1), vs2, vm  # ordered 64-bit SEWデータのインデックスストア命令

注釈

静的にエンコードされたEEWがデータではなくインデックスであることを示すために、 ``e``**x** の代わりに ``ei``**x** を使用しています。

注釈

他のベクトルアドレッシングモードには文字がありません。 この方法は、一貫性に欠けるかもしれませんが、VSXEIが以前は"順序付き"を意味していたように、 既存のソフトウェアの混乱を最小限に抑えることができます。 また、移行中にオペコードを別名として保持することで、ソフトウェアの解約を減らすことができます。

ユニットストライドFault-Only-Firstロード

ユニットストライドfault-only-first load命令は、データに依存した終了条件を持つループ("while "ループ)をベクトル化するために使用されます。 これらの命令は、要素0で発生した同期例外による例外のみを取得することを除いて、 通常のロードと同様に実行されます。 要素 > 0 で例外が発生した場合、対応する例外は取られず、 ベクトル長 vl は例外が発生したであろう要素のインデックスに縮小されます。

ロード命令は、例外が報告された要素のインデックスを超えて、アクティブな書き込みベクトルレジスタグループの要素を上書きする可能性があります。 同様に、fault-only-firstのロード命令では、書き込みレジスタの要素が、ベクトルの長さを切り詰める原因となる要素を超えて更新されることがあります(ただし、元のベクトルの長さを超えることはありません)。 これらの疑似更新の値は、アドレスされたメモリ位置のメモリ内の値と一致する必要はありません。 非占有のメモリ位置は、対応する要素のロード操作が例外やベクトル長のトリミングによって再起動されないことがわかっている場合にのみアクセスできます。

# ベクトルユニットストライドfault-only-firstロード

# vdは書き込みレジスタ, rs1はベースアドレス, vmはマスクエンコーディング (v0.t もしくは<指定なし>)
vle8ff.v    vd, (rs1), vm  #    8-bit ユニットストライドfault-only-firstロード
vle16ff.v   vd, (rs1), vm  #   16-bit ユニットストライドfault-only-firstロード
vle32ff.v   vd, (rs1), vm  #   32-bit ユニットストライドfault-only-firstロード
vle64ff.v   vd, (rs1), vm  #   64-bit ユニットストライドfault-only-firstロード
# vle128ff.v  vd, (rs1), vm  #  128-bit ユニットストライドfault-only-firstロード(予約)
# vle256ff.v  vd, (rs1), vm  #  256-bit ユニットストライドfault-only-firstロード(予約)
# vle512ff.v  vd, (rs1), vm  #  512-bit ユニットストライドfault-only-firstロード(予約)
# vle1024ff.v vd, (rs1), vm  # 1024-bit ユニットストライドfault-only-firstロード(予約)
ユニットストライドfault-only-first命令によるstrlenの例

include::example/strlen.s[lines=4..-1]

注釈

セキュリティ上の懸念があります。 ストライドおよびスキャッター/ギャザーのfault-on-firstロード命令は、エンコーディング空間がないため提供されていません。 また、より大きなセキュリティ全体となる可能性があり、ソフトウェアは例外を経験することなく、 複数のランダムなページのアクセス性を簡単にチェックすることができます。 ユニットストライド版では、既知の領域とすぐに隣接する領域のプロービングしかできないため、セキュリティに大きな影響はありません。 将来のベクトル拡張では、非連続アクセスの fault-only-first を可能にするセキュリティ緩和策が実装される可能性があります。

例外が発生しない場合でも、実装では vl より少ない要素を処理し、それに応じて vl を減らすことが許可されていますが、 vstart`=0 かつ `vl>0 の場合は、少なくとも 1 つの要素を処理する必要があります。

fault-on-firstロード命令が割り込みによる例外を発生する場合、 実装は vl を削減せず、代わりに vstart の値を設定する必要があります。

注釈

実装は vl を減らすのではなく、イベントが失われる可能性があるため、 デバッグ・例外をトリガーするべきです。

ベクトルロードストアセグメント命令

この命令サブセットには、ISAの文字列名 Zvlsseg が与えられています。

ベクトルロード/ストアセグメント命令は、メモリ上の複数の連続したフィールドを、 連続した番号のベクトルレジスタとの間で移動します。

注釈

"構造体の配列"データタイプの操作をサポートします。

ベクトル命令の符号化における3ビットの nf フィールドは、セグメントごとのフィールド数 NFIELDS よりも1つ少ない符号なし整数です。

EMULの設定は、EMUL * NFIELDS {le} 8となるようにしなければならず、 そうでない場合は、命令のエンコーディングは予約されています。

EMUL * NFIELDSは、セグメント化されたロード/ストア命令でタッチされる基本的なベクトルレジスタの数を表しています。 この制約により、この合計はアーキテクチャレジスタファイルの1/4以下となり、EMUL=8の通常の演算と同じになります。

各フィールドは、連続した番号のベクトルレジスタグループに保持されます。 EMUL>1の場合、各フィールドは複数の連続した番号のベクトルレジスタで保持されるベクトルレジスタグループを占有し、 各フィールドのベクトルレジスタグループは通常のベクトルレジスタアライメント制約に従わなければなりません (例えば、EMUL=2、NFIELDS=4の場合、各フィールドのベクトルレジスタグループは偶数のベクトルレジスタで開始しなければなりませんが、 8の倍数のベクトルレジスタ番号で開始する必要はありません)。

セグメント・ロードまたはストアによってアクセスされるベクトルレジスタ番号が31を超えてインクリメントされる場合、 その命令エンコーディングは予約されています。

注釈

将来のより長い命令エンコーディングとの前方互換性を確保するためのものです。

vl レジスタは、移動する構造体の数を示しており、 これは各ベクトルレジスタグループに転送される要素の数と同じです。 マスキングは構造体全体のレベルでも適用されます。

セグメントロードおよびストアでは、各セグメント内のフィールドにアクセスするために使用される個々のメモリアクセスは、 順序付きのインデックス付きのセグメントロードおよびストアであっても、お互いに順序付けられていません。

例外が発生した場合、vstart は構造体の単位になります。 構造体へのアクセスの途中で例外が発生した場合、 構造体へのアクセスのサブセットを実行するかどうかは、実装で定義されています。

ベクトルユニットストライドセグメントロードストア命令

ベクトルユニットストライドのセグメントロードおよびセグメントストア命令は、 パックされた連続したセグメント("array-of-structures")を 複数の書き込みベクトルレジスタグループに移動させます。

注釈

ソフトウェアは追加の命令を使ってセグメントから構造体フィールドをアンパックすることができます。

ユニットストライドのセグメントロードとストアには、 それぞれ vlseg/vsseg というアセンブラのプレフィックスが使われます。

# フォーマット
vlseg<nf>e<eew>.v vd, (rs1), vm       # ユニットストライドセグメントロードのテンプレート
vsseg<nf>e<eew>.v vs3, (rs1), vm       # ユニットストライドセグメントストア命令のテンプレート

# Examples
vlseg8e8.v vd, (rs1), vm   # 1バイトフィールドを8つ持つ要素を8つのベクトルレジスタにロードする

vsseg3e32.v vs3, (rs1), vm  # 3*4バイトセグメントの要素をvs3,vs3+1,vs3+2からメモリにストアする

ロードの場合、vd レジスタはセグメントからロードされる最初のフィールドを保持します。 ストアの場合は、 vs3 レジスタが読み込まれ、各セグメントに格納される最初のフィールドが提供されます。

# 例1
# パッキングされたRGBピクセル(8bppの24ビットデータ構造)
vsetvli a1, t0, e8, ta, ma
vlseg3e8.v v8, (a0), vm
# v8 は赤ピクセルを持っている
# v9 は緑ピクセルを持っている
# v10 青ピクセルを持っている

# 例2
# メモリ構造は複素数を持っている。32ビットの実数と32ビットの虚数を持っている
vsetvli a1, t0, e32, ta, ma
vlseg2e32.v v8, (a0), vm
# v8 は実数を持っている
# v9 虚数を持っている

ユニットストライド命令については、fault-only-first版も定義されている。

# ベクトルfault-only-firstユニットストライドセグメントロード命令の例
vlseg<nf>e<eew>ff.v vd, (rs1),  vm          # ユニットストライドfault-only-firstセグメントロード

fault-only-firstセグメントのロードでは、セグメントへのアクセスの途中で例外が検出された場合、 要素のインデックスがゼロであるかどうかにかかわらず、セグメントのサブセットをロードするかどうかは実装で定義されます。

これらの命令は、例外が報告された時点や、ベクトル長がトリムされた時点を過ぎても、 書き込みベクトルレジスタグループの要素を上書きすることがあります。

ベクトルストライドセグメントロードストア命令

ベクトルのストライドセグメントは、GPRの引数 rs2 で指定されたバイトストライドの オフセットで区切られた連続したセグメントを移動してロード、ストアします。

# フォーマット
vlsseg<nf>e<eew>.v vd, (rs1), rs2, vm          # ストライドセグメントロード
vssseg<nf>e<eew>.v vs3, (rs1), rs2, vm         # ストライドセグメントストア

# 例
vsetvli a1, t0, e8, ta, ma
vlsseg3e8.v v4, (x5), x6   # アドレスx5+i*x6をv4[i]に格納する
                          #  x5+i*x6+1をv5[i]に格納する
                          #  x5+i*x6+2をv6[i]に格納する

# 例
vsetvli a1, t0, e32, ta, ma
vssseg2e32.v v2, (x5), x6   # v2[i]のワードをアドレスx5+i*x6にストアする
                            #   また、v3[i]のワードをx5+i*x6+4にストアする

各セグメント内のフィールドへのアクセスは、 セグメントがメモリ内で重なるようなバイトストライドの場合も含め、 どのような順序でも行うことができます。

ベクトルインデックスセグメントロードストア命令

各セグメントは、rs1 フィールドのスカラのベースアドレスと、ベクトルレジスタ vs2 のバイトオフセットを足したアドレスに位置します。 Index-Ordered形式とIndex-Unordered形式の両方が提供されており、 Index-Ordered形式はセグメントを要素順にアクセスします。 しかし、順序付けられた形式でも、個々のセグメント内のフィールドへのアクセスは、お互いに順序付けられていません。

データベクトルレジスタ群はEEW=SEW、EMUL=LMUL、 インデックスベクトルレジスタ群はEEWがEMUL=(EEW/SEW)*LMULで命令にエンコードされています。

# 例
vluxseg<nf>ei<eew>.v vd, (rs1), vs2, vm   # Indexed-unorderedセグメントロード
vloxseg<nf>ei<eew>.v vd, (rs1), vs2, vm   # Indexed-orderedセグメントロード
vsuxseg<nf>ei<eew>.v vs3, (rs1), vs2, vm  # Indexed-unorderedセグメントストア
vsoxseg<nf>ei<eew>.v vs3, (rs1), vs2, vm  # Indexed-orderedセグメントストア

# 例
vsetvli a1, t0, e8, ta, ma
vluxseg3ei32.v v4, (x5), v3   # アドレスx5+v3[i]のバイトデータをv4[i]にロードする
                          #  アドレスx5+v3[i]+1のバイトデータをv5[i]にロードする
                          #  アドレスx5+v3[i]+2のバイトデータをv6[i]にロードする

# 例
vsetvli a1, t0, e32, ta, ma
vsuxseg2ei32.v v2, (x5), v5   # v2[i]中のワードをアドレスx5+v5[i]にストアする
                          #   v3[i]中のワードをアドレスx5+v5[i]+4にストアする

ベクトルインデックスセグメントロードでは、 書き込みベクトルレジスタグループはソースベクトルレジスタグループ(vs2 で指定)と重なることはできません。

ベクトル全体レジスタロードストア命令

LOAD-FPメジャーオペコードのベクトルロード全体レジスタ命令のフォーマット

```wavedrom {reg: [

{bits: 7, name: 0x07, attr: 'VL*R*'}, {bits: 5, name: 'vd', attr: 'destination of load', type: 2}, {bits: 3, name: 'width'}, {bits: 5, name: 'rs1', attr: 'base address', type: 4}, {bits: 5, name: 8, attr: 'lumop'}, {bits: 1, name: 1, attr: 'vm'}, {bits: 2, name: 0x10000, attr: 'mop'}, {bits: 1, name: 'mew'}, {bits: 3, name: 'nf'},

```wavedrom {reg: [

{bits: 7, name: 0x27, attr: 'VS*R*'}, {bits: 5, name: 'vs3', attr: 'store data', type: 2}, {bits: 3, name: 0x1000}, {bits: 5, name: 'rs1', attr: 'base address', type: 4}, {bits: 5, name: 8, attr: 'sumop'}, {bits: 1, name: 1, attr: 'vm'}, {bits: 2, name: 0x100, attr: 'mop'}, {bits: 1, name: 0x100, attr: 'mew'}, {bits: 3, name: 'nf'},

これらの命令は、ベクトルレジスタグループ全体をロードおよびストアします。

注釈

vlvtype を変更するとコストがかかる場合に、ベクトル・レジスタの保存や復元に使用することを目的としています。 例えば、コンパイラのレジスタ・スピル、ベクトル・レジスタで値が渡されるベクトル関数呼び出し、割り込みハンドラ、OSのコンテキスト・スイッチなどです。 ソフトウェアは、 vlenb レジスタを読むことで、転送されたバイト数を知ることができます。

ロード命令では、通常のユニットストライド・ロードのパターンに従って、 mew および width フィールドにEEWがエンコードされています。

注釈

EEWに関係なく同じデータが出力先のレジスタ群に書き込まれます。 そのため、EEW=8 のバリエーションだけを用意すれば十分でした。 EEWのバリエーションをすべて用意したのは、エンコードされたEEWをヒントにして、 次にこのEEWでアクセスされる書き込みレジスタグループを示すことができるようにするためで、 これは内部的にデータを再配置する実装の助けになります。

ベクトル全体レジスタストア命令は、EEW=8 のマスクされていない ユニットストライドストアと同様にエンコードされます。

フィールド nf は、ロードおよびストアするベクトルレジスタの数をエンコードします。 符号化されたレジスタ数は2の累乗でなければならず、 ベクトルレジスタ番号はベクトルレジスタグループと同様にアラインメントされていなければならず、 そうでなければ命令の符号化は予約されます。 nf フィールドは、転送するベクトルレジスタの数をエンコードするもので、 ベースの後に連続して番号が付けられます。 nf の値は1、2、4、8のみがサポートされており、その他の値は予約されています。 複数のレジスタを転送する場合、最も低い番号のベクトルレジスタは最も低い番号のメモリアドレスに保持され、 連続したベクトルレジスタ番号はメモリに連続して配置されます。

この命令は、 vtypevl の現在の設定にかかわらず、 evl`=`nf *VLEN/EEWという実効ベクトル長で動作します。 vstart {ge} vl の場合には要素が書き込まれないという通常の特性は、 vtypevl の現在の設定に関係なく動作します。 vstart {ge} vl の場合には要素が書き込まれないという通常の特性は、 これらの命令には適用されません。 代わりに、vstart {ge} evl の場合には要素は書き込まれません。

この命令は、要素のマスクされていないユニットストライドロードおよびストア命令と同様に動作し、 ベースアドレスは rs1 で指定されるスカラ x レジスタで渡されます。

実装では、ベースアドレスが、エンコードされたEEWのサイズ(バイト)(EEW/8)と実装でサポートされている SEWの最小サイズ(バイト)(SEW~MIN~/8)のいずれか大きい方に自然にアラインされていない場合、 レジスタ全体のロードとストアでアドレスのずれの例外を発生させることができます。

注釈

これらの命令の実装が簡素化されます。 サブセットの実装によっては、より小さなSEW幅をサポートしていない場合があるため、 エンコードされたEEWよりも大きくても、サポートされている最小のSEWに対してミスアラインド例外を報告することが許可されています。 極端な実装では、例えば SEW~MIN~>XLEN のようになります。 ソフトウェア環境は、ABIをサポートするための最小アラインメント要件を義務付けることができます。

# 全体レジスタロードストア命令のフォーマット
vl1r.v v3, (a0)       # vl1re8.vの疑似命令

vl1re8.v    v3, (a0)  # a0に保持されているアドレスからVLEN/8バイトだけロードしv3に格納する
vl1re16.v   v3, (a0)  # a0に保持されているアドレスからVLEN/16バイトだけロードしv3に格納する
vl1re32.v   v3, (a0)  # a0に保持されているアドレスからVLEN/32バイトだけロードしv3に格納する
vl1re64.v   v3, (a0)  # a0に保持されているアドレスからVLEN/64バイトだけロードしv3に格納する
# vl1re128.v  v3, (a0)
# vl1re256.v  v3, (a0)
# vl1re512.v  v3, (a0)
# vl1re1024.v v3, (a0)

vl2r.v v2, (a0)       # vl2re8.v v2, (a0)の疑似命令

vl2re8.v    v2, (a0)  # a0に保持されているアドレスから2*VLEN/8バイトだけロードしv2-v3に格納する
vl2re16.v   v2, (a0)  # a0に保持されているアドレスから2*VLEN/16バイトだけロードしv2-v3に格納する
vl2re32.v   v2, (a0)  # a0に保持されているアドレスから2*VLEN/32バイトだけロードしv2-v3に格納する
vl2re64.v   v2, (a0)  # a0に保持されているアドレスから2*VLEN/64バイトだけロードしv2-v3に格納する
# vl2re128.v  v2, (a0)
# vl2re256.v  v2, (a0)
# vl2re512.v  v2, (a0)
# vl2re1024.v v2, (a0)

vl4r.v v4, (a0)       # vl4re8.vの疑似命令

vl4re8.v    v4, (a0)  # a0に保持されているアドレスから4*VLEN/8バイトだけロードしv4-v7に格納する
vl4re16.v   v4, (a0)
vl4re32.v   v4, (a0)
vl4re64.v   v4, (a0)
# vl4re128.v  v4, (a0)
# vl4re256.v  v4, (a0)
# vl4re512.v  v4, (a0)
# vl4re1024.v v4, (a0)

vl8r.v v8, (a0)       # vl8re8.vの疑似命令

vl8re8.v    v8, (a0)  # a0に保持されているアドレスから8*VLEN/8バイトだけロードしv8-v15に格納する
vl8re16.v   v8, (a0)
vl8re32.v   v8, (a0)
vl8re64.v   v8, (a0)
# vl8re128.v  v8, (a0)
# vl8re256.v  v8, (a0)
# vl8re512.v  v8, (a0)
# vl8re1024.v v8, (a0)

vs1r.v v3, (a1)      # v3をa1に保持されているアドレスにストアする
vs2r.v v2, (a1)      # v2-v3をa1に保持されているアドレスにストアする
vs4r.v v4, (a1)      # v4-v7をa1に保持されているアドレスにストアする
vs8r.v v8, (a1)      # v8-v15をa1に保持されているアドレスにストアする

注釈

実装上、不正命令例外を発生させる必要があります。

注釈

これは現在PoRにはありません。

ベクトルメモリアラインメント制約

ベクトルメモリ命令でアクセスした要素のサイズが自然にアラインされていない場合、 その要素は正常に転送されるか、その要素に対してアドレスミスアラインの例外が発生します。

ベクトルメモリアクセスのミスアラインメントのサポートは、 スカラメモリアクセスのミスアラインメントのサポートとは独立しています。

注釈

関連するアドレス範囲でベクトルのミスアラインドアクセスがサポートされているかどうかを判断するために、別のPMAを定義する必要があります。

ベクトルのミスアラインドメモリアクセスは、 スカラのミスアラインドメモリアクセスと同じアトミック性のルールに従います。

ベクトルメモリコンシステンシモデル

ベクトルメモリアクセス命令は、ローカルのhartではプログラム順に実行されているように見えます。

ベクトルメモリアクセス命令は、命令レベルではRVWMOに従います。

Index-Ordered形式以外のロード・ストア命令を除き、要素操作は命令内では順不同です。

Index-Ordered形式ロード・ストア命令は、 要素をメモリに読み書きする際に、それぞれ要素順に行います。

ベクトル長レジスタ vl の影響を受ける命令は、データ依存ではなく、 vl への制御依存を持ちます。 同様に、マスクされたベクトル命令は、データ依存ではなく、ソースマスクレジスタへの制御依存を持ちます。

注釈

ここでは通常、分岐命令が使用されていました。 マスクを制御として扱うことで、マスクされたベクトルロード命令は、 マスク値が判明する前にメモリにアクセスすることができ、 分岐予測失敗時に回復するメカニズムを必要としません。

ベクトル算術演算命令

ベクトル演算命令では、OP-FPに隣接する新しいメジャーオペコード(OP-V = 1010111~2~)を使用します。 3ビットの funct3 フィールドは、ベクトル命令のサブカテゴリを定義するのに使われます。

include::valu-format.adoc[]

ベクトル算術演算命令エンコーディング

funct3 フィールによりオペランドのタイプとソース位置をエンコードします。

整数演算は、オペコードに応じて符号なしまたは2の補数の符号付き整数演算で行われます。

すべての標準ベクトル浮動小数点演算は、IEEE-754/2008 規格に準拠しています。 すべてのベクトル浮動小数点演算は、frm レジスタのダイナミック丸めモードを使用します。 丸めモードに依存しない命令であっても、ベクトル浮動小数点演算命令で無効な丸めモードが含まれている場合や、 vl`=0 の場合、または `vstart {ge} vl の場合の frm フィールドの使用は予約されています。

注釈

実装では、制御ロジックを単純化するために、丸めモードが無効なときにすべてのベクトルFP命令が例外を報告するようにすることができます。

ベクトル演算は、vs2vs1 でそれぞれ指定されたベクトルレジスタグループから、 オペランドの2つのベクトルを取ります。

ベクトル・スカラ演算には3つの形式がありますが、いずれの場合も、 vs2 で指定されたベクトルレジスタ群から1つのベクトルのオペランドを取り、 3つの代替ソースのうちの1つから2つ目のスカラソースのオペランドを取ります。

  • 整数演算の場合、スカラは rs1 フィールドでエンコードされた5ビットの即値になります。

この値は、特に指定がない限り、SEWビットに符号拡張されます。 * 整数演算では、スカラは rs1 で指定されたスカラ x レジスタから取ることができます。 XLEN>SEWの場合、特に指定がない限り、x レジスタの最下位SEWビットが使用されます。 XLEN<SEWの場合、x レジスタからの値はSEWビットに符号拡張されます。 浮動小数点演算の場合、スカラはスカラ f レジスタから取得できます。 FLEN > SEWの場合、 f レジスタの値が有効なNaNボックス値であるかどうかがチェックされ、 その場合は f レジスタの最下位SEWビットが使用され、そうでない場合は正規のNaN値が使用されます。 浮動小数点ベクトルオペランドのEEWがサポートされていない浮動小数点型の幅であるベクトル命令(FLEN < SEWの場合を含む)は予約されています。

ベクトル演算命令は、vm フィールドの制御下でマスクされます。

# ベクトル2項算術演算命令のアセンブリ構文パタン

# ベクトル演算の結果はvm(v0.t, <指定なし>)によりマスクされる
vop.vv  vd, vs2, vs1, vm  # 整数 ベクトル-ベクトル vd[i] = vs2[i] op vs1[i]
vop.vx  vd, vs2, rs1, vm  # 整数 ベクトル-スカラ   vd[i] = vs2[i] op x[rs1]
vop.vi  vd, vs2, imm, vm  # 整数 ベクトル-即値     vd[i] = vs2[i] op imm

vfop.vv  vd, vs2, vs1, vm # 浮動小数点 ベクトル-ベクトル 演算 vd[i] = vs2[i] fop vs1[i]
vfop.vf  vd, vs2, rs1, vm # 浮動小数点 ベクトル-スカラ 演算   vd[i] = vs2[i] fop f[rs1]

注釈

これは、標準的なスカラの順序とは逆です。 この配列は、1つのスカラレジスタのみを読み出す命令は rs1 から読み出すという既存のエンコーディング規約を維持し、 5ビットの即値は rs1 フィールドから供給されます。

# ベクトル3項算術演算命令(multiply-add)のアセンブリ構文パタン

# 加算入力値を上書きする整数演算
vop.vv vd, vs1, vs2, vm  # vd[i] = vs1[i] * vs2[i] + vd[i]
vop.vx vd, rs1, vs2, vm  # vd[i] = x[rs1] * vs2[i] + vd[i]

# 乗算入力値を上書きする整数演算
vop.vv vd, vs1, vs2, vm  # vd[i] = vs1[i] * vd[i] + vs2[i]
vop.vx vd, rs1, vs2, vm  # vd[i] = x[rs1] * vd[i] + vs2[i]

# 加算入力値を上書きする浮動小数点演算
vfop.vv vd, vs1, vs2, vm  # vd[i] = vs1[i] * vs2[i] + vd[i]
vfop.vf vd, rs1, vs2, vm  # vd[i] = f[rs1] * vs2[i] + vd[i]

# 乗算入力値を上書きする浮動小数点演算
vfop.vv vd, vs1, vs2, vm  # vd[i] = vs1[i] * vd[i] + vs2[i]
vfop.vf vd, rs1, vs2, vm  # vd[i] = f[rs1] * vd[i] + vs2[i]

注釈

次に rs1 または vs1 、そして vs2 の順になります。 この順序では、乗算オペランドが常に隣り合っているため、 これらの三項演算のアセンブラをより自然に読むことができます。

幅拡張ベクトル算術演算命令

いくつかのベクトル演算命令は、書き込みベクトルレジスタグループがEEW=2*SEWおよびEMUL=2*LMULを持つ**幅拡張** 演算が定義されています。

第1ベクトルレジスタグループのオペランドは、単一幅または二倍幅のいずれかです。 これらは通常、オペコードの前に vw* というプレフィックスを付けて記述され、 ベクトル浮動小数点演算の場合は vfw* となります。

ベクトル幅拡張算術演算命令のアセンブリ構文パタン

# 2つの1倍幅ソースで2倍幅の結果: 2*SEW = SEW op SEW
vwop.vv  vd, vs2, vs1, vm  # 整数 vector-vector      vd[i] = vs2[i] op vs1[i]
vwop.vx  vd, vs2, rs1, vm  # 整数 vector-scalar      vd[i] = vs2[i] op x[rs1]

# 1番目のソースオペランドが2倍幅, 2番目のソースオペランドが1倍幅, 結果が2倍幅: 2*SEW = SEW op SEW
vwop.wv  vd, vs2, vs1, vm  # 整数 vector-vector      vd[i] = vs2[i] op vs1[i]
vwop.wx  vd, vs2, rs1, vm  # 整数 vector-scalar      vd[i] = vs2[i] op x[rs1]

注釈

2倍幅整数のワードサイズの演算を意味する w という接尾語と混同される恐れがあったため、 w はプレフィックスに移されました。

注釈

vwf* から vfw* に変更されました。

注釈

これらは4倍にするために、オペコードの前に vq* という接頭語を付けることで区別されます。 これらは、現時点では含まれていませんが、将来の拡張で追加される可能性があります。

すべての幅拡張命令において、書き込みのEEWおよびEMULの値はサポートされているコンフィギュレーションでなければならず、 そうでない場合は命令のエンコーディングは予約されています。

書き込みベクトルレジスタグループは、書き込みのEMULに有効なベクトルレジスタ番号を使って指定しなければならず、 そうでない場合は命令エンコーディングは予約されます。

ベクトル幅縮小算術演算命令

2 倍幅のソースベクトルを 1 倍幅の書き込みベクトルに変換する命令がいくつか用意されています。 これらの命令は、EEW/EMUL=2*SEW/2*LMULのベクトルレジスタグループを、 現在のSEW/LMUL設定のベクトルレジスタグループに変換します。

EEW > ELENまたはEMUL > 8の場合、命令のエンコーディングは予約されています。

注釈

ここでの選択は、選択されたアプローチがより少ない vtype の変更を必要とするという信念に基づいています。

ソースおよび書き込みベクトルレジスタグループは、ソースおよび書き込みのEMUL値に対してそれぞれ正当な ベクトルレジスタ番号で指定されなければならず、そうでなければ命令エンコーディングは予約されます。

第2のソースベクトルレジスタグループ(vs1 で指定)がある場合、 これは結果と同じ(より狭い)幅を持ちます(すなわち、EEW=SEW)。

アセンブラでこれらの命令を区別するためにオペコードに vn* というプレフィックスをつけたり、 浮動小数点オペコードを絞り込むために vfn* というプレフィックスをつけたりします。 2倍幅ソースベクトルレジスタグループは、 ソースオペランドのサフィックスに w を付けて表します(例: vnsra.wv)。

ベクトル整数算術演算命令

整数ベクトル算術演算命令が提供されています。

ベクトル単一幅整数加算減算命令

ベクトル整数加減算命令が提供されています。 ベクトル・スカラ形式においては逆減算命令も提供されています。

# 整数加算
vadd.vv vd, vs2, vs1, vm   # ベクトル-ベクトル
vadd.vx vd, vs2, rs1, vm   # ベクトル-スカラ
vadd.vi vd, vs2, imm, vm   # ベクトル-即値

# 整数減算
vsub.vv vd, vs2, vs1, vm   # ベクトル-ベクトル
vsub.vx vd, vs2, rs1, vm   # ベクトル-スカラ

# 整数逆減算
vrsub.vx vd, vs2, rs1, vm   # vd[i] = x[rs1] - vs2[i]
vrsub.vi vd, vs2, imm, vm   # vd[i] = imm - vs2[i]

ベクトル内の整数値は、x0 とのスカラ逆減算によって符号を反転することができます。 これは vneg vd,vs = vrsub.vx vd,vs,x0 としてアセンブリ疑似命令を定義することができます。

ベクトル幅拡張整数加減算命令

符号付きと符号なしの両方で、幅拡張加減算命令が定義されています。 これらは幅の小さいオペランドが最初に符号拡張かゼロ拡張され、 倍幅での加減算が行われます。

# 符号なし整数の幅拡張加減算命令, 2*SEW = SEW +/- SEW
vwaddu.vv  vd, vs2, vs1, vm  # vector-vector
vwaddu.vx  vd, vs2, rs1, vm  # vector-scalar
vwsubu.vv  vd, vs2, vs1, vm  # vector-vector
vwsubu.vx  vd, vs2, rs1, vm  # vector-scalar

# 符号付き整数の幅拡張加減算命令, 2*SEW = SEW +/- SEW
vwadd.vv  vd, vs2, vs1, vm  # vector-vector
vwadd.vx  vd, vs2, rs1, vm  # vector-scalar
vwsub.vv  vd, vs2, vs1, vm  # vector-vector
vwsub.vx  vd, vs2, rs1, vm  # vector-scalar

# 符号なし整数の幅拡張加減算命令, 2*SEW = 2*SEW +/- SEW
vwaddu.wv  vd, vs2, vs1, vm  # vector-vector
vwaddu.wx  vd, vs2, rs1, vm  # vector-scalar
vwsubu.wv  vd, vs2, vs1, vm  # vector-vector
vwsubu.wx  vd, vs2, rs1, vm  # vector-scalar

# 符号付き整数の幅拡張加減算命令, 2*SEW = 2*SEW +/- SEW
vwadd.wv  vd, vs2, vs1, vm  # vector-vector
vwadd.wx  vd, vs2, rs1, vm  # vector-scalar
vwsub.wv  vd, vs2, vs1, vm  # vector-vector
vwsub.wx  vd, vs2, rs1, vm  # vector-scalar

注釈

vwcvt.x.x.v vd,vs,vm = vwadd.vx vd,vs,x0,vmvwcvtu.x.x.v vd,vs,vm = vwaddu.vx vd,vs,x0,vm により 疑似アセンブリ命令を定義することができます。

ベクトル整数拡張

ゼロ拡張と符号拡張のベクトル整数拡張命令は、SEWよりも小さいEEWの整数オペランドを SEWの幅まで拡張して書き込みレジスタに転送します。 ソースのEEWはSEWの1/2, 1/4, 1/8であり、ソースのEMULは(EEW/SEW)*LMULです。 書き込み側のEEWはSEWと同一であり、EMULはLMULと同一です。

vzext.vf2 vd, vs2, vm  # SEW/2のソースオペランドをゼロ拡張してSEW幅化し書き込む
vsext.vf2 vd, vs2, vm  # SEW/2のソースオペランドを符号拡張してSEW幅化し書き込む
vzext.vf4 vd, vs2, vm  # SEW/4のソースオペランドをゼロ拡張してSEW幅化し書き込む
vsext.vf4 vd, vs2, vm  # SEW/4のソースオペランドを符号拡張してSEW幅化し書き込む
vzext.vf8 vd, vs2, vm  # SEW/8のソースオペランドをゼロ拡張してSEW幅化し書き込む
vsext.vf8 vd, vs2, vm  # SEW/8のソースオペランドを符号拡張してSEW幅化し書き込む

ソースのEEWがサポートされていない場合もしくはEMULがLMULの最小値よりも小さい場合、 命令エンコーディングは予約されています。

ベクトル整数 キャリー付き加算 / ボロー付き減算命令

複数ワードの整数演算をサポートするために、キャリービットを操作する命令が用意されています。 各演算(加算または減算)には2つの命令が用意されています。 1つは演算結果(SEW幅)を提供し、 もう1つはキャリー出力(マスク・ブールとしてエンコードされた1ビット)を生成します。

キャリー入出力は、 <sec-mask-register-layout> 節で説明したマスクレジスタのレイアウトを用いて表現されます。 エンコーディングの制約により、キャリー入力は暗黙の v0 レジスタから出力されなければなりませんが、 キャリー出力はソース/書き込みのオーバーラップの制約を満たす任意のベクトルレジスタに書き込むことができます。

vadcvsbc は、ソースオペランドとキャリーインまたはボローインの加算または減算を行い、 その結果をベクトルレジスタ vd に書き込みます。 これらの命令は、マスクされた命令 (vm=0) としてエンコードされていますが、すべてのボディ要素を操作し、書き戻します。 マスクされていないバージョン(vm=1)に対応するエンコーディングは予約されています。

vvmadcvmsbc は、ソースオペランドを加算または減算し、マスクされている (vm=0) 場合にはオプションでキャリーインを加算またはボローインを減算し、 その結果をマスクレジスタ vd に書き戻します。 マスクされていない場合 (vm=1)、キャリーインやボローインはありません。 これらの命令は、マスクされていても、すべてのボディ要素を操作し、書き戻します。 これらの命令はマスク値を生成するため、常に末尾Agnosticポリシで動作します。

# キャリー付き加算命令

# vd[i] = vs2[i] + vs1[i] + v0.mask[i]
vadc.vvm   vd, vs2, vs1, v0  # ベクトル-ベクトル

# vd[i] = vs2[i] + x[rs1] + v0.mask[i]
vadc.vxm   vd, vs2, rs1, v0  # ベクトル-スカラ

# vd[i] = vs2[i] + imm + v0.mask[i]
vadc.vim   vd, vs2, imm, v0  # ベクトル-即値

# マスクレジスタフォーマットにキャリーアウトを生成する

# vd.mask[i] = carry*out(vs2[i] + vs1[i] + v0.mask[i])
vmadc.vvm   vd, vs2, vs1, v0  # ベクトル-ベクトル

# vd.mask[i] = carry*out(vs2[i] + x[rs1] + v0.mask[i])
vmadc.vxm   vd, vs2, rs1, v0  # ベクトル-スカラ

# vd.mask[i] = carry*out(vs2[i] + imm + v0.mask[i])
vmadc.vim   vd, vs2, imm, v0  # ベクトル-即値

# vd.mask[i] = carry*out(vs2[i] + vs1[i])
vmadc.vv    vd, vs2, vs1      # ベクトル-ベクトル, no carry-in

# vd.mask[i] = carry*out(vs2[i] + x[rs1])
vmadc.vx    vd, vs2, rs1      # ベクトル-スカラ, no carry-in

# vd.mask[i] = carry*out(vs2[i] + imm)
vmadc.vi    vd, vs2, imm      # ベクトル-即値, no carry-in

キャリー伝搬を実装するには、入力が変更されていない状態で2つの命令を実行する必要があるため、 破壊的な蓄積を行うと、正しい結果を得るために追加の移動が必要になります。

# v4に値を蓄積する複数ワード算術演算命令列
vmadc.vvm v1, v4, v8, v0  # 一時レジスタv1にキャリーを格納する
vadc.vvm v4, v4, v8, v0   # 加算を行う
vmmv.m v0, v1             # 次のワードのために一時キャリーをv0に移動する

ボロー付き減算命令 vsbc は、減算のためのロングワード演算をサポートするための機能を果たします。 即値での減算命令はありません。

# ボロー付きの差分を計算する

# vd[i] = vs2[i] - vs1[i] - v0.mask[i]
vsbc.vvm   vd, vs2, vs1, v0  # Vector-vector

# vd[i] = vs2[i] - x[rs1] - v0.mask[i]
vsbc.vxm   vd, vs2, rs1, v0  # Vector-scalar

# マスクレジスタフォーマットでボロー出力を生成する

# vd.mask[i] = borrow*out(vs2[i] - vs1[i] - v0.mask[i])
vmsbc.vvm   vd, vs2, vs1, v0  # Vector-vector

# vd.mask[i] = borrow*out(vs2[i] - x[rs1] - v0.mask[i])
vmsbc.vxm   vd, vs2, rs1, v0  # Vector-scalar

# vd.mask[i] = borrow*out(vs2[i] - vs1[i])
vmsbc.vv    vd, vs2, vs1      # Vector-vector, no borrow-in

# vd.mask[i] = borrow*out(vs2[i] - x[rs1])
vmsbc.vx    vd, vs2, rs1      # Vector-scalar, no borrow-in

vmsbc では、切り捨て前の差が負であるときに限りボローは1と定義される。

vadcvsbc では書き込みベクトルレジスタが v0 の場合、命令エンコーディングが予約されます。

ベクトル論理命令

# 論理命令
vand.vv vd, vs2, vs1, vm   # ベクトル-ベクトル
vand.vx vd, vs2, rs1, vm   # ベクトル-スカラ
vand.vi vd, vs2, imm, vm   # ベクトル-即値

vor.vv vd, vs2, vs1, vm    # ベクトル-ベクトル
vor.vx vd, vs2, rs1, vm    # ベクトル-スカラ
vor.vi vd, vs2, imm, vm    # ベクトル-即値

vxor.vv vd, vs2, vs1, vm    # ベクトル-ベクトル
vxor.vx vd, vs2, rs1, vm    # ベクトル-スカラ
vxor.vi vd, vs2, imm, vm    # ベクトル-即値

注釈

これは、アセンブラの疑似命令 vnot.v として提供することができます。

ベクトル単一幅ビットシフト命令

左への論理シフト、右への論理(ゼロ拡張)および算術(符号拡張)シフトを含む、完全なベクトルシフト命令が用意されています。 シフトするデータは、 vs2 で指定されたベクトルレジスタグループにあり、シフト量はベクトルレジスタグループ vs1 、スカラ整数レジスタ rs1 、または即値となります。 ベクトルまたはスカラのシフト量の値の下位lg2(SEW)ビットが使用され、シフト量の即値はゼロ拡張されます。

# ビットシフト操作
vsll.vv vd, vs2, vs1, vm   # ベクトル-ベクトル
vsll.vx vd, vs2, rs1, vm   # ベクトル-スカラ
vsll.vi vd, vs2, uimm, vm   # ベクトル-即値

vsrl.vv vd, vs2, vs1, vm   # ベクトル-ベクトル
vsrl.vx vd, vs2, rs1, vm   # ベクトル-スカラ
vsrl.vi vd, vs2, uimm, vm   # ベクトル-即値

vsra.vv vd, vs2, vs1, vm   # ベクトル-ベクトル
vsra.vx vd, vs2, rs1, vm   # ベクトル-スカラ
vsra.vi vd, vs2, uimm, vm   # ベクトル-即値

ベクトルサイズ幅縮退整数右シフト命令

サイズ幅縮退の右シフトは、広いオペランドからより小さいフィールドを取り出すもので、ゼロ拡張(srl)と符号拡張(sra)の両方の形式があります。 シフト量は、ベクトル、スカラの x レジスタ、または5ビットの即値から得られます。 ベクトルまたはスカラのシフト量の下位lg2(2*SEW)ビットが使用されます(例えば、SEW=64ビットからSEW=32ビットへの狭帯域化の場合は下位6ビット)。 即値形式は、シフト量の即値オペランドをゼロ拡張します。

# Narrowing shift right logical, SEW = (2*SEW) >> SEW
# ビット幅縮退論理右シフト命令, SEW = (2*SEW) >> SEW
vnsrl.wv vd, vs2, vs1, vm   # vector-vector
vnsrl.wx vd, vs2, rs1, vm   # vector-scalar
vnsrl.wi vd, vs2, uimm, vm   # vector-immediate

# Narrowing shift right arithmetic, SEW = (2*SEW) >> SEW
# ビット幅縮退算術右シフト命令, SEW = (2*SEW) >> SEW
vnsra.wv vd, vs2, vs1, vm   # vector-vector
vnsra.wx vd, vs2, rs1, vm   # vector-scalar
vnsra.wi vd, vs2, uimm, vm   # vector-immediate

注釈

アセンブリ疑似命令 vncvt.x.x.w vd,vs,vm = vnsrl.wx vd,vs,x0,vm を定義することができます。

ベクトル整数比較命令

以下の整数比較命令は、比較の結果が真であれば書き込みマスクレジスタの要素に1を、そうでなければ0を書き込みます。 書き込みマスクベクトルは常に単一のベクトルレジスタに保持され、その要素のレイアウトはセクション マスクレジスタのレイアウト で説明されています。 書き込みマスクレジスタは、ソースベクトルのマスクレジスタ(v0)と同じものでも構いません。

# Set if equal
vmseq.vv vd, vs2, vs1, vm  # ベクトル-ベクトル
vmseq.vx vd, vs2, rs1, vm  # ベクトル-スカラ
vmseq.vi vd, vs2, imm, vm  # ベクトル-即値

# Set if not equal
vmsne.vv vd, vs2, vs1, vm  # ベクトル-ベクトル
vmsne.vx vd, vs2, rs1, vm  # ベクトル-スカラ
vmsne.vi vd, vs2, imm, vm  # ベクトル-即値

# Set if less than, unsigned
vmsltu.vv vd, vs2, vs1, vm  # ベクトル-ベクトル
vmsltu.vx vd, vs2, rs1, vm  # ベクトル-スカラ

# Set if less than, signed
vmslt.vv vd, vs2, vs1, vm  # ベクトル-ベクトル
vmslt.vx vd, vs2, rs1, vm  # ベクトル-スカラ

# Set if less than or equal, unsigned
vmsleu.vv vd, vs2, vs1, vm   # ベクトル-ベクトル
vmsleu.vx vd, vs2, rs1, vm   # ベクトル-スカラ
vmsleu.vi vd, vs2, imm, vm   # ベクトル-即値

# Set if less than or equal, signed
vmsle.vv vd, vs2, vs1, vm  # ベクトル-ベクトル
vmsle.vx vd, vs2, rs1, vm  # ベクトル-スカラ
vmsle.vi vd, vs2, imm, vm  # ベクトル-即値

# Set if greater than, unsigned
vmsgtu.vx vd, vs2, rs1, vm   # ベクトル-スカラ
vmsgtu.vi vd, vs2, imm, vm   # ベクトル-即値

# Set if greater than, signed
vmsgt.vx vd, vs2, rs1, vm    # ベクトル-スカラ
vmsgt.vi vd, vs2, imm, vm    # ベクトル-即値

# 以下の2命令は直接提供されない
# Set if greater than or equal, unsigned
# vmsgeu.vx vd, vs2, rs1, vm    # ベクトル-スカラ
# Set if greater than or equal, signed
# vmsge.vx vd, vs2, rs1, vm    # ベクトル-スカラ

以下の表は全ての比較操作がどのようにネイティブマシンコードに実装されるのかを示しています。

比較            アセンブラマッピング          アセンブラ疑似命令

va < vb         vmslt{u}.vv vd, va, vb, vm
va <= vb        vmsle{u}.vv vd, va, vb, vm
va > vb         vmslt{u}.vv vd, vb, va, vm    vmsgt{u}.vv vd, va, vb, vm
va >= vb        vmsle{u}.vv vd, vb, va, vm    vmsge{u}.vv vd, va, vb, vm

va < x          vmslt{u}.vx vd, va, x, vm
va <= x         vmsle{u}.vx vd, va, x, vm
va > x          vmsgt{u}.vx vd, va, x, vm
va >= x         see below

va < i          vmsle{u}.vi vd, va, i-1, vm    vmslt{u}.vi vd, va, i, vm
va <= i         vmsle{u}.vi vd, va, i, vm
va > i          vmsgt{u}.vi vd, va, i, vm
va >= i         vmsgt{u}.vi vd, va, i-1, vm    vmsge{u}.vi vd, va, i, vm

va, vb ベクトルレジスタグループ
x      スカラ整数レジスタ
i      即値

注釈

vmsle.vi の範囲は -16 から 15 で、その結果、実効的な vmslt.vi の範囲は -15 から 16 となります。 vmsleu.vi の範囲は0から15で、実効的な vmsltu.vi の範囲は1から16になります (注意: 即値0の vmsltu.vi は常に偽なので役に立ちません)。 5ビットのベクトル即値は常に符号拡張されているので、vmsleu.vi2^SEW^-16 から 2^SEW^-1 の範囲の符号なし即値もサポートしており、 2^SEW^-15 から 2^SEW^ の範囲の符号なし即値に対する vmsltu.vi の比較が可能です。 即値 2^SEW^vlsltu.vi は常に真なので、有用ではないことに注意してください。

同様に、vmsge{u}.vi は提供されず、即値を1だけデクリメントした vmsgt{u}.vi を使用して比較を実装します。 その結果、実効的な vmsge.vi の範囲は-15~16、実効的な vmsgeu.vi の範囲は1~16となります(なお、即値が0の vmsgeu.vi は常に真なので役に立ちません)。

注釈

1つの比較命令でマスク値の正しい極性を提供できるようにするために提供されています。

エンコーディング空間を減らすために、vmsge{u}.vx 形式は直接提供されていないので、va {ge} x の場合は特別な処理が必要です。

注釈

しかし、OPIVIでスカラの x レジスタを使用する命令はこれらだけです。 別の方法として、さらに2つのfunct6エンコーディングを使用することもできますが、 これらは同じ8つのfunct6エンコーディングのグループの他のものとは異なるオペランドフォーマット(マスクレジスタへの書き込み)になります。 現在のPoRでは、これらの命令を省略し、必要に応じて以下のように合成しています。

vmsge{u}.vx の演算は、 x の表現がアンダーフローしないことがわかっている場合、 x の値を1だけ減らして vmsgt{u}.vx 命令を使用することで合成できます。

`vmsge{u}.vx` 命令を合成するための命令列

va >= x,  x > minimum

   addi t0, x, -1; vmsgt{u}.vx vd, va, t0, vm

通常は上記の順序が最も効率的な実装になりますが、 x の範囲が不明な場合にはアセンブラの疑似命令を提供することができます。

マスク無し va >= x

  疑似命令: vmsge{u}.vx vd, va, x
  展開: vmslt{u}.vx vd, va, x; vmnand.mm vd, vd, vd

マスク付き va >= x, vd != v0

  疑似命令: vmsge{u}.vx vd, va, x, v0.t
  展開: vmslt{u}.vx vd, va, x, v0.t; vmxor.mm vd, vd, v0

マスク付き va >= x, vd == v0

  疑似命令: vmsge{u}.vx vd, va, x, v0.t, vt
  展開: vmslt{u}.vx vt, va, x;  vmandnot.mm vd, vd, vt

マスク付き va >= x, any vd

  疑似命令: vmsge{u}.vx vd, va, x, v0.t, vt
  展開: vmslt{u}.vx vt, va, x;  vmandnot.mm vt, v0, vt;  vmandnot.mm vd, vd, v0;  vmor.mm vd, vt, vd

  疑似命令中のvt引数は一時ベクトルレジスタの意味であり、
  vdとは異なり破壊される問題ないレジスタでなければならない

マスク付きundisturbedポリシによって複数の比較をANDする例を以下に示します。

# (a < b) && (b < c) をマスク付きundisturbedによって2命令で実現する
vmslt.vv    v0, va, vb        # 全ての要素に書き込みを行う
vmslt.vv    v0, vb, vc, v0.t  # マスクの設定された場所のみ書き込みを行う

比較はマスクレジスタを書き込むため、常に末尾agnosticポリシで動作します。

ベクトル整数最大/最小命令

符号付き整数/符号なし整数の最大・最小値計算命令がサポートされている。

# 符号なし最小値
vminu.vv vd, vs2, vs1, vm   # ベクトル-ベクトル
vminu.vx vd, vs2, rs1, vm   # ベクトル-スカラ

# 符号付き最小値
vmin.vv vd, vs2, vs1, vm   # ベクトル-ベクトル
vmin.vx vd, vs2, rs1, vm   # ベクトル-スカラ

# 符号なし最大値
vmaxu.vv vd, vs2, vs1, vm   # ベクトル-ベクトル
vmaxu.vx vd, vs2, rs1, vm   # ベクトル-スカラ

# 符号付き最大値
vmax.vv vd, vs2, vs1, vm   # ベクトル-ベクトル
vmax.vx vd, vs2, rs1, vm   # ベクトル-スカラ

ベクトル単一幅整数乗算命令

単一幅の乗算命令は、SEWビット*SEWビットの乗算を行い、SEWビット幅の結果を返す。 *mulh* 版では、積の上位ワードを出力レジスタに書き込みます。

# 符号付き乗算、積の下位ビットを返す
vmul.vv vd, vs2, vs1, vm   # Vector-vector
vmul.vx vd, vs2, rs1, vm   # vector-scalar

# 符号付き乗算、積の上位ビットを返す
vmulh.vv vd, vs2, vs1, vm   # Vector-vector
vmulh.vx vd, vs2, rs1, vm   # vector-scalar

# 符号なし乗算、積の上位ビットを返す
vmulhu.vv vd, vs2, vs1, vm   # Vector-vector
vmulhu.vx vd, vs2, rs1, vm   # vector-scalar

# vs2を符号付き、vs1を符号なしとした乗算、積の上位ビットを返す
vmulhsu.vv vd, vs2, vs1, vm   # Vector-vector
vmulhsu.vx vd, vs2, rs1, vm   # vector-scalar

注釈

拡張機能としては、vmulh, vmulhu, vmulhsu のバリエーションが考えられ、積の下半分を破棄する際に vxrm 丸めモードを使用します。 これらのケースではオーバーフローの可能性はありません。

ベクトル整数除算命令

除算・剰余命令は、RISC-V標準のスカラ整数乗除算と同等で、極端な入力に対しても同じ結果が得られます。

# 符号なし除算
vdivu.vv vd, vs2, vs1, vm   # ベクトル-ベクトル
vdivu.vx vd, vs2, rs1, vm   # ベクトル-スカラ

# 符号付除算
vdiv.vv vd, vs2, vs1, vm   # ベクトル-ベクトル
vdiv.vx vd, vs2, rs1, vm   # ベクトル-スカラ

# 符号なし剰余
vremu.vv vd, vs2, vs1, vm   # ベクトル-ベクトル
vremu.vx vd, vs2, rs1, vm   # ベクトル-スカラ

# 符号付剰余
vrem.vv vd, vs2, vs1, vm   # ベクトル-ベクトル
vrem.vx vd, vs2, rs1, vm   # ベクトル-スカラ

注釈

標準的な命令がない場合、ソフトウェアは演算を実行するために何らかのアルゴリズムを選択しなければならず、 マイクロアーキテクチャによってはパフォーマンスが低下する可能性があるというのが賛成の理由です。

ベクトル幅拡張乗算命令

幅拡張整数乗算命令は、SEWビット*SEWビット乗算から完全な2*SEWビット積を返します。

# 幅拡張符号付き整数乗算
vwmul.vv  vd, vs2, vs1, vm # vector-vector
vwmul.vx  vd, vs2, rs1, vm # vector-scalar

# 幅拡張符号なし整数乗算
vwmulu.vv vd, vs2, vs1, vm # vector-vector
vwmulu.vx vd, vs2, rs1, vm # vector-scalar

# 幅拡張符号付き・符号なし整数乗算
vwmulsu.vv vd, vs2, vs1, vm # vector-vector
vwmulsu.vx vd, vs2, rs1, vm # vector-scalar

ベクトル単一幅整数乗算加算命令

整数の乗算加算命令は破壊的で、加算値や最小値を上書きするもの(vmaccvnmsac)と、 最初の乗算値を上書きするもの(vmaddvnmsub)の2種類が用意されています。

積の下位ビットの半分が第3オペランドに加算または減算されます。

注釈

オペコードは、(残念ながら直感に反する)浮動小数点の fnmsub 命令の定義に合わせて vnmsac となっています。 オペコードは vnmsub と似ています。

# 整数乗算加算命令、加算項上書き
vmacc.vv vd, vs1, vs2, vm    # vd[i] = +(vs1[i] * vs2[i]) + vd[i]
vmacc.vx vd, rs1, vs2, vm    # vd[i] = +(x[rs1] * vs2[i]) + vd[i]

# 整数乗算減算命令、減算項上書き
vnmsac.vv vd, vs1, vs2, vm    # vd[i] = -(vs1[i] * vs2[i]) + vd[i]
vnmsac.vx vd, rs1, vs2, vm    # vd[i] = -(x[rs1] * vs2[i]) + vd[i]

# 整数乗算加算命令、乗算項上書き
vmadd.vv vd, vs1, vs2, vm    # vd[i] = (vs1[i] * vd[i]) + vs2[i]
vmadd.vx vd, rs1, vs2, vm    # vd[i] = (x[rs1] * vd[i]) + vs2[i]

# 整数乗算減算命令、乗算項上書き
vnmsub.vv vd, vs1, vs2, vm    # vd[i] = -(vs1[i] * vd[i]) + vs2[i]
vnmsub.vx vd, rs1, vs2, vm    # vd[i] = -(x[rs1] * vd[i]) + vs2[i]

ベクトル幅拡張整数乗算加算命令

幅拡張整数乗算・加算命令は、SEWビット*SEWビットの乗算から2*SEWビットの値に2*SEWビットの乗算を加算し、 2*SEWビットの結果を生成します。 符号付きおよび符号なしの乗算オペランドのすべての組み合わせがサポートされています。

# 幅拡張符号なし整数乗算加算命令、加算項上書き
vwmaccu.vv vd, vs1, vs2, vm    # vd[i] = +(vs1[i] * vs2[i]) + vd[i]
vwmaccu.vx vd, rs1, vs2, vm    # vd[i] = +(x[rs1] * vs2[i]) + vd[i]

# 幅拡張符号付き整数乗算加算命令、加算項上書き
vwmacc.vv vd, vs1, vs2, vm    # vd[i] = +(vs1[i] * vs2[i]) + vd[i]
vwmacc.vx vd, rs1, vs2, vm    # vd[i] = +(x[rs1] * vs2[i]) + vd[i]

# 幅拡張符号なし整数乗算加算命令、加算項上書き
vwmaccsu.vv vd, vs1, vs2, vm  # vd[i] = +(signed(vs1[i]) * unsigned(vs2[i])) + vd[i]
vwmaccsu.vx vd, rs1, vs2, vm  # vd[i] = +(signed(x[rs1]) * unsigned(vs2[i])) + vd[i]

# Widening unsigned-signed-integer multiply-add, overwrite addend
# 幅拡張符号なし・符号付き整数乗算加算命令、加算項上書き
vwmaccus.vx vd, rs1, vs2, vm  # vd[i] = +(unsigned(x[rs1]) * signed(vs2[i])) + vd[i]

ベクトル整数マージ命令

ベクトル整数マージ命令は、2つのソースオペランドをマスクに基づいて結合します。 通常の算術命令とは異なり、マージはすべてのボディ要素(すなわち、 vstart から vl の現在のベクトル長までの要素の集合)に対して動作します。

vmerge 命令は、マスクされた命令(vm=0)としてエンコードされます。 この命令は、次のように2つのソースを組み合わせます。 マスク値がゼロの要素では、第1オペランドが書き込み要素にコピーされ、そうでない場合は第2オペランドが書き込み要素にコピーされます。 第1オペランドは常に vs2 で指定されるベクトルレジスタ群です。 第2オペランドは、 vs1 で指定されるベクトルレジスタ群、 rs1 で指定されるスカラ x レジスタ、または5ビットの符号拡張即値です。

vmerge.vvm vd, vs2, vs1, v0  # vd[i] = v0.mask[i] ? vs1[i] : vs2[i]
vmerge.vxm vd, vs2, rs1, v0  # vd[i] = v0.mask[i] ? x[rs1] : vs2[i]
vmerge.vim vd, vs2, imm, v0  # vd[i] = v0.mask[i] ? imm    : vs2[i]

ベクトル整数移動命令

ベクトル整数移動命令は、ソース・オペランドをベクトル・レジスタ・グループにコピーします。 vmv.v.v はベクトルレジスタ群をコピーしますが、 vmv.v.xvmv.v.i はスカラレジスタまたは即値をコピー先のベクトルレジスタ群のすべてのアクティブな要素に **転送**します。 これらの命令は、マスクされていない命令(vm=1)としてエンコードされます。 第1オペランド指定子(vs2)には、 v0 が含まれていなければならず、 vs2 に含まれるその他のベクトルレジスタ番号は 予約されています

vmv.v.v vd, vs1 # vd[i] = vs1[i]
vmv.v.x vd, rs1 # vd[i] = x[rs1]
vmv.v.i vd, imm # vd[i] = imm

ベクトル整数移動命令は、ベクトルマージ命令とエンコーディングが同じですが、 vm=1vs2=v0 となっています。

ボディ要素を変更しない vmv.v.vd, vd という形式は、そのレジスタが次に SEW と等しい EEW で使用されることを示すヒントとして使用されます。

注釈

SEWに従って内部表現をシャッフルすることができます。 データを内部的に再編成しない実装では、この命令を動的に省略し、NOP として扱うことができます。

ベクトル固定小数点算術演算命令

前述の整数演算命令群を拡張し、固定小数点演算がサポートされています。

固定小数点数とは、暗黙の分母を持つ分数の分子として解釈される2の補数の符号付きまたは符号なしの整数です。 固定小数点命令は分子に適用されることを意図しており、分母を管理するのはソフトウェアの責任です。 Nビットの要素には、-2^N-1^...+2^N-1^-1の範囲の2の補数の符号付き整数と、0...+2^N-1^-1の範囲の符号なし整数を格納できます。 固定小数点命令は、スケーリングと丸めをサポートすることで狭いオペランドの精度を維持し、 結果を出力フォーマット範囲に飽和させることでオーバーフローを処理することができます。

ベクトル単一幅飽和加算と飽和減算

符号付き整数と符号なし整数の両方に対して、飽和形式の整数の加算と減算が提供されます。 結果が出力先をオーバーフローする場合、結果は最も近い表現可能な値で置き換えられ、 vxsat ビットが設定されます。

# 符号なし整数の飽和加算
vsaddu.vv vd, vs2, vs1, vm   # ベクトル-ベクトル
vsaddu.vx vd, vs2, rs1, vm   # ベクトル-スカラ
vsaddu.vi vd, vs2, imm, vm   # ベクトル-即値

# 符号付き整数の飽和加算
vsadd.vv vd, vs2, vs1, vm   # ベクトル-ベクトル
vsadd.vx vd, vs2, rs1, vm   # ベクトル-スカラ
vsadd.vi vd, vs2, imm, vm   # ベクトル-即値

# 符号付き整数の飽和減算
vssubu.vv vd, vs2, vs1, vm   # ベクトル-ベクトル
vssubu.vx vd, vs2, rs1, vm   # ベクトル-スカラ

# 符号付き整数の飽和減算
vssub.vv vd, vs2, vs1, vm   # ベクトル-ベクトル
vssub.vx vd, vs2, rs1, vm   # ベクトル-スカラ

ベクトル単一幅平均加算と平均減算命令

平均化された加算・減算命令は、結果を1ビット右シフトし、 vxrm の設定に従って結果を丸める。 符号なしと符号ありのバージョンがあります。 vaadduvaadd では、結果にオーバーフローがあってはなりません。 vasubvasubu では、オーバーフローは無視され、結果は折り返されます。

# 平均加算

# 符号なし整数の平均加算
vaaddu.vv vd, vs2, vs1, vm   # roundoff*unsigned(vs2[i] + vs1[i], 1)
vaaddu.vx vd, vs2, rs1, vm   # roundoff*unsigned(vs2[i] + x[rs1], 1)

# 符号付き整数の整数加算
vaadd.vv vd, vs2, vs1, vm   # roundoff*signed(vs2[i] + vs1[i], 1)
vaadd.vx vd, vs2, rs1, vm   # roundoff*signed(vs2[i] + x[rs1], 1)

# 平均減算

# 符号なし整数の平均減算
vasubu.vv vd, vs2, vs1, vm   # roundoff*unsigned(vs2[i] - vs1[i], 1)
vasubu.vx vd, vs2, rs1, vm   # roundoff*unsigned(vs2[i] - x[rs1], 1)

# 符号付き整数の平均減算
vasub.vv vd, vs2, vs1, vm   # roundoff*signed(vs2[i] - vs1[i], 1)
vasub.vx vd, vs2, rs1, vm   # roundoff*signed(vs2[i] - x[rs1], 1)

丸めと飽和を用いたベクトル単一幅分数乗算

符号付き分数乗算命令は、2つのSEW入力の2*SEW積を生成し、その結果をSEW-1ビットだけ右にシフトし、これらのビットを vxrm に従って丸めた後、SEWビットに収まるように結果を飽和させます。 結果が飽和した場合は、 vxsat ビットがセットされます。

# 符号付き飽和丸め分数乗算
# 丸め演算については、vxrmの説明を参照のこと
vsmul.vv vd, vs2, vs1, vm  # vd[i] = clip(roundoff*signed(vs2[i]*vs1[i], SEW-1))
vsmul.vx vd, vs2, rs1, vm  # vd[i] = clip(roundoff*signed(vs2[i]*x[rs1], SEW-1))

注釈

結果は+2^2N-2^となり、2Nビットで保持する場合、符号ビットは1つ(ゼロ)となります。 他のすべての製品は、2Nビットで2つの符号ビットを持ちます。 N個の結果ビットでより高い精度を維持するために、製品はNよりも1ビット少ない数だけ右にシフトされ、 最大の大きさの結果は飽和しますが、他のすべての製品では結果の精度が1ビット増加します。

注釈

この操作は、丸めが単なる切り捨て(rdn)である場合には、 vmulhu および vmulhsu 命令によって部分的にカバーされます。

ベクトル単一幅スケーリングシフト命令

これらの命令は、入力値を右にシフトし、シフトしたビットを vxrm に従って丸めます。 スケーリングの右シフトには、ゼロ拡張型 (vssrl) と符号拡張型 (vssra) があります。 ベクトルまたはスカラのシフト量の値の下位lg2(SEW)ビットが使用され、シフト量の即値はゼロ拡張されます。

# 論理スケーリング右シフト
vssrl.vv vd, vs2, vs1, vm   # vd[i] = roundoff*unsigned(vs2[i], vs1[i])
vssrl.vx vd, vs2, rs1, vm   # vd[i] = roundoff*unsigned(vs2[i], x[rs1])
vssrl.vi vd, vs2, uimm, vm  # vd[i] = roundoff*unsigned(vs2[i], uimm)

# 算術スケーリング右シフト
vssra.vv vd, vs2, vs1, vm   # vd[i] = roundoff*signed(vs2[i],vs1[i])
vssra.vx vd, vs2, rs1, vm   # vd[i] = roundoff*signed(vs2[i], x[rs1])
vssra.vi vd, vs2, uimm, vm  # vd[i] = roundoff*signed(vs2[i], uimm)

ベクトル固定小数点幅縮小クリップ命令

vnclip 命令は、固定小数点の値をより狭い出力先に詰めるために使用されます。 この命令は、最終的な出力形式への丸め、スケーリング、および飽和をサポートします。

2番目の引数(ベクトル要素、スカラ値、即値)は、狭義のシフト命令のようにソースを右シフトする量を与え、スケーリングを行います。 ベクトルまたはスカラのシフト量の値の下位lg2(2*SEW)ビットが使用されます(例:SEW=64ビットからSEW=32ビットへの狭帯域化操作の場合は下位6ビット)。 即値形式は、シフト量の即値オペランドをゼロ拡張します。

# 符号なし幅縮小クリップ命令
#                                SEW                            2*SEW   SEW
 vnclipu.wv vd, vs2, vs1, vm  # vd[i] = clip(roundoff*unsigned(vs2[i], vs1[i]))
 vnclipu.wx vd, vs2, rs1, vm  # vd[i] = clip(roundoff*unsigned(vs2[i], x[rs1]))
 vnclipu.wi vd, vs2, uimm, vm # vd[i] = clip(roundoff*unsigned(vs2[i], uimm))

# 符号付き幅縮小クリップ
 vnclip.wv vd, vs2, vs1, vm   # vd[i] = clip(roundoff*signed(vs2[i], vs1[i]))
 vnclip.wx vd, vs2, rs1, vm   # vd[i] = clip(roundoff*signed(vs2[i], x[rs1]))
 vnclip.wi vd, vs2, uimm, vm  # vd[i] = clip(roundoff*signed(vs2[i], uimm))

vnclipu/vnclip では、丸め方は vxrm CSR で指定します。 丸めは、書き込みレジスタの最下位ビットを中心に、飽和演算の前に行われます。

vnclipu では、シフトされた丸められたソース値は符号なし整数として扱われ、 その結果が符号なし整数として見た書き込みレジスタをオーバーフローする場合は飽和します。

注釈

vxsat の値を設定する必要がない場合は、まず vmax を使って0に対する最大値を実行して負の数を取り除き、 次に vnclipu を使って結果の符号なしの値を出力先にクリップする、2つのベクトル命令列を使用できます。 SEWを変更するには、この2つの命令の間に、 vsetvli が必要です。

vnclip では、丸められたシフト元の値を符号付き整数として扱い、その結果が符号付き整数として見たときに 書き込みレジスタをオーバーフローさせるようであれば飽和を行います。

いずれかの書き込みレジスタの要素が飽和した場合、 vxsat レジスタに vxsat ビットが設定されます。

ベクトル浮動小数点命令

標準のベクトル浮動小数点命令では、16ビット、32ビット、64ビット、128ビットの要素をIEEE-754/2008互換の値として扱います。 ベクトル浮動小数点演算子のEEWが、サポートされているIEEE浮動小数点型に対応していない場合、 その命令のエンコーディングは予約されています。

ベクトル浮動小数点命令では、サポートされているベクトル浮動小数点の要素幅に対応する スカラ浮動小数点拡張が有効であることが必要です。

注釈

f レジスタでのスカラ半精度浮動小数点サポートも実装する必要があります。

浮動小数点ユニット状態フィールド mstatus.FSOff の場合、 ベクトル浮動小数点命令を実行しようとすると、不正な命令例外が発生します。 浮動小数点拡張状態(浮動小数点CSRや f レジスタなど)を変更するベクトル浮動小数点命令は、 mstatus.FSDirty に設定しなければなりません。

ベクトル浮動小数点命令は、NaNに関してはスカラ浮動小数点命令と同じ動作をします。

ベクトルスカラ演算のスカラ値は、 ベクトル算術演算命令エンコーディング で説明したように、 標準的なスカラ f レジスタから供給することができます。

ベクトル浮動小数点例外フラグ

アクティブな浮動小数点要素でのベクトル浮動小数点例外は、 fflags レジスタの標準FP例外フラグを設定します。 非アクティブな要素はFP例外フラグを設定しません。

ベクトル単一幅浮動小数点加減算命令

# 浮動小数点加算
vfadd.vv vd, vs2, vs1, vm   # ベクトル-ベクトル
vfadd.vf vd, vs2, rs1, vm   # ベクトル-スカラ

# 浮動小数点減算
vfsub.vv vd, vs2, vs1, vm   # ベクトル-ベクトル
vfsub.vf vd, vs2, rs1, vm   # ベクトル-スカラ vd[i] = vs2[i] - f[rs1]
vfrsub.vf vd, vs2, rs1, vm  # スカラ-ベクトル vd[i] = f[rs1] - vs2[i]

ベクトル幅拡張浮動小数点加減算命令

# 浮動小数点幅拡張加減算命令, 2*SEW = SEW +/- SEW
vfwadd.vv vd, vs2, vs1, vm  # ベクトル-ベクトル
vfwadd.vf vd, vs2, rs1, vm  # ベクトル-スカラ
vfwsub.vv vd, vs2, vs1, vm  # ベクトル-ベクトル
vfwsub.vf vd, vs2, rs1, vm  # ベクトル-スカラ

# 浮動小数点幅拡張加減算命令, 2*SEW = 2*SEW +/- SEW
vfwadd.wv  vd, vs2, vs1, vm  # ベクトル-ベクトル
vfwadd.wf  vd, vs2, rs1, vm  # ベクトル-スカラ
vfwsub.wv  vd, vs2, vs1, vm  # ベクトル-ベクトル
vfwsub.wf  vd, vs2, rs1, vm  # ベクトル-スカラ

ベクトル単一幅浮動小数点乗算除算命令

# 浮動小数点乗算
vfmul.vv vd, vs2, vs1, vm   # ベクトル-ベクトル
vfmul.vf vd, vs2, rs1, vm   # ベクトル-スカラ

# 浮動小数点除算
vfdiv.vv vd, vs2, vs1, vm   # ベクトル-ベクトル
vfdiv.vf vd, vs2, rs1, vm   # ベクトル-スカラ

# 浮動小数点逆除算 ベクトル = スカラ / ベクトル
vfrdiv.vf vd, vs2, rs1, vm  # scalar-vector, vd[i] = f[rs1]/vs2[i]

ベクトル幅拡張浮動小数点乗算命令

# 幅拡張浮動小数点乗算
vfwmul.vv    vd, vs2, vs1, vm # ベクトル-ベクトル
vfwmul.vf    vd, vs2, rs1, vm # ベクトル-スカラ

ベクトル単一幅浮動小数点複合乗算加算命令

複合乗算加算の4種類すべてが提供されており、加算値または最初の乗算値のいずれかのオペランドを上書きする2つの破壊的な形式があります。

# FP multiply-accumulate, overwrites addend
vfmacc.vv vd, vs1, vs2, vm    # vd[i] = +(vs1[i] * vs2[i]) + vd[i]
vfmacc.vf vd, rs1, vs2, vm    # vd[i] = +(f[rs1] * vs2[i]) + vd[i]

# FP negate-(multiply-accumulate), overwrites subtrahend
vfnmacc.vv vd, vs1, vs2, vm   # vd[i] = -(vs1[i] * vs2[i]) - vd[i]
vfnmacc.vf vd, rs1, vs2, vm   # vd[i] = -(f[rs1] * vs2[i]) - vd[i]

# FP multiply-subtract-accumulator, overwrites subtrahend
vfmsac.vv vd, vs1, vs2, vm    # vd[i] = +(vs1[i] * vs2[i]) - vd[i]
vfmsac.vf vd, rs1, vs2, vm    # vd[i] = +(f[rs1] * vs2[i]) - vd[i]

# FP negate-(multiply-subtract-accumulator), overwrites minuend
vfnmsac.vv vd, vs1, vs2, vm   # vd[i] = -(vs1[i] * vs2[i]) + vd[i]
vfnmsac.vf vd, rs1, vs2, vm   # vd[i] = -(f[rs1] * vs2[i]) + vd[i]

# FP multiply-add, overwrites multiplicand
vfmadd.vv vd, vs1, vs2, vm    # vd[i] = +(vs1[i] * vd[i]) + vs2[i]
vfmadd.vf vd, rs1, vs2, vm    # vd[i] = +(f[rs1] * vd[i]) + vs2[i]

# FP negate-(multiply-add), overwrites multiplicand
vfnmadd.vv vd, vs1, vs2, vm   # vd[i] = -(vs1[i] * vd[i]) - vs2[i]
vfnmadd.vf vd, rs1, vs2, vm   # vd[i] = -(f[rs1] * vd[i]) - vs2[i]

# FP multiply-sub, overwrites multiplicand
vfmsub.vv vd, vs1, vs2, vm    # vd[i] = +(vs1[i] * vd[i]) - vs2[i]
vfmsub.vf vd, rs1, vs2, vm    # vd[i] = +(f[rs1] * vd[i]) - vs2[i]

# FP negate-(multiply-sub), overwrites multiplicand
vfnmsub.vv vd, vs1, vs2, vm   # vd[i] = -(vs1[i] * vd[i]) + vs2[i]
vfnmsub.vf vd, rs1, vs2, vm   # vd[i] = -(f[rs1] * vd[i]) + vs2[i]

注釈

いくつかの非破壊的なFMAを提供することは可能でしょう。 しかし、これは3つの入力と別々の出力を持つ唯一のマスク可能な演算となります。

ベクトル幅拡張浮動小数点複合乗算加算命令

幅拡張された浮動小数点複合乗算加算命令は、すべて幅拡張された加算先を結果で上書きします。 乗算器の入力はすべてSEW幅で、加算器と出力は2*SEWビット幅です。

# FP widening multiply-accumulate, overwrites addend
vfwmacc.vv vd, vs1, vs2, vm    # vd[i] = +(vs1[i] * vs2[i]) + vd[i]
vfwmacc.vf vd, rs1, vs2, vm    # vd[i] = +(f[rs1] * vs2[i]) + vd[i]

# FP widening negate-(multiply-accumulate), overwrites addend
vfwnmacc.vv vd, vs1, vs2, vm   # vd[i] = -(vs1[i] * vs2[i]) - vd[i]
vfwnmacc.vf vd, rs1, vs2, vm   # vd[i] = -(f[rs1] * vs2[i]) - vd[i]

# FP widening multiply-subtract-accumulator, overwrites addend
vfwmsac.vv vd, vs1, vs2, vm    # vd[i] = +(vs1[i] * vs2[i]) - vd[i]
vfwmsac.vf vd, rs1, vs2, vm    # vd[i] = +(f[rs1] * vs2[i]) - vd[i]

# FP widening negate-(multiply-subtract-accumulator), overwrites addend
vfwnmsac.vv vd, vs1, vs2, vm   # vd[i] = -(vs1[i] * vs2[i]) + vd[i]
vfwnmsac.vf vd, rs1, vs2, vm   # vd[i] = -(f[rs1] * vs2[i]) + vd[i]

ベクトル浮動小数点平方根命令

これは単精度ベクトル-ベクトル命令です。

# 浮動小数点平方根命令
vfsqrt.v vd, vs2, vm   # ベクトル-ベクトル 平方根

ベクトル浮動小数点逆平方根推定命令

# 7ビットの浮動小数点逆平方根推定命令
vfrsqrt7.v vd, vs2, vm

これは、7ビットの精度で1/sqrt(x)の推定値を返す、単項のベクトル-ベクトル命令です。

注釈

後方互換性のために、ツールチェインのエイリアスとして以前の名前を残すことができます。

次の表は、すべてのクラスの浮動小数点入力に対するこの命令の動作を示しています。

例外的なケースでは、指数の下位ビットと合数の上位6ビット(先頭の1ビットの後)が連結され、以下のテーブルのアドレスに使用されます。 このテーブルの出力は、結果として得られる信号の上位7ビット(先頭の1ビットの後)となり、結果として得られる信号の残りの部分はゼロとなります。 正常でない入力は、ルックアップの前に正規化され、指数が適切に調整されます。 出力の指数は、結果が引数の平方根の逆数に近似するように選択されます。

より正確には、結果は以下のように計算されます。 正規化された入力指数を、入力が正常な場合は入力指数と等しく、そうでない場合は0から符号の先頭のゼロの数を引いた値とします。 入力が非正規の場合、正規化された入力指数は、先頭の1ビットを捨てて、入力指数を1から正規化された入力指数を引いて左にシフトすることで与えられます。 出力指数は floor((3*B - 1 - 正規化された入力指数) / 2) に等しくなります。 出力符号は入力符号に等しくなります。

次の表は、正規化された入力指数のLSBと正規化された入力記号の6つのMSBの関数として、出力記号の7つのMSBを示したもので、出力記号の他のビットはゼロです。

include::vfrsqrt7.adoc[]

注釈

および vfrsqrt7(0x7f765432 ({approx} 3.274e38)) = 0x1f820000 ({approx} 5.506e-20)となります。

注釈

将来的には、より高い推定精度の命令を定義することができます。

ベクトル浮動小数点逆数推定命令

# 7ビットの浮動小数点逆数推定命令
vfrec7.v vd, vs2, vm

注釈

要素の幅を表す ``e``**x** 記法との混同を招くと判断されました。 以前の名前は後方互換性のためにツールチェインのエイリアスとして保持することができます。

これは単項のベクトル・ベクトル命令で、7ビットの精度で1/xの推定値を返します。

次の表は、すべてのクラスの浮動小数点入力に対するこの命令の動作を示しています(*B*は指数バイアスです)。

注釈

少なくとも2^B-1^の大きさを持つ通常の入力は、サブノーマルの出力を生成し、他の通常の入力は通常の出力を生成します。

例外が発生しないケースでは、上位7ビットの仮数部(先頭の1ビットの後)が次の表のアドレスに使用されます。 このテーブルの出力は、結果として得られる信号の上位7ビット(先頭の1ビットの後)となり、結果として得られる信号の残りの部分はゼロとなります。 正常でない入力は、ルックアップの前に正規化され、指数が適切に調整されます。 出力の指数は、結果が引数の逆数に近似するように選択され、サブノーマル出力はそれに応じて非正規化されます。

より正確には、結果は以下のように計算されます。 正規化された入力指数を、入力が正常な場合は入力指数と等しく、そうでない場合は0から符号の先頭のゼロの数を引いたものとします。 正規化された出力指数は、(2*B - 1 - 正規化された入力指数)に等しくなります。 正規化された出力指数が[-1, 2*B]の範囲外である場合、その結果は上の表の例外的なケースの1つに対応します。

入力が非正規の場合、正規化された入力多項式は、入力多項式を1から正規化された入力指数を引いて左にシフトし、先頭の1ビットを捨てて与えられます。 それ以外の場合は、正規化された入力信号は入力信号と同じです。 次の表は、正規化された入力信号の7つのMSBの関数として、正規化された出力信号の7つのMSBを示したもので、正規化された出力信号の他のビットはゼロです。

include::vfrec7.adoc[]

正規化された出力指数が0または-1の場合、結果はサブノーマル数となります。 出力指数は0で、出力の仮数部は正規化された出力仮数部の左にある1ビットを連結し、 その量を正規化された出力指数から1を引いて右にシフトしたものになります。 それ以外の場合は、出力指数は正規化された出力指数に等しく、出力合言葉は正規化された出力仮数部に等しくなります。 出力符号は入力符号に等しくなります。

注釈

およびvfrec7(0x7f765432 ({approx} 3.274e38)) = 0x00214000 ({approx} 3.053e-39)となります。

注釈

将来的には、より高い推定精度の命令を定義することができます。

ベクトル浮動小数点MIN/MAX命令

ベクトル浮動小数点 vfmin および vfmax 命令は、RISC-V F/D/Q 拡張のバージョン 2.2 における対応するスカラ浮動小数点命令と同じ動作をします。

# 浮動小数点最小値
vfmin.vv vd, vs2, vs1, vm   # ベクトル-ベクトル
vfmin.vf vd, vs2, rs1, vm   # ベクトル-スカラ

# 浮動小数点最大値
vfmax.vv vd, vs2, vs1, vm   # ベクトル-ベクトル
vfmax.vf vd, vs2, rs1, vm   # ベクトル-スカラ

ベクトル浮動小数点符号挿入命令

スカラの符号挿入命令のベクトル版です。 結果は符号ビットを除くすべてのビットを、ベクトルの vs2 オペランドから取得します。

vfsgnj.vv vd, vs2, vs1, vm   # ベクトル-ベクトル
vfsgnj.vf vd, vs2, rs1, vm   # ベクトル-スカラ

vfsgnjn.vv vd, vs2, vs1, vm  # ベクトル-ベクトル
vfsgnjn.vf vd, vs2, rs1, vm  # ベクトル-スカラ

vfsgnjx.vv vd, vs2, vs1, vm  # ベクトル-ベクトル
vfsgnjx.vf vd, vs2, rs1, vm  # ベクトル-スカラ

注釈

アセンブリ疑似命令 vfneg.vd,vs = vfsgnjn.vv vd,vs,vs を定義することができます。

注釈

アセンブリ疑似命令 vfabs.vd,vs = vfsgnjx.vv vd,vs,vs を定義できます。

ベクトル浮動小数点比較命令

これらのベクトルFP比較命令は、2つのソースオペランドを比較し、比較結果をマスクレジスタに書き込みます。 書き込みマスクベクトルは常に単一のベクトルレジスタに保持され、その要素のレイアウトは マスクレジスタのレイアウト 節で説明されています。 書き込みマスクレジスタはソースベクトルマスクレジスタ(v0)と同じであってもかまいません。 比較はマスクレジスタを書き込むため、常にTail-agnosticポリシで動作します。

比較命令は、スカラ浮動小数点比較命令の文法に従います。 vmfeqvmfne は NaN 入力の信号に対してのみ無効な操作という例外を発生させます。 vmfltvmflevmfgtvmfge は、シグナリング NaN 入力とサイレント NaN 入力の両方で無効な操作に関する例外を発生させます。 vmfne は、どちらかのオペランドが NaN のときに出力要素に 1 を書き込みますが、 他の比較ではどちらかのオペランドが NaN のときに 0 を書き込みます。

# 等価比較
vmfeq.vv vd, vs2, vs1, vm  # ベクトル-ベクトル
vmfeq.vf vd, vs2, rs1, vm  # ベクトル-スカラ

# 非等価比較
vmfne.vv vd, vs2, vs1, vm  # ベクトル-ベクトル
vmfne.vf vd, vs2, rs1, vm  # ベクトル-スカラ

# 小なり比較
vmflt.vv vd, vs2, vs1, vm  # ベクトル-ベクトル
vmflt.vf vd, vs2, rs1, vm  # ベクトル-スカラ

# 以下比較
vmfle.vv vd, vs2, vs1, vm  # ベクトル-ベクトル
vmfle.vf vd, vs2, rs1, vm  # ベクトル-スカラ

# 大なり比較
vmfgt.vf vd, vs2, rs1, vm  # ベクトル-スカラ

# 以上比較
vmfge.vf vd, vs2, rs1, vm  # ベクトル-スカラ
比較            アセンブリ言語マッピング   アセンブリ言語疑似命令

va < vb         vmflt.vv vd, va, vb, vm
va <= vb        vmfle.vv vd, va, vb, vm
va > vb         vmflt.vv vd, vb, va, vm    vmfgt.vv vd, va, vb, vm
va >= vb        vmfle.vv vd, vb, va, vm    vmfge.vv vd, va, vb, vm

va < f          vmflt.vf vd, va, f, vm
va <= f         vmfle.vf vd, va, f, vm
va > f          vmfgt.vf vd, va, f, vm
va >= f         vmfge.vf vd, va, f, vm

va, vb ベクトルレジスタグループ
f      スカラ浮動小数点レジスタ

注釈

比較対象が非 NaN 定数の場合は、中間の2つの命令を省略できます。

# isgreater() の実装例
vmfeq.vv v0, va, va        # AがNaNでない場合にのみセットされる
vmfeq.vv v1, vb, vb        # BがNaNでない場合にのみセットされる
vmand.mm v0, v0, v1        # AとBに順序関係があるときのみセットされる
vmfgt.vv v0, va, vb, v0.t  #  従って、順序関係がある値の場合にのみフラグが設定される

注釈

より効率的なシーケンスでは、va の要素に quiet NaN が含まれ、vb の対応する要素に signaling NaN が含まれている場合に、 不正な例外を発生させることができません。

ベクトル浮動小数点分類命令

スカラ分類命令と同様に動作する単項のベクトル-ベクトル命令です。

vfclass.v vd, vs2, vm   # ベクトル-ベクトル

この命令で生成された10ビットのマスクは、結果要素の最下位ビットに配置されます。 結果の上位(SEW-10)ビットには0が入ります。 この命令はSEW=16b以上でのみ定義されているため、結果は常に書き込み要素に収まります。

ベクトル浮動小数点マージ命令

ベクトルスカラ浮動小数点マージ命令が提供されています。 この命令は、マスク値に関係なく、vstart から vl の現在のベクトル長までのすべてのボディ要素で動作します。

vfmerge.vfm 命令は、マスクされた命令 (vm=0) としてエンコードされます。 マスク値がゼロの要素では、最初のベクトルオペランドが書き込み要素にコピーされ、そうでない場合は、スカラ浮動小数点レジスタ値が書き込み要素にコピーされます。

vfmerge.vfm vd, vs2, rs1, v0  # vd[i] = v0.mask[i] ? f[rs1] : vs2[i]

ベクトル浮動小数点移動命令

ベクトル浮動小数点移動命令は、浮動小数点のスカラオペランドをベクトルレジスタグループに 転送 します。 この命令は、スカラ f レジスタ値をベクトルレジスタグループのすべてのアクティブな要素にコピーします。 この命令はマスクされた命令(vm=1)としてエンコードされます。 この命令は、vs2 フィールドが v0 に設定されていなければならず、vs2 の他の値はすべて予約されています。

vfmv.v.f vd, rs1  # vd[i] = f[rs1]

単一幅浮動所数点/整数型変換命令

浮動小数点値、符号なし整数、符号あり整数との間の変換操作が用意されており、変換元と変換先の両方がSEW幅である。

vfcvt.xu.f.v vd, vs2, vm       # 浮動小数点から符号なし整数への変換.
vfcvt.x.f.v  vd, vs2, vm       # 浮動小数点から符号付き整数への変換.

vfcvt.rtz.xu.f.v vd, vs2, vm   # 浮動小数点からtruncateを使用した符号なし整数への変換.
vfcvt.rtz.x.f.v  vd, vs2, vm   # 浮動小数点からtruncateを使用した符号付き整数への変換.

vfcvt.f.xu.v vd, vs2, vm       # 符号なし整数から浮動小数点への変換.
vfcvt.f.x.v  vd, vs2, vm       # 符号付き整数から浮動小数点への変換.

変換命令は、スカラ変換命令と同じ例外的な条件に関するルールに従います。 これらの変換は、ゼロに向かって丸める rtz の変種を除いて、frm の動的丸めモードを使用します。

注釈

浮動小数点から整数への切り捨て変換を高速化するために提供されています。

幅拡張浮動小数点/整数型変換命令

より小さな整数型や浮動小数点型のデータタイプを2倍の幅の型に変換する変換命令群が用意されています。

vfwcvt.xu.f.v vd, vs2, vm       # 浮動小数点を倍幅の符号なし整数に変換.
vfwcvt.x.f.v  vd, vs2, vm       # 浮動小数点を倍幅の符号付き整数に変換.

vfwcvt.rtz.xu.f.v vd, vs2, vm   # 浮動小数点をtruncateを使用した倍幅の符号なし整数に変換.
vfwcvt.rtz.x.f.v  vd, vs2, vm   # 浮動小数点をtruncateを使用した倍幅の符号付き整数に変換.

vfwcvt.f.xu.v vd, vs2, vm       # 符号なし整数を倍幅の浮動小数点に変換.
vfwcvt.f.x.v  vd, vs2, vm       # 符号付き整数を倍幅の浮動小数点に変換.

vfwcvt.f.f.v vd, vs2, vm        # 単一幅浮動小数点を倍幅の浮動小数点に変換.

これらの命令は、他の幅拡張命令(幅拡張ベクトル算術演算命令 参照)と同様に、ベクトルレジスタのオーバーラップに対する制約があります。

注釈

同等の結果と追加の例外フラグを発生させずに、いくつかの倍のステップとして実装することができます。

浮動小数点/整数 幅縮小型変換命令

vfncvt.xu.f.w vd, vs2, vm       # 倍幅の浮動小数点を符号付き整数に変換.
vfncvt.x.f.w  vd, vs2, vm       # 倍幅の浮動小数点を符号なし整数に変換.

vfncvt.rtz.xu.f.w vd, vs2, vm   # 倍幅の浮動小数点をtruncateを使用した符号なし整数に変換.
vfncvt.rtz.x.f.w  vd, vs2, vm   # 倍幅の浮動小数点をtruncateを使用した符号付き整数に変換.

vfncvt.f.xu.w vd, vs2, vm       # 倍幅の符号なし整数を浮動小数点に変換.
vfncvt.f.x.w  vd, vs2, vm       # 倍幅の符号付き整数を浮動小数点に変換.

vfncvt.f.f.w vd, vs2, vm        # 倍幅浮動小数点を単一幅の浮動小数点に変換.
vfncvt.rod.f.f.w vd, vs2, vm    # 倍幅浮動小数点をodd方向の丸めに使用して単一幅の浮動小数点に変換.

これらの命令は、他の幅縮小命令(ベクトル幅縮小算術演算命令 参照)と同様に、ベクトルレジスタのオーバーラップに制約があります。

注釈

変換は半減ステップのシーケンスで実装できます。 最後の半減ステップ以外が round-towards-odd (vfncvt.rod.f.f.w) を使用した場合、結果は同等に丸められ、同じ例外フラグが立てられます。 最後のステップだけは、希望する丸め方向を使用する必要があります。

ベクトルリダクション操作

ベクトルリダクションは、ベクトルレジスタ群の要素と、ベクトルレジスタの要素0に保持されているスカラを受け取り、 何らかの二項演算子を用いてリダクションを行い、ベクトルレジスタの要素0にスカラの結果を出力するものです。 スカラの入出力オペランドは、ベクトルレジスタ群ではなく、単一のベクトルレジスタの要素0に保持されるため、LMULの設定に関わらず、 どのベクトルレジスタもベクトルリダクションのスカラのソースまたは書き込みレジスタとなります。

書き込みのベクトルレジスタは、マスクレジスタを含むソースオペランドとオーバーラップすることができます。

注釈

スカラユニットでサポートされていない将来の型で将来のポリモーフィックな使用をサポートするために、 スカラオペランドと結果をベクトルレジスタの要素0に読み書きします。

ソースベクトルレジスタグループの非アクティブな要素はリダクションから除外されますが、 スカラオペランドはマスク値にかかわらず常に含まれます。

書き込みベクトルレジスタ内の他の要素(0 < index < VLEN/SEW)は末尾とみなされ、 現在のtail agnostic/undisturbedポリシで管理されます。

`vl`=0の場合は、操作は行われず、書き込みレジスタは更新されません。

ベクトルリダクション命令の例外は、常に vstart が0で報告されます。 ベクトルリダクション操作は、vstart が 0 でない場合、不正な命令の例外を発生させます。

縮小演算のアセンブラ構文は、vredop.vs です。.vs は、第1オペランドがベクトルレジスタグループで、 第 2 オペランドがベクトルレジスタの要素 0 に格納されたスカラであることを表します。

ベクトル単一幅整数リダクション命令

単一幅のリダクション命令のオペランドと結果は、すべて同じSEW幅になります。 算術加算ではオーバーフローは丸められます。

  # 単純なリダクション命令. [*]は全てのアクティブな要素を意味する:
vredsum.vs  vd, vs2, vs1, vm   # vd[0] =  sum( vs1[0] , vs2[*] )
vredmaxu.vs vd, vs2, vs1, vm   # vd[0] = maxu( vs1[0] , vs2[*] )
vredmax.vs  vd, vs2, vs1, vm   # vd[0] =  max( vs1[0] , vs2[*] )
vredminu.vs vd, vs2, vs1, vm   # vd[0] = minu( vs1[0] , vs2[*] )
vredmin.vs  vd, vs2, vs1, vm   # vd[0] =  min( vs1[0] , vs2[*] )
vredand.vs  vd, vs2, vs1, vm   # vd[0] =  and( vs1[0] , vs2[*] )
vredor.vs   vd, vs2, vs1, vm   # vd[0] =   or( vs1[0] , vs2[*] )
vredxor.vs  vd, vs2, vs1, vm   # vd[0] =  xor( vs1[0] , vs2[*] )

ベクトル幅拡張整数リダクション命令

符号なしの vwredsumu.vs 命令は、SEW幅のベクトル要素をゼロ拡張してから合計し、 次に2*SEW幅のスカラー要素を加え、その結果を2*SEW幅のスカラー要素に格納します。

vwredsum.vs 命令は、SEW幅のベクトル要素を符号拡張してから加算します。

  # 2倍幅での符号なしリダクション加算を倍幅でアキュムレートする
vwredsumu.vs vd, vs2, vs1, vm   # 2*SEW = 2*SEW + sum(zero-extend(SEW))

  # 符号付きリダクション加算を倍幅でアキュムレートする
vwredsum.vs  vd, vs2, vs1, vm   # 2*SEW = 2*SEW + sum(sign-extend(SEW))

ベクトル単一幅浮動小数点リダクション命令

# 単純なリダクション
vfredosum.vs vd, vs2, vs1, vm # 順序付き加算
vfredusum.vs vd, vs2, vs1, vm # 順序無し加算
vfredmax.vs  vd, vs2, vs1, vm # 最大値
vfredmin.vs  vd, vs2, vs1, vm # 最小値

ベクトル順序付き単一幅浮動小数点リダクション加算命令

vfredosum 命令は、vs1[0] のスカラーから順に、 浮動小数点値を要素順に合計しなければなりません--つまり、以下のように計算を行います。

vd[0] = `(((vs1[0] + vs2[0]) + vs2[1]) + ...) + vs2[vl-1]`

ここで各加算は、例外フラグの発生や特別な値の生成・伝搬という点で、スカラ浮動小数点演算命令と同じ動作をします。

演算がマスクされている場合(vm=0)、マスクされていない要素は結果や例外フラグに影響を与えません。

注釈

この動作は、スカラの加算ループを自動ベクトル化する際のNaN、例外、丸めの処理と同一です。

ベクトル順序無し単一幅浮動小数点リダクション加算命令

順序無しリダクション命令である vfredusum は、リダクションを実行する際の実装の自由度を高めます。

実装では、ソースのベクトルレジスタ群(vs2)とソースのスカラー値(vs1[0])の要素を入力とし バイナリ演算子ノードで構成されるリダクションツリーと同等の結果を生成する必要があります。 ツリー内の各演算子は、2つの入力を受け入れ、1つの結果を生成します。 各演算子は、まず、RISC-Vのスカラ浮動小数点加算として、指数の範囲と精度が無限大の正確な和を計算し、 次に、この正確な和を、SEWで示される要素浮動小数点フォーマットと少なくとも同じ範囲と精度を持つ浮動小数点フォーマットに変換し、 現在アクティブな浮動小数点ダイナミック丸めモードを用いて丸めます。 各演算子の結果には、異なる浮動小数点の範囲と精度を選択することができます。 一方の入力が、マスクされた要素やアクティブなベクトル長を超えた要素からのみ得られるノードは、 その入力を適切なEEWの加法単位元として扱うか、あるいは単に他方の入力をその出力にコピーすることができます。 ツリーのルートノードからの丸められた結果は、SEW で示される標準的な浮動小数点フォーマットに変換されます(動的丸めモードを使用して再度丸められます)。 実装では、最終結果に加法単位元を加えることができます。

加法単位元は、切り捨て(-{inf}方向)の場合は+0.0、その他の丸め方の場合は-0.0です。

リダクションツリーの構造は、vtypevl に与えられた値に対して決定的でなければなりません。

注釈

特に、アクティブな要素がなく、スカラー入力がNaNの場合、実装はNaNを正規化し、NaNがシグナリングの場合は、無効な例外フラグを設定することが許可されています。 また、vfredosum のように、元のNaNを通過させ、例外フラグを設定しないことも可能です。

ベクトル単一幅浮動小数点最大・最小リダクション

注釈

その際、例外フラグは設定されず、NaNの処理も行われません。

ベクトル幅拡張浮動小数点リダクション命令

リダクション加算命令における幅拡張の形式は、倍幅のデータの読み書きを行います。。

# 単純なリダクション
vfwredosum.vs vd, vs2, vs1, vm # 順序付きリダクション加算
vfwredusum.vs vd, vs2, vs1, vm # 順序なしリダクション加算命令

SEW幅の要素のリダクション操作は単一幅で行われ、vs2 の要素は2*SEWに拡張されて2*SEWビットのアキュムレータに加算されます。

注釈

vfwredusum.vsvfredusum.vs と同様に動作します。

ベクトルマスク命令

ベクトルレジスタに格納されているマスクを操作するための命令がいくつか提供されています。

ベクトルマスクレジスタ論理命令

ベクトルマスクレジスタ論理命令は、マスクレジスタに対して演算を実行します。 マスクレジスタの各要素は1ビットであり、従ってこれらの命令は vtype フィールド内の vlmul の設定に関係なく単一のベクトルレジスタを操作します。 これらの命令は vlmul の設定を変更しません。 書き込みベクトルレジスタはソースベクトルレジスタと同一である可能性があります。

他のベクトル命令と同様に、vstart インデックスよりも小さな要素は変更されず、命令実行後には vstart の値は0にリセットされます。 ベクトルマスク論理命令は常にマスクは適用されず、従って非アクティブ要素はありませんん。vm=0 に相当するエンコーディングは予約されています。 vl 以降のマスク要素、つまり末尾エレメントは常にtail-agnosticポリシに基づいて更新されます。

vmand.mm vd, vs2, vs1     # vd.mask[i] =   vs2.mask[i] &&  vs1.mask[i]
vmnand.mm vd, vs2, vs1    # vd.mask[i] = !(vs2.mask[i] &&  vs1.mask[i])
vmandnot.mm vd, vs2, vs1  # vd.mask[i] =   vs2.mask[i] && !vs1.mask[i]
vmxor.mm  vd, vs2, vs1    # vd.mask[i] =   vs2.mask[i] ^^  vs1.mask[i]
vmor.mm  vd, vs2, vs1     # vd.mask[i] =   vs2.mask[i] ||  vs1.mask[i]
vmnor.mm  vd, vs2, vs1    # vd.mask[i] = !(vs2.mask[i] ||  vs1.mask[i])
vmornot.mm  vd, vs2, vs1  # vd.mask[i] =   vs2.mask[i] || !vs1.mask[i]
vmxnor.mm vd, vs2, vs1    # vd.mask[i] = !(vs2.mask[i] ^^  vs1.mask[i])

一般的に使用されるマスク論理操作のために、いくつかのアセンブラ疑似命令が定義されています。

vmmv.m vd, vs  => vmand.mm vd, vs, vs  # Copy mask register
vmclr.m vd     => vmxor.mm vd, vd, vd   # Clear mask register
vmset.m vd     => vmxnor.mm vd, vd, vd  # Set mask register
vmnot.m vd, vs => vmnand.mm vd, vs, vs  # Invert bits

注釈

ビットが解釈無しにコピーされるため "mv"と読んだ方が整合性があります。 vmcpy.m アセンブラ疑似命令は互換性のために残されています。

8つのマスク論理命令は2つの入力マスクに対する任意の16個のバイナリ論理演算を実行することができます。

注釈

次のマスクされたベクトル演算と簡単に融合できるように設計されています。

ベクトルマスクPopカウント vpopc

vpopc.m rd, vs2, vm

ソースオペランドは、 マスクレジスタのレイアウト 節で説明されているように、マスクレジスタの値を保持する単一のベクトルレジスタです。

vpopc.m 命令は、ベクトルソースマスクレジスタのアクティブ要素のうち、値が1であるマスク要素の数を数え、その結果をスカラの x レジスタに書き込みます。

この操作はマスク下で行うことができ、その場合はマスクされた要素のみがカウントされます。

vpopc.m rd, vs2, v0.t # x[rd] = sum**i ( vs2.mask[i] && v0.mask[i] )

vpopc.m 上の例外は、常に vstart が 0 で通知されます。 vpopc 命令は、vstart が0でない場合、不正命令例外を発生させます。

vfirst find-first-set マスクビット命令

vfirst.m rd, vs2, vm

vfirst 命令は、ソースマスクベクトルの中から、値1を持つ最も低い番号のアクティブな要素を見つけ、その要素のインデックスをGPRに書き込みます。 値が1のアクティブな要素がない場合は、-1が書き込まれます。

ベクトルの長さはどのような実装でも2^(XLEN-1)^ を超えることはありませんので、ソフトウェアは負の値(最上位ビットの設定)があれば、 要素が見つからないと仮定することができます。

vfirst の例外は常に 0 の vstart で報告されます。 vstart が 0 でない場合、vfirst 命令は不正命令例外を発生させます。

vmsbf.m set-before-firstマスクビット

   vmsbf.m vd, vs2, vm

# 例

    7 6 5 4 3 2 1 0   要素番号

    1 0 0 1 0 1 0 0   v3 の値
                      vmsbf.m v2, v3
    0 0 0 0 0 0 1 1   v2 の値

    1 0 0 1 0 1 0 1   v3 の値
                      vmsbf.m v2, v3
    0 0 0 0 0 0 0 0   v2

    0 0 0 0 0 0 0 0   v3 
                      vmsbf.m v2, v3
    1 1 1 1 1 1 1 1   v2

    1 1 0 0 0 0 1 1   v0 の値
    1 0 0 1 0 1 0 0   v3 の値
                      vmsbf.m v2, v3, v0.t
    0 1 x x x x 1 1   v2 の値

vmsbf.m 命令は、マスク・レジスタを入力とし、結果をマスク・レジスタに書き込みます。 この命令は、1である最初のソース要素の前にあるすべてのアクティブなマスク要素に1を書き込み、 その要素とそれに続くすべてのアクティブな要素に0を書き込みます。 ソースベクトルにセットビットがない場合、書き込みレジスタのすべてのアクティブ要素に1が書き込まれます。

書き込みマスクレジスタの末尾要素はtail-agnosticポリシに基づいて更新されます。

vmsbf.m の例外は、常に vstart =0の状態で報告されます。 vmsbf 命令は、vstart が 0 でない場合、不正命令例外を発生します。

書き込みレジスタはソースレジスタをオーバラップすることは出来ません。 マスク付き命令の場合、v0 マスクレジスタとオーバラップすることは出来ません。

vmsif.m set-including-first マスクビット命令

ベクトルset-including-first命令はset-before-first命令と似ていますが、 セットビットを含めるところが異なります。

   vmsif.m vd, vs2, vm

# 例

    7 6 5 4 3 2 1 0   要素番号

    1 0 0 1 0 1 0 0   v3 の値
                      vmsif.m v2, v3
    0 0 0 0 0 1 1 1   v2 の値

    1 0 0 1 0 1 0 1   v3 の値
                      vmsif.m v2, v3
    0 0 0 0 0 0 0 1   v2

    1 1 0 0 0 0 1 1   v0 の値
    1 0 0 1 0 1 0 0   v3 の値
                      vmsif.m v2, v3, v0.t
    1 1 x x x x 1 1   v2 の値

書き込みマスクレジスタの末尾要素はtail-agnosticポリシに基づいて更新されます。

vmsif.m の例外は、常に vstart =0の状態で報告されます。 vmsif 命令は、vstart が 0 でない場合、不正命令例外を発生します。

書き込みレジスタはソースレジスタをオーバラップすることは出来ません。 マスク付き命令の場合、v0 マスクレジスタとオーバラップすることは出来ません。

vmsof.m set-only-first マスクビット命令

set-only-firstベクトル命令はset-before-first命令と似ていますが、 ビットがセットされている最初の要素のみを設定するところが異なります。

   vmsof.m vd, vs2, vm

# 例

    7 6 5 4 3 2 1 0   要素番号

    1 0 0 1 0 1 0 0   v3 の値
                      vmsof.m v2, v3
    0 0 0 0 0 1 0 0   v2 の値

    1 0 0 1 0 1 0 1   v3 の値
                      vmsof.m v2, v3
    0 0 0 0 0 0 0 1   v2

    1 1 0 0 0 0 1 1   v0 の値
    1 1 0 1 0 1 0 0   v3 の値
                      vmsof.m v2, v3, v0.t
    0 1 x x x x 0 0   v2 の値

書き込みマスクレジスタの末尾要素はtail-agnosticポリシに基づいて更新されます。

vmsof.m の例外は、常に vstart =0の状態で報告されます。 vmsof 命令は、vstart が 0 でない場合、不正命令例外を発生します。

書き込みレジスタはソースレジスタをオーバラップすることは出来ません。 マスク付き命令の場合、v0 マスクレジスタとオーバラップすることは出来ません。

ベクトルマスク命令の使用例

以下はベクトル化されたデータに依存するループ終了コードです。

include::example/strcpy.s[lines=4..-1]
include::example/strncpy.s[lines=4..-1]

ベクトルIota命令

viota.m 命令は、ソースベクトルマスクレジスタを読み込み、書き込みベクトルレジスタグループの各要素に マスク・レジスタの要素のうち、インデックスがその要素よりも小さい要素のすべてのビットの合計、 すなわち、マスク値のパラレルプレフィックス和を書き込みます。

この命令はマスクを使用することができます。この場合アクティブな要素のみが 加算に使用されます。

viota.m vd, vs2, vm

# 例

    7 6 5 4 3 2 1 0   要素数

    1 0 0 1 0 0 0 1   v2 の値
                      viota.m v4, v2 # Unmasked
    2 2 2 1 1 1 1 0   v4 の結果

    1 1 1 0 1 0 1 1   v0 の値
    1 0 0 1 0 0 0 1   v2 の値
    2 3 4 5 6 7 8 9   v4 の値
                      viota.m v4, v2, v0.t # Masked, vtype.vma=0
    1 1 1 5 1 7 1 0   v4 の値

SEWが結果の値よりも大きい場合は、結果値をゼロ拡張して出力要素を埋めます。 結果値が出力先のSEWをオーバーフローする場合は、最下位のSEWビットが保持されます。

viota.m の例外は、常に vstart =0として報告され、例外ハンドラの後に再開するときは、常に最初から実行が再開されます。 vstart が 0 でない場合は、不正命令例外が発生します。

書き込みレジスタグループはソース・レジスタと重なることはできず、マスクされている場合はマスク・レジスタ (v0) と重なることはできません。

注釈

1つ目の理由は、時間的に長いベクトル・レジスタを持ち、ベクトル・レジスタのリネームを行わない実装において、WARハザードの回避を容易にするためです。 第二に、例外が単純化された後に実行を再開することを可能にするためです。

viota.m 命令は、メモリ・スキャッタ命令(インデックス・ストア)と組み合わせて、 ベクトル圧縮機能を実行することができます。

      # 入力メモリ配列から、非ゼロの要素を圧縮して出力メモリ配列に格納する
    #
    # size*t compact*non*zero(size*t n, const int* in, int* out)
    # {
    #   size**t i;
    #   size**t count = 0;
    #   int *p = out;
    #
    #   for (i=0; i<n; i++)
    #   {
    #       const int v = *in++;
    #       if (v != 0)
    #           *p++ = v;
    #   }
    #
    #   return (size**t) (p - out);
    # }
    #
    # a0 = n
    # a1 = &in
    # a2 = &out

compact*non*zero:
    li a6, 0                      # 非ゼロ要素のカウンタをクリアする
loop:
    vsetvli a5, a0, e32, m8, ta, ma   # 32-bit整数
    vle32.v v8, (a1)               # 入力ベクトルをロードする
      sub a0, a0, a5               # ロードした要素数を減算する
      slli a5, a5, 2               # 4倍する
    vmsne.vi v0, v8, 0             # 非ゼロの場所を特定する
      add a1, a1, a5               # 入力ポインタを進める
    vpopc.m a5, v0                 # v0中の非ゼロ値を数える
    viota.m v16, v0                # アクティブ要素の出力オフセットを取得する
      add a6, a6, a5               # 要素数を加算する
    vsll.vi v16, v16, 2, v0.t      # オフセットを4バイト分乗算する
      slli a5, a5, 2               # 非ゼロの要素の数を4バイト分乗算する
    vsuxei32.v v8, (a2), v16, v0.t # スケールしたviotaの結果をマスクに基づいてメモリに書き込む
      add a2, a2, a5               # 出力ポインタを進める
      bnez a0, loop                # これ以上あるか?

      mv a0, a6                    # カウント数を返す
      ret

vid.v 命令は、各要素のインデックスを、0から vl -1までの書き込みベクトルレジスタグループに書き込みます。

vid.v vd, vm  # 要素のインデックスを書き込みレジスタに書き込む

この命令はマスクを使用することができます。

この命令の vs2 フィールドは v0 を設定しなければなりません、 そうでない場合のエンコーディングは 予約されています

結果がSEWよりも小さいビット幅である場合、ゼロ拡張して書き込み要素に書き込まれます。 結果がSEWよりも大きい場合、下位のSEWビットが保持されます。

注釈

同じデータパスを使用して、暗黙的なマスクソースを使用することで実装することができます。

ベクトル組み合わせ命令

ベクトルレジスタ内の要素を移動させるために、さまざまな並べ替え命令が用意されています。

整数スカラ移動命令

整数スカラ読み込み・書き込み命令は、スカラ x レジスタとベクトルレジスタの要素0との間で1つの値を転送します。 この命令はLMULやベクトルレジスタグループを無視します。

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

vmv.x.s は SEW 幅の単一要素をソースベクトルレジスタのインデックス0から書き込み整数レジスタにコピーする命令です。 SEW > XLENの場合、最下位のXLENビットが転送され、上位のSEW-XLENビットは無視されます。 SEW < XLENの場合、値はXLENビットに符号拡張されます。

vmv.s.x 命令は、スカラ整数レジスタを書き込みベクトルレジスタの要素 0 にコピーします。 SEW < XLENの場合、最下位のビットがコピーされ、XLEN-SEWの上位ビットは無視されます。 SEW > XLENの場合、値はSEWビットに符号拡張されます。 書き込みベクトルレジスタ内の他の要素 ( 0 < index < VLEN/SEW ) は 現在の末尾agnostic/undisturbedポリシを使用して、末尾要素として扱われます。 vstart {ge}の場合 vl の場合、操作は行われず、書き込みレジスタは更新されません。

vmv.x.svmv.s.x のマスク付きバージョン (vm=0) に対応するエンコーディングは予約されています。

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

浮動小数点スカラの読み込み・書き込み命令は、スカラ f レジスタとベクトルレジスタの要素0との間で1つの値を転送します。 この命令は、LMULとベクトルレジスタグループを無視します。

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

vfmv.f.s は、SEW幅の要素を1つだけ、コピー元のベクトルレジスタの要素0からコピー先のスカラ浮動小数点レジスタにコピーします。

vfmv.s.f 命令は、スカラ浮動小数点レジスタを、書き込みベクトルレジスタの要素0にコピーします。 書き込みベクトルレジスタの他の要素(0 < index < VLEN/SW)は、現在のTail-agnostic/Undisturbedポリシを用いて、末尾要素として扱われます。 もし、vstart {ge} vl の場合、操作は行われず、書き込みレジスタは更新されません。

vfmv.f.svfmv.s.f のマスクバージョン(vm=0)に対応するエンコーディングは予約されています。

ベクトルスライド命令

スライド命令は、ベクトルレジスタグループの要素を上下に移動させます。

注釈

実装では、特定のオフセット値を vslideup および vslidedown に最適化することができます。 特に、2の累乗オフセットは、他のオフセットよりも大幅に高速に動作する可能性があります。

すべての vslideup, vslidedown, v[f]slide1up, v[f]slide1down 命令において、vstart {ge} vl の場合、 この命令は操作を行わず、書き込みベクトルレジスタを変更せずに残します。

末尾要素については、Tail agnostic/undisturbedポリシに基づいて適用されます。

スライド命令はマスクされていて、マスク要素 i が、書き込み 要素 i を書き込むかどうかを制御している場合があります。 非アクティブな要素については、Mask undisturbed/agnosticポリシに従います。

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

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

vslideup では、vl の値で、書き込みレジスタの最大要素数を指定します。 書き込みレジスタの開始インデックス (OFFSET) は、rs1 で指定された x レジスタの符号なし整数、 または XLEN ビットにゼロ拡張された 5 ビットの即値のいずれかを使用して指定できます。 XLEN > SEWの場合、OFFSET はSEWビットに切り捨てられません。 マスキングされておらず、かつ、 OFFSET < vl であれば、 OFFSET から vl -1 までの出力要素が書き込まれます。

 vslideup の書き込みレジスタ要素の動作

 OFFSET is amount to slideup, either from x register or a 5-bit immediate

                  0 <  i < max(vstart, OFFSET)  Unchanged
max(vstart, OFFSET) <= i < vl                   vd[i] = vs2[i-OFFSET] if v0.mask[i] enabled
                 vl <= i < VLMAX                Follow tail policy

vslideup の書き込みベクトルレジスタグループはソースベクトルレジスタグループと重ならないようにしてください。

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

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

vslidedown では、vl の値は、書き込まれる宛先要素の最大数を指定します。 vl を過ぎた残りの要素は、現在の末尾ポリシ(Tail Agnostic とVector Mask Agnostic vta と vma 節)に従って処理されます。

ソースの開始インデックス (OFFSET) は、rs1 で指定された x レジスタの符号なし整数を使用して指定するか、 または XLEN ビットまでゼロ拡張された 5 ビットの即値を使用します。 XLEN > SEWの場合、*OFFSET*はSEWビットに切り捨てられません。

vslidedown behavior for source elements for element i in slide
                 0 <= i+OFFSET < VLMAX   src[i] = vs2[i+OFFSET]
             VLMAX <= i+OFFSET           src[i] = 0

vslidedown behavior for destination element i in slide
                 0 <  i < vstart         Unchanged
            vstart <= i < vl             vd[i] = src[i] if v0.mask[i] enabled
                vl <= i < VLMAX          Follow tail policy

ベクトル Slide1up

スライドのバリエーションとして、要素を1つ移動するだけでなく、 空いた要素の位置にスカラーの整数値を挿入できるものが用意されています。

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

vslide1up 命令は、要素0がアクティブであれば、x レジスタの引数を書き込みベクトルレジスタグループの要素0に配置し、 そうでなければ、書き込みベクトル要素の更新は、現在のMask Agnostic/Undisturbed ポリシに従います。 XLEN < SEWの場合、値はSEWビットに符号拡張されます。 XLEN > SEWの場合、最下位のビットがコピーされ、SEW-XLENの上位ビットは無視されます。

残りのアクティブな vl -1 要素は、ソースベクトルレジスタ群のインデックス i から書き込みベクトルレジスタ群のインデックス *i*+1 にコピーオーバーされます。

vl レジスタはソースの値で更新される書き込みベクトルレジスタ要素の最大数を指定し、 vl を超えた残りの要素は現在の末尾ポリシ(Tail Agnostic とVector Mask Agnostic vta と vma 節)に従って処理されます。

 vslide1up behavior

                  i < vstart  unchanged
              0 = i = vstart  vd[i] = x[rs1] if v0.mask[i] enabled
max(vstart, 1) <= i < vl      vd[i] = vs2[i-1] if v0.mask[i] enabled
            vl <= i < VLMAX   Follow tail policy

vslide1up 命令は、書き込みベクトルレジスタグループがソースのベクトルレジスタグループと重ならないことが必要です。 それ以外の場合は、命令のエンコーディングは予約されています。

vfslide1up 命令は類似して定義されていますが、そのスカラ引数を f レジスタから供給します。

ベクトル Slide1down 命令

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

vl レジスタはソースの値で書き込まれる書き込みベクトルレジスタ要素の最大数を指定し、 vl を超えた残りの要素は現在の末尾ポリシ(Tail Agnostic とVector Mask Agnostic vta と vma 節)に従って処理されます。

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

vslide1down 命令は、要素 vl-1 がアクティブであれば、x レジスタの引数を書き込みベクトルレジスタの位置 vl -1に置き、 そうでなければ、書き込み要素は変更されません。 XLEN < SEWの場合、値はSEWビットに符号拡張されます。 XLEN > SEWの場合、最下位のビットがコピーされ、SEW-XLENの上位ビットは無視されます。

vslide1down behavior

                    i < vstart  unchanged
          vstart <= i < vl-1    vd[i] = vs2[i+1] if v0.mask[i] enabled
          vstart <= i = vl-1    vd[vl-1] = x[rs1] if v0.mask[i] enabled
              vl <= i < VLMAX   Follow tail policy

vfslide1down 命令は同様に定義されていますが、スカラー引数は f レジスタから供給されます。

注釈

これは、デバッガが複数回の vslide1down の呼び出しを繰り返すことで、ゆっくりではありますが、ベクトルレジスタの内容を変更するためのパスを提供します。

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

ベクトル・レジスタ・ギャザー命令は、第2のソースベクトルレジスタグループによって与えられる位置から第1のソースベクトルレジスタグループの要素を読み出します。 第2ベクトルのインデックス値は、符号なし整数として扱われます。 ソースベクトルは、vl にかかわらず、任意のインデックス < VLMAX で読み取ることができます。 書き込みレジスタに書き込む最大要素数は vl で与えられ、vl を過ぎた残りの要素は現在の末尾要素のポリシ (Tail Agnostic とVector Mask Agnostic vta と vma 節) に従って処理されます。 この操作はマスクすることができ、非アクティブな要素に対しては、マスク undisturbed/agnostic ポリシに従います。

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

vrgather.vv 形式では、データとインデックスの両方に SEW/LMUL を使用しています。 また、vrgatherei16.vv 形式では、vs2 のデータには SEW/LMUL を使用しますが、 vs1 のインデックスには EEW=16 と EMUL = (16/SEW)*LMUL を使用します。

注釈

また,vrgatherei16 形式では,64K 個の要素のインデックスを作成することができ, SEW > 16 の場合にインデックスを保持するために必要なレジスタの容量を減らすために使用することもできます。

要素のインデックスが範囲外の場合 ( vs1[i] {ge} VLMAX )、要素の値は 0 を返します。

レジスタギャザーのベクトルスカラ形式とベクトル即値形式も用意されています。 これらは、与えられたインデックスでソース・ベクトルから1つの要素を読み、この値を書き込みベクトルレジスタの最初のアクティブの要素に書き込みます。 スカラレジスタのインデックス値と、XLENビットまでゼロ拡張された即値は、符号なし整数として扱われます。 XLEN > SEWの場合,インデックス値はSEWビットまで切り捨てられません。

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 命令では、書き込みベクトルレジスタグループはソースベクトルレジスタグループとオーバーラップすることはできません。

ベクトル圧縮命令

ベクトル圧縮命令は、ソースベクトルレジスタ群からベクトルマスクレジスタによって選択された要素を、 書き込みベクトルレジスタ群の先頭の連続した要素にパックすることができます。

vcompress.vm vd, vs2, vs1  # vs1で有効なvs2の要素をvdに圧縮する

vs1 で指定されたベクトルマスクレジスタは、ベクトルレジスタグループ vs2 の最初の vl 要素のうち、 どの要素を抽出して、ベクトルレジスタ vd の先頭の連続した要素にパックすべきかを示します。 vd の残りの要素は、現在の末尾要素ポリシ (Tail Agnostic とVector Mask Agnostic vta と vma 節) に従って、末尾要素として扱われます。

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)は予約されています。

書き込みベクトルレジスタグループはソースベクトルレジスタグループやソースマスクレジスタと重なることはできません。

非ゼロの vstartvcompress 命令を実行すると、不正命令例外が発生します。

注釈

実装ではこれを行わずに要素 0 から再起動することを想定しています。

vdecompress の合成

逆の操作を行う vdecompress 命令は定義されていませんが、この操作はiota命令とマスク付き vrgather 命令を用いて合成できます。

`vdecompress` の所望の動作
  7 6 5 4 3 2 1 0     # vid

        e d c b a     # パッキングされたベクトルの5要素
  1 0 0 1 1 1 0 1     # 8要素のベクトルマスク
  p q r s t u v w     # vdecompress実行前の書き込みレジスタ

  e q r d c b v a     # vdecompress実行後
# v0はマスクを保持している
# v1はパックデータを保持している
# v11は展開されたベクトルと結果を保持している
viota.m v10, v0                 # v0のマスクを使用してiotaを実行する
vrgather.vv v11, v1, v10, v0.t  # 書き込みレジスタを展開する
p q r s t u v w    # v11書き込みレジスタ
      e d c b a    # v1ソースレジスタ
1 0 0 1 1 1 0 1    # v0マスクレジスタ

4 4 4 3 2 1 1 0    # viota.m実行後のv10レジスタ
e q r d c b v a    # マスク付きviota.mを用いたvrgatherの書き込みレジスタ

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

vmv<nr>r.v 命令は、ベクトルレジスタ全体(VLENビット全て)をコピーし、 ベクトルレジスタグループ全体をコピーすることができます。 EEW=SEW、EMUL=`nr` 、実効長 evl =EMUL * VLEN/SEWのように動作します。

注釈

ベクトルレジスタをシャッフルすることを支援するためのものです。

注釈

代わりに、vstart {ge} evl の場合には要素は書き込まれません。

注釈

そのレジスタグループが次に SEW に等しい EEW でアクセスされることを示すヒントとして扱われます。

この命令はOPIVI命令としてエンコードされます。 コピーするベクトルレジスタの数は、 メモリ命令の nf フィールドと同じエンコーディングで simm フィールドの下位3ビットにエンコードされます。 nr フィールドの値は、1、2、4、8のいずれかでなければならず、その他の値は予約されています。

注釈

このエンコーディングが選ばれたのは、関連する vmerge エンコーディングに近いことと、vsmul 命令が即値フォームから恩恵を受ける可能性が低いことによります。

vmv<nr>r.v vd, vs2  # 一般的なフォーム

vmv1r.v v1, v2   #  v2をv1にコピーする
vmv2r.v v10, v12 #  v12をv10にコピーし、v13をv11にコピーする
vmv4r.v v4, v8   #  v8をv4に、v9をv5に、v10をv6に、v11をv7にコピーする
vmv8r.v v0, v8   #  v8をv0に、v9をv1に、... v15をv7にコピーする

ソースと書き込みのベクトルレジスタ番号は、ベクトルレジスタグループのサイズに合わせて適切にアラインメントする必要があり、 他のベクトルレジスタ番号とのエンコーディングは予約されています。

例外処理

ベクトル命令中の例外(同期例外または非同期割込みのいずれかが原因)では、 既存の *epc CSR には例外の発生したベクトル命令へのポインタが書き込まれ、 vstart CSR には例外の原因となった要素のインデックスが書き込まれます。

注釈

これは、IBM 3090のベクトル機能のスキームに似ています。 vstart CSRなしで前進性を確保するためには、実装は、ベクトル命令全体が例外を発生させることなく常にアトミックに完了することを保証しなければなりません。 これは、ストライド演算やスキャッタ/ギャザ演算、デマンドページングされた仮想メモリがある場合には、特に困難です。

正確なベクトル例外

正確なベクトル例外には以下の要件が必要です:

  • 例外の発生したベクトル命令よりも古い命令が結果をコミットしていること

  • 例外の発生したベクトル命令よりも新しい命令がアーキテクチャ状態を変更していないこと

  • 例外の発生したベクトル命令内で、 vstart CSR のインデックスより前の結果要素に影響を与える演算が結果をコミットしていること

  • 例外の発生したベクトル命令内で、 vstart CSR 以降の要素に影響を与える演算がアーキテクチャ状態を変更していないこと。ただし、影響を受けるベクトル命令を再起動して完了させても、正しい最終状態が得られる場合を除く。

最後の要件を緩和して、例外が報告された時点で vstart 以降の要素が更新されていても、 与えられた vstart から命令を再実行することでそれらの要素が正しく上書きされることを許可します。

非デバイスメモリ領域では、ベクトルストア命令が、同期例外の原因となった要素を超えて、メモリ内の要素を更新している可能性があります。 デバイスメモリ領域では、ベクトルストア命令中に同期例外を引き起こした要素と同じかそれ以上のインデックスで更新されていてはなりません。

上述の場合を除き、ベクトル命令は入力を上書きすることができますので、ほとんどの場合、 ベクトル命令の再起動は vstart の位置からでなければなりません。 しかし、ベクトル命令の実行結果が常に同一であり、どの場所からでも再起動できるようにするために、 この上書きを禁止するケースがいくつかあります。

実装では、vstart で報告された要素やセグメントについて、最終的に前進が保証されるようにしなければなりません。

不正確ベクトル例外

不正確なベクトル例外とは、正確ではない例外のことです。 特に、 *epc よりも新しい命令は結果をコミットしているかもしれませんし、 *epc よりも古い命令は実行を完了していないかもしれません。 不正確な例外は主に、エラーを報告して実行を終了することが適切な反応である場合に使用することを意図しています。

注釈

多くの組み込み機器では、致命的なエラーが発生したときには、再開可能な例外を必要としないため、 ベクトル命令のための不正確な例外のみを生成することを想定しています。

不正確な例外は、同期ベクトル例外によって引き起こされた例外のために、vstart で障害要素を報告しなければなりません。

正確・不正確選択可能な例外

プロファイルによっては、特権モードのビットを用意して、正確なベクトル例外と不正確ベクトル例外を選択することができます。 不正確なモードでは、高性能に動作しますが、エラーの原因を特定することが困難になる可能性があります。 一方、正確なモードでは、動作速度が遅くなりますが、不正確なモードと同じエラーが発生しない可能性があるものの、 エラーのデバッグが行いやすくなります。

スワップ可能な例外

別の例外モードでは、ベクトルユニットのスワップ可能な状態をサポートし、 例外時に特別な命令でベクトルユニットのマイクロアーキテクチャの状態を保存・復元することで、 不正確な例外の周辺でも実行を正しく継続できるようにします。

このメカニズムは、現在の標準拡張では定義されていません。

注釈

ベクトルユニットの実装から不透明なマイクロアーキテクチャの状態を保存・復元する標準的な方法を定義する可能性があります。

標準ベクトル拡張

このセクションでは、パブリックレビューのために提案される標準ベクトル拡張について説明します。 組み込み用途を目的とした小規模な拡張機能のセットには "Zve "という接頭辞を付け、 アプリケーションプロセッサ向けに設計された大規模なベクター拡張機能には1文字のVという拡張子を付けています。

初期のベクトル拡張は、暗号や機械学習などの様々な領域で追加のベクトル拡張を行うためのベースとして設計されています。

Zve*: 組み込みプロセッサ用のベクトル拡張

以下の5つの標準的な拡張機能は、さまざまな程度のベクトルサポートを提供するために定義されており、 組み込みプロセッサでの使用を目的としています。 これらの拡張機能は、XLEN=32 または XLEN=64 のベース ISA に追加することができます。 表には、各拡張機能の最小VLENとサポートされるEEW、およびサポートされる浮動小数点型を示しています。

全ての Zve* 拡張は正確な例外を持ちます。

すべてのZve*拡張は、8,16,32のEEWをサポートしており、Zve64*拡張は64のEEWもサポートしています。

すべての Zve* 拡張機能は、ベクトル構成命令 (コンフィグレーション設定命令 (vsetvli/vsetivl/vsetvl) 節) をサポートしています。

全ての Zve* 拡張は全てのベクトルロード・ストア命令(ベクトルロード・ストア命令 節)をサポートしていますが、 Zve64* 拡張は XLEN=32 の時のインデックス値に対する EEW=64 をサポートしていません。

すべての Zve* 拡張は、すべてのベクトル整数命令 (ベクトル整数算術演算命令 節) をサポートしています。 ただし、積の上位ワードを返す vmulh 整数乗算バリエーション (vmulh.vv, vmulh.vx, vmulhu.vv, vmulhu.vx, vmulhsu.vv, vmulhsu.vx ) は、Zve64* では EEW=64 に対応していません。

すべてのZve*拡張は、すべてのベクトル固定小数点演算命令(ベクトル固定小数点算術演算命令 )をサポートしています。 ただし、 vsmul.vvvsmul.vx は、Zve64*のEEW=64ではサポートされていません。

すべての Zve* 拡張は、すべてのベクトル整数の単一幅および幅拡張および幅縮小操作をサポートします (ベクトル単一幅整数リダクション命令 節, ベクトル幅拡張整数リダクション命令 節)。

全ての Zve* 拡張は全てのベクトルマスク命令をサポートします (ベクトルマスク命令 節)。

Zve32x と Zve64x が浮動小数点スカラ移動命令を実装していないことを除いて、 すべての Zve* 拡張はすべてのベクトル組み合わせ命令 (ベクトル組み合わせ命令 節) をサポートしています。

Zve32fおよびZve64f拡張は、スカラ・プロセッサがF拡張を実装し、EEW=32の浮動小数点オペランドに対するすべてのベクトル浮動小数点命令(ベクトル浮動小数点命令 節)を実装することを要求し、 サポートされているすべての整数EEWとの間の変換命令が提供されています。 EEW=32のベクトル単幅浮動小数点演算(ベクトル単一幅浮動小数点リダクション命令 節)をサポートしています。

Zve32d および Zve64d 拡張は、スカラ・プロセッサが D 拡張を実装し、EEW=32 または EEW=64 の浮動小数点オペランドに対するすべてのベクトル浮動小数点命令 (ベクトル浮動小数点命令 節) を実装する必要があります (幅拡張命令および FP32 と FP64 の間の変換を含む)。 EEW=32およびEEW=64のベクトル単幅浮動小数点演算(ベクトル単一幅浮動小数点リダクション命令 節)がサポートされており、 FP32からFP64への幅拡張リダクションもサポートされています。

V: アプリケーションプロセッサのためのベクトル拡張

1文字のV拡張は、アプリケーションプロセッサのプロファイルでの使用を目的としています。

V ベクトル拡張には正確なトラップをサポートします。

V ベクトル拡張は、VLEN {ge} 128 が必要です。

注釈

VLEN を大きくすると、短いベクターの場合にストリップマイニングコードを省略できる場合がありますが、 最小実装のサイズが大きくなります。 LMULを大きくすると、既知のサイズの長いアプリケーションベクターのストリップマイニングを回避することができますが、 利用可能なベクトルレジスタグループの数が少なくなりますので注意してください。 たとえば、LMULが8の場合、最大16個の64ビット要素を持つベクトルを、4つのベクトルレジスターグループを使用して、 ストリップマイニングを行わずに処理することができます。

V拡張は、8、16、32、および64のEEWをサポートしています。

V拡張は,ベクトルコンフィグレーション設定命令(vsetvli/vsetivl/vsetvl)をサポートしています。

V拡張は全てのロードストア命令をサポートしていますが(ベクトルロード・ストア命令 節) XLEN=32の時のインデックス値に関するEEW=64のV拡張はサポートされていません。

V拡張機能は、すべてのベクトル整数命令 (ベクトル整数算術演算命令 節) をサポートしています。

V 拡張機能は、すべてのベクトル固定小数点演算命令 (ベクトル整数算術演算命令 節) をサポートしています。

V拡張は、すべてのベクトル整数の単一幅および幅縮小演算をサポートしています(ベクトル単一幅整数リダクション命令 , ベクトル幅拡張整数リダクション命令 節)。

V 拡張機能は、すべてのベクトルマスク命令をサポートします (ベクトルマスク命令 節)。

V拡張は、すべてのベクトル組み合わせ命令をサポートしています(ベクトル組み合わせ命令 節)。

また、EEW=32 または EEW=64 の浮動小数点オペランドに対するすべてのベクトル浮動小数点命令 (ベクトル浮動小数点命令 節) を実装します (幅拡張命令およびFP32とFP64 間の変換を含む)。 EEW=32およびEEW=64のベクトル単一幅浮動小数点リダクション命令(ベクトル単一幅浮動小数点リダクション命令 ) は、FP32からFP64への幅拡張リダクションと同様にサポートされています。

ベクトル命令リスト

include::inst-table.adoc[]

include::vector-examples.adoc[]

include::calling-convention.adoc[]