1 %{ 2 #include "a.h" 3 %} 4 %union { 5 Sym *sym; 6 vlong lval; 7 double dval; 8 char sval[8]; 9 Gen gen; 10 Gen2 gen2; 11 } 12 %left '|' 13 %left '^' 14 %left '&' 15 %left '<' '>' 16 %left '+' '-' 17 %left '*' '/' '%' 18 %token <lval> LTYPE0 LTYPE1 LTYPE2 LTYPE3 LTYPE4 19 %token <lval> LTYPEC LTYPED LTYPEN LTYPER LTYPET LTYPES LTYPEM LTYPEI LTYPEG LTYPEXC LTYPEX LTYPEY LTYPERT 20 %token <lval> LCONST LFP LPC LSB 21 %token <lval> LBREG LLREG LSREG LFREG LMREG LXREG LYREG 22 %token <dval> LFCONST 23 %token <sval> LSCONST LSP 24 %token <sym> LNAME LLAB LVAR 25 %type <lval> con expr pointer offset 26 %type <gen> mem imm reg nam rel rem rim rom omem nmem 27 %type <gen2> nonnon nonrel nonrem rimnon rimrem remrim 28 %type <gen2> spec1 spec2 spec3 spec4 spec5 spec6 spec7 spec8 spec9 spec10 spec11 spec12 29 %% 30 prog: 31 | prog line 32 33 line: 34 LLAB ':' 35 { 36 if($1->value != pc) 37 yyerror("redeclaration of %s", $1->name); 38 $1->value = pc; 39 } 40 line 41 | LNAME ':' 42 { 43 $1->type = LLAB; 44 $1->value = pc; 45 } 46 line 47 | ';' 48 | inst ';' 49 | error ';' 50 51 inst: 52 LNAME '=' expr 53 { 54 $1->type = LVAR; 55 $1->value = $3; 56 } 57 | LVAR '=' expr 58 { 59 if($1->value != $3) 60 yyerror("redeclaration of %s", $1->name); 61 $1->value = $3; 62 } 63 | LTYPE0 nonnon { outcode($1, &$2); } 64 | LTYPE1 nonrem { outcode($1, &$2); } 65 | LTYPE2 rimnon { outcode($1, &$2); } 66 | LTYPE3 rimrem { outcode($1, &$2); } 67 | LTYPE4 remrim { outcode($1, &$2); } 68 | LTYPER nonrel { outcode($1, &$2); } 69 | LTYPED spec1 { outcode($1, &$2); } 70 | LTYPET spec2 { outcode($1, &$2); } 71 | LTYPEC spec3 { outcode($1, &$2); } 72 | LTYPEN spec4 { outcode($1, &$2); } 73 | LTYPES spec5 { outcode($1, &$2); } 74 | LTYPEM spec6 { outcode($1, &$2); } 75 | LTYPEI spec7 { outcode($1, &$2); } 76 | LTYPEXC spec8 { outcode($1, &$2); } 77 | LTYPEX spec9 { outcode($1, &$2); } 78 | LTYPEG spec10 { outcode($1, &$2); } 79 | LTYPEY spec11 { outcode($1, &$2); } 80 | LTYPERT spec12 { outcode($1, &$2); } 81 82 nonnon: 83 { 84 $$.from = nullgen; 85 $$.to = nullgen; 86 } 87 | ',' 88 { 89 $$.from = nullgen; 90 $$.to = nullgen; 91 } 92 93 rimrem: 94 rim ',' rem 95 { 96 $$.from = $1; 97 $$.to = $3; 98 } 99 100 remrim: 101 rem ',' rim 102 { 103 $$.from = $1; 104 $$.to = $3; 105 } 106 107 rimnon: 108 rim ',' 109 { 110 $$.from = $1; 111 $$.to = nullgen; 112 } 113 | rim 114 { 115 $$.from = $1; 116 $$.to = nullgen; 117 } 118 119 nonrem: 120 ',' rem 121 { 122 $$.from = nullgen; 123 $$.to = $2; 124 } 125 | rem 126 { 127 $$.from = nullgen; 128 $$.to = $1; 129 } 130 131 nonrel: 132 ',' rel 133 { 134 $$.from = nullgen; 135 $$.to = $2; 136 } 137 | rel 138 { 139 $$.from = nullgen; 140 $$.to = $1; 141 } 142 143 spec1: /* DATA */ 144 nam '/' con ',' imm 145 { 146 $$.from = $1; 147 $$.from.scale = $3; 148 $$.to = $5; 149 } 150 151 spec2: /* TEXT */ 152 mem ',' imm 153 { 154 $$.from = $1; 155 $$.to = $3; 156 } 157 | mem ',' con ',' imm 158 { 159 $$.from = $1; 160 $$.from.scale = $3; 161 $$.to = $5; 162 } 163 164 spec3: /* JMP/CALL */ 165 ',' rom 166 { 167 $$.from = nullgen; 168 $$.to = $2; 169 } 170 | rom 171 { 172 $$.from = nullgen; 173 $$.to = $1; 174 } 175 176 spec4: /* NOP */ 177 nonnon 178 | nonrem 179 180 spec5: /* SHL/SHR */ 181 rim ',' rem 182 { 183 $$.from = $1; 184 $$.to = $3; 185 } 186 | rim ',' rem ':' LLREG 187 { 188 $$.from = $1; 189 $$.to = $3; 190 if($$.from.index != D_NONE) 191 yyerror("dp shift with lhs index"); 192 $$.from.index = $5; 193 } 194 195 spec6: /* MOVW/MOVL */ 196 rim ',' rem 197 { 198 $$.from = $1; 199 $$.to = $3; 200 } 201 | rim ',' rem ':' LSREG 202 { 203 $$.from = $1; 204 $$.to = $3; 205 if($$.to.index != D_NONE) 206 yyerror("dp move with lhs index"); 207 $$.to.index = $5; 208 } 209 210 spec7: 211 rim ',' 212 { 213 $$.from = $1; 214 $$.to = nullgen; 215 } 216 | rim 217 { 218 $$.from = $1; 219 $$.to = nullgen; 220 } 221 | rim ',' rem 222 { 223 $$.from = $1; 224 $$.to = $3; 225 } 226 227 spec8: /* CMPPS/CMPPD */ 228 reg ',' rem ',' con 229 { 230 $$.from = $1; 231 $$.to = $3; 232 $$.from.offset = $5; 233 } 234 | reg ',' reg ',' rem ',' con /* VCMPPS/VCMPPD */ 235 { 236 $$.from = $1; 237 if(!isxyreg($3.type)) 238 yyerror("second source operand must be X/Y register"); 239 $$.from.index = $3.type; 240 $$.to = $5; 241 $$.from.offset = $7; 242 } 243 244 spec9: /* SHUFL */ 245 imm ',' rem ',' reg 246 { 247 $$.from = $3; 248 $$.to = $5; 249 if($1.type != D_CONST) 250 yyerror("illegal constant"); 251 $$.to.offset = $1.offset; 252 } 253 | imm ',' rem ',' reg ',' reg 254 { 255 $$.from = $3; 256 $$.to = $7; 257 if($1.type != D_CONST) 258 yyerror("illegal constant"); 259 $$.to.offset = $1.offset; 260 if(!isxyreg($5.type)) 261 yyerror("second source operand must be X/Y register"); 262 $$.to.index = $5.type; 263 } 264 265 spec10: /* GLOBL */ 266 mem ',' imm 267 { 268 $$.from = $1; 269 $$.to = $3; 270 } 271 | mem ',' con ',' imm 272 { 273 $$.from = $1; 274 $$.from.scale = $3; 275 $$.to = $5; 276 } 277 278 spec11: 279 rimrem 280 | rim ',' reg ',' rem 281 { 282 $$.from = $1; 283 $$.to = $5; 284 if(isxyreg($3.type)) { 285 if(isxyreg($1.type)) 286 $$.from.index = $3.type; 287 else if(isxyreg($5.type)) 288 $$.to.index = $3.type; 289 } else 290 yyerror("second source operand must be X or Y register"); 291 } 292 293 spec12: /* RET/RETF */ 294 { 295 $$.from = nullgen; 296 $$.to = nullgen; 297 } 298 | imm 299 { 300 $$.from = $1; 301 $$.to = nullgen; 302 } 303 304 rem: 305 reg 306 | mem 307 308 rom: 309 rel 310 | nmem 311 | '*' reg 312 { 313 $$ = $2; 314 } 315 | '*' omem 316 { 317 $$ = $2; 318 } 319 | reg 320 | omem 321 | imm 322 323 rim: 324 rem 325 | imm 326 327 rel: 328 con '(' LPC ')' 329 { 330 $$ = nullgen; 331 $$.type = D_BRANCH; 332 $$.offset = $1 + pc; 333 } 334 | LNAME offset 335 { 336 $$ = nullgen; 337 if(pass == 2) 338 yyerror("undefined label: %s", $1->name); 339 $$.type = D_BRANCH; 340 $$.sym = $1; 341 $$.offset = $2; 342 } 343 | LLAB offset 344 { 345 $$ = nullgen; 346 $$.type = D_BRANCH; 347 $$.sym = $1; 348 $$.offset = $1->value + $2; 349 } 350 351 reg: 352 LBREG 353 { 354 $$ = nullgen; 355 $$.type = $1; 356 } 357 | LFREG 358 { 359 $$ = nullgen; 360 $$.type = $1; 361 } 362 | LLREG 363 { 364 $$ = nullgen; 365 $$.type = $1; 366 } 367 | LMREG 368 { 369 $$ = nullgen; 370 $$.type = $1; 371 } 372 | LSP 373 { 374 $$ = nullgen; 375 $$.type = D_SP; 376 } 377 | LSREG 378 { 379 $$ = nullgen; 380 $$.type = $1; 381 } 382 | LXREG 383 { 384 $$ = nullgen; 385 $$.type = $1; 386 } 387 | LYREG 388 { 389 $$ = nullgen; 390 $$.type = $1; 391 } 392 393 imm: 394 '$' con 395 { 396 $$ = nullgen; 397 $$.type = D_CONST; 398 $$.offset = $2; 399 } 400 | '$' nam 401 { 402 $$ = $2; 403 $$.index = $2.type; 404 $$.type = D_ADDR; 405 /* 406 if($2.type == D_AUTO || $2.type == D_PARAM) 407 yyerror("constant cannot be automatic: %s", 408 $2.sym->name); 409 */ 410 } 411 | '$' LSCONST 412 { 413 $$ = nullgen; 414 $$.type = D_SCONST; 415 memcpy($$.sval, $2, sizeof($$.sval)); 416 } 417 | '$' LFCONST 418 { 419 $$ = nullgen; 420 $$.type = D_FCONST; 421 $$.dval = $2; 422 } 423 | '$' '(' LFCONST ')' 424 { 425 $$ = nullgen; 426 $$.type = D_FCONST; 427 $$.dval = $3; 428 } 429 | '$' '-' LFCONST 430 { 431 $$ = nullgen; 432 $$.type = D_FCONST; 433 $$.dval = -$3; 434 } 435 436 mem: 437 omem 438 | nmem 439 440 omem: 441 con 442 { 443 $$ = nullgen; 444 $$.type = D_INDIR+D_NONE; 445 $$.offset = $1; 446 } 447 | con '(' LLREG ')' 448 { 449 $$ = nullgen; 450 $$.type = D_INDIR+$3; 451 $$.offset = $1; 452 } 453 | con '(' LSP ')' 454 { 455 $$ = nullgen; 456 $$.type = D_INDIR+D_SP; 457 $$.offset = $1; 458 } 459 | con '(' LLREG '*' con ')' 460 { 461 $$ = nullgen; 462 $$.type = D_INDIR+D_NONE; 463 $$.offset = $1; 464 $$.index = $3; 465 $$.scale = $5; 466 checkscale($$.scale); 467 } 468 | con '(' LLREG ')' '(' LLREG '*' con ')' 469 { 470 $$ = nullgen; 471 $$.type = D_INDIR+$3; 472 $$.offset = $1; 473 $$.index = $6; 474 $$.scale = $8; 475 checkscale($$.scale); 476 } 477 | '(' LLREG ')' 478 { 479 $$ = nullgen; 480 $$.type = D_INDIR+$2; 481 } 482 | '(' LSP ')' 483 { 484 $$ = nullgen; 485 $$.type = D_INDIR+D_SP; 486 } 487 | con '(' LSREG ')' 488 { 489 $$ = nullgen; 490 $$.type = D_INDIR+$3; 491 $$.offset = $1; 492 } 493 | '(' LLREG '*' con ')' 494 { 495 $$ = nullgen; 496 $$.type = D_INDIR+D_NONE; 497 $$.index = $2; 498 $$.scale = $4; 499 checkscale($$.scale); 500 } 501 | '(' LLREG ')' '(' LLREG '*' con ')' 502 { 503 $$ = nullgen; 504 $$.type = D_INDIR+$2; 505 $$.index = $5; 506 $$.scale = $7; 507 checkscale($$.scale); 508 } 509 510 nmem: 511 nam 512 { 513 $$ = $1; 514 } 515 | nam '(' LLREG '*' con ')' 516 { 517 $$ = $1; 518 $$.index = $3; 519 $$.scale = $5; 520 checkscale($$.scale); 521 } 522 523 nam: 524 LNAME offset '(' pointer ')' 525 { 526 $$ = nullgen; 527 $$.type = $4; 528 $$.sym = $1; 529 $$.offset = $2; 530 } 531 | LNAME '<' '>' offset '(' LSB ')' 532 { 533 $$ = nullgen; 534 $$.type = D_STATIC; 535 $$.sym = $1; 536 $$.offset = $4; 537 } 538 539 offset: 540 { 541 $$ = 0; 542 } 543 | '+' con 544 { 545 $$ = $2; 546 } 547 | '-' con 548 { 549 $$ = -$2; 550 } 551 552 pointer: 553 LSB 554 | LSP 555 { 556 $$ = D_AUTO; 557 } 558 | LFP 559 560 con: 561 LCONST 562 | LVAR 563 { 564 $$ = $1->value; 565 } 566 | '-' con 567 { 568 $$ = -$2; 569 } 570 | '+' con 571 { 572 $$ = $2; 573 } 574 | '~' con 575 { 576 $$ = ~$2; 577 } 578 | '(' expr ')' 579 { 580 $$ = $2; 581 } 582 583 expr: 584 con 585 | expr '+' expr 586 { 587 $$ = $1 + $3; 588 } 589 | expr '-' expr 590 { 591 $$ = $1 - $3; 592 } 593 | expr '*' expr 594 { 595 $$ = $1 * $3; 596 } 597 | expr '/' expr 598 { 599 $$ = $1 / $3; 600 } 601 | expr '%' expr 602 { 603 $$ = $1 % $3; 604 } 605 | expr '<' '<' expr 606 { 607 $$ = $1 << $4; 608 } 609 | expr '>' '>' expr 610 { 611 $$ = $1 >> $4; 612 } 613 | expr '&' expr 614 { 615 $$ = $1 & $3; 616 } 617 | expr '^' expr 618 { 619 $$ = $1 ^ $3; 620 } 621 | expr '|' expr 622 { 623 $$ = $1 | $3; 624 } 625