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