countersince January 6, 2001X68000 LIBRARYEnglish
更新日: 2016 年 8 月 18 日
X68000 LIBRARY > ソフトウェアライブラリ > 特定のハードウェア用のソフトウェア > 060turbo 関連 > 060turbo.sys > 68060を斬る!!(第5回)

68060を斬る!!(第5回)

説明

MC68060 の解説記事です。月刊電脳倶楽部 117 号(1998 年 2 月号)から 139 号(1999 年 12 月号)にかけて読み物横町で不定期連載していました。転載にあたって内容の再考証は行っていません。ご了承下さい。

68060_05.txt
────────────────────────────────────

                          68060を斬る!!

                                 第5回
                                                                鎌田誠
────────────────────────────────────


  今回も例外処理の続きですが、前回のアクセスフォルトの中で出てきた分岐予

測エラーの説明が不十分だったと思うので、最初に分岐予測エラーの解説をして

おきましょう。


━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

                             分岐予測エラー

────────────────────────────────────


●分岐予測エラー

  分岐予測エラー(Branch Prediction Error)は、68060 において分岐キャッ

シュ(Branch Cache)が分岐命令以外の場所でヒットしてしまった場合に発生す

る例外です。当然、分岐キャッシュの使用が禁止されていれば発生しません。

  分岐予測エラーが発生すると、アクセスフォルト例外ハンドラが駆動されます。

前回説明した FSLW(Fault Status Long Word)の BPE(Branch Prediction

Error)ビットがセットされていることから、分岐予測エラーであることがわか

ります。

  分岐予測エラーが発生した場合は、分岐キャッシュをクリアしてから処理を続

行することが推奨されています。つまり、アクセスフォルトの例外ハンドラで

FSLW の BPE ビットがセットされていたときは CACR を操作して分岐キャッシュ

をクリアしてから RTE 命令で復帰すればよいわけです(060turbo.sys v0.54 に

はこの処置が施されています)。

  分岐予測エラーが発生してもプログラムの動作内容に影響はありませんが、例

外の発生で無駄な時間が費やされることになるので、なるべく分岐予測エラーを

発生させないようにするべきです。


●分岐予測エラーが発生する例

  分岐予測エラーは、68000 用に最適化されたプログラムを 68060 で実行した

場合に稀に発生する可能性があります。それは、命令のオペランドワードで分岐

命令を飛び越えている場合です。例えば、次のような 68000 用の最適化が分岐

予測エラーを引き起こす可能性があります。

      ┌───────────────┬───────────────┐
      │           最適化前           │           最適化後           │
      ├───────────────┼───────────────┤
      │        bsr     subB          │        bsr     subB          │
      │        bsr     subA          │        bsr     subA          │
      │                :             │                :             │
      │                              │                              │
      │subA:                         │subA:                         │
      │        bsr.s   subC          │        bsr.s   subC          │
      │        bra.s   common        │        .dc.w   $303C   ←※  │
      │subB:                         │subB:                         │
      │        bsr.s   subD          │        bsr.s   subD          │
      │common:                       │                              │
      │        clr.w   d0            │        clr.w   d0            │
      │                :             │                :             │
      │        rts                   │        rts                   │
      │                              │                              │
      │subC:                         │subC:                         │
      │                :             │                :             │
      │        rts                   │        rts                   │
      │                              │                              │
      │subD:                         │subD:                         │
      │                :             │                :             │
      │        rts                   │        rts                   │
      └───────────────┴───────────────┘
        ※ $303C … move.w #imm,dn のオペコード


  このプログラムでは、subA と subB という 2 つのサブルーチンがあって、そ

れらの違いが先頭が bsr subC か bsr subD というだけでそれ以降がまったく同

じだったので、subA の bsr subC の直後で subB の bsr subD の直後に飛び込

んでいます。

  最適化後で使われている $303C は move.w #imm,d0 という命令のオペコード

です。bra.s common の代わりに、d0.w を犠牲にして直後の bsr.s subD を飛び

越えています。

  68000 の場合、bra.s は 10 クロックサイクルで move.w #imm,dn は 8 クロ

ックサイクルですから、最適化後のほうが 2 クロックサイクル少なくなってい

