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