diff --git a/.gitignore b/.gitignore index ae5d9f4..837765c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,9 @@ .work *.dSYM/ .vscode +vgscpu.a vgscpu.o +vgsapi.o tp_stack_a tp_stack_b tp_stack_c @@ -61,3 +63,4 @@ tp_cmp2_a tp_cmp2_b tp_cmp2_c tp_cmp2_d +tp_vgs diff --git a/CHANGES.md b/CHANGES.md new file mode 100644 index 0000000..ab1c98e --- /dev/null +++ b/CHANGES.md @@ -0,0 +1,5 @@ +# Changes + +## Version 0.0.1 +- CPU実装完了 (APIはまだ全部揃っていない) + diff --git a/README.md b/README.md index d4a5207..53b9ea9 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,9 @@ -# [WIP] VGS CPU [![Build Status](https://travis-ci.org/suzukiplan/vgs-cpu.svg?branch=master)](https://travis-ci.org/suzukiplan/vgs-cpu) +# VGS CPU [![Build Status](https://travis-ci.org/suzukiplan/vgs-cpu.svg?branch=master)](https://travis-ci.org/suzukiplan/vgs-cpu) - SUZUKI PLAN - Video Game System - Central Processing Unit - VGS-CPU is a 32bit cpu that spacialized for creating games of VGS. -## Developmental status -WIP外しの残todo: -- [x] ACU-B の test case を全て追加 -- [x] ACU-C の test case を全て追加 -- [x] ACU-D の test case を全て追加 -- [x] CAL operand の実装 -- [x] branch operand の test case を全て追加 -- [ ] VGS operand の実装 -- [ ] VGS operand の test case を全て実装 -- [ ] ドキュメント整備 - -## About VGS-CPU -- 将来的には Cコンパイラ も作りたいと思っていますが __32bit CPUなのに6502並にフルアセンブリ言語でもコーディングしやすい石__ として, 嘗て私がフルアセでコードを書いていたことを色々思い出しながら設計しています _(単にCコンパイラを作るのは大変だからという説もある)_ -- VGSの推奨言語を今まで「C言語」としてきた伏線がようやくここで回収される訳です(ゲーム本体は普通にC++で書いた方が楽ですが、C++コンパイラを作るのは私には荷が重すぎるので... _Cなら標準関数を除けば多分作れる_) - ## How to use -- このリポジトリには コード + テスト しかありません +- UNIX系OS全般(mac/Linuxを含む) の ターミナル で `make` を実行すれば, できることが書いてあります - 利用したいプログラムに `git subversion add` して利用する想定 ## API specification @@ -215,4 +200,4 @@ void vgscpu_release_context(void *ctx); |---:|:---|:---|:---:|:---| |0|NOOP|n/a|0|何も実行せずに 0 を返す| -todo: 書き途中 +_※VGS APIは実装途中で、今後拡張していきます_ diff --git a/makefile b/makefile index 867a00d..b20223c 100644 --- a/makefile +++ b/makefile @@ -57,18 +57,24 @@ TESTCASE=\ tp_or_d\ tp_xor_d\ tp_cmp_d\ - tp_cmp2_d + tp_cmp2_d\ + tp_vgs all: @echo usage: @echo $$ make format : executes clang-format + @echo $$ make build : builds vgscpu.a @echo $$ make test : runs test + @echo $$ make clean : clean modules clean: + -@rm -f vgscpu.a + -@rm -f vgsapi.o -@rm -f vgscpu.o -@rm -f $(TESTCASE) format: + sh tools/format.sh src/cpu/vgsapi.c sh tools/format.sh src/cpu/vgscpu.c sh tools/format.sh src/cpu/vgscpu.h sh tools/format.sh src/cpu/vgscpu_internal.h @@ -79,18 +85,25 @@ format: sh tools/format.sh src/test/tp.h for TP in $(TESTCASE); do make format-test-src TP=$$TP; done -test: vgscpu.o - @for TP in $(TESTCASE); do make run-test-exec TP=$$TP; done - @rm vgscpu.o +build: vgscpu.a + +vgscpu.a: vgscpu.o vgsapi.o + ar ruv vgscpu.a vgscpu.o vgsapi.o vgscpu.o: src/cpu/vgscpu.c src/cpu/vgscpu.h src/cpu/vgscpu_internal.h - @gcc -I./src/cpu src/cpu/vgscpu.c -c -o vgscpu.o + gcc -O2 -I./src/cpu src/cpu/vgscpu.c -c -o vgscpu.o + +vgsapi.o: src/cpu/vgsapi.c src/cpu/vgscpu_internal.h + gcc -O2 -I./src/cpu src/cpu/vgsapi.c -c -o vgsapi.o + +test: build + for TP in $(TESTCASE); do make run-test-exec TP=$$TP; done format-test-src: @sh tools/format.sh src/test/$(TP).c run-test-exec: @echo testing: $(TP) - @gcc -I./src/cpu vgscpu.o src/test/$(TP).c -o $(TP) - @./$(TP) + gcc -I./src/cpu src/test/$(TP).c -o $(TP) vgscpu.a + ./$(TP) @rm ./$(TP) diff --git a/src/cpu/vgsapi.c b/src/cpu/vgsapi.c new file mode 100644 index 0000000..cc93e9e --- /dev/null +++ b/src/cpu/vgsapi.c @@ -0,0 +1,6 @@ +#include "vgscpu_internal.h" + +int vgsapi_noop(struct vgscpu_context* c) +{ + return 0; +} \ No newline at end of file diff --git a/src/cpu/vgscpu.c b/src/cpu/vgscpu.c index c5a9466..6a0444c 100644 --- a/src/cpu/vgscpu.c +++ b/src/cpu/vgscpu.c @@ -65,6 +65,8 @@ c->r.s += 4; \ } +static int (*vgsapi[1])(struct vgscpu_context *) = {vgsapi_noop}; + void *vgscpu_create_context() { return vgscpu_create_specific_context(VGSCPU_PROGRAM_SIZE_DEFAULT, VGSCPU_STACK_SIZE_DEFAULT, VGSCPU_MEMORY_SIZE_DEFAULT); @@ -2643,6 +2645,12 @@ int vgscpu_run(void *ctx) ASSERT_IF_OUT_OF_PROGRAM_MEMORY_SPECIFIC(i); c->r.p = i; break; + case VGSCPU_OP_VGS: + ASSERT_IF_OUT_OF_PROGRAM_MEMORY(2); + c->r.p++; + c->r.d = vgsapi[c->p[c->r.p]](c); + c->r.p++; + break; default: sprintf(c->error, "UNKNOWN INSTRUCTION(%02X)", (int)c->p[c->r.p]); loop_flag = 0; diff --git a/src/cpu/vgscpu_internal.h b/src/cpu/vgscpu_internal.h index 45d5710..b29e58c 100644 --- a/src/cpu/vgscpu_internal.h +++ b/src/cpu/vgscpu_internal.h @@ -33,3 +33,5 @@ struct vgscpu_context { unsigned char* s; /* stack */ unsigned char* m; /* main memory */ }; + +int vgsapi_noop(struct vgscpu_context* c); diff --git a/src/test/tp_vgs.c b/src/test/tp_vgs.c new file mode 100644 index 0000000..1e25aec --- /dev/null +++ b/src/test/tp_vgs.c @@ -0,0 +1,31 @@ +#include "tp.h" + +int test(struct vgscpu_context *c) +{ + unsigned char op1[] = {VGSCPU_OP_LD_D_1, 0xff, VGSCPU_OP_VGS, VGSCPU_OP_BRK}; + unsigned char op2[] = {VGSCPU_OP_LD_D_1, 0xff, VGSCPU_OP_VGS, 0x00, VGSCPU_OP_BRK}; + + vgscpu_load_program(c, op1, sizeof(op1)); + TEST(__FILE__, __LINE__, vgscpu_run(c), -1); + TEST(__FILE__, __LINE__, strcmp(c->error, "OUT OF PROGRAM MEMORY: $00000004"), 0); + + vgscpu_load_program(c, op2, sizeof(op2)); + TEST(__FILE__, __LINE__, vgscpu_run(c), 0); + TEST(__FILE__, __LINE__, c->r.d, 0); + return 0; +} + +int main() +{ + struct vgscpu_context *c = (struct vgscpu_context *)vgscpu_create_context(); + if (!c) return -1; + int result = -1; + + if (test(c)) goto END_TEST; + + result = 0; + puts("success"); +END_TEST: + vgscpu_release_context(c); + return result; +} \ No newline at end of file