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