MC68000

歴史

68000 は1976年に開始された MACSS (Motorola Advanced Computer System on Silicon) プロジェクトから出てきたものである。従来製品との互換性を考慮するような妥協したアーキテクチャにはしないということが開発の初期に決定されていた。これは、利用者がその新システムを一から新たに学ぶ必要があることを意味しており、一種の賭けだった。最終的に、6800系の周辺デバイスとのインタフェースの互換性だけは持つこととなったが、6800のコードは実行できないものとなった。しかし、その後の拡張における互換性には最大限の注意が払われ、68000に乗り換えさえすれば今後が保証されるようにした。例えば、CPUのレジスタは32ビット幅とされたが、外部バスはより小さく設計され、アドレスバスは24ビット幅であり、データバスは16ビット幅となっている。MACSSチームはPDP-11やVAXシステムのようなミニコンピュータのプロセッサに影響を受けた。命令セットはハードウェアの制限よりもソフトウェア開発の観点で設計された。そこにはミニコンピュータでの開発になれた技術者がプログラミングしやすいものにしようとの考えがあった。
開発が進むと同時に、製品名の選定が行われた。"68000" という名称は6800との連続性を想起させるよう選択されたが、これらの間に設計上の類似点はあまりない。集積されたトランジスタ数が68,000だったからとも言われているが、実際には70,000に近かった。
当時、8ビットから16ビットへの移行で熾烈な競争が繰り広げられていた。ナショナル セミコンダクターは1973年から1975年にかけてIMP-16とPACEというプロセッサで一歩先んじたが、使用したプロセス技術が原因で、性能に問題を抱えていた。次にテキサス・インスツルメンツがTMS9900をリリースしたが、広く使われるには至らなかった。そして1977年にインテルが8086をリリースした。しかし、モトローラのマーケティング部門は68000をより完全な16ビット設計にすることが重要と考えた。このため、68000はハードウェアとしては複雑なものとなった。複雑さの指標としてトランジスタ数を見ると、8086は29000個であり、68000は前述のように70000近い。
68000の単純な命令は4クロックサイクルで実行できたが、複雑な命令の実行にはもっと時間がかかった。8MHzの68000で、平均性能は約1MIPS弱だった。
典型的なプログラムで平均をとると、68000のコードはインテルのプロセッサよりも一命令あたりにできることが多く、コードのサイズが小さくて済んだ。また、8086が、8080との互換性を重視した結果、汎用レジスタの不足や実行速度の低下に苦しんだ事に対して、十分な数のレジスタと、当時としては先進的な内部設計のため、実行速度の面では8086に対して優位に立っていた。さらに68000は24ビットリニアアドレッシングによって最大16MBの連続するメモリ空間をサポートし、この空間内の任意のアドレスへのダイレクトアクセスを可能としている。これは開発当時としては非常に広大なメモリ空間だった。これに対し8086は従来の8080との間でソフトウェアのアセンブリ言語レベル（注: バイナリレベルではない）での互換性のため、従来と同じ16ビットのアドレッシングを「オフセット」とし、「セグメント」と称する（詳細はセグメント方式#x86を参照）16ビットレジスタの値を4ビットシフトしてベースアドレスとする、20ビット空間のノンリニアアドレッシングだった。そのため、64Kバイトを超えるデータやコードを扱うにはセグメントレジスタの値を適宜変更する必要があり、面倒であった。32ビットアドレッシングは、x86では1986年の80386で初めて可能になった。
このような事情から68000は8086と比較して学習が容易で使いやすく、開発者に好まれた。
オリジナルのMC68000は、3.5μmルールのHMOSプロセスで製造された。技術サンプルは1979年末に出荷された。量産チップは1980年に出荷され、当初のクロック周波数は4, 6, 8MHzだった。10MHz版は1981年、12.5MHz版が1982年に登場している。HMOSでは最高速の16.67MHz版 (12F) は1980年代終盤まで生産されなかった。
メモリ量の少ないシステム向けの低価格版として1982年に MC68008 が登場した。これは MC68000 の8ビットデータバス版であり、アドレスバスも当初は24ビットよりも縮小され、48ピンDIP版は20ビット。後の52ピンPLCCパッケージ版では22ビットである。MC68012 は後に31ビットアドレスバスで登場した。
68HC000はモトローラと日立製作所が1985年にリリースしたオリジナルとピン配置互換のHCMOS版である。モトローラのものは MC68HC000、日立のものはHD68HC000と呼ばれた。68HC000では8MHzから20MHzまでのクロック周波数が可能となった。またCMOS化されただけでオリジナルと機能が全く変わらず、かつ電力消費が低減されている。オリジナル版は25℃の環境で約1.35ワットを消費した（クロック周波数に依存しない）。一方、MC68HC000は8MHzで0.13ワット、20MHzで0.38ワットしか消費しない。なお、CMOSとは異なり、HMOS回路の電力消費はスイッチング時も何もしていないときも一定である。従って、クロック周波数が違っても電力消費はほとんど変化しない。ただし、周囲の気温には影響される。
モトローラは1990年、MC68HC001をリリースした。このチップは68HC000と仕様がほぼ共通であるが、データバスに16ビット幅と8ビット幅の2つのモードが用意されており、リセット時のピンへの入力でモード選択が行えるようになっていた。従って、このチップは68008の代替として 8ビットメモリを使った安価なシステムで利用できた。
HMOS版の68000はいくつかのセカンドソース企業で製造された。日立 (HD68000)、Mostek (MK68000)、ロックウェル (R68000)、シグネティックス (SCN68000)、Thomson/SGS-Thomson (EF68000, TS68000)、東芝 (TMP68000) などである。東芝はCMOS版の68HC000のセカンドソースでもあった (TMP68HC000)。また、後にシグネティックスがアーキテクチャ互換のSCC68070を製造した。 SCC68070は現在フィリップスが版権を持つ。
68000は数々のマイクロコントローラや組み込み用プロセッサのベースにもなった。1989年、モトローラはMC68302通信プロセッサをリリースした。これが68000CPUコアを使用した最初のマイクロコントローラだった。このコアはCMOS版の68HC000をベースとしているが、8ビットの6800周辺チップとのインタフェース機能が省略されている。1991年、モトローラはここからプロセッサ部分だけを抜き出したMC68EC000をリリースした。
モトローラは68EC000コアを使ったいくつかのマイクロコントローラを開発した。MC68306とMC68307は汎用マイクロコントローラ、MC68322 "Bandit" はプリンターコントローラ、MC68356はモデム用、MC68328 DragonBallは携帯機器向けだった。他のマイクロコントローラとして683XXファミリーは、より強力なCPU32プロセッサコアを使っていた。
68EC000ベースの683XXマイクロコントローラの一部にはスタティック版の68EC000コアが使われた。この場合クロックを遅くしたり停止させたりして電力消費を抑えることができる。1996年、モトローラはこのスタティックコアをプロセッサとして独立させ、MC68SEC000としてリリースした。
モトローラは1996年、HMOS版MC68000とMC68008の製造を終了した。生産終了の予告は1994年末ごろなされた。モトローラの通常の手順からいけば、1995年まで注文を受け付け、最後の出荷は1996年になったということになる。その後スピンオフしたフリースケール・セミコンダクタは現在もMC68HC000、MC68HC001、MC68EC000、MC68SEC000を製造販売し続けている。また、MC68302やMC68306マイクロコントローラやその後のDragonBallファミリーも生産し続けている。68000のアーキテクチャを受け継いだ680x0、CPU32、Coldfireも生産されている。
後継のMC68020からは外部データバス、アドレスバス共に32ビットの、名実共に32ビットのCPUとなり、コプロセッサがサポートされた。ソフトウェア的には、アドレッシングモードが拡張されたほか、ユーザーモードではほぼMC68000の上位互換だった。一部互換性のない部分は、存在しない命令を実行しようとしたときに割り込みでトラップ処理することで、ソフト的に吸収することができた。このMC68020や、後継のMC68030は数多くのワークステーションで採用された。
なおRISCであるPowerPCシリーズとの互換性はなく、同プロセッサを搭載したMacintoshではMC68LC040をエミュレーションしている。
RISC技術を採用したColdFireシリーズは、68000から使用頻度の低い命令の多くを削除した下位互換の組み込み用プロセッサである。

