github.com/bgentry/go@v0.0.0-20150121062915-6cf5a733d54d/src/cmd/9a/a.y (about) 1 // cmd/9a/a.y from Vita Nuova. 2 // 3 // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. 4 // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) 5 // Portions Copyright © 1997-1999 Vita Nuova Limited 6 // Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com) 7 // Portions Copyright © 2004,2006 Bruce Ellis 8 // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) 9 // Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others 10 // Portions Copyright © 2009 The Go Authors. All rights reserved. 11 // 12 // Permission is hereby granted, free of charge, to any person obtaining a copy 13 // of this software and associated documentation files (the "Software"), to deal 14 // in the Software without restriction, including without limitation the rights 15 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 // copies of the Software, and to permit persons to whom the Software is 17 // furnished to do so, subject to the following conditions: 18 // 19 // The above copyright notice and this permission notice shall be included in 20 // all copies or substantial portions of the Software. 21 // 22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 28 // THE SOFTWARE. 29 30 %{ 31 #include <u.h> 32 #include <stdio.h> /* if we don't, bison will, and a.h re-#defines getc */ 33 #include <libc.h> 34 #include "a.h" 35 #include "../../runtime/funcdata.h" 36 %} 37 %union 38 { 39 Sym *sym; 40 vlong lval; 41 double dval; 42 char sval[8]; 43 Addr addr; 44 } 45 %left '|' 46 %left '^' 47 %left '&' 48 %left '<' '>' 49 %left '+' '-' 50 %left '*' '/' '%' 51 %token <lval> LMOVW LMOVB LABS LLOGW LSHW LADDW LCMP LCROP 52 %token <lval> LBRA LFMOV LFCONV LFCMP LFADD LFMA LTRAP LXORW 53 %token <lval> LNOP LEND LRETT LWORD LTEXT LDATA LRETRN 54 %token <lval> LCONST LSP LSB LFP LPC LCREG LFLUSH 55 %token <lval> LREG LFREG LR LCR LF LFPSCR 56 %token <lval> LLR LCTR LSPR LSPREG LSEG LMSR 57 %token <lval> LPCDAT LFUNCDAT LSCHED LXLD LXST LXOP LXMV 58 %token <lval> LRLWM LMOVMW LMOVEM LMOVFL LMTFSB LMA 59 %token <dval> LFCONST 60 %token <sval> LSCONST 61 %token <sym> LNAME LLAB LVAR 62 %type <lval> con expr pointer offset sreg 63 %type <addr> addr rreg regaddr name creg freg xlreg lr ctr 64 %type <addr> imm ximm fimm rel psr lcr cbit fpscr fpscrf msr mask 65 %% 66 prog: 67 | prog line 68 69 line: 70 LNAME ':' 71 { 72 $1 = labellookup($1); 73 if($1->type == LLAB && $1->value != pc) 74 yyerror("redeclaration of %s", $1->labelname); 75 $1->type = LLAB; 76 $1->value = pc; 77 } 78 line 79 | LNAME '=' expr ';' 80 { 81 $1->type = LVAR; 82 $1->value = $3; 83 } 84 | LVAR '=' expr ';' 85 { 86 if($1->value != $3) 87 yyerror("redeclaration of %s", $1->name); 88 $1->value = $3; 89 } 90 | LSCHED ';' 91 { 92 nosched = $1; 93 } 94 | ';' 95 | inst ';' 96 | error ';' 97 98 inst: 99 /* 100 * load ints and bytes 101 */ 102 LMOVW rreg ',' rreg 103 { 104 outcode($1, &$2, NREG, &$4); 105 } 106 | LMOVW addr ',' rreg 107 { 108 outcode($1, &$2, NREG, &$4); 109 } 110 | LMOVW regaddr ',' rreg 111 { 112 outcode($1, &$2, NREG, &$4); 113 } 114 | LMOVB rreg ',' rreg 115 { 116 outcode($1, &$2, NREG, &$4); 117 } 118 | LMOVB addr ',' rreg 119 { 120 outcode($1, &$2, NREG, &$4); 121 } 122 | LMOVB regaddr ',' rreg 123 { 124 outcode($1, &$2, NREG, &$4); 125 } 126 /* 127 * load floats 128 */ 129 | LFMOV addr ',' freg 130 { 131 outcode($1, &$2, NREG, &$4); 132 } 133 | LFMOV regaddr ',' freg 134 { 135 outcode($1, &$2, NREG, &$4); 136 } 137 | LFMOV fimm ',' freg 138 { 139 outcode($1, &$2, NREG, &$4); 140 } 141 | LFMOV freg ',' freg 142 { 143 outcode($1, &$2, NREG, &$4); 144 } 145 | LFMOV freg ',' addr 146 { 147 outcode($1, &$2, NREG, &$4); 148 } 149 | LFMOV freg ',' regaddr 150 { 151 outcode($1, &$2, NREG, &$4); 152 } 153 /* 154 * store ints and bytes 155 */ 156 | LMOVW rreg ',' addr 157 { 158 outcode($1, &$2, NREG, &$4); 159 } 160 | LMOVW rreg ',' regaddr 161 { 162 outcode($1, &$2, NREG, &$4); 163 } 164 | LMOVB rreg ',' addr 165 { 166 outcode($1, &$2, NREG, &$4); 167 } 168 | LMOVB rreg ',' regaddr 169 { 170 outcode($1, &$2, NREG, &$4); 171 } 172 /* 173 * store floats 174 */ 175 | LMOVW freg ',' addr 176 { 177 outcode($1, &$2, NREG, &$4); 178 } 179 | LMOVW freg ',' regaddr 180 { 181 outcode($1, &$2, NREG, &$4); 182 } 183 /* 184 * floating point status 185 */ 186 | LMOVW fpscr ',' freg 187 { 188 outcode($1, &$2, NREG, &$4); 189 } 190 | LMOVW freg ',' fpscr 191 { 192 outcode($1, &$2, NREG, &$4); 193 } 194 | LMOVW freg ',' imm ',' fpscr 195 { 196 outgcode($1, &$2, NREG, &$4, &$6); 197 } 198 | LMOVW fpscr ',' creg 199 { 200 outcode($1, &$2, NREG, &$4); 201 } 202 | LMOVW imm ',' fpscrf 203 { 204 outcode($1, &$2, NREG, &$4); 205 } 206 | LMTFSB imm ',' con 207 { 208 outcode($1, &$2, $4, &nullgen); 209 } 210 /* 211 * field moves (mtcrf) 212 */ 213 | LMOVW rreg ',' imm ',' lcr 214 { 215 outgcode($1, &$2, NREG, &$4, &$6); 216 } 217 | LMOVW rreg ',' creg 218 { 219 outcode($1, &$2, NREG, &$4); 220 } 221 | LMOVW rreg ',' lcr 222 { 223 outcode($1, &$2, NREG, &$4); 224 } 225 /* 226 * integer operations 227 * logical instructions 228 * shift instructions 229 * unary instructions 230 */ 231 | LADDW rreg ',' sreg ',' rreg 232 { 233 outcode($1, &$2, $4, &$6); 234 } 235 | LADDW imm ',' sreg ',' rreg 236 { 237 outcode($1, &$2, $4, &$6); 238 } 239 | LADDW rreg ',' imm ',' rreg 240 { 241 outgcode($1, &$2, NREG, &$4, &$6); 242 } 243 | LADDW rreg ',' rreg 244 { 245 outcode($1, &$2, NREG, &$4); 246 } 247 | LADDW imm ',' rreg 248 { 249 outcode($1, &$2, NREG, &$4); 250 } 251 | LLOGW rreg ',' sreg ',' rreg 252 { 253 outcode($1, &$2, $4, &$6); 254 } 255 | LLOGW rreg ',' rreg 256 { 257 outcode($1, &$2, NREG, &$4); 258 } 259 | LSHW rreg ',' sreg ',' rreg 260 { 261 outcode($1, &$2, $4, &$6); 262 } 263 | LSHW rreg ',' rreg 264 { 265 outcode($1, &$2, NREG, &$4); 266 } 267 | LSHW imm ',' sreg ',' rreg 268 { 269 outcode($1, &$2, $4, &$6); 270 } 271 | LSHW imm ',' rreg 272 { 273 outcode($1, &$2, NREG, &$4); 274 } 275 | LABS rreg ',' rreg 276 { 277 outcode($1, &$2, NREG, &$4); 278 } 279 | LABS rreg 280 { 281 outcode($1, &$2, NREG, &$2); 282 } 283 /* 284 * multiply-accumulate 285 */ 286 | LMA rreg ',' sreg ',' rreg 287 { 288 outcode($1, &$2, $4, &$6); 289 } 290 /* 291 * move immediate: macro for cau+or, addi, addis, and other combinations 292 */ 293 | LMOVW imm ',' rreg 294 { 295 outcode($1, &$2, NREG, &$4); 296 } 297 | LMOVW ximm ',' rreg 298 { 299 outcode($1, &$2, NREG, &$4); 300 } 301 /* 302 * condition register operations 303 */ 304 | LCROP cbit ',' cbit 305 { 306 outcode($1, &$2, $4.reg, &$4); 307 } 308 | LCROP cbit ',' con ',' cbit 309 { 310 outcode($1, &$2, $4, &$6); 311 } 312 /* 313 * condition register moves 314 * move from machine state register 315 */ 316 | LMOVW creg ',' creg 317 { 318 outcode($1, &$2, NREG, &$4); 319 } 320 | LMOVW psr ',' creg 321 { 322 outcode($1, &$2, NREG, &$4); 323 } 324 | LMOVW lcr ',' rreg 325 { 326 outcode($1, &$2, NREG, &$4); 327 } 328 | LMOVW psr ',' rreg 329 { 330 outcode($1, &$2, NREG, &$4); 331 } 332 | LMOVW xlreg ',' rreg 333 { 334 outcode($1, &$2, NREG, &$4); 335 } 336 | LMOVW rreg ',' xlreg 337 { 338 outcode($1, &$2, NREG, &$4); 339 } 340 | LMOVW creg ',' psr 341 { 342 outcode($1, &$2, NREG, &$4); 343 } 344 | LMOVW rreg ',' psr 345 { 346 outcode($1, &$2, NREG, &$4); 347 } 348 /* 349 * branch, branch conditional 350 * branch conditional register 351 * branch conditional to count register 352 */ 353 | LBRA rel 354 { 355 outcode($1, &nullgen, NREG, &$2); 356 } 357 | LBRA addr 358 { 359 outcode($1, &nullgen, NREG, &$2); 360 } 361 | LBRA '(' xlreg ')' 362 { 363 outcode($1, &nullgen, NREG, &$3); 364 } 365 | LBRA ',' rel 366 { 367 outcode($1, &nullgen, NREG, &$3); 368 } 369 | LBRA ',' addr 370 { 371 outcode($1, &nullgen, NREG, &$3); 372 } 373 | LBRA ',' '(' xlreg ')' 374 { 375 outcode($1, &nullgen, NREG, &$4); 376 } 377 | LBRA creg ',' rel 378 { 379 outcode($1, &$2, NREG, &$4); 380 } 381 | LBRA creg ',' addr 382 { 383 outcode($1, &$2, NREG, &$4); 384 } 385 | LBRA creg ',' '(' xlreg ')' 386 { 387 outcode($1, &$2, NREG, &$5); 388 } 389 | LBRA con ',' rel 390 { 391 outcode($1, &nullgen, $2, &$4); 392 } 393 | LBRA con ',' addr 394 { 395 outcode($1, &nullgen, $2, &$4); 396 } 397 | LBRA con ',' '(' xlreg ')' 398 { 399 outcode($1, &nullgen, $2, &$5); 400 } 401 | LBRA con ',' con ',' rel 402 { 403 Addr g; 404 g = nullgen; 405 g.type = D_CONST; 406 g.offset = $2; 407 outcode($1, &g, $4, &$6); 408 } 409 | LBRA con ',' con ',' addr 410 { 411 Addr g; 412 g = nullgen; 413 g.type = D_CONST; 414 g.offset = $2; 415 outcode($1, &g, $4, &$6); 416 } 417 | LBRA con ',' con ',' '(' xlreg ')' 418 { 419 Addr g; 420 g = nullgen; 421 g.type = D_CONST; 422 g.offset = $2; 423 outcode($1, &g, $4, &$7); 424 } 425 /* 426 * conditional trap 427 */ 428 | LTRAP rreg ',' sreg 429 { 430 outcode($1, &$2, $4, &nullgen); 431 } 432 | LTRAP imm ',' sreg 433 { 434 outcode($1, &$2, $4, &nullgen); 435 } 436 | LTRAP rreg comma 437 { 438 outcode($1, &$2, NREG, &nullgen); 439 } 440 | LTRAP comma 441 { 442 outcode($1, &nullgen, NREG, &nullgen); 443 } 444 /* 445 * floating point operate 446 */ 447 | LFCONV freg ',' freg 448 { 449 outcode($1, &$2, NREG, &$4); 450 } 451 | LFADD freg ',' freg 452 { 453 outcode($1, &$2, NREG, &$4); 454 } 455 | LFADD freg ',' freg ',' freg 456 { 457 outcode($1, &$2, $4.reg, &$6); 458 } 459 | LFMA freg ',' freg ',' freg ',' freg 460 { 461 outgcode($1, &$2, $4.reg, &$6, &$8); 462 } 463 | LFCMP freg ',' freg 464 { 465 outcode($1, &$2, NREG, &$4); 466 } 467 | LFCMP freg ',' freg ',' creg 468 { 469 outcode($1, &$2, $6.reg, &$4); 470 } 471 /* 472 * CMP 473 */ 474 | LCMP rreg ',' rreg 475 { 476 outcode($1, &$2, NREG, &$4); 477 } 478 | LCMP rreg ',' imm 479 { 480 outcode($1, &$2, NREG, &$4); 481 } 482 | LCMP rreg ',' rreg ',' creg 483 { 484 outcode($1, &$2, $6.reg, &$4); 485 } 486 | LCMP rreg ',' imm ',' creg 487 { 488 outcode($1, &$2, $6.reg, &$4); 489 } 490 /* 491 * rotate and mask 492 */ 493 | LRLWM imm ',' rreg ',' imm ',' rreg 494 { 495 outgcode($1, &$2, $4.reg, &$6, &$8); 496 } 497 | LRLWM imm ',' rreg ',' mask ',' rreg 498 { 499 outgcode($1, &$2, $4.reg, &$6, &$8); 500 } 501 | LRLWM rreg ',' rreg ',' imm ',' rreg 502 { 503 outgcode($1, &$2, $4.reg, &$6, &$8); 504 } 505 | LRLWM rreg ',' rreg ',' mask ',' rreg 506 { 507 outgcode($1, &$2, $4.reg, &$6, &$8); 508 } 509 /* 510 * load/store multiple 511 */ 512 | LMOVMW addr ',' rreg 513 { 514 outcode($1, &$2, NREG, &$4); 515 } 516 | LMOVMW rreg ',' addr 517 { 518 outcode($1, &$2, NREG, &$4); 519 } 520 /* 521 * various indexed load/store 522 * indexed unary (eg, cache clear) 523 */ 524 | LXLD regaddr ',' rreg 525 { 526 outcode($1, &$2, NREG, &$4); 527 } 528 | LXLD regaddr ',' imm ',' rreg 529 { 530 outgcode($1, &$2, NREG, &$4, &$6); 531 } 532 | LXST rreg ',' regaddr 533 { 534 outcode($1, &$2, NREG, &$4); 535 } 536 | LXST rreg ',' imm ',' regaddr 537 { 538 outgcode($1, &$2, NREG, &$4, &$6); 539 } 540 | LXMV regaddr ',' rreg 541 { 542 outcode($1, &$2, NREG, &$4); 543 } 544 | LXMV rreg ',' regaddr 545 { 546 outcode($1, &$2, NREG, &$4); 547 } 548 | LXOP regaddr 549 { 550 outcode($1, &$2, NREG, &nullgen); 551 } 552 /* 553 * NOP 554 */ 555 | LNOP comma 556 { 557 outcode($1, &nullgen, NREG, &nullgen); 558 } 559 | LNOP rreg comma 560 { 561 outcode($1, &$2, NREG, &nullgen); 562 } 563 | LNOP freg comma 564 { 565 outcode($1, &$2, NREG, &nullgen); 566 } 567 | LNOP ',' rreg 568 { 569 outcode($1, &nullgen, NREG, &$3); 570 } 571 | LNOP ',' freg 572 { 573 outcode($1, &nullgen, NREG, &$3); 574 } 575 | LNOP imm /* SYSCALL $num: load $num to R0 before syscall and restore R0 to 0 afterwards. */ 576 { 577 outcode($1, &$2, NREG, &nullgen); 578 } 579 /* 580 * word 581 */ 582 | LWORD imm comma 583 { 584 outcode($1, &$2, NREG, &nullgen); 585 } 586 | LWORD ximm comma 587 { 588 outcode($1, &$2, NREG, &nullgen); 589 } 590 /* 591 * PCDATA 592 */ 593 | LPCDAT imm ',' imm 594 { 595 if($2.type != D_CONST || $4.type != D_CONST) 596 yyerror("arguments to PCDATA must be integer constants"); 597 outcode($1, &$2, NREG, &$4); 598 } 599 /* 600 * FUNCDATA 601 */ 602 | LFUNCDAT imm ',' addr 603 { 604 if($2.type != D_CONST) 605 yyerror("index for FUNCDATA must be integer constant"); 606 if($4.type != D_EXTERN && $4.type != D_STATIC && $4.type != D_OREG) 607 yyerror("value for FUNCDATA must be symbol reference"); 608 outcode($1, &$2, NREG, &$4); 609 } 610 /* 611 * END 612 */ 613 | LEND comma 614 { 615 outcode($1, &nullgen, NREG, &nullgen); 616 } 617 /* 618 * TEXT/GLOBL 619 */ 620 | LTEXT name ',' imm 621 { 622 settext($2.sym); 623 outcode($1, &$2, NREG, &$4); 624 } 625 | LTEXT name ',' con ',' imm 626 { 627 settext($2.sym); 628 $6.offset &= 0xffffffffull; 629 $6.offset |= (vlong)ArgsSizeUnknown << 32; 630 outcode($1, &$2, $4, &$6); 631 } 632 | LTEXT name ',' con ',' imm '-' con 633 { 634 settext($2.sym); 635 $6.offset &= 0xffffffffull; 636 $6.offset |= ($8 & 0xffffffffull) << 32; 637 outcode($1, &$2, $4, &$6); 638 } 639 /* 640 * DATA 641 */ 642 | LDATA name '/' con ',' imm 643 { 644 outcode($1, &$2, $4, &$6); 645 } 646 | LDATA name '/' con ',' ximm 647 { 648 outcode($1, &$2, $4, &$6); 649 } 650 | LDATA name '/' con ',' fimm 651 { 652 outcode($1, &$2, $4, &$6); 653 } 654 /* 655 * RETURN 656 */ 657 | LRETRN comma 658 { 659 outcode($1, &nullgen, NREG, &nullgen); 660 } 661 662 rel: 663 con '(' LPC ')' 664 { 665 $$ = nullgen; 666 $$.type = D_BRANCH; 667 $$.offset = $1 + pc; 668 } 669 | LNAME offset 670 { 671 $1 = labellookup($1); 672 $$ = nullgen; 673 if(pass == 2 && $1->type != LLAB) 674 yyerror("undefined label: %s", $1->labelname); 675 $$.type = D_BRANCH; 676 $$.offset = $1->value + $2; 677 } 678 679 rreg: 680 sreg 681 { 682 $$ = nullgen; 683 $$.type = D_REG; 684 $$.reg = $1; 685 } 686 687 xlreg: 688 lr 689 | ctr 690 691 lr: 692 LLR 693 { 694 $$ = nullgen; 695 $$.type = D_SPR; 696 $$.offset = $1; 697 } 698 699 lcr: 700 LCR 701 { 702 $$ = nullgen; 703 $$.type = D_CREG; 704 $$.reg = NREG; /* whole register */ 705 } 706 707 ctr: 708 LCTR 709 { 710 $$ = nullgen; 711 $$.type = D_SPR; 712 $$.offset = $1; 713 } 714 715 msr: 716 LMSR 717 { 718 $$ = nullgen; 719 $$.type = D_MSR; 720 } 721 722 psr: 723 LSPREG 724 { 725 $$ = nullgen; 726 $$.type = D_SPR; 727 $$.offset = $1; 728 } 729 | LSPR '(' con ')' 730 { 731 $$ = nullgen; 732 $$.type = $1; 733 $$.offset = $3; 734 } 735 | msr 736 737 fpscr: 738 LFPSCR 739 { 740 $$ = nullgen; 741 $$.type = D_FPSCR; 742 $$.reg = NREG; 743 } 744 745 fpscrf: 746 LFPSCR '(' con ')' 747 { 748 $$ = nullgen; 749 $$.type = D_FPSCR; 750 $$.reg = $3; 751 } 752 753 freg: 754 LFREG 755 { 756 $$ = nullgen; 757 $$.type = D_FREG; 758 $$.reg = $1; 759 } 760 | LF '(' con ')' 761 { 762 $$ = nullgen; 763 $$.type = D_FREG; 764 $$.reg = $3; 765 } 766 767 creg: 768 LCREG 769 { 770 $$ = nullgen; 771 $$.type = D_CREG; 772 $$.reg = $1; 773 } 774 | LCR '(' con ')' 775 { 776 $$ = nullgen; 777 $$.type = D_CREG; 778 $$.reg = $3; 779 } 780 781 782 cbit: con 783 { 784 $$ = nullgen; 785 $$.type = D_REG; 786 $$.reg = $1; 787 } 788 789 mask: 790 con ',' con 791 { 792 int mb, me; 793 uint32 v; 794 795 $$ = nullgen; 796 $$.type = D_CONST; 797 mb = $1; 798 me = $3; 799 if(mb < 0 || mb > 31 || me < 0 || me > 31){ 800 yyerror("illegal mask start/end value(s)"); 801 mb = me = 0; 802 } 803 if(mb <= me) 804 v = ((uint32)~0L>>mb) & (~0L<<(31-me)); 805 else 806 v = ~(((uint32)~0L>>(me+1)) & (~0L<<(31-(mb-1)))); 807 $$.offset = v; 808 } 809 810 ximm: 811 '$' addr 812 { 813 $$ = $2; 814 $$.type = D_CONST; 815 } 816 | '$' LSCONST 817 { 818 $$ = nullgen; 819 $$.type = D_SCONST; 820 memcpy($$.u.sval, $2, sizeof($$.u.sval)); 821 } 822 823 fimm: 824 '$' LFCONST 825 { 826 $$ = nullgen; 827 $$.type = D_FCONST; 828 $$.u.dval = $2; 829 } 830 | '$' '-' LFCONST 831 { 832 $$ = nullgen; 833 $$.type = D_FCONST; 834 $$.u.dval = -$3; 835 } 836 837 imm: '$' con 838 { 839 $$ = nullgen; 840 $$.type = D_CONST; 841 $$.offset = $2; 842 } 843 844 sreg: 845 LREG 846 | LR '(' con ')' 847 { 848 if($$ < 0 || $$ >= NREG) 849 print("register value out of range\n"); 850 $$ = $3; 851 } 852 853 regaddr: 854 '(' sreg ')' 855 { 856 $$ = nullgen; 857 $$.type = D_OREG; 858 $$.reg = $2; 859 $$.offset = 0; 860 } 861 | '(' sreg '+' sreg ')' 862 { 863 $$ = nullgen; 864 $$.type = D_OREG; 865 $$.reg = $2; 866 $$.scale = $4; 867 $$.offset = 0; 868 } 869 870 addr: 871 name 872 | con '(' sreg ')' 873 { 874 $$ = nullgen; 875 $$.type = D_OREG; 876 $$.reg = $3; 877 $$.offset = $1; 878 } 879 880 name: 881 con '(' pointer ')' 882 { 883 $$ = nullgen; 884 $$.type = D_OREG; 885 $$.name = $3; 886 $$.sym = nil; 887 $$.offset = $1; 888 } 889 | LNAME offset '(' pointer ')' 890 { 891 $$ = nullgen; 892 $$.type = D_OREG; 893 $$.name = $4; 894 $$.sym = linklookup(ctxt, $1->name, 0); 895 $$.offset = $2; 896 } 897 | LNAME '<' '>' offset '(' LSB ')' 898 { 899 $$ = nullgen; 900 $$.type = D_OREG; 901 $$.name = D_STATIC; 902 $$.sym = linklookup(ctxt, $1->name, 0); 903 $$.offset = $4; 904 } 905 906 comma: 907 | ',' 908 909 offset: 910 { 911 $$ = 0; 912 } 913 | '+' con 914 { 915 $$ = $2; 916 } 917 | '-' con 918 { 919 $$ = -$2; 920 } 921 922 pointer: 923 LSB 924 | LSP 925 | LFP 926 927 con: 928 LCONST 929 | LVAR 930 { 931 $$ = $1->value; 932 } 933 | '-' con 934 { 935 $$ = -$2; 936 } 937 | '+' con 938 { 939 $$ = $2; 940 } 941 | '~' con 942 { 943 $$ = ~$2; 944 } 945 | '(' expr ')' 946 { 947 $$ = $2; 948 } 949 950 expr: 951 con 952 | expr '+' expr 953 { 954 $$ = $1 + $3; 955 } 956 | expr '-' expr 957 { 958 $$ = $1 - $3; 959 } 960 | expr '*' expr 961 { 962 $$ = $1 * $3; 963 } 964 | expr '/' expr 965 { 966 $$ = $1 / $3; 967 } 968 | expr '%' expr 969 { 970 $$ = $1 % $3; 971 } 972 | expr '<' '<' expr 973 { 974 $$ = $1 << $4; 975 } 976 | expr '>' '>' expr 977 { 978 $$ = $1 >> $4; 979 } 980 | expr '&' expr 981 { 982 $$ = $1 & $3; 983 } 984 | expr '^' expr 985 { 986 $$ = $1 ^ $3; 987 } 988 | expr '|' expr 989 { 990 $$ = $1 | $3; 991 }