root/src/assemble.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. printline
  2. getadr
  3. grword
  4. getliteral
  5. writememory
  6. writestr
  7. writedc
  8. assemble_start
  9. assemble_end
  10. assemble_ds
  11. assemble_dc
  12. assemble_in
  13. assemble_out
  14. assemble_rpush
  15. assemble_rpop
  16. casl2cmd
  17. assemble_comet2cmd
  18. assembletok
  19. assembleline
  20. assemblefile
  21. assemble
  22. addcerrlist_assemble
  23. outassemble

   1 #include "assemble.h"
   2 
   3 /**
   4  * @brief ファイルストリームの現在行を番号付きで表示する
   5  *
   6  * @return なし
   7  *
   8  * @param *stream ファイルストリーム
   9  * @param *filename ファイル名
  10  * @param lineno 行番号
  11  * @param line 行の文字列
  12  */
  13 void printline(FILE *stream, const char *filename, int lineno, char *line);
  14 
  15 /**
  16  * @brief アドレスを返す
  17  *
  18  * アドレスには、リテラル/10進定数/16進定数/アドレス定数が含まれる
  19  *
  20  * @return アドレス
  21  *
  22  * @param *prog プログラム名
  23  * @param *str アドレスを表す文字列
  24  * @param pass アセンブラが何回目かを表す数
  25  */
  26 WORD getadr(const char *prog, const char *str, PASS pass);
  27 
  28 /**
  29  * @brief 汎用レジスタを表す文字列からレジスタ番号を返す
  30  *
  31  * @brief 文字列が汎用レジスタを表さない場合は、0xFFFFを返す
  32  *
  33  * is_xがtrueの場合は指標レジスタとなり、GR0が指定された場合はCOMET IIの仕様によりエラー発生
  34  *
  35  * @return レジスタ番号[0-7]を表すWORD値
  36  *
  37  * @param *str 汎用レジスタを表す文字列。「GR0」「GR1」・・・「GR7」のいずれか
  38  * @param is_x trueの場合は指標レジスタ
  39  */
  40 WORD grword(const char *str, bool is_x);
  41 
  42 /**
  43  * @brief リテラルを返す
  44  *
  45  * リテラルには、10進定数/16進定数/文字定数が含まれる
  46  *
  47  * @param *str リテラル。定数の前に等号(=)をつけて記述される
  48  * @param pass アセンブラが何回目かを表す数
  49  */
  50 WORD getliteral(const char *str, PASS pass);
  51 
  52 /**
  53  * @brief アドレス値をメモリに書き込む
  54  *
  55  * @return なし
  56  *
  57  * @param word アドレス値
  58  * @param adr アドレス
  59  * @param pass アセンブラが何回目かを表す数
  60  */
  61 void writememory(WORD word, WORD adr, PASS pass);
  62 
  63 /**
  64  * @brief 文字をメモリに書き込む
  65  *
  66  * @return なし
  67  *
  68  * @param *str アドレスを表す文字列。リテラル/10進定数/16進定数/アドレス定数が含まれる
  69  * @param literal リテラルの場合はtrue
  70  * @param pass アセンブラが何回目かを表す数
  71  */
  72 void writestr(const char *str, bool literal, PASS pass);
  73 
  74 /**
  75  * @brief DC命令を書込
  76  *
  77  * @return なし
  78  *
  79  * @param str アドレスを表す文字列。10進定数/16進定数/アドレス定数が含まれる
  80  * @param pass アセンブラが何回目かを表す数
  81  */
  82 void writedc(const char *str, PASS pass);
  83 
  84 /**
  85  * @brief アセンブラ命令STARTの処理
  86  * @relatesalso Casl2cmd
  87  *
  88  * @return なし
  89  *
  90  * @param *cmdl 1行分のラベル・コマンド・オペランド
  91  * @param pass アセンブラが何回目かを表す数
  92  */
  93 void assemble_start(const CMDLINE *cmdl, PASS pass);
  94 
  95 /**
  96  * @brief アセンブラ命令DSの処理
  97  * @relatesalso Casl2cmd
  98  *
  99  * @return なし
 100  *
 101  * @param *cmdl 1行分のラベル・コマンド・オペランド
 102  * @param pass アセンブラが何回目かを表す数
 103  */
 104 void assemble_ds(const CMDLINE *cmdl, PASS pass);
 105 
 106 /**
 107  * @brief アセンブラ命令ENDの処理
 108  * @relatesalso Casl2cmd
 109  *
 110  * @return なし
 111  *
 112  * @param *cmdl 1行分のラベル・コマンド・オペランド
 113  * @param pass アセンブラが何回目かを表す数
 114  */
 115 void assemble_end(const CMDLINE *cmdl, PASS pass);
 116 
 117 /**
 118  * @brief アセンブラ命令DCの処理
 119  * @relatesalso Casl2cmd
 120  *
 121  * @return なし
 122  *
 123  * @param *cmdl 1行分のラベル・コマンド・オペランド
 124  * @param pass アセンブラが何回目かを表す数
 125  */
 126 void assemble_dc(const CMDLINE *cmdl, PASS pass);
 127 
 128 /**
 129  * @brief マクロ命令 "IN IBUF,LEN" をアセンブル
 130  *
 131  * @code
 132  *      PUSH 0,GR1
 133  *      PUSH 0,GR2
 134  *      LAD GR1,IBUF
 135  *      LAD GR2,LEN
 136  *      SVC 1
 137  *      POP GR2
 138  *      POP GR1
 139  * @endcode
 140  * @relatesalso Casl2cmd
 141  *
 142  *
 143  * @return なし
 144  *
 145  * @param *cmdl 1行分のラベル・コマンド・オペランド
 146  * @param pass アセンブラが何回目かを表す数
 147  */
 148 void assemble_in(const CMDLINE *cmdl, PASS pass);
 149 
 150 /**
 151  * @brief マクロ命令 "OUT OBUF,LEN" をアセンブル
 152  *
 153  * @code
 154  *      PUSH 0,GR1
 155  *      PUSH 0,GR2
 156  *      LAD GR1,OBUF
 157  *      LAD GR2,LEN
 158  *      SVC 2
 159  *      LAD GR1,=#A
 160  *      LAD GR2,=1
 161  *      SVC 2
 162  *      POP GR2
 163  *      POP GR1
 164  * @endcode
 165  * @relatesalso Casl2cmd
 166  *
 167  * @return なし
 168  *
 169  * @param *cmdl 1行分のラベル・コマンド・オペランド
 170  * @param pass アセンブラが何回目かを表す数
 171  */
 172 void assemble_out(const CMDLINE *cmdl, PASS pass);
 173 
 174 /**
 175  * @brief マクロ命令 "RPUSH" をメモリに書き込む
 176  *
 177  * @code
 178  *       PUSH 0,GR1
 179  *       PUSH 0,GR2
 180  *       PUSH 0,GR3
 181  *       PUSH 0,GR4
 182  *       PUSH 0,GR5
 183  *       PUSH 0,GR6
 184  *       PUSH 0,GR7
 185  * @endcode
 186  * @relatesalso Casl2cmd
 187  *
 188  * @return なし
 189  *
 190  * @param *cmdl 1行分のラベル・コマンド・オペランド
 191  * @param pass アセンブラが何回目かを表す数
 192  */
 193 void assemble_rpush(const CMDLINE *cmdl, PASS pass);
 194 
 195 /**
 196  * @brief マクロ命令 "RPOP" をメモリに書き込む
 197  *
 198  * @code
 199  *      POP GR7
 200  *      POP GR6
 201  *      POP GR5
 202  *      POP GR4
 203  *      POP GR3
 204  *      POP GR3
 205  *      POP GR2
 206  *      POP GR1
 207  * @endcode
 208  * @relatesalso Casl2cmd
 209  *
 210  * @return なし
 211  *
 212  * @param *cmdl 1行分のラベル・コマンド・オペランド
 213  * @param pass アセンブラが何回目かを表す数
 214  */
 215 void assemble_rpop(const CMDLINE *cmdl, PASS pass);
 216 
 217 /**
 218  * @class Casl2cmd
 219  * @brief casl2cmdから関数ポインタで呼び出される関数
 220  */
 221 
 222 /**
 223  * @brief アセンブラ言語CASL IIの命令を処理する。
 224  *
 225  * エラー発生時は、cerrを設定
 226  *
 227  * @relatesalso Casl2cmd
 228  *
 229  * @return 命令が表で定義されている場合はtrue、それ以外の場合はfalseを返す
 230  *
 231  * @param *cmdtbl アセンブラ言語CASL IIの命令表
 232  * @param *cmdl 1行分のラベル・コマンド・オペランド
 233  * @param pass アセンブルが何回目か
 234  */
 235 bool casl2cmd(CMD *cmdtbl, const CMDLINE *cmdl, PASS pass);
 236 
 237 /**
 238  * @brief システムCOMET IIの命令をアセンブルする
 239  *
 240  * @return アセンブル成功時はtrue、失敗時はfalseを返す
 241  *
 242  * @param *cmdl 1行分のラベル・コマンド・オペランド
 243  * @param pass アセンブルが何回目か
 244  */
 245 bool assemble_comet2cmd(const CMDLINE *cmdl, PASS pass);
 246 
 247 /**
 248  * @brief トークンをアセンブルする
 249  *
 250  * @return アセンブル成功時はtrue、失敗時はfalseを返す
 251  *
 252  * @param *cmdl 1行分のラベル・コマンド・オペランド
 253  * @param pass アセンブラが何回目かを表す数
 254  */
 255 bool assembletok(const CMDLINE *cmdl, PASS pass);
 256 
 257 /**
 258  * @brief 1行をアセンブルする
 259  *
 260  * passが1の場合はラベルを登録し、2の場合はラベルからアドレスを読み込む
 261  *
 262  * @return アセンブル成功時はtrue、失敗時はfalseを返す
 263  *
 264  * @param *line 1行分の文字列
 265  * @param pass アセンブラが何回目かを表す数
 266  */
 267 bool assembleline(const char *line, PASS pass);
 268 
 269 /**
 270  * @brief アセンブルのエラー
 271  */
 272 static CERR cerr_assemble[] = {
 273     { 106, "operand mismatch in CASL II command" },
 274     { 107, "no label in START" },
 275     { 108, "not command of operand \"r\"" },
 276     { 109, "not command of operand \"r1,r2\"" },
 277     { 110, "not command of operand \"r,adr[,x]\"" },
 278     { 111, "not command of operand \"adr[,x]\"" },
 279     { 112, "not command of no operand" },
 280     { 113, "operand too many in COMET II command" },
 281     { 119, "out of COMET II memory" },
 282     { 120, "GR0 in operand x" },
 283     { 122, "cannot create hash table" },
 284     { 124, "more than one character in literal" },
 285     { 125, "not GR in operand x" },
 286 };
 287 
 288 /**
 289  * @brief アセンブラ命令
 290  */
 291 static CMD ascmd[] = {
 292     { "START", assemble_start },
 293     { "END", assemble_end },
 294     { "DS", assemble_ds },
 295     { "DC", assemble_dc },
 296     { "", NULL }
 297 };
 298 
 299 /**
 300  * @brief マクロ命令
 301  */
 302 static CMD macrocmd[] = {
 303     { "OUT", assemble_out },
 304     { "IN", assemble_in },
 305     { "RPUSH", assemble_rpush },
 306     { "RPOP", assemble_rpop },
 307     { "", NULL }
 308 };
 309 
 310 ASPTR *asptr = NULL;
 311 
 312 ASMODE asmode = {false, false, false, false, false};
 313 
 314 void printline(FILE *stream, const char *filename, int lineno, char *line)
 315 {
 316     fprintf(stream, "%s:%5d:%s", filename, lineno, line);
 317 }
 318 
 319 WORD getadr(const char *prog, const char *str, PASS pass)
 320 {
 321     WORD adr = 0;
 322 
 323     if(str[0] == '=') {
 324         adr = getliteral(str, pass);
 325     } else if(isdigit(str[0]) || str[0] == '-' || str[0] == '#') {
 326         adr = nh2word(str);
 327     } else {
 328         if(pass == SECOND) {
 329             if((adr = getlabel(prog, str)) == 0xFFFF) {
 330                 setcerr(103, str);    /* label not found */
 331             }
 332         }
 333     }
 334     return adr;
 335 }
 336 
 337 WORD grword(const char *str, bool is_x)
 338 {
 339     WORD r = 0;
 340 
 341     /*  "GR[0-7]" 以外の文字列では、0xFFFFを返して終了 */
 342     if(strlen(str) != 3 ||
 343        strncmp(str, "GR", 2) != 0 ||
 344        str[2] < '0' || str[2] > '0' + (GRSIZE - 1))
 345     {
 346         return 0xFFFF;
 347     }
 348     r = (WORD)(str[2] - '0');
 349     /* GR0は指標レジスタとして用いることができない */
 350     if(is_x == true && r == 0x0) {
 351         setcerr(120, "");    /* GR0 in operand x */
 352         return 0;
 353     }
 354     return r;
 355 }
 356 
 357 WORD getliteral(const char *str, PASS pass)
 358 {
 359     assert(str[0] == '=');
 360     WORD adr = asptr->lptr;
 361 
 362     str++;
 363     if(str[0] == '\'') {    /* 文字定数 */
 364         writestr(str, true, pass);
 365     } else {
 366         writememory(nh2word(str), (asptr->lptr)++, pass);
 367     }
 368     return adr;
 369 }
 370 
 371 void writememory(WORD word, WORD adr, PASS pass)
 372 {
 373     char *n = NULL;
 374 
 375     /* メモリオーバーの場合、エラー発生 */
 376     if(adr >= sys->memsize) {
 377         setcerr(119, (n = word2n(adr)));    /* out of COMET II memory */
 378         FREE(n)
 379         return;
 380     }
 381     (sys->memory)[adr] = word;
 382     if(pass == SECOND && asmode.asdetail == true) {
 383         fprintf(stdout, "\t#%04X\t#%04X\n", adr, word);
 384     }
 385 }
 386 
 387 void writestr(const char *str, bool literal, PASS pass)
 388 {
 389     assert(str[0] == '\'');
 390     bool lw = false;
 391 
 392     /* 「'」の場合、1文字スキップし、次の文字が「'」でなければ正常終了 */
 393     for(int i = 1; str[i] != '\'' || str[++i] == '\''; i++) {
 394         /* 「'」が閉じないまま文字列が終了した場合はエラー */
 395         if(!str[i]) {
 396             setcerr(123, str);    /* unclosed quote */
 397             break;
 398         }
 399         if(literal == true && lw == true) {
 400             setcerr(124, str);    /* more than one character in literal */
 401             break;
 402         }
 403         /*リテラルの場合はリテラル領域に書込 */
 404         if(literal == true) {
 405             writememory(str[i], (asptr->lptr)++, pass);
 406             lw = true;
 407         } else {
 408             writememory(str[i], (asptr->ptr)++, pass);
 409         }
 410     }
 411 }
 412 
 413 void writedc(const char *str, PASS pass)
 414 {
 415     WORD adr = 0;
 416 
 417     if(*str == '\'') {
 418         writestr(str, false, pass);
 419     } else {
 420         if(str[0] == '#' || isdigit(str[0]) || str[0] == '-') {
 421             adr = nh2word(str);
 422         } else {
 423             if(pass == SECOND && (adr = getlabel(asptr->prog, str)) == 0xFFFF) {
 424                 setcerr(103, str);    /* label not found */
 425             }
 426         }
 427         writememory(adr, (asptr->ptr)++, pass);
 428     }
 429 }
 430 
 431 void assemble_start(const CMDLINE *cmdl, PASS pass)
 432 {
 433     if(cmdl->opd->opdc > 1) {
 434         setcerr(106, "");    /* operand count mismatch */
 435         return;
 436     }
 437     if(!cmdl->label[0]) {
 438         setcerr(107, "");    /* no label in START */
 439         return;
 440     }
 441     /* プログラム名の設定 */
 442     strcpy(asptr->prog, cmdl->label);
 443     /* オペランドがある場合、書き込みと実行の開始アドレスを設定 */
 444     if(cmdl->opd->opdv[0] != NULL) {
 445         asptr->ptr = execptr->start = getadr(asptr->prog, cmdl->opd->opdv[0], pass);
 446     }
 447 }
 448 
 449 void assemble_end(const CMDLINE *cmdl, PASS pass)
 450 {
 451     if(cmdl->opd->opdc > 0) {
 452         setcerr(106, "");    /* operand count mismatch */
 453         return;
 454     }
 455     /* 1回目のアセンブルの場合は、リテラル領域開始アドレスを設定 */
 456     if(pass == FIRST) {
 457         asptr->lptr = asptr->ptr;
 458     }
 459     /* 2回目のアセンブルの場合は、リテラル領域終了アドレスを実行終了アドレスとして設定 */
 460     else if(pass == SECOND) {
 461         execptr->end = asptr->lptr;
 462     }
 463     strcpy(asptr->prog, "");
 464 }
 465 
 466 void assemble_ds(const CMDLINE *cmdl, PASS pass)
 467 {
 468     if(cmdl->opd->opdc != 1) {
 469         setcerr(106, "");    /* operand count mismatch */
 470         return;
 471     }
 472     for(int i = 0; i < atoi(cmdl->opd->opdv[0]); i++) {
 473         writememory(0x0, (asptr->ptr)++, pass);
 474         if(cerr->num > 0) {
 475             break;
 476         }
 477     }
 478 }
 479 
 480 void assemble_dc(const CMDLINE *cmdl, PASS pass)
 481 {
 482     if(cmdl->opd->opdc == 0 || cmdl->opd->opdc >= OPDSIZE) {
 483         setcerr(106, "");    /* operand count mismatch */
 484         return;
 485     }
 486     for(int i = 0; i < cmdl->opd->opdc; i++) {
 487         writedc(cmdl->opd->opdv[i], pass);
 488         if(cerr->num > 0) {
 489             break;
 490         }
 491     }
 492 }
 493 
 494 void assemble_in(const CMDLINE *cmdl, PASS pass)
 495 {
 496     char *line = malloc_chk(LINESIZE + 1, "assemble_in.line");
 497 
 498     if(cmdl->opd->opdc == 0 || cmdl->opd->opdc > 2) {
 499         setcerr(106, "");    /* operand count mismatch */
 500         return;
 501     }
 502     assembleline("    PUSH 0,GR1", pass);
 503     assembleline("    PUSH 0,GR2", pass);
 504     sprintf(line, "    LAD GR1,%s", cmdl->opd->opdv[0]);
 505     assembleline(line, pass);
 506     sprintf(line, "    LAD GR2,%s", cmdl->opd->opdv[1]);
 507     assembleline(line, pass);
 508     assembleline("    SVC 1", pass);
 509     assembleline("    POP GR2", pass);
 510     assembleline("    POP GR1", pass);
 511     FREE(line);
 512 }
 513 
 514 void assemble_out(const CMDLINE *cmdl, PASS pass)
 515 {
 516     char *line = malloc_chk(LINESIZE + 1, "assemble_out.line");
 517 
 518     if(cmdl->opd->opdc == 0 || cmdl->opd->opdc > 2) {
 519         setcerr(106, "");    /* operand count mismatch */
 520         return;
 521     }
 522     assembleline("    PUSH 0,GR1", pass);
 523     assembleline("    PUSH 0,GR2", pass);
 524     sprintf(line, "    LAD GR1,%s", cmdl->opd->opdv[0]);
 525     assembleline(line, pass);
 526     sprintf(line, "    LAD GR2,%s", cmdl->opd->opdv[1]);
 527     assembleline(line, pass);
 528     assembleline("    SVC 2", pass);
 529     assembleline("    LAD GR1,=#A", pass);
 530     assembleline("    LAD GR2,=1", pass);
 531     assembleline("    SVC 2", pass);
 532     assembleline("    POP GR2", pass);
 533     assembleline("    POP GR1", pass);
 534     FREE(line);
 535 }
 536 
 537 void assemble_rpush(const CMDLINE *cmdl, PASS pass)
 538 {
 539     char *line = malloc_chk(LINESIZE + 1, "assemble_rpush.line");
 540 
 541     if(cmdl->opd->opdc > 0) {
 542         setcerr(106, "");    /* operand count mismatch */
 543         return;
 544     }
 545     for(int i = 1; i <= GRSIZE-1; i++) {
 546         sprintf(line, "    PUSH 0,GR%d", i);
 547         assembleline(line, pass);
 548     }
 549     FREE(line);
 550 }
 551 
 552 void assemble_rpop(const CMDLINE *cmdl, PASS pass)
 553 {
 554     char *line = malloc_chk(LINESIZE + 1, "assemble_rpop.line");
 555 
 556     if(cmdl->opd->opdc > 0) {
 557         setcerr(106, "");    /* operand count mismatch */
 558         return;
 559     }
 560     for(int i = GRSIZE-1; i >= 1; i--) {
 561         sprintf(line, "    POP GR%d", i);
 562         assembleline(line, pass);
 563     }
 564     FREE(line);
 565 }
 566 
 567 bool casl2cmd(CMD *cmdtbl, const CMDLINE *cmdl, PASS pass)
 568 {
 569     void (*cmdptr)() = NULL;
 570 
 571     for(int i = 0; cmdtbl[i].name[0]; i++) {
 572         if(strcmp(cmdl->cmd, cmdtbl[i].name) == 0) {
 573             cmdptr = cmdtbl[i].ptr;
 574             (*cmdptr)(cmdl, pass);
 575             return true;
 576         }
 577     }
 578     return false;
 579 }
 580 
 581 bool assemble_comet2cmd(const CMDLINE *cmdl, PASS pass)
 582 {
 583     WORD cmd = 0;
 584     WORD r_r1 = 0;
 585     WORD x_r2 = 0;
 586     WORD adr = 0;
 587 
 588     /* オペランドなし */
 589     if(cmdl->opd->opdc == 0) {
 590         if((cmd = getcmdcode(cmdl->cmd, NONE)) == 0xFFFF) {
 591             setcerr(112, cmdl->cmd);    /* not command of no operand */
 592             return false;
 593         }
 594         writememory(cmd, (asptr->ptr)++, pass);
 595     }
 596     /* 第1オペランドは汎用レジスタ */
 597     else if((r_r1 = grword(cmdl->opd->opdv[0], false)) != 0xFFFF) {
 598         /* オペランド数1 */
 599         if(cmdl->opd->opdc == 1) {
 600             if((cmd = getcmdcode(cmdl->cmd, R_)) == 0xFFFF) {
 601                 setcerr(108, cmdl->cmd);    /* not command of operand "r" */
 602                 return false;
 603             }
 604             cmd |= (r_r1 << 4);
 605             writememory(cmd, (asptr->ptr)++, pass);
 606         }
 607         /* オペランド数2。第2オペランドは汎用レジスタ */
 608         else if(cmdl->opd->opdc == 2 && (x_r2 = grword(cmdl->opd->opdv[1], false)) != 0xFFFF) {
 609             if((cmd = getcmdcode(cmdl->cmd, R1_R2)) == 0xFFFF) {
 610                 setcerr(109, cmdl->cmd);    /* not command of operand "r1,r2" */
 611                 return false;
 612             }
 613             cmd |= ((r_r1 << 4) | x_r2);               /* 第1オペランド、第2オペランドともに汎用レジスタ */
 614             /* メモリへの書き込み */
 615             writememory(cmd, (asptr->ptr)++, pass);
 616         }
 617         /* オペランド数2または3 */
 618         else if(cmdl->opd->opdc == 2 || cmdl->opd->opdc == 3) {
 619             if((cmd = getcmdcode(cmdl->cmd, R_ADR_X)) == 0xFFFF) {
 620                 setcerr(110, cmdl->cmd);    /* not command of operand "r,adr[,x]" */
 621                 return false;
 622             }
 623             cmd |= (r_r1 << 4);                    /* 第1オペランドは汎用レジスタ */
 624             /* オペランド数3の場合 */
 625             if(cmdl->opd->opdc == 3) {             /* 第3オペランドは指標レジスタとして用いる汎用レジスタ */
 626                 if((x_r2 = grword(cmdl->opd->opdv[2], true)) == 0xFFFF) {
 627                     setcerr(125, cmdl->cmd);    /* not GR in operand x */
 628                     return false;
 629                 }
 630                 cmd |= x_r2;
 631             }
 632             adr = getadr(asptr->prog, cmdl->opd->opdv[1], pass); /* 第2オペランドはアドレス */
 633             /* メモリへの書き込み */
 634             writememory(cmd, (asptr->ptr)++, pass);
 635             writememory(adr, (asptr->ptr)++, pass);
 636         } else {
 637             setcerr(113, cmdl->cmd);    /* operand too many in COMET II command */
 638             return false;
 639         }
 640     }
 641     /* オペランド数1または2。第1オペランドはアドレス */
 642     else if(cmdl->opd->opdc == 1 || cmdl->opd->opdc == 2) {
 643         if((cmd = getcmdcode(cmdl->cmd, ADR_X)) == 0xFFFF) {
 644             setcerr(111, cmdl->cmd);    /* not command of operand "adr[,x]" */
 645             return false;
 646         }
 647         /* オペランド数2の場合 */
 648         if(cmdl->opd->opdc == 2) {             /* 第2オペランドは指標レジスタとして用いる汎用レジスタ */
 649             x_r2 = grword(cmdl->opd->opdv[1], true);
 650             if(cerr->num > 0) {
 651                 return false;
 652             }
 653             cmd |= x_r2;
 654         }
 655         /* CALLの場合はプログラムの入口名を表すラベルを取得 */
 656         /* CALL以外の命令の場合と、プログラムの入口名を取得できない場合は、 */
 657         /* 同一プログラム内のラベルを取得 */
 658         if(pass == SECOND && cmd == 0x8000) {        /* CALL命令 */
 659             adr = getlabel("", cmdl->opd->opdv[0]);
 660         }
 661         if(cmd != 0x8000 || (pass == SECOND && adr == 0xFFFF)) {
 662             adr = getadr(asptr->prog, cmdl->opd->opdv[0], pass);
 663         }
 664         /* メモリへの書込 */
 665         writememory(cmd, (asptr->ptr)++, pass);
 666         writememory(adr, (asptr->ptr)++, pass);
 667     }
 668     return (cerr->num == 0) ? true : false;
 669 }
 670 
 671 bool assembletok(const CMDLINE *cmdl, PASS pass)
 672 {
 673     /* 命令がない場合 */
 674     if(!cmdl->cmd[0]) {
 675         return true;
 676     }
 677     /* アセンブラ命令またはマクロ命令の書込 */
 678     if(casl2cmd(ascmd, cmdl, pass) == false && casl2cmd(macrocmd, cmdl, pass) == false) {
 679         /* 機械語命令の書込 */
 680         if(assemble_comet2cmd(cmdl, pass) == false) {
 681             if(cerr->num == 0) {
 682                 setcerr(113, cmdl->cmd);    /* operand too many in COMET II command */
 683             }
 684         }
 685     }
 686     return (cerr->num == 0) ? true : false;
 687 }
 688 
 689 bool assembleline(const char *line, PASS pass)
 690 {
 691     CMDLINE *cmdl = NULL;
 692     bool stat = true;
 693 
 694     cmdl = linetok(line);
 695     stat = (cerr->num == 0) ? true : false;
 696     if(cmdl != NULL) {
 697         if(stat == true) {
 698             if(pass == FIRST && cmdl->label[0]) {
 699                 stat = addlabel(asptr->prog, cmdl->label, asptr->ptr);
 700             }
 701         }
 702         if(stat == true) {
 703             stat = assembletok(cmdl, pass);
 704         }
 705         FREE(cmdl->label);
 706         if(cmdl->opd != NULL) {
 707             for(int i = 0; i < cmdl->opd->opdc; i++) {
 708                 FREE(cmdl->opd->opdv[i]);
 709             }
 710         }
 711         FREE(cmdl->opd);
 712         FREE(cmdl->cmd);
 713     }
 714     FREE(cmdl);
 715     return stat;
 716 }
 717 
 718 /**
 719  * @brief 指定された名前のファイルをアセンブル
 720  *
 721  * アセンブル完了時はtrue、エラー発生時はfalseを返す
 722  */
 723 bool assemblefile(const char *file, PASS pass)
 724 {
 725     int lineno = 1;
 726     char *line = NULL;
 727     FILE *fp = NULL;
 728 
 729     if((fp = fopen(file, "r")) == NULL) {
 730         cerr->num = errno;
 731         perror(file);
 732         return false;
 733     }
 734     for(line = malloc_chk(LINESIZE + 1, "assemble.line"); fgets(line, LINESIZE, fp); lineno++) {
 735         if((pass == FIRST && asmode.src == true) || (pass == SECOND && asmode.asdetail == true)) {
 736             printline(stdout, file, lineno, line);
 737         }
 738         if(assembleline(line, pass) == false) {
 739             break;
 740         }
 741     }
 742     if(cerr->num > 0) {
 743         fprintf(stderr, "Assemble error - %d: %s\n", cerr->num, cerr->msg);
 744         printline(stderr, file, lineno, line);
 745     }
 746     FREE(line);
 747     fclose(fp);
 748     return (cerr->num == 0) ? true : false;
 749 }
 750 
 751 bool assemble(int filec, char *filev[], WORD adr)
 752 {
 753     int i;
 754     PASS pass;
 755     WORD bp[filec];
 756     bool stat = false;
 757 
 758     asptr = malloc_chk(sizeof(ASPTR), "asptr");    /* アセンブル時のプロパティ用の領域確保 */
 759     asptr->prog = malloc_chk(LABELSIZE + 1, "asptr.prog");
 760     asptr->ptr = adr;
 761     /* アセンブル。ラベル表作成のため、2回行う */
 762     for(pass = FIRST; pass <= SECOND; pass++) {
 763         for(i = 0; i < filec; i++) {
 764             /* データの格納開始位置 */
 765             if(pass == FIRST) {
 766                 bp[i] = asptr->ptr;
 767             } else if(pass == SECOND) {
 768                 asptr->ptr = bp[i];
 769             }
 770             if(execmode.trace == true || execmode.dump == true ||
 771                asmode.src == true || asmode.label == true || asmode.asdetail == true)
 772             {
 773                 fprintf(stdout, "\nAssemble %s (%d)\n", filev[i], pass);
 774             }
 775             /* ファイルをアセンブル */
 776             stat = assemblefile(filev[i], pass);
 777             if(stat == false) {
 778                 goto asfin;
 779             }
 780         }
 781         if(pass == FIRST && asmode.label == true) {
 782             fprintf(stdout, "\nLabel::::\n");
 783             printlabel();
 784             if(asmode.onlylabel == true) {
 785                 break;
 786             }
 787         }
 788     }
 789 asfin:
 790     freelabel();                              /* ラベルハッシュ表を解放 */
 791     FREE(asptr->prog);                        /* アセンブル時のプロパティを解放 */
 792     FREE(asptr);
 793     return stat;
 794 }
 795 
 796 /* assemble.hで定義された関数群 */
 797 void addcerrlist_assemble()
 798 {
 799     addcerrlist_tok();
 800     addcerrlist_word();
 801     addcerrlist_label();
 802     addcerrlist(ARRAYSIZE(cerr_assemble), cerr_assemble);
 803 }
 804 
 805 void outassemble(const char *file)
 806 {
 807     FILE *fp = NULL;
 808 
 809     if((fp = fopen(file, "w")) == NULL) {
 810         perror(file);
 811         exit(1);
 812     }
 813     fwrite(sys->memory, sizeof(WORD), execptr->end, fp);
 814     fclose(fp);
 815 }

/* [<][>][^][v][top][bottom][index][help] */