MC68000とは何か


このページは、OldGoodCOMPUTER!! の番外扱いです

X68000ではその名前にまで使われ、他にもMacintoshやAmiga、最近ではPilotに搭載さ れるなど、多くの人に愛されてきたCPU、MC68000とは、いったいどのようなものだったのでしょう?

68000は、UNIXワークステーションでの使用を想定し、1979年にモトローラ社が開発した16bitMPU(Micro Processor Unit)です。その基本構造は伝説のミニコンとも言われるDEC社PDP-11を参考にしたといわれ、とくにC言語での使用に適した命令セットを備えています。

とてもすべての命令を紹介することはできませんが、ここではその設計思想の一部でもお伝えできればと思います。

目次

レジスタセット

 データレジスタ アドレスレジスタ

アドレッシング

 直値 アドレス直接 データレジスタ直接 アドレスレジスタ直接 アドレスレジスタ間接 ポストインクリメント・アドレスレジスタ間接 プリデクリメント・アドレスレジスタ間接 ディスプレースメント付き・アドレスレジスタ間接 インデックス付き・アドレスレジスタ間接

命令群

 データ転送命令 算術命令 スタックフレーム命令 分岐命令 例外処理命令

メモリ保護


レジスタセット

68000は16bitCPUですが、その内部のレジスタは32bitで統一されています。そのため、68000を32bitだと主張する人もいます。

さて、レジスタは8本のデータレジスタと、8本のアドレスレジスタ、それにプログラムカウンタと、これだけ16bitのステータスレジスタ(フラグ)があります。


データレジスタは、32bit、16bit、8bitとして使用可能なレジスタで、データ転送や計算に使われます。

ただし、当時のライバルだったi8086が16bitのレジスタを8bit2本に分割できたのに対し、68000では上位のビットは単に無視されるだけです。


アドレスレジスタは32bit固定ですが、実際にバスに出力されるのは24bitです。これは名前の通りアドレスようのレジスタで、豊富なアドレッシングモードと組みあわせて使用することで真価を発揮します。

8086が16bitレジスタしかもたず、メモリを16bitで表現できる64Kの積み重ねで1Mまでしかもてなかったのにたいし、24bitで直接16Mの空間を指定できるのは非常に優れた設計です。

68000のレジスタ群

 詳しくは後に説明しますが、データレジスタは8bit、16bitとしても使用可能です。アドレスは実際には24bitしか出力されませんが、内部では32bitです。
 a7レジスタは裏にもう一つのレジスタが隠れていて、システムとユーザーで切り替わります。また、ステータスレジスタも8bitづつユーザー用とシステム用にわかれています。

68000は「データとアドレスは別のものである」という思想が強かった時代のCPUです(現在は、それらを区別するのは工学的には無意味だと考えられています)。

ですから、このようにレジスタも厳密に分けられ、アドレスレジスタの掛け算やデータレジスタの示すメモリへの代入など、在り得ないことはできないようになっています。


データレジスタとアドレスレジスタはそれぞれ8本の使い道が自由です。構造的には、どれも対等な立場であり、使うレジスタによって使える命令が異なったりすることはありません。

ただし、アドレスレジスタの最後のレジスタ(A7レジスタ)だけは特殊で、スタックポインタとして使用されます。ユーザーが使用する場合は普通に使用される命令の組みあわせでスタックを実現しているため気になりませんが、サブルーチンコールなどでは暗黙のうちに使用されるので注意が必要です。


アドレッシング

68000には、豊富なレジスタ群を活用するために多くのアドレッシングが用意されて います。そのアドレッシングの多くがソース・ディスティネーション双方に自由な組み合せで使用でき(直交性が高い)、命令の汎用性を高めています。

アドレッシングは大きく2つにわかれ、目的とするメモリ・レジスタに直接値を設定する「直接指定」と、アドレスレジスタの示すメモリにデータを入れる「間接指定」があります。

直接指定

直値 アドレス直接 データレジスタ直接 アドレスレジスタ直接

間接指定

アドレスレジスタ間接

ポストインクリメント・アドレスレジスタ間接 プリデクリメント・アドレスレジスタ間接

ディスプレースメント付き・アドレスレジスタ間接 インデックス付き・アドレスレジスタ間接