概要

32ビットのデータレジスタを8本、また、32ビットのアドレスレジスタを8本持つ、CISCアーキテクチャのマイクロプロセッサである。8ビットのMC6800シリーズとはアセンブラソースレベルでもバイナリレベルでも互換性を持たない。
MC68000は、DECのVAXを参考にしたと言われる、直交性の高い命令体系をもつ。
外部バス幅はアドレスバス24ビット、データバス16ビットで、発表当初のクロック周波数は4 - 16MHz。約68,000個のトランジスタからなるN-MOS集積回路であり、当初は巨大な64ピンDIPパッケージ、後にPGAパッケージでも供給された。
データーバスはダイナミックバスサイジングを採用しており8ビットまたは16ビットのバスにアクセス可能である。これはM68000ファミリ周辺チップだけではなく、M6800ファミリなど廉価な8ビット周辺チップとの接続を考慮したものである。
MC68000自体は16ビットCPUとして取り扱われたが、内部アーキテクチャは32ビットプロセッサとして設計されており、レジスタとアドレスのデータ長は等しく32ビットとなっている。
32ビットのアドレス空間は4GBに相当するが、当時の技術では、4GB分のアドレス空間をフルに使う可能性は無いとされ、外部のアドレスバスとのデータ入出力では上位8ビットをマスクして下位24ビットを使用し、最大16MB分のメモリ領域を管理する実装とされていた。
このように最初に理想とする32ビットアーキテクチャを決めておき、その時々で利用できる技術で実現可能な機能から順に実装するという方式をとっていたため、無理なく上位互換性が確保できた。
また、ライバルであるx86系プロセッサではメモリ空間とは別にI/O空間が設けられ、専用のI/O命令が用意されていたが、MC68000シリーズではメモリ空間内にI/O用領域を割り当てるメモリマップドI/O方式を採用しているのも特徴の一つである。

