1 /* 2 * Tiny Code Generator for QEMU 3 * 4 * Copyright (c) 2008 Fabrice Bellard 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and associated documentation files (the "Software"), to deal 8 * in the Software without restriction, including without limitation the rights 9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 * copies of the Software, and to permit persons to whom the Software is 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 * THE SOFTWARE. 23 */ 24 25 /* define it to use liveness analysis (better code) */ 26 #define USE_LIVENESS_ANALYSIS 27 #define USE_TCG_OPTIMIZATIONS 28 29 #include "config.h" 30 31 #if !defined(CONFIG_DEBUG_TCG) && !defined(NDEBUG) 32 /* define it to suppress various consistency checks (faster) */ 33 #define NDEBUG 34 #endif 35 36 #include "qemu-common.h" 37 #include "cache-utils.h" 38 #include "host-utils.h" 39 #include "qemu-timer.h" 40 41 /* Note: the long term plan is to reduce the dependancies on the QEMU 42 CPU definitions. Currently they are used for qemu_ld/st 43 instructions */ 44 #define NO_CPU_IO_DEFS 45 #include "cpu.h" 46 47 #include "tcg-op.h" 48 #include "elf.h" 49 50 #if defined(CONFIG_USE_GUEST_BASE) && !defined(TCG_TARGET_HAS_GUEST_BASE) 51 #error GUEST_BASE not supported on this host. 52 #endif 53 54 /* Forward declarations for functions declared in tcg-target.c and used here. */ 55 static void tcg_target_init(TCGContext *s); 56 static void tcg_target_qemu_prologue(TCGContext *s); 57 static void patch_reloc(uint8_t *code_ptr, int type, 58 tcg_target_long value, tcg_target_long addend); 59 60 /* Forward declarations for functions declared and used in tcg-target.c. */ 61 static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str); 62 static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg1, 63 tcg_target_long arg2); 64 static void tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg); 65 static void tcg_out_movi(TCGContext *s, TCGType type, 66 TCGReg ret, tcg_target_long arg); 67 static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args, 68 const int *const_args); 69 static void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, TCGReg arg1, 70 tcg_target_long arg2); 71 static int tcg_target_const_match(tcg_target_long val, 72 const TCGArgConstraint *arg_ct); 73 static int tcg_target_get_call_iarg_regs_count(int flags); 74 75 TCGOpDef tcg_op_defs[] = { 76 #define DEF(s, oargs, iargs, cargs, flags) { #s, oargs, iargs, cargs, iargs + oargs + cargs, flags }, 77 #include "tcg-opc.h" 78 #undef DEF 79 }; 80 const size_t tcg_op_defs_max = ARRAY_SIZE(tcg_op_defs); 81 82 static TCGRegSet tcg_target_available_regs[2]; 83 static TCGRegSet tcg_target_call_clobber_regs; 84 85 /* XXX: move that inside the context */ 86 uint16_t *gen_opc_ptr; 87 TCGArg *gen_opparam_ptr; 88 89 static inline void tcg_out8(TCGContext *s, uint8_t v) 90 { 91 *s->code_ptr++ = v; 92 } 93 94 static inline void tcg_out16(TCGContext *s, uint16_t v) 95 { 96 *(uint16_t *)s->code_ptr = v; 97 s->code_ptr += 2; 98 } 99 100 static inline void tcg_out32(TCGContext *s, uint32_t v) 101 { 102 *(uint32_t *)s->code_ptr = v; 103 s->code_ptr += 4; 104 } 105 106 /* label relocation processing */ 107 108 static void tcg_out_reloc(TCGContext *s, uint8_t *code_ptr, int type, 109 int label_index, long addend) 110 { 111 TCGLabel *l; 112 TCGRelocation *r; 113 114 l = &s->labels[label_index]; 115 if (l->has_value) { 116 /* FIXME: This may break relocations on RISC targets that 117 modify instruction fields in place. The caller may not have 118 written the initial value. */ 119 patch_reloc(code_ptr, type, l->u.value, addend); 120 } else { 121 /* add a new relocation entry */ 122 r = tcg_malloc(sizeof(TCGRelocation)); 123 r->type = type; 124 r->ptr = code_ptr; 125 r->addend = addend; 126 r->next = l->u.first_reloc; 127 l->u.first_reloc = r; 128 } 129 } 130 131 static void tcg_out_label(TCGContext *s, int label_index, void *ptr) 132 { 133 TCGLabel *l; 134 TCGRelocation *r; 135 tcg_target_long value = (tcg_target_long)ptr; 136 137 l = &s->labels[label_index]; 138 if (l->has_value) 139 tcg_abort(); 140 r = l->u.first_reloc; 141 while (r != NULL) { 142 patch_reloc(r->ptr, r->type, value, r->addend); 143 r = r->next; 144 } 145 l->has_value = 1; 146 l->u.value = value; 147 } 148 149 int gen_new_label(void) 150 { 151 TCGContext *s = &tcg_ctx; 152 int idx; 153 TCGLabel *l; 154 155 if (s->nb_labels >= TCG_MAX_LABELS) 156 tcg_abort(); 157 idx = s->nb_labels++; 158 l = &s->labels[idx]; 159 l->has_value = 0; 160 l->u.first_reloc = NULL; 161 return idx; 162 } 163 164 #include "tcg-target.c" 165 166 /* pool based memory allocation */ 167 void *tcg_malloc_internal(TCGContext *s, int size) 168 { 169 TCGPool *p; 170 int pool_size; 171 172 if (size > TCG_POOL_CHUNK_SIZE) { 173 /* big malloc: insert a new pool (XXX: could optimize) */ 174 p = g_malloc(sizeof(TCGPool) + size); 175 p->size = size; 176 if (s->pool_current) 177 s->pool_current->next = p; 178 else 179 s->pool_first = p; 180 p->next = s->pool_current; 181 } else { 182 p = s->pool_current; 183 if (!p) { 184 p = s->pool_first; 185 if (!p) 186 goto new_pool; 187 } else { 188 if (!p->next) { 189 new_pool: 190 pool_size = TCG_POOL_CHUNK_SIZE; 191 p = g_malloc(sizeof(TCGPool) + pool_size); 192 p->size = pool_size; 193 p->next = NULL; 194 if (s->pool_current) 195 s->pool_current->next = p; 196 else 197 s->pool_first = p; 198 } else { 199 p = p->next; 200 } 201 } 202 } 203 s->pool_current = p; 204 s->pool_cur = p->data + size; 205 s->pool_end = p->data + p->size; 206 return p->data; 207 } 208 209 void tcg_pool_reset(TCGContext *s) 210 { 211 s->pool_cur = s->pool_end = NULL; 212 s->pool_current = NULL; 213 } 214 215 void tcg_context_init(TCGContext *s) 216 { 217 int op, total_args, n; 218 TCGOpDef *def; 219 TCGArgConstraint *args_ct; 220 int *sorted_args; 221 222 memset(s, 0, sizeof(*s)); 223 s->temps = s->static_temps; 224 s->nb_globals = 0; 225 226 /* Count total number of arguments and allocate the corresponding 227 space */ 228 total_args = 0; 229 for(op = 0; op < NB_OPS; op++) { 230 def = &tcg_op_defs[op]; 231 n = def->nb_iargs + def->nb_oargs; 232 total_args += n; 233 } 234 235 args_ct = g_malloc(sizeof(TCGArgConstraint) * total_args); 236 sorted_args = g_malloc(sizeof(int) * total_args); 237 238 for(op = 0; op < NB_OPS; op++) { 239 def = &tcg_op_defs[op]; 240 def->args_ct = args_ct; 241 def->sorted_args = sorted_args; 242 n = def->nb_iargs + def->nb_oargs; 243 sorted_args += n; 244 args_ct += n; 245 } 246 247 tcg_target_init(s); 248 } 249 250 void tcg_prologue_init(TCGContext *s) 251 { 252 /* init global prologue and epilogue */ 253 s->code_buf = code_gen_prologue; 254 s->code_ptr = s->code_buf; 255 tcg_target_qemu_prologue(s); 256 flush_icache_range((tcg_target_ulong)s->code_buf, 257 (tcg_target_ulong)s->code_ptr); 258 } 259 260 void tcg_set_frame(TCGContext *s, int reg, 261 tcg_target_long start, tcg_target_long size) 262 { 263 s->frame_start = start; 264 s->frame_end = start + size; 265 s->frame_reg = reg; 266 } 267 268 void tcg_func_start(TCGContext *s) 269 { 270 int i; 271 tcg_pool_reset(s); 272 s->nb_temps = s->nb_globals; 273 for(i = 0; i < (TCG_TYPE_COUNT * 2); i++) 274 s->first_free_temp[i] = -1; 275 s->labels = tcg_malloc(sizeof(TCGLabel) * TCG_MAX_LABELS); 276 s->nb_labels = 0; 277 s->current_frame_offset = s->frame_start; 278 279 gen_opc_ptr = gen_opc_buf; 280 gen_opparam_ptr = gen_opparam_buf; 281 } 282 283 static inline void tcg_temp_alloc(TCGContext *s, int n) 284 { 285 if (n > TCG_MAX_TEMPS) 286 tcg_abort(); 287 } 288 289 static inline int tcg_global_reg_new_internal(TCGType type, int reg, 290 const char *name) 291 { 292 TCGContext *s = &tcg_ctx; 293 TCGTemp *ts; 294 int idx; 295 296 #if TCG_TARGET_REG_BITS == 32 297 if (type != TCG_TYPE_I32) 298 tcg_abort(); 299 #endif 300 if (tcg_regset_test_reg(s->reserved_regs, reg)) 301 tcg_abort(); 302 idx = s->nb_globals; 303 tcg_temp_alloc(s, s->nb_globals + 1); 304 ts = &s->temps[s->nb_globals]; 305 ts->base_type = type; 306 ts->type = type; 307 ts->fixed_reg = 1; 308 ts->reg = reg; 309 ts->name = name; 310 s->nb_globals++; 311 tcg_regset_set_reg(s->reserved_regs, reg); 312 return idx; 313 } 314 315 TCGv_i32 tcg_global_reg_new_i32(int reg, const char *name) 316 { 317 int idx; 318 319 idx = tcg_global_reg_new_internal(TCG_TYPE_I32, reg, name); 320 return MAKE_TCGV_I32(idx); 321 } 322 323 TCGv_i64 tcg_global_reg_new_i64(int reg, const char *name) 324 { 325 int idx; 326 327 idx = tcg_global_reg_new_internal(TCG_TYPE_I64, reg, name); 328 return MAKE_TCGV_I64(idx); 329 } 330 331 static inline int tcg_global_mem_new_internal(TCGType type, int reg, 332 tcg_target_long offset, 333 const char *name) 334 { 335 TCGContext *s = &tcg_ctx; 336 TCGTemp *ts; 337 int idx; 338 339 idx = s->nb_globals; 340 #if TCG_TARGET_REG_BITS == 32 341 if (type == TCG_TYPE_I64) { 342 char buf[64]; 343 tcg_temp_alloc(s, s->nb_globals + 2); 344 ts = &s->temps[s->nb_globals]; 345 ts->base_type = type; 346 ts->type = TCG_TYPE_I32; 347 ts->fixed_reg = 0; 348 ts->mem_allocated = 1; 349 ts->mem_reg = reg; 350 #ifdef TCG_TARGET_WORDS_BIGENDIAN 351 ts->mem_offset = offset + 4; 352 #else 353 ts->mem_offset = offset; 354 #endif 355 pstrcpy(buf, sizeof(buf), name); 356 pstrcat(buf, sizeof(buf), "_0"); 357 ts->name = strdup(buf); 358 ts++; 359 360 ts->base_type = type; 361 ts->type = TCG_TYPE_I32; 362 ts->fixed_reg = 0; 363 ts->mem_allocated = 1; 364 ts->mem_reg = reg; 365 #ifdef TCG_TARGET_WORDS_BIGENDIAN 366 ts->mem_offset = offset; 367 #else 368 ts->mem_offset = offset + 4; 369 #endif 370 pstrcpy(buf, sizeof(buf), name); 371 pstrcat(buf, sizeof(buf), "_1"); 372 ts->name = strdup(buf); 373 374 s->nb_globals += 2; 375 } else 376 #endif 377 { 378 tcg_temp_alloc(s, s->nb_globals + 1); 379 ts = &s->temps[s->nb_globals]; 380 ts->base_type = type; 381 ts->type = type; 382 ts->fixed_reg = 0; 383 ts->mem_allocated = 1; 384 ts->mem_reg = reg; 385 ts->mem_offset = offset; 386 ts->name = name; 387 s->nb_globals++; 388 } 389 return idx; 390 } 391 392 TCGv_i32 tcg_global_mem_new_i32(int reg, tcg_target_long offset, 393 const char *name) 394 { 395 int idx; 396 397 idx = tcg_global_mem_new_internal(TCG_TYPE_I32, reg, offset, name); 398 return MAKE_TCGV_I32(idx); 399 } 400 401 TCGv_i64 tcg_global_mem_new_i64(int reg, tcg_target_long offset, 402 const char *name) 403 { 404 int idx; 405 406 idx = tcg_global_mem_new_internal(TCG_TYPE_I64, reg, offset, name); 407 return MAKE_TCGV_I64(idx); 408 } 409 410 static inline int tcg_temp_new_internal(TCGType type, int temp_local) 411 { 412 TCGContext *s = &tcg_ctx; 413 TCGTemp *ts; 414 int idx, k; 415 416 k = type; 417 if (temp_local) 418 k += TCG_TYPE_COUNT; 419 idx = s->first_free_temp[k]; 420 if (idx != -1) { 421 /* There is already an available temp with the 422 right type */ 423 ts = &s->temps[idx]; 424 s->first_free_temp[k] = ts->next_free_temp; 425 ts->temp_allocated = 1; 426 assert(ts->temp_local == temp_local); 427 } else { 428 idx = s->nb_temps; 429 #if TCG_TARGET_REG_BITS == 32 430 if (type == TCG_TYPE_I64) { 431 tcg_temp_alloc(s, s->nb_temps + 2); 432 ts = &s->temps[s->nb_temps]; 433 ts->base_type = type; 434 ts->type = TCG_TYPE_I32; 435 ts->temp_allocated = 1; 436 ts->temp_local = temp_local; 437 ts->name = NULL; 438 ts++; 439 ts->base_type = TCG_TYPE_I32; 440 ts->type = TCG_TYPE_I32; 441 ts->temp_allocated = 1; 442 ts->temp_local = temp_local; 443 ts->name = NULL; 444 s->nb_temps += 2; 445 } else 446 #endif 447 { 448 tcg_temp_alloc(s, s->nb_temps + 1); 449 ts = &s->temps[s->nb_temps]; 450 ts->base_type = type; 451 ts->type = type; 452 ts->temp_allocated = 1; 453 ts->temp_local = temp_local; 454 ts->name = NULL; 455 s->nb_temps++; 456 } 457 } 458 459 #if defined(CONFIG_DEBUG_TCG) 460 s->temps_in_use++; 461 #endif 462 return idx; 463 } 464 465 TCGv_i32 tcg_temp_new_internal_i32(int temp_local) 466 { 467 int idx; 468 469 idx = tcg_temp_new_internal(TCG_TYPE_I32, temp_local); 470 return MAKE_TCGV_I32(idx); 471 } 472 473 TCGv_i64 tcg_temp_new_internal_i64(int temp_local) 474 { 475 int idx; 476 477 idx = tcg_temp_new_internal(TCG_TYPE_I64, temp_local); 478 return MAKE_TCGV_I64(idx); 479 } 480 481 static inline void tcg_temp_free_internal(int idx) 482 { 483 TCGContext *s = &tcg_ctx; 484 TCGTemp *ts; 485 int k; 486 487 #if defined(CONFIG_DEBUG_TCG) 488 s->temps_in_use--; 489 if (s->temps_in_use < 0) { 490 fprintf(stderr, "More temporaries freed than allocated!\n"); 491 } 492 #endif 493 494 assert(idx >= s->nb_globals && idx < s->nb_temps); 495 ts = &s->temps[idx]; 496 assert(ts->temp_allocated != 0); 497 ts->temp_allocated = 0; 498 k = ts->base_type; 499 if (ts->temp_local) 500 k += TCG_TYPE_COUNT; 501 ts->next_free_temp = s->first_free_temp[k]; 502 s->first_free_temp[k] = idx; 503 } 504 505 void tcg_temp_free_i32(TCGv_i32 arg) 506 { 507 tcg_temp_free_internal(GET_TCGV_I32(arg)); 508 } 509 510 void tcg_temp_free_i64(TCGv_i64 arg) 511 { 512 tcg_temp_free_internal(GET_TCGV_I64(arg)); 513 } 514 515 TCGv_i32 tcg_const_i32(int32_t val) 516 { 517 TCGv_i32 t0; 518 t0 = tcg_temp_new_i32(); 519 tcg_gen_movi_i32(t0, val); 520 return t0; 521 } 522 523 TCGv_i64 tcg_const_i64(int64_t val) 524 { 525 TCGv_i64 t0; 526 t0 = tcg_temp_new_i64(); 527 tcg_gen_movi_i64(t0, val); 528 return t0; 529 } 530 531 TCGv_i32 tcg_const_local_i32(int32_t val) 532 { 533 TCGv_i32 t0; 534 t0 = tcg_temp_local_new_i32(); 535 tcg_gen_movi_i32(t0, val); 536 return t0; 537 } 538 539 TCGv_i64 tcg_const_local_i64(int64_t val) 540 { 541 TCGv_i64 t0; 542 t0 = tcg_temp_local_new_i64(); 543 tcg_gen_movi_i64(t0, val); 544 return t0; 545 } 546 547 #if defined(CONFIG_DEBUG_TCG) 548 void tcg_clear_temp_count(void) 549 { 550 TCGContext *s = &tcg_ctx; 551 s->temps_in_use = 0; 552 } 553 554 int tcg_check_temp_count(void) 555 { 556 TCGContext *s = &tcg_ctx; 557 if (s->temps_in_use) { 558 /* Clear the count so that we don't give another 559 * warning immediately next time around. 560 */ 561 s->temps_in_use = 0; 562 return 1; 563 } 564 return 0; 565 } 566 #endif 567 568 void tcg_register_helper(void *func, const char *name) 569 { 570 TCGContext *s = &tcg_ctx; 571 int n; 572 if ((s->nb_helpers + 1) > s->allocated_helpers) { 573 n = s->allocated_helpers; 574 if (n == 0) { 575 n = 4; 576 } else { 577 n *= 2; 578 } 579 s->helpers = realloc(s->helpers, n * sizeof(TCGHelperInfo)); 580 s->allocated_helpers = n; 581 } 582 s->helpers[s->nb_helpers].func = (tcg_target_ulong)func; 583 s->helpers[s->nb_helpers].name = name; 584 s->nb_helpers++; 585 } 586 587 /* Note: we convert the 64 bit args to 32 bit and do some alignment 588 and endian swap. Maybe it would be better to do the alignment 589 and endian swap in tcg_reg_alloc_call(). */ 590 void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags, 591 int sizemask, TCGArg ret, int nargs, TCGArg *args) 592 { 593 #if defined(TCG_TARGET_I386) && TCG_TARGET_REG_BITS < 64 594 int call_type; 595 #endif 596 int i; 597 int real_args; 598 int nb_rets; 599 TCGArg *nparam; 600 601 #if defined(TCG_TARGET_EXTEND_ARGS) && TCG_TARGET_REG_BITS == 64 602 for (i = 0; i < nargs; ++i) { 603 int is_64bit = sizemask & (1 << (i+1)*2); 604 int is_signed = sizemask & (2 << (i+1)*2); 605 if (!is_64bit) { 606 TCGv_i64 temp = tcg_temp_new_i64(); 607 TCGv_i64 orig = MAKE_TCGV_I64(args[i]); 608 if (is_signed) { 609 tcg_gen_ext32s_i64(temp, orig); 610 } else { 611 tcg_gen_ext32u_i64(temp, orig); 612 } 613 args[i] = GET_TCGV_I64(temp); 614 } 615 } 616 #endif /* TCG_TARGET_EXTEND_ARGS */ 617 618 *gen_opc_ptr++ = INDEX_op_call; 619 nparam = gen_opparam_ptr++; 620 #if defined(TCG_TARGET_I386) && TCG_TARGET_REG_BITS < 64 621 call_type = (flags & TCG_CALL_TYPE_MASK); 622 #endif 623 if (ret != TCG_CALL_DUMMY_ARG) { 624 #if TCG_TARGET_REG_BITS < 64 625 if (sizemask & 1) { 626 #ifdef TCG_TARGET_WORDS_BIGENDIAN 627 *gen_opparam_ptr++ = ret + 1; 628 *gen_opparam_ptr++ = ret; 629 #else 630 *gen_opparam_ptr++ = ret; 631 *gen_opparam_ptr++ = ret + 1; 632 #endif 633 nb_rets = 2; 634 } else 635 #endif 636 { 637 *gen_opparam_ptr++ = ret; 638 nb_rets = 1; 639 } 640 } else { 641 nb_rets = 0; 642 } 643 real_args = 0; 644 for (i = 0; i < nargs; i++) { 645 #if TCG_TARGET_REG_BITS < 64 646 int is_64bit = sizemask & (1 << (i+1)*2); 647 if (is_64bit) { 648 #ifdef TCG_TARGET_I386 649 /* REGPARM case: if the third parameter is 64 bit, it is 650 allocated on the stack */ 651 if (i == 2 && call_type == TCG_CALL_TYPE_REGPARM) { 652 call_type = TCG_CALL_TYPE_REGPARM_2; 653 flags = (flags & ~TCG_CALL_TYPE_MASK) | call_type; 654 } 655 #endif 656 #ifdef TCG_TARGET_CALL_ALIGN_ARGS 657 /* some targets want aligned 64 bit args */ 658 if (real_args & 1) { 659 *gen_opparam_ptr++ = TCG_CALL_DUMMY_ARG; 660 real_args++; 661 } 662 #endif 663 /* If stack grows up, then we will be placing successive 664 arguments at lower addresses, which means we need to 665 reverse the order compared to how we would normally 666 treat either big or little-endian. For those arguments 667 that will wind up in registers, this still works for 668 HPPA (the only current STACK_GROWSUP target) since the 669 argument registers are *also* allocated in decreasing 670 order. If another such target is added, this logic may 671 have to get more complicated to differentiate between 672 stack arguments and register arguments. */ 673 #if defined(TCG_TARGET_WORDS_BIGENDIAN) != defined(TCG_TARGET_STACK_GROWSUP) 674 *gen_opparam_ptr++ = args[i] + 1; 675 *gen_opparam_ptr++ = args[i]; 676 #else 677 *gen_opparam_ptr++ = args[i]; 678 *gen_opparam_ptr++ = args[i] + 1; 679 #endif 680 real_args += 2; 681 continue; 682 } 683 #endif /* TCG_TARGET_REG_BITS < 64 */ 684 685 *gen_opparam_ptr++ = args[i]; 686 real_args++; 687 } 688 *gen_opparam_ptr++ = GET_TCGV_PTR(func); 689 690 *gen_opparam_ptr++ = flags; 691 692 *nparam = (nb_rets << 16) | (real_args + 1); 693 694 /* total parameters, needed to go backward in the instruction stream */ 695 *gen_opparam_ptr++ = 1 + nb_rets + real_args + 3; 696 697 #if defined(TCG_TARGET_EXTEND_ARGS) && TCG_TARGET_REG_BITS == 64 698 for (i = 0; i < nargs; ++i) { 699 int is_64bit = sizemask & (1 << (i+1)*2); 700 if (!is_64bit) { 701 TCGv_i64 temp = MAKE_TCGV_I64(args[i]); 702 tcg_temp_free_i64(temp); 703 } 704 } 705 #endif /* TCG_TARGET_EXTEND_ARGS */ 706 } 707 708 #if TCG_TARGET_REG_BITS == 32 709 void tcg_gen_shifti_i64(TCGv_i64 ret, TCGv_i64 arg1, 710 int c, int right, int arith) 711 { 712 if (c == 0) { 713 tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg1)); 714 tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1)); 715 } else if (c >= 32) { 716 c -= 32; 717 if (right) { 718 if (arith) { 719 tcg_gen_sari_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c); 720 tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 31); 721 } else { 722 tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c); 723 tcg_gen_movi_i32(TCGV_HIGH(ret), 0); 724 } 725 } else { 726 tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_LOW(arg1), c); 727 tcg_gen_movi_i32(TCGV_LOW(ret), 0); 728 } 729 } else { 730 TCGv_i32 t0, t1; 731 732 t0 = tcg_temp_new_i32(); 733 t1 = tcg_temp_new_i32(); 734 if (right) { 735 tcg_gen_shli_i32(t0, TCGV_HIGH(arg1), 32 - c); 736 if (arith) 737 tcg_gen_sari_i32(t1, TCGV_HIGH(arg1), c); 738 else 739 tcg_gen_shri_i32(t1, TCGV_HIGH(arg1), c); 740 tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_LOW(arg1), c); 741 tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(ret), t0); 742 tcg_gen_mov_i32(TCGV_HIGH(ret), t1); 743 } else { 744 tcg_gen_shri_i32(t0, TCGV_LOW(arg1), 32 - c); 745 /* Note: ret can be the same as arg1, so we use t1 */ 746 tcg_gen_shli_i32(t1, TCGV_LOW(arg1), c); 747 tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c); 748 tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t0); 749 tcg_gen_mov_i32(TCGV_LOW(ret), t1); 750 } 751 tcg_temp_free_i32(t0); 752 tcg_temp_free_i32(t1); 753 } 754 } 755 #endif 756 757 758 static void tcg_reg_alloc_start(TCGContext *s) 759 { 760 int i; 761 TCGTemp *ts; 762 for(i = 0; i < s->nb_globals; i++) { 763 ts = &s->temps[i]; 764 if (ts->fixed_reg) { 765 ts->val_type = TEMP_VAL_REG; 766 } else { 767 ts->val_type = TEMP_VAL_MEM; 768 } 769 } 770 for(i = s->nb_globals; i < s->nb_temps; i++) { 771 ts = &s->temps[i]; 772 ts->val_type = TEMP_VAL_DEAD; 773 ts->mem_allocated = 0; 774 ts->fixed_reg = 0; 775 } 776 for(i = 0; i < TCG_TARGET_NB_REGS; i++) { 777 s->reg_to_temp[i] = -1; 778 } 779 } 780 781 static char *tcg_get_arg_str_idx(TCGContext *s, char *buf, int buf_size, 782 int idx) 783 { 784 TCGTemp *ts; 785 786 assert(idx >= 0 && idx < s->nb_temps); 787 ts = &s->temps[idx]; 788 assert(ts); 789 if (idx < s->nb_globals) { 790 pstrcpy(buf, buf_size, ts->name); 791 } else { 792 if (ts->temp_local) 793 snprintf(buf, buf_size, "loc%d", idx - s->nb_globals); 794 else 795 snprintf(buf, buf_size, "tmp%d", idx - s->nb_globals); 796 } 797 return buf; 798 } 799 800 char *tcg_get_arg_str_i32(TCGContext *s, char *buf, int buf_size, TCGv_i32 arg) 801 { 802 return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I32(arg)); 803 } 804 805 char *tcg_get_arg_str_i64(TCGContext *s, char *buf, int buf_size, TCGv_i64 arg) 806 { 807 return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I64(arg)); 808 } 809 810 static int helper_cmp(const void *p1, const void *p2) 811 { 812 const TCGHelperInfo *th1 = p1; 813 const TCGHelperInfo *th2 = p2; 814 if (th1->func < th2->func) 815 return -1; 816 else if (th1->func == th2->func) 817 return 0; 818 else 819 return 1; 820 } 821 822 /* find helper definition (Note: A hash table would be better) */ 823 static TCGHelperInfo *tcg_find_helper(TCGContext *s, tcg_target_ulong val) 824 { 825 int m, m_min, m_max; 826 TCGHelperInfo *th; 827 tcg_target_ulong v; 828 829 if (unlikely(!s->helpers_sorted)) { 830 qsort(s->helpers, s->nb_helpers, sizeof(TCGHelperInfo), 831 helper_cmp); 832 s->helpers_sorted = 1; 833 } 834 835 /* binary search */ 836 m_min = 0; 837 m_max = s->nb_helpers - 1; 838 while (m_min <= m_max) { 839 m = (m_min + m_max) >> 1; 840 th = &s->helpers[m]; 841 v = th->func; 842 if (v == val) 843 return th; 844 else if (val < v) { 845 m_max = m - 1; 846 } else { 847 m_min = m + 1; 848 } 849 } 850 return NULL; 851 } 852 853 static const char * const cond_name[] = 854 { 855 [TCG_COND_EQ] = "eq", 856 [TCG_COND_NE] = "ne", 857 [TCG_COND_LT] = "lt", 858 [TCG_COND_GE] = "ge", 859 [TCG_COND_LE] = "le", 860 [TCG_COND_GT] = "gt", 861 [TCG_COND_LTU] = "ltu", 862 [TCG_COND_GEU] = "geu", 863 [TCG_COND_LEU] = "leu", 864 [TCG_COND_GTU] = "gtu" 865 }; 866 867 void tcg_dump_ops(TCGContext *s, FILE *outfile) 868 { 869 const uint16_t *opc_ptr; 870 const TCGArg *args; 871 TCGArg arg; 872 TCGOpcode c; 873 int i, k, nb_oargs, nb_iargs, nb_cargs, first_insn; 874 const TCGOpDef *def; 875 char buf[128]; 876 877 first_insn = 1; 878 opc_ptr = gen_opc_buf; 879 args = gen_opparam_buf; 880 while (opc_ptr < gen_opc_ptr) { 881 c = *opc_ptr++; 882 def = &tcg_op_defs[c]; 883 if (c == INDEX_op_debug_insn_start) { 884 uint64_t pc; 885 #if TARGET_LONG_BITS > TCG_TARGET_REG_BITS 886 pc = ((uint64_t)args[1] << 32) | args[0]; 887 #else 888 pc = args[0]; 889 #endif 890 if (!first_insn) 891 fprintf(outfile, "\n"); 892 fprintf(outfile, " ---- 0x%" PRIx64, pc); 893 first_insn = 0; 894 nb_oargs = def->nb_oargs; 895 nb_iargs = def->nb_iargs; 896 nb_cargs = def->nb_cargs; 897 } else if (c == INDEX_op_call) { 898 TCGArg arg; 899 900 /* variable number of arguments */ 901 arg = *args++; 902 nb_oargs = arg >> 16; 903 nb_iargs = arg & 0xffff; 904 nb_cargs = def->nb_cargs; 905 906 fprintf(outfile, " %s ", def->name); 907 908 /* function name */ 909 fprintf(outfile, "%s", 910 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + nb_iargs - 1])); 911 /* flags */ 912 fprintf(outfile, ",$0x%" TCG_PRIlx, 913 args[nb_oargs + nb_iargs]); 914 /* nb out args */ 915 fprintf(outfile, ",$%d", nb_oargs); 916 for(i = 0; i < nb_oargs; i++) { 917 fprintf(outfile, ","); 918 fprintf(outfile, "%s", 919 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[i])); 920 } 921 for(i = 0; i < (nb_iargs - 1); i++) { 922 fprintf(outfile, ","); 923 if (args[nb_oargs + i] == TCG_CALL_DUMMY_ARG) { 924 fprintf(outfile, "<dummy>"); 925 } else { 926 fprintf(outfile, "%s", 927 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + i])); 928 } 929 } 930 } else if (c == INDEX_op_movi_i32 931 #if TCG_TARGET_REG_BITS == 64 932 || c == INDEX_op_movi_i64 933 #endif 934 ) { 935 tcg_target_ulong val; 936 TCGHelperInfo *th; 937 938 nb_oargs = def->nb_oargs; 939 nb_iargs = def->nb_iargs; 940 nb_cargs = def->nb_cargs; 941 fprintf(outfile, " %s %s,$", def->name, 942 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[0])); 943 val = args[1]; 944 th = tcg_find_helper(s, val); 945 if (th) { 946 fprintf(outfile, "%s", th->name); 947 } else { 948 if (c == INDEX_op_movi_i32) 949 fprintf(outfile, "0x%x", (uint32_t)val); 950 else 951 fprintf(outfile, "0x%" PRIx64 , (uint64_t)val); 952 } 953 } else { 954 fprintf(outfile, " %s ", def->name); 955 if (c == INDEX_op_nopn) { 956 /* variable number of arguments */ 957 nb_cargs = *args; 958 nb_oargs = 0; 959 nb_iargs = 0; 960 } else { 961 nb_oargs = def->nb_oargs; 962 nb_iargs = def->nb_iargs; 963 nb_cargs = def->nb_cargs; 964 } 965 966 k = 0; 967 for(i = 0; i < nb_oargs; i++) { 968 if (k != 0) 969 fprintf(outfile, ","); 970 fprintf(outfile, "%s", 971 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++])); 972 } 973 for(i = 0; i < nb_iargs; i++) { 974 if (k != 0) 975 fprintf(outfile, ","); 976 fprintf(outfile, "%s", 977 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++])); 978 } 979 switch (c) { 980 case INDEX_op_brcond_i32: 981 #if TCG_TARGET_REG_BITS == 32 982 case INDEX_op_brcond2_i32: 983 #elif TCG_TARGET_REG_BITS == 64 984 case INDEX_op_brcond_i64: 985 #endif 986 case INDEX_op_setcond_i32: 987 #if TCG_TARGET_REG_BITS == 32 988 case INDEX_op_setcond2_i32: 989 #elif TCG_TARGET_REG_BITS == 64 990 case INDEX_op_setcond_i64: 991 #endif 992 if (args[k] < ARRAY_SIZE(cond_name) && cond_name[args[k]]) 993 fprintf(outfile, ",%s", cond_name[args[k++]]); 994 else 995 fprintf(outfile, ",$0x%" TCG_PRIlx, args[k++]); 996 i = 1; 997 break; 998 default: 999 i = 0; 1000 break; 1001 } 1002 for(; i < nb_cargs; i++) { 1003 if (k != 0) 1004 fprintf(outfile, ","); 1005 arg = args[k++]; 1006 fprintf(outfile, "$0x%" TCG_PRIlx, arg); 1007 } 1008 } 1009 fprintf(outfile, "\n"); 1010 args += nb_iargs + nb_oargs + nb_cargs; 1011 } 1012 } 1013 1014 /* we give more priority to constraints with less registers */ 1015 static int get_constraint_priority(const TCGOpDef *def, int k) 1016 { 1017 const TCGArgConstraint *arg_ct; 1018 1019 int i, n; 1020 arg_ct = &def->args_ct[k]; 1021 if (arg_ct->ct & TCG_CT_ALIAS) { 1022 /* an alias is equivalent to a single register */ 1023 n = 1; 1024 } else { 1025 if (!(arg_ct->ct & TCG_CT_REG)) 1026 return 0; 1027 n = 0; 1028 for(i = 0; i < TCG_TARGET_NB_REGS; i++) { 1029 if (tcg_regset_test_reg(arg_ct->u.regs, i)) 1030 n++; 1031 } 1032 } 1033 return TCG_TARGET_NB_REGS - n + 1; 1034 } 1035 1036 /* sort from highest priority to lowest */ 1037 static void sort_constraints(TCGOpDef *def, int start, int n) 1038 { 1039 int i, j, p1, p2, tmp; 1040 1041 for(i = 0; i < n; i++) 1042 def->sorted_args[start + i] = start + i; 1043 if (n <= 1) 1044 return; 1045 for(i = 0; i < n - 1; i++) { 1046 for(j = i + 1; j < n; j++) { 1047 p1 = get_constraint_priority(def, def->sorted_args[start + i]); 1048 p2 = get_constraint_priority(def, def->sorted_args[start + j]); 1049 if (p1 < p2) { 1050 tmp = def->sorted_args[start + i]; 1051 def->sorted_args[start + i] = def->sorted_args[start + j]; 1052 def->sorted_args[start + j] = tmp; 1053 } 1054 } 1055 } 1056 } 1057 1058 void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs) 1059 { 1060 TCGOpcode op; 1061 TCGOpDef *def; 1062 const char *ct_str; 1063 int i, nb_args; 1064 1065 for(;;) { 1066 if (tdefs->op == (TCGOpcode)-1) 1067 break; 1068 op = tdefs->op; 1069 assert((unsigned)op < NB_OPS); 1070 def = &tcg_op_defs[op]; 1071 #if defined(CONFIG_DEBUG_TCG) 1072 /* Duplicate entry in op definitions? */ 1073 assert(!def->used); 1074 def->used = 1; 1075 #endif 1076 nb_args = def->nb_iargs + def->nb_oargs; 1077 for(i = 0; i < nb_args; i++) { 1078 ct_str = tdefs->args_ct_str[i]; 1079 /* Incomplete TCGTargetOpDef entry? */ 1080 assert(ct_str != NULL); 1081 tcg_regset_clear(def->args_ct[i].u.regs); 1082 def->args_ct[i].ct = 0; 1083 if (ct_str[0] >= '0' && ct_str[0] <= '9') { 1084 int oarg; 1085 oarg = ct_str[0] - '0'; 1086 assert(oarg < def->nb_oargs); 1087 assert(def->args_ct[oarg].ct & TCG_CT_REG); 1088 /* TCG_CT_ALIAS is for the output arguments. The input 1089 argument is tagged with TCG_CT_IALIAS. */ 1090 def->args_ct[i] = def->args_ct[oarg]; 1091 def->args_ct[oarg].ct = TCG_CT_ALIAS; 1092 def->args_ct[oarg].alias_index = i; 1093 def->args_ct[i].ct |= TCG_CT_IALIAS; 1094 def->args_ct[i].alias_index = oarg; 1095 } else { 1096 for(;;) { 1097 if (*ct_str == '\0') 1098 break; 1099 switch(*ct_str) { 1100 case 'i': 1101 def->args_ct[i].ct |= TCG_CT_CONST; 1102 ct_str++; 1103 break; 1104 default: 1105 if (target_parse_constraint(&def->args_ct[i], &ct_str) < 0) { 1106 fprintf(stderr, "Invalid constraint '%s' for arg %d of operation '%s'\n", 1107 ct_str, i, def->name); 1108 exit(1); 1109 } 1110 } 1111 } 1112 } 1113 } 1114 1115 /* TCGTargetOpDef entry with too much information? */ 1116 assert(i == TCG_MAX_OP_ARGS || tdefs->args_ct_str[i] == NULL); 1117 1118 /* sort the constraints (XXX: this is just an heuristic) */ 1119 sort_constraints(def, 0, def->nb_oargs); 1120 sort_constraints(def, def->nb_oargs, def->nb_iargs); 1121 1122 #if 0 1123 { 1124 int i; 1125 1126 printf("%s: sorted=", def->name); 1127 for(i = 0; i < def->nb_oargs + def->nb_iargs; i++) 1128 printf(" %d", def->sorted_args[i]); 1129 printf("\n"); 1130 } 1131 #endif 1132 tdefs++; 1133 } 1134 1135 #if defined(CONFIG_DEBUG_TCG) 1136 i = 0; 1137 for (op = 0; op < ARRAY_SIZE(tcg_op_defs); op++) { 1138 const TCGOpDef *def = &tcg_op_defs[op]; 1139 if (op < INDEX_op_call 1140 || op == INDEX_op_debug_insn_start 1141 || (def->flags & TCG_OPF_NOT_PRESENT)) { 1142 /* Wrong entry in op definitions? */ 1143 if (def->used) { 1144 fprintf(stderr, "Invalid op definition for %s\n", def->name); 1145 i = 1; 1146 } 1147 } else { 1148 /* Missing entry in op definitions? */ 1149 if (!def->used) { 1150 fprintf(stderr, "Missing op definition for %s\n", def->name); 1151 i = 1; 1152 } 1153 } 1154 } 1155 if (i == 1) { 1156 tcg_abort(); 1157 } 1158 #endif 1159 } 1160 1161 #ifdef USE_LIVENESS_ANALYSIS 1162 1163 /* set a nop for an operation using 'nb_args' */ 1164 static inline void tcg_set_nop(TCGContext *s, uint16_t *opc_ptr, 1165 TCGArg *args, int nb_args) 1166 { 1167 if (nb_args == 0) { 1168 *opc_ptr = INDEX_op_nop; 1169 } else { 1170 *opc_ptr = INDEX_op_nopn; 1171 args[0] = nb_args; 1172 args[nb_args - 1] = nb_args; 1173 } 1174 } 1175 1176 /* liveness analysis: end of function: globals are live, temps are 1177 dead. */ 1178 /* XXX: at this stage, not used as there would be little gains because 1179 most TBs end with a conditional jump. */ 1180 static inline void tcg_la_func_end(TCGContext *s, uint8_t *dead_temps) 1181 { 1182 memset(dead_temps, 0, s->nb_globals); 1183 memset(dead_temps + s->nb_globals, 1, s->nb_temps - s->nb_globals); 1184 } 1185 1186 /* liveness analysis: end of basic block: globals are live, temps are 1187 dead, local temps are live. */ 1188 static inline void tcg_la_bb_end(TCGContext *s, uint8_t *dead_temps) 1189 { 1190 int i; 1191 TCGTemp *ts; 1192 1193 memset(dead_temps, 0, s->nb_globals); 1194 ts = &s->temps[s->nb_globals]; 1195 for(i = s->nb_globals; i < s->nb_temps; i++) { 1196 if (ts->temp_local) 1197 dead_temps[i] = 0; 1198 else 1199 dead_temps[i] = 1; 1200 ts++; 1201 } 1202 } 1203 1204 /* Liveness analysis : update the opc_dead_args array to tell if a 1205 given input arguments is dead. Instructions updating dead 1206 temporaries are removed. */ 1207 static void tcg_liveness_analysis(TCGContext *s) 1208 { 1209 int i, op_index, nb_args, nb_iargs, nb_oargs, arg, nb_ops; 1210 TCGOpcode op; 1211 TCGArg *args; 1212 const TCGOpDef *def; 1213 uint8_t *dead_temps; 1214 unsigned int dead_args; 1215 1216 gen_opc_ptr++; /* skip end */ 1217 1218 nb_ops = gen_opc_ptr - gen_opc_buf; 1219 1220 s->op_dead_args = tcg_malloc(nb_ops * sizeof(uint16_t)); 1221 1222 dead_temps = tcg_malloc(s->nb_temps); 1223 memset(dead_temps, 1, s->nb_temps); 1224 1225 args = gen_opparam_ptr; 1226 op_index = nb_ops - 1; 1227 while (op_index >= 0) { 1228 op = gen_opc_buf[op_index]; 1229 def = &tcg_op_defs[op]; 1230 switch(op) { 1231 case INDEX_op_call: 1232 { 1233 int call_flags; 1234 1235 nb_args = args[-1]; 1236 args -= nb_args; 1237 nb_iargs = args[0] & 0xffff; 1238 nb_oargs = args[0] >> 16; 1239 args++; 1240 call_flags = args[nb_oargs + nb_iargs]; 1241 1242 /* pure functions can be removed if their result is not 1243 used */ 1244 if (call_flags & TCG_CALL_PURE) { 1245 for(i = 0; i < nb_oargs; i++) { 1246 arg = args[i]; 1247 if (!dead_temps[arg]) 1248 goto do_not_remove_call; 1249 } 1250 tcg_set_nop(s, gen_opc_buf + op_index, 1251 args - 1, nb_args); 1252 } else { 1253 do_not_remove_call: 1254 1255 /* output args are dead */ 1256 dead_args = 0; 1257 for(i = 0; i < nb_oargs; i++) { 1258 arg = args[i]; 1259 if (dead_temps[arg]) { 1260 dead_args |= (1 << i); 1261 } 1262 dead_temps[arg] = 1; 1263 } 1264 1265 if (!(call_flags & TCG_CALL_CONST)) { 1266 /* globals are live (they may be used by the call) */ 1267 memset(dead_temps, 0, s->nb_globals); 1268 } 1269 1270 /* input args are live */ 1271 for(i = nb_oargs; i < nb_iargs + nb_oargs; i++) { 1272 arg = args[i]; 1273 if (arg != TCG_CALL_DUMMY_ARG) { 1274 if (dead_temps[arg]) { 1275 dead_args |= (1 << i); 1276 } 1277 dead_temps[arg] = 0; 1278 } 1279 } 1280 s->op_dead_args[op_index] = dead_args; 1281 } 1282 args--; 1283 } 1284 break; 1285 case INDEX_op_set_label: 1286 args--; 1287 /* mark end of basic block */ 1288 tcg_la_bb_end(s, dead_temps); 1289 break; 1290 case INDEX_op_debug_insn_start: 1291 args -= def->nb_args; 1292 break; 1293 case INDEX_op_nopn: 1294 nb_args = args[-1]; 1295 args -= nb_args; 1296 break; 1297 case INDEX_op_discard: 1298 args--; 1299 /* mark the temporary as dead */ 1300 dead_temps[args[0]] = 1; 1301 break; 1302 case INDEX_op_end: 1303 break; 1304 /* XXX: optimize by hardcoding common cases (e.g. triadic ops) */ 1305 default: 1306 args -= def->nb_args; 1307 nb_iargs = def->nb_iargs; 1308 nb_oargs = def->nb_oargs; 1309 1310 /* Test if the operation can be removed because all 1311 its outputs are dead. We assume that nb_oargs == 0 1312 implies side effects */ 1313 if (!(def->flags & TCG_OPF_SIDE_EFFECTS) && nb_oargs != 0) { 1314 for(i = 0; i < nb_oargs; i++) { 1315 arg = args[i]; 1316 if (!dead_temps[arg]) 1317 goto do_not_remove; 1318 } 1319 tcg_set_nop(s, gen_opc_buf + op_index, args, def->nb_args); 1320 #ifdef CONFIG_PROFILER 1321 s->del_op_count++; 1322 #endif 1323 } else { 1324 do_not_remove: 1325 1326 /* output args are dead */ 1327 dead_args = 0; 1328 for(i = 0; i < nb_oargs; i++) { 1329 arg = args[i]; 1330 if (dead_temps[arg]) { 1331 dead_args |= (1 << i); 1332 } 1333 dead_temps[arg] = 1; 1334 } 1335 1336 /* if end of basic block, update */ 1337 if (def->flags & TCG_OPF_BB_END) { 1338 tcg_la_bb_end(s, dead_temps); 1339 } else if (def->flags & TCG_OPF_CALL_CLOBBER) { 1340 /* globals are live */ 1341 memset(dead_temps, 0, s->nb_globals); 1342 } 1343 1344 /* input args are live */ 1345 for(i = nb_oargs; i < nb_oargs + nb_iargs; i++) { 1346 arg = args[i]; 1347 if (dead_temps[arg]) { 1348 dead_args |= (1 << i); 1349 } 1350 dead_temps[arg] = 0; 1351 } 1352 s->op_dead_args[op_index] = dead_args; 1353 } 1354 break; 1355 } 1356 op_index--; 1357 } 1358 1359 if (args != gen_opparam_buf) 1360 tcg_abort(); 1361 } 1362 #else 1363 /* dummy liveness analysis */ 1364 static void tcg_liveness_analysis(TCGContext *s) 1365 { 1366 int nb_ops; 1367 nb_ops = gen_opc_ptr - gen_opc_buf; 1368 1369 s->op_dead_args = tcg_malloc(nb_ops * sizeof(uint16_t)); 1370 memset(s->op_dead_args, 0, nb_ops * sizeof(uint16_t)); 1371 } 1372 #endif 1373 1374 #ifndef NDEBUG 1375 static void dump_regs(TCGContext *s) 1376 { 1377 TCGTemp *ts; 1378 int i; 1379 char buf[64]; 1380 1381 for(i = 0; i < s->nb_temps; i++) { 1382 ts = &s->temps[i]; 1383 printf(" %10s: ", tcg_get_arg_str_idx(s, buf, sizeof(buf), i)); 1384 switch(ts->val_type) { 1385 case TEMP_VAL_REG: 1386 printf("%s", tcg_target_reg_names[ts->reg]); 1387 break; 1388 case TEMP_VAL_MEM: 1389 printf("%d(%s)", (int)ts->mem_offset, tcg_target_reg_names[ts->mem_reg]); 1390 break; 1391 case TEMP_VAL_CONST: 1392 printf("$0x%" TCG_PRIlx, ts->val); 1393 break; 1394 case TEMP_VAL_DEAD: 1395 printf("D"); 1396 break; 1397 default: 1398 printf("???"); 1399 break; 1400 } 1401 printf("\n"); 1402 } 1403 1404 for(i = 0; i < TCG_TARGET_NB_REGS; i++) { 1405 if (s->reg_to_temp[i] >= 0) { 1406 printf("%s: %s\n", 1407 tcg_target_reg_names[i], 1408 tcg_get_arg_str_idx(s, buf, sizeof(buf), s->reg_to_temp[i])); 1409 } 1410 } 1411 } 1412 1413 static void check_regs(TCGContext *s) 1414 { 1415 int reg, k; 1416 TCGTemp *ts; 1417 char buf[64]; 1418 1419 for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) { 1420 k = s->reg_to_temp[reg]; 1421 if (k >= 0) { 1422 ts = &s->temps[k]; 1423 if (ts->val_type != TEMP_VAL_REG || 1424 ts->reg != reg) { 1425 printf("Inconsistency for register %s:\n", 1426 tcg_target_reg_names[reg]); 1427 goto fail; 1428 } 1429 } 1430 } 1431 for(k = 0; k < s->nb_temps; k++) { 1432 ts = &s->temps[k]; 1433 if (ts->val_type == TEMP_VAL_REG && 1434 !ts->fixed_reg && 1435 s->reg_to_temp[ts->reg] != k) { 1436 printf("Inconsistency for temp %s:\n", 1437 tcg_get_arg_str_idx(s, buf, sizeof(buf), k)); 1438 fail: 1439 printf("reg state:\n"); 1440 dump_regs(s); 1441 tcg_abort(); 1442 } 1443 } 1444 } 1445 #endif 1446 1447 static void temp_allocate_frame(TCGContext *s, int temp) 1448 { 1449 TCGTemp *ts; 1450 ts = &s->temps[temp]; 1451 #ifndef __sparc_v9__ /* Sparc64 stack is accessed with offset of 2047 */ 1452 s->current_frame_offset = (s->current_frame_offset + 1453 (tcg_target_long)sizeof(tcg_target_long) - 1) & 1454 ~(sizeof(tcg_target_long) - 1); 1455 #endif 1456 if (s->current_frame_offset + (tcg_target_long)sizeof(tcg_target_long) > 1457 s->frame_end) { 1458 tcg_abort(); 1459 } 1460 ts->mem_offset = s->current_frame_offset; 1461 ts->mem_reg = s->frame_reg; 1462 ts->mem_allocated = 1; 1463 s->current_frame_offset += (tcg_target_long)sizeof(tcg_target_long); 1464 } 1465 1466 /* free register 'reg' by spilling the corresponding temporary if necessary */ 1467 static void tcg_reg_free(TCGContext *s, int reg) 1468 { 1469 TCGTemp *ts; 1470 int temp; 1471 1472 temp = s->reg_to_temp[reg]; 1473 if (temp != -1) { 1474 ts = &s->temps[temp]; 1475 assert(ts->val_type == TEMP_VAL_REG); 1476 if (!ts->mem_coherent) { 1477 if (!ts->mem_allocated) 1478 temp_allocate_frame(s, temp); 1479 tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset); 1480 } 1481 ts->val_type = TEMP_VAL_MEM; 1482 s->reg_to_temp[reg] = -1; 1483 } 1484 } 1485 1486 /* Allocate a register belonging to reg1 & ~reg2 */ 1487 static int tcg_reg_alloc(TCGContext *s, TCGRegSet reg1, TCGRegSet reg2) 1488 { 1489 int i, reg; 1490 TCGRegSet reg_ct; 1491 1492 tcg_regset_andnot(reg_ct, reg1, reg2); 1493 1494 /* first try free registers */ 1495 for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) { 1496 reg = tcg_target_reg_alloc_order[i]; 1497 if (tcg_regset_test_reg(reg_ct, reg) && s->reg_to_temp[reg] == -1) 1498 return reg; 1499 } 1500 1501 /* XXX: do better spill choice */ 1502 for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) { 1503 reg = tcg_target_reg_alloc_order[i]; 1504 if (tcg_regset_test_reg(reg_ct, reg)) { 1505 tcg_reg_free(s, reg); 1506 return reg; 1507 } 1508 } 1509 1510 tcg_abort(); 1511 } 1512 1513 /* save a temporary to memory. 'allocated_regs' is used in case a 1514 temporary registers needs to be allocated to store a constant. */ 1515 static void temp_save(TCGContext *s, int temp, TCGRegSet allocated_regs) 1516 { 1517 TCGTemp *ts; 1518 int reg; 1519 1520 ts = &s->temps[temp]; 1521 if (!ts->fixed_reg) { 1522 switch(ts->val_type) { 1523 case TEMP_VAL_REG: 1524 tcg_reg_free(s, ts->reg); 1525 break; 1526 case TEMP_VAL_DEAD: 1527 ts->val_type = TEMP_VAL_MEM; 1528 break; 1529 case TEMP_VAL_CONST: 1530 reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], 1531 allocated_regs); 1532 if (!ts->mem_allocated) 1533 temp_allocate_frame(s, temp); 1534 tcg_out_movi(s, ts->type, reg, ts->val); 1535 tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset); 1536 ts->val_type = TEMP_VAL_MEM; 1537 break; 1538 case TEMP_VAL_MEM: 1539 break; 1540 default: 1541 tcg_abort(); 1542 } 1543 } 1544 } 1545 1546 /* save globals to their canonical location and assume they can be 1547 modified be the following code. 'allocated_regs' is used in case a 1548 temporary registers needs to be allocated to store a constant. */ 1549 static void save_globals(TCGContext *s, TCGRegSet allocated_regs) 1550 { 1551 int i; 1552 1553 for(i = 0; i < s->nb_globals; i++) { 1554 temp_save(s, i, allocated_regs); 1555 } 1556 } 1557 1558 /* at the end of a basic block, we assume all temporaries are dead and 1559 all globals are stored at their canonical location. */ 1560 static void tcg_reg_alloc_bb_end(TCGContext *s, TCGRegSet allocated_regs) 1561 { 1562 TCGTemp *ts; 1563 int i; 1564 1565 for(i = s->nb_globals; i < s->nb_temps; i++) { 1566 ts = &s->temps[i]; 1567 if (ts->temp_local) { 1568 temp_save(s, i, allocated_regs); 1569 } else { 1570 if (ts->val_type == TEMP_VAL_REG) { 1571 s->reg_to_temp[ts->reg] = -1; 1572 } 1573 ts->val_type = TEMP_VAL_DEAD; 1574 } 1575 } 1576 1577 save_globals(s, allocated_regs); 1578 } 1579 1580 #define IS_DEAD_ARG(n) ((dead_args >> (n)) & 1) 1581 1582 static void tcg_reg_alloc_movi(TCGContext *s, const TCGArg *args) 1583 { 1584 TCGTemp *ots; 1585 tcg_target_ulong val; 1586 1587 ots = &s->temps[args[0]]; 1588 val = args[1]; 1589 1590 if (ots->fixed_reg) { 1591 /* for fixed registers, we do not do any constant 1592 propagation */ 1593 tcg_out_movi(s, ots->type, ots->reg, val); 1594 } else { 1595 /* The movi is not explicitly generated here */ 1596 if (ots->val_type == TEMP_VAL_REG) 1597 s->reg_to_temp[ots->reg] = -1; 1598 ots->val_type = TEMP_VAL_CONST; 1599 ots->val = val; 1600 } 1601 } 1602 1603 static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def, 1604 const TCGArg *args, 1605 unsigned int dead_args) 1606 { 1607 TCGTemp *ts, *ots; 1608 int reg; 1609 const TCGArgConstraint *arg_ct; 1610 1611 ots = &s->temps[args[0]]; 1612 ts = &s->temps[args[1]]; 1613 arg_ct = &def->args_ct[0]; 1614 1615 /* XXX: always mark arg dead if IS_DEAD_ARG(1) */ 1616 if (ts->val_type == TEMP_VAL_REG) { 1617 if (IS_DEAD_ARG(1) && !ts->fixed_reg && !ots->fixed_reg) { 1618 /* the mov can be suppressed */ 1619 if (ots->val_type == TEMP_VAL_REG) 1620 s->reg_to_temp[ots->reg] = -1; 1621 reg = ts->reg; 1622 s->reg_to_temp[reg] = -1; 1623 ts->val_type = TEMP_VAL_DEAD; 1624 } else { 1625 if (ots->val_type == TEMP_VAL_REG) { 1626 reg = ots->reg; 1627 } else { 1628 reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs); 1629 } 1630 if (ts->reg != reg) { 1631 tcg_out_mov(s, ots->type, reg, ts->reg); 1632 } 1633 } 1634 } else if (ts->val_type == TEMP_VAL_MEM) { 1635 if (ots->val_type == TEMP_VAL_REG) { 1636 reg = ots->reg; 1637 } else { 1638 reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs); 1639 } 1640 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset); 1641 } else if (ts->val_type == TEMP_VAL_CONST) { 1642 if (ots->fixed_reg) { 1643 reg = ots->reg; 1644 tcg_out_movi(s, ots->type, reg, ts->val); 1645 } else { 1646 /* propagate constant */ 1647 if (ots->val_type == TEMP_VAL_REG) 1648 s->reg_to_temp[ots->reg] = -1; 1649 ots->val_type = TEMP_VAL_CONST; 1650 ots->val = ts->val; 1651 return; 1652 } 1653 } else { 1654 tcg_abort(); 1655 } 1656 s->reg_to_temp[reg] = args[0]; 1657 ots->reg = reg; 1658 ots->val_type = TEMP_VAL_REG; 1659 ots->mem_coherent = 0; 1660 } 1661 1662 static void tcg_reg_alloc_op(TCGContext *s, 1663 const TCGOpDef *def, TCGOpcode opc, 1664 const TCGArg *args, 1665 unsigned int dead_args) 1666 { 1667 TCGRegSet allocated_regs; 1668 int i, k, nb_iargs, nb_oargs, reg; 1669 TCGArg arg; 1670 const TCGArgConstraint *arg_ct; 1671 TCGTemp *ts; 1672 TCGArg new_args[TCG_MAX_OP_ARGS]; 1673 int const_args[TCG_MAX_OP_ARGS]; 1674 1675 nb_oargs = def->nb_oargs; 1676 nb_iargs = def->nb_iargs; 1677 1678 /* copy constants */ 1679 memcpy(new_args + nb_oargs + nb_iargs, 1680 args + nb_oargs + nb_iargs, 1681 sizeof(TCGArg) * def->nb_cargs); 1682 1683 /* satisfy input constraints */ 1684 tcg_regset_set(allocated_regs, s->reserved_regs); 1685 for(k = 0; k < nb_iargs; k++) { 1686 i = def->sorted_args[nb_oargs + k]; 1687 arg = args[i]; 1688 arg_ct = &def->args_ct[i]; 1689 ts = &s->temps[arg]; 1690 if (ts->val_type == TEMP_VAL_MEM) { 1691 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs); 1692 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset); 1693 ts->val_type = TEMP_VAL_REG; 1694 ts->reg = reg; 1695 ts->mem_coherent = 1; 1696 s->reg_to_temp[reg] = arg; 1697 } else if (ts->val_type == TEMP_VAL_CONST) { 1698 if (tcg_target_const_match(ts->val, arg_ct)) { 1699 /* constant is OK for instruction */ 1700 const_args[i] = 1; 1701 new_args[i] = ts->val; 1702 goto iarg_end; 1703 } else { 1704 /* need to move to a register */ 1705 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs); 1706 tcg_out_movi(s, ts->type, reg, ts->val); 1707 ts->val_type = TEMP_VAL_REG; 1708 ts->reg = reg; 1709 ts->mem_coherent = 0; 1710 s->reg_to_temp[reg] = arg; 1711 } 1712 } 1713 assert(ts->val_type == TEMP_VAL_REG); 1714 if (arg_ct->ct & TCG_CT_IALIAS) { 1715 if (ts->fixed_reg) { 1716 /* if fixed register, we must allocate a new register 1717 if the alias is not the same register */ 1718 if (arg != args[arg_ct->alias_index]) 1719 goto allocate_in_reg; 1720 } else { 1721 /* if the input is aliased to an output and if it is 1722 not dead after the instruction, we must allocate 1723 a new register and move it */ 1724 if (!IS_DEAD_ARG(i)) { 1725 goto allocate_in_reg; 1726 } 1727 } 1728 } 1729 reg = ts->reg; 1730 if (tcg_regset_test_reg(arg_ct->u.regs, reg)) { 1731 /* nothing to do : the constraint is satisfied */ 1732 } else { 1733 allocate_in_reg: 1734 /* allocate a new register matching the constraint 1735 and move the temporary register into it */ 1736 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs); 1737 tcg_out_mov(s, ts->type, reg, ts->reg); 1738 } 1739 new_args[i] = reg; 1740 const_args[i] = 0; 1741 tcg_regset_set_reg(allocated_regs, reg); 1742 iarg_end: ; 1743 } 1744 1745 if (def->flags & TCG_OPF_BB_END) { 1746 tcg_reg_alloc_bb_end(s, allocated_regs); 1747 } else { 1748 /* mark dead temporaries and free the associated registers */ 1749 for(i = nb_oargs; i < nb_oargs + nb_iargs; i++) { 1750 arg = args[i]; 1751 if (IS_DEAD_ARG(i)) { 1752 ts = &s->temps[arg]; 1753 if (!ts->fixed_reg) { 1754 if (ts->val_type == TEMP_VAL_REG) 1755 s->reg_to_temp[ts->reg] = -1; 1756 ts->val_type = TEMP_VAL_DEAD; 1757 } 1758 } 1759 } 1760 1761 if (def->flags & TCG_OPF_CALL_CLOBBER) { 1762 /* XXX: permit generic clobber register list ? */ 1763 for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) { 1764 if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) { 1765 tcg_reg_free(s, reg); 1766 } 1767 } 1768 /* XXX: for load/store we could do that only for the slow path 1769 (i.e. when a memory callback is called) */ 1770 1771 /* store globals and free associated registers (we assume the insn 1772 can modify any global. */ 1773 save_globals(s, allocated_regs); 1774 } 1775 1776 /* satisfy the output constraints */ 1777 tcg_regset_set(allocated_regs, s->reserved_regs); 1778 for(k = 0; k < nb_oargs; k++) { 1779 i = def->sorted_args[k]; 1780 arg = args[i]; 1781 arg_ct = &def->args_ct[i]; 1782 ts = &s->temps[arg]; 1783 if (arg_ct->ct & TCG_CT_ALIAS) { 1784 reg = new_args[arg_ct->alias_index]; 1785 } else { 1786 /* if fixed register, we try to use it */ 1787 reg = ts->reg; 1788 if (ts->fixed_reg && 1789 tcg_regset_test_reg(arg_ct->u.regs, reg)) { 1790 goto oarg_end; 1791 } 1792 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs); 1793 } 1794 tcg_regset_set_reg(allocated_regs, reg); 1795 /* if a fixed register is used, then a move will be done afterwards */ 1796 if (!ts->fixed_reg) { 1797 if (ts->val_type == TEMP_VAL_REG) 1798 s->reg_to_temp[ts->reg] = -1; 1799 if (IS_DEAD_ARG(i)) { 1800 ts->val_type = TEMP_VAL_DEAD; 1801 } else { 1802 ts->val_type = TEMP_VAL_REG; 1803 ts->reg = reg; 1804 /* temp value is modified, so the value kept in memory is 1805 potentially not the same */ 1806 ts->mem_coherent = 0; 1807 s->reg_to_temp[reg] = arg; 1808 } 1809 } 1810 oarg_end: 1811 new_args[i] = reg; 1812 } 1813 } 1814 1815 /* emit instruction */ 1816 tcg_out_op(s, opc, new_args, const_args); 1817 1818 /* move the outputs in the correct register if needed */ 1819 for(i = 0; i < nb_oargs; i++) { 1820 ts = &s->temps[args[i]]; 1821 reg = new_args[i]; 1822 if (ts->fixed_reg && ts->reg != reg) { 1823 tcg_out_mov(s, ts->type, ts->reg, reg); 1824 } 1825 } 1826 } 1827 1828 #ifdef TCG_TARGET_STACK_GROWSUP 1829 #define STACK_DIR(x) (-(x)) 1830 #else 1831 #define STACK_DIR(x) (x) 1832 #endif 1833 1834 static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def, 1835 TCGOpcode opc, const TCGArg *args, 1836 unsigned int dead_args) 1837 { 1838 int nb_iargs, nb_oargs, flags, nb_regs, i, reg, nb_params; 1839 TCGArg arg, func_arg; 1840 TCGTemp *ts; 1841 tcg_target_long stack_offset, call_stack_size, func_addr; 1842 int const_func_arg, allocate_args; 1843 TCGRegSet allocated_regs; 1844 const TCGArgConstraint *arg_ct; 1845 1846 arg = *args++; 1847 1848 nb_oargs = arg >> 16; 1849 nb_iargs = arg & 0xffff; 1850 nb_params = nb_iargs - 1; 1851 1852 flags = args[nb_oargs + nb_iargs]; 1853 1854 nb_regs = tcg_target_get_call_iarg_regs_count(flags); 1855 if (nb_regs > nb_params) 1856 nb_regs = nb_params; 1857 1858 /* assign stack slots first */ 1859 call_stack_size = (nb_params - nb_regs) * sizeof(tcg_target_long); 1860 call_stack_size = (call_stack_size + TCG_TARGET_STACK_ALIGN - 1) & 1861 ~(TCG_TARGET_STACK_ALIGN - 1); 1862 allocate_args = (call_stack_size > TCG_STATIC_CALL_ARGS_SIZE); 1863 if (allocate_args) { 1864 /* XXX: if more than TCG_STATIC_CALL_ARGS_SIZE is needed, 1865 preallocate call stack */ 1866 tcg_abort(); 1867 } 1868 1869 stack_offset = TCG_TARGET_CALL_STACK_OFFSET; 1870 for(i = nb_regs; i < nb_params; i++) { 1871 arg = args[nb_oargs + i]; 1872 #ifdef TCG_TARGET_STACK_GROWSUP 1873 stack_offset -= sizeof(tcg_target_long); 1874 #endif 1875 if (arg != TCG_CALL_DUMMY_ARG) { 1876 ts = &s->temps[arg]; 1877 if (ts->val_type == TEMP_VAL_REG) { 1878 tcg_out_st(s, ts->type, ts->reg, TCG_REG_CALL_STACK, stack_offset); 1879 } else if (ts->val_type == TEMP_VAL_MEM) { 1880 reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], 1881 s->reserved_regs); 1882 /* XXX: not correct if reading values from the stack */ 1883 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset); 1884 tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset); 1885 } else if (ts->val_type == TEMP_VAL_CONST) { 1886 reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], 1887 s->reserved_regs); 1888 /* XXX: sign extend may be needed on some targets */ 1889 tcg_out_movi(s, ts->type, reg, ts->val); 1890 tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset); 1891 } else { 1892 tcg_abort(); 1893 } 1894 } 1895 #ifndef TCG_TARGET_STACK_GROWSUP 1896 stack_offset += sizeof(tcg_target_long); 1897 #endif 1898 } 1899 1900 /* assign input registers */ 1901 tcg_regset_set(allocated_regs, s->reserved_regs); 1902 for(i = 0; i < nb_regs; i++) { 1903 arg = args[nb_oargs + i]; 1904 if (arg != TCG_CALL_DUMMY_ARG) { 1905 ts = &s->temps[arg]; 1906 reg = tcg_target_call_iarg_regs[i]; 1907 tcg_reg_free(s, reg); 1908 if (ts->val_type == TEMP_VAL_REG) { 1909 if (ts->reg != reg) { 1910 tcg_out_mov(s, ts->type, reg, ts->reg); 1911 } 1912 } else if (ts->val_type == TEMP_VAL_MEM) { 1913 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset); 1914 } else if (ts->val_type == TEMP_VAL_CONST) { 1915 /* XXX: sign extend ? */ 1916 tcg_out_movi(s, ts->type, reg, ts->val); 1917 } else { 1918 tcg_abort(); 1919 } 1920 tcg_regset_set_reg(allocated_regs, reg); 1921 } 1922 } 1923 1924 /* assign function address */ 1925 func_arg = args[nb_oargs + nb_iargs - 1]; 1926 arg_ct = &def->args_ct[0]; 1927 ts = &s->temps[func_arg]; 1928 func_addr = ts->val; 1929 const_func_arg = 0; 1930 if (ts->val_type == TEMP_VAL_MEM) { 1931 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs); 1932 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset); 1933 func_arg = reg; 1934 tcg_regset_set_reg(allocated_regs, reg); 1935 } else if (ts->val_type == TEMP_VAL_REG) { 1936 reg = ts->reg; 1937 if (!tcg_regset_test_reg(arg_ct->u.regs, reg)) { 1938 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs); 1939 tcg_out_mov(s, ts->type, reg, ts->reg); 1940 } 1941 func_arg = reg; 1942 tcg_regset_set_reg(allocated_regs, reg); 1943 } else if (ts->val_type == TEMP_VAL_CONST) { 1944 if (tcg_target_const_match(func_addr, arg_ct)) { 1945 const_func_arg = 1; 1946 func_arg = func_addr; 1947 } else { 1948 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs); 1949 tcg_out_movi(s, ts->type, reg, func_addr); 1950 func_arg = reg; 1951 tcg_regset_set_reg(allocated_regs, reg); 1952 } 1953 } else { 1954 tcg_abort(); 1955 } 1956 1957 1958 /* mark dead temporaries and free the associated registers */ 1959 for(i = nb_oargs; i < nb_iargs + nb_oargs; i++) { 1960 arg = args[i]; 1961 if (IS_DEAD_ARG(i)) { 1962 ts = &s->temps[arg]; 1963 if (!ts->fixed_reg) { 1964 if (ts->val_type == TEMP_VAL_REG) 1965 s->reg_to_temp[ts->reg] = -1; 1966 ts->val_type = TEMP_VAL_DEAD; 1967 } 1968 } 1969 } 1970 1971 /* clobber call registers */ 1972 for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) { 1973 if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) { 1974 tcg_reg_free(s, reg); 1975 } 1976 } 1977 1978 /* store globals and free associated registers (we assume the call 1979 can modify any global. */ 1980 if (!(flags & TCG_CALL_CONST)) { 1981 save_globals(s, allocated_regs); 1982 } 1983 1984 tcg_out_op(s, opc, &func_arg, &const_func_arg); 1985 1986 /* assign output registers and emit moves if needed */ 1987 for(i = 0; i < nb_oargs; i++) { 1988 arg = args[i]; 1989 ts = &s->temps[arg]; 1990 reg = tcg_target_call_oarg_regs[i]; 1991 assert(s->reg_to_temp[reg] == -1); 1992 if (ts->fixed_reg) { 1993 if (ts->reg != reg) { 1994 tcg_out_mov(s, ts->type, ts->reg, reg); 1995 } 1996 } else { 1997 if (ts->val_type == TEMP_VAL_REG) 1998 s->reg_to_temp[ts->reg] = -1; 1999 if (IS_DEAD_ARG(i)) { 2000 ts->val_type = TEMP_VAL_DEAD; 2001 } else { 2002 ts->val_type = TEMP_VAL_REG; 2003 ts->reg = reg; 2004 ts->mem_coherent = 0; 2005 s->reg_to_temp[reg] = arg; 2006 } 2007 } 2008 } 2009 2010 return nb_iargs + nb_oargs + def->nb_cargs + 1; 2011 } 2012 2013 #ifdef CONFIG_PROFILER 2014 2015 static int64_t tcg_table_op_count[NB_OPS]; 2016 2017 static void dump_op_count(void) 2018 { 2019 int i; 2020 FILE *f; 2021 f = fopen("/tmp/op.log", "w"); 2022 for(i = INDEX_op_end; i < NB_OPS; i++) { 2023 fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name, tcg_table_op_count[i]); 2024 } 2025 fclose(f); 2026 } 2027 #endif 2028 2029 2030 static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf, 2031 long search_pc) 2032 { 2033 TCGOpcode opc; 2034 int op_index; 2035 const TCGOpDef *def; 2036 unsigned int dead_args; 2037 const TCGArg *args; 2038 2039 #ifdef DEBUG_DISAS 2040 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) { 2041 qemu_log("OP:\n"); 2042 tcg_dump_ops(s, logfile); 2043 qemu_log("\n"); 2044 } 2045 #endif 2046 2047 #ifdef USE_TCG_OPTIMIZATIONS 2048 gen_opparam_ptr = 2049 tcg_optimize(s, gen_opc_ptr, gen_opparam_buf, tcg_op_defs); 2050 #endif 2051 2052 #ifdef CONFIG_PROFILER 2053 s->la_time -= profile_getclock(); 2054 #endif 2055 tcg_liveness_analysis(s); 2056 #ifdef CONFIG_PROFILER 2057 s->la_time += profile_getclock(); 2058 #endif 2059 2060 #ifdef DEBUG_DISAS 2061 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_OPT))) { 2062 qemu_log("OP after liveness analysis:\n"); 2063 tcg_dump_ops(s, logfile); 2064 qemu_log("\n"); 2065 } 2066 #endif 2067 2068 tcg_reg_alloc_start(s); 2069 2070 s->code_buf = gen_code_buf; 2071 s->code_ptr = gen_code_buf; 2072 2073 args = gen_opparam_buf; 2074 op_index = 0; 2075 2076 for(;;) { 2077 opc = gen_opc_buf[op_index]; 2078 #ifdef CONFIG_PROFILER 2079 tcg_table_op_count[opc]++; 2080 #endif 2081 def = &tcg_op_defs[opc]; 2082 #if 0 2083 printf("%s: %d %d %d\n", def->name, 2084 def->nb_oargs, def->nb_iargs, def->nb_cargs); 2085 // dump_regs(s); 2086 #endif 2087 switch(opc) { 2088 case INDEX_op_mov_i32: 2089 #if TCG_TARGET_REG_BITS == 64 2090 case INDEX_op_mov_i64: 2091 #endif 2092 dead_args = s->op_dead_args[op_index]; 2093 tcg_reg_alloc_mov(s, def, args, dead_args); 2094 break; 2095 case INDEX_op_movi_i32: 2096 #if TCG_TARGET_REG_BITS == 64 2097 case INDEX_op_movi_i64: 2098 #endif 2099 tcg_reg_alloc_movi(s, args); 2100 break; 2101 case INDEX_op_debug_insn_start: 2102 /* debug instruction */ 2103 break; 2104 case INDEX_op_nop: 2105 case INDEX_op_nop1: 2106 case INDEX_op_nop2: 2107 case INDEX_op_nop3: 2108 break; 2109 case INDEX_op_nopn: 2110 args += args[0]; 2111 goto next; 2112 case INDEX_op_discard: 2113 { 2114 TCGTemp *ts; 2115 ts = &s->temps[args[0]]; 2116 /* mark the temporary as dead */ 2117 if (!ts->fixed_reg) { 2118 if (ts->val_type == TEMP_VAL_REG) 2119 s->reg_to_temp[ts->reg] = -1; 2120 ts->val_type = TEMP_VAL_DEAD; 2121 } 2122 } 2123 break; 2124 case INDEX_op_set_label: 2125 tcg_reg_alloc_bb_end(s, s->reserved_regs); 2126 tcg_out_label(s, args[0], s->code_ptr); 2127 break; 2128 case INDEX_op_call: 2129 dead_args = s->op_dead_args[op_index]; 2130 args += tcg_reg_alloc_call(s, def, opc, args, dead_args); 2131 goto next; 2132 case INDEX_op_end: 2133 goto the_end; 2134 default: 2135 /* Sanity check that we've not introduced any unhandled opcodes. */ 2136 if (def->flags & TCG_OPF_NOT_PRESENT) { 2137 tcg_abort(); 2138 } 2139 /* Note: in order to speed up the code, it would be much 2140 faster to have specialized register allocator functions for 2141 some common argument patterns */ 2142 dead_args = s->op_dead_args[op_index]; 2143 tcg_reg_alloc_op(s, def, opc, args, dead_args); 2144 break; 2145 } 2146 args += def->nb_args; 2147 next: 2148 if (search_pc >= 0 && search_pc < s->code_ptr - gen_code_buf) { 2149 return op_index; 2150 } 2151 op_index++; 2152 #ifndef NDEBUG 2153 check_regs(s); 2154 #endif 2155 } 2156 the_end: 2157 return -1; 2158 } 2159 2160 int tcg_gen_code(TCGContext *s, uint8_t *gen_code_buf) 2161 { 2162 #ifdef CONFIG_PROFILER 2163 { 2164 int n; 2165 n = (gen_opc_ptr - gen_opc_buf); 2166 s->op_count += n; 2167 if (n > s->op_count_max) 2168 s->op_count_max = n; 2169 2170 s->temp_count += s->nb_temps; 2171 if (s->nb_temps > s->temp_count_max) 2172 s->temp_count_max = s->nb_temps; 2173 } 2174 #endif 2175 2176 tcg_gen_code_common(s, gen_code_buf, -1); 2177 2178 /* flush instruction cache */ 2179 flush_icache_range((tcg_target_ulong)gen_code_buf, 2180 (tcg_target_ulong)s->code_ptr); 2181 2182 return s->code_ptr - gen_code_buf; 2183 } 2184 2185 /* Return the index of the micro operation such as the pc after is < 2186 offset bytes from the start of the TB. The contents of gen_code_buf must 2187 not be changed, though writing the same values is ok. 2188 Return -1 if not found. */ 2189 int tcg_gen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, long offset) 2190 { 2191 return tcg_gen_code_common(s, gen_code_buf, offset); 2192 } 2193 2194 #ifdef CONFIG_PROFILER 2195 void tcg_dump_info(FILE *f, fprintf_function cpu_fprintf) 2196 { 2197 TCGContext *s = &tcg_ctx; 2198 int64_t tot; 2199 2200 tot = s->interm_time + s->code_time; 2201 cpu_fprintf(f, "JIT cycles %" PRId64 " (%0.3f s at 2.4 GHz)\n", 2202 tot, tot / 2.4e9); 2203 cpu_fprintf(f, "translated TBs %" PRId64 " (aborted=%" PRId64 " %0.1f%%)\n", 2204 s->tb_count, 2205 s->tb_count1 - s->tb_count, 2206 s->tb_count1 ? (double)(s->tb_count1 - s->tb_count) / s->tb_count1 * 100.0 : 0); 2207 cpu_fprintf(f, "avg ops/TB %0.1f max=%d\n", 2208 s->tb_count ? (double)s->op_count / s->tb_count : 0, s->op_count_max); 2209 cpu_fprintf(f, "deleted ops/TB %0.2f\n", 2210 s->tb_count ? 2211 (double)s->del_op_count / s->tb_count : 0); 2212 cpu_fprintf(f, "avg temps/TB %0.2f max=%d\n", 2213 s->tb_count ? 2214 (double)s->temp_count / s->tb_count : 0, 2215 s->temp_count_max); 2216 2217 cpu_fprintf(f, "cycles/op %0.1f\n", 2218 s->op_count ? (double)tot / s->op_count : 0); 2219 cpu_fprintf(f, "cycles/in byte %0.1f\n", 2220 s->code_in_len ? (double)tot / s->code_in_len : 0); 2221 cpu_fprintf(f, "cycles/out byte %0.1f\n", 2222 s->code_out_len ? (double)tot / s->code_out_len : 0); 2223 if (tot == 0) 2224 tot = 1; 2225 cpu_fprintf(f, " gen_interm time %0.1f%%\n", 2226 (double)s->interm_time / tot * 100.0); 2227 cpu_fprintf(f, " gen_code time %0.1f%%\n", 2228 (double)s->code_time / tot * 100.0); 2229 cpu_fprintf(f, "liveness/code time %0.1f%%\n", 2230 (double)s->la_time / (s->code_time ? s->code_time : 1) * 100.0); 2231 cpu_fprintf(f, "cpu_restore count %" PRId64 "\n", 2232 s->restore_count); 2233 cpu_fprintf(f, " avg cycles %0.1f\n", 2234 s->restore_count ? (double)s->restore_time / s->restore_count : 0); 2235 2236 dump_op_count(); 2237 } 2238 #else 2239 void tcg_dump_info(FILE *f, fprintf_function cpu_fprintf) 2240 { 2241 cpu_fprintf(f, "[TCG profiler not compiled]\n"); 2242 } 2243 #endif 2244