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