「CPUの創りかた」でおなじみのTD4 CPUのエミュレータをNES上で実装しました。
実際の動作画面はこちら↓
- cc65のインストール
- 生成した.nesファイルを実行するためのNESエミュレータ
本リポジトリをクローンします。
git clone https://github.com/yugodenki/td4-emulator-on-nes.git
cc65を用いてアセンブルを行います。
ca65 td4emu.asm -o td4emu.o
続けてリンカを実行します。
ld65 -C memory.cfg -o td4emu.nes td4emu.o
上記の処理が終了すればtd4emu.nes
ファイルが生成されるので、お好みのNESエミュレータで実行してください。
- 画面左側はTD4のROMです。8-bit x 16個のDIPスイッチを模しています。 矢印ボタンでカーソルを移動し、Aボタンでスイッチを切り替えます。
- 「INPUT」はTD4の4-bitの入力です。
- 「SPEED」はTD4の実行速度を調整できます。1Hzあるいは10Hzを選択できます。
- 「RESET」はリセットボタンです。Aボタンを押した瞬間にTD4がリセットされます。
- 「CLOCK」はTD4のクロックを表示しています。
- 「PC」はTD4のプログラムカウンタです。プログラムカウンタに表示されているアドレスの命令が実行されています。
- 「OUTPUT」はTD4の4-bitの出力です。
下記の命令が実行可能です。
ADD A, Im ; 0000xxxx AレジスタにImの内容を加算、オーバーフローした場合はキャリーフラグをセット
ADD B, Im ; 0101xxxx BレジスタにImの内容を加算、オーバーフローした場合はキャリーフラグをセット
MOV A, Im ; 0011xxxx AレジスタにImの内容を転送
MOV B, Im ; 0111xxxx BレジスタにImの内容を転送
MOV A, B ; 00010000 Bレジスタの内容をAレジスタに転送
MOV B, A ; 01000000 Aレジスタの内容をBレジスタに転送
JMP Im ; 1111xxxx Imのアドレスにジャンプ
JNC Im ; 1110xxxx キャリーフラグが無ければImのアドレスにジャンプ
IN A ; 00100000 INPUTのデータをAレジスタに転送
IN B ; 01100000 INPUTのデータをBレジスタに転送
OUT B ; 10010000 Bレジスタの内容をOUTPUTに表示
OUT Im ; 1011xxxx Imの内容をOUTPUTに表示
; ※下位4-bitのxxxxはImデータを表しています。
TD4 CPUの実機では、基本的にどの命令においてもデータの転送が4-bit全加算器(74HC283)を通して行われ、かつImデータも参照されています。つまり、下位4-bitに0000
を指定する前提となっている下記の5つの命令については:
MOV A, B ; 00010000 Bレジスタの内容をAレジスタに転送
MOV B, A ; 01000000 Aレジスタの内容をBレジスタに転送
IN A ; 00100000 INPUTのデータをAレジスタに転送
IN B ; 01100000 INPUTのデータをBレジスタに転送
OUT B ; 10010000 Bレジスタの内容をOUTPUTに表示
以下のように解釈することも可能です:
MOV A, B + Im ; 0001xxxx Bレジスタ + Imの内容をAレジスタに転送
MOV B, A + Im ; 0100xxxx Aレジスタ + Imの内容をBレジスタに転送
IN + Im A ; 0010xxxx INPUT + Imの内容をAレジスタに転送
IN + Im B ; 0110xxxx INPUT + Imの内容をBレジスタに転送
OUT B + Im ; 1001xxxx Bレジスタ + Imの内容をOUTPUTに表示
; ※さらに、全加算器を通るため、これらの5命令もキャリーフラグに影響を与えます。
本エミュレータではこの仕様も再現しているため、転送命令と加算命令を1命令に短縮するなどして、16バイトのROMを最大限に活かすことができます。