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規格では、未定義 */
};
/* ハッシュ値を取得する */
typedef unsigned short WORD;
/* COMET IIのメモリ */
-extern WORD memory[MEMSIZE];
+extern WORD *memory;
/* COMET IIのCPUレジスタ */
extern WORD GR[REGSIZE], SP, PR, FR;
/* ラベル表を表示する場合は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;
{
bool status = false;
/* COMET IIメモリオーバーの場合 */
- if(adr >= MEMSIZE) {
+ if(adr >= memsize) {
setcerr(119, wtoa(adr)); /* out of COMET II memory */
}
if(cerrno == 0) {
void writeDC(const char *str, PASS pass)
{
WORD adr = 0x0;
- if(*str == '\''){
+ if(*str == '\'') {
writestr(str, false, pass);
} else {
if(*str == '#') {
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 */
}
/* オペランド数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;
}
}
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[])
bool status = false;
WORD beginptr[argc];
char *objfile = NULL;
- const char *usage = "Usage: %s [-tTdslaAh] [-o <OUTFILE>] FILE ...\n";
+ const char *default_objfile = "a.o";
+ const char *usage = "Usage: %s [-slLaAtTdh] [-oO<OUTFILE>] [-M <memsize>] [-C <clocks>] 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]);
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++) {
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(); /* プログラム実行 */
}
}
{ 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値を文字列に変換 */
/* 指定されたファイルから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;
}
{"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}
};
int main(int argc, char *argv[])
{
int opt;
- const char *usage = "Usage: %s [-tTdh] FILE\n";
+ const char *usage = "Usage: %s [-tTdh] [-M<memsize>] [-C<clocks>] 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;
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);
--i;
break;
}
- if(GR[1] + i >= MEMSIZE - 1) {
+ if(GR[1] + i >= memsize - 1) {
setcerr(202, NULL); /* SVC input - out of Input memory */
break;
}
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;
}
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;
}
}
}
/* フラグレジスタの初期値設定 */
FR = 0x0;
- SP = MEMSIZE;
+ SP = memsize;
PR = startptr;
if(create_code_type() == false) {
goto execerr;
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);
}
/* ロード/算術論理演算命令/比較演算命令では、アドレスに格納されている内容を取得 */
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;
}
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++];
}
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);
#include "casl2.h"
/* COMET IIのメモリ */
-WORD memory[MEMSIZE];
+WORD *memory;
/* COMET IIのCPUレジスタ */
WORD GR[REGSIZE], SP, PR, FR;
/* レジストリの内容を表示する場合はtrue */
bool tracemode = false;
-/* レジストリの内容を論理値(0〜65535)で表示する場合はTRUE */
+/* レジストリの内容を論理値(0〜65535)で表示する場合はtrue */
bool logicalmode = false;
/* メモリの内容を表示する場合はtrue */
/* ラベル表を表示する場合は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;