CALL命令で、ローカルレベルも読み込めるように仕様変更
[YACASL2.git] / src / assemble.c
index 3b91398..15d991a 100644 (file)
@@ -7,6 +7,9 @@ WORD ptr;
 /* リテラル(=付きの値)を格納するポインタ */
 WORD lptr;
 
+/* 他のプログラムで参照する入口名 */
+char *prog;
+
 /* 汎用レジスタを表す文字列「GR[0-7]」をWORD値に変換
    is_xがtrueの場合は、指標レジスタとして用いる汎用レジスタ
    文字列が汎用レジスタを表さない場合は、0xFFFFを返す */
@@ -69,7 +72,7 @@ WORD gethex(const char *str)
 
 /* アドレスを返す
    アドレスには、リテラル/10進定数/16進定数/アドレス定数が含まれる */
-WORD getadr(const char *str, PASS pass)
+WORD getadr(const char *prog, const char *str, PASS pass)
 {
     WORD adr = 0x0;
     if(*str == '=') {
@@ -79,8 +82,10 @@ WORD getadr(const char *str, PASS pass)
     } else if(isdigit(*str) || *str == '-') {
         adr = getint(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;
@@ -161,7 +166,7 @@ void writeDC(const char *str, PASS pass)
         } else if(isdigit(*str) || *str == '-') {
             adr = getint(str);
         } else {
-            if(pass == SECOND && (adr = getlabel(str)) == 0xFFFF) {
+            if(pass == SECOND && (adr = getlabel(prog, str)) == 0xFFFF) {
                 setcerr(103, str);    /* label not found */
             }
         }
@@ -202,9 +207,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 +226,7 @@ bool assemblecmd(const CMDLINE *cmdl, PASS pass)
         else if(pass == SECOND) {
             endptr = lptr;
         }
+        prog = NULL;
         status = true;
         break;
     case DS:
@@ -293,7 +301,6 @@ bool macrocmd(const CMDLINE *cmdl, PASS pass)
     return status;
 }
 
-
 /* 機械語命令の書込
    書込に成功した場合はtrue、それ以外の場合はfalseを返す */
 bool cometcmd(const CMDLINE *cmdl, PASS pass)
@@ -329,7 +336,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;
@@ -353,7 +360,7 @@ bool cometcmd(const CMDLINE *cmdl, PASS pass)
                 }
                 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) {
@@ -378,7 +385,14 @@ bool cometcmd(const CMDLINE *cmdl, PASS pass)
             }
             cmd |= x;
         }
-        adr = getadr(cmdl->opd->opdv[0], pass);
+        /* CALLの場合はプログラムの入口名を表すラベル、
+           それ以外の場合は同一プログラム内のラベルを取得 */
+        if(cmd == 0x8000) {        /* CALL命令 */
+            adr = getadr(NULL, cmdl->opd->opdv[0], pass);
+        }
+        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 +444,7 @@ bool assemble(const char *file, PASS pass)
     CMDLINE *cmdl;
     char *line;
     FILE *fp;
-    
+
     if(create_cmdtype_code() == false) {
         return false;
     }
@@ -446,11 +460,11 @@ bool assemble(const char *file, PASS pass)
         }
         lineno++;
         if((pass == FIRST && srcmode == true) || (pass == SECOND && asdetailmode == true)) {
-            fprintf(stdout, "%s:%d:%s", file, lineno, line);
+            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;
                 }
             }