未定義命令におけるTD4とKagekiの動作の違い

自作CPUの [Kageki](https://elchika.com/article/9ac9fd67-86c5-4b1b-a355-4f662e8af794/) は定義されたTD4の命令を実行できるが、その内部構造はTD4と異なる。
そのため、未定義の命令を実行した時の挙動はTD4と異なる。
そこで、この記事ではTD4およびKagekiそれぞれについて未定義の命令における挙動をまとめる。

# 定義されたTD4の命令

TD4では、以下の命令が定義されている。
([CPUの創りかた TD4](http://xyama.sakura.ne.jp/hp/4bitCPU_TD4.html) に基づき作成)

|ビット列|命令|動作|実行後のフラグ|
|---|---|---|:-:|
|`0011 mmmm`|`MOV A, Im`|即値をAレジスタに格納する|0|
|`0111 mmmm`|`MOV B, Im`|即値をBレジスタに格納する|0|
|`0001 0000`|`MOV A, B`|Bレジスタの値をAレジスタに格納する|0|
|`0100 0000`|`MOV B, A`|Aレジスタの値をBレジスタに格納する|0|
|`0000 mmmm`|`ADD A, Im`|Aレジスタの値と即値の和をAレジスタに格納する|キャリー|
|`0101 mmmm`|`ADD B, Im`|Bレジスタの値と即値の和をBレジスタに格納する|キャリー|
|`0010 0000`|`IN  A`|入力ポートのデータをAレジスタに格納する|0|
|`0110 0000`|`IN  B`|入力ポートのデータをBレジスタに格納する|0|
|`1011 mmmm`|`OUT Im`|即値を出力ポートに出力する|0|
|`1001 0000`|`OUT B`|Bレジスタの値を出力ポートに出力する|0|
|`1111 mmmm`|`JMP Im`|無条件で、即値が示す位置にジャンプする|0|
|`1110 mmmm`|`JNC Im`|フラグが0なら、即値が示す位置にジャンプする|0|

# TD4の命令として未定義のビット列

以下のビット列は、TD4の命令として定義されていない。
なお、`mmmm` は任意の4桁のビット列を、`xxxx` は `0000` 以外の任意の4桁のビット列を表す。

* `0001 xxxx`
* `0100 xxxx`
* `0010 xxxx`
* `0110 xxxx`
* `1001 xxxx`
* `1000 mmmm`
* `1010 mmmm`
* `1100 mmmm`
* `1101 mmmm`

# TD4およびKagekiの処理の構造

TD4およびKagekiの処理は、共通で、以下の構造になっている。

1. データ取得
   * Aレジスタ、Bレジスタ、入力ポート、定数0の中から、命令に基づいて加算器に渡すデータを選択する
2. 加算
   * 取得したデータと命令の下位4ビットを加算する
3. ライトバック
   * 命令およびフラグレジスタの値に基づき、格納するべき場所に加算結果の下位4ビットを格納する
   * 無条件で、フラグレジスタに加算結果のキャリーを格納する

この後、これに基づいて解析を行う。

# 上位4ビットが定義された命令と同じで、下位4ビットが未定義のケース

TD4の命令として未定義のビット列のうち、

* `0001 xxxx`
* `0100 xxxx`
* `0010 xxxx`
* `0110 xxxx`
* `1001 xxxx`

は、上位4ビットは定義された命令と同じであり、下位4ビットが `0000` の場合のみ命令として定義されているビット列である。
この下位4ビットは、TD4、Kageki ともに、加算器の入力の一つ (足す数) としてのみ用いられている。

したがって、この下位4ビットはTD4およびKagekiの処理のうち「加算」にのみ影響し、「データ取得」および「ライトバック」には影響しない。
すなわち、「データ取得」および「ライトバック」は定義された命令と同じ動作をする。
よって、定義された命令によってデータが更新される場所のデータが、下位4ビットが `0000` だった場合に格納される値に下位4ビットの値を加算した結果の値に更新されることになる。
また、フラグレジスタにも加算結果のキャリーが反映される。

# 上位4ビットが定義された命令と一致しないケース

上位4ビットが定義された命令と一致しない場合、「データ取得」や「ライトバック」の動作が定義された命令とは異なるものになることが予想できる。
そこで、TD4およびKagekiそれぞれの構造に基づいて動作を考える。
以下、命令の上位4ビットを、上位から順に $i_7, i_6, i_5, i_4$ と表し、フラグレジスタの値を $c$ で表す。
また、ビットANDを $\cdot$ で、ビットORを $+$ で、ビットNOTを $\lnot$ で表す。

## TD4

### データ取得

Aレジスタ、Bレジスタ、入力ポート、定数0の中から、74HC153 を用いて加算器に渡すデータを決定する。
74HC153は、4種類の入力の中から、入力A・Bに基づいて1個を選択して出力するICである。
ただし、入力$\overline{\textrm{G}}$が1のときは、出力は強制的に0となる。
TD4において、74HC153の入力A・Bと加算器に渡すデータの関係は、以下のようになっている。

|A|B|加算機に渡すデータ|
|---|---|---|
|0|0|Aレジスタ|
|1|0|Bレジスタ|
|0|1|入力ポート|
|1|1|定数0|

命令と74HC153の入力の関係は、以下のようになっている。

* $\textrm{A} = i_7 + i_4$
* $\textrm{B} = i_5$
* $\overline{\textrm{G}} = 0$

入力$\overline{\textrm{G}}$は0固定なので、常に入力A・Bに対応するデータが加算器に渡される。
したがって、命令の上位4ビットと加算器に渡されるデータの関係は以下のようになる。

|命令の上位4ビット|A|B|加算器に渡されるデータ|
|---|---|---|---|
|`1000`|$1 + 0 = 1$|$0$|Bレジスタ|
|`1010`|$1 + 0 = 1$|$1$|定数0|
|`1100`|$1 + 0 = 1$|$0$|Bレジスタ|
|`1101`|$1 + 1 = 1$|$0$|Bレジスタ|

### ライトバック

命令の各ビットおよびフラグレジスタの値のビットNOTを論理ゲートに入力し、
その出力を74HC161の$\overline{\textrm{LOAD}}$に入力することで、論理ゲートの出力が0になった更新先のデータを更新する。
TD4における更新先と論理ゲートによる計算の対応は、以下のようになっている。

|更新先|計算 (結果が0のとき更新する)|
|---|---|
|Aレジスタ|$i_7 + i_6$|
|Bレジスタ|$i_7 + \lnot i_6$|
|出力ポート|$\lnot (i_7 \cdot \lnot i_6)$|
|プログラムカウンタ|$\lnot (i_7 \cdot i_6 \cdot (i_4 + \lnot c))$|

命令の上位4ビットおよびフラグレジスタと、これらの計算の結果の関係は、以下のようになる。

|命令|Aレジスタ|Bレジスタ|出力ポート|プログラムカウンタ<br>(フラグ = 0)|プログラムカウンタ<br>(フラグ = 1)|
|---|---|---|---|---|--|
|`1000`|$1 + 0 = 1$|$1 + \lnot 0 = 1$|$\lnot (1 \cdot \lnot 0) = 0$|$\lnot (1 \cdot 0 \cdot (0 + \lnot 0)) = 1$|$\lnot (1 \cdot 0 \cdot (0 + \lnot 1)) = 1$|
|`1010`|$1 + 0 = 1$|$1 + \lnot 0 = 1$|$\lnot (1 \cdot \lnot 0) = 0$|$\lnot (1 \cdot 0 \cdot (0 + \lnot 0)) = 1$|$\lnot (1 \cdot 0 \cdot (0 + \lnot 1)) = 1$|
|`1100`|$1 + 1 = 1$|$1 + \lnot 1 = 1$|$\lnot (1 \cdot \lnot 1) = 1$|$\lnot (1 \cdot 1 \cdot (0 + \lnot 0)) = 0$|$\lnot (1 \cdot 1 \cdot (0 + \lnot 1)) = 1$|
|`1101`|$1 + 1 = 1$|$1 + \lnot 1 = 1$|$\lnot (1 \cdot \lnot 1) = 1$|$\lnot (1 \cdot 1 \cdot (1 + \lnot 0)) = 0$|$\lnot (1 \cdot 1 \cdot (1 + \lnot 1)) = 0$|

よって、命令の上位4ビットと加算結果の格納先の関係は、以下のようになる。

|命令の上位4ビット|格納先|
|---|---|
|`1000`|出力ポート|
|`1010`|出力ポート|
|`1100`|プログラムカウンタ (フラグが0のときのみ)|
|`1101`|プログラムカウンタ|

### 命令の動作

「データ選択」と「ライトバック」の動作を合わせると、以下のビット列を命令として実行したとき、TD4 は以下の動作をすることがわかる。

|命令|動作|
|---|---|
|`1000 mmmm`|Bレジスタの値に即値を加算し、出力ポートに出力する|
|`1010 mmmm`|即値を出力ポートに出力する|
|`1100 mmmm`|フラグが0なら、Bレジスタの値に即値を加算した位置にジャンプする|
|`1101 mmmm`|無条件で、Bレジスタの値に即値を加算した位置にジャンプする|

全てのビット列について、加算結果のキャリーをフラグレジスタに格納する。
(`1010 mmmm` では加算する値の一方が0であるため、キャリーは常に0である)

## Kageki

### データ取得

Aレジスタ、Bレジスタ、入力ポート、定数0の中から、TD4と同じ 74HC153 を用いて加算器に渡すデータを決定する。
Kageki においては、$i_4$が74HC153の入力Aに、$i_5$が入力Bに接続されている。
これらのビットと加算器に渡すデータの関係は、以下のようになっている。

|$i_4$ (A)|$i_5$ (B)|加算機に渡すデータ|
|---|---|---|
|0|0|Aレジスタ|
|1|0|Bレジスタ|
|0|1|入力ポート|
|1|1|定数0|

さらに、Kageki における 74HC153 の入力$\overline{\textrm{G}}$には、$i_7 i_6$ が `11` のとき1、それ以外のとき0となる信号 (作り方は後述) が入力されている。
したがって、命令の上位4ビットと加算器に渡されるデータの関係は以下のようになる。

|命令の上位4ビット|A|B|$\overline{\textrm{G}}$|加算器に渡されるデータ|
|---|---|--|--|--|
|`1000`|0|0|0|Aレジスタ|
|`1010`|0|1|0|入力ポート|
|`1100`|0|0|1|定数0|
|`1101`|1|0|1|定数0|

### ライトバック

Kageki では、74HC138 を用いてデータの更新先を決定する。
74HC138 は、A,B,C の3本の入力に基づき、8本の出力のうち対応する1本を0、他の7本を1にする。
ただし、イネーブル入力が3本あり、うちどれか1本でも条件を満たさない場合は8本全ての出力を1にする。
Kagekiでは、$i_6$ を 74HC138 の入力Aに、$i_7$ を 74HC138 の入力Bに接続し、74HC138の入力Cは0で固定する。
また、74HC138 のイネーブル入力は、全て0となる出力が存在する値に固定する。
74HC138 の出力を 74HC161 の$\overline{\textrm{LOAD}}$に入力することで、対応する更新先のデータを更新する。
ただし、プログラムカウンタについては、74HC138 と 74HC161 の間に論理ゲートによる追加の条件付けを行う。

Kagekiにおける74HC138の入力とデータの更新先の関係は、以下のようになっている。

|$i_6$ (A)|$i_7$ (B)|データの更新先|
|---|---|---|
|0|0|Aレジスタ|
|1|0|Bレジスタ|
|0|1|出力ポート|
|1|1|プログラムカウンタ (追加条件あり)|

ここで、`ABC=110` に対応する 74HC138 の出力を $p$ とする。
この $p$ のビットNOT $\lnot p$ を、データ取得で用いる「$i_7 i_6$ が `11` のとき1、それ以外のとき0となる信号」として供給する。
Kageki のプログラムカウンタに対応する 74HC161 の入力$\overline{\textrm{LOAD}}$への入力は、
$\lnot (\lnot p \cdot \lnot (\lnot i_4 \cdot c))$ である。

命令の上位4ビットおよびフラグレジスタの値と、この式の計算結果の関係は、以下のようになる。

|命令|計算結果<br>(フラグ = 0)|計算結果<br>(フラグ = 1)|
|---|---|---|
|`1000`|$\lnot (\lnot 1 \cdot \lnot (\lnot 0 \cdot 0)) = 1$|$\lnot (\lnot 1 \cdot \lnot (\lnot 0 \cdot 1)) = 1$|
|`1010`|$\lnot (\lnot 1 \cdot \lnot (\lnot 0 \cdot 0)) = 1$|$\lnot (\lnot 1 \cdot \lnot (\lnot 0 \cdot 1)) = 1$|
|`1100`|$\lnot (\lnot 0 \cdot \lnot (\lnot 0 \cdot 0)) = 0$|$\lnot (\lnot 0 \cdot \lnot (\lnot 0 \cdot 1)) = 1$|
|`1101`|$\lnot (\lnot 0 \cdot \lnot (\lnot 1 \cdot 0)) = 0$|$\lnot (\lnot 0 \cdot \lnot (\lnot 1 \cdot 1)) = 0$|

よって、命令の上位4ビットと加算結果の格納先の関係は、以下のようになる。

|命令の上位4ビット|格納先|
|---|---|
|`1000`|出力ポート|
|`1010`|出力ポート|
|`1100`|プログラムカウンタ (フラグが0のときのみ)|
|`1101`|プログラムカウンタ|

### 命令の動作

「データ選択」と「ライトバック」の動作を合わせると、以下のビット列を命令として実行したとき、Kageki は以下の動作をすることがわかる。

|命令|動作|
|---|---|
|`1000 mmmm`|Aレジスタの値に即値を加算し、出力ポートに出力する|
|`1010 mmmm`|入力ポートのデータに即値を加算し、出力ポートに出力する|
|`1100 mmmm`|フラグが0なら、即値が示す位置にジャンプする|
|`1101 mmmm`|無条件で、即値が示す位置にジャンプする|

全てのビット列について、加算結果のキャリーをフラグレジスタに格納する。
(`1100 mmmm` および `1101 mmmm` では加算する値の一方が0であるため、キャリーは常に0である)

# まとめ

TD4の命令として未定義のビット列を命令として実行した時の TD4 および Kageki の動作を短く表すと、以下のようになる。

|命令|TD4|Kageki|
|---|---|---|
|`0001 xxxx`|`MOV A, B + Im`|`MOV A, B + Im`|
|`0100 xxxx`|`MOV B, A + Im`|`MOV B, A + Im`|
|`0010 xxxx`|`IN A; ADD A, Im`|`IN A; ADD A, Im`|
|`0110 xxxx`|`IN B; ADD B, Im`|`IN B; ADD B, Im`|
|`1001 xxxx`|`OUT B + Im`|`OUT B + Im`|
|`1000 mmmm`|`OUT B + Im`|`OUT A + Im`|
|`1010 mmmm`|`OUT Im`|`OUT IN + Im`|
|`1100 mmmm`|`JNC B + Im`|`JNC Im`|
|`1101 mmmm`|`JMP B + Im`|`JMP Im`|

TD4 と Kageki 共通で、下位4ビットが `0000` のときのみ命令として定義されているビット列は、該当する命令で本来格納する値に下位4ビットを加算した結果を該当する命令で本来格納する場所に格納し、フラグレジスタを加算結果のキャリーに設定する。

TD4 ではBレジスタを用いた間接ジャンプができるが、Kageki ではできず、$i_5$を1にした定義済みの命令と同じ動作になっている。
一方、Kageki ではAレジスタや入力ポートの値を出力ポートに出力できるが、TD4 ではできず、$i_4$を1にした定義済みの命令と同じ動作になっている。