rsc.io/go@v0.0.0-20150416155037-e040fd465409/src/cmd/old6a/a.y (about) 1 // Inferno utils/6a/a.y 2 // http://code.google.com/p/inferno-os/source/browse/utils/6a/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/x86" 38 ) 39 %} 40 41 %union { 42 sym *asm.Sym 43 lval int64 44 dval float64 45 sval string 46 addr obj.Addr 47 addr2 Addr2 48 } 49 50 %left '|' 51 %left '^' 52 %left '&' 53 %left '<' '>' 54 %left '+' '-' 55 %left '*' '/' '%' 56 %token <lval> LTYPE0 LTYPE1 LTYPE2 LTYPE3 LTYPE4 57 %token <lval> LTYPEC LTYPED LTYPEN LTYPER LTYPET LTYPEG LTYPEPC 58 %token <lval> LTYPES LTYPEM LTYPEI LTYPEXC LTYPEX LTYPERT LTYPEF 59 %token <lval> LCONST LFP LPC LSB 60 %token <lval> LBREG LLREG LSREG LFREG LMREG LXREG 61 %token <dval> LFCONST 62 %token <sval> LSCONST LSP 63 %token <sym> LNAME LLAB LVAR 64 %type <lval> con expr pointer offset 65 %type <addr> mem imm textsize reg nam rel rem rim rom omem nmem 66 %type <addr2> nonnon nonrel nonrem rimnon rimrem remrim 67 %type <addr2> spec3 spec4 spec5 spec6 spec7 spec8 spec9 68 %type <addr2> spec10 spec12 spec13 69 %% 70 prog: 71 | prog 72 { 73 stmtline = asm.Lineno; 74 } 75 line 76 77 line: 78 LNAME ':' 79 { 80 $1 = asm.LabelLookup($1); 81 if $1.Type == LLAB && $1.Value != int64(asm.PC) { 82 yyerror("redeclaration of %s (%s)", $1.Labelname, $1.Name); 83 } 84 $1.Type = LLAB; 85 $1.Value = int64(asm.PC) 86 } 87 line 88 | ';' 89 | inst ';' 90 | error ';' 91 92 inst: 93 LNAME '=' expr 94 { 95 $1.Type = LVAR; 96 $1.Value = $3; 97 } 98 | LVAR '=' expr 99 { 100 if $1.Value != $3 { 101 yyerror("redeclaration of %s", $1.Name); 102 } 103 $1.Value = $3; 104 } 105 | LTYPE0 nonnon { outcode(int($1), &$2); } 106 | LTYPE1 nonrem { outcode(int($1), &$2); } 107 | LTYPE2 rimnon { outcode(int($1), &$2); } 108 | LTYPE3 rimrem { outcode(int($1), &$2); } 109 | LTYPE4 remrim { outcode(int($1), &$2); } 110 | LTYPER nonrel { outcode(int($1), &$2); } 111 | spec1 112 | spec2 113 | LTYPEC spec3 { outcode(int($1), &$2); } 114 | LTYPEN spec4 { outcode(int($1), &$2); } 115 | LTYPES spec5 { outcode(int($1), &$2); } 116 | LTYPEM spec6 { outcode(int($1), &$2); } 117 | LTYPEI spec7 { outcode(int($1), &$2); } 118 | LTYPEXC spec8 { outcode(int($1), &$2); } 119 | LTYPEX spec9 { outcode(int($1), &$2); } 120 | LTYPERT spec10 { outcode(int($1), &$2); } 121 | spec11 122 | LTYPEPC spec12 { outcode(int($1), &$2); } 123 | LTYPEF spec13 { outcode(int($1), &$2); } 124 125 nonnon: 126 { 127 $$.from = nullgen; 128 $$.to = nullgen; 129 } 130 | ',' 131 { 132 $$.from = nullgen; 133 $$.to = nullgen; 134 } 135 136 rimrem: 137 rim ',' rem 138 { 139 $$.from = $1; 140 $$.to = $3; 141 } 142 143 remrim: 144 rem ',' rim 145 { 146 $$.from = $1; 147 $$.to = $3; 148 } 149 150 rimnon: 151 rim ',' 152 { 153 $$.from = $1; 154 $$.to = nullgen; 155 } 156 | rim 157 { 158 $$.from = $1; 159 $$.to = nullgen; 160 } 161 162 nonrem: 163 ',' rem 164 { 165 $$.from = nullgen; 166 $$.to = $2; 167 } 168 | rem 169 { 170 $$.from = nullgen; 171 $$.to = $1; 172 } 173 174 nonrel: 175 ',' rel 176 { 177 $$.from = nullgen; 178 $$.to = $2; 179 } 180 | rel 181 { 182 $$.from = nullgen; 183 $$.to = $1; 184 } 185 | imm ',' rel 186 { 187 $$.from = $1; 188 $$.to = $3; 189 } 190 191 spec1: /* DATA */ 192 LTYPED nam '/' con ',' imm 193 { 194 var a Addr2 195 a.from = $2 196 a.to = $6 197 outcode(obj.ADATA, &a) 198 if asm.Pass > 1 { 199 lastpc.From3.Type = obj.TYPE_CONST 200 lastpc.From3.Offset = $4 201 } 202 } 203 204 spec2: /* TEXT */ 205 LTYPET mem ',' '$' textsize 206 { 207 asm.Settext($2.Sym); 208 outcode(obj.ATEXT, &Addr2{from: $2, to: $5}) 209 } 210 | LTYPET mem ',' con ',' '$' textsize 211 { 212 asm.Settext($2.Sym); 213 outcode(obj.ATEXT, &Addr2{from: $2, to: $7}) 214 if asm.Pass > 1 { 215 lastpc.From3.Type = obj.TYPE_CONST 216 lastpc.From3.Offset = $4 217 } 218 } 219 220 spec11: /* GLOBL */ 221 LTYPEG mem ',' imm 222 { 223 asm.Settext($2.Sym) 224 outcode(obj.AGLOBL, &Addr2{from: $2, to: $4}) 225 } 226 | LTYPEG mem ',' con ',' imm 227 { 228 asm.Settext($2.Sym) 229 outcode(obj.AGLOBL, &Addr2{from: $2, to: $6}) 230 if asm.Pass > 1 { 231 lastpc.From3.Type = obj.TYPE_CONST 232 lastpc.From3.Offset = $4 233 } 234 } 235 236 spec3: /* JMP/CALL */ 237 ',' rom 238 { 239 $$.from = nullgen; 240 $$.to = $2; 241 } 242 | rom 243 { 244 $$.from = nullgen; 245 $$.to = $1; 246 } 247 248 spec4: /* NOP */ 249 nonnon 250 | nonrem 251 252 spec5: /* SHL/SHR */ 253 rim ',' rem 254 { 255 $$.from = $1; 256 $$.to = $3; 257 } 258 | rim ',' rem ':' LLREG 259 { 260 $$.from = $1; 261 $$.to = $3; 262 if $$.from.Index != obj.TYPE_NONE { 263 yyerror("dp shift with lhs index"); 264 } 265 $$.from.Index = int16($5); 266 } 267 268 spec6: /* MOVW/MOVL */ 269 rim ',' rem 270 { 271 $$.from = $1; 272 $$.to = $3; 273 } 274 | rim ',' rem ':' LSREG 275 { 276 $$.from = $1; 277 $$.to = $3; 278 if $$.to.Index != obj.TYPE_NONE { 279 yyerror("dp move with lhs index"); 280 } 281 $$.to.Index = int16($5); 282 } 283 284 spec7: 285 rim ',' 286 { 287 $$.from = $1; 288 $$.to = nullgen; 289 } 290 | rim 291 { 292 $$.from = $1; 293 $$.to = nullgen; 294 } 295 | rim ',' rem 296 { 297 $$.from = $1; 298 $$.to = $3; 299 } 300 301 spec8: /* CMPPS/CMPPD */ 302 rem ',' reg ',' con 303 { 304 $$.from = $1; 305 $$.from3 = $3; 306 $$.to.Type = obj.TYPE_MEM; // to give library something to do 307 $$.to.Offset = $5; 308 } 309 310 spec9: /* shufl */ 311 imm ',' rem ',' reg 312 { 313 $$.from = $1; 314 $$.from3 = $3; 315 $$.to = $5; 316 } 317 318 spec10: /* RET/RETF */ 319 { 320 $$.from = nullgen; 321 $$.to = nullgen; 322 } 323 | imm 324 { 325 $$.from = $1; 326 $$.to = nullgen; 327 } 328 329 spec12: /* asm.PCDATA */ 330 rim ',' rim 331 { 332 if $1.Type != obj.TYPE_CONST || $3.Type != obj.TYPE_CONST { 333 yyerror("arguments to asm.PCDATA must be integer constants"); 334 } 335 $$.from = $1; 336 $$.to = $3; 337 } 338 339 spec13: /* FUNCDATA */ 340 rim ',' rim 341 { 342 if $1.Type != obj.TYPE_CONST { 343 yyerror("index for FUNCDATA must be integer constant"); 344 } 345 if $3.Type != obj.TYPE_MEM || ($3.Name != obj.NAME_EXTERN && $3.Name != obj.NAME_STATIC) { 346 yyerror("value for FUNCDATA must be symbol reference"); 347 } 348 $$.from = $1; 349 $$.to = $3; 350 } 351 352 rem: 353 reg 354 | mem 355 356 rom: 357 rel 358 | nmem 359 | '*' reg 360 { 361 $$ = $2; 362 } 363 | '*' omem 364 { 365 $$ = $2; 366 } 367 | reg 368 | omem 369 370 rim: 371 rem 372 | imm 373 374 rel: 375 con '(' LPC ')' 376 { 377 $$ = nullgen; 378 $$.Type = obj.TYPE_BRANCH; 379 $$.Offset = $1 + int64(asm.PC); 380 } 381 | LNAME offset 382 { 383 $1 = asm.LabelLookup($1); 384 $$ = nullgen; 385 if asm.Pass == 2 && $1.Type != LLAB { 386 yyerror("undefined label: %s", $1.Labelname); 387 } 388 $$.Type = obj.TYPE_BRANCH; 389 $$.Offset = $1.Value + $2; 390 } 391 392 reg: 393 LBREG 394 { 395 $$ = nullgen; 396 $$.Type = obj.TYPE_REG 397 $$.Reg = int16($1); 398 } 399 | LFREG 400 { 401 $$ = nullgen; 402 $$.Type = obj.TYPE_REG 403 $$.Reg = int16($1); 404 } 405 | LLREG 406 { 407 $$ = nullgen; 408 $$.Type = obj.TYPE_REG 409 $$.Reg = int16($1); 410 } 411 | LMREG 412 { 413 $$ = nullgen; 414 $$.Type = obj.TYPE_REG 415 $$.Reg = int16($1); 416 } 417 | LSP 418 { 419 $$ = nullgen; 420 $$.Type = obj.TYPE_REG 421 $$.Reg = x86.REG_SP; 422 } 423 | LSREG 424 { 425 $$ = nullgen; 426 $$.Type = obj.TYPE_REG 427 $$.Reg = int16($1); 428 } 429 | LXREG 430 { 431 $$ = nullgen; 432 $$.Type = obj.TYPE_REG 433 $$.Reg = int16($1); 434 } 435 436 imm: 437 '$' con 438 { 439 $$ = nullgen; 440 $$.Type = obj.TYPE_CONST; 441 $$.Offset = $2; 442 } 443 | '$' nam 444 { 445 $$ = $2; 446 $$.Type = obj.TYPE_ADDR; 447 /* 448 if($2.Type == x86.D_AUTO || $2.Type == x86.D_PARAM) 449 yyerror("constant cannot be automatic: %s", 450 $2.sym.Name); 451 */ 452 } 453 | '$' LSCONST 454 { 455 $$ = nullgen; 456 $$.Type = obj.TYPE_SCONST; 457 $$.Val = ($2+"\x00\x00\x00\x00\x00\x00\x00\x00")[:8] 458 } 459 | '$' LFCONST 460 { 461 $$ = nullgen; 462 $$.Type = obj.TYPE_FCONST; 463 $$.Val = $2; 464 } 465 | '$' '(' LFCONST ')' 466 { 467 $$ = nullgen; 468 $$.Type = obj.TYPE_FCONST; 469 $$.Val = $3; 470 } 471 | '$' '(' '-' LFCONST ')' 472 { 473 $$ = nullgen; 474 $$.Type = obj.TYPE_FCONST; 475 $$.Val = -$4; 476 } 477 | '$' '-' LFCONST 478 { 479 $$ = nullgen; 480 $$.Type = obj.TYPE_FCONST; 481 $$.Val = -$3; 482 } 483 484 mem: 485 omem 486 | nmem 487 488 omem: 489 con 490 { 491 $$ = nullgen; 492 $$.Type = obj.TYPE_MEM 493 $$.Offset = $1; 494 } 495 | con '(' LLREG ')' 496 { 497 $$ = nullgen; 498 $$.Type = obj.TYPE_MEM 499 $$.Reg = int16($3) 500 $$.Offset = $1; 501 } 502 | con '(' LSP ')' 503 { 504 $$ = nullgen; 505 $$.Type = obj.TYPE_MEM 506 $$.Reg = x86.REG_SP 507 $$.Offset = $1; 508 } 509 | con '(' LSREG ')' 510 { 511 $$ = nullgen; 512 $$.Type = obj.TYPE_MEM 513 $$.Reg = int16($3) 514 $$.Offset = $1; 515 } 516 | con '(' LLREG '*' con ')' 517 { 518 $$ = nullgen; 519 $$.Type = obj.TYPE_MEM 520 $$.Offset = $1; 521 $$.Index = int16($3); 522 $$.Scale = int16($5); 523 checkscale($$.Scale); 524 } 525 | con '(' LLREG ')' '(' LLREG '*' con ')' 526 { 527 $$ = nullgen; 528 $$.Type = obj.TYPE_MEM 529 $$.Reg = int16($3) 530 $$.Offset = $1; 531 $$.Index = int16($6); 532 $$.Scale = int16($8); 533 checkscale($$.Scale); 534 } 535 | con '(' LLREG ')' '(' LSREG '*' con ')' 536 { 537 $$ = nullgen; 538 $$.Type = obj.TYPE_MEM 539 $$.Reg = int16($3) 540 $$.Offset = $1; 541 $$.Index = int16($6); 542 $$.Scale = int16($8); 543 checkscale($$.Scale); 544 } 545 | '(' LLREG ')' 546 { 547 $$ = nullgen; 548 $$.Type = obj.TYPE_MEM 549 $$.Reg = int16($2) 550 } 551 | '(' LSP ')' 552 { 553 $$ = nullgen; 554 $$.Type = obj.TYPE_MEM 555 $$.Reg = x86.REG_SP 556 } 557 | '(' LLREG '*' con ')' 558 { 559 $$ = nullgen; 560 $$.Type = obj.TYPE_MEM 561 $$.Index = int16($2); 562 $$.Scale = int16($4); 563 checkscale($$.Scale); 564 } 565 | '(' LLREG ')' '(' LLREG '*' con ')' 566 { 567 $$ = nullgen; 568 $$.Type = obj.TYPE_MEM 569 $$.Reg = int16($2) 570 $$.Index = int16($5); 571 $$.Scale = int16($7); 572 checkscale($$.Scale); 573 } 574 575 nmem: 576 nam 577 { 578 $$ = $1; 579 } 580 | nam '(' LLREG '*' con ')' 581 { 582 $$ = $1; 583 $$.Index = int16($3); 584 $$.Scale = int16($5); 585 checkscale($$.Scale); 586 } 587 588 nam: 589 LNAME offset '(' pointer ')' 590 { 591 $$ = nullgen; 592 $$.Type = obj.TYPE_MEM 593 $$.Name = int8($4) 594 $$.Sym = obj.Linklookup(asm.Ctxt, $1.Name, 0); 595 $$.Offset = $2; 596 } 597 | LNAME '<' '>' offset '(' LSB ')' 598 { 599 $$ = nullgen; 600 $$.Type = obj.TYPE_MEM 601 $$.Name = obj.NAME_STATIC 602 $$.Sym = obj.Linklookup(asm.Ctxt, $1.Name, 1); 603 $$.Offset = $4; 604 } 605 606 offset: 607 { 608 $$ = 0; 609 } 610 | '+' con 611 { 612 $$ = $2; 613 } 614 | '-' con 615 { 616 $$ = -$2; 617 } 618 619 pointer: 620 LSB 621 | LSP 622 { 623 $$ = obj.NAME_AUTO; 624 } 625 | LFP 626 627 con: 628 LCONST 629 | LVAR 630 { 631 $$ = $1.Value; 632 } 633 | '-' con 634 { 635 $$ = -$2; 636 } 637 | '+' con 638 { 639 $$ = $2; 640 } 641 | '~' con 642 { 643 $$ = ^$2; 644 } 645 | '(' expr ')' 646 { 647 $$ = $2; 648 } 649 650 textsize: 651 LCONST 652 { 653 $$ = nullgen; 654 $$.Type = obj.TYPE_TEXTSIZE; 655 $$.Offset = $1; 656 $$.Val = int32(obj.ArgsSizeUnknown); 657 } 658 | '-' LCONST 659 { 660 $$ = nullgen; 661 $$.Type = obj.TYPE_TEXTSIZE; 662 $$.Offset = -$2; 663 $$.Val = int32(obj.ArgsSizeUnknown); 664 } 665 | LCONST '-' LCONST 666 { 667 $$ = nullgen; 668 $$.Type = obj.TYPE_TEXTSIZE; 669 $$.Offset = $1; 670 $$.Val = int32($3); 671 } 672 | '-' LCONST '-' LCONST 673 { 674 $$ = nullgen; 675 $$.Type = obj.TYPE_TEXTSIZE; 676 $$.Offset = -$2; 677 $$.Val = int32($4); 678 } 679 680 expr: 681 con 682 | expr '+' expr 683 { 684 $$ = $1 + $3; 685 } 686 | expr '-' expr 687 { 688 $$ = $1 - $3; 689 } 690 | expr '*' expr 691 { 692 $$ = $1 * $3; 693 } 694 | expr '/' expr 695 { 696 $$ = $1 / $3; 697 } 698 | expr '%' expr 699 { 700 $$ = $1 % $3; 701 } 702 | expr '<' '<' expr 703 { 704 $$ = $1 << uint($4); 705 } 706 | expr '>' '>' expr 707 { 708 $$ = $1 >> uint($4); 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 }