1 /* 2 * Copyright(c) 2019-2022 rev.ng Labs Srl. All Rights Reserved. 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 #include <assert.h> 19 #include <inttypes.h> 20 #include <stdarg.h> 21 #include <stdbool.h> 22 #include <stdint.h> 23 #include <stdio.h> 24 #include <stdlib.h> 25 #include <string.h> 26 #include <unistd.h> 27 28 #include "idef-parser.h" 29 #include "parser-helpers.h" 30 #include "idef-parser.tab.h" 31 #include "idef-parser.yy.h" 32 33 void yyerror(YYLTYPE *locp, 34 yyscan_t scanner __attribute__((unused)), 35 Context *c, 36 const char *s) 37 { 38 const char *code_ptr = c->input_buffer; 39 40 fprintf(stderr, "WARNING (%s): '%s'\n", c->inst.name->str, s); 41 42 fprintf(stderr, "Problematic range: "); 43 for (int i = locp->first_column; i < locp->last_column; i++) { 44 if (code_ptr[i] != '\n') { 45 fprintf(stderr, "%c", code_ptr[i]); 46 } 47 } 48 fprintf(stderr, "\n"); 49 50 for (unsigned i = 0; 51 i < 80 && 52 code_ptr[locp->first_column - 10 + i] != '\0' && 53 code_ptr[locp->first_column - 10 + i] != '\n'; 54 i++) { 55 fprintf(stderr, "%c", code_ptr[locp->first_column - 10 + i]); 56 } 57 fprintf(stderr, "\n"); 58 for (unsigned i = 0; i < 9; i++) { 59 fprintf(stderr, " "); 60 } 61 fprintf(stderr, "^"); 62 for (int i = 0; i < (locp->last_column - locp->first_column) - 1; i++) { 63 fprintf(stderr, "~"); 64 } 65 fprintf(stderr, "\n"); 66 c->inst.error_count++; 67 } 68 69 bool is_direct_predicate(HexValue *value) 70 { 71 return value->pred.id >= '0' && value->pred.id <= '3'; 72 } 73 74 bool is_inside_ternary(Context *c) 75 { 76 return c->ternary->len > 0; 77 } 78 79 /* Print functions */ 80 void str_print(Context *c, YYLTYPE *locp, const char *string) 81 { 82 (void) locp; 83 EMIT(c, "%s", string); 84 } 85 86 void uint8_print(Context *c, YYLTYPE *locp, uint8_t *num) 87 { 88 (void) locp; 89 EMIT(c, "%u", *num); 90 } 91 92 void uint64_print(Context *c, YYLTYPE *locp, uint64_t *num) 93 { 94 (void) locp; 95 EMIT(c, "%" PRIu64, *num); 96 } 97 98 void int_print(Context *c, YYLTYPE *locp, int *num) 99 { 100 (void) locp; 101 EMIT(c, "%d", *num); 102 } 103 104 void uint_print(Context *c, YYLTYPE *locp, unsigned *num) 105 { 106 (void) locp; 107 EMIT(c, "%u", *num); 108 } 109 110 void tmp_print(Context *c, YYLTYPE *locp, HexTmp *tmp) 111 { 112 (void) locp; 113 EMIT(c, "tmp_%d", tmp->index); 114 } 115 116 void pred_print(Context *c, YYLTYPE *locp, HexPred *pred, bool is_dotnew) 117 { 118 (void) locp; 119 char suffix = is_dotnew ? 'N' : 'V'; 120 EMIT(c, "P%c%c", pred->id, suffix); 121 } 122 123 void reg_compose(Context *c, YYLTYPE *locp, HexReg *reg, char reg_id[5]) 124 { 125 memset(reg_id, 0, 5 * sizeof(char)); 126 switch (reg->type) { 127 case GENERAL_PURPOSE: 128 reg_id[0] = 'R'; 129 break; 130 case CONTROL: 131 reg_id[0] = 'C'; 132 break; 133 case MODIFIER: 134 reg_id[0] = 'M'; 135 break; 136 case DOTNEW: 137 reg_id[0] = 'N'; 138 reg_id[1] = reg->id; 139 reg_id[2] = 'N'; 140 return; 141 } 142 switch (reg->bit_width) { 143 case 32: 144 reg_id[1] = reg->id; 145 reg_id[2] = 'V'; 146 break; 147 case 64: 148 reg_id[1] = reg->id; 149 reg_id[2] = reg->id; 150 reg_id[3] = 'V'; 151 break; 152 default: 153 yyassert(c, locp, false, "Unhandled register bit width!\n"); 154 } 155 } 156 157 static void reg_arg_print(Context *c, YYLTYPE *locp, HexReg *reg) 158 { 159 char reg_id[5]; 160 reg_compose(c, locp, reg, reg_id); 161 EMIT(c, "%s", reg_id); 162 } 163 164 void reg_print(Context *c, YYLTYPE *locp, HexReg *reg) 165 { 166 (void) locp; 167 EMIT(c, "hex_gpr[%u]", reg->id); 168 } 169 170 void imm_print(Context *c, YYLTYPE *locp, HexImm *imm) 171 { 172 switch (imm->type) { 173 case I: 174 EMIT(c, "i"); 175 break; 176 case VARIABLE: 177 EMIT(c, "%ciV", imm->id); 178 break; 179 case VALUE: 180 EMIT(c, "((int64_t) %" PRIu64 "ULL)", (int64_t) imm->value); 181 break; 182 case QEMU_TMP: 183 EMIT(c, "qemu_tmp_%" PRIu64, imm->index); 184 break; 185 case IMM_PC: 186 EMIT(c, "ctx->base.pc_next"); 187 break; 188 case IMM_NPC: 189 EMIT(c, "ctx->npc"); 190 break; 191 case IMM_CONSTEXT: 192 EMIT(c, "insn->extension_valid"); 193 break; 194 default: 195 yyassert(c, locp, false, "Cannot print this expression!"); 196 } 197 } 198 199 void var_print(Context *c, YYLTYPE *locp, HexVar *var) 200 { 201 (void) locp; 202 EMIT(c, "%s", var->name->str); 203 } 204 205 void rvalue_print(Context *c, YYLTYPE *locp, void *pointer) 206 { 207 HexValue *rvalue = (HexValue *) pointer; 208 switch (rvalue->type) { 209 case REGISTER: 210 reg_print(c, locp, &rvalue->reg); 211 break; 212 case REGISTER_ARG: 213 reg_arg_print(c, locp, &rvalue->reg); 214 break; 215 case TEMP: 216 tmp_print(c, locp, &rvalue->tmp); 217 break; 218 case IMMEDIATE: 219 imm_print(c, locp, &rvalue->imm); 220 break; 221 case VARID: 222 var_print(c, locp, &rvalue->var); 223 break; 224 case PREDICATE: 225 pred_print(c, locp, &rvalue->pred, rvalue->is_dotnew); 226 break; 227 default: 228 yyassert(c, locp, false, "Cannot print this expression!"); 229 } 230 } 231 232 void out_assert(Context *c, YYLTYPE *locp, 233 void *dummy __attribute__((unused))) 234 { 235 yyassert(c, locp, false, "Unhandled print type!"); 236 } 237 238 /* Copy output code buffer */ 239 void commit(Context *c) 240 { 241 /* Emit instruction pseudocode */ 242 EMIT_SIG(c, "\n" START_COMMENT " "); 243 for (char *x = c->inst.code_begin; x < c->inst.code_end; x++) { 244 EMIT_SIG(c, "%c", *x); 245 } 246 EMIT_SIG(c, " " END_COMMENT "\n"); 247 248 /* Commit instruction code to output file */ 249 fwrite(c->signature_str->str, sizeof(char), c->signature_str->len, 250 c->output_file); 251 fwrite(c->header_str->str, sizeof(char), c->header_str->len, 252 c->output_file); 253 fwrite(c->out_str->str, sizeof(char), c->out_str->len, 254 c->output_file); 255 256 fwrite(c->signature_str->str, sizeof(char), c->signature_str->len, 257 c->defines_file); 258 fprintf(c->defines_file, ";\n"); 259 } 260 261 static void gen_c_int_type(Context *c, YYLTYPE *locp, unsigned bit_width, 262 HexSignedness signedness) 263 { 264 const char *signstr = (signedness == UNSIGNED) ? "u" : ""; 265 OUT(c, locp, signstr, "int", &bit_width, "_t"); 266 } 267 268 static HexValue gen_constant(Context *c, 269 YYLTYPE *locp, 270 const char *value, 271 unsigned bit_width, 272 HexSignedness signedness) 273 { 274 HexValue rvalue; 275 assert(bit_width == 32 || bit_width == 64); 276 memset(&rvalue, 0, sizeof(HexValue)); 277 rvalue.type = TEMP; 278 rvalue.bit_width = bit_width; 279 rvalue.signedness = signedness; 280 rvalue.is_dotnew = false; 281 rvalue.is_manual = true; 282 rvalue.tmp.index = c->inst.tmp_count; 283 OUT(c, locp, "TCGv_i", &bit_width, " tmp_", &c->inst.tmp_count, 284 " = tcg_constant_i", &bit_width, "(", value, ");\n"); 285 c->inst.tmp_count++; 286 return rvalue; 287 } 288 289 /* Temporary values creation */ 290 HexValue gen_tmp(Context *c, 291 YYLTYPE *locp, 292 unsigned bit_width, 293 HexSignedness signedness) 294 { 295 HexValue rvalue; 296 assert(bit_width == 32 || bit_width == 64); 297 memset(&rvalue, 0, sizeof(HexValue)); 298 rvalue.type = TEMP; 299 rvalue.bit_width = bit_width; 300 rvalue.signedness = signedness; 301 rvalue.is_dotnew = false; 302 rvalue.is_manual = false; 303 rvalue.tmp.index = c->inst.tmp_count; 304 OUT(c, locp, "TCGv_i", &bit_width, " tmp_", &c->inst.tmp_count, 305 " = tcg_temp_new_i", &bit_width, "();\n"); 306 c->inst.tmp_count++; 307 return rvalue; 308 } 309 310 HexValue gen_tmp_local(Context *c, 311 YYLTYPE *locp, 312 unsigned bit_width, 313 HexSignedness signedness) 314 { 315 HexValue rvalue; 316 assert(bit_width == 32 || bit_width == 64); 317 memset(&rvalue, 0, sizeof(HexValue)); 318 rvalue.type = TEMP; 319 rvalue.bit_width = bit_width; 320 rvalue.signedness = signedness; 321 rvalue.is_dotnew = false; 322 rvalue.is_manual = false; 323 rvalue.tmp.index = c->inst.tmp_count; 324 OUT(c, locp, "TCGv_i", &bit_width, " tmp_", &c->inst.tmp_count, 325 " = tcg_temp_local_new_i", &bit_width, "();\n"); 326 c->inst.tmp_count++; 327 return rvalue; 328 } 329 330 HexValue gen_tmp_value(Context *c, 331 YYLTYPE *locp, 332 const char *value, 333 unsigned bit_width, 334 HexSignedness signedness) 335 { 336 HexValue rvalue; 337 assert(bit_width == 32 || bit_width == 64); 338 memset(&rvalue, 0, sizeof(HexValue)); 339 rvalue.type = TEMP; 340 rvalue.bit_width = bit_width; 341 rvalue.signedness = signedness; 342 rvalue.is_dotnew = false; 343 rvalue.is_manual = false; 344 rvalue.tmp.index = c->inst.tmp_count; 345 OUT(c, locp, "TCGv_i", &bit_width, " tmp_", &c->inst.tmp_count, 346 " = tcg_const_i", &bit_width, "(", value, ");\n"); 347 c->inst.tmp_count++; 348 return rvalue; 349 } 350 351 static HexValue gen_tmp_value_from_imm(Context *c, 352 YYLTYPE *locp, 353 HexValue *value) 354 { 355 HexValue rvalue; 356 assert(value->type == IMMEDIATE); 357 memset(&rvalue, 0, sizeof(HexValue)); 358 rvalue.type = TEMP; 359 rvalue.bit_width = value->bit_width; 360 rvalue.signedness = value->signedness; 361 rvalue.is_dotnew = false; 362 rvalue.is_manual = false; 363 rvalue.tmp.index = c->inst.tmp_count; 364 /* 365 * Here we output the call to `tcg_const_i<width>` in 366 * order to create the temporary value. Note, that we 367 * add a cast 368 * 369 * `tcg_const_i<width>`((int<width>_t) ...)` 370 * 371 * This cast is required to avoid implicit integer 372 * conversion warnings since all immediates are 373 * output as `((int64_t) 123ULL)`, even if the 374 * integer is 32-bit. 375 */ 376 OUT(c, locp, "TCGv_i", &rvalue.bit_width, " tmp_", &c->inst.tmp_count); 377 OUT(c, locp, " = tcg_const_i", &rvalue.bit_width, 378 "((int", &rvalue.bit_width, "_t) (", value, "));\n"); 379 380 c->inst.tmp_count++; 381 return rvalue; 382 } 383 384 HexValue gen_imm_value(Context *c __attribute__((unused)), 385 YYLTYPE *locp, 386 int value, 387 unsigned bit_width, 388 HexSignedness signedness) 389 { 390 (void) locp; 391 HexValue rvalue; 392 assert(bit_width == 32 || bit_width == 64); 393 memset(&rvalue, 0, sizeof(HexValue)); 394 rvalue.type = IMMEDIATE; 395 rvalue.bit_width = bit_width; 396 rvalue.signedness = signedness; 397 rvalue.is_dotnew = false; 398 rvalue.is_manual = false; 399 rvalue.imm.type = VALUE; 400 rvalue.imm.value = value; 401 return rvalue; 402 } 403 404 HexValue gen_imm_qemu_tmp(Context *c, YYLTYPE *locp, unsigned bit_width, 405 HexSignedness signedness) 406 { 407 (void) locp; 408 HexValue rvalue; 409 assert(bit_width == 32 || bit_width == 64); 410 memset(&rvalue, 0, sizeof(HexValue)); 411 rvalue.type = IMMEDIATE; 412 rvalue.is_dotnew = false; 413 rvalue.is_manual = false; 414 rvalue.bit_width = bit_width; 415 rvalue.signedness = signedness; 416 rvalue.imm.type = QEMU_TMP; 417 rvalue.imm.index = c->inst.qemu_tmp_count++; 418 return rvalue; 419 } 420 421 void gen_rvalue_free(Context *c, YYLTYPE *locp, HexValue *rvalue) 422 { 423 if (rvalue->type == TEMP && !rvalue->is_manual) { 424 const char *bit_suffix = (rvalue->bit_width == 64) ? "i64" : "i32"; 425 OUT(c, locp, "tcg_temp_free_", bit_suffix, "(", rvalue, ");\n"); 426 } 427 } 428 429 static void gen_rvalue_free_manual(Context *c, YYLTYPE *locp, HexValue *rvalue) 430 { 431 rvalue->is_manual = false; 432 gen_rvalue_free(c, locp, rvalue); 433 } 434 435 HexValue rvalue_materialize(Context *c, YYLTYPE *locp, HexValue *rvalue) 436 { 437 if (rvalue->type == IMMEDIATE) { 438 HexValue res = gen_tmp_value_from_imm(c, locp, rvalue); 439 gen_rvalue_free(c, locp, rvalue); 440 return res; 441 } 442 return *rvalue; 443 } 444 445 HexValue gen_rvalue_extend(Context *c, YYLTYPE *locp, HexValue *rvalue) 446 { 447 assert_signedness(c, locp, rvalue->signedness); 448 if (rvalue->bit_width > 32) { 449 return *rvalue; 450 } 451 452 if (rvalue->type == IMMEDIATE) { 453 HexValue res = gen_imm_qemu_tmp(c, locp, 64, rvalue->signedness); 454 bool is_unsigned = (rvalue->signedness == UNSIGNED); 455 const char *sign_suffix = is_unsigned ? "u" : ""; 456 gen_c_int_type(c, locp, 64, rvalue->signedness); 457 OUT(c, locp, " ", &res, " = "); 458 OUT(c, locp, "(", sign_suffix, "int64_t) "); 459 OUT(c, locp, "(", sign_suffix, "int32_t) "); 460 OUT(c, locp, rvalue, ";\n"); 461 return res; 462 } else { 463 HexValue res = gen_tmp(c, locp, 64, rvalue->signedness); 464 bool is_unsigned = (rvalue->signedness == UNSIGNED); 465 const char *sign_suffix = is_unsigned ? "u" : ""; 466 OUT(c, locp, "tcg_gen_ext", sign_suffix, 467 "_i32_i64(", &res, ", ", rvalue, ");\n"); 468 gen_rvalue_free(c, locp, rvalue); 469 return res; 470 } 471 } 472 473 HexValue gen_rvalue_truncate(Context *c, YYLTYPE *locp, HexValue *rvalue) 474 { 475 if (rvalue->type == IMMEDIATE) { 476 HexValue res = *rvalue; 477 res.bit_width = 32; 478 return res; 479 } else { 480 if (rvalue->bit_width == 64) { 481 HexValue res = gen_tmp(c, locp, 32, rvalue->signedness); 482 OUT(c, locp, "tcg_gen_trunc_i64_tl(", &res, ", ", rvalue, ");\n"); 483 gen_rvalue_free(c, locp, rvalue); 484 return res; 485 } 486 } 487 return *rvalue; 488 } 489 490 /* 491 * Attempts to lookup the `Var` struct associated with the given `varid`. 492 * The `dst` argument is populated with the found name, bit_width, and 493 * signedness, given that `dst` is non-NULL. Returns true if the lookup 494 * succeeded and false otherwise. 495 */ 496 static bool try_find_variable(Context *c, YYLTYPE *locp, 497 HexValue *dst, 498 HexValue *varid) 499 { 500 yyassert(c, locp, varid, "varid to lookup is NULL"); 501 yyassert(c, locp, varid->type == VARID, 502 "Can only lookup variables by varid"); 503 for (unsigned i = 0; i < c->inst.allocated->len; i++) { 504 Var *curr = &g_array_index(c->inst.allocated, Var, i); 505 if (g_string_equal(varid->var.name, curr->name)) { 506 if (dst) { 507 dst->var.name = curr->name; 508 dst->bit_width = curr->bit_width; 509 dst->signedness = curr->signedness; 510 } 511 return true; 512 } 513 } 514 return false; 515 } 516 517 /* Calls `try_find_variable` and asserts succcess. */ 518 static void find_variable(Context *c, YYLTYPE *locp, 519 HexValue *dst, 520 HexValue *varid) 521 { 522 bool found = try_find_variable(c, locp, dst, varid); 523 yyassert(c, locp, found, "Use of undeclared variable!\n"); 524 } 525 526 /* Handle signedness, if both unsigned -> result is unsigned, else signed */ 527 static inline HexSignedness bin_op_signedness(Context *c, YYLTYPE *locp, 528 HexSignedness sign1, 529 HexSignedness sign2) 530 { 531 assert_signedness(c, locp, sign1); 532 assert_signedness(c, locp, sign2); 533 return (sign1 == UNSIGNED && sign2 == UNSIGNED) ? UNSIGNED : SIGNED; 534 } 535 536 void gen_varid_allocate(Context *c, 537 YYLTYPE *locp, 538 HexValue *varid, 539 unsigned bit_width, 540 HexSignedness signedness) 541 { 542 const char *bit_suffix = (bit_width == 64) ? "i64" : "i32"; 543 bool found = try_find_variable(c, locp, NULL, varid); 544 Var new_var; 545 546 memset(&new_var, 0, sizeof(Var)); 547 548 yyassert(c, locp, !found, "Redeclaration of variables not allowed!"); 549 assert_signedness(c, locp, signedness); 550 551 /* `varid` only carries name information */ 552 new_var.name = varid->var.name; 553 new_var.bit_width = bit_width; 554 new_var.signedness = signedness; 555 556 EMIT_HEAD(c, "TCGv_%s %s", bit_suffix, varid->var.name->str); 557 EMIT_HEAD(c, " = tcg_temp_local_new_%s();\n", bit_suffix); 558 g_array_append_val(c->inst.allocated, new_var); 559 } 560 561 enum OpTypes { 562 IMM_IMM = 0, 563 IMM_REG = 1, 564 REG_IMM = 2, 565 REG_REG = 3, 566 }; 567 568 HexValue gen_bin_cmp(Context *c, 569 YYLTYPE *locp, 570 TCGCond type, 571 HexValue *op1, 572 HexValue *op2) 573 { 574 HexValue op1_m = *op1; 575 HexValue op2_m = *op2; 576 enum OpTypes op_types = (op1_m.type != IMMEDIATE) << 1 577 | (op2_m.type != IMMEDIATE); 578 579 bool op_is64bit = op1_m.bit_width == 64 || op2_m.bit_width == 64; 580 const char *bit_suffix = op_is64bit ? "i64" : "i32"; 581 unsigned bit_width = (op_is64bit) ? 64 : 32; 582 HexValue res = gen_tmp(c, locp, bit_width, UNSIGNED); 583 584 /* Extend to 64-bits, if required */ 585 if (op_is64bit) { 586 op1_m = gen_rvalue_extend(c, locp, &op1_m); 587 op2_m = gen_rvalue_extend(c, locp, &op2_m); 588 } 589 590 switch (op_types) { 591 case IMM_IMM: 592 case IMM_REG: 593 yyassert(c, locp, false, "Binary comparisons between IMM op IMM and" 594 "IMM op REG not handled!"); 595 break; 596 case REG_IMM: 597 OUT(c, locp, "tcg_gen_setcondi_", bit_suffix, "("); 598 OUT(c, locp, cond_to_str(type), ", ", &res, ", ", &op1_m, ", ", &op2_m, 599 ");\n"); 600 break; 601 case REG_REG: 602 OUT(c, locp, "tcg_gen_setcond_", bit_suffix, "("); 603 OUT(c, locp, cond_to_str(type), ", ", &res, ", ", &op1_m, ", ", &op2_m, 604 ");\n"); 605 break; 606 default: 607 fprintf(stderr, "Error in evalutating immediateness!"); 608 abort(); 609 } 610 611 /* Free operands */ 612 gen_rvalue_free(c, locp, &op1_m); 613 gen_rvalue_free(c, locp, &op2_m); 614 615 return res; 616 } 617 618 static void gen_simple_op(Context *c, YYLTYPE *locp, unsigned bit_width, 619 const char *bit_suffix, HexValue *res, 620 enum OpTypes op_types, 621 HexValue *op1, 622 HexValue *op2, 623 const char *imm_imm, 624 const char *imm_reg, 625 const char *reg_imm, 626 const char *reg_reg) 627 { 628 switch (op_types) { 629 case IMM_IMM: { 630 HexSignedness signedness = bin_op_signedness(c, locp, 631 op1->signedness, 632 op2->signedness); 633 gen_c_int_type(c, locp, bit_width, signedness); 634 OUT(c, locp, " ", res, 635 " = ", op1, imm_imm, op2, ";\n"); 636 } break; 637 case IMM_REG: 638 OUT(c, locp, imm_reg, bit_suffix, 639 "(", res, ", ", op2, ", ", op1, ");\n"); 640 break; 641 case REG_IMM: 642 OUT(c, locp, reg_imm, bit_suffix, 643 "(", res, ", ", op1, ", ", op2, ");\n"); 644 break; 645 case REG_REG: 646 OUT(c, locp, reg_reg, bit_suffix, 647 "(", res, ", ", op1, ", ", op2, ");\n"); 648 break; 649 } 650 gen_rvalue_free(c, locp, op1); 651 gen_rvalue_free(c, locp, op2); 652 } 653 654 static void gen_sub_op(Context *c, YYLTYPE *locp, unsigned bit_width, 655 const char *bit_suffix, HexValue *res, 656 enum OpTypes op_types, HexValue *op1, 657 HexValue *op2) 658 { 659 switch (op_types) { 660 case IMM_IMM: { 661 HexSignedness signedness = bin_op_signedness(c, locp, 662 op1->signedness, 663 op2->signedness); 664 gen_c_int_type(c, locp, bit_width, signedness); 665 OUT(c, locp, " ", res, 666 " = ", op1, " - ", op2, ";\n"); 667 } break; 668 case IMM_REG: { 669 OUT(c, locp, "tcg_gen_subfi_", bit_suffix, 670 "(", res, ", ", op1, ", ", op2, ");\n"); 671 } break; 672 case REG_IMM: { 673 OUT(c, locp, "tcg_gen_subi_", bit_suffix, 674 "(", res, ", ", op1, ", ", op2, ");\n"); 675 } break; 676 case REG_REG: { 677 OUT(c, locp, "tcg_gen_sub_", bit_suffix, 678 "(", res, ", ", op1, ", ", op2, ");\n"); 679 } break; 680 } 681 gen_rvalue_free(c, locp, op1); 682 gen_rvalue_free(c, locp, op2); 683 } 684 685 static void gen_asl_op(Context *c, YYLTYPE *locp, unsigned bit_width, 686 bool op_is64bit, const char *bit_suffix, 687 HexValue *res, enum OpTypes op_types, 688 HexValue *op1, HexValue *op2) 689 { 690 HexValue op1_m = *op1; 691 HexValue op2_m = *op2; 692 switch (op_types) { 693 case IMM_IMM: { 694 HexSignedness signedness = bin_op_signedness(c, locp, 695 op1->signedness, 696 op2->signedness); 697 gen_c_int_type(c, locp, bit_width, signedness); 698 OUT(c, locp, " ", res, 699 " = ", op1, " << ", op2, ";\n"); 700 } break; 701 case REG_IMM: { 702 OUT(c, locp, "if (", op2, " >= ", &bit_width, ") {\n"); 703 OUT(c, locp, "tcg_gen_movi_", bit_suffix, "(", res, ", 0);\n"); 704 OUT(c, locp, "} else {\n"); 705 OUT(c, locp, "tcg_gen_shli_", bit_suffix, 706 "(", res, ", ", op1, ", ", op2, ");\n"); 707 OUT(c, locp, "}\n"); 708 } break; 709 case IMM_REG: 710 op1_m.bit_width = bit_width; 711 op1_m = rvalue_materialize(c, locp, &op1_m); 712 /* fallthrough */ 713 case REG_REG: { 714 OUT(c, locp, "tcg_gen_shl_", bit_suffix, 715 "(", res, ", ", &op1_m, ", ", op2, ");\n"); 716 } break; 717 } 718 if (op_types == IMM_REG || op_types == REG_REG) { 719 /* 720 * Handle left shift by 64/32 which hexagon-sim expects to clear out 721 * register 722 */ 723 HexValue zero = gen_constant(c, locp, "0", bit_width, UNSIGNED); 724 HexValue edge = gen_imm_value(c, locp, bit_width, bit_width, UNSIGNED); 725 edge = rvalue_materialize(c, locp, &edge); 726 if (op_is64bit) { 727 op2_m = gen_rvalue_extend(c, locp, &op2_m); 728 } 729 op1_m = rvalue_materialize(c, locp, &op1_m); 730 op2_m = rvalue_materialize(c, locp, &op2_m); 731 OUT(c, locp, "tcg_gen_movcond_i", &bit_width); 732 OUT(c, locp, "(TCG_COND_GEU, ", res, ", ", &op2_m, ", ", &edge); 733 OUT(c, locp, ", ", &zero, ", ", res, ");\n"); 734 gen_rvalue_free(c, locp, &edge); 735 } 736 gen_rvalue_free(c, locp, &op1_m); 737 gen_rvalue_free(c, locp, &op2_m); 738 } 739 740 static void gen_asr_op(Context *c, YYLTYPE *locp, unsigned bit_width, 741 bool op_is64bit, const char *bit_suffix, 742 HexValue *res, enum OpTypes op_types, 743 HexValue *op1, HexValue *op2) 744 { 745 HexValue op1_m = *op1; 746 HexValue op2_m = *op2; 747 switch (op_types) { 748 case IMM_IMM: 749 case IMM_REG: 750 yyassert(c, locp, false, "ASR between IMM op IMM, and IMM op REG" 751 " not handled!"); 752 break; 753 case REG_IMM: { 754 HexSignedness signedness = bin_op_signedness(c, locp, 755 op1->signedness, 756 op2->signedness); 757 OUT(c, locp, "{\n"); 758 gen_c_int_type(c, locp, bit_width, signedness); 759 OUT(c, locp, " shift = ", op2, ";\n"); 760 OUT(c, locp, "if (", op2, " >= ", &bit_width, ") {\n"); 761 OUT(c, locp, " shift = ", &bit_width, " - 1;\n"); 762 OUT(c, locp, "}\n"); 763 OUT(c, locp, "tcg_gen_sari_", bit_suffix, 764 "(", res, ", ", op1, ", shift);\n}\n"); 765 } break; 766 case REG_REG: 767 OUT(c, locp, "tcg_gen_sar_", bit_suffix, 768 "(", res, ", ", &op1_m, ", ", op2, ");\n"); 769 break; 770 } 771 if (op_types == REG_REG) { 772 /* Handle right shift by values >= bit_width */ 773 const char *offset = op_is64bit ? "63" : "31"; 774 HexValue tmp = gen_tmp(c, locp, bit_width, SIGNED); 775 HexValue zero = gen_constant(c, locp, "0", bit_width, SIGNED); 776 HexValue edge = gen_imm_value(c, locp, bit_width, bit_width, UNSIGNED); 777 778 edge = rvalue_materialize(c, locp, &edge); 779 if (op_is64bit) { 780 op2_m = gen_rvalue_extend(c, locp, &op2_m); 781 } 782 op1_m = rvalue_materialize(c, locp, &op1_m); 783 op2_m = rvalue_materialize(c, locp, &op2_m); 784 785 OUT(c, locp, "tcg_gen_extract_", bit_suffix, "(", 786 &tmp, ", ", &op1_m, ", ", offset, ", 1);\n"); 787 OUT(c, locp, "tcg_gen_sub_", bit_suffix, "(", 788 &tmp, ", ", &zero, ", ", &tmp, ");\n"); 789 OUT(c, locp, "tcg_gen_movcond_i", &bit_width); 790 OUT(c, locp, "(TCG_COND_GEU, ", res, ", ", &op2_m, ", ", &edge); 791 OUT(c, locp, ", ", &tmp, ", ", res, ");\n"); 792 gen_rvalue_free(c, locp, &edge); 793 gen_rvalue_free(c, locp, &tmp); 794 } 795 gen_rvalue_free(c, locp, &op1_m); 796 gen_rvalue_free(c, locp, &op2_m); 797 } 798 799 static void gen_lsr_op(Context *c, YYLTYPE *locp, unsigned bit_width, 800 bool op_is64bit, const char *bit_suffix, 801 HexValue *res, enum OpTypes op_types, 802 HexValue *op1, HexValue *op2) 803 { 804 HexValue op1_m = *op1; 805 HexValue op2_m = *op2; 806 switch (op_types) { 807 case IMM_IMM: 808 case IMM_REG: 809 yyassert(c, locp, false, "LSR between IMM op IMM, and IMM op REG" 810 " not handled!"); 811 break; 812 case REG_IMM: 813 OUT(c, locp, "if (", op2, " >= ", &bit_width, ") {\n"); 814 OUT(c, locp, "tcg_gen_movi_", bit_suffix, "(", res, ", 0);\n"); 815 OUT(c, locp, "} else {\n"); 816 OUT(c, locp, "tcg_gen_shri_", bit_suffix, 817 "(", res, ", ", op1, ", ", op2, ");\n"); 818 OUT(c, locp, "}\n"); 819 break; 820 case REG_REG: 821 OUT(c, locp, "tcg_gen_shr_", bit_suffix, 822 "(", res, ", ", &op1_m, ", ", op2, ");\n"); 823 break; 824 } 825 if (op_types == REG_REG) { 826 /* Handle right shift by values >= bit_width */ 827 HexValue zero = gen_constant(c, locp, "0", bit_width, UNSIGNED); 828 HexValue edge = gen_imm_value(c, locp, bit_width, bit_width, UNSIGNED); 829 edge = rvalue_materialize(c, locp, &edge); 830 if (op_is64bit) { 831 op2_m = gen_rvalue_extend(c, locp, &op2_m); 832 } 833 op1_m = rvalue_materialize(c, locp, &op1_m); 834 op2_m = rvalue_materialize(c, locp, &op2_m); 835 OUT(c, locp, "tcg_gen_movcond_i", &bit_width); 836 OUT(c, locp, "(TCG_COND_GEU, ", res, ", ", &op2_m, ", ", &edge); 837 OUT(c, locp, ", ", &zero, ", ", res, ");\n"); 838 gen_rvalue_free(c, locp, &edge); 839 } 840 gen_rvalue_free(c, locp, &op1_m); 841 gen_rvalue_free(c, locp, &op2_m); 842 } 843 844 /* 845 * Note: This implementation of logical `and` does not mirror that in C. 846 * We do not short-circuit logical expressions! 847 */ 848 static void gen_andl_op(Context *c, YYLTYPE *locp, unsigned bit_width, 849 const char *bit_suffix, HexValue *res, 850 enum OpTypes op_types, HexValue *op1, 851 HexValue *op2) 852 { 853 (void) bit_width; 854 HexValue tmp1, tmp2; 855 HexValue zero = gen_constant(c, locp, "0", 32, UNSIGNED); 856 memset(&tmp1, 0, sizeof(HexValue)); 857 memset(&tmp2, 0, sizeof(HexValue)); 858 switch (op_types) { 859 case IMM_IMM: 860 case IMM_REG: 861 case REG_IMM: 862 yyassert(c, locp, false, "ANDL between IMM op IMM, IMM op REG, and" 863 " REG op IMM, not handled!"); 864 break; 865 case REG_REG: 866 tmp1 = gen_bin_cmp(c, locp, TCG_COND_NE, op1, &zero); 867 tmp2 = gen_bin_cmp(c, locp, TCG_COND_NE, op2, &zero); 868 OUT(c, locp, "tcg_gen_and_", bit_suffix, 869 "(", res, ", ", &tmp1, ", ", &tmp2, ");\n"); 870 gen_rvalue_free_manual(c, locp, &zero); 871 gen_rvalue_free(c, locp, &tmp1); 872 gen_rvalue_free(c, locp, &tmp2); 873 break; 874 } 875 } 876 877 static void gen_minmax_op(Context *c, YYLTYPE *locp, unsigned bit_width, 878 HexValue *res, enum OpTypes op_types, 879 HexValue *op1, HexValue *op2, bool minmax) 880 { 881 const char *mm; 882 HexValue op1_m = *op1; 883 HexValue op2_m = *op2; 884 bool is_unsigned; 885 886 assert_signedness(c, locp, res->signedness); 887 is_unsigned = res->signedness == UNSIGNED; 888 889 if (minmax) { 890 /* Max */ 891 mm = is_unsigned ? "tcg_gen_umax" : "tcg_gen_smax"; 892 } else { 893 /* Min */ 894 mm = is_unsigned ? "tcg_gen_umin" : "tcg_gen_smin"; 895 } 896 switch (op_types) { 897 case IMM_IMM: 898 yyassert(c, locp, false, "MINMAX between IMM op IMM, not handled!"); 899 break; 900 case IMM_REG: 901 op1_m.bit_width = bit_width; 902 op1_m = rvalue_materialize(c, locp, &op1_m); 903 OUT(c, locp, mm, "_i", &bit_width, "("); 904 OUT(c, locp, res, ", ", &op1_m, ", ", op2, ");\n"); 905 break; 906 case REG_IMM: 907 op2_m.bit_width = bit_width; 908 op2_m = rvalue_materialize(c, locp, &op2_m); 909 /* Fallthrough */ 910 case REG_REG: 911 OUT(c, locp, mm, "_i", &bit_width, "("); 912 OUT(c, locp, res, ", ", op1, ", ", &op2_m, ");\n"); 913 break; 914 } 915 gen_rvalue_free(c, locp, &op1_m); 916 gen_rvalue_free(c, locp, &op2_m); 917 } 918 919 /* Code generation functions */ 920 HexValue gen_bin_op(Context *c, 921 YYLTYPE *locp, 922 OpType type, 923 HexValue *op1, 924 HexValue *op2) 925 { 926 /* Replicate operands to avoid side effects */ 927 HexValue op1_m = *op1; 928 HexValue op2_m = *op2; 929 enum OpTypes op_types; 930 bool op_is64bit; 931 HexSignedness signedness; 932 unsigned bit_width; 933 const char *bit_suffix; 934 HexValue res; 935 936 memset(&res, 0, sizeof(HexValue)); 937 938 /* 939 * If the operands are VARID's we need to look up the 940 * type information. 941 */ 942 if (op1_m.type == VARID) { 943 find_variable(c, locp, &op1_m, &op1_m); 944 } 945 if (op2_m.type == VARID) { 946 find_variable(c, locp, &op2_m, &op2_m); 947 } 948 949 op_types = (op1_m.type != IMMEDIATE) << 1 950 | (op2_m.type != IMMEDIATE); 951 op_is64bit = op1_m.bit_width == 64 || op2_m.bit_width == 64; 952 /* Shift greater than 32 are 64 bits wide */ 953 954 if (type == ASL_OP && op2_m.type == IMMEDIATE && 955 op2_m.imm.type == VALUE && op2_m.imm.value >= 32) { 956 op_is64bit = true; 957 } 958 959 bit_width = (op_is64bit) ? 64 : 32; 960 bit_suffix = op_is64bit ? "i64" : "i32"; 961 962 /* Extend to 64-bits, if required */ 963 if (op_is64bit) { 964 op1_m = gen_rvalue_extend(c, locp, &op1_m); 965 op2_m = gen_rvalue_extend(c, locp, &op2_m); 966 } 967 968 signedness = bin_op_signedness(c, locp, op1_m.signedness, op2_m.signedness); 969 if (op_types != IMM_IMM) { 970 res = gen_tmp(c, locp, bit_width, signedness); 971 } else { 972 res = gen_imm_qemu_tmp(c, locp, bit_width, signedness); 973 } 974 975 switch (type) { 976 case ADD_OP: 977 gen_simple_op(c, locp, bit_width, bit_suffix, &res, 978 op_types, &op1_m, &op2_m, 979 " + ", 980 "tcg_gen_addi_", 981 "tcg_gen_addi_", 982 "tcg_gen_add_"); 983 break; 984 case SUB_OP: 985 gen_sub_op(c, locp, bit_width, bit_suffix, &res, op_types, 986 &op1_m, &op2_m); 987 break; 988 case MUL_OP: 989 gen_simple_op(c, locp, bit_width, bit_suffix, &res, 990 op_types, &op1_m, &op2_m, 991 " * ", 992 "tcg_gen_muli_", 993 "tcg_gen_muli_", 994 "tcg_gen_mul_"); 995 break; 996 case ASL_OP: 997 gen_asl_op(c, locp, bit_width, op_is64bit, bit_suffix, &res, op_types, 998 &op1_m, &op2_m); 999 break; 1000 case ASR_OP: 1001 gen_asr_op(c, locp, bit_width, op_is64bit, bit_suffix, &res, op_types, 1002 &op1_m, &op2_m); 1003 break; 1004 case LSR_OP: 1005 gen_lsr_op(c, locp, bit_width, op_is64bit, bit_suffix, &res, op_types, 1006 &op1_m, &op2_m); 1007 break; 1008 case ANDB_OP: 1009 gen_simple_op(c, locp, bit_width, bit_suffix, &res, 1010 op_types, &op1_m, &op2_m, 1011 " & ", 1012 "tcg_gen_andi_", 1013 "tcg_gen_andi_", 1014 "tcg_gen_and_"); 1015 break; 1016 case ORB_OP: 1017 gen_simple_op(c, locp, bit_width, bit_suffix, &res, 1018 op_types, &op1_m, &op2_m, 1019 " | ", 1020 "tcg_gen_ori_", 1021 "tcg_gen_ori_", 1022 "tcg_gen_or_"); 1023 break; 1024 case XORB_OP: 1025 gen_simple_op(c, locp, bit_width, bit_suffix, &res, 1026 op_types, &op1_m, &op2_m, 1027 " ^ ", 1028 "tcg_gen_xori_", 1029 "tcg_gen_xori_", 1030 "tcg_gen_xor_"); 1031 break; 1032 case ANDL_OP: 1033 gen_andl_op(c, locp, bit_width, bit_suffix, &res, op_types, &op1_m, 1034 &op2_m); 1035 break; 1036 case MINI_OP: 1037 gen_minmax_op(c, locp, bit_width, &res, op_types, &op1_m, &op2_m, 1038 false); 1039 break; 1040 case MAXI_OP: 1041 gen_minmax_op(c, locp, bit_width, &res, op_types, &op1_m, &op2_m, true); 1042 break; 1043 } 1044 return res; 1045 } 1046 1047 HexValue gen_cast_op(Context *c, 1048 YYLTYPE *locp, 1049 HexValue *src, 1050 unsigned target_width, 1051 HexSignedness signedness) 1052 { 1053 assert_signedness(c, locp, src->signedness); 1054 if (src->bit_width == target_width) { 1055 return *src; 1056 } else if (src->type == IMMEDIATE) { 1057 HexValue res = *src; 1058 res.bit_width = target_width; 1059 res.signedness = signedness; 1060 return res; 1061 } else { 1062 HexValue res = gen_tmp(c, locp, target_width, signedness); 1063 /* Truncate */ 1064 if (src->bit_width > target_width) { 1065 OUT(c, locp, "tcg_gen_trunc_i64_tl(", &res, ", ", src, ");\n"); 1066 } else { 1067 assert_signedness(c, locp, src->signedness); 1068 if (src->signedness == UNSIGNED) { 1069 /* Extend unsigned */ 1070 OUT(c, locp, "tcg_gen_extu_i32_i64(", 1071 &res, ", ", src, ");\n"); 1072 } else { 1073 /* Extend signed */ 1074 OUT(c, locp, "tcg_gen_ext_i32_i64(", 1075 &res, ", ", src, ");\n"); 1076 } 1077 } 1078 gen_rvalue_free(c, locp, src); 1079 return res; 1080 } 1081 } 1082 1083 1084 /* 1085 * Implements an extension when the `src_width` is an immediate. 1086 * If the `value` to extend is also an immediate we use `extract/sextract` 1087 * from QEMU `bitops.h`. If `value` is a TCGv then we rely on 1088 * `tcg_gen_extract/tcg_gen_sextract`. 1089 */ 1090 static HexValue gen_extend_imm_width_op(Context *c, 1091 YYLTYPE *locp, 1092 HexValue *src_width, 1093 unsigned dst_width, 1094 HexValue *value, 1095 HexSignedness signedness) 1096 { 1097 /* 1098 * If the source width is not an immediate value, we need to guard 1099 * our extend op with if statements to handle the case where 1100 * `src_width_m` is 0. 1101 */ 1102 const char *sign_prefix; 1103 bool need_guarding; 1104 1105 assert_signedness(c, locp, signedness); 1106 assert(dst_width == 64 || dst_width == 32); 1107 assert(src_width->type == IMMEDIATE); 1108 1109 sign_prefix = (signedness == UNSIGNED) ? "" : "s"; 1110 need_guarding = (src_width->imm.type != VALUE); 1111 1112 if (src_width->imm.type == VALUE && 1113 src_width->imm.value == 0) { 1114 /* 1115 * We can bail out early if the source width is known to be zero 1116 * at translation time. 1117 */ 1118 return gen_imm_value(c, locp, 0, dst_width, signedness); 1119 } 1120 1121 if (value->type == IMMEDIATE) { 1122 /* 1123 * If both the value and source width are immediates, 1124 * we can perform the extension at translation time 1125 * using QEMUs bitops. 1126 */ 1127 HexValue res = gen_imm_qemu_tmp(c, locp, dst_width, signedness); 1128 gen_c_int_type(c, locp, dst_width, signedness); 1129 OUT(c, locp, " ", &res, " = 0;\n"); 1130 if (need_guarding) { 1131 OUT(c, locp, "if (", src_width, " != 0) {\n"); 1132 } 1133 OUT(c, locp, &res, " = ", sign_prefix, "extract", &dst_width); 1134 OUT(c, locp, "(", value, ", 0, ", src_width, ");\n"); 1135 if (need_guarding) { 1136 OUT(c, locp, "}\n"); 1137 } 1138 1139 gen_rvalue_free(c, locp, value); 1140 return res; 1141 } else { 1142 /* 1143 * If the source width is an immediate and the value to 1144 * extend is a TCGv, then use tcg_gen_extract/tcg_gen_sextract 1145 */ 1146 HexValue res = gen_tmp(c, locp, dst_width, signedness); 1147 1148 /* 1149 * If the width is an immediate value we know it is non-zero 1150 * at this point, otherwise we need an if-statement 1151 */ 1152 if (need_guarding) { 1153 OUT(c, locp, "if (", src_width, " != 0) {\n"); 1154 } 1155 OUT(c, locp, "tcg_gen_", sign_prefix, "extract_i", &dst_width); 1156 OUT(c, locp, "(", &res, ", ", value, ", 0, ", src_width, 1157 ");\n"); 1158 if (need_guarding) { 1159 OUT(c, locp, "} else {\n"); 1160 OUT(c, locp, "tcg_gen_movi_i", &dst_width, "(", &res, 1161 ", 0);\n"); 1162 OUT(c, locp, "}\n"); 1163 } 1164 1165 gen_rvalue_free(c, locp, value); 1166 return res; 1167 } 1168 } 1169 1170 /* 1171 * Implements an extension when the `src_width` is given by 1172 * a TCGv. Here we need to reimplement the behaviour of 1173 * `tcg_gen_extract` and the like using shifts and masks. 1174 */ 1175 static HexValue gen_extend_tcg_width_op(Context *c, 1176 YYLTYPE *locp, 1177 HexValue *src_width, 1178 unsigned dst_width, 1179 HexValue *value, 1180 HexSignedness signedness) 1181 { 1182 HexValue src_width_m = rvalue_materialize(c, locp, src_width); 1183 HexValue zero = gen_constant(c, locp, "0", dst_width, UNSIGNED); 1184 HexValue shift = gen_tmp(c, locp, dst_width, UNSIGNED); 1185 HexValue res; 1186 1187 assert_signedness(c, locp, signedness); 1188 assert(dst_width == 64 || dst_width == 32); 1189 assert(src_width->type != IMMEDIATE); 1190 1191 res = gen_tmp(c, locp, dst_width, signedness); 1192 1193 OUT(c, locp, "tcg_gen_subfi_i", &dst_width); 1194 OUT(c, locp, "(", &shift, ", ", &dst_width, ", ", &src_width_m, ");\n"); 1195 if (signedness == UNSIGNED) { 1196 const char *mask_str = (dst_width == 32) 1197 ? "0xffffffff" 1198 : "0xffffffffffffffff"; 1199 HexValue mask = gen_tmp_value(c, locp, mask_str, 1200 dst_width, UNSIGNED); 1201 OUT(c, locp, "tcg_gen_shr_i", &dst_width, "(", 1202 &mask, ", ", &mask, ", ", &shift, ");\n"); 1203 OUT(c, locp, "tcg_gen_and_i", &dst_width, "(", 1204 &res, ", ", value, ", ", &mask, ");\n"); 1205 gen_rvalue_free(c, locp, &mask); 1206 } else { 1207 OUT(c, locp, "tcg_gen_shl_i", &dst_width, "(", 1208 &res, ", ", value, ", ", &shift, ");\n"); 1209 OUT(c, locp, "tcg_gen_sar_i", &dst_width, "(", 1210 &res, ", ", &res, ", ", &shift, ");\n"); 1211 } 1212 OUT(c, locp, "tcg_gen_movcond_i", &dst_width, "(TCG_COND_EQ, ", &res, 1213 ", "); 1214 OUT(c, locp, &src_width_m, ", ", &zero, ", ", &zero, ", ", &res, 1215 ");\n"); 1216 1217 gen_rvalue_free(c, locp, &src_width_m); 1218 gen_rvalue_free(c, locp, value); 1219 gen_rvalue_free(c, locp, &shift); 1220 1221 return res; 1222 } 1223 1224 HexValue gen_extend_op(Context *c, 1225 YYLTYPE *locp, 1226 HexValue *src_width, 1227 unsigned dst_width, 1228 HexValue *value, 1229 HexSignedness signedness) 1230 { 1231 unsigned bit_width = (dst_width = 64) ? 64 : 32; 1232 HexValue value_m = *value; 1233 HexValue src_width_m = *src_width; 1234 1235 assert_signedness(c, locp, signedness); 1236 yyassert(c, locp, value_m.bit_width <= bit_width && 1237 src_width_m.bit_width <= bit_width, 1238 "Extending to a size smaller than the current size" 1239 " makes no sense"); 1240 1241 if (value_m.bit_width < bit_width) { 1242 value_m = gen_rvalue_extend(c, locp, &value_m); 1243 } 1244 1245 if (src_width_m.bit_width < bit_width) { 1246 src_width_m = gen_rvalue_extend(c, locp, &src_width_m); 1247 } 1248 1249 if (src_width_m.type == IMMEDIATE) { 1250 return gen_extend_imm_width_op(c, locp, &src_width_m, bit_width, 1251 &value_m, signedness); 1252 } else { 1253 return gen_extend_tcg_width_op(c, locp, &src_width_m, bit_width, 1254 &value_m, signedness); 1255 } 1256 } 1257 1258 /* 1259 * Implements `rdeposit` for the special case where `width` 1260 * is of TCGv type. In this case we need to reimplement the behaviour 1261 * of `tcg_gen_deposit*` using binary operations and masks/shifts. 1262 * 1263 * Note: this is the only type of `rdeposit` that occurs, meaning the 1264 * `width` is _NEVER_ of IMMEDIATE type. 1265 */ 1266 void gen_rdeposit_op(Context *c, 1267 YYLTYPE *locp, 1268 HexValue *dst, 1269 HexValue *value, 1270 HexValue *begin, 1271 HexValue *width) 1272 { 1273 /* 1274 * Otherwise if the width is not known, we fallback on reimplementing 1275 * desposit in TCG. 1276 */ 1277 HexValue begin_m = *begin; 1278 HexValue value_m = *value; 1279 HexValue width_m = *width; 1280 const char *mask_str = (dst->bit_width == 32) 1281 ? "0xffffffffUL" 1282 : "0xffffffffffffffffUL"; 1283 HexValue mask = gen_constant(c, locp, mask_str, dst->bit_width, 1284 UNSIGNED); 1285 const char *dst_width_str = (dst->bit_width == 32) ? "32" : "64"; 1286 HexValue k64 = gen_constant(c, locp, dst_width_str, dst->bit_width, 1287 UNSIGNED); 1288 HexValue res; 1289 HexValue zero; 1290 1291 assert(dst->bit_width >= value->bit_width); 1292 assert(begin->type == IMMEDIATE && begin->imm.type == VALUE); 1293 assert(dst->type == REGISTER_ARG); 1294 1295 yyassert(c, locp, width->type != IMMEDIATE, 1296 "Immediate index to rdeposit not handled!"); 1297 1298 yyassert(c, locp, value_m.bit_width == dst->bit_width && 1299 begin_m.bit_width == dst->bit_width && 1300 width_m.bit_width == dst->bit_width, 1301 "Extension/truncation should be taken care of" 1302 " before rdeposit!"); 1303 1304 width_m = rvalue_materialize(c, locp, &width_m); 1305 1306 /* 1307 * mask = 0xffffffffffffffff >> (64 - width) 1308 * mask = mask << begin 1309 * value = (value << begin) & mask 1310 * res = dst & ~mask 1311 * res = res | value 1312 * dst = (width != 0) ? res : dst 1313 */ 1314 k64 = gen_bin_op(c, locp, SUB_OP, &k64, &width_m); 1315 mask = gen_bin_op(c, locp, LSR_OP, &mask, &k64); 1316 begin_m.is_manual = true; 1317 mask = gen_bin_op(c, locp, ASL_OP, &mask, &begin_m); 1318 mask.is_manual = true; 1319 value_m = gen_bin_op(c, locp, ASL_OP, &value_m, &begin_m); 1320 value_m = gen_bin_op(c, locp, ANDB_OP, &value_m, &mask); 1321 1322 OUT(c, locp, "tcg_gen_not_i", &dst->bit_width, "(", &mask, ", ", 1323 &mask, ");\n"); 1324 mask.is_manual = false; 1325 res = gen_bin_op(c, locp, ANDB_OP, dst, &mask); 1326 res = gen_bin_op(c, locp, ORB_OP, &res, &value_m); 1327 1328 /* 1329 * We don't need to truncate `res` here, since all operations involved use 1330 * the same bit width. 1331 */ 1332 1333 /* If the width is zero, then return the identity dst = dst */ 1334 zero = gen_constant(c, locp, "0", res.bit_width, UNSIGNED); 1335 OUT(c, locp, "tcg_gen_movcond_i", &res.bit_width, "(TCG_COND_NE, ", 1336 dst); 1337 OUT(c, locp, ", ", &width_m, ", ", &zero, ", ", &res, ", ", dst, 1338 ");\n"); 1339 1340 gen_rvalue_free(c, locp, width); 1341 gen_rvalue_free(c, locp, &res); 1342 } 1343 1344 void gen_deposit_op(Context *c, 1345 YYLTYPE *locp, 1346 HexValue *dst, 1347 HexValue *value, 1348 HexValue *index, 1349 HexCast *cast) 1350 { 1351 HexValue value_m = *value; 1352 unsigned bit_width = (dst->bit_width == 64) ? 64 : 32; 1353 unsigned width = cast->bit_width; 1354 1355 yyassert(c, locp, index->type == IMMEDIATE, 1356 "Deposit index must be immediate!\n"); 1357 1358 /* 1359 * Using tcg_gen_deposit_i**(dst, dst, ...) requires dst to be 1360 * initialized. 1361 */ 1362 gen_inst_init_args(c, locp); 1363 1364 /* If the destination value is 32, truncate the value, otherwise extend */ 1365 if (dst->bit_width != value->bit_width) { 1366 if (bit_width == 32) { 1367 value_m = gen_rvalue_truncate(c, locp, &value_m); 1368 } else { 1369 value_m = gen_rvalue_extend(c, locp, &value_m); 1370 } 1371 } 1372 value_m = rvalue_materialize(c, locp, &value_m); 1373 OUT(c, locp, "tcg_gen_deposit_i", &bit_width, "(", dst, ", ", dst, ", "); 1374 OUT(c, locp, &value_m, ", ", index, " * ", &width, ", ", &width, ");\n"); 1375 gen_rvalue_free(c, locp, index); 1376 gen_rvalue_free(c, locp, &value_m); 1377 } 1378 1379 HexValue gen_rextract_op(Context *c, 1380 YYLTYPE *locp, 1381 HexValue *src, 1382 unsigned begin, 1383 unsigned width) 1384 { 1385 unsigned bit_width = (src->bit_width == 64) ? 64 : 32; 1386 HexValue res = gen_tmp(c, locp, bit_width, UNSIGNED); 1387 OUT(c, locp, "tcg_gen_extract_i", &bit_width, "(", &res); 1388 OUT(c, locp, ", ", src, ", ", &begin, ", ", &width, ");\n"); 1389 gen_rvalue_free(c, locp, src); 1390 return res; 1391 } 1392 1393 HexValue gen_extract_op(Context *c, 1394 YYLTYPE *locp, 1395 HexValue *src, 1396 HexValue *index, 1397 HexExtract *extract) 1398 { 1399 unsigned bit_width = (src->bit_width == 64) ? 64 : 32; 1400 unsigned width = extract->bit_width; 1401 const char *sign_prefix; 1402 HexValue res; 1403 1404 yyassert(c, locp, index->type == IMMEDIATE, 1405 "Extract index must be immediate!\n"); 1406 assert_signedness(c, locp, extract->signedness); 1407 1408 sign_prefix = (extract->signedness == UNSIGNED) ? "" : "s"; 1409 res = gen_tmp(c, locp, bit_width, extract->signedness); 1410 1411 OUT(c, locp, "tcg_gen_", sign_prefix, "extract_i", &bit_width, 1412 "(", &res, ", ", src); 1413 OUT(c, locp, ", ", index, " * ", &width, ", ", &width, ");\n"); 1414 1415 /* Some extract operations have bit_width != storage_bit_width */ 1416 if (extract->storage_bit_width > bit_width) { 1417 HexValue tmp = gen_tmp(c, locp, extract->storage_bit_width, 1418 extract->signedness); 1419 const char *sign_suffix = (extract->signedness == UNSIGNED) ? "u" : ""; 1420 OUT(c, locp, "tcg_gen_ext", sign_suffix, "_i32_i64(", 1421 &tmp, ", ", &res, ");\n"); 1422 gen_rvalue_free(c, locp, &res); 1423 res = tmp; 1424 } 1425 1426 gen_rvalue_free(c, locp, src); 1427 gen_rvalue_free(c, locp, index); 1428 return res; 1429 } 1430 1431 void gen_write_reg(Context *c, YYLTYPE *locp, HexValue *reg, HexValue *value) 1432 { 1433 HexValue value_m = *value; 1434 yyassert(c, locp, reg->type == REGISTER, "reg must be a register!"); 1435 value_m = gen_rvalue_truncate(c, locp, &value_m); 1436 value_m = rvalue_materialize(c, locp, &value_m); 1437 OUT(c, 1438 locp, 1439 "gen_log_reg_write(", ®->reg.id, ", ", 1440 &value_m, ");\n"); 1441 OUT(c, 1442 locp, 1443 "ctx_log_reg_write(ctx, ", ®->reg.id, 1444 ");\n"); 1445 gen_rvalue_free(c, locp, reg); 1446 gen_rvalue_free(c, locp, &value_m); 1447 } 1448 1449 void gen_assign(Context *c, 1450 YYLTYPE *locp, 1451 HexValue *dst, 1452 HexValue *value) 1453 { 1454 HexValue value_m = *value; 1455 unsigned bit_width; 1456 1457 yyassert(c, locp, !is_inside_ternary(c), 1458 "Assign in ternary not allowed!"); 1459 1460 if (dst->type == REGISTER) { 1461 gen_write_reg(c, locp, dst, &value_m); 1462 return; 1463 } 1464 1465 if (dst->type == VARID) { 1466 find_variable(c, locp, dst, dst); 1467 } 1468 bit_width = dst->bit_width == 64 ? 64 : 32; 1469 1470 if (bit_width != value_m.bit_width) { 1471 if (bit_width == 64) { 1472 value_m = gen_rvalue_extend(c, locp, &value_m); 1473 } else { 1474 value_m = gen_rvalue_truncate(c, locp, &value_m); 1475 } 1476 } 1477 1478 const char *imm_suffix = (value_m.type == IMMEDIATE) ? "i" : ""; 1479 OUT(c, locp, "tcg_gen_mov", imm_suffix, "_i", &bit_width, 1480 "(", dst, ", ", &value_m, ");\n"); 1481 1482 gen_rvalue_free(c, locp, &value_m); 1483 } 1484 1485 HexValue gen_convround(Context *c, 1486 YYLTYPE *locp, 1487 HexValue *src) 1488 { 1489 HexValue src_m = *src; 1490 unsigned bit_width = src_m.bit_width; 1491 const char *size = (bit_width == 32) ? "32" : "64"; 1492 HexValue res = gen_tmp(c, locp, bit_width, src->signedness); 1493 HexValue mask = gen_constant(c, locp, "0x3", bit_width, UNSIGNED); 1494 HexValue one = gen_constant(c, locp, "1", bit_width, UNSIGNED); 1495 HexValue and; 1496 HexValue src_p1; 1497 1498 src_m.is_manual = true; 1499 1500 and = gen_bin_op(c, locp, ANDB_OP, &src_m, &mask); 1501 src_p1 = gen_bin_op(c, locp, ADD_OP, &src_m, &one); 1502 1503 OUT(c, locp, "tcg_gen_movcond_i", size, "(TCG_COND_EQ, ", &res); 1504 OUT(c, locp, ", ", &and, ", ", &mask, ", "); 1505 OUT(c, locp, &src_p1, ", ", &src_m, ");\n"); 1506 1507 /* Free src but use the original `is_manual` value */ 1508 gen_rvalue_free(c, locp, src); 1509 1510 /* Free the rest of the values */ 1511 gen_rvalue_free(c, locp, &src_p1); 1512 1513 return res; 1514 } 1515 1516 static HexValue gen_convround_n_b(Context *c, 1517 YYLTYPE *locp, 1518 HexValue *a, 1519 HexValue *n) 1520 { 1521 HexValue one = gen_constant(c, locp, "1", 32, UNSIGNED); 1522 HexValue res = gen_tmp(c, locp, 64, UNSIGNED); 1523 HexValue tmp = gen_tmp(c, locp, 32, UNSIGNED); 1524 HexValue tmp_64 = gen_tmp(c, locp, 64, UNSIGNED); 1525 1526 assert(n->type != IMMEDIATE); 1527 OUT(c, locp, "tcg_gen_ext_i32_i64(", &res, ", ", a, ");\n"); 1528 OUT(c, locp, "tcg_gen_shl_i32(", &tmp); 1529 OUT(c, locp, ", ", &one, ", ", n, ");\n"); 1530 OUT(c, locp, "tcg_gen_and_i32(", &tmp); 1531 OUT(c, locp, ", ", &tmp, ", ", a, ");\n"); 1532 OUT(c, locp, "tcg_gen_shri_i32(", &tmp); 1533 OUT(c, locp, ", ", &tmp, ", 1);\n"); 1534 OUT(c, locp, "tcg_gen_ext_i32_i64(", &tmp_64, ", ", &tmp, ");\n"); 1535 OUT(c, locp, "tcg_gen_add_i64(", &res); 1536 OUT(c, locp, ", ", &res, ", ", &tmp_64, ");\n"); 1537 1538 gen_rvalue_free(c, locp, &tmp); 1539 gen_rvalue_free(c, locp, &tmp_64); 1540 1541 return res; 1542 } 1543 1544 static HexValue gen_convround_n_c(Context *c, 1545 YYLTYPE *locp, 1546 HexValue *a, 1547 HexValue *n) 1548 { 1549 HexValue res = gen_tmp(c, locp, 64, UNSIGNED); 1550 HexValue one = gen_constant(c, locp, "1", 32, UNSIGNED); 1551 HexValue tmp = gen_tmp(c, locp, 32, UNSIGNED); 1552 HexValue tmp_64 = gen_tmp(c, locp, 64, UNSIGNED); 1553 1554 OUT(c, locp, "tcg_gen_ext_i32_i64(", &res, ", ", a, ");\n"); 1555 OUT(c, locp, "tcg_gen_subi_i32(", &tmp); 1556 OUT(c, locp, ", ", n, ", 1);\n"); 1557 OUT(c, locp, "tcg_gen_shl_i32(", &tmp); 1558 OUT(c, locp, ", ", &one, ", ", &tmp, ");\n"); 1559 OUT(c, locp, "tcg_gen_ext_i32_i64(", &tmp_64, ", ", &tmp, ");\n"); 1560 OUT(c, locp, "tcg_gen_add_i64(", &res); 1561 OUT(c, locp, ", ", &res, ", ", &tmp_64, ");\n"); 1562 1563 gen_rvalue_free(c, locp, &one); 1564 gen_rvalue_free(c, locp, &tmp); 1565 gen_rvalue_free(c, locp, &tmp_64); 1566 1567 return res; 1568 } 1569 1570 HexValue gen_convround_n(Context *c, 1571 YYLTYPE *locp, 1572 HexValue *src, 1573 HexValue *pos) 1574 { 1575 HexValue zero = gen_constant(c, locp, "0", 64, UNSIGNED); 1576 HexValue l_32 = gen_constant(c, locp, "1", 32, UNSIGNED); 1577 HexValue cond = gen_tmp(c, locp, 32, UNSIGNED); 1578 HexValue cond_64 = gen_tmp(c, locp, 64, UNSIGNED); 1579 HexValue mask = gen_tmp(c, locp, 32, UNSIGNED); 1580 HexValue n_64 = gen_tmp(c, locp, 64, UNSIGNED); 1581 HexValue res = gen_tmp(c, locp, 64, UNSIGNED); 1582 /* If input is 64 bit cast it to 32 */ 1583 HexValue src_casted = gen_cast_op(c, locp, src, 32, src->signedness); 1584 HexValue pos_casted = gen_cast_op(c, locp, pos, 32, pos->signedness); 1585 HexValue r1; 1586 HexValue r2; 1587 HexValue r3; 1588 1589 src_casted = rvalue_materialize(c, locp, &src_casted); 1590 pos_casted = rvalue_materialize(c, locp, &pos_casted); 1591 1592 /* 1593 * r1, r2, and r3 represent the results of three different branches. 1594 * - r1 picked if pos_casted == 0 1595 * - r2 picked if (src_casted & ((1 << (pos_casted - 1)) - 1)) == 0), 1596 * that is if bits 0, ..., pos_casted-1 are all 0. 1597 * - r3 picked otherwise. 1598 */ 1599 r1 = gen_rvalue_extend(c, locp, &src_casted); 1600 r2 = gen_convround_n_b(c, locp, &src_casted, &pos_casted); 1601 r3 = gen_convround_n_c(c, locp, &src_casted, &pos_casted); 1602 1603 /* 1604 * Calculate the condition 1605 * (src_casted & ((1 << (pos_casted - 1)) - 1)) == 0), 1606 * which checks if the bits 0,...,pos-1 are all 0. 1607 */ 1608 OUT(c, locp, "tcg_gen_sub_i32(", &mask); 1609 OUT(c, locp, ", ", &pos_casted, ", ", &l_32, ");\n"); 1610 OUT(c, locp, "tcg_gen_shl_i32(", &mask); 1611 OUT(c, locp, ", ", &l_32, ", ", &mask, ");\n"); 1612 OUT(c, locp, "tcg_gen_sub_i32(", &mask); 1613 OUT(c, locp, ", ", &mask, ", ", &l_32, ");\n"); 1614 OUT(c, locp, "tcg_gen_and_i32(", &cond); 1615 OUT(c, locp, ", ", &src_casted, ", ", &mask, ");\n"); 1616 OUT(c, locp, "tcg_gen_extu_i32_i64(", &cond_64, ", ", &cond, ");\n"); 1617 1618 OUT(c, locp, "tcg_gen_ext_i32_i64(", &n_64, ", ", &pos_casted, ");\n"); 1619 1620 /* 1621 * if the bits 0, ..., pos_casted-1 are all 0, then pick r2 otherwise, 1622 * pick r3. 1623 */ 1624 OUT(c, locp, "tcg_gen_movcond_i64"); 1625 OUT(c, locp, "(TCG_COND_EQ, ", &res, ", ", &cond_64, ", ", &zero); 1626 OUT(c, locp, ", ", &r2, ", ", &r3, ");\n"); 1627 1628 /* Lastly, if the pos_casted == 0, then pick r1 */ 1629 OUT(c, locp, "tcg_gen_movcond_i64"); 1630 OUT(c, locp, "(TCG_COND_EQ, ", &res, ", ", &n_64, ", ", &zero); 1631 OUT(c, locp, ", ", &r1, ", ", &res, ");\n"); 1632 1633 /* Finally shift back val >>= n */ 1634 OUT(c, locp, "tcg_gen_shr_i64(", &res); 1635 OUT(c, locp, ", ", &res, ", ", &n_64, ");\n"); 1636 1637 gen_rvalue_free(c, locp, &src_casted); 1638 gen_rvalue_free(c, locp, &pos_casted); 1639 1640 gen_rvalue_free(c, locp, &r1); 1641 gen_rvalue_free(c, locp, &r2); 1642 gen_rvalue_free(c, locp, &r3); 1643 1644 gen_rvalue_free(c, locp, &cond); 1645 gen_rvalue_free(c, locp, &cond_64); 1646 gen_rvalue_free(c, locp, &mask); 1647 gen_rvalue_free(c, locp, &n_64); 1648 1649 res = gen_rvalue_truncate(c, locp, &res); 1650 return res; 1651 } 1652 1653 HexValue gen_round(Context *c, 1654 YYLTYPE *locp, 1655 HexValue *src, 1656 HexValue *pos) 1657 { 1658 HexValue zero = gen_constant(c, locp, "0", 64, UNSIGNED); 1659 HexValue one = gen_constant(c, locp, "1", 64, UNSIGNED); 1660 HexValue res; 1661 HexValue n_m1; 1662 HexValue shifted; 1663 HexValue sum; 1664 HexValue src_width; 1665 HexValue a; 1666 HexValue b; 1667 1668 assert_signedness(c, locp, src->signedness); 1669 yyassert(c, locp, src->bit_width <= 32, 1670 "fRNDN not implemented for bit widths > 32!"); 1671 1672 res = gen_tmp(c, locp, 64, src->signedness); 1673 1674 src_width = gen_imm_value(c, locp, src->bit_width, 32, UNSIGNED); 1675 a = gen_extend_op(c, locp, &src_width, 64, src, SIGNED); 1676 a = rvalue_materialize(c, locp, &a); 1677 1678 src_width = gen_imm_value(c, locp, 5, 32, UNSIGNED); 1679 b = gen_extend_op(c, locp, &src_width, 64, pos, UNSIGNED); 1680 b = rvalue_materialize(c, locp, &b); 1681 1682 /* Disable auto-free of values used more than once */ 1683 a.is_manual = true; 1684 b.is_manual = true; 1685 1686 n_m1 = gen_bin_op(c, locp, SUB_OP, &b, &one); 1687 shifted = gen_bin_op(c, locp, ASL_OP, &one, &n_m1); 1688 sum = gen_bin_op(c, locp, ADD_OP, &shifted, &a); 1689 1690 OUT(c, locp, "tcg_gen_movcond_i64"); 1691 OUT(c, locp, "(TCG_COND_EQ, ", &res, ", ", &b, ", ", &zero); 1692 OUT(c, locp, ", ", &a, ", ", &sum, ");\n"); 1693 1694 gen_rvalue_free_manual(c, locp, &a); 1695 gen_rvalue_free_manual(c, locp, &b); 1696 gen_rvalue_free(c, locp, &sum); 1697 1698 return res; 1699 } 1700 1701 /* Circular addressing mode with auto-increment */ 1702 void gen_circ_op(Context *c, 1703 YYLTYPE *locp, 1704 HexValue *addr, 1705 HexValue *increment, 1706 HexValue *modifier) 1707 { 1708 HexValue cs = gen_tmp(c, locp, 32, UNSIGNED); 1709 HexValue increment_m = *increment; 1710 increment_m = rvalue_materialize(c, locp, &increment_m); 1711 OUT(c, locp, "gen_read_reg(", &cs, ", HEX_REG_CS0 + MuN);\n"); 1712 OUT(c, 1713 locp, 1714 "gen_helper_fcircadd(", 1715 addr, 1716 ", ", 1717 addr, 1718 ", ", 1719 &increment_m, 1720 ", ", 1721 modifier); 1722 OUT(c, locp, ", ", &cs, ");\n"); 1723 gen_rvalue_free(c, locp, &increment_m); 1724 gen_rvalue_free(c, locp, modifier); 1725 gen_rvalue_free(c, locp, &cs); 1726 } 1727 1728 HexValue gen_locnt_op(Context *c, YYLTYPE *locp, HexValue *src) 1729 { 1730 const char *bit_suffix = src->bit_width == 64 ? "64" : "32"; 1731 HexValue src_m = *src; 1732 HexValue res; 1733 1734 assert_signedness(c, locp, src->signedness); 1735 res = gen_tmp(c, locp, src->bit_width == 64 ? 64 : 32, src->signedness); 1736 src_m = rvalue_materialize(c, locp, &src_m); 1737 OUT(c, locp, "tcg_gen_not_i", bit_suffix, "(", 1738 &res, ", ", &src_m, ");\n"); 1739 OUT(c, locp, "tcg_gen_clzi_i", bit_suffix, "(", &res, ", ", &res, ", "); 1740 OUT(c, locp, bit_suffix, ");\n"); 1741 gen_rvalue_free(c, locp, &src_m); 1742 return res; 1743 } 1744 1745 HexValue gen_ctpop_op(Context *c, YYLTYPE *locp, HexValue *src) 1746 { 1747 const char *bit_suffix = src->bit_width == 64 ? "64" : "32"; 1748 HexValue src_m = *src; 1749 HexValue res; 1750 assert_signedness(c, locp, src->signedness); 1751 res = gen_tmp(c, locp, src->bit_width == 64 ? 64 : 32, src->signedness); 1752 src_m = rvalue_materialize(c, locp, &src_m); 1753 OUT(c, locp, "tcg_gen_ctpop_i", bit_suffix, 1754 "(", &res, ", ", &src_m, ");\n"); 1755 gen_rvalue_free(c, locp, &src_m); 1756 return res; 1757 } 1758 1759 HexValue gen_rotl(Context *c, YYLTYPE *locp, HexValue *src, HexValue *width) 1760 { 1761 const char *suffix = src->bit_width == 64 ? "i64" : "i32"; 1762 HexValue amount = *width; 1763 HexValue res; 1764 assert_signedness(c, locp, src->signedness); 1765 res = gen_tmp(c, locp, src->bit_width, src->signedness); 1766 if (amount.bit_width < src->bit_width) { 1767 amount = gen_rvalue_extend(c, locp, &amount); 1768 } else { 1769 amount = gen_rvalue_truncate(c, locp, &amount); 1770 } 1771 amount = rvalue_materialize(c, locp, &amount); 1772 OUT(c, locp, "tcg_gen_rotl_", suffix, "(", 1773 &res, ", ", src, ", ", &amount, ");\n"); 1774 gen_rvalue_free(c, locp, src); 1775 gen_rvalue_free(c, locp, &amount); 1776 1777 return res; 1778 } 1779 1780 HexValue gen_carry_from_add(Context *c, 1781 YYLTYPE *locp, 1782 HexValue *op1, 1783 HexValue *op2, 1784 HexValue *op3) 1785 { 1786 HexValue zero = gen_constant(c, locp, "0", 64, UNSIGNED); 1787 HexValue res = gen_tmp(c, locp, 64, UNSIGNED); 1788 HexValue cf = gen_tmp(c, locp, 64, UNSIGNED); 1789 HexValue op1_m = rvalue_materialize(c, locp, op1); 1790 HexValue op2_m = rvalue_materialize(c, locp, op2); 1791 HexValue op3_m = rvalue_materialize(c, locp, op3); 1792 op3_m = gen_rvalue_extend(c, locp, &op3_m); 1793 1794 OUT(c, locp, "tcg_gen_add2_i64(", &res, ", ", &cf, ", ", &op1_m, ", ", 1795 &zero); 1796 OUT(c, locp, ", ", &op3_m, ", ", &zero, ");\n"); 1797 OUT(c, locp, "tcg_gen_add2_i64(", &res, ", ", &cf, ", ", &res, ", ", &cf); 1798 OUT(c, locp, ", ", &op2_m, ", ", &zero, ");\n"); 1799 1800 gen_rvalue_free(c, locp, &op1_m); 1801 gen_rvalue_free(c, locp, &op2_m); 1802 gen_rvalue_free(c, locp, &op3_m); 1803 gen_rvalue_free(c, locp, &res); 1804 return cf; 1805 } 1806 1807 void gen_addsat64(Context *c, 1808 YYLTYPE *locp, 1809 HexValue *dst, 1810 HexValue *op1, 1811 HexValue *op2) 1812 { 1813 HexValue op1_m = rvalue_materialize(c, locp, op1); 1814 HexValue op2_m = rvalue_materialize(c, locp, op2); 1815 OUT(c, locp, "gen_add_sat_i64(", dst, ", ", &op1_m, ", ", &op2_m, ");\n"); 1816 } 1817 1818 void gen_inst(Context *c, GString *iname) 1819 { 1820 c->total_insn++; 1821 c->inst.name = iname; 1822 c->inst.allocated = g_array_new(FALSE, FALSE, sizeof(Var)); 1823 c->inst.init_list = g_array_new(FALSE, FALSE, sizeof(HexValue)); 1824 c->inst.strings = g_array_new(FALSE, FALSE, sizeof(GString *)); 1825 EMIT_SIG(c, "void emit_%s(DisasContext *ctx, Insn *insn, Packet *pkt", 1826 c->inst.name->str); 1827 } 1828 1829 1830 /* 1831 * Initialize declared but uninitialized registers, but only for 1832 * non-conditional instructions 1833 */ 1834 void gen_inst_init_args(Context *c, YYLTYPE *locp) 1835 { 1836 if (!c->inst.init_list) { 1837 return; 1838 } 1839 1840 for (unsigned i = 0; i < c->inst.init_list->len; i++) { 1841 HexValue *val = &g_array_index(c->inst.init_list, HexValue, i); 1842 if (val->type == REGISTER_ARG) { 1843 char reg_id[5]; 1844 reg_compose(c, locp, &val->reg, reg_id); 1845 EMIT_HEAD(c, "tcg_gen_movi_i%u(%s, 0);\n", val->bit_width, reg_id); 1846 } else if (val->type == PREDICATE) { 1847 char suffix = val->is_dotnew ? 'N' : 'V'; 1848 EMIT_HEAD(c, "tcg_gen_movi_i%u(P%c%c, 0);\n", val->bit_width, 1849 val->pred.id, suffix); 1850 } else { 1851 yyassert(c, locp, false, "Invalid arg type!"); 1852 } 1853 } 1854 1855 /* Free argument init list once we have initialized everything */ 1856 g_array_free(c->inst.init_list, TRUE); 1857 c->inst.init_list = NULL; 1858 } 1859 1860 void gen_inst_code(Context *c, YYLTYPE *locp) 1861 { 1862 if (c->inst.error_count != 0) { 1863 fprintf(stderr, 1864 "Parsing of instruction %s generated %d errors!\n", 1865 c->inst.name->str, 1866 c->inst.error_count); 1867 } else { 1868 free_variables(c, locp); 1869 c->implemented_insn++; 1870 fprintf(c->enabled_file, "%s\n", c->inst.name->str); 1871 emit_footer(c); 1872 commit(c); 1873 } 1874 free_instruction(c); 1875 } 1876 1877 void gen_pred_assign(Context *c, YYLTYPE *locp, HexValue *left_pred, 1878 HexValue *right_pred) 1879 { 1880 char pred_id[2] = {left_pred->pred.id, 0}; 1881 bool is_direct = is_direct_predicate(left_pred); 1882 HexValue r = rvalue_materialize(c, locp, right_pred); 1883 r = gen_rvalue_truncate(c, locp, &r); 1884 yyassert(c, locp, !is_inside_ternary(c), 1885 "Predicate assign not allowed in ternary!"); 1886 /* Extract predicate TCGv */ 1887 if (is_direct) { 1888 *left_pred = gen_tmp_value(c, locp, "0", 32, UNSIGNED); 1889 } 1890 /* Extract first 8 bits, and store new predicate value */ 1891 OUT(c, locp, "tcg_gen_mov_i32(", left_pred, ", ", &r, ");\n"); 1892 OUT(c, locp, "tcg_gen_andi_i32(", left_pred, ", ", left_pred, 1893 ", 0xff);\n"); 1894 if (is_direct) { 1895 OUT(c, locp, "gen_log_pred_write(ctx, ", pred_id, ", ", left_pred, 1896 ");\n"); 1897 OUT(c, locp, "ctx_log_pred_write(ctx, ", pred_id, ");\n"); 1898 gen_rvalue_free(c, locp, left_pred); 1899 } 1900 /* Free temporary value */ 1901 gen_rvalue_free(c, locp, &r); 1902 } 1903 1904 void gen_cancel(Context *c, YYLTYPE *locp) 1905 { 1906 OUT(c, locp, "gen_cancel(insn->slot);\n"); 1907 } 1908 1909 void gen_load_cancel(Context *c, YYLTYPE *locp) 1910 { 1911 gen_cancel(c, locp); 1912 OUT(c, locp, "if (insn->slot == 0 && pkt->pkt_has_store_s1) {\n"); 1913 OUT(c, locp, "ctx->s1_store_processed = false;\n"); 1914 OUT(c, locp, "process_store(ctx, 1);\n"); 1915 OUT(c, locp, "}\n"); 1916 } 1917 1918 void gen_load(Context *c, YYLTYPE *locp, HexValue *width, 1919 HexSignedness signedness, HexValue *ea, HexValue *dst) 1920 { 1921 char size_suffix[4] = {0}; 1922 const char *sign_suffix; 1923 /* Memop width is specified in the load macro */ 1924 assert_signedness(c, locp, signedness); 1925 sign_suffix = (width->imm.value > 4) 1926 ? "" 1927 : ((signedness == UNSIGNED) ? "u" : "s"); 1928 /* If dst is a variable, assert that is declared and load the type info */ 1929 if (dst->type == VARID) { 1930 find_variable(c, locp, dst, dst); 1931 } 1932 1933 snprintf(size_suffix, 4, "%" PRIu64, width->imm.value * 8); 1934 /* Lookup the effective address EA */ 1935 find_variable(c, locp, ea, ea); 1936 OUT(c, locp, "if (insn->slot == 0 && pkt->pkt_has_store_s1) {\n"); 1937 OUT(c, locp, "probe_noshuf_load(", ea, ", ", width, ", ctx->mem_idx);\n"); 1938 OUT(c, locp, "process_store(ctx, 1);\n"); 1939 OUT(c, locp, "}\n"); 1940 OUT(c, locp, "tcg_gen_qemu_ld", size_suffix, sign_suffix); 1941 OUT(c, locp, "("); 1942 if (dst->bit_width > width->imm.value * 8) { 1943 /* 1944 * Cast to the correct TCG type if necessary, to avoid implict cast 1945 * warnings. This is needed when the width of the destination var is 1946 * larger than the size of the requested load. 1947 */ 1948 OUT(c, locp, "(TCGv) "); 1949 } 1950 OUT(c, locp, dst, ", ", ea, ", ctx->mem_idx);\n"); 1951 /* If the var in EA was truncated it is now a tmp HexValue, so free it. */ 1952 gen_rvalue_free(c, locp, ea); 1953 } 1954 1955 void gen_store(Context *c, YYLTYPE *locp, HexValue *width, HexValue *ea, 1956 HexValue *src) 1957 { 1958 HexValue src_m = *src; 1959 /* Memop width is specified in the store macro */ 1960 unsigned mem_width = width->imm.value; 1961 /* Lookup the effective address EA */ 1962 find_variable(c, locp, ea, ea); 1963 src_m = rvalue_materialize(c, locp, &src_m); 1964 OUT(c, locp, "gen_store", &mem_width, "(cpu_env, ", ea, ", ", &src_m); 1965 OUT(c, locp, ", insn->slot);\n"); 1966 gen_rvalue_free(c, locp, &src_m); 1967 /* If the var in ea was truncated it is now a tmp HexValue, so free it. */ 1968 gen_rvalue_free(c, locp, ea); 1969 } 1970 1971 void gen_sethalf(Context *c, YYLTYPE *locp, HexCast *sh, HexValue *n, 1972 HexValue *dst, HexValue *value) 1973 { 1974 yyassert(c, locp, n->type == IMMEDIATE, 1975 "Deposit index must be immediate!\n"); 1976 if (dst->type == VARID) { 1977 find_variable(c, locp, dst, dst); 1978 } 1979 1980 gen_deposit_op(c, locp, dst, value, n, sh); 1981 } 1982 1983 void gen_setbits(Context *c, YYLTYPE *locp, HexValue *hi, HexValue *lo, 1984 HexValue *dst, HexValue *value) 1985 { 1986 unsigned len; 1987 HexValue tmp; 1988 1989 yyassert(c, locp, hi->type == IMMEDIATE && 1990 hi->imm.type == VALUE && 1991 lo->type == IMMEDIATE && 1992 lo->imm.type == VALUE, 1993 "Range deposit needs immediate values!\n"); 1994 1995 *value = gen_rvalue_truncate(c, locp, value); 1996 len = hi->imm.value + 1 - lo->imm.value; 1997 tmp = gen_tmp(c, locp, 32, value->signedness); 1998 /* Emit an `and` to ensure `value` is either 0 or 1. */ 1999 OUT(c, locp, "tcg_gen_andi_i32(", &tmp, ", ", value, ", 1);\n"); 2000 /* Use `neg` to map 0 -> 0 and 1 -> 0xffff... */ 2001 OUT(c, locp, "tcg_gen_neg_i32(", &tmp, ", ", &tmp, ");\n"); 2002 OUT(c, locp, "tcg_gen_deposit_i32(", dst, ", ", dst, 2003 ", ", &tmp, ", "); 2004 OUT(c, locp, lo, ", ", &len, ");\n"); 2005 2006 gen_rvalue_free(c, locp, &tmp); 2007 gen_rvalue_free(c, locp, hi); 2008 gen_rvalue_free(c, locp, lo); 2009 gen_rvalue_free(c, locp, value); 2010 } 2011 2012 unsigned gen_if_cond(Context *c, YYLTYPE *locp, HexValue *cond) 2013 { 2014 const char *bit_suffix; 2015 /* Generate an end label, if false branch to that label */ 2016 OUT(c, locp, "TCGLabel *if_label_", &c->inst.if_count, 2017 " = gen_new_label();\n"); 2018 *cond = rvalue_materialize(c, locp, cond); 2019 bit_suffix = (cond->bit_width == 64) ? "i64" : "i32"; 2020 OUT(c, locp, "tcg_gen_brcondi_", bit_suffix, "(TCG_COND_EQ, ", cond, 2021 ", 0, if_label_", &c->inst.if_count, ");\n"); 2022 gen_rvalue_free(c, locp, cond); 2023 return c->inst.if_count++; 2024 } 2025 2026 unsigned gen_if_else(Context *c, YYLTYPE *locp, unsigned index) 2027 { 2028 unsigned if_index = c->inst.if_count++; 2029 /* Generate label to jump if else is not verified */ 2030 OUT(c, locp, "TCGLabel *if_label_", &if_index, 2031 " = gen_new_label();\n"); 2032 /* Jump out of the else statement */ 2033 OUT(c, locp, "tcg_gen_br(if_label_", &if_index, ");\n"); 2034 /* Fix the else label */ 2035 OUT(c, locp, "gen_set_label(if_label_", &index, ");\n"); 2036 return if_index; 2037 } 2038 2039 HexValue gen_rvalue_pred(Context *c, YYLTYPE *locp, HexValue *pred) 2040 { 2041 /* Predicted instructions need to zero out result args */ 2042 gen_inst_init_args(c, locp); 2043 2044 if (is_direct_predicate(pred)) { 2045 bool is_dotnew = pred->is_dotnew; 2046 char predicate_id[2] = { pred->pred.id, '\0' }; 2047 char *pred_str = (char *) &predicate_id; 2048 *pred = gen_tmp_value(c, locp, "0", 32, UNSIGNED); 2049 if (is_dotnew) { 2050 OUT(c, locp, "tcg_gen_mov_i32(", pred, 2051 ", hex_new_pred_value["); 2052 OUT(c, locp, pred_str, "]);\n"); 2053 } else { 2054 OUT(c, locp, "gen_read_preg(", pred, ", ", pred_str, ");\n"); 2055 } 2056 } 2057 2058 return *pred; 2059 } 2060 2061 HexValue gen_rvalue_var(Context *c, YYLTYPE *locp, HexValue *var) 2062 { 2063 find_variable(c, locp, var, var); 2064 return *var; 2065 } 2066 2067 HexValue gen_rvalue_mpy(Context *c, YYLTYPE *locp, HexMpy *mpy, 2068 HexValue *op1, HexValue *op2) 2069 { 2070 HexValue res; 2071 memset(&res, 0, sizeof(HexValue)); 2072 2073 assert_signedness(c, locp, mpy->first_signedness); 2074 assert_signedness(c, locp, mpy->second_signedness); 2075 2076 *op1 = gen_cast_op(c, locp, op1, mpy->first_bit_width * 2, 2077 mpy->first_signedness); 2078 /* Handle fMPTY3216.. */ 2079 if (mpy->first_bit_width == 32) { 2080 *op2 = gen_cast_op(c, locp, op2, 64, mpy->second_signedness); 2081 } else { 2082 *op2 = gen_cast_op(c, locp, op2, mpy->second_bit_width * 2, 2083 mpy->second_signedness); 2084 } 2085 res = gen_bin_op(c, locp, MUL_OP, op1, op2); 2086 /* Handle special cases required by the language */ 2087 if (mpy->first_bit_width == 16 && mpy->second_bit_width == 16) { 2088 HexValue src_width = gen_imm_value(c, locp, 32, 32, UNSIGNED); 2089 HexSignedness signedness = bin_op_signedness(c, locp, 2090 mpy->first_signedness, 2091 mpy->second_signedness); 2092 res = gen_extend_op(c, locp, &src_width, 64, &res, 2093 signedness); 2094 } 2095 return res; 2096 } 2097 2098 static inline HexValue gen_rvalue_simple_unary(Context *c, YYLTYPE *locp, 2099 HexValue *value, 2100 const char *c_code, 2101 const char *tcg_code) 2102 { 2103 unsigned bit_width = (value->bit_width == 64) ? 64 : 32; 2104 HexValue res; 2105 if (value->type == IMMEDIATE) { 2106 res = gen_imm_qemu_tmp(c, locp, bit_width, value->signedness); 2107 gen_c_int_type(c, locp, value->bit_width, value->signedness); 2108 OUT(c, locp, " ", &res, " = ", c_code, "(", value, ");\n"); 2109 } else { 2110 res = gen_tmp(c, locp, bit_width, value->signedness); 2111 OUT(c, locp, tcg_code, "_i", &bit_width, "(", &res, ", ", value, 2112 ");\n"); 2113 gen_rvalue_free(c, locp, value); 2114 } 2115 return res; 2116 } 2117 2118 2119 HexValue gen_rvalue_not(Context *c, YYLTYPE *locp, HexValue *value) 2120 { 2121 return gen_rvalue_simple_unary(c, locp, value, "~", "tcg_gen_not"); 2122 } 2123 2124 HexValue gen_rvalue_notl(Context *c, YYLTYPE *locp, HexValue *value) 2125 { 2126 unsigned bit_width = (value->bit_width == 64) ? 64 : 32; 2127 HexValue res; 2128 if (value->type == IMMEDIATE) { 2129 res = gen_imm_qemu_tmp(c, locp, bit_width, value->signedness); 2130 gen_c_int_type(c, locp, value->bit_width, value->signedness); 2131 OUT(c, locp, " ", &res, " = !(", value, ");\n"); 2132 } else { 2133 HexValue zero = gen_constant(c, locp, "0", bit_width, UNSIGNED); 2134 HexValue one = gen_constant(c, locp, "0xff", bit_width, UNSIGNED); 2135 res = gen_tmp(c, locp, bit_width, value->signedness); 2136 OUT(c, locp, "tcg_gen_movcond_i", &bit_width); 2137 OUT(c, locp, "(TCG_COND_EQ, ", &res, ", ", value, ", ", &zero); 2138 OUT(c, locp, ", ", &one, ", ", &zero, ");\n"); 2139 gen_rvalue_free(c, locp, value); 2140 } 2141 return res; 2142 } 2143 2144 HexValue gen_rvalue_sat(Context *c, YYLTYPE *locp, HexSat *sat, 2145 HexValue *width, HexValue *value) 2146 { 2147 const char *unsigned_str; 2148 const char *bit_suffix = (value->bit_width == 64) ? "i64" : "i32"; 2149 HexValue res; 2150 HexValue ovfl; 2151 /* 2152 * Note: all saturates are assumed to implicitly set overflow. 2153 * This assumption holds for the instructions currently parsed 2154 * by idef-parser. 2155 */ 2156 yyassert(c, locp, width->imm.value < value->bit_width, 2157 "To compute overflow, source width must be greater than" 2158 " saturation width!"); 2159 yyassert(c, locp, !is_inside_ternary(c), 2160 "Saturating from within a ternary is not allowed!"); 2161 assert_signedness(c, locp, sat->signedness); 2162 2163 unsigned_str = (sat->signedness == UNSIGNED) ? "u" : ""; 2164 res = gen_tmp_local(c, locp, value->bit_width, sat->signedness); 2165 ovfl = gen_tmp_local(c, locp, 32, sat->signedness); 2166 OUT(c, locp, "gen_sat", unsigned_str, "_", bit_suffix, "_ovfl("); 2167 OUT(c, locp, &ovfl, ", ", &res, ", ", value, ", ", &width->imm.value, 2168 ");\n"); 2169 OUT(c, locp, "gen_set_usr_field_if(USR_OVF,", &ovfl, ");\n"); 2170 gen_rvalue_free(c, locp, value); 2171 2172 return res; 2173 } 2174 2175 HexValue gen_rvalue_fscr(Context *c, YYLTYPE *locp, HexValue *value) 2176 { 2177 HexValue key = gen_tmp(c, locp, 64, UNSIGNED); 2178 HexValue res = gen_tmp(c, locp, 64, UNSIGNED); 2179 HexValue frame_key = gen_tmp(c, locp, 32, UNSIGNED); 2180 *value = gen_rvalue_extend(c, locp, value); 2181 OUT(c, locp, "gen_read_reg(", &frame_key, ", HEX_REG_FRAMEKEY);\n"); 2182 OUT(c, locp, "tcg_gen_concat_i32_i64(", 2183 &key, ", ", &frame_key, ", ", &frame_key, ");\n"); 2184 OUT(c, locp, "tcg_gen_xor_i64(", &res, ", ", value, ", ", &key, ");\n"); 2185 gen_rvalue_free(c, locp, &key); 2186 gen_rvalue_free(c, locp, &frame_key); 2187 gen_rvalue_free(c, locp, value); 2188 return res; 2189 } 2190 2191 HexValue gen_rvalue_abs(Context *c, YYLTYPE *locp, HexValue *value) 2192 { 2193 return gen_rvalue_simple_unary(c, locp, value, "abs", "tcg_gen_abs"); 2194 } 2195 2196 HexValue gen_rvalue_neg(Context *c, YYLTYPE *locp, HexValue *value) 2197 { 2198 return gen_rvalue_simple_unary(c, locp, value, "-", "tcg_gen_neg"); 2199 } 2200 2201 HexValue gen_rvalue_brev(Context *c, YYLTYPE *locp, HexValue *value) 2202 { 2203 HexValue res; 2204 yyassert(c, locp, value->bit_width <= 32, 2205 "fbrev not implemented for 64-bit integers!"); 2206 res = gen_tmp(c, locp, value->bit_width, value->signedness); 2207 *value = rvalue_materialize(c, locp, value); 2208 OUT(c, locp, "gen_helper_fbrev(", &res, ", ", value, ");\n"); 2209 gen_rvalue_free(c, locp, value); 2210 return res; 2211 } 2212 2213 HexValue gen_rvalue_ternary(Context *c, YYLTYPE *locp, HexValue *cond, 2214 HexValue *true_branch, HexValue *false_branch) 2215 { 2216 bool is_64bit = (true_branch->bit_width == 64) || 2217 (false_branch->bit_width == 64); 2218 unsigned bit_width = (is_64bit) ? 64 : 32; 2219 HexValue zero = gen_constant(c, locp, "0", bit_width, UNSIGNED); 2220 HexValue res = gen_tmp(c, locp, bit_width, UNSIGNED); 2221 Ternary *ternary = NULL; 2222 2223 if (is_64bit) { 2224 *cond = gen_rvalue_extend(c, locp, cond); 2225 *true_branch = gen_rvalue_extend(c, locp, true_branch); 2226 *false_branch = gen_rvalue_extend(c, locp, false_branch); 2227 } else { 2228 *cond = gen_rvalue_truncate(c, locp, cond); 2229 } 2230 *cond = rvalue_materialize(c, locp, cond); 2231 *true_branch = rvalue_materialize(c, locp, true_branch); 2232 *false_branch = rvalue_materialize(c, locp, false_branch); 2233 2234 OUT(c, locp, "tcg_gen_movcond_i", &bit_width); 2235 OUT(c, locp, "(TCG_COND_NE, ", &res, ", ", cond, ", ", &zero); 2236 OUT(c, locp, ", ", true_branch, ", ", false_branch, ");\n"); 2237 2238 assert(c->ternary->len > 0); 2239 ternary = &g_array_index(c->ternary, Ternary, c->ternary->len - 1); 2240 gen_rvalue_free_manual(c, locp, &ternary->cond); 2241 g_array_remove_index(c->ternary, c->ternary->len - 1); 2242 2243 gen_rvalue_free(c, locp, cond); 2244 gen_rvalue_free(c, locp, true_branch); 2245 gen_rvalue_free(c, locp, false_branch); 2246 return res; 2247 } 2248 2249 const char *cond_to_str(TCGCond cond) 2250 { 2251 switch (cond) { 2252 case TCG_COND_NEVER: 2253 return "TCG_COND_NEVER"; 2254 case TCG_COND_ALWAYS: 2255 return "TCG_COND_ALWAYS"; 2256 case TCG_COND_EQ: 2257 return "TCG_COND_EQ"; 2258 case TCG_COND_NE: 2259 return "TCG_COND_NE"; 2260 case TCG_COND_LT: 2261 return "TCG_COND_LT"; 2262 case TCG_COND_GE: 2263 return "TCG_COND_GE"; 2264 case TCG_COND_LE: 2265 return "TCG_COND_LE"; 2266 case TCG_COND_GT: 2267 return "TCG_COND_GT"; 2268 case TCG_COND_LTU: 2269 return "TCG_COND_LTU"; 2270 case TCG_COND_GEU: 2271 return "TCG_COND_GEU"; 2272 case TCG_COND_LEU: 2273 return "TCG_COND_LEU"; 2274 case TCG_COND_GTU: 2275 return "TCG_COND_GTU"; 2276 default: 2277 abort(); 2278 } 2279 } 2280 2281 void emit_arg(Context *c, YYLTYPE *locp, HexValue *arg) 2282 { 2283 switch (arg->type) { 2284 case REGISTER_ARG: 2285 if (arg->reg.type == DOTNEW) { 2286 EMIT_SIG(c, ", TCGv N%cN", arg->reg.id); 2287 } else { 2288 bool is64 = (arg->bit_width == 64); 2289 const char *type = is64 ? "TCGv_i64" : "TCGv_i32"; 2290 char reg_id[5]; 2291 reg_compose(c, locp, &(arg->reg), reg_id); 2292 EMIT_SIG(c, ", %s %s", type, reg_id); 2293 /* MuV register requires also MuN to provide its index */ 2294 if (arg->reg.type == MODIFIER) { 2295 EMIT_SIG(c, ", int MuN"); 2296 } 2297 } 2298 break; 2299 case PREDICATE: 2300 { 2301 char suffix = arg->is_dotnew ? 'N' : 'V'; 2302 EMIT_SIG(c, ", TCGv P%c%c", arg->pred.id, suffix); 2303 } 2304 break; 2305 default: 2306 { 2307 fprintf(stderr, "emit_arg got unsupported argument!"); 2308 abort(); 2309 } 2310 } 2311 } 2312 2313 void emit_footer(Context *c) 2314 { 2315 EMIT(c, "}\n"); 2316 EMIT(c, "\n"); 2317 } 2318 2319 void track_string(Context *c, GString *s) 2320 { 2321 g_array_append_val(c->inst.strings, s); 2322 } 2323 2324 void free_variables(Context *c, YYLTYPE *locp) 2325 { 2326 for (unsigned i = 0; i < c->inst.allocated->len; ++i) { 2327 Var *var = &g_array_index(c->inst.allocated, Var, i); 2328 const char *suffix = var->bit_width == 64 ? "i64" : "i32"; 2329 OUT(c, locp, "tcg_temp_free_", suffix, "(", var->name->str, ");\n"); 2330 } 2331 } 2332 2333 void free_instruction(Context *c) 2334 { 2335 assert(!is_inside_ternary(c)); 2336 /* Free the strings */ 2337 g_string_truncate(c->signature_str, 0); 2338 g_string_truncate(c->out_str, 0); 2339 g_string_truncate(c->header_str, 0); 2340 /* Free strings allocated by the instruction */ 2341 for (unsigned i = 0; i < c->inst.strings->len; i++) { 2342 g_string_free(g_array_index(c->inst.strings, GString*, i), TRUE); 2343 } 2344 g_array_free(c->inst.strings, TRUE); 2345 /* Free INAME token value */ 2346 g_string_free(c->inst.name, TRUE); 2347 /* Free variables and registers */ 2348 g_array_free(c->inst.allocated, TRUE); 2349 /* Initialize instruction-specific portion of the context */ 2350 memset(&(c->inst), 0, sizeof(Inst)); 2351 } 2352 2353 void assert_signedness(Context *c, 2354 YYLTYPE *locp, 2355 HexSignedness signedness) 2356 { 2357 yyassert(c, locp, 2358 signedness != UNKNOWN_SIGNEDNESS, 2359 "Unspecified signedness"); 2360 } 2361