X-Git-Url: http://j8takagi.net/cgi-bin/gitweb.cgi?p=YACASL2.git;a=blobdiff_plain;f=src%2Fassemble.c;h=ee8449d0b33cfb6fee5048529994b2f56a63c510;hp=bfd15e1feed986bf89c1ad8125e2f0b3b53c7e15;hb=b0f981469cdea23225ca5c3ef0ca6759d6a92b43;hpb=fda1563ea37180835e0b9c6e7a9c7ae607895446 diff --git a/src/assemble.c b/src/assemble.c index bfd15e1..ee8449d 100644 --- a/src/assemble.c +++ b/src/assemble.c @@ -1,6 +1,9 @@ #include "casl2.h" #include "assemble.h" +/* アセンブルモード: src, label, onlylabel, asdetail, onlyassemble */ +ASMODE asmode = {false, false, false, false, false}; + /* 値を格納するポインタ */ WORD ptr; @@ -10,20 +13,53 @@ WORD lptr; /* 他のプログラムで参照する入口名 */ char *prog; -/* 汎用レジスタを表す文字列「GR[0-7]」をWORD値に変換 - is_xがtrueの場合は、指標レジスタとして用いる汎用レジスタ - 文字列が汎用レジスタを表さない場合は、0xFFFFを返す */ + +/* アセンブルのエラー定義 */ +CERRARRAY cerr_assemble[] = { + { 101, "label already defined" }, + { 102, "label table is full" }, + { 103, "label not found" }, + { 104, "label length is too long" }, + { 105, "no command in the line" }, + { 106, "operand mismatch in assemble command" }, + { 107, "no label in START" }, + { 108, "not command of operand \"r\"" }, + { 109, "not command of operand \"r1,r2\"" }, + { 110, "not command of operand \"r,adr[,x]\"" }, + { 111, "not command of operand \"adr[,x]\"" }, + { 112, "not command of no operand" }, + { 113, "operand too many in COMET II command" }, + { 117, "operand too many in DC" }, + { 118, "operand length too long" }, + { 119, "out of COMET II memory" }, + { 120, "GR0 in operand x" }, + { 121, "cannot get operand token" }, + { 122, "cannot create hash table" }, + { 123, "unclosed quote" }, + { 124, "more than one character in literal" }, + { 125, "not GR in operand x" }, +}; + +bool addcerrlist_assemble() +{ + return addcerrlist(ARRAYSIZE(cerr_assemble), cerr_assemble); +} + +/* 汎用レジスタを表す文字列「GR[0-7]」から、レジスタ番号[0-7]をWORD値で返す */ +/* 文字列が汎用レジスタを表さない場合は、0xFFFFを返す */ +/* is_xがtrueの場合は指標レジスタ。GR0は、COMET IIの仕様により、エラー発生 */ WORD getgr(const char *str, bool is_x) { assert(str != NULL); WORD r; + /* 「GR[0-7]」以外の文字列では、0xFFFFを返して終了 */ if(!(strlen(str) == 3 && strncmp(str, "GR", 2) == 0 && (*(str+2) >= '0' && *(str+2) <= '7'))) { return 0xFFFF; } r = (WORD)(*(str+2) - '0'); - /* COMET IIの仕様により、GR0は指標レジスタとして用いることはできない */ + /* GR0は指標レジスタとして用いることができない */ if(is_x == true && r == 0x0) { setcerr(120, NULL); /* GR0 in operand x */ return 0x0; @@ -31,76 +67,38 @@ WORD getgr(const char *str, bool is_x) return r; } -/* 10進定数をWORD値に変換 */ -WORD getint(const char *str) -{ - assert(isdigit(*str) || *str == '-'); - char *check; - int n; - /* WORD値に変換 */ - n = strtol(str, &check, 10); - if(*check != '\0') { - setcerr(114, str); /* not integer */ - return 0x0; - } - /* nが-32768〜32767の範囲にないときは、その下位16ビットを格納 */ - if(n < -32768 || n > 32767) { - n = n % 32768; - } - return (WORD)n; -} - -/* 16進定数をWORD値に変換 */ -WORD gethex(const char *str) -{ - assert(*str == '#'); - WORD adr = 0x0; - char *check; - str++; - if(*str == '-' || strlen(str) > 4) { - setcerr(116, str-1); /* out of hex range */ - return 0; - } - /* WORD値に変換 */ - adr = (WORD)strtol(str, &check, 16); - if(*check != '\0') { - setcerr(115, str-1); /* not hex */ - return 0x0; - } - return adr; -} - -/* アドレスを返す - アドレスには、リテラル/10進定数/16進定数/アドレス定数が含まれる */ +/* アドレスを返す */ +/* アドレスには、リテラル/10進定数/16進定数/アドレス定数が含まれる */ WORD getadr(const char *prog, const char *str, PASS pass) { WORD adr = 0x0; if(*str == '=') { adr = getliteral(str, pass); - } else if(*str == '#') { - adr = gethex(str); - } else if(isdigit(*str) || *str == '-') { - adr = getint(str); + } else if((*str == '#') || isdigit(*str) || *str == '-') { + adr = nh2word(str); } else { if(pass == SECOND && (adr = getlabel(prog, str)) == 0xFFFF) { - setcerr(103, str); /* label not found */ + if(prog != NULL) { + setcerr(103, str); /* label not found */ + } } } return adr; } -/* WORD値wordをアドレスadrに書込 - 書込に成功した場合はtrue、失敗した場合はfalseを返す */ +/* WORD値wordをアドレスadrに書込 */ +/* 書込に成功した場合はtrue、失敗した場合はfalseを返す */ bool writememory(WORD word, WORD adr, PASS pass) { bool status = false; + /* COMET IIメモリオーバーの場合 */ if(adr >= memsize) { - setcerr(119, wtoa(adr)); /* out of COMET II memory */ + setcerr(119, word2n(adr)); /* out of COMET II memory */ } if(cerrno == 0) { memory[adr] = word; - if(pass == SECOND && asdetailmode == true) { + if(pass == SECOND && asmode.asdetail == true) { fprintf(stdout, "\t#%04X\t#%04X\n", adr, word); } status = true; @@ -112,19 +110,12 @@ bool writememory(WORD word, WORD adr, PASS pass) /* リテラルには、10進定数/16進定数/文字定数が含まれる */ WORD getliteral(const char *str, PASS pass) { - WORD adr = lptr, word = 0x0; + WORD adr = lptr; assert(*str == '='); - str++; - if(*str == '\'') { /* 文字定数 */ + if(*(++str) == '\'') { /* 文字定数 */ writestr(str, true, pass); } else { - if(*str == '#') { /* 16進定数 */ - word = gethex(str); - } else if(isdigit(*str) || *str == '-') { /* 10進定数 */ - word = getint(str); - } - /* リテラル領域に書込 */ - writememory(word, lptr++, pass); + writememory(nh2word(str), lptr++, pass); } return adr; } @@ -133,21 +124,29 @@ WORD getliteral(const char *str, PASS pass) /* DC命令とリテラルで使い、リテラルの場合はリテラル領域に書込 */ void writestr(const char *str, bool literal, PASS pass) { - assert(cerrno == 0); - assert(*str == '\''); - str++; - while(*str != '\0') { - if(*str == '\'') { - if(*(str+1) != '\'') { - break; - } - str++; + assert(cerrno == 0 && *str == '\''); + const char *p = str + 1; + bool lw = false; + + for(; ;) { + /* 閉じ「'」がないまま文字列が終了した場合 */ + if(*p == '\0') { + setcerr(123, str); /* unclosed quote */ + break; + } + /* 「'」の場合、次の文字が「'」でない場合は正常終了 */ + if(*p == '\'' && *(++p) != '\'') { + break; + } else if(literal == true && lw == true) { + setcerr(124, str); /* more than one character in literal */ + break; } /*リテラルの場合はリテラル領域に書込 */ if(literal == true) { - writememory(*(str++), lptr++, pass); + writememory(*(p++), lptr++, pass); + lw = true; } else { - writememory(*(str++), ptr++, pass); + writememory(*(p++), ptr++, pass); } } } @@ -159,10 +158,8 @@ void writeDC(const char *str, PASS pass) if(*str == '\'') { writestr(str, false, pass); } else { - if(*str == '#') { - adr = gethex(str); - } else if(isdigit(*str) || *str == '-') { - adr = getint(str); + if(*str == '#' || isdigit(*str) || *str == '-') { + adr = nh2word(str); } else { if(pass == SECOND && (adr = getlabel(prog, str)) == 0xFFFF) { setcerr(103, str); /* label not found */ @@ -172,8 +169,8 @@ void writeDC(const char *str, PASS pass) } } -/* 命令がアセンブラ命令の場合は処理を実行 - 実行に成功した場合はtrue、それ以外の場合はfalseを返す */ +/* 命令がアセンブラ命令の場合は処理を実行 */ +/* 実行に成功した場合はtrue、それ以外の場合はfalseを返す */ bool assemblecmd(const CMDLINE *cmdl, PASS pass) { int i = 0; @@ -182,7 +179,7 @@ bool assemblecmd(const CMDLINE *cmdl, PASS pass) CMDARRAY ascmd[] = { { START, 0, 1, "START" }, { END, 0, 0, "END" }, - { DC, 0, OPDSIZE, "DC" }, + { DC, 1, OPDSIZE, "DC" }, { DS, 1, 1, "DS" }, { 0, 0, 0, NULL } }; @@ -254,8 +251,8 @@ bool assemblecmd(const CMDLINE *cmdl, PASS pass) return status; } -/* 命令がマクロ命令の場合はメモリに書込 - 書込に成功した場合はtrue、それ以外の場合はfalseを返す */ +/* 命令がマクロ命令の場合はメモリに書込 */ +/* 書込に成功した場合はtrue、それ以外の場合はfalseを返す */ bool macrocmd(const CMDLINE *cmdl, PASS pass) { int i = 0; @@ -299,9 +296,8 @@ bool macrocmd(const CMDLINE *cmdl, PASS pass) return status; } - -/* 機械語命令の書込 - 書込に成功した場合はtrue、それ以外の場合はfalseを返す */ +/* 機械語命令の書込 */ +/* 書込に成功した場合はtrue、それ以外の場合はfalseを返す */ bool cometcmd(const CMDLINE *cmdl, PASS pass) { WORD cmd, adr, r1, r2, x; @@ -335,7 +331,7 @@ bool cometcmd(const CMDLINE *cmdl, PASS pass) if((cmd = getcmdcode(cmdl->cmd, R1_R2)) == 0xFFFF) { setcerr(109, cmdl->cmd); /* not command of operand "r1,r2" */ return false; - } + } cmd |= ((r1 << 4) | r2); if(cerrno == 0 && writememory(cmd, ptr++, pass) == true) { status = true; @@ -343,8 +339,7 @@ bool cometcmd(const CMDLINE *cmdl, PASS pass) } /* オペランド数2〜3。第2オペランドはアドレス、 第3オペランドは指標レジスタとして用いる汎用レジスタ */ - else if(cmdl->opd->opdc == 2 || cmdl->opd->opdc == 3) - { + else if(cmdl->opd->opdc == 2 || cmdl->opd->opdc == 3) { if((cmd = getcmdcode(cmdl->cmd, R_ADR_X_)) == 0xFFFF && (cmd = getcmdcode(cmdl->cmd, R_ADR_X)) == 0xFFFF) { @@ -355,6 +350,7 @@ bool cometcmd(const CMDLINE *cmdl, PASS pass) /* オペランド数3 */ if(cmdl->opd->opdc == 3) { if((x = getgr(cmdl->opd->opdv[2], true)) == 0xFFFF) { + setcerr(125, cmdl->cmd); /* not GR in operand x */ return false; } cmd |= x; @@ -366,7 +362,7 @@ bool cometcmd(const CMDLINE *cmdl, PASS pass) status = true; } } else { - setcerr(113, cmdl->cmd); /* command not defined */ + setcerr(113, cmdl->cmd); /* operand too many in COMET II command */ return false; } } @@ -384,11 +380,13 @@ bool cometcmd(const CMDLINE *cmdl, PASS pass) } cmd |= x; } - /* CALLの場合はプログラムの入口名を表すラベル、 - それ以外の場合は同一プログラム内のラベルを取得 */ - if(cmd == 0x8000) { /* CALL命令 */ - adr = getadr(NULL, cmdl->opd->opdv[0], pass); - } else { + /* CALLの場合はプログラムの入口名を表すラベルを取得 */ + /* CALL以外の命令の場合と、プログラムの入口名を取得できない場合は、 */ + /* 同一プログラム内のラベルを取得 */ + if(pass == SECOND && cmd == 0x8000) { /* CALL命令 */ + adr = getlabel(NULL, cmdl->opd->opdv[0]); + } + if(cmd != 0x8000 || (pass == SECOND && adr == 0xFFFF)) { adr = getadr(prog, cmdl->opd->opdv[0], pass); } writememory(cmd, ptr++, pass); @@ -424,7 +422,7 @@ bool assembleline(const CMDLINE *cmdl, PASS pass) ; } else if(cerrno == 0) { - setcerr(113, cmdl->cmd); /* command not defined */ + setcerr(113, cmdl->cmd); /* operand too many in COMET II command */ } /* エラーが発生していないか確認 */ if(cerrno == 0) { @@ -433,6 +431,10 @@ bool assembleline(const CMDLINE *cmdl, PASS pass) return status; } +void printline(FILE *stream, const char *filename, int lineno, char *line) { + fprintf(stream, "%s:%5d:%s", filename, lineno, line); +} + /* 指定された名前のファイルをアセンブル */ /* 2回実行される */ bool assemble(const char *file, PASS pass) @@ -443,22 +445,22 @@ bool assemble(const char *file, PASS pass) char *line; FILE *fp; - if(create_cmdtype_code() == false) { - return false; - } + addcerrlist_assemble(); if((fp = fopen(file, "r")) == NULL) { perror(file); return false; } for(; ;) { cmdl = malloc(sizeof(CMDLINE)); - line = malloc(LINESIZE+1); + line = malloc(LINESIZE + 1); if((line = fgets(line, LINESIZE, fp)) == NULL) { break; } lineno++; - if((pass == FIRST && srcmode == true) || (pass == SECOND && asdetailmode == true)) { - fprintf(stdout, "%s:%5d:%s", file, lineno, line); + if((pass == FIRST && asmode.src == true) || + (pass == SECOND && asmode.asdetail == true)) + { + printline(stdout, file, lineno, line); } if((cmdl = linetok(line)) != NULL) { if(pass == FIRST && cmdl->label != NULL) { @@ -475,7 +477,8 @@ bool assemble(const char *file, PASS pass) } } if(cerrno > 0) { - fprintf(stderr, "Assemble error - %d: %s\n %s:%d: %s\n", cerrno, cerrmsg, file, lineno, line); + fprintf(stderr, "Assemble error - %d: %s\n", cerrno, cerrmsg); + printline(stderr, file, lineno, line); status = false; } fclose(fp);