65xx ファミリのマイクロプロセッサは、MOS Technology 6502とその派生製品であるWDC 65C02、WDC 65C802 、WDC 65C816、CSG 65CE02で構成され、すべて同様の方法で割り込みを処理します。すべての 65xx プロセッサに共通する 3 つのハードウェア割り込み信号と、 1 つのソフトウェア割り込み(BRK命令) があります。WDC 65C816 では、4 つ目のハードウェア割り込み(仮想メモリ アーキテクチャの実装に便利なABORT ) と、何らかのコプロセッサ(浮動小数点プロセッサなど)を備えたシステムで使用することを目的としたCOPソフトウェア割り込み命令 (65C802 にも存在) が追加されています。[1] [2]
割り込みの種類
ハードウェア割り込み信号はすべてアクティブローであり、次のようになります。[1]
- リセット
- リセット信号、レベルトリガー
- 北アイルランド
- マスク不可能な割り込み、エッジトリガー
- IRQ
- マスク可能な割り込み、レベルトリガー
- アボート
- 特殊目的のマスク不可能割り込み(65C816のみ、下記参照)、レベルトリガー
RESET信号が検出されると、プロセッサは6クロックサイクルのシステム初期化期間に入り、その後、ステータスレジスタの割り込み要求無効化フラグを設定し、実行を開始する前にプロセッサ初期化ベクトル( $00FFFC- $ 00FFFD)に格納されている値をプログラムカウンタにロードします。 [1] ネイティブモードで動作している場合、65C816/65C802はエミュレーションモードに戻り、ソフトウェア制御によってネイティブモードに戻るまでそのモードのままになります。
NMIまたはIRQ信号の検出、およびBRK命令の実行は、同じ全体的なイベントシーケンスを引き起こします。順序は次のとおりです。[1] [3]
- プロセッサは、割り込みに応答する前に、現在の命令を完了し、必要に応じてレジスタまたはメモリを更新します。
- 65C816/65C802 がネイティブ モードで動作している場合: プログラム バンク レジスタ ( PB、アドレス バスのA16 ~ A23部分) がハードウェア スタックにプッシュされます。
- プログラムカウンタ( PC )の最上位バイト(MSB)がスタックにプッシュされます。
- プログラム カウンターの最下位バイト (LSB) がスタックにプッシュされます。
- ステータスレジスタ ( SR ) がスタックにプッシュされます。
- ステータス レジスタに割り込み無効フラグが設定されます。
- 65C816/65C802: PBに$00がロードされます。
- PC は関連するベクターからロードされます (表を参照)。
ABORTがアサートされたときの 65C816 の動作は、上記の説明とはいくつかの点で異なるため、以下で別途説明します。
プロセッサはアキュムレータとインデックスレジスタをスタックにプッシュしないことに注意してください。割り込みハンドラのコードがそのタスクを実行し、必要に応じて割り込み処理の終了時にレジスタを復元する必要があります。また、 IRQのベクターは、すべての 8 ビット 65xx プロセッサ、およびエミュレーション モードで動作している 65C802/65C816 のBRKのベクターと同じであることにも注意してください。ネイティブ モードで動作している場合、65C802/65C816 はIRQとBRKに別々のベクターを提供します。[4]
割り込み要求無効化フラグ (ステータス レジスタのIビット) がセットされると、 IRQ信号の検出が無効になりますが、他の割り込みには影響しません (ただし、 WDC CMOS プロセッサに実装されているWAI命令については、以下のセクションを参照してください)。さらに、65(c)02 または 65C816/65C802 がエミュレーション モードで動作している場合、スタックにプッシュされるステータス レジスタのコピーでは、BRK (ソフトウェア割り込み) が割り込みの原因である場合はBフラグがセットされ、 IRQ が原因である場合はクリアされます。[注 4] したがって、割り込みサービス ルーチンは、スタックにプッシュされた場所から保存されたステータス レジスタのコピーを取得し、Bフラグの状態をチェックして、 IRQとBRKを区別する必要があります。[1] [2] [4] この要件は、65C802/65C816 をネイティブ モードで動作させる場合は、2 つの割り込み タイプに別々のベクターがあるため、不要になります。[2]
アボート割り込み
65C816 のABORTB割り込み入力は、ページ フォールトやメモリ アクセス違反などのハードウェア例外が検出されたときに、プログラム実行をリダイレクトする手段を提供することを目的としています。したがって、 ABORTB入力がアサート (ネゲート) されたときのプロセッサの応答は、 IRQBやNMIBがアサートされたときとは異なります。また、 ABORTBに応答して正しい動作を実現するには、割り込みがマシン サイクル中の適切なタイミングで発生することが必要ですが、 IRQBやNMIBにはそのような要件はありません。
有効なメモリサイクル中にABORTBがアサートされると、つまりプロセッサがVDAおよび/またはVPAステータス出力をアサートすると、次の一連のイベントが発生します。[2]
- プロセッサは現在の命令を完了しますが、レジスタやメモリを一切変更しません。完了した命令の計算結果は破棄されます。中止割り込みは文字通り命令を中止するものではありません。[2]
- プログラム バンク ( PB、上記参照) がスタックにプッシュされます。
- 中止された命令のアドレスの最上位バイト (MSB)がスタックにプッシュされます。
- 中止された命令のアドレスの最下位バイト (LSB)がスタックにプッシュされます。
- ステータス レジスタがスタックにプッシュされます。
- ステータス レジスタに割り込み無効フラグが設定されます。
- PBには$00がロードされます。
- プログラム カウンターはABORTベクトルからロードされます (表を参照)。
スタックにプッシュされるアドレスはプログラム カウンタの内容ではなく中止された命令のアドレスであるため、ABORT 割り込みの後に RTI (割り込みからの復帰) を実行すると、プロセッサは他の割り込みの場合のように次の命令ではなく中止された命令に戻ります。
プロセッサがアボートに正しく応答するためには、有効なアドレスがバス上に配置され、そのアドレスがページフォールト、メモリアクセス違反、またはその他の異常(特権命令の実行試行など)を構成すると判断されるとすぐに、システムロジックがABORTB入力をアサート(ネゲート)する必要があります。したがって、プロセッサがVDAまたはVPA信号をアサートするまで、ロジックはABORTB をアサートしてはなりません。また、ABORTB はフェーズ 2 クロックの立ち下がりまでアサートされたままで、その後すぐに解放される必要があります。これらのタイミング制約が守られない場合、アボート割り込みハンドラ自体がアボートされ、レジスタやメモリが定義されていない方法で変更される可能性があります。[2]
割り込み異常
NMOS 6502 および派生製品 (例: 6510)では、ハードウェア割り込みラインの同時アサートとBRKの実行は設計上考慮されておらず、このような場合にはBRK命令は無視されます。また、プロセッサ ステータス レジスタの10 進モードフラグの状態は、どのような割り込みの後も変更されません。この動作により、割り込み時に 10 進モードが有効になっている場合、割り込み ハンドラでバグを見つけるのが困難になる可能性があります。これらの異常は、プロセッサのすべてのCMOSバージョンで修正されました。 [2]
割り込みハンドラの考慮事項
適切に設計された簡潔な割り込みハンドラまたは割り込みサービス ルーチン(ISR) は、割り込みの原因となるイベントを迅速に処理するだけでなく、中断されたフォアグラウンド タスクに一切干渉することなく処理を行います。つまり、ISR は中断されたタスクに対して「透過的」である必要があります (ただし、特殊なケースでは例外が適用される場合があります)。つまり、ISR はマイクロプロセッサ (MPU) の状態を保持し、メモリ内の干渉すべきでないものを干渉しない必要があります。さらに、ISR は完全に再入可能である必要があります。つまり、2 つの割り込みが連続して到着した場合、ISR は 2 番目の割り込みが処理された後に最初の割り込みの処理を再開できます。再入可能性は通常、ストレージにMPU ハードウェア スタックのみを使用することで実現されます(ただし、他の方法も使用できます)。
MPU の状態を保存するということは、割り込み時に MPU レジスタにあった値が ISR の終了時にも存在することを ISR が保証する必要があることを意味します。保存プロセスの一部は、割り込みを認識すると MPU によって自動的に処理され、ISR を実行する前にプログラム カウンタ (および 65C816/65C802 のプログラム バンク) とステータス レジスタがスタックにプッシュされます。ISR の完了時にRTI命令が実行されると、MPU はプロセスを逆にします。65xx ファミリのどのメンバーも、他のレジスタをスタックにプッシュしません。[2]
ほとんどの ISR では、アキュムレータ レジスタやインデックス レジスタは透過性を保証するために保存され、RTI を実行する前の最終ステップとして後で復元される必要があります。65C816/65C802 の場合、割り込み時にエミュレーション モードとネイティブ モードのどちらで動作しているかを考慮する必要があります。後者の場合、透過性を保証するためにデータ バンク ( DB ) レジスタと直接 (ゼロ) ページ ( DP ) レジスタも保存する必要がある可能性があります。また、65C816 ネイティブ モード オペレーティング システムは、アプリケーション ソフトウェアとは異なるスタック位置を使用する可能性が高いため、ISR はスタック ポインタ( SP )を保存し、後で復元する必要があります。65C816/65C802 でさらに問題を複雑にしているのは、ネイティブ モードで動作しているときのアキュムレータ レジスタとインデックス レジスタのサイズが 8 ビットまたは 16 ビットのいずれかになる可能性があるため、後で復元できるようにサイズを保存する必要があることです。[2]
ISR 内で MPU の状態を保存および復元する方法は、65xx ファミリのバージョンによって異なります。NMOS プロセッサ (6502、6510、8502 など) の場合、スタックにプッシュしたりスタックからプルしたりできるのはアキュムレータのみであるため、アキュムレータとインデックス レジスタを保存する方法は 1 つしかありません。[5] したがって、次の ISR エントリ コードが一般的です。
PHA ; アキュムレータを保存TXA PHA ; Xレジスタを保存TYA PHA ; Yレジスタを保存CLD ; 10進フラグをクリアしてバイナリモードを確保する
CLD命令が必要なのは、前述のように、6502 の NMOS バージョンでは割り込みが発生したときにステータス レジスタの D (10 進モード) フラグがクリアされないためです。
アキュムレータとインデックス レジスタが保存されると、ISR は必要に応じてそれらを使用できます。ISR は作業を完了すると、レジスタを復元し、中断されたフォアグラウンド タスクを再開します。ここでも、次の NMOS コードが一般的です。
PLA
TAY ; Yレジスタを復元PLA TAX ; Xレジスタを復元PLA ; アキュムレータを復元RTI ; 中断されたタスクを再開
RTI命令の結果、MPUは割り込み時の状態であれば10進モードに戻ります。[5]
65C02および 65C816/65C802は、エミュレーションモードで動作する場合、アキュムレータを仲介として使用せずにインデックスレジスタをプッシュおよびプルできるため、必要なコードが少なくなります。[2] また、ISR を実行する前に 10 進モードを自動的にクリアします。[2] 典型的な例は次のとおりです。
PHA ; アキュムレータを保存PHX ; Xレジスタを保存PHY ; Yレジスタを保存
終了すると、ISR はプロセスを逆に実行します。
PLY ; Yレジスタを復元PLX ; Xレジスタを復元PLA ; アキュムレータを復元RTI ; 中断されたタスクを再開
前述のように、65C816/65C802 をネイティブ モードで動作させる場合、レジスタ サイズが可変であることと、DB レジスタとDPレジスタを考慮する必要があることから、少し複雑になります。インデックス レジスタの場合、サイズに関係なくプッシュできます。サイズを変更すると、これらのレジスタの最上位バイト (MSB) が自動的にゼロに設定され、プッシュされた値が復元されてもインデックス レジスタがプッシュされたときと同じサイズであれば、データは失われません。[2]
しかし、アキュムレータは実際には 2 つのレジスタで、.Aと.Bで指定されます。[2] アキュムレータが 8 ビットに設定されているときにプッシュすると、.Bは保持されません。 [2]その結果、ISR が.B を何らかの方法で変更した場合に透過性が失われる可能性があります。したがって、ISR が.B を使用する場合は、プッシュまたはプルする前にアキュムレータを常に16 ビットに設定する必要があります。また、インデックス レジスタをプッシュする前に 16 ビットに設定すると効率的です。そうしないと、ISR はステータス レジスタの追加のコピーをプッシュして、スタックからプルする前にレジスタ サイズを復元する必要があります。
ほとんどの ISR では、次のエントリ コードによって透明性の目的が達成されます。
PHB ; 現在のデータ バンクを保存PHD ; 直接ページ ポインタを保存REP #%00110000 ; 16 ビット レジスタを選択PHA ; アキュムレータを保存PHX ; X レジスタを保存PHY ; Y レジスタを保存
上記のコード フラグメントでは、シンボル% は、ビット単位のオペランドのMOS テクノロジーおよびWDC標準アセンブリ言語構文です。
ISR に独自のスタック位置が割り当てられている場合、上記のプッシュが発生した後、スタック ポインタ ( SP ) がメモリ内に保存される必要があります。その理由は明らかです。上記のシーケンスに追加される次のコードは、この要件を処理します。
TSC ; スタック ポインタをアキュムレータにコピーしますSTA stkptr ; 安全な RAM のどこかに保存しますLDA isrptr ; ISR のスタック ポインタを取得します &... TCS ; 新しいスタックの場所を設定します
ISR が完了すると、上記のプロセスは次のように逆になります。
REP #%00110000 ; 16 ビット レジスタを選択TSC ; ISR の SP を保存... STA isrptr ; 後続の使用のためLDA isstkptr ; フォアグラウンド タスクの SP を取得... TCS ; それを設定するPLY ; Y レジスタを復元PLX ; X レジスタを復元PLA ; アキュムレータを復元PLD ; 直接ページ ポインタを復元PLB ; 現在のデータ バンクを復元RTI ; 中断されたタスクを再開する
RTIを実行すると、65C816/65C802は、以前に保存されたステータスレジスタを引き出すことで、両方のレジスタサイズビットを割り込み時の状態に設定またはクリアするため、レジスタサイズを割り込み発生時の状態に自動的に復元することに注意してください。[2]
65C816/65C802 を ISR 内でネイティブ モードからエミュレーション モードに切り替えることは可能ですが、これには危険が伴います。[2] エミュレーション モードに入ると、アキュムレータとインデックス レジスタが 8 ビットに強制される (インデックス レジスタの最上位バイトが失われる) ことに加え、スタック ポインタが 8 ビットに切り捨てられ、スタック自体がページ 1 RAMに再配置されます。[2] その結果、割り込み時に存在していたスタックは、ページ 1 RAM に存在し、256 バイト以下でない限りアクセスできなくなります。一般に、割り込み処理中のモード切り替えは推奨される手順ではありませんが、特定の動作環境では必要な場合があります。
使用BRKそして警官
前述のように、BRKとCOP はソフトウェア割り込みであり、システム機能を実装するためにさまざまな方法で使用できます。
BRKの歴史的使用法は 、システムのファームウェアでバグが発見されたときにPROM のパッチ適用を支援することでした。ファームウェア開発中によく使用される典型的な手法は、BRKベクトルが PROM 内のプログラムされていない「パッチ領域」を指すようにすることです。バグが発見された場合、パッチ適用は、欠陥のある命令が配置されているアドレスのすべてのヒューズを「飛ばす」ことによって行われ、その結果、命令のオペコードが$00に変更されます。結果として得られたBRK を実行すると、MPU はパッチ領域にリダイレクトされ、適切なパッチ コードがそこに書き込まれます。多くの場合、パッチ領域コードは、バグが発生したアドレスを決定するために「スタックをスニッフィング」することから始まり、PROM 内に複数のパッチが存在する可能性があります。EPROM と EEPROM が一般的に利用可能になると、PROM パッチ適用のための BRK の使用は減少し ました。
ソフトウェア開発におけるBRKのもう 1 つの用途は、マシン言語モニターと組み合わせたデバッグ補助機能です。オペコードをBRK ( $00 ) で上書きし、BRKハードウェア ベクトルをモニターのエントリ ポイントに向けると、任意のポイントでプログラムを停止してモニターに制御を移すことができます。そのときに、メモリを調べたり、プロセッサのレジスタ値を表示したり、コードを修正したりすることができます。Kuckes と Thompson が提唱しているように、デバッグは、デバッグ対象のプログラムの実際の動作を変更することなくBRK命令に置き換えることができるNOP命令 (オペコード$EA ) をコードにたっぷり散りばめることによって容易になります。 [5] [6] [7]
BRK命令とCOP命令の特徴は、プロセッサがどちらも 2 バイト命令として扱うことです。オペコード自体と、それに続くバイト (「シグネチャ」と呼ばれます) です。[2] BRKまたはCOP を実行すると、プロセッサはプログラム カウンタをスタックにプッシュする前に、そのカウンタに 2 を加算します。したがって、RTI (割り込みからの復帰)が実行されると、中断されたプログラムはシグネチャの直後のアドレスから続行されます。BRKをデバッグ デバイスとして使用する場合、実行が期待どおりに再開されるように、プログラム カウンタを調整してシグネチャを指すようにする必要があります。または、シグネチャの「プレースホルダ」としてNOP を挿入することもできます。この場合、プログラム カウンタの調整は必要ありません。
BRKとCOP はプログラム カウンタをスタックにプッシュする前に 2 倍に増分するため、一部のメインフレーム コンピュータで見られるようなスーパーバイザ呼び出し命令として扱う手法が容易になります。通常の手順では、シグネチャをオペレーティング システムのサービス インデックスとして扱います。オペレーティング システムのBRKまたはCOPハンドラは、スタックにプッシュされたプログラム カウンタの値を取得し、それを減分して、結果のメモリ位置から読み取り、シグネチャを取得します。[8] [9] シグネチャをゼロベースのインデックスに変換した後、簡単なルックアップ テーブルを参照して、適切なサービス ルーチンのアドレスをプログラム カウンタにロードできます。サービス ルーチンが完了すると、RTI命令を使用して、オペレーティング システム コールを実行したプログラムに制御が返されます。BRK のシグネチャは任意の値にすることができますが、COPのシグネチャは$00 - $7F の範囲に制限されることに注意してください。[2]
BRKやCOPを使用してオペレーティング システム サービスを要求すると、ユーザー アプリケーションは各オペレーティング システム関数のエントリ アドレスを知る必要がなくなり、目的の操作を呼び出すための正しいシグネチャ バイトのみを知る必要があります。したがって、メモリ内のオペレーティング システムの再配置によって、既存のユーザー アプリケーションとの互換性が損なわれることはありません。また、BRKまたはCOP を実行するとプロセッサが常に同じアドレスにベクトル化されるため、要求されたサービスに制御を渡す前に、単純なコードを使用してスタック上のレジスタを保持できます。ただし、このプログラミング モデルでは、主に割り込みで発生するスタック アクティビティの結果として、サービスをサブルーチンとして呼び出す場合と比較して、実行速度がいくらか遅くなります。また、 BRKまたはCOP を実行すると割り込み要求が無効になるため、オペレーティング システムで再度有効にする必要があります。
ワイそして標準説明書
WAI ( WA it はI nterrupt の略、オペコード$CB ) は、65C02 および 65C816/65C802 マイクロプロセッサ (MPU) の WDC バージョンで使用可能な命令ハードウェア割り込みが発生するまでMPU を停止して半緊張状態にします。 [2] WAIの主な用途は、予期されるイベントが発生するまで MPU が何もする必要がなく、システムが待機中であるため消費電力を最小限に抑えたい場合や、迅速な応答が必要な場合など、低電力の組み込みシステムです。WAIを使用する典型的なコード例は次のとおりです。
SEI ; IRQ を無効にするWAI ; ハードウェア割り込みを待つ; ... ここで実行が再開されます
上記のコード フラグメントでは、MPU はWAIの実行時に停止し、非常に低消費電力の状態になります。WAI 命令の前に割り込み要求 (IRQ) が無効になっているにもかかわらず、 MPU は待機中にハードウェア割り込みに応答します。IRQ を受信すると、MPU は 1 クロック サイクルで「起動」し、WAI の直後の命令から実行を再開します。したがって、割り込み待ち時間は非常に短く (14 メガヘルツで 70 ナノ秒)、外部イベントに対して可能な限り迅速に応答できます。
WAIといくつかの点で似ているのがSTP ( ST o P、オペコード$DB ) 命令で、これは単一の割り込み入力を待機している間 MPU を完全にシャットダウンします。[2] STPが実行されると、MPU は内部クロックを高位相で停止し、レジスタ内のすべてのデータを保持して、低電力状態になります。MPU は、リセット入力ピン ( RESB、割り込み入力として分類される) を低にすることでこの状態から解除されます。その後、実行は、ハードウェア リセット ベクターである$00FFFC-$00FFFDに格納されているアドレスから再開されます。 WAIと同様に、STP は、MPU の注意を必要とするイベント間に長い時間が経過し、他の処理が不要な低電力組み込みアプリケーションで使用することを目的としています。STPは、処理が完全に停止するため、通常のプログラミングでは使用されません。
脚注
- ^ ab ABORT入力はW65C816Sでのみ使用可能です。[2]
- ^ ab COP命令は両方の動作モードで使用可能です。[2]
- ^ 65C816/65C802にはRESET信号用のネイティブモード割り込みベクターがないため、リセットによってプロセッサは常にエミュレーションモードに戻ります。[2]
- ^ ステータスレジスタ自体のBフラグの値は、割り込みの種類に関係なく 常に1です。Bは、割り込みに応答してスタックにプッシュされるステータスレジスタのコピーでのみ意味を持ち、フラグレジスタには実際には存在しません。[2]
参考文献
- ^ abcde Anderson, JS (1994).マイクロプロセッサテクノロジー. Butterworth-Heinemann. pp. 143–144. ISBN 9780750618397。
- ^ abcdefghijklmnopqrstu vwxyz aa David Eyes および Ron Lichty (1992-04-28). 「65816 のプログラミング」(PDF) 。The Western Design Center, Inc. 2012-07-23 のオリジナル(PDF)からアーカイブ。2012-11-29に取得。
- ^ ab 「基本アーキテクチャ」6502. 2002-01-02.
- ^ ab Leo J. Scanlon (1980). 6502 ソフトウェア設計. HW Sams. pp. 172–173. ISBN 9780672216565。
- ^ abc Lance A. Leventhal (1986). 6502 アセンブリ言語プログラミング. Osborne/McGraw-Hill. ISBN 9780078812163。
- ^ Ronald J. Tocci および Lester P. Laskowski (1979)。マイクロプロセッサとマイクロコンピュータ: ハードウェアとソフトウェア。Prentice-Hall。p. 379。ISBN 9780135813225。
- ^ クックス、アーサー F.トンプソン、BG (1987)。研究室の Apple II。アーカイブをUPしました。 p. 93.ISBN 9780521321983LCCN 86-21531 。
- ^ Harrod, Dennette A. (1980 年 10 月)。「6502 がマイクロプログラム可能な命令を搭載」。BYTE。第 5 巻、第 10 号。McGraw Hill。282~ 285 ページ。2006 年 5 月 25 日時点のオリジナルよりアーカイブ。2009年 5 月 31 日閲覧。
- ^ Richard R. Smardzewski (1984)。科学者とエンジニアのためのマイクロプロセッサプログラミングとアプリケーション。Elsevier。p. 125。ISBN 9780444424075。
さらに読む
- MOS 6502 の BRK/IRQ/NMI/RESET の内部
- Brad Taylor。「6502 'B' フラグと BRK オペコード」。
- 6502 ファミリー マイクロプロセッサ リソースとフォーラム
- 65xx 割り込み入門 – 65xx ファミリの割り込み処理に関する詳細な説明。
- 65C816 割り込みの調査 – 65C816 ネイティブ モード操作に固有の割り込み処理に関する詳細な説明。