ます。つまり、68000 用の最適化としては間違っていません。

  ところが、上の例の最適化後のプログラムを 68060 で実行したとき、bsr.s

subD が分岐キャッシュに乗っている状態で move.w #imm,dn($303C)が実行さ

れると、分岐予測エラーが発生してしまいます。なぜなら、move.w #imm,dn は

分岐命令ではないのに、その途中で分岐キャッシュがヒットしてしまうからです。


●分岐予測エラーが発生するパターン

  前述のように、直後の命令を飛び越えるために分岐命令ではなく直後の命令の

オペコードをオペランドにするような命令を使うと、直後の命令が分岐命令だっ

た場合に分岐予測エラーが発生することがあります。

  68060 で分岐キャッシュが更新される命令は以下の 10 通りです。

        BRA.*   <label>
        BSR.*   <label>
        Bcc.*   <label>
        DBRA.W  Dn,<label>
        DBcc.W  Dn,<label>
        FBcc.*  <label>
        JMP     (d16,PC)
        JMP     xxx.WL
        JSR     (d16,PC)
        JSR     xxx.WL

ここで、Bcc.S、BRA.S、BSR.S の 3 つ以外は命令長が 2 ワード以上あるので、

68000 用の最適化ではほとんど該当しないと思われます。

  68020〜68040 用のプログラムでは、直後の命令を飛び越える目的で TRAPF.W

#imm や TRAPF.L #imm が使われていることがあります(68060 が登場する以前

に、直後の命令を飛び越える手段として TRAPF 命令を使う方法を Motorola 自

身が推奨していました)。この場合も条件が揃えば分岐予測エラーが発生する可

能性があります。しかし、68000 には TRAPF 命令が存在しないので、X680x0 用

のプログラムで TRAPF 命令を使っているものはほとんどないと思います。

  分岐キャッシュはデータキャッシュと違って論理アドレスで記録されているの

で、シングルプロセッサのマルチタスク環境で複数のタスクの論理アドレス空間

がオーバーラップしている場合には、コンテキストスイッチで分岐キャッシュを

クリアしないと、あるタスクで更新された分岐キャッシュが別のタスクでヒット

してしまって分岐予測エラーが発生する可能性があります。


●分岐キャッシュの制御方法

  分岐キャッシュは CACR(Cache Control Register)の EBC(Enable Branch

Cache)ビット(ビット 23)をセットした場合に有効になります。同じく CACR

の CABC(Clear All entries in the Branch Cache)ビット(ビット 22)をセ

ットすることで、すべての分岐キャッシュをクリアすることができます。また、

CUBC(Clean all User entries in the Branch Cache)ビット(ビット 21)を

セットすると、分岐キャッシュの中でユーザモードで記録されたものだけをクリ

アすることができます。これはコンテキストスイッチの際にユーザプログラムの

分岐キャッシュだけを効率よくクリアするための機能だと思われます。なお、

CABC と CUBC は読み出すと常に 0 が返ります。

  命令キャッシュのプッシュや無効化を行う命令(CPUSH または CINV 命令)で

も分岐キャッシュがクリアされます。



━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

                             アドレスエラー

────────────────────────────────────

  アドレスエラー例外(Address Error Exception)は、奇数アドレスから命令

を取り出そうとしたとき、つまり、PC(プログラムカウンタ)の最下位ビットを

1 にしようとした場合に発生します。具体的には、以下の場合です。

      ・BRA/BSR/Bcc/JMP/JSR でターゲットのアドレスが奇数だったとき

      ・RTD/RTE/RTR/RTS でスタックの PC のフィールドが奇数だったとき

      ・例外が発生したとき使おうとした例外ベクタが奇数だったとき

  アドレスエラー例外では 6 ワードスタックフレーム(フォーマット 2)が生

成されます。PC のフィールドには、アドレスエラーを発生させた命令のアドレ

スが入ります。ベクタオフセットは $00C で、アドレスのフィールドには PC に

入れようとした奇数値の最下位ビットをクリアした値が入ります。

  なお、68060 は 68020〜68040 と同様にワードまたはロングワードのデータの

アクセスで奇数アドレスを指定できるので、PC を奇数にしようとした場合以外

でアドレスエラーが発生することはありません。



━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

                             命令による例外

