CPUアーキテクチャがフラグレジスタを使用する理由(利点)


15

一部のCPUにはフラグレジスタ(ARM、x86、...)があり、他のCPUにはありません(MIPS、...)。ゼロレジスタと条件分岐を使用して符号やオーバーフローなどをチェックする代わりに、フラグ命令を更新するCMP命令の後に分岐命令が続く利点は何ですか?

回答:


11

レジスタの名前を変更する現代のマイクロアーキテクチャでは、フラグの実装コストまたはフラグの実装コストはかなり似ています。私が考えることができる主な違いは、いくつかのフラグは値の特性を示します(値は負ですか?値はゼロですか?値は偶数または奇数パリティを持っていますか?)が、いくつかは前の操作中に発生したイベントを表します(add命令にキャリーアウトまたはオーバーフローがありましたか?)これにより、32ビットアーキテクチャで64ビット加算をシミュレートする場合(または、 64ビットアーキテクチャ。)キャリーフラグのあるほとんどのアーキテクチャには、特別なものがあります。add-with-carry前の追加命令からのキャリーフラグを含む命令。これにより、フラグレジスタを備えた多くのアーキテクチャで、多精度演算のシミュレーションが比較的安価になります。

反対に、Nビットレジスタのゼロまたはゼロ以外のテストは、実際には驚くほど高価です。Nビットレジスタのゼロをテストするには、NビットNOR演算を実行する必要があります。計算にはレベルのロジックが必要です。フラグレジスタを使用するアーキテクチャでは、ALUステージの最後にゼロ/非ゼロ計算用の追加のロジックを使用すると、クロックが遅くなる(またはALUに2サイクルの動作を強制する)可能性があります。 SPARCのようなアーキテクチャには、各算術演算の2つのバージョンがあり、1つはフラグを設定し、もう1つは設定しませんでした。OログN

しかし、MIPSはここには何も保存しません。彼らは問題をどこか別の場所に移動しただけです。MIPSにはbranch-on-equal指示があります。これは、分岐がどの方向に進むかを決定する前に、分岐命令に実際にALUステージ(ビット単位のxor演算とそれに続くnor単一の等しい/等しくないビットまで減らすことなど)が必要であることを意味します。

DEC Alphaアーキテクチャは、トリックを使用して違いを分割しようとしました。DEC Alphaにはフラグレジスタがありませんでしたが、branch-on-equal命令もありませんでした。代わりに、分岐命令はすべて単一の汎用レジスターの状態を調べます。ありbranch-on-zerobranch-on-not-zerobranch-on-less-than-zeroトリックはあなたが他の64ビットがすべてゼロであるか否かを示しています余分な65ビットのレジスタのすべての一般的な目的を与えることができるということであるなど、。これにより、フラグレジスタを持つようになります。すべての分岐命令は、単一のビット(既に計算済み)を見て決定を下しますが、通常のALUでその余分なゼロインジケータービットを計算する方法に戻りますサイクル。(また、前の操作のキャリーフラグを見ただけでは、多精度の算術演算を行うことはできません。)


2
非CC設定操作は(私が理解していることから)コンパイラーの最適化であり、コンパイラーは、CC設定命令を、後者の命令によって値が上書きされることなく早期にスケジュールできるようにします。PowerPC750は、条件レジスタ(8つの4ビットレジスタ)をフロントエンドの近くに配置したため、分岐ターゲット命令キャッシュにヒットし、条件を十分早く利用できるようにすると、ペナルティなしで分岐を解決できます。(AT&TのCRISPも初期のブランチ解決を悪用しました。)CCが少量で専門化されているため、これはより実用的です。
ポールA.クレイトン14年

詳細:すべてのフラグ計算が等しくなるわけではありません。CPUに従来のNZVCフラグがあると想像してください。すべてのALU命令でフラグの更新が許可されている場合、加算器/減算器といくつかのマルチプレクサの後にフラグ生成を配置する必要があります。ネガティブフラグは簡単で、MSBのみですが、ゼロフラグは高価で、すべてのビットに依存します。フラグを比較(およびビットテスト)命令に制限すると、減算の結果を待たずに、ソースオペランドの並列XORでゼロフラグを計算できます。追加後のZフラグの計算はほとんど役に立ちません。
TEMLIB 14年

7

1 ISAの観点から

  1. フラグのみを設定するテスト命令を使用することは、レジスタが不足しているアーキテクチャでレジスタのプレッシャーを軽減する方法にすぎません。十分なレジスタがある場合は、そのうちの1つを変更し、結果を無視します。入力値が0のレジスタ0を持つトリックは、レジスタの1つを0に固定する方が命令数を増やすよりも優れている場合に便利なエンコードトリックです。ターゲットとしても使用すると便利です(誤った依存関係の数を減らします)。

  2. 再度エンコード。ジャンプで条件をエンコードする場合、3つのオペランド(比較する2つとジャンプターゲット)を持つジャンプがあり、そのうち2つは即値にしたい、1つはできるだけ大きくしたい可能(ターゲットはできるだけ多くのビットを使用できるように、多くの場合、ジャンプには独自のエンコード形式があります)。または、可能性を落とします。

  3. フラグを使用すると、フラグを設定する機会が増えます。フラグを設定できるのは比較操作だけではなく、必要なものです。(フラグを設定する操作が増えるほど、フラグを設定する最後の操作が目的のものになるように注意する必要があります)。フラグがある場合は、条件の数(多くの場合16)にフラグを設定できる命令の数を掛けてテストできます(フラグを使用していない場合、ほぼ同じ数の条件付きジャンプが発生します)テストするものがあるか、テストが簡単にできないものがあります(キャリーまたはオーバーフローなど)。

