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