R3000はMIPS I命令セットアーキテクチャ (ISA) のマイクロプロセッサで、ミップス社が開発し、1988年6月にリリースした。MIPSアーキテクチャとしては2つ目の実装であり、R2000の後継である。
オリジナルのR3000 はCPUと、メモリ管理および例外処理を担当するCP0と呼ばれる部分から構成される。またFPUはR3010という別チップであり、R3000と密に結合して使用される。キャッシュメモリは内蔵していないが、命令キャッシュとデータキャッシュのコントローラを内蔵し、それぞれ256KBまでの1次キャッシュを接続することができた。動作周波数は20MHzから最大で40MHzだが、主に30MHz、33MHzで使用されることが多い。1.2μmのCMOSプロセスで製造され、56 mm2 のチップサイズに11万5千個のトランジスタを集積している。
ミップス社は設計のみを行い、製造はメーカーに任せていた。R3000 を製造したメーカーとしては、IDT、LSIロジック、NEC、シーメンス、東芝などがある。SGIなどのワークステーションやサーバに使用された。また、派生品がPlayStationのプロセッサとしても使用され、組み込みシステムにも多く使われた。
R3000 は、4つのコプロセッサをサポート可能なアーキテクチャとなっているが、実際に使っているのはふたつであり、CP0 としてメモリ管理ユニットと例外処理ユニットを内蔵し、CP1 として接続された FPU を制御する。後継アーキテクチャでは FPU の拡張命令を CP1X として従来 CP3用とされていたオペコード表に割り当てている。命令長は32ビット固定となっていて命令フェッチとデコードを単純化している。CPUのパイプラインは5段になっていて、実行ユニットとしてALU以外に、乗除算ユニットなどを持っている。CPUの汎用レジスタは32ビット×32本で、他に乗除算の結果を格納する専用レジスタ(32ビット×2本)とプログラムカウンタがある。
PlayStationはジオメトリエンジン(GTE)となるベクトル演算ユニットを未使用のCP2に割り当てて使用している。
CP0 は、以下のような機能を持つ。
FPU(R3010)は、以下のような特徴を持つ。
命令は三種類のフォーマットに分類される(R, I, J)。Rフォーマットは三つのレジスタとオペコードから構成される。Iフォーマットは二つのレジスタと16ビットのイミディエート値(とオペコード)から構成される。Jフォーマットは6ビットのオペコードと26ビットのイミディエート値から構成される。
算術演算(加減算)は以下のような形式である。
add $1, $2, $3 ; $1 = $2 + $3 (符号付) addu $1, $2, $3 ; $1 = $2 + $3 (符号無) sub $1, $2, $3 ; $1 = $2 - $3 (符号付) subu $1, $2, $3 ; $1 = $2 - $3 (符号無) addi $1, $2, 100 ; $1 = $2 + 100 (符号無・符号拡張されたイミディエート値) addiu $1, $2, 100 ; $1 = $2 + 100 (符号付・符号拡張されたイミディエート値)
符号付き演算であるadd, sub, addiでは、オーバーフロー時に例外処理が発生する。一方、符号無し演算であるaddu, subu, addiuでは、オーバーフロー時に例外処理が発生しない。C言語ではオーバーフロー時に例外処理を行わないことや、負の数は2の補数で表現可能であることから、ほとんどの場合、符号無し演算が用いられる。
MIPSは、ロード・ストア型のアーキテクチャなので、メモリへのアクセスは基本的に以下のふたつの命令で実現される。
lw $1, 100($2) ; $2 + 100 で示されるアドレスのメモリワード(32ビット)を $1 レジスタにロードする。 sw $1, 100($2) ; $1 レジスタの内容(32ビット)を $2 + 100 で示されるアドレスのメモリにストアする。
分岐とジャンプ命令には、以下のようなものがある。これらは必ず次の命令を実行してからジャンプするため(ディレイスロット)、注意が必要である。
beq $1, $2, 100 ; もし ($1 == $2) ならば、PC+4+100 へ飛ぶ。 slt $1, $2, $3 ; もし ($2 < $3) ならば $1 = 1、そうでなければ $1 = 0 。(これは正確には比較命令) j 10000 ; 10000番地へ飛ぶ。 jal 10000 ; $31 = PC + 4 とした上で、10000番地へ飛ぶ。サブルーチンコールで使用する。
他に重要な命令として、以下のものがある。
lui $1, 100 ; イミディエート値 100 を $1 レジスタの上位16ビットに格納する。
MIPSでは、命令サイズが32ビットであるため、32ビットの定数やアドレスを一命令ではレジスタに格納できない。そこで、lui 命令と addiu 命令などを組み合わせて使用する。アセンブリ言語には32ビット定数をレジスタに格納するマクロ命令があり、マクロ命令のために汎用レジスタのうちのひとつをアセンブリ言語に固定的に割り当てている。
ハードウェアアーキテクチャ上、汎用レジスタの使用に次のような制約がある。
これら以外に制約はない。
MIPSの用意したコンパイラなどのツール群は呼出規約の一環としてレジスタの使用法を規定している。これらの規定はハードウェアの制約ではないが、ツール群がこれに従っている関係で、MIPSアーキテクチャを採用したシステムではほぼ間違いなくこの規定に従ってレジスタを使用している。
名称 | 番号 | 用途 | Callee must preserve? |
---|---|---|---|
$zero | $0 | 常に 0 | N/A |
$at | $1 | アセンブラが一時的に使用 | no |
$v0–$v1 | $2–$3 | 関数のリターン値または式評価の結果を格納 | no |
$a0–$a3 | $4–$7 | 関数の引数 | no |
$t0–$t7 | $8–$15 | 一時変数用 | no |
$s0–$s7 | $16–$23 | セーブされる一時変数用 | yes |
$t8–$t9 | $24–$25 | 一時変数用 | no |
$k0–$k1 | $26–$27 | OSカーネル専用 | no |
$gp | $28 | グローバルポインタ(広域変数領域のベース) | yes |
$sp | $29 | スタックポインタ | yes |
$fp | $30 | フレームポインタ | yes |
$ra | $31 | リターンアドレス | N/A |
なお、"Callee must preserve?" とは、あるルーチンの中でそのルーチンに入ってきたときの値を保持した状態で呼び出した側に戻る必要があることを意味する。例えば、$s-レジスタをルーチン内で使うときは、その内容をスタックに一時的に退避させなければならない。$sp と $fp はルーチンに入ってきたときにセーブされ、それぞれルーチン固有の固定値でインクリメントされる。そして、そのルーチンから戻るときに元の値に戻す。一方 $ra は jal 命令でルーチンに飛び込むときに自動的に変更される。$t-レジスタはサブルーチンを呼び出すと内容が破壊されるので、必要なら呼び出す側がセーブしておかなければならない。$at はアセンブラの仮想命令(マクロ命令)で一時変数として使われる。$t-レジスタだけを使って、サブルーチンを呼び出すことがないルーチンは、スタックにレジスタをセーブする必要がないため、$sp や $fp もセーブする必要がない。
R3000は大いに成功したマイクロプロセッサで、ワークステーションやサーバに各社が採用した。次のような例がある。
組み込みシステム用にも採用され、当初はハイエンドとして、後には低コストの組み込みシステム用として長く使われた。LSI Logic などは組み込み用途に特化したR3000派生品を開発している。
組み込み用途に特化していない派生品として次がある。
組み込み向けの派生品として次がある。
宇宙空間での使用を想定した派生品として次がある。