Skip to content

Commit

Permalink
Merge pull request #1 from suzukiplan/create-vgsasm
Browse files Browse the repository at this point in the history
make vgsasm
  • Loading branch information
suzukiplan committed Jul 17, 2016
2 parents c217b81 + c93e011 commit e0be8b7
Show file tree
Hide file tree
Showing 22 changed files with 1,391 additions and 1 deletion.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,7 @@ tp_cmp2_b
tp_cmp2_c
tp_cmp2_d
tp_vgs
vgsasm
asmtest
tp.bin

3 changes: 3 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Changes

## Version 0.0.2
- `vgsasm` コマンドを実装 (注意: テスト未実施)

## Version 0.0.1
- CPU実装完了 (APIはまだ全部揃っていない)

10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
# 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.
- This repository also provides assember for VGS-CPU.

## How to use
- UNIX系OS全般(mac/Linuxを含む) の ターミナル で `make` を実行すれば, できることが書いてあります
- `make build` を実行すればアセンブラ (vgsasmコマンド) をビルドできます
- 利用したいプログラムに `git subversion add` して利用する想定

## API specification
Expand Down Expand Up @@ -179,6 +181,7 @@ void vgscpu_release_context(void *ctx);
|`JNP n`|-|x|`f.q` が 非1 の場合, アドレスn へジャンプ|
|`CAL n`|-|-|アドレスn を呼び出す|
|`RET`|-|-|`CAL` の呼び出し元へ復帰|
|`BRK`|-|-|プログラムの実行状態を解除|
- `CAL` を実行すると, スタック領域に 戻りアドレス(4byte) を PUSH して アドレスn へジャンプする
- `RET` を実行すると, スタック領域から 戻りアドレス(4byte) を POP して 戻りアドレス へジャンプする
Expand All @@ -201,3 +204,10 @@ void vgscpu_release_context(void *ctx);
|0|NOOP|n/a|0|何も実行せずに 0 を返す|
_※VGS APIは実装途中で、今後拡張していきます_
## [WIP] VGS ASM
### vgsasm command
```
$ vgsasm [-o output-binary] input-source
```
_現時点ではビルドのみ完了している状態です(テストはまだしていません)_
35 changes: 34 additions & 1 deletion makefile
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,23 @@ TESTCASE=\
tp_cmp2_d\
tp_vgs

VGSASM_SRC=\
src/asm/vgsasm.c\
src/asm/vgsasm_parse.c\
src/asm/vgsasm_parse_push.c\
src/asm/vgsasm_parse_pop.c\
src/asm/vgsasm_parse_ld.c\
src/asm/vgsasm_parse_st.c\
src/asm/vgsasm_parse_inc.c\
src/asm/vgsasm_parse_dec.c\
src/asm/vgsasm_parse_not.c\
src/asm/vgsasm_parse_shift.c\
src/asm/vgsasm_parse_acu.c\
src/asm/vgsasm_parse_arl.c\
src/asm/vgsasm_parse_branch.c\
src/asm/vgsasm_parse_vgs.c\
src/asm/vgsasm_util.c

all:
@echo usage:
@echo $$ make format : executes clang-format
Expand All @@ -74,6 +91,7 @@ clean:
-@rm -f $(TESTCASE)

format:
sh tools/format.sh src/asm/vgsasm.h
sh tools/format.sh src/cpu/vgsapi.c
sh tools/format.sh src/cpu/vgscpu.c
sh tools/format.sh src/cpu/vgscpu.h
Expand All @@ -83,9 +101,13 @@ format:
sh tools/format.sh src/cpu/vgscpu_op_acu_c.h
sh tools/format.sh src/cpu/vgscpu_op_acu_d.h
sh tools/format.sh src/test/tp.h
for AS in $(VGSASM_SRC); do make format-src SRC=$$AS; done
for TP in $(TESTCASE); do make format-test-src TP=$$TP; done

build: vgscpu.a
format-src:
@sh tools/format.sh $(SRC)

build: vgscpu.a vgsasm

vgscpu.a: vgscpu.o vgsapi.o
ar ruv vgscpu.a vgscpu.o vgsapi.o
Expand All @@ -96,8 +118,12 @@ vgscpu.o: src/cpu/vgscpu.c src/cpu/vgscpu.h src/cpu/vgscpu_internal.h
vgsapi.o: src/cpu/vgsapi.c src/cpu/vgscpu_internal.h
gcc -O2 -I./src/cpu src/cpu/vgsapi.c -c -o vgsapi.o

vgsasm: src/asm/vgsasm.h src/cpu/vgscpu_internal.h $(VGSASM_SRC)
gcc -O2 -I./src/asm -I./src/cpu $(VGSASM_SRC) -o vgsasm

test: build
for TP in $(TESTCASE); do make run-test-exec TP=$$TP; done
make asm-test

format-test-src:
@sh tools/format.sh src/test/$(TP).c
Expand All @@ -107,3 +133,10 @@ run-test-exec:
gcc -I./src/cpu src/test/$(TP).c -o $(TP) vgscpu.a
./$(TP)
@rm ./$(TP)

asm-test:
@sh tools/format.sh src/test/asmtest.c
gcc -I./src/cpu src/test/asmtest.c -o asmtest vgscpu.a
./asmtest src/test/asm_push_pop_a.asm
@rm asmtest
@rm tp.bin
131 changes: 131 additions & 0 deletions src/asm/vgsasm.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
#ifndef _WIN32
#include <sys/time.h>
#endif
#include "vgsasm.h"

