From ecd73ba08f9b8721742ae5dbb72e1c4261574b36 Mon Sep 17 00:00:00 2001 From: j8takagi Date: Thu, 21 Jan 2010 23:11:09 +0900 Subject: [PATCH] =?utf8?q?=E5=BC=95=E6=95=B0=E3=81=AE=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit -M: メモリーサイズの指定 -C: クロック周波数を指定 -o: アセンブラ結果をファイルに出力し、実行。出力先のデフォルトは、a.o -O: アセンブラ結果をファイルに出力し、終了。出力先のデフォルトは、a.o --- include/casl2.h | 15 +++++++-- src/assemble.c | 8 ++--- src/casl2.c | 88 +++++++++++++++++++++++++++++++++---------------- src/cerr.c | 3 +- src/comet2.c | 15 +++++++-- src/exec.c | 28 +++++++++++----- src/struct.c | 13 ++++++-- 7 files changed, 119 insertions(+), 51 deletions(-) diff --git a/include/casl2.h b/include/casl2.h index 70e25c5..47461dc 100644 --- a/include/casl2.h +++ b/include/casl2.h @@ -13,8 +13,8 @@ enum { CMDSIZE = 4, /* 命令の最大文字数 */ REGSIZE = 8, /* 汎用レジスタの数 */ - MEMSIZE = 512, /* メモリ容量。COMET II規格では、65536語 */ - CLOCKS = 5000000 /* クロック周波数。COMET II規格では、未定義 */ + DEFAULT_MEMSIZE = 512, /* デフォルトのメモリ容量。COMET II規格では、65536語 */ + DEFAULT_CLOCKS = 5000000 /* デフォルトのクロック周波数。COMET II規格では、未定義 */ }; /* ハッシュ値を取得する */ @@ -24,7 +24,7 @@ unsigned hash(const char *key, int size); typedef unsigned short WORD; /* COMET IIのメモリ */ -extern WORD memory[MEMSIZE]; +extern WORD *memory; /* COMET IIのCPUレジスタ */ extern WORD GR[REGSIZE], SP, PR, FR; @@ -57,12 +57,21 @@ extern bool srcmode; /* ラベル表を表示する場合はTRUE */ extern bool labelmode; +/* ラベル表を表示して終了する場合はTRUE */ +extern bool onlylabelmode; + /* アセンブラ詳細結果を表示するならTRUE */ extern bool asdetailmode; /* アセンブルだけを行う場合はTRUE */ extern bool onlyassemblemode; +/* メモリーサイズ */ +extern int memsize; + +/* クロック周波数 */ +extern int clocks; + /* 実行開始番地 */ extern WORD startptr; diff --git a/src/assemble.c b/src/assemble.c index 3549c61..3b91398 100644 --- a/src/assemble.c +++ b/src/assemble.c @@ -92,7 +92,7 @@ bool writememory(WORD word, WORD adr, PASS pass) { bool status = false; /* COMET IIメモリオーバーの場合 */ - if(adr >= MEMSIZE) { + if(adr >= memsize) { setcerr(119, wtoa(adr)); /* out of COMET II memory */ } if(cerrno == 0) { @@ -153,7 +153,7 @@ void writestr(const char *str, bool literal, PASS pass) void writeDC(const char *str, PASS pass) { WORD adr = 0x0; - if(*str == '\''){ + if(*str == '\'') { writestr(str, false, pass); } else { if(*str == '#') { @@ -202,7 +202,7 @@ bool assemblecmd(const CMDLINE *cmdl, PASS pass) setcerr(107, NULL); /* no label in START */ return false; } - /* オペランドがある場合、実行開始番地を設定 */ + /* オペランドがある場合、実行開始番地を設定 */ if(pass == SECOND && cmdl->opd->opdc == 1) { if((startptr = getlabel(cmdl->opd->opdv[0])) == 0xFFFF) { setcerr(103, cmdl->opd->opdv[0]); /* label not found */ @@ -366,7 +366,7 @@ bool cometcmd(const CMDLINE *cmdl, PASS pass) } /* オペランド数1〜2。第1オペランドはアドレス */ else if(cmdl->opd->opdc == 1 || cmdl->opd->opdc == 2) { - if((cmd = getcmdcode(cmdl->cmd, ADR_X)) == 0xFFFF) { + if((cmd = getcmdcode(cmdl->cmd, ADR_X)) == 0xFFFF) { setcerr(111, cmdl->cmd); /* not command of operand "adr[,x]" */ return false; } diff --git a/src/casl2.c b/src/casl2.c index 2d17acd..f4c8f88 100644 --- a/src/casl2.c +++ b/src/casl2.c @@ -16,17 +16,21 @@ void outassemble(char *file) { } static struct option longopts[] = { + {"source", no_argument, NULL, 's'}, + {"label", no_argument, NULL, 'l'}, + {"labelonly", no_argument, NULL, 'L'}, + {"assembledetail", no_argument, NULL, 'a'}, + {"assembledetailonly", no_argument, NULL, 'A'}, + {"assembleout", optional_argument, NULL, 'o'}, + {"assembleoutonly", optional_argument, NULL, 'O'}, {"trace", no_argument, NULL, 't'}, {"tracearithmetic", no_argument, NULL, 't'}, {"tracelogical", no_argument, NULL, 'T'}, {"dump", no_argument, NULL, 'd'}, - {"source", no_argument, NULL, 's'}, - {"label", no_argument, NULL, 'l'}, - {"assembledetail", no_argument, NULL, 'a'}, - {"onlyassemble", optional_argument, NULL, 'o'}, - {"assembledetailonly", no_argument, NULL, 'A'}, + {"memsize", required_argument, NULL, 'M'}, + {"clocks", required_argument, NULL, 'C'}, {"help", no_argument, NULL, 'h'}, - {0, 0, 0, 0} + {0, 0, 0, 0}, }; int main(int argc, char *argv[]) @@ -36,39 +40,57 @@ int main(int argc, char *argv[]) bool status = false; WORD beginptr[argc]; char *objfile = NULL; - const char *usage = "Usage: %s [-tTdslaAh] [-o ] FILE ...\n"; + const char *default_objfile = "a.o"; + const char *usage = "Usage: %s [-slLaAtTdh] [-oO] [-M ] [-C ] FILE ...\n"; - while((opt = getopt_long(argc, argv, "tTdslao:Ah", longopts, NULL)) != -1) { + while((opt = getopt_long(argc, argv, "tTdslLao::O::AM:C:h", longopts, NULL)) != -1) { switch(opt) { - case 't': - tracemode = true; - break; - case 'T': - tracemode = true; - logicalmode = true; - break; - case 'd': - dumpmode = true; - break; case 's': srcmode = true; break; case 'l': labelmode = true; break; + case 'L': + onlylabelmode = true; + break; case 'a': asdetailmode = true; break; - case 'o': + case 'A': onlyassemblemode = true; - if(optarg != NULL) { + asdetailmode = true; + break; + case 'o': + if(optarg == NULL) { + objfile = strdup(default_objfile); + } else { objfile = strdup(optarg); } break; - case 'A': + case 'O': onlyassemblemode = true; - objfile = NULL; - asdetailmode = true; + if(optarg == NULL) { + objfile = strdup(default_objfile); + } else { + objfile = strdup(optarg); + } + break; + case 't': + tracemode = true; + break; + case 'T': + tracemode = true; + logicalmode = true; + break; + case 'd': + dumpmode = true; + break; + case 'M': + memsize = atoi(optarg); + break; + case 'C': + clocks = atoi(optarg); break; case 'h': fprintf(stdout, usage, argv[0]); @@ -78,6 +100,12 @@ int main(int argc, char *argv[]) exit(-1); } } + if(argv[optind] == NULL) { + fprintf(stderr, "source file is not specified\n"); + exit(-1); + } + /* ソースファイルが指定されていない場合は終了 */ + reset(); /* アセンブル。ラベル表作成のため、2回行う */ for(pass = FIRST; pass <= SECOND; pass++) { for(i = optind; i < argc; i++) { @@ -99,18 +127,20 @@ int main(int argc, char *argv[]) exit(-1); } } - if(pass == FIRST && labelmode == true) { + if(pass == FIRST && (labelmode == true || onlylabelmode == true)) { fprintf(stdout, "\nLabel::::\n"); printlabel(); + if(onlylabelmode == true) { + return 0; + } } } freelabel(); /* ラベル表の解放 */ if(status == true) { - if(onlyassemblemode) { - if(objfile != NULL) { - outassemble(objfile); - } - } else { + if(objfile != NULL) { + outassemble(objfile); + } + if(onlyassemblemode == false) { exec(); /* プログラム実行 */ } } diff --git a/src/cerr.c b/src/cerr.c index 250ad80..74dec44 100644 --- a/src/cerr.c +++ b/src/cerr.c @@ -33,7 +33,8 @@ CERRARRAY cerr[] = { { 203, "SVC output - out of COMET II memory" }, { 204, "Program Register (PR) - out of COMET II memory" }, { 205, "Stack Pointer (SP) - cannot allocate stack buffer" }, - { 206, "Address - out of COMET II memory" } + { 206, "Address - out of COMET II memory" }, + { 207, "Stack Pointer (SP) - out of COMET II memory" }, }; /* WORD値を文字列に変換 */ diff --git a/src/comet2.c b/src/comet2.c index 0312035..24040b3 100644 --- a/src/comet2.c +++ b/src/comet2.c @@ -6,11 +6,12 @@ /* 指定されたファイルからCOMET II仮想メモリ(アセンブル結果)を読込 */ bool inassemble(char *file) { FILE *fp; + reset(); if((fp = fopen(file, "r")) == NULL) { perror(file); return false; } - fread(memory, sizeof(WORD), MEMSIZE, fp); + fread(memory, sizeof(WORD), memsize, fp); fclose(fp); return true; } @@ -20,6 +21,8 @@ static struct option longopts[] = { {"tracearithmetic", no_argument, NULL, 't'}, {"tracelogical", no_argument, NULL, 'T'}, {"dump", no_argument, NULL, 'd'}, + {"memsize", required_argument, NULL, 'M'}, + {"clocks", required_argument, NULL, 'C'}, {"help", no_argument, NULL, 'h'}, {0, 0, 0, 0} }; @@ -27,9 +30,9 @@ static struct option longopts[] = { int main(int argc, char *argv[]) { int opt; - const char *usage = "Usage: %s [-tTdh] FILE\n"; + const char *usage = "Usage: %s [-tTdh] [-M] [-C] FILE\n"; - while((opt = getopt_long(argc, argv, "tTdh", longopts, NULL)) != -1) { + while((opt = getopt_long(argc, argv, "tTdM:C:h", longopts, NULL)) != -1) { switch(opt) { case 't': tracemode = true; @@ -41,6 +44,12 @@ int main(int argc, char *argv[]) case 'd': dumpmode = true; break; + case 'M': + memsize = atoi(optarg); + break; + case 'C': + clocks = atoi(optarg); + break; case 'h': fprintf(stdout, usage, argv[0]); exit(-1); diff --git a/src/exec.c b/src/exec.c index 19be801..25d6c38 100644 --- a/src/exec.c +++ b/src/exec.c @@ -17,7 +17,7 @@ void svcin() --i; break; } - if(GR[1] + i >= MEMSIZE - 1) { + if(GR[1] + i >= memsize - 1) { setcerr(202, NULL); /* SVC input - out of Input memory */ break; } @@ -33,7 +33,7 @@ void svcout() char c; for(i = 0; i < GR[2]; i++) { - if(GR[1] + i >= MEMSIZE - 1) { + if(GR[1] + i >= memsize - 1) { setcerr(203, NULL); /* SVC output - out of Comet II memory */ return; } @@ -255,7 +255,8 @@ void reset() GR[i] = 0x0; } SP = PR = FR = 0x0; - for(i = 0; i < MEMSIZE; i++) { + memory = malloc(memsize); + for(i = 0; i < memsize; i++) { memory[i] = 0x0; } } @@ -273,7 +274,7 @@ void exec() } /* フラグレジスタの初期値設定 */ FR = 0x0; - SP = MEMSIZE; + SP = memsize; PR = startptr; if(create_code_type() == false) { goto execerr; @@ -282,10 +283,15 @@ void exec() for (; ; ) { clock_begin = clock(); /* プログラムレジスタのアドレスが主記憶の範囲外の場合はエラー */ - if(PR >= MEMSIZE) { + if(PR >= memsize) { sprintf(errpr, "PR:#%04X", PR); setcerr(204, errpr); /* Program Register (PR) - out of COMET II memory */ } + /* スタック領域のアドレスが主記憶の範囲外の場合はエラー */ + if(SP > memsize) { + sprintf(errpr, "PR:#%04X", PR); + setcerr(207, errpr); /* Stack Pointer (SP) - out of COMET II memory */ + } /* スタック領域を確保できない場合はエラー */ if(SP <= endptr) { sprintf(errpr, "PR:#%04X", PR); @@ -325,7 +331,7 @@ void exec() } /* ロード/算術論理演算命令/比較演算命令では、アドレスに格納されている内容を取得 */ if(cmdtype == R_ADR_X_) { - if(val >= MEMSIZE) { + if(val >= memsize) { sprintf(errpr, "PR:#%04X", PR-1); setcerr(206, errpr); /* Address - out of COMET II memory */ goto execerr; @@ -419,18 +425,21 @@ void exec() } break; case 0x7000: /* PUSH */ + assert(SP > endptr && SP <= memsize); memory[--SP] = val; break; case 0x7100: /* POP */ + assert(SP > endptr && SP <= memsize); GR[r_r1] = memory[SP++]; break; case 0x8000: /* CALL */ + assert(SP > endptr && SP <= memsize); memory[--SP] = PR; PR = val; break; case 0x8100: /* RET */ - assert(SP > endptr && SP <= MEMSIZE); - if(SP == MEMSIZE) { + assert(SP > endptr && SP <= memsize); + if(SP == memsize) { return; } else { PR = memory[SP++]; @@ -453,7 +462,8 @@ void exec() } do { clock_end = clock(); - } while(clock_end - clock_begin < CLOCKS_PER_SEC / CLOCKS); + } while(clock_end - clock_begin < CLOCKS_PER_SEC / clocks); +/* printf("PR:%04X; time: %f\n", PR, (double)((clock_end - clock_begin) * CLOCKS_PER_SEC)); */ } execerr: fprintf(stderr, "Execute error - %d: %s\n", cerrno, cerrmsg); diff --git a/src/struct.c b/src/struct.c index dc1f358..7f6fd41 100644 --- a/src/struct.c +++ b/src/struct.c @@ -1,7 +1,7 @@ #include "casl2.h" /* COMET IIのメモリ */ -WORD memory[MEMSIZE]; +WORD *memory; /* COMET IIのCPUレジスタ */ WORD GR[REGSIZE], SP, PR, FR; @@ -13,7 +13,7 @@ char *cerrmsg; /* レジストリの内容を表示する場合はtrue */ bool tracemode = false; -/* レジストリの内容を論理値(0〜65535)で表示する場合はTRUE */ +/* レジストリの内容を論理値(0〜65535)で表示する場合はtrue */ bool logicalmode = false; /* メモリの内容を表示する場合はtrue */ @@ -25,12 +25,21 @@ bool srcmode = false; /* ラベル表を表示する場合はtrue */ bool labelmode = false; +/* ラベル表を表示して終了する場合はtrue */ +bool onlylabelmode = false; + /* アセンブラ詳細結果を表示する場合はtrue */ bool asdetailmode = false; /* アセンブルだけを行う場合はtrue */ bool onlyassemblemode = false; +/* メモリーサイズ */ +int memsize = DEFAULT_MEMSIZE; + +/* クロック周波数 */ +int clocks = DEFAULT_CLOCKS; + /* 実行開始番地 */ WORD startptr = 0x0; -- 2.18.0