github.com/tcnksm/go@v0.0.0-20141208075154-439b32936367/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 int 55 Lconv(Fmt *fp) 56 { 57 return linklinefmt(ctxt, fp); 58 } 59 60 void 61 dodef(char *p) 62 { 63 if(nDlist%8 == 0) 64 Dlist = allocn(Dlist, nDlist*sizeof(char *), 65 8*sizeof(char *)); 66 Dlist[nDlist++] = p; 67 } 68 69 void 70 usage(void) 71 { 72 print("usage: %ca [options] file.c...\n", thechar); 73 flagprint(1); 74 errorexit(); 75 } 76 77 void 78 main(int argc, char *argv[]) 79 { 80 char *p; 81 82 thechar = '5'; 83 thestring = "arm"; 84 85 ctxt = linknew(&linkarm); 86 ctxt->diag = yyerror; 87 ctxt->bso = &bstdout; 88 ctxt->enforce_data_order = 1; 89 Binit(&bstdout, 1, OWRITE); 90 listinit5(); 91 fmtinstall('L', Lconv); 92 93 // Allow GOARCH=thestring or GOARCH=thestringsuffix, 94 // but not other values. 95 p = getgoarch(); 96 if(strncmp(p, thestring, strlen(thestring)) != 0) 97 sysfatal("cannot use %cc with GOARCH=%s", thechar, p); 98 99 ensuresymb(NSYMB); 100 memset(debug, 0, sizeof(debug)); 101 cinit(); 102 outfile = 0; 103 setinclude("."); 104 105 flagfn1("D", "name[=value]: add #define", dodef); 106 flagfn1("I", "dir: add dir to include path", setinclude); 107 flagcount("S", "print assembly and machine code", &debug['S']); 108 flagcount("m", "debug preprocessor macros", &debug['m']); 109 flagstr("o", "file: set output file", &outfile); 110 flagstr("trimpath", "prefix: remove prefix from recorded source file paths", &ctxt->trimpath); 111 112 flagparse(&argc, &argv, usage); 113 ctxt->debugasm = debug['S']; 114 115 if(argc < 1) 116 usage(); 117 if(argc > 1){ 118 print("can't assemble multiple files\n"); 119 errorexit(); 120 } 121 122 if(assemble(argv[0])) 123 errorexit(); 124 Bflush(&bstdout); 125 exits(0); 126 } 127 128 int 129 assemble(char *file) 130 { 131 char *ofile, *p; 132 int i, of; 133 134 ofile = alloc(strlen(file)+3); // +3 for .x\0 (x=thechar) 135 strcpy(ofile, file); 136 p = utfrrune(ofile, '/'); 137 if(p) { 138 include[0] = ofile; 139 *p++ = 0; 140 } else 141 p = ofile; 142 if(outfile == 0) { 143 outfile = p; 144 if(outfile){ 145 p = utfrrune(outfile, '.'); 146 if(p) 147 if(p[1] == 's' && p[2] == 0) 148 p[0] = 0; 149 p = utfrune(outfile, 0); 150 p[0] = '.'; 151 p[1] = thechar; 152 p[2] = 0; 153 } else 154 outfile = "/dev/null"; 155 } 156 157 of = create(outfile, OWRITE, 0664); 158 if(of < 0) { 159 yyerror("%ca: cannot create %s", thechar, outfile); 160 errorexit(); 161 } 162 Binit(&obuf, of, OWRITE); 163 Bprint(&obuf, "go object %s %s %s\n", getgoos(), getgoarch(), getgoversion()); 164 Bprint(&obuf, "!\n"); 165 166 for(pass = 1; pass <= 2; pass++) { 167 pinit(file); 168 for(i=0; i<nDlist; i++) 169 dodefine(Dlist[i]); 170 yyparse(); 171 cclean(); 172 if(nerrors) 173 return nerrors; 174 } 175 176 writeobj(ctxt, &obuf); 177 Bflush(&obuf); 178 return 0; 179 } 180 181 struct 182 { 183 char *name; 184 ushort type; 185 ushort value; 186 } itab[] = 187 { 188 "SP", LSP, D_AUTO, 189 "SB", LSB, D_EXTERN, 190 "FP", LFP, D_PARAM, 191 "PC", LPC, D_BRANCH, 192 193 "R", LR, 0, 194 "R0", LREG, 0, 195 "R1", LREG, 1, 196 "R2", LREG, 2, 197 "R3", LREG, 3, 198 "R4", LREG, 4, 199 "R5", LREG, 5, 200 "R6", LREG, 6, 201 "R7", LREG, 7, 202 "R8", LREG, 8, 203 "R9", LREG, 9, 204 "g", LREG, 10, // avoid unintentionally clobber g using R10 205 "R11", LREG, 11, 206 "R12", LREG, 12, 207 "R13", LREG, 13, 208 "R14", LREG, 14, 209 "R15", LREG, 15, 210 211 "F", LF, 0, 212 213 "F0", LFREG, 0, 214 "F1", LFREG, 1, 215 "F2", LFREG, 2, 216 "F3", LFREG, 3, 217 "F4", LFREG, 4, 218 "F5", LFREG, 5, 219 "F6", LFREG, 6, 220 "F7", LFREG, 7, 221 "F8", LFREG, 8, 222 "F9", LFREG, 9, 223 "F10", LFREG, 10, 224 "F11", LFREG, 11, 225 "F12", LFREG, 12, 226 "F13", LFREG, 13, 227 "F14", LFREG, 14, 228 "F15", LFREG, 15, 229 230 "C", LC, 0, 231 232 "C0", LCREG, 0, 233 "C1", LCREG, 1, 234 "C2", LCREG, 2, 235 "C3", LCREG, 3, 236 "C4", LCREG, 4, 237 "C5", LCREG, 5, 238 "C6", LCREG, 6, 239 "C7", LCREG, 7, 240 "C8", LCREG, 8, 241 "C9", LCREG, 9, 242 "C10", LCREG, 10, 243 "C11", LCREG, 11, 244 "C12", LCREG, 12, 245 "C13", LCREG, 13, 246 "C14", LCREG, 14, 247 "C15", LCREG, 15, 248 249 "CPSR", LPSR, 0, 250 "SPSR", LPSR, 1, 251 252 "FPSR", LFCR, 0, 253 "FPCR", LFCR, 1, 254 255 ".EQ", LCOND, 0, 256 ".NE", LCOND, 1, 257 ".CS", LCOND, 2, 258 ".HS", LCOND, 2, 259 ".CC", LCOND, 3, 260 ".LO", LCOND, 3, 261 ".MI", LCOND, 4, 262 ".PL", LCOND, 5, 263 ".VS", LCOND, 6, 264 ".VC", LCOND, 7, 265 ".HI", LCOND, 8, 266 ".LS", LCOND, 9, 267 ".GE", LCOND, 10, 268 ".LT", LCOND, 11, 269 ".GT", LCOND, 12, 270 ".LE", LCOND, 13, 271 ".AL", LCOND, Always, 272 273 ".U", LS, C_UBIT, 274 ".S", LS, C_SBIT, 275 ".W", LS, C_WBIT, 276 ".P", LS, C_PBIT, 277 ".PW", LS, C_WBIT|C_PBIT, 278 ".WP", LS, C_WBIT|C_PBIT, 279 280 ".F", LS, C_FBIT, 281 282 ".IBW", LS, C_WBIT|C_PBIT|C_UBIT, 283 ".IAW", LS, C_WBIT|C_UBIT, 284 ".DBW", LS, C_WBIT|C_PBIT, 285 ".DAW", LS, C_WBIT, 286 ".IB", LS, C_PBIT|C_UBIT, 287 ".IA", LS, C_UBIT, 288 ".DB", LS, C_PBIT, 289 ".DA", LS, 0, 290 291 "@", LAT, 0, 292 293 "AND", LTYPE1, AAND, 294 "EOR", LTYPE1, AEOR, 295 "SUB", LTYPE1, ASUB, 296 "RSB", LTYPE1, ARSB, 297 "ADD", LTYPE1, AADD, 298 "ADC", LTYPE1, AADC, 299 "SBC", LTYPE1, ASBC, 300 "RSC", LTYPE1, ARSC, 301 "ORR", LTYPE1, AORR, 302 "BIC", LTYPE1, ABIC, 303 304 "SLL", LTYPE1, ASLL, 305 "SRL", LTYPE1, ASRL, 306 "SRA", LTYPE1, ASRA, 307 308 "MUL", LTYPE1, AMUL, 309 "MULA", LTYPEN, AMULA, 310 "DIV", LTYPE1, ADIV, 311 "MOD", LTYPE1, AMOD, 312 313 "MULL", LTYPEM, AMULL, 314 "MULAL", LTYPEM, AMULAL, 315 "MULLU", LTYPEM, AMULLU, 316 "MULALU", LTYPEM, AMULALU, 317 318 "MVN", LTYPE2, AMVN, /* op2 ignored */ 319 320 "MOVB", LTYPE3, AMOVB, 321 "MOVBU", LTYPE3, AMOVBU, 322 "MOVH", LTYPE3, AMOVH, 323 "MOVHU", LTYPE3, AMOVHU, 324 "MOVW", LTYPE3, AMOVW, 325 326 "MOVD", LTYPE3, AMOVD, 327 "MOVDF", LTYPE3, AMOVDF, 328 "MOVDW", LTYPE3, AMOVDW, 329 "MOVF", LTYPE3, AMOVF, 330 "MOVFD", LTYPE3, AMOVFD, 331 "MOVFW", LTYPE3, AMOVFW, 332 "MOVWD", LTYPE3, AMOVWD, 333 "MOVWF", LTYPE3, AMOVWF, 334 335 "LDREX", LTYPE3, ALDREX, 336 "LDREXD", LTYPE3, ALDREXD, 337 "STREX", LTYPE9, ASTREX, 338 "STREXD", LTYPE9, ASTREXD, 339 340 /* 341 "NEGF", LTYPEI, ANEGF, 342 "NEGD", LTYPEI, ANEGD, 343 "SQTF", LTYPEI, ASQTF, 344 "SQTD", LTYPEI, ASQTD, 345 "RNDF", LTYPEI, ARNDF, 346 "RNDD", LTYPEI, ARNDD, 347 "URDF", LTYPEI, AURDF, 348 "URDD", LTYPEI, AURDD, 349 "NRMF", LTYPEI, ANRMF, 350 "NRMD", LTYPEI, ANRMD, 351 */ 352 353 "ABSF", LTYPEI, AABSF, 354 "ABSD", LTYPEI, AABSD, 355 "SQRTF", LTYPEI, ASQRTF, 356 "SQRTD", LTYPEI, ASQRTD, 357 "CMPF", LTYPEL, ACMPF, 358 "CMPD", LTYPEL, ACMPD, 359 "ADDF", LTYPEK, AADDF, 360 "ADDD", LTYPEK, AADDD, 361 "SUBF", LTYPEK, ASUBF, 362 "SUBD", LTYPEK, ASUBD, 363 "MULF", LTYPEK, AMULF, 364 "MULD", LTYPEK, AMULD, 365 "DIVF", LTYPEK, ADIVF, 366 "DIVD", LTYPEK, ADIVD, 367 368 "B", LTYPE4, AB, 369 "BL", LTYPE4, ABL, 370 "BX", LTYPEBX, ABX, 371 372 "BEQ", LTYPE5, ABEQ, 373 "BNE", LTYPE5, ABNE, 374 "BCS", LTYPE5, ABCS, 375 "BHS", LTYPE5, ABHS, 376 "BCC", LTYPE5, ABCC, 377 "BLO", LTYPE5, ABLO, 378 "BMI", LTYPE5, ABMI, 379 "BPL", LTYPE5, ABPL, 380 "BVS", LTYPE5, ABVS, 381 "BVC", LTYPE5, ABVC, 382 "BHI", LTYPE5, ABHI, 383 "BLS", LTYPE5, ABLS, 384 "BGE", LTYPE5, ABGE, 385 "BLT", LTYPE5, ABLT, 386 "BGT", LTYPE5, ABGT, 387 "BLE", LTYPE5, ABLE, 388 "BCASE", LTYPE5, ABCASE, 389 390 "SWI", LTYPE6, ASWI, 391 392 "CMP", LTYPE7, ACMP, 393 "TST", LTYPE7, ATST, 394 "TEQ", LTYPE7, ATEQ, 395 "CMN", LTYPE7, ACMN, 396 397 "MOVM", LTYPE8, AMOVM, 398 399 "SWPBU", LTYPE9, ASWPBU, 400 "SWPW", LTYPE9, ASWPW, 401 402 "RET", LTYPEA, ARET, 403 "RFE", LTYPEA, ARFE, 404 405 "TEXT", LTYPEB, ATEXT, 406 "GLOBL", LTYPEB, AGLOBL, 407 "DATA", LTYPEC, ADATA, 408 "CASE", LTYPED, ACASE, 409 "END", LTYPEE, AEND, 410 "WORD", LTYPEH, AWORD, 411 "NOP", LTYPEI, ANOP, 412 413 "MCR", LTYPEJ, 0, 414 "MRC", LTYPEJ, 1, 415 416 "PLD", LTYPEPLD, APLD, 417 "UNDEF", LTYPEE, AUNDEF, 418 "CLZ", LTYPE2, ACLZ, 419 420 "MULWT", LTYPE1, AMULWT, 421 "MULWB", LTYPE1, AMULWB, 422 "MULAWT", LTYPEN, AMULAWT, 423 "MULAWB", LTYPEN, AMULAWB, 424 425 "USEFIELD", LTYPEN, AUSEFIELD, 426 "PCDATA", LTYPEPC, APCDATA, 427 "FUNCDATA", LTYPEF, AFUNCDATA, 428 429 0 430 }; 431 432 void 433 cinit(void) 434 { 435 Sym *s; 436 int i; 437 438 nullgen.type = D_NONE; 439 nullgen.name = D_NONE; 440 nullgen.reg = NREG; 441 442 nerrors = 0; 443 iostack = I; 444 iofree = I; 445 peekc = IGN; 446 nhunk = 0; 447 for(i=0; i<NHASH; i++) 448 hash[i] = S; 449 for(i=0; itab[i].name; i++) { 450 s = slookup(itab[i].name); 451 s->type = itab[i].type; 452 s->value = itab[i].value; 453 } 454 } 455 456 void 457 syminit(Sym *s) 458 { 459 460 s->type = LNAME; 461 s->value = 0; 462 } 463 464 int 465 isreg(Addr *g) 466 { 467 468 USED(g); 469 return 1; 470 } 471 472 void 473 cclean(void) 474 { 475 outcode(AEND, Always, &nullgen, NREG, &nullgen); 476 } 477 478 static int bcode[] = 479 { 480 ABEQ, 481 ABNE, 482 ABCS, 483 ABCC, 484 ABMI, 485 ABPL, 486 ABVS, 487 ABVC, 488 ABHI, 489 ABLS, 490 ABGE, 491 ABLT, 492 ABGT, 493 ABLE, 494 AB, 495 ANOP, 496 }; 497 498 static Prog *lastpc; 499 500 void 501 outcode(int a, int scond, Addr *g1, int reg, Addr *g2) 502 { 503 Prog *p; 504 Plist *pl; 505 506 /* hack to make B.NE etc. work: turn it into the corresponding conditional */ 507 if(a == AB){ 508 a = bcode[scond&0xf]; 509 scond = (scond & ~0xf) | Always; 510 } 511 512 if(pass == 1) 513 goto out; 514 515 p = malloc(sizeof *p); 516 memset(p, 0, sizeof *p); 517 p->as = a; 518 p->lineno = stmtline; 519 p->scond = scond; 520 p->from = *g1; 521 p->reg = reg; 522 p->to = *g2; 523 p->pc = pc; 524 525 if(lastpc == nil) { 526 pl = linknewplist(ctxt); 527 pl->firstpc = p; 528 } else 529 lastpc->link = p; 530 lastpc = p; 531 532 out: 533 if(a != AGLOBL && a != ADATA) 534 pc++; 535 } 536 537 #include "../cc/lexbody" 538 #include "../cc/macbody"