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