直値
基本的で、ほぼ唯一の直交性例外です。このアドレッシングはソース側にしか使用できません。
アドレス直接
直値アドレスで示されたメモリの値を操作します。また、ジャンプ命令などでも使われます。
データレジスタ直接
データレジスタの値を操作します。アセンブラではデータレジスタは d0〜d7の記号で示されます。
アドレスレジスタ直接
アドレスレジスタの値を操作します。アドレスレジスタはa0〜a7の記号です。
アドレスレジスタ間接
アドレスレジスタの示すメモリの値を操作します。 (a0)と示されます。
ポストインクリメント・アドレスレジスタ間接
アドレスレジスタの示すメモリの値を操作した後、アドレスレジスタを増加します。
増加する値はデータ長により自動的に変更されます(1byteデータなら1増加。4byteデータなら4増加)。(a0)+ と示されます。
プリデクリメント・アドレスレジスタ間接
ポストインクリメントの逆の動作です。 -(a0) と示します。
ポストインクリメント/プリデクリメントを使えば連続したデータ転送も簡単に行えますし、スタックの表現にも使われます( -(a7)はpush、(a7)+はpopに相当します)。


通常のプログラムでは、ここまでのアドレッシングがあれば十分なはずです。



ディスプレースメント付アドレスレジスタ間接
アドレスレジスタの値に一定の値(ディスプレースメント)を加え、そのアドレスの示すメモリの値を操作します。
10(a0) と書かれれば、a0 に入っているアドレスの10バイト先を読むということです。なんに使うかというと、C言語でいう構造体です。
インデックス付アドレスレジスタ間接
アドレスレジスタにディスプレースメントを加えて、さらにインデックスに示されたレジスタの値にデータ長を掛けたものを加えたアドレスのメモリの値を操作します(あぁややこしい)。

10(a0,d0) と書かれていて、これが32bit(4byte)アクセスなら、a0+d0×4+10 のアドレスを示すということです。なお、このときd0がインデックスに当たるのですが、これはデータ/アドレスどちらのレジスタでも構いません。

