標準TTLだけ(!)でCPUをつくろう!(組立てキットです!)
(ホントは74HC、CMOSなんだけど…)
[第200回]

●算術演算命令のテストプログラムです

算術演算命令のADD、ADC、SUB、SBBの動作を確認するためにテストプログラムを作りました。
Z80アセンブラをもとにして作った8080アセンブラ([第180回])を使ってマシン語に翻訳しました。
下がそのリストです。


ソースプログラムからマシン語に翻訳したファイルは、[第189回]で作った232C送信プログラムで、「つくるCPU」試作基板に送りました。

そのようにして、「つくるCPU」試作基板のRAMに書き込まれたプログラムを、いつものようにマシンクロック毎にステップ動作させて、その写真を撮りました。
プログラムは先頭からマシンクロック毎にステップ動作で実行させていきましたが、全ての命令動作の写真を撮るのは大変ですし、算術演算命令以外の動作はすでに確認済みですから、今回は加算、減算命令の部分だけの写真を撮りました。

●テストプログラムの説明です

プログラムの前半部分では、キャリー無し加算命令のADDとキャリー付加算命令のADCの動作を確認するため、2バイトの16進数同士の加算を行います。
HLレジスタに56ABを、そしてDEレジスタに3489を入れたあとで、最初にLレジスタとEレジスタの値を加算(ADD)し、次にその加算でのキャリーを含めて、HレジスタとDレジスタの値を加算(ADC)します。
加算した結果はBCレジスタに格納します。
8080は、加算されるレジスタはAレジスタでなければなりません。加算の結果もAレジスタに入れられます。

ですから、まずLレジスタの値をAレジスタに入れてから、AレジスタとEレジスタの間で加算を行います。加算の結果は、AレジスタからCレジスタにMOV命令で転送します。
HレジスタとDレジスタとの間の加算も同様に、まずHレジスタの値をAレジスタに入れてから、AレジスタとDレジスタの間で加算を行います。加算の結果は、MOV命令で、AレジスタからBレジスタに転送します。

プログラムの後半部分では、キャリー無し減算命令のSUBとキャリー付減算命令のSBBの動作を確認するため、2バイトの16進数同士の減算を行います。
先の加算のときに、DEレジスタに入れた3489をXCHG命令でHLに入れ、DEレジスタには12CDを入れたあとで、最初にLレジスタからEレジスタの値を減算(SUB)し、次にその減算でのボローを含めて、HレジスタからDレジスタの値を減算します。
減算した結果はBCレジスタに格納します。
8080は、減算されるレジスタはAレジスタでなければなりません。減算の結果もAレジスタに入れられます。

ですから、まずLレジスタの値をAレジスタに入れてから、AレジスタとEレジスタの間で減算を行います。減算の結果は、AレジスタからCレジスタにMOV命令で転送します。
HレジスタとDレジスタとの間の減算も同様に、まずHレジスタの値をAレジスタに入れてから、AレジスタとDレジスタの間で減算を行います。減算の結果は、MOV命令で、AレジスタからBレジスタに転送します。

