CPU実験室

誰も見向きもしない古いCPUをいじって動かしてみようというプロジェクトです

割込みテスト

受信完了で割込みを発生させるためV53内蔵割込みコントローラ(ICU)のテスト。
V53に内蔵されているICUは昔からあるi8259のサブセット(というか不要な8085モードを削除しただけ)でこれは使った経験はあります。
8259はアドレス空間が2つしかないのにここにたくさんのレジスタマッピングしているので一見複雑そうですがシーケンスに従い2,3個のレジスタの初期化ですみます。

あ、あとV53という石は8251/8253/8259/8237がほとんどフルセットで組込まれ、
ピンもそのまま素で出ていて内部結線すらされていません。
最近の1chipマイクロコントローラはピン節約のために1つのピンに機能がマルチプレックスされていて設定も複雑だし、設定によって使えない機能も出てしまうのだけれど、
V53はその点単純で教育用には良いかもしれませんw。
ただしそのためにピンが多くなり168ピンセラミックPGAという仰々しいパッケージになったんだけど。

割込みの方ですが、初期化は良いとしてC言語で割込みルーチンをどう記述するかが問題です。Cの通常のサブルーチンはRETで終わりますが、割込みルーチンはIRETで終了させなければなりません。
処理系によってはたとえば#pragma interruptといった指定でつづくサブルーチンの最後をIRETにしてくれたりするのですがLSIC86ではそれができません。
調べていたらこんなうまい方法で解決しているソースを見つけました。

割込みルーチンの先頭と最後にインライン文でニーモニックを直接記述してしまう。
ここで最後にPOP DXを入れるのがミソでこれでCコンパイラが生成するPUSH DXと対になって整合が取れる。そして最後のIRETで割り込みルーチンを終わる

ソース;
void far func(void)
{
_asm_c("\n\tPUSH AX\n\tPUSH ES\n");

:処理の本体

_asm_c("\n\tPOP ES\n\tPOP AX\n\tPOP DX\n\tIRET\n");

}
これをコンパイルすると→のところにコードが挿入されて割り込みルーチンの体裁になる。
func_::
PUSH DX ;コンパイラが生成
→ PUSH AX  ;挿入
→ PUSH ES ;挿入

:処理の本体

→ POP ES ;挿入
→ POP AX ;挿入
→ POP DX ;挿入
→ IRET ;挿入されたIRET
POP DX ;コンパイラが生成(ここのコードは無意味になる)
RETF ;コンパイラが生成(ここのコードは無意味になる)