[PP0906] 14. 不正命令例外
ここまでで 28 種類の命令を追加してきました。デコーダにあたる switch 文もかなり長くなったことと思います。ところで、この switch 文ですが、まだ default ラベルを書いていませんね。今回は、定義されていない命令を実行しようとしたときの PP0906 の動作を定義したいと思います。
PP0906 では、定義されていない命令を実行しようとすると、不正命令例外が発生します。不正命令例外はプロセッサの例外の一種です。内部割込みという言いかたをする場合もあります。
不正命令例外が発生すると、PP0906 の場合、現在の PC の値をスタックに退避したうえで、0xf000 番地にある例外ハンドラを呼出します。例外ハンドラは一種のサブルーチンですので、RET 命令で戻ることができます。
それでは、不正命令例外を発生させるプログラムを書いてみることにします。
int program[] =
{
LXI, 0x10000,
MOVSX,
-2,
LI, 123,
OUT,
-1
};
int illegal[] =
{
LI, -2,
OUT,
RET
};
{
LXI, 0x10000,
MOVSX,
-2,
LI, 123,
OUT,
-1
};
int illegal[] =
{
LI, -2,
OUT,
RET
};
ここで、-2 というのが「不正命令」にあたります。配列 illegal は不正命令例外のための例外ハンドラですので、memcpy で 0xf000 番地のロードしてください。このプログラムを実行した場合に想定する結果は次の通りです。
0xfffffffe(-2)
0x0000007b(123)
0x0000007b(123)
では、不正命令例外を発生させる動作を定義しましょう。
default:
eaddr = 0xf000;
sp = sp - 1;
memory[sp] = pc;
pc = eaddr;
break;
eaddr = 0xf000;
sp = sp - 1;
memory[sp] = pc;
pc = eaddr;
break;
CALL 命令と比べてみると、呼出し先のアドレスを取得する必要がない点をのぞけば、まったく同じであることがわかると思います。実際のプロセッサでは、例外ないしは内部割込みの動作が、サブルーチンの呼び出しとは異なる場合もよくあります。例えば、スタックに退避するのが PC だけでなく、フラグなど、別のレジスタも一緒に退避したりします。PP0906 は簡単であることを目標にしていますので、このような設計にしました。
この記事のトラックバックURL:
http://www.kijineko.co.jp/trackback/529
ブックナビゲーション
- 技術情報
- Boost C++ Libraries メモ
- C++と組込み環境
- C++サンプル集
- C++テンプレート集
- C++プログラマのためのC言語入門
- C/C++迷信集
- C99関数・マクロ・前処理スクリプト集
- C言語再入門
- C言語徹底入門
- Drupal メモ
- TOPPERS 情報
- ベターCとしてのC++
- マイコン メモ
- ライブラリ開発入門
- 分割コンパイルをきわめる
- 擬似プロセッサを作る
- PP0906 - 初級者向け擬似プロセッサ
- [PP0906] 00. 擬似プロセッサ PP0906 を作る
- [PP0906] 01. 擬似プロセッサ PP0906 の仕様
- [PP0906] 02. 主記憶と制御装置
- [PP0906] 03. 何もしないプログラム
- [PP0906] 04. 即値のロードと出力
- [PP0906] 05. レジスタ間の転送
- [PP0906] 06. ニーモニックを使う
- [PP0906] 07. ロードとストア
- [PP0906] 08. ジャンプ
- [PP0906] 09. スタック操作
- [PP0906] 10. コールとリターン
- [PP0906] 11. インクリメントとデクリメント
- [PP0906] 12. 条件分岐
- [PP0906] 13. 加算と減算
- [PP0906] 14. 不正命令例外
- [PP0906] 15. まとめ
- PP0906 - 初級者向け擬似プロセッサ
- 象の卵を探して...
- 車輪の再発明
- 過去の情報

