コンピュータアーキテクチャのエッセンスを読んだときのメモ:第5章 さまざまなプロセッサと命令セット

5.1 はじめに

  • 前章では、プログラム可能なプロセッサが用いるフェッチ-実行サイクルを説明した
  • プロセッサが実行できる演算群に焦点を当てる
  • これまでのコンピュータアーキテクトが選んだアプローチの説明、それぞれの利点と欠点

5.2 計算能力、便利さ、コスト

  • プロセッサは、最低限の基本演算を提供するだけで、どんな関数であっても計算することは出来る、だけれども
  • それでは使いにくく、実用的ではない
  • プロセッサに算術演算機能を追加することは、使いやすさとハードウェアコスト、電力消費量のトレードオフ

5.3 命令セットとその表現

  • プログラム可能なプロセッサの設計では、次の2つを決める必要がある
    • ハードウェアが認識する演算群、命令セット
    • ハードウェアが各命令に用いる表現、命令セットの文法のようなもの。ハードウェアとソフトウェアをつなぐもの。

5.4 オペコード、オペランド、結果

  • オペコードは実行する演算そのものを意味。数字で表現。例えば、整数加算はオペコード5、とか。
  • オペランドは、演算を実行するために必要な値。演算の対象となる値や変数に相当。

5.5 典型的な命令形式

  • 命令は2進数で表す。
  • たいていのプロセッサの命令は、オペコードを含む部分が先頭、それに複数のオペランドが続く。オペコードによって、オペランドがいくつ必要かが決まる。

5.6 可変長命令と固定長命令

  • 命令の長さは同じであるべきか
  • 可変長の命令の方が、メモリを無駄にしないのでよいように見えるが
  • 命令毎に長さが違うと、ハードウェアは複雑になる
  • いつでも長さが同じ命令を使って、命令が含まれない部分には零を入れる、というのもある

5.7 汎用レジスタ

  • フェッチとストアという2つの基本的な動作を支援する部分
  • 次に実行すべき命令のアドレスを示す、プログラムカウンタなど、特定の役割を持つものもある
  • 一時的にデータを保持する、汎用レジスタもある

5.8 浮動小数レジスタレジスタ識別(ID)

5.9 レジスタを使ったプログラミング

  • プロセッサに命令を実行させる場合、たいていの場合はそのオペランドを汎用レジスタに設定する
  • 結果をレジスタに収納する場合もある
  • レジスタからメモリに値を移すのは比較的思い処理なので避けるべきである
  • なるべくレジスタを使用・再利用すべきだが、レジスタの資源は限られている
  • レジスタがどの値を保持するか決める手続きをレジスタ割り付けという
  • 単精度又は倍精度で、レジスタの大きさが違う

5.10 レジスタバンク

  • レジスタを複数のバンクに分割する
  • 複数の物理アクセス機構が働くので、高速に処理できる
  • 同じバンクに複数のアクセスが起きるという、「衝突」が起こりうる

5.11 複雑な命令セットと縮小した命令セット

  • コンピュータアーキテクトでは、命令セットを二つに分類
    • 複雑なもの:CISC
    • 縮小したもの:RISC
  • 数クロックを要する複雑な計算を行う命令セットを持つのがCISC、1クロックで実行可能な少数の命令を持つものがRISCとして分類される

5.12 RISC設計と実行パイプライン

  • RISCは1クロックで命令が終了できるように設計されている、とも言える
  • 大まかには5つの段階(それぞれが1から数クロックに相当するはず)
    • 命令をフェッチする
    • 必要となるオペランドの個数を決定すべくオペコードを調べる。
    • レジスタからの値を読み出すなど、各オペランドをフェッチする
    • オペコードで指定された演算を実行
    • レジスタなどに結果をストア
  • これらの各段階を高速に処理するハードが備わっていて、これらは多段のパイプラインを形成する

5.13 パイプライン命令とストール

  • パイプライン構造を知らないプログラマは、効率の悪いコーディングをする可能性
  • あるオペランドが利用可能になるまでに、他の命令をいくつか実行する必要がある場合などは、パイプラインがストールしてしまう

5.14 パイプラインストールの他の要因

  • オペランドが利用可能になるまで待つ他に、「プロセッサが処理を遅らせるような命令を実行」したり、「通常の処理の流れに混乱が生じる様な場合」にパイプラインはストールする。例えば、以下のような場合。
    • 外部記憶装置へのアクセス
    • コプロセッサの起動
    • 新たな方向への条件分岐
    • サブルーチンのコール
  • 洗練されたプロセッサは、ストールを回避するためのハードウェア機構を備えている。たとえば、条件分岐にて分岐の両方の命令を解読しておき、どちらに分岐しても対応出来るように備えておく機能など。

5.15 プログラマのための帰結

  • 最大速度を達成するためにプログラマがやるべきことは
  • 次に実行する命令では、直前の結果が入るレジスタを参照しないようにする
    • レジスタ参照によるパイプラインストールを回避
  • ハードウェアに任せてしまう、という手もある

5.16 プログラミングとストール、そして何もしないという命令

  • パイプラインストールが避けられない場合もある
  • そのような場合は、ストールが起こる場所にドキュメントを残すことが適切
  • no-op命令で、パイプラインを満たすこともできる

5.17 フォワーディング

  • 計算結果を引き渡す連続した算術命令において生じる問題は、フォワーディングで解決

5.18 演算の型

  • 汎用プロセッサでは、命令はあらゆるカテゴリに分類されている。分類例を示す。
    • 算術命令(整数演算)
    • 論理演算命令(ブール演算)
    • データアクセス、転送命令
    • 条件/無条件分岐命令
    • 浮動小数点演算命令
    • プロセッサ制御命令

5.19 プログラムカウンタ、フェッチ−実行、分岐

  • 第4章にて説明:全てのプロセッサでは、基本的な「フェッチ−実行」のサイクルが行われている
    • プログラムカウンタ(命令ポインタ)を呼ばれる専用の内部レジスタが備わっている
  • プログラムカウンタには、次に実行される命令のアドレスが格納されている
  • 分岐命令ががどのよう動作するかは:絶対分岐と相対分岐の例で説明
    • 絶対分岐
    • 相対分岐

5.20 サブルーチンコール、引数、レジスタウィンドウ

  • プロセッサ間の相違には、基本ハードウェアがサブルーチンに引数を渡す方法が挙げられる
    • メモリから読み出す場合、レジスタから読み出す場合
  • レジスタはメモリに比べて高速処理できる
  • 一般的には、引数は汎用レジスタに格納される
  • 汎用レジスタは他の演算にも使用される(算術演算のオペランドを格納するなど)
    • 限られているので、悩みどころではある
  • レジスタウィンドウというしくみ

5.21 命令セット例