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, "SET_USR_FIELD(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 /* Assign target signedness */ 598 $2.signedness = $1.signedness; 599 $$ = gen_cast_op(c, &@1, &$2, $1.bit_width, $1.signedness); 600 } 601 | rvalue EQ rvalue 602 { 603 @1.last_column = @3.last_column; 604 $$ = gen_bin_cmp(c, &@1, TCG_COND_EQ, &$1, &$3); 605 } 606 | rvalue NEQ rvalue 607 { 608 @1.last_column = @3.last_column; 609 $$ = gen_bin_cmp(c, &@1, TCG_COND_NE, &$1, &$3); 610 } 611 | rvalue '<' rvalue 612 { 613 @1.last_column = @3.last_column; 614 615 assert_signedness(c, &@1, $1.signedness); 616 assert_signedness(c, &@1, $3.signedness); 617 if ($1.signedness == UNSIGNED || $3.signedness == UNSIGNED) { 618 $$ = gen_bin_cmp(c, &@1, TCG_COND_LTU, &$1, &$3); 619 } else { 620 $$ = gen_bin_cmp(c, &@1, TCG_COND_LT, &$1, &$3); 621 } 622 } 623 | rvalue '>' rvalue 624 { 625 @1.last_column = @3.last_column; 626 627 assert_signedness(c, &@1, $1.signedness); 628 assert_signedness(c, &@1, $3.signedness); 629 if ($1.signedness == UNSIGNED || $3.signedness == UNSIGNED) { 630 $$ = gen_bin_cmp(c, &@1, TCG_COND_GTU, &$1, &$3); 631 } else { 632 $$ = gen_bin_cmp(c, &@1, TCG_COND_GT, &$1, &$3); 633 } 634 } 635 | rvalue LTE rvalue 636 { 637 @1.last_column = @3.last_column; 638 639 assert_signedness(c, &@1, $1.signedness); 640 assert_signedness(c, &@1, $3.signedness); 641 if ($1.signedness == UNSIGNED || $3.signedness == UNSIGNED) { 642 $$ = gen_bin_cmp(c, &@1, TCG_COND_LEU, &$1, &$3); 643 } else { 644 $$ = gen_bin_cmp(c, &@1, TCG_COND_LE, &$1, &$3); 645 } 646 } 647 | rvalue GTE rvalue 648 { 649 @1.last_column = @3.last_column; 650 651 assert_signedness(c, &@1, $1.signedness); 652 assert_signedness(c, &@1, $3.signedness); 653 if ($1.signedness == UNSIGNED || $3.signedness == UNSIGNED) { 654 $$ = gen_bin_cmp(c, &@1, TCG_COND_GEU, &$1, &$3); 655 } else { 656 $$ = gen_bin_cmp(c, &@1, TCG_COND_GE, &$1, &$3); 657 } 658 } 659 | rvalue '?' 660 { 661 Ternary t = { 0 }; 662 t.state = IN_LEFT; 663 t.cond = $1; 664 g_array_append_val(c->ternary, t); 665 } 666 rvalue ':' 667 { 668 Ternary *t = &g_array_index(c->ternary, Ternary, 669 c->ternary->len - 1); 670 t->state = IN_RIGHT; 671 } 672 rvalue 673 { 674 @1.last_column = @5.last_column; 675 $$ = gen_rvalue_ternary(c, &@1, &$1, &$4, &$7); 676 } 677 | FSCR '(' rvalue ')' 678 { 679 @1.last_column = @4.last_column; 680 $$ = gen_rvalue_fscr(c, &@1, &$3); 681 } 682 | SXT '(' rvalue ',' IMM ',' rvalue ')' 683 { 684 @1.last_column = @8.last_column; 685 yyassert(c, &@1, $5.type == IMMEDIATE && 686 $5.imm.type == VALUE, 687 "SXT expects immediate values\n"); 688 $$ = gen_extend_op(c, &@1, &$3, $5.imm.value, &$7, SIGNED); 689 } 690 | ZXT '(' rvalue ',' IMM ',' rvalue ')' 691 { 692 @1.last_column = @8.last_column; 693 yyassert(c, &@1, $5.type == IMMEDIATE && 694 $5.imm.type == VALUE, 695 "ZXT expects immediate values\n"); 696 $$ = gen_extend_op(c, &@1, &$3, $5.imm.value, &$7, UNSIGNED); 697 } 698 | '(' rvalue ')' 699 { 700 $$ = $2; 701 } 702 | ABS rvalue 703 { 704 @1.last_column = @2.last_column; 705 $$ = gen_rvalue_abs(c, &@1, &$2); 706 } 707 | CROUND '(' rvalue ',' rvalue ')' 708 { 709 @1.last_column = @6.last_column; 710 $$ = gen_convround_n(c, &@1, &$3, &$5); 711 } 712 | CROUND '(' rvalue ')' 713 { 714 @1.last_column = @4.last_column; 715 $$ = gen_convround(c, &@1, &$3); 716 } 717 | ROUND '(' rvalue ',' rvalue ')' 718 { 719 @1.last_column = @6.last_column; 720 $$ = gen_round(c, &@1, &$3, &$5); 721 } 722 | '-' rvalue 723 { 724 @1.last_column = @2.last_column; 725 $$ = gen_rvalue_neg(c, &@1, &$2); 726 } 727 | ICIRC '(' rvalue ')' ASL IMM 728 { 729 @1.last_column = @6.last_column; 730 $$ = gen_tmp(c, &@1, 32, UNSIGNED); 731 OUT(c, &@1, "gen_read_ireg(", &$$, ", ", &$3, ", ", &$6, ");\n"); 732 } 733 | CIRCADD '(' rvalue ',' rvalue ',' rvalue ')' 734 { 735 @1.last_column = @8.last_column; 736 gen_circ_op(c, &@1, &$3, &$5, &$7); 737 } 738 | LOCNT '(' rvalue ')' 739 { 740 @1.last_column = @4.last_column; 741 /* Leading ones count */ 742 $$ = gen_locnt_op(c, &@1, &$3); 743 } 744 | COUNTONES '(' rvalue ')' 745 { 746 @1.last_column = @4.last_column; 747 /* Ones count */ 748 $$ = gen_ctpop_op(c, &@1, &$3); 749 } 750 | EXTRACT '(' rvalue ',' rvalue ')' 751 { 752 @1.last_column = @6.last_column; 753 $$ = gen_extract_op(c, &@1, &$5, &$3, &$1); 754 } 755 | EXTRANGE '(' rvalue ',' rvalue ',' rvalue ')' 756 { 757 @1.last_column = @8.last_column; 758 yyassert(c, &@1, $5.type == IMMEDIATE && 759 $5.imm.type == VALUE && 760 $7.type == IMMEDIATE && 761 $7.imm.type == VALUE, 762 "Range extract needs immediate values!\n"); 763 $$ = gen_rextract_op(c, 764 &@1, 765 &$3, 766 $7.imm.value, 767 $5.imm.value - $7.imm.value + 1); 768 } 769 | CAST4_8U '(' rvalue ')' 770 { 771 @1.last_column = @4.last_column; 772 $$ = gen_rvalue_truncate(c, &@1, &$3); 773 $$.signedness = UNSIGNED; 774 $$ = rvalue_materialize(c, &@1, &$$); 775 $$ = gen_rvalue_extend(c, &@1, &$$); 776 } 777 | BREV '(' rvalue ')' 778 { 779 @1.last_column = @4.last_column; 780 $$ = gen_rvalue_brev(c, &@1, &$3); 781 } 782 | ROTL '(' rvalue ',' rvalue ')' 783 { 784 @1.last_column = @6.last_column; 785 $$ = gen_rotl(c, &@1, &$3, &$5); 786 } 787 | ADDSAT64 '(' rvalue ',' rvalue ',' rvalue ')' 788 { 789 @1.last_column = @8.last_column; 790 gen_addsat64(c, &@1, &$3, &$5, &$7); 791 } 792 | CARRY_FROM_ADD '(' rvalue ',' rvalue ',' rvalue ')' 793 { 794 @1.last_column = @8.last_column; 795 $$ = gen_carry_from_add(c, &@1, &$3, &$5, &$7); 796 } 797 | LSBNEW '(' rvalue ')' 798 { 799 @1.last_column = @4.last_column; 800 HexValue one = gen_imm_value(c, &@1, 1, 32, UNSIGNED); 801 $$ = gen_bin_op(c, &@1, ANDB_OP, &$3, &one); 802 } 803 ; 804 805 lvalue : FAIL 806 { 807 @1.last_column = @1.last_column; 808 yyassert(c, &@1, false, "Encountered a FAIL token as lvalue.\n"); 809 } 810 | REG 811 { 812 $$ = $1; 813 } 814 | var 815 { 816 $$ = $1; 817 } 818 ; 819 820 %% 821 822 int main(int argc, char **argv) 823 { 824 if (argc != 5) { 825 fprintf(stderr, 826 "Semantics: Hexagon ISA to tinycode generator compiler\n\n"); 827 fprintf(stderr, 828 "Usage: ./semantics IDEFS EMITTER_C EMITTER_H " 829 "ENABLED_INSTRUCTIONS_LIST\n"); 830 return 1; 831 } 832 833 enum { 834 ARG_INDEX_ARGV0 = 0, 835 ARG_INDEX_IDEFS, 836 ARG_INDEX_EMITTER_C, 837 ARG_INDEX_EMITTER_H, 838 ARG_INDEX_ENABLED_INSTRUCTIONS_LIST 839 }; 840 841 FILE *enabled_file = fopen(argv[ARG_INDEX_ENABLED_INSTRUCTIONS_LIST], "w"); 842 843 FILE *output_file = fopen(argv[ARG_INDEX_EMITTER_C], "w"); 844 fputs("#include \"qemu/osdep.h\"\n", output_file); 845 fputs("#include \"qemu/log.h\"\n", output_file); 846 fputs("#include \"cpu.h\"\n", output_file); 847 fputs("#include \"internal.h\"\n", output_file); 848 fputs("#include \"tcg/tcg-op.h\"\n", output_file); 849 fputs("#include \"insn.h\"\n", output_file); 850 fputs("#include \"opcodes.h\"\n", output_file); 851 fputs("#include \"translate.h\"\n", output_file); 852 fputs("#define QEMU_GENERATE\n", output_file); 853 fputs("#include \"genptr.h\"\n", output_file); 854 fputs("#include \"tcg/tcg.h\"\n", output_file); 855 fputs("#include \"macros.h\"\n", output_file); 856 fprintf(output_file, "#include \"%s\"\n", argv[ARG_INDEX_EMITTER_H]); 857 858 FILE *defines_file = fopen(argv[ARG_INDEX_EMITTER_H], "w"); 859 assert(defines_file != NULL); 860 fputs("#ifndef HEX_EMITTER_H\n", defines_file); 861 fputs("#define HEX_EMITTER_H\n", defines_file); 862 fputs("\n", defines_file); 863 fputs("#include \"insn.h\"\n\n", defines_file); 864 865 /* Parser input file */ 866 Context context = { 0 }; 867 context.defines_file = defines_file; 868 context.output_file = output_file; 869 context.enabled_file = enabled_file; 870 /* Initialize buffers */ 871 context.out_str = g_string_new(NULL); 872 context.signature_str = g_string_new(NULL); 873 context.header_str = g_string_new(NULL); 874 context.ternary = g_array_new(FALSE, TRUE, sizeof(Ternary)); 875 /* Read input file */ 876 FILE *input_file = fopen(argv[ARG_INDEX_IDEFS], "r"); 877 fseek(input_file, 0L, SEEK_END); 878 long input_size = ftell(input_file); 879 context.input_buffer = (char *) calloc(input_size + 1, sizeof(char)); 880 fseek(input_file, 0L, SEEK_SET); 881 size_t read_chars = fread(context.input_buffer, 882 sizeof(char), 883 input_size, 884 input_file); 885 if (read_chars != (size_t) input_size) { 886 fprintf(stderr, "Error: an error occurred while reading input file!\n"); 887 return -1; 888 } 889 yylex_init(&context.scanner); 890 YY_BUFFER_STATE buffer; 891 buffer = yy_scan_string(context.input_buffer, context.scanner); 892 /* Start the parsing procedure */ 893 yyparse(context.scanner, &context); 894 if (context.implemented_insn != context.total_insn) { 895 fprintf(stderr, 896 "Warning: %d/%d meta instructions have been implemented!\n", 897 context.implemented_insn, 898 context.total_insn); 899 } 900 fputs("#endif " START_COMMENT " HEX_EMITTER_h " END_COMMENT "\n", 901 defines_file); 902 /* Cleanup */ 903 yy_delete_buffer(buffer, context.scanner); 904 yylex_destroy(context.scanner); 905 free(context.input_buffer); 906 g_string_free(context.out_str, TRUE); 907 g_string_free(context.signature_str, TRUE); 908 g_string_free(context.header_str, TRUE); 909 g_array_free(context.ternary, TRUE); 910 fclose(output_file); 911 fclose(input_file); 912 fclose(defines_file); 913 fclose(enabled_file); 914 915 return 0; 916 } 917