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