MC68010

簡単にいえば、MC68000に仮想マシンおよび仮想記憶サポートを追加したものがMC68010です。1982年に発表されました。
MC68000ではユーザモードとスーパバイザモードの2種類のモードがあって、スーパバイザモードでオペレーティングシステムのカーネル部分を動作させ、ユーザプロセスやオペレーティングシステムでも特権の不要な部分をユーザモードで動作させられるようになっています。MC68000では、ユーザモードで動作しているプログラムがステータスレジスタを調べて、自分が実際にユーザモードで動作していることを確かめられましたし、同様にしてスーパバイザモードで動作しているプログラムが本当にスーパバイザモードで動作しているか確認できました。MC68010では、ユーザモードで動作しているプログラムがステータスレジスタを調べようとすると例外が発生するように、MOVE from SR命令が新たに特権命令の仲間になっています。これがMC68010の仮想マシンのサポートです。仮想マシンとは何か、まだ説明していませんでした。端的に言ってしまえば、複数のオペレーティングシステムの同時実行です。あるオペレーティングシステムがそのオペレーティングシステムの管理下で多数のプロセスを管理し動作させるように、複数のオペレーティングシステムを管理し並行動作させるようなオペレーティングシステムのためのオペレーティングシステムを実装するための仕組みです。本来はスーパバイザモードで動作するはずのオペレーティングシステムをユーザモードで動作させないと、複数のオペレーティングシステム間の資源の調整などができなくなります。複数のオペレーティングシステムのための上位オペレーティングシステムだけがスーパバイザモードで動作させるわけです。ところがMC68000だと、管理される側の下位オペレーティングシステムがMOVE from SR命令を用いて、スーパバイザモードにあるはずなのにユーザモードになっていることを検出できてしまいます。これでは、下位オペレーティングシステムが正常動作できなくなる可能性があります。そこでMC68010ではMOVE from SR命令を特権命令として扱い、下位オペレーティングシステムがステータスレジスタを参照すると制御が上位オペレーティングシステムに移って、下位オペレーティングシステムに見せかけのステータスレジスタの内容を与えることができるようになりました。これで、複数の下位オペレーティングシステムをうまく調整して並行動作できるような上位オペレーティングシステムを、理屈の上では実装できます。もちろん、他の特権命令を下位オペレーティングシステムが実行した場合も、上位オペレーティングシステムが代わりに適切な動作を行なって、システム全体がうまく働くようにしなくてはなりません。
歴史的には、IBM製のメインフレームマシンなんかが仮想マシンを実現して複数オペレーティングシステムの同時動作を行なっていました。が、マイクロプロセッサで、一応の仕組みだけでも取り込んだのは初めてです。もっとも、MC68010クラスのプロセッサで、複数オペレーティングシステムの同時実行が必要か、疑問ですけどね。他の改良を行なっているうちに仮想マシンを実現するためのメカニズムを組み込むのが簡単だとわかって、データシートに機能を追加してみましたってだけではないかという気もします。MC68010は最初の頃は高価だったといっても10万円の程度の価格。MC68010を使用したコンピュータは数十万円程度ですから、複数オペレーティングシステムの同時実行が可能な上位オペレーティングシステムの開発を行なうより、オペレーティングシステムごとに独立のコンピュータを割り当ててしまって、情報の共有を行なう必要がある場面ではLAN接続かなにかで通信した方が、実用的で安上がりのように思えます。
なんて書いてしまったけど、Motorolaの資料を読み直したら、仮想マシンの使いみちについて別の目的が書いてありました。とりあえず動作するオペレーティングシステム上で、新たな別のオペレーティングシステムを開発することがあるだろう。その場合、仮想マシン機能があれば、オペレーティングシステム環境下でデバッグ中の新オペレーティングシステムを動かすことができるというわけです。なるほど、オペレーティングシステムのカーネルすら、がんばればデバッガの監視下で動作させられるのなら便利ですね。
もう一方の目玉機能の仮想記憶は説明の必要がずっと少ないでしょう。MC68000では命令の実行途中でのページフォールトで例外を発生した場合、コンテキストを完全に保存できませんでしたから、仮想記憶管理用のルーチンを実行後にページフォールトの原因となった命令を継続実行することができませんでした。そのため、仮想記憶管理用の処理は別プロセッサに行なわせるなどの対策をしないと、仮想記憶を実装することはできず、少々コストがよけいにかかりました。MC68010では命令の実行途中でのページフォールトの場合でも、プロセッサの内部状態をすべてシステムスタック上に保存するようにしましたので、同じMC68010を用いて仮想記憶管理用の処理を実行後に、再びページフォールトの原因となった命令の実行を継続できます。ただし、プロセッサの内部状態を表すデータは合計58 Byteにもおよび、ずいぶんと手間のかかることになってしまいました。ま、ページフォールト処理ではハードディスクアクセスなんかも必要になるので、58 Byteの保存や復帰の時間は無視できるでしょうけど。

