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 = '5'; 13 thestring = "arm"; 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 case 't': 40 thechar = 't'; 41 thestring = "thumb"; 42 break; 43 } ARGEND 44 if(*argv == 0) { 45 print("usage: %ca [-options] file.s\n", thechar); 46 errorexit(); 47 } 48 if(argc > 1 && systemtype(Windows)){ 49 print("can't assemble multiple files on windows\n"); 50 errorexit(); 51 } 52 if(argc > 1 && !systemtype(Windows)) { 53 nproc = 1; 54 if(p = getenv("NPROC")) 55 nproc = atol(p); /* */ 56 c = 0; 57 nout = 0; 58 for(;;) { 59 while(nout < nproc && argc > 0) { 60 i = myfork(); 61 if(i < 0) { 62 i = mywait(&status); 63 if(i < 0) 64 errorexit(); 65 if(status) 66 c++; 67 nout--; 68 continue; 69 } 70 if(i == 0) { 71 print("%s:\n", *argv); 72 if(assemble(*argv)) 73 errorexit(); 74 exits(0); 75 } 76 nout++; 77 argc--; 78 argv++; 79 } 80 i = mywait(&status); 81 if(i < 0) { 82 if(c) 83 errorexit(); 84 exits(0); 85 } 86 if(status) 87 c++; 88 nout--; 89 } 90 } 91 if(assemble(argv[0])) 92 errorexit(); 93 exits(0); 94 } 95 96 int 97 assemble(char *file) 98 { 99 char ofile[100], incfile[20], *p; 100 int i, of; 101 102 strcpy(ofile, file); 103 p = utfrrune(ofile, pathchar()); 104 if(p) { 105 include[0] = ofile; 106 *p++ = 0; 107 } else 108 p = ofile; 109 if(outfile == 0) { 110 outfile = p; 111 if(outfile){ 112 p = utfrrune(outfile, '.'); 113 if(p) 114 if(p[1] == 's' && p[2] == 0) 115 p[0] = 0; 116 p = utfrune(outfile, 0); 117 p[0] = '.'; 118 p[1] = thechar; 119 p[2] = 0; 120 } else 121 outfile = "/dev/null"; 122 } 123 p = getenv("INCLUDE"); 124 if(p) { 125 setinclude(p); 126 } else { 127 if(systemtype(Plan9)) { 128 sprint(incfile,"/%s/include", thestring); 129 setinclude(strdup(incfile)); 130 } 131 } 132 133 of = mycreat(outfile, 0664); 134 if(of < 0) { 135 yyerror("%ca: cannot create %s", thechar, outfile); 136 errorexit(); 137 } 138 Binit(&obuf, of, OWRITE); 139 140 pass = 1; 141 pinit(file); 142 for(i=0; i<nDlist; i++) 143 dodefine(Dlist[i]); 144 yyparse(); 145 if(nerrors) { 146 cclean(); 147 return nerrors; 148 } 149 150 pass = 2; 151 outhist(); 152 pinit(file); 153 for(i=0; i<nDlist; i++) 154 dodefine(Dlist[i]); 155 yyparse(); 156 cclean(); 157 return nerrors; 158 } 159 160 struct 161 { 162 char *name; 163 ushort type; 164 ushort value; 165 } itab[] = 166 { 167 "SP", LSP, D_AUTO, 168 "SB", LSB, D_EXTERN, 169 "FP", LFP, D_PARAM, 170 "PC", LPC, D_BRANCH, 171 172 "R", LR, 0, 173 "R0", LREG, 0, 174 "R1", LREG, 1, 175 "R2", LREG, 2, 176 "R3", LREG, 3, 177 "R4", LREG, 4, 178 "R5", LREG, 5, 179 "R6", LREG, 6, 180 "R7", LREG, 7, 181 "R8", LREG, 8, 182 "R9", LREG, 9, 183 "R10", LREG, 10, 184 "R11", LREG, 11, 185 "R12", LREG, 12, 186 "R13", LREG, 13, 187 "R14", LREG, 14, 188 "R15", LREG, 15, 189 190 "F", LF, 0, 191 192 "F0", LFREG, 0, 193 "F1", LFREG, 1, 194 "F2", LFREG, 2, 195 "F3", LFREG, 3, 196 "F4", LFREG, 4, 197 "F5", LFREG, 5, 198 "F6", LFREG, 6, 199 "F7", LFREG, 7, 200 "F8", LFREG, 8, 201 "F9", LFREG, 9, 202 "F10", LFREG, 10, 203 "F11", LFREG, 11, 204 "F12", LFREG, 12, 205 "F13", LFREG, 13, 206 "F14", LFREG, 14, 207 "F15", LFREG, 15, 208 209 "C", LC, 0, 210 211 "C0", LCREG, 0, 212 "C1", LCREG, 1, 213 "C2", LCREG, 2, 214 "C3", LCREG, 3, 215 "C4", LCREG, 4, 216 "C5", LCREG, 5, 217 "C6", LCREG, 6, 218 "C7", LCREG, 7, 219 "C8", LCREG, 8, 220 "C9", LCREG, 9, 221 "C10", LCREG, 10, 222 "C11", LCREG, 11, 223 "C12", LCREG, 12, 224 "C13", LCREG, 13, 225 "C14", LCREG, 14, 226 "C15", LCREG, 15, 227 228 "CPSR", LPSR, 0, 229 "SPSR", LPSR, 1, 230 231 "FPSR", LFCR, 0, 232 "FPCR", LFCR, 1, 233 234 ".EQ", LCOND, 0, 235 ".NE", LCOND, 1, 236 ".CS", LCOND, 2, 237 ".HS", LCOND, 2, 238 ".CC", LCOND, 3, 239 ".LO", LCOND, 3, 240 ".MI", LCOND, 4, 241 ".PL", LCOND, 5, 242 ".VS", LCOND, 6, 243 ".VC", LCOND, 7, 244 ".HI", LCOND, 8, 245 ".LS", LCOND, 9, 246 ".GE", LCOND, 10, 247 ".LT", LCOND, 11, 248 ".GT", LCOND, 12, 249 ".LE", LCOND, 13, 250 ".AL", LCOND, Always, 251 252 ".U", LS, C_UBIT, 253 ".S", LS, C_SBIT, 254 ".W", LS, C_WBIT, 255 ".P", LS, C_PBIT, 256 ".PW", LS, C_WBIT|C_PBIT, 257 ".WP", LS, C_WBIT|C_PBIT, 258 259 ".F", LS, C_FBIT, 260 261 ".IBW", LS, C_WBIT|C_PBIT|C_UBIT, 262 ".IAW", LS, C_WBIT|C_UBIT, 263 ".DBW", LS, C_WBIT|C_PBIT, 264 ".DAW", LS, C_WBIT, 265 ".IB", LS, C_PBIT|C_UBIT, 266 ".IA", LS, C_UBIT, 267 ".DB", LS, C_PBIT, 268 ".DA", LS, 0, 269 270 "@", LAT, 0, 271 272 "AND", LTYPE1, AAND, 273 "EOR", LTYPE1, AEOR, 274 "SUB", LTYPE1, ASUB, 275 "RSB", LTYPE1, ARSB, 276 "ADD", LTYPE1, AADD, 277 "ADC", LTYPE1, AADC, 278 "SBC", LTYPE1, ASBC, 279 "RSC", LTYPE1, ARSC, 280 "ORR", LTYPE1, AORR, 281 "BIC", LTYPE1, ABIC, 282 283 "SLL", LTYPE1, ASLL, 284 "SRL", LTYPE1, ASRL, 285 "SRA", LTYPE1, ASRA, 286 287 "MUL", LTYPE1, AMUL, 288 "MULA", LTYPEN, AMULA, 289 "DIV", LTYPE1, ADIV, 290 "MOD", LTYPE1, AMOD, 291 292 "MULL", LTYPEM, AMULL, 293 "MULAL", LTYPEM, AMULAL, 294 "MULLU", LTYPEM, AMULLU, 295 "MULALU", LTYPEM, AMULALU, 296 297 "MVN", LTYPE2, AMVN, /* op2 ignored */ 298 299 "MOVB", LTYPE3, AMOVB, 300 "MOVBU", LTYPE3, AMOVBU, 301 "MOVH", LTYPE3, AMOVH, 302 "MOVHU", LTYPE3, AMOVHU, 303 "MOVW", LTYPE3, AMOVW, 304 305 "MOVD", LTYPE3, AMOVD, 306 "MOVDF", LTYPE3, AMOVDF, 307 "MOVDW", LTYPE3, AMOVDW, 308 "MOVF", LTYPE3, AMOVF, 309 "MOVFD", LTYPE3, AMOVFD, 310 "MOVFW", LTYPE3, AMOVFW, 311 "MOVWD", LTYPE3, AMOVWD, 312 "MOVWF", LTYPE3, AMOVWF, 313 314 "LDREX", LTYPE3, ALDREX, 315 "LDREXD", LTYPE3, ALDREXD, 316 "STREX", LTYPE9, ASTREX, 317 "STREXD", LTYPE9, ASTREXD, 318 319 /* 320 "ABSF", LTYPEI, AABSF, 321 "ABSD", LTYPEI, AABSD, 322 "NEGF", LTYPEI, ANEGF, 323 "NEGD", LTYPEI, ANEGD, 324 "SQTF", LTYPEI, ASQTF, 325 "SQTD", LTYPEI, ASQTD, 326 "RNDF", LTYPEI, ARNDF, 327 "RNDD", LTYPEI, ARNDD, 328 "URDF", LTYPEI, AURDF, 329 "URDD", LTYPEI, AURDD, 330 "NRMF", LTYPEI, ANRMF, 331 "NRMD", LTYPEI, ANRMD, 332 */ 333 334 "SQRTF", LTYPEI, ASQRTF, 335 "SQRTD", LTYPEI, ASQRTD, 336 "CMPF", LTYPEL, ACMPF, 337 "CMPD", LTYPEL, ACMPD, 338 "ADDF", LTYPEK, AADDF, 339 "ADDD", LTYPEK, AADDD, 340 "SUBF", LTYPEK, ASUBF, 341 "SUBD", LTYPEK, ASUBD, 342 "MULF", LTYPEK, AMULF, 343 "MULD", LTYPEK, AMULD, 344 "DIVF", LTYPEK, ADIVF, 345 "DIVD", LTYPEK, ADIVD, 346 347 "B", LTYPE4, AB, 348 "BL", LTYPE4, ABL, 349 "BX", LTYPEBX, ABX, 350 351 "BEQ", LTYPE5, ABEQ, 352 "BNE", LTYPE5, ABNE, 353 "BCS", LTYPE5, ABCS, 354 "BHS", LTYPE5, ABHS, 355 "BCC", LTYPE5, ABCC, 356 "BLO", LTYPE5, ABLO, 357 "BMI", LTYPE5, ABMI, 358 "BPL", LTYPE5, ABPL, 359 "BVS", LTYPE5, ABVS, 360 "BVC", LTYPE5, ABVC, 361 "BHI", LTYPE5, ABHI, 362 "BLS", LTYPE5, ABLS, 363 "BGE", LTYPE5, ABGE, 364 "BLT", LTYPE5, ABLT, 365 "BGT", LTYPE5, ABGT, 366 "BLE", LTYPE5, ABLE, 367 "BCASE", LTYPE5, ABCASE, 368 369 "SWI", LTYPE6, ASWI, 370 371 "CMP", LTYPE7, ACMP, 372 "TST", LTYPE7, ATST, 373 "TEQ", LTYPE7, ATEQ, 374 "CMN", LTYPE7, ACMN, 375 376 "MOVM", LTYPE8, AMOVM, 377 378 "SWPBU", LTYPE9, ASWPBU, 379 "SWPW", LTYPE9, ASWPW, 380 381 "RET", LTYPEA, ARET, 382 "RFE", LTYPEA, ARFE, 383 384 "TEXT", LTYPEB, ATEXT, 385 "GLOBL", LTYPEB, AGLOBL, 386 "DATA", LTYPEC, ADATA, 387 "CASE", LTYPED, ACASE, 388 "END", LTYPEE, AEND, 389 "WORD", LTYPEH, AWORD, 390 "NOP", LTYPEI, ANOP, 391 392 "MCR", LTYPEJ, 0, 393 "MRC", LTYPEJ, 1, 394 0 395 }; 396 397 void 398 cinit(void) 399 { 400 Sym *s; 401 int i; 402 403 nullgen.sym = S; 404 nullgen.offset = 0; 405 nullgen.type = D_NONE; 406 nullgen.name = D_NONE; 407 nullgen.reg = NREG; 408 if(FPCHIP) 409 nullgen.dval = 0; 410 for(i=0; i<sizeof(nullgen.sval); i++) 411 nullgen.sval[i] = 0; 412 413 nerrors = 0; 414 iostack = I; 415 iofree = I; 416 peekc = IGN; 417 nhunk = 0; 418 for(i=0; i<NHASH; i++) 419 hash[i] = S; 420 for(i=0; itab[i].name; i++) { 421 s = slookup(itab[i].name); 422 s->type = itab[i].type; 423 s->value = itab[i].value; 424 } 425 426 pathname = allocn(pathname, 0, 100); 427 if(getwd(pathname, 99) == 0) { 428 pathname = allocn(pathname, 100, 900); 429 if(getwd(pathname, 999) == 0) 430 strcpy(pathname, "/?"); 431 } 432 } 433 434 void 435 syminit(Sym *s) 436 { 437 438 s->type = LNAME; 439 s->value = 0; 440 } 441 442 int 443 isreg(Gen *g) 444 { 445 446 USED(g); 447 return 1; 448 } 449 450 void 451 cclean(void) 452 { 453 454 outcode(AEND, Always, &nullgen, NREG, &nullgen); 455 Bflush(&obuf); 456 } 457 458 void 459 zname(char *n, int t, int s) 460 { 461 462 Bputc(&obuf, ANAME); 463 Bputc(&obuf, t); /* type */ 464 Bputc(&obuf, s); /* sym */ 465 while(*n) { 466 Bputc(&obuf, *n); 467 n++; 468 } 469 Bputc(&obuf, 0); 470 } 471 472 void 473 zaddr(Gen *a, int s) 474 { 475 long l; 476 int i; 477 char *n; 478 Ieee e; 479 480 Bputc(&obuf, a->type); 481 Bputc(&obuf, a->reg); 482 Bputc(&obuf, s); 483 Bputc(&obuf, a->name); 484 switch(a->type) { 485 default: 486 print("unknown type %d\n", a->type); 487 exits("arg"); 488 489 case D_NONE: 490 case D_REG: 491 case D_FREG: 492 case D_PSR: 493 case D_FPCR: 494 break; 495 496 case D_REGREG: 497 Bputc(&obuf, a->offset); 498 break; 499 500 case D_OREG: 501 case D_CONST: 502 case D_BRANCH: 503 case D_SHIFT: 504 l = a->offset; 505 Bputc(&obuf, l); 506 Bputc(&obuf, l>>8); 507 Bputc(&obuf, l>>16); 508 Bputc(&obuf, l>>24); 509 break; 510 511 case D_SCONST: 512 n = a->sval; 513 for(i=0; i<NSNAME; i++) { 514 Bputc(&obuf, *n); 515 n++; 516 } 517 break; 518 519 case D_FCONST: 520 ieeedtod(&e, a->dval); 521 Bputc(&obuf, e.l); 522 Bputc(&obuf, e.l>>8); 523 Bputc(&obuf, e.l>>16); 524 Bputc(&obuf, e.l>>24); 525 Bputc(&obuf, e.h); 526 Bputc(&obuf, e.h>>8); 527 Bputc(&obuf, e.h>>16); 528 Bputc(&obuf, e.h>>24); 529 break; 530 } 531 } 532 533 static int bcode[] = 534 { 535 ABEQ, 536 ABNE, 537 ABCS, 538 ABCC, 539 ABMI, 540 ABPL, 541 ABVS, 542 ABVC, 543 ABHI, 544 ABLS, 545 ABGE, 546 ABLT, 547 ABGT, 548 ABLE, 549 AB, 550 ANOP, 551 }; 552 553 void 554 outcode(int a, int scond, Gen *g1, int reg, Gen *g2) 555 { 556 int sf, st, t; 557 Sym *s; 558 559 /* hack to make B.NE etc. work: turn it into the corresponding conditional */ 560 if(a == AB){ 561 a = bcode[scond&0xf]; 562 scond = (scond & ~0xf) | Always; 563 } 564 565 if(pass == 1) 566 goto out; 567 jackpot: 568 sf = 0; 569 s = g1->sym; 570 while(s != S) { 571 sf = s->sym; 572 if(sf < 0 || sf >= NSYM) 573 sf = 0; 574 t = g1->name; 575 if(h[sf].type == t) 576 if(h[sf].sym == s) 577 break; 578 zname(s->name, t, sym); 579 s->sym = sym; 580 h[sym].sym = s; 581 h[sym].type = t; 582 sf = sym; 583 sym++; 584 if(sym >= NSYM) 585 sym = 1; 586 break; 587 } 588 st = 0; 589 s = g2->sym; 590 while(s != S) { 591 st = s->sym; 592 if(st < 0 || st >= NSYM) 593 st = 0; 594 t = g2->name; 595 if(h[st].type == t) 596 if(h[st].sym == s) 597 break; 598 zname(s->name, t, sym); 599 s->sym = sym; 600 h[sym].sym = s; 601 h[sym].type = t; 602 st = sym; 603 sym++; 604 if(sym >= NSYM) 605 sym = 1; 606 if(st == sf) 607 goto jackpot; 608 break; 609 } 610 Bputc(&obuf, a); 611 Bputc(&obuf, scond); 612 Bputc(&obuf, reg); 613 Bputc(&obuf, lineno); 614 Bputc(&obuf, lineno>>8); 615 Bputc(&obuf, lineno>>16); 616 Bputc(&obuf, lineno>>24); 617 zaddr(g1, sf); 618 zaddr(g2, st); 619 620 out: 621 if(a != AGLOBL && a != ADATA) 622 pc++; 623 } 624 625 void 626 outhist(void) 627 { 628 Gen g; 629 Hist *h; 630 char *p, *q, *op, c; 631 int n; 632 633 g = nullgen; 634 c = pathchar(); 635 for(h = hist; h != H; h = h->link) { 636 p = h->name; 637 op = 0; 638 /* on windows skip drive specifier in pathname */ 639 if(systemtype(Windows) && p && p[1] == ':'){ 640 p += 2; 641 c = *p; 642 } 643 if(p && p[0] != c && h->offset == 0 && pathname){ 644 /* on windows skip drive specifier in pathname */ 645 if(systemtype(Windows) && pathname[1] == ':') { 646 op = p; 647 p = pathname+2; 648 c = *p; 649 } else if(pathname[0] == c){ 650 op = p; 651 p = pathname; 652 } 653 } 654 while(p) { 655 q = strchr(p, c); 656 if(q) { 657 n = q-p; 658 if(n == 0){ 659 n = 1; /* leading "/" */ 660 *p = '/'; /* don't emit "\" on windows */ 661 } 662 q++; 663 } else { 664 n = strlen(p); 665 q = 0; 666 } 667 if(n) { 668 Bputc(&obuf, ANAME); 669 Bputc(&obuf, D_FILE); /* type */ 670 Bputc(&obuf, 1); /* sym */ 671 Bputc(&obuf, '<'); 672 Bwrite(&obuf, p, n); 673 Bputc(&obuf, 0); 674 } 675 p = q; 676 if(p == 0 && op) { 677 p = op; 678 op = 0; 679 } 680 } 681 g.offset = h->offset; 682 683 Bputc(&obuf, AHISTORY); 684 Bputc(&obuf, Always); 685 Bputc(&obuf, 0); 686 Bputc(&obuf, h->line); 687 Bputc(&obuf, h->line>>8); 688 Bputc(&obuf, h->line>>16); 689 Bputc(&obuf, h->line>>24); 690 zaddr(&nullgen, 0); 691 zaddr(&g, 0); 692 } 693 } 694 695 #include "../cc/lexbody" 696 #include "../cc/macbody" 697