1 %{ 2 #include "a.h" 3 %} 4 %union 5 { 6 Sym *sym; 7 vlong 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> LCONST LSP LSB LFP LPC LHI LLO LMREG 23 %token <lval> LTYPEX LREG LFREG LFCREG LR LM LF 24 %token <lval> LFCR LSCHED 25 %token <dval> LFCONST 26 %token <sval> LSCONST 27 %token <lval> LVCONST 28 %token <sym> LNAME LLAB LVAR 29 %type <lval> con expr pointer offset sreg 30 %type <gen> gen vgen lgen vlgen rel reg freg mreg fcreg 31 %type <gen> imm ximm ireg name oreg imr nireg fgen 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 * Immed-type 72 */ 73 LTYPE1 imr ',' sreg ',' reg 74 { 75 outcode($1, &$2, $4, &$6); 76 } 77 | LTYPE1 imr ',' reg 78 { 79 outcode($1, &$2, NREG, &$4); 80 } 81 /* 82 * NOR 83 */ 84 | LTYPE2 imr ',' sreg ',' imr 85 { 86 outcode($1, &$2, $4, &$6); 87 } 88 | LTYPE2 imr ',' imr 89 { 90 outcode($1, &$2, NREG, &$4); 91 } 92 /* 93 * LOAD/STORE, but not MOVW 94 */ 95 | LTYPE3 lgen ',' gen 96 { 97 if(!isreg(&$2) && !isreg(&$4)) 98 print("one side must be register\n"); 99 outcode($1, &$2, NREG, &$4); 100 } 101 /* 102 * SPECIAL 103 */ 104 | LTYPE4 comma 105 { 106 outcode($1, &nullgen, NREG, &nullgen); 107 } 108 /* 109 * MOVW 110 */ 111 | LTYPE5 vlgen ',' vgen 112 { 113 if(!isreg(&$2) && !isreg(&$4)) 114 print("one side must be register\n"); 115 outcode($1, &$2, NREG, &$4); 116 } 117 /* 118 * MUL/DIV 119 */ 120 | LTYPE6 reg ',' sreg comma 121 { 122 outcode($1, &$2, $4, &nullgen); 123 } 124 | LTYPE6 reg ',' sreg ',' reg 125 { 126 outcode($1, &$2, $4, &$6); 127 } 128 /* 129 * JMP/JAL 130 */ 131 | LTYPE7 comma rel 132 { 133 outcode($1, &nullgen, NREG, &$3); 134 } 135 | LTYPE7 comma nireg 136 { 137 outcode($1, &nullgen, NREG, &$3); 138 } 139 | LTYPE8 comma rel 140 { 141 outcode($1, &nullgen, NREG, &$3); 142 } 143 | LTYPE8 comma nireg 144 { 145 outcode($1, &nullgen, NREG, &$3); 146 } 147 | LTYPE8 sreg ',' nireg 148 { 149 outcode($1, &nullgen, $2, &$4); 150 } 151 /* 152 * BEQ/BNE 153 */ 154 | LTYPE9 gen ',' rel 155 { 156 if(!isreg(&$2)) 157 print("left side must be register\n"); 158 outcode($1, &$2, NREG, &$4); 159 } 160 | LTYPE9 gen ',' sreg ',' rel 161 { 162 if(!isreg(&$2)) 163 print("left side must be register\n"); 164 outcode($1, &$2, $4, &$6); 165 } 166 /* 167 * B-other 168 */ 169 | LTYPEA gen ',' rel 170 { 171 if(!isreg(&$2)) 172 print("left side must be register\n"); 173 outcode($1, &$2, NREG, &$4); 174 } 175 /* 176 * TEXT/GLOBL 177 */ 178 | LTYPEB name ',' imm 179 { 180 outcode($1, &$2, NREG, &$4); 181 } 182 | LTYPEB name ',' con ',' imm 183 { 184 outcode($1, &$2, $4, &$6); 185 } 186 /* 187 * DATA 188 */ 189 | LTYPEC name '/' con ',' ximm 190 { 191 outcode($1, &$2, $4, &$6); 192 } 193 /* 194 * floating-type 195 */ 196 | LTYPED freg ',' freg 197 { 198 outcode($1, &$2, NREG, &$4); 199 } 200 | LTYPEE freg ',' freg 201 { 202 outcode($1, &$2, NREG, &$4); 203 } 204 | LTYPEE freg ',' LFREG ',' freg 205 { 206 outcode($1, &$2, $4, &$6); 207 } 208 | LTYPEF freg ',' LFREG comma 209 { 210 outcode($1, &$2, $4, &nullgen); 211 } 212 /* 213 * coprocessor branch 214 */ 215 | LTYPEG comma rel 216 { 217 outcode($1, &nullgen, NREG, &$3); 218 } 219 /* 220 * word 221 */ 222 | LTYPEH comma ximm 223 { 224 outcode($1, &nullgen, NREG, &$3); 225 } 226 /* 227 * NOP 228 */ 229 | LTYPEI comma 230 { 231 outcode($1, &nullgen, NREG, &nullgen); 232 } 233 | LTYPEI ',' vgen 234 { 235 outcode($1, &nullgen, NREG, &$3); 236 } 237 | LTYPEI vgen comma 238 { 239 outcode($1, &$2, NREG, &nullgen); 240 } 241 /* 242 * BREAK -- overloaded with CACHE opcode 243 */ 244 | LTYPEJ comma 245 { 246 outcode($1, &nullgen, NREG, &nullgen); 247 } 248 | LTYPEJ vgen ',' vgen 249 { 250 outcode($1, &$2, NREG, &$4); 251 } 252 253 comma: 254 | ',' 255 256 rel: 257 con '(' LPC ')' 258 { 259 $$ = nullgen; 260 $$.type = D_BRANCH; 261 $$.offset = $1 + pc; 262 } 263 | LNAME offset 264 { 265 $$ = nullgen; 266 if(pass == 2) 267 yyerror("undefined label: %s", $1->name); 268 $$.type = D_BRANCH; 269 $$.sym = $1; 270 $$.offset = $2; 271 } 272 | LLAB offset 273 { 274 $$ = nullgen; 275 $$.type = D_BRANCH; 276 $$.sym = $1; 277 $$.offset = $1->value + $2; 278 } 279 280 vlgen: 281 lgen 282 | fgen 283 | mreg 284 | fcreg 285 | LHI 286 { 287 $$ = nullgen; 288 $$.type = D_HI; 289 } 290 | LLO 291 { 292 $$ = nullgen; 293 $$.type = D_LO; 294 } 295 296 vgen: 297 gen 298 | fgen 299 | mreg 300 | fcreg 301 | LHI 302 { 303 $$ = nullgen; 304 $$.type = D_HI; 305 } 306 | LLO 307 { 308 $$ = nullgen; 309 $$.type = D_LO; 310 } 311 312 lgen: 313 gen 314 | ximm 315 316 fgen: 317 freg 318 319 mreg: 320 LMREG 321 { 322 $$ = nullgen; 323 $$.type = D_MREG; 324 $$.reg = $1; 325 } 326 | LM '(' con ')' 327 { 328 $$ = nullgen; 329 $$.type = D_MREG; 330 $$.reg = $3; 331 } 332 333 fcreg: 334 LFCREG 335 { 336 $$ = nullgen; 337 $$.type = D_FCREG; 338 $$.reg = $1; 339 } 340 | LFCR '(' con ')' 341 { 342 $$ = nullgen; 343 $$.type = D_FCREG; 344 $$.reg = $3; 345 } 346 347 freg: 348 LFREG 349 { 350 $$ = nullgen; 351 $$.type = D_FREG; 352 $$.reg = $1; 353 } 354 | LF '(' con ')' 355 { 356 $$ = nullgen; 357 $$.type = D_FREG; 358 $$.reg = $3; 359 } 360 361 ximm: '$' con 362 { 363 $$ = nullgen; 364 if(isvconst($2)) 365 $$.type = D_VCONST; 366 else 367 $$.type = D_CONST; 368 $$.offset = $2; 369 } 370 | '$' oreg 371 { 372 $$ = $2; 373 $$.type = D_CONST; 374 } 375 | '$' '*' '$' oreg 376 { 377 $$ = $4; 378 $$.type = D_OCONST; 379 } 380 | '$' LSCONST 381 { 382 $$ = nullgen; 383 $$.type = D_SCONST; 384 memcpy($$.sval, $2, sizeof($$.sval)); 385 } 386 | '$' LFCONST 387 { 388 $$ = nullgen; 389 $$.type = D_FCONST; 390 $$.dval = $2; 391 } 392 | '$' '-' LFCONST 393 { 394 $$ = nullgen; 395 $$.type = D_FCONST; 396 $$.dval = -$3; 397 } 398 399 nireg: 400 ireg 401 | con ireg 402 { 403 if($1 != 0) 404 yyerror("offset must be zero"); 405 $$ = $2; 406 } 407 | name 408 { 409 $$ = $1; 410 if($1.name != D_EXTERN && $1.name != D_STATIC) { 411 } 412 } 413 414 ireg: 415 '(' sreg ')' 416 { 417 $$ = nullgen; 418 $$.type = D_OREG; 419 $$.reg = $2; 420 $$.offset = 0; 421 } 422 423 gen: 424 reg 425 | con 426 { 427 $$ = nullgen; 428 $$.type = D_OREG; 429 $$.offset = $1; 430 } 431 | oreg 432 433 oreg: 434 name 435 | name '(' sreg ')' 436 { 437 $$ = $1; 438 $$.type = D_OREG; 439 $$.reg = $3; 440 } 441 | '(' sreg ')' 442 { 443 $$ = nullgen; 444 $$.type = D_OREG; 445 $$.reg = $2; 446 $$.offset = 0; 447 } 448 | con '(' sreg ')' 449 { 450 $$ = nullgen; 451 $$.type = D_OREG; 452 $$.reg = $3; 453 $$.offset = $1; 454 } 455 456 imr: 457 reg 458 | imm 459 460 imm: '$' con 461 { 462 $$ = nullgen; 463 if(isvconst($2)) 464 $$.type = D_VCONST; 465 else 466 $$.type = D_CONST; 467 $$.offset = $2; 468 } 469 470 reg: 471 sreg 472 { 473 $$ = nullgen; 474 $$.type = D_REG; 475 $$.reg = $1; 476 } 477 478 sreg: 479 LREG 480 | LR '(' con ')' 481 { 482 if($$ < 0 || $$ >= NREG) 483 print("register value out of range\n"); 484 $$ = $3; 485 } 486 487 name: 488 con '(' pointer ')' 489 { 490 $$ = nullgen; 491 $$.type = D_OREG; 492 $$.name = $3; 493 $$.sym = S; 494 $$.offset = $1; 495 } 496 | LNAME offset '(' pointer ')' 497 { 498 $$ = nullgen; 499 $$.type = D_OREG; 500 $$.name = $4; 501 $$.sym = $1; 502 $$.offset = $2; 503 } 504 | LNAME '<' '>' offset '(' LSB ')' 505 { 506 $$ = nullgen; 507 $$.type = D_OREG; 508 $$.name = D_STATIC; 509 $$.sym = $1; 510 $$.offset = $4; 511 } 512 513 offset: 514 { 515 $$ = 0; 516 } 517 | '+' con 518 { 519 $$ = $2; 520 } 521 | '-' con 522 { 523 $$ = -$2; 524 } 525 526 pointer: 527 LSB 528 | LSP 529 | LFP 530 531 con: 532 LCONST 533 | LVAR 534 { 535 $$ = $1->value; 536 } 537 | '-' con 538 { 539 $$ = -$2; 540 } 541 | '+' con 542 { 543 $$ = $2; 544 } 545 | '~' con 546 { 547 $$ = ~$2; 548 } 549 | '(' expr ')' 550 { 551 $$ = $2; 552 } 553 554 expr: 555 con 556 | expr '+' expr 557 { 558 $$ = $1 + $3; 559 } 560 | expr '-' expr 561 { 562 $$ = $1 - $3; 563 } 564 | expr '*' expr 565 { 566 $$ = $1 * $3; 567 } 568 | expr '/' expr 569 { 570 $$ = $1 / $3; 571 } 572 | expr '%' expr 573 { 574 $$ = $1 % $3; 575 } 576 | expr '<' '<' expr 577 { 578 $$ = $1 << $4; 579 } 580 | expr '>' '>' expr 581 { 582 $$ = $1 >> $4; 583 } 584 | expr '&' expr 585 { 586 $$ = $1 & $3; 587 } 588 | expr '^' expr 589 { 590 $$ = $1 ^ $3; 591 } 592 | expr '|' expr 593 { 594 $$ = $1 | $3; 595 } 596 %% 597 598 int 599 isvconst(vlong con) 600 { 601 long l; 602 603 l = con; 604 return (vlong)l != con; 605 } 606