1 %{ 2 /* 3 * Copyright(c) 2019-2023 rev.ng Labs Srl. All Rights Reserved. 4 * 5 * This program is distributed in the hope that it will be useful, 6 * but WITHOUT ANY WARRANTY; without even the implied warranty of 7 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 8 * GNU General Public License for more details. 9 * 10 * You should have received a copy of the GNU General Public License 11 * along with this program; if not, see <http://www.gnu.org/licenses/>. 12 */ 13 14 #include "idef-parser.h" 15 #include "parser-helpers.h" 16 #include "idef-parser.tab.h" 17 #include "idef-parser.yy.h" 18 19 /* Uncomment this to disable yyasserts */ 20 /* #define NDEBUG */ 21 22 #define ERR_LINE_CONTEXT 40 23 24 %} 25 26 %lex-param {void *scanner} 27 %parse-param {void *scanner} 28 %parse-param {Context *c} 29 30 %define parse.error verbose 31 %define parse.lac full 32 %define api.pure full 33 34 %locations 35 36 %union { 37 GString *string; 38 HexValue rvalue; 39 HexSat sat; 40 HexCast cast; 41 HexExtract extract; 42 HexMpy mpy; 43 HexSignedness signedness; 44 int index; 45 } 46 47 /* Tokens */ 48 %start input 49 50 %expect 1 51 52 %token IN INAME VAR 53 %token ABS CROUND ROUND CIRCADD COUNTONES INC DEC ANDA ORA XORA PLUSPLUS ASL 54 %token ASR LSR EQ NEQ LTE GTE MIN MAX ANDL FOR ICIRC IF MUN FSCR FCHK SXT 55 %token ZXT CONSTEXT LOCNT BREV SIGN LOAD STORE PC LPCFG 56 %token LOAD_CANCEL STORE_CANCEL CANCEL IDENTITY ROTL INSBITS SETBITS EXTRANGE 57 %token CAST4_8U FAIL CARRY_FROM_ADD ADDSAT64 LSBNEW 58 %token TYPE_SIZE_T TYPE_INT TYPE_SIGNED TYPE_UNSIGNED TYPE_LONG 59 60 %token <rvalue> REG IMM PRED 61 %token <index> ELSE 62 %token <mpy> MPY 63 %token <sat> SAT 64 %token <cast> CAST DEPOSIT SETHALF 65 %token <extract> EXTRACT 66 %type <string> INAME 67 %type <rvalue> rvalue lvalue VAR assign_statement var var_decl var_type 68 %type <rvalue> FAIL 69 %type <rvalue> TYPE_SIGNED TYPE_UNSIGNED TYPE_INT TYPE_LONG TYPE_SIZE_T 70 %type <index> if_stmt IF 71 %type <signedness> SIGN 72 73 /* Operator Precedences */ 74 %left MIN MAX 75 %left '(' 76 %left ',' 77 %left '=' 78 %right CIRCADD 79 %right INC DEC ANDA ORA XORA 80 %left '?' ':' 81 %left ANDL 82 %left '|' 83 %left '^' ANDOR 84 %left '&' 85 %left EQ NEQ 86 %left '<' '>' LTE GTE 87 %left ASL ASR LSR 88 %right ABS 89 %left '-' '+' 90 %left '*' '/' '%' MPY 91 %right '~' '!' 92 %left '[' 93 %right CAST 94 %right LOCNT BREV 95 96 /* Bison Grammar */ 97 %% 98 99 /* Input file containing the description of each hexagon instruction */ 100 input : instructions 101 { 102 /* Suppress warning about unused yynerrs */ 103 (void) yynerrs; 104 YYACCEPT; 105 } 106 ; 107 108 instructions : instruction instructions 109 | %empty 110 ; 111 112 instruction : INAME 113 { 114 gen_inst(c, $1); 115 } 116 arguments 117 { 118 EMIT_SIG(c, ")"); 119 EMIT_HEAD(c, "{\n"); 120 } 121 code 122 { 123 gen_inst_code(c, &@1); 124 } 125 | error /* Recover gracefully after instruction compilation error */ 126 { 127 free_instruction(c); 128 } 129 ; 130 131 arguments : '(' ')' 132 | '(' argument_list ')'; 133 134 argument_list : argument_decl ',' argument_list 135 | argument_decl 136 ; 137 138 var : VAR 139 { 140 track_string(c, $1.var.name); 141 $$ = $1; 142 } 143 ; 144 145 /* 146 * Here the integer types are defined from valid combinations of 147 * `signed`, `unsigned`, `int`, and `long` tokens. The `signed` 148 * and `unsigned` tokens are here assumed to always be placed 149 * first in the type declaration, which is not the case in 150 * normal C. Similarly, `int` is assumed to always be placed 151 * last in the type. 152 */ 153 type_int : TYPE_INT 154 | TYPE_SIGNED 155 | TYPE_SIGNED TYPE_INT; 156 type_uint : TYPE_UNSIGNED 157 | TYPE_UNSIGNED TYPE_INT; 158 type_ulonglong : TYPE_UNSIGNED TYPE_LONG TYPE_LONG 159 | TYPE_UNSIGNED TYPE_LONG TYPE_LONG TYPE_INT; 160 161 /* 162 * Here the various valid int types defined above specify 163 * their `signedness` and `bit_width`. The LP64 convention 164 * is assumed where longs are 64-bit, long longs are then 165 * assumed to also be 64-bit. 166 */ 167 var_type : TYPE_SIZE_T 168 { 169 yyassert(c, &@1, $1.bit_width <= 64, 170 "Variables with size > 64-bit are not supported!"); 171 $$ = $1; 172 } 173 | type_int 174 { 175 $$.signedness = SIGNED; 176 $$.bit_width = 32; 177 } 178 | type_uint 179 { 180 $$.signedness = UNSIGNED; 181 $$.bit_width = 32; 182 } 183 | type_ulonglong 184 { 185 $$.signedness = UNSIGNED; 186 $$.bit_width = 64; 187 } 188 ; 189 190 /* Rule to capture declarations of VARs */ 191 var_decl : var_type IMM 192 { 193 /* 194 * Rule to capture "int i;" declarations since "i" is special 195 * and assumed to be always be IMM. Moreover, "i" is only 196 * assumed to be used in for-loops. 197 * 198 * Therefore we want to NOP these declarations. 199 */ 200 yyassert(c, &@2, $2.imm.type == I, 201 "Variable declaration with immedaties only allowed" 202 " for the loop induction variable \"i\""); 203 $$ = $2; 204 } 205 | var_type var 206 { 207 /* 208 * Allocate new variable, this checks that it hasn't already 209 * been declared. 210 */ 211 gen_varid_allocate(c, &@1, &$2, $1.bit_width, $1.signedness); 212 /* Copy var for variable name */ 213 $$ = $2; 214 /* Copy type info from var_type */ 215 $$.signedness = $1.signedness; 216 $$.bit_width = $1.bit_width; 217 } 218 ; 219 220 /* Return the modified registers list */ 221 code : '{' statements '}' 222 { 223 c->inst.code_begin = c->input_buffer + @2.first_column - 1; 224 c->inst.code_end = c->input_buffer + @2.last_column - 1; 225 } 226 | '{' 227 { 228 /* Nop */ 229 } 230 '}' 231 ; 232 233 argument_decl : REG 234 { 235 emit_arg(c, &@1, &$1); 236 /* Enqueue register into initialization list */ 237 g_array_append_val(c->inst.init_list, $1); 238 } 239 | PRED 240 { 241 emit_arg(c, &@1, &$1); 242 /* Enqueue predicate into initialization list */ 243 g_array_append_val(c->inst.init_list, $1); 244 } 245 | IN REG 246 { 247 emit_arg(c, &@2, &$2); 248 } 249 | IN PRED 250 { 251 emit_arg(c, &@2, &$2); 252 } 253 | IMM 254 { 255 EMIT_SIG(c, ", int %ciV", $1.imm.id); 256 } 257 ; 258 259 code_block : '{' statements '}' 260 | '{' '}' 261 ; 262 263 /* A list of one or more statements */ 264 statements : statements statement 265 | statement 266 ; 267 268 /* Statements can be assignment (rvalue ';'), control or memory statements */ 269 statement : control_statement 270 | var_decl ';' 271 | rvalue ';' 272 | code_block 273 | ';' 274 ; 275 276 assign_statement : lvalue '=' rvalue 277 { 278 @1.last_column = @3.last_column; 279 gen_assign(c, &@1, &$1, &$3); 280 $$ = $1; 281 } 282 | var_decl '=' rvalue 283 { 284 @1.last_column = @3.last_column; 285 gen_assign(c, &@1, &$1, &$3); 286 $$ = $1; 287 } 288 | lvalue INC rvalue 289 { 290 @1.last_column = @3.last_column; 291 HexValue tmp = gen_bin_op(c, &@1, ADD_OP, &$1, &$3); 292 gen_assign(c, &@1, &$1, &tmp); 293 $$ = $1; 294 } 295 | lvalue DEC rvalue 296 { 297 @1.last_column = @3.last_column; 298 HexValue tmp = gen_bin_op(c, &@1, SUB_OP, &$1, &$3); 299 gen_assign(c, &@1, &$1, &tmp); 300 $$ = $1; 301 } 302 | lvalue ANDA rvalue 303 { 304 @1.last_column = @3.last_column; 305 HexValue tmp = gen_bin_op(c, &@1, ANDB_OP, &$1, &$3); 306 gen_assign(c, &@1, &$1, &tmp); 307 $$ = $1; 308 } 309 | lvalue ORA rvalue 310 { 311 @1.last_column = @3.last_column; 312 HexValue tmp = gen_bin_op(c, &@1, ORB_OP, &$1, &$3); 313 gen_assign(c, &@1, &$1, &tmp); 314 $$ = $1; 315 } 316 | lvalue XORA rvalue 317 { 318 @1.last_column = @3.last_column; 319 HexValue tmp = gen_bin_op(c, &@1, XORB_OP, &$1, &$3); 320 gen_assign(c, &@1, &$1, &tmp); 321 $$ = $1; 322 } 323 | PRED '=' rvalue 324 { 325 @1.last_column = @3.last_column; 326 gen_pred_assign(c, &@1, &$1, &$3); 327 } 328 | IMM '=' rvalue 329 { 330 @1.last_column = @3.last_column; 331 yyassert(c, &@1, $3.type == IMMEDIATE, 332 "Cannot assign non-immediate to immediate!"); 333 yyassert(c, &@1, $1.imm.type == VARIABLE, 334 "Cannot assign to non-variable!"); 335 /* Assign to the function argument */ 336 OUT(c, &@1, &$1, " = ", &$3, ";\n"); 337 $$ = $1; 338 } 339 | LOAD '(' IMM ',' IMM ',' SIGN ',' var ',' lvalue ')' 340 { 341 @1.last_column = @12.last_column; 342 yyassert(c, &@1, !is_inside_ternary(c), 343 "Assignment side-effect not modeled!"); 344 yyassert(c, &@1, $3.imm.value == 1, 345 "LOAD of arrays not supported!"); 346 gen_load(c, &@1, &$5, $7, &$9, &$11); 347 } 348 | STORE '(' IMM ',' IMM ',' var ',' rvalue ')' 349 /* Store primitive */ 350 { 351 @1.last_column = @10.last_column; 352 yyassert(c, &@1, !is_inside_ternary(c), 353 "Assignment side-effect not modeled!"); 354 yyassert(c, &@1, $3.imm.value == 1, 355 "STORE of arrays not supported!"); 356 gen_store(c, &@1, &$5, &$7, &$9); 357 } 358 | LPCFG '=' rvalue 359 { 360 @1.last_column = @3.last_column; 361 yyassert(c, &@1, !is_inside_ternary(c), 362 "Assignment side-effect not modeled!"); 363 $3 = gen_rvalue_truncate(c, &@1, &$3); 364 $3 = rvalue_materialize(c, &@1, &$3); 365 OUT(c, &@1, "gen_set_usr_field(ctx, USR_LPCFG, ", &$3, ");\n"); 366 } 367 | DEPOSIT '(' rvalue ',' rvalue ',' rvalue ')' 368 { 369 @1.last_column = @8.last_column; 370 yyassert(c, &@1, !is_inside_ternary(c), 371 "Assignment side-effect not modeled!"); 372 gen_deposit_op(c, &@1, &$5, &$7, &$3, &$1); 373 } 374 | SETHALF '(' rvalue ',' lvalue ',' rvalue ')' 375 { 376 @1.last_column = @8.last_column; 377 yyassert(c, &@1, !is_inside_ternary(c), 378 "Assignment side-effect not modeled!"); 379 gen_sethalf(c, &@1, &$1, &$3, &$5, &$7); 380 } 381 | SETBITS '(' rvalue ',' rvalue ',' rvalue ',' rvalue ')' 382 { 383 @1.last_column = @10.last_column; 384 yyassert(c, &@1, !is_inside_ternary(c), 385 "Assignment side-effect not modeled!"); 386 gen_setbits(c, &@1, &$3, &$5, &$7, &$9); 387 } 388 | INSBITS '(' lvalue ',' rvalue ',' rvalue ',' rvalue ')' 389 { 390 @1.last_column = @10.last_column; 391 yyassert(c, &@1, !is_inside_ternary(c), 392 "Assignment side-effect not modeled!"); 393 gen_rdeposit_op(c, &@1, &$3, &$9, &$7, &$5); 394 } 395 | IDENTITY '(' rvalue ')' 396 { 397 @1.last_column = @4.last_column; 398 $$ = $3; 399 } 400 ; 401 402 control_statement : frame_check 403 | cancel_statement 404 | if_statement 405 | for_statement 406 ; 407 408 frame_check : FCHK '(' rvalue ',' rvalue ')' ';' 409 ; 410 411 cancel_statement : LOAD_CANCEL 412 { 413 gen_load_cancel(c, &@1); 414 } 415 | STORE_CANCEL 416 { 417 gen_cancel(c, &@1); 418 } 419 | CANCEL 420 ; 421 422 if_statement : if_stmt 423 { 424 /* Fix else label */ 425 OUT(c, &@1, "gen_set_label(if_label_", &$1, ");\n"); 426 } 427 | if_stmt ELSE 428 { 429 @1.last_column = @2.last_column; 430 $2 = gen_if_else(c, &@1, $1); 431 } 432 statement 433 { 434 OUT(c, &@1, "gen_set_label(if_label_", &$2, ");\n"); 435 } 436 ; 437 438 for_statement : FOR '(' IMM '=' IMM ';' IMM '<' IMM ';' IMM PLUSPLUS ')' 439 { 440 yyassert(c, &@3, 441 $3.imm.type == I && 442 $7.imm.type == I && 443 $11.imm.type == I, 444 "Loop induction variable must be \"i\""); 445 @1.last_column = @13.last_column; 446 OUT(c, &@1, "for (int ", &$3, " = ", &$5, "; ", 447 &$7, " < ", &$9); 448 OUT(c, &@1, "; ", &$11, "++) {\n"); 449 } 450 code_block 451 { 452 OUT(c, &@1, "}\n"); 453 } 454 ; 455 456 if_stmt : IF '(' rvalue ')' 457 { 458 @1.last_column = @3.last_column; 459 $1 = gen_if_cond(c, &@1, &$3); 460 } 461 statement 462 { 463 $$ = $1; 464 } 465 ; 466 467 rvalue : FAIL 468 { 469 yyassert(c, &@1, false, "Encountered a FAIL token as rvalue.\n"); 470 } 471 | assign_statement 472 | REG 473 { 474 $$ = $1; 475 } 476 | IMM 477 { 478 $$ = $1; 479 } 480 | PRED 481 { 482 $$ = gen_rvalue_pred(c, &@1, &$1); 483 } 484 | PC 485 { 486 /* Read PC from the CR */ 487 HexValue rvalue; 488 memset(&rvalue, 0, sizeof(HexValue)); 489 rvalue.type = IMMEDIATE; 490 rvalue.imm.type = IMM_PC; 491 rvalue.bit_width = 32; 492 rvalue.signedness = UNSIGNED; 493 $$ = rvalue; 494 } 495 | CONSTEXT 496 { 497 HexValue rvalue; 498 memset(&rvalue, 0, sizeof(HexValue)); 499 rvalue.type = IMMEDIATE; 500 rvalue.imm.type = IMM_CONSTEXT; 501 rvalue.signedness = UNSIGNED; 502 rvalue.is_dotnew = false; 503 $$ = rvalue; 504 } 505 | var 506 { 507 $$ = gen_rvalue_var(c, &@1, &$1); 508 } 509 | MPY '(' rvalue ',' rvalue ')' 510 { 511 @1.last_column = @6.last_column; 512 $$ = gen_rvalue_mpy(c, &@1, &$1, &$3, &$5); 513 } 514 | rvalue '+' rvalue 515 { 516 @1.last_column = @3.last_column; 517 $$ = gen_bin_op(c, &@1, ADD_OP, &$1, &$3); 518 } 519 | rvalue '-' rvalue 520 { 521 @1.last_column = @3.last_column; 522 $$ = gen_bin_op(c, &@1, SUB_OP, &$1, &$3); 523 } 524 | rvalue '*' rvalue 525 { 526 @1.last_column = @3.last_column; 527 $$ = gen_bin_op(c, &@1, MUL_OP, &$1, &$3); 528 } 529 | rvalue ASL rvalue 530 { 531 @1.last_column = @3.last_column; 532 $$ = gen_bin_op(c, &@1, ASL_OP, &$1, &$3); 533 } 534 | rvalue ASR rvalue 535 { 536 @1.last_column = @3.last_column; 537 assert_signedness(c, &@1, $1.signedness); 538 if ($1.signedness == UNSIGNED) { 539 $$ = gen_bin_op(c, &@1, LSR_OP, &$1, &$3); 540 } else if ($1.signedness == SIGNED) { 541 $$ = gen_bin_op(c, &@1, ASR_OP, &$1, &$3); 542 } 543 } 544 | rvalue LSR rvalue 545 { 546 @1.last_column = @3.last_column; 547 $$ = gen_bin_op(c, &@1, LSR_OP, &$1, &$3); 548 } 549 | rvalue '&' rvalue 550 { 551 @1.last_column = @3.last_column; 552 $$ = gen_bin_op(c, &@1, ANDB_OP, &$1, &$3); 553 } 554 | rvalue '|' rvalue 555 { 556 @1.last_column = @3.last_column; 557 $$ = gen_bin_op(c, &@1, ORB_OP, &$1, &$3); 558 } 559 | rvalue '^' rvalue 560 { 561 @1.last_column = @3.last_column; 562 $$ = gen_bin_op(c, &@1, XORB_OP, &$1, &$3); 563 } 564 | rvalue ANDL rvalue 565 { 566 @1.last_column = @3.last_column; 567 $$ = gen_bin_op(c, &@1, ANDL_OP, &$1, &$3); 568 } 569 | MIN '(' rvalue ',' rvalue ')' 570 { 571 @1.last_column = @3.last_column; 572 $$ = gen_bin_op(c, &@1, MINI_OP, &$3, &$5); 573 } 574 | MAX '(' rvalue ',' rvalue ')' 575 { 576 @1.last_column = @3.last_column; 577 $$ = gen_bin_op(c, &@1, MAXI_OP, &$3, &$5); 578 } 579 | '~' rvalue 580 { 581 @1.last_column = @2.last_column; 582 $$ = gen_rvalue_not(c, &@1, &$2); 583 } 584 | '!' rvalue 585 { 586 @1.last_column = @2.last_column; 587 $$ = gen_rvalue_notl(c, &@1, &$2); 588 } 589 | SAT '(' IMM ',' rvalue ')' 590 { 591 @1.last_column = @6.last_column; 592 $$ = gen_rvalue_sat(c, &@1, &$1, &$3, &$5); 593 } 594 | CAST rvalue 595 { 596 @1.last_column = @2.last_column; 597 $$ = gen_cast_op(c, &@1, &$2, $1.bit_width, $1.signedness); 598 } 599 | rvalue EQ rvalue 600 { 601 @1.last_column = @3.last_column; 602 $$ = gen_bin_cmp(c, &@1, TCG_COND_EQ, &$1, &$3); 603 } 604 | rvalue NEQ rvalue 605 { 606 @1.last_column = @3.last_column; 607 $$ = gen_bin_cmp(c, &@1, TCG_COND_NE, &$1, &$3); 608 } 609 | rvalue '<' rvalue 610 { 611 @1.last_column = @3.last_column; 612 613 assert_signedness(c, &@1, $1.signedness); 614 assert_signedness(c, &@1, $3.signedness); 615 if ($1.signedness == UNSIGNED || $3.signedness == UNSIGNED) { 616 $$ = gen_bin_cmp(c, &@1, TCG_COND_LTU, &$1, &$3); 617 } else { 618 $$ = gen_bin_cmp(c, &@1, TCG_COND_LT, &$1, &$3); 619 } 620 } 621 | rvalue '>' rvalue 622 { 623 @1.last_column = @3.last_column; 624 625 assert_signedness(c, &@1, $1.signedness); 626 assert_signedness(c, &@1, $3.signedness); 627 if ($1.signedness == UNSIGNED || $3.signedness == UNSIGNED) { 628 $$ = gen_bin_cmp(c, &@1, TCG_COND_GTU, &$1, &$3); 629 } else { 630 $$ = gen_bin_cmp(c, &@1, TCG_COND_GT, &$1, &$3); 631 } 632 } 633 | rvalue LTE rvalue 634 { 635 @1.last_column = @3.last_column; 636 637 assert_signedness(c, &@1, $1.signedness); 638 assert_signedness(c, &@1, $3.signedness); 639 if ($1.signedness == UNSIGNED || $3.signedness == UNSIGNED) { 640 $$ = gen_bin_cmp(c, &@1, TCG_COND_LEU, &$1, &$3); 641 } else { 642 $$ = gen_bin_cmp(c, &@1, TCG_COND_LE, &$1, &$3); 643 } 644 } 645 | rvalue GTE rvalue 646 { 647 @1.last_column = @3.last_column; 648 649 assert_signedness(c, &@1, $1.signedness); 650 assert_signedness(c, &@1, $3.signedness); 651 if ($1.signedness == UNSIGNED || $3.signedness == UNSIGNED) { 652 $$ = gen_bin_cmp(c, &@1, TCG_COND_GEU, &$1, &$3); 653 } else { 654 $$ = gen_bin_cmp(c, &@1, TCG_COND_GE, &$1, &$3); 655 } 656 } 657 | rvalue '?' 658 { 659 Ternary t = { 0 }; 660 t.state = IN_LEFT; 661 t.cond = $1; 662 g_array_append_val(c->ternary, t); 663 } 664 rvalue ':' 665 { 666 Ternary *t = &g_array_index(c->ternary, Ternary, 667 c->ternary->len - 1); 668 t->state = IN_RIGHT; 669 } 670 rvalue 671 { 672 @1.last_column = @5.last_column; 673 $$ = gen_rvalue_ternary(c, &@1, &$1, &$4, &$7); 674 } 675 | FSCR '(' rvalue ')' 676 { 677 @1.last_column = @4.last_column; 678 $$ = gen_rvalue_fscr(c, &@1, &$3); 679 } 680 | SXT '(' rvalue ',' IMM ',' rvalue ')' 681 { 682 @1.last_column = @8.last_column; 683 yyassert(c, &@1, $5.type == IMMEDIATE && 684 $5.imm.type == VALUE, 685 "SXT expects immediate values\n"); 686 $$ = gen_extend_op(c, &@1, &$3, 64, &$7, SIGNED); 687 } 688 | ZXT '(' rvalue ',' IMM ',' rvalue ')' 689 { 690 @1.last_column = @8.last_column; 691 yyassert(c, &@1, $5.type == IMMEDIATE && 692 $5.imm.type == VALUE, 693 "ZXT expects immediate values\n"); 694 $$ = gen_extend_op(c, &@1, &$3, 64, &$7, UNSIGNED); 695 } 696 | '(' rvalue ')' 697 { 698 $$ = $2; 699 } 700 | ABS rvalue 701 { 702 @1.last_column = @2.last_column; 703 $$ = gen_rvalue_abs(c, &@1, &$2); 704 } 705 | CROUND '(' rvalue ',' rvalue ')' 706 { 707 @1.last_column = @6.last_column; 708 $$ = gen_convround_n(c, &@1, &$3, &$5); 709 } 710 | CROUND '(' rvalue ')' 711 { 712 @1.last_column = @4.last_column; 713 $$ = gen_convround(c, &@1, &$3); 714 } 715 | ROUND '(' rvalue ',' rvalue ')' 716 { 717 @1.last_column = @6.last_column; 718 $$ = gen_round(c, &@1, &$3, &$5); 719 } 720 | '-' rvalue 721 { 722 @1.last_column = @2.last_column; 723 $$ = gen_rvalue_neg(c, &@1, &$2); 724 } 725 | ICIRC '(' rvalue ')' ASL IMM 726 { 727 @1.last_column = @6.last_column; 728 $$ = gen_tmp(c, &@1, 32, UNSIGNED); 729 OUT(c, &@1, "gen_read_ireg(", &$$, ", ", &$3, ", ", &$6, ");\n"); 730 } 731 | CIRCADD '(' rvalue ',' rvalue ',' rvalue ')' 732 { 733 @1.last_column = @8.last_column; 734 gen_circ_op(c, &@1, &$3, &$5, &$7); 735 } 736 | LOCNT '(' rvalue ')' 737 { 738 @1.last_column = @4.last_column; 739 /* Leading ones count */ 740 $$ = gen_locnt_op(c, &@1, &$3); 741 } 742 | COUNTONES '(' rvalue ')' 743 { 744 @1.last_column = @4.last_column; 745 /* Ones count */ 746 $$ = gen_ctpop_op(c, &@1, &$3); 747 } 748 | EXTRACT '(' rvalue ',' rvalue ')' 749 { 750 @1.last_column = @6.last_column; 751 $$ = gen_extract_op(c, &@1, &$5, &$3, &$1); 752 } 753 | EXTRANGE '(' rvalue ',' rvalue ',' rvalue ')' 754 { 755 @1.last_column = @8.last_column; 756 yyassert(c, &@1, $5.type == IMMEDIATE && 757 $5.imm.type == VALUE && 758 $7.type == IMMEDIATE && 759 $7.imm.type == VALUE, 760 "Range extract needs immediate values!\n"); 761 $$ = gen_rextract_op(c, 762 &@1, 763 &$3, 764 $7.imm.value, 765 $5.imm.value - $7.imm.value + 1); 766 } 767 | CAST4_8U '(' rvalue ')' 768 { 769 @1.last_column = @4.last_column; 770 $$ = gen_rvalue_truncate(c, &@1, &$3); 771 $$.signedness = UNSIGNED; 772 $$ = rvalue_materialize(c, &@1, &$$); 773 $$ = gen_rvalue_extend(c, &@1, &$$); 774 } 775 | BREV '(' rvalue ')' 776 { 777 @1.last_column = @4.last_column; 778 $$ = gen_rvalue_brev(c, &@1, &$3); 779 } 780 | ROTL '(' rvalue ',' rvalue ')' 781 { 782 @1.last_column = @6.last_column; 783 $$ = gen_rotl(c, &@1, &$3, &$5); 784 } 785 | ADDSAT64 '(' rvalue ',' rvalue ',' rvalue ')' 786 { 787 @1.last_column = @8.last_column; 788 gen_addsat64(c, &@1, &$3, &$5, &$7); 789 } 790 | CARRY_FROM_ADD '(' rvalue ',' rvalue ',' rvalue ')' 791 { 792 @1.last_column = @8.last_column; 793 $$ = gen_carry_from_add(c, &@1, &$3, &$5, &$7); 794 } 795 | LSBNEW '(' rvalue ')' 796 { 797 @1.last_column = @4.last_column; 798 HexValue one = gen_imm_value(c, &@1, 1, 32, UNSIGNED); 799 $$ = gen_bin_op(c, &@1, ANDB_OP, &$3, &one); 800 } 801 ; 802 803 lvalue : FAIL 804 { 805 @1.last_column = @1.last_column; 806 yyassert(c, &@1, false, "Encountered a FAIL token as lvalue.\n"); 807 } 808 | REG 809 { 810 $$ = $1; 811 } 812 | var 813 { 814 $$ = $1; 815 } 816 ; 817 818 %% 819 820 int main(int argc, char **argv) 821 { 822 if (argc != 5) { 823 fprintf(stderr, 824 "Semantics: Hexagon ISA to tinycode generator compiler\n\n"); 825 fprintf(stderr, 826 "Usage: ./semantics IDEFS EMITTER_C EMITTER_H " 827 "ENABLED_INSTRUCTIONS_LIST\n"); 828 return 1; 829 } 830 831 enum { 832 ARG_INDEX_ARGV0 = 0, 833 ARG_INDEX_IDEFS, 834 ARG_INDEX_EMITTER_C, 835 ARG_INDEX_EMITTER_H, 836 ARG_INDEX_ENABLED_INSTRUCTIONS_LIST 837 }; 838 839 FILE *enabled_file = fopen(argv[ARG_INDEX_ENABLED_INSTRUCTIONS_LIST], "w"); 840 841 FILE *output_file = fopen(argv[ARG_INDEX_EMITTER_C], "w"); 842 fputs("#include \"qemu/osdep.h\"\n", output_file); 843 fputs("#include \"qemu/log.h\"\n", output_file); 844 fputs("#include \"cpu.h\"\n", output_file); 845 fputs("#include \"internal.h\"\n", output_file); 846 fputs("#include \"tcg/tcg-op.h\"\n", output_file); 847 fputs("#include \"insn.h\"\n", output_file); 848 fputs("#include \"opcodes.h\"\n", output_file); 849 fputs("#include \"translate.h\"\n", output_file); 850 fputs("#define QEMU_GENERATE\n", output_file); 851 fputs("#include \"genptr.h\"\n", output_file); 852 fputs("#include \"tcg/tcg.h\"\n", output_file); 853 fputs("#include \"macros.h\"\n", output_file); 854 fprintf(output_file, "#include \"%s\"\n", argv[ARG_INDEX_EMITTER_H]); 855 856 FILE *defines_file = fopen(argv[ARG_INDEX_EMITTER_H], "w"); 857 assert(defines_file != NULL); 858 fputs("#ifndef HEX_EMITTER_H\n", defines_file); 859 fputs("#define HEX_EMITTER_H\n", defines_file); 860 fputs("\n", defines_file); 861 fputs("#include \"insn.h\"\n\n", defines_file); 862 863 /* Parser input file */ 864 Context context = { 0 }; 865 context.defines_file = defines_file; 866 context.output_file = output_file; 867 context.enabled_file = enabled_file; 868 /* Initialize buffers */ 869 context.out_str = g_string_new(NULL); 870 context.signature_str = g_string_new(NULL); 871 context.header_str = g_string_new(NULL); 872 context.ternary = g_array_new(FALSE, TRUE, sizeof(Ternary)); 873 /* Read input file */ 874 FILE *input_file = fopen(argv[ARG_INDEX_IDEFS], "r"); 875 fseek(input_file, 0L, SEEK_END); 876 long input_size = ftell(input_file); 877 context.input_buffer = (char *) calloc(input_size + 1, sizeof(char)); 878 fseek(input_file, 0L, SEEK_SET); 879 size_t read_chars = fread(context.input_buffer, 880 sizeof(char), 881 input_size, 882 input_file); 883 if (read_chars != (size_t) input_size) { 884 fprintf(stderr, "Error: an error occurred while reading input file!\n"); 885 return -1; 886 } 887 yylex_init(&context.scanner); 888 YY_BUFFER_STATE buffer; 889 buffer = yy_scan_string(context.input_buffer, context.scanner); 890 /* Start the parsing procedure */ 891 yyparse(context.scanner, &context); 892 if (context.implemented_insn != context.total_insn) { 893 fprintf(stderr, 894 "Warning: %d/%d meta instructions have been implemented!\n", 895 context.implemented_insn, 896 context.total_insn); 897 } 898 fputs("#endif " START_COMMENT " HEX_EMITTER_h " END_COMMENT "\n", 899 defines_file); 900 /* Cleanup */ 901 yy_delete_buffer(buffer, context.scanner); 902 yylex_destroy(context.scanner); 903 free(context.input_buffer); 904 g_string_free(context.out_str, TRUE); 905 g_string_free(context.signature_str, TRUE); 906 g_string_free(context.header_str, TRUE); 907 g_array_free(context.ternary, TRUE); 908 fclose(output_file); 909 fclose(input_file); 910 fclose(defines_file); 911 fclose(enabled_file); 912 913 return 0; 914 } 915