スタック

スタックがOS用とアプリケーション用に二つあり、特権モード（スーパバイザモード）と、ユーザモードの2つの特権レベルを持つなど、当初よりUNIXに代表される高度なメモリ管理機能やマルチタスク機能を備えたOSを搭載することを前提に設計されている。
ユーザーモードで動作するプログラムの互換性はMC68000からMC68060までバイナリレベルでほぼ完全に保たれているが、スーパバイザモードでの動作についてはこのモードで動作するOSが差異を吸収することを前提として、世代ごとに改良や変更が加えられている。
このため特にスタックポインタの実装とその挙動には世代間での相違が多く、アプリケーションがハードウェアリソースへ直接アクセスするためにスーパーバイザモードをアプリケーションに解放した原始的な実装のOSではMC68000用に書かれたこの種の動作を行うアプリケーションプログラムが後継各プロセッサで正常動作しないケースが存在する。

メモリアドレッシング

MC68000は16ビットのALUを持つ一方で、アドレスは常に32ビットで扱われ、フラットな32ビットアドレス空間を持つ。その実効アドレスの演算の為に、専用の16ビット幅のALUを2個持つ。
8086は20ビットのアドレス空間を持つが、リニアにアクセスできるのはセグメントと称された（セグメント方式#x86）16ビットの空間だけであった。これは特にグラフィックの扱いなどを面倒にした。
MC68000では実効アドレス演算の為に専用の2つの16ビットのALUを接続して用い、3つめのALUが16ビットの演算を行った。
例えば、32ビットのアドレスレジスタのポストインクリメント（そのアドレスにアクセスした後、アドレスレジスタの内容をインクリメント（増加）するアドレッシングモード）「ADD.W (An)+,Dn」はポストインクリメントをしない場合に較べても速度低下することがない。
したがって、16ビットCPUとして始まってはいるが、68000の命令セットは32ビットアーキテクチャになっている。後継のMC68020は32ビットのALUと32ビットのデータバスを持っていたが、68000用のソフトウェアをほぼ変更することなしに、データバス幅を32ビットに拡張することで速度向上を果たした。
しかし、ソフトウェアの互換性を完全に保てたわけではない。68000では（同様のテクニックは同じく32ビットマシンだがアドレスが24ビットだったSystem/360で行われていたが）使われない（無視される）上位8ビットに何らかの情報を持たせる、というテクニックが一部のシステムプログラムなどで使われた。例えば、LISPなどでポインタの指すオブジェクトの種類を区別する情報をそこに格納したり、ガベージコレクション用のフラグを格納した。そのようなコードを、後継のより広いアドレスバスを持つマシンで実行するとバスエラーが発生した（やはりSystem/360の後継機でも同様の問題が起きており、System/370-XAではMSBを互換モードのために残した31ビット化という苦肉の策がとられている）。
Macintoshでは8MB以上のRAMを搭載する際にソフトウェアのアップグレードが必要だった。
多くのアプリケーションは将来を見越して書かれており、問題は発生しなかった。

