擬似プロセッサ
擬似プロセッサの新作を作ってみました。
まだテストもしきれていませんし、コードも雑なのですが、擬似プロセッサの新作を作ってみました。
http://www.kijineko.co.jp/files/pt2010-20100225.zip
他にやらなければならないことが山積なのですが、あいにく風邪で体調が悪く、混みいったことはできそうにないので、思いっきり現実逃避した結果の成果物です。
今回はC++で実装し、レジスタにはboolの配列を使いました。当然、加減算器は半加算器をもとに作った全加算器を組み合わせて使っています。ステータスフラグもあれば、マスク可能な割り込み(ただし優先度はなし)も作ってみました。外部I/Oはコールバック関数で処理するようにしましたので、どんな足回りでも外付けすることができます。まだドキュメントがありませんので、そのうち解説記事を書くようにします。
ところで、擬似プロセッサという呼称はいまいちよくなくて、本当は仮想プロセッサと呼ぶべきなのでしょうが、そう呼ぶと別のものを想像してしまったりするので、あえてこう読んでいます。
PP0906 - 初級者向け擬似プロセッサ
PP0906は、初級者向けのごく簡単な擬似プロセッサです。C言語を使って実装していますが、ポインタが苦手な人でも理解しやすいように工夫しています。ただ、ワードマシンですので、現在の多くのプロセッサとはかなり雰囲気が異なります。
[PP0906] 15. まとめ
擬似プロセッサ PP0906 について連載を続けてきましたが、今回でひとまず終わりにしたいと思います。まだ、シフト命令や論理命令、乗除算命令などを定義していませんが、加減算と同じようにすれば簡単に追加することができるはずです。0 で除算しようとした場合に、ゼロ除算例外を発生させるのもよいでしょう。
今回は、これまでのまとめですので、断片的にしか記載してこなかったプログラムをまとめたソースファイルを添付しておきます。ほとんどコメントは入っていませんが、本文で十分な解説を行いましたので大丈夫でしょう。
今後、また機会があれば、もう少し本格的な擬似プロセッサ、あるいは実在するプロセッサのシミュレータなどを作ってみたいと思います。
[PP0906] 14. 不正命令例外
ここまでで 28 種類の命令を追加してきました。デコーダにあたる switch 文もかなり長くなったことと思います。ところで、この switch 文ですが、まだ default ラベルを書いていませんね。今回は、定義されていない命令を実行しようとしたときの PP0906 の動作を定義したいと思います。
PP0906 では、定義されていない命令を実行しようとすると、不正命令例外が発生します。不正命令例外はプロセッサの例外の一種です。内部割込みという言いかたをする場合もあります。
不正命令例外が発生すると、PP0906 の場合、現在の PC の値をスタックに退避したうえで、0xf000 番地にある例外ハンドラを呼出します。例外ハンドラは一種のサブルーチンですので、RET 命令で戻ることができます。
それでは、不正命令例外を発生させるプログラムを書いてみることにします。
[PP0906] 13. 加算と減算
11. インクリメントとデクリメントでは、1 増やすまたは 1 減らすための命令を作りました。しかし、一般的には任意の値どうしを足したり、引いたりできる必要があります。今回は、そのための加算と減算の命令を追加していきます。
[PP0906] 12. 条件分岐
プログラムでは、状態によって処理の流れを変えたいことがよくあります。C 言語でも if 文を使って、変数の値によって処理を変えることがあると思います。それを実現するための命令が条件分岐です。
| 命令 | ニーモニック | 命令長 | 意味 |
|---|---|---|---|
| 23 | BZ | 2 | アキュムレータが 0 であれば PC 相対アドレスへ分岐 |
| 24 | BNZ | 2 | アキュムレータが 0 でなければ PC 相対アドレスへ分岐 |
BZ と BNZ 命令は、PC 相対アドレスへ分岐します。つまり、相対アドレス指定方式によって実効アドレスを求めるわけです。具体的には、BZ または BNZ 命令の次の命令の位置を ±0 として、それより先の位置に分岐するならプラス、前の位置に分岐するならマイナスの値を指定します。マイナスの値を指定した場合には、ループを作ることになります。
[PP0906] 11. インクリメントとデクリメント
今回は、息抜きとして、簡単な命令を追加することにします。インクリメントは、1 増やすという意味であり、デクリメントは 1 減らすという意味です。
| 命令 | ニーモニック | 命令長 | 意味 |
|---|---|---|---|
| 19 | INC | 1 | アキュムレータをインクリメント |
| 20 | DEC | 1 | アキュムレータをデクリメント |
| 21 | INCX | 1 | インデックスレジスタをインクリメント |
| 22 | DECX | 1 | インデックスレジスタをデクリメント |
それでは例によって、インクリメントとデクリメントを使ったプログラムを作ってみましょう。
[PP0906] 09. スタック操作
プログラムを実行する上で、非常に重要なデータ構造がスタックです。多くのプロセッサでは、スタックを利用するためのハードウェア的な仕組みが設けられています。スタックは、レジスタの値を一時的に退避したり、サブルーチンを呼出すときに戻り先のアドレスを退避する目的に使われます。
[PP0906] 08. ジャンプ
これまで作ってきた命令では、プログラムは上から下へ向かって順番に実行することしかできませんでした。しかし、実際のプログラムでは、途中で別の場所へ行ったり来たりすることが少なくありません。通常、それらは条件判断を行って、条件に合うかどうかで別の場所にジャンプするかどうかを決めますが、今回はその準備段階として無条件にジャンプする命令を追加することにしましょう。
| 命令 | ニーモニック | 命令長 | 意味 |
|---|---|---|---|
| 12 | JMP | 2 | ジャンプ |
それでは、JMP 命令を使った簡単なプログラムを作ってみましょう。
[PP0906] 07. ロードとストア
今回は、メモリに対するアクセスを行うためのロードおよびストア命令を追加することにします。PP0906 では、ロードとストアに関して、二種類のアドレス指定方式(アドレッシングモード)を用意することにします。
| 命令 | ニーモニック | 命令長 | 意味 |
|---|---|---|---|
| 8 | LD | 2 | 直接アドレス指定方式によるロード |
| 9 | ST | 2 | 直接アドレス指定方式によるストア |
| 10 | LDIX | 2 | 指標アドレス指定方式によるロード |
| 11 | STIX | 2 | 指標アドレス指定方式によるストア |
これらの命令を使った簡単なプログラムを次に示します。

