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