2つのレジスタをXORして0を生成できるのにMIPSがR0を「ゼロ」として使用するのはなぜですか?


10

雑学クイズの答えを探していると思います。MIPSアーキテクチャがレジスタに対して明示的な「ゼロ」値を使用する理由を理解しようとしていますが、それに対してレジスタをXORするだけで同じことが実現できます。操作はすでに行われていると言えます。ただし、「ゼロ」値を多く使用するような状況は想像できません。私はヘネシーの元の論文を読みましたが、実際には正当な理由もなくゼロが割り当てられています。

ゼロのハードコーディングされたバイナリ割り当てがある論理的な理由はありますか?

更新: PIC32MZのMIPSコア用のxc32-gccからの実行可能ファイルの8kで、「ゼロ」の単一インスタンスがあります。

add     t3,t1,zero

実際の答え: MIPSと条件コードに関する情報を持っている人に賞金を授与しました。答えは、実際には条件のMIPSアーキテクチャにあります。最初はこれに時間を割くつもりはありませんでしたが、opensparcMIPS-V、およびOpenPOWER(このドキュメントは内部ドキュメントです)のアーキテクチャを確認しました。その概要を次に示します。パイプラインのアーキテクチャにより、ブランチでの比較に必要なR0レジスタ。

  • 整数とゼロとの比較(bgez、bgtz、blez、bltz)
  • 整数は2つのレジスタを比較して分岐します(beq、bne)
  • 整数2つのレジスタを比較してトラップ(teq、tge、tlt、tne)
  • 整数比較レジスタと即値およびトラップ(teqi、tgei、tlti、tnei)

それは単に、ハードウェアが実装でどのように見えるかにかかっています。MIPS-Vマニュアルから、68ページに参​​照されていない引用があります。

条件分岐は、条件コード(x86、ARM、SPARC、PowerPC)を使用するのではなく、(PA-RISCとXtensa ISAで行われるように)2つのレジスタ間の算術比較演算を含めるか、1つのレジスタのみをゼロと比較するように設計されました( Alpha、MIPS)、または2つのレジスター(MIPS)。この設計は、比較と分岐の命令tsを通常のパイプラインに結合し、追加の条件コード状態や一時レジスタの使用を回避し、静的コードサイズと動的命令フェッチトラックを削減するという観察に基づいています。もう1つのポイントは、ゼロとの比較には重要な回路遅延(特に、高度なプロセスでのスタティックロジックへの移行後)が必要であるため、算術マグニチュードの比較とほぼ同じくらいのコストがかかるということです。融合比較分岐命令の別の利点は、分岐がフロントエンド命令ストリームの早い段階で観察されるため、より早く予測できることです。同じ条件コードに基づいて複数の分岐を行うことができる場合、条件コードを使用した設計にはおそらく利点がありますが、このケースは比較的まれであると考えています。

MIPS-Vドキュメントは、引用されたセクションの作成者にヒットしません。皆様の時間とご配慮に感謝いたします。


6
ソース値としていくつかの操作で0値のレジスタを使用することがよくあります。これらの操作の前にレジスターをゼロにすることは多少のオーバーヘッドになるため、必要なときにいつでも自分で作成するのではなく、提供されたゼロを使用できる場合は、パフォーマンスが向上します。例として、キャリーフラグの追加があります。
JimmyB 2017年

3
AVRアーキテクチャーでは、gccは起動時にr1をゼロに初期化し、その値に再び触れることはありません。即時0を使用できない場合は、r1をソースとして使用します。ここでは、パフォーマンス上の理由から、コンパイラによってソフトウェアで専用のゼロレジスタが「エミュレート」されます。(ほとんどのAVRには32個のレジスターがあるため、1つ(実際には2つ)を脇に置いても、パフォーマンスとコードサイズの利点の可能性に関してそれほどコストはかかりません。)
JimmyB

1
MIPSについては知りませんが、r0をXORしてクリアするよりも、r0を別のレジスタに移動した方が速い場合があります。
JimmyB 2017年

では、ゼロは非常に頻繁に存在するため、レジスター・ファイル内の位置に値するという点に同意しませんか?次に、これは議論の余地があり、多くのISAがゼロレジスタを予約しないことを選択しているため、それはおそらく正しいでしょう。レジスタウィンドウ、ブランチスロット、「昔」からの命令予測など、当時の議論の余地のある機能と同様に、ISAを設計する場合は、使用しない場合でもそれらを使用する必要はありません。
user3528438 2017年

