2016年7月24日日曜日

vgsdrun (デバッグ実行コマンド)

vgsasmのテスト(アセンブル+実行テスト)をもりもり実施中なのですが、アセンブリ言語自体のコーディングミスでテストがコケるというケース(=テストケースの間違い)が割と多い。

まぁ、それ自体は仕方のないことですが、どういう経路を辿ってエラーになったのかを特定するのが割とツライ。

という訳で、vgsdrun というデバッグ用コマンドを作ってみました。
https://github.com/suzukiplan/vgs-cpu/pull/10

これでアセンブリ言語のソースを実行すると、以下のように実行経過の情報をズラズラと出力していきます。

$ ./vgsdrun src/test/asm_add_a.asm 
assembling: src/test/asm_add_a.asm on memory
starting debug run.
00000000: 08 E8 03               : line#00006 > LD   A, 1000
00000003: 5D 00                  : line#00007 > ADD  A, 0
00000005: A6 E8 03               : line#00008 > CMP  A, 1000
00000008: F8 02 01 00 00         : line#00009 > JNE  $102
0000000d: F5 02 01 00 00         : line#00010 > JZ   $102
00000012: 5D FF                  : line#00011 > ADD  A, 255
00000014: A6 E7 04               : line#00012 > CMP  A, 1255
00000017: F8 02 01 00 00         : line#00013 > JNE  $102
0000001c: F5 02 01 00 00         : line#00014 > JZ   $102
00000021: 5E 00 01               : line#00015 > ADD  A, 256
00000024: A6 E7 05               : line#00016 > CMP  A, 1511
00000027: F8 02 01 00 00         : line#00017 > JNE  $102
0000002c: F5 02 01 00 00         : line#00018 > JZ   $102
00000031: 5E FF FF               : line#00019 > ADD  A, 65535
00000034: A7 E6 05 01 00         : line#00020 > CMP  A, 67046
00000039: F8 02 01 00 00         : line#00021 > JNE  $102
0000003e: F5 02 01 00 00         : line#00022 > JZ   $102
00000043: 5F 00 00 01 00         : line#00023 > ADD  A, 65536
00000048: A7 E6 05 02 00         : line#00024 > CMP  A, 132582
0000004d: F8 02 01 00 00         : line#00025 > JNE  $102
00000052: F5 02 01 00 00         : line#00026 > JZ   $102
00000057: 5F 1A FA FD FF         : line#00027 > ADD  A, -132582
0000005c: F6 02 01 00 00         : line#00028 > JNZ  $102
00000061: 09 78 56 34 12         : line#00031 > LD   A, $12345678
00000066: 12 00 00 00 00         : line#00032 > ST   A, [0]
0000006b: 07 00                  : line#00033 > LD   A, 0
0000006d: 63 00 00 00 00         : line#00034 > ADD  A, [0]O
00000072: A5 78                  : line#00035 > CMP  A, $78
00000074: F8 02 01 00 00         : line#00036 > JNE  $102
00000079: F5 02 01 00 00         : line#00037 > JZ   $102
0000007e: 5F 88 FF FF FF         : line#00038 > ADD  A, -120
00000083: F6 02 01 00 00         : line#00039 > JNZ  $102
00000088: 64 00 00 00 00         : line#00040 > ADD  A, [0]H
0000008d: A6 78 56               : line#00041 > CMP  A, $5678
00000090: F8 02 01 00 00         : line#00042 > JNE  $102
00000095: F5 02 01 00 00         : line#00043 > JZ   $102
0000009a: 5F 88 A9 FF FF         : line#00044 > ADD  A, -22136
0000009f: F6 02 01 00 00         : line#00045 > JNZ  $102
000000a4: 65 00 00 00 00         : line#00046 > ADD  A, [0]
000000a9: A7 78 56 34 12         : line#00047 > CMP  A, $12345678
000000ae: F8 02 01 00 00         : line#00048 > JNE  $102
000000b3: F5 02 01 00 00         : line#00049 > JZ   $102
000000b8: 5F 88 A9 CB ED         : line#00050 > ADD  A, -305419896
000000bd: F6 02 01 00 00         : line#00051 > JNZ  $102
000000c2: 1E 00 00 11 11         : line#00054 > LD   B, $11110000
000000c7: 32 11 11               : line#00055 > LD   C, $00001111
000000ca: 48 11 11 11 11         : line#00056 > LD   D, $11111111
000000cf: 60                     : line#00057 > ADD  A, B
000000d0: A7 00 00 11 11         : line#00058 > CMP  A, $11110000
000000d5: F8 02 01 00 00         : line#00059 > JNE  $102
000000da: F5 02 01 00 00         : line#00060 > JZ   $102
000000df: 61                     : line#00061 > ADD  A, C
000000e0: A7 11 11 11 11         : line#00062 > CMP  A, $11111111
000000e5: F8 02 01 00 00         : line#00063 > JNE  $102
000000ea: F5 02 01 00 00         : line#00064 > JZ   $102
000000ef: 62                     : line#00065 > ADD  A, D
000000f0: A7 22 22 22 22         : line#00066 > CMP  A, $22222222
000000f5: F8 02 01 00 00         : line#00067 > JNE  $102
000000fa: F5 02 01 00 00         : line#00068 > JZ   $102
000000ff: 46 01                  : line#00070 > LD   D, 1
00000101: 00                     : line#00071 > BRK 

[registers]
c->r.a = 22222222, c->r.b = 11110000, c->r.c = 00001111, c->r.d = 00000001
c->r.p = 00000101, c->r.s = 00000000, c->f.z = 00000000, c->f.q = 00000000
$

最初は、普通のgdbやxdbなどと同じようなステップ実行コマンドを用意しようと思ったのですが、それを作ろうとするとディスアセンブラを作らなければならず、ディスアセンブラ自体、後々必要になるかもしれませんが、今のところ必要になりそうな気配が無い。

という訳で、vgs-asm と vgs-cpu のコードをベースにして簡単に作ってみたのが、このvgsdrun コマンドです。

仕組みは物凄く単純で、vgs-asmは行バッファという領域にオペコードに変換したデータを持っているので、その情報をvgs-cpuの命令実行サイクル時にコールバックしてプログラムレジスタから該当する行バッファの内容を表示してあげるというもの。

ディスアセンブラをガチで作ると多分2000行の開発コストが掛かりますが、この方式ならだいたい200行ぐらいの改造(要するに労力的には1/10の作業量)で作れました。

まぁ、こういう所で削っていかないと、いつまで経ってもモノが完成しないので。

今回のCPU開発(というかVGS mk-III開発)のゴールは、
1. CPU(vgs-cpu)を自作する
2. アセンブラ(vgs-asm)を自作する
3. VGS mk-III の SDK をWindows + Mac + Linuxでザックリ使えるレベルで仕上げる
4. Invader Block を VGS mk-III で作って何処かにリリース
という風に想定していて、現在はとりあえず1と2が一区切りついた段階です。
前記事で完成したと言いましたが、アレは初期目標段階に達した(マイルストーンをクリアした)という意味で、まだまだ実際にゲームを作るのには不足した機能が割とあります。

あまり最初から完璧なモノを仕上げるより、とりあえず次フェーズに進めそうな形にしておき、次フェーズを進めながら随時細かいエンハンスを繰り返していくという開発モデル(だいたいアジャイル)です。