Skip to content

Commit

Permalink
Merge pull request #8 from suzukiplan/ldst-from-regaddr
Browse files Browse the repository at this point in the history
load/store from register specified address
  • Loading branch information
suzukiplan committed Jul 23, 2016
2 parents 5554c75 + f7cc477 commit 3743673
Show file tree
Hide file tree
Showing 21 changed files with 1,574 additions and 20 deletions.
12 changes: 10 additions & 2 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
# Changes

## version 0.1.2
## Version 0.2.0
- cpu
- レジスタが指すアドレス値からの load/store に対応
- `vgsasm`
- LD/ST の 引数 に レジスタアドレス `[GR]` を指定できるようにする
- ブラケット `[` に対応する `]` が無い場合を syntax error にする
- エラー時のコマンド戻り値の仕様を変更

## Version 0.1.2
- license の修正(不要文言削除のみ)
- `vgsasm` のテストを追加
- bugfix: SHL, SHR の結果が ゼロフラグ に反映されない

## Version 0.1.1
- `vgsasm` のテストを追加: LD, ST
- bugfix: 引数またはレジスタが指定できる第2オペランドにレジスタBを指定する2進数の0が指定されてしまう
- bugfix: 引数またはレジスタが指定できる第2オペランドにレジスタBを指定すると2進数の0が指定されたものとみなされる

## Version 0.1.0 (破壊的変更)
- `VGS` 命令を廃止
Expand Down
13 changes: 12 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
# 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.
- VGS-CPU is a 32bit CPU that spacialized for creating games of VGS.
- This repository also provides assember for VGS-CPU.

## License
[2-clause BSD](https://github.com/suzukiplan/vgs-cpu/blob/master/LICENSE.txt)

## Support environment
- `make test` を実行して全ての項目が success になる環境であれば動作できます
- big-endian の環境には対応していません

## How to use
- UNIX系OS全般(mac/Linuxを含む) の ターミナル で `make` を実行すれば, できることが書いてあります
- `make build` を実行すればアセンブラ (vgsasmコマンド) をビルドできます
Expand Down Expand Up @@ -115,6 +119,11 @@ void vgscpu_release_context(void *ctx);
- `[n]H` : 通常, アドレスが指す 16bit の領域を意味する
- `[n]O` : 通常, アドレスが指す 8bit の領域を意味する
- 例外的にアドレスの先頭を単純に指し示す場合は単に `[n]` と表記
- `[GR]` : general register address
- `[GR]` : 通常, アドレス (GR値) が指す 32bit の領域を意味する
- `[GR]H` : 通常, アドレス (GR値) が指す 16bit の領域を意味する
- `[GR]O` : 通常, アドレス (GR値) が指す 8bit の領域を意味する
- 例外的にアドレスの先頭を単純に指し示す場合は単に `[GR]` と表記
### memory operations
|operand|z|q|outline|
Expand All @@ -124,7 +133,9 @@ void vgscpu_release_context(void *ctx);
|`LD GR, n`|-|-|汎用レジスタ `<-` 定数|
|`LD GR, [n]`|-|-|汎用レジスタ `<-` 主記憶のn番地の内容|
|`LD GR1, GR2`|-|-|汎用レジスタ1 に 汎用レジスタ2 の内容をロード|
|`LD GR1, [GR2]`|-|-|汎用レジスタ1 に 主記憶の 汎用レジスタ2 が指す番地の内容をロード|
|`ST GR, [n]`|-|-|汎用レジスタ の 値 `->` 主記憶のn番地|
|`ST GR, [GR2]`|-|-|汎用レジスタ の 値 `->` 主記憶の 汎用レジスタ2 が指す番地|
### arithmetic calculation
|operand|z|q|outline|
Expand Down
2 changes: 0 additions & 2 deletions makefile
Original file line number Diff line number Diff line change
Expand Up @@ -147,5 +147,3 @@ asm-test:
./asmtest src/test/asm_add_c.asm
./asmtest src/test/asm_add_d.asm
./asmtest src/test/asm_shift.asm
@rm asmtest
@rm tp.bin
30 changes: 20 additions & 10 deletions src/asm/vgsasm.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@
#endif
#include "vgsasm.h"

#define NO_ERROR 0
#define PARAM_ERROR 1
#define FILE_READ_ERROR 2
#define FILE_WRITE_ERROR 3
#define SYNTAX_ERROR 4

struct program_table {
char input[1024];
char output[1024];
Expand Down Expand Up @@ -66,48 +72,52 @@ int main(int argc, char* argv[])

if (check_arguments(argc, argv)) {
puts("usage: vgsasm [-o output.bin] input.asm");
return 1;
return PARAM_ERROR;
}
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;
return FILE_READ_ERROR;
}

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

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

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

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

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

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

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;
return FILE_WRITE_ERROR;
}
}
}
Expand All @@ -127,5 +137,5 @@ int main(int argc, char* argv[])
printf("success (%fsec)\n", sec);
#endif

return 0;
return NO_ERROR;
}
17 changes: 16 additions & 1 deletion src/asm/vgsasm.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,19 @@
#define M2 2
#define M4 4

#define RA1 0x01
#define RA2 0x02
#define RA4 0x04
#define RB1 0x11
#define RB2 0x12
#define RB4 0x14
#define RC1 0x21
#define RC2 0x22
#define RC4 0x24
#define RD1 0x31
#define RD2 0x32
#define RD4 0x34

