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