1 #define EXTERN 2 #include "a.h" 3 #include "y.tab.h" 4 #include <ctype.h> 5 6 void 7 main(int argc, char *argv[]) 8 { 9 char *p; 10 int nout, nproc, status, i, c; 11 12 thechar = '0'; 13 thestring = "spim"; 14 memset(debug, 0, sizeof(debug)); 15 cinit(); 16 outfile = 0; 17 include[ninclude++] = "."; 18 ARGBEGIN { 19 default: 20 c = ARGC(); 21 if(c >= 0 || c < sizeof(debug)) 22 debug[c] = 1; 23 break; 24 25 case 'o': 26 outfile = ARGF(); 27 break; 28 29 case 'D': 30 p = ARGF(); 31 if(p) 32 Dlist[nDlist++] = p; 33 break; 34 35 case 'I': 36 p = ARGF(); 37 setinclude(p); 38 break; 39 } ARGEND 40 if(*argv == 0) { 41 print("usage: %ca [-options] file.s\n", thechar); 42 errorexit(); 43 } 44 if(argc > 1 && systemtype(Windows)) { 45 print("can't assemble multiple files on windows\n"); 46 errorexit(); 47 } 48 if(argc > 1 && !systemtype(Windows)) { 49 nproc = 1; 50 if(p = getenv("NPROC")) 51 nproc = atol(p); /* */ 52 c = 0; 53 nout = 0; 54 for(;;) { 55 while(nout < nproc && argc > 0) { 56 i = myfork(); 57 if(i < 0) { 58 i = mywait(&status); 59 if(i < 0) 60 errorexit(); 61 if(status) 62 c++; 63 nout--; 64 continue; 65 } 66 if(i == 0) { 67 print("%s:\n", *argv); 68 if(assemble(*argv)) 69 errorexit(); 70 exits(0); 71 } 72 nout++; 73 argc--; 74 argv++; 75 } 76 i = mywait(&status); 77 if(i < 0) { 78 if(c) 79 errorexit(); 80 exits(0); 81 } 82 if(status) 83 c++; 84 nout--; 85 } 86 } 87 if(assemble(argv[0])) 88 errorexit(); 89 exits(0); 90 } 91 92 int 93 assemble(char *file) 94 { 95 char ofile[100], incfile[20], *p; 96 int i, of; 97 98 strcpy(ofile, file); 99 p = utfrrune(ofile, '/'); 100 if(p) { 101 include[0] = ofile; 102 *p++ = 0; 103 } else 104 p = ofile; 105 if(outfile == 0) { 106 outfile = p; 107 if(outfile){ 108 p = utfrrune(outfile, '.'); 109 if(p) 110 if(p[1] == 's' && p[2] == 0) 111 p[0] = 0; 112 p = utfrune(outfile, 0); 113 p[0] = '.'; 114 p[1] = thechar; 115 p[2] = 0; 116 } else 117 outfile = "/dev/null"; 118 } 119 p = getenv("INCLUDE"); 120 if(p) { 121 setinclude(p); 122 } else { 123 if(systemtype(Plan9)) { 124 sprint(incfile,"/%s/include", thestring); 125 setinclude(strdup(incfile)); 126 } 127 } 128 129 of = mycreat(outfile, 0664); 130 if(of < 0) { 131 yyerror("%ca: cannot create %s", thechar, outfile); 132 errorexit(); 133 } 134 Binit(&obuf, of, OWRITE); 135 136 pass = 1; 137 pinit(file); 138 for(i=0; i<nDlist; i++) 139 dodefine(Dlist[i]); 140 yyparse(); 141 if(nerrors) { 142 cclean(); 143 return nerrors; 144 } 145 146 pass = 2; 147 outhist(); 148 pinit(file); 149 for(i=0; i<nDlist; i++) 150 dodefine(Dlist[i]); 151 yyparse(); 152 cclean(); 153 return nerrors; 154 } 155 156 struct 157 { 158 char *name; 159 ushort type; 160 ushort value; 161 } itab[] = 162 { 163 "SP", LSP, D_AUTO, 164 "SB", LSB, D_EXTERN, 165 "FP", LFP, D_PARAM, 166 "PC", LPC, D_BRANCH, 167 "HI", LHI, D_HI, 168 "LO", LLO, D_LO, 169 170 "R", LR, 0, 171 "R0", LREG, 0, 172 "R1", LREG, 1, 173 "R2", LREG, 2, 174 "R3", LREG, 3, 175 "R4", LREG, 4, 176 "R5", LREG, 5, 177 "R6", LREG, 6, 178 "R7", LREG, 7, 179 "R8", LREG, 8, 180 "R9", LREG, 9, 181 "R10", LREG, 10, 182 "R11", LREG, 11, 183 "R12", LREG, 12, 184 "R13", LREG, 13, 185 "R14", LREG, 14, 186 "R15", LREG, 15, 187 "R16", LREG, 16, 188 "R17", LREG, 17, 189 "R18", LREG, 18, 190 "R19", LREG, 19, 191 "R20", LREG, 20, 192 "R21", LREG, 21, 193 "R22", LREG, 22, 194 "R23", LREG, 23, 195 "R24", LREG, 24, 196 "R25", LREG, 25, 197 "R26", LREG, 26, 198 "R27", LREG, 27, 199 "R28", LREG, 28, 200 "R29", LREG, 29, 201 "R30", LREG, 30, 202 "R31", LREG, 31, 203 204 "M", LM, 0, 205 "M0", LMREG, 0, 206 "M1", LMREG, 1, 207 "M2", LMREG, 2, 208 "M3", LMREG, 3, 209 "M4", LMREG, 4, 210 "M5", LMREG, 5, 211 "M6", LMREG, 6, 212 "M7", LMREG, 7, 213 "M8", LMREG, 8, 214 "M9", LMREG, 9, 215 "M10", LMREG, 10, 216 "M11", LMREG, 11, 217 "M12", LMREG, 12, 218 "M13", LMREG, 13, 219 "M14", LMREG, 14, 220 "M15", LMREG, 15, 221 "M16", LMREG, 16, 222 "M17", LMREG, 17, 223 "M18", LMREG, 18, 224 "M19", LMREG, 19, 225 "M20", LMREG, 20, 226 "M21", LMREG, 21, 227 "M22", LMREG, 22, 228 "M23", LMREG, 23, 229 "M24", LMREG, 24, 230 "M25", LMREG, 25, 231 "M26", LMREG, 26, 232 "M27", LMREG, 27, 233 "M28", LMREG, 28, 234 "M29", LMREG, 29, 235 "M30", LMREG, 30, 236 "M31", LMREG, 31, 237 238 "F", LF, 0, 239 240 "F0", LFREG, 0, 241 "F1", LFREG, 1, 242 "F2", LFREG, 2, 243 "F3", LFREG, 3, 244 "F4", LFREG, 4, 245 "F5", LFREG, 5, 246 "F6", LFREG, 6, 247 "F7", LFREG, 7, 248 "F8", LFREG, 8, 249 "F9", LFREG, 9, 250 "F10", LFREG, 10, 251 "F11", LFREG, 11, 252 "F12", LFREG, 12, 253 "F13", LFREG, 13, 254 "F14", LFREG, 14, 255 "F15", LFREG, 15, 256 "F16", LFREG, 16, 257 "F17", LFREG, 17, 258 "F18", LFREG, 18, 259 "F19", LFREG, 19, 260 "F20", LFREG, 20, 261 "F21", LFREG, 21, 262 "F22", LFREG, 22, 263 "F23", LFREG, 23, 264 "F24", LFREG, 24, 265 "F25", LFREG, 25, 266 "F26", LFREG, 26, 267 "F27", LFREG, 27, 268 "F28", LFREG, 28, 269 "F29", LFREG, 29, 270 "F30", LFREG, 30, 271 "F31", LFREG, 31, 272 273 "FCR", LFCR, 0, 274 "FCR0", LFCREG, 0, 275 "FCR1", LFCREG, 1, 276 "FCR2", LFCREG, 2, 277 "FCR3", LFCREG, 3, 278 "FCR4", LFCREG, 4, 279 "FCR5", LFCREG, 5, 280 "FCR6", LFCREG, 6, 281 "FCR7", LFCREG, 7, 282 "FCR8", LFCREG, 8, 283 "FCR9", LFCREG, 9, 284 "FCR10", LFCREG, 10, 285 "FCR11", LFCREG, 11, 286 "FCR12", LFCREG, 12, 287 "FCR13", LFCREG, 13, 288 "FCR14", LFCREG, 14, 289 "FCR15", LFCREG, 15, 290 "FCR16", LFCREG, 16, 291 "FCR17", LFCREG, 17, 292 "FCR18", LFCREG, 18, 293 "FCR19", LFCREG, 19, 294 "FCR20", LFCREG, 20, 295 "FCR21", LFCREG, 21, 296 "FCR22", LFCREG, 22, 297 "FCR23", LFCREG, 23, 298 "FCR24", LFCREG, 24, 299 "FCR25", LFCREG, 25, 300 "FCR26", LFCREG, 26, 301 "FCR27", LFCREG, 27, 302 "FCR28", LFCREG, 28, 303 "FCR29", LFCREG, 29, 304 "FCR30", LFCREG, 30, 305 "FCR31", LFCREG, 31, 306 307 "ADD", LTYPE1, AADD, 308 "ADDU", LTYPE1, AADDU, 309 "SUB", LTYPE1, ASUB, /* converted to ADD(-) in loader */ 310 "SUBU", LTYPE1, ASUBU, 311 "SGT", LTYPE1, ASGT, 312 "SGTU", LTYPE1, ASGTU, 313 "AND", LTYPE1, AAND, 314 "OR", LTYPE1, AOR, 315 "XOR", LTYPE1, AXOR, 316 "SLL", LTYPE1, ASLL, 317 "SRL", LTYPE1, ASRL, 318 "SRA", LTYPE1, ASRA, 319 320 "ADDV", LTYPE1, AADDV, 321 "ADDVU", LTYPE1, AADDVU, 322 "SUBV", LTYPE1, ASUBV, /* converted to ADD(-) in loader */ 323 "SUBVU", LTYPE1, ASUBVU, 324 "SLLV", LTYPE1, ASLLV, 325 "SRLV", LTYPE1, ASRLV, 326 "SRAV", LTYPE1, ASRAV, 327 328 "NOR", LTYPE2, ANOR, 329 330 "MOVB", LTYPE3, AMOVB, 331 "MOVBU", LTYPE3, AMOVBU, 332 "MOVH", LTYPE3, AMOVH, 333 "MOVHU", LTYPE3, AMOVHU, 334 "MOVWL", LTYPE3, AMOVWL, 335 "MOVWR", LTYPE3, AMOVWR, 336 "MOVVL", LTYPE3, AMOVVL, 337 "MOVVR", LTYPE3, AMOVVR, 338 339 "BREAK", LTYPEJ, ABREAK, /* overloaded CACHE opcode */ 340 "END", LTYPE4, AEND, 341 "REM", LTYPE6, AREM, 342 "REMU", LTYPE6, AREMU, 343 "RET", LTYPE4, ARET, 344 "SYSCALL", LTYPE4, ASYSCALL, 345 "TLBP", LTYPE4, ATLBP, 346 "TLBR", LTYPE4, ATLBR, 347 "TLBWI", LTYPE4, ATLBWI, 348 "TLBWR", LTYPE4, ATLBWR, 349 350 "MOVW", LTYPE5, AMOVW, 351 "MOVV", LTYPE5, AMOVV, 352 "MOVD", LTYPE5, AMOVD, 353 "MOVF", LTYPE5, AMOVF, 354 355 "DIV", LTYPE6, ADIV, 356 "DIVU", LTYPE6, ADIVU, 357 "MUL", LTYPE6, AMUL, 358 "MULU", LTYPE6, AMULU, 359 "DIVV", LTYPE6, ADIVV, 360 "DIVVU", LTYPE6, ADIVVU, 361 "MULV", LTYPE6, AMULV, 362 "MULVU", LTYPE6, AMULVU, 363 364 "RFE", LTYPE7, ARFE, 365 "JMP", LTYPE7, AJMP, 366 367 "JAL", LTYPE8, AJAL, 368 369 "BEQ", LTYPE9, ABEQ, 370 "BNE", LTYPE9, ABNE, 371 372 "BGEZ", LTYPEA, ABGEZ, 373 "BGEZAL", LTYPEA, ABGEZAL, 374 "BGTZ", LTYPEA, ABGTZ, 375 "BLEZ", LTYPEA, ABLEZ, 376 "BLTZ", LTYPEA, ABLTZ, 377 "BLTZAL", LTYPEA, ABLTZAL, 378 379 "TEXT", LTYPEB, ATEXT, 380 "GLOBL", LTYPEB, AGLOBL, 381 382 "DATA", LTYPEC, ADATA, 383 384 "MOVDF", LTYPE5, AMOVDF, 385 "MOVDW", LTYPE5, AMOVDW, 386 "MOVFD", LTYPE5, AMOVFD, 387 "MOVFW", LTYPE5, AMOVFW, 388 "MOVWD", LTYPE5, AMOVWD, 389 "MOVWF", LTYPE5, AMOVWF, 390 391 "ABSD", LTYPED, AABSD, 392 "ABSF", LTYPED, AABSF, 393 "ABSW", LTYPED, AABSW, 394 "NEGD", LTYPED, ANEGD, 395 "NEGF", LTYPED, ANEGF, 396 "NEGW", LTYPED, ANEGW, 397 398 "CMPEQD", LTYPEF, ACMPEQD, 399 "CMPEQF", LTYPEF, ACMPEQF, 400 "CMPGED", LTYPEF, ACMPGED, 401 "CMPGEF", LTYPEF, ACMPGEF, 402 "CMPGTD", LTYPEF, ACMPGTD, 403 "CMPGTF", LTYPEF, ACMPGTF, 404 405 "ADDD", LTYPEE, AADDD, 406 "ADDF", LTYPEE, AADDF, 407 "ADDW", LTYPEE, AADDW, 408 "DIVD", LTYPEE, ADIVD, 409 "DIVF", LTYPEE, ADIVF, 410 "DIVW", LTYPEE, ADIVW, 411 "MULD", LTYPEE, AMULD, 412 "MULF", LTYPEE, AMULF, 413 "MULW", LTYPEE, AMULW, 414 "SUBD", LTYPEE, ASUBD, 415 "SUBF", LTYPEE, ASUBF, 416 "SUBW", LTYPEE, ASUBW, 417 418 "BFPT", LTYPEG, ABFPT, 419 "BFPF", LTYPEG, ABFPF, 420 421 "WORD", LTYPEH, AWORD, 422 "NOP", LTYPEI, ANOP, 423 "SCHED", LSCHED, 0, 424 "NOSCHED", LSCHED, 0x80, 425 0 426 }; 427 428 void 429 cinit(void) 430 { 431 Sym *s; 432 int i; 433 434 nullgen.sym = S; 435 nullgen.offset = 0; 436 nullgen.type = D_NONE; 437 nullgen.name = D_NONE; 438 nullgen.reg = NREG; 439 if(FPCHIP) 440 nullgen.dval = 0; 441 for(i=0; i<sizeof(nullgen.sval); i++) 442 nullgen.sval[i] = 0; 443 444 nerrors = 0; 445 iostack = I; 446 iofree = I; 447 peekc = IGN; 448 nhunk = 0; 449 for(i=0; i<NHASH; i++) 450 hash[i] = S; 451 for(i=0; itab[i].name; i++) { 452 s = slookup(itab[i].name); 453 s->type = itab[i].type; 454 s->value = itab[i].value; 455 } 456 457 pathname = alloc(100); 458 if(mygetwd(pathname, 99) == 0) { 459 pathname = allocn(pathname, 100, 900); 460 if(mygetwd(pathname, 999) == 0) 461 strcpy(pathname, "/?"); 462 } 463 } 464 465 void 466 syminit(Sym *s) 467 { 468 469 s->type = LNAME; 470 s->value = 0; 471 } 472 473 int 474 isreg(Gen *g) 475 { 476 477 USED(g); 478 return 1; 479 } 480 481 void 482 cclean(void) 483 { 484 485 outcode(AEND, &nullgen, NREG, &nullgen); 486 Bflush(&obuf); 487 } 488 489 void 490 zname(char *n, int t, int s) 491 { 492 493 Bputc(&obuf, ANAME); 494 Bputc(&obuf, t); /* type */ 495 Bputc(&obuf, s); /* sym */ 496 while(*n) { 497 Bputc(&obuf, *n); 498 n++; 499 } 500 Bputc(&obuf, 0); 501 } 502 503 void 504 zaddr(Gen *a, int s) 505 { 506 long l; 507 int i; 508 char *n; 509 Ieee e; 510 511 Bputc(&obuf, a->type); 512 Bputc(&obuf, a->reg); 513 Bputc(&obuf, s); 514 Bputc(&obuf, a->name); 515 switch(a->type) { 516 default: 517 print("unknown type %d\n", a->type); 518 exits("arg"); 519 520 case D_NONE: 521 case D_REG: 522 case D_FREG: 523 case D_MREG: 524 case D_FCREG: 525 case D_LO: 526 case D_HI: 527 break; 528 529 case D_OREG: 530 case D_CONST: 531 case D_OCONST: 532 case D_BRANCH: 533 l = a->offset; 534 Bputc(&obuf, l); 535 Bputc(&obuf, l>>8); 536 Bputc(&obuf, l>>16); 537 Bputc(&obuf, l>>24); 538 break; 539 540 case D_SCONST: 541 n = a->sval; 542 for(i=0; i<NSNAME; i++) { 543 Bputc(&obuf, *n); 544 n++; 545 } 546 break; 547 548 case D_FCONST: 549 ieeedtod(&e, a->dval); 550 Bputc(&obuf, e.l); 551 Bputc(&obuf, e.l>>8); 552 Bputc(&obuf, e.l>>16); 553 Bputc(&obuf, e.l>>24); 554 Bputc(&obuf, e.h); 555 Bputc(&obuf, e.h>>8); 556 Bputc(&obuf, e.h>>16); 557 Bputc(&obuf, e.h>>24); 558 break; 559 } 560 } 561 562 void 563 outcode(int a, Gen *g1, int reg, Gen *g2) 564 { 565 int sf, st, t; 566 Sym *s; 567 568 if(pass == 1) 569 goto out; 570 jackpot: 571 sf = 0; 572 s = g1->sym; 573 while(s != S) { 574 sf = s->sym; 575 if(sf < 0 || sf >= NSYM) 576 sf = 0; 577 t = g1->name; 578 if(h[sf].type == t) 579 if(h[sf].sym == s) 580 break; 581 zname(s->name, t, sym); 582 s->sym = sym; 583 h[sym].sym = s; 584 h[sym].type = t; 585 sf = sym; 586 sym++; 587 if(sym >= NSYM) 588 sym = 1; 589 break; 590 } 591 st = 0; 592 s = g2->sym; 593 while(s != S) { 594 st = s->sym; 595 if(st < 0 || st >= NSYM) 596 st = 0; 597 t = g2->name; 598 if(h[st].type == t) 599 if(h[st].sym == s) 600 break; 601 zname(s->name, t, sym); 602 s->sym = sym; 603 h[sym].sym = s; 604 h[sym].type = t; 605 st = sym; 606 sym++; 607 if(sym >= NSYM) 608 sym = 1; 609 if(st == sf) 610 goto jackpot; 611 break; 612 } 613 Bputc(&obuf, a); 614 Bputc(&obuf, reg|nosched); 615 Bputc(&obuf, lineno); 616 Bputc(&obuf, lineno>>8); 617 Bputc(&obuf, lineno>>16); 618 Bputc(&obuf, lineno>>24); 619 zaddr(g1, sf); 620 zaddr(g2, st); 621 622 out: 623 if(a != AGLOBL && a != ADATA) 624 pc++; 625 } 626 627 void 628 outhist(void) 629 { 630 Gen g; 631 Hist *h; 632 char *p, *q, *op, c; 633 int n; 634 635 g = nullgen; 636 c = pathchar(); 637 for(h = hist; h != H; h = h->link) { 638 p = h->name; 639 op = 0; 640 /* on windows skip drive specifier in pathname */ 641 if(systemtype(Windows) && p && p[1] == ':'){ 642 p += 2; 643 c = *p; 644 } 645 if(p && p[0] != c && h->offset == 0 && pathname){ 646 /* on windows skip drive specifier in pathname */ 647 if(systemtype(Windows) && pathname[1] == ':') { 648 op = p; 649 p = pathname+2; 650 c = *p; 651 } else if(pathname[0] == c){ 652 op = p; 653 p = pathname; 654 } 655 } 656 while(p) { 657 q = strchr(p, c); 658 if(q) { 659 n = q-p; 660 if(n == 0){ 661 n = 1; /* leading "/" */ 662 *p = '/'; /* don't emit "\" on windows */ 663 } 664 q++; 665 } else { 666 n = strlen(p); 667 q = 0; 668 } 669 if(n) { 670 Bputc(&obuf, ANAME); 671 Bputc(&obuf, D_FILE); /* type */ 672 Bputc(&obuf, 1); /* sym */ 673 Bputc(&obuf, '<'); 674 Bwrite(&obuf, p, n); 675 Bputc(&obuf, 0); 676 } 677 p = q; 678 if(p == 0 && op) { 679 p = op; 680 op = 0; 681 } 682 } 683 g.offset = h->offset; 684 685 Bputc(&obuf, AHISTORY); 686 Bputc(&obuf, 0); 687 Bputc(&obuf, h->line); 688 Bputc(&obuf, h->line>>8); 689 Bputc(&obuf, h->line>>16); 690 Bputc(&obuf, h->line>>24); 691 zaddr(&nullgen, 0); 692 zaddr(&g, 0); 693 } 694 } 695 696 #include "../cc/lexbody" 697 #include "../cc/macbody" 698