#define ACU_ADD 0
#define ACU_SUB 1
#define ACU_MUL 2
Expand Down Expand Up @@ -49,17 +62,19 @@ struct line_data {

char* load_file(const char* path);
void trimstring(char* src);
void back_space(char* ln);
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);
int check_register_address(char* token, int* r);

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_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);
Expand Down
20 changes: 19 additions & 1 deletion src/asm/vgsasm_parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -109,14 +109,31 @@ void remove_empty_line(struct line_data* line, int* len)
}
}

void parse_token(struct line_data* line, int len)
int parse_token(struct line_data* line, int len)
{
int error_count = 0;
int i;
char* w;
char* bs;
for (i = 0; i < len; i++) {
w = line[i].buffer;
while (*w) {
line[i].token[line[i].toknum++] = w;
if ('[' == *w) {
bs = w;
while (*w && ']' != *w) {
if (' ' == *w)
back_space(w);
else
w++;
}
if (']' != *w) {
sprintf(line[i].error, "syntax error: there is no corresponding bracket: %s", bs);
error_count++;
} else {
w++;
}
}
while (*w && ' ' != *w) {
w++;
}
Expand All @@ -129,6 +146,7 @@ void parse_token(struct line_data* line, int len)
}
}
}
return error_count;
}

int parse_operation(struct line_data* line, int len)
Expand Down
22 changes: 22 additions & 0 deletions src/asm/vgsasm_parse_arl.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,28 @@ int _parse_arl(struct line_data* line, int i, int r, int op)
line[i].oplen = 5;
}
return 0;
} else if (0 == check_register_address(line[i].token[2], &m)) {
switch (op) {
case VGSCPU_OP_LD_A_1:
op = VGSCPU_OP_LD_A_RM;
break;
case VGSCPU_OP_LD_B_1:
op = VGSCPU_OP_LD_B_RM;
break;
case VGSCPU_OP_LD_C_1:
op = VGSCPU_OP_LD_C_RM;
break;
case VGSCPU_OP_LD_D_1:
op = VGSCPU_OP_LD_D_RM;
break;
default:
sprintf(line[i].error, "syntax error: cannot specify register address argument to the %s operand", line[i].token[1]);
return -1;
}
line[i].op[0] = op;
line[i].op[1] = m & 0xff;
line[i].oplen = 2;
return 0;
} else if (0 == check_address(line[i].token[2], &v, &m)) {
memcpy(&line[i].op[1], &v, 4);
line[i].oplen = 5;
Expand Down
20 changes: 20 additions & 0 deletions src/asm/vgsasm_parse_st.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,26 @@ static int parse_st_internal(struct line_data* line, int i, int op)
unsigned int v;
unsigned short s;
int m;
if (0 == check_register_address(line[i].token[2], &m)) {
switch (op) {
case VGSCPU_OP_ST_A_M1:
op = VGSCPU_OP_ST_A_RM;
break;
case VGSCPU_OP_ST_B_M1:
op = VGSCPU_OP_ST_B_RM;
break;
case VGSCPU_OP_ST_C_M1:
op = VGSCPU_OP_ST_C_RM;
break;
case VGSCPU_OP_ST_D_M1:
op = VGSCPU_OP_ST_D_RM;
break;
}
line[i].op[0] = op;
line[i].op[1] = m & 0xff;
line[i].oplen = 2;
return 0;
}
if (0 == check_address(line[i].token[2], &v, &m)) {
memcpy(&line[i].op[1], &v, 4);
line[i].oplen = 5;
Expand Down
73 changes: 73 additions & 0 deletions src/asm/vgsasm_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,15 @@ void trimstring(char* src)
}
}

void back_space(char* ln)
{
if (!*ln) return;
do {
*ln = *(ln + 1);
ln++;
} while (*(ln - 1));
}

int check_GR(char* token)
{
if (0 == strcasecmp(token, "A")) {
Expand Down Expand Up @@ -271,3 +280,67 @@ int check_address(char* token, unsigned int* result, int* m)
}
return -1;
}

int check_register_address(char* token, int* r)
{
char buf[1024];
strcpy(buf, token);
size_t len = strlen(buf);
if (len < 3) return -1;
if ('[' == buf[0] && ']' == buf[len - 1]) {
buf[len - 1] = '\0';
switch (check_GR(buf + 1)) {
case A4:
*r = RA4;
return 0;
case B4:
*r = RB4;
return 0;
case C4:
*r = RC4;
return 0;
case D4:
*r = RD4;
return 0;
default:
return -1;
}
} else if ('[' == buf[0] && ']' == buf[len - 2] && ('H' == buf[len - 1] || 'h' == buf[len - 1])) {
buf[len - 2] = '\0';
switch (check_GR(buf + 1)) {
case A4:
*r = RA2;
return 0;
case B4:
*r = RB2;
return 0;
case C4:
*r = RC2;
return 0;
case D4:
*r = RD2;
return 0;
default:
return -1;
}
} else if ('[' == buf[0] && ']' == buf[len - 2] && ('O' == buf[len - 1] || 'o' == buf[len - 1])) {
buf[len - 2] = '\0';
switch (check_GR(buf + 1)) {
case A4:
*r = RA1;
return 0;
case B4:
*r = RB1;
return 0;
case C4:
*r = RC1;
return 0;
case D4:
*r = RD1;
return 0;
default:
return -1;
}
}
return -1;
}
Loading

0 comments on commit 3743673

Please sign in to comment.