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