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