github.com/yanyiwu/go@v0.0.0-20150106053140-03d6637dbb7f/src/cmd/8a/a.y (about) 1 // Inferno utils/8a/a.y 2 // http://code.google.com/p/inferno-os/source/browse/utils/8a/a.y 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 %{ 32 #include <u.h> 33 #include <stdio.h> /* if we don't, bison will, and a.h re-#defines getc */ 34 #include <libc.h> 35 #include "a.h" 36 #include "../../runtime/funcdata.h" 37 %} 38 %union { 39 Sym *sym; 40 int32 lval; 41 struct { 42 int32 v1; 43 int32 v2; 44 } con2; 45 double dval; 46 char sval[8]; 47 Addr addr; 48 Addr2 addr2; 49 } 50 %left '|' 51 %left '^' 52 %left '&' 53 %left '<' '>' 54 %left '+' '-' 55 %left '*' '/' '%' 56 %token <lval> LTYPE0 LTYPE1 LTYPE2 LTYPE3 LTYPE4 57 %token <lval> LTYPEC LTYPED LTYPEN LTYPER LTYPET LTYPES LTYPEM LTYPEI LTYPEG LTYPEXC 58 %token <lval> LTYPEX LTYPEPC LTYPEF LCONST LFP LPC LSB 59 %token <lval> LBREG LLREG LSREG LFREG LXREG 60 %token <dval> LFCONST 61 %token <sval> LSCONST LSP 62 %token <sym> LNAME LLAB LVAR 63 %type <lval> con expr pointer offset 64 %type <con2> con2 65 %type <addr> mem imm imm2 reg nam rel rem rim rom omem nmem 66 %type <addr2> nonnon nonrel nonrem rimnon rimrem remrim 67 %type <addr2> spec1 spec2 spec3 spec4 spec5 spec6 spec7 spec8 spec9 spec10 spec11 spec12 68 %% 69 prog: 70 | prog 71 { 72 stmtline = lineno; 73 } 74 line 75 76 line: 77 LNAME ':' 78 { 79 $1 = labellookup($1); 80 if($1->type == LLAB && $1->value != pc) 81 yyerror("redeclaration of %s", $1->labelname); 82 $1->type = LLAB; 83 $1->value = pc; 84 } 85 line 86 | ';' 87 | inst ';' 88 | error ';' 89 90 inst: 91 LNAME '=' expr 92 { 93 $1->type = LVAR; 94 $1->value = $3; 95 } 96 | LVAR '=' expr 97 { 98 if($1->value != $3) 99 yyerror("redeclaration of %s", $1->name); 100 $1->value = $3; 101 } 102 | LTYPE0 nonnon { outcode($1, &$2); } 103 | LTYPE1 nonrem { outcode($1, &$2); } 104 | LTYPE2 rimnon { outcode($1, &$2); } 105 | LTYPE3 rimrem { outcode($1, &$2); } 106 | LTYPE4 remrim { outcode($1, &$2); } 107 | LTYPER nonrel { outcode($1, &$2); } 108 | LTYPED spec1 { outcode($1, &$2); } 109 | LTYPET spec2 { outcode($1, &$2); } 110 | LTYPEC spec3 { outcode($1, &$2); } 111 | LTYPEN spec4 { outcode($1, &$2); } 112 | LTYPES spec5 { outcode($1, &$2); } 113 | LTYPEM spec6 { outcode($1, &$2); } 114 | LTYPEI spec7 { outcode($1, &$2); } 115 | LTYPEG spec8 { outcode($1, &$2); } 116 | LTYPEXC spec9 { outcode($1, &$2); } 117 | LTYPEX spec10 { outcode($1, &$2); } 118 | LTYPEPC spec11 { outcode($1, &$2); } 119 | LTYPEF spec12 { outcode($1, &$2); } 120 121 nonnon: 122 { 123 $$.from = nullgen; 124 $$.to = nullgen; 125 } 126 | ',' 127 { 128 $$.from = nullgen; 129 $$.to = nullgen; 130 } 131 132 rimrem: 133 rim ',' rem 134 { 135 $$.from = $1; 136 $$.to = $3; 137 } 138 139 remrim: 140 rem ',' rim 141 { 142 $$.from = $1; 143 $$.to = $3; 144 } 145 146 rimnon: 147 rim ',' 148 { 149 $$.from = $1; 150 $$.to = nullgen; 151 } 152 | rim 153 { 154 $$.from = $1; 155 $$.to = nullgen; 156 } 157 158 nonrem: 159 ',' rem 160 { 161 $$.from = nullgen; 162 $$.to = $2; 163 } 164 | rem 165 { 166 $$.from = nullgen; 167 $$.to = $1; 168 } 169 170 nonrel: 171 ',' rel 172 { 173 $$.from = nullgen; 174 $$.to = $2; 175 } 176 | rel 177 { 178 $$.from = nullgen; 179 $$.to = $1; 180 } 181 | imm ',' rel 182 { 183 $$.from = $1; 184 $$.to = $3; 185 } 186 187 spec1: /* DATA */ 188 nam '/' con ',' imm 189 { 190 $$.from = $1; 191 $$.from.scale = $3; 192 $$.to = $5; 193 } 194 195 spec2: /* TEXT */ 196 mem ',' imm2 197 { 198 settext($1.sym); 199 $$.from = $1; 200 $$.to = $3; 201 } 202 | mem ',' con ',' imm2 203 { 204 settext($1.sym); 205 $$.from = $1; 206 $$.from.scale = $3; 207 $$.to = $5; 208 } 209 210 spec3: /* JMP/CALL */ 211 ',' rom 212 { 213 $$.from = nullgen; 214 $$.to = $2; 215 } 216 | rom 217 { 218 $$.from = nullgen; 219 $$.to = $1; 220 } 221 | '*' nam 222 { 223 $$.from = nullgen; 224 $$.to = $2; 225 $$.to.index = $2.type; 226 $$.to.type = D_INDIR+D_ADDR; 227 } 228 229 spec4: /* NOP */ 230 nonnon 231 | nonrem 232 233 spec5: /* SHL/SHR */ 234 rim ',' rem 235 { 236 $$.from = $1; 237 $$.to = $3; 238 } 239 | rim ',' rem ':' LLREG 240 { 241 $$.from = $1; 242 $$.to = $3; 243 if($$.from.index != D_NONE) 244 yyerror("dp shift with lhs index"); 245 $$.from.index = $5; 246 } 247 248 spec6: /* MOVW/MOVL */ 249 rim ',' rem 250 { 251 $$.from = $1; 252 $$.to = $3; 253 } 254 | rim ',' rem ':' LSREG 255 { 256 $$.from = $1; 257 $$.to = $3; 258 if($$.to.index != D_NONE) 259 yyerror("dp move with lhs index"); 260 $$.to.index = $5; 261 } 262 263 spec7: 264 rim ',' 265 { 266 $$.from = $1; 267 $$.to = nullgen; 268 } 269 | rim 270 { 271 $$.from = $1; 272 $$.to = nullgen; 273 } 274 | rim ',' rem 275 { 276 $$.from = $1; 277 $$.to = $3; 278 } 279 280 spec8: /* GLOBL */ 281 mem ',' imm 282 { 283 $$.from = $1; 284 $$.to = $3; 285 } 286 | mem ',' con ',' imm 287 { 288 $$.from = $1; 289 $$.from.scale = $3; 290 $$.to = $5; 291 } 292 293 spec9: /* CMPPS/CMPPD */ 294 reg ',' rem ',' con 295 { 296 $$.from = $1; 297 $$.to = $3; 298 $$.to.offset = $5; 299 } 300 301 spec10: /* PINSRD */ 302 imm ',' rem ',' reg 303 { 304 $$.from = $3; 305 $$.to = $5; 306 if($1.type != D_CONST) 307 yyerror("illegal constant"); 308 $$.to.offset = $1.offset; 309 } 310 311 spec11: /* PCDATA */ 312 rim ',' rim 313 { 314 if($1.type != D_CONST || $3.type != D_CONST) 315 yyerror("arguments to PCDATA must be integer constants"); 316 $$.from = $1; 317 $$.to = $3; 318 } 319 320 spec12: /* FUNCDATA */ 321 rim ',' rim 322 { 323 if($1.type != D_CONST) 324 yyerror("index for FUNCDATA must be integer constant"); 325 if($3.type != D_EXTERN && $3.type != D_STATIC) 326 yyerror("value for FUNCDATA must be symbol reference"); 327 $$.from = $1; 328 $$.to = $3; 329 } 330 331 rem: 332 reg 333 | mem 334 335 rom: 336 rel 337 | nmem 338 | '*' reg 339 { 340 $$ = $2; 341 } 342 | '*' omem 343 { 344 $$ = $2; 345 } 346 | reg 347 | omem 348 | imm 349 350 rim: 351 rem 352 | imm 353 354 rel: 355 con '(' LPC ')' 356 { 357 $$ = nullgen; 358 $$.type = D_BRANCH; 359 $$.offset = $1 + pc; 360 } 361 | LNAME offset 362 { 363 $1 = labellookup($1); 364 $$ = nullgen; 365 if(pass == 2 && $1->type != LLAB) 366 yyerror("undefined label: %s", $1->labelname); 367 $$.type = D_BRANCH; 368 $$.offset = $1->value + $2; 369 } 370 371 reg: 372 LBREG 373 { 374 $$ = nullgen; 375 $$.type = $1; 376 } 377 | LFREG 378 { 379 $$ = nullgen; 380 $$.type = $1; 381 } 382 | LLREG 383 { 384 $$ = nullgen; 385 $$.type = $1; 386 } 387 | LXREG 388 { 389 $$ = nullgen; 390 $$.type = $1; 391 } 392 | LSP 393 { 394 $$ = nullgen; 395 $$.type = D_SP; 396 } 397 | LSREG 398 { 399 $$ = nullgen; 400 $$.type = $1; 401 } 402 403 imm: 404 '$' con 405 { 406 $$ = nullgen; 407 $$.type = D_CONST; 408 $$.offset = $2; 409 } 410 | '$' nam 411 { 412 $$ = $2; 413 $$.index = $2.type; 414 $$.type = D_ADDR; 415 /* 416 if($2.type == D_AUTO || $2.type == D_PARAM) 417 yyerror("constant cannot be automatic: %s", 418 $2.sym->name); 419 */ 420 } 421 | '$' LSCONST 422 { 423 $$ = nullgen; 424 $$.type = D_SCONST; 425 memcpy($$.u.sval, $2, sizeof($$.u.sval)); 426 } 427 | '$' LFCONST 428 { 429 $$ = nullgen; 430 $$.type = D_FCONST; 431 $$.u.dval = $2; 432 } 433 | '$' '(' LFCONST ')' 434 { 435 $$ = nullgen; 436 $$.type = D_FCONST; 437 $$.u.dval = $3; 438 } 439 | '$' '(' '-' LFCONST ')' 440 { 441 $$ = nullgen; 442 $$.type = D_FCONST; 443 $$.u.dval = -$4; 444 } 445 | '$' '-' LFCONST 446 { 447 $$ = nullgen; 448 $$.type = D_FCONST; 449 $$.u.dval = -$3; 450 } 451 452 imm2: 453 '$' con2 454 { 455 $$ = nullgen; 456 $$.type = D_CONST2; 457 $$.offset = $2.v1; 458 $$.offset2 = $2.v2; 459 } 460 461 con2: 462 LCONST 463 { 464 $$.v1 = $1; 465 $$.v2 = ArgsSizeUnknown; 466 } 467 | '-' LCONST 468 { 469 $$.v1 = -$2; 470 $$.v2 = ArgsSizeUnknown; 471 } 472 | LCONST '-' LCONST 473 { 474 $$.v1 = $1; 475 $$.v2 = $3; 476 } 477 | '-' LCONST '-' LCONST 478 { 479 $$.v1 = -$2; 480 $$.v2 = $4; 481 } 482 483 mem: 484 omem 485 | nmem 486 487 omem: 488 con 489 { 490 $$ = nullgen; 491 $$.type = D_INDIR+D_NONE; 492 $$.offset = $1; 493 } 494 | con '(' LLREG ')' 495 { 496 $$ = nullgen; 497 $$.type = D_INDIR+$3; 498 $$.offset = $1; 499 } 500 | con '(' LSP ')' 501 { 502 $$ = nullgen; 503 $$.type = D_INDIR+D_SP; 504 $$.offset = $1; 505 } 506 | con '(' LLREG '*' con ')' 507 { 508 $$ = nullgen; 509 $$.type = D_INDIR+D_NONE; 510 $$.offset = $1; 511 $$.index = $3; 512 $$.scale = $5; 513 checkscale($$.scale); 514 } 515 | con '(' LLREG ')' '(' LLREG '*' con ')' 516 { 517 $$ = nullgen; 518 $$.type = D_INDIR+$3; 519 $$.offset = $1; 520 $$.index = $6; 521 $$.scale = $8; 522 checkscale($$.scale); 523 } 524 | con '(' LLREG ')' '(' LSREG '*' con ')' 525 { 526 $$ = nullgen; 527 $$.type = D_INDIR+$3; 528 $$.offset = $1; 529 $$.index = $6; 530 $$.scale = $8; 531 checkscale($$.scale); 532 } 533 | '(' LLREG ')' 534 { 535 $$ = nullgen; 536 $$.type = D_INDIR+$2; 537 } 538 | '(' LSP ')' 539 { 540 $$ = nullgen; 541 $$.type = D_INDIR+D_SP; 542 } 543 | con '(' LSREG ')' 544 { 545 $$ = nullgen; 546 $$.type = D_INDIR+$3; 547 $$.offset = $1; 548 } 549 | '(' LLREG '*' con ')' 550 { 551 $$ = nullgen; 552 $$.type = D_INDIR+D_NONE; 553 $$.index = $2; 554 $$.scale = $4; 555 checkscale($$.scale); 556 } 557 | '(' LLREG ')' '(' LLREG '*' con ')' 558 { 559 $$ = nullgen; 560 $$.type = D_INDIR+$2; 561 $$.index = $5; 562 $$.scale = $7; 563 checkscale($$.scale); 564 } 565 566 nmem: 567 nam 568 { 569 $$ = $1; 570 } 571 | nam '(' LLREG '*' con ')' 572 { 573 $$ = $1; 574 $$.index = $3; 575 $$.scale = $5; 576 checkscale($$.scale); 577 } 578 579 nam: 580 LNAME offset '(' pointer ')' 581 { 582 $$ = nullgen; 583 $$.type = $4; 584 $$.sym = linklookup(ctxt, $1->name, 0); 585 $$.offset = $2; 586 } 587 | LNAME '<' '>' offset '(' LSB ')' 588 { 589 $$ = nullgen; 590 $$.type = D_STATIC; 591 $$.sym = linklookup(ctxt, $1->name, 1); 592 $$.offset = $4; 593 } 594 595 offset: 596 { 597 $$ = 0; 598 } 599 | '+' con 600 { 601 $$ = $2; 602 } 603 | '-' con 604 { 605 $$ = -$2; 606 } 607 608 pointer: 609 LSB 610 | LSP 611 { 612 $$ = D_AUTO; 613 } 614 | LFP 615 616 con: 617 LCONST 618 | LVAR 619 { 620 $$ = $1->value; 621 } 622 | '-' con 623 { 624 $$ = -$2; 625 } 626 | '+' con 627 { 628 $$ = $2; 629 } 630 | '~' con 631 { 632 $$ = ~$2; 633 } 634 | '(' expr ')' 635 { 636 $$ = $2; 637 } 638 639 expr: 640 con 641 | expr '+' expr 642 { 643 $$ = $1 + $3; 644 } 645 | expr '-' expr 646 { 647 $$ = $1 - $3; 648 } 649 | expr '*' expr 650 { 651 $$ = $1 * $3; 652 } 653 | expr '/' expr 654 { 655 $$ = $1 / $3; 656 } 657 | expr '%' expr 658 { 659 $$ = $1 % $3; 660 } 661 | expr '<' '<' expr 662 { 663 $$ = $1 << $4; 664 } 665 | expr '>' '>' expr 666 { 667 $$ = $1 >> $4; 668 } 669 | expr '&' expr 670 { 671 $$ = $1 & $3; 672 } 673 | expr '^' expr 674 { 675 $$ = $1 ^ $3; 676 } 677 | expr '|' expr 678 { 679 $$ = $1 | $3; 680 }