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

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