16進数2バイトの加算と減算の結果は以下のようになります。

  56AB
  3489(
  8B34

  3489
  12CD(
  21BC

8080には2バイトの加算命令DADがあります。
DAD D命令を使えば、HLレジスタとDEレジスタの加算を1命令で実行することができます。
でも今回は、1バイトの加算命令のテストですから、上の説明のように、LレジスタとEレジスタの加算、HレジスタとDレジスタの加算、のように分けて計算を行います。
なお8080には2バイトの減算命令はありません(Z80にはあります)。

●ADD命令のクロック毎の動作の写真です

アドレス0107のADD E命令のT0の写真です。



ここまでに実行された、LXI命令、MOV命令によって、Hレジスタに56、LレジスタにAB、Dレジスタに34、Eレジスタに89が入れられていて、AレジスタにはLレジスタの値のABが入れられています。
上から3列目の左から、D、E、B、C、Aの各レジスタ、
その下の列の左からH、Lレジスタがあります。
プログラムカウンタはその下の行の右側です。0107が表示されています。
その下の列は、左から外部アドレスバスのA15〜A8、A7〜A0、外部データバスのD7〜D0があります。
少し下に下がって、内部データバスiB7〜iB0があり、その右上にはOPコードレジスタがあります。
外部アドレスバスには0107が表示されていて、データバスは外部、内部ともADD E命令のOPコード83が表示されていますが、OPコードレジスタにはまだ読み込まれていません。
OPコードレジスタの列の右端の5個のLEDはマシンクロックのTサイクルを示す5ビットの表示です。

写真の上から2列目、少し下がって、左から、ALUのレジスタ”A”とレジスタ”B”があります。
その列の、少し上に上がって右端にあるのが、ADDレジスタ(8ビット加算器回路)からの出力表示です。

実は写真を撮るときに、ステップ動作の途中でちょっと失敗をしてしまって、もう一度最初から撮り直しをしました。
そのために、Cレジスタと、ALUのレジスタ”A”、レジスタ”B”、それとADDレジスタには、計算した結果が入ってしまっています。
なんだかおかしな感じですけれど、全部レジスタをクリアして、また最初から写真を撮るのも大変なので、そのままの写真でいくことにしました。

毎回説明していますように、OPコードフェッチサイクルのT1〜T3は、どの命令でも同じ動作ですから、そのところの写真は省略することにします。

ADD E命令のT4の写真です。



Aレジスタの値、ABが内部データバスに読み出され、ALUのレジスタ”A”に書き込まれています。
Aレジスタの左にある、AregRD(黄LED)が点灯しています。
ALUのレジスタ”A”の左にある、ALUreg”A”WR(緑LED)が点灯しています。

このとき、ALUのレジスタ”B”の値はまだ書き込まれていなくて、先に行った演算のときの値の34が残っています。
しかしADD回路は、このレジスタ”A”とレジスタの”B”の値の加算をただちに行って、AB+34+1=E0の結果を表示します。
最後に加算した1はキャリーです。
フラグレジスタは一番上の列の左から2番目にある、5個のLEDです。
左から、S(サイン)、Z(ゼロ)、H(ハーフキャリー)、P(パリティ)、C(キャリー)の各フラグです。
キャリーフラグは消灯していますが、ADD回路では、下位桁からの桁上げがあることを示すLED(ADDレジスタの右下の赤LED)が点灯しています。これも、先に行った計算結果がそのまま残って表示されているためです。
もちろんこれらの計算結果は過渡的なもので、命令の実行ステップが進むことによってクリアされて正しい値に変わります。

ADD E命令のT5の写真です。



ALUreg”A”WR(緑LED)が消灯しました。

[2009.4.10追記ここから]
ADDレジスタ表示LEDの右下にある、下位桁からの桁上げを示すLEDが消灯しました。

この桁上げは8ビット加算器を構成する2個の74HC283のうちの下位4ビットの方の74HC283のC0に入力されます。
74HC283周りの回路図はこちら([第191回]加算回路)です。

同回路図の右下に、74HC283のC0への、下位桁からのキャリーを保持する74HC74回路があります。
74HC74のD入力は、OPコードのOP3、OP4によって1か0か、または現在のCF(キャリーフラグ)か、CFを反転したものか、のいずれかの値になります。

今はADD E命令(OPコードは10000011)の実行中です。
ADD命令はOP3=OP4=0です。このとき、74HC74のD入力は0になります。
ADD命令はキャリー無し加算ですから、加算前のキャリー(C0入力)を0にします。

74HC74のD入力はこれだけでは、出力には伝わりません。
CK入力がL→Hになって、はじめて出力に反映されます。
もう一度さきほどの回路図([第191回]加算回路)を見てください。
CKにはALUreg”A”WRが入っています(「regAWR」になっていますが、記載ミスです)。

ALUreg”A”WRは、[第179回]●ALU命令のデコード回路にあります。
T4のときにアクティブになっています(信号名がまだ定まっていなくて、「”A”WR」になっています)。
T4のときに、↓_↑という信号が、さきほどの74HC74のCK端子(pin3)に入力されますから、T4の終りに、D入力の0が、Qから出力されます。

下位4ビットの加算をする74HC283のC0入力が、この時点(T4の終り、つまりT5になったとき)にクリアされたのは、以上説明した働きによります。

このタイミングで74HC283のC0入力がクリアされたことは、ただちに加算結果に反映されます。
さきほどまでの加算結果の表示は、AB+34+1=E0だったのが、AB+34=DF(11011111)に変わりました。
[2009.4.10追記ここまで]

ADD E命令のT6の写真です。



Eレジスタの値、89が内部データバスに読み出され、ALUのレジスタ”B”に書き込まれています。
Eレジスタの左にある、EregRD(黄LED)が点灯しています。内部データバスに読み出された89は、ALUレジスタ”B”に書き込まれていて、ALUレジスタ”B”も89になりました。
ALUレジスタ”B”の左側にあるALUreg”B”WR(緑LED)が点灯しています。

ALUレジスタ”A”とALUレジスタ”B”の値は即座に加算されて、ADDレジスタに表示されます。
AB+89=34の計算が行われて、ADDレジスタの表示が34になりました。

キャリー無し加算を行うADD命令なので、さきほどまで点灯していた、下位桁からの桁上げを示すLEDは消灯しています(2009.4.10追記)。
その代わりに、上位桁への桁上げを示す左側のLEDが点灯しました。
AB+89の加算によって、上位バイトへの桁上げが発生したことを示しています。
しかし、まだこの段階では、キャリーフラグへの反映は行われません。

ADD E命令のT7の写真です。



ALUreg”B”WR(緑LED)が消灯しました。

ADD E命令のT8の写真です。



ADDレジスタのLED表示の左側にある、AddRD(黄LED)が点灯して、ADDの結果(34)が内部データバスに出されています。
Aレジスタの右側にあるAregWR(緑LED)が点灯して、Aレジスタに内部データバスの値、34が書き込まれています。

フラグレジスタは、左端のS(サイン)フラグとその右のZ(ゼロ)フラグが消灯、その右のH(ハーフキャリー)フラグと、右端のC(キャリー)フラグが点灯しました。

ADD E命令のT9の写真です。



AregWR(緑LED)が消灯しました。

まだ、説明の途中ですが、本日は時間がなくなってしまいました。
この続きはまた次回にいたします。
2009.4.9upload
2009.4.10追記

前へ
次へ
ホームページトップへ戻る