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> LADD LMUL LBEQ LBR LBRET LCALL LFLT2 LFLT3 19 %token <lval> LMOVB LMOVBU LMOVW LMOVF LLUI LSYS LSYS0 LCSR LSWAP LAMO 20 %token <lval> LCONST LSP LSB LFP LPC LREG LFREG LR FR LCTL 21 %token <lval> LDATA LTEXT LWORD 22 %token <sval> LSCONST 23 %token <dval> LFCONST 24 %token <sym> LNAME LLAB LVAR 25 %type <lval> con expr pointer offset sreg freg oprrr 26 %type <gen> rreg dreg ctlreg drreg 27 %type <gen> addr name oreg rel imm ximm fimm 28 %% 29 prog: 30 | prog line 31 32 line: 33 LLAB ':' 34 { 35 if($1->value != pc) 36 yyerror("redeclaration of %s", $1->name); 37 $1->value = pc; 38 } 39 line 40 | LNAME ':' 41 { 42 $1->type = LLAB; 43 $1->value = pc; 44 } 45 line 46 | LNAME '=' expr ';' 47 { 48 $1->type = LVAR; 49 $1->value = $3; 50 } 51 | LVAR '=' expr ';' 52 { 53 if($1->value != $3) 54 yyerror("redeclaration of %s", $1->name); 55 $1->value = $3; 56 } 57 | ';' 58 | inst ';' 59 | error ';' 60 61 inst: 62 LADD imm ',' rreg 63 { 64 outcode($1, &$2, NREG, &$4); 65 } 66 | oprrr rreg ',' rreg 67 { 68 outcode($1, &$2, NREG, &$4); 69 } 70 | LADD imm ',' sreg ',' rreg 71 { 72 outcode($1, &$2, $4, &$6); 73 } 74 | oprrr rreg ',' sreg ',' rreg 75 { 76 outcode($1, &$2, $4, &$6); 77 } 78 79 | LFLT2 drreg ',' drreg 80 { 81 outcode($1, &$2, NREG, &$4); 82 } 83 | LFLT3 drreg ',' freg ',' drreg 84 { 85 outcode($1, &$2, $4, &$6); 86 } 87 88 | LBEQ rreg ',' sreg ',' rel 89 { 90 outcode($1, &$2, $4, &$6); 91 } 92 93 | LBEQ rreg ',' rel 94 { 95 Gen regzero; 96 regzero = nullgen; 97 regzero.type = D_REG; 98 regzero.reg = 0; 99 outcode($1, ®zero, $2.reg, &$4); 100 } 101 102 | LBR rel 103 { 104 outcode($1, &nullgen, NREG, &$2); 105 } 106 107 | LBR oreg 108 { 109 outcode($1, &nullgen, NREG, &$2); 110 } 111 112 113 | LBRET 114 { 115 outcode($1, &nullgen, NREG, &nullgen); 116 } 117 118 | LCALL sreg ',' addr 119 { 120 outcode($1, &nullgen, $2, &$4); 121 } 122 | LCALL sreg ',' rel 123 { 124 outcode($1, &nullgen, $2, &$4); 125 } 126 127 | LMOVB addr ',' rreg 128 { 129 outcode($1, &$2, NREG, &$4); 130 } 131 | LMOVBU addr ',' rreg 132 { 133 outcode($1, &$2, NREG, &$4); 134 } 135 | LMOVB rreg ',' addr 136 { 137 outcode($1, &$2, NREG, &$4); 138 } 139 140 | LMOVF addr ',' dreg 141 { 142 outcode($1, &$2, NREG, &$4); 143 } 144 | LMOVF dreg ',' addr 145 { 146 outcode($1, &$2, NREG, &$4); 147 } 148 | LMOVF dreg ',' dreg 149 { 150 outcode($1, &$2, NREG, &$4); 151 } 152 153 154 | LMOVW imm ',' rreg 155 { 156 outcode($1, &$2, NREG, &$4); 157 } 158 | LMOVW ximm ',' rreg 159 { 160 outcode($1, &$2, NREG, &$4); 161 } 162 | LMOVW rreg ',' rreg 163 { 164 outcode($1, &$2, NREG, &$4); 165 } 166 | LMOVW addr ',' rreg 167 { 168 outcode($1, &$2, NREG, &$4); 169 } 170 | LMOVW rreg ',' addr 171 { 172 outcode($1, &$2, NREG, &$4); 173 } 174 | LMOVW rreg ',' ctlreg 175 { 176 Gen regzero; 177 regzero = nullgen; 178 regzero.type = D_REG; 179 regzero.reg = 0; 180 outcode(ACSRRW, &$4, $2.reg, ®zero); 181 } 182 | LMOVW imm ',' ctlreg 183 { 184 Gen regzero; 185 int r = $2.offset; 186 if(r < 0 || r >= NREG) 187 yyerror("immediate value out of range"); 188 regzero = nullgen; 189 regzero.type = D_REG; 190 regzero.reg = 0; 191 outcode(ACSRRWI, &$4, r, ®zero); 192 } 193 | LMOVW ctlreg ',' rreg 194 { 195 outcode(ACSRRS, &$2, REGZERO, &$4); 196 } 197 198 | LLUI name ',' rreg 199 { 200 outcode($1, &$2, NREG, &$4); 201 } 202 | LLUI imm ',' rreg 203 { 204 outcode($1, &$2, NREG, &$4); 205 } 206 207 208 | LSYS imm 209 { 210 outcode($1, &nullgen, NREG, &$2); 211 } 212 213 | LSYS0 214 { 215 Gen syscon; 216 syscon = nullgen; 217 syscon.type = D_CONST; 218 syscon.offset = $1; 219 outcode(ASYS, &nullgen, NREG, &syscon); 220 } 221 222 | LCSR ctlreg ',' sreg ',' rreg 223 { 224 outcode($1, &$2, $4, &$6); 225 } 226 227 | LCSR ctlreg ',' '$' con ',' rreg 228 { 229 if($5 < 0 || $5 >= NREG) 230 yyerror("immediate value out of range"); 231 outcode($1 + (ACSRRWI-ACSRRW), &$2, $5, &$7); 232 } 233 234 | LSWAP rreg ',' sreg ',' rreg 235 { 236 outcode($1, &$2, $4, &$6); 237 } 238 239 | LAMO con ',' rreg ',' sreg ',' rreg 240 { 241 outcode($1, &$4, ($2<<16)|$6, &$8); 242 } 243 244 | LTEXT name ',' imm 245 { 246 outcode($1, &$2, NREG, &$4); 247 } 248 | LTEXT name ',' con ',' imm 249 { 250 outcode($1, &$2, $4, &$6); 251 } 252 253 | LDATA name '/' con ',' imm 254 { 255 outcode($1, &$2, $4, &$6); 256 } 257 | LDATA name '/' con ',' ximm 258 { 259 outcode($1, &$2, $4, &$6); 260 } 261 | LDATA name '/' con ',' fimm 262 { 263 outcode($1, &$2, $4, &$6); 264 } 265 266 | LWORD imm 267 { 268 outcode($1, &nullgen, NREG, &$2); 269 } 270 271 rel: 272 con '(' LPC ')' 273 { 274 $$ = nullgen; 275 $$.type = D_BRANCH; 276 $$.offset = $1 + pc; 277 } 278 | LNAME offset 279 { 280 $$ = nullgen; 281 if(pass == 2) 282 yyerror("undefined label: %s", $1->name); 283 $$.type = D_BRANCH; 284 $$.sym = $1; 285 $$.offset = $2; 286 } 287 | LLAB offset 288 { 289 $$ = nullgen; 290 $$.type = D_BRANCH; 291 $$.sym = $1; 292 $$.offset = $1->value + $2; 293 } 294 295 oprrr: 296 LADD 297 | LMUL 298 299 addr: 300 oreg 301 | name 302 303 oreg: 304 '(' sreg ')' 305 { 306 $$ = nullgen; 307 $$.type = D_OREG; 308 $$.reg = $2; 309 $$.offset = 0; 310 } 311 | con '(' sreg ')' 312 { 313 $$ = nullgen; 314 $$.type = D_OREG; 315 $$.reg = $3; 316 $$.offset = $1; 317 } 318 319 name: 320 con '(' pointer ')' 321 { 322 $$ = nullgen; 323 $$.type = D_OREG; 324 $$.name = $3; 325 $$.sym = S; 326 $$.offset = $1; 327 } 328 | LNAME offset '(' pointer ')' 329 { 330 $$ = nullgen; 331 $$.type = D_OREG; 332 $$.name = $4; 333 $$.sym = $1; 334 $$.offset = $2; 335 } 336 | LNAME '<' '>' offset '(' LSB ')' 337 { 338 $$ = nullgen; 339 $$.type = D_OREG; 340 $$.name = D_STATIC; 341 $$.sym = $1; 342 $$.offset = $4; 343 } 344 345 offset: 346 { 347 $$ = 0; 348 } 349 | '+' con 350 { 351 $$ = $2; 352 } 353 | '-' con 354 { 355 $$ = -$2; 356 } 357 358 pointer: 359 LSB 360 | LSP 361 | LFP 362 363 rreg: 364 sreg 365 { 366 $$ = nullgen; 367 $$.type = D_REG; 368 $$.reg = $1; 369 } 370 371 dreg: 372 freg 373 { 374 $$ = nullgen; 375 $$.type = D_FREG; 376 $$.reg = $1; 377 } 378 379 drreg: 380 dreg 381 | rreg 382 383 sreg: 384 LREG 385 | LR '(' expr ')' 386 { 387 if($3 < 0 || $3 >= NREG) 388 yyerror("register value out of range"); 389 $$ = $3; 390 } 391 392 freg: 393 LFREG 394 | FR '(' expr ')' 395 { 396 if($3 < 0 || $3 >= NREG) 397 yyerror("register value out of range"); 398 $$ = $3; 399 } 400 401 ctlreg: 402 LCTL '(' expr ')' 403 { 404 if($3 < 0 || $3 >= 0xFFF) 405 yyerror("CSR value out of range"); 406 $$ = nullgen; 407 $$.type = D_CTLREG; 408 $$.offset = $3; 409 } 410 411 ximm: 412 '$' addr 413 { 414 $$ = $2; 415 $$.type = D_CONST; 416 } 417 | '$' LSCONST 418 { 419 $$ = nullgen; 420 $$.type = D_SCONST; 421 memcpy($$.sval, $2, sizeof($$.sval)); 422 } 423 424 fimm: 425 '$' LFCONST 426 { 427 $$ = nullgen; 428 $$.type = D_FCONST; 429 $$.dval = $2; 430 } 431 | '$' '-' LFCONST 432 { 433 $$ = nullgen; 434 $$.type = D_FCONST; 435 $$.dval = -$3; 436 } 437 438 imm: 439 '$' con 440 { 441 $$ = nullgen; 442 $$.type = D_CONST; 443 $$.offset = $2; 444 if(thechar == 'j' && (vlong)$$.offset != $2){ 445 $$.type = D_VCONST; 446 $$.vval = $2; 447 } 448 } 449 450 con: 451 LCONST 452 | LVAR 453 { 454 $$ = $1->value; 455 } 456 | '-' con 457 { 458 $$ = -$2; 459 } 460 | '+' con 461 { 462 $$ = $2; 463 } 464 | '~' con 465 { 466 $$ = ~$2; 467 } 468 | '(' expr ')' 469 { 470 $$ = $2; 471 } 472 473 expr: 474 con 475 | expr '+' expr 476 { 477 $$ = $1 + $3; 478 } 479 | expr '-' expr 480 { 481 $$ = $1 - $3; 482 } 483 | expr '*' expr 484 { 485 $$ = $1 * $3; 486 } 487 | expr '/' expr 488 { 489 $$ = $1 / $3; 490 } 491 | expr '%' expr 492 { 493 $$ = $1 % $3; 494 } 495 | expr '<' '<' expr 496 { 497 $$ = $1 << $4; 498 } 499 | expr '>' '>' expr 500 { 501 $$ = $1 >> $4; 502 } 503 | expr '&' expr 504 { 505 $$ = $1 & $3; 506 } 507 | expr '^' expr 508 { 509 $$ = $1 ^ $3; 510 } 511 | expr '|' expr 512 { 513 $$ = $1 | $3; 514 } 515