2
古いバークレーRISC論文の1つであるRISC I:A Reduced Instruction Set VLSI Computerを読むのは興味深いかもしれません。これは、ハードワイヤードゼロレジスタR0を使用して、いくつかのVAX命令とアドレッシングモードを単一のRISC命令に実装する方法を示しています。
Mark Plotnick 2017年

回答:


14

RISC CPUのゼロレジスタは、次の2つの理由で役立ちます。

それは便利な定数です

ISAの制限によっては、一部の命令エンコードでリテラルを使用できませんが、それを使用しr0て0を取得できることを確認できます。

他の命令を合成するために使用できます

これがおそらく最も重要なポイントです。ISA設計者は、汎用レジスタをゼロレジスタにトレードオフして、他の有用な命令を合成できます。実際の命令を少なくすることで、演算をオペコードにエンコードするために必要なビットが少なくなり、命令のエンコーディングスペースのスペースが解放されるため、命令の合成は適切です。そのスペースを使用して、たとえばより大きなアドレスオフセットやリテラルを設定できます。

ゼロレジスタのセマンティクスは/dev/zero* nixシステムの場合と同様です。書き込まれたものはすべて破棄され、常に0を読み取ります。

r0zero-register を使用して疑似命令を作成する方法の例をいくつか見てみましょう。

; ### Hypothetical CPU ###

; Assembler with syntax:
; op rd, rm, rn 
; => rd: destination, rm: 1st operand, rn: 2nd operand
; literal as #lit

; On an CPU architecture with a status register (which contains arithmetic status
; flags), `sub` can be used, with r0 as destination to discard result.
cmp rn, rm     ; => sub r0, rn, rm

; `add` instruction can be used as a `mov` instruction:
mov rd, rm     ; => add rd, rm, r0
mov rd, #lit   ; => add rd, r0, #lit

; Negate:
neg rd, rm     ; => sub rd, r0, rm

; On CPU without status flags,
nop            ; => add r0, r0, r0

; RISC-V's `jal` instruction -- Jump and Link: Jump to PC-relative instruction,
; save return address into rd; we can synthesize a `jmp` instruction out of it.
jmp dest       ; => jal r0, dest

