2005年06月25日

MinCaml読解ノート: SPARC概要

次のフェーズで生成する仮想マシンコードは実際のターゲットであるSPARCの命令に近いものになる。そこで、先にSPARCアーキテクチャの概要、特にMinCamlに必要な部分を中心に整理する(全部を説明するのは大変なので)。

SPARCの概要

  • RISCアーキテクチャであり、メモリのロード・ストアと演算命令が分離している。
  • 命令はどれも1ワード(32bit)の固定長である。
  • レジスタウィンドウという独特の仕組みを持つ(MinCamlでは使っていない)。

SPARCの大きな特徴の一つはレジスタウィンドウであるが、MinCamlでは利用しない(そのほかにもSPARCでのC関数呼び出し規約は全く無視している)。

SPARCのレジスタ

SPARCのレジスタのうち、特に関係するのは次のものである。

汎用32bitレジスタ
多数あるが、一度に見えるのは32個 (r0〜r31)
プロセッサステータスレジスタ (PSR)
フラグ、モード(カーネル/ユーザモード)、CPU優先レベルなど
プログラムカウンタ (PC)
実行している命令のアドレス
ネクストプログラムカウンタ (nPC)
次に実行する命令のアドレス (プリフェッチに使われる)
演算結果の一部を入れるレジスタ (Y)
主に整数演算で使われる(乗算の上位ワード等)

32個の汎用レジスタにはレジスタウィンドウでの役割から、g0〜g7, i0〜i7, l0〜l7, o0〜o7という別名がついている。但しMinCamlではレジスタウィンドウという仕組みを使わないので、汎用レジスタについては単に同じようなレジスタが32個あると考えて差し支えない。

SPARCの浮動小数点ユニット(FPU)には32個の作業レジスタ(f0〜f31)がある。但しMinCamlで使う倍精度浮動小数点数を表すには2つのレジスタが必要なので、一度に表現できる倍精度浮動小数点数は16個である。

特定の用途に使われる汎用レジスタ

汎用レジスタのうち、いくつかのものは特定の用途に使われることが決まっている。 関数呼び出しの際、o7はリターンアドレス、o6はスタックポインタを入れるのに使われる。

またg0は特殊なレジスタで、常に値は0である。g0への値のセットは効果がない。

命令セット

SPARCの次の6種類に大別される。

  • ロード・ストア
  • 算術・論理演算命令
  • 制御転送命令: call、ジャンプ、トラップ(システムコール発行)
  • 制御レジスタ操作 (カーネルのみ)
  • 浮動小数点命令
  • その他

SPARCの命令はレジスタとレジスタ(または即値)間の演算が基本である。メモリ上のデータを処理するには、一旦レジスタにロードし、処理結果を再びメモリにストアする。

命令は1ワード(32ビット)の固定長。命令の多くは13ビット符号つきの即値を持てる。

算術・論理演算は3オペランド形式で、第1・第2オペランド間を演算した結果が第3オペランドのレジスタにセットされる。

オペランドの種類
reg レジスタ
freg 浮動小数点レジスタ
simm13 13ビット符号つき即値
reg_or_imm レジスタまたは13ビット即値
address アドレス。 reg, simm13, reg+/-simm13, reg1+reg2の4通りが可能。
MinCamlで利用する命令一覧
ld [address], reg ワードをレジスタにロード
st reg, [address] ワードをメモリに書き込む
ldd [address], freg ダブルワードを浮動小数点レジスタにロード
std freg, [address] ダブルワードをメモリに書き込む
nop 何もしない
set value, reg ワードの即値をレジスタに代入 (※合成命令)
mov reg1, reg2 レジスタ間でデータをコピー
neg reg1, reg2 符号を反転させる
add reg1, reg_or_imm, reg2 足し算
sub reg1, reg_or_imm, reg2 引き算
sll reg1, reg_or_imm, reg2 論理左シフト
fmovs freg1, freg2 浮動小数点レジスタ間でデータをコピー
fnegs freg1, freg2 浮動小数の符号を反転させる
faddd reg1, reg_or_imm, reg2 倍精度浮動小数の足し算
fsubd reg1, reg_or_imm, reg2 倍精度浮動小数の引き算
fmuld reg1, reg_or_imm, reg2 倍精度浮動小数の乗算
fdivd reg1, reg_or_imm, reg2 倍精度浮動小数の除算
cmp reg, reg_or_imm 比較
fcmpd freg1, freg2 倍精度浮動小数の比較
jmp address ジャンプ
be label 条件分岐
bne label
ble label
bg label
bge label
bl label
fbe label 浮動小数点ユニットのフラグによる条件分岐
fbne label
fble label
fbg label
fbge label
fbl label
call label サブルーチン呼び出し
retl サブルーチンからの復帰