こんなややこしいものを何に使うのかというと、多次元配列や構造体に含まれた配列、ダイナミックなメモリ管理が行われるときの配列のハンドリングなどです。(普通、こんなことCPUレベルでサポートしないよ (^^; )


最後の2つは、アドレスレジスタの代わりにプログラムカウンタを使用することも可能です。このようにするとプログラムからの相対位置にデータを置くことが可能なので、プログラムをメモリのどこに置いても動作するように出来ます。


命令群

次に命令群を紹介しますが、68000はCISCでも円熟期に作られたものですので、と ても全部は紹介しきれません。

ここではいくつか特徴的な命令だけを紹介します。なお、命令フォーマットは2、4、6バイトのいずれかです。

命令は、主に以下のような分類になっています。

データ転送命令 算術命令 スタックフレーム命令 条件分岐・ジャンプ命令 例外処理命令

データ転送命令群
最も基本的なものです。データ長は命令コード内で指定できるようになっています。
スタックはデータ転送にポストインクリメント/プリデクリメント命令を組み合わせて作るため、push pop は用意されていません。

特徴的な命令として、ポストインクリメント/プリデクリメントと組み合わせたときのみ、レジスタ16本のうち好きな組み合わせをまとめて転送することが出来ます。これはルーチン呼び出しのレジスタ一括待避等のために作られた機能ですが、メモリを高速に塗りつぶすのにも使えます。
算術命令
これも基本的ですね。特徴といえば、足し算引き算だけでなく掛け算割り算ももっていることでしょうか。

8086系では必須のインクリメント、デクリメント(INC/DEC)命令はありません。アドレスについてINC/DECを行いたいのであれば、アドレッシングモードに用意されています。
データについてINC/DECを行いたいのであれば「Quick命令」というのが用意されています。これは命令コードに3bitまでのデータを含んでしまい、1〜8の足し算/引き算を高速に行うものです。INC/DECをより使いやすくしたものだと思えばよいでしょう。
スタックフレーム命令
アドレスレジスタを1つ使い、そのレジスタをスタックに積んだ後スタックポインタをレジスタに転送し、指定されたアドレスだけスタックポインタを進めます。逆の動作をして元に戻す命令もあります。

なんに使うかというと、C言語のローカル変数を作るためです。ローカル変数は一般にスタック上に取られるため、そのための命令を用意しているのです。
条件分岐・ジャンプ命令
条件分岐は、いわゆる「IF」に相当するものです。この概念がないプログラム言語はありえないほど、コンピューターにとって重要な命令です。
それに対し、ジャンプは「GOTO」や「GOSUB」です。最近の言語では関数呼び出しもこれに当たると考えてよいでしょうか。こちらも、コンピューターにとっては不可欠な概念です。
CPUのコマンドとしては、一般に分岐はジャンプよりも高速に動作します。また、ジャンプとは異なりアドレスを相対位置で示す分岐命令では、プログラムをメモリ上のどこに配置しても同じように動作するというメリットもあります。

8086系のCPUでは分岐命令の「相対指定」の距離が短い(8bit)ため、実際のプログラムではジャンプ命令と組み合わせて使うことが必要です。
しかし、68000では条件分岐命令の有効距離が非常に長く(16bit)、分岐条件のなかに「必ず」というものがあるために、通常のプログラムのジャンプは分岐命令だけで書くことが出来ます。

68000の分岐命令にはデータレジスタを引き数にとるものがあり、その場合は条件をチェックした後、条件を満たさない場合はデータレジスタをデクリメントし、結果が正の場合だけジャンプします(条件を満たすか規定回数回るまでのループ、というのは結構使われるプログラムです)。

68000にはもちろんジャンプ命令もあり、こちらは32bitのアドレスすべてをカバーしています。
また、サブルーチンを呼び出すのにも分岐とジャンプの両方が使えますが、この場合の分岐命令にはフラグをチェックする機能はありません。
例外処理命令
例外処理とは割り込みのことです。普通は外部からの信号で割り込みがかかるのですが、ソフトウェアで割り込みを発生することも出来ます。
一つの方法は「割り込み命令」を使う正統派の方法でもう一つは未実装命令を使う方法です。

未実装命令とは、命令としては無意味だけどそのコードを呼んでも動作が保証されるというもので、その保証される動作とは「割り込みルーチンに移ること」です。
(もっとも、保証されない命令を使っても「不当命令割り込み」という割り込みルーチンに移るのだが)

未実装命令には16bitの命令コードのうち上位4bitが F のものと A のものがあり、それ以下の12bitには何を設定しても構いません。また、割り込みルーチン内で戻り先アドレスを適切に操作してくれれば、後ろにデータをつけても構いません。

つまり、68000はCPUの命令をユーザーが追加できるのです。ここまで基本的な命令を説明しましたが、プログラム上良く使うルーチンなどは命令にしてしまい、快適にプログラムを組んだりすることが可能です。

通常、未実装命令はOSが使用して、サービスルーチンの呼び出しなどに使っています(だって、それが一番「良く使うルーチン」だもの)。

メモリ保護

68000はUNIXを動かすために設計されているため、マルチユーザー下での安定性を確 保するための工夫がなされています。それが端的に現われているのがメモリ保護です。


68000はプログラムの実行をスーパーバイザーモードかユーザーモードかのいずれかでおこないま す。スーパーバイザーのプログラムがユーザーに移行することはできますが、その逆はできません。

そして、メモリはハード設計時にスーパーバイザーメモリとユーザーメモリにわけられ、ユーザーモードでスーパーバイザーメモリをアクセスしようとすると、例外処理が発生し、アクセスできません。


この特徴をいかし、OSやI/Oをスーパーバイザーメモリに置き、ユーザーに直接触らせ ないことで危険な状況を回避できます。

この場合、OSのファンクション呼び出しなどは割り込みをつかって処理します。割りこみプログラムはスーパーバイザーモードで走りますので、こうすることで間接的にユーザーモードからスーパーバイザーメモリにアクセスできます。


ところで、、スタックエリアはどちらに置くのでしょう。スタックはプログラムの実行に重要なものなのでユーザーエリアに置くのは危険ですし、かといってスーパーバイザーエリアに置いてしまえばユーザーモードでスタックが使えなくなってしまいます。

この問題を解決するため、68000は2つのスタックポインタをもちます。それはどちらもa7レジスタとして表現されますが、内部では2本のレジスタもち、実行モードによってどちらを見せるか切り替えているのです。


メモリ保護とはちがいますが、奇数アドレスから16bit、32bitをアクセスした場合にも例外が発生します。これにより、暴走したプログラムも結構な割合でとまってくれました。

(Macintoshでプログラムが暴走すると爆弾が出たりするのは、この割り込みを使用しています。)


このように、68000は効率的なプログラムが作れるようにレジスタや命令を工夫するとともに、「プログラムとは暴走するものだ」という前提に立ってその対策を講じています。

しかしUNIXワークステーションはともかく、パソコン用のCPUとしては、いささか先進的過ぎたかもしれません。メモリ保護機能などは多くのパソコンで無視され、アプリケーションもスーパーバイザーモードで動かしたり(Macintosh)、ユーザープログラムが簡単にスーパーバイザーに変身できたり(X68000)するOSがほとんどのようです。


68000はこの後も進化を続け、バグを取った68010、外部バスも32bitにした68020、さらにバグを取った68030、パイプラインを導入して大幅に高速化した68040、そして最新の(最近発売されたばかりの)68060とシリーズ化されています。




ところで余談なのですが、68000の普及は意外なところで進んだというデータがあります。

1986年ごろ、68000の総出荷数は70万個程度でした(おそらく、ほとんどの用途がMacintoshでしょう)。

しかしこの頃、家庭用ゲーム機のメガドライブ(セガ社)が68000をCPUに選び、コストを抑えるために100万個を発注しました。総出荷数よりも多い数を一度に注文した、というので当時は多くのパソコン雑誌で話題になりました。


結局このゲーム機は2200万台を売り上げ、量産効果で68000はかなり安価になりました。昔は組み込み機器などには安価なZ80が使用されていましたが、最近は組み込みでも68000が使われることが多くなったと聞きます。


最近は同じ理由で、一番売れているRISC CPUはRシリーズでも PowerPCでもなく、なんとSHシリーズなんだそうです。

これも、最初の原因は同じくセが社の「セガサターン」で、1台に2つのSH2と1つのSH1が使われていたからのようです。しかし、量産効果で値段の下がったSHシリーズはその後もいろいろなところで使用され、今では定番の組み込みチップの一つとなっています。


最近では ARMチップも良く使われる、という話もちらほら聞きます。ARMはやはり松下のゲーム機「3DO REAL」やAppleの「Newton Message Pad」に使われていたCPUですが、爆発的に売れたのはヨーロッパの携帯電話で標準CPUとして採用されて以降だとか。

いずれにせよ、CPUの売れ行きを決めるのが実は「パソコン」ではなく、それ以外の製品だというのが興味深いところです。

2011.03.05追記

上記記事は、基本的に1997年に書かれたものです。以下、余談部分の「その後」。

その後、国内でも ARM チップの使用は一般的になり、現状では ARM が一番普及した CPU シリーズとなっています。


特に 2001 年には各社が相次いで ARM を採用した新製品を発表。その後、ARM の決定的優位が決まりました。


QUALCOM は 2001 年に BREW を発表。これは、ARM を採用した携帯電話でネイティブアプリを動作させるための環境でした。国内では 2003 年より AU が採用しています。

任天堂は 2001 年にゲームボーイアドバンスを発売。それまでのゲームボーイシリーズが CPU に 8080 を採用していたのに対し、互換性のない ARM を使用しながら、エミュレーションによって互換性を確保する、という離れ業をやってのけました。その後、NintendoDS 、Nintendo 3DS に至るまで ARM がメイン CPU です。


アドバンスの互換機能はエミュレーションじゃないよ、という指摘をいただきました。
GB までの CPU は持っていて、プログラムはそこで実行されているようです。エミュレーションしているのは、一部のハードウェアの違いを吸収する部分のみ、と言うことみたい。

Apple Computer(当時)は、2001 年に iPod を発売。CPU に ARM を採用しました。後の iPhone 、iPad に至るまで、CPU は ARM 系のままです。

翌年になりますが、SHARP は 2002 年に Zaurus SL シリーズを発売。CPU に ARM を、OS に Linux を採用した PDA として話題を呼びました。これはその後シリーズが途絶えますが、事実上の後継機として、現在は Netwalker や GARAPAGOS が続いています。




一方で、モバイル「以外」の分野では、案外 PowerPC が頑張っていたりもします。

Wii も PS3 も XBOX も、PowerPC を採用しています。完全な組み込み用途なら ARM なのですが、組み込み以上 PC 未満の製品だと PowerPC という感じ。

一方で、2006年以前は PowerPC を使用していた Mac は、現在では Intel CPU を使用しています。これも、PowerPC の性能が「PC未満」でしかなくなったことを物語ります。


これだけ CPU が細分化したのも、CPU が組み込まれる製品が増えたから。いまどき、どんな単純な製品にも CPU が組み込まれていたりします。1980年代に坂村教授が「どこにでも、なんにでもパソコンが組み込まれる」(後に「ユビキュタス・コンピューティング」と呼ばれた思想)と予言した時にはみんな笑っていたけど、現実になったね。

(ページ作成 1997-04-06)
(最終更新  2011-03-05)

戻る
トップページへ

このページの誤字脱字発見・情報提供・意見などありましたら、下の一行掲示板へどうぞ。樫樹の広場から全体を見ることも出来ます。

名前 内容

あきよし】 個人的にいろいろ納得できなかったので、8080かZ80か、命令を詳細に比較しました。だからどうした、って話だけど、結論としては「Z80カスタム」って書いてる日本語版 wikipedia が悪い。英語版には 8080 に近い、って書いてあるよ…  (2012-01-23 17:28:56)

【さり】 なるほど、つまり8080・Z80のどちらから見ても完全なコンパチではないCPUということですね。ありがとうございます、勉強になりました。  (2012-01-20 11:09:24)

あきよし】 すみません。昨日紹介した資料、英語なので読み込み不足でした。もっと読み込んだら、資料では「8080よりもZ80に似ている」という表記もありました。ただ、大幅に命令を削除し、独自命令も追加し、一部命令コードを変更しているため、Z80とはずいぶん異なっているが、8080互換部分は1命令の削除を除いて完全に同一だ、とのこと。そういう意味では、「Z80カスタマイズ」でも正しい気がします。 (2012-01-19 13:59:59)

あきよし】 ニモニックはCPUではなく、言語(アセンブラ)の問題ですが、ザイログニモニックが普及していたので、任天堂公式開発キットでもザイログニモニックでやっていたような気がします。 (2012-01-19 13:57:33)

【さり】 そうだったのですね。いい加減なことを書いてしまい申し訳ありませんでした。8080カスタムなのにニモニックはZ80なんですね。遅ればせながら、いつも楽しく拝見させていただいています。これからも更新楽しみにしています。 (2012-01-19 09:33:09)

あきよし】 公式資料ではありませんが、GB のCPUの詳細資料がありました。GAME BOY CPU Manual。これによれば「8080 をカスタマイズし、Z80の便利な命令を数個、使えるようにしたもの」という位置づけのようです。この数個は、Z80と同等の機能ではあるが、命令コードが違う場合があるので、CPU としては 8080 のカスタムであり、Z80の機能を削除したのではない、とのこと。  (2012-01-18 14:45:48)

【さり】 ゲームボーイのCPUは、Z80から裏レジ・インデックスレジスタとそれらに関する命令を削除したものだったと記憶しています。なので、16bitのキャリー加算や減算、相対ジャンプやループ等はZ80と同じ命令が使えたと思います。昔のことなので定かではありませんが・・。 (2012-01-18 12:04:37)

あきよし】 情報ありがとうございます。他の情報もしらべたところ、アドバンスに「カスタムZ80」を搭載していた、ということを確認しました。…8080ではないんだ。というか、ゲームボーイも「Z80」としている記述が多い。大学時代にGB のプログラムも少しやっていたので、8080と認識しているのですが…(Z80をベースに、機能を削除して8080相当にしていた、ということかな?) (2011-06-20 09:46:26)

【かき】 ゲームボーイアドバンスのゲームボーイソフト動作はARMによるエミュレートではなく、ARMとは別にゲームボーイカラーと同様のCPUを載せてそっちを使ってるそうですよ。 (2011-06-19 02:06:10)

東京電力 輪番停電
第5Dグループ地域で サーバーを運用して
おります。
停電時の停止を
御了承ください。
(当面掲示を残します)

Loading