2 * Tiny Code Generator for QEMU
4 * Copyright (c) 2008 Fabrice Bellard
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:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
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
25 /* define it to use liveness analysis (better code) */
26 #define USE_LIVENESS_ANALYSIS
27 #define USE_TCG_OPTIMIZATIONS
31 #if !defined(CONFIG_DEBUG_TCG) && !defined(NDEBUG)
32 /* define it to suppress various consistency checks (faster) */
36 #include "qemu-common.h"
37 #include "cache-utils.h"
38 #include "host-utils.h"
39 #include "qemu-timer.h"
41 /* Note: the long term plan is to reduce the dependancies on the QEMU
42 CPU definitions. Currently they are used for qemu_ld/st
44 #define NO_CPU_IO_DEFS
50 #if defined(CONFIG_USE_GUEST_BASE) && !defined(TCG_TARGET_HAS_GUEST_BASE)
51 #error GUEST_BASE not supported on this host.
54 /* Forward declarations for functions declared in tcg-target.c and used here. */
55 static void tcg_target_init(TCGContext *s);
56 static void tcg_target_qemu_prologue(TCGContext *s);
57 static void patch_reloc(uint8_t *code_ptr, int type,
58 tcg_target_long value, tcg_target_long addend);
60 /* Forward declarations for functions declared and used in tcg-target.c. */
61 static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str);
62 static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg1,
63 tcg_target_long arg2);
64 static void tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg);
65 static void tcg_out_movi(TCGContext *s, TCGType type,
66 TCGReg ret, tcg_target_long arg);
67 static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
68 const int *const_args);
69 static void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, TCGReg arg1,
70 tcg_target_long arg2);
71 static int tcg_target_const_match(tcg_target_long val,
72 const TCGArgConstraint *arg_ct);
73 static int tcg_target_get_call_iarg_regs_count(int flags);
75 TCGOpDef tcg_op_defs[] = {
76 #define DEF(s, oargs, iargs, cargs, flags) { #s, oargs, iargs, cargs, iargs + oargs + cargs, flags },
80 const size_t tcg_op_defs_max = ARRAY_SIZE(tcg_op_defs);
82 static TCGRegSet tcg_target_available_regs[2];
83 static TCGRegSet tcg_target_call_clobber_regs;
85 /* XXX: move that inside the context */
86 uint16_t *gen_opc_ptr;
87 TCGArg *gen_opparam_ptr;
89 static inline void tcg_out8(TCGContext *s, uint8_t v)
94 static inline void tcg_out16(TCGContext *s, uint16_t v)
96 *(uint16_t *)s->code_ptr = v;
100 static inline void tcg_out32(TCGContext *s, uint32_t v)
102 *(uint32_t *)s->code_ptr = v;
106 /* label relocation processing */
108 static void tcg_out_reloc(TCGContext *s, uint8_t *code_ptr, int type,
109 int label_index, long addend)
114 l = &s->labels[label_index];
116 /* FIXME: This may break relocations on RISC targets that
117 modify instruction fields in place. The caller may not have
118 written the initial value. */
119 patch_reloc(code_ptr, type, l->u.value, addend);
121 /* add a new relocation entry */
122 r = tcg_malloc(sizeof(TCGRelocation));
126 r->next = l->u.first_reloc;
127 l->u.first_reloc = r;
131 static void tcg_out_label(TCGContext *s, int label_index,
132 tcg_target_long value)
137 l = &s->labels[label_index];
140 r = l->u.first_reloc;
142 patch_reloc(r->ptr, r->type, value, r->addend);
149 int gen_new_label(void)
151 TCGContext *s = &tcg_ctx;
155 if (s->nb_labels >= TCG_MAX_LABELS)
157 idx = s->nb_labels++;
160 l->u.first_reloc = NULL;
164 #include "tcg-target.c"
166 /* pool based memory allocation */
167 void *tcg_malloc_internal(TCGContext *s, int size)
172 if (size > TCG_POOL_CHUNK_SIZE) {
173 /* big malloc: insert a new pool (XXX: could optimize) */
174 p = g_malloc(sizeof(TCGPool) + size);
177 s->pool_current->next = p;
180 p->next = s->pool_current;
190 pool_size = TCG_POOL_CHUNK_SIZE;
191 p = g_malloc(sizeof(TCGPool) + pool_size);
195 s->pool_current->next = p;
204 s->pool_cur = p->data + size;
205 s->pool_end = p->data + p->size;
209 void tcg_pool_reset(TCGContext *s)
211 s->pool_cur = s->pool_end = NULL;
212 s->pool_current = NULL;
215 void tcg_context_init(TCGContext *s)
217 int op, total_args, n;
219 TCGArgConstraint *args_ct;
222 memset(s, 0, sizeof(*s));
223 s->temps = s->static_temps;
226 /* Count total number of arguments and allocate the corresponding
229 for(op = 0; op < NB_OPS; op++) {
230 def = &tcg_op_defs[op];
231 n = def->nb_iargs + def->nb_oargs;
235 args_ct = g_malloc(sizeof(TCGArgConstraint) * total_args);
236 sorted_args = g_malloc(sizeof(int) * total_args);
238 for(op = 0; op < NB_OPS; op++) {
239 def = &tcg_op_defs[op];
240 def->args_ct = args_ct;
241 def->sorted_args = sorted_args;
242 n = def->nb_iargs + def->nb_oargs;
250 void tcg_prologue_init(TCGContext *s)
252 /* init global prologue and epilogue */
253 s->code_buf = code_gen_prologue;
254 s->code_ptr = s->code_buf;
255 tcg_target_qemu_prologue(s);
256 flush_icache_range((unsigned long)s->code_buf,
257 (unsigned long)s->code_ptr);
260 void tcg_set_frame(TCGContext *s, int reg,
261 tcg_target_long start, tcg_target_long size)
263 s->frame_start = start;
264 s->frame_end = start + size;
268 void tcg_func_start(TCGContext *s)
272 s->nb_temps = s->nb_globals;
273 for(i = 0; i < (TCG_TYPE_COUNT * 2); i++)
274 s->first_free_temp[i] = -1;
275 s->labels = tcg_malloc(sizeof(TCGLabel) * TCG_MAX_LABELS);
277 s->current_frame_offset = s->frame_start;
279 gen_opc_ptr = gen_opc_buf;
280 gen_opparam_ptr = gen_opparam_buf;
283 static inline void tcg_temp_alloc(TCGContext *s, int n)
285 if (n > TCG_MAX_TEMPS)
289 static inline int tcg_global_reg_new_internal(TCGType type, int reg,
292 TCGContext *s = &tcg_ctx;
296 #if TCG_TARGET_REG_BITS == 32
297 if (type != TCG_TYPE_I32)
300 if (tcg_regset_test_reg(s->reserved_regs, reg))
303 tcg_temp_alloc(s, s->nb_globals + 1);
304 ts = &s->temps[s->nb_globals];
305 ts->base_type = type;
311 tcg_regset_set_reg(s->reserved_regs, reg);
315 TCGv_i32 tcg_global_reg_new_i32(int reg, const char *name)
319 idx = tcg_global_reg_new_internal(TCG_TYPE_I32, reg, name);
320 return MAKE_TCGV_I32(idx);
323 TCGv_i64 tcg_global_reg_new_i64(int reg, const char *name)
327 idx = tcg_global_reg_new_internal(TCG_TYPE_I64, reg, name);
328 return MAKE_TCGV_I64(idx);
331 static inline int tcg_global_mem_new_internal(TCGType type, int reg,
332 tcg_target_long offset,
335 TCGContext *s = &tcg_ctx;
340 #if TCG_TARGET_REG_BITS == 32
341 if (type == TCG_TYPE_I64) {
343 tcg_temp_alloc(s, s->nb_globals + 2);
344 ts = &s->temps[s->nb_globals];
345 ts->base_type = type;
346 ts->type = TCG_TYPE_I32;
348 ts->mem_allocated = 1;
350 #ifdef TCG_TARGET_WORDS_BIGENDIAN
351 ts->mem_offset = offset + 4;
353 ts->mem_offset = offset;
355 pstrcpy(buf, sizeof(buf), name);
356 pstrcat(buf, sizeof(buf), "_0");
357 ts->name = strdup(buf);
360 ts->base_type = type;
361 ts->type = TCG_TYPE_I32;
363 ts->mem_allocated = 1;
365 #ifdef TCG_TARGET_WORDS_BIGENDIAN
366 ts->mem_offset = offset;
368 ts->mem_offset = offset + 4;
370 pstrcpy(buf, sizeof(buf), name);
371 pstrcat(buf, sizeof(buf), "_1");
372 ts->name = strdup(buf);
378 tcg_temp_alloc(s, s->nb_globals + 1);
379 ts = &s->temps[s->nb_globals];
380 ts->base_type = type;
383 ts->mem_allocated = 1;
385 ts->mem_offset = offset;
392 TCGv_i32 tcg_global_mem_new_i32(int reg, tcg_target_long offset,
397 idx = tcg_global_mem_new_internal(TCG_TYPE_I32, reg, offset, name);
398 return MAKE_TCGV_I32(idx);
401 TCGv_i64 tcg_global_mem_new_i64(int reg, tcg_target_long offset,
406 idx = tcg_global_mem_new_internal(TCG_TYPE_I64, reg, offset, name);
407 return MAKE_TCGV_I64(idx);
410 static inline int tcg_temp_new_internal(TCGType type, int temp_local)
412 TCGContext *s = &tcg_ctx;
419 idx = s->first_free_temp[k];
421 /* There is already an available temp with the
424 s->first_free_temp[k] = ts->next_free_temp;
425 ts->temp_allocated = 1;
426 assert(ts->temp_local == temp_local);
429 #if TCG_TARGET_REG_BITS == 32
430 if (type == TCG_TYPE_I64) {
431 tcg_temp_alloc(s, s->nb_temps + 2);
432 ts = &s->temps[s->nb_temps];
433 ts->base_type = type;
434 ts->type = TCG_TYPE_I32;
435 ts->temp_allocated = 1;
436 ts->temp_local = temp_local;
439 ts->base_type = TCG_TYPE_I32;
440 ts->type = TCG_TYPE_I32;
441 ts->temp_allocated = 1;
442 ts->temp_local = temp_local;
448 tcg_temp_alloc(s, s->nb_temps + 1);
449 ts = &s->temps[s->nb_temps];
450 ts->base_type = type;
452 ts->temp_allocated = 1;
453 ts->temp_local = temp_local;
459 #if defined(CONFIG_DEBUG_TCG)
465 TCGv_i32 tcg_temp_new_internal_i32(int temp_local)
469 idx = tcg_temp_new_internal(TCG_TYPE_I32, temp_local);
470 return MAKE_TCGV_I32(idx);
473 TCGv_i64 tcg_temp_new_internal_i64(int temp_local)
477 idx = tcg_temp_new_internal(TCG_TYPE_I64, temp_local);
478 return MAKE_TCGV_I64(idx);
481 static inline void tcg_temp_free_internal(int idx)
483 TCGContext *s = &tcg_ctx;
487 #if defined(CONFIG_DEBUG_TCG)
489 if (s->temps_in_use < 0) {
490 fprintf(stderr, "More temporaries freed than allocated!\n");
494 assert(idx >= s->nb_globals && idx < s->nb_temps);
496 assert(ts->temp_allocated != 0);
497 ts->temp_allocated = 0;
501 ts->next_free_temp = s->first_free_temp[k];
502 s->first_free_temp[k] = idx;
505 void tcg_temp_free_i32(TCGv_i32 arg)
507 tcg_temp_free_internal(GET_TCGV_I32(arg));
510 void tcg_temp_free_i64(TCGv_i64 arg)
512 tcg_temp_free_internal(GET_TCGV_I64(arg));
515 TCGv_i32 tcg_const_i32(int32_t val)
518 t0 = tcg_temp_new_i32();
519 tcg_gen_movi_i32(t0, val);
523 TCGv_i64 tcg_const_i64(int64_t val)
526 t0 = tcg_temp_new_i64();
527 tcg_gen_movi_i64(t0, val);
531 TCGv_i32 tcg_const_local_i32(int32_t val)
534 t0 = tcg_temp_local_new_i32();
535 tcg_gen_movi_i32(t0, val);
539 TCGv_i64 tcg_const_local_i64(int64_t val)
542 t0 = tcg_temp_local_new_i64();
543 tcg_gen_movi_i64(t0, val);
547 #if defined(CONFIG_DEBUG_TCG)
548 void tcg_clear_temp_count(void)
550 TCGContext *s = &tcg_ctx;
554 int tcg_check_temp_count(void)
556 TCGContext *s = &tcg_ctx;
557 if (s->temps_in_use) {
558 /* Clear the count so that we don't give another
559 * warning immediately next time around.
568 void tcg_register_helper(void *func, const char *name)
570 TCGContext *s = &tcg_ctx;
572 if ((s->nb_helpers + 1) > s->allocated_helpers) {
573 n = s->allocated_helpers;
579 s->helpers = realloc(s->helpers, n * sizeof(TCGHelperInfo));
580 s->allocated_helpers = n;
582 s->helpers[s->nb_helpers].func = (tcg_target_ulong)func;
583 s->helpers[s->nb_helpers].name = name;
587 /* Note: we convert the 64 bit args to 32 bit and do some alignment
588 and endian swap. Maybe it would be better to do the alignment
589 and endian swap in tcg_reg_alloc_call(). */
590 void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags,
591 int sizemask, TCGArg ret, int nargs, TCGArg *args)
593 #if defined(TCG_TARGET_I386) && TCG_TARGET_REG_BITS < 64
601 #if defined(TCG_TARGET_EXTEND_ARGS) && TCG_TARGET_REG_BITS == 64
602 for (i = 0; i < nargs; ++i) {
603 int is_64bit = sizemask & (1 << (i+1)*2);
604 int is_signed = sizemask & (2 << (i+1)*2);
606 TCGv_i64 temp = tcg_temp_new_i64();
607 TCGv_i64 orig = MAKE_TCGV_I64(args[i]);
609 tcg_gen_ext32s_i64(temp, orig);
611 tcg_gen_ext32u_i64(temp, orig);
613 args[i] = GET_TCGV_I64(temp);
616 #endif /* TCG_TARGET_EXTEND_ARGS */
618 *gen_opc_ptr++ = INDEX_op_call;
619 nparam = gen_opparam_ptr++;
620 #if defined(TCG_TARGET_I386) && TCG_TARGET_REG_BITS < 64
621 call_type = (flags & TCG_CALL_TYPE_MASK);
623 if (ret != TCG_CALL_DUMMY_ARG) {
624 #if TCG_TARGET_REG_BITS < 64
626 #ifdef TCG_TARGET_WORDS_BIGENDIAN
627 *gen_opparam_ptr++ = ret + 1;
628 *gen_opparam_ptr++ = ret;
630 *gen_opparam_ptr++ = ret;
631 *gen_opparam_ptr++ = ret + 1;
637 *gen_opparam_ptr++ = ret;
644 for (i = 0; i < nargs; i++) {
645 #if TCG_TARGET_REG_BITS < 64
646 int is_64bit = sizemask & (1 << (i+1)*2);
648 #ifdef TCG_TARGET_I386
649 /* REGPARM case: if the third parameter is 64 bit, it is
650 allocated on the stack */
651 if (i == 2 && call_type == TCG_CALL_TYPE_REGPARM) {
652 call_type = TCG_CALL_TYPE_REGPARM_2;
653 flags = (flags & ~TCG_CALL_TYPE_MASK) | call_type;
656 #ifdef TCG_TARGET_CALL_ALIGN_ARGS
657 /* some targets want aligned 64 bit args */
659 *gen_opparam_ptr++ = TCG_CALL_DUMMY_ARG;
663 /* If stack grows up, then we will be placing successive
664 arguments at lower addresses, which means we need to
665 reverse the order compared to how we would normally
666 treat either big or little-endian. For those arguments
667 that will wind up in registers, this still works for
668 HPPA (the only current STACK_GROWSUP target) since the
669 argument registers are *also* allocated in decreasing
670 order. If another such target is added, this logic may
671 have to get more complicated to differentiate between
672 stack arguments and register arguments. */
673 #if defined(TCG_TARGET_WORDS_BIGENDIAN) != defined(TCG_TARGET_STACK_GROWSUP)
674 *gen_opparam_ptr++ = args[i] + 1;
675 *gen_opparam_ptr++ = args[i];
677 *gen_opparam_ptr++ = args[i];
678 *gen_opparam_ptr++ = args[i] + 1;
683 #endif /* TCG_TARGET_REG_BITS < 64 */
685 *gen_opparam_ptr++ = args[i];
688 *gen_opparam_ptr++ = GET_TCGV_PTR(func);
690 *gen_opparam_ptr++ = flags;
692 *nparam = (nb_rets << 16) | (real_args + 1);
694 /* total parameters, needed to go backward in the instruction stream */
695 *gen_opparam_ptr++ = 1 + nb_rets + real_args + 3;
697 #if defined(TCG_TARGET_EXTEND_ARGS) && TCG_TARGET_REG_BITS == 64
698 for (i = 0; i < nargs; ++i) {
699 int is_64bit = sizemask & (1 << (i+1)*2);
701 TCGv_i64 temp = MAKE_TCGV_I64(args[i]);
702 tcg_temp_free_i64(temp);
705 #endif /* TCG_TARGET_EXTEND_ARGS */
708 #if TCG_TARGET_REG_BITS == 32
709 void tcg_gen_shifti_i64(TCGv_i64 ret, TCGv_i64 arg1,
710 int c, int right, int arith)
713 tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg1));
714 tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
715 } else if (c >= 32) {
719 tcg_gen_sari_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
720 tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 31);
722 tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
723 tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
726 tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_LOW(arg1), c);
727 tcg_gen_movi_i32(TCGV_LOW(ret), 0);
732 t0 = tcg_temp_new_i32();
733 t1 = tcg_temp_new_i32();
735 tcg_gen_shli_i32(t0, TCGV_HIGH(arg1), 32 - c);
737 tcg_gen_sari_i32(t1, TCGV_HIGH(arg1), c);
739 tcg_gen_shri_i32(t1, TCGV_HIGH(arg1), c);
740 tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_LOW(arg1), c);
741 tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(ret), t0);
742 tcg_gen_mov_i32(TCGV_HIGH(ret), t1);
744 tcg_gen_shri_i32(t0, TCGV_LOW(arg1), 32 - c);
745 /* Note: ret can be the same as arg1, so we use t1 */
746 tcg_gen_shli_i32(t1, TCGV_LOW(arg1), c);
747 tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c);
748 tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t0);
749 tcg_gen_mov_i32(TCGV_LOW(ret), t1);
751 tcg_temp_free_i32(t0);
752 tcg_temp_free_i32(t1);
758 static void tcg_reg_alloc_start(TCGContext *s)
762 for(i = 0; i < s->nb_globals; i++) {
765 ts->val_type = TEMP_VAL_REG;
767 ts->val_type = TEMP_VAL_MEM;
770 for(i = s->nb_globals; i < s->nb_temps; i++) {
772 ts->val_type = TEMP_VAL_DEAD;
773 ts->mem_allocated = 0;
776 for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
777 s->reg_to_temp[i] = -1;
781 static char *tcg_get_arg_str_idx(TCGContext *s, char *buf, int buf_size,
786 assert(idx >= 0 && idx < s->nb_temps);
789 if (idx < s->nb_globals) {
790 pstrcpy(buf, buf_size, ts->name);
793 snprintf(buf, buf_size, "loc%d", idx - s->nb_globals);
795 snprintf(buf, buf_size, "tmp%d", idx - s->nb_globals);
800 char *tcg_get_arg_str_i32(TCGContext *s, char *buf, int buf_size, TCGv_i32 arg)
802 return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I32(arg));
805 char *tcg_get_arg_str_i64(TCGContext *s, char *buf, int buf_size, TCGv_i64 arg)
807 return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I64(arg));
810 static int helper_cmp(const void *p1, const void *p2)
812 const TCGHelperInfo *th1 = p1;
813 const TCGHelperInfo *th2 = p2;
814 if (th1->func < th2->func)
816 else if (th1->func == th2->func)
822 /* find helper definition (Note: A hash table would be better) */
823 static TCGHelperInfo *tcg_find_helper(TCGContext *s, tcg_target_ulong val)
829 if (unlikely(!s->helpers_sorted)) {
830 qsort(s->helpers, s->nb_helpers, sizeof(TCGHelperInfo),
832 s->helpers_sorted = 1;
837 m_max = s->nb_helpers - 1;
838 while (m_min <= m_max) {
839 m = (m_min + m_max) >> 1;
853 static const char * const cond_name[] =
855 [TCG_COND_EQ] = "eq",
856 [TCG_COND_NE] = "ne",
857 [TCG_COND_LT] = "lt",
858 [TCG_COND_GE] = "ge",
859 [TCG_COND_LE] = "le",
860 [TCG_COND_GT] = "gt",
861 [TCG_COND_LTU] = "ltu",
862 [TCG_COND_GEU] = "geu",
863 [TCG_COND_LEU] = "leu",
864 [TCG_COND_GTU] = "gtu"
867 void tcg_dump_ops(TCGContext *s, FILE *outfile)
869 const uint16_t *opc_ptr;
873 int i, k, nb_oargs, nb_iargs, nb_cargs, first_insn;
878 opc_ptr = gen_opc_buf;
879 args = gen_opparam_buf;
880 while (opc_ptr < gen_opc_ptr) {
882 def = &tcg_op_defs[c];
883 if (c == INDEX_op_debug_insn_start) {
885 #if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
886 pc = ((uint64_t)args[1] << 32) | args[0];
891 fprintf(outfile, "\n");
892 fprintf(outfile, " ---- 0x%" PRIx64, pc);
894 nb_oargs = def->nb_oargs;
895 nb_iargs = def->nb_iargs;
896 nb_cargs = def->nb_cargs;
897 } else if (c == INDEX_op_call) {
900 /* variable number of arguments */
902 nb_oargs = arg >> 16;
903 nb_iargs = arg & 0xffff;
904 nb_cargs = def->nb_cargs;
906 fprintf(outfile, " %s ", def->name);
909 fprintf(outfile, "%s",
910 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + nb_iargs - 1]));
912 fprintf(outfile, ",$0x%" TCG_PRIlx,
913 args[nb_oargs + nb_iargs]);
915 fprintf(outfile, ",$%d", nb_oargs);
916 for(i = 0; i < nb_oargs; i++) {
917 fprintf(outfile, ",");
918 fprintf(outfile, "%s",
919 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[i]));
921 for(i = 0; i < (nb_iargs - 1); i++) {
922 fprintf(outfile, ",");
923 if (args[nb_oargs + i] == TCG_CALL_DUMMY_ARG) {
924 fprintf(outfile, "<dummy>");
926 fprintf(outfile, "%s",
927 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + i]));
930 } else if (c == INDEX_op_movi_i32
931 #if TCG_TARGET_REG_BITS == 64
932 || c == INDEX_op_movi_i64
935 tcg_target_ulong val;
938 nb_oargs = def->nb_oargs;
939 nb_iargs = def->nb_iargs;
940 nb_cargs = def->nb_cargs;
941 fprintf(outfile, " %s %s,$", def->name,
942 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[0]));
944 th = tcg_find_helper(s, val);
946 fprintf(outfile, "%s", th->name);
948 if (c == INDEX_op_movi_i32)
949 fprintf(outfile, "0x%x", (uint32_t)val);
951 fprintf(outfile, "0x%" PRIx64 , (uint64_t)val);
954 fprintf(outfile, " %s ", def->name);
955 if (c == INDEX_op_nopn) {
956 /* variable number of arguments */
961 nb_oargs = def->nb_oargs;
962 nb_iargs = def->nb_iargs;
963 nb_cargs = def->nb_cargs;
967 for(i = 0; i < nb_oargs; i++) {
969 fprintf(outfile, ",");
970 fprintf(outfile, "%s",
971 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
973 for(i = 0; i < nb_iargs; i++) {
975 fprintf(outfile, ",");
976 fprintf(outfile, "%s",
977 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
980 case INDEX_op_brcond_i32:
981 #if TCG_TARGET_REG_BITS == 32
982 case INDEX_op_brcond2_i32:
983 #elif TCG_TARGET_REG_BITS == 64
984 case INDEX_op_brcond_i64:
986 case INDEX_op_setcond_i32:
987 #if TCG_TARGET_REG_BITS == 32
988 case INDEX_op_setcond2_i32:
989 #elif TCG_TARGET_REG_BITS == 64
990 case INDEX_op_setcond_i64:
992 if (args[k] < ARRAY_SIZE(cond_name) && cond_name[args[k]])
993 fprintf(outfile, ",%s", cond_name[args[k++]]);
995 fprintf(outfile, ",$0x%" TCG_PRIlx, args[k++]);
1002 for(; i < nb_cargs; i++) {
1004 fprintf(outfile, ",");
1006 fprintf(outfile, "$0x%" TCG_PRIlx, arg);
1009 fprintf(outfile, "\n");
1010 args += nb_iargs + nb_oargs + nb_cargs;
1014 /* we give more priority to constraints with less registers */
1015 static int get_constraint_priority(const TCGOpDef *def, int k)
1017 const TCGArgConstraint *arg_ct;
1020 arg_ct = &def->args_ct[k];
1021 if (arg_ct->ct & TCG_CT_ALIAS) {
1022 /* an alias is equivalent to a single register */
1025 if (!(arg_ct->ct & TCG_CT_REG))
1028 for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
1029 if (tcg_regset_test_reg(arg_ct->u.regs, i))
1033 return TCG_TARGET_NB_REGS - n + 1;
1036 /* sort from highest priority to lowest */
1037 static void sort_constraints(TCGOpDef *def, int start, int n)
1039 int i, j, p1, p2, tmp;
1041 for(i = 0; i < n; i++)
1042 def->sorted_args[start + i] = start + i;
1045 for(i = 0; i < n - 1; i++) {
1046 for(j = i + 1; j < n; j++) {
1047 p1 = get_constraint_priority(def, def->sorted_args[start + i]);
1048 p2 = get_constraint_priority(def, def->sorted_args[start + j]);
1050 tmp = def->sorted_args[start + i];
1051 def->sorted_args[start + i] = def->sorted_args[start + j];
1052 def->sorted_args[start + j] = tmp;
1058 void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs)
1066 if (tdefs->op == (TCGOpcode)-1)
1069 assert((unsigned)op < NB_OPS);
1070 def = &tcg_op_defs[op];
1071 #if defined(CONFIG_DEBUG_TCG)
1072 /* Duplicate entry in op definitions? */
1076 nb_args = def->nb_iargs + def->nb_oargs;
1077 for(i = 0; i < nb_args; i++) {
1078 ct_str = tdefs->args_ct_str[i];
1079 /* Incomplete TCGTargetOpDef entry? */
1080 assert(ct_str != NULL);
1081 tcg_regset_clear(def->args_ct[i].u.regs);
1082 def->args_ct[i].ct = 0;
1083 if (ct_str[0] >= '0' && ct_str[0] <= '9') {
1085 oarg = ct_str[0] - '0';
1086 assert(oarg < def->nb_oargs);
1087 assert(def->args_ct[oarg].ct & TCG_CT_REG);
1088 /* TCG_CT_ALIAS is for the output arguments. The input
1089 argument is tagged with TCG_CT_IALIAS. */
1090 def->args_ct[i] = def->args_ct[oarg];
1091 def->args_ct[oarg].ct = TCG_CT_ALIAS;
1092 def->args_ct[oarg].alias_index = i;
1093 def->args_ct[i].ct |= TCG_CT_IALIAS;
1094 def->args_ct[i].alias_index = oarg;
1097 if (*ct_str == '\0')
1101 def->args_ct[i].ct |= TCG_CT_CONST;
1105 if (target_parse_constraint(&def->args_ct[i], &ct_str) < 0) {
1106 fprintf(stderr, "Invalid constraint '%s' for arg %d of operation '%s'\n",
1107 ct_str, i, def->name);
1115 /* TCGTargetOpDef entry with too much information? */
1116 assert(i == TCG_MAX_OP_ARGS || tdefs->args_ct_str[i] == NULL);
1118 /* sort the constraints (XXX: this is just an heuristic) */
1119 sort_constraints(def, 0, def->nb_oargs);
1120 sort_constraints(def, def->nb_oargs, def->nb_iargs);
1126 printf("%s: sorted=", def->name);
1127 for(i = 0; i < def->nb_oargs + def->nb_iargs; i++)
1128 printf(" %d", def->sorted_args[i]);
1135 #if defined(CONFIG_DEBUG_TCG)
1137 for (op = 0; op < ARRAY_SIZE(tcg_op_defs); op++) {
1138 const TCGOpDef *def = &tcg_op_defs[op];
1139 if (op < INDEX_op_call
1140 || op == INDEX_op_debug_insn_start
1141 || (def->flags & TCG_OPF_NOT_PRESENT)) {
1142 /* Wrong entry in op definitions? */
1144 fprintf(stderr, "Invalid op definition for %s\n", def->name);
1148 /* Missing entry in op definitions? */
1150 fprintf(stderr, "Missing op definition for %s\n", def->name);
1161 #ifdef USE_LIVENESS_ANALYSIS
1163 /* set a nop for an operation using 'nb_args' */
1164 static inline void tcg_set_nop(TCGContext *s, uint16_t *opc_ptr,
1165 TCGArg *args, int nb_args)
1168 *opc_ptr = INDEX_op_nop;
1170 *opc_ptr = INDEX_op_nopn;
1172 args[nb_args - 1] = nb_args;
1176 /* liveness analysis: end of function: globals are live, temps are
1178 /* XXX: at this stage, not used as there would be little gains because
1179 most TBs end with a conditional jump. */
1180 static inline void tcg_la_func_end(TCGContext *s, uint8_t *dead_temps)
1182 memset(dead_temps, 0, s->nb_globals);
1183 memset(dead_temps + s->nb_globals, 1, s->nb_temps - s->nb_globals);
1186 /* liveness analysis: end of basic block: globals are live, temps are
1187 dead, local temps are live. */
1188 static inline void tcg_la_bb_end(TCGContext *s, uint8_t *dead_temps)
1193 memset(dead_temps, 0, s->nb_globals);
1194 ts = &s->temps[s->nb_globals];
1195 for(i = s->nb_globals; i < s->nb_temps; i++) {
1204 /* Liveness analysis : update the opc_dead_args array to tell if a
1205 given input arguments is dead. Instructions updating dead
1206 temporaries are removed. */
1207 static void tcg_liveness_analysis(TCGContext *s)
1209 int i, op_index, nb_args, nb_iargs, nb_oargs, arg, nb_ops;
1212 const TCGOpDef *def;
1213 uint8_t *dead_temps;
1214 unsigned int dead_args;
1216 gen_opc_ptr++; /* skip end */
1218 nb_ops = gen_opc_ptr - gen_opc_buf;
1220 s->op_dead_args = tcg_malloc(nb_ops * sizeof(uint16_t));
1222 dead_temps = tcg_malloc(s->nb_temps);
1223 memset(dead_temps, 1, s->nb_temps);
1225 args = gen_opparam_ptr;
1226 op_index = nb_ops - 1;
1227 while (op_index >= 0) {
1228 op = gen_opc_buf[op_index];
1229 def = &tcg_op_defs[op];
1237 nb_iargs = args[0] & 0xffff;
1238 nb_oargs = args[0] >> 16;
1240 call_flags = args[nb_oargs + nb_iargs];
1242 /* pure functions can be removed if their result is not
1244 if (call_flags & TCG_CALL_PURE) {
1245 for(i = 0; i < nb_oargs; i++) {
1247 if (!dead_temps[arg])
1248 goto do_not_remove_call;
1250 tcg_set_nop(s, gen_opc_buf + op_index,
1255 /* output args are dead */
1257 for(i = 0; i < nb_oargs; i++) {
1259 if (dead_temps[arg]) {
1260 dead_args |= (1 << i);
1262 dead_temps[arg] = 1;
1265 if (!(call_flags & TCG_CALL_CONST)) {
1266 /* globals are live (they may be used by the call) */
1267 memset(dead_temps, 0, s->nb_globals);
1270 /* input args are live */
1271 for(i = nb_oargs; i < nb_iargs + nb_oargs; i++) {
1273 if (arg != TCG_CALL_DUMMY_ARG) {
1274 if (dead_temps[arg]) {
1275 dead_args |= (1 << i);
1277 dead_temps[arg] = 0;
1280 s->op_dead_args[op_index] = dead_args;
1285 case INDEX_op_set_label:
1287 /* mark end of basic block */
1288 tcg_la_bb_end(s, dead_temps);
1290 case INDEX_op_debug_insn_start:
1291 args -= def->nb_args;
1297 case INDEX_op_discard:
1299 /* mark the temporary as dead */
1300 dead_temps[args[0]] = 1;
1304 /* XXX: optimize by hardcoding common cases (e.g. triadic ops) */
1306 args -= def->nb_args;
1307 nb_iargs = def->nb_iargs;
1308 nb_oargs = def->nb_oargs;
1310 /* Test if the operation can be removed because all
1311 its outputs are dead. We assume that nb_oargs == 0
1312 implies side effects */
1313 if (!(def->flags & TCG_OPF_SIDE_EFFECTS) && nb_oargs != 0) {
1314 for(i = 0; i < nb_oargs; i++) {
1316 if (!dead_temps[arg])
1319 tcg_set_nop(s, gen_opc_buf + op_index, args, def->nb_args);
1320 #ifdef CONFIG_PROFILER
1326 /* output args are dead */
1328 for(i = 0; i < nb_oargs; i++) {
1330 if (dead_temps[arg]) {
1331 dead_args |= (1 << i);
1333 dead_temps[arg] = 1;
1336 /* if end of basic block, update */
1337 if (def->flags & TCG_OPF_BB_END) {
1338 tcg_la_bb_end(s, dead_temps);
1339 } else if (def->flags & TCG_OPF_CALL_CLOBBER) {
1340 /* globals are live */
1341 memset(dead_temps, 0, s->nb_globals);
1344 /* input args are live */
1345 for(i = nb_oargs; i < nb_oargs + nb_iargs; i++) {
1347 if (dead_temps[arg]) {
1348 dead_args |= (1 << i);
1350 dead_temps[arg] = 0;
1352 s->op_dead_args[op_index] = dead_args;
1359 if (args != gen_opparam_buf)
1363 /* dummy liveness analysis */
1364 static void tcg_liveness_analysis(TCGContext *s)
1367 nb_ops = gen_opc_ptr - gen_opc_buf;
1369 s->op_dead_args = tcg_malloc(nb_ops * sizeof(uint16_t));
1370 memset(s->op_dead_args, 0, nb_ops * sizeof(uint16_t));
1375 static void dump_regs(TCGContext *s)
1381 for(i = 0; i < s->nb_temps; i++) {
1383 printf(" %10s: ", tcg_get_arg_str_idx(s, buf, sizeof(buf), i));
1384 switch(ts->val_type) {
1386 printf("%s", tcg_target_reg_names[ts->reg]);
1389 printf("%d(%s)", (int)ts->mem_offset, tcg_target_reg_names[ts->mem_reg]);
1391 case TEMP_VAL_CONST:
1392 printf("$0x%" TCG_PRIlx, ts->val);
1404 for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
1405 if (s->reg_to_temp[i] >= 0) {
1407 tcg_target_reg_names[i],
1408 tcg_get_arg_str_idx(s, buf, sizeof(buf), s->reg_to_temp[i]));
1413 static void check_regs(TCGContext *s)
1419 for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1420 k = s->reg_to_temp[reg];
1423 if (ts->val_type != TEMP_VAL_REG ||
1425 printf("Inconsistency for register %s:\n",
1426 tcg_target_reg_names[reg]);
1431 for(k = 0; k < s->nb_temps; k++) {
1433 if (ts->val_type == TEMP_VAL_REG &&
1435 s->reg_to_temp[ts->reg] != k) {
1436 printf("Inconsistency for temp %s:\n",
1437 tcg_get_arg_str_idx(s, buf, sizeof(buf), k));
1439 printf("reg state:\n");
1447 static void temp_allocate_frame(TCGContext *s, int temp)
1450 ts = &s->temps[temp];
1451 #ifndef __sparc_v9__ /* Sparc64 stack is accessed with offset of 2047 */
1452 s->current_frame_offset = (s->current_frame_offset +
1453 (tcg_target_long)sizeof(tcg_target_long) - 1) &
1454 ~(sizeof(tcg_target_long) - 1);
1456 if (s->current_frame_offset + (tcg_target_long)sizeof(tcg_target_long) >
1460 ts->mem_offset = s->current_frame_offset;
1461 ts->mem_reg = s->frame_reg;
1462 ts->mem_allocated = 1;
1463 s->current_frame_offset += (tcg_target_long)sizeof(tcg_target_long);
1466 /* free register 'reg' by spilling the corresponding temporary if necessary */
1467 static void tcg_reg_free(TCGContext *s, int reg)
1472 temp = s->reg_to_temp[reg];
1474 ts = &s->temps[temp];
1475 assert(ts->val_type == TEMP_VAL_REG);
1476 if (!ts->mem_coherent) {
1477 if (!ts->mem_allocated)
1478 temp_allocate_frame(s, temp);
1479 tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1481 ts->val_type = TEMP_VAL_MEM;
1482 s->reg_to_temp[reg] = -1;
1486 /* Allocate a register belonging to reg1 & ~reg2 */
1487 static int tcg_reg_alloc(TCGContext *s, TCGRegSet reg1, TCGRegSet reg2)
1492 tcg_regset_andnot(reg_ct, reg1, reg2);
1494 /* first try free registers */
1495 for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1496 reg = tcg_target_reg_alloc_order[i];
1497 if (tcg_regset_test_reg(reg_ct, reg) && s->reg_to_temp[reg] == -1)
1501 /* XXX: do better spill choice */
1502 for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1503 reg = tcg_target_reg_alloc_order[i];
1504 if (tcg_regset_test_reg(reg_ct, reg)) {
1505 tcg_reg_free(s, reg);
1513 /* save a temporary to memory. 'allocated_regs' is used in case a
1514 temporary registers needs to be allocated to store a constant. */
1515 static void temp_save(TCGContext *s, int temp, TCGRegSet allocated_regs)
1520 ts = &s->temps[temp];
1521 if (!ts->fixed_reg) {
1522 switch(ts->val_type) {
1524 tcg_reg_free(s, ts->reg);
1527 ts->val_type = TEMP_VAL_MEM;
1529 case TEMP_VAL_CONST:
1530 reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type],
1532 if (!ts->mem_allocated)
1533 temp_allocate_frame(s, temp);
1534 tcg_out_movi(s, ts->type, reg, ts->val);
1535 tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1536 ts->val_type = TEMP_VAL_MEM;
1546 /* save globals to their canonical location and assume they can be
1547 modified be the following code. 'allocated_regs' is used in case a
1548 temporary registers needs to be allocated to store a constant. */
1549 static void save_globals(TCGContext *s, TCGRegSet allocated_regs)
1553 for(i = 0; i < s->nb_globals; i++) {
1554 temp_save(s, i, allocated_regs);
1558 /* at the end of a basic block, we assume all temporaries are dead and
1559 all globals are stored at their canonical location. */
1560 static void tcg_reg_alloc_bb_end(TCGContext *s, TCGRegSet allocated_regs)
1565 for(i = s->nb_globals; i < s->nb_temps; i++) {
1567 if (ts->temp_local) {
1568 temp_save(s, i, allocated_regs);
1570 if (ts->val_type == TEMP_VAL_REG) {
1571 s->reg_to_temp[ts->reg] = -1;
1573 ts->val_type = TEMP_VAL_DEAD;
1577 save_globals(s, allocated_regs);
1580 #define IS_DEAD_ARG(n) ((dead_args >> (n)) & 1)
1582 static void tcg_reg_alloc_movi(TCGContext *s, const TCGArg *args)
1585 tcg_target_ulong val;
1587 ots = &s->temps[args[0]];
1590 if (ots->fixed_reg) {
1591 /* for fixed registers, we do not do any constant
1593 tcg_out_movi(s, ots->type, ots->reg, val);
1595 /* The movi is not explicitly generated here */
1596 if (ots->val_type == TEMP_VAL_REG)
1597 s->reg_to_temp[ots->reg] = -1;
1598 ots->val_type = TEMP_VAL_CONST;
1603 static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
1605 unsigned int dead_args)
1609 const TCGArgConstraint *arg_ct;
1611 ots = &s->temps[args[0]];
1612 ts = &s->temps[args[1]];
1613 arg_ct = &def->args_ct[0];
1615 /* XXX: always mark arg dead if IS_DEAD_ARG(1) */
1616 if (ts->val_type == TEMP_VAL_REG) {
1617 if (IS_DEAD_ARG(1) && !ts->fixed_reg && !ots->fixed_reg) {
1618 /* the mov can be suppressed */
1619 if (ots->val_type == TEMP_VAL_REG)
1620 s->reg_to_temp[ots->reg] = -1;
1622 s->reg_to_temp[reg] = -1;
1623 ts->val_type = TEMP_VAL_DEAD;
1625 if (ots->val_type == TEMP_VAL_REG) {
1628 reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1630 if (ts->reg != reg) {
1631 tcg_out_mov(s, ots->type, reg, ts->reg);
1634 } else if (ts->val_type == TEMP_VAL_MEM) {
1635 if (ots->val_type == TEMP_VAL_REG) {
1638 reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1640 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1641 } else if (ts->val_type == TEMP_VAL_CONST) {
1642 if (ots->fixed_reg) {
1644 tcg_out_movi(s, ots->type, reg, ts->val);
1646 /* propagate constant */
1647 if (ots->val_type == TEMP_VAL_REG)
1648 s->reg_to_temp[ots->reg] = -1;
1649 ots->val_type = TEMP_VAL_CONST;
1656 s->reg_to_temp[reg] = args[0];
1658 ots->val_type = TEMP_VAL_REG;
1659 ots->mem_coherent = 0;
1662 static void tcg_reg_alloc_op(TCGContext *s,
1663 const TCGOpDef *def, TCGOpcode opc,
1665 unsigned int dead_args)
1667 TCGRegSet allocated_regs;
1668 int i, k, nb_iargs, nb_oargs, reg;
1670 const TCGArgConstraint *arg_ct;
1672 TCGArg new_args[TCG_MAX_OP_ARGS];
1673 int const_args[TCG_MAX_OP_ARGS];
1675 nb_oargs = def->nb_oargs;
1676 nb_iargs = def->nb_iargs;
1678 /* copy constants */
1679 memcpy(new_args + nb_oargs + nb_iargs,
1680 args + nb_oargs + nb_iargs,
1681 sizeof(TCGArg) * def->nb_cargs);
1683 /* satisfy input constraints */
1684 tcg_regset_set(allocated_regs, s->reserved_regs);
1685 for(k = 0; k < nb_iargs; k++) {
1686 i = def->sorted_args[nb_oargs + k];
1688 arg_ct = &def->args_ct[i];
1689 ts = &s->temps[arg];
1690 if (ts->val_type == TEMP_VAL_MEM) {
1691 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1692 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1693 ts->val_type = TEMP_VAL_REG;
1695 ts->mem_coherent = 1;
1696 s->reg_to_temp[reg] = arg;
1697 } else if (ts->val_type == TEMP_VAL_CONST) {
1698 if (tcg_target_const_match(ts->val, arg_ct)) {
1699 /* constant is OK for instruction */
1701 new_args[i] = ts->val;
1704 /* need to move to a register */
1705 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1706 tcg_out_movi(s, ts->type, reg, ts->val);
1707 ts->val_type = TEMP_VAL_REG;
1709 ts->mem_coherent = 0;
1710 s->reg_to_temp[reg] = arg;
1713 assert(ts->val_type == TEMP_VAL_REG);
1714 if (arg_ct->ct & TCG_CT_IALIAS) {
1715 if (ts->fixed_reg) {
1716 /* if fixed register, we must allocate a new register
1717 if the alias is not the same register */
1718 if (arg != args[arg_ct->alias_index])
1719 goto allocate_in_reg;
1721 /* if the input is aliased to an output and if it is
1722 not dead after the instruction, we must allocate
1723 a new register and move it */
1724 if (!IS_DEAD_ARG(i)) {
1725 goto allocate_in_reg;
1730 if (tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1731 /* nothing to do : the constraint is satisfied */
1734 /* allocate a new register matching the constraint
1735 and move the temporary register into it */
1736 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1737 tcg_out_mov(s, ts->type, reg, ts->reg);
1741 tcg_regset_set_reg(allocated_regs, reg);
1745 if (def->flags & TCG_OPF_BB_END) {
1746 tcg_reg_alloc_bb_end(s, allocated_regs);
1748 /* mark dead temporaries and free the associated registers */
1749 for(i = nb_oargs; i < nb_oargs + nb_iargs; i++) {
1751 if (IS_DEAD_ARG(i)) {
1752 ts = &s->temps[arg];
1753 if (!ts->fixed_reg) {
1754 if (ts->val_type == TEMP_VAL_REG)
1755 s->reg_to_temp[ts->reg] = -1;
1756 ts->val_type = TEMP_VAL_DEAD;
1761 if (def->flags & TCG_OPF_CALL_CLOBBER) {
1762 /* XXX: permit generic clobber register list ? */
1763 for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1764 if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
1765 tcg_reg_free(s, reg);
1768 /* XXX: for load/store we could do that only for the slow path
1769 (i.e. when a memory callback is called) */
1771 /* store globals and free associated registers (we assume the insn
1772 can modify any global. */
1773 save_globals(s, allocated_regs);
1776 /* satisfy the output constraints */
1777 tcg_regset_set(allocated_regs, s->reserved_regs);
1778 for(k = 0; k < nb_oargs; k++) {
1779 i = def->sorted_args[k];
1781 arg_ct = &def->args_ct[i];
1782 ts = &s->temps[arg];
1783 if (arg_ct->ct & TCG_CT_ALIAS) {
1784 reg = new_args[arg_ct->alias_index];
1786 /* if fixed register, we try to use it */
1788 if (ts->fixed_reg &&
1789 tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1792 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1794 tcg_regset_set_reg(allocated_regs, reg);
1795 /* if a fixed register is used, then a move will be done afterwards */
1796 if (!ts->fixed_reg) {
1797 if (ts->val_type == TEMP_VAL_REG)
1798 s->reg_to_temp[ts->reg] = -1;
1799 if (IS_DEAD_ARG(i)) {
1800 ts->val_type = TEMP_VAL_DEAD;
1802 ts->val_type = TEMP_VAL_REG;
1804 /* temp value is modified, so the value kept in memory is
1805 potentially not the same */
1806 ts->mem_coherent = 0;
1807 s->reg_to_temp[reg] = arg;
1815 /* emit instruction */
1816 tcg_out_op(s, opc, new_args, const_args);
1818 /* move the outputs in the correct register if needed */
1819 for(i = 0; i < nb_oargs; i++) {
1820 ts = &s->temps[args[i]];
1822 if (ts->fixed_reg && ts->reg != reg) {
1823 tcg_out_mov(s, ts->type, ts->reg, reg);
1828 #ifdef TCG_TARGET_STACK_GROWSUP
1829 #define STACK_DIR(x) (-(x))
1831 #define STACK_DIR(x) (x)
1834 static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
1835 TCGOpcode opc, const TCGArg *args,
1836 unsigned int dead_args)
1838 int nb_iargs, nb_oargs, flags, nb_regs, i, reg, nb_params;
1839 TCGArg arg, func_arg;
1841 tcg_target_long stack_offset, call_stack_size, func_addr;
1842 int const_func_arg, allocate_args;
1843 TCGRegSet allocated_regs;
1844 const TCGArgConstraint *arg_ct;
1848 nb_oargs = arg >> 16;
1849 nb_iargs = arg & 0xffff;
1850 nb_params = nb_iargs - 1;
1852 flags = args[nb_oargs + nb_iargs];
1854 nb_regs = tcg_target_get_call_iarg_regs_count(flags);
1855 if (nb_regs > nb_params)
1856 nb_regs = nb_params;
1858 /* assign stack slots first */
1859 call_stack_size = (nb_params - nb_regs) * sizeof(tcg_target_long);
1860 call_stack_size = (call_stack_size + TCG_TARGET_STACK_ALIGN - 1) &
1861 ~(TCG_TARGET_STACK_ALIGN - 1);
1862 allocate_args = (call_stack_size > TCG_STATIC_CALL_ARGS_SIZE);
1863 if (allocate_args) {
1864 /* XXX: if more than TCG_STATIC_CALL_ARGS_SIZE is needed,
1865 preallocate call stack */
1869 stack_offset = TCG_TARGET_CALL_STACK_OFFSET;
1870 for(i = nb_regs; i < nb_params; i++) {
1871 arg = args[nb_oargs + i];
1872 #ifdef TCG_TARGET_STACK_GROWSUP
1873 stack_offset -= sizeof(tcg_target_long);
1875 if (arg != TCG_CALL_DUMMY_ARG) {
1876 ts = &s->temps[arg];
1877 if (ts->val_type == TEMP_VAL_REG) {
1878 tcg_out_st(s, ts->type, ts->reg, TCG_REG_CALL_STACK, stack_offset);
1879 } else if (ts->val_type == TEMP_VAL_MEM) {
1880 reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type],
1882 /* XXX: not correct if reading values from the stack */
1883 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1884 tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
1885 } else if (ts->val_type == TEMP_VAL_CONST) {
1886 reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type],
1888 /* XXX: sign extend may be needed on some targets */
1889 tcg_out_movi(s, ts->type, reg, ts->val);
1890 tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
1895 #ifndef TCG_TARGET_STACK_GROWSUP
1896 stack_offset += sizeof(tcg_target_long);
1900 /* assign input registers */
1901 tcg_regset_set(allocated_regs, s->reserved_regs);
1902 for(i = 0; i < nb_regs; i++) {
1903 arg = args[nb_oargs + i];
1904 if (arg != TCG_CALL_DUMMY_ARG) {
1905 ts = &s->temps[arg];
1906 reg = tcg_target_call_iarg_regs[i];
1907 tcg_reg_free(s, reg);
1908 if (ts->val_type == TEMP_VAL_REG) {
1909 if (ts->reg != reg) {
1910 tcg_out_mov(s, ts->type, reg, ts->reg);
1912 } else if (ts->val_type == TEMP_VAL_MEM) {
1913 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1914 } else if (ts->val_type == TEMP_VAL_CONST) {
1915 /* XXX: sign extend ? */
1916 tcg_out_movi(s, ts->type, reg, ts->val);
1920 tcg_regset_set_reg(allocated_regs, reg);
1924 /* assign function address */
1925 func_arg = args[nb_oargs + nb_iargs - 1];
1926 arg_ct = &def->args_ct[0];
1927 ts = &s->temps[func_arg];
1928 func_addr = ts->val;
1930 if (ts->val_type == TEMP_VAL_MEM) {
1931 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1932 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1934 tcg_regset_set_reg(allocated_regs, reg);
1935 } else if (ts->val_type == TEMP_VAL_REG) {
1937 if (!tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1938 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1939 tcg_out_mov(s, ts->type, reg, ts->reg);
1942 tcg_regset_set_reg(allocated_regs, reg);
1943 } else if (ts->val_type == TEMP_VAL_CONST) {
1944 if (tcg_target_const_match(func_addr, arg_ct)) {
1946 func_arg = func_addr;
1948 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1949 tcg_out_movi(s, ts->type, reg, func_addr);
1951 tcg_regset_set_reg(allocated_regs, reg);
1958 /* mark dead temporaries and free the associated registers */
1959 for(i = nb_oargs; i < nb_iargs + nb_oargs; i++) {
1961 if (IS_DEAD_ARG(i)) {
1962 ts = &s->temps[arg];
1963 if (!ts->fixed_reg) {
1964 if (ts->val_type == TEMP_VAL_REG)
1965 s->reg_to_temp[ts->reg] = -1;
1966 ts->val_type = TEMP_VAL_DEAD;
1971 /* clobber call registers */
1972 for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1973 if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
1974 tcg_reg_free(s, reg);
1978 /* store globals and free associated registers (we assume the call
1979 can modify any global. */
1980 if (!(flags & TCG_CALL_CONST)) {
1981 save_globals(s, allocated_regs);
1984 tcg_out_op(s, opc, &func_arg, &const_func_arg);
1986 /* assign output registers and emit moves if needed */
1987 for(i = 0; i < nb_oargs; i++) {
1989 ts = &s->temps[arg];
1990 reg = tcg_target_call_oarg_regs[i];
1991 assert(s->reg_to_temp[reg] == -1);
1992 if (ts->fixed_reg) {
1993 if (ts->reg != reg) {
1994 tcg_out_mov(s, ts->type, ts->reg, reg);
1997 if (ts->val_type == TEMP_VAL_REG)
1998 s->reg_to_temp[ts->reg] = -1;
1999 if (IS_DEAD_ARG(i)) {
2000 ts->val_type = TEMP_VAL_DEAD;
2002 ts->val_type = TEMP_VAL_REG;
2004 ts->mem_coherent = 0;
2005 s->reg_to_temp[reg] = arg;
2010 return nb_iargs + nb_oargs + def->nb_cargs + 1;
2013 #ifdef CONFIG_PROFILER
2015 static int64_t tcg_table_op_count[NB_OPS];
2017 static void dump_op_count(void)
2021 f = fopen("/tmp/op.log", "w");
2022 for(i = INDEX_op_end; i < NB_OPS; i++) {
2023 fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name, tcg_table_op_count[i]);
2030 static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
2035 const TCGOpDef *def;
2036 unsigned int dead_args;
2040 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
2042 tcg_dump_ops(s, logfile);
2047 #ifdef USE_TCG_OPTIMIZATIONS
2049 tcg_optimize(s, gen_opc_ptr, gen_opparam_buf, tcg_op_defs);
2052 #ifdef CONFIG_PROFILER
2053 s->la_time -= profile_getclock();
2055 tcg_liveness_analysis(s);
2056 #ifdef CONFIG_PROFILER
2057 s->la_time += profile_getclock();
2061 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_OPT))) {
2062 qemu_log("OP after liveness analysis:\n");
2063 tcg_dump_ops(s, logfile);
2068 tcg_reg_alloc_start(s);
2070 s->code_buf = gen_code_buf;
2071 s->code_ptr = gen_code_buf;
2073 args = gen_opparam_buf;
2077 opc = gen_opc_buf[op_index];
2078 #ifdef CONFIG_PROFILER
2079 tcg_table_op_count[opc]++;
2081 def = &tcg_op_defs[opc];
2083 printf("%s: %d %d %d\n", def->name,
2084 def->nb_oargs, def->nb_iargs, def->nb_cargs);
2088 case INDEX_op_mov_i32:
2089 #if TCG_TARGET_REG_BITS == 64
2090 case INDEX_op_mov_i64:
2092 dead_args = s->op_dead_args[op_index];
2093 tcg_reg_alloc_mov(s, def, args, dead_args);
2095 case INDEX_op_movi_i32:
2096 #if TCG_TARGET_REG_BITS == 64
2097 case INDEX_op_movi_i64:
2099 tcg_reg_alloc_movi(s, args);
2101 case INDEX_op_debug_insn_start:
2102 /* debug instruction */
2112 case INDEX_op_discard:
2115 ts = &s->temps[args[0]];
2116 /* mark the temporary as dead */
2117 if (!ts->fixed_reg) {
2118 if (ts->val_type == TEMP_VAL_REG)
2119 s->reg_to_temp[ts->reg] = -1;
2120 ts->val_type = TEMP_VAL_DEAD;
2124 case INDEX_op_set_label:
2125 tcg_reg_alloc_bb_end(s, s->reserved_regs);
2126 tcg_out_label(s, args[0], (long)s->code_ptr);
2129 dead_args = s->op_dead_args[op_index];
2130 args += tcg_reg_alloc_call(s, def, opc, args, dead_args);
2135 /* Sanity check that we've not introduced any unhandled opcodes. */
2136 if (def->flags & TCG_OPF_NOT_PRESENT) {
2139 /* Note: in order to speed up the code, it would be much
2140 faster to have specialized register allocator functions for
2141 some common argument patterns */
2142 dead_args = s->op_dead_args[op_index];
2143 tcg_reg_alloc_op(s, def, opc, args, dead_args);
2146 args += def->nb_args;
2148 if (search_pc >= 0 && search_pc < s->code_ptr - gen_code_buf) {
2160 int tcg_gen_code(TCGContext *s, uint8_t *gen_code_buf)
2162 #ifdef CONFIG_PROFILER
2165 n = (gen_opc_ptr - gen_opc_buf);
2167 if (n > s->op_count_max)
2168 s->op_count_max = n;
2170 s->temp_count += s->nb_temps;
2171 if (s->nb_temps > s->temp_count_max)
2172 s->temp_count_max = s->nb_temps;
2176 tcg_gen_code_common(s, gen_code_buf, -1);
2178 /* flush instruction cache */
2179 flush_icache_range((unsigned long)gen_code_buf,
2180 (unsigned long)s->code_ptr);
2181 return s->code_ptr - gen_code_buf;
2184 /* Return the index of the micro operation such as the pc after is <
2185 offset bytes from the start of the TB. The contents of gen_code_buf must
2186 not be changed, though writing the same values is ok.
2187 Return -1 if not found. */
2188 int tcg_gen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, long offset)
2190 return tcg_gen_code_common(s, gen_code_buf, offset);
2193 #ifdef CONFIG_PROFILER
2194 void tcg_dump_info(FILE *f, fprintf_function cpu_fprintf)
2196 TCGContext *s = &tcg_ctx;
2199 tot = s->interm_time + s->code_time;
2200 cpu_fprintf(f, "JIT cycles %" PRId64 " (%0.3f s at 2.4 GHz)\n",
2202 cpu_fprintf(f, "translated TBs %" PRId64 " (aborted=%" PRId64 " %0.1f%%)\n",
2204 s->tb_count1 - s->tb_count,
2205 s->tb_count1 ? (double)(s->tb_count1 - s->tb_count) / s->tb_count1 * 100.0 : 0);
2206 cpu_fprintf(f, "avg ops/TB %0.1f max=%d\n",
2207 s->tb_count ? (double)s->op_count / s->tb_count : 0, s->op_count_max);
2208 cpu_fprintf(f, "deleted ops/TB %0.2f\n",
2210 (double)s->del_op_count / s->tb_count : 0);
2211 cpu_fprintf(f, "avg temps/TB %0.2f max=%d\n",
2213 (double)s->temp_count / s->tb_count : 0,
2216 cpu_fprintf(f, "cycles/op %0.1f\n",
2217 s->op_count ? (double)tot / s->op_count : 0);
2218 cpu_fprintf(f, "cycles/in byte %0.1f\n",
2219 s->code_in_len ? (double)tot / s->code_in_len : 0);
2220 cpu_fprintf(f, "cycles/out byte %0.1f\n",
2221 s->code_out_len ? (double)tot / s->code_out_len : 0);
2224 cpu_fprintf(f, " gen_interm time %0.1f%%\n",
2225 (double)s->interm_time / tot * 100.0);
2226 cpu_fprintf(f, " gen_code time %0.1f%%\n",
2227 (double)s->code_time / tot * 100.0);
2228 cpu_fprintf(f, "liveness/code time %0.1f%%\n",
2229 (double)s->la_time / (s->code_time ? s->code_time : 1) * 100.0);
2230 cpu_fprintf(f, "cpu_restore count %" PRId64 "\n",
2232 cpu_fprintf(f, " avg cycles %0.1f\n",
2233 s->restore_count ? (double)s->restore_time / s->restore_count : 0);
2238 void tcg_dump_info(FILE *f, fprintf_function cpu_fprintf)
2240 cpu_fprintf(f, "[TCG profiler not compiled]\n");