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