ロード・ストア命令では、アドレスはロード・ストアするデータのアラインメント境界に合わせる必要がある。

制御転送命令(ジャンプ、条件分岐、サブルーチンコール、サブルーチンからの復帰など)では、その命令の次の命令を実行してから実際の制御が移る。 これはパイプラインで仕掛かり中の処理を無駄にしないため。 ジャンプ先はワード境界に合っていなければならない。

set命令は値によって一つまたは複数の命令に翻訳される。SPARCではワード即値をレジスタに代入する命令はない(SPARCの命令は1ワードの固定長だから、ワード即値はとれない)。その代わりレジスタの上位22ビットに即値を与えるsethiという命令があり、これと論理和orを組み合わせてレジスタへのワード即値の代入を行う。

レジスタウィンドウ

既に記したようにMinCamlでは使用しないが紹介しておく。

SPARCの汎用レジスタは多数ある(プロセッサによって異なる)が、ある時点ではそのうちの32個だけが見えるようになっている。

関数呼び出しの際にウィンドウが「スライド」し、一部のレジスタが見えなくなり、代わりに新しいレジスタが使えるようになる。この仕組みをレジスタウィンドウと呼ぶ。

このときレジスタウィンドウは一部がオーバーラップして、いくつかのレジスタは呼び出し元でも呼び出し先でもアクセスできる。関数呼び出しではそのレジスタを利用して引数を渡す。

この仕組みを反映し、汎用レジスタの32個は次のように4種類に分けられそれぞれ別名がついている。

  • グローバル(8) (どの関数からも見える) : g0〜g7 (r0〜r7)
  • 出力 (8) (関数を呼び出すときに引数を入れる): o0〜o7 (r8〜r15)
  • ローカル (8) (関数内の計算のみに利用): l0〜07 (r16〜r23)
  • 入力 (8) (自分に渡された引数が入っている): i0〜i7 (r24〜r31)

グローバルの8個を除く24個がウィンドウとなる。関数呼び出しでは16個分スライドさせるので、8個がオーバーラップする。この8個は呼び出し元から見るとo0〜o7、呼び出し先の関数ではi0〜i7になる。

関数呼び出しのネストが深くなりレジスタが不足すると、割込みが発生してカーネルに制御が移り、スタック上に書き出してレジスタを空ける。

資料

SPARC V8、V9のアーキテクチャマニュアルはweb上で公開されている。大学等のwebで解説ページを見付けることもできる。


この記事へのトラックバック
この記事へのコメント
コメントを書く
お名前: [必須入力]

メールアドレス:

ホームページアドレス:

コメント: [必須入力]

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。

広告


この広告は60日以上更新がないブログに表示がされております。

以下のいずれかの方法で非表示にすることが可能です。

・記事の投稿、編集をおこなう
・マイブログの【設定】 > 【広告設定】 より、「60日間更新が無い場合」 の 「広告を表示しない」にチェックを入れて保存する。


×

この広告は1年以上新しい記事の投稿がないブログに表示されております。