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 /* Define to jump the ELF file used to communicate with GDB. */
34 #if !defined(CONFIG_DEBUG_TCG) && !defined(NDEBUG)
35 /* define it to suppress various consistency checks (faster) */
39 #include "qemu-common.h"
40 #include "qemu/cache-utils.h"
41 #include "qemu/host-utils.h"
42 #include "qemu/timer.h"
44 /* Note: the long term plan is to reduce the dependancies on the QEMU
45 CPU definitions. Currently they are used for qemu_ld/st
47 #define NO_CPU_IO_DEFS
52 #if UINTPTR_MAX == UINT32_MAX
53 # define ELF_CLASS ELFCLASS32
55 # define ELF_CLASS ELFCLASS64
57 #ifdef HOST_WORDS_BIGENDIAN
58 # define ELF_DATA ELFDATA2MSB
60 # define ELF_DATA ELFDATA2LSB
65 /* Forward declarations for functions declared in tcg-target.c and used here. */
66 static void tcg_target_init(TCGContext
*s
);
67 static void tcg_target_qemu_prologue(TCGContext
*s
);
68 static void patch_reloc(uint8_t *code_ptr
, int type
,
69 intptr_t value
, intptr_t addend
);
71 /* The CIE and FDE header definitions will be common to all hosts. */
73 uint32_t len
__attribute__((aligned((sizeof(void *)))));
79 uint8_t return_column
;
82 typedef struct QEMU_PACKED
{
83 uint32_t len
__attribute__((aligned((sizeof(void *)))));
87 } DebugFrameFDEHeader
;
89 static void tcg_register_jit_int(void *buf
, size_t size
,
90 void *debug_frame
, size_t debug_frame_size
)
91 __attribute__((unused
));
93 /* Forward declarations for functions declared and used in tcg-target.c. */
94 static int target_parse_constraint(TCGArgConstraint
*ct
, const char **pct_str
);
95 static void tcg_out_ld(TCGContext
*s
, TCGType type
, TCGReg ret
, TCGReg arg1
,
97 static void tcg_out_mov(TCGContext
*s
, TCGType type
, TCGReg ret
, TCGReg arg
);
98 static void tcg_out_movi(TCGContext
*s
, TCGType type
,
99 TCGReg ret
, tcg_target_long arg
);
100 static void tcg_out_op(TCGContext
*s
, TCGOpcode opc
, const TCGArg
*args
,
101 const int *const_args
);
102 static void tcg_out_st(TCGContext
*s
, TCGType type
, TCGReg arg
, TCGReg arg1
,
104 static int tcg_target_const_match(tcg_target_long val
,
105 const TCGArgConstraint
*arg_ct
);
107 TCGOpDef tcg_op_defs
[] = {
108 #define DEF(s, oargs, iargs, cargs, flags) { #s, oargs, iargs, cargs, iargs + oargs + cargs, flags },
112 const size_t tcg_op_defs_max
= ARRAY_SIZE(tcg_op_defs
);
114 static TCGRegSet tcg_target_available_regs
[2];
115 static TCGRegSet tcg_target_call_clobber_regs
;
117 static inline void tcg_out8(TCGContext
*s
, uint8_t v
)
122 static inline void tcg_out16(TCGContext
*s
, uint16_t v
)
124 uint8_t *p
= s
->code_ptr
;
129 static inline void tcg_out32(TCGContext
*s
, uint32_t v
)
131 uint8_t *p
= s
->code_ptr
;
136 static inline void tcg_out64(TCGContext
*s
, uint64_t v
)
138 uint8_t *p
= s
->code_ptr
;
143 /* label relocation processing */
145 static void tcg_out_reloc(TCGContext
*s
, uint8_t *code_ptr
, int type
,
146 int label_index
, intptr_t addend
)
151 l
= &s
->labels
[label_index
];
153 /* FIXME: This may break relocations on RISC targets that
154 modify instruction fields in place. The caller may not have
155 written the initial value. */
156 patch_reloc(code_ptr
, type
, l
->u
.value
, addend
);
158 /* add a new relocation entry */
159 r
= tcg_malloc(sizeof(TCGRelocation
));
163 r
->next
= l
->u
.first_reloc
;
164 l
->u
.first_reloc
= r
;
168 static void tcg_out_label(TCGContext
*s
, int label_index
, void *ptr
)
172 intptr_t value
= (intptr_t)ptr
;
174 l
= &s
->labels
[label_index
];
178 r
= l
->u
.first_reloc
;
180 patch_reloc(r
->ptr
, r
->type
, value
, r
->addend
);
187 int gen_new_label(void)
189 TCGContext
*s
= &tcg_ctx
;
193 if (s
->nb_labels
>= TCG_MAX_LABELS
)
195 idx
= s
->nb_labels
++;
198 l
->u
.first_reloc
= NULL
;
202 #include "tcg-target.c"
204 /* pool based memory allocation */
205 void *tcg_malloc_internal(TCGContext
*s
, int size
)
210 if (size
> TCG_POOL_CHUNK_SIZE
) {
211 /* big malloc: insert a new pool (XXX: could optimize) */
212 p
= g_malloc(sizeof(TCGPool
) + size
);
214 p
->next
= s
->pool_first_large
;
215 s
->pool_first_large
= p
;
226 pool_size
= TCG_POOL_CHUNK_SIZE
;
227 p
= g_malloc(sizeof(TCGPool
) + pool_size
);
231 s
->pool_current
->next
= p
;
240 s
->pool_cur
= p
->data
+ size
;
241 s
->pool_end
= p
->data
+ p
->size
;
245 void tcg_pool_reset(TCGContext
*s
)
248 for (p
= s
->pool_first_large
; p
; p
= t
) {
252 s
->pool_first_large
= NULL
;
253 s
->pool_cur
= s
->pool_end
= NULL
;
254 s
->pool_current
= NULL
;
259 typedef struct TCGHelperInfo
{
264 static const TCGHelperInfo all_helpers
[] = {
268 /* Include tcg-runtime.c functions. */
269 { tcg_helper_div_i32
, "div_i32" },
270 { tcg_helper_rem_i32
, "rem_i32" },
271 { tcg_helper_divu_i32
, "divu_i32" },
272 { tcg_helper_remu_i32
, "remu_i32" },
274 { tcg_helper_shl_i64
, "shl_i64" },
275 { tcg_helper_shr_i64
, "shr_i64" },
276 { tcg_helper_sar_i64
, "sar_i64" },
277 { tcg_helper_div_i64
, "div_i64" },
278 { tcg_helper_rem_i64
, "rem_i64" },
279 { tcg_helper_divu_i64
, "divu_i64" },
280 { tcg_helper_remu_i64
, "remu_i64" },
281 { tcg_helper_mulsh_i64
, "mulsh_i64" },
282 { tcg_helper_muluh_i64
, "muluh_i64" },
285 void tcg_context_init(TCGContext
*s
)
287 int op
, total_args
, n
, i
;
289 TCGArgConstraint
*args_ct
;
292 memset(s
, 0, sizeof(*s
));
295 /* Count total number of arguments and allocate the corresponding
298 for(op
= 0; op
< NB_OPS
; op
++) {
299 def
= &tcg_op_defs
[op
];
300 n
= def
->nb_iargs
+ def
->nb_oargs
;
304 args_ct
= g_malloc(sizeof(TCGArgConstraint
) * total_args
);
305 sorted_args
= g_malloc(sizeof(int) * total_args
);
307 for(op
= 0; op
< NB_OPS
; op
++) {
308 def
= &tcg_op_defs
[op
];
309 def
->args_ct
= args_ct
;
310 def
->sorted_args
= sorted_args
;
311 n
= def
->nb_iargs
+ def
->nb_oargs
;
316 /* Register helpers. */
317 for (i
= 0; i
< ARRAY_SIZE(all_helpers
); ++i
) {
318 tcg_register_helper(all_helpers
[i
].func
, all_helpers
[i
].name
);
324 void tcg_prologue_init(TCGContext
*s
)
326 /* init global prologue and epilogue */
327 s
->code_buf
= s
->code_gen_prologue
;
328 s
->code_ptr
= s
->code_buf
;
329 tcg_target_qemu_prologue(s
);
330 flush_icache_range((uintptr_t)s
->code_buf
, (uintptr_t)s
->code_ptr
);
333 if (qemu_loglevel_mask(CPU_LOG_TB_OUT_ASM
)) {
334 size_t size
= s
->code_ptr
- s
->code_buf
;
335 qemu_log("PROLOGUE: [size=%zu]\n", size
);
336 log_disas(s
->code_buf
, size
);
343 void tcg_set_frame(TCGContext
*s
, int reg
, intptr_t start
, intptr_t size
)
345 s
->frame_start
= start
;
346 s
->frame_end
= start
+ size
;
350 void tcg_func_start(TCGContext
*s
)
354 s
->nb_temps
= s
->nb_globals
;
355 for(i
= 0; i
< (TCG_TYPE_COUNT
* 2); i
++)
356 s
->first_free_temp
[i
] = -1;
357 s
->labels
= tcg_malloc(sizeof(TCGLabel
) * TCG_MAX_LABELS
);
359 s
->current_frame_offset
= s
->frame_start
;
361 #ifdef CONFIG_DEBUG_TCG
362 s
->goto_tb_issue_mask
= 0;
365 s
->gen_opc_ptr
= s
->gen_opc_buf
;
366 s
->gen_opparam_ptr
= s
->gen_opparam_buf
;
368 #if defined(CONFIG_QEMU_LDST_OPTIMIZATION) && defined(CONFIG_SOFTMMU)
369 /* Initialize qemu_ld/st labels to assist code generation at the end of TB
370 for TLB miss cases at the end of TB */
371 s
->qemu_ldst_labels
= tcg_malloc(sizeof(TCGLabelQemuLdst
) *
373 s
->nb_qemu_ldst_labels
= 0;
377 static inline void tcg_temp_alloc(TCGContext
*s
, int n
)
379 if (n
> TCG_MAX_TEMPS
)
383 static inline int tcg_global_reg_new_internal(TCGType type
, int reg
,
386 TCGContext
*s
= &tcg_ctx
;
390 #if TCG_TARGET_REG_BITS == 32
391 if (type
!= TCG_TYPE_I32
)
394 if (tcg_regset_test_reg(s
->reserved_regs
, reg
))
397 tcg_temp_alloc(s
, s
->nb_globals
+ 1);
398 ts
= &s
->temps
[s
->nb_globals
];
399 ts
->base_type
= type
;
405 tcg_regset_set_reg(s
->reserved_regs
, reg
);
409 TCGv_i32
tcg_global_reg_new_i32(int reg
, const char *name
)
413 idx
= tcg_global_reg_new_internal(TCG_TYPE_I32
, reg
, name
);
414 return MAKE_TCGV_I32(idx
);
417 TCGv_i64
tcg_global_reg_new_i64(int reg
, const char *name
)
421 idx
= tcg_global_reg_new_internal(TCG_TYPE_I64
, reg
, name
);
422 return MAKE_TCGV_I64(idx
);
425 static inline int tcg_global_mem_new_internal(TCGType type
, int reg
,
429 TCGContext
*s
= &tcg_ctx
;
434 #if TCG_TARGET_REG_BITS == 32
435 if (type
== TCG_TYPE_I64
) {
437 tcg_temp_alloc(s
, s
->nb_globals
+ 2);
438 ts
= &s
->temps
[s
->nb_globals
];
439 ts
->base_type
= type
;
440 ts
->type
= TCG_TYPE_I32
;
442 ts
->mem_allocated
= 1;
444 #ifdef TCG_TARGET_WORDS_BIGENDIAN
445 ts
->mem_offset
= offset
+ 4;
447 ts
->mem_offset
= offset
;
449 pstrcpy(buf
, sizeof(buf
), name
);
450 pstrcat(buf
, sizeof(buf
), "_0");
451 ts
->name
= strdup(buf
);
454 ts
->base_type
= type
;
455 ts
->type
= TCG_TYPE_I32
;
457 ts
->mem_allocated
= 1;
459 #ifdef TCG_TARGET_WORDS_BIGENDIAN
460 ts
->mem_offset
= offset
;
462 ts
->mem_offset
= offset
+ 4;
464 pstrcpy(buf
, sizeof(buf
), name
);
465 pstrcat(buf
, sizeof(buf
), "_1");
466 ts
->name
= strdup(buf
);
472 tcg_temp_alloc(s
, s
->nb_globals
+ 1);
473 ts
= &s
->temps
[s
->nb_globals
];
474 ts
->base_type
= type
;
477 ts
->mem_allocated
= 1;
479 ts
->mem_offset
= offset
;
486 TCGv_i32
tcg_global_mem_new_i32(int reg
, intptr_t offset
, const char *name
)
488 int idx
= tcg_global_mem_new_internal(TCG_TYPE_I32
, reg
, offset
, name
);
489 return MAKE_TCGV_I32(idx
);
492 TCGv_i64
tcg_global_mem_new_i64(int reg
, intptr_t offset
, const char *name
)
494 int idx
= tcg_global_mem_new_internal(TCG_TYPE_I64
, reg
, offset
, name
);
495 return MAKE_TCGV_I64(idx
);
498 static inline int tcg_temp_new_internal(TCGType type
, int temp_local
)
500 TCGContext
*s
= &tcg_ctx
;
507 idx
= s
->first_free_temp
[k
];
509 /* There is already an available temp with the
512 s
->first_free_temp
[k
] = ts
->next_free_temp
;
513 ts
->temp_allocated
= 1;
514 assert(ts
->temp_local
== temp_local
);
517 #if TCG_TARGET_REG_BITS == 32
518 if (type
== TCG_TYPE_I64
) {
519 tcg_temp_alloc(s
, s
->nb_temps
+ 2);
520 ts
= &s
->temps
[s
->nb_temps
];
521 ts
->base_type
= type
;
522 ts
->type
= TCG_TYPE_I32
;
523 ts
->temp_allocated
= 1;
524 ts
->temp_local
= temp_local
;
527 ts
->base_type
= TCG_TYPE_I32
;
528 ts
->type
= TCG_TYPE_I32
;
529 ts
->temp_allocated
= 1;
530 ts
->temp_local
= temp_local
;
536 tcg_temp_alloc(s
, s
->nb_temps
+ 1);
537 ts
= &s
->temps
[s
->nb_temps
];
538 ts
->base_type
= type
;
540 ts
->temp_allocated
= 1;
541 ts
->temp_local
= temp_local
;
547 #if defined(CONFIG_DEBUG_TCG)
553 TCGv_i32
tcg_temp_new_internal_i32(int temp_local
)
557 idx
= tcg_temp_new_internal(TCG_TYPE_I32
, temp_local
);
558 return MAKE_TCGV_I32(idx
);
561 TCGv_i64
tcg_temp_new_internal_i64(int temp_local
)
565 idx
= tcg_temp_new_internal(TCG_TYPE_I64
, temp_local
);
566 return MAKE_TCGV_I64(idx
);
569 static inline void tcg_temp_free_internal(int idx
)
571 TCGContext
*s
= &tcg_ctx
;
575 #if defined(CONFIG_DEBUG_TCG)
577 if (s
->temps_in_use
< 0) {
578 fprintf(stderr
, "More temporaries freed than allocated!\n");
582 assert(idx
>= s
->nb_globals
&& idx
< s
->nb_temps
);
584 assert(ts
->temp_allocated
!= 0);
585 ts
->temp_allocated
= 0;
589 ts
->next_free_temp
= s
->first_free_temp
[k
];
590 s
->first_free_temp
[k
] = idx
;
593 void tcg_temp_free_i32(TCGv_i32 arg
)
595 tcg_temp_free_internal(GET_TCGV_I32(arg
));
598 void tcg_temp_free_i64(TCGv_i64 arg
)
600 tcg_temp_free_internal(GET_TCGV_I64(arg
));
603 TCGv_i32
tcg_const_i32(int32_t val
)
606 t0
= tcg_temp_new_i32();
607 tcg_gen_movi_i32(t0
, val
);
611 TCGv_i64
tcg_const_i64(int64_t val
)
614 t0
= tcg_temp_new_i64();
615 tcg_gen_movi_i64(t0
, val
);
619 TCGv_i32
tcg_const_local_i32(int32_t val
)
622 t0
= tcg_temp_local_new_i32();
623 tcg_gen_movi_i32(t0
, val
);
627 TCGv_i64
tcg_const_local_i64(int64_t val
)
630 t0
= tcg_temp_local_new_i64();
631 tcg_gen_movi_i64(t0
, val
);
635 #if defined(CONFIG_DEBUG_TCG)
636 void tcg_clear_temp_count(void)
638 TCGContext
*s
= &tcg_ctx
;
642 int tcg_check_temp_count(void)
644 TCGContext
*s
= &tcg_ctx
;
645 if (s
->temps_in_use
) {
646 /* Clear the count so that we don't give another
647 * warning immediately next time around.
656 void tcg_register_helper(void *func
, const char *name
)
658 TCGContext
*s
= &tcg_ctx
;
659 GHashTable
*table
= s
->helpers
;
662 /* Use g_direct_hash/equal for direct pointer comparisons on func. */
663 table
= g_hash_table_new(NULL
, NULL
);
667 g_hash_table_insert(table
, (gpointer
)func
, (gpointer
)name
);
670 /* Note: we convert the 64 bit args to 32 bit and do some alignment
671 and endian swap. Maybe it would be better to do the alignment
672 and endian swap in tcg_reg_alloc_call(). */
673 void tcg_gen_callN(TCGContext
*s
, TCGv_ptr func
, unsigned int flags
,
674 int sizemask
, TCGArg ret
, int nargs
, TCGArg
*args
)
681 #if defined(TCG_TARGET_EXTEND_ARGS) && TCG_TARGET_REG_BITS == 64
682 for (i
= 0; i
< nargs
; ++i
) {
683 int is_64bit
= sizemask
& (1 << (i
+1)*2);
684 int is_signed
= sizemask
& (2 << (i
+1)*2);
686 TCGv_i64 temp
= tcg_temp_new_i64();
687 TCGv_i64 orig
= MAKE_TCGV_I64(args
[i
]);
689 tcg_gen_ext32s_i64(temp
, orig
);
691 tcg_gen_ext32u_i64(temp
, orig
);
693 args
[i
] = GET_TCGV_I64(temp
);
696 #endif /* TCG_TARGET_EXTEND_ARGS */
698 *s
->gen_opc_ptr
++ = INDEX_op_call
;
699 nparam
= s
->gen_opparam_ptr
++;
700 if (ret
!= TCG_CALL_DUMMY_ARG
) {
701 #if TCG_TARGET_REG_BITS < 64
703 #ifdef TCG_TARGET_WORDS_BIGENDIAN
704 *s
->gen_opparam_ptr
++ = ret
+ 1;
705 *s
->gen_opparam_ptr
++ = ret
;
707 *s
->gen_opparam_ptr
++ = ret
;
708 *s
->gen_opparam_ptr
++ = ret
+ 1;
714 *s
->gen_opparam_ptr
++ = ret
;
721 for (i
= 0; i
< nargs
; i
++) {
722 #if TCG_TARGET_REG_BITS < 64
723 int is_64bit
= sizemask
& (1 << (i
+1)*2);
725 #ifdef TCG_TARGET_CALL_ALIGN_ARGS
726 /* some targets want aligned 64 bit args */
728 *s
->gen_opparam_ptr
++ = TCG_CALL_DUMMY_ARG
;
732 /* If stack grows up, then we will be placing successive
733 arguments at lower addresses, which means we need to
734 reverse the order compared to how we would normally
735 treat either big or little-endian. For those arguments
736 that will wind up in registers, this still works for
737 HPPA (the only current STACK_GROWSUP target) since the
738 argument registers are *also* allocated in decreasing
739 order. If another such target is added, this logic may
740 have to get more complicated to differentiate between
741 stack arguments and register arguments. */
742 #if defined(TCG_TARGET_WORDS_BIGENDIAN) != defined(TCG_TARGET_STACK_GROWSUP)
743 *s
->gen_opparam_ptr
++ = args
[i
] + 1;
744 *s
->gen_opparam_ptr
++ = args
[i
];
746 *s
->gen_opparam_ptr
++ = args
[i
];
747 *s
->gen_opparam_ptr
++ = args
[i
] + 1;
752 #endif /* TCG_TARGET_REG_BITS < 64 */
754 *s
->gen_opparam_ptr
++ = args
[i
];
757 *s
->gen_opparam_ptr
++ = GET_TCGV_PTR(func
);
759 *s
->gen_opparam_ptr
++ = flags
;
761 *nparam
= (nb_rets
<< 16) | (real_args
+ 1);
763 /* total parameters, needed to go backward in the instruction stream */
764 *s
->gen_opparam_ptr
++ = 1 + nb_rets
+ real_args
+ 3;
766 #if defined(TCG_TARGET_EXTEND_ARGS) && TCG_TARGET_REG_BITS == 64
767 for (i
= 0; i
< nargs
; ++i
) {
768 int is_64bit
= sizemask
& (1 << (i
+1)*2);
770 TCGv_i64 temp
= MAKE_TCGV_I64(args
[i
]);
771 tcg_temp_free_i64(temp
);
774 #endif /* TCG_TARGET_EXTEND_ARGS */
777 #if TCG_TARGET_REG_BITS == 32
778 void tcg_gen_shifti_i64(TCGv_i64 ret
, TCGv_i64 arg1
,
779 int c
, int right
, int arith
)
782 tcg_gen_mov_i32(TCGV_LOW(ret
), TCGV_LOW(arg1
));
783 tcg_gen_mov_i32(TCGV_HIGH(ret
), TCGV_HIGH(arg1
));
784 } else if (c
>= 32) {
788 tcg_gen_sari_i32(TCGV_LOW(ret
), TCGV_HIGH(arg1
), c
);
789 tcg_gen_sari_i32(TCGV_HIGH(ret
), TCGV_HIGH(arg1
), 31);
791 tcg_gen_shri_i32(TCGV_LOW(ret
), TCGV_HIGH(arg1
), c
);
792 tcg_gen_movi_i32(TCGV_HIGH(ret
), 0);
795 tcg_gen_shli_i32(TCGV_HIGH(ret
), TCGV_LOW(arg1
), c
);
796 tcg_gen_movi_i32(TCGV_LOW(ret
), 0);
801 t0
= tcg_temp_new_i32();
802 t1
= tcg_temp_new_i32();
804 tcg_gen_shli_i32(t0
, TCGV_HIGH(arg1
), 32 - c
);
806 tcg_gen_sari_i32(t1
, TCGV_HIGH(arg1
), c
);
808 tcg_gen_shri_i32(t1
, TCGV_HIGH(arg1
), c
);
809 tcg_gen_shri_i32(TCGV_LOW(ret
), TCGV_LOW(arg1
), c
);
810 tcg_gen_or_i32(TCGV_LOW(ret
), TCGV_LOW(ret
), t0
);
811 tcg_gen_mov_i32(TCGV_HIGH(ret
), t1
);
813 tcg_gen_shri_i32(t0
, TCGV_LOW(arg1
), 32 - c
);
814 /* Note: ret can be the same as arg1, so we use t1 */
815 tcg_gen_shli_i32(t1
, TCGV_LOW(arg1
), c
);
816 tcg_gen_shli_i32(TCGV_HIGH(ret
), TCGV_HIGH(arg1
), c
);
817 tcg_gen_or_i32(TCGV_HIGH(ret
), TCGV_HIGH(ret
), t0
);
818 tcg_gen_mov_i32(TCGV_LOW(ret
), t1
);
820 tcg_temp_free_i32(t0
);
821 tcg_temp_free_i32(t1
);
827 static void tcg_reg_alloc_start(TCGContext
*s
)
831 for(i
= 0; i
< s
->nb_globals
; i
++) {
834 ts
->val_type
= TEMP_VAL_REG
;
836 ts
->val_type
= TEMP_VAL_MEM
;
839 for(i
= s
->nb_globals
; i
< s
->nb_temps
; i
++) {
841 if (ts
->temp_local
) {
842 ts
->val_type
= TEMP_VAL_MEM
;
844 ts
->val_type
= TEMP_VAL_DEAD
;
846 ts
->mem_allocated
= 0;
849 for(i
= 0; i
< TCG_TARGET_NB_REGS
; i
++) {
850 s
->reg_to_temp
[i
] = -1;
854 static char *tcg_get_arg_str_idx(TCGContext
*s
, char *buf
, int buf_size
,
859 assert(idx
>= 0 && idx
< s
->nb_temps
);
861 if (idx
< s
->nb_globals
) {
862 pstrcpy(buf
, buf_size
, ts
->name
);
865 snprintf(buf
, buf_size
, "loc%d", idx
- s
->nb_globals
);
867 snprintf(buf
, buf_size
, "tmp%d", idx
- s
->nb_globals
);
872 char *tcg_get_arg_str_i32(TCGContext
*s
, char *buf
, int buf_size
, TCGv_i32 arg
)
874 return tcg_get_arg_str_idx(s
, buf
, buf_size
, GET_TCGV_I32(arg
));
877 char *tcg_get_arg_str_i64(TCGContext
*s
, char *buf
, int buf_size
, TCGv_i64 arg
)
879 return tcg_get_arg_str_idx(s
, buf
, buf_size
, GET_TCGV_I64(arg
));
882 /* Find helper name. */
883 static inline const char *tcg_find_helper(TCGContext
*s
, uintptr_t val
)
885 const char *ret
= NULL
;
887 ret
= g_hash_table_lookup(s
->helpers
, (gpointer
)val
);
892 static const char * const cond_name
[] =
894 [TCG_COND_NEVER
] = "never",
895 [TCG_COND_ALWAYS
] = "always",
896 [TCG_COND_EQ
] = "eq",
897 [TCG_COND_NE
] = "ne",
898 [TCG_COND_LT
] = "lt",
899 [TCG_COND_GE
] = "ge",
900 [TCG_COND_LE
] = "le",
901 [TCG_COND_GT
] = "gt",
902 [TCG_COND_LTU
] = "ltu",
903 [TCG_COND_GEU
] = "geu",
904 [TCG_COND_LEU
] = "leu",
905 [TCG_COND_GTU
] = "gtu"
908 void tcg_dump_ops(TCGContext
*s
)
910 const uint16_t *opc_ptr
;
914 int i
, k
, nb_oargs
, nb_iargs
, nb_cargs
, first_insn
;
919 opc_ptr
= s
->gen_opc_buf
;
920 args
= s
->gen_opparam_buf
;
921 while (opc_ptr
< s
->gen_opc_ptr
) {
923 def
= &tcg_op_defs
[c
];
924 if (c
== INDEX_op_debug_insn_start
) {
926 #if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
927 pc
= ((uint64_t)args
[1] << 32) | args
[0];
934 qemu_log(" ---- 0x%" PRIx64
, pc
);
936 nb_oargs
= def
->nb_oargs
;
937 nb_iargs
= def
->nb_iargs
;
938 nb_cargs
= def
->nb_cargs
;
939 } else if (c
== INDEX_op_call
) {
942 /* variable number of arguments */
944 nb_oargs
= arg
>> 16;
945 nb_iargs
= arg
& 0xffff;
946 nb_cargs
= def
->nb_cargs
;
948 qemu_log(" %s ", def
->name
);
952 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
),
953 args
[nb_oargs
+ nb_iargs
- 1]));
955 qemu_log(",$0x%" TCG_PRIlx
, args
[nb_oargs
+ nb_iargs
]);
957 qemu_log(",$%d", nb_oargs
);
958 for(i
= 0; i
< nb_oargs
; i
++) {
960 qemu_log("%s", tcg_get_arg_str_idx(s
, buf
, sizeof(buf
),
963 for(i
= 0; i
< (nb_iargs
- 1); i
++) {
965 if (args
[nb_oargs
+ i
] == TCG_CALL_DUMMY_ARG
) {
968 qemu_log("%s", tcg_get_arg_str_idx(s
, buf
, sizeof(buf
),
969 args
[nb_oargs
+ i
]));
972 } else if (c
== INDEX_op_movi_i32
|| c
== INDEX_op_movi_i64
) {
973 tcg_target_ulong val
;
976 nb_oargs
= def
->nb_oargs
;
977 nb_iargs
= def
->nb_iargs
;
978 nb_cargs
= def
->nb_cargs
;
979 qemu_log(" %s %s,$", def
->name
,
980 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), args
[0]));
982 name
= tcg_find_helper(s
, val
);
984 qemu_log("%s", name
);
986 if (c
== INDEX_op_movi_i32
) {
987 qemu_log("0x%x", (uint32_t)val
);
989 qemu_log("0x%" PRIx64
, (uint64_t)val
);
993 qemu_log(" %s ", def
->name
);
994 if (c
== INDEX_op_nopn
) {
995 /* variable number of arguments */
1000 nb_oargs
= def
->nb_oargs
;
1001 nb_iargs
= def
->nb_iargs
;
1002 nb_cargs
= def
->nb_cargs
;
1006 for(i
= 0; i
< nb_oargs
; i
++) {
1010 qemu_log("%s", tcg_get_arg_str_idx(s
, buf
, sizeof(buf
),
1013 for(i
= 0; i
< nb_iargs
; i
++) {
1017 qemu_log("%s", tcg_get_arg_str_idx(s
, buf
, sizeof(buf
),
1021 case INDEX_op_brcond_i32
:
1022 case INDEX_op_setcond_i32
:
1023 case INDEX_op_movcond_i32
:
1024 case INDEX_op_brcond2_i32
:
1025 case INDEX_op_setcond2_i32
:
1026 case INDEX_op_brcond_i64
:
1027 case INDEX_op_setcond_i64
:
1028 case INDEX_op_movcond_i64
:
1029 if (args
[k
] < ARRAY_SIZE(cond_name
) && cond_name
[args
[k
]]) {
1030 qemu_log(",%s", cond_name
[args
[k
++]]);
1032 qemu_log(",$0x%" TCG_PRIlx
, args
[k
++]);
1040 for(; i
< nb_cargs
; i
++) {
1045 qemu_log("$0x%" TCG_PRIlx
, arg
);
1049 args
+= nb_iargs
+ nb_oargs
+ nb_cargs
;
1053 /* we give more priority to constraints with less registers */
1054 static int get_constraint_priority(const TCGOpDef
*def
, int k
)
1056 const TCGArgConstraint
*arg_ct
;
1059 arg_ct
= &def
->args_ct
[k
];
1060 if (arg_ct
->ct
& TCG_CT_ALIAS
) {
1061 /* an alias is equivalent to a single register */
1064 if (!(arg_ct
->ct
& TCG_CT_REG
))
1067 for(i
= 0; i
< TCG_TARGET_NB_REGS
; i
++) {
1068 if (tcg_regset_test_reg(arg_ct
->u
.regs
, i
))
1072 return TCG_TARGET_NB_REGS
- n
+ 1;
1075 /* sort from highest priority to lowest */
1076 static void sort_constraints(TCGOpDef
*def
, int start
, int n
)
1078 int i
, j
, p1
, p2
, tmp
;
1080 for(i
= 0; i
< n
; i
++)
1081 def
->sorted_args
[start
+ i
] = start
+ i
;
1084 for(i
= 0; i
< n
- 1; i
++) {
1085 for(j
= i
+ 1; j
< n
; j
++) {
1086 p1
= get_constraint_priority(def
, def
->sorted_args
[start
+ i
]);
1087 p2
= get_constraint_priority(def
, def
->sorted_args
[start
+ j
]);
1089 tmp
= def
->sorted_args
[start
+ i
];
1090 def
->sorted_args
[start
+ i
] = def
->sorted_args
[start
+ j
];
1091 def
->sorted_args
[start
+ j
] = tmp
;
1097 void tcg_add_target_add_op_defs(const TCGTargetOpDef
*tdefs
)
1105 if (tdefs
->op
== (TCGOpcode
)-1)
1108 assert((unsigned)op
< NB_OPS
);
1109 def
= &tcg_op_defs
[op
];
1110 #if defined(CONFIG_DEBUG_TCG)
1111 /* Duplicate entry in op definitions? */
1115 nb_args
= def
->nb_iargs
+ def
->nb_oargs
;
1116 for(i
= 0; i
< nb_args
; i
++) {
1117 ct_str
= tdefs
->args_ct_str
[i
];
1118 /* Incomplete TCGTargetOpDef entry? */
1119 assert(ct_str
!= NULL
);
1120 tcg_regset_clear(def
->args_ct
[i
].u
.regs
);
1121 def
->args_ct
[i
].ct
= 0;
1122 if (ct_str
[0] >= '0' && ct_str
[0] <= '9') {
1124 oarg
= ct_str
[0] - '0';
1125 assert(oarg
< def
->nb_oargs
);
1126 assert(def
->args_ct
[oarg
].ct
& TCG_CT_REG
);
1127 /* TCG_CT_ALIAS is for the output arguments. The input
1128 argument is tagged with TCG_CT_IALIAS. */
1129 def
->args_ct
[i
] = def
->args_ct
[oarg
];
1130 def
->args_ct
[oarg
].ct
= TCG_CT_ALIAS
;
1131 def
->args_ct
[oarg
].alias_index
= i
;
1132 def
->args_ct
[i
].ct
|= TCG_CT_IALIAS
;
1133 def
->args_ct
[i
].alias_index
= oarg
;
1136 if (*ct_str
== '\0')
1140 def
->args_ct
[i
].ct
|= TCG_CT_CONST
;
1144 if (target_parse_constraint(&def
->args_ct
[i
], &ct_str
) < 0) {
1145 fprintf(stderr
, "Invalid constraint '%s' for arg %d of operation '%s'\n",
1146 ct_str
, i
, def
->name
);
1154 /* TCGTargetOpDef entry with too much information? */
1155 assert(i
== TCG_MAX_OP_ARGS
|| tdefs
->args_ct_str
[i
] == NULL
);
1157 /* sort the constraints (XXX: this is just an heuristic) */
1158 sort_constraints(def
, 0, def
->nb_oargs
);
1159 sort_constraints(def
, def
->nb_oargs
, def
->nb_iargs
);
1165 printf("%s: sorted=", def
->name
);
1166 for(i
= 0; i
< def
->nb_oargs
+ def
->nb_iargs
; i
++)
1167 printf(" %d", def
->sorted_args
[i
]);
1174 #if defined(CONFIG_DEBUG_TCG)
1176 for (op
= 0; op
< ARRAY_SIZE(tcg_op_defs
); op
++) {
1177 const TCGOpDef
*def
= &tcg_op_defs
[op
];
1178 if (def
->flags
& TCG_OPF_NOT_PRESENT
) {
1179 /* Wrong entry in op definitions? */
1181 fprintf(stderr
, "Invalid op definition for %s\n", def
->name
);
1185 /* Missing entry in op definitions? */
1187 fprintf(stderr
, "Missing op definition for %s\n", def
->name
);
1198 #ifdef USE_LIVENESS_ANALYSIS
1200 /* set a nop for an operation using 'nb_args' */
1201 static inline void tcg_set_nop(TCGContext
*s
, uint16_t *opc_ptr
,
1202 TCGArg
*args
, int nb_args
)
1205 *opc_ptr
= INDEX_op_nop
;
1207 *opc_ptr
= INDEX_op_nopn
;
1209 args
[nb_args
- 1] = nb_args
;
1213 /* liveness analysis: end of function: all temps are dead, and globals
1214 should be in memory. */
1215 static inline void tcg_la_func_end(TCGContext
*s
, uint8_t *dead_temps
,
1218 memset(dead_temps
, 1, s
->nb_temps
);
1219 memset(mem_temps
, 1, s
->nb_globals
);
1220 memset(mem_temps
+ s
->nb_globals
, 0, s
->nb_temps
- s
->nb_globals
);
1223 /* liveness analysis: end of basic block: all temps are dead, globals
1224 and local temps should be in memory. */
1225 static inline void tcg_la_bb_end(TCGContext
*s
, uint8_t *dead_temps
,
1230 memset(dead_temps
, 1, s
->nb_temps
);
1231 memset(mem_temps
, 1, s
->nb_globals
);
1232 for(i
= s
->nb_globals
; i
< s
->nb_temps
; i
++) {
1233 mem_temps
[i
] = s
->temps
[i
].temp_local
;
1237 /* Liveness analysis : update the opc_dead_args array to tell if a
1238 given input arguments is dead. Instructions updating dead
1239 temporaries are removed. */
1240 static void tcg_liveness_analysis(TCGContext
*s
)
1242 int i
, op_index
, nb_args
, nb_iargs
, nb_oargs
, arg
, nb_ops
;
1243 TCGOpcode op
, op_new
, op_new2
;
1245 const TCGOpDef
*def
;
1246 uint8_t *dead_temps
, *mem_temps
;
1251 s
->gen_opc_ptr
++; /* skip end */
1253 nb_ops
= s
->gen_opc_ptr
- s
->gen_opc_buf
;
1255 s
->op_dead_args
= tcg_malloc(nb_ops
* sizeof(uint16_t));
1256 s
->op_sync_args
= tcg_malloc(nb_ops
* sizeof(uint8_t));
1258 dead_temps
= tcg_malloc(s
->nb_temps
);
1259 mem_temps
= tcg_malloc(s
->nb_temps
);
1260 tcg_la_func_end(s
, dead_temps
, mem_temps
);
1262 args
= s
->gen_opparam_ptr
;
1263 op_index
= nb_ops
- 1;
1264 while (op_index
>= 0) {
1265 op
= s
->gen_opc_buf
[op_index
];
1266 def
= &tcg_op_defs
[op
];
1274 nb_iargs
= args
[0] & 0xffff;
1275 nb_oargs
= args
[0] >> 16;
1277 call_flags
= args
[nb_oargs
+ nb_iargs
];
1279 /* pure functions can be removed if their result is not
1281 if (call_flags
& TCG_CALL_NO_SIDE_EFFECTS
) {
1282 for(i
= 0; i
< nb_oargs
; i
++) {
1284 if (!dead_temps
[arg
] || mem_temps
[arg
]) {
1285 goto do_not_remove_call
;
1288 tcg_set_nop(s
, s
->gen_opc_buf
+ op_index
,
1293 /* output args are dead */
1296 for(i
= 0; i
< nb_oargs
; i
++) {
1298 if (dead_temps
[arg
]) {
1299 dead_args
|= (1 << i
);
1301 if (mem_temps
[arg
]) {
1302 sync_args
|= (1 << i
);
1304 dead_temps
[arg
] = 1;
1308 if (!(call_flags
& TCG_CALL_NO_READ_GLOBALS
)) {
1309 /* globals should be synced to memory */
1310 memset(mem_temps
, 1, s
->nb_globals
);
1312 if (!(call_flags
& (TCG_CALL_NO_WRITE_GLOBALS
|
1313 TCG_CALL_NO_READ_GLOBALS
))) {
1314 /* globals should go back to memory */
1315 memset(dead_temps
, 1, s
->nb_globals
);
1318 /* input args are live */
1319 for(i
= nb_oargs
; i
< nb_iargs
+ nb_oargs
; i
++) {
1321 if (arg
!= TCG_CALL_DUMMY_ARG
) {
1322 if (dead_temps
[arg
]) {
1323 dead_args
|= (1 << i
);
1325 dead_temps
[arg
] = 0;
1328 s
->op_dead_args
[op_index
] = dead_args
;
1329 s
->op_sync_args
[op_index
] = sync_args
;
1334 case INDEX_op_debug_insn_start
:
1335 args
-= def
->nb_args
;
1341 case INDEX_op_discard
:
1343 /* mark the temporary as dead */
1344 dead_temps
[args
[0]] = 1;
1345 mem_temps
[args
[0]] = 0;
1350 case INDEX_op_add2_i32
:
1351 op_new
= INDEX_op_add_i32
;
1353 case INDEX_op_sub2_i32
:
1354 op_new
= INDEX_op_sub_i32
;
1356 case INDEX_op_add2_i64
:
1357 op_new
= INDEX_op_add_i64
;
1359 case INDEX_op_sub2_i64
:
1360 op_new
= INDEX_op_sub_i64
;
1365 /* Test if the high part of the operation is dead, but not
1366 the low part. The result can be optimized to a simple
1367 add or sub. This happens often for x86_64 guest when the
1368 cpu mode is set to 32 bit. */
1369 if (dead_temps
[args
[1]] && !mem_temps
[args
[1]]) {
1370 if (dead_temps
[args
[0]] && !mem_temps
[args
[0]]) {
1373 /* Create the single operation plus nop. */
1374 s
->gen_opc_buf
[op_index
] = op
= op_new
;
1377 assert(s
->gen_opc_buf
[op_index
+ 1] == INDEX_op_nop
);
1378 tcg_set_nop(s
, s
->gen_opc_buf
+ op_index
+ 1, args
+ 3, 3);
1379 /* Fall through and mark the single-word operation live. */
1385 case INDEX_op_mulu2_i32
:
1386 op_new
= INDEX_op_mul_i32
;
1387 op_new2
= INDEX_op_muluh_i32
;
1388 have_op_new2
= TCG_TARGET_HAS_muluh_i32
;
1390 case INDEX_op_muls2_i32
:
1391 op_new
= INDEX_op_mul_i32
;
1392 op_new2
= INDEX_op_mulsh_i32
;
1393 have_op_new2
= TCG_TARGET_HAS_mulsh_i32
;
1395 case INDEX_op_mulu2_i64
:
1396 op_new
= INDEX_op_mul_i64
;
1397 op_new2
= INDEX_op_muluh_i64
;
1398 have_op_new2
= TCG_TARGET_HAS_muluh_i64
;
1400 case INDEX_op_muls2_i64
:
1401 op_new
= INDEX_op_mul_i64
;
1402 op_new2
= INDEX_op_mulsh_i64
;
1403 have_op_new2
= TCG_TARGET_HAS_mulsh_i64
;
1409 if (dead_temps
[args
[1]] && !mem_temps
[args
[1]]) {
1410 if (dead_temps
[args
[0]] && !mem_temps
[args
[0]]) {
1411 /* Both parts of the operation are dead. */
1414 /* The high part of the operation is dead; generate the low. */
1415 s
->gen_opc_buf
[op_index
] = op
= op_new
;
1418 } else if (have_op_new2
&& dead_temps
[args
[0]]
1419 && !mem_temps
[args
[0]]) {
1420 /* The low part of the operation is dead; generate the high. */
1421 s
->gen_opc_buf
[op_index
] = op
= op_new2
;
1428 assert(s
->gen_opc_buf
[op_index
+ 1] == INDEX_op_nop
);
1429 tcg_set_nop(s
, s
->gen_opc_buf
+ op_index
+ 1, args
+ 3, 1);
1430 /* Mark the single-word operation live. */
1435 /* XXX: optimize by hardcoding common cases (e.g. triadic ops) */
1436 args
-= def
->nb_args
;
1437 nb_iargs
= def
->nb_iargs
;
1438 nb_oargs
= def
->nb_oargs
;
1440 /* Test if the operation can be removed because all
1441 its outputs are dead. We assume that nb_oargs == 0
1442 implies side effects */
1443 if (!(def
->flags
& TCG_OPF_SIDE_EFFECTS
) && nb_oargs
!= 0) {
1444 for(i
= 0; i
< nb_oargs
; i
++) {
1446 if (!dead_temps
[arg
] || mem_temps
[arg
]) {
1451 tcg_set_nop(s
, s
->gen_opc_buf
+ op_index
, args
, def
->nb_args
);
1452 #ifdef CONFIG_PROFILER
1458 /* output args are dead */
1461 for(i
= 0; i
< nb_oargs
; i
++) {
1463 if (dead_temps
[arg
]) {
1464 dead_args
|= (1 << i
);
1466 if (mem_temps
[arg
]) {
1467 sync_args
|= (1 << i
);
1469 dead_temps
[arg
] = 1;
1473 /* if end of basic block, update */
1474 if (def
->flags
& TCG_OPF_BB_END
) {
1475 tcg_la_bb_end(s
, dead_temps
, mem_temps
);
1476 } else if (def
->flags
& TCG_OPF_SIDE_EFFECTS
) {
1477 /* globals should be synced to memory */
1478 memset(mem_temps
, 1, s
->nb_globals
);
1481 /* input args are live */
1482 for(i
= nb_oargs
; i
< nb_oargs
+ nb_iargs
; i
++) {
1484 if (dead_temps
[arg
]) {
1485 dead_args
|= (1 << i
);
1487 dead_temps
[arg
] = 0;
1489 s
->op_dead_args
[op_index
] = dead_args
;
1490 s
->op_sync_args
[op_index
] = sync_args
;
1497 if (args
!= s
->gen_opparam_buf
) {
1502 /* dummy liveness analysis */
1503 static void tcg_liveness_analysis(TCGContext
*s
)
1506 nb_ops
= s
->gen_opc_ptr
- s
->gen_opc_buf
;
1508 s
->op_dead_args
= tcg_malloc(nb_ops
* sizeof(uint16_t));
1509 memset(s
->op_dead_args
, 0, nb_ops
* sizeof(uint16_t));
1510 s
->op_sync_args
= tcg_malloc(nb_ops
* sizeof(uint8_t));
1511 memset(s
->op_sync_args
, 0, nb_ops
* sizeof(uint8_t));
1516 static void dump_regs(TCGContext
*s
)
1522 for(i
= 0; i
< s
->nb_temps
; i
++) {
1524 printf(" %10s: ", tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), i
));
1525 switch(ts
->val_type
) {
1527 printf("%s", tcg_target_reg_names
[ts
->reg
]);
1530 printf("%d(%s)", (int)ts
->mem_offset
, tcg_target_reg_names
[ts
->mem_reg
]);
1532 case TEMP_VAL_CONST
:
1533 printf("$0x%" TCG_PRIlx
, ts
->val
);
1545 for(i
= 0; i
< TCG_TARGET_NB_REGS
; i
++) {
1546 if (s
->reg_to_temp
[i
] >= 0) {
1548 tcg_target_reg_names
[i
],
1549 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), s
->reg_to_temp
[i
]));
1554 static void check_regs(TCGContext
*s
)
1560 for(reg
= 0; reg
< TCG_TARGET_NB_REGS
; reg
++) {
1561 k
= s
->reg_to_temp
[reg
];
1564 if (ts
->val_type
!= TEMP_VAL_REG
||
1566 printf("Inconsistency for register %s:\n",
1567 tcg_target_reg_names
[reg
]);
1572 for(k
= 0; k
< s
->nb_temps
; k
++) {
1574 if (ts
->val_type
== TEMP_VAL_REG
&&
1576 s
->reg_to_temp
[ts
->reg
] != k
) {
1577 printf("Inconsistency for temp %s:\n",
1578 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), k
));
1580 printf("reg state:\n");
1588 static void temp_allocate_frame(TCGContext
*s
, int temp
)
1591 ts
= &s
->temps
[temp
];
1592 #if !(defined(__sparc__) && TCG_TARGET_REG_BITS == 64)
1593 /* Sparc64 stack is accessed with offset of 2047 */
1594 s
->current_frame_offset
= (s
->current_frame_offset
+
1595 (tcg_target_long
)sizeof(tcg_target_long
) - 1) &
1596 ~(sizeof(tcg_target_long
) - 1);
1598 if (s
->current_frame_offset
+ (tcg_target_long
)sizeof(tcg_target_long
) >
1602 ts
->mem_offset
= s
->current_frame_offset
;
1603 ts
->mem_reg
= s
->frame_reg
;
1604 ts
->mem_allocated
= 1;
1605 s
->current_frame_offset
+= sizeof(tcg_target_long
);
1608 /* sync register 'reg' by saving it to the corresponding temporary */
1609 static inline void tcg_reg_sync(TCGContext
*s
, int reg
)
1614 temp
= s
->reg_to_temp
[reg
];
1615 ts
= &s
->temps
[temp
];
1616 assert(ts
->val_type
== TEMP_VAL_REG
);
1617 if (!ts
->mem_coherent
&& !ts
->fixed_reg
) {
1618 if (!ts
->mem_allocated
) {
1619 temp_allocate_frame(s
, temp
);
1621 tcg_out_st(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
1623 ts
->mem_coherent
= 1;
1626 /* free register 'reg' by spilling the corresponding temporary if necessary */
1627 static void tcg_reg_free(TCGContext
*s
, int reg
)
1631 temp
= s
->reg_to_temp
[reg
];
1633 tcg_reg_sync(s
, reg
);
1634 s
->temps
[temp
].val_type
= TEMP_VAL_MEM
;
1635 s
->reg_to_temp
[reg
] = -1;
1639 /* Allocate a register belonging to reg1 & ~reg2 */
1640 static int tcg_reg_alloc(TCGContext
*s
, TCGRegSet reg1
, TCGRegSet reg2
)
1645 tcg_regset_andnot(reg_ct
, reg1
, reg2
);
1647 /* first try free registers */
1648 for(i
= 0; i
< ARRAY_SIZE(tcg_target_reg_alloc_order
); i
++) {
1649 reg
= tcg_target_reg_alloc_order
[i
];
1650 if (tcg_regset_test_reg(reg_ct
, reg
) && s
->reg_to_temp
[reg
] == -1)
1654 /* XXX: do better spill choice */
1655 for(i
= 0; i
< ARRAY_SIZE(tcg_target_reg_alloc_order
); i
++) {
1656 reg
= tcg_target_reg_alloc_order
[i
];
1657 if (tcg_regset_test_reg(reg_ct
, reg
)) {
1658 tcg_reg_free(s
, reg
);
1666 /* mark a temporary as dead. */
1667 static inline void temp_dead(TCGContext
*s
, int temp
)
1671 ts
= &s
->temps
[temp
];
1672 if (!ts
->fixed_reg
) {
1673 if (ts
->val_type
== TEMP_VAL_REG
) {
1674 s
->reg_to_temp
[ts
->reg
] = -1;
1676 if (temp
< s
->nb_globals
|| ts
->temp_local
) {
1677 ts
->val_type
= TEMP_VAL_MEM
;
1679 ts
->val_type
= TEMP_VAL_DEAD
;
1684 /* sync a temporary to memory. 'allocated_regs' is used in case a
1685 temporary registers needs to be allocated to store a constant. */
1686 static inline void temp_sync(TCGContext
*s
, int temp
, TCGRegSet allocated_regs
)
1690 ts
= &s
->temps
[temp
];
1691 if (!ts
->fixed_reg
) {
1692 switch(ts
->val_type
) {
1693 case TEMP_VAL_CONST
:
1694 ts
->reg
= tcg_reg_alloc(s
, tcg_target_available_regs
[ts
->type
],
1696 ts
->val_type
= TEMP_VAL_REG
;
1697 s
->reg_to_temp
[ts
->reg
] = temp
;
1698 ts
->mem_coherent
= 0;
1699 tcg_out_movi(s
, ts
->type
, ts
->reg
, ts
->val
);
1702 tcg_reg_sync(s
, ts
->reg
);
1713 /* save a temporary to memory. 'allocated_regs' is used in case a
1714 temporary registers needs to be allocated to store a constant. */
1715 static inline void temp_save(TCGContext
*s
, int temp
, TCGRegSet allocated_regs
)
1717 #ifdef USE_LIVENESS_ANALYSIS
1718 /* The liveness analysis already ensures that globals are back
1719 in memory. Keep an assert for safety. */
1720 assert(s
->temps
[temp
].val_type
== TEMP_VAL_MEM
|| s
->temps
[temp
].fixed_reg
);
1722 temp_sync(s
, temp
, allocated_regs
);
1727 /* save globals to their canonical location and assume they can be
1728 modified be the following code. 'allocated_regs' is used in case a
1729 temporary registers needs to be allocated to store a constant. */
1730 static void save_globals(TCGContext
*s
, TCGRegSet allocated_regs
)
1734 for(i
= 0; i
< s
->nb_globals
; i
++) {
1735 temp_save(s
, i
, allocated_regs
);
1739 /* sync globals to their canonical location and assume they can be
1740 read by the following code. 'allocated_regs' is used in case a
1741 temporary registers needs to be allocated to store a constant. */
1742 static void sync_globals(TCGContext
*s
, TCGRegSet allocated_regs
)
1746 for (i
= 0; i
< s
->nb_globals
; i
++) {
1747 #ifdef USE_LIVENESS_ANALYSIS
1748 assert(s
->temps
[i
].val_type
!= TEMP_VAL_REG
|| s
->temps
[i
].fixed_reg
||
1749 s
->temps
[i
].mem_coherent
);
1751 temp_sync(s
, i
, allocated_regs
);
1756 /* at the end of a basic block, we assume all temporaries are dead and
1757 all globals are stored at their canonical location. */
1758 static void tcg_reg_alloc_bb_end(TCGContext
*s
, TCGRegSet allocated_regs
)
1763 for(i
= s
->nb_globals
; i
< s
->nb_temps
; i
++) {
1765 if (ts
->temp_local
) {
1766 temp_save(s
, i
, allocated_regs
);
1768 #ifdef USE_LIVENESS_ANALYSIS
1769 /* The liveness analysis already ensures that temps are dead.
1770 Keep an assert for safety. */
1771 assert(ts
->val_type
== TEMP_VAL_DEAD
);
1778 save_globals(s
, allocated_regs
);
1781 #define IS_DEAD_ARG(n) ((dead_args >> (n)) & 1)
1782 #define NEED_SYNC_ARG(n) ((sync_args >> (n)) & 1)
1784 static void tcg_reg_alloc_movi(TCGContext
*s
, const TCGArg
*args
,
1785 uint16_t dead_args
, uint8_t sync_args
)
1788 tcg_target_ulong val
;
1790 ots
= &s
->temps
[args
[0]];
1793 if (ots
->fixed_reg
) {
1794 /* for fixed registers, we do not do any constant
1796 tcg_out_movi(s
, ots
->type
, ots
->reg
, val
);
1798 /* The movi is not explicitly generated here */
1799 if (ots
->val_type
== TEMP_VAL_REG
)
1800 s
->reg_to_temp
[ots
->reg
] = -1;
1801 ots
->val_type
= TEMP_VAL_CONST
;
1804 if (NEED_SYNC_ARG(0)) {
1805 temp_sync(s
, args
[0], s
->reserved_regs
);
1807 if (IS_DEAD_ARG(0)) {
1808 temp_dead(s
, args
[0]);
1812 static void tcg_reg_alloc_mov(TCGContext
*s
, const TCGOpDef
*def
,
1813 const TCGArg
*args
, uint16_t dead_args
,
1816 TCGRegSet allocated_regs
;
1818 const TCGArgConstraint
*arg_ct
, *oarg_ct
;
1820 tcg_regset_set(allocated_regs
, s
->reserved_regs
);
1821 ots
= &s
->temps
[args
[0]];
1822 ts
= &s
->temps
[args
[1]];
1823 oarg_ct
= &def
->args_ct
[0];
1824 arg_ct
= &def
->args_ct
[1];
1826 /* If the source value is not in a register, and we're going to be
1827 forced to have it in a register in order to perform the copy,
1828 then copy the SOURCE value into its own register first. That way
1829 we don't have to reload SOURCE the next time it is used. */
1830 if (((NEED_SYNC_ARG(0) || ots
->fixed_reg
) && ts
->val_type
!= TEMP_VAL_REG
)
1831 || ts
->val_type
== TEMP_VAL_MEM
) {
1832 ts
->reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1833 if (ts
->val_type
== TEMP_VAL_MEM
) {
1834 tcg_out_ld(s
, ts
->type
, ts
->reg
, ts
->mem_reg
, ts
->mem_offset
);
1835 ts
->mem_coherent
= 1;
1836 } else if (ts
->val_type
== TEMP_VAL_CONST
) {
1837 tcg_out_movi(s
, ts
->type
, ts
->reg
, ts
->val
);
1839 s
->reg_to_temp
[ts
->reg
] = args
[1];
1840 ts
->val_type
= TEMP_VAL_REG
;
1843 if (IS_DEAD_ARG(0) && !ots
->fixed_reg
) {
1844 /* mov to a non-saved dead register makes no sense (even with
1845 liveness analysis disabled). */
1846 assert(NEED_SYNC_ARG(0));
1847 /* The code above should have moved the temp to a register. */
1848 assert(ts
->val_type
== TEMP_VAL_REG
);
1849 if (!ots
->mem_allocated
) {
1850 temp_allocate_frame(s
, args
[0]);
1852 tcg_out_st(s
, ots
->type
, ts
->reg
, ots
->mem_reg
, ots
->mem_offset
);
1853 if (IS_DEAD_ARG(1)) {
1854 temp_dead(s
, args
[1]);
1856 temp_dead(s
, args
[0]);
1857 } else if (ts
->val_type
== TEMP_VAL_CONST
) {
1858 /* propagate constant */
1859 if (ots
->val_type
== TEMP_VAL_REG
) {
1860 s
->reg_to_temp
[ots
->reg
] = -1;
1862 ots
->val_type
= TEMP_VAL_CONST
;
1865 /* The code in the first if block should have moved the
1866 temp to a register. */
1867 assert(ts
->val_type
== TEMP_VAL_REG
);
1868 if (IS_DEAD_ARG(1) && !ts
->fixed_reg
&& !ots
->fixed_reg
) {
1869 /* the mov can be suppressed */
1870 if (ots
->val_type
== TEMP_VAL_REG
) {
1871 s
->reg_to_temp
[ots
->reg
] = -1;
1874 temp_dead(s
, args
[1]);
1876 if (ots
->val_type
!= TEMP_VAL_REG
) {
1877 /* When allocating a new register, make sure to not spill the
1879 tcg_regset_set_reg(allocated_regs
, ts
->reg
);
1880 ots
->reg
= tcg_reg_alloc(s
, oarg_ct
->u
.regs
, allocated_regs
);
1882 tcg_out_mov(s
, ots
->type
, ots
->reg
, ts
->reg
);
1884 ots
->val_type
= TEMP_VAL_REG
;
1885 ots
->mem_coherent
= 0;
1886 s
->reg_to_temp
[ots
->reg
] = args
[0];
1887 if (NEED_SYNC_ARG(0)) {
1888 tcg_reg_sync(s
, ots
->reg
);
1893 static void tcg_reg_alloc_op(TCGContext
*s
,
1894 const TCGOpDef
*def
, TCGOpcode opc
,
1895 const TCGArg
*args
, uint16_t dead_args
,
1898 TCGRegSet allocated_regs
;
1899 int i
, k
, nb_iargs
, nb_oargs
, reg
;
1901 const TCGArgConstraint
*arg_ct
;
1903 TCGArg new_args
[TCG_MAX_OP_ARGS
];
1904 int const_args
[TCG_MAX_OP_ARGS
];
1906 nb_oargs
= def
->nb_oargs
;
1907 nb_iargs
= def
->nb_iargs
;
1909 /* copy constants */
1910 memcpy(new_args
+ nb_oargs
+ nb_iargs
,
1911 args
+ nb_oargs
+ nb_iargs
,
1912 sizeof(TCGArg
) * def
->nb_cargs
);
1914 /* satisfy input constraints */
1915 tcg_regset_set(allocated_regs
, s
->reserved_regs
);
1916 for(k
= 0; k
< nb_iargs
; k
++) {
1917 i
= def
->sorted_args
[nb_oargs
+ k
];
1919 arg_ct
= &def
->args_ct
[i
];
1920 ts
= &s
->temps
[arg
];
1921 if (ts
->val_type
== TEMP_VAL_MEM
) {
1922 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1923 tcg_out_ld(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
1924 ts
->val_type
= TEMP_VAL_REG
;
1926 ts
->mem_coherent
= 1;
1927 s
->reg_to_temp
[reg
] = arg
;
1928 } else if (ts
->val_type
== TEMP_VAL_CONST
) {
1929 if (tcg_target_const_match(ts
->val
, arg_ct
)) {
1930 /* constant is OK for instruction */
1932 new_args
[i
] = ts
->val
;
1935 /* need to move to a register */
1936 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1937 tcg_out_movi(s
, ts
->type
, reg
, ts
->val
);
1938 ts
->val_type
= TEMP_VAL_REG
;
1940 ts
->mem_coherent
= 0;
1941 s
->reg_to_temp
[reg
] = arg
;
1944 assert(ts
->val_type
== TEMP_VAL_REG
);
1945 if (arg_ct
->ct
& TCG_CT_IALIAS
) {
1946 if (ts
->fixed_reg
) {
1947 /* if fixed register, we must allocate a new register
1948 if the alias is not the same register */
1949 if (arg
!= args
[arg_ct
->alias_index
])
1950 goto allocate_in_reg
;
1952 /* if the input is aliased to an output and if it is
1953 not dead after the instruction, we must allocate
1954 a new register and move it */
1955 if (!IS_DEAD_ARG(i
)) {
1956 goto allocate_in_reg
;
1961 if (tcg_regset_test_reg(arg_ct
->u
.regs
, reg
)) {
1962 /* nothing to do : the constraint is satisfied */
1965 /* allocate a new register matching the constraint
1966 and move the temporary register into it */
1967 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1968 tcg_out_mov(s
, ts
->type
, reg
, ts
->reg
);
1972 tcg_regset_set_reg(allocated_regs
, reg
);
1976 /* mark dead temporaries and free the associated registers */
1977 for (i
= nb_oargs
; i
< nb_oargs
+ nb_iargs
; i
++) {
1978 if (IS_DEAD_ARG(i
)) {
1979 temp_dead(s
, args
[i
]);
1983 if (def
->flags
& TCG_OPF_BB_END
) {
1984 tcg_reg_alloc_bb_end(s
, allocated_regs
);
1986 if (def
->flags
& TCG_OPF_CALL_CLOBBER
) {
1987 /* XXX: permit generic clobber register list ? */
1988 for(reg
= 0; reg
< TCG_TARGET_NB_REGS
; reg
++) {
1989 if (tcg_regset_test_reg(tcg_target_call_clobber_regs
, reg
)) {
1990 tcg_reg_free(s
, reg
);
1994 if (def
->flags
& TCG_OPF_SIDE_EFFECTS
) {
1995 /* sync globals if the op has side effects and might trigger
1997 sync_globals(s
, allocated_regs
);
2000 /* satisfy the output constraints */
2001 tcg_regset_set(allocated_regs
, s
->reserved_regs
);
2002 for(k
= 0; k
< nb_oargs
; k
++) {
2003 i
= def
->sorted_args
[k
];
2005 arg_ct
= &def
->args_ct
[i
];
2006 ts
= &s
->temps
[arg
];
2007 if (arg_ct
->ct
& TCG_CT_ALIAS
) {
2008 reg
= new_args
[arg_ct
->alias_index
];
2010 /* if fixed register, we try to use it */
2012 if (ts
->fixed_reg
&&
2013 tcg_regset_test_reg(arg_ct
->u
.regs
, reg
)) {
2016 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
2018 tcg_regset_set_reg(allocated_regs
, reg
);
2019 /* if a fixed register is used, then a move will be done afterwards */
2020 if (!ts
->fixed_reg
) {
2021 if (ts
->val_type
== TEMP_VAL_REG
) {
2022 s
->reg_to_temp
[ts
->reg
] = -1;
2024 ts
->val_type
= TEMP_VAL_REG
;
2026 /* temp value is modified, so the value kept in memory is
2027 potentially not the same */
2028 ts
->mem_coherent
= 0;
2029 s
->reg_to_temp
[reg
] = arg
;
2036 /* emit instruction */
2037 tcg_out_op(s
, opc
, new_args
, const_args
);
2039 /* move the outputs in the correct register if needed */
2040 for(i
= 0; i
< nb_oargs
; i
++) {
2041 ts
= &s
->temps
[args
[i
]];
2043 if (ts
->fixed_reg
&& ts
->reg
!= reg
) {
2044 tcg_out_mov(s
, ts
->type
, ts
->reg
, reg
);
2046 if (NEED_SYNC_ARG(i
)) {
2047 tcg_reg_sync(s
, reg
);
2049 if (IS_DEAD_ARG(i
)) {
2050 temp_dead(s
, args
[i
]);
2055 #ifdef TCG_TARGET_STACK_GROWSUP
2056 #define STACK_DIR(x) (-(x))
2058 #define STACK_DIR(x) (x)
2061 static int tcg_reg_alloc_call(TCGContext
*s
, const TCGOpDef
*def
,
2062 TCGOpcode opc
, const TCGArg
*args
,
2063 uint16_t dead_args
, uint8_t sync_args
)
2065 int nb_iargs
, nb_oargs
, flags
, nb_regs
, i
, reg
, nb_params
;
2066 TCGArg arg
, func_arg
;
2068 intptr_t stack_offset
;
2069 size_t call_stack_size
;
2070 uintptr_t func_addr
;
2071 int const_func_arg
, allocate_args
;
2072 TCGRegSet allocated_regs
;
2073 const TCGArgConstraint
*arg_ct
;
2077 nb_oargs
= arg
>> 16;
2078 nb_iargs
= arg
& 0xffff;
2079 nb_params
= nb_iargs
- 1;
2081 flags
= args
[nb_oargs
+ nb_iargs
];
2083 nb_regs
= ARRAY_SIZE(tcg_target_call_iarg_regs
);
2084 if (nb_regs
> nb_params
)
2085 nb_regs
= nb_params
;
2087 /* assign stack slots first */
2088 call_stack_size
= (nb_params
- nb_regs
) * sizeof(tcg_target_long
);
2089 call_stack_size
= (call_stack_size
+ TCG_TARGET_STACK_ALIGN
- 1) &
2090 ~(TCG_TARGET_STACK_ALIGN
- 1);
2091 allocate_args
= (call_stack_size
> TCG_STATIC_CALL_ARGS_SIZE
);
2092 if (allocate_args
) {
2093 /* XXX: if more than TCG_STATIC_CALL_ARGS_SIZE is needed,
2094 preallocate call stack */
2098 stack_offset
= TCG_TARGET_CALL_STACK_OFFSET
;
2099 for(i
= nb_regs
; i
< nb_params
; i
++) {
2100 arg
= args
[nb_oargs
+ i
];
2101 #ifdef TCG_TARGET_STACK_GROWSUP
2102 stack_offset
-= sizeof(tcg_target_long
);
2104 if (arg
!= TCG_CALL_DUMMY_ARG
) {
2105 ts
= &s
->temps
[arg
];
2106 if (ts
->val_type
== TEMP_VAL_REG
) {
2107 tcg_out_st(s
, ts
->type
, ts
->reg
, TCG_REG_CALL_STACK
, stack_offset
);
2108 } else if (ts
->val_type
== TEMP_VAL_MEM
) {
2109 reg
= tcg_reg_alloc(s
, tcg_target_available_regs
[ts
->type
],
2111 /* XXX: not correct if reading values from the stack */
2112 tcg_out_ld(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
2113 tcg_out_st(s
, ts
->type
, reg
, TCG_REG_CALL_STACK
, stack_offset
);
2114 } else if (ts
->val_type
== TEMP_VAL_CONST
) {
2115 reg
= tcg_reg_alloc(s
, tcg_target_available_regs
[ts
->type
],
2117 /* XXX: sign extend may be needed on some targets */
2118 tcg_out_movi(s
, ts
->type
, reg
, ts
->val
);
2119 tcg_out_st(s
, ts
->type
, reg
, TCG_REG_CALL_STACK
, stack_offset
);
2124 #ifndef TCG_TARGET_STACK_GROWSUP
2125 stack_offset
+= sizeof(tcg_target_long
);
2129 /* assign input registers */
2130 tcg_regset_set(allocated_regs
, s
->reserved_regs
);
2131 for(i
= 0; i
< nb_regs
; i
++) {
2132 arg
= args
[nb_oargs
+ i
];
2133 if (arg
!= TCG_CALL_DUMMY_ARG
) {
2134 ts
= &s
->temps
[arg
];
2135 reg
= tcg_target_call_iarg_regs
[i
];
2136 tcg_reg_free(s
, reg
);
2137 if (ts
->val_type
== TEMP_VAL_REG
) {
2138 if (ts
->reg
!= reg
) {
2139 tcg_out_mov(s
, ts
->type
, reg
, ts
->reg
);
2141 } else if (ts
->val_type
== TEMP_VAL_MEM
) {
2142 tcg_out_ld(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
2143 } else if (ts
->val_type
== TEMP_VAL_CONST
) {
2144 /* XXX: sign extend ? */
2145 tcg_out_movi(s
, ts
->type
, reg
, ts
->val
);
2149 tcg_regset_set_reg(allocated_regs
, reg
);
2153 /* assign function address */
2154 func_arg
= args
[nb_oargs
+ nb_iargs
- 1];
2155 arg_ct
= &def
->args_ct
[0];
2156 ts
= &s
->temps
[func_arg
];
2157 func_addr
= ts
->val
;
2159 if (ts
->val_type
== TEMP_VAL_MEM
) {
2160 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
2161 tcg_out_ld(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
2163 tcg_regset_set_reg(allocated_regs
, reg
);
2164 } else if (ts
->val_type
== TEMP_VAL_REG
) {
2166 if (!tcg_regset_test_reg(arg_ct
->u
.regs
, reg
)) {
2167 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
2168 tcg_out_mov(s
, ts
->type
, reg
, ts
->reg
);
2171 tcg_regset_set_reg(allocated_regs
, reg
);
2172 } else if (ts
->val_type
== TEMP_VAL_CONST
) {
2173 if (tcg_target_const_match(func_addr
, arg_ct
)) {
2175 func_arg
= func_addr
;
2177 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
2178 tcg_out_movi(s
, ts
->type
, reg
, func_addr
);
2180 tcg_regset_set_reg(allocated_regs
, reg
);
2187 /* mark dead temporaries and free the associated registers */
2188 for(i
= nb_oargs
; i
< nb_iargs
+ nb_oargs
; i
++) {
2189 if (IS_DEAD_ARG(i
)) {
2190 temp_dead(s
, args
[i
]);
2194 /* clobber call registers */
2195 for(reg
= 0; reg
< TCG_TARGET_NB_REGS
; reg
++) {
2196 if (tcg_regset_test_reg(tcg_target_call_clobber_regs
, reg
)) {
2197 tcg_reg_free(s
, reg
);
2201 /* Save globals if they might be written by the helper, sync them if
2202 they might be read. */
2203 if (flags
& TCG_CALL_NO_READ_GLOBALS
) {
2205 } else if (flags
& TCG_CALL_NO_WRITE_GLOBALS
) {
2206 sync_globals(s
, allocated_regs
);
2208 save_globals(s
, allocated_regs
);
2211 tcg_out_op(s
, opc
, &func_arg
, &const_func_arg
);
2213 /* assign output registers and emit moves if needed */
2214 for(i
= 0; i
< nb_oargs
; i
++) {
2216 ts
= &s
->temps
[arg
];
2217 reg
= tcg_target_call_oarg_regs
[i
];
2218 assert(s
->reg_to_temp
[reg
] == -1);
2219 if (ts
->fixed_reg
) {
2220 if (ts
->reg
!= reg
) {
2221 tcg_out_mov(s
, ts
->type
, ts
->reg
, reg
);
2224 if (ts
->val_type
== TEMP_VAL_REG
) {
2225 s
->reg_to_temp
[ts
->reg
] = -1;
2227 ts
->val_type
= TEMP_VAL_REG
;
2229 ts
->mem_coherent
= 0;
2230 s
->reg_to_temp
[reg
] = arg
;
2231 if (NEED_SYNC_ARG(i
)) {
2232 tcg_reg_sync(s
, reg
);
2234 if (IS_DEAD_ARG(i
)) {
2235 temp_dead(s
, args
[i
]);
2240 return nb_iargs
+ nb_oargs
+ def
->nb_cargs
+ 1;
2243 #ifdef CONFIG_PROFILER
2245 static int64_t tcg_table_op_count
[NB_OPS
];
2247 static void dump_op_count(void)
2251 f
= fopen("/tmp/op.log", "w");
2252 for(i
= INDEX_op_end
; i
< NB_OPS
; i
++) {
2253 fprintf(f
, "%s %" PRId64
"\n", tcg_op_defs
[i
].name
, tcg_table_op_count
[i
]);
2260 static inline int tcg_gen_code_common(TCGContext
*s
, uint8_t *gen_code_buf
,
2265 const TCGOpDef
*def
;
2269 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP
))) {
2276 #ifdef CONFIG_PROFILER
2277 s
->opt_time
-= profile_getclock();
2280 #ifdef USE_TCG_OPTIMIZATIONS
2281 s
->gen_opparam_ptr
=
2282 tcg_optimize(s
, s
->gen_opc_ptr
, s
->gen_opparam_buf
, tcg_op_defs
);
2285 #ifdef CONFIG_PROFILER
2286 s
->opt_time
+= profile_getclock();
2287 s
->la_time
-= profile_getclock();
2290 tcg_liveness_analysis(s
);
2292 #ifdef CONFIG_PROFILER
2293 s
->la_time
+= profile_getclock();
2297 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_OPT
))) {
2298 qemu_log("OP after optimization and liveness analysis:\n");
2304 tcg_reg_alloc_start(s
);
2306 s
->code_buf
= gen_code_buf
;
2307 s
->code_ptr
= gen_code_buf
;
2309 args
= s
->gen_opparam_buf
;
2313 opc
= s
->gen_opc_buf
[op_index
];
2314 #ifdef CONFIG_PROFILER
2315 tcg_table_op_count
[opc
]++;
2317 def
= &tcg_op_defs
[opc
];
2319 printf("%s: %d %d %d\n", def
->name
,
2320 def
->nb_oargs
, def
->nb_iargs
, def
->nb_cargs
);
2324 case INDEX_op_mov_i32
:
2325 case INDEX_op_mov_i64
:
2326 tcg_reg_alloc_mov(s
, def
, args
, s
->op_dead_args
[op_index
],
2327 s
->op_sync_args
[op_index
]);
2329 case INDEX_op_movi_i32
:
2330 case INDEX_op_movi_i64
:
2331 tcg_reg_alloc_movi(s
, args
, s
->op_dead_args
[op_index
],
2332 s
->op_sync_args
[op_index
]);
2334 case INDEX_op_debug_insn_start
:
2335 /* debug instruction */
2345 case INDEX_op_discard
:
2346 temp_dead(s
, args
[0]);
2348 case INDEX_op_set_label
:
2349 tcg_reg_alloc_bb_end(s
, s
->reserved_regs
);
2350 tcg_out_label(s
, args
[0], s
->code_ptr
);
2353 args
+= tcg_reg_alloc_call(s
, def
, opc
, args
,
2354 s
->op_dead_args
[op_index
],
2355 s
->op_sync_args
[op_index
]);
2360 /* Sanity check that we've not introduced any unhandled opcodes. */
2361 if (def
->flags
& TCG_OPF_NOT_PRESENT
) {
2364 /* Note: in order to speed up the code, it would be much
2365 faster to have specialized register allocator functions for
2366 some common argument patterns */
2367 tcg_reg_alloc_op(s
, def
, opc
, args
, s
->op_dead_args
[op_index
],
2368 s
->op_sync_args
[op_index
]);
2371 args
+= def
->nb_args
;
2373 if (search_pc
>= 0 && search_pc
< s
->code_ptr
- gen_code_buf
) {
2382 #if defined(CONFIG_QEMU_LDST_OPTIMIZATION) && defined(CONFIG_SOFTMMU)
2383 /* Generate TB finalization at the end of block */
2384 tcg_out_tb_finalize(s
);
2389 int tcg_gen_code(TCGContext
*s
, uint8_t *gen_code_buf
)
2391 #ifdef CONFIG_PROFILER
2394 n
= (s
->gen_opc_ptr
- s
->gen_opc_buf
);
2396 if (n
> s
->op_count_max
)
2397 s
->op_count_max
= n
;
2399 s
->temp_count
+= s
->nb_temps
;
2400 if (s
->nb_temps
> s
->temp_count_max
)
2401 s
->temp_count_max
= s
->nb_temps
;
2405 tcg_gen_code_common(s
, gen_code_buf
, -1);
2407 /* flush instruction cache */
2408 flush_icache_range((uintptr_t)gen_code_buf
, (uintptr_t)s
->code_ptr
);
2410 return s
->code_ptr
- gen_code_buf
;
2413 /* Return the index of the micro operation such as the pc after is <
2414 offset bytes from the start of the TB. The contents of gen_code_buf must
2415 not be changed, though writing the same values is ok.
2416 Return -1 if not found. */
2417 int tcg_gen_code_search_pc(TCGContext
*s
, uint8_t *gen_code_buf
, long offset
)
2419 return tcg_gen_code_common(s
, gen_code_buf
, offset
);
2422 #ifdef CONFIG_PROFILER
2423 void tcg_dump_info(FILE *f
, fprintf_function cpu_fprintf
)
2425 TCGContext
*s
= &tcg_ctx
;
2428 tot
= s
->interm_time
+ s
->code_time
;
2429 cpu_fprintf(f
, "JIT cycles %" PRId64
" (%0.3f s at 2.4 GHz)\n",
2431 cpu_fprintf(f
, "translated TBs %" PRId64
" (aborted=%" PRId64
" %0.1f%%)\n",
2433 s
->tb_count1
- s
->tb_count
,
2434 s
->tb_count1
? (double)(s
->tb_count1
- s
->tb_count
) / s
->tb_count1
* 100.0 : 0);
2435 cpu_fprintf(f
, "avg ops/TB %0.1f max=%d\n",
2436 s
->tb_count
? (double)s
->op_count
/ s
->tb_count
: 0, s
->op_count_max
);
2437 cpu_fprintf(f
, "deleted ops/TB %0.2f\n",
2439 (double)s
->del_op_count
/ s
->tb_count
: 0);
2440 cpu_fprintf(f
, "avg temps/TB %0.2f max=%d\n",
2442 (double)s
->temp_count
/ s
->tb_count
: 0,
2445 cpu_fprintf(f
, "cycles/op %0.1f\n",
2446 s
->op_count
? (double)tot
/ s
->op_count
: 0);
2447 cpu_fprintf(f
, "cycles/in byte %0.1f\n",
2448 s
->code_in_len
? (double)tot
/ s
->code_in_len
: 0);
2449 cpu_fprintf(f
, "cycles/out byte %0.1f\n",
2450 s
->code_out_len
? (double)tot
/ s
->code_out_len
: 0);
2453 cpu_fprintf(f
, " gen_interm time %0.1f%%\n",
2454 (double)s
->interm_time
/ tot
* 100.0);
2455 cpu_fprintf(f
, " gen_code time %0.1f%%\n",
2456 (double)s
->code_time
/ tot
* 100.0);
2457 cpu_fprintf(f
, "optim./code time %0.1f%%\n",
2458 (double)s
->opt_time
/ (s
->code_time
? s
->code_time
: 1)
2460 cpu_fprintf(f
, "liveness/code time %0.1f%%\n",
2461 (double)s
->la_time
/ (s
->code_time
? s
->code_time
: 1) * 100.0);
2462 cpu_fprintf(f
, "cpu_restore count %" PRId64
"\n",
2464 cpu_fprintf(f
, " avg cycles %0.1f\n",
2465 s
->restore_count
? (double)s
->restore_time
/ s
->restore_count
: 0);
2470 void tcg_dump_info(FILE *f
, fprintf_function cpu_fprintf
)
2472 cpu_fprintf(f
, "[TCG profiler not compiled]\n");
2476 #ifdef ELF_HOST_MACHINE
2477 /* In order to use this feature, the backend needs to do three things:
2479 (1) Define ELF_HOST_MACHINE to indicate both what value to
2480 put into the ELF image and to indicate support for the feature.
2482 (2) Define tcg_register_jit. This should create a buffer containing
2483 the contents of a .debug_frame section that describes the post-
2484 prologue unwind info for the tcg machine.
2486 (3) Call tcg_register_jit_int, with the constructed .debug_frame.
2489 /* Begin GDB interface. THE FOLLOWING MUST MATCH GDB DOCS. */
2496 struct jit_code_entry
{
2497 struct jit_code_entry
*next_entry
;
2498 struct jit_code_entry
*prev_entry
;
2499 const void *symfile_addr
;
2500 uint64_t symfile_size
;
2503 struct jit_descriptor
{
2505 uint32_t action_flag
;
2506 struct jit_code_entry
*relevant_entry
;
2507 struct jit_code_entry
*first_entry
;
2510 void __jit_debug_register_code(void) __attribute__((noinline
));
2511 void __jit_debug_register_code(void)
2516 /* Must statically initialize the version, because GDB may check
2517 the version before we can set it. */
2518 struct jit_descriptor __jit_debug_descriptor
= { 1, 0, 0, 0 };
2520 /* End GDB interface. */
2522 static int find_string(const char *strtab
, const char *str
)
2524 const char *p
= strtab
+ 1;
2527 if (strcmp(p
, str
) == 0) {
2534 static void tcg_register_jit_int(void *buf_ptr
, size_t buf_size
,
2535 void *debug_frame
, size_t debug_frame_size
)
2537 struct __attribute__((packed
)) DebugInfo
{
2544 uintptr_t cu_low_pc
;
2545 uintptr_t cu_high_pc
;
2548 uintptr_t fn_low_pc
;
2549 uintptr_t fn_high_pc
;
2558 struct DebugInfo di
;
2563 struct ElfImage
*img
;
2565 static const struct ElfImage img_template
= {
2567 .e_ident
[EI_MAG0
] = ELFMAG0
,
2568 .e_ident
[EI_MAG1
] = ELFMAG1
,
2569 .e_ident
[EI_MAG2
] = ELFMAG2
,
2570 .e_ident
[EI_MAG3
] = ELFMAG3
,
2571 .e_ident
[EI_CLASS
] = ELF_CLASS
,
2572 .e_ident
[EI_DATA
] = ELF_DATA
,
2573 .e_ident
[EI_VERSION
] = EV_CURRENT
,
2575 .e_machine
= ELF_HOST_MACHINE
,
2576 .e_version
= EV_CURRENT
,
2577 .e_phoff
= offsetof(struct ElfImage
, phdr
),
2578 .e_shoff
= offsetof(struct ElfImage
, shdr
),
2579 .e_ehsize
= sizeof(ElfW(Shdr
)),
2580 .e_phentsize
= sizeof(ElfW(Phdr
)),
2582 .e_shentsize
= sizeof(ElfW(Shdr
)),
2583 .e_shnum
= ARRAY_SIZE(img
->shdr
),
2584 .e_shstrndx
= ARRAY_SIZE(img
->shdr
) - 1,
2585 #ifdef ELF_HOST_FLAGS
2586 .e_flags
= ELF_HOST_FLAGS
,
2589 .e_ident
[EI_OSABI
] = ELF_OSABI
,
2597 [0] = { .sh_type
= SHT_NULL
},
2598 /* Trick: The contents of code_gen_buffer are not present in
2599 this fake ELF file; that got allocated elsewhere. Therefore
2600 we mark .text as SHT_NOBITS (similar to .bss) so that readers
2601 will not look for contents. We can record any address. */
2603 .sh_type
= SHT_NOBITS
,
2604 .sh_flags
= SHF_EXECINSTR
| SHF_ALLOC
,
2606 [2] = { /* .debug_info */
2607 .sh_type
= SHT_PROGBITS
,
2608 .sh_offset
= offsetof(struct ElfImage
, di
),
2609 .sh_size
= sizeof(struct DebugInfo
),
2611 [3] = { /* .debug_abbrev */
2612 .sh_type
= SHT_PROGBITS
,
2613 .sh_offset
= offsetof(struct ElfImage
, da
),
2614 .sh_size
= sizeof(img
->da
),
2616 [4] = { /* .debug_frame */
2617 .sh_type
= SHT_PROGBITS
,
2618 .sh_offset
= sizeof(struct ElfImage
),
2620 [5] = { /* .symtab */
2621 .sh_type
= SHT_SYMTAB
,
2622 .sh_offset
= offsetof(struct ElfImage
, sym
),
2623 .sh_size
= sizeof(img
->sym
),
2625 .sh_link
= ARRAY_SIZE(img
->shdr
) - 1,
2626 .sh_entsize
= sizeof(ElfW(Sym
)),
2628 [6] = { /* .strtab */
2629 .sh_type
= SHT_STRTAB
,
2630 .sh_offset
= offsetof(struct ElfImage
, str
),
2631 .sh_size
= sizeof(img
->str
),
2635 [1] = { /* code_gen_buffer */
2636 .st_info
= ELF_ST_INFO(STB_GLOBAL
, STT_FUNC
),
2641 .len
= sizeof(struct DebugInfo
) - 4,
2643 .ptr_size
= sizeof(void *),
2645 .cu_lang
= 0x8001, /* DW_LANG_Mips_Assembler */
2647 .fn_name
= "code_gen_buffer"
2650 1, /* abbrev number (the cu) */
2651 0x11, 1, /* DW_TAG_compile_unit, has children */
2652 0x13, 0x5, /* DW_AT_language, DW_FORM_data2 */
2653 0x11, 0x1, /* DW_AT_low_pc, DW_FORM_addr */
2654 0x12, 0x1, /* DW_AT_high_pc, DW_FORM_addr */
2655 0, 0, /* end of abbrev */
2656 2, /* abbrev number (the fn) */
2657 0x2e, 0, /* DW_TAG_subprogram, no children */
2658 0x3, 0x8, /* DW_AT_name, DW_FORM_string */
2659 0x11, 0x1, /* DW_AT_low_pc, DW_FORM_addr */
2660 0x12, 0x1, /* DW_AT_high_pc, DW_FORM_addr */
2661 0, 0, /* end of abbrev */
2662 0 /* no more abbrev */
2664 .str
= "\0" ".text\0" ".debug_info\0" ".debug_abbrev\0"
2665 ".debug_frame\0" ".symtab\0" ".strtab\0" "code_gen_buffer",
2668 /* We only need a single jit entry; statically allocate it. */
2669 static struct jit_code_entry one_entry
;
2671 uintptr_t buf
= (uintptr_t)buf_ptr
;
2672 size_t img_size
= sizeof(struct ElfImage
) + debug_frame_size
;
2674 img
= g_malloc(img_size
);
2675 *img
= img_template
;
2676 memcpy(img
+ 1, debug_frame
, debug_frame_size
);
2678 img
->phdr
.p_vaddr
= buf
;
2679 img
->phdr
.p_paddr
= buf
;
2680 img
->phdr
.p_memsz
= buf_size
;
2682 img
->shdr
[1].sh_name
= find_string(img
->str
, ".text");
2683 img
->shdr
[1].sh_addr
= buf
;
2684 img
->shdr
[1].sh_size
= buf_size
;
2686 img
->shdr
[2].sh_name
= find_string(img
->str
, ".debug_info");
2687 img
->shdr
[3].sh_name
= find_string(img
->str
, ".debug_abbrev");
2689 img
->shdr
[4].sh_name
= find_string(img
->str
, ".debug_frame");
2690 img
->shdr
[4].sh_size
= debug_frame_size
;
2692 img
->shdr
[5].sh_name
= find_string(img
->str
, ".symtab");
2693 img
->shdr
[6].sh_name
= find_string(img
->str
, ".strtab");
2695 img
->sym
[1].st_name
= find_string(img
->str
, "code_gen_buffer");
2696 img
->sym
[1].st_value
= buf
;
2697 img
->sym
[1].st_size
= buf_size
;
2699 img
->di
.cu_low_pc
= buf
;
2700 img
->di
.cu_high_pc
= buf
+ buf_size
;
2701 img
->di
.fn_low_pc
= buf
;
2702 img
->di
.fn_high_pc
= buf
+ buf_size
;
2705 /* Enable this block to be able to debug the ELF image file creation.
2706 One can use readelf, objdump, or other inspection utilities. */
2708 FILE *f
= fopen("/tmp/qemu.jit", "w+b");
2710 if (fwrite(img
, img_size
, 1, f
) != img_size
) {
2711 /* Avoid stupid unused return value warning for fwrite. */
2718 one_entry
.symfile_addr
= img
;
2719 one_entry
.symfile_size
= img_size
;
2721 __jit_debug_descriptor
.action_flag
= JIT_REGISTER_FN
;
2722 __jit_debug_descriptor
.relevant_entry
= &one_entry
;
2723 __jit_debug_descriptor
.first_entry
= &one_entry
;
2724 __jit_debug_register_code();
2727 /* No support for the feature. Provide the entry point expected by exec.c,
2728 and implement the internal function we declared earlier. */
2730 static void tcg_register_jit_int(void *buf
, size_t size
,
2731 void *debug_frame
, size_t debug_frame_size
)
2735 void tcg_register_jit(void *buf
, size_t buf_size
)
2738 #endif /* ELF_HOST_MACHINE */