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