X-Git-Url: http://j8takagi.net/cgi-bin/gitweb.cgi?p=YACASL2.git;a=blobdiff_plain;f=src%2Fassemble.c;h=36edd2bf783cb67c94f70330f2a70bb7f9456060;hp=3549c610fa6a0121a22697a7378d4aa6b2d35f04;hb=f958640f07ddce6100e7eed1504ecaf05f6c1f02;hpb=44cde08e6cf148928a219593c78a57abfd89b424 diff --git a/src/assemble.c b/src/assemble.c index 3549c61..36edd2b 100644 --- a/src/assemble.c +++ b/src/assemble.c @@ -7,20 +7,24 @@ WORD ptr; /* リテラル(=付きの値)を格納するポインタ */ WORD lptr; -/* 汎用レジスタを表す文字列「GR[0-7]」をWORD値に変換 - is_xがtrueの場合は、指標レジスタとして用いる汎用レジスタ - 文字列が汎用レジスタを表さない場合は、0xFFFFを返す */ +/* 他のプログラムで参照する入口名 */ +char *prog; + +/* 汎用レジスタを表す文字列「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は指標レジスタとして用いることはできない */ + /* 指標レジスタとして用いることはできない */ if(is_x == true && r == 0x0) { setcerr(120, NULL); /* GR0 in operand x */ return 0x0; @@ -28,76 +32,37 @@ 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進定数/アドレス定数が含まれる */ -WORD getadr(const char *str, PASS pass) +/* アドレスを返す */ +/* アドレスには、リテラル/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(str)) == 0xFFFF) { - setcerr(103, str); /* label not found */ + if(pass == SECOND && (adr = getlabel(prog, str)) == 0xFFFF) { + 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 */ + if(adr >= memsize) { + 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; @@ -109,19 +74,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; } @@ -130,21 +88,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); /* illegal string */ + 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); } } } @@ -153,15 +119,13 @@ 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 == '#') { - 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(str)) == 0xFFFF) { + if(pass == SECOND && (adr = getlabel(prog, str)) == 0xFFFF) { setcerr(103, str); /* label not found */ } } @@ -169,8 +133,8 @@ void writeDC(const char *str, PASS pass) } } -/* 命令がアセンブラ命令の場合は処理を実行 - 実行に成功した場合はtrue、それ以外の場合はfalseを返す */ +/* 命令がアセンブラ命令の場合は処理を実行 */ +/* 実行に成功した場合はtrue、それ以外の場合はfalseを返す */ bool assemblecmd(const CMDLINE *cmdl, PASS pass) { int i = 0; @@ -202,9 +166,11 @@ bool assemblecmd(const CMDLINE *cmdl, PASS pass) setcerr(107, NULL); /* no label in START */ return false; } - /* オペランドがある場合、実行開始番地を設定 */ + /* プログラム名の設定 */ + prog = strdup(cmdl->label); + /* オペランドがある場合、実行開始番地を設定 */ if(pass == SECOND && cmdl->opd->opdc == 1) { - if((startptr = getlabel(cmdl->opd->opdv[0])) == 0xFFFF) { + if((startptr = getlabel(prog, cmdl->opd->opdv[0])) == 0xFFFF) { setcerr(103, cmdl->opd->opdv[0]); /* label not found */ } } @@ -219,6 +185,7 @@ bool assemblecmd(const CMDLINE *cmdl, PASS pass) else if(pass == SECOND) { endptr = lptr; } + prog = NULL; status = true; break; case DS: @@ -248,8 +215,8 @@ bool assemblecmd(const CMDLINE *cmdl, PASS pass) return status; } -/* 命令がマクロ命令の場合はメモリに書込 - 書込に成功した場合はtrue、それ以外の場合はfalseを返す */ +/* 命令がマクロ命令の場合はメモリに書込 */ +/* 書込に成功した場合はtrue、それ以外の場合はfalseを返す */ bool macrocmd(const CMDLINE *cmdl, PASS pass) { int i = 0; @@ -293,9 +260,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; @@ -329,7 +295,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; @@ -337,8 +303,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) { @@ -349,11 +314,12 @@ 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; } - adr = getadr(cmdl->opd->opdv[1], pass); + adr = getadr(prog, cmdl->opd->opdv[1], pass); writememory(cmd, ptr++, pass); writememory(adr, ptr++, pass); if(cerrno == 0) { @@ -366,7 +332,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; } @@ -378,7 +344,15 @@ bool cometcmd(const CMDLINE *cmdl, PASS pass) } cmd |= x; } - adr = getadr(cmdl->opd->opdv[0], pass); + /* 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); writememory(adr, ptr++, pass); if(cerrno == 0) { @@ -430,7 +404,7 @@ bool assemble(const char *file, PASS pass) CMDLINE *cmdl; char *line; FILE *fp; - + if(create_cmdtype_code() == false) { return false; } @@ -445,12 +419,14 @@ bool assemble(const char *file, PASS pass) break; } lineno++; - if((pass == FIRST && srcmode == true) || (pass == SECOND && asdetailmode == true)) { - fprintf(stdout, "%s:%d:%s", file, lineno, line); + if((pass == FIRST && (&asmode)->src == true) || + (pass == SECOND && (&asmode)->asdetail == true)) + { + fprintf(stdout, "%s:%5d:%s", file, lineno, line); } if((cmdl = linetok(line)) != NULL) { if(pass == FIRST && cmdl->label != NULL) { - if(addlabel(cmdl->label, ptr) == false) { + if(addlabel(prog, cmdl->label, ptr) == false) { break; } }