struct program_table {
char input[1024];
char output[1024];
char* buffer;
struct line_data* line;
int line_number;
} PT;

static int check_arguments(int argc, char* argv[])
{
int i;
memset(&PT, 0, sizeof(PT));
for (i = 1; i < argc; i++) {
if (0 == strcmp("-o", argv[i])) {
if (PT.output[0]) return -1;
if (argc <= ++i) return -1;
if (sizeof(PT.output) <= strlen(argv[i])) return -1;
strcpy(PT.output, argv[i]);
} else {
if (PT.input[0]) return -1;
if (sizeof(PT.input) <= strlen(argv[i])) return -1;
strcpy(PT.input, argv[i]);
}
}
if (!PT.input[0]) return -1;
if (!PT.output[0]) {
strcpy(PT.output, PT.input);
char* ext = strrchr(PT.output, '.');
if (ext) *ext = '\0';
if (sizeof(PT.output) <= strlen(PT.output) + 4) return -1;
strcat(PT.output, ".bin");
}
return 0;
}

static void show_errors(struct line_data* line, int len)
{
int i;
int n = 0;
for (i = 0; i < len; i++) {
if (line[i].error[0]) {
fprintf(stderr, "%s (line=%d)\n", line[i].error, line[i].number);
n++;
}
}
fprintf(stderr, "detected %d error%s.\n", n, 1 < n ? "s" : "");
}

int main(int argc, char* argv[])
{
FILE* fp;
int i;

#ifndef _WIN32
long usec;
double sec;
struct timeval tvStart;
struct timeval tvEnd;
gettimeofday(&tvStart, NULL);
#endif

if (check_arguments(argc, argv)) {
puts("usage: vgsasm [-o output.bin] input.asm");
return 1;
}
LOGV("assembling: %s -> %s\n", PT.input, PT.output);

PT.buffer = load_file(PT.input);
if (NULL == PT.buffer) {
fprintf(stderr, "file load error.\n");
return 2;
}

PT.line = parse_lines(PT.buffer, &PT.line_number);
if (NULL == PT.line) {
return 3;
}

remove_empty_line(PT.line, &PT.line_number);
if (0 == PT.line_number) {
fprintf(stderr, "empty source file.\n");
return 4;
}

parse_token(PT.line, PT.line_number);
if (parse_operation(PT.line, PT.line_number)) {
show_errors(PT.line, PT.line_number);
return 5;
}

if (check_label(PT.line, PT.line_number)) {
show_errors(PT.line, PT.line_number);
return 6;
}

if (NULL == (fp = fopen(PT.output, "wb"))) {
fprintf(stderr, "file open error.\n");
return 7;
}

for (i = 0; i < PT.line_number; i++) {
if (PT.line[i].oplen) {
if (PT.line[i].oplen != fwrite(PT.line[i].op, 1, PT.line[i].oplen, fp)) {
fprintf(stderr, "file write error.\n");
return 8;
}
}
}
fclose(fp);
free(PT.line);
free(PT.buffer);

#ifdef _WIN32
printf("success\n");
#else
gettimeofday(&tvEnd, NULL);
usec = tvEnd.tv_sec - tvStart.tv_sec;
usec *= 1000000;
usec += tvEnd.tv_usec;
usec -= tvStart.tv_usec;
sec = usec / 1000000.0;
printf("success (%fsec)\n", sec);
#endif

return 0;
}
76 changes: 76 additions & 0 deletions src/asm/vgsasm.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "vgscpu_internal.h"

#define LOGV printf
#define A1 0
#define A2 1
#define A4 2
#define B1 3
#define B2 4
#define B4 5
#define C1 6
#define C2 7
#define C4 8
#define D1 9
#define D2 10
#define D4 11

#define M1 1
#define M2 2
#define M4 4

#define ACU_ADD 0
#define ACU_SUB 1
#define ACU_MUL 2
#define ACU_DIV 3
#define ACU_MOD 4
#define ACU_AND 5
#define ACU_OR 6
#define ACU_XOR 7
#define ACU_CMP 8
#define ACU_CMP2 9

#define SHIFT_LEFT 0
#define SHIFT_RIGHT 1

struct line_data {
char error[1024];
char* buffer;
int number;
char* token[8];
int toknum;
unsigned char op[16];
int oplen;
char branch_label[256];
int label_resolved;
};

char* load_file(const char* path);
void trimstring(char* src);
int check_GR(char* token);
int getHex(char c);
int getDec(char c);
int getOct(char c);
int getBin(char c);
int check_literal(char* token, unsigned int* result);
int check_address(char* token, unsigned int* result, int* m);

struct line_data* parse_lines(char* buf, int* line);
void remove_empty_line(struct line_data* line, int* len);
void parse_token(struct line_data* line, int len);
int parse_operation(struct line_data* line, int len);
int parse_push(struct line_data* line, int i);
int parse_pop(struct line_data* line, int i);
int parse_ld(struct line_data* line, int i);
int parse_st(struct line_data* line, int i);
int parse_inc(struct line_data* line, int i);
int parse_dec(struct line_data* line, int i);
int parse_not(struct line_data* line, int i);
int parse_shift(struct line_data* line, int i, int lr);
int parse_acu(struct line_data* line, int i, int acu);
int _parse_arl(struct line_data* line, int i, int r, int op);
int parse_branch(struct line_data* line, int i, unsigned char op);
int parse_vgs(struct line_data* line, int i);
int check_label(struct line_data* line, int len);
Loading

0 comments on commit e0be8b7

Please sign in to comment.