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 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 tcg_target_long value
, tcg_target_long addend
);
71 static TCGOpDef tcg_op_defs
[] = {
72 #define DEF(s, oargs, iargs, cargs, flags) { #s, oargs, iargs, cargs, iargs + oargs + cargs, flags },
77 static TCGRegSet tcg_target_available_regs
[2];
78 static TCGRegSet tcg_target_call_clobber_regs
;
80 /* XXX: move that inside the context */
81 uint16_t *gen_opc_ptr
;
82 TCGArg
*gen_opparam_ptr
;
84 static inline void tcg_out8(TCGContext
*s
, uint8_t v
)
89 static inline void tcg_out16(TCGContext
*s
, uint16_t v
)
91 *(uint16_t *)s
->code_ptr
= v
;
95 static inline void tcg_out32(TCGContext
*s
, uint32_t v
)
97 *(uint32_t *)s
->code_ptr
= v
;
101 /* label relocation processing */
103 static void tcg_out_reloc(TCGContext
*s
, uint8_t *code_ptr
, int type
,
104 int label_index
, long addend
)
109 l
= &s
->labels
[label_index
];
111 /* FIXME: This may break relocations on RISC targets that
112 modify instruction fields in place. The caller may not have
113 written the initial value. */
114 patch_reloc(code_ptr
, type
, l
->u
.value
, addend
);
116 /* add a new relocation entry */
117 r
= tcg_malloc(sizeof(TCGRelocation
));
121 r
->next
= l
->u
.first_reloc
;
122 l
->u
.first_reloc
= r
;
126 static void tcg_out_label(TCGContext
*s
, int label_index
,
127 tcg_target_long value
)
132 l
= &s
->labels
[label_index
];
135 r
= l
->u
.first_reloc
;
137 patch_reloc(r
->ptr
, r
->type
, value
, r
->addend
);
144 int gen_new_label(void)
146 TCGContext
*s
= &tcg_ctx
;
150 if (s
->nb_labels
>= TCG_MAX_LABELS
)
152 idx
= s
->nb_labels
++;
155 l
->u
.first_reloc
= NULL
;
159 #include "tcg-target.c"
161 /* pool based memory allocation */
162 void *tcg_malloc_internal(TCGContext
*s
, int size
)
167 if (size
> TCG_POOL_CHUNK_SIZE
) {
168 /* big malloc: insert a new pool (XXX: could optimize) */
169 p
= qemu_malloc(sizeof(TCGPool
) + size
);
172 s
->pool_current
->next
= p
;
175 p
->next
= s
->pool_current
;
185 pool_size
= TCG_POOL_CHUNK_SIZE
;
186 p
= qemu_malloc(sizeof(TCGPool
) + pool_size
);
190 s
->pool_current
->next
= p
;
199 s
->pool_cur
= p
->data
+ size
;
200 s
->pool_end
= p
->data
+ p
->size
;
204 void tcg_pool_reset(TCGContext
*s
)
206 s
->pool_cur
= s
->pool_end
= NULL
;
207 s
->pool_current
= NULL
;
210 void tcg_context_init(TCGContext
*s
)
212 int op
, total_args
, n
;
214 TCGArgConstraint
*args_ct
;
217 memset(s
, 0, sizeof(*s
));
218 s
->temps
= s
->static_temps
;
221 /* Count total number of arguments and allocate the corresponding
224 for(op
= 0; op
< NB_OPS
; op
++) {
225 def
= &tcg_op_defs
[op
];
226 n
= def
->nb_iargs
+ def
->nb_oargs
;
230 args_ct
= qemu_malloc(sizeof(TCGArgConstraint
) * total_args
);
231 sorted_args
= qemu_malloc(sizeof(int) * total_args
);
233 for(op
= 0; op
< NB_OPS
; op
++) {
234 def
= &tcg_op_defs
[op
];
235 def
->args_ct
= args_ct
;
236 def
->sorted_args
= sorted_args
;
237 n
= def
->nb_iargs
+ def
->nb_oargs
;
245 void tcg_prologue_init(TCGContext
*s
)
247 /* init global prologue and epilogue */
248 s
->code_buf
= code_gen_prologue
;
249 s
->code_ptr
= s
->code_buf
;
250 tcg_target_qemu_prologue(s
);
251 flush_icache_range((unsigned long)s
->code_buf
,
252 (unsigned long)s
->code_ptr
);
255 void tcg_set_frame(TCGContext
*s
, int reg
,
256 tcg_target_long start
, tcg_target_long size
)
258 s
->frame_start
= start
;
259 s
->frame_end
= start
+ size
;
263 void tcg_func_start(TCGContext
*s
)
267 s
->nb_temps
= s
->nb_globals
;
268 for(i
= 0; i
< (TCG_TYPE_COUNT
* 2); i
++)
269 s
->first_free_temp
[i
] = -1;
270 s
->labels
= tcg_malloc(sizeof(TCGLabel
) * TCG_MAX_LABELS
);
272 s
->current_frame_offset
= s
->frame_start
;
274 gen_opc_ptr
= gen_opc_buf
;
275 gen_opparam_ptr
= gen_opparam_buf
;
278 static inline void tcg_temp_alloc(TCGContext
*s
, int n
)
280 if (n
> TCG_MAX_TEMPS
)
284 static inline int tcg_global_reg_new_internal(TCGType type
, int reg
,
287 TCGContext
*s
= &tcg_ctx
;
291 #if TCG_TARGET_REG_BITS == 32
292 if (type
!= TCG_TYPE_I32
)
295 if (tcg_regset_test_reg(s
->reserved_regs
, reg
))
298 tcg_temp_alloc(s
, s
->nb_globals
+ 1);
299 ts
= &s
->temps
[s
->nb_globals
];
300 ts
->base_type
= type
;
306 tcg_regset_set_reg(s
->reserved_regs
, reg
);
310 TCGv_i32
tcg_global_reg_new_i32(int reg
, const char *name
)
314 idx
= tcg_global_reg_new_internal(TCG_TYPE_I32
, reg
, name
);
315 return MAKE_TCGV_I32(idx
);
318 TCGv_i64
tcg_global_reg_new_i64(int reg
, const char *name
)
322 idx
= tcg_global_reg_new_internal(TCG_TYPE_I64
, reg
, name
);
323 return MAKE_TCGV_I64(idx
);
326 static inline int tcg_global_mem_new_internal(TCGType type
, int reg
,
327 tcg_target_long offset
,
330 TCGContext
*s
= &tcg_ctx
;
335 #if TCG_TARGET_REG_BITS == 32
336 if (type
== TCG_TYPE_I64
) {
338 tcg_temp_alloc(s
, s
->nb_globals
+ 2);
339 ts
= &s
->temps
[s
->nb_globals
];
340 ts
->base_type
= type
;
341 ts
->type
= TCG_TYPE_I32
;
343 ts
->mem_allocated
= 1;
345 #ifdef TCG_TARGET_WORDS_BIGENDIAN
346 ts
->mem_offset
= offset
+ 4;
348 ts
->mem_offset
= offset
;
350 pstrcpy(buf
, sizeof(buf
), name
);
351 pstrcat(buf
, sizeof(buf
), "_0");
352 ts
->name
= strdup(buf
);
355 ts
->base_type
= type
;
356 ts
->type
= TCG_TYPE_I32
;
358 ts
->mem_allocated
= 1;
360 #ifdef TCG_TARGET_WORDS_BIGENDIAN
361 ts
->mem_offset
= offset
;
363 ts
->mem_offset
= offset
+ 4;
365 pstrcpy(buf
, sizeof(buf
), name
);
366 pstrcat(buf
, sizeof(buf
), "_1");
367 ts
->name
= strdup(buf
);
373 tcg_temp_alloc(s
, s
->nb_globals
+ 1);
374 ts
= &s
->temps
[s
->nb_globals
];
375 ts
->base_type
= type
;
378 ts
->mem_allocated
= 1;
380 ts
->mem_offset
= offset
;
387 TCGv_i32
tcg_global_mem_new_i32(int reg
, tcg_target_long offset
,
392 idx
= tcg_global_mem_new_internal(TCG_TYPE_I32
, reg
, offset
, name
);
393 return MAKE_TCGV_I32(idx
);
396 TCGv_i64
tcg_global_mem_new_i64(int reg
, tcg_target_long offset
,
401 idx
= tcg_global_mem_new_internal(TCG_TYPE_I64
, reg
, offset
, name
);
402 return MAKE_TCGV_I64(idx
);
405 static inline int tcg_temp_new_internal(TCGType type
, int temp_local
)
407 TCGContext
*s
= &tcg_ctx
;
414 idx
= s
->first_free_temp
[k
];
416 /* There is already an available temp with the
419 s
->first_free_temp
[k
] = ts
->next_free_temp
;
420 ts
->temp_allocated
= 1;
421 assert(ts
->temp_local
== temp_local
);
424 #if TCG_TARGET_REG_BITS == 32
425 if (type
== TCG_TYPE_I64
) {
426 tcg_temp_alloc(s
, s
->nb_temps
+ 2);
427 ts
= &s
->temps
[s
->nb_temps
];
428 ts
->base_type
= type
;
429 ts
->type
= TCG_TYPE_I32
;
430 ts
->temp_allocated
= 1;
431 ts
->temp_local
= temp_local
;
434 ts
->base_type
= TCG_TYPE_I32
;
435 ts
->type
= TCG_TYPE_I32
;
436 ts
->temp_allocated
= 1;
437 ts
->temp_local
= temp_local
;
443 tcg_temp_alloc(s
, s
->nb_temps
+ 1);
444 ts
= &s
->temps
[s
->nb_temps
];
445 ts
->base_type
= type
;
447 ts
->temp_allocated
= 1;
448 ts
->temp_local
= temp_local
;
454 #if defined(CONFIG_DEBUG_TCG)
460 TCGv_i32
tcg_temp_new_internal_i32(int temp_local
)
464 idx
= tcg_temp_new_internal(TCG_TYPE_I32
, temp_local
);
465 return MAKE_TCGV_I32(idx
);
468 TCGv_i64
tcg_temp_new_internal_i64(int temp_local
)
472 idx
= tcg_temp_new_internal(TCG_TYPE_I64
, temp_local
);
473 return MAKE_TCGV_I64(idx
);
476 static inline void tcg_temp_free_internal(int idx
)
478 TCGContext
*s
= &tcg_ctx
;
482 #if defined(CONFIG_DEBUG_TCG)
484 if (s
->temps_in_use
< 0) {
485 fprintf(stderr
, "More temporaries freed than allocated!\n");
489 assert(idx
>= s
->nb_globals
&& idx
< s
->nb_temps
);
491 assert(ts
->temp_allocated
!= 0);
492 ts
->temp_allocated
= 0;
496 ts
->next_free_temp
= s
->first_free_temp
[k
];
497 s
->first_free_temp
[k
] = idx
;
500 void tcg_temp_free_i32(TCGv_i32 arg
)
502 tcg_temp_free_internal(GET_TCGV_I32(arg
));
505 void tcg_temp_free_i64(TCGv_i64 arg
)
507 tcg_temp_free_internal(GET_TCGV_I64(arg
));
510 TCGv_i32
tcg_const_i32(int32_t val
)
513 t0
= tcg_temp_new_i32();
514 tcg_gen_movi_i32(t0
, val
);
518 TCGv_i64
tcg_const_i64(int64_t val
)
521 t0
= tcg_temp_new_i64();
522 tcg_gen_movi_i64(t0
, val
);
526 TCGv_i32
tcg_const_local_i32(int32_t val
)
529 t0
= tcg_temp_local_new_i32();
530 tcg_gen_movi_i32(t0
, val
);
534 TCGv_i64
tcg_const_local_i64(int64_t val
)
537 t0
= tcg_temp_local_new_i64();
538 tcg_gen_movi_i64(t0
, val
);
542 #if defined(CONFIG_DEBUG_TCG)
543 void tcg_clear_temp_count(void)
545 TCGContext
*s
= &tcg_ctx
;
549 int tcg_check_temp_count(void)
551 TCGContext
*s
= &tcg_ctx
;
552 if (s
->temps_in_use
) {
553 /* Clear the count so that we don't give another
554 * warning immediately next time around.
563 void tcg_register_helper(void *func
, const char *name
)
565 TCGContext
*s
= &tcg_ctx
;
567 if ((s
->nb_helpers
+ 1) > s
->allocated_helpers
) {
568 n
= s
->allocated_helpers
;
574 s
->helpers
= realloc(s
->helpers
, n
* sizeof(TCGHelperInfo
));
575 s
->allocated_helpers
= n
;
577 s
->helpers
[s
->nb_helpers
].func
= (tcg_target_ulong
)func
;
578 s
->helpers
[s
->nb_helpers
].name
= name
;
582 /* Note: we convert the 64 bit args to 32 bit and do some alignment
583 and endian swap. Maybe it would be better to do the alignment
584 and endian swap in tcg_reg_alloc_call(). */
585 void tcg_gen_callN(TCGContext
*s
, TCGv_ptr func
, unsigned int flags
,
586 int sizemask
, TCGArg ret
, int nargs
, TCGArg
*args
)
588 #if defined(TCG_TARGET_I386) && TCG_TARGET_REG_BITS < 64
596 #if defined(TCG_TARGET_EXTEND_ARGS) && TCG_TARGET_REG_BITS == 64
597 for (i
= 0; i
< nargs
; ++i
) {
598 int is_64bit
= sizemask
& (1 << (i
+1)*2);
599 int is_signed
= sizemask
& (2 << (i
+1)*2);
601 TCGv_i64 temp
= tcg_temp_new_i64();
602 TCGv_i64 orig
= MAKE_TCGV_I64(args
[i
]);
604 tcg_gen_ext32s_i64(temp
, orig
);
606 tcg_gen_ext32u_i64(temp
, orig
);
608 args
[i
] = GET_TCGV_I64(temp
);
611 #endif /* TCG_TARGET_EXTEND_ARGS */
613 *gen_opc_ptr
++ = INDEX_op_call
;
614 nparam
= gen_opparam_ptr
++;
615 #if defined(TCG_TARGET_I386) && TCG_TARGET_REG_BITS < 64
616 call_type
= (flags
& TCG_CALL_TYPE_MASK
);
618 if (ret
!= TCG_CALL_DUMMY_ARG
) {
619 #if TCG_TARGET_REG_BITS < 64
621 #ifdef TCG_TARGET_WORDS_BIGENDIAN
622 *gen_opparam_ptr
++ = ret
+ 1;
623 *gen_opparam_ptr
++ = ret
;
625 *gen_opparam_ptr
++ = ret
;
626 *gen_opparam_ptr
++ = ret
+ 1;
632 *gen_opparam_ptr
++ = ret
;
639 for (i
= 0; i
< nargs
; i
++) {
640 #if TCG_TARGET_REG_BITS < 64
641 int is_64bit
= sizemask
& (1 << (i
+1)*2);
643 #ifdef TCG_TARGET_I386
644 /* REGPARM case: if the third parameter is 64 bit, it is
645 allocated on the stack */
646 if (i
== 2 && call_type
== TCG_CALL_TYPE_REGPARM
) {
647 call_type
= TCG_CALL_TYPE_REGPARM_2
;
648 flags
= (flags
& ~TCG_CALL_TYPE_MASK
) | call_type
;
651 #ifdef TCG_TARGET_CALL_ALIGN_ARGS
652 /* some targets want aligned 64 bit args */
654 *gen_opparam_ptr
++ = TCG_CALL_DUMMY_ARG
;
658 /* If stack grows up, then we will be placing successive
659 arguments at lower addresses, which means we need to
660 reverse the order compared to how we would normally
661 treat either big or little-endian. For those arguments
662 that will wind up in registers, this still works for
663 HPPA (the only current STACK_GROWSUP target) since the
664 argument registers are *also* allocated in decreasing
665 order. If another such target is added, this logic may
666 have to get more complicated to differentiate between
667 stack arguments and register arguments. */
668 #if defined(TCG_TARGET_WORDS_BIGENDIAN) != defined(TCG_TARGET_STACK_GROWSUP)
669 *gen_opparam_ptr
++ = args
[i
] + 1;
670 *gen_opparam_ptr
++ = args
[i
];
672 *gen_opparam_ptr
++ = args
[i
];
673 *gen_opparam_ptr
++ = args
[i
] + 1;
678 #endif /* TCG_TARGET_REG_BITS < 64 */
680 *gen_opparam_ptr
++ = args
[i
];
683 *gen_opparam_ptr
++ = GET_TCGV_PTR(func
);
685 *gen_opparam_ptr
++ = flags
;
687 *nparam
= (nb_rets
<< 16) | (real_args
+ 1);
689 /* total parameters, needed to go backward in the instruction stream */
690 *gen_opparam_ptr
++ = 1 + nb_rets
+ real_args
+ 3;
692 #if defined(TCG_TARGET_EXTEND_ARGS) && TCG_TARGET_REG_BITS == 64
693 for (i
= 0; i
< nargs
; ++i
) {
694 int is_64bit
= sizemask
& (1 << (i
+1)*2);
696 TCGv_i64 temp
= MAKE_TCGV_I64(args
[i
]);
697 tcg_temp_free_i64(temp
);
700 #endif /* TCG_TARGET_EXTEND_ARGS */
703 #if TCG_TARGET_REG_BITS == 32
704 void tcg_gen_shifti_i64(TCGv_i64 ret
, TCGv_i64 arg1
,
705 int c
, int right
, int arith
)
708 tcg_gen_mov_i32(TCGV_LOW(ret
), TCGV_LOW(arg1
));
709 tcg_gen_mov_i32(TCGV_HIGH(ret
), TCGV_HIGH(arg1
));
710 } else if (c
>= 32) {
714 tcg_gen_sari_i32(TCGV_LOW(ret
), TCGV_HIGH(arg1
), c
);
715 tcg_gen_sari_i32(TCGV_HIGH(ret
), TCGV_HIGH(arg1
), 31);
717 tcg_gen_shri_i32(TCGV_LOW(ret
), TCGV_HIGH(arg1
), c
);
718 tcg_gen_movi_i32(TCGV_HIGH(ret
), 0);
721 tcg_gen_shli_i32(TCGV_HIGH(ret
), TCGV_LOW(arg1
), c
);
722 tcg_gen_movi_i32(TCGV_LOW(ret
), 0);
727 t0
= tcg_temp_new_i32();
728 t1
= tcg_temp_new_i32();
730 tcg_gen_shli_i32(t0
, TCGV_HIGH(arg1
), 32 - c
);
732 tcg_gen_sari_i32(t1
, TCGV_HIGH(arg1
), c
);
734 tcg_gen_shri_i32(t1
, TCGV_HIGH(arg1
), c
);
735 tcg_gen_shri_i32(TCGV_LOW(ret
), TCGV_LOW(arg1
), c
);
736 tcg_gen_or_i32(TCGV_LOW(ret
), TCGV_LOW(ret
), t0
);
737 tcg_gen_mov_i32(TCGV_HIGH(ret
), t1
);
739 tcg_gen_shri_i32(t0
, TCGV_LOW(arg1
), 32 - c
);
740 /* Note: ret can be the same as arg1, so we use t1 */
741 tcg_gen_shli_i32(t1
, TCGV_LOW(arg1
), c
);
742 tcg_gen_shli_i32(TCGV_HIGH(ret
), TCGV_HIGH(arg1
), c
);
743 tcg_gen_or_i32(TCGV_HIGH(ret
), TCGV_HIGH(ret
), t0
);
744 tcg_gen_mov_i32(TCGV_LOW(ret
), t1
);
746 tcg_temp_free_i32(t0
);
747 tcg_temp_free_i32(t1
);
753 static void tcg_reg_alloc_start(TCGContext
*s
)
757 for(i
= 0; i
< s
->nb_globals
; i
++) {
760 ts
->val_type
= TEMP_VAL_REG
;
762 ts
->val_type
= TEMP_VAL_MEM
;
765 for(i
= s
->nb_globals
; i
< s
->nb_temps
; i
++) {
767 ts
->val_type
= TEMP_VAL_DEAD
;
768 ts
->mem_allocated
= 0;
771 for(i
= 0; i
< TCG_TARGET_NB_REGS
; i
++) {
772 s
->reg_to_temp
[i
] = -1;
776 static char *tcg_get_arg_str_idx(TCGContext
*s
, char *buf
, int buf_size
,
782 if (idx
< s
->nb_globals
) {
783 pstrcpy(buf
, buf_size
, ts
->name
);
786 snprintf(buf
, buf_size
, "loc%d", idx
- s
->nb_globals
);
788 snprintf(buf
, buf_size
, "tmp%d", idx
- s
->nb_globals
);
793 char *tcg_get_arg_str_i32(TCGContext
*s
, char *buf
, int buf_size
, TCGv_i32 arg
)
795 return tcg_get_arg_str_idx(s
, buf
, buf_size
, GET_TCGV_I32(arg
));
798 char *tcg_get_arg_str_i64(TCGContext
*s
, char *buf
, int buf_size
, TCGv_i64 arg
)
800 return tcg_get_arg_str_idx(s
, buf
, buf_size
, GET_TCGV_I64(arg
));
803 static int helper_cmp(const void *p1
, const void *p2
)
805 const TCGHelperInfo
*th1
= p1
;
806 const TCGHelperInfo
*th2
= p2
;
807 if (th1
->func
< th2
->func
)
809 else if (th1
->func
== th2
->func
)
815 /* find helper definition (Note: A hash table would be better) */
816 static TCGHelperInfo
*tcg_find_helper(TCGContext
*s
, tcg_target_ulong val
)
822 if (unlikely(!s
->helpers_sorted
)) {
823 qsort(s
->helpers
, s
->nb_helpers
, sizeof(TCGHelperInfo
),
825 s
->helpers_sorted
= 1;
830 m_max
= s
->nb_helpers
- 1;
831 while (m_min
<= m_max
) {
832 m
= (m_min
+ m_max
) >> 1;
846 static const char * const cond_name
[] =
848 [TCG_COND_EQ
] = "eq",
849 [TCG_COND_NE
] = "ne",
850 [TCG_COND_LT
] = "lt",
851 [TCG_COND_GE
] = "ge",
852 [TCG_COND_LE
] = "le",
853 [TCG_COND_GT
] = "gt",
854 [TCG_COND_LTU
] = "ltu",
855 [TCG_COND_GEU
] = "geu",
856 [TCG_COND_LEU
] = "leu",
857 [TCG_COND_GTU
] = "gtu"
860 void tcg_dump_ops(TCGContext
*s
, FILE *outfile
)
862 const uint16_t *opc_ptr
;
866 int i
, k
, nb_oargs
, nb_iargs
, nb_cargs
, first_insn
;
871 opc_ptr
= gen_opc_buf
;
872 args
= gen_opparam_buf
;
873 while (opc_ptr
< gen_opc_ptr
) {
875 def
= &tcg_op_defs
[c
];
876 if (c
== INDEX_op_debug_insn_start
) {
878 #if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
879 pc
= ((uint64_t)args
[1] << 32) | args
[0];
884 fprintf(outfile
, "\n");
885 fprintf(outfile
, " ---- 0x%" PRIx64
, pc
);
887 nb_oargs
= def
->nb_oargs
;
888 nb_iargs
= def
->nb_iargs
;
889 nb_cargs
= def
->nb_cargs
;
890 } else if (c
== INDEX_op_call
) {
893 /* variable number of arguments */
895 nb_oargs
= arg
>> 16;
896 nb_iargs
= arg
& 0xffff;
897 nb_cargs
= def
->nb_cargs
;
899 fprintf(outfile
, " %s ", def
->name
);
902 fprintf(outfile
, "%s",
903 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), args
[nb_oargs
+ nb_iargs
- 1]));
905 fprintf(outfile
, ",$0x%" TCG_PRIlx
,
906 args
[nb_oargs
+ nb_iargs
]);
908 fprintf(outfile
, ",$%d", nb_oargs
);
909 for(i
= 0; i
< nb_oargs
; i
++) {
910 fprintf(outfile
, ",");
911 fprintf(outfile
, "%s",
912 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), args
[i
]));
914 for(i
= 0; i
< (nb_iargs
- 1); i
++) {
915 fprintf(outfile
, ",");
916 if (args
[nb_oargs
+ i
] == TCG_CALL_DUMMY_ARG
) {
917 fprintf(outfile
, "<dummy>");
919 fprintf(outfile
, "%s",
920 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), args
[nb_oargs
+ i
]));
923 } else if (c
== INDEX_op_movi_i32
924 #if TCG_TARGET_REG_BITS == 64
925 || c
== INDEX_op_movi_i64
928 tcg_target_ulong val
;
931 nb_oargs
= def
->nb_oargs
;
932 nb_iargs
= def
->nb_iargs
;
933 nb_cargs
= def
->nb_cargs
;
934 fprintf(outfile
, " %s %s,$", def
->name
,
935 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), args
[0]));
937 th
= tcg_find_helper(s
, val
);
939 fprintf(outfile
, "%s", th
->name
);
941 if (c
== INDEX_op_movi_i32
)
942 fprintf(outfile
, "0x%x", (uint32_t)val
);
944 fprintf(outfile
, "0x%" PRIx64
, (uint64_t)val
);
947 fprintf(outfile
, " %s ", def
->name
);
948 if (c
== INDEX_op_nopn
) {
949 /* variable number of arguments */
954 nb_oargs
= def
->nb_oargs
;
955 nb_iargs
= def
->nb_iargs
;
956 nb_cargs
= def
->nb_cargs
;
960 for(i
= 0; i
< nb_oargs
; i
++) {
962 fprintf(outfile
, ",");
963 fprintf(outfile
, "%s",
964 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), args
[k
++]));
966 for(i
= 0; i
< nb_iargs
; i
++) {
968 fprintf(outfile
, ",");
969 fprintf(outfile
, "%s",
970 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), args
[k
++]));
973 case INDEX_op_brcond_i32
:
974 #if TCG_TARGET_REG_BITS == 32
975 case INDEX_op_brcond2_i32
:
976 #elif TCG_TARGET_REG_BITS == 64
977 case INDEX_op_brcond_i64
:
979 case INDEX_op_setcond_i32
:
980 #if TCG_TARGET_REG_BITS == 32
981 case INDEX_op_setcond2_i32
:
982 #elif TCG_TARGET_REG_BITS == 64
983 case INDEX_op_setcond_i64
:
985 if (args
[k
] < ARRAY_SIZE(cond_name
) && cond_name
[args
[k
]])
986 fprintf(outfile
, ",%s", cond_name
[args
[k
++]]);
988 fprintf(outfile
, ",$0x%" TCG_PRIlx
, args
[k
++]);
995 for(; i
< nb_cargs
; i
++) {
997 fprintf(outfile
, ",");
999 fprintf(outfile
, "$0x%" TCG_PRIlx
, arg
);
1002 fprintf(outfile
, "\n");
1003 args
+= nb_iargs
+ nb_oargs
+ nb_cargs
;
1007 /* we give more priority to constraints with less registers */
1008 static int get_constraint_priority(const TCGOpDef
*def
, int k
)
1010 const TCGArgConstraint
*arg_ct
;
1013 arg_ct
= &def
->args_ct
[k
];
1014 if (arg_ct
->ct
& TCG_CT_ALIAS
) {
1015 /* an alias is equivalent to a single register */
1018 if (!(arg_ct
->ct
& TCG_CT_REG
))
1021 for(i
= 0; i
< TCG_TARGET_NB_REGS
; i
++) {
1022 if (tcg_regset_test_reg(arg_ct
->u
.regs
, i
))
1026 return TCG_TARGET_NB_REGS
- n
+ 1;
1029 /* sort from highest priority to lowest */
1030 static void sort_constraints(TCGOpDef
*def
, int start
, int n
)
1032 int i
, j
, p1
, p2
, tmp
;
1034 for(i
= 0; i
< n
; i
++)
1035 def
->sorted_args
[start
+ i
] = start
+ i
;
1038 for(i
= 0; i
< n
- 1; i
++) {
1039 for(j
= i
+ 1; j
< n
; j
++) {
1040 p1
= get_constraint_priority(def
, def
->sorted_args
[start
+ i
]);
1041 p2
= get_constraint_priority(def
, def
->sorted_args
[start
+ j
]);
1043 tmp
= def
->sorted_args
[start
+ i
];
1044 def
->sorted_args
[start
+ i
] = def
->sorted_args
[start
+ j
];
1045 def
->sorted_args
[start
+ j
] = tmp
;
1051 void tcg_add_target_add_op_defs(const TCGTargetOpDef
*tdefs
)
1059 if (tdefs
->op
== (TCGOpcode
)-1)
1062 assert((unsigned)op
< NB_OPS
);
1063 def
= &tcg_op_defs
[op
];
1064 #if defined(CONFIG_DEBUG_TCG)
1065 /* Duplicate entry in op definitions? */
1069 nb_args
= def
->nb_iargs
+ def
->nb_oargs
;
1070 for(i
= 0; i
< nb_args
; i
++) {
1071 ct_str
= tdefs
->args_ct_str
[i
];
1072 /* Incomplete TCGTargetOpDef entry? */
1073 assert(ct_str
!= NULL
);
1074 tcg_regset_clear(def
->args_ct
[i
].u
.regs
);
1075 def
->args_ct
[i
].ct
= 0;
1076 if (ct_str
[0] >= '0' && ct_str
[0] <= '9') {
1078 oarg
= ct_str
[0] - '0';
1079 assert(oarg
< def
->nb_oargs
);
1080 assert(def
->args_ct
[oarg
].ct
& TCG_CT_REG
);
1081 /* TCG_CT_ALIAS is for the output arguments. The input
1082 argument is tagged with TCG_CT_IALIAS. */
1083 def
->args_ct
[i
] = def
->args_ct
[oarg
];
1084 def
->args_ct
[oarg
].ct
= TCG_CT_ALIAS
;
1085 def
->args_ct
[oarg
].alias_index
= i
;
1086 def
->args_ct
[i
].ct
|= TCG_CT_IALIAS
;
1087 def
->args_ct
[i
].alias_index
= oarg
;
1090 if (*ct_str
== '\0')
1094 def
->args_ct
[i
].ct
|= TCG_CT_CONST
;
1098 if (target_parse_constraint(&def
->args_ct
[i
], &ct_str
) < 0) {
1099 fprintf(stderr
, "Invalid constraint '%s' for arg %d of operation '%s'\n",
1100 ct_str
, i
, def
->name
);
1108 /* TCGTargetOpDef entry with too much information? */
1109 assert(i
== TCG_MAX_OP_ARGS
|| tdefs
->args_ct_str
[i
] == NULL
);
1111 /* sort the constraints (XXX: this is just an heuristic) */
1112 sort_constraints(def
, 0, def
->nb_oargs
);
1113 sort_constraints(def
, def
->nb_oargs
, def
->nb_iargs
);
1119 printf("%s: sorted=", def
->name
);
1120 for(i
= 0; i
< def
->nb_oargs
+ def
->nb_iargs
; i
++)
1121 printf(" %d", def
->sorted_args
[i
]);
1128 #if defined(CONFIG_DEBUG_TCG)
1130 for (op
= 0; op
< ARRAY_SIZE(tcg_op_defs
); op
++) {
1131 if (op
< INDEX_op_call
|| op
== INDEX_op_debug_insn_start
) {
1132 /* Wrong entry in op definitions? */
1133 if (tcg_op_defs
[op
].used
) {
1134 fprintf(stderr
, "Invalid op definition for %s\n",
1135 tcg_op_defs
[op
].name
);
1139 /* Missing entry in op definitions? */
1140 if (!tcg_op_defs
[op
].used
) {
1141 fprintf(stderr
, "Missing op definition for %s\n",
1142 tcg_op_defs
[op
].name
);
1153 #ifdef USE_LIVENESS_ANALYSIS
1155 /* set a nop for an operation using 'nb_args' */
1156 static inline void tcg_set_nop(TCGContext
*s
, uint16_t *opc_ptr
,
1157 TCGArg
*args
, int nb_args
)
1160 *opc_ptr
= INDEX_op_nop
;
1162 *opc_ptr
= INDEX_op_nopn
;
1164 args
[nb_args
- 1] = nb_args
;
1168 /* liveness analysis: end of function: globals are live, temps are
1170 /* XXX: at this stage, not used as there would be little gains because
1171 most TBs end with a conditional jump. */
1172 static inline void tcg_la_func_end(TCGContext
*s
, uint8_t *dead_temps
)
1174 memset(dead_temps
, 0, s
->nb_globals
);
1175 memset(dead_temps
+ s
->nb_globals
, 1, s
->nb_temps
- s
->nb_globals
);
1178 /* liveness analysis: end of basic block: globals are live, temps are
1179 dead, local temps are live. */
1180 static inline void tcg_la_bb_end(TCGContext
*s
, uint8_t *dead_temps
)
1185 memset(dead_temps
, 0, s
->nb_globals
);
1186 ts
= &s
->temps
[s
->nb_globals
];
1187 for(i
= s
->nb_globals
; i
< s
->nb_temps
; i
++) {
1196 /* Liveness analysis : update the opc_dead_args array to tell if a
1197 given input arguments is dead. Instructions updating dead
1198 temporaries are removed. */
1199 static void tcg_liveness_analysis(TCGContext
*s
)
1201 int i
, op_index
, nb_args
, nb_iargs
, nb_oargs
, arg
, nb_ops
;
1204 const TCGOpDef
*def
;
1205 uint8_t *dead_temps
;
1206 unsigned int dead_args
;
1208 gen_opc_ptr
++; /* skip end */
1210 nb_ops
= gen_opc_ptr
- gen_opc_buf
;
1212 s
->op_dead_args
= tcg_malloc(nb_ops
* sizeof(uint16_t));
1214 dead_temps
= tcg_malloc(s
->nb_temps
);
1215 memset(dead_temps
, 1, s
->nb_temps
);
1217 args
= gen_opparam_ptr
;
1218 op_index
= nb_ops
- 1;
1219 while (op_index
>= 0) {
1220 op
= gen_opc_buf
[op_index
];
1221 def
= &tcg_op_defs
[op
];
1229 nb_iargs
= args
[0] & 0xffff;
1230 nb_oargs
= args
[0] >> 16;
1232 call_flags
= args
[nb_oargs
+ nb_iargs
];
1234 /* pure functions can be removed if their result is not
1236 if (call_flags
& TCG_CALL_PURE
) {
1237 for(i
= 0; i
< nb_oargs
; i
++) {
1239 if (!dead_temps
[arg
])
1240 goto do_not_remove_call
;
1242 tcg_set_nop(s
, gen_opc_buf
+ op_index
,
1247 /* output args are dead */
1249 for(i
= 0; i
< nb_oargs
; i
++) {
1251 if (dead_temps
[arg
]) {
1252 dead_args
|= (1 << i
);
1254 dead_temps
[arg
] = 1;
1257 if (!(call_flags
& TCG_CALL_CONST
)) {
1258 /* globals are live (they may be used by the call) */
1259 memset(dead_temps
, 0, s
->nb_globals
);
1262 /* input args are live */
1263 for(i
= nb_oargs
; i
< nb_iargs
+ nb_oargs
; i
++) {
1265 if (arg
!= TCG_CALL_DUMMY_ARG
) {
1266 if (dead_temps
[arg
]) {
1267 dead_args
|= (1 << i
);
1269 dead_temps
[arg
] = 0;
1272 s
->op_dead_args
[op_index
] = dead_args
;
1277 case INDEX_op_set_label
:
1279 /* mark end of basic block */
1280 tcg_la_bb_end(s
, dead_temps
);
1282 case INDEX_op_debug_insn_start
:
1283 args
-= def
->nb_args
;
1289 case INDEX_op_discard
:
1291 /* mark the temporary as dead */
1292 dead_temps
[args
[0]] = 1;
1296 /* XXX: optimize by hardcoding common cases (e.g. triadic ops) */
1298 args
-= def
->nb_args
;
1299 nb_iargs
= def
->nb_iargs
;
1300 nb_oargs
= def
->nb_oargs
;
1302 /* Test if the operation can be removed because all
1303 its outputs are dead. We assume that nb_oargs == 0
1304 implies side effects */
1305 if (!(def
->flags
& TCG_OPF_SIDE_EFFECTS
) && nb_oargs
!= 0) {
1306 for(i
= 0; i
< nb_oargs
; i
++) {
1308 if (!dead_temps
[arg
])
1311 tcg_set_nop(s
, gen_opc_buf
+ op_index
, args
, def
->nb_args
);
1312 #ifdef CONFIG_PROFILER
1318 /* output args are dead */
1320 for(i
= 0; i
< nb_oargs
; i
++) {
1322 if (dead_temps
[arg
]) {
1323 dead_args
|= (1 << i
);
1325 dead_temps
[arg
] = 1;
1328 /* if end of basic block, update */
1329 if (def
->flags
& TCG_OPF_BB_END
) {
1330 tcg_la_bb_end(s
, dead_temps
);
1331 } else if (def
->flags
& TCG_OPF_CALL_CLOBBER
) {
1332 /* globals are live */
1333 memset(dead_temps
, 0, s
->nb_globals
);
1336 /* input args are live */
1337 for(i
= nb_oargs
; i
< nb_oargs
+ nb_iargs
; i
++) {
1339 if (dead_temps
[arg
]) {
1340 dead_args
|= (1 << i
);
1342 dead_temps
[arg
] = 0;
1344 s
->op_dead_args
[op_index
] = dead_args
;
1351 if (args
!= gen_opparam_buf
)
1355 /* dummy liveness analysis */
1356 static void tcg_liveness_analysis(TCGContext
*s
)
1359 nb_ops
= gen_opc_ptr
- gen_opc_buf
;
1361 s
->op_dead_args
= tcg_malloc(nb_ops
* sizeof(uint16_t));
1362 memset(s
->op_dead_args
, 0, nb_ops
* sizeof(uint16_t));
1367 static void dump_regs(TCGContext
*s
)
1373 for(i
= 0; i
< s
->nb_temps
; i
++) {
1375 printf(" %10s: ", tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), i
));
1376 switch(ts
->val_type
) {
1378 printf("%s", tcg_target_reg_names
[ts
->reg
]);
1381 printf("%d(%s)", (int)ts
->mem_offset
, tcg_target_reg_names
[ts
->mem_reg
]);
1383 case TEMP_VAL_CONST
:
1384 printf("$0x%" TCG_PRIlx
, ts
->val
);
1396 for(i
= 0; i
< TCG_TARGET_NB_REGS
; i
++) {
1397 if (s
->reg_to_temp
[i
] >= 0) {
1399 tcg_target_reg_names
[i
],
1400 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), s
->reg_to_temp
[i
]));
1405 static void check_regs(TCGContext
*s
)
1411 for(reg
= 0; reg
< TCG_TARGET_NB_REGS
; reg
++) {
1412 k
= s
->reg_to_temp
[reg
];
1415 if (ts
->val_type
!= TEMP_VAL_REG
||
1417 printf("Inconsistency for register %s:\n",
1418 tcg_target_reg_names
[reg
]);
1423 for(k
= 0; k
< s
->nb_temps
; k
++) {
1425 if (ts
->val_type
== TEMP_VAL_REG
&&
1427 s
->reg_to_temp
[ts
->reg
] != k
) {
1428 printf("Inconsistency for temp %s:\n",
1429 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), k
));
1431 printf("reg state:\n");
1439 static void temp_allocate_frame(TCGContext
*s
, int temp
)
1442 ts
= &s
->temps
[temp
];
1443 #ifndef __sparc_v9__ /* Sparc64 stack is accessed with offset of 2047 */
1444 s
->current_frame_offset
= (s
->current_frame_offset
+
1445 (tcg_target_long
)sizeof(tcg_target_long
) - 1) &
1446 ~(sizeof(tcg_target_long
) - 1);
1448 if (s
->current_frame_offset
+ (tcg_target_long
)sizeof(tcg_target_long
) >
1452 ts
->mem_offset
= s
->current_frame_offset
;
1453 ts
->mem_reg
= s
->frame_reg
;
1454 ts
->mem_allocated
= 1;
1455 s
->current_frame_offset
+= (tcg_target_long
)sizeof(tcg_target_long
);
1458 /* free register 'reg' by spilling the corresponding temporary if necessary */
1459 static void tcg_reg_free(TCGContext
*s
, int reg
)
1464 temp
= s
->reg_to_temp
[reg
];
1466 ts
= &s
->temps
[temp
];
1467 assert(ts
->val_type
== TEMP_VAL_REG
);
1468 if (!ts
->mem_coherent
) {
1469 if (!ts
->mem_allocated
)
1470 temp_allocate_frame(s
, temp
);
1471 tcg_out_st(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
1473 ts
->val_type
= TEMP_VAL_MEM
;
1474 s
->reg_to_temp
[reg
] = -1;
1478 /* Allocate a register belonging to reg1 & ~reg2 */
1479 static int tcg_reg_alloc(TCGContext
*s
, TCGRegSet reg1
, TCGRegSet reg2
)
1484 tcg_regset_andnot(reg_ct
, reg1
, reg2
);
1486 /* first try free registers */
1487 for(i
= 0; i
< ARRAY_SIZE(tcg_target_reg_alloc_order
); i
++) {
1488 reg
= tcg_target_reg_alloc_order
[i
];
1489 if (tcg_regset_test_reg(reg_ct
, reg
) && s
->reg_to_temp
[reg
] == -1)
1493 /* XXX: do better spill choice */
1494 for(i
= 0; i
< ARRAY_SIZE(tcg_target_reg_alloc_order
); i
++) {
1495 reg
= tcg_target_reg_alloc_order
[i
];
1496 if (tcg_regset_test_reg(reg_ct
, reg
)) {
1497 tcg_reg_free(s
, reg
);
1505 /* save a temporary to memory. 'allocated_regs' is used in case a
1506 temporary registers needs to be allocated to store a constant. */
1507 static void temp_save(TCGContext
*s
, int temp
, TCGRegSet allocated_regs
)
1512 ts
= &s
->temps
[temp
];
1513 if (!ts
->fixed_reg
) {
1514 switch(ts
->val_type
) {
1516 tcg_reg_free(s
, ts
->reg
);
1519 ts
->val_type
= TEMP_VAL_MEM
;
1521 case TEMP_VAL_CONST
:
1522 reg
= tcg_reg_alloc(s
, tcg_target_available_regs
[ts
->type
],
1524 if (!ts
->mem_allocated
)
1525 temp_allocate_frame(s
, temp
);
1526 tcg_out_movi(s
, ts
->type
, reg
, ts
->val
);
1527 tcg_out_st(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
1528 ts
->val_type
= TEMP_VAL_MEM
;
1538 /* save globals to their cannonical location and assume they can be
1539 modified be the following code. 'allocated_regs' is used in case a
1540 temporary registers needs to be allocated to store a constant. */
1541 static void save_globals(TCGContext
*s
, TCGRegSet allocated_regs
)
1545 for(i
= 0; i
< s
->nb_globals
; i
++) {
1546 temp_save(s
, i
, allocated_regs
);
1550 /* at the end of a basic block, we assume all temporaries are dead and
1551 all globals are stored at their canonical location. */
1552 static void tcg_reg_alloc_bb_end(TCGContext
*s
, TCGRegSet allocated_regs
)
1557 for(i
= s
->nb_globals
; i
< s
->nb_temps
; i
++) {
1559 if (ts
->temp_local
) {
1560 temp_save(s
, i
, allocated_regs
);
1562 if (ts
->val_type
== TEMP_VAL_REG
) {
1563 s
->reg_to_temp
[ts
->reg
] = -1;
1565 ts
->val_type
= TEMP_VAL_DEAD
;
1569 save_globals(s
, allocated_regs
);
1572 #define IS_DEAD_ARG(n) ((dead_args >> (n)) & 1)
1574 static void tcg_reg_alloc_movi(TCGContext
*s
, const TCGArg
*args
)
1577 tcg_target_ulong val
;
1579 ots
= &s
->temps
[args
[0]];
1582 if (ots
->fixed_reg
) {
1583 /* for fixed registers, we do not do any constant
1585 tcg_out_movi(s
, ots
->type
, ots
->reg
, val
);
1587 /* The movi is not explicitly generated here */
1588 if (ots
->val_type
== TEMP_VAL_REG
)
1589 s
->reg_to_temp
[ots
->reg
] = -1;
1590 ots
->val_type
= TEMP_VAL_CONST
;
1595 static void tcg_reg_alloc_mov(TCGContext
*s
, const TCGOpDef
*def
,
1597 unsigned int dead_args
)
1601 const TCGArgConstraint
*arg_ct
;
1603 ots
= &s
->temps
[args
[0]];
1604 ts
= &s
->temps
[args
[1]];
1605 arg_ct
= &def
->args_ct
[0];
1607 /* XXX: always mark arg dead if IS_DEAD_ARG(1) */
1608 if (ts
->val_type
== TEMP_VAL_REG
) {
1609 if (IS_DEAD_ARG(1) && !ts
->fixed_reg
&& !ots
->fixed_reg
) {
1610 /* the mov can be suppressed */
1611 if (ots
->val_type
== TEMP_VAL_REG
)
1612 s
->reg_to_temp
[ots
->reg
] = -1;
1614 s
->reg_to_temp
[reg
] = -1;
1615 ts
->val_type
= TEMP_VAL_DEAD
;
1617 if (ots
->val_type
== TEMP_VAL_REG
) {
1620 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, s
->reserved_regs
);
1622 if (ts
->reg
!= reg
) {
1623 tcg_out_mov(s
, ots
->type
, reg
, ts
->reg
);
1626 } else if (ts
->val_type
== TEMP_VAL_MEM
) {
1627 if (ots
->val_type
== TEMP_VAL_REG
) {
1630 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, s
->reserved_regs
);
1632 tcg_out_ld(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
1633 } else if (ts
->val_type
== TEMP_VAL_CONST
) {
1634 if (ots
->fixed_reg
) {
1636 tcg_out_movi(s
, ots
->type
, reg
, ts
->val
);
1638 /* propagate constant */
1639 if (ots
->val_type
== TEMP_VAL_REG
)
1640 s
->reg_to_temp
[ots
->reg
] = -1;
1641 ots
->val_type
= TEMP_VAL_CONST
;
1648 s
->reg_to_temp
[reg
] = args
[0];
1650 ots
->val_type
= TEMP_VAL_REG
;
1651 ots
->mem_coherent
= 0;
1654 static void tcg_reg_alloc_op(TCGContext
*s
,
1655 const TCGOpDef
*def
, TCGOpcode opc
,
1657 unsigned int dead_args
)
1659 TCGRegSet allocated_regs
;
1660 int i
, k
, nb_iargs
, nb_oargs
, reg
;
1662 const TCGArgConstraint
*arg_ct
;
1664 TCGArg new_args
[TCG_MAX_OP_ARGS
];
1665 int const_args
[TCG_MAX_OP_ARGS
];
1667 nb_oargs
= def
->nb_oargs
;
1668 nb_iargs
= def
->nb_iargs
;
1670 /* copy constants */
1671 memcpy(new_args
+ nb_oargs
+ nb_iargs
,
1672 args
+ nb_oargs
+ nb_iargs
,
1673 sizeof(TCGArg
) * def
->nb_cargs
);
1675 /* satisfy input constraints */
1676 tcg_regset_set(allocated_regs
, s
->reserved_regs
);
1677 for(k
= 0; k
< nb_iargs
; k
++) {
1678 i
= def
->sorted_args
[nb_oargs
+ k
];
1680 arg_ct
= &def
->args_ct
[i
];
1681 ts
= &s
->temps
[arg
];
1682 if (ts
->val_type
== TEMP_VAL_MEM
) {
1683 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1684 tcg_out_ld(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
1685 ts
->val_type
= TEMP_VAL_REG
;
1687 ts
->mem_coherent
= 1;
1688 s
->reg_to_temp
[reg
] = arg
;
1689 } else if (ts
->val_type
== TEMP_VAL_CONST
) {
1690 if (tcg_target_const_match(ts
->val
, arg_ct
)) {
1691 /* constant is OK for instruction */
1693 new_args
[i
] = ts
->val
;
1696 /* need to move to a register */
1697 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1698 tcg_out_movi(s
, ts
->type
, reg
, ts
->val
);
1699 ts
->val_type
= TEMP_VAL_REG
;
1701 ts
->mem_coherent
= 0;
1702 s
->reg_to_temp
[reg
] = arg
;
1705 assert(ts
->val_type
== TEMP_VAL_REG
);
1706 if (arg_ct
->ct
& TCG_CT_IALIAS
) {
1707 if (ts
->fixed_reg
) {
1708 /* if fixed register, we must allocate a new register
1709 if the alias is not the same register */
1710 if (arg
!= args
[arg_ct
->alias_index
])
1711 goto allocate_in_reg
;
1713 /* if the input is aliased to an output and if it is
1714 not dead after the instruction, we must allocate
1715 a new register and move it */
1716 if (!IS_DEAD_ARG(i
)) {
1717 goto allocate_in_reg
;
1722 if (tcg_regset_test_reg(arg_ct
->u
.regs
, reg
)) {
1723 /* nothing to do : the constraint is satisfied */
1726 /* allocate a new register matching the constraint
1727 and move the temporary register into it */
1728 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1729 tcg_out_mov(s
, ts
->type
, reg
, ts
->reg
);
1733 tcg_regset_set_reg(allocated_regs
, reg
);
1737 if (def
->flags
& TCG_OPF_BB_END
) {
1738 tcg_reg_alloc_bb_end(s
, allocated_regs
);
1740 /* mark dead temporaries and free the associated registers */
1741 for(i
= nb_oargs
; i
< nb_oargs
+ nb_iargs
; i
++) {
1743 if (IS_DEAD_ARG(i
)) {
1744 ts
= &s
->temps
[arg
];
1745 if (!ts
->fixed_reg
) {
1746 if (ts
->val_type
== TEMP_VAL_REG
)
1747 s
->reg_to_temp
[ts
->reg
] = -1;
1748 ts
->val_type
= TEMP_VAL_DEAD
;
1753 if (def
->flags
& TCG_OPF_CALL_CLOBBER
) {
1754 /* XXX: permit generic clobber register list ? */
1755 for(reg
= 0; reg
< TCG_TARGET_NB_REGS
; reg
++) {
1756 if (tcg_regset_test_reg(tcg_target_call_clobber_regs
, reg
)) {
1757 tcg_reg_free(s
, reg
);
1760 /* XXX: for load/store we could do that only for the slow path
1761 (i.e. when a memory callback is called) */
1763 /* store globals and free associated registers (we assume the insn
1764 can modify any global. */
1765 save_globals(s
, allocated_regs
);
1768 /* satisfy the output constraints */
1769 tcg_regset_set(allocated_regs
, s
->reserved_regs
);
1770 for(k
= 0; k
< nb_oargs
; k
++) {
1771 i
= def
->sorted_args
[k
];
1773 arg_ct
= &def
->args_ct
[i
];
1774 ts
= &s
->temps
[arg
];
1775 if (arg_ct
->ct
& TCG_CT_ALIAS
) {
1776 reg
= new_args
[arg_ct
->alias_index
];
1778 /* if fixed register, we try to use it */
1780 if (ts
->fixed_reg
&&
1781 tcg_regset_test_reg(arg_ct
->u
.regs
, reg
)) {
1784 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1786 tcg_regset_set_reg(allocated_regs
, reg
);
1787 /* if a fixed register is used, then a move will be done afterwards */
1788 if (!ts
->fixed_reg
) {
1789 if (ts
->val_type
== TEMP_VAL_REG
)
1790 s
->reg_to_temp
[ts
->reg
] = -1;
1791 if (IS_DEAD_ARG(i
)) {
1792 ts
->val_type
= TEMP_VAL_DEAD
;
1794 ts
->val_type
= TEMP_VAL_REG
;
1796 /* temp value is modified, so the value kept in memory is
1797 potentially not the same */
1798 ts
->mem_coherent
= 0;
1799 s
->reg_to_temp
[reg
] = arg
;
1807 /* emit instruction */
1808 tcg_out_op(s
, opc
, new_args
, const_args
);
1810 /* move the outputs in the correct register if needed */
1811 for(i
= 0; i
< nb_oargs
; i
++) {
1812 ts
= &s
->temps
[args
[i
]];
1814 if (ts
->fixed_reg
&& ts
->reg
!= reg
) {
1815 tcg_out_mov(s
, ts
->type
, ts
->reg
, reg
);
1820 #ifdef TCG_TARGET_STACK_GROWSUP
1821 #define STACK_DIR(x) (-(x))
1823 #define STACK_DIR(x) (x)
1826 static int tcg_reg_alloc_call(TCGContext
*s
, const TCGOpDef
*def
,
1827 TCGOpcode opc
, const TCGArg
*args
,
1828 unsigned int dead_args
)
1830 int nb_iargs
, nb_oargs
, flags
, nb_regs
, i
, reg
, nb_params
;
1831 TCGArg arg
, func_arg
;
1833 tcg_target_long stack_offset
, call_stack_size
, func_addr
;
1834 int const_func_arg
, allocate_args
;
1835 TCGRegSet allocated_regs
;
1836 const TCGArgConstraint
*arg_ct
;
1840 nb_oargs
= arg
>> 16;
1841 nb_iargs
= arg
& 0xffff;
1842 nb_params
= nb_iargs
- 1;
1844 flags
= args
[nb_oargs
+ nb_iargs
];
1846 nb_regs
= tcg_target_get_call_iarg_regs_count(flags
);
1847 if (nb_regs
> nb_params
)
1848 nb_regs
= nb_params
;
1850 /* assign stack slots first */
1851 call_stack_size
= (nb_params
- nb_regs
) * sizeof(tcg_target_long
);
1852 call_stack_size
= (call_stack_size
+ TCG_TARGET_STACK_ALIGN
- 1) &
1853 ~(TCG_TARGET_STACK_ALIGN
- 1);
1854 allocate_args
= (call_stack_size
> TCG_STATIC_CALL_ARGS_SIZE
);
1855 if (allocate_args
) {
1856 /* XXX: if more than TCG_STATIC_CALL_ARGS_SIZE is needed,
1857 preallocate call stack */
1861 stack_offset
= TCG_TARGET_CALL_STACK_OFFSET
;
1862 for(i
= nb_regs
; i
< nb_params
; i
++) {
1863 arg
= args
[nb_oargs
+ i
];
1864 #ifdef TCG_TARGET_STACK_GROWSUP
1865 stack_offset
-= sizeof(tcg_target_long
);
1867 if (arg
!= TCG_CALL_DUMMY_ARG
) {
1868 ts
= &s
->temps
[arg
];
1869 if (ts
->val_type
== TEMP_VAL_REG
) {
1870 tcg_out_st(s
, ts
->type
, ts
->reg
, TCG_REG_CALL_STACK
, stack_offset
);
1871 } else if (ts
->val_type
== TEMP_VAL_MEM
) {
1872 reg
= tcg_reg_alloc(s
, tcg_target_available_regs
[ts
->type
],
1874 /* XXX: not correct if reading values from the stack */
1875 tcg_out_ld(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
1876 tcg_out_st(s
, ts
->type
, reg
, TCG_REG_CALL_STACK
, stack_offset
);
1877 } else if (ts
->val_type
== TEMP_VAL_CONST
) {
1878 reg
= tcg_reg_alloc(s
, tcg_target_available_regs
[ts
->type
],
1880 /* XXX: sign extend may be needed on some targets */
1881 tcg_out_movi(s
, ts
->type
, reg
, ts
->val
);
1882 tcg_out_st(s
, ts
->type
, reg
, TCG_REG_CALL_STACK
, stack_offset
);
1887 #ifndef TCG_TARGET_STACK_GROWSUP
1888 stack_offset
+= sizeof(tcg_target_long
);
1892 /* assign input registers */
1893 tcg_regset_set(allocated_regs
, s
->reserved_regs
);
1894 for(i
= 0; i
< nb_regs
; i
++) {
1895 arg
= args
[nb_oargs
+ i
];
1896 if (arg
!= TCG_CALL_DUMMY_ARG
) {
1897 ts
= &s
->temps
[arg
];
1898 reg
= tcg_target_call_iarg_regs
[i
];
1899 tcg_reg_free(s
, reg
);
1900 if (ts
->val_type
== TEMP_VAL_REG
) {
1901 if (ts
->reg
!= reg
) {
1902 tcg_out_mov(s
, ts
->type
, reg
, ts
->reg
);
1904 } else if (ts
->val_type
== TEMP_VAL_MEM
) {
1905 tcg_out_ld(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
1906 } else if (ts
->val_type
== TEMP_VAL_CONST
) {
1907 /* XXX: sign extend ? */
1908 tcg_out_movi(s
, ts
->type
, reg
, ts
->val
);
1912 tcg_regset_set_reg(allocated_regs
, reg
);
1916 /* assign function address */
1917 func_arg
= args
[nb_oargs
+ nb_iargs
- 1];
1918 arg_ct
= &def
->args_ct
[0];
1919 ts
= &s
->temps
[func_arg
];
1920 func_addr
= ts
->val
;
1922 if (ts
->val_type
== TEMP_VAL_MEM
) {
1923 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1924 tcg_out_ld(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
1926 tcg_regset_set_reg(allocated_regs
, reg
);
1927 } else if (ts
->val_type
== TEMP_VAL_REG
) {
1929 if (!tcg_regset_test_reg(arg_ct
->u
.regs
, reg
)) {
1930 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1931 tcg_out_mov(s
, ts
->type
, reg
, ts
->reg
);
1934 tcg_regset_set_reg(allocated_regs
, reg
);
1935 } else if (ts
->val_type
== TEMP_VAL_CONST
) {
1936 if (tcg_target_const_match(func_addr
, arg_ct
)) {
1938 func_arg
= func_addr
;
1940 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1941 tcg_out_movi(s
, ts
->type
, reg
, func_addr
);
1943 tcg_regset_set_reg(allocated_regs
, reg
);
1950 /* mark dead temporaries and free the associated registers */
1951 for(i
= nb_oargs
; i
< nb_iargs
+ nb_oargs
; i
++) {
1953 if (IS_DEAD_ARG(i
)) {
1954 ts
= &s
->temps
[arg
];
1955 if (!ts
->fixed_reg
) {
1956 if (ts
->val_type
== TEMP_VAL_REG
)
1957 s
->reg_to_temp
[ts
->reg
] = -1;
1958 ts
->val_type
= TEMP_VAL_DEAD
;
1963 /* clobber call registers */
1964 for(reg
= 0; reg
< TCG_TARGET_NB_REGS
; reg
++) {
1965 if (tcg_regset_test_reg(tcg_target_call_clobber_regs
, reg
)) {
1966 tcg_reg_free(s
, reg
);
1970 /* store globals and free associated registers (we assume the call
1971 can modify any global. */
1972 if (!(flags
& TCG_CALL_CONST
)) {
1973 save_globals(s
, allocated_regs
);
1976 tcg_out_op(s
, opc
, &func_arg
, &const_func_arg
);
1978 /* assign output registers and emit moves if needed */
1979 for(i
= 0; i
< nb_oargs
; i
++) {
1981 ts
= &s
->temps
[arg
];
1982 reg
= tcg_target_call_oarg_regs
[i
];
1983 assert(s
->reg_to_temp
[reg
] == -1);
1984 if (ts
->fixed_reg
) {
1985 if (ts
->reg
!= reg
) {
1986 tcg_out_mov(s
, ts
->type
, ts
->reg
, reg
);
1989 if (ts
->val_type
== TEMP_VAL_REG
)
1990 s
->reg_to_temp
[ts
->reg
] = -1;
1991 if (IS_DEAD_ARG(i
)) {
1992 ts
->val_type
= TEMP_VAL_DEAD
;
1994 ts
->val_type
= TEMP_VAL_REG
;
1996 ts
->mem_coherent
= 0;
1997 s
->reg_to_temp
[reg
] = arg
;
2002 return nb_iargs
+ nb_oargs
+ def
->nb_cargs
+ 1;
2005 #ifdef CONFIG_PROFILER
2007 static int64_t tcg_table_op_count
[NB_OPS
];
2009 static void dump_op_count(void)
2013 f
= fopen("/tmp/op.log", "w");
2014 for(i
= INDEX_op_end
; i
< NB_OPS
; i
++) {
2015 fprintf(f
, "%s %" PRId64
"\n", tcg_op_defs
[i
].name
, tcg_table_op_count
[i
]);
2022 static inline int tcg_gen_code_common(TCGContext
*s
, uint8_t *gen_code_buf
,
2027 const TCGOpDef
*def
;
2028 unsigned int dead_args
;
2032 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP
))) {
2034 tcg_dump_ops(s
, logfile
);
2039 #ifdef USE_TCG_OPTIMIZATIONS
2041 tcg_optimize(s
, gen_opc_ptr
, gen_opparam_buf
, tcg_op_defs
);
2044 #ifdef CONFIG_PROFILER
2045 s
->la_time
-= profile_getclock();
2047 tcg_liveness_analysis(s
);
2048 #ifdef CONFIG_PROFILER
2049 s
->la_time
+= profile_getclock();
2053 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_OPT
))) {
2054 qemu_log("OP after liveness analysis:\n");
2055 tcg_dump_ops(s
, logfile
);
2060 tcg_reg_alloc_start(s
);
2062 s
->code_buf
= gen_code_buf
;
2063 s
->code_ptr
= gen_code_buf
;
2065 args
= gen_opparam_buf
;
2069 opc
= gen_opc_buf
[op_index
];
2070 #ifdef CONFIG_PROFILER
2071 tcg_table_op_count
[opc
]++;
2073 def
= &tcg_op_defs
[opc
];
2075 printf("%s: %d %d %d\n", def
->name
,
2076 def
->nb_oargs
, def
->nb_iargs
, def
->nb_cargs
);
2080 case INDEX_op_mov_i32
:
2081 #if TCG_TARGET_REG_BITS == 64
2082 case INDEX_op_mov_i64
:
2084 dead_args
= s
->op_dead_args
[op_index
];
2085 tcg_reg_alloc_mov(s
, def
, args
, dead_args
);
2087 case INDEX_op_movi_i32
:
2088 #if TCG_TARGET_REG_BITS == 64
2089 case INDEX_op_movi_i64
:
2091 tcg_reg_alloc_movi(s
, args
);
2093 case INDEX_op_debug_insn_start
:
2094 /* debug instruction */
2104 case INDEX_op_discard
:
2107 ts
= &s
->temps
[args
[0]];
2108 /* mark the temporary as dead */
2109 if (!ts
->fixed_reg
) {
2110 if (ts
->val_type
== TEMP_VAL_REG
)
2111 s
->reg_to_temp
[ts
->reg
] = -1;
2112 ts
->val_type
= TEMP_VAL_DEAD
;
2116 case INDEX_op_set_label
:
2117 tcg_reg_alloc_bb_end(s
, s
->reserved_regs
);
2118 tcg_out_label(s
, args
[0], (long)s
->code_ptr
);
2121 dead_args
= s
->op_dead_args
[op_index
];
2122 args
+= tcg_reg_alloc_call(s
, def
, opc
, args
, dead_args
);
2127 /* Note: in order to speed up the code, it would be much
2128 faster to have specialized register allocator functions for
2129 some common argument patterns */
2130 dead_args
= s
->op_dead_args
[op_index
];
2131 tcg_reg_alloc_op(s
, def
, opc
, args
, dead_args
);
2134 args
+= def
->nb_args
;
2136 if (search_pc
>= 0 && search_pc
< s
->code_ptr
- gen_code_buf
) {
2148 int tcg_gen_code(TCGContext
*s
, uint8_t *gen_code_buf
)
2150 #ifdef CONFIG_PROFILER
2153 n
= (gen_opc_ptr
- gen_opc_buf
);
2155 if (n
> s
->op_count_max
)
2156 s
->op_count_max
= n
;
2158 s
->temp_count
+= s
->nb_temps
;
2159 if (s
->nb_temps
> s
->temp_count_max
)
2160 s
->temp_count_max
= s
->nb_temps
;
2164 tcg_gen_code_common(s
, gen_code_buf
, -1);
2166 /* flush instruction cache */
2167 flush_icache_range((unsigned long)gen_code_buf
,
2168 (unsigned long)s
->code_ptr
);
2169 return s
->code_ptr
- gen_code_buf
;
2172 /* Return the index of the micro operation such as the pc after is <
2173 offset bytes from the start of the TB. The contents of gen_code_buf must
2174 not be changed, though writing the same values is ok.
2175 Return -1 if not found. */
2176 int tcg_gen_code_search_pc(TCGContext
*s
, uint8_t *gen_code_buf
, long offset
)
2178 return tcg_gen_code_common(s
, gen_code_buf
, offset
);
2181 #ifdef CONFIG_PROFILER
2182 void tcg_dump_info(FILE *f
, fprintf_function cpu_fprintf
)
2184 TCGContext
*s
= &tcg_ctx
;
2187 tot
= s
->interm_time
+ s
->code_time
;
2188 cpu_fprintf(f
, "JIT cycles %" PRId64
" (%0.3f s at 2.4 GHz)\n",
2190 cpu_fprintf(f
, "translated TBs %" PRId64
" (aborted=%" PRId64
" %0.1f%%)\n",
2192 s
->tb_count1
- s
->tb_count
,
2193 s
->tb_count1
? (double)(s
->tb_count1
- s
->tb_count
) / s
->tb_count1
* 100.0 : 0);
2194 cpu_fprintf(f
, "avg ops/TB %0.1f max=%d\n",
2195 s
->tb_count
? (double)s
->op_count
/ s
->tb_count
: 0, s
->op_count_max
);
2196 cpu_fprintf(f
, "deleted ops/TB %0.2f\n",
2198 (double)s
->del_op_count
/ s
->tb_count
: 0);
2199 cpu_fprintf(f
, "avg temps/TB %0.2f max=%d\n",
2201 (double)s
->temp_count
/ s
->tb_count
: 0,
2204 cpu_fprintf(f
, "cycles/op %0.1f\n",
2205 s
->op_count
? (double)tot
/ s
->op_count
: 0);
2206 cpu_fprintf(f
, "cycles/in byte %0.1f\n",
2207 s
->code_in_len
? (double)tot
/ s
->code_in_len
: 0);
2208 cpu_fprintf(f
, "cycles/out byte %0.1f\n",
2209 s
->code_out_len
? (double)tot
/ s
->code_out_len
: 0);
2212 cpu_fprintf(f
, " gen_interm time %0.1f%%\n",
2213 (double)s
->interm_time
/ tot
* 100.0);
2214 cpu_fprintf(f
, " gen_code time %0.1f%%\n",
2215 (double)s
->code_time
/ tot
* 100.0);
2216 cpu_fprintf(f
, "liveness/code time %0.1f%%\n",
2217 (double)s
->la_time
/ (s
->code_time
? s
->code_time
: 1) * 100.0);
2218 cpu_fprintf(f
, "cpu_restore count %" PRId64
"\n",
2220 cpu_fprintf(f
, " avg cycles %0.1f\n",
2221 s
->restore_count
? (double)s
->restore_time
/ s
->restore_count
: 0);
2226 void tcg_dump_info(FILE *f
, fprintf_function cpu_fprintf
)
2228 cpu_fprintf(f
, "[TCG profiler not compiled]\n");