────────────────────────────────────

  システムコールなどの呼び出しに使う TRAP #n 命令、エラーの検出などに使

われる TRAPcc 命令、算術演算でオーバーフローしたときの処理に使う TRAPV

命令、数値が範囲外のときの処理に使う CHK 命令と CHK2 命令、および、整数

除算の DIVS 命令と DIVU 命令で、命令による例外(Instruction Trap

Exception)が無条件または条件付きで発生します。


  ユーザモードで命令による例外が発生するとスーパーバイザモードに移行する

ので、ユーザのプログラムをスーパーバイザモードに移行させるシステムコール

を作ることができます。実際に TRAP #n 命令を使ってこれを実現しているのが、

IOCS _B_SUPER です。逆に、システムがこのようなシステムコールを提供しなけ

れば、ユーザのプログラムが勝手にスーパーバイザモードに移行することを禁止

することができます。


● TRAP #n 命令

  TRAP #n 命令は、無条件に例外を発生させる最もポピュラーな命令による例外

です。例外ベクタ番号は 32+n になっており、#n の指定でそれぞれ異なった例

外ハンドラを駆動できます。例外スタックフレームフォーマットは最もシンプル

な 0 番で、例外スタックの PC は例外を発生させた TRAP #n 命令の直後を指し

ています。つまり、例外ハンドラで RTE 命令を実行すると TRAP #n 命令の直後

に復帰します。Human では TRAP #8〜TRAP #15 がシステムで使用または予約さ

れており、TRAP #0〜TRAP #7 をユーザが使えるようになっています。


● TRAPV 命令と TRAPcc 命令

  TRAPV 命令は 68000〜68060 で使える「CCR の V フラグが立っていたら例外

処理を発生させる」という命令です。TRAPcc 命令は 68020 以上でだけ使える命

令で、「cc で指定した条件が成立していたら例外処理を発生させる」というも

のです。いずれも Human では使用されておらず、例外ハンドラを設定せずにこ

れらの例外を発生させると、「TRAPV命令を実行しました」という白帯が表

示されます。

  これらの例外ベクタ番号は 7、例外スタックフレームのフォーマットは 2 番

で、例外スタックフレームの PC のフィールドには例外を発生させた命令の直後、

アドレスのフィールドには命令のアドレスが入ります。


● CHK 命令と CHK2 命令

  68000 でも使える CHK 命令は CMP 命令のように値を比較して範囲外と判定さ

れたときに例外を発生させるものです。また、68020 以上で使える CHK2 命令は

68020 以上で使える CMP2 命令に例外発生処理を加えたようなもので、調べる値

の範囲を狭めることができます。これらの例外処理は Human では特に決められ

ていないので、ユーザが例外ハンドラを記述していなければ「CHK命令を実行

しました」という白帯が表示されます。

  CHK 命令と CHK2 命令の例外ベクタ番号は 6。例外スタックフレームは TRAPV

命令と共通です。

  なお、CHK2 命令と CHK 命令の一部は 68060 ではソフトウェアエミュレーシ

ョンによって処理されますが、例外の発生もエミュレートされるので、これらの

例外ベクタ(例外ベクタ番号 6)も有効です。


● DIVS 命令と DIVU 命令

  DIVS 命令と DIVU 命令では、0 で除算しようとしたときに例外が発生します。

通常は「0で除算しました」と表示されます。

  DIVS 命令と DIVU 命令の例外ベクタ番号は 5。例外スタックフレームは

TRAPV 命令と共通です。


●命令による例外のまとめ

  上記の命令による例外の、例外ベクタ番号、例外スタックフォーマット、およ

び、例外スタックフレームの内容を、表にまとめておきましょう。TRAP #n 命令

の Human における利用方法もメモ程度に書いておきました。


                        命令による例外のまとめ
