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