@jalfの回答はほとんどの理由をカバーしていますが、言及されていない興味深い詳細が1つあります。内部RISCのようなコアは、ARM / PPC / MIPSのような命令セットを実行するように設計されていません。x86-taxは、電力を大量に消費するデコーダーで支払われるだけでなく、コア全体である程度支払われます。つまり、x86命令のエンコーディングだけではありません。それは奇妙なセマンティクスを持つすべての命令です。
Intelが、命令ストリームがx86以外のものであり、命令がuopsに直接マップされる動作モードを作成したとしましょう。また、各CPUモデルにこのモード用の独自のISAがあると仮定して、必要に応じて内部を自由に変更し、この代替形式の命令デコード用に最小限のトランジスタでそれらを公開します。
おそらく、x86アーキテクチャー状態にマップされたレジスターの数は同じであるため、x86 OSは、CPU固有の命令セットを使用せずに、コンテキストスイッチにレジスターを保存/復元できます。しかし、その実際的な制限を捨てれば、マイクロコード1用に通常予約されている非表示の一時レジスターを使用できるため、さらにいくつかのレジスターを持つことができます。
後のパイプラインステージ(実行ユニット)に変更を加えずに代替デコーダーがある場合でも、このISAには多くのx86偏心があります。 それはあまり良いRISCアーキテクチャではないでしょう。単一の命令が非常に複雑になることはありませんが、x86の他の狂気のいくつかはまだそこにあります。
例:シフトカウントが1でない限り、左/右シフトはオーバーフローフラグを未定義のままにします。1の場合、OF =通常の符号付きオーバーフロー検出です。回転のための同様の狂気。ただし、公開されたRISC命令は、フラグのないシフトなどを提供する可能性があります(通常、複雑なx86命令に含まれる複数のuopのうち1つまたは2つだけを使用できます)。したがって、これは主な反論として実際には持ちこたえられません。
RISC ISA用のまったく新しいデコーダーを作成する場合は、RISC命令として公開するx86命令の一部を選択して選択することができます。これにより、コアのx86特殊化がいくらか軽減されます。
単一のuopsは大量のデータを保持できるため、命令のエンコードはおそらく固定サイズではありません。すべてのinsnが同じサイズである場合、意味をなすよりもはるかに多くのデータ。単一のマイクロフューズドuopは、2つのレジスタと32ビットのディスプレイスメントを備えたアドレッシングモードを使用する32ビットのイミディエートとメモリオペランドを追加できます。(SnB以降では、単一レジスタのアドレッシングモードのみがALU演算とマイクロヒューズできます)。
uopsは非常に大きく、固定幅のARM命令とはあまり似ていません。固定幅の32ビット命令セットは一度に16ビットのイミディエートしかロードできないため、32ビットアドレスをロードするには、load-immediate low-half / loadhigh-immediateペアが必要です。x86はそれを行う必要はありません。これは、15個のGPレジスタだけで、レジスタ内の定数を維持する機能を制限することで、ひどいことをしないようにするのに役立ちます。(15は7レジスタよりも大きな助けになりますが、再び31に倍増すると、はるかに少なくなります。シミュレーションが見つかったと思います。RSPは通常汎用ではないため、15 GPレジスタとスタックに似ています。)
TL; DRの概要:
とにかく、この答えは「x86命令セットは、x86命令を迅速に実行できなければならないCPUをプログラムするためのおそらく最良の方法です」に要約されますが、うまくいけば、理由にいくつかの光を当てます。
フロントエンドとバックエンドの内部uop形式
フロントエンドとバックエンドのuop形式がIntelCPUで表すことができる違いの1つのケースについては、マイクロフュージョンモードとアドレッシングモードも参照してください。
脚注1:マイクロコードによって一時的に使用するための「隠された」レジスタがいくつかあります。これらのレジスタは、x86アーキテクチャレジスタと同じように名前が変更されるため、multi-uop命令が順不同で実行される可能性があります。
たとえばxchg eax, ecx
、IntelCPUでは3uopsとしてデコードされ(なぜ?)、これらはMOVのようなuopsであると推測されますtmp = eax; ecx=eax ; eax=tmp;
。この順序で、dst-> src方向のレイテンシーを約1サイクルで測定するのに対し、他の方法では2サイクルです。そして、これらの移動uopsは、通常のmov
指示とは異なります。それらは、ゼロレイテンシのmov-eliminationの候補ではないようです。
PRFサイズを実験的に測定しようとすること、および非表示レジスタを含むアーキテクチャ状態を保持するために使用される物理レジスタを考慮する必要があることについては、http://blog.stuffedcow.net/2013/05/measuring-rob-capacity/も参照してください。
デコーダーの後のフロントエンドで、レジスターの名前を物理レジスターファイルに変更する発行/名前変更段階の前に、内部uop形式はx86 reg番号と同様のレジスター番号を使用しますが、これらの非表示レジスターをアドレス指定する余地があります。
uop形式は、アウトオブオーダーコア(ROBおよびRS)、別名バックエンド(発行/名前変更段階の後)内では多少異なります。int / FP物理レジスタファイルにはそれぞれHaswellに168のエントリがあるため、uopの各レジスタフィールドは、その数に対応するのに十分な幅が必要です。
名前変更はHWにあるので、静的にスケジュールされた命令をバックエンドに直接供給するのではなく、おそらくそれを使用する方がよいでしょう。したがって、x86アーキテクチャレジスタと一時的なマイクロコードと同じ大きさのレジスタのセットを使用することができます。
バックエンドは、WAW / WARの危険を回避するフロントエンドの名前変更機能と連携するように設計されているため、必要な場合でも、インオーダーCPUのように使用することはできませんでした。これらの依存関係を検出するためのインターロックはありません。それはissue / renameによって処理されます。
問題/名前の変更段階のボトルネックなしにバックエンドにuopsをフィードできれば、それは素晴らしいことかもしれません(たとえば、Skylakeの4ワイドvs.4 ALU +2ロード+1ストアポートの最新のIntelパイプラインの最も狭いポイントバックエンド)。しかし、そうすると、レジスタの再利用を回避するためにコードを静的にスケジュールして、キャッシュミスによって負荷が長時間停止した場合でも必要な結果を踏むことができないと思います。
したがって、uopsを発行/名前変更ステージにフィードする必要があります。おそらく、uopキャッシュやIDQではなく、デコードをバイパスするだけです。次に、正常なハザード検出を備えた通常のOoOexecを取得します。レジスタ割り当てテーブルは、16 +いくつかの整数レジスタの名前を168エントリの整数PRFに変更するように設計されています。HWがより多くの論理レジスタのセットを同じ数の物理レジスタに名前変更することは期待できませんでした。それはより大きなRATを必要とします。