ロードストア命令の処理

ここまでは、通常の演算命令を対象としてスーパスカラの処理を説明してきたが、メモリをアクセスするロード、ストア命令のスーパスカラ実行には追加の考慮が必要となる。

メモリから複数のデータを読み、それを処理して結果をメモリに格納するという処理は一般的であるが、最初のロード命令がキャッシュをミスしてメインメモリにアクセスしてしまうと、最近のクロック周波数の高いプロセサでは、データが得られるのは100サイクル以上も後になってしまう。しかし、次のロード命令はキャッシュにヒットする場合は、最初のロード命令の完了を待たず、アウトオブオーダで次のロード命令を実行し、最初の命令のロードデータには依存しない演算命令を先に実行できれば、効率が良い。

これを実現するメカニズムとしては、図6.24に示すように、ロードストア命令用のリザベーションステーションでアドレス計算用のオペランドやストアデータの待ち合わせを行い、メモリアクセスに必要なこれらのデータが揃うと、アドレスアダーでメモリアドレスを計算して、ロードキュー、ストアキューというメモリアクセスの実行ユニットに必要情報を書き込んで、メモリアクセス動作を依頼するという構造が用いられる。

図6.24 ロードストアリザベーションステーションとロードキュー、ストアキュー

ロード、ストア命令をデコードすると、図6.24のロードストア用のリザベーションステーションに格納するのと併せて、ロード命令の場合はロードキュー、ストア命令の場合はストアキューにエントリを確保する。そして、メモリアドレスの計算のためのオペランドが揃うと、アドレス計算ユニットを使ってメモリアドレスを計算し、そのアドレスを命令発行時に確保したロードキュー、あるいは、ストアキューのエントリに格納する。

ロードの場合は、これでメモリアクセスが開始できるが、ストアの場合は、アドレスだけでなく、ストアデータがストアキューに格納されてメモリアクセスの準備が整う。

そして、ロードキュー、ストアキューは、格納されたエントリから、実行準備が整った命令を取り出し、メモリアクセスパイプラインに送り出す。そしてロード命令の場合は、メモリからのデータが帰ってくると、ロードキューに格納された物理レジスタ番号とともに、データをリザルトバスに載せる。リザルトバスは、なんらかの調停を行って演算ユニットと共用しても良いが、ロードのレイテンシを短縮するため、ロードデータ専用のリザルトバスを設けるプロセサが多い。

ストア命令の場合は、メモリアクセスパイプラインが依頼された仕事を確実にやってくれれば良いので、ストアキューからメモリアクセスパイプラインにアクセス要求を送り出した時点で、プロセサコアとしては実行終了することができる。しかし、一旦メモリ(あるいはキャッシュ)にデータを書き込んでしまうと取り消せない(メモリを書き戻す手が無いわけではないが、容易ではないし、時間も掛かる)ので、巻き戻しが発生する場合に対応するため、ストア命令がコミットする時点でメモリアクセス要求を送出する。ストア命令にはコミット時に開放する物理レジスタはないので、コミット機構のこのフィールドにコミット時にメモリアクセスを実行すべきストアキューのエントリ番号を書いておけば、この情報を使ってストアキューからメモリアクセス要求を取り出して実行することができる。

ただし、ここで1つ問題がある。これらのメモリアクセス命令がロード命令だけであれば、メモリから読んだデータを使う命令との依存関係はリネームにより確保されているので、どんな順序で実行しても構わないが、A番地にストアする命令の後にA番地からロードする命令がある場合、この2つの命令の実行順序は正しく保たれる必要がある。つまり、アクセスされるメモリを介してのデータ依存関係を正しく処理しなければならない。しかし、レジスタ間の演算命令では、デコード時に論理レジスタ番号を比較することで依存関係を判断することができたが、メモリアクセスの場合は、アドレスを計算してみないと依存関係が判定できない。このため、ロードキューの命令の実行に当たっては、ストアキューに登録された(機械語命令順で)先行するすべてのストア命令のアドレスが計算済みで確定しており、かつ、実行しようとしているロード命令のアドレスと一致していないことを確認する必要がある。これをメモリディスアンビギュエーション(Memory Dis-umbiguation)という。