/* 他のプログラムで参照する入口名 */
char *prog;
-/* æ±\8eç\94¨ã\83¬ã\82¸ã\82¹ã\82¿ã\82\92表ã\81\99æ\96\87å\97å\88\97ã\80\8cGR[0-7]ã\80\8dã\82\92WORDå\80¤ã\81«å¤\89æ\8f\9b
- is_xがtrueの場合は、指標レジスタとして用いる汎用レジスタ
- 文字列が汎用レジスタを表さない場合は、0xFFFFを返す */
+/* æ±\8eç\94¨ã\83¬ã\82¸ã\82¹ã\82¿ã\82\92表ã\81\99æ\96\87å\97å\88\97ã\80\8cGR[0-7]ã\80\8dã\81\8bã\82\89ã\80\81ã\83¬ã\82¸ã\82¹ã\82¿ç\95ªå\8f·[0-7]ã\82\92WORDå\80¤ã\81§è¿\94ã\81\99 */
+/* 文字列が汎用レジスタを表さない場合は、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;
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, prog)) == 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 */
+ 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;
/* リテラルには、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;
}
/* 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);
}
}
}
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, prog)) == 0xFFFF) {
+ if(pass == SECOND && (adr = getlabel(prog, str)) == 0xFFFF) {
setcerr(103, str); /* label not found */
}
}
}
}
-/* 命令がアセンブラ命令の場合は処理を実行
- 実行に成功した場合はtrue、それ以外の場合はfalseを返す */
+/* 命令がアセンブラ命令の場合は処理を実行 */
+/* 実行に成功した場合はtrue、それ以外の場合はfalseを返す */
bool assemblecmd(const CMDLINE *cmdl, PASS pass)
{
int i = 0;
prog = strdup(cmdl->label);
/* オペランドがある場合、実行開始番地を設定 */
if(pass == SECOND && cmdl->opd->opdc == 1) {
- if((startptr = getlabel(cmdl->opd->opdv[0], prog)) == 0xFFFF) {
+ if((startptr = getlabel(prog, cmdl->opd->opdv[0])) == 0xFFFF) {
setcerr(103, cmdl->opd->opdv[0]); /* label not found */
}
}
return status;
}
-/* 命令がマクロ命令の場合はメモリに書込
- 書込に成功した場合はtrue、それ以外の場合はfalseを返す */
+/* 命令がマクロ命令の場合はメモリに書込 */
+/* 書込に成功した場合はtrue、それ以外の場合はfalseを返す */
bool macrocmd(const CMDLINE *cmdl, PASS pass)
{
int i = 0;
return status;
}
-
-/* 機械語命令の書込
- 書込に成功した場合はtrue、それ以外の場合はfalseを返す */
+/* 機械語命令の書込 */
+/* 書込に成功した場合はtrue、それ以外の場合はfalseを返す */
bool cometcmd(const CMDLINE *cmdl, PASS pass)
{
WORD cmd, adr, r1, r2, x;
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;
}
/* オペランド数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)
{
}
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) {
}
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) {
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) {