内部レジスタ

8本の汎用データレジスタ (D0 - D7)と8本のアドレスレジスタ (A0 - A7) を持つ。
アドレスレジスタ (A7) はスタックポインタ (SP) であり、スタック上位のオブジェクトをアクセスする事が容易となった。
68000ファミリでの多バイトデータのメモリ上での配置はビッグ・エンディアンである。

ステータスレジスタ

68000の比較命令、算術演算命令、論理演算命令は実行結果をステータスレジスタに反映させ、後で条件ジャンプ命令でそれを使えるようになっている。
ステータスレジスタのビットには、"Z"ero（ゼロ）、"C"arry（キャリー）、o"V"erflow（オーバーフロー）、eXtend、そして"N"egative（ネガティブ）がある。
eXtendビットはCarryビットと分離されている。
eXtendとCarryは、シフト/算術演算/論理演算命令の桁上がり結果を保持するが、eXtendビットはより多バイトの演算を実現するために使い、Carryビットは処理の流れを制御するのに用いる。

命令セット

68000の設計者はアセンブリ言語が直交性を持つよう注意を払った。つまり、命令は操作とアドレッシングモードに分けられ、多くの場合は任意の操作に任意のアドレッシングモードを使えるようになっている。
ビットレベルで見ると、命令のオペコードの値は必ずしも現状の通りである必然性はない。このことは、ある意味でよい妥協点だった。真の直交性のあるマシンと同等の利便性を得ると同時にCPU設計者はオペコード表を自由に埋めることができた。
最小命令サイズは当時としては大きい16ビットである。さらに多くの命令やアドレッシングモードは追加のワードでアドレスやアドレスモードビット等を表現する。
多くの設計者はMC68000アーキテクチャはコストに見合うコンパクトなコードを実現していると信じている（特にコンパイラがコードを生成した場合）。多くの組み込み制御システムの設計者はメモリのコストに敏感であり、コードがコンパクトであるという信念がMC68000ならびに後継CPUを採用する動機に繋がり、アーキテクチャの寿命を延ばした。そして同様にコンパクトなARMアーキテクチャのThumb命令セットが登場するまで、多くの68000命令セット（のCPU）の採用をもたらし続けた。

特権レベル

このCPUと他の全ファミリは二段階の特権レベルを実装している。ユーザモードでは割り込みレベル制御以外はアクセス可能である。
スーパバイザ特権では全てにアクセスできる。割り込みが発生するとスーパバイザモードに移行する。
スーパバイザビットはステータスレジスタに格納され、ユーザプログラムからも見える。

割り込み

