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

●PUSH命令の説明です

前回、スタックとスタックポインタの説明の中で、PUSH命令の動作についても説明をしました。
PUSH命令は、レジスタの値をメモリに一時的に保存するための命令で、対象となるレジスタによって、下記の4命令があります。

PUSH B      BレジスタとCレジスタをスタックに保存します
PUSH D      DレジスタとEレジスタをスタックに保存します
PUSH H      HレジスタとLレジスタをスタックに保存します
PUSH PSW   Aレジスタとフラグレジスタをスタックに保存します

各命令の命令コードは次の通りです。

命令コード(2進数)   命令コード(16進数)  ニーモニック    
110000101          C5          PUSH B
110100101          D5          PUSH D
111000101          E5          PUSH H
111100101          F5          PUSH PSW

PSWというのは、Processor Status Wordの略語のようです。
CPUの状態をPUSHするということで、なるほど、AレジスタとフラグレジスタをPUSHするということか、と一応は納得、なのですけれど、やっぱり、Z80ニーモニックのように、ダイレクトに
PUSH AF
としてしまったほうがわかりやすいですね。

命令コードのbit5とbit4が00のときに、BCレジスタ、01のときにDEレジスタ、10のときにHLレジスタ、11のときにAレジスタとフラグレジスタを対象とするPUSH命令になります。

●PUSH命令の回路図です



回路としてはごくごく簡単なものですが、op5とop4が11のとき、つまりAレジスタとフラグレジスタを選択するときだけは少し工夫が必要です。

レジスタが選択される仕組みについては、何回か説明しましたが、もう一度おさらいします。
d3〜d0とregWRで、レジスタが選択されて、そのレジスタに内部データバスの値が書き込まれます。
s3〜s0とregRDで、レジスタが選択されて、そのレジスタの値が内部データバスに出力されます。
d3〜d0、s3〜s0とレジスタの関係は、こちらの「レジスタコード表」([第27回])を参照してください。

上のPUSHの命令コードのところでop5とop4が00のとき、BCに対するPUSH命令になり、01のときはDEに対するPUSH命令になり、10のときにHLに対するPUSH命令になると説明しました。

「レジスタコード表」([第27回])を見ると、
Bレジスタはs3〜s0(またはd3〜d0)=1000、Cレジスタは1001、Dレジスタは1010、Eレジスタは1011、Hレジスタは1100、Lレジスタは1101であることがわかります。
つまりB〜Lレジスタはop5、op4をそのままs2、s1(またはd2、d1)に出力し、B、D、Hレジスタに対しては、さらにs0(またはd0)を0にすることで選択されることになります。

s3(またはd3)は1ですが、d3〜d0、s3〜s0は抵抗でプルアップしてあるので、なにも信号を出力しないときは、”1”になります。ですから、d3〜d0、s3〜s0のうち、”0”にしたい信号ラインにだけ”0”を出力すればよく、”1”にしたいラインについては何もしなくてもそのまま”1”になります。

op5、op4が11のときにはAレジスタ、フラグレジスタに対するPUSH命令になります。
Aレジスタのレジスタコードはs3〜s0(またはd3〜d0)=1111なので、B〜Lと同じルールでいけそうなのですが、フラグレジスタについては、そうはいきません。

フラグレジスタのレジスタコードは0001なので、op5、op4と逆になってしまいます。
フラグレジスタのレジスタコードを”1110”にできればよかったのですが、”1110”はM(HLで指定するメモリアドレス)に割り当てていますから、フラグレジスタに使うことはできません。
そこでPUSH命令の回路図にあるように、op5、op4が11のときとそうでないときとで、s3〜s0を出力する回路を分けているのです。

●PUSH命令のタイミングチャートです



タイミングチャートを見ながら回路図を見ると、より理解しやすくなります。

PUSH命令は、いままで説明してきた命令と違い、OPコードフェッチサイクルのT3のときに、スタックポインタに、−1カウントダウンさせるためのクロック(SPclk)を出力しています。

PUSH命令は、先にスタックポインタを−1カウントダウンしておいてから、そのメモリアドレスにレジスタの値を書き込みます。
書き込みをするよりも前のT3のときに、スタックポインタに−1するためのクロックを出力しているのは、その理由からです。

●AレジスタはHighかLowか?

8080はどういうわけか、ちぐはぐなところが目立ちます。
Aレジスタのレジスタコードもそのよい例です。

Aレジスタはレジスタコードで示すと”111”です(s3、d3は「つくるCPU」の回路のために勝手に追加したビットなので、本来のコードは3ビットです)。
コードビットがすべて”1”ということは、何も出力しなくてもAレジスタが選択されることになるので、Aに”オール1”のコードを割り当てたことは理にかなっています。

ところで、コードの一番下のビットs0(またはd0)が”1”ということは、レジスタを2つつないで16ビットレジスタ構成にしたときに、そのレジスタが下位レジスタであることを示しています(C、E、Lレジスタが下位レジスタ)。
Aレジスタは他に組み合わせて16ビットレジスタを構成することはしないで、つねに単独で用いられますから、下位も上位も無いとも言えますが、PUSH命令とPOP命令だけは、Aレジスタとフラグレジスタを組み合わせてスタックに保存します。

PUSH命令では、Aレジスタとフラグレジスタをどのように組み合わせているかというと…。
Aレジスタが上位レジスタとして扱われているのです(タイミングチャート参照)。

フラグレジスタと組み合わせてみたところで、他のレジスタと同じように16ビットレジスタとして扱えるわけではなくて、ただスタックに入れる順序だけのことですから、あえてAレジスタを”上位レジスタ”として扱う必要はないはずです。

うーん。
なぜなのでしょうか、ねぇ。
回路の都合からAレジスタをコード111にはしてみたものの、Aレジスタを”下位”に置きたくはなかった???
2008.9.16upload

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