github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/cmd/5a/a.y (about) 1 // Inferno utils/5a/a.y 2 // http://code.google.com/p/inferno-os/source/browse/utils/5a/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 { 39 Sym *sym; 40 int32 lval; 41 double dval; 42 char sval[8]; 43 Gen gen; 44 } 45 %left '|' 46 %left '^' 47 %left '&' 48 %left '<' '>' 49 %left '+' '-' 50 %left '*' '/' '%' 51 %token <lval> LTYPE1 LTYPE2 LTYPE3 LTYPE4 LTYPE5 52 %token <lval> LTYPE6 LTYPE7 LTYPE8 LTYPE9 LTYPEA 53 %token <lval> LTYPEB LTYPEC LTYPED LTYPEE LTYPEF 54 %token <lval> LTYPEG LTYPEH LTYPEI LTYPEJ LTYPEK 55 %token <lval> LTYPEL LTYPEM LTYPEN LTYPEBX LTYPEPLD 56 %token <lval> LCONST LSP LSB LFP LPC 57 %token <lval> LTYPEX LR LREG LF LFREG LC LCREG LPSR LFCR 58 %token <lval> LCOND LS LAT 59 %token <dval> LFCONST 60 %token <sval> LSCONST 61 %token <sym> LNAME LLAB LVAR 62 %type <lval> con expr oexpr pointer offset sreg spreg creg 63 %type <lval> rcon cond reglist 64 %type <gen> gen rel reg regreg freg shift fcon frcon 65 %type <gen> imm ximm name oreg ireg nireg ioreg imsr 66 %% 67 prog: 68 | prog 69 { 70 stmtline = lineno; 71 } 72 line 73 74 line: 75 LLAB ':' 76 { 77 if($1->value != pc) 78 yyerror("redeclaration of %s", $1->name); 79 $1->value = pc; 80 } 81 line 82 | LNAME ':' 83 { 84 $1->type = LLAB; 85 $1->value = pc; 86 } 87 line 88 | LNAME '=' expr ';' 89 { 90 $1->type = LVAR; 91 $1->value = $3; 92 } 93 | LVAR '=' expr ';' 94 { 95 if($1->value != $3) 96 yyerror("redeclaration of %s", $1->name); 97 $1->value = $3; 98 } 99 | ';' 100 | inst ';' 101 | error ';' 102 103 inst: 104 /* 105 * ADD 106 */ 107 LTYPE1 cond imsr ',' spreg ',' reg 108 { 109 outcode($1, $2, &$3, $5, &$7); 110 } 111 | LTYPE1 cond imsr ',' spreg ',' 112 { 113 outcode($1, $2, &$3, $5, &nullgen); 114 } 115 | LTYPE1 cond imsr ',' reg 116 { 117 outcode($1, $2, &$3, NREG, &$5); 118 } 119 /* 120 * MVN 121 */ 122 | LTYPE2 cond imsr ',' reg 123 { 124 outcode($1, $2, &$3, NREG, &$5); 125 } 126 /* 127 * MOVW 128 */ 129 | LTYPE3 cond gen ',' gen 130 { 131 outcode($1, $2, &$3, NREG, &$5); 132 } 133 /* 134 * B/BL 135 */ 136 | LTYPE4 cond comma rel 137 { 138 outcode($1, $2, &nullgen, NREG, &$4); 139 } 140 | LTYPE4 cond comma nireg 141 { 142 outcode($1, $2, &nullgen, NREG, &$4); 143 } 144 /* 145 * BX 146 */ 147 | LTYPEBX comma ireg 148 { 149 outcode($1, Always, &nullgen, NREG, &$3); 150 } 151 /* 152 * BEQ 153 */ 154 | LTYPE5 comma rel 155 { 156 outcode($1, Always, &nullgen, NREG, &$3); 157 } 158 /* 159 * SWI 160 */ 161 | LTYPE6 cond comma gen 162 { 163 outcode($1, $2, &nullgen, NREG, &$4); 164 } 165 /* 166 * CMP 167 */ 168 | LTYPE7 cond imsr ',' spreg comma 169 { 170 outcode($1, $2, &$3, $5, &nullgen); 171 } 172 /* 173 * MOVM 174 */ 175 | LTYPE8 cond ioreg ',' '[' reglist ']' 176 { 177 Gen g; 178 179 g = nullgen; 180 g.type = D_CONST; 181 g.offset = $6; 182 outcode($1, $2, &$3, NREG, &g); 183 } 184 | LTYPE8 cond '[' reglist ']' ',' ioreg 185 { 186 Gen g; 187 188 g = nullgen; 189 g.type = D_CONST; 190 g.offset = $4; 191 outcode($1, $2, &g, NREG, &$7); 192 } 193 /* 194 * SWAP 195 */ 196 | LTYPE9 cond reg ',' ireg ',' reg 197 { 198 outcode($1, $2, &$5, $3.reg, &$7); 199 } 200 | LTYPE9 cond reg ',' ireg comma 201 { 202 outcode($1, $2, &$5, $3.reg, &$3); 203 } 204 | LTYPE9 cond comma ireg ',' reg 205 { 206 outcode($1, $2, &$4, $6.reg, &$6); 207 } 208 /* 209 * RET 210 */ 211 | LTYPEA cond comma 212 { 213 outcode($1, $2, &nullgen, NREG, &nullgen); 214 } 215 /* 216 * TEXT/GLOBL 217 */ 218 | LTYPEB name ',' imm 219 { 220 outcode($1, Always, &$2, 0, &$4); 221 } 222 | LTYPEB name ',' con ',' imm 223 { 224 outcode($1, Always, &$2, $4, &$6); 225 } 226 /* 227 * DATA 228 */ 229 | LTYPEC name '/' con ',' ximm 230 { 231 outcode($1, Always, &$2, $4, &$6); 232 } 233 /* 234 * CASE 235 */ 236 | LTYPED cond reg comma 237 { 238 outcode($1, $2, &$3, NREG, &nullgen); 239 } 240 /* 241 * word 242 */ 243 | LTYPEH comma ximm 244 { 245 outcode($1, Always, &nullgen, NREG, &$3); 246 } 247 /* 248 * floating-point coprocessor 249 */ 250 | LTYPEI cond freg ',' freg 251 { 252 outcode($1, $2, &$3, NREG, &$5); 253 } 254 | LTYPEK cond frcon ',' freg 255 { 256 outcode($1, $2, &$3, NREG, &$5); 257 } 258 | LTYPEK cond frcon ',' LFREG ',' freg 259 { 260 outcode($1, $2, &$3, $5, &$7); 261 } 262 | LTYPEL cond freg ',' freg comma 263 { 264 outcode($1, $2, &$3, $5.reg, &nullgen); 265 } 266 /* 267 * MCR MRC 268 */ 269 | LTYPEJ cond con ',' expr ',' spreg ',' creg ',' creg oexpr 270 { 271 Gen g; 272 273 g = nullgen; 274 g.type = D_CONST; 275 g.offset = 276 (0xe << 24) | /* opcode */ 277 ($1 << 20) | /* MCR/MRC */ 278 ($2 << 28) | /* scond */ 279 (($3 & 15) << 8) | /* coprocessor number */ 280 (($5 & 7) << 21) | /* coprocessor operation */ 281 (($7 & 15) << 12) | /* arm register */ 282 (($9 & 15) << 16) | /* Crn */ 283 (($11 & 15) << 0) | /* Crm */ 284 (($12 & 7) << 5) | /* coprocessor information */ 285 (1<<4); /* must be set */ 286 outcode(AWORD, Always, &nullgen, NREG, &g); 287 } 288 /* 289 * MULL r1,r2,(hi,lo) 290 */ 291 | LTYPEM cond reg ',' reg ',' regreg 292 { 293 outcode($1, $2, &$3, $5.reg, &$7); 294 } 295 /* 296 * MULA r1,r2,r3,r4: (r1*r2+r3) & 0xffffffff -> r4 297 * MULAW{T,B} r1,r2,r3,r4 298 */ 299 | LTYPEN cond reg ',' reg ',' reg ',' spreg 300 { 301 $7.type = D_REGREG2; 302 $7.offset = $9; 303 outcode($1, $2, &$3, $5.reg, &$7); 304 } 305 /* 306 * PLD 307 */ 308 | LTYPEPLD oreg 309 { 310 outcode($1, Always, &$2, NREG, &nullgen); 311 } 312 /* 313 * END 314 */ 315 | LTYPEE comma 316 { 317 outcode($1, Always, &nullgen, NREG, &nullgen); 318 } 319 320 cond: 321 { 322 $$ = Always; 323 } 324 | cond LCOND 325 { 326 $$ = ($1 & ~C_SCOND) | $2; 327 } 328 | cond LS 329 { 330 $$ = $1 | $2; 331 } 332 333 comma: 334 | ',' comma 335 336 rel: 337 con '(' LPC ')' 338 { 339 $$ = nullgen; 340 $$.type = D_BRANCH; 341 $$.offset = $1 + pc; 342 } 343 | LNAME offset 344 { 345 $$ = nullgen; 346 if(pass == 2) 347 yyerror("undefined label: %s", $1->name); 348 $$.type = D_BRANCH; 349 $$.sym = $1; 350 $$.offset = $2; 351 } 352 | LLAB offset 353 { 354 $$ = nullgen; 355 $$.type = D_BRANCH; 356 $$.sym = $1; 357 $$.offset = $1->value + $2; 358 } 359 360 ximm: '$' con 361 { 362 $$ = nullgen; 363 $$.type = D_CONST; 364 $$.offset = $2; 365 } 366 | '$' oreg 367 { 368 $$ = $2; 369 $$.type = D_CONST; 370 } 371 | '$' '*' '$' oreg 372 { 373 $$ = $4; 374 $$.type = D_OCONST; 375 } 376 | '$' LSCONST 377 { 378 $$ = nullgen; 379 $$.type = D_SCONST; 380 memcpy($$.sval, $2, sizeof($$.sval)); 381 } 382 | fcon 383 384 fcon: 385 '$' LFCONST 386 { 387 $$ = nullgen; 388 $$.type = D_FCONST; 389 $$.dval = $2; 390 } 391 | '$' '-' LFCONST 392 { 393 $$ = nullgen; 394 $$.type = D_FCONST; 395 $$.dval = -$3; 396 } 397 398 reglist: 399 spreg 400 { 401 $$ = 1 << $1; 402 } 403 | spreg '-' spreg 404 { 405 int i; 406 $$=0; 407 for(i=$1; i<=$3; i++) 408 $$ |= 1<<i; 409 for(i=$3; i<=$1; i++) 410 $$ |= 1<<i; 411 } 412 | spreg comma reglist 413 { 414 $$ = (1<<$1) | $3; 415 } 416 417 gen: 418 reg 419 | ximm 420 | shift 421 | shift '(' spreg ')' 422 { 423 $$ = $1; 424 $$.reg = $3; 425 } 426 | LPSR 427 { 428 $$ = nullgen; 429 $$.type = D_PSR; 430 $$.reg = $1; 431 } 432 | LFCR 433 { 434 $$ = nullgen; 435 $$.type = D_FPCR; 436 $$.reg = $1; 437 } 438 | con 439 { 440 $$ = nullgen; 441 $$.type = D_OREG; 442 $$.offset = $1; 443 } 444 | oreg 445 | freg 446 447 nireg: 448 ireg 449 | name 450 { 451 $$ = $1; 452 if($1.name != D_EXTERN && $1.name != D_STATIC) { 453 } 454 } 455 456 ireg: 457 '(' spreg ')' 458 { 459 $$ = nullgen; 460 $$.type = D_OREG; 461 $$.reg = $2; 462 $$.offset = 0; 463 } 464 465 ioreg: 466 ireg 467 | con '(' sreg ')' 468 { 469 $$ = nullgen; 470 $$.type = D_OREG; 471 $$.reg = $3; 472 $$.offset = $1; 473 } 474 475 oreg: 476 name 477 | name '(' sreg ')' 478 { 479 $$ = $1; 480 $$.type = D_OREG; 481 $$.reg = $3; 482 } 483 | ioreg 484 485 imsr: 486 reg 487 | imm 488 | shift 489 490 imm: '$' con 491 { 492 $$ = nullgen; 493 $$.type = D_CONST; 494 $$.offset = $2; 495 } 496 497 reg: 498 spreg 499 { 500 $$ = nullgen; 501 $$.type = D_REG; 502 $$.reg = $1; 503 } 504 505 regreg: 506 '(' spreg ',' spreg ')' 507 { 508 $$ = nullgen; 509 $$.type = D_REGREG; 510 $$.reg = $2; 511 $$.offset = $4; 512 } 513 514 shift: 515 spreg '<' '<' rcon 516 { 517 $$ = nullgen; 518 $$.type = D_SHIFT; 519 $$.offset = $1 | $4 | (0 << 5); 520 } 521 | spreg '>' '>' rcon 522 { 523 $$ = nullgen; 524 $$.type = D_SHIFT; 525 $$.offset = $1 | $4 | (1 << 5); 526 } 527 | spreg '-' '>' rcon 528 { 529 $$ = nullgen; 530 $$.type = D_SHIFT; 531 $$.offset = $1 | $4 | (2 << 5); 532 } 533 | spreg LAT '>' rcon 534 { 535 $$ = nullgen; 536 $$.type = D_SHIFT; 537 $$.offset = $1 | $4 | (3 << 5); 538 } 539 540 rcon: 541 spreg 542 { 543 if($$ < 0 || $$ >= 16) 544 print("register value out of range\n"); 545 $$ = (($1&15) << 8) | (1 << 4); 546 } 547 | con 548 { 549 if($$ < 0 || $$ >= 32) 550 print("shift value out of range\n"); 551 $$ = ($1&31) << 7; 552 } 553 554 sreg: 555 LREG 556 | LPC 557 { 558 $$ = REGPC; 559 } 560 | LR '(' expr ')' 561 { 562 if($3 < 0 || $3 >= NREG) 563 print("register value out of range\n"); 564 $$ = $3; 565 } 566 567 spreg: 568 sreg 569 | LSP 570 { 571 $$ = REGSP; 572 } 573 574 creg: 575 LCREG 576 | LC '(' expr ')' 577 { 578 if($3 < 0 || $3 >= NREG) 579 print("register value out of range\n"); 580 $$ = $3; 581 } 582 583 frcon: 584 freg 585 | fcon 586 587 freg: 588 LFREG 589 { 590 $$ = nullgen; 591 $$.type = D_FREG; 592 $$.reg = $1; 593 } 594 | LF '(' con ')' 595 { 596 $$ = nullgen; 597 $$.type = D_FREG; 598 $$.reg = $3; 599 } 600 601 name: 602 con '(' pointer ')' 603 { 604 $$ = nullgen; 605 $$.type = D_OREG; 606 $$.name = $3; 607 $$.sym = S; 608 $$.offset = $1; 609 } 610 | LNAME offset '(' pointer ')' 611 { 612 $$ = nullgen; 613 $$.type = D_OREG; 614 $$.name = $4; 615 $$.sym = $1; 616 $$.offset = $2; 617 } 618 | LNAME '<' '>' offset '(' LSB ')' 619 { 620 $$ = nullgen; 621 $$.type = D_OREG; 622 $$.name = D_STATIC; 623 $$.sym = $1; 624 $$.offset = $4; 625 } 626 627 offset: 628 { 629 $$ = 0; 630 } 631 | '+' con 632 { 633 $$ = $2; 634 } 635 | '-' con 636 { 637 $$ = -$2; 638 } 639 640 pointer: 641 LSB 642 | LSP 643 | LFP 644 645 con: 646 LCONST 647 | LVAR 648 { 649 $$ = $1->value; 650 } 651 | '-' con 652 { 653 $$ = -$2; 654 } 655 | '+' con 656 { 657 $$ = $2; 658 } 659 | '~' con 660 { 661 $$ = ~$2; 662 } 663 | '(' expr ')' 664 { 665 $$ = $2; 666 } 667 668 oexpr: 669 { 670 $$ = 0; 671 } 672 | ',' expr 673 { 674 $$ = $2; 675 } 676 677 expr: 678 con 679 | expr '+' expr 680 { 681 $$ = $1 + $3; 682 } 683 | expr '-' expr 684 { 685 $$ = $1 - $3; 686 } 687 | expr '*' expr 688 { 689 $$ = $1 * $3; 690 } 691 | expr '/' expr 692 { 693 $$ = $1 / $3; 694 } 695 | expr '%' expr 696 { 697 $$ = $1 % $3; 698 } 699 | expr '<' '<' expr 700 { 701 $$ = $1 << $4; 702 } 703 | expr '>' '>' expr 704 { 705 $$ = $1 >> $4; 706 } 707 | expr '&' expr 708 { 709 $$ = $1 & $3; 710 } 711 | expr '^' expr 712 { 713 $$ = $1 ^ $3; 714 } 715 | expr '|' expr 716 { 717 $$ = $1 | $3; 718 }