Intel 80286

Intel 80286（インテル はちまるにいはちろく）はインテルの16ビットマイクロプロセッサ (CPU)。IBMのPC/AT（日本ではPC-9800シリーズ）およびその互換機によって広く普及した、DOS時代の代表的なパーソナルコンピュータ (PC) 用プロセッサであった。 1982年2月1日に発表、1984年から6MHz版と8MHz版が出荷された。134,000個のトランジスタを集積した1.5μmのNMOSプロセス（インテルの呼称だとHMOS-III）で製造され、性能を大幅に増加させるパイプラインを構成する4つの独立したユニット（アドレスユニット、バスユニット、命令ユニットと実行ユニット）を持っていた。クロック周波数は6、8、10、12MHz があった。パッケージには68ピンPLCC、LCC、PGAがあった。 8086とソフトウェアの上位互換性を持ち、より高速に命令実行可能（同クロック8086比で約2.5倍）。また、物理メモリ空間が16MBに拡張され、1GBの仮想記憶やマルチタスク処理に対応している。 また、インテルはこのモデルまではセカンドソース推進戦略を採用したため、AMD、富士通、シーメンス、ハリス・コーポレーション（英語版）（以降、ハリスと表記）からもセカンドソース品が供給された。特にAMDとハリスは、ライセンスが受けられない80386に対抗するため、16、20MHz、ハリスは25MHz、といった、より高クロックの80286を市場に投入した。後述するようにDOSで動作させる限り、同一クロックの80386よりも高い実行速度が得られたからである。 インテル社のiAPX 286 Programmer's Reference Manualでは、CPUの80286と後述の周辺LSIの組み合わせがiAPX 286であるとしている。 8086や80186に対する上位互換性を持つリアルモードに加えて、プロセスやメモリを保護するプロテクトモードを追加し、これをサポートする命令が追加された。また、マルチタスクオペレーティングシステムを実装する際に必要な仕組みや命令群が拡張され、その後の32ビットCPUへ繋がる基礎ができあがった。4階層の特権レベル、仮想記憶機能、メモリ保護機能、TSS(Task state segment)を使用したタスクスイッチ機能などを持つ。 PC DOSおよびMS-DOS IBMが1984年にPC/XTの後継機種PC/ATを発表したとき、8086/8088とリアルモード互換性を持つ80286を採用した。しかし、プロテクトモードを活かして設計されたオペレーティングシステムは一般向けに普及しておらず、80286はもっぱら高速な8086としてPC-DOS (MS-DOS) 上で利用されることが多かった。 DOS/V 前述の通りPC/ATは80286機であるため、AT互換機用の日本語OSであるDOS/Vは80286以上のシステムが前提となっている。 Windows 3.x Windows 3.0や英語版Windows 3.1において、いずれもスタンダードモードでは、80286のプロテクトモードが活用された。Windows 3.0の発売は、IBM PC/ATの発売から6年後の1990年であった。 日本語版Windows 3.1以降、およびWindows for Workgroups 3.11以降は80286には対応していない。 OS/2 1.x PC DOSおよびMS-DOS後継のプロテクトモード用オペレーティングシステムとしてIBMとマイクロソフトが共同開発したが、パソコン用OSのひとつとしての地位を獲得するにとどまった。OS/2 1.0の発売は、IBM PC/ATの発売から3年後の1987年であった。 OS/2 2.0以降は80286には対応していない。 XENIX マイクロソフトによって開発されたUNIXである。 80286で、DOSやBIOSの資産を継承しつつ、更に仮想記憶機能を生かすためにはリアルモードとプロテクトモードの間を往復することが必要だが、80286にはプロテクトモードからリアルモードへの復帰命令が無く、復帰にはCPUのリセット信号線を有効にするしかなかった。そのため、80286搭載機では特定のI/Oポートを操作することによりCPUのリセットパルスを発生させるハードウェアを持っており、ソフトウェアからCPUのみのリセットを行うことができた。BIOSの初期化プログラムの中で通常のハードウェアリセット（電源ONまたはリセットスイッチ押下）と前述のソフトウェアリセットを区別し、初期化方法を切り替えるという処理が必要だった。これら一連の処理はオーバーヘッドが大きいため、結果的に80286を用いたリアル／プロテクトモード間のスイッチングは非効率的なものとなった。 なお後継の80386以降では、両モード間を任意に往復できる機能や仮想86モードなどを備えていた。 リアルモードへ戻るための方法はハードウェア独自のものとなっており、具体的な手順は以下のようにハードウェアによって異なる。 IBM PC/AT 80286を搭載したIBM PC/ATではキーボードコントローラのI/Oにリセット機能が搭載されていた。これはI/Oポート64hにあり、通例はFEhを書き込みそのbit0を0にすることでリセット動作となる。これに先立ち当該プログラムはリセット後に処理を再開するアドレスCS:IPをBIOS Data Areaの0040:0067hに保存する。それ以外のスタックの位置(SS:SP)などプログラムの動作継続に必要な情報は当該プログラム自身のデータ領域などに保存する。次にリセット後の動作を決めるシャットダウンコードをRTC用 不揮発性CMOSメモリのオフセット0FhにI/Oポート70h, 71hを使用して書き込む。5を書き込めばリアルモードへの復帰、0を書き込めば通常の電源ON、またはリセットスイッチ押下である。プロテクトモードから戻るとBIOSはBIOS Data Areaに保存したアドレスから当該プログラムの実行を再開させる。当該プログラムはあらかじめ保存しておいたスタックの位置などの情報を戻す。 NEC PC-9800シリーズ PC-9800シリーズでは1986年に登場したPC-9801VXに80286とV30の両方が搭載され、このとき80286とV30を切り替えるためのリセット用I/Oポートが設けられている。該当機ではI/O 00F0hに0を出力することでCPUがV30に切り替わらずにリセットされるが、これに先立ちリセット後に処理を続行するか再起動するかを事前に設定しておく必要がある。この設定はI/O 0035hのbit5,7にあり、再起動の場合は両方のbitを1に、処理続行の場合はbit7を0に設定する。処理を続行する場合は事前に戻りアドレスとなるCS:IPをスタックに保存（PUSH）したうえで、そのスタックの位置（SS:SP）をメモリアドレス0000:0404から0407までの4バイトに保存しておく必要がある。 上記の通り80286はリアルモードとプロテクトモードを備えており、起動直後やMS-DOSでは基本的に8086や80186と互換性の高いリアルモードで動作する。 8086では1MiB(000000H - 0FFFFFH)のメモリ空間を持つが、本来16ビットのレジスタでは64KBまでのアドレス(00000H - 0FFFFH)しか表現できない。そこで16ビットレジスタを2つ用意し、まず1MB中のメモリ空間からアドレスの「原点」を10Hバイト単位で大雑把に指定し、もう１つのレジスタでそこから上位の64KBまでをアクセスできるようにしていた。したがって「原点」を示すセグメントレジスタを最大の0FFFFHに設定すれば、0FFFF0Hからさらに上位の64KBすなわち1MBを超える10FFEFHまでアドレスを表現できることになる。しかし8086ではアドレス線がA0 - A19の20本しか用意されていないため100000H - 10FFEFHのアドレスにはアクセスできず、桁あふれした部分は000000H - 0FFEFHにラップアラウンドしてアクセスすることになる。 80286ではこのようなラップアラウンドは起こらないため、インテル社のiAPX 286 Programmer's Reference Manualでは「もしリアルモードのプログラムがアドレス空間のラップアラウンドに依存している場合（例えばFFF0:0400 = 0000:0300）、上位アドレス4ビットをゼロにするために外部ハードウェアを使用すべきである」としている。 アドレス線を24本持つ80286を採用したシステム(PC/ATなど)では、ラップアラウンドを前提で作られたソフトウェアとの互換性を維持しつつ100000H以上のメモリにもアクセスできるように、21本目のアドレス線 (A20) の無効／有効を切り替えるハードウェアを持っていた。特定のI/Oポート（PC/ATではキーボードコントローラ）からA20を有効にするとリアルモードのままでも64Kバイト程度の上位メモリを参照することが可能になり、HMAと呼ばれた。 HMAは64Kバイト程度であるが640Kバイトの約10%にも相当し、メモリ枯渇に苦しむDOSユーザーにわずかな救いとなった。80386以降のプロセッサでもHMAは使用できる。 キャッシュを内蔵した80486以降のCPUではA20を無効にする機能を内蔵し、CPUにA20M#というピンを追加した。これは外部ハードウェアでA20を無効にしても80486がキャッシュに保存されたHMAにアクセスしてしまうためである。このA20M#を制御するのは、PC/ATではキーボードコントローラで変化していない。 なお、80286は16Mバイトの後ろの約64Kバイトにアクセスした場合、先頭の000000H番地にラップアラウンドにするが80386ではこのラップアラウンドは起こらない。このことが問題になる場合は、80386のページング機能を使用して16Mバイトの後ろの64Kバイトの領域を先頭の000000Hにマッピングすることで回避できる。 80286にはCPUID命令は無く、インテルはフラグレジスタを使ったCPUの判別方法を紹介している。 PUSHF/POPF命令で読み書きできる16ビット分のフラグのうち、上位4ビットは8086世代（V30、80186などを含む）では使われていない予約ビットとなっていた。実際はその部分が1111bとして読み出せたものの、変更はできなかった。80286ではこの部分がプロテクトモードで使われるようになったため、リアルモードではゼロクリアされた状態になった。さらに仮想86モードを持つ80386からはリアルモードにおいてもこのビットが変更可能な仕様になっている。すなわちリアルモードの時点 (BIOSやMS-DOS) において、フラグレジスタのbit15-12が1111bから変更できなければ8086世代、0000bから変更できなければ80286、そのどちらでもない、つまり一部でも変更可能であれば80386以降と判断できる。 8086から使用できる基本命令セットに加え、以下の命令セットが追加された。 80286で新たに追加された命令のうち11個の拡張命令セットは、後に発表された80186にも採用され、共通で使用できた。このほか既存の命令ではIMULとPUSHに即値（イミディエイト）が指定できるようになり、シフト・ローテイト命令ではCLレジスタを介さずに 1 以外の値を直接指定できるようになった。これらは80186でも同様である。 80286で追加されたシステム制御/プロセッサ制御の命令はいずれもプロテクトモードないしは80287関連の命令である。このほか既存命令としてはI/O（入出力）命令の類もシステム制御に使われる命令であり、プロテクトモードでは特権命令の扱いになった。HLTも特権レベルに依存するシステム命令となった。 SGDT, SIDT, SLDT, STR, SMSWは特権命令ではなく、アプリケーションプログラムからも実行可能である。このことは30年以上続いている。インテルは、CPUIDでUMIP(User-Mode Instruction Prevention)ビットがセットされているCPUではこれらの命令を特権命令にする機能を持つとしている。 LGDT … Load Global Descriptor Table Register SGDT … Store Global Descriptor Table Register LIDT … Load Interrupt Descriptor Table Register SIDT … Store Interrupt Descriptor Table Register LLDT … Load Local Descriptor Table Register SLDT … Store Local Descriptor Table Register LAR … Load Access Right LSL … Load Segment Limit ARPL … Adjust Requested Privilege Level VERR … Verify Read Access VERW … Verify Write Access LTR … Load Task Register STR … Store Task Register CLTS … Clear Task Switched Flag LMSW … Load Machine Status Word SMSW … Store Machine Status Word 80286ではPOP CS命令(オペコード 0F)は廃止された。80186/V30も同様である。このオペコードは、80286以降、拡張命令のプリフィックスとして使用された。80286で使われている0Fプリフィックスは、上記のシステム命令のうち、ARPL以外の15命令が該当する。 80286の非公開命令であるLOADALLを使用するとリアルモードのままで、プロテクトメモリを含む16Mバイトのメモリにアクセス可能となる。 80286はリアルモードにおいて8086や80186と高い互換性を持つものの、完全に等価というわけではない。異なる点としては、80286以降ではPUSH SP命令の挙動が変更されている。また既存命令の組み合わせであっても、プロテクトモード上では挙動の異なる場合がある。 このほか変更点として、シフト・ローテイト命令で指定できるCLレジスタの値や即値が31以下に限定されるようになった。指定できる値は8ビットだが、実際には下位5ビット分しか使われない。この変更は80186も同様だが、V30では適用されておらず、8086相当の挙動となる。例えばシフト命令で31（16進数で0x1F）を超える値を指定した場合、8086やV30では演算結果が必ずゼロになるが、80186/286以降では32で割った余剰の分だけシフト演算される。 8086ではFPU命令の実行中はWAIT命令でCPUを止めておく必要があったが、80186以降ではその必要が無くなった。また、LOCK命令はもともとあらゆる命令においてバスをロックできる仕様だったが、80286以降ではロックできる命令とできない命令が決められている。 GDTR (Global Descriptor Table Regsister) IDTR (Interrupt Descriptor Table Regsister) LDTR (Local Descriptor Table Regsister) TR (Task Register) 16bitあるフラグレジスタのうち、bit0からbit11までの12ビットは8086と同様のものが用意されている。前述の通り80186以前では上位4ビットが使われていなかったが、80286ではマルチタスクOSを想定した新たなフラグが追加されている。 IOPL (IO privilege level) フラグ bit12・13を用いる2ビット分のフラグで、0から3までのフラグ状態を持ち、いわゆるIO特権レベルを表す。通常はPOPF命令でなければ変更できない。 NT (Nested task) フラグ bit14。裏のタスクが有効であることを示すフラグ。割り込みなどで呼び出された場合に1となり、これによりIRET命令でのリターン処理の動作が変わる。 なおbit15は予約ビットになっており、80286では不定（80386以降は0）とされている。 80286ではMSW (Machine status word) レジスタが追加された。MSWを読み書きするLMSW、SMSWという専用の命令が用意されている。MSWは16bit分あるが、80286で定義されているのは下位4ビット分だけである。80386以降では新たに設けられたコントロールレジスタに統合され、CR0レジスタの下位16ビットが該当するが、互換性のためMSWとしてもアクセスできる。 PE (Protection enable) MSWのbit0。プロテクトモードであることを表す。このbitをセットすることでプロテクトモードになる。 MP (Math present) MSWのbit1。FPUが存在する場合にセットされる。 EM (Emulate math coprocessor) MSWのbit2。このビットがセットされているとFPUが無い扱いになる。 TS (Task switched) MSWのbit3。タスク切り替え時にセットされる。 8086では割り込みは、割り込み4まで定義されており、80286では割り込み5以降が追加された。割り込み5から31まではインテル予約済みであったが、IBM PCでは割り込み8から15までを8259A経由の外部割込みに割り当てていた。プロテクトモードのOS/2などは8259Aの割り込み番号を別の値に変更する。 割り込み0：除算エラー 除算命令(DIV, IDIV)で0で割ろうとした場合や商が大きすぎてレジスタに収まらない場合に発生する。 割り込み1：シングルステップ割り込み 割り込み2：NMI(マスク不可能割り込み） 割り込み3：ブレークポイント割り込み 割り込み4：INTOオーバーフロー 割り込み5：バウンドチェック BOUND命令に指定されたオペランドが、配列の範囲外に出ていると発生する。 割り込み6：無効オペコード 割り込み7：コプロセッサ不在 タスクスイッチ後、または、80287が装着されていないときに80287の命令を実行すると発生する。 割り込み8：ダブルフォルト 例外を処理しているときにさらに別の例外が発生し処理できなくなったときに発生する。 割り込み9：コプロセッサ・セグメント・オーバーラン 割り込み10：無効タスク・ステート・セグメント 割り込み11：セグメント不在 メモリ上に無いスワップアウトされたセグメントにアクセスした場合に発生する。この割り込みは80286のプロテクトモードで仮想記憶のために使用される。 割り込み12：スタック・フォルト 割り込み13：一般保護例外 80286のリアルモードでは、オフセットFFFFにあるワードオペランドをアクセスしたり、オフセットFFFFから複数バイトの命令を実行しようとすると発生する。8086ではオフセット0にラップアラウンドし例外は発生しない。80286のプロテクトモードでは、データセグメント内の命令の実行、コードセグメント内のデータの書き替え、現在の特権レベルより高い特権レベルのセグメントへのアクセスなどでも一般保護例外が発生する。 割り込み14 - 15：インテル予約済み 割り込み16：コプロセッサ・エラー IBM PC/ATでは80287のERROR#ピンを80286に直結せず、割り込みコントローラ8259Aに接続する設計とした。コプロセッサ(FPU)を内蔵した80486以降のCPUではIBM PC/ATとの互換性を維持するためにCPUにFERR#, IGNNE#というピンを追加したが、CR0レジスタのNEビットを1にすると8259A経由ではなく本来の割り込み16でコプロセッサのエラーを通知する。 割り込み17 - 31：インテル予約済み 80286ではセグメントレジスタには可視部とディスクリプターキャッシュ部があり、プログラムから直接 ディスクリプターキャッシュ部の変更はできない。プロテクトモードでは、セグメントレジスタの値の変更時に、グローバルディスクリプターテーブル、またはローカルディスクリプターテーブルからディスクリプターキャッシュ部にアクセス権、ベースアドレス、セグメントリミットが読み込まれ、実際のメモリアクセスはディスクプターキャッシュ部が使われる。 リアルモードでは、セグメントレジスタの値の変更時に、セグメントレジスタの内容が16倍されたものがディスクリプターキャッシュ部のベースアドレスにロードされ、実際のメモリアクセスはディスクプターキャッシュ部が使われる。このためリアルモードからプロテクトモードに移行した直後、セグメントレジスタの値がプロテクトモードでは不正な値でもハングアップや例外は発生しない。 また、80286は電源ONまたはリセット後、コードセグメントのディスクリプタキャッシュ部は、ベースアドレスがFF0000Hに設定され、IPはFFF0に設定されるので、FFFFF0Hから実行が開始される特殊なリアルモードで始まる。この特殊な状態はCALL FAR, JMP FAR命令などでセグメントレジスタが更新されるまで続く。 80287 NPX 80286用の数値演算コプロセッサ。8086用のコプロセッサである8087と異なりI/Oポート （00F8H - 00FDH） を用いてデータや命令のやり取りを行う。パッケージは40ピンDIPである。 82284 クロック生成器 82288 バスコントローラ 82289 バス調停器 8259A 割り込みコントローラ 80286システムはCPUアクセラレータ製品により、より上位のプロセッサが利用できる場合があった。その際、486相当の製品は起動後にソフトウエアでCPUキャッシュを有効にすることで高速化させる必要があった。80286システムは16ビットバスであるため、外部16ビットであるi386SXにピン互換のCyrix Cx486SLC登場後は、これを用いた80286用のCPUアクセラレータ製品が各社から登場した。特に日本で主流だったPC-9800シリーズおよびEPSON PC-286シリーズでは80286をソケット経由で実装した機種が多く、CPU交換が容易だった。結果的にV30や後のi386SXと比べてCPUのアップグレードパスに恵まれ、様々なバリエーションのCPUアクセラレータ製品を生んだ。 ABM 486GT-Xは前述のような486互換プロセッサを80286ピン互換のワンチップサイズに封入したもので、CPUアクセラレータと言うより80286ピン互換CPUに近いものだった。 CPUアクセラレータ基板上でCyrix Cx486DLCのような外部32ビットプロセッサを動かす製品も存在した。 メルコはシステムバスのクロックに関係無く独立クロック動作する製品も出していた。 最終的にメルコやアイ・オー・データ機器から発売されていたIBM 486SLC2を用いた80286向け製品では最大4倍速(約50MHz)で動作した。 数値演算プロセッサ 多くの80286用CPUアクセラレータはその基板上に80387のソケットもしくはその互換チップを直付けしており、386/486互換CPU換装時に80387相当の数値演算機能が利用できるようになっていた。 HIMEM.SYSの問題 PC-9800シリーズにおいては、80286のシステムとi386以上のシステムではA20ラインを制御するI/Oポートが異なり、前者にi386以上のプロセッサを載せた場合、そのシステムには後者にあるI/Oポート00F6hが無く、MS-DOS付属のメモリマネージャ(HIMEM.SYS)がA20ラインを正常にコントロールできない旨の警告を出す問題が知られている。その対策として、いくつかのCPUアクセラレータではCPUキャッシュドライバとは別に独自のメモリマネージャを添付、もしくは専用メモリマネージャにCPUキャッシュドライバを統合していた。 日本語版Windows 3.1への対応 上記の通り、英語版Windows 3.1は80286プロテクトモードをサポートしたが、マイクロソフト版やNEC版の日本語版Windows 3.1では80286をサポートしなかった。CPUをi386以上にアップグレードした場合でもマザーボードが80286用であることをWindows 3.1のインストーラが感知してセットアップを中断してしまう場合があり、これを防止するために80286用CPUアクセラレータ製品のいくつかはWindows 3.1をインストールできるようにするためのツールが用意されていた。 ただし80286システムはCPUを386以上に変えてもメモリまわりに制約が残るケースが多く、快適にWindowsを利用できるケースは限られていた。もともと80286全盛時代の機種にはプロテクトモード用の1MBを超えるアドレスのメモリ（プロテクトメモリ）に専用の高速スロットが無いか、あっても増設できる容量が少ないケースがあった。そのうえ本来のDOS用途ではプロテクトメモリをEMSに転用すると80286機では効率が悪く低速になることが知られていた。結果的に80286機ではWindows用途に向いた専用プロテクトメモリが普及せず、DOS用途のメモリとして汎用拡張スロット用メモリが主に使われていた。その中にはプロテクトメモリに転用できるものもあったが、プロテクトメモリ用途としては専用スロットに増設するよりも低速であるため、メモリに負担をかけるWindows用途ではそれによる速度低下が顕著に現れた。 なおWindows 95や98はOS自体が早い段階で80286以下のマザーを感知して起動を止めてしまう仕様のため、事前にDOSを起動するなどしてCPU情報を再設定したうえで高速再起動ツールなどでその「早い段階」をパスできるように工面するか、もしくはOSの起動プログラムを改造して機種判別ルーチンをつぶさない限り、たとえCPUを換えても80286マザー上でWindows 95を動かすことはできない。 注釈