めざせ4004! IC24個で電卓用CPUを作ってみた: Chapter 3-2 内部構造
図9にEX4-2024のブロック図を示します。点線で示している枠内がEX4-2024で拡張した部分です。
簡単に解説すると、左下のプログラムカウンタ(PC)から実行する命令のアドレスがROMに供給され、ROMの内容は8bits Instructionとして上方向に出力されます。このとき命令の1バイト目はLatch 1に格納されて右端の命令デコーダー(Decode)に送られ、命令の2バイト目は直接プログラムカウンタ(PC)に送られるか、中央の加算回路(ADD)に送られます。
中央の加算回路(ADD)はRAMアドレスの計算用です。ROMから供給されるオフセット(Ofs)とインデックスレジスタ(X、Y、Z)の値を加算し、RAMのアドレスバスに出力します。またLEA命令用にRAMアドレスをインデックスレジスタに読み込むための配線もあります。 アキュムレーター周辺はTD4から変わっていません。AレジスタとBレジスタの値はSelect 1を経由して演算回路(ALU)に送られ、Select 2を経由して送られてくるRAMデータもしくはROMからのイミディエイトデータと加減算を行います。
Chapter 3-2-1 イミディエイトデータの読み込み
言葉だけでは分かりにくいので実際の動作パターンを見てみましょう。まずは命令中に埋め込まれているイミディエイトデータの読み込みです。
読み込まれるデータは命令の1バイト目にあるのでLatch 1からデータを取り出してALUを経由してアキュムレーターに格納します。
命令の2バイト目は無視されます。
Chapter 3-2-2 RAMから読み込んだデータとの加算
RAM内のデータをアキュムレーターに加算します。RAMのアドレスは命令中で直接指定します。インデックスレジスタは使いません。
命令2バイト目にあるオフセット(Ofs)がそのままRAMアドレスとなります。
RAMアドレスが8ビット幅になっている以外はTD4EX4と同様です。
Chapter 3-2-3 インデックスレジスタを用いたRAMへの書き込み
インデックスレジスタを使ってRAMアドレスを指定する例です。
命令の2バイト目にあるオフセット(Ofs)とインデックスレジスタの値が加算されRAMアドレスとなります。
インデックスレジスタの値をそのままRAMのアドレスにしたい場合は、オフセット(Ofs)にゼロを指定します。
Chapter 3-2-4 ジャンプ命令
ジャンプ命令 (JMPとJNC) はTD4EX4と同じです。
これらは元々2バイト命令でしたので、命令の1バイト目にアドレスの最下位4ビット、命令の2バイト目に上位8ビットが格納されています。それらを図13のような経路でプログラムカウンタ (PC) に読み込みます。
Chapter 3-2-5 アドレス計算命令(LEA)
MC6809に倣いEX4-2024ではアドレス計算のためにLEA命令も用意しました。これは
LEA irt, [irs+Ofs]
のように表記します。irtが計算結果を格納するインデックスレジスタ、irsが計算元となるインデックスレジスタ、Ofsは命令の2バイト目で指定するオフセットです。つまり
irt = irs + Ofs
という計算を行います。
例えばirtとirsにインデックスレジスタXを指定したうえでOfsに0x01を指定すると X = X + 1 となり、インデックスレジスタXをインクリメントします。
またirsにインデックスレジスタを指定せず、オフセット指定のみにすることもできます。その場合は
X = 1 のようにOfsの値がそのままirtで指定されたインデックスレジスタに格納されます。
またirtとirsに別々のインデックスレジスタを指定しOfsをゼロにすると Y = X のようにインデックスレジスタ間の代入を行えます。ただし Y = X + Y のようなインデックスレジスタ間での加減算は出来ません。可能なのはインデックスレジスタとOfs間での加算だけです。
Chapter 3-2-6 インデックスレジスタの限界
EX4-2024はZ80に類似したオフセット付きのインデックスレジスタに加えてMC6809のようなLEA命令も装備しているので4ビットCPUとしては十分すぎる機能を持っていますが、それでも重要な機能が欠けています。それはインデックスレジスタに対するロード/ストア機能が無いことです。
LEA命令を使えばインデックスレジスタにイミディエイトデータを読み込むことは出来ます。しかしRAM上にある数値をインデックスレジスタに読み込むことは出来ませんし、インデックスレジスタの値をRAMに保存することもできません。
またアキュムレーターであるAレジスタやBレジスタとの間での転送もできません。
つまりEX4-2024のインデックスレジスタはRAMアドレスの計算に特化していて汎用レジスタのような使い方は一切できません。
さらにLEA命令による加減算はできるものの、その結果がゼロのなったか、あるいはオーバーフローしたか等を知ることもできません。第2章ではインデックスレジスタをカウンタに使うと説明しましたが、実際にはEX4-2024では不可能です。以下のコードのようにforループのカウンタを配列の添え字に使うことは出来ません。
これは演算系とアドレス系が完全に分離していることが原因です。ブロック図をよくご覧になれば分かることですが、EX4-2024では使用するIC数を出来る限り減らすためにTD4EX4のRAMのアドレス幅を8ビットに拡大した「だけ」に留めており、それ以上の拡張は意図的に排除しています。そのためせっかく搭載したインデックスレジスタではありますが、その機能には様々な制約があります。