2016年7月18日月曜日

vgs-cpuを完成させる

昨日書いた VGS-CPU + アセンブラ (VGS-ASM) を(とりあえず)完成させた。ただし、アセンブラの方は、まだ十分にテストしていないのでまだバグがあるかもしれません。(CPUの方にはバグはありません)
https://github.com/suzukiplan/vgs-cpu

命令セットの仕様的には、8086 と 6502 がごっちゃになった感じで、尚且つ32bit CPU という、一見するとカオスな感じでありながら、実際のところかなりアセンブリ言語でのコーディングがし易い形になっているのではないかと思います。

当初VGSオペランドという特殊命令を実装するつもりでしたが、それだと VGS-CPU の用途が狭まってしまう。元々、VGS用ゲーム開発専用のCPUを開発するつもりで作っていたので、それでも目的は外れていないのですが、VGS-CPUをベースにした亜種CPUを開発し易いようにするため、8086のINT命令相当のものを実装することにしました。

INT命令といえば、MS-DOSのサービスコール INT 21h とかよく使いましたね。

INT命令で実行される命令は、以下のように簡単に(最大256個)登録できます。

int hello_world(struct vgscpu_context *c)
{
    printf("HELLO, VGS-CPU");
    return 0;
}

int main()
{
    struct vgscpu_context *c = (struct vgscpu_context *)vgscpu_create_context();
    vgscpu_regist_interrupt(c, 0, hello_world);

VGS mark-III では、この割り込みの大半が VGS-API に割り当てる形になります。
INT命令を実装したことで、VGS-CPU と VGS-ASM の責務範囲は一通り実装できたことになるので、「だいたい完成した」といって良い状態ではないかと思います。

VGS-ASMの方は、まだまだ実装したい項目が盛り沢山ですが。
とりあえず、VGS-CPUの全ての命令セットを使用したコーディングができるという状態。

テストが通っているアセンブリ言語のサンプルソース:

/*
    PUSH/POP A の テストプログラム
 */
start:
    LD      A, $deadbeef
    PUSH    A
    PUSH    AH
    PUSH    AO

    POP     AO
    CMP     A, $ef
    JNE     test-failed

    POP     AH
    CMP     A, $beef
    JNE     test-failed

    POP     A
    CMP     A, $deadbeef
    JNE     test-failed

    LD      D, 1
    BRK

test-failed:
    LD      D, -1
    BRK

中々良い感じではないでしょうか。

今は MMM; main memory mapper という、フルアセでコーディングする上で一番厄介になる主記憶のメモリマッピングをアセンブリ言語で簡潔に表現できる仕組みを脳内で設計中。(あとはテストも書かないと)