github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/cmd/5a/lex.c (about) 1 // Inferno utils/5a/lex.c 2 // http://code.google.com/p/inferno-os/source/browse/utils/5a/lex.c 3 // 4 // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. 5 // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) 6 // Portions Copyright © 1997-1999 Vita Nuova Limited 7 // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) 8 // Portions Copyright © 2004,2006 Bruce Ellis 9 // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) 10 // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others 11 // Portions Copyright © 2009 The Go Authors. All rights reserved. 12 // 13 // Permission is hereby granted, free of charge, to any person obtaining a copy 14 // of this software and associated documentation files (the "Software"), to deal 15 // in the Software without restriction, including without limitation the rights 16 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 // copies of the Software, and to permit persons to whom the Software is 18 // furnished to do so, subject to the following conditions: 19 // 20 // The above copyright notice and this permission notice shall be included in 21 // all copies or substantial portions of the Software. 22 // 23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 29 // THE SOFTWARE. 30 31 #define EXTERN 32 #include <u.h> 33 #include <libc.h> 34 #include "a.h" 35 #include "y.tab.h" 36 37 enum 38 { 39 Plan9 = 1<<0, 40 Unix = 1<<1, 41 Windows = 1<<2, 42 }; 43 44 int 45 systemtype(int sys) 46 { 47 #ifdef _WIN32 48 return sys&Windows; 49 #else 50 return sys&Plan9; 51 #endif 52 } 53 54 void 55 main(int argc, char *argv[]) 56 { 57 char *p; 58 int c; 59 60 thechar = '5'; 61 thestring = "arm"; 62 63 ensuresymb(NSYMB); 64 memset(debug, 0, sizeof(debug)); 65 cinit(); 66 outfile = 0; 67 setinclude("."); 68 ARGBEGIN { 69 default: 70 c = ARGC(); 71 if(c >= 0 || c < sizeof(debug)) 72 debug[c] = 1; 73 break; 74 75 case 'o': 76 outfile = ARGF(); 77 break; 78 79 case 'D': 80 p = ARGF(); 81 if(p) { 82 if (nDlist%8 == 0) 83 Dlist = allocn(Dlist, nDlist*sizeof(char *), 84 8*sizeof(char *)); 85 Dlist[nDlist++] = p; 86 } 87 break; 88 89 case 'I': 90 p = ARGF(); 91 setinclude(p); 92 break; 93 case 't': 94 thechar = 't'; 95 thestring = "thumb"; 96 break; 97 } ARGEND 98 if(*argv == 0) { 99 print("usage: %ca [-options] file.s\n", thechar); 100 errorexit(); 101 } 102 if(argc > 1){ 103 print("can't assemble multiple files\n"); 104 errorexit(); 105 } 106 if(assemble(argv[0])) 107 errorexit(); 108 exits(0); 109 } 110 111 int 112 assemble(char *file) 113 { 114 char *ofile, *p; 115 int i, of; 116 117 ofile = alloc(strlen(file)+3); // +3 for .x\0 (x=thechar) 118 strcpy(ofile, file); 119 p = utfrrune(ofile, '/'); 120 if(p) { 121 include[0] = ofile; 122 *p++ = 0; 123 } else 124 p = ofile; 125 if(outfile == 0) { 126 outfile = p; 127 if(outfile){ 128 p = utfrrune(outfile, '.'); 129 if(p) 130 if(p[1] == 's' && p[2] == 0) 131 p[0] = 0; 132 p = utfrune(outfile, 0); 133 p[0] = '.'; 134 p[1] = thechar; 135 p[2] = 0; 136 } else 137 outfile = "/dev/null"; 138 } 139 140 of = create(outfile, OWRITE, 0664); 141 if(of < 0) { 142 yyerror("%ca: cannot create %s", thechar, outfile); 143 errorexit(); 144 } 145 Binit(&obuf, of, OWRITE); 146 147 pass = 1; 148 pinit(file); 149 150 Bprint(&obuf, "go object %s %s %s\n", getgoos(), thestring, getgoversion()); 151 152 for(i=0; i<nDlist; i++) 153 dodefine(Dlist[i]); 154 yyparse(); 155 if(nerrors) { 156 cclean(); 157 return nerrors; 158 } 159 160 Bprint(&obuf, "\n!\n"); 161 162 pass = 2; 163 outhist(); 164 pinit(file); 165 for(i=0; i<nDlist; i++) 166 dodefine(Dlist[i]); 167 yyparse(); 168 cclean(); 169 return nerrors; 170 } 171 172 struct 173 { 174 char *name; 175 ushort type; 176 ushort value; 177 } itab[] = 178 { 179 "SP", LSP, D_AUTO, 180 "SB", LSB, D_EXTERN, 181 "FP", LFP, D_PARAM, 182 "PC", LPC, D_BRANCH, 183 184 "R", LR, 0, 185 "R0", LREG, 0, 186 "R1", LREG, 1, 187 "R2", LREG, 2, 188 "R3", LREG, 3, 189 "R4", LREG, 4, 190 "R5", LREG, 5, 191 "R6", LREG, 6, 192 "R7", LREG, 7, 193 "R8", LREG, 8, 194 "R9", LREG, 9, 195 "R10", LREG, 10, 196 "R11", LREG, 11, 197 "R12", LREG, 12, 198 "R13", LREG, 13, 199 "R14", LREG, 14, 200 "R15", LREG, 15, 201 202 "F", LF, 0, 203 204 "F0", LFREG, 0, 205 "F1", LFREG, 1, 206 "F2", LFREG, 2, 207 "F3", LFREG, 3, 208 "F4", LFREG, 4, 209 "F5", LFREG, 5, 210 "F6", LFREG, 6, 211 "F7", LFREG, 7, 212 "F8", LFREG, 8, 213 "F9", LFREG, 9, 214 "F10", LFREG, 10, 215 "F11", LFREG, 11, 216 "F12", LFREG, 12, 217 "F13", LFREG, 13, 218 "F14", LFREG, 14, 219 "F15", LFREG, 15, 220 221 "C", LC, 0, 222 223 "C0", LCREG, 0, 224 "C1", LCREG, 1, 225 "C2", LCREG, 2, 226 "C3", LCREG, 3, 227 "C4", LCREG, 4, 228 "C5", LCREG, 5, 229 "C6", LCREG, 6, 230 "C7", LCREG, 7, 231 "C8", LCREG, 8, 232 "C9", LCREG, 9, 233 "C10", LCREG, 10, 234 "C11", LCREG, 11, 235 "C12", LCREG, 12, 236 "C13", LCREG, 13, 237 "C14", LCREG, 14, 238 "C15", LCREG, 15, 239 240 "CPSR", LPSR, 0, 241 "SPSR", LPSR, 1, 242 243 "FPSR", LFCR, 0, 244 "FPCR", LFCR, 1, 245 246 ".EQ", LCOND, 0, 247 ".NE", LCOND, 1, 248 ".CS", LCOND, 2, 249 ".HS", LCOND, 2, 250 ".CC", LCOND, 3, 251 ".LO", LCOND, 3, 252 ".MI", LCOND, 4, 253 ".PL", LCOND, 5, 254 ".VS", LCOND, 6, 255 ".VC", LCOND, 7, 256 ".HI", LCOND, 8, 257 ".LS", LCOND, 9, 258 ".GE", LCOND, 10, 259 ".LT", LCOND, 11, 260 ".GT", LCOND, 12, 261 ".LE", LCOND, 13, 262 ".AL", LCOND, Always, 263 264 ".U", LS, C_UBIT, 265 ".S", LS, C_SBIT, 266 ".W", LS, C_WBIT, 267 ".P", LS, C_PBIT, 268 ".PW", LS, C_WBIT|C_PBIT, 269 ".WP", LS, C_WBIT|C_PBIT, 270 271 ".F", LS, C_FBIT, 272 273 ".IBW", LS, C_WBIT|C_PBIT|C_UBIT, 274 ".IAW", LS, C_WBIT|C_UBIT, 275 ".DBW", LS, C_WBIT|C_PBIT, 276 ".DAW", LS, C_WBIT, 277 ".IB", LS, C_PBIT|C_UBIT, 278 ".IA", LS, C_UBIT, 279 ".DB", LS, C_PBIT, 280 ".DA", LS, 0, 281 282 "@", LAT, 0, 283 284 "AND", LTYPE1, AAND, 285 "EOR", LTYPE1, AEOR, 286 "SUB", LTYPE1, ASUB, 287 "RSB", LTYPE1, ARSB, 288 "ADD", LTYPE1, AADD, 289 "ADC", LTYPE1, AADC, 290 "SBC", LTYPE1, ASBC, 291 "RSC", LTYPE1, ARSC, 292 "ORR", LTYPE1, AORR, 293 "BIC", LTYPE1, ABIC, 294 295 "SLL", LTYPE1, ASLL, 296 "SRL", LTYPE1, ASRL, 297 "SRA", LTYPE1, ASRA, 298 299 "MUL", LTYPE1, AMUL, 300 "MULA", LTYPEN, AMULA, 301 "DIV", LTYPE1, ADIV, 302 "MOD", LTYPE1, AMOD, 303 304 "MULL", LTYPEM, AMULL, 305 "MULAL", LTYPEM, AMULAL, 306 "MULLU", LTYPEM, AMULLU, 307 "MULALU", LTYPEM, AMULALU, 308 309 "MVN", LTYPE2, AMVN, /* op2 ignored */ 310 311 "MOVB", LTYPE3, AMOVB, 312 "MOVBU", LTYPE3, AMOVBU, 313 "MOVH", LTYPE3, AMOVH, 314 "MOVHU", LTYPE3, AMOVHU, 315 "MOVW", LTYPE3, AMOVW, 316 317 "MOVD", LTYPE3, AMOVD, 318 "MOVDF", LTYPE3, AMOVDF, 319 "MOVDW", LTYPE3, AMOVDW, 320 "MOVF", LTYPE3, AMOVF, 321 "MOVFD", LTYPE3, AMOVFD, 322 "MOVFW", LTYPE3, AMOVFW, 323 "MOVWD", LTYPE3, AMOVWD, 324 "MOVWF", LTYPE3, AMOVWF, 325 326 "LDREX", LTYPE3, ALDREX, 327 "LDREXD", LTYPE3, ALDREXD, 328 "STREX", LTYPE9, ASTREX, 329 "STREXD", LTYPE9, ASTREXD, 330 331 /* 332 "NEGF", LTYPEI, ANEGF, 333 "NEGD", LTYPEI, ANEGD, 334 "SQTF", LTYPEI, ASQTF, 335 "SQTD", LTYPEI, ASQTD, 336 "RNDF", LTYPEI, ARNDF, 337 "RNDD", LTYPEI, ARNDD, 338 "URDF", LTYPEI, AURDF, 339 "URDD", LTYPEI, AURDD, 340 "NRMF", LTYPEI, ANRMF, 341 "NRMD", LTYPEI, ANRMD, 342 */ 343 344 "ABSF", LTYPEI, AABSF, 345 "ABSD", LTYPEI, AABSD, 346 "SQRTF", LTYPEI, ASQRTF, 347 "SQRTD", LTYPEI, ASQRTD, 348 "CMPF", LTYPEL, ACMPF, 349 "CMPD", LTYPEL, ACMPD, 350 "ADDF", LTYPEK, AADDF, 351 "ADDD", LTYPEK, AADDD, 352 "SUBF", LTYPEK, ASUBF, 353 "SUBD", LTYPEK, ASUBD, 354 "MULF", LTYPEK, AMULF, 355 "MULD", LTYPEK, AMULD, 356 "DIVF", LTYPEK, ADIVF, 357 "DIVD", LTYPEK, ADIVD, 358 359 "B", LTYPE4, AB, 360 "BL", LTYPE4, ABL, 361 "BX", LTYPEBX, ABX, 362 363 "BEQ", LTYPE5, ABEQ, 364 "BNE", LTYPE5, ABNE, 365 "BCS", LTYPE5, ABCS, 366 "BHS", LTYPE5, ABHS, 367 "BCC", LTYPE5, ABCC, 368 "BLO", LTYPE5, ABLO, 369 "BMI", LTYPE5, ABMI, 370 "BPL", LTYPE5, ABPL, 371 "BVS", LTYPE5, ABVS, 372 "BVC", LTYPE5, ABVC, 373 "BHI", LTYPE5, ABHI, 374 "BLS", LTYPE5, ABLS, 375 "BGE", LTYPE5, ABGE, 376 "BLT", LTYPE5, ABLT, 377 "BGT", LTYPE5, ABGT, 378 "BLE", LTYPE5, ABLE, 379 "BCASE", LTYPE5, ABCASE, 380 381 "SWI", LTYPE6, ASWI, 382 383 "CMP", LTYPE7, ACMP, 384 "TST", LTYPE7, ATST, 385 "TEQ", LTYPE7, ATEQ, 386 "CMN", LTYPE7, ACMN, 387 388 "MOVM", LTYPE8, AMOVM, 389 390 "SWPBU", LTYPE9, ASWPBU, 391 "SWPW", LTYPE9, ASWPW, 392 393 "RET", LTYPEA, ARET, 394 "RFE", LTYPEA, ARFE, 395 396 "TEXT", LTYPEB, ATEXT, 397 "GLOBL", LTYPEB, AGLOBL, 398 "DATA", LTYPEC, ADATA, 399 "CASE", LTYPED, ACASE, 400 "END", LTYPEE, AEND, 401 "WORD", LTYPEH, AWORD, 402 "NOP", LTYPEI, ANOP, 403 404 "MCR", LTYPEJ, 0, 405 "MRC", LTYPEJ, 1, 406 407 "PLD", LTYPEPLD, APLD, 408 "UNDEF", LTYPEE, AUNDEF, 409 "CLZ", LTYPE2, ACLZ, 410 411 "MULWT", LTYPE1, AMULWT, 412 "MULWB", LTYPE1, AMULWB, 413 "MULAWT", LTYPEN, AMULAWT, 414 "MULAWB", LTYPEN, AMULAWB, 415 416 "USEFIELD", LTYPEN, AUSEFIELD, 417 418 0 419 }; 420 421 void 422 cinit(void) 423 { 424 Sym *s; 425 int i; 426 427 nullgen.sym = S; 428 nullgen.offset = 0; 429 nullgen.type = D_NONE; 430 nullgen.name = D_NONE; 431 nullgen.reg = NREG; 432 if(FPCHIP) 433 nullgen.dval = 0; 434 for(i=0; i<sizeof(nullgen.sval); i++) 435 nullgen.sval[i] = 0; 436 437 nerrors = 0; 438 iostack = I; 439 iofree = I; 440 peekc = IGN; 441 nhunk = 0; 442 for(i=0; i<NHASH; i++) 443 hash[i] = S; 444 for(i=0; itab[i].name; i++) { 445 s = slookup(itab[i].name); 446 s->type = itab[i].type; 447 s->value = itab[i].value; 448 } 449 450 pathname = allocn(pathname, 0, 100); 451 if(getwd(pathname, 99) == 0) { 452 pathname = allocn(pathname, 100, 900); 453 if(getwd(pathname, 999) == 0) 454 strcpy(pathname, "/???"); 455 } 456 } 457 458 void 459 syminit(Sym *s) 460 { 461 462 s->type = LNAME; 463 s->value = 0; 464 } 465 466 int 467 isreg(Gen *g) 468 { 469 470 USED(g); 471 return 1; 472 } 473 474 void 475 cclean(void) 476 { 477 478 outcode(AEND, Always, &nullgen, NREG, &nullgen); 479 Bflush(&obuf); 480 } 481 482 void 483 zname(char *n, int t, int s) 484 { 485 486 Bputc(&obuf, ANAME); 487 Bputc(&obuf, t); /* type */ 488 Bputc(&obuf, s); /* sym */ 489 while(*n) { 490 Bputc(&obuf, *n); 491 n++; 492 } 493 Bputc(&obuf, 0); 494 } 495 496 void 497 zaddr(Gen *a, int s) 498 { 499 int32 l; 500 int i; 501 char *n; 502 Ieee e; 503 504 Bputc(&obuf, a->type); 505 Bputc(&obuf, a->reg); 506 Bputc(&obuf, s); 507 Bputc(&obuf, a->name); 508 Bputc(&obuf, 0); 509 switch(a->type) { 510 default: 511 print("unknown type %d\n", a->type); 512 exits("arg"); 513 514 case D_NONE: 515 case D_REG: 516 case D_FREG: 517 case D_PSR: 518 case D_FPCR: 519 break; 520 521 case D_REGREG: 522 case D_REGREG2: 523 Bputc(&obuf, a->offset); 524 break; 525 526 case D_OREG: 527 case D_CONST: 528 case D_BRANCH: 529 case D_SHIFT: 530 l = a->offset; 531 Bputc(&obuf, l); 532 Bputc(&obuf, l>>8); 533 Bputc(&obuf, l>>16); 534 Bputc(&obuf, l>>24); 535 break; 536 537 case D_SCONST: 538 n = a->sval; 539 for(i=0; i<NSNAME; i++) { 540 Bputc(&obuf, *n); 541 n++; 542 } 543 break; 544 545 case D_FCONST: 546 ieeedtod(&e, a->dval); 547 Bputc(&obuf, e.l); 548 Bputc(&obuf, e.l>>8); 549 Bputc(&obuf, e.l>>16); 550 Bputc(&obuf, e.l>>24); 551 Bputc(&obuf, e.h); 552 Bputc(&obuf, e.h>>8); 553 Bputc(&obuf, e.h>>16); 554 Bputc(&obuf, e.h>>24); 555 break; 556 } 557 } 558 559 static int bcode[] = 560 { 561 ABEQ, 562 ABNE, 563 ABCS, 564 ABCC, 565 ABMI, 566 ABPL, 567 ABVS, 568 ABVC, 569 ABHI, 570 ABLS, 571 ABGE, 572 ABLT, 573 ABGT, 574 ABLE, 575 AB, 576 ANOP, 577 }; 578 579 void 580 outcode(int a, int scond, Gen *g1, int reg, Gen *g2) 581 { 582 int sf, st, t; 583 Sym *s; 584 585 /* hack to make B.NE etc. work: turn it into the corresponding conditional */ 586 if(a == AB){ 587 a = bcode[scond&0xf]; 588 scond = (scond & ~0xf) | Always; 589 } 590 591 if(pass == 1) 592 goto out; 593 jackpot: 594 sf = 0; 595 s = g1->sym; 596 while(s != S) { 597 sf = s->sym; 598 if(sf < 0 || sf >= NSYM) 599 sf = 0; 600 t = g1->name; 601 if(h[sf].type == t) 602 if(h[sf].sym == s) 603 break; 604 zname(s->name, t, sym); 605 s->sym = sym; 606 h[sym].sym = s; 607 h[sym].type = t; 608 sf = sym; 609 sym++; 610 if(sym >= NSYM) 611 sym = 1; 612 break; 613 } 614 st = 0; 615 s = g2->sym; 616 while(s != S) { 617 st = s->sym; 618 if(st < 0 || st >= NSYM) 619 st = 0; 620 t = g2->name; 621 if(h[st].type == t) 622 if(h[st].sym == s) 623 break; 624 zname(s->name, t, sym); 625 s->sym = sym; 626 h[sym].sym = s; 627 h[sym].type = t; 628 st = sym; 629 sym++; 630 if(sym >= NSYM) 631 sym = 1; 632 if(st == sf) 633 goto jackpot; 634 break; 635 } 636 Bputc(&obuf, a); 637 Bputc(&obuf, scond); 638 Bputc(&obuf, reg); 639 Bputc(&obuf, stmtline); 640 Bputc(&obuf, stmtline>>8); 641 Bputc(&obuf, stmtline>>16); 642 Bputc(&obuf, stmtline>>24); 643 zaddr(g1, sf); 644 zaddr(g2, st); 645 646 out: 647 if(a != AGLOBL && a != ADATA) 648 pc++; 649 } 650 651 void 652 outhist(void) 653 { 654 Gen g; 655 Hist *h; 656 char *p, *q, *op, c; 657 int n; 658 char *tofree; 659 static int first = 1; 660 static char *goroot, *goroot_final; 661 662 if(first) { 663 // Decide whether we need to rewrite paths from $GOROOT to $GOROOT_FINAL. 664 first = 0; 665 goroot = getenv("GOROOT"); 666 goroot_final = getenv("GOROOT_FINAL"); 667 if(goroot == nil) 668 goroot = ""; 669 if(goroot_final == nil) 670 goroot_final = goroot; 671 if(strcmp(goroot, goroot_final) == 0) { 672 goroot = nil; 673 goroot_final = nil; 674 } 675 } 676 677 tofree = nil; 678 g = nullgen; 679 c = '/'; 680 for(h = hist; h != H; h = h->link) { 681 p = h->name; 682 if(p != nil && goroot != nil) { 683 n = strlen(goroot); 684 if(strncmp(p, goroot, strlen(goroot)) == 0 && p[n] == '/') { 685 tofree = smprint("%s%s", goroot_final, p+n); 686 p = tofree; 687 } 688 } 689 op = 0; 690 if(systemtype(Windows) && p && p[1] == ':'){ 691 c = p[2]; 692 } else if(p && p[0] != c && h->offset == 0 && pathname){ 693 if(systemtype(Windows) && pathname[1] == ':') { 694 op = p; 695 p = pathname; 696 c = p[2]; 697 } else if(pathname[0] == c){ 698 op = p; 699 p = pathname; 700 } 701 } 702 while(p) { 703 q = strchr(p, c); 704 if(q) { 705 n = q-p; 706 if(n == 0){ 707 n = 1; /* leading "/" */ 708 *p = '/'; /* don't emit "\" on windows */ 709 } 710 q++; 711 } else { 712 n = strlen(p); 713 q = 0; 714 } 715 if(n) { 716 Bputc(&obuf, ANAME); 717 Bputc(&obuf, D_FILE); /* type */ 718 Bputc(&obuf, 1); /* sym */ 719 Bputc(&obuf, '<'); 720 Bwrite(&obuf, p, n); 721 Bputc(&obuf, 0); 722 } 723 p = q; 724 if(p == 0 && op) { 725 p = op; 726 op = 0; 727 } 728 } 729 g.offset = h->offset; 730 731 Bputc(&obuf, AHISTORY); 732 Bputc(&obuf, Always); 733 Bputc(&obuf, 0); 734 Bputc(&obuf, h->line); 735 Bputc(&obuf, h->line>>8); 736 Bputc(&obuf, h->line>>16); 737 Bputc(&obuf, h->line>>24); 738 zaddr(&nullgen, 0); 739 zaddr(&g, 0); 740 741 if(tofree) { 742 free(tofree); 743 tofree = nil; 744 } 745 } 746 } 747 748 #include "../cc/lexbody" 749 #include "../cc/macbody"