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