MC68010
左上は8 MHzクロック64 pin DIP、左下は10 MHz版で、同じマスクが使われている。右は10 MHzクロック68 pin PGAパッケージのもの。

MC68010では他にもいくつもの改良が行われています。
命令プリフェッチの改良で、ループモードと呼ばれる動作が可能になりました。命令プリフェッチ用にMC68010には6 Byteのバッファがあります。ループ制御を行なう4 Byte命令のDBcc命令と他の2 Byte命令と組み合わせて、6 Byteのバッファの中でループを行なう場合、命令をメモリから読み込まずにプリフェッチ用バッファの中に残っている命令を続けて実行します。そのため、毎回命令を読み込むMC68000と比べてはるかに性能が向上します。条件にあてはまった場合だけですが。2 Byte命令といっても、MC68000系のプロセッサにはプリデクリメントやポストインクリメントを行なうアドレッシングモードがありますから、ループモードで実行可能な作業は意外なほど多岐にわたります。たとえば、文字列のコピーや比較も可能ですし、100 LongWordの数値の総和を求めるようなこともできます。これで、文字列処理で専用の命令(とプリフィックス)を持つ8086と比べるとMC68000は文字列処理能力が劣っていると言われた欠点がなくなりました。しかし、原理的にループに関する命令が6 Byte以上になってしまえば、ループモードでの実行が不可能になります。やはり、より効果的なキャッシュメモリの装備が望まれますが、これはMC68020になって初めて取り入れられます。
他の改良については、MC68010になって追加された、スーパバイザモードでしかアクセスできない内部レジスタに関係しているので、そちらを先に図示します。MC68010では仮想マシン・仮想メモリの実現の都合なんかにより、MC68000よりもユーザモードとスーパバイザモードの区別が厳しくなっています。まずはユーザモードから使用できるレジスタセットですが、これはMC68000と互換性があります。

MC68010 user programming model

8本ずつのデータレジスタとアドレスレジスタがあって、そのうちのA7だけはサブルーチン呼び出し時にリターンアドレスを格納するのに使われるユーザスタックポインタになっています。フラグ類は演算結果に影響されるものだけがアクセス可能とされてコンデションコードレジスタと呼ばれるようになりました。MC68000では読み出すだけならステータスレジスタ全体にアクセス可能でしたから、このままでは互換性がありません。もっともユーザモードからステータスレジスタにアクセスした際には例外が発生してシステムソフトウェアに制御が移るので、前述のようにシステムソフトウェアが適切な処理をしてステータスレジスタを読み出したかのように見せかけることができます。システムソフトウェアの補助があれば互換性が保証されるわけです。
スーパバイザモードからは、以上のユーザモードで使えるレジスタの他に、次の特殊レジスタが使用可能になっています。

MC68010 supervisor programming model supplement

