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