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