SSPとSRはMC68000とまったく同じです。したがって、新設された特殊レジスタはVBR, SFC, DFCの3種類となります。
VBRはベクタベースレジスタというもので、割り込みベクタテーブルの先頭アドレスを指示するためのレジスタです。MC68000系列の割り込みを含む例外処理機構では、例外の種別ごとに8 bitのベクタ番号というものが割り当てられています。たとえば割り込みの場合には基本的に割り込み発生源からベクタ番号が送出されますし、0除算の場合には$05がベクタ番号と規定されています。そのベクタ番号をインデックスとして、ベクタテーブルというロングワードアドレスを要素として持つ配列を参照し、例外処理ルーチンの開始アドレスをプロセッサが取得するしくみになっています。そのベクタテーブルの置かれている場所ですが、MC68000はアドレス$000000からベクタテーブルが配置されていました。リセット後の処理開始アドレスもベクタテーブルに登録することになっていますから、MC68000では$000000からROMを配置する必要性があります。そういったシステムでは、他のベクタ、つまり各種割り込みサービスルーチンの開始アドレスも同じROMに書き込んでしまうのが、ハードウェア的に簡単になります。ただ、そうしてしまうと、パーソナルコンピュータ的な応用に使用する場合に、デバイスドライバなんかを後から組み込むのが困難になります。デバイスドライバは割り込みを使用したいだろうし、デバイスドライバがどこにロードされるか、どんなデバイスドライバがロードされるか、システム管理者の都合によって変わるでしょうから、デバイスドライバ内の割り込みサービスルーチンの開始アドレスを前もってROMに書き込んでおくなんてことはできません。そのため、一種のバンク切り替えのようなハードウェアメカニズムを用意して、リセット直後はアドレス$000000からROMが見えるけど、しかるべき初期設定が済んだらアドレス$000000からRWMが配置されるようにするのが普通です。もちろん、割り込みサービスルーチンもROMに入れられている組み込みシステムでは、こんな心配は必要ないんですけど。
MC68010では、ベクタテーブルの先頭アドレスをVBRに保持するように改良が行われました。これで、ROMだろうがRWMだろうが、任意のアドレスにベクタテーブルを配置できますし、仮に必要なら動的にベクタテーブル全体を切り替えることだって可能になります。また、リセット直後にはVBRを0クリアするようになっていますから、リセット用のベクタアドレスはMC68000と同じようにアドレス$000000から始まるテーブルに書き込んでおけば良いわけです。さらに、命令で明示的に変更しなければVBRはずっと0のままですから、MC68000と互換性があります。
SFCはソースファンクションコードレジスタ、DFCはデスティネーションファンクションコードレジスタの略で、二つ合わせてオルタネートファンクションコードレジスタと呼ばれます。このオルタネートファンクションコードレジスタの役割を理解するには、MC68000系列のプロセッサで使われている、アドレスバスに出力されるアドレス情報を修飾するファンクションコードと呼ばれるFC0, FC1, FC2の3本の信号線について先に知る必要があります。そのファンクションコードで指定されるアドレス空間を具体的に示すと次のようになります。

FC2 FC1 FC0 アドレス空間
0 0 0 未使用
0 0 1 ユーザデータ
0 1 0 ユーザプログラム
0 1 1 未使用
1 0 0 未使用
1 0 1 スーパバイザデータ
1 1 0 スーパバイザプログラム
1 1 1 CPU空間
(MC68000では割り込みアクノレッジ)

