あなたCPUなんか創ってどうするのかしら?! 第1章 第6節
~あんたCPUなんか創ってどうするのよ?! Vol.4~
2019/4/14
技術書典6
池袋サンシャインシティ 文化会館ビル2F 展示ホールD「う11」
第1章 第6節 命令デコーダーの基本方針
レジスタ間の演算命令と転送命令を不採用としたため、TD4EX4にはRAMとアキュムレーターとの間での演算命令と転送命令、そしてジャンプ命令だけを採用することになりました。そして演算命令には加算と減算だけを採用します。前述のように乗除算命令は多数のICが必要となるため採用できませんし、ANDやORなどの論理演算は電卓には不必要なので不採用とします。
では、これらの4つの命令(加算と減算と転送とジャンプ)を、どのようにTD4EX4に組み込むのが最適でしょうか?
第1章 第6節 第1項 各命令に共通する部分は何か
最初に検討すべきは、これら4つの命令の共通点と相違点です。共通する部分は同じ回路で処理すれば良いので、共通点が多ければ多いほどIC数を削減できます。対する相違点はそれぞれの命令ごとに専用の回路を用意して処理することになります。
検討の結果、筆者は4つの命令を以下のように分類しました。
- RAMもしくはROMからデータを読み出し、結果をCPU内のレジスタ(アキュムレーターやPC)に格納するという点では、この4つの命令は共通している。ただし転送命令にはアキュムレーターの内容をRAMに書き込む命令も存在するため、例外として処理する必要がある。
- 加算命令と減算命令は同一の命令と考えることができる。両者の違いは、減算命令では対象のデータ(RAMやROMから読み出したデータ)を2の補数に変換してから加算する事だけである。
- RAMもしくはROMからアキュムレーターにデータを転送する命令も、加算命令と同一の命令と考えることができる。両者の違いは、転送命令ではRAMもしくはROMからのデータのみを使用し、アキュムレーターの値を使用しない点である。
- ジャンプ命令はイミディエイトデータの転送命令と同一と考えることができる。両者の違いは、データの格納先がPCかアキュムレーターかという点だけである。
以上の分類を踏まえ、筆者は加算命令を基本とし、そこから他の命令を派生させることにしました。これはTD4と同じ考え方です。そして命令コードの上位2ビットを使って加算、転送、減算、ジャンプの4つの命令をデコードする事にしました。例外扱いであるRAMへの書き込み命令は別途検討します。
また前述のようにbit4で2個のアキュムレーターを判別することも決めました。このbit4はJMP命令とJNC命令の判別にも用いているので、残りのbit7~5で命令を判別するように設計すれば命令デコーダーのIC数を削減できます。
第1章 第6節 第2項 命令コードの各ビットへの役割の割り当て
加算命令を基本とし、そこから他の命令を派生させることで、命令デコーダーを大幅に簡素化できます。うまく工夫すればICを使用せずに命令を判別できますが、さすがに完全にゼロにはできませんでした。
命令コードの上位2ビットを使って加算、転送、減算、ジャンプの4つの命令を判別するために、筆者はTD4EX4の命令コードの各ビットに以下の意味を持たせることにしました。
- bit4: アキュムレーターの選択。0ならAレジスタ、1ならBレジスタ。このビットで計算元となるデータと計算結果の格納先の両方を指定する。アキュムレーターを使わないジャンプ命令は例外として処理する。
- bit5: RAM/ROMの選択。0ならRAMからデータを読み出し、1なら命令コードの下位4ビットをイミディエイトデータとして計算に用いる。
- bit6: アキュムレーターからの読み出しを行うか否かの選択。0なら読み出しを行い、RAM/ROMの値との加算または減算を行う。1の場合はRAM/ROMの値をそのまま出力する。
- bit7: 例外処理。ジャンプ命令、減算命令、RAMへの書き込み命令は全て例外扱いとしてデコードする。と言っても何もかもが例外という訳でなく、共通する部分は共通化する。
このような割り当てによって、表3のように命令の大半を簡単に判別できるようになりました。
デコード種類 | アキュムレーターの読み出し | RAM/ROM | アキュムレーターの選択 | 例外処理 | 該当する命令 |
---|---|---|---|---|---|
通常デコード (bit7=0) |
加算する bit6=0) |
RAM (bit5=0) |
A (bit4=0) | – | ADD A, [Adr] |
B (bit4=1) | – | ADD B, [Adr] | |||
ROM (bit5=1) |
A | – | ADD A, Im | ||
B | – | ADD B, Im | |||
加算しない (bit6=1) |
RAM | A | – | MOV A, [Adr] | |
B | – | MOV B, [Adr] | |||
ROM | A | – | MOV A, Im | ||
B | – | MOV B, Im | |||
例外デコード (bit7=1) |
加算する | RAM | A | 2の補数化 | SUB A, [Adr] |
B | SUB B, [Adr] | ||||
ROM | A | SUB A, Im | |||
B | SUB B, Im | ||||
加算しない | RAM | – | 結果をPCに 格納 | JMP [Adr] | |
ROM | – | JMP Im |
この表3を説明するうえで重要なのはジャンプ命令です。
表3では各ビットに意味を持たせていますが、この1と0を決める根拠となっているのがジャンプ命令なのです。例えばイミディエイトデータの転送命令とジャンプ命令は同一だと考えられることから、両者の命令コードを似たものにしておくと命令デコーダーを簡略化できます。ジャンプ命令の命令コードは1111(JMP命令)と1110(JNC命令)ですから、イミディエイトデータの転送命令はbit7だけを0にした命令コードを割り当てるのが最適だと考えました。
それに伴い、筆者は命令コードのbit6とbit5を以下のように決めました。
- ジャンプ命令ではアキュムレーターとの加算は行わないため、bit6が1の時には加算を行わない。
- ジャンプ命令のジャンプ先はイミディエイトデータで指定するので、bit5が1の時にはイミディエイトデータとの加算を行い、0の時にはRAMとの加算を行う。
これによりジャンプ命令を他の演算命令と共通化することができ、使用IC数を大幅に削減できました。