68000は8つの割り込みレベルを持つ。レベル0から7まで厳密に優先順位が決まっている。
番号が大きい割り込みが番号の小さい割り込みに対して割り込むことが出来る。ステータスレジスタには現在の割り込みレベルを特権命令でセットすることができ、これにより低いレベルの割り込みをブロックする。レベル7はマスクすることができないため、NMI（英: Non-Maskable Interrupt）とも言う。レベル0は他の全てのレベルが割り込むことができる。レベルはステータスレジスタに格納され、ユーザレベルプログラムからも見ることが出来る。
ハードウェア割り込みは3本の信号線によってCPUに伝えられ、この3本の値がペンディング中の最も高い割り込みレベルにエンコードされる。別途割り込みをエンコードするための割り込みコントローラが必要である。ただし、割り込み発生源が三つ以下のシステムでは、各割り込みを三本の信号線にそれぞれつなぐことで割り込みコントローラを省略できる。ただし、割り込みレベルと割り込みの対応が単純ではないためソフトウェアでの処理が複雑になる。割り込みコントローラは汎用ロジックIC74148のような単純なエンコーダでもよいし、VLSIの周辺チップでもよい。例えばMC68901は、割り込み制御だけでなくUART（シリアル）、タイマー、パラレルI/Oを備えている。
例外テーブル（割り込みベクターテーブル）はアドレス0番地から1023番地まで固定で置かれ、256個の32ビットアドレスを表す。最初のベクターは初期スタックアドレスであり、二番目のベクターは初期コードアドレスである。3番から15番のベクターは各種エラー処理ルーチンのアドレスである。エラーの種類としてはバスエラー、アドレスエラー、不正命令、ゼロによる割り算、CHK/CHK2命令ベクター、特権違反、そして予約されたベクター（後にline 1010エミュレータ、line 1111エミュレータ、ハードウェアブレークポイントに割り当てられた）がある。ベクター24から実際の割り込みに対応する。ハードウェアに対応しない擬似割り込み、レベル1から7のベクター、15個のTRAPベクター、いくつかの予約されたベクター、ユーザ定義ベクターの順番で並んでいる。
リセットされたとき、少なくともスタートコードアドレスのベクターには正しいアドレスが入っている必要がある。多くのシステムは不揮発メモリ（つまりROM）を持っていて、0番地に配置し、そのROMにベクターテーブルとブートストラップコードが入っている。しかし、汎用システムでは動作中にベクターを書き換えられるのが望ましい。これを実現するため、ROM上のベクターがRAM上のジャンプテーブルを指すようにするか、バンク切り替えで動作中に0番地付近の配置をROMからRAM変更する。
68000はPopekとGoldbergの仮想化要件（英: virtualization requirements for full processor virtualization）を満たしていない。というのは、"MOVE from SR" 命令が特権命令でないため、ユーザモードから特権ステータスが見えてしまうからである。この問題は後述する仮想記憶サポートの問題とともに後のMC68010で改善された。"MOVE from SR" 命令は特権命令となり、ユーザモードのソフトウェア用に "MOVE from CCR" 命令を追加した。ユーザモードで "MOVE from SR" 命令を使った場合、トラップが発生してOS側でエミュレートすることも可能である。

MC68000 でのデマンドページングの実現

680x0系の最初のプロセッサであるMC68000の仕様は、外部支援なしにはデマンドページングの実現が困難なものであった。
デマンドページングでは、実行中の命令のメモリアクセスがページフォールトを起こしたら、（それが正常なアクセスであれば）その実行中の命令の実行を一旦フリーズし、外部記憶と主記憶の間でスワッピングをおこなってから、実行中だった命令の実行から再開する、という処理が必要である。
しかし、MC68000がページフォールトの際に保存する内部情報は、「実行中だった命令の実行からの再開」ができないものであった。このため、MC68000の通常の割り込みの処理に従ってしまうと、デマンドページングは実現できない。これを、単にそもそもサポートするつもりが無かったものとみるむきもあれば、「仕様のバグ」とみるむきもあれば、後述のようにして実現が可能であるし、MMUも計画中に過ぎなかったのだから「将来仮想記憶をシリコン上に実装することを正当化する需要が発生するまでの暫定的な実装仕様」だったと考えるほうが自然である、とみるむきもある。
そのようなMC68000で仮想記憶を実装するためには、MC68000には次のような機能があった。バスアクセス中にあるピンをアサートすることにより、命令の実行をそこで一旦フリーズし、スリーステートバスをハイインピーダンスにして解放させたままいつまででも止めておいて、そののち、元の命令の中断したバスアクセスから再実行（re-run）する機能である。これによるバスサイクルをリランサイクル（rerun cycle）という。
これを利用して、メインのCPUであるMC68000を止めた状態で、別のプロセッサでページ処理をおこなうようにして、デマンドページングを実装できる。必然性はないが、同じバスに接続する容易性から、この補助プロセッサにもMC68000が使われることが多い。
以上のようなMC68000のデュアル・プロセッサによる仮想記憶を実現したコンピュータとしてはアポロコンピュータのDomainが有名である。同社の実装ではページスワップを担うスレーブ・プロセッサは、通常時はグラフィックス・プロセッサとして動作し、必要に応じてマスターのページ・スワップ要求に応じた。
この問題は後のMC68010で解決された。MC68010では、バスエラーとアドレスエラーが発生した場合、エラーを発生させた元の命令を指すプログラムカウンタのアドレスをスーパバイザスタックに保存することにより、元の処理に復帰できるようになった。