MC68000系列のプロセッサではユーザモードとスーパバイザモードがあって、ユーザモードではシステム全体に影響を及ぼすような命令の使用を禁止されています。この二つのモードの違いはハードウェア的にも重要で、ファンクションコードに符号化されて外部に出力されています。さらに、プログラムカウンタの指す場所からプロセッサが命令をフェッチする場合にはプログラム参照、命令ではなくて処理対象のデータをアクセスする場合にはデータ参照として区別されます。さらに、割り込み応答時にベクタ番号をフェッチしたり、ブレークポイント応答サイクルなどの場合にはCPU空間アクセスとして特別なファンクションコードが出力され、通常のメモリの読み書きとは区別されます。
外部のハードウェアがファンクションコードをデコードし、たとえばオペレーティングシステム専用のワークエリアを設定して、そこをユーザデータやユーザプログラムとして参照した場合には例外を発生させるなどの管理をすることができます。このように、ハードウェア的にもユーザとスーパバイザの区別をサポートし、システム全体の信頼性や頑強性を向上させることができます。さらに、ファンクションコードでアドレス空間を分離し、アドレス空間を広げることができます。たとえばFC2をアドレス信号のA24と見なすことによって、ユーザメモリ16 MByte、スーパバイザメモリ16 MByteの32 MByteのメモリ空間を使用できるシステムを作ることができます。そこまで完璧に独立したアドレス空間を使用しなくても、ユーザとスーパバイザの区別をしてハードウェアを設計し、拡張したりした結果、同じアドレスの値でもユーザとスーパバイザの違いによって別のメモリを参照するようになったシステムができあがることがあります。すると、システム全権を握るスーパバイザモードで動作するオペレーティングシステムなどのプログラムから、一部であってもユーザモードアドレス空間のメモリの値を直接読み書きできないということが起こり得ます。それでは不都合なこともあるので、MC68000では外部回路でスーパバイザ空間の一部にユーザ空間を覗くための窓を付けて、バンク切り替え的な形でユーザ空間全体をそこからアクセスできるようにしておく必要があります。
そういった外部回路のめんどうをなくすためにオルタネートファンクションコードレジスタがMC68010で追加されたのです。MOVES (Move Address Space)命令という新設された専用の命令を用いてメモリアクセスした場合に限り、本来のファンクションコードでなくてオルタネートファンクションコードレジスタの内容がファンクションコードに出力されます。MOVES命令でメモリを読み出す場合にはSFCレジスタが、メモリに書き込む場合にはDFCレジスタが、使用されます。これでよけいな外部回路を使用せずに、安心してユーザ空間とスーパバイザ空間を分離したメモリ構成にできます。もちろんMOVES命令の性質上、スーパバイザモードでしか使用できない特権命令になっています。
SFC, DFC, VBRレジスタの読み書きには、やはり新設されたMOVEC (Move Control Register)命令という特権命令が使われます。

MC68010に追加された機能として、ちょうど新設命令が二つ出ましたので、他の新設命令も紹介しましょう。といっても、実は残りはひとつだけ。RTD (Return and Deallocate Parameters)命令です。RTD命令はサブルーチンリターン命令の一種ですが、定数オペランドをひとつ取り、戻りアドレスをスタックからポップした後でスタックポインタにその定数オペランドを加算します。サブルーチンを呼び出す前にスタックに積み上げた引数を、スタックから削除する命令です。一般的なC言語の処理系では、サブルーチンから返ってきた後でスタックポインタに定数を加算するので、コンパイラがこの命令を生成することはないでしょう。Pascalの処理系では逆にサブルーチンの末尾で引数の後始末をするので、便利になります。
命令実行に必要なクロック数も、MC68000の資料とMC68010の資料をよく突き合わせて調べてみると、微妙に改善されています。もともと処理時間の長い乗除算命令に関しては40 %くらいの高速化が行われていますが、その他の命令でも2クロックくらい短縮されているものが散見されます。
この他、ファンクションコードの説明で少々触れましたが、不当命令の一部、$4848から$484Fまでの8種類の命令コードを読み込むと、MC68000では単に不当命令例外処理が開始されましたが、MC68010ではブレークポイントサイクルという特別なバスサイクルが実行されてから不当命令例外処理が始まります。ブレークポイントサイクルではデータの読み書きは行われず、ブレークポイントサイクルを表すファンクションコードとアドレス値を出力して、DTACK*, BERR*, VPA*のいずれかのバス応答を待つだけです。ただ、ブレークポイントサイクルの識別を外部回路で行なうのは簡単ですから、たとえばロジックアナライザのトリガにブレークポイントサイクル検出を使用すれば、不当命令実行直前のバスの状態なんかを把握しやすくなったりします。

だいたいMC68010での新機能はこれくらいでしょうか。ハードウェア的には、上記のブレークポイントサイクルのような拡張もありますが、ほとんどMC68000と互換で、差し替えても動作することが多いでしょう。もちろんバスエラーを検出してなんらかの動作を行なうようになっているMC68000システムなんかだと、MC68010ではスタックに退避される内部状態が量からして異なりますから、うまく動作しないでしょうけど。

Return to IC Collection.