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> LTYPE1 LTYPE2 LTYPE3 LTYPE4 LTYPE5 19 %token <lval> LTYPE6 LTYPE7 LTYPE8 LTYPE9 LTYPEA 20 %token <lval> LTYPEB LTYPEC LTYPED LTYPEE LTYPEF 21 %token <lval> LTYPEG LTYPEH LTYPEI LTYPEJ LTYPEK 22 %token <lval> LTYPEL LTYPEM LTYPEN LTYPEBX 23 %token <lval> LCONST LSP LSB LFP LPC 24 %token <lval> LTYPEX LR LREG LF LFREG LC LCREG LPSR LFCR 25 %token <lval> LCOND LS LAT 26 %token <dval> LFCONST 27 %token <sval> LSCONST 28 %token <sym> LNAME LLAB LVAR 29 %type <lval> con expr oexpr pointer offset sreg spreg creg 30 %type <lval> rcon cond reglist 31 %type <gen> gen rel reg regreg freg shift fcon frcon 32 %type <gen> imm ximm name oreg ireg nireg ioreg imsr 33 %% 34 prog: 35 | prog line 36 37 line: 38 LLAB ':' 39 { 40 if($1->value != pc) 41 yyerror("redeclaration of %s", $1->name); 42 $1->value = pc; 43 } 44 line 45 | LNAME ':' 46 { 47 $1->type = LLAB; 48 $1->value = pc; 49 } 50 line 51 | LNAME '=' expr ';' 52 { 53 $1->type = LVAR; 54 $1->value = $3; 55 } 56 | LVAR '=' expr ';' 57 { 58 if($1->value != $3) 59 yyerror("redeclaration of %s", $1->name); 60 $1->value = $3; 61 } 62 | ';' 63 | inst ';' 64 | error ';' 65 66 inst: 67 /* 68 * ADD 69 */ 70 LTYPE1 cond imsr ',' spreg ',' reg 71 { 72 outcode($1, $2, &$3, $5, &$7); 73 } 74 | LTYPE1 cond imsr ',' spreg ',' 75 { 76 outcode($1, $2, &$3, $5, &nullgen); 77 } 78 | LTYPE1 cond imsr ',' reg 79 { 80 outcode($1, $2, &$3, NREG, &$5); 81 } 82 /* 83 * MVN 84 */ 85 | LTYPE2 cond imsr ',' reg 86 { 87 outcode($1, $2, &$3, NREG, &$5); 88 } 89 /* 90 * MOVW 91 */ 92 | LTYPE3 cond gen ',' gen 93 { 94 outcode($1, $2, &$3, NREG, &$5); 95 } 96 /* 97 * B/BL 98 */ 99 | LTYPE4 cond comma rel 100 { 101 outcode($1, $2, &nullgen, NREG, &$4); 102 } 103 | LTYPE4 cond comma nireg 104 { 105 outcode($1, $2, &nullgen, NREG, &$4); 106 } 107 /* 108 * BX 109 */ 110 | LTYPEBX comma ireg 111 { 112 outcode($1, Always, &nullgen, NREG, &$3); 113 } 114 /* 115 * BEQ 116 */ 117 | LTYPE5 comma rel 118 { 119 outcode($1, Always, &nullgen, NREG, &$3); 120 } 121 /* 122 * SWI 123 */ 124 | LTYPE6 cond comma gen 125 { 126 outcode($1, $2, &nullgen, NREG, &$4); 127 } 128 /* 129 * CMP 130 */ 131 | LTYPE7 cond imsr ',' spreg comma 132 { 133 outcode($1, $2, &$3, $5, &nullgen); 134 } 135 /* 136 * MOVM 137 */ 138 | LTYPE8 cond ioreg ',' '[' reglist ']' 139 { 140 Gen g; 141 142 g = nullgen; 143 g.type = D_CONST; 144 g.offset = $6; 145 outcode($1, $2, &$3, NREG, &g); 146 } 147 | LTYPE8 cond '[' reglist ']' ',' ioreg 148 { 149 Gen g; 150 151 g = nullgen; 152 g.type = D_CONST; 153 g.offset = $4; 154 outcode($1, $2, &g, NREG, &$7); 155 } 156 /* 157 * SWAP 158 */ 159 | LTYPE9 cond reg ',' ireg ',' reg 160 { 161 outcode($1, $2, &$5, $3.reg, &$7); 162 } 163 | LTYPE9 cond reg ',' ireg comma 164 { 165 outcode($1, $2, &$5, $3.reg, &$3); 166 } 167 | LTYPE9 cond comma ireg ',' reg 168 { 169 outcode($1, $2, &$4, $6.reg, &$6); 170 } 171 /* 172 * RET 173 */ 174 | LTYPEA cond comma 175 { 176 outcode($1, $2, &nullgen, NREG, &nullgen); 177 } 178 /* 179 * TEXT/GLOBL 180 */ 181 | LTYPEB name ',' imm 182 { 183 outcode($1, Always, &$2, NREG, &$4); 184 } 185 | LTYPEB name ',' con ',' imm 186 { 187 outcode($1, Always, &$2, $4, &$6); 188 } 189 /* 190 * DATA 191 */ 192 | LTYPEC name '/' con ',' ximm 193 { 194 outcode($1, Always, &$2, $4, &$6); 195 } 196 /* 197 * CASE 198 */ 199 | LTYPED cond reg comma 200 { 201 outcode($1, $2, &$3, NREG, &nullgen); 202 } 203 /* 204 * word 205 */ 206 | LTYPEH comma ximm 207 { 208 outcode($1, Always, &nullgen, NREG, &$3); 209 } 210 /* 211 * floating-point coprocessor 212 */ 213 | LTYPEI cond freg ',' freg 214 { 215 outcode($1, $2, &$3, NREG, &$5); 216 } 217 | LTYPEK cond frcon ',' freg 218 { 219 outcode($1, $2, &$3, NREG, &$5); 220 } 221 | LTYPEK cond frcon ',' LFREG ',' freg 222 { 223 outcode($1, $2, &$3, $5, &$7); 224 } 225 | LTYPEL cond freg ',' freg comma 226 { 227 outcode($1, $2, &$3, $5.reg, &nullgen); 228 } 229 /* 230 * MCR MRC 231 */ 232 | LTYPEJ cond con ',' expr ',' spreg ',' creg ',' creg oexpr 233 { 234 Gen g; 235 236 g = nullgen; 237 g.type = D_CONST; 238 g.offset = 239 (0xe << 24) | /* opcode */ 240 ($1 << 20) | /* MCR/MRC */ 241 ($2 << 28) | /* scond */ 242 (($3 & 15) << 8) | /* coprocessor number */ 243 (($5 & 7) << 21) | /* coprocessor operation */ 244 (($7 & 15) << 12) | /* arm register */ 245 (($9 & 15) << 16) | /* Crn */ 246 (($11 & 15) << 0) | /* Crm */ 247 (($12 & 7) << 5) | /* coprocessor information */ 248 (1<<4); /* must be set */ 249 outcode(AWORD, Always, &nullgen, NREG, &g); 250 } 251 /* 252 * MULL hi,lo,r1,r2 253 */ 254 | LTYPEM cond reg ',' reg ',' regreg 255 { 256 outcode($1, $2, &$3, $5.reg, &$7); 257 } 258 /* 259 * MULA hi,lo,r1,r2 260 */ 261 | LTYPEN cond reg ',' reg ',' reg ',' spreg 262 { 263 $7.type = D_REGREG; 264 $7.offset = $9; 265 outcode($1, $2, &$3, $5.reg, &$7); 266 } 267 /* 268 * END 269 */ 270 | LTYPEE comma 271 { 272 outcode($1, Always, &nullgen, NREG, &nullgen); 273 } 274 275 cond: 276 { 277 $$ = Always; 278 } 279 | cond LCOND 280 { 281 $$ = ($1 & ~C_SCOND) | $2; 282 } 283 | cond LS 284 { 285 $$ = $1 | $2; 286 } 287 288 comma: 289 | ',' comma 290 291 rel: 292 con '(' LPC ')' 293 { 294 $$ = nullgen; 295 $$.type = D_BRANCH; 296 $$.offset = $1 + pc; 297 } 298 | LNAME offset 299 { 300 $$ = nullgen; 301 if(pass == 2) 302 yyerror("undefined label: %s", $1->name); 303 $$.type = D_BRANCH; 304 $$.sym = $1; 305 $$.offset = $2; 306 } 307 | LLAB offset 308 { 309 $$ = nullgen; 310 $$.type = D_BRANCH; 311 $$.sym = $1; 312 $$.offset = $1->value + $2; 313 } 314 315 ximm: '$' con 316 { 317 $$ = nullgen; 318 $$.type = D_CONST; 319 $$.offset = $2; 320 } 321 | '$' oreg 322 { 323 $$ = $2; 324 $$.type = D_CONST; 325 } 326 | '$' '*' '$' oreg 327 { 328 $$ = $4; 329 $$.type = D_OCONST; 330 } 331 | '$' LSCONST 332 { 333 $$ = nullgen; 334 $$.type = D_SCONST; 335 memcpy($$.sval, $2, sizeof($$.sval)); 336 } 337 | fcon 338 339 fcon: 340 '$' LFCONST 341 { 342 $$ = nullgen; 343 $$.type = D_FCONST; 344 $$.dval = $2; 345 } 346 | '$' '-' LFCONST 347 { 348 $$ = nullgen; 349 $$.type = D_FCONST; 350 $$.dval = -$3; 351 } 352 353 reglist: 354 spreg 355 { 356 $$ = 1 << $1; 357 } 358 | spreg '-' spreg 359 { 360 int i; 361 $$=0; 362 for(i=$1; i<=$3; i++) 363 $$ |= 1<<i; 364 for(i=$3; i<=$1; i++) 365 $$ |= 1<<i; 366 } 367 | spreg comma reglist 368 { 369 $$ = (1<<$1) | $3; 370 } 371 372 gen: 373 reg 374 | ximm 375 | shift 376 | shift '(' spreg ')' 377 { 378 $$ = $1; 379 $$.reg = $3; 380 } 381 | LPSR 382 { 383 $$ = nullgen; 384 $$.type = D_PSR; 385 $$.reg = $1; 386 } 387 | LFCR 388 { 389 $$ = nullgen; 390 $$.type = D_FPCR; 391 $$.reg = $1; 392 } 393 | con 394 { 395 $$ = nullgen; 396 $$.type = D_OREG; 397 $$.offset = $1; 398 } 399 | oreg 400 | freg 401 402 nireg: 403 ireg 404 | name 405 { 406 $$ = $1; 407 if($1.name != D_EXTERN && $1.name != D_STATIC) { 408 } 409 } 410 411 ireg: 412 '(' spreg ')' 413 { 414 $$ = nullgen; 415 $$.type = D_OREG; 416 $$.reg = $2; 417 $$.offset = 0; 418 } 419 420 ioreg: 421 ireg 422 | con '(' sreg ')' 423 { 424 $$ = nullgen; 425 $$.type = D_OREG; 426 $$.reg = $3; 427 $$.offset = $1; 428 } 429 430 oreg: 431 name 432 | name '(' sreg ')' 433 { 434 $$ = $1; 435 $$.type = D_OREG; 436 $$.reg = $3; 437 } 438 | ioreg 439 440 imsr: 441 reg 442 | imm 443 | shift 444 445 imm: '$' con 446 { 447 $$ = nullgen; 448 $$.type = D_CONST; 449 $$.offset = $2; 450 } 451 452 reg: 453 spreg 454 { 455 $$ = nullgen; 456 $$.type = D_REG; 457 $$.reg = $1; 458 } 459 460 regreg: 461 '(' spreg ',' spreg ')' 462 { 463 $$ = nullgen; 464 $$.type = D_REGREG; 465 $$.reg = $2; 466 $$.offset = $4; 467 } 468 469 shift: 470 spreg '<' '<' rcon 471 { 472 $$ = nullgen; 473 $$.type = D_SHIFT; 474 $$.offset = $1 | $4 | (0 << 5); 475 } 476 | spreg '>' '>' rcon 477 { 478 $$ = nullgen; 479 $$.type = D_SHIFT; 480 $$.offset = $1 | $4 | (1 << 5); 481 } 482 | spreg '-' '>' rcon 483 { 484 $$ = nullgen; 485 $$.type = D_SHIFT; 486 $$.offset = $1 | $4 | (2 << 5); 487 } 488 | spreg LAT '>' rcon 489 { 490 $$ = nullgen; 491 $$.type = D_SHIFT; 492 $$.offset = $1 | $4 | (3 << 5); 493 } 494 495 rcon: 496 spreg 497 { 498 if($$ < 0 || $$ >= 16) 499 print("register value out of range\n"); 500 $$ = (($1&15) << 8) | (1 << 4); 501 } 502 | con 503 { 504 if($$ < 0 || $$ >= 32) 505 print("shift value out of range\n"); 506 $$ = ($1&31) << 7; 507 } 508 509 sreg: 510 LREG 511 | LPC 512 { 513 $$ = REGPC; 514 } 515 | LR '(' expr ')' 516 { 517 if($3 < 0 || $3 >= NREG) 518 print("register value out of range\n"); 519 $$ = $3; 520 } 521 522 spreg: 523 sreg 524 | LSP 525 { 526 $$ = REGSP; 527 } 528 529 creg: 530 LCREG 531 | LC '(' expr ')' 532 { 533 if($3 < 0 || $3 >= NREG) 534 print("register value out of range\n"); 535 $$ = $3; 536 } 537 538 frcon: 539 freg 540 | fcon 541 542 freg: 543 LFREG 544 { 545 $$ = nullgen; 546 $$.type = D_FREG; 547 $$.reg = $1; 548 } 549 | LF '(' con ')' 550 { 551 $$ = nullgen; 552 $$.type = D_FREG; 553 $$.reg = $3; 554 } 555 556 name: 557 con '(' pointer ')' 558 { 559 $$ = nullgen; 560 $$.type = D_OREG; 561 $$.name = $3; 562 $$.sym = S; 563 $$.offset = $1; 564 } 565 | LNAME offset '(' pointer ')' 566 { 567 $$ = nullgen; 568 $$.type = D_OREG; 569 $$.name = $4; 570 $$.sym = $1; 571 $$.offset = $2; 572 } 573 | LNAME '<' '>' offset '(' LSB ')' 574 { 575 $$ = nullgen; 576 $$.type = D_OREG; 577 $$.name = D_STATIC; 578 $$.sym = $1; 579 $$.offset = $4; 580 } 581 582 offset: 583 { 584 $$ = 0; 585 } 586 | '+' con 587 { 588 $$ = $2; 589 } 590 | '-' con 591 { 592 $$ = -$2; 593 } 594 595 pointer: 596 LSB 597 | LSP 598 | LFP 599 600 con: 601 LCONST 602 | LVAR 603 { 604 $$ = $1->value; 605 } 606 | '-' con 607 { 608 $$ = -$2; 609 } 610 | '+' con 611 { 612 $$ = $2; 613 } 614 | '~' con 615 { 616 $$ = ~$2; 617 } 618 | '(' expr ')' 619 { 620 $$ = $2; 621 } 622 623 oexpr: 624 { 625 $$ = 0; 626 } 627 | ',' expr 628 { 629 $$ = $2; 630 } 631 632 expr: 633 con 634 | expr '+' expr 635 { 636 $$ = $1 + $3; 637 } 638 | expr '-' expr 639 { 640 $$ = $1 - $3; 641 } 642 | expr '*' expr 643 { 644 $$ = $1 * $3; 645 } 646 | expr '/' expr 647 { 648 $$ = $1 / $3; 649 } 650 | expr '%' expr 651 { 652 $$ = $1 % $3; 653 } 654 | expr '<' '<' expr 655 { 656 $$ = $1 << $4; 657 } 658 | expr '>' '>' expr 659 { 660 $$ = $1 >> $4; 661 } 662 | expr '&' expr 663 { 664 $$ = $1 & $3; 665 } 666 | expr '^' expr 667 { 668 $$ = $1 ^ $3; 669 } 670 | expr '|' expr 671 { 672 $$ = $1 | $3; 673 } 674