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