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

●LHLD命令

またまた、なんともよくわからないニーモニックの命令です。
Load H&L Directの略のようです。
ここでDirectというのは、Direct memory accessのことです。直接アドレスを指定するメモリアドレス方式の意味です(これに対してメモリアドレスを間接的に示す方式を、”間接メモリアドレス方式”と言います)。

MOV命令で、MOV r,M(レジスタにメモリの値を転送する)の場合のMが間接メモリアドレッシングでのメモリアドレス指定になります。
メモリアドレスを直接指定するのではなくて、HLレジスタの値を使ってメモリアドレスを間接的に指定するから、間接アドレッシングです。

LHLD命令のマシン語コードは”2A”です。
”2A3412”のようにOPコードのあとに2バイトのデータ部が続きます。
”2A3412”の場合で説明すると、メモリアドレス”1234”番地にあるデータをLレジスタに入れ、その次のアドレス”1235”番地にあるデータをHレジスタに入れる、という動作をします。

良く似た動作をする、HLレジスタに16ビットのデータを直接入れるLXI Hという命令がありました([第65回])。
LHLDとLXI Hは、命令コードも動作もちょっと似ています。
LXI HをLHLDと同じようにコードで示すと、
”213412”になります。

LXI HはHLレジスタに”1234”が入ります。
これに対して、LHLDはHLレジスタに”1234”番地と”1235”番地のデータが入ります。

両者の違いを理解しやすくするために図を用意しました。

LXI H命令では、命令コードに続く2バイトのデータがそのままHLレジスタに入りますが、LHLD命令では、命令コードに続く2バイトは、HLレジスタに入れるデータの”メモリアドレス”になっています。

LXI命令では、命令に続くデータを読んで、最初のデータはそのまま下位レジスタに入れ、次のデータは上位レジスタに入れれば良かったので、回路は簡単でした。
ところがLHLD命令では、命令コードに続く2バイトのデータをメモリアドレスとして使わなければなりません。
今までそのような場合にはWKレジスタを使いました。
と、ここまで書いてきて思い出しました。

LHLD命令の動作に最も近い命令がありました。
LDA命令([第64回])です。
LDA命令はOPコードに続く2バイトでメモリアドレスを直接指定して、そのメモリアドレスにあるデータをAレジスタに入れる命令でした。
Aレジスタですから8ビット(1バイト)のデータですが、データが1バイトか2バイトかの違いを別にすれば、LDA命令とLHLD命令は全く同じ動作になります。

LDA命令では、2バイトのデータをWKレジスタに読み込んで、その後、WKレジスタの値をアドレスバスに出力することで、メモリアドレスを指定しました。
しかしLHLD命令では同じ方法は使えません。

LDA命令ではメモリアドレスを指定して、一度だけデータを読み込むだけで済みますが、LHLDでは2バイト分のデータを読み込まなくてはならないので、指定したメモリアドレスと、その次のメモリアドレスの2回メモリアドレスを指定してデータを読まなければならないのです。
つまりメモリアドレスをインクリメント(+1)しなければなりません。WKレジスタはただのレジスタ(74HC373を2個使用)ですから、値のインクリメントはできません。
LDAのようにメモリアドレスを出力するためにWKレジスタを使うことができないのはそのためです。

LHLD命令でもWKレジスタは利用しますが、それはメモリアドレスを出力するためではなくて、一時記憶として使用します。文字通りワークレジスタそのものとしての利用です。

ここは、設計の当初かなりあれこれ迷いました。
WKレジスタを74HC373ではなくて、74HC191などのプリセッタブルなアップタ゜ウンカウンタにすることも考えました。
でもこの命令だけのために、74HC373の代わりに74HC191を使うというのは、どうにも面白くありません。

INR、DCR命令の回路を利用することも考えました([第58回]INRレジスタ回路)。
しかしその回路は8ビットです。
メモリアドレスをインクリメントするためには、16ビットのインクリメント回路が必要です。

INX命令([第95回])は16ビットのインクリメントを行っていますが、それは8ビットの回路を2回繰り返して利用するような回路になっています。8ビットのINR回路を16ビットのインクリメントに利用するためには、INX命令と同じような回路を付加しなければなりません。
そんなくらいならば、最初からWKレジスタを16ビットのアップカウンタ(74HC191を4個使う)にした方がずっと簡単です。

●SP(スタックポインタ)を利用する

SP(スタックポインタ)を利用することを思いつきました。
16ビットありますし、もともとアドレスを指定するためのレジスタですから目的にぴったりです。もちろんインクリメントも問題なくできます。
1)最初にまず現在のSP(スタックポインタ)の中身をWKレジスタに保存します。
2)そうしておいてから、命令コードの次の2バイトの値をSP(スタックポインタ)に読み込みます。
3)SP(スタックポインタ)の値をアドレスバスに出力します。
4)SP(スタックポインタ)で指定するメモリアドレスにあるデータを、まずLレジスタに入れ、SP(スタックポインタ)を+1して、そのメモリアドレスにあるデータをHレジスタに入れます。
5)最後にWKレジスタに保存しておいたSP(スタックポインタ)の値をもとに戻します。

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



SP(スタックポインタ)の値をWKレジスタに退避、復帰するために、20クロックもかかってしまいました。
T4〜T7がSP(スタックポインタ)の値をWKレジスタに保存、
T8〜T11が命令コードに続く2バイトをSP(スタックポインタ)に読み込み、
T12〜T15がSP(スタックポインタ)の値をアドレスバスに出力して、そのメモリアドレスにあるデータをLレジスタに、次のメモリアドレスにあるデータをHLレジスタに読み込み、
T16〜T19がWKレジスタの値をSP(スタックポインタ)に戻す、作業です。

WKレジスタ、SP(スタックポインタ)はs3−s0とregRD、d3−d0とregWRによって選択され、値の読み出し、書き込みが行われます。
s3−s0、d3−d0とレジスタの関係については、「レジスタコード表」([第27回])を参照してください。

●SHLD命令

LHLD命令はメモリアドレスをダイレクトに指定して、そのメモリアドレスにあるデータをHLレジスタに読み込む命令ですが、LHLD命令と対になる命令としてSHLDがあります。
Store H&L Directです。
命令コードは”22”です。
ダイレクトに指定したメモリアドレス(とその次のアドレス)にHLレジスタの値を書き込みます。

LHLDとSHLDのタイミングチャートは、T12〜T15でメモリから読み出す作業と、メモリに書き込む作業との違いがあるだけで、残りの部分は全て同じです。
したがって回路もほとんど共通にできます。

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



T12〜T15で、HLレジスタからのデータをSP(スタックポインタ)で指定するメモリアドレスに書き込んでいます。この部分が異なっているだけで、あとの部分はLHLD命令のタイミングチャートと同じです。

●LHLD命令とSHLD命令の回路図です



回路図の右半分がLHLD命令とSHLD命令の共通部分の回路です。
2008.10.29upload

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