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