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(", dst, ", ", &op1_m, ", ", &op2_m, ");\n"); 1644 } 1645 1646 void gen_inst(Context *c, GString *iname) 1647 { 1648 c->total_insn++; 1649 c->inst.name = iname; 1650 c->inst.allocated = g_array_new(FALSE, FALSE, sizeof(Var)); 1651 c->inst.init_list = g_array_new(FALSE, FALSE, sizeof(HexValue)); 1652 c->inst.strings = g_array_new(FALSE, FALSE, sizeof(GString *)); 1653 EMIT_SIG(c, "void emit_%s(DisasContext *ctx, Insn *insn, Packet *pkt", 1654 c->inst.name->str); 1655 } 1656 1657 1658 /* 1659 * Initialize declared but uninitialized registers, but only for 1660 * non-conditional instructions 1661 */ 1662 void gen_inst_init_args(Context *c, YYLTYPE *locp) 1663 { 1664 if (!c->inst.init_list) { 1665 return; 1666 } 1667 1668 for (unsigned i = 0; i < c->inst.init_list->len; i++) { 1669 HexValue *val = &g_array_index(c->inst.init_list, HexValue, i); 1670 if (val->type == REGISTER_ARG) { 1671 /* Nothing to do here */ 1672 } else if (val->type == PREDICATE) { 1673 char suffix = val->is_dotnew ? 'N' : 'V'; 1674 EMIT_HEAD(c, "tcg_gen_movi_i%u(P%c%c, 0);\n", val->bit_width, 1675 val->pred.id, suffix); 1676 } else { 1677 yyassert(c, locp, false, "Invalid arg type!"); 1678 } 1679 } 1680 1681 /* Free argument init list once we have initialized everything */ 1682 g_array_free(c->inst.init_list, TRUE); 1683 c->inst.init_list = NULL; 1684 } 1685 1686 void gen_inst_code(Context *c, YYLTYPE *locp) 1687 { 1688 if (c->inst.error_count != 0) { 1689 fprintf(stderr, 1690 "Parsing of instruction %s generated %d errors!\n", 1691 c->inst.name->str, 1692 c->inst.error_count); 1693 } else { 1694 c->implemented_insn++; 1695 fprintf(c->enabled_file, "%s\n", c->inst.name->str); 1696 emit_footer(c); 1697 commit(c); 1698 } 1699 free_instruction(c); 1700 } 1701 1702 void gen_pred_assign(Context *c, YYLTYPE *locp, HexValue *left_pred, 1703 HexValue *right_pred) 1704 { 1705 char pred_id[2] = {left_pred->pred.id, 0}; 1706 bool is_direct = is_direct_predicate(left_pred); 1707 HexValue r = rvalue_materialize(c, locp, right_pred); 1708 r = gen_rvalue_truncate(c, locp, &r); 1709 yyassert(c, locp, !is_inside_ternary(c), 1710 "Predicate assign not allowed in ternary!"); 1711 /* Extract predicate TCGv */ 1712 if (is_direct) { 1713 *left_pred = gen_tmp(c, locp, 32, UNSIGNED); 1714 } 1715 /* Extract first 8 bits, and store new predicate value */ 1716 OUT(c, locp, "tcg_gen_andi_i32(", left_pred, ", ", &r, ", 0xff);\n"); 1717 if (is_direct) { 1718 OUT(c, locp, "gen_log_pred_write(ctx, ", pred_id, ", ", left_pred, 1719 ");\n"); 1720 } 1721 } 1722 1723 void gen_cancel(Context *c, YYLTYPE *locp) 1724 { 1725 OUT(c, locp, "gen_cancel(insn->slot);\n"); 1726 } 1727 1728 void gen_load_cancel(Context *c, YYLTYPE *locp) 1729 { 1730 OUT(c, locp, "if (insn->slot == 0 && pkt->pkt_has_store_s1) {\n"); 1731 OUT(c, locp, "ctx->s1_store_processed = false;\n"); 1732 OUT(c, locp, "process_store(ctx, 1);\n"); 1733 OUT(c, locp, "}\n"); 1734 } 1735 1736 void gen_load(Context *c, YYLTYPE *locp, HexValue *width, 1737 HexSignedness signedness, HexValue *ea, HexValue *dst) 1738 { 1739 char size_suffix[4] = {0}; 1740 const char *sign_suffix; 1741 /* Memop width is specified in the load macro */ 1742 assert_signedness(c, locp, signedness); 1743 sign_suffix = (width->imm.value > 4) 1744 ? "" 1745 : ((signedness == UNSIGNED) ? "u" : "s"); 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 snprintf(size_suffix, 4, "%" PRIu64, width->imm.value * 8); 1752 /* Lookup the effective address EA */ 1753 find_variable(c, locp, ea, ea); 1754 OUT(c, locp, "if (insn->slot == 0 && pkt->pkt_has_store_s1) {\n"); 1755 OUT(c, locp, "probe_noshuf_load(", ea, ", ", width, ", ctx->mem_idx);\n"); 1756 OUT(c, locp, "process_store(ctx, 1);\n"); 1757 OUT(c, locp, "}\n"); 1758 OUT(c, locp, "tcg_gen_qemu_ld", size_suffix, sign_suffix); 1759 OUT(c, locp, "("); 1760 if (dst->bit_width > width->imm.value * 8) { 1761 /* 1762 * Cast to the correct TCG type if necessary, to avoid implict cast 1763 * warnings. This is needed when the width of the destination var is 1764 * larger than the size of the requested load. 1765 */ 1766 OUT(c, locp, "(TCGv) "); 1767 } 1768 OUT(c, locp, dst, ", ", ea, ", ctx->mem_idx);\n"); 1769 } 1770 1771 void gen_store(Context *c, YYLTYPE *locp, HexValue *width, HexValue *ea, 1772 HexValue *src) 1773 { 1774 HexValue src_m = *src; 1775 /* Memop width is specified in the store macro */ 1776 unsigned mem_width = width->imm.value; 1777 /* Lookup the effective address EA */ 1778 find_variable(c, locp, ea, ea); 1779 src_m = rvalue_materialize(c, locp, &src_m); 1780 OUT(c, locp, "gen_store", &mem_width, "(cpu_env, ", ea, ", ", &src_m); 1781 OUT(c, locp, ", insn->slot);\n"); 1782 } 1783 1784 void gen_sethalf(Context *c, YYLTYPE *locp, HexCast *sh, HexValue *n, 1785 HexValue *dst, HexValue *value) 1786 { 1787 yyassert(c, locp, n->type == IMMEDIATE, 1788 "Deposit index must be immediate!\n"); 1789 if (dst->type == VARID) { 1790 find_variable(c, locp, dst, dst); 1791 } 1792 1793 gen_deposit_op(c, locp, dst, value, n, sh); 1794 } 1795 1796 void gen_setbits(Context *c, YYLTYPE *locp, HexValue *hi, HexValue *lo, 1797 HexValue *dst, HexValue *value) 1798 { 1799 unsigned len; 1800 HexValue tmp; 1801 1802 yyassert(c, locp, hi->type == IMMEDIATE && 1803 hi->imm.type == VALUE && 1804 lo->type == IMMEDIATE && 1805 lo->imm.type == VALUE, 1806 "Range deposit needs immediate values!\n"); 1807 1808 *value = gen_rvalue_truncate(c, locp, value); 1809 len = hi->imm.value + 1 - lo->imm.value; 1810 tmp = gen_tmp(c, locp, 32, value->signedness); 1811 /* Emit an `and` to ensure `value` is either 0 or 1. */ 1812 OUT(c, locp, "tcg_gen_andi_i32(", &tmp, ", ", value, ", 1);\n"); 1813 /* Use `neg` to map 0 -> 0 and 1 -> 0xffff... */ 1814 OUT(c, locp, "tcg_gen_neg_i32(", &tmp, ", ", &tmp, ");\n"); 1815 OUT(c, locp, "tcg_gen_deposit_i32(", dst, ", ", dst, 1816 ", ", &tmp, ", "); 1817 OUT(c, locp, lo, ", ", &len, ");\n"); 1818 } 1819 1820 unsigned gen_if_cond(Context *c, YYLTYPE *locp, HexValue *cond) 1821 { 1822 const char *bit_suffix; 1823 /* Generate an end label, if false branch to that label */ 1824 OUT(c, locp, "TCGLabel *if_label_", &c->inst.if_count, 1825 " = gen_new_label();\n"); 1826 *cond = rvalue_materialize(c, locp, cond); 1827 bit_suffix = (cond->bit_width == 64) ? "i64" : "i32"; 1828 OUT(c, locp, "tcg_gen_brcondi_", bit_suffix, "(TCG_COND_EQ, ", cond, 1829 ", 0, if_label_", &c->inst.if_count, ");\n"); 1830 return c->inst.if_count++; 1831 } 1832 1833 unsigned gen_if_else(Context *c, YYLTYPE *locp, unsigned index) 1834 { 1835 unsigned if_index = c->inst.if_count++; 1836 /* Generate label to jump if else is not verified */ 1837 OUT(c, locp, "TCGLabel *if_label_", &if_index, 1838 " = gen_new_label();\n"); 1839 /* Jump out of the else statement */ 1840 OUT(c, locp, "tcg_gen_br(if_label_", &if_index, ");\n"); 1841 /* Fix the else label */ 1842 OUT(c, locp, "gen_set_label(if_label_", &index, ");\n"); 1843 return if_index; 1844 } 1845 1846 HexValue gen_rvalue_pred(Context *c, YYLTYPE *locp, HexValue *pred) 1847 { 1848 /* Predicted instructions need to zero out result args */ 1849 gen_inst_init_args(c, locp); 1850 1851 if (is_direct_predicate(pred)) { 1852 bool is_dotnew = pred->is_dotnew; 1853 char predicate_id[2] = { pred->pred.id, '\0' }; 1854 char *pred_str = (char *) &predicate_id; 1855 *pred = gen_tmp(c, locp, 32, UNSIGNED); 1856 if (is_dotnew) { 1857 OUT(c, locp, "tcg_gen_mov_i32(", pred, 1858 ", hex_new_pred_value["); 1859 OUT(c, locp, pred_str, "]);\n"); 1860 } else { 1861 OUT(c, locp, "gen_read_preg(", pred, ", ", pred_str, ");\n"); 1862 } 1863 } 1864 1865 return *pred; 1866 } 1867 1868 HexValue gen_rvalue_var(Context *c, YYLTYPE *locp, HexValue *var) 1869 { 1870 find_variable(c, locp, var, var); 1871 return *var; 1872 } 1873 1874 HexValue gen_rvalue_mpy(Context *c, YYLTYPE *locp, HexMpy *mpy, 1875 HexValue *op1, HexValue *op2) 1876 { 1877 HexValue res; 1878 memset(&res, 0, sizeof(HexValue)); 1879 1880 assert_signedness(c, locp, mpy->first_signedness); 1881 assert_signedness(c, locp, mpy->second_signedness); 1882 1883 *op1 = gen_cast_op(c, locp, op1, mpy->first_bit_width * 2, 1884 mpy->first_signedness); 1885 /* Handle fMPTY3216.. */ 1886 if (mpy->first_bit_width == 32) { 1887 *op2 = gen_cast_op(c, locp, op2, 64, mpy->second_signedness); 1888 } else { 1889 *op2 = gen_cast_op(c, locp, op2, mpy->second_bit_width * 2, 1890 mpy->second_signedness); 1891 } 1892 res = gen_bin_op(c, locp, MUL_OP, op1, op2); 1893 /* Handle special cases required by the language */ 1894 if (mpy->first_bit_width == 16 && mpy->second_bit_width == 16) { 1895 HexValue src_width = gen_imm_value(c, locp, 32, 32, UNSIGNED); 1896 HexSignedness signedness = bin_op_signedness(c, locp, 1897 mpy->first_signedness, 1898 mpy->second_signedness); 1899 res = gen_extend_op(c, locp, &src_width, 64, &res, 1900 signedness); 1901 } 1902 return res; 1903 } 1904 1905 static inline HexValue gen_rvalue_simple_unary(Context *c, YYLTYPE *locp, 1906 HexValue *value, 1907 const char *c_code, 1908 const char *tcg_code) 1909 { 1910 unsigned bit_width = (value->bit_width == 64) ? 64 : 32; 1911 HexValue res; 1912 if (value->type == IMMEDIATE) { 1913 res = gen_imm_qemu_tmp(c, locp, bit_width, value->signedness); 1914 gen_c_int_type(c, locp, value->bit_width, value->signedness); 1915 OUT(c, locp, " ", &res, " = ", c_code, "(", value, ");\n"); 1916 } else { 1917 res = gen_tmp(c, locp, bit_width, value->signedness); 1918 OUT(c, locp, tcg_code, "_i", &bit_width, "(", &res, ", ", value, 1919 ");\n"); 1920 } 1921 return res; 1922 } 1923 1924 1925 HexValue gen_rvalue_not(Context *c, YYLTYPE *locp, HexValue *value) 1926 { 1927 return gen_rvalue_simple_unary(c, locp, value, "~", "tcg_gen_not"); 1928 } 1929 1930 HexValue gen_rvalue_notl(Context *c, YYLTYPE *locp, HexValue *value) 1931 { 1932 unsigned bit_width = (value->bit_width == 64) ? 64 : 32; 1933 HexValue res; 1934 if (value->type == IMMEDIATE) { 1935 res = gen_imm_qemu_tmp(c, locp, bit_width, value->signedness); 1936 gen_c_int_type(c, locp, value->bit_width, value->signedness); 1937 OUT(c, locp, " ", &res, " = !(", value, ");\n"); 1938 } else { 1939 HexValue zero = gen_constant(c, locp, "0", bit_width, UNSIGNED); 1940 HexValue one = gen_constant(c, locp, "0xff", bit_width, UNSIGNED); 1941 res = gen_tmp(c, locp, bit_width, value->signedness); 1942 OUT(c, locp, "tcg_gen_movcond_i", &bit_width); 1943 OUT(c, locp, "(TCG_COND_EQ, ", &res, ", ", value, ", ", &zero); 1944 OUT(c, locp, ", ", &one, ", ", &zero, ");\n"); 1945 } 1946 return res; 1947 } 1948 1949 HexValue gen_rvalue_sat(Context *c, YYLTYPE *locp, HexSat *sat, 1950 HexValue *width, HexValue *value) 1951 { 1952 const char *unsigned_str; 1953 const char *bit_suffix = (value->bit_width == 64) ? "i64" : "i32"; 1954 HexValue res; 1955 HexValue ovfl; 1956 /* 1957 * Note: all saturates are assumed to implicitly set overflow. 1958 * This assumption holds for the instructions currently parsed 1959 * by idef-parser. 1960 */ 1961 yyassert(c, locp, width->imm.value < value->bit_width, 1962 "To compute overflow, source width must be greater than" 1963 " saturation width!"); 1964 yyassert(c, locp, !is_inside_ternary(c), 1965 "Saturating from within a ternary is not allowed!"); 1966 assert_signedness(c, locp, sat->signedness); 1967 1968 unsigned_str = (sat->signedness == UNSIGNED) ? "u" : ""; 1969 res = gen_tmp(c, locp, value->bit_width, sat->signedness); 1970 ovfl = gen_tmp(c, locp, 32, sat->signedness); 1971 OUT(c, locp, "gen_sat", unsigned_str, "_", bit_suffix, "_ovfl("); 1972 OUT(c, locp, &ovfl, ", ", &res, ", ", value, ", ", &width->imm.value, 1973 ");\n"); 1974 OUT(c, locp, "gen_set_usr_field_if(USR_OVF,", &ovfl, ");\n"); 1975 1976 return res; 1977 } 1978 1979 HexValue gen_rvalue_fscr(Context *c, YYLTYPE *locp, HexValue *value) 1980 { 1981 HexValue key = gen_tmp(c, locp, 64, UNSIGNED); 1982 HexValue res = gen_tmp(c, locp, 64, UNSIGNED); 1983 HexValue frame_key = gen_tmp(c, locp, 32, UNSIGNED); 1984 *value = gen_rvalue_extend(c, locp, value); 1985 OUT(c, locp, "gen_read_reg(", &frame_key, ", HEX_REG_FRAMEKEY);\n"); 1986 OUT(c, locp, "tcg_gen_concat_i32_i64(", 1987 &key, ", ", &frame_key, ", ", &frame_key, ");\n"); 1988 OUT(c, locp, "tcg_gen_xor_i64(", &res, ", ", value, ", ", &key, ");\n"); 1989 return res; 1990 } 1991 1992 HexValue gen_rvalue_abs(Context *c, YYLTYPE *locp, HexValue *value) 1993 { 1994 return gen_rvalue_simple_unary(c, locp, value, "abs", "tcg_gen_abs"); 1995 } 1996 1997 HexValue gen_rvalue_neg(Context *c, YYLTYPE *locp, HexValue *value) 1998 { 1999 return gen_rvalue_simple_unary(c, locp, value, "-", "tcg_gen_neg"); 2000 } 2001 2002 HexValue gen_rvalue_brev(Context *c, YYLTYPE *locp, HexValue *value) 2003 { 2004 HexValue res; 2005 yyassert(c, locp, value->bit_width <= 32, 2006 "fbrev not implemented for 64-bit integers!"); 2007 res = gen_tmp(c, locp, value->bit_width, value->signedness); 2008 *value = rvalue_materialize(c, locp, value); 2009 OUT(c, locp, "gen_helper_fbrev(", &res, ", ", value, ");\n"); 2010 return res; 2011 } 2012 2013 HexValue gen_rvalue_ternary(Context *c, YYLTYPE *locp, HexValue *cond, 2014 HexValue *true_branch, HexValue *false_branch) 2015 { 2016 bool is_64bit = (true_branch->bit_width == 64) || 2017 (false_branch->bit_width == 64); 2018 unsigned bit_width = (is_64bit) ? 64 : 32; 2019 HexValue zero = gen_constant(c, locp, "0", bit_width, UNSIGNED); 2020 HexValue res = gen_tmp(c, locp, bit_width, UNSIGNED); 2021 2022 if (is_64bit) { 2023 *cond = gen_rvalue_extend(c, locp, cond); 2024 *true_branch = gen_rvalue_extend(c, locp, true_branch); 2025 *false_branch = gen_rvalue_extend(c, locp, false_branch); 2026 } else { 2027 *cond = gen_rvalue_truncate(c, locp, cond); 2028 } 2029 *cond = rvalue_materialize(c, locp, cond); 2030 *true_branch = rvalue_materialize(c, locp, true_branch); 2031 *false_branch = rvalue_materialize(c, locp, false_branch); 2032 2033 OUT(c, locp, "tcg_gen_movcond_i", &bit_width); 2034 OUT(c, locp, "(TCG_COND_NE, ", &res, ", ", cond, ", ", &zero); 2035 OUT(c, locp, ", ", true_branch, ", ", false_branch, ");\n"); 2036 2037 assert(c->ternary->len > 0); 2038 g_array_remove_index(c->ternary, c->ternary->len - 1); 2039 2040 return res; 2041 } 2042 2043 const char *cond_to_str(TCGCond cond) 2044 { 2045 switch (cond) { 2046 case TCG_COND_NEVER: 2047 return "TCG_COND_NEVER"; 2048 case TCG_COND_ALWAYS: 2049 return "TCG_COND_ALWAYS"; 2050 case TCG_COND_EQ: 2051 return "TCG_COND_EQ"; 2052 case TCG_COND_NE: 2053 return "TCG_COND_NE"; 2054 case TCG_COND_LT: 2055 return "TCG_COND_LT"; 2056 case TCG_COND_GE: 2057 return "TCG_COND_GE"; 2058 case TCG_COND_LE: 2059 return "TCG_COND_LE"; 2060 case TCG_COND_GT: 2061 return "TCG_COND_GT"; 2062 case TCG_COND_LTU: 2063 return "TCG_COND_LTU"; 2064 case TCG_COND_GEU: 2065 return "TCG_COND_GEU"; 2066 case TCG_COND_LEU: 2067 return "TCG_COND_LEU"; 2068 case TCG_COND_GTU: 2069 return "TCG_COND_GTU"; 2070 default: 2071 abort(); 2072 } 2073 } 2074 2075 void emit_arg(Context *c, YYLTYPE *locp, HexValue *arg) 2076 { 2077 switch (arg->type) { 2078 case REGISTER_ARG: 2079 if (arg->reg.type == DOTNEW) { 2080 EMIT_SIG(c, ", TCGv N%cN", arg->reg.id); 2081 } else { 2082 bool is64 = (arg->bit_width == 64); 2083 const char *type = is64 ? "TCGv_i64" : "TCGv_i32"; 2084 char reg_id[5]; 2085 reg_compose(c, locp, &(arg->reg), reg_id); 2086 EMIT_SIG(c, ", %s %s", type, reg_id); 2087 /* MuV register requires also MuN to provide its index */ 2088 if (arg->reg.type == MODIFIER) { 2089 EMIT_SIG(c, ", int MuN"); 2090 } 2091 } 2092 break; 2093 case PREDICATE: 2094 { 2095 char suffix = arg->is_dotnew ? 'N' : 'V'; 2096 EMIT_SIG(c, ", TCGv P%c%c", arg->pred.id, suffix); 2097 } 2098 break; 2099 default: 2100 { 2101 fprintf(stderr, "emit_arg got unsupported argument!"); 2102 abort(); 2103 } 2104 } 2105 } 2106 2107 void emit_footer(Context *c) 2108 { 2109 EMIT(c, "}\n"); 2110 EMIT(c, "\n"); 2111 } 2112 2113 void track_string(Context *c, GString *s) 2114 { 2115 g_array_append_val(c->inst.strings, s); 2116 } 2117 2118 void free_instruction(Context *c) 2119 { 2120 assert(!is_inside_ternary(c)); 2121 /* Free the strings */ 2122 g_string_truncate(c->signature_str, 0); 2123 g_string_truncate(c->out_str, 0); 2124 g_string_truncate(c->header_str, 0); 2125 /* Free strings allocated by the instruction */ 2126 for (unsigned i = 0; i < c->inst.strings->len; i++) { 2127 g_string_free(g_array_index(c->inst.strings, GString*, i), TRUE); 2128 } 2129 g_array_free(c->inst.strings, TRUE); 2130 /* Free INAME token value */ 2131 g_string_free(c->inst.name, TRUE); 2132 /* Free variables and registers */ 2133 g_array_free(c->inst.allocated, TRUE); 2134 /* Initialize instruction-specific portion of the context */ 2135 memset(&(c->inst), 0, sizeof(Inst)); 2136 } 2137 2138 void assert_signedness(Context *c, 2139 YYLTYPE *locp, 2140 HexSignedness signedness) 2141 { 2142 yyassert(c, locp, 2143 signedness != UNKNOWN_SIGNEDNESS, 2144 "Unspecified signedness"); 2145 } 2146