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