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