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) */
48 #include "qemu-common.h"
49 #include "cache-utils.h"
50 #include "host-utils.h"
51 #include "qemu-timer.h"
53 /* Note: the long term plan is to reduce the dependancies on the QEMU
54 CPU definitions. Currently they are used for qemu_ld/st
56 #define NO_CPU_IO_DEFS
62 #if defined(CONFIG_USE_GUEST_BASE) && !defined(TCG_TARGET_HAS_GUEST_BASE)
63 #error GUEST_BASE not supported on this host.
66 /* Forward declarations for functions declared in tcg-target.c and used here. */
67 static void tcg_target_init(TCGContext
*s
);
68 static void tcg_target_qemu_prologue(TCGContext
*s
);
69 static void patch_reloc(uint8_t *code_ptr
, int type
,
70 tcg_target_long value
, tcg_target_long addend
);
72 /* Forward declarations for functions declared and used in tcg-target.c. */
73 static int target_parse_constraint(TCGArgConstraint
*ct
, const char **pct_str
);
74 static void tcg_out_ld(TCGContext
*s
, TCGType type
, int ret
, int arg1
,
75 tcg_target_long arg2
);
76 static void tcg_out_mov(TCGContext
*s
, TCGType type
, int ret
, int arg
);
77 static void tcg_out_movi(TCGContext
*s
, TCGType type
,
78 int ret
, tcg_target_long arg
);
79 static void tcg_out_op(TCGContext
*s
, TCGOpcode opc
, const TCGArg
*args
,
80 const int *const_args
);
81 static void tcg_out_st(TCGContext
*s
, TCGType type
, int arg
, int arg1
,
82 tcg_target_long arg2
);
83 static int tcg_target_const_match(tcg_target_long val
,
84 const TCGArgConstraint
*arg_ct
);
85 static int tcg_target_get_call_iarg_regs_count(int flags
);
87 TCGOpDef tcg_op_defs
[] = {
88 #define DEF(s, oargs, iargs, cargs, flags) { #s, oargs, iargs, cargs, iargs + oargs + cargs, flags },
93 static TCGRegSet tcg_target_available_regs
[2];
94 static TCGRegSet tcg_target_call_clobber_regs
;
96 /* XXX: move that inside the context */
97 uint16_t *gen_opc_ptr
;
98 TCGArg
*gen_opparam_ptr
;
100 static inline void tcg_out8(TCGContext
*s
, uint8_t v
)
105 static inline void tcg_out16(TCGContext
*s
, uint16_t v
)
107 *(uint16_t *)s
->code_ptr
= v
;
111 static inline void tcg_out32(TCGContext
*s
, uint32_t v
)
113 *(uint32_t *)s
->code_ptr
= v
;
117 /* label relocation processing */
119 static void tcg_out_reloc(TCGContext
*s
, uint8_t *code_ptr
, int type
,
120 int label_index
, long addend
)
125 l
= &s
->labels
[label_index
];
127 /* FIXME: This may break relocations on RISC targets that
128 modify instruction fields in place. The caller may not have
129 written the initial value. */
130 patch_reloc(code_ptr
, type
, l
->u
.value
, addend
);
132 /* add a new relocation entry */
133 r
= tcg_malloc(sizeof(TCGRelocation
));
137 r
->next
= l
->u
.first_reloc
;
138 l
->u
.first_reloc
= r
;
142 static void tcg_out_label(TCGContext
*s
, int label_index
,
143 tcg_target_long value
)
148 l
= &s
->labels
[label_index
];
151 r
= l
->u
.first_reloc
;
153 patch_reloc(r
->ptr
, r
->type
, value
, r
->addend
);
160 int gen_new_label(void)
162 TCGContext
*s
= &tcg_ctx
;
166 if (s
->nb_labels
>= TCG_MAX_LABELS
)
168 idx
= s
->nb_labels
++;
171 l
->u
.first_reloc
= NULL
;
175 #include "tcg-target.c"
177 /* pool based memory allocation */
178 void *tcg_malloc_internal(TCGContext
*s
, int size
)
183 if (size
> TCG_POOL_CHUNK_SIZE
) {
184 /* big malloc: insert a new pool (XXX: could optimize) */
185 p
= g_malloc(sizeof(TCGPool
) + size
);
188 s
->pool_current
->next
= p
;
191 p
->next
= s
->pool_current
;
201 pool_size
= TCG_POOL_CHUNK_SIZE
;
202 p
= g_malloc(sizeof(TCGPool
) + pool_size
);
206 s
->pool_current
->next
= p
;
215 s
->pool_cur
= p
->data
+ size
;
216 s
->pool_end
= p
->data
+ p
->size
;
220 void tcg_pool_reset(TCGContext
*s
)
222 s
->pool_cur
= s
->pool_end
= NULL
;
223 s
->pool_current
= NULL
;
226 void tcg_context_init(TCGContext
*s
)
228 int op
, total_args
, n
;
230 TCGArgConstraint
*args_ct
;
233 memset(s
, 0, sizeof(*s
));
234 s
->temps
= s
->static_temps
;
237 /* Count total number of arguments and allocate the corresponding
240 for(op
= 0; op
< NB_OPS
; op
++) {
241 def
= &tcg_op_defs
[op
];
242 n
= def
->nb_iargs
+ def
->nb_oargs
;
246 args_ct
= g_malloc(sizeof(TCGArgConstraint
) * total_args
);
247 sorted_args
= g_malloc(sizeof(int) * total_args
);
249 for(op
= 0; op
< NB_OPS
; op
++) {
250 def
= &tcg_op_defs
[op
];
251 def
->args_ct
= args_ct
;
252 def
->sorted_args
= sorted_args
;
253 n
= def
->nb_iargs
+ def
->nb_oargs
;
261 void tcg_prologue_init(TCGContext
*s
)
263 /* init global prologue and epilogue */
264 s
->code_buf
= code_gen_prologue
;
265 s
->code_ptr
= s
->code_buf
;
266 tcg_target_qemu_prologue(s
);
267 flush_icache_range((unsigned long)s
->code_buf
,
268 (unsigned long)s
->code_ptr
);
271 void tcg_set_frame(TCGContext
*s
, int reg
,
272 tcg_target_long start
, tcg_target_long size
)
274 s
->frame_start
= start
;
275 s
->frame_end
= start
+ size
;
279 void tcg_func_start(TCGContext
*s
)
283 s
->nb_temps
= s
->nb_globals
;
284 for(i
= 0; i
< (TCG_TYPE_COUNT
* 2); i
++)
285 s
->first_free_temp
[i
] = -1;
286 s
->labels
= tcg_malloc(sizeof(TCGLabel
) * TCG_MAX_LABELS
);
288 s
->current_frame_offset
= s
->frame_start
;
290 gen_opc_ptr
= gen_opc_buf
;
291 gen_opparam_ptr
= gen_opparam_buf
;
294 static inline void tcg_temp_alloc(TCGContext
*s
, int n
)
296 if (n
> TCG_MAX_TEMPS
)
300 static inline int tcg_global_reg_new_internal(TCGType type
, int reg
,
303 TCGContext
*s
= &tcg_ctx
;
307 #if TCG_TARGET_REG_BITS == 32
308 if (type
!= TCG_TYPE_I32
)
311 if (tcg_regset_test_reg(s
->reserved_regs
, reg
))
314 tcg_temp_alloc(s
, s
->nb_globals
+ 1);
315 ts
= &s
->temps
[s
->nb_globals
];
316 ts
->base_type
= type
;
322 tcg_regset_set_reg(s
->reserved_regs
, reg
);
326 TCGv_i32
tcg_global_reg_new_i32(int reg
, const char *name
)
330 idx
= tcg_global_reg_new_internal(TCG_TYPE_I32
, reg
, name
);
331 return MAKE_TCGV_I32(idx
);
334 TCGv_i64
tcg_global_reg_new_i64(int reg
, const char *name
)
338 idx
= tcg_global_reg_new_internal(TCG_TYPE_I64
, reg
, name
);
339 return MAKE_TCGV_I64(idx
);
342 static inline int tcg_global_mem_new_internal(TCGType type
, int reg
,
343 tcg_target_long offset
,
346 TCGContext
*s
= &tcg_ctx
;
351 #if TCG_TARGET_REG_BITS == 32
352 if (type
== TCG_TYPE_I64
) {
354 tcg_temp_alloc(s
, s
->nb_globals
+ 2);
355 ts
= &s
->temps
[s
->nb_globals
];
356 ts
->base_type
= type
;
357 ts
->type
= TCG_TYPE_I32
;
359 ts
->mem_allocated
= 1;
361 #ifdef TCG_TARGET_WORDS_BIGENDIAN
362 ts
->mem_offset
= offset
+ 4;
364 ts
->mem_offset
= offset
;
366 pstrcpy(buf
, sizeof(buf
), name
);
367 pstrcat(buf
, sizeof(buf
), "_0");
368 ts
->name
= strdup(buf
);
371 ts
->base_type
= type
;
372 ts
->type
= TCG_TYPE_I32
;
374 ts
->mem_allocated
= 1;
376 #ifdef TCG_TARGET_WORDS_BIGENDIAN
377 ts
->mem_offset
= offset
;
379 ts
->mem_offset
= offset
+ 4;
381 pstrcpy(buf
, sizeof(buf
), name
);
382 pstrcat(buf
, sizeof(buf
), "_1");
383 ts
->name
= strdup(buf
);
389 tcg_temp_alloc(s
, s
->nb_globals
+ 1);
390 ts
= &s
->temps
[s
->nb_globals
];
391 ts
->base_type
= type
;
394 ts
->mem_allocated
= 1;
396 ts
->mem_offset
= offset
;
403 TCGv_i32
tcg_global_mem_new_i32(int reg
, tcg_target_long offset
,
408 idx
= tcg_global_mem_new_internal(TCG_TYPE_I32
, reg
, offset
, name
);
409 return MAKE_TCGV_I32(idx
);
412 TCGv_i64
tcg_global_mem_new_i64(int reg
, tcg_target_long offset
,
417 idx
= tcg_global_mem_new_internal(TCG_TYPE_I64
, reg
, offset
, name
);
418 return MAKE_TCGV_I64(idx
);
421 static inline int tcg_temp_new_internal(TCGType type
, int temp_local
)
423 TCGContext
*s
= &tcg_ctx
;
430 idx
= s
->first_free_temp
[k
];
432 /* There is already an available temp with the
435 s
->first_free_temp
[k
] = ts
->next_free_temp
;
436 ts
->temp_allocated
= 1;
437 assert(ts
->temp_local
== temp_local
);
440 #if TCG_TARGET_REG_BITS == 32
441 if (type
== TCG_TYPE_I64
) {
442 tcg_temp_alloc(s
, s
->nb_temps
+ 2);
443 ts
= &s
->temps
[s
->nb_temps
];
444 ts
->base_type
= type
;
445 ts
->type
= TCG_TYPE_I32
;
446 ts
->temp_allocated
= 1;
447 ts
->temp_local
= temp_local
;
450 ts
->base_type
= TCG_TYPE_I32
;
451 ts
->type
= TCG_TYPE_I32
;
452 ts
->temp_allocated
= 1;
453 ts
->temp_local
= temp_local
;
459 tcg_temp_alloc(s
, s
->nb_temps
+ 1);
460 ts
= &s
->temps
[s
->nb_temps
];
461 ts
->base_type
= type
;
463 ts
->temp_allocated
= 1;
464 ts
->temp_local
= temp_local
;
470 #if defined(CONFIG_DEBUG_TCG)
476 TCGv_i32
tcg_temp_new_internal_i32(int temp_local
)
480 idx
= tcg_temp_new_internal(TCG_TYPE_I32
, temp_local
);
481 return MAKE_TCGV_I32(idx
);
484 TCGv_i64
tcg_temp_new_internal_i64(int temp_local
)
488 idx
= tcg_temp_new_internal(TCG_TYPE_I64
, temp_local
);
489 return MAKE_TCGV_I64(idx
);
492 static inline void tcg_temp_free_internal(int idx
)
494 TCGContext
*s
= &tcg_ctx
;
498 #if defined(CONFIG_DEBUG_TCG)
500 if (s
->temps_in_use
< 0) {
501 fprintf(stderr
, "More temporaries freed than allocated!\n");
505 assert(idx
>= s
->nb_globals
&& idx
< s
->nb_temps
);
507 assert(ts
->temp_allocated
!= 0);
508 ts
->temp_allocated
= 0;
512 ts
->next_free_temp
= s
->first_free_temp
[k
];
513 s
->first_free_temp
[k
] = idx
;
516 void tcg_temp_free_i32(TCGv_i32 arg
)
518 tcg_temp_free_internal(GET_TCGV_I32(arg
));
521 void tcg_temp_free_i64(TCGv_i64 arg
)
523 tcg_temp_free_internal(GET_TCGV_I64(arg
));
526 TCGv_i32
tcg_const_i32(int32_t val
)
529 t0
= tcg_temp_new_i32();
530 tcg_gen_movi_i32(t0
, val
);
534 TCGv_i64
tcg_const_i64(int64_t val
)
537 t0
= tcg_temp_new_i64();
538 tcg_gen_movi_i64(t0
, val
);
542 TCGv_i32
tcg_const_local_i32(int32_t val
)
545 t0
= tcg_temp_local_new_i32();
546 tcg_gen_movi_i32(t0
, val
);
550 TCGv_i64
tcg_const_local_i64(int64_t val
)
553 t0
= tcg_temp_local_new_i64();
554 tcg_gen_movi_i64(t0
, val
);
558 #if defined(CONFIG_DEBUG_TCG)
559 void tcg_clear_temp_count(void)
561 TCGContext
*s
= &tcg_ctx
;
565 int tcg_check_temp_count(void)
567 TCGContext
*s
= &tcg_ctx
;
568 if (s
->temps_in_use
) {
569 /* Clear the count so that we don't give another
570 * warning immediately next time around.
579 void tcg_register_helper(void *func
, const char *name
)
581 TCGContext
*s
= &tcg_ctx
;
583 if ((s
->nb_helpers
+ 1) > s
->allocated_helpers
) {
584 n
= s
->allocated_helpers
;
590 s
->helpers
= realloc(s
->helpers
, n
* sizeof(TCGHelperInfo
));
591 s
->allocated_helpers
= n
;
593 s
->helpers
[s
->nb_helpers
].func
= (tcg_target_ulong
)func
;
594 s
->helpers
[s
->nb_helpers
].name
= name
;
598 /* Note: we convert the 64 bit args to 32 bit and do some alignment
599 and endian swap. Maybe it would be better to do the alignment
600 and endian swap in tcg_reg_alloc_call(). */
601 void tcg_gen_callN(TCGContext
*s
, TCGv_ptr func
, unsigned int flags
,
602 int sizemask
, TCGArg ret
, int nargs
, TCGArg
*args
)
604 #if defined(TCG_TARGET_I386) && TCG_TARGET_REG_BITS < 64
612 #if defined(TCG_TARGET_EXTEND_ARGS) && TCG_TARGET_REG_BITS == 64
613 for (i
= 0; i
< nargs
; ++i
) {
614 int is_64bit
= sizemask
& (1 << (i
+1)*2);
615 int is_signed
= sizemask
& (2 << (i
+1)*2);
617 TCGv_i64 temp
= tcg_temp_new_i64();
618 TCGv_i64 orig
= MAKE_TCGV_I64(args
[i
]);
620 tcg_gen_ext32s_i64(temp
, orig
);
622 tcg_gen_ext32u_i64(temp
, orig
);
624 args
[i
] = GET_TCGV_I64(temp
);
627 #endif /* TCG_TARGET_EXTEND_ARGS */
629 *gen_opc_ptr
++ = INDEX_op_call
;
630 nparam
= gen_opparam_ptr
++;
631 #if defined(TCG_TARGET_I386) && TCG_TARGET_REG_BITS < 64
632 call_type
= (flags
& TCG_CALL_TYPE_MASK
);
634 if (ret
!= TCG_CALL_DUMMY_ARG
) {
635 #if TCG_TARGET_REG_BITS < 64
637 #ifdef TCG_TARGET_WORDS_BIGENDIAN
638 *gen_opparam_ptr
++ = ret
+ 1;
639 *gen_opparam_ptr
++ = ret
;
641 *gen_opparam_ptr
++ = ret
;
642 *gen_opparam_ptr
++ = ret
+ 1;
648 *gen_opparam_ptr
++ = ret
;
655 for (i
= 0; i
< nargs
; i
++) {
656 #if TCG_TARGET_REG_BITS < 64
657 int is_64bit
= sizemask
& (1 << (i
+1)*2);
659 #ifdef TCG_TARGET_I386
660 /* REGPARM case: if the third parameter is 64 bit, it is
661 allocated on the stack */
662 if (i
== 2 && call_type
== TCG_CALL_TYPE_REGPARM
) {
663 call_type
= TCG_CALL_TYPE_REGPARM_2
;
664 flags
= (flags
& ~TCG_CALL_TYPE_MASK
) | call_type
;
667 #ifdef TCG_TARGET_CALL_ALIGN_ARGS
668 /* some targets want aligned 64 bit args */
670 *gen_opparam_ptr
++ = TCG_CALL_DUMMY_ARG
;
674 /* If stack grows up, then we will be placing successive
675 arguments at lower addresses, which means we need to
676 reverse the order compared to how we would normally
677 treat either big or little-endian. For those arguments
678 that will wind up in registers, this still works for
679 HPPA (the only current STACK_GROWSUP target) since the
680 argument registers are *also* allocated in decreasing
681 order. If another such target is added, this logic may
682 have to get more complicated to differentiate between
683 stack arguments and register arguments. */
684 #if defined(TCG_TARGET_WORDS_BIGENDIAN) != defined(TCG_TARGET_STACK_GROWSUP)
685 *gen_opparam_ptr
++ = args
[i
] + 1;
686 *gen_opparam_ptr
++ = args
[i
];
688 *gen_opparam_ptr
++ = args
[i
];
689 *gen_opparam_ptr
++ = args
[i
] + 1;
694 #endif /* TCG_TARGET_REG_BITS < 64 */
696 *gen_opparam_ptr
++ = args
[i
];
699 *gen_opparam_ptr
++ = GET_TCGV_PTR(func
);
701 *gen_opparam_ptr
++ = flags
;
703 *nparam
= (nb_rets
<< 16) | (real_args
+ 1);
705 /* total parameters, needed to go backward in the instruction stream */
706 *gen_opparam_ptr
++ = 1 + nb_rets
+ real_args
+ 3;
708 #if defined(TCG_TARGET_EXTEND_ARGS) && TCG_TARGET_REG_BITS == 64
709 for (i
= 0; i
< nargs
; ++i
) {
710 int is_64bit
= sizemask
& (1 << (i
+1)*2);
712 TCGv_i64 temp
= MAKE_TCGV_I64(args
[i
]);
713 tcg_temp_free_i64(temp
);
716 #endif /* TCG_TARGET_EXTEND_ARGS */
719 #if TCG_TARGET_REG_BITS == 32
720 void tcg_gen_shifti_i64(TCGv_i64 ret
, TCGv_i64 arg1
,
721 int c
, int right
, int arith
)
724 tcg_gen_mov_i32(TCGV_LOW(ret
), TCGV_LOW(arg1
));
725 tcg_gen_mov_i32(TCGV_HIGH(ret
), TCGV_HIGH(arg1
));
726 } else if (c
>= 32) {
730 tcg_gen_sari_i32(TCGV_LOW(ret
), TCGV_HIGH(arg1
), c
);
731 tcg_gen_sari_i32(TCGV_HIGH(ret
), TCGV_HIGH(arg1
), 31);
733 tcg_gen_shri_i32(TCGV_LOW(ret
), TCGV_HIGH(arg1
), c
);
734 tcg_gen_movi_i32(TCGV_HIGH(ret
), 0);
737 tcg_gen_shli_i32(TCGV_HIGH(ret
), TCGV_LOW(arg1
), c
);
738 tcg_gen_movi_i32(TCGV_LOW(ret
), 0);
743 t0
= tcg_temp_new_i32();
744 t1
= tcg_temp_new_i32();
746 tcg_gen_shli_i32(t0
, TCGV_HIGH(arg1
), 32 - c
);
748 tcg_gen_sari_i32(t1
, TCGV_HIGH(arg1
), c
);
750 tcg_gen_shri_i32(t1
, TCGV_HIGH(arg1
), c
);
751 tcg_gen_shri_i32(TCGV_LOW(ret
), TCGV_LOW(arg1
), c
);
752 tcg_gen_or_i32(TCGV_LOW(ret
), TCGV_LOW(ret
), t0
);
753 tcg_gen_mov_i32(TCGV_HIGH(ret
), t1
);
755 tcg_gen_shri_i32(t0
, TCGV_LOW(arg1
), 32 - c
);
756 /* Note: ret can be the same as arg1, so we use t1 */
757 tcg_gen_shli_i32(t1
, TCGV_LOW(arg1
), c
);
758 tcg_gen_shli_i32(TCGV_HIGH(ret
), TCGV_HIGH(arg1
), c
);
759 tcg_gen_or_i32(TCGV_HIGH(ret
), TCGV_HIGH(ret
), t0
);
760 tcg_gen_mov_i32(TCGV_LOW(ret
), t1
);
762 tcg_temp_free_i32(t0
);
763 tcg_temp_free_i32(t1
);
769 static void tcg_reg_alloc_start(TCGContext
*s
)
773 for(i
= 0; i
< s
->nb_globals
; i
++) {
776 ts
->val_type
= TEMP_VAL_REG
;
778 ts
->val_type
= TEMP_VAL_MEM
;
781 for(i
= s
->nb_globals
; i
< s
->nb_temps
; i
++) {
783 ts
->val_type
= TEMP_VAL_DEAD
;
784 ts
->mem_allocated
= 0;
787 for(i
= 0; i
< TCG_TARGET_NB_REGS
; i
++) {
788 s
->reg_to_temp
[i
] = -1;
792 static char *tcg_get_arg_str_idx(TCGContext
*s
, char *buf
, int buf_size
,
797 assert(idx
>= 0 && idx
< s
->nb_temps
);
800 if (idx
< s
->nb_globals
) {
801 pstrcpy(buf
, buf_size
, ts
->name
);
804 snprintf(buf
, buf_size
, "loc%d", idx
- s
->nb_globals
);
806 snprintf(buf
, buf_size
, "tmp%d", idx
- s
->nb_globals
);
811 char *tcg_get_arg_str_i32(TCGContext
*s
, char *buf
, int buf_size
, TCGv_i32 arg
)
813 return tcg_get_arg_str_idx(s
, buf
, buf_size
, GET_TCGV_I32(arg
));
816 char *tcg_get_arg_str_i64(TCGContext
*s
, char *buf
, int buf_size
, TCGv_i64 arg
)
818 return tcg_get_arg_str_idx(s
, buf
, buf_size
, GET_TCGV_I64(arg
));
821 static int helper_cmp(const void *p1
, const void *p2
)
823 const TCGHelperInfo
*th1
= p1
;
824 const TCGHelperInfo
*th2
= p2
;
825 if (th1
->func
< th2
->func
)
827 else if (th1
->func
== th2
->func
)
833 /* find helper definition (Note: A hash table would be better) */
834 static TCGHelperInfo
*tcg_find_helper(TCGContext
*s
, tcg_target_ulong val
)
840 if (unlikely(!s
->helpers_sorted
)) {
841 qsort(s
->helpers
, s
->nb_helpers
, sizeof(TCGHelperInfo
),
843 s
->helpers_sorted
= 1;
848 m_max
= s
->nb_helpers
- 1;
849 while (m_min
<= m_max
) {
850 m
= (m_min
+ m_max
) >> 1;
864 static const char * const cond_name
[] =
866 [TCG_COND_EQ
] = "eq",
867 [TCG_COND_NE
] = "ne",
868 [TCG_COND_LT
] = "lt",
869 [TCG_COND_GE
] = "ge",
870 [TCG_COND_LE
] = "le",
871 [TCG_COND_GT
] = "gt",
872 [TCG_COND_LTU
] = "ltu",
873 [TCG_COND_GEU
] = "geu",
874 [TCG_COND_LEU
] = "leu",
875 [TCG_COND_GTU
] = "gtu"
878 void tcg_dump_ops(TCGContext
*s
, FILE *outfile
)
880 const uint16_t *opc_ptr
;
884 int i
, k
, nb_oargs
, nb_iargs
, nb_cargs
, first_insn
;
889 opc_ptr
= gen_opc_buf
;
890 args
= gen_opparam_buf
;
891 while (opc_ptr
< gen_opc_ptr
) {
893 def
= &tcg_op_defs
[c
];
894 if (c
== INDEX_op_debug_insn_start
) {
896 #if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
897 pc
= ((uint64_t)args
[1] << 32) | args
[0];
902 fprintf(outfile
, "\n");
903 fprintf(outfile
, " ---- 0x%" PRIx64
, pc
);
905 nb_oargs
= def
->nb_oargs
;
906 nb_iargs
= def
->nb_iargs
;
907 nb_cargs
= def
->nb_cargs
;
908 } else if (c
== INDEX_op_call
) {
911 /* variable number of arguments */
913 nb_oargs
= arg
>> 16;
914 nb_iargs
= arg
& 0xffff;
915 nb_cargs
= def
->nb_cargs
;
917 fprintf(outfile
, " %s ", def
->name
);
920 fprintf(outfile
, "%s",
921 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), args
[nb_oargs
+ nb_iargs
- 1]));
923 fprintf(outfile
, ",$0x%" TCG_PRIlx
,
924 args
[nb_oargs
+ nb_iargs
]);
926 fprintf(outfile
, ",$%d", nb_oargs
);
927 for(i
= 0; i
< nb_oargs
; i
++) {
928 fprintf(outfile
, ",");
929 fprintf(outfile
, "%s",
930 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), args
[i
]));
932 for(i
= 0; i
< (nb_iargs
- 1); i
++) {
933 fprintf(outfile
, ",");
934 if (args
[nb_oargs
+ i
] == TCG_CALL_DUMMY_ARG
) {
935 fprintf(outfile
, "<dummy>");
937 fprintf(outfile
, "%s",
938 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), args
[nb_oargs
+ i
]));
941 } else if (c
== INDEX_op_movi_i32
942 #if TCG_TARGET_REG_BITS == 64
943 || c
== INDEX_op_movi_i64
946 tcg_target_ulong val
;
949 nb_oargs
= def
->nb_oargs
;
950 nb_iargs
= def
->nb_iargs
;
951 nb_cargs
= def
->nb_cargs
;
952 fprintf(outfile
, " %s %s,$", def
->name
,
953 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), args
[0]));
955 th
= tcg_find_helper(s
, val
);
957 fprintf(outfile
, "%s", th
->name
);
959 if (c
== INDEX_op_movi_i32
)
960 fprintf(outfile
, "0x%x", (uint32_t)val
);
962 fprintf(outfile
, "0x%" PRIx64
, (uint64_t)val
);
965 fprintf(outfile
, " %s ", def
->name
);
966 if (c
== INDEX_op_nopn
) {
967 /* variable number of arguments */
972 nb_oargs
= def
->nb_oargs
;
973 nb_iargs
= def
->nb_iargs
;
974 nb_cargs
= def
->nb_cargs
;
978 for(i
= 0; i
< nb_oargs
; i
++) {
980 fprintf(outfile
, ",");
981 fprintf(outfile
, "%s",
982 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), args
[k
++]));
984 for(i
= 0; i
< nb_iargs
; i
++) {
986 fprintf(outfile
, ",");
987 fprintf(outfile
, "%s",
988 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), args
[k
++]));
991 case INDEX_op_brcond_i32
:
992 #if TCG_TARGET_REG_BITS == 32
993 case INDEX_op_brcond2_i32
:
994 #elif TCG_TARGET_REG_BITS == 64
995 case INDEX_op_brcond_i64
:
997 case INDEX_op_setcond_i32
:
998 #if TCG_TARGET_REG_BITS == 32
999 case INDEX_op_setcond2_i32
:
1000 #elif TCG_TARGET_REG_BITS == 64
1001 case INDEX_op_setcond_i64
:
1003 if (args
[k
] < ARRAY_SIZE(cond_name
) && cond_name
[args
[k
]])
1004 fprintf(outfile
, ",%s", cond_name
[args
[k
++]]);
1006 fprintf(outfile
, ",$0x%" TCG_PRIlx
, args
[k
++]);
1013 for(; i
< nb_cargs
; i
++) {
1015 fprintf(outfile
, ",");
1017 fprintf(outfile
, "$0x%" TCG_PRIlx
, arg
);
1020 fprintf(outfile
, "\n");
1021 args
+= nb_iargs
+ nb_oargs
+ nb_cargs
;
1025 /* we give more priority to constraints with less registers */
1026 static int get_constraint_priority(const TCGOpDef
*def
, int k
)
1028 const TCGArgConstraint
*arg_ct
;
1031 arg_ct
= &def
->args_ct
[k
];
1032 if (arg_ct
->ct
& TCG_CT_ALIAS
) {
1033 /* an alias is equivalent to a single register */
1036 if (!(arg_ct
->ct
& TCG_CT_REG
))
1039 for(i
= 0; i
< TCG_TARGET_NB_REGS
; i
++) {
1040 if (tcg_regset_test_reg(arg_ct
->u
.regs
, i
))
1044 return TCG_TARGET_NB_REGS
- n
+ 1;
1047 /* sort from highest priority to lowest */
1048 static void sort_constraints(TCGOpDef
*def
, int start
, int n
)
1050 int i
, j
, p1
, p2
, tmp
;
1052 for(i
= 0; i
< n
; i
++)
1053 def
->sorted_args
[start
+ i
] = start
+ i
;
1056 for(i
= 0; i
< n
- 1; i
++) {
1057 for(j
= i
+ 1; j
< n
; j
++) {
1058 p1
= get_constraint_priority(def
, def
->sorted_args
[start
+ i
]);
1059 p2
= get_constraint_priority(def
, def
->sorted_args
[start
+ j
]);
1061 tmp
= def
->sorted_args
[start
+ i
];
1062 def
->sorted_args
[start
+ i
] = def
->sorted_args
[start
+ j
];
1063 def
->sorted_args
[start
+ j
] = tmp
;
1069 void tcg_add_target_add_op_defs(const TCGTargetOpDef
*tdefs
)
1077 if (tdefs
->op
== (TCGOpcode
)-1)
1080 assert((unsigned)op
< NB_OPS
);
1081 def
= &tcg_op_defs
[op
];
1082 #if defined(CONFIG_DEBUG_TCG)
1083 /* Duplicate entry in op definitions? */
1087 nb_args
= def
->nb_iargs
+ def
->nb_oargs
;
1088 for(i
= 0; i
< nb_args
; i
++) {
1089 ct_str
= tdefs
->args_ct_str
[i
];
1090 /* Incomplete TCGTargetOpDef entry? */
1091 assert(ct_str
!= NULL
);
1092 tcg_regset_clear(def
->args_ct
[i
].u
.regs
);
1093 def
->args_ct
[i
].ct
= 0;
1094 if (ct_str
[0] >= '0' && ct_str
[0] <= '9') {
1096 oarg
= ct_str
[0] - '0';
1097 assert(oarg
< def
->nb_oargs
);
1098 assert(def
->args_ct
[oarg
].ct
& TCG_CT_REG
);
1099 /* TCG_CT_ALIAS is for the output arguments. The input
1100 argument is tagged with TCG_CT_IALIAS. */
1101 def
->args_ct
[i
] = def
->args_ct
[oarg
];
1102 def
->args_ct
[oarg
].ct
= TCG_CT_ALIAS
;
1103 def
->args_ct
[oarg
].alias_index
= i
;
1104 def
->args_ct
[i
].ct
|= TCG_CT_IALIAS
;
1105 def
->args_ct
[i
].alias_index
= oarg
;
1108 if (*ct_str
== '\0')
1112 def
->args_ct
[i
].ct
|= TCG_CT_CONST
;
1116 if (target_parse_constraint(&def
->args_ct
[i
], &ct_str
) < 0) {
1117 fprintf(stderr
, "Invalid constraint '%s' for arg %d of operation '%s'\n",
1118 ct_str
, i
, def
->name
);
1126 /* TCGTargetOpDef entry with too much information? */
1127 assert(i
== TCG_MAX_OP_ARGS
|| tdefs
->args_ct_str
[i
] == NULL
);
1129 /* sort the constraints (XXX: this is just an heuristic) */
1130 sort_constraints(def
, 0, def
->nb_oargs
);
1131 sort_constraints(def
, def
->nb_oargs
, def
->nb_iargs
);
1137 printf("%s: sorted=", def
->name
);
1138 for(i
= 0; i
< def
->nb_oargs
+ def
->nb_iargs
; i
++)
1139 printf(" %d", def
->sorted_args
[i
]);
1146 #if defined(CONFIG_DEBUG_TCG)
1148 for (op
= 0; op
< ARRAY_SIZE(tcg_op_defs
); op
++) {
1149 const TCGOpDef
*def
= &tcg_op_defs
[op
];
1150 if (op
< INDEX_op_call
1151 || op
== INDEX_op_debug_insn_start
1152 || (def
->flags
& TCG_OPF_NOT_PRESENT
)) {
1153 /* Wrong entry in op definitions? */
1155 fprintf(stderr
, "Invalid op definition for %s\n", def
->name
);
1159 /* Missing entry in op definitions? */
1161 fprintf(stderr
, "Missing op definition for %s\n", def
->name
);
1172 #ifdef USE_LIVENESS_ANALYSIS
1174 /* set a nop for an operation using 'nb_args' */
1175 static inline void tcg_set_nop(TCGContext
*s
, uint16_t *opc_ptr
,
1176 TCGArg
*args
, int nb_args
)
1179 *opc_ptr
= INDEX_op_nop
;
1181 *opc_ptr
= INDEX_op_nopn
;
1183 args
[nb_args
- 1] = nb_args
;
1187 /* liveness analysis: end of function: globals are live, temps are
1189 /* XXX: at this stage, not used as there would be little gains because
1190 most TBs end with a conditional jump. */
1191 static inline void tcg_la_func_end(TCGContext
*s
, uint8_t *dead_temps
)
1193 memset(dead_temps
, 0, s
->nb_globals
);
1194 memset(dead_temps
+ s
->nb_globals
, 1, s
->nb_temps
- s
->nb_globals
);
1197 /* liveness analysis: end of basic block: globals are live, temps are
1198 dead, local temps are live. */
1199 static inline void tcg_la_bb_end(TCGContext
*s
, uint8_t *dead_temps
)
1204 memset(dead_temps
, 0, s
->nb_globals
);
1205 ts
= &s
->temps
[s
->nb_globals
];
1206 for(i
= s
->nb_globals
; i
< s
->nb_temps
; i
++) {
1215 /* Liveness analysis : update the opc_dead_args array to tell if a
1216 given input arguments is dead. Instructions updating dead
1217 temporaries are removed. */
1218 static void tcg_liveness_analysis(TCGContext
*s
)
1220 int i
, op_index
, nb_args
, nb_iargs
, nb_oargs
, arg
, nb_ops
;
1223 const TCGOpDef
*def
;
1224 uint8_t *dead_temps
;
1225 unsigned int dead_args
;
1227 gen_opc_ptr
++; /* skip end */
1229 nb_ops
= gen_opc_ptr
- gen_opc_buf
;
1231 s
->op_dead_args
= tcg_malloc(nb_ops
* sizeof(uint16_t));
1233 dead_temps
= tcg_malloc(s
->nb_temps
);
1234 memset(dead_temps
, 1, s
->nb_temps
);
1236 args
= gen_opparam_ptr
;
1237 op_index
= nb_ops
- 1;
1238 while (op_index
>= 0) {
1239 op
= gen_opc_buf
[op_index
];
1240 def
= &tcg_op_defs
[op
];
1248 nb_iargs
= args
[0] & 0xffff;
1249 nb_oargs
= args
[0] >> 16;
1251 call_flags
= args
[nb_oargs
+ nb_iargs
];
1253 /* pure functions can be removed if their result is not
1255 if (call_flags
& TCG_CALL_PURE
) {
1256 for(i
= 0; i
< nb_oargs
; i
++) {
1258 if (!dead_temps
[arg
])
1259 goto do_not_remove_call
;
1261 tcg_set_nop(s
, gen_opc_buf
+ op_index
,
1266 /* output args are dead */
1268 for(i
= 0; i
< nb_oargs
; i
++) {
1270 if (dead_temps
[arg
]) {
1271 dead_args
|= (1 << i
);
1273 dead_temps
[arg
] = 1;
1276 if (!(call_flags
& TCG_CALL_CONST
)) {
1277 /* globals are live (they may be used by the call) */
1278 memset(dead_temps
, 0, s
->nb_globals
);
1281 /* input args are live */
1282 for(i
= nb_oargs
; i
< nb_iargs
+ nb_oargs
; i
++) {
1284 if (arg
!= TCG_CALL_DUMMY_ARG
) {
1285 if (dead_temps
[arg
]) {
1286 dead_args
|= (1 << i
);
1288 dead_temps
[arg
] = 0;
1291 s
->op_dead_args
[op_index
] = dead_args
;
1296 case INDEX_op_set_label
:
1298 /* mark end of basic block */
1299 tcg_la_bb_end(s
, dead_temps
);
1301 case INDEX_op_debug_insn_start
:
1302 args
-= def
->nb_args
;
1308 case INDEX_op_discard
:
1310 /* mark the temporary as dead */
1311 dead_temps
[args
[0]] = 1;
1315 /* XXX: optimize by hardcoding common cases (e.g. triadic ops) */
1317 args
-= def
->nb_args
;
1318 nb_iargs
= def
->nb_iargs
;
1319 nb_oargs
= def
->nb_oargs
;
1321 /* Test if the operation can be removed because all
1322 its outputs are dead. We assume that nb_oargs == 0
1323 implies side effects */
1324 if (!(def
->flags
& TCG_OPF_SIDE_EFFECTS
) && nb_oargs
!= 0) {
1325 for(i
= 0; i
< nb_oargs
; i
++) {
1327 if (!dead_temps
[arg
])
1330 tcg_set_nop(s
, gen_opc_buf
+ op_index
, args
, def
->nb_args
);
1331 #ifdef CONFIG_PROFILER
1337 /* output args are dead */
1339 for(i
= 0; i
< nb_oargs
; i
++) {
1341 if (dead_temps
[arg
]) {
1342 dead_args
|= (1 << i
);
1344 dead_temps
[arg
] = 1;
1347 /* if end of basic block, update */
1348 if (def
->flags
& TCG_OPF_BB_END
) {
1349 tcg_la_bb_end(s
, dead_temps
);
1350 } else if (def
->flags
& TCG_OPF_CALL_CLOBBER
) {
1351 /* globals are live */
1352 memset(dead_temps
, 0, s
->nb_globals
);
1355 /* input args are live */
1356 for(i
= nb_oargs
; i
< nb_oargs
+ nb_iargs
; i
++) {
1358 if (dead_temps
[arg
]) {
1359 dead_args
|= (1 << i
);
1361 dead_temps
[arg
] = 0;
1363 s
->op_dead_args
[op_index
] = dead_args
;
1370 if (args
!= gen_opparam_buf
)
1374 /* dummy liveness analysis */
1375 static void tcg_liveness_analysis(TCGContext
*s
)
1378 nb_ops
= gen_opc_ptr
- gen_opc_buf
;
1380 s
->op_dead_args
= tcg_malloc(nb_ops
* sizeof(uint16_t));
1381 memset(s
->op_dead_args
, 0, nb_ops
* sizeof(uint16_t));
1386 static void dump_regs(TCGContext
*s
)
1392 for(i
= 0; i
< s
->nb_temps
; i
++) {
1394 printf(" %10s: ", tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), i
));
1395 switch(ts
->val_type
) {
1397 printf("%s", tcg_target_reg_names
[ts
->reg
]);
1400 printf("%d(%s)", (int)ts
->mem_offset
, tcg_target_reg_names
[ts
->mem_reg
]);
1402 case TEMP_VAL_CONST
:
1403 printf("$0x%" TCG_PRIlx
, ts
->val
);
1415 for(i
= 0; i
< TCG_TARGET_NB_REGS
; i
++) {
1416 if (s
->reg_to_temp
[i
] >= 0) {
1418 tcg_target_reg_names
[i
],
1419 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), s
->reg_to_temp
[i
]));
1424 static void check_regs(TCGContext
*s
)
1430 for(reg
= 0; reg
< TCG_TARGET_NB_REGS
; reg
++) {
1431 k
= s
->reg_to_temp
[reg
];
1434 if (ts
->val_type
!= TEMP_VAL_REG
||
1436 printf("Inconsistency for register %s:\n",
1437 tcg_target_reg_names
[reg
]);
1442 for(k
= 0; k
< s
->nb_temps
; k
++) {
1444 if (ts
->val_type
== TEMP_VAL_REG
&&
1446 s
->reg_to_temp
[ts
->reg
] != k
) {
1447 printf("Inconsistency for temp %s:\n",
1448 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), k
));
1450 printf("reg state:\n");
1458 static void temp_allocate_frame(TCGContext
*s
, int temp
)
1461 ts
= &s
->temps
[temp
];
1462 #ifndef __sparc_v9__ /* Sparc64 stack is accessed with offset of 2047 */
1463 s
->current_frame_offset
= (s
->current_frame_offset
+
1464 (tcg_target_long
)sizeof(tcg_target_long
) - 1) &
1465 ~(sizeof(tcg_target_long
) - 1);
1467 if (s
->current_frame_offset
+ (tcg_target_long
)sizeof(tcg_target_long
) >
1471 ts
->mem_offset
= s
->current_frame_offset
;
1472 ts
->mem_reg
= s
->frame_reg
;
1473 ts
->mem_allocated
= 1;
1474 s
->current_frame_offset
+= (tcg_target_long
)sizeof(tcg_target_long
);
1477 /* free register 'reg' by spilling the corresponding temporary if necessary */
1478 static void tcg_reg_free(TCGContext
*s
, int reg
)
1483 temp
= s
->reg_to_temp
[reg
];
1485 ts
= &s
->temps
[temp
];
1486 assert(ts
->val_type
== TEMP_VAL_REG
);
1487 if (!ts
->mem_coherent
) {
1488 if (!ts
->mem_allocated
)
1489 temp_allocate_frame(s
, temp
);
1490 tcg_out_st(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
1492 ts
->val_type
= TEMP_VAL_MEM
;
1493 s
->reg_to_temp
[reg
] = -1;
1497 /* Allocate a register belonging to reg1 & ~reg2 */
1498 static int tcg_reg_alloc(TCGContext
*s
, TCGRegSet reg1
, TCGRegSet reg2
)
1503 tcg_regset_andnot(reg_ct
, reg1
, reg2
);
1505 /* first try free registers */
1506 for(i
= 0; i
< ARRAY_SIZE(tcg_target_reg_alloc_order
); i
++) {
1507 reg
= tcg_target_reg_alloc_order
[i
];
1508 if (tcg_regset_test_reg(reg_ct
, reg
) && s
->reg_to_temp
[reg
] == -1)
1512 /* XXX: do better spill choice */
1513 for(i
= 0; i
< ARRAY_SIZE(tcg_target_reg_alloc_order
); i
++) {
1514 reg
= tcg_target_reg_alloc_order
[i
];
1515 if (tcg_regset_test_reg(reg_ct
, reg
)) {
1516 tcg_reg_free(s
, reg
);
1524 /* save a temporary to memory. 'allocated_regs' is used in case a
1525 temporary registers needs to be allocated to store a constant. */
1526 static void temp_save(TCGContext
*s
, int temp
, TCGRegSet allocated_regs
)
1531 ts
= &s
->temps
[temp
];
1532 if (!ts
->fixed_reg
) {
1533 switch(ts
->val_type
) {
1535 tcg_reg_free(s
, ts
->reg
);
1538 ts
->val_type
= TEMP_VAL_MEM
;
1540 case TEMP_VAL_CONST
:
1541 reg
= tcg_reg_alloc(s
, tcg_target_available_regs
[ts
->type
],
1543 if (!ts
->mem_allocated
)
1544 temp_allocate_frame(s
, temp
);
1545 tcg_out_movi(s
, ts
->type
, reg
, ts
->val
);
1546 tcg_out_st(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
1547 ts
->val_type
= TEMP_VAL_MEM
;
1557 /* save globals to their cannonical location and assume they can be
1558 modified be the following code. 'allocated_regs' is used in case a
1559 temporary registers needs to be allocated to store a constant. */
1560 static void save_globals(TCGContext
*s
, TCGRegSet allocated_regs
)
1564 for(i
= 0; i
< s
->nb_globals
; i
++) {
1565 temp_save(s
, i
, allocated_regs
);
1569 /* at the end of a basic block, we assume all temporaries are dead and
1570 all globals are stored at their canonical location. */
1571 static void tcg_reg_alloc_bb_end(TCGContext
*s
, TCGRegSet allocated_regs
)
1576 for(i
= s
->nb_globals
; i
< s
->nb_temps
; i
++) {
1578 if (ts
->temp_local
) {
1579 temp_save(s
, i
, allocated_regs
);
1581 if (ts
->val_type
== TEMP_VAL_REG
) {
1582 s
->reg_to_temp
[ts
->reg
] = -1;
1584 ts
->val_type
= TEMP_VAL_DEAD
;
1588 save_globals(s
, allocated_regs
);
1591 #define IS_DEAD_ARG(n) ((dead_args >> (n)) & 1)
1593 static void tcg_reg_alloc_movi(TCGContext
*s
, const TCGArg
*args
)
1596 tcg_target_ulong val
;
1598 ots
= &s
->temps
[args
[0]];
1601 if (ots
->fixed_reg
) {
1602 /* for fixed registers, we do not do any constant
1604 tcg_out_movi(s
, ots
->type
, ots
->reg
, val
);
1606 /* The movi is not explicitly generated here */
1607 if (ots
->val_type
== TEMP_VAL_REG
)
1608 s
->reg_to_temp
[ots
->reg
] = -1;
1609 ots
->val_type
= TEMP_VAL_CONST
;
1614 static void tcg_reg_alloc_mov(TCGContext
*s
, const TCGOpDef
*def
,
1616 unsigned int dead_args
)
1620 const TCGArgConstraint
*arg_ct
;
1622 ots
= &s
->temps
[args
[0]];
1623 ts
= &s
->temps
[args
[1]];
1624 arg_ct
= &def
->args_ct
[0];
1626 /* XXX: always mark arg dead if IS_DEAD_ARG(1) */
1627 if (ts
->val_type
== TEMP_VAL_REG
) {
1628 if (IS_DEAD_ARG(1) && !ts
->fixed_reg
&& !ots
->fixed_reg
) {
1629 /* the mov can be suppressed */
1630 if (ots
->val_type
== TEMP_VAL_REG
)
1631 s
->reg_to_temp
[ots
->reg
] = -1;
1633 s
->reg_to_temp
[reg
] = -1;
1634 ts
->val_type
= TEMP_VAL_DEAD
;
1636 if (ots
->val_type
== TEMP_VAL_REG
) {
1639 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, s
->reserved_regs
);
1641 if (ts
->reg
!= reg
) {
1642 tcg_out_mov(s
, ots
->type
, reg
, ts
->reg
);
1645 } else if (ts
->val_type
== TEMP_VAL_MEM
) {
1646 if (ots
->val_type
== TEMP_VAL_REG
) {
1649 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, s
->reserved_regs
);
1651 tcg_out_ld(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
1652 } else if (ts
->val_type
== TEMP_VAL_CONST
) {
1653 if (ots
->fixed_reg
) {
1655 tcg_out_movi(s
, ots
->type
, reg
, ts
->val
);
1657 /* propagate constant */
1658 if (ots
->val_type
== TEMP_VAL_REG
)
1659 s
->reg_to_temp
[ots
->reg
] = -1;
1660 ots
->val_type
= TEMP_VAL_CONST
;
1667 s
->reg_to_temp
[reg
] = args
[0];
1669 ots
->val_type
= TEMP_VAL_REG
;
1670 ots
->mem_coherent
= 0;
1673 static void tcg_reg_alloc_op(TCGContext
*s
,
1674 const TCGOpDef
*def
, TCGOpcode opc
,
1676 unsigned int dead_args
)
1678 TCGRegSet allocated_regs
;
1679 int i
, k
, nb_iargs
, nb_oargs
, reg
;
1681 const TCGArgConstraint
*arg_ct
;
1683 TCGArg new_args
[TCG_MAX_OP_ARGS
];
1684 int const_args
[TCG_MAX_OP_ARGS
];
1686 nb_oargs
= def
->nb_oargs
;
1687 nb_iargs
= def
->nb_iargs
;
1689 /* copy constants */
1690 memcpy(new_args
+ nb_oargs
+ nb_iargs
,
1691 args
+ nb_oargs
+ nb_iargs
,
1692 sizeof(TCGArg
) * def
->nb_cargs
);
1694 /* satisfy input constraints */
1695 tcg_regset_set(allocated_regs
, s
->reserved_regs
);
1696 for(k
= 0; k
< nb_iargs
; k
++) {
1697 i
= def
->sorted_args
[nb_oargs
+ k
];
1699 arg_ct
= &def
->args_ct
[i
];
1700 ts
= &s
->temps
[arg
];
1701 if (ts
->val_type
== TEMP_VAL_MEM
) {
1702 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1703 tcg_out_ld(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
1704 ts
->val_type
= TEMP_VAL_REG
;
1706 ts
->mem_coherent
= 1;
1707 s
->reg_to_temp
[reg
] = arg
;
1708 } else if (ts
->val_type
== TEMP_VAL_CONST
) {
1709 if (tcg_target_const_match(ts
->val
, arg_ct
)) {
1710 /* constant is OK for instruction */
1712 new_args
[i
] = ts
->val
;
1715 /* need to move to a register */
1716 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1717 tcg_out_movi(s
, ts
->type
, reg
, ts
->val
);
1718 ts
->val_type
= TEMP_VAL_REG
;
1720 ts
->mem_coherent
= 0;
1721 s
->reg_to_temp
[reg
] = arg
;
1724 assert(ts
->val_type
== TEMP_VAL_REG
);
1725 if (arg_ct
->ct
& TCG_CT_IALIAS
) {
1726 if (ts
->fixed_reg
) {
1727 /* if fixed register, we must allocate a new register
1728 if the alias is not the same register */
1729 if (arg
!= args
[arg_ct
->alias_index
])
1730 goto allocate_in_reg
;
1732 /* if the input is aliased to an output and if it is
1733 not dead after the instruction, we must allocate
1734 a new register and move it */
1735 if (!IS_DEAD_ARG(i
)) {
1736 goto allocate_in_reg
;
1741 if (tcg_regset_test_reg(arg_ct
->u
.regs
, reg
)) {
1742 /* nothing to do : the constraint is satisfied */
1745 /* allocate a new register matching the constraint
1746 and move the temporary register into it */
1747 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1748 tcg_out_mov(s
, ts
->type
, reg
, ts
->reg
);
1752 tcg_regset_set_reg(allocated_regs
, reg
);
1756 if (def
->flags
& TCG_OPF_BB_END
) {
1757 tcg_reg_alloc_bb_end(s
, allocated_regs
);
1759 /* mark dead temporaries and free the associated registers */
1760 for(i
= nb_oargs
; i
< nb_oargs
+ nb_iargs
; i
++) {
1762 if (IS_DEAD_ARG(i
)) {
1763 ts
= &s
->temps
[arg
];
1764 if (!ts
->fixed_reg
) {
1765 if (ts
->val_type
== TEMP_VAL_REG
)
1766 s
->reg_to_temp
[ts
->reg
] = -1;
1767 ts
->val_type
= TEMP_VAL_DEAD
;
1772 if (def
->flags
& TCG_OPF_CALL_CLOBBER
) {
1773 /* XXX: permit generic clobber register list ? */
1774 for(reg
= 0; reg
< TCG_TARGET_NB_REGS
; reg
++) {
1775 if (tcg_regset_test_reg(tcg_target_call_clobber_regs
, reg
)) {
1776 tcg_reg_free(s
, reg
);
1779 /* XXX: for load/store we could do that only for the slow path
1780 (i.e. when a memory callback is called) */
1782 /* store globals and free associated registers (we assume the insn
1783 can modify any global. */
1784 save_globals(s
, allocated_regs
);
1787 /* satisfy the output constraints */
1788 tcg_regset_set(allocated_regs
, s
->reserved_regs
);
1789 for(k
= 0; k
< nb_oargs
; k
++) {
1790 i
= def
->sorted_args
[k
];
1792 arg_ct
= &def
->args_ct
[i
];
1793 ts
= &s
->temps
[arg
];
1794 if (arg_ct
->ct
& TCG_CT_ALIAS
) {
1795 reg
= new_args
[arg_ct
->alias_index
];
1797 /* if fixed register, we try to use it */
1799 if (ts
->fixed_reg
&&
1800 tcg_regset_test_reg(arg_ct
->u
.regs
, reg
)) {
1803 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1805 tcg_regset_set_reg(allocated_regs
, reg
);
1806 /* if a fixed register is used, then a move will be done afterwards */
1807 if (!ts
->fixed_reg
) {
1808 if (ts
->val_type
== TEMP_VAL_REG
)
1809 s
->reg_to_temp
[ts
->reg
] = -1;
1810 if (IS_DEAD_ARG(i
)) {
1811 ts
->val_type
= TEMP_VAL_DEAD
;
1813 ts
->val_type
= TEMP_VAL_REG
;
1815 /* temp value is modified, so the value kept in memory is
1816 potentially not the same */
1817 ts
->mem_coherent
= 0;
1818 s
->reg_to_temp
[reg
] = arg
;
1826 /* emit instruction */
1827 tcg_out_op(s
, opc
, new_args
, const_args
);
1829 /* move the outputs in the correct register if needed */
1830 for(i
= 0; i
< nb_oargs
; i
++) {
1831 ts
= &s
->temps
[args
[i
]];
1833 if (ts
->fixed_reg
&& ts
->reg
!= reg
) {
1834 tcg_out_mov(s
, ts
->type
, ts
->reg
, reg
);
1839 #ifdef TCG_TARGET_STACK_GROWSUP
1840 #define STACK_DIR(x) (-(x))
1842 #define STACK_DIR(x) (x)
1845 static int tcg_reg_alloc_call(TCGContext
*s
, const TCGOpDef
*def
,
1846 TCGOpcode opc
, const TCGArg
*args
,
1847 unsigned int dead_args
)
1849 int nb_iargs
, nb_oargs
, flags
, nb_regs
, i
, reg
, nb_params
;
1850 TCGArg arg
, func_arg
;
1852 tcg_target_long stack_offset
, call_stack_size
, func_addr
;
1853 int const_func_arg
, allocate_args
;
1854 TCGRegSet allocated_regs
;
1855 const TCGArgConstraint
*arg_ct
;
1859 nb_oargs
= arg
>> 16;
1860 nb_iargs
= arg
& 0xffff;
1861 nb_params
= nb_iargs
- 1;
1863 flags
= args
[nb_oargs
+ nb_iargs
];
1865 nb_regs
= tcg_target_get_call_iarg_regs_count(flags
);
1866 if (nb_regs
> nb_params
)
1867 nb_regs
= nb_params
;
1869 /* assign stack slots first */
1870 call_stack_size
= (nb_params
- nb_regs
) * sizeof(tcg_target_long
);
1871 call_stack_size
= (call_stack_size
+ TCG_TARGET_STACK_ALIGN
- 1) &
1872 ~(TCG_TARGET_STACK_ALIGN
- 1);
1873 allocate_args
= (call_stack_size
> TCG_STATIC_CALL_ARGS_SIZE
);
1874 if (allocate_args
) {
1875 /* XXX: if more than TCG_STATIC_CALL_ARGS_SIZE is needed,
1876 preallocate call stack */
1880 stack_offset
= TCG_TARGET_CALL_STACK_OFFSET
;
1881 for(i
= nb_regs
; i
< nb_params
; i
++) {
1882 arg
= args
[nb_oargs
+ i
];
1883 #ifdef TCG_TARGET_STACK_GROWSUP
1884 stack_offset
-= sizeof(tcg_target_long
);
1886 if (arg
!= TCG_CALL_DUMMY_ARG
) {
1887 ts
= &s
->temps
[arg
];
1888 if (ts
->val_type
== TEMP_VAL_REG
) {
1889 tcg_out_st(s
, ts
->type
, ts
->reg
, TCG_REG_CALL_STACK
, stack_offset
);
1890 } else if (ts
->val_type
== TEMP_VAL_MEM
) {
1891 reg
= tcg_reg_alloc(s
, tcg_target_available_regs
[ts
->type
],
1893 /* XXX: not correct if reading values from the stack */
1894 tcg_out_ld(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
1895 tcg_out_st(s
, ts
->type
, reg
, TCG_REG_CALL_STACK
, stack_offset
);
1896 } else if (ts
->val_type
== TEMP_VAL_CONST
) {
1897 reg
= tcg_reg_alloc(s
, tcg_target_available_regs
[ts
->type
],
1899 /* XXX: sign extend may be needed on some targets */
1900 tcg_out_movi(s
, ts
->type
, reg
, ts
->val
);
1901 tcg_out_st(s
, ts
->type
, reg
, TCG_REG_CALL_STACK
, stack_offset
);
1906 #ifndef TCG_TARGET_STACK_GROWSUP
1907 stack_offset
+= sizeof(tcg_target_long
);
1911 /* assign input registers */
1912 tcg_regset_set(allocated_regs
, s
->reserved_regs
);
1913 for(i
= 0; i
< nb_regs
; i
++) {
1914 arg
= args
[nb_oargs
+ i
];
1915 if (arg
!= TCG_CALL_DUMMY_ARG
) {
1916 ts
= &s
->temps
[arg
];
1917 reg
= tcg_target_call_iarg_regs
[i
];
1918 tcg_reg_free(s
, reg
);
1919 if (ts
->val_type
== TEMP_VAL_REG
) {
1920 if (ts
->reg
!= reg
) {
1921 tcg_out_mov(s
, ts
->type
, reg
, ts
->reg
);
1923 } else if (ts
->val_type
== TEMP_VAL_MEM
) {
1924 tcg_out_ld(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
1925 } else if (ts
->val_type
== TEMP_VAL_CONST
) {
1926 /* XXX: sign extend ? */
1927 tcg_out_movi(s
, ts
->type
, reg
, ts
->val
);
1931 tcg_regset_set_reg(allocated_regs
, reg
);
1935 /* assign function address */
1936 func_arg
= args
[nb_oargs
+ nb_iargs
- 1];
1937 arg_ct
= &def
->args_ct
[0];
1938 ts
= &s
->temps
[func_arg
];
1939 func_addr
= ts
->val
;
1941 if (ts
->val_type
== TEMP_VAL_MEM
) {
1942 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1943 tcg_out_ld(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
1945 tcg_regset_set_reg(allocated_regs
, reg
);
1946 } else if (ts
->val_type
== TEMP_VAL_REG
) {
1948 if (!tcg_regset_test_reg(arg_ct
->u
.regs
, reg
)) {
1949 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1950 tcg_out_mov(s
, ts
->type
, reg
, ts
->reg
);
1953 tcg_regset_set_reg(allocated_regs
, reg
);
1954 } else if (ts
->val_type
== TEMP_VAL_CONST
) {
1955 if (tcg_target_const_match(func_addr
, arg_ct
)) {
1957 func_arg
= func_addr
;
1959 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1960 tcg_out_movi(s
, ts
->type
, reg
, func_addr
);
1962 tcg_regset_set_reg(allocated_regs
, reg
);
1969 /* mark dead temporaries and free the associated registers */
1970 for(i
= nb_oargs
; i
< nb_iargs
+ nb_oargs
; i
++) {
1972 if (IS_DEAD_ARG(i
)) {
1973 ts
= &s
->temps
[arg
];
1974 if (!ts
->fixed_reg
) {
1975 if (ts
->val_type
== TEMP_VAL_REG
)
1976 s
->reg_to_temp
[ts
->reg
] = -1;
1977 ts
->val_type
= TEMP_VAL_DEAD
;
1982 /* clobber call registers */
1983 for(reg
= 0; reg
< TCG_TARGET_NB_REGS
; reg
++) {
1984 if (tcg_regset_test_reg(tcg_target_call_clobber_regs
, reg
)) {
1985 tcg_reg_free(s
, reg
);
1989 /* store globals and free associated registers (we assume the call
1990 can modify any global. */
1991 if (!(flags
& TCG_CALL_CONST
)) {
1992 save_globals(s
, allocated_regs
);
1995 tcg_out_op(s
, opc
, &func_arg
, &const_func_arg
);
1997 /* assign output registers and emit moves if needed */
1998 for(i
= 0; i
< nb_oargs
; i
++) {
2000 ts
= &s
->temps
[arg
];
2001 reg
= tcg_target_call_oarg_regs
[i
];
2002 assert(s
->reg_to_temp
[reg
] == -1);
2003 if (ts
->fixed_reg
) {
2004 if (ts
->reg
!= reg
) {
2005 tcg_out_mov(s
, ts
->type
, ts
->reg
, reg
);
2008 if (ts
->val_type
== TEMP_VAL_REG
)
2009 s
->reg_to_temp
[ts
->reg
] = -1;
2010 if (IS_DEAD_ARG(i
)) {
2011 ts
->val_type
= TEMP_VAL_DEAD
;
2013 ts
->val_type
= TEMP_VAL_REG
;
2015 ts
->mem_coherent
= 0;
2016 s
->reg_to_temp
[reg
] = arg
;
2021 return nb_iargs
+ nb_oargs
+ def
->nb_cargs
+ 1;
2024 #ifdef CONFIG_PROFILER
2026 static int64_t tcg_table_op_count
[NB_OPS
];
2028 static void dump_op_count(void)
2032 f
= fopen("/tmp/op.log", "w");
2033 for(i
= INDEX_op_end
; i
< NB_OPS
; i
++) {
2034 fprintf(f
, "%s %" PRId64
"\n", tcg_op_defs
[i
].name
, tcg_table_op_count
[i
]);
2041 static inline int tcg_gen_code_common(TCGContext
*s
, uint8_t *gen_code_buf
,
2046 const TCGOpDef
*def
;
2047 unsigned int dead_args
;
2051 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP
))) {
2053 tcg_dump_ops(s
, logfile
);
2058 #ifdef USE_TCG_OPTIMIZATIONS
2060 tcg_optimize(s
, gen_opc_ptr
, gen_opparam_buf
, tcg_op_defs
);
2063 #ifdef CONFIG_PROFILER
2064 s
->la_time
-= profile_getclock();
2066 tcg_liveness_analysis(s
);
2067 #ifdef CONFIG_PROFILER
2068 s
->la_time
+= profile_getclock();
2072 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_OPT
))) {
2073 qemu_log("OP after liveness analysis:\n");
2074 tcg_dump_ops(s
, logfile
);
2079 tcg_reg_alloc_start(s
);
2081 s
->code_buf
= gen_code_buf
;
2082 s
->code_ptr
= gen_code_buf
;
2084 args
= gen_opparam_buf
;
2088 opc
= gen_opc_buf
[op_index
];
2089 #ifdef CONFIG_PROFILER
2090 tcg_table_op_count
[opc
]++;
2092 def
= &tcg_op_defs
[opc
];
2094 printf("%s: %d %d %d\n", def
->name
,
2095 def
->nb_oargs
, def
->nb_iargs
, def
->nb_cargs
);
2099 case INDEX_op_mov_i32
:
2100 #if TCG_TARGET_REG_BITS == 64
2101 case INDEX_op_mov_i64
:
2103 dead_args
= s
->op_dead_args
[op_index
];
2104 tcg_reg_alloc_mov(s
, def
, args
, dead_args
);
2106 case INDEX_op_movi_i32
:
2107 #if TCG_TARGET_REG_BITS == 64
2108 case INDEX_op_movi_i64
:
2110 tcg_reg_alloc_movi(s
, args
);
2112 case INDEX_op_debug_insn_start
:
2113 /* debug instruction */
2123 case INDEX_op_discard
:
2126 ts
= &s
->temps
[args
[0]];
2127 /* mark the temporary as dead */
2128 if (!ts
->fixed_reg
) {
2129 if (ts
->val_type
== TEMP_VAL_REG
)
2130 s
->reg_to_temp
[ts
->reg
] = -1;
2131 ts
->val_type
= TEMP_VAL_DEAD
;
2135 case INDEX_op_set_label
:
2136 tcg_reg_alloc_bb_end(s
, s
->reserved_regs
);
2137 tcg_out_label(s
, args
[0], (long)s
->code_ptr
);
2140 dead_args
= s
->op_dead_args
[op_index
];
2141 args
+= tcg_reg_alloc_call(s
, def
, opc
, args
, dead_args
);
2146 /* Sanity check that we've not introduced any unhandled opcodes. */
2147 if (def
->flags
& TCG_OPF_NOT_PRESENT
) {
2150 /* Note: in order to speed up the code, it would be much
2151 faster to have specialized register allocator functions for
2152 some common argument patterns */
2153 dead_args
= s
->op_dead_args
[op_index
];
2154 tcg_reg_alloc_op(s
, def
, opc
, args
, dead_args
);
2157 args
+= def
->nb_args
;
2159 if (search_pc
>= 0 && search_pc
< s
->code_ptr
- gen_code_buf
) {
2171 int tcg_gen_code(TCGContext
*s
, uint8_t *gen_code_buf
)
2173 #ifdef CONFIG_PROFILER
2176 n
= (gen_opc_ptr
- gen_opc_buf
);
2178 if (n
> s
->op_count_max
)
2179 s
->op_count_max
= n
;
2181 s
->temp_count
+= s
->nb_temps
;
2182 if (s
->nb_temps
> s
->temp_count_max
)
2183 s
->temp_count_max
= s
->nb_temps
;
2187 tcg_gen_code_common(s
, gen_code_buf
, -1);
2189 /* flush instruction cache */
2190 flush_icache_range((unsigned long)gen_code_buf
,
2191 (unsigned long)s
->code_ptr
);
2192 return s
->code_ptr
- gen_code_buf
;
2195 /* Return the index of the micro operation such as the pc after is <
2196 offset bytes from the start of the TB. The contents of gen_code_buf must
2197 not be changed, though writing the same values is ok.
2198 Return -1 if not found. */
2199 int tcg_gen_code_search_pc(TCGContext
*s
, uint8_t *gen_code_buf
, long offset
)
2201 return tcg_gen_code_common(s
, gen_code_buf
, offset
);
2204 #ifdef CONFIG_PROFILER
2205 void tcg_dump_info(FILE *f
, fprintf_function cpu_fprintf
)
2207 TCGContext
*s
= &tcg_ctx
;
2210 tot
= s
->interm_time
+ s
->code_time
;
2211 cpu_fprintf(f
, "JIT cycles %" PRId64
" (%0.3f s at 2.4 GHz)\n",
2213 cpu_fprintf(f
, "translated TBs %" PRId64
" (aborted=%" PRId64
" %0.1f%%)\n",
2215 s
->tb_count1
- s
->tb_count
,
2216 s
->tb_count1
? (double)(s
->tb_count1
- s
->tb_count
) / s
->tb_count1
* 100.0 : 0);
2217 cpu_fprintf(f
, "avg ops/TB %0.1f max=%d\n",
2218 s
->tb_count
? (double)s
->op_count
/ s
->tb_count
: 0, s
->op_count_max
);
2219 cpu_fprintf(f
, "deleted ops/TB %0.2f\n",
2221 (double)s
->del_op_count
/ s
->tb_count
: 0);
2222 cpu_fprintf(f
, "avg temps/TB %0.2f max=%d\n",
2224 (double)s
->temp_count
/ s
->tb_count
: 0,
2227 cpu_fprintf(f
, "cycles/op %0.1f\n",
2228 s
->op_count
? (double)tot
/ s
->op_count
: 0);
2229 cpu_fprintf(f
, "cycles/in byte %0.1f\n",
2230 s
->code_in_len
? (double)tot
/ s
->code_in_len
: 0);
2231 cpu_fprintf(f
, "cycles/out byte %0.1f\n",
2232 s
->code_out_len
? (double)tot
/ s
->code_out_len
: 0);
2235 cpu_fprintf(f
, " gen_interm time %0.1f%%\n",
2236 (double)s
->interm_time
/ tot
* 100.0);
2237 cpu_fprintf(f
, " gen_code time %0.1f%%\n",
2238 (double)s
->code_time
/ tot
* 100.0);
2239 cpu_fprintf(f
, "liveness/code time %0.1f%%\n",
2240 (double)s
->la_time
/ (s
->code_time
? s
->code_time
: 1) * 100.0);
2241 cpu_fprintf(f
, "cpu_restore count %" PRId64
"\n",
2243 cpu_fprintf(f
, " avg cycles %0.1f\n",
2244 s
->restore_count
? (double)s
->restore_time
/ s
->restore_count
: 0);
2249 void tcg_dump_info(FILE *f
, fprintf_function cpu_fprintf
)
2251 cpu_fprintf(f
, "[TCG profiler not compiled]\n");