; You can even load from an absolute (direct) address, for a usually small range
; of addresses by using a literal offset as an address.
ld rd, addr    ; => ld rd, [r0, #addr]

MIPSの場合

MIPS命令セットをさらに詳しく調べました。を使用するいくつかの疑似命令があります$zero。彼らは主に枝に使用されます。ここに私が見つけたもののいくつかの例があります:

move $rt, $rs          => add $rt, $rs, $zero

not $rt, $rs           => nor $rt, $rs, $zero

b Label                => beq $zero, $zero, Label ; a small relative branch

bgt $rs, $rt, Label    => slt $at, $rt, $rs
                          bne $at, $zero, Label

blt $rs, $rt, Label    => slt $at, $rs, $rt
                          bne $at, $zero, Label

bge $rs, $rt, Label    => slt $at, $rs, $rt
                          beq $at, $zero, Label

ble $rs, $rt, Label    => slt $at, $rt, $rs
                          beq $at, $zero, Label

$zero逆アセンブリでレジスタのインスタンスが1つしか見つからなかった理由については、おそらく、既知の命令シーケンスを同等の疑似命令に変換するのに十分スマートなのは逆アセンブラでしょう。

ゼロレジスタは本当に便利ですか?

まあ、どうやら、ARMはゼロレジスタを使用することが十分に有用であることを理解しています。AAレジスタ64を実装する(やや)新しいARMv8-Aコアでは、64ビットモードでゼロレジスタが使用されています。以前はゼロレジスタはありませんでした。(レジスターは少し特殊ですが、一部のエンコーディングコンテキストではゼロレジスターであり、スタックポインターを指定するレジスターもあります


MIPSはフラグを使用しないと思いますか?ゼロレジスタは、CPUレジスタの内容に関係なく特定のアドレスを無条件に読み取り/書き込みする機能を追加し、「即時移動」スタイルの操作を容易にしますが、他のmovはソース自体を論理ORすることで実行できます。
スーパーキャット2017年

1
確かに、算術フラグを保持するレジスタ全くありませんが、代わりに3つの命令があり、そのヘルプエミュレート共通条件分岐(sltsltisltu)。
ジャールマンダー2017年

MIPS命令セットを見て、私が理解していることから、前の命令が実行されるまでに各命令がフェッチされることを考えると、何にも直接関係しないオペコードを作成するのは難しいのではなく、即時モード命令が実行され、次にフェッチされた命令がそのビットパターンを持つ場合、オペランドの上位16ビットがプリフェッチされた命令から取得されますか?32ビットの即時モード操作は、2ワードと2サイクルを費やすのではなく、2ワード、2サイクルの命令で処理されます...
supercat

...オペランドをロードしてから、実際に使用するための3番目のサイクル。
スーパーキャット2017年

7

ほとんどのARM / POWER / SPARC実装には、非表示のRAZレジスタがあります

ARM32、SPARCなどには0レジスタがないと思うかもしれませんが、実際にはあります!マイクロアーキテクチャレベルでは、ほとんどのCPU設計エンジニアが、ソフトウェアからは見えない可能性のある0レジスタを追加し(ARMのゼロレジスタは見えない)、そのゼロレジスタを使用して命令のデコードを効率化します。

ソフトウェアに表示されないレジスタを備えた典型的な最新のARM32設計について考えてみます。たとえば、R16が0に配線されているとします。ARM32のロードについて考えてみます。 )...

LDR ra, [rb] // NOTE:The ! is optional and represents address writeback.
LDR ra, [rb, rc](!)
LDR ra, [rb, #k](!)

プロセッサ内部では、これは一般的な

ldr.uop ra, rb, rx, rc, #c // Internal decoded instruction format.

レジスタが読み取られる発行ステージに入る前。rxは、更新されたアドレスを書き戻すためのレジスタを表すことに注意してください。以下はデコードの例です。

LDR R0, [R1]      ==> ldr.uop R0, R1, R16, R16, #0 // Writeback to NULL. 
LDR R0, [R1, R2]! ==> ldr.uop R0, R1, R1, R2,   #0 // Writeback to R1.
LDR R0, [R1, #2]  ==> ldr.uop R0, R1, R16, R16, #2 // Writeback to NULL.

回路レベルでは、3つの負荷はすべて同じ内部命令であり、このような直交性を実現する簡単な方法は、グラウンドレジスタR16を作成することです。R16は常に接地されているため、これらの命令は自然に正しくデコードし、余分なロジックはありません。命令のクラスを単一の内部フォーマットにマッピングすると、ロジックの複雑さが軽減されるため、スーパースカラーの実装に非常に役立ちます。

もう1つの理由は、書き込みを破棄する効率的な方法です。宛先レジスタとフラグをR16に設定するだけで、命令を無効にできます。ライトバックなどを無効にするために他の制御信号を作成する必要はありません。

アーキテクチャに関係なく、ほとんどのプロセッサ実装は、パイプラインの早い段階でRAZレジスタモデルになります。MIPSパイプラインは基本的に、他のアーキテクチャでは数段階になる時点から始まります。

MIPSは正しい選択をしました

したがって、最新のプロセッサ実装では、ゼロ読み取りレジスターがほぼ必須であり、MIPSがそれをソフトウェアから見えるようにすることは、内部デコードロジックを合理化する方法を考えると、間違いなくプラスの点です。MIPSプロセッサの設計者は、$ 0がすでに使用されているため、追加のRAZレジスタを追加する必要はありません。RAZはアセンブラーで使用できるため、多くの疑似命令をMIPSで使用できます。これは、ソフトウェアからRAZレジスターを隠すために各命令タイプの専用フォーマットを作成する代わりに、デコードロジックの一部をアセンブラー自体にプッシュするものと考えることができます。他のアーキテクチャと同様に。RAZレジスタは良いアイデアであり、それがARMv8がそれをコピーした理由です。

ARM32に$ 0レジスタがあった場合、デコードロジックはより単純になり、アーキテクチャは速度、面積、および電力の点ではるかに優れていたはずです。たとえば、上記の3つのバージョンのLDRのうち、必要なフォーマットは2つだけです。同様に、MOVおよびMVN命令のデコードロジックを予約する必要はありません。また、CMP / CMN / TST / TEQは冗長になります。また、短い乗算は高レジスターが$ 0に設定された長い乗算と見なすことができるため、短い乗算(MUL)と長い乗算(UMULL / SMULL)を区別する必要はありません。

MIPSは最初は小さなチームによって設計されたので、設計の単純さが重要であり、したがって$ 0はRISCの精神に基づいて明示的に選択されました。ARM32は、アーキテクチャレベルで多くの従来のCISC機能を保持しています。


1
すべてのARM32 CPUが、説明したとおりに機能するわけではありません。より複雑なロード命令やレジスターへの書き戻しのパフォーマンスが低いものもあります。そのため、すべてを同じ方法でデコードすることはできません。
Peter Cordes

6

Disclamer:私はMIPSアセンブラーを本当に知りませんが、0値レジスターはこのアーキテクチャーに固有ではありません。私が知っている他のRISCアーキテクチャーと同じように使用されていると思います。

レジスタをXORして0を取得すると1命令のコストがかかりますが、定義済みの0値レジスタを使用するとコストはかかりません。

たとえば、mov RX, RY命令はしばしばとして実装されadd RX, RY, R0ます。値が0のレジスタがないと、xor RZ, RZ毎回使用する必要がありますmov

別の例は、cmp命令とその変形(「比較してジャンプ」、「比較して移動」など)で、cmp RX, R0負の数をテストするために使用されます。


1
MOV Rx,Ryとして実装するときに問題が発生しAND Rx,Ry,Ryますか?
スーパーキャット2017年

3
あなたがエンコードすることはできません@supercat mov RX, Immか、mov RX, mem[RY]あなたの命令セットする場合にのみ、単一の即値と命令ごとに単一のメモリアクセスをサポートしています。
Dmitry Grigoryev 2017年

MIPSのアドレッシングモードについてはよく知りません。ARMには[Rx + Ry << scale]モードと[Rx + disp]モードがあることは知っています。後者を一部の絶対アドレスに使用できると便利な場合もありますが、通常は必須ではありません。ストレート[Rx]モードは、ゼロ変位を使用して[Rx + disp]でエミュレートできます。MIPSは何を使用しますか?
スーパーキャット2017年

mov悪い例です。ゼロレジスタの代わりに即値0を使用して実装できます。例えばori dst, src, 0。しかし、はい、あなたは持っていなかった場合は、MOV、即時に登録するためのオペコード必要があるだろうaddiu $dst, $zero, 1234と同じように、lui代わりに上位16の下位16ビットのためにそして、あなたは使用できませんでしたnorか、sub1オペランドない/ NEGを構築することを。
Peter Cordes

@supercat:まだ疑問に思っている場合:クラシックMIPSには、単一のアドレス指定モードしかありません:レジスタ+ disp16。最新のMIPSは、FPロード/ストア用の2レジスタアドレッシングモード用に他のオペコードを追加し、配列のインデックス作成を高速化しました。(ただし、整数のロード/ストアにはまだ対応していません。これは、2つのアドレスレジスタ+ストアのデータレジスタの整数レジスタファイルで、より多くの読み取りポートが必要になる可能性があるためです。レジスタをオフセットとして使用するを参照してください )
Peter Cordes

3

レジスターバンクの最後に数本のリード線をアースに接続するのは簡単です(完全なレジスターにするよりも安上がりです)。

実際のxorを実行するには、ゲートを切り替えてレジスタに格納するために少しの電力と時間がかかります。既存の0値が簡単に利用できるのに、そのコストを支払う理由は何ですか。

最新のCPUには、xor eax eaxレジスタの名前変更による命令の結果として使用できる(非表示の)0値レジスタもあります。


6
の実際のコストはR0、数本のワイヤの接地ではなく、レジスタを扱うすべての命令でそのためのコードを予約する必要があるという事実です。
Dmitry Grigoryev 2017年

xorは赤いニシンです。xorゼロ化は、x86でのみ有効です。この場合、CPUはイディオムを認識し、入力への依存を回避します。ご指摘のとおり、Sandybridge-familyはuopも実行せず、register-renameステージで処理するだけです。(x86アセンブリでレジスタをゼロに設定する最良の方法は何ですか:xor、movまたはand?)しかし、MIPSでは、レジスタのXORを実行すると、誤った依存関係が発生します。メモリ依存関係の順序付け規則(C ++のHW相当std::memory_order_consume)では、依存関係を伝播するためにXORが必要です。
Peter Cordes

ゼロレジスタがない場合は、オペコードを含めて、イミディエートをレジスタに移動します。のようですluiが、16だけ左シフトされません。したがって、1つの命令でレジスタに小さな数を入れることができます。誤った依存関係を持つゼロのみを許可することは、正気ではないでしょう。(通常のMIPSはaddiu $dst, $zero, 1234またはoriでゼロ以外の値を作成するため、「電力コスト」の引数は機能しません。ALUの起動を回避したい場合は、ソフトウェアのADDまたはORの代わりに、mov-immediateのopcodeを登録してください。ゼロの即時。)
Peter Cordes
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.