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