2実装者の観点から

  1. フラグのテストは簡単で、すぐに実行できます。テストが複雑になるほど、サイクル時間(またはパイプライン化されている場合はパイプライン構造)に与える影響が大きくなります。本のすべてのトリックを使用してハイエンドプロセッサに到達する場合、それは特に単純な実装に当てはまります。その影響はごくわずかです。

  2. フラグがあるということは、多くの命令が複数の結果(自然な結果と変更された各フラグ)を持つことを意味します。また、マイクロアーキテクチャPOVからは、複数の結果が悪い(それらの関連付けを追跡する必要がある)。依存関係を導入するフラグのセットが1つしかない場合(フラグが使用されない場合は不要)、何らかの方法で処理する必要があります。繰り返しますが、特に単純な実装では、本のすべてのトリックを使用してハイエンドプロセッサに到達すると、プロセッサの残りの部分によって追加の困難がd小化されます。


2

32ビットマシンでは、多精度加算シーケンスの一部として使用される「キャリー付き加算」命令は、65ビットのオペランドを受け入れ、33ビットの合計を計算する必要があります。ソースレジスタの仕様は、64オペランドビットの出所を特定し、宛先レジスタの仕様は、結果の下位32ビットがどこに行くべきかを示しますが、「1つ余分に追加」オペランドまたは上位ビットをどうするか結果の?追加のオペランドがどこから来て、追加の結果ビットがどこに行くべきかを命令の一部として指定することは中程度に有用ですが、通常はオペコード内の追加フィールドを正当化するほど有用ではありません。キャリーフラグを処理するための固定された「場所」を持つことは、命令スケジューリングの観点からは少し厄介な場合がありますが、

多精度演算を可能にする命令セットを設計しようとしていて、各命令が2つの32ビットオペランドと1つの32ビット宛先オペランドに制限されている場合、4つの命令で64ビット「追加」を実装できます。 r0 + r2の場合はr5から1、それ以外の場合はゼロ、r4 = r1 + r3の計算、r5 = r4 + r5の計算、r4 = r0 + r2の計算」を超えます。キャリーフラグを補助的なソースおよびデスティネーションとして使用できるようにすると、コストがワードごとに1命令になります。

なお、フラグビットを使用または変更する命令は相互にシーケンスを維持する必要がありますが、どちらも実行しない命令は、順序を維持する必要があるため自由に再配置されます。与えられたシーケンス:

ldr  r0,[r1]
add  r0,r0,r2
eors r4,r5,r6

実行ユニットは、データの読み取りを待たずに3番目の命令を実行できることを非常に簡単に認識できます[r1]が、2番目の命令がadds r0,r0,r2あれば、実行ユニットが何かを使用しようとしたときにフラグ、ゼロフラグは3番目の命令で設定された値を保持しますが、キャリーフラグは2番目の命令で値を保持します。


1
「命令がフラグレジスタを更新するかどうかの命令ビット制御」:たとえば、PowerPC、SPARCで使用可能。
TEMLIB

MIPSは「r5 = r1 + r2; r6がr1未満の場合はr6を設定します。r7= r3 + r4; r5 = R5 + R6;」を使用します。一部のSIMD拡張機能では、すべてのビットをゼロまたは1(つまり、ゼロまたは-1の2の補数整数)に設定する比較を使用して、キャリーと減算を検出し、キャリーを適用できます。
ポールA.クレイトン

@ PaulA.Clayton:「r5がr1より小さい場合」を意味すると思います。MIPSはより長い数学をどのように処理しますか?単語ごとに3つ、3つ以上、または3つ未満の命令が必要ですか?
supercat

@supercatええ、それは「r5がr1より小さい場合、r6を設定する」べきでした!
ポールA.クレイトン

@ PaulA.Clayton:32ビットMIPSで、たとえば2つの64ワード(2048ビット)番号を追加するにはどうすればよいでしょうか?中間段階のキャリーを効率的に処理する方法はありますか?
-supercat

0

簡単な答え...命令自体を除いて内部バスの使用をまったく必要としない、迅速で安価なメモリ操作。メモリなしで、スタックまたはプロセスビットなしのスタックboolとして使用できます。


1
この答えは、かなり詳細なものです。長い回答は必ずしも必要ではありませんが、より具体的なことは明確な改善です。
デビッドリチャービー

フラグの設定またはフラグ値の比較は、アセンブリコードに含まれる引数の形式で他の情報を持たない単一の命令です。フラグはuprocessor操作またはテストの結果でもあり、分岐に効率的に使用できます。これらは、2つの値がレジスタで比較されるときにトグルまたは設定される実際のビットです。
SkipBerne
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.