┏━━┯━━━┯━━━━━━┯━━━━━━━━━━━━━━━━━━━━━┓
┃ベク│ベクタ│スタックフレ│                 割り当て                 ┃
┃タ番│オフセ│ームフォーマ│アドレ│                                  ┃
┃号  │ット  │ット  │ PC │ス    │                                  ┃
┠──┼───┼───┼──┼───┼─────────────────┨
┃  5 │ $014 │   2  │直後│ 該当 │DIVS,DIVU(0による除算)            ┃
┃  6 │ $018 │   2  │直後│ 該当 │CHK,CHK2(範囲外)                  ┃
┃  7 │ $01C │   2  │直後│ 該当 │TRAPcc,TRAPV(条件成立時)          ┃
┠──┼───┼───┼──┼───┼─────────────────┨
┃ 32 │ $080 │   0  │直後│  −  │TRAP #0                           ┃
┃ 33 │ $084 │   0  │直後│  −  │TRAP #1                           ┃
┃ 34 │ $088 │   0  │直後│  −  │TRAP #2   PCM8                    ┃
┃ 35 │ $08C │   0  │直後│  −  │TRAP #3   ZMUSIC                  ┃
┠──┼───┼───┼──┼───┼─────────────────┨
┃ 36 │ $090 │   0  │直後│  −  │TRAP #4                           ┃
┃ 37 │ $094 │   0  │直後│  −  │TRAP #5   CDC                     ┃
┃ 38 │ $098 │   0  │直後│  −  │TRAP #6                           ┃
┃ 39 │ $09C │   0  │直後│  −  │TRAP #7                           ┃
┠──┼───┼───┼──┼───┼─────────────────┨
┃ 40 │ $0A0 │   0  │直後│  −  │TRAP #8   ROMDBのブレークポイント ┃
┃ 41 │ $0A4 │   0  │直後│  −  │TRAP #9   DBのブレークポイント    ┃
┃ 42 │ $0A8 │   0  │直後│  −  │TRAP #10  POWER OFF/リセット      ┃
┃ 43 │ $0AC │   0  │直後│  −  │TRAP #11  BREAK                   ┃
┠──┼───┼───┼──┼───┼─────────────────┨
┃ 44 │ $0B0 │   0  │直後│  −  │TRAP #12  COPY                    ┃
┃ 45 │ $0B4 │   0  │直後│  −  │TRAP #13  ^C                      ┃
┃ 46 │ $0B8 │   0  │直後│  −  │TRAP #14  白帯表示                ┃
┃ 47 │ $0BC │   0  │直後│  −  │TRAP #15  IOCSコール              ┃
┗━━┷━━━┷━━━┷━━┷━━━┷━━━━━━━━━━━━━━━━━┛
                         ↑     ↑
                        該当: 例外を発生させた命令のアドレス
                        直後: 例外を発生させた命令の直後の命令のアドレス


━───────────────────────────────────

        目次

────────────────────────────────────
第1回(月刊 117 号)
  <本編>
        はじめに/パイプラインとは/パイプラインの利点/パイプラインの欠
        点/分岐予測/分岐キャッシュを用いた分岐予測/68060 のパイプライ
        ン/68060 の命令フェッチパイプライン/68060 における分岐予測/
        68060 の命令実行パイプライン
  <68060 関連の話題>
        060turbo における SIMM の効果/Motorola のホームページを覗いてみ
        よう/エラッタ/マスクセットの見分けかた/HAS060.X/060pcr5.x
━───────────────────────────────────
第2回(月刊 119 号)
  <本編>
        スーパースカラ(superscalar)/ディスパッチテスト(1)/ディス
        パッチテスト(2)/ディスパッチテスト(3)/ディスパッチテスト
        (4)/ディスパッチテスト(5)/ディスパッチテスト(6)
  <68060 関連の話題>
        XL/Image/060turbo が少し速くなったゾ/mpeg2play.x
  <68060 の命令のスーパースカラ分類表>
        スーパースカラ分類の意味/整数命令/特権命令/浮動小数点命令/参
        考文献
━───────────────────────────────────
第3回(月刊 120 号)
  <本編>
        例外処理/割り込み/例外ハンドラ/例外処理の流れ/ダブルバスフォ
        ルト/例外スタックフレーム/例外ベクタテーブル
  <質問箱>
        データキャッシュが効かない場合のメモリアクセスのクロック数/デー
        タキャッシュの有効な利用方法/SharpenHimemPatch の副作用?
  <68060 関連の話題>
        060turbo.sys v0.54/060turbo の ROM の不具合
━───────────────────────────────────
第4回(月刊 122 号)
  <本編>
        例外スタックフレームの構造/アクセスフォルト
────────────────────────────────────

(EOF)