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
30 #if !defined(CONFIG_DEBUG_TCG) && !defined(NDEBUG)
31 /* define it to suppress various consistency checks (faster) */
47 #include "qemu-common.h"
48 #include "cache-utils.h"
49 #include "host-utils.h"
50 #include "qemu-timer.h"
52 /* Note: the long term plan is to reduce the dependancies on the QEMU
53 CPU definitions. Currently they are used for qemu_ld/st
55 #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, 0 },
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
;
456 TCGv_i32
tcg_temp_new_internal_i32(int temp_local
)
460 idx
= tcg_temp_new_internal(TCG_TYPE_I32
, temp_local
);
461 return MAKE_TCGV_I32(idx
);
464 TCGv_i64
tcg_temp_new_internal_i64(int temp_local
)
468 idx
= tcg_temp_new_internal(TCG_TYPE_I64
, temp_local
);
469 return MAKE_TCGV_I64(idx
);
472 static inline void tcg_temp_free_internal(int idx
)
474 TCGContext
*s
= &tcg_ctx
;
478 assert(idx
>= s
->nb_globals
&& idx
< s
->nb_temps
);
480 assert(ts
->temp_allocated
!= 0);
481 ts
->temp_allocated
= 0;
485 ts
->next_free_temp
= s
->first_free_temp
[k
];
486 s
->first_free_temp
[k
] = idx
;
489 void tcg_temp_free_i32(TCGv_i32 arg
)
491 tcg_temp_free_internal(GET_TCGV_I32(arg
));
494 void tcg_temp_free_i64(TCGv_i64 arg
)
496 tcg_temp_free_internal(GET_TCGV_I64(arg
));
499 TCGv_i32
tcg_const_i32(int32_t val
)
502 t0
= tcg_temp_new_i32();
503 tcg_gen_movi_i32(t0
, val
);
507 TCGv_i64
tcg_const_i64(int64_t val
)
510 t0
= tcg_temp_new_i64();
511 tcg_gen_movi_i64(t0
, val
);
515 TCGv_i32
tcg_const_local_i32(int32_t val
)
518 t0
= tcg_temp_local_new_i32();
519 tcg_gen_movi_i32(t0
, val
);
523 TCGv_i64
tcg_const_local_i64(int64_t val
)
526 t0
= tcg_temp_local_new_i64();
527 tcg_gen_movi_i64(t0
, val
);
531 void tcg_register_helper(void *func
, const char *name
)
533 TCGContext
*s
= &tcg_ctx
;
535 if ((s
->nb_helpers
+ 1) > s
->allocated_helpers
) {
536 n
= s
->allocated_helpers
;
542 s
->helpers
= realloc(s
->helpers
, n
* sizeof(TCGHelperInfo
));
543 s
->allocated_helpers
= n
;
545 s
->helpers
[s
->nb_helpers
].func
= (tcg_target_ulong
)func
;
546 s
->helpers
[s
->nb_helpers
].name
= name
;
550 /* Note: we convert the 64 bit args to 32 bit and do some alignment
551 and endian swap. Maybe it would be better to do the alignment
552 and endian swap in tcg_reg_alloc_call(). */
553 void tcg_gen_callN(TCGContext
*s
, TCGv_ptr func
, unsigned int flags
,
554 int sizemask
, TCGArg ret
, int nargs
, TCGArg
*args
)
556 #ifdef TCG_TARGET_I386
563 *gen_opc_ptr
++ = INDEX_op_call
;
564 nparam
= gen_opparam_ptr
++;
565 #ifdef TCG_TARGET_I386
566 call_type
= (flags
& TCG_CALL_TYPE_MASK
);
568 if (ret
!= TCG_CALL_DUMMY_ARG
) {
569 #if TCG_TARGET_REG_BITS < 64
571 #ifdef TCG_TARGET_WORDS_BIGENDIAN
572 *gen_opparam_ptr
++ = ret
+ 1;
573 *gen_opparam_ptr
++ = ret
;
575 *gen_opparam_ptr
++ = ret
;
576 *gen_opparam_ptr
++ = ret
+ 1;
582 *gen_opparam_ptr
++ = ret
;
589 for (i
= 0; i
< nargs
; i
++) {
590 #if TCG_TARGET_REG_BITS < 64
591 if (sizemask
& (2 << i
)) {
592 #ifdef TCG_TARGET_I386
593 /* REGPARM case: if the third parameter is 64 bit, it is
594 allocated on the stack */
595 if (i
== 2 && call_type
== TCG_CALL_TYPE_REGPARM
) {
596 call_type
= TCG_CALL_TYPE_REGPARM_2
;
597 flags
= (flags
& ~TCG_CALL_TYPE_MASK
) | call_type
;
600 #ifdef TCG_TARGET_CALL_ALIGN_ARGS
601 /* some targets want aligned 64 bit args */
603 *gen_opparam_ptr
++ = TCG_CALL_DUMMY_ARG
;
607 /* If stack grows up, then we will be placing successive
608 arguments at lower addresses, which means we need to
609 reverse the order compared to how we would normally
610 treat either big or little-endian. For those arguments
611 that will wind up in registers, this still works for
612 HPPA (the only current STACK_GROWSUP target) since the
613 argument registers are *also* allocated in decreasing
614 order. If another such target is added, this logic may
615 have to get more complicated to differentiate between
616 stack arguments and register arguments. */
617 #if defined(TCG_TARGET_WORDS_BIGENDIAN) != defined(TCG_TARGET_STACK_GROWSUP)
618 *gen_opparam_ptr
++ = args
[i
] + 1;
619 *gen_opparam_ptr
++ = args
[i
];
621 *gen_opparam_ptr
++ = args
[i
];
622 *gen_opparam_ptr
++ = args
[i
] + 1;
628 *gen_opparam_ptr
++ = args
[i
];
632 *gen_opparam_ptr
++ = GET_TCGV_PTR(func
);
634 *gen_opparam_ptr
++ = flags
;
636 *nparam
= (nb_rets
<< 16) | (real_args
+ 1);
638 /* total parameters, needed to go backward in the instruction stream */
639 *gen_opparam_ptr
++ = 1 + nb_rets
+ real_args
+ 3;
642 #if TCG_TARGET_REG_BITS == 32
643 void tcg_gen_shifti_i64(TCGv_i64 ret
, TCGv_i64 arg1
,
644 int c
, int right
, int arith
)
647 tcg_gen_mov_i32(TCGV_LOW(ret
), TCGV_LOW(arg1
));
648 tcg_gen_mov_i32(TCGV_HIGH(ret
), TCGV_HIGH(arg1
));
649 } else if (c
>= 32) {
653 tcg_gen_sari_i32(TCGV_LOW(ret
), TCGV_HIGH(arg1
), c
);
654 tcg_gen_sari_i32(TCGV_HIGH(ret
), TCGV_HIGH(arg1
), 31);
656 tcg_gen_shri_i32(TCGV_LOW(ret
), TCGV_HIGH(arg1
), c
);
657 tcg_gen_movi_i32(TCGV_HIGH(ret
), 0);
660 tcg_gen_shli_i32(TCGV_HIGH(ret
), TCGV_LOW(arg1
), c
);
661 tcg_gen_movi_i32(TCGV_LOW(ret
), 0);
666 t0
= tcg_temp_new_i32();
667 t1
= tcg_temp_new_i32();
669 tcg_gen_shli_i32(t0
, TCGV_HIGH(arg1
), 32 - c
);
671 tcg_gen_sari_i32(t1
, TCGV_HIGH(arg1
), c
);
673 tcg_gen_shri_i32(t1
, TCGV_HIGH(arg1
), c
);
674 tcg_gen_shri_i32(TCGV_LOW(ret
), TCGV_LOW(arg1
), c
);
675 tcg_gen_or_i32(TCGV_LOW(ret
), TCGV_LOW(ret
), t0
);
676 tcg_gen_mov_i32(TCGV_HIGH(ret
), t1
);
678 tcg_gen_shri_i32(t0
, TCGV_LOW(arg1
), 32 - c
);
679 /* Note: ret can be the same as arg1, so we use t1 */
680 tcg_gen_shli_i32(t1
, TCGV_LOW(arg1
), c
);
681 tcg_gen_shli_i32(TCGV_HIGH(ret
), TCGV_HIGH(arg1
), c
);
682 tcg_gen_or_i32(TCGV_HIGH(ret
), TCGV_HIGH(ret
), t0
);
683 tcg_gen_mov_i32(TCGV_LOW(ret
), t1
);
685 tcg_temp_free_i32(t0
);
686 tcg_temp_free_i32(t1
);
692 static void tcg_reg_alloc_start(TCGContext
*s
)
696 for(i
= 0; i
< s
->nb_globals
; i
++) {
699 ts
->val_type
= TEMP_VAL_REG
;
701 ts
->val_type
= TEMP_VAL_MEM
;
704 for(i
= s
->nb_globals
; i
< s
->nb_temps
; i
++) {
706 ts
->val_type
= TEMP_VAL_DEAD
;
707 ts
->mem_allocated
= 0;
710 for(i
= 0; i
< TCG_TARGET_NB_REGS
; i
++) {
711 s
->reg_to_temp
[i
] = -1;
715 static char *tcg_get_arg_str_idx(TCGContext
*s
, char *buf
, int buf_size
,
721 if (idx
< s
->nb_globals
) {
722 pstrcpy(buf
, buf_size
, ts
->name
);
725 snprintf(buf
, buf_size
, "loc%d", idx
- s
->nb_globals
);
727 snprintf(buf
, buf_size
, "tmp%d", idx
- s
->nb_globals
);
732 char *tcg_get_arg_str_i32(TCGContext
*s
, char *buf
, int buf_size
, TCGv_i32 arg
)
734 return tcg_get_arg_str_idx(s
, buf
, buf_size
, GET_TCGV_I32(arg
));
737 char *tcg_get_arg_str_i64(TCGContext
*s
, char *buf
, int buf_size
, TCGv_i64 arg
)
739 return tcg_get_arg_str_idx(s
, buf
, buf_size
, GET_TCGV_I64(arg
));
742 static int helper_cmp(const void *p1
, const void *p2
)
744 const TCGHelperInfo
*th1
= p1
;
745 const TCGHelperInfo
*th2
= p2
;
746 if (th1
->func
< th2
->func
)
748 else if (th1
->func
== th2
->func
)
754 /* find helper definition (Note: A hash table would be better) */
755 static TCGHelperInfo
*tcg_find_helper(TCGContext
*s
, tcg_target_ulong val
)
761 if (unlikely(!s
->helpers_sorted
)) {
762 qsort(s
->helpers
, s
->nb_helpers
, sizeof(TCGHelperInfo
),
764 s
->helpers_sorted
= 1;
769 m_max
= s
->nb_helpers
- 1;
770 while (m_min
<= m_max
) {
771 m
= (m_min
+ m_max
) >> 1;
785 static const char * const cond_name
[] =
787 [TCG_COND_EQ
] = "eq",
788 [TCG_COND_NE
] = "ne",
789 [TCG_COND_LT
] = "lt",
790 [TCG_COND_GE
] = "ge",
791 [TCG_COND_LE
] = "le",
792 [TCG_COND_GT
] = "gt",
793 [TCG_COND_LTU
] = "ltu",
794 [TCG_COND_GEU
] = "geu",
795 [TCG_COND_LEU
] = "leu",
796 [TCG_COND_GTU
] = "gtu"
799 void tcg_dump_ops(TCGContext
*s
, FILE *outfile
)
801 const uint16_t *opc_ptr
;
805 int i
, k
, nb_oargs
, nb_iargs
, nb_cargs
, first_insn
;
810 opc_ptr
= gen_opc_buf
;
811 args
= gen_opparam_buf
;
812 while (opc_ptr
< gen_opc_ptr
) {
814 def
= &tcg_op_defs
[c
];
815 if (c
== INDEX_op_debug_insn_start
) {
817 #if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
818 pc
= ((uint64_t)args
[1] << 32) | args
[0];
823 fprintf(outfile
, "\n");
824 fprintf(outfile
, " ---- 0x%" PRIx64
, pc
);
826 nb_oargs
= def
->nb_oargs
;
827 nb_iargs
= def
->nb_iargs
;
828 nb_cargs
= def
->nb_cargs
;
829 } else if (c
== INDEX_op_call
) {
832 /* variable number of arguments */
834 nb_oargs
= arg
>> 16;
835 nb_iargs
= arg
& 0xffff;
836 nb_cargs
= def
->nb_cargs
;
838 fprintf(outfile
, " %s ", def
->name
);
841 fprintf(outfile
, "%s",
842 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), args
[nb_oargs
+ nb_iargs
- 1]));
844 fprintf(outfile
, ",$0x%" TCG_PRIlx
,
845 args
[nb_oargs
+ nb_iargs
]);
847 fprintf(outfile
, ",$%d", nb_oargs
);
848 for(i
= 0; i
< nb_oargs
; i
++) {
849 fprintf(outfile
, ",");
850 fprintf(outfile
, "%s",
851 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), args
[i
]));
853 for(i
= 0; i
< (nb_iargs
- 1); i
++) {
854 fprintf(outfile
, ",");
855 if (args
[nb_oargs
+ i
] == TCG_CALL_DUMMY_ARG
) {
856 fprintf(outfile
, "<dummy>");
858 fprintf(outfile
, "%s",
859 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), args
[nb_oargs
+ i
]));
862 } else if (c
== INDEX_op_movi_i32
863 #if TCG_TARGET_REG_BITS == 64
864 || c
== INDEX_op_movi_i64
867 tcg_target_ulong val
;
870 nb_oargs
= def
->nb_oargs
;
871 nb_iargs
= def
->nb_iargs
;
872 nb_cargs
= def
->nb_cargs
;
873 fprintf(outfile
, " %s %s,$", def
->name
,
874 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), args
[0]));
876 th
= tcg_find_helper(s
, val
);
878 fprintf(outfile
, "%s", th
->name
);
880 if (c
== INDEX_op_movi_i32
)
881 fprintf(outfile
, "0x%x", (uint32_t)val
);
883 fprintf(outfile
, "0x%" PRIx64
, (uint64_t)val
);
886 fprintf(outfile
, " %s ", def
->name
);
887 if (c
== INDEX_op_nopn
) {
888 /* variable number of arguments */
893 nb_oargs
= def
->nb_oargs
;
894 nb_iargs
= def
->nb_iargs
;
895 nb_cargs
= def
->nb_cargs
;
899 for(i
= 0; i
< nb_oargs
; i
++) {
901 fprintf(outfile
, ",");
902 fprintf(outfile
, "%s",
903 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), args
[k
++]));
905 for(i
= 0; i
< nb_iargs
; i
++) {
907 fprintf(outfile
, ",");
908 fprintf(outfile
, "%s",
909 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), args
[k
++]));
912 case INDEX_op_brcond_i32
:
913 #if TCG_TARGET_REG_BITS == 32
914 case INDEX_op_brcond2_i32
:
915 #elif TCG_TARGET_REG_BITS == 64
916 case INDEX_op_brcond_i64
:
918 case INDEX_op_setcond_i32
:
919 #if TCG_TARGET_REG_BITS == 32
920 case INDEX_op_setcond2_i32
:
921 #elif TCG_TARGET_REG_BITS == 64
922 case INDEX_op_setcond_i64
:
924 if (args
[k
] < ARRAY_SIZE(cond_name
) && cond_name
[args
[k
]])
925 fprintf(outfile
, ",%s", cond_name
[args
[k
++]]);
927 fprintf(outfile
, ",$0x%" TCG_PRIlx
, args
[k
++]);
934 for(; i
< nb_cargs
; i
++) {
936 fprintf(outfile
, ",");
938 fprintf(outfile
, "$0x%" TCG_PRIlx
, arg
);
941 fprintf(outfile
, "\n");
942 args
+= nb_iargs
+ nb_oargs
+ nb_cargs
;
946 /* we give more priority to constraints with less registers */
947 static int get_constraint_priority(const TCGOpDef
*def
, int k
)
949 const TCGArgConstraint
*arg_ct
;
952 arg_ct
= &def
->args_ct
[k
];
953 if (arg_ct
->ct
& TCG_CT_ALIAS
) {
954 /* an alias is equivalent to a single register */
957 if (!(arg_ct
->ct
& TCG_CT_REG
))
960 for(i
= 0; i
< TCG_TARGET_NB_REGS
; i
++) {
961 if (tcg_regset_test_reg(arg_ct
->u
.regs
, i
))
965 return TCG_TARGET_NB_REGS
- n
+ 1;
968 /* sort from highest priority to lowest */
969 static void sort_constraints(TCGOpDef
*def
, int start
, int n
)
971 int i
, j
, p1
, p2
, tmp
;
973 for(i
= 0; i
< n
; i
++)
974 def
->sorted_args
[start
+ i
] = start
+ i
;
977 for(i
= 0; i
< n
- 1; i
++) {
978 for(j
= i
+ 1; j
< n
; j
++) {
979 p1
= get_constraint_priority(def
, def
->sorted_args
[start
+ i
]);
980 p2
= get_constraint_priority(def
, def
->sorted_args
[start
+ j
]);
982 tmp
= def
->sorted_args
[start
+ i
];
983 def
->sorted_args
[start
+ i
] = def
->sorted_args
[start
+ j
];
984 def
->sorted_args
[start
+ j
] = tmp
;
990 void tcg_add_target_add_op_defs(const TCGTargetOpDef
*tdefs
)
998 if (tdefs
->op
== (TCGOpcode
)-1)
1001 assert(op
>= 0 && op
< NB_OPS
);
1002 def
= &tcg_op_defs
[op
];
1003 #if defined(CONFIG_DEBUG_TCG)
1004 /* Duplicate entry in op definitions? */
1008 nb_args
= def
->nb_iargs
+ def
->nb_oargs
;
1009 for(i
= 0; i
< nb_args
; i
++) {
1010 ct_str
= tdefs
->args_ct_str
[i
];
1011 /* Incomplete TCGTargetOpDef entry? */
1012 assert(ct_str
!= NULL
);
1013 tcg_regset_clear(def
->args_ct
[i
].u
.regs
);
1014 def
->args_ct
[i
].ct
= 0;
1015 if (ct_str
[0] >= '0' && ct_str
[0] <= '9') {
1017 oarg
= ct_str
[0] - '0';
1018 assert(oarg
< def
->nb_oargs
);
1019 assert(def
->args_ct
[oarg
].ct
& TCG_CT_REG
);
1020 /* TCG_CT_ALIAS is for the output arguments. The input
1021 argument is tagged with TCG_CT_IALIAS. */
1022 def
->args_ct
[i
] = def
->args_ct
[oarg
];
1023 def
->args_ct
[oarg
].ct
= TCG_CT_ALIAS
;
1024 def
->args_ct
[oarg
].alias_index
= i
;
1025 def
->args_ct
[i
].ct
|= TCG_CT_IALIAS
;
1026 def
->args_ct
[i
].alias_index
= oarg
;
1029 if (*ct_str
== '\0')
1033 def
->args_ct
[i
].ct
|= TCG_CT_CONST
;
1037 if (target_parse_constraint(&def
->args_ct
[i
], &ct_str
) < 0) {
1038 fprintf(stderr
, "Invalid constraint '%s' for arg %d of operation '%s'\n",
1039 ct_str
, i
, def
->name
);
1047 /* TCGTargetOpDef entry with too much information? */
1048 assert(i
== TCG_MAX_OP_ARGS
|| tdefs
->args_ct_str
[i
] == NULL
);
1050 /* sort the constraints (XXX: this is just an heuristic) */
1051 sort_constraints(def
, 0, def
->nb_oargs
);
1052 sort_constraints(def
, def
->nb_oargs
, def
->nb_iargs
);
1058 printf("%s: sorted=", def
->name
);
1059 for(i
= 0; i
< def
->nb_oargs
+ def
->nb_iargs
; i
++)
1060 printf(" %d", def
->sorted_args
[i
]);
1067 #if defined(CONFIG_DEBUG_TCG)
1069 for (op
= 0; op
< ARRAY_SIZE(tcg_op_defs
); op
++) {
1070 if (op
< INDEX_op_call
|| op
== INDEX_op_debug_insn_start
) {
1071 /* Wrong entry in op definitions? */
1072 if (tcg_op_defs
[op
].used
) {
1073 fprintf(stderr
, "Invalid op definition for %s\n",
1074 tcg_op_defs
[op
].name
);
1078 /* Missing entry in op definitions? */
1079 if (!tcg_op_defs
[op
].used
) {
1080 fprintf(stderr
, "Missing op definition for %s\n",
1081 tcg_op_defs
[op
].name
);
1092 #ifdef USE_LIVENESS_ANALYSIS
1094 /* set a nop for an operation using 'nb_args' */
1095 static inline void tcg_set_nop(TCGContext
*s
, uint16_t *opc_ptr
,
1096 TCGArg
*args
, int nb_args
)
1099 *opc_ptr
= INDEX_op_nop
;
1101 *opc_ptr
= INDEX_op_nopn
;
1103 args
[nb_args
- 1] = nb_args
;
1107 /* liveness analysis: end of function: globals are live, temps are
1109 /* XXX: at this stage, not used as there would be little gains because
1110 most TBs end with a conditional jump. */
1111 static inline void tcg_la_func_end(TCGContext
*s
, uint8_t *dead_temps
)
1113 memset(dead_temps
, 0, s
->nb_globals
);
1114 memset(dead_temps
+ s
->nb_globals
, 1, s
->nb_temps
- s
->nb_globals
);
1117 /* liveness analysis: end of basic block: globals are live, temps are
1118 dead, local temps are live. */
1119 static inline void tcg_la_bb_end(TCGContext
*s
, uint8_t *dead_temps
)
1124 memset(dead_temps
, 0, s
->nb_globals
);
1125 ts
= &s
->temps
[s
->nb_globals
];
1126 for(i
= s
->nb_globals
; i
< s
->nb_temps
; i
++) {
1135 /* Liveness analysis : update the opc_dead_iargs array to tell if a
1136 given input arguments is dead. Instructions updating dead
1137 temporaries are removed. */
1138 static void tcg_liveness_analysis(TCGContext
*s
)
1140 int i
, op_index
, nb_args
, nb_iargs
, nb_oargs
, arg
, nb_ops
;
1143 const TCGOpDef
*def
;
1144 uint8_t *dead_temps
;
1145 unsigned int dead_iargs
;
1147 gen_opc_ptr
++; /* skip end */
1149 nb_ops
= gen_opc_ptr
- gen_opc_buf
;
1151 s
->op_dead_iargs
= tcg_malloc(nb_ops
* sizeof(uint16_t));
1153 dead_temps
= tcg_malloc(s
->nb_temps
);
1154 memset(dead_temps
, 1, s
->nb_temps
);
1156 args
= gen_opparam_ptr
;
1157 op_index
= nb_ops
- 1;
1158 while (op_index
>= 0) {
1159 op
= gen_opc_buf
[op_index
];
1160 def
= &tcg_op_defs
[op
];
1168 nb_iargs
= args
[0] & 0xffff;
1169 nb_oargs
= args
[0] >> 16;
1171 call_flags
= args
[nb_oargs
+ nb_iargs
];
1173 /* pure functions can be removed if their result is not
1175 if (call_flags
& TCG_CALL_PURE
) {
1176 for(i
= 0; i
< nb_oargs
; i
++) {
1178 if (!dead_temps
[arg
])
1179 goto do_not_remove_call
;
1181 tcg_set_nop(s
, gen_opc_buf
+ op_index
,
1186 /* output args are dead */
1187 for(i
= 0; i
< nb_oargs
; i
++) {
1189 dead_temps
[arg
] = 1;
1192 if (!(call_flags
& TCG_CALL_CONST
)) {
1193 /* globals are live (they may be used by the call) */
1194 memset(dead_temps
, 0, s
->nb_globals
);
1197 /* input args are live */
1199 for(i
= 0; i
< nb_iargs
; i
++) {
1200 arg
= args
[i
+ nb_oargs
];
1201 if (arg
!= TCG_CALL_DUMMY_ARG
) {
1202 if (dead_temps
[arg
]) {
1203 dead_iargs
|= (1 << i
);
1205 dead_temps
[arg
] = 0;
1208 s
->op_dead_iargs
[op_index
] = dead_iargs
;
1213 case INDEX_op_set_label
:
1215 /* mark end of basic block */
1216 tcg_la_bb_end(s
, dead_temps
);
1218 case INDEX_op_debug_insn_start
:
1219 args
-= def
->nb_args
;
1225 case INDEX_op_discard
:
1227 /* mark the temporary as dead */
1228 dead_temps
[args
[0]] = 1;
1232 /* XXX: optimize by hardcoding common cases (e.g. triadic ops) */
1234 args
-= def
->nb_args
;
1235 nb_iargs
= def
->nb_iargs
;
1236 nb_oargs
= def
->nb_oargs
;
1238 /* Test if the operation can be removed because all
1239 its outputs are dead. We assume that nb_oargs == 0
1240 implies side effects */
1241 if (!(def
->flags
& TCG_OPF_SIDE_EFFECTS
) && nb_oargs
!= 0) {
1242 for(i
= 0; i
< nb_oargs
; i
++) {
1244 if (!dead_temps
[arg
])
1247 tcg_set_nop(s
, gen_opc_buf
+ op_index
, args
, def
->nb_args
);
1248 #ifdef CONFIG_PROFILER
1254 /* output args are dead */
1255 for(i
= 0; i
< nb_oargs
; i
++) {
1257 dead_temps
[arg
] = 1;
1260 /* if end of basic block, update */
1261 if (def
->flags
& TCG_OPF_BB_END
) {
1262 tcg_la_bb_end(s
, dead_temps
);
1263 } else if (def
->flags
& TCG_OPF_CALL_CLOBBER
) {
1264 /* globals are live */
1265 memset(dead_temps
, 0, s
->nb_globals
);
1268 /* input args are live */
1270 for(i
= 0; i
< nb_iargs
; i
++) {
1271 arg
= args
[i
+ nb_oargs
];
1272 if (dead_temps
[arg
]) {
1273 dead_iargs
|= (1 << i
);
1275 dead_temps
[arg
] = 0;
1277 s
->op_dead_iargs
[op_index
] = dead_iargs
;
1284 if (args
!= gen_opparam_buf
)
1288 /* dummy liveness analysis */
1289 static void tcg_liveness_analysis(TCGContext
*s
)
1292 nb_ops
= gen_opc_ptr
- gen_opc_buf
;
1294 s
->op_dead_iargs
= tcg_malloc(nb_ops
* sizeof(uint16_t));
1295 memset(s
->op_dead_iargs
, 0, nb_ops
* sizeof(uint16_t));
1300 static void dump_regs(TCGContext
*s
)
1306 for(i
= 0; i
< s
->nb_temps
; i
++) {
1308 printf(" %10s: ", tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), i
));
1309 switch(ts
->val_type
) {
1311 printf("%s", tcg_target_reg_names
[ts
->reg
]);
1314 printf("%d(%s)", (int)ts
->mem_offset
, tcg_target_reg_names
[ts
->mem_reg
]);
1316 case TEMP_VAL_CONST
:
1317 printf("$0x%" TCG_PRIlx
, ts
->val
);
1329 for(i
= 0; i
< TCG_TARGET_NB_REGS
; i
++) {
1330 if (s
->reg_to_temp
[i
] >= 0) {
1332 tcg_target_reg_names
[i
],
1333 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), s
->reg_to_temp
[i
]));
1338 static void check_regs(TCGContext
*s
)
1344 for(reg
= 0; reg
< TCG_TARGET_NB_REGS
; reg
++) {
1345 k
= s
->reg_to_temp
[reg
];
1348 if (ts
->val_type
!= TEMP_VAL_REG
||
1350 printf("Inconsistency for register %s:\n",
1351 tcg_target_reg_names
[reg
]);
1356 for(k
= 0; k
< s
->nb_temps
; k
++) {
1358 if (ts
->val_type
== TEMP_VAL_REG
&&
1360 s
->reg_to_temp
[ts
->reg
] != k
) {
1361 printf("Inconsistency for temp %s:\n",
1362 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), k
));
1364 printf("reg state:\n");
1372 static void temp_allocate_frame(TCGContext
*s
, int temp
)
1375 ts
= &s
->temps
[temp
];
1376 s
->current_frame_offset
= (s
->current_frame_offset
+ sizeof(tcg_target_long
) - 1) & ~(sizeof(tcg_target_long
) - 1);
1377 if (s
->current_frame_offset
+ sizeof(tcg_target_long
) > s
->frame_end
)
1379 ts
->mem_offset
= s
->current_frame_offset
;
1380 ts
->mem_reg
= s
->frame_reg
;
1381 ts
->mem_allocated
= 1;
1382 s
->current_frame_offset
+= sizeof(tcg_target_long
);
1385 /* free register 'reg' by spilling the corresponding temporary if necessary */
1386 static void tcg_reg_free(TCGContext
*s
, int reg
)
1391 temp
= s
->reg_to_temp
[reg
];
1393 ts
= &s
->temps
[temp
];
1394 assert(ts
->val_type
== TEMP_VAL_REG
);
1395 if (!ts
->mem_coherent
) {
1396 if (!ts
->mem_allocated
)
1397 temp_allocate_frame(s
, temp
);
1398 tcg_out_st(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
1400 ts
->val_type
= TEMP_VAL_MEM
;
1401 s
->reg_to_temp
[reg
] = -1;
1405 /* Allocate a register belonging to reg1 & ~reg2 */
1406 static int tcg_reg_alloc(TCGContext
*s
, TCGRegSet reg1
, TCGRegSet reg2
)
1411 tcg_regset_andnot(reg_ct
, reg1
, reg2
);
1413 /* first try free registers */
1414 for(i
= 0; i
< ARRAY_SIZE(tcg_target_reg_alloc_order
); i
++) {
1415 reg
= tcg_target_reg_alloc_order
[i
];
1416 if (tcg_regset_test_reg(reg_ct
, reg
) && s
->reg_to_temp
[reg
] == -1)
1420 /* XXX: do better spill choice */
1421 for(i
= 0; i
< ARRAY_SIZE(tcg_target_reg_alloc_order
); i
++) {
1422 reg
= tcg_target_reg_alloc_order
[i
];
1423 if (tcg_regset_test_reg(reg_ct
, reg
)) {
1424 tcg_reg_free(s
, reg
);
1432 /* save a temporary to memory. 'allocated_regs' is used in case a
1433 temporary registers needs to be allocated to store a constant. */
1434 static void temp_save(TCGContext
*s
, int temp
, TCGRegSet allocated_regs
)
1439 ts
= &s
->temps
[temp
];
1440 if (!ts
->fixed_reg
) {
1441 switch(ts
->val_type
) {
1443 tcg_reg_free(s
, ts
->reg
);
1446 ts
->val_type
= TEMP_VAL_MEM
;
1448 case TEMP_VAL_CONST
:
1449 reg
= tcg_reg_alloc(s
, tcg_target_available_regs
[ts
->type
],
1451 if (!ts
->mem_allocated
)
1452 temp_allocate_frame(s
, temp
);
1453 tcg_out_movi(s
, ts
->type
, reg
, ts
->val
);
1454 tcg_out_st(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
1455 ts
->val_type
= TEMP_VAL_MEM
;
1465 /* save globals to their cannonical location and assume they can be
1466 modified be the following code. 'allocated_regs' is used in case a
1467 temporary registers needs to be allocated to store a constant. */
1468 static void save_globals(TCGContext
*s
, TCGRegSet allocated_regs
)
1472 for(i
= 0; i
< s
->nb_globals
; i
++) {
1473 temp_save(s
, i
, allocated_regs
);
1477 /* at the end of a basic block, we assume all temporaries are dead and
1478 all globals are stored at their canonical location. */
1479 static void tcg_reg_alloc_bb_end(TCGContext
*s
, TCGRegSet allocated_regs
)
1484 for(i
= s
->nb_globals
; i
< s
->nb_temps
; i
++) {
1486 if (ts
->temp_local
) {
1487 temp_save(s
, i
, allocated_regs
);
1489 if (ts
->val_type
== TEMP_VAL_REG
) {
1490 s
->reg_to_temp
[ts
->reg
] = -1;
1492 ts
->val_type
= TEMP_VAL_DEAD
;
1496 save_globals(s
, allocated_regs
);
1499 #define IS_DEAD_IARG(n) ((dead_iargs >> (n)) & 1)
1501 static void tcg_reg_alloc_movi(TCGContext
*s
, const TCGArg
*args
)
1504 tcg_target_ulong val
;
1506 ots
= &s
->temps
[args
[0]];
1509 if (ots
->fixed_reg
) {
1510 /* for fixed registers, we do not do any constant
1512 tcg_out_movi(s
, ots
->type
, ots
->reg
, val
);
1514 /* The movi is not explicitly generated here */
1515 if (ots
->val_type
== TEMP_VAL_REG
)
1516 s
->reg_to_temp
[ots
->reg
] = -1;
1517 ots
->val_type
= TEMP_VAL_CONST
;
1522 static void tcg_reg_alloc_mov(TCGContext
*s
, const TCGOpDef
*def
,
1524 unsigned int dead_iargs
)
1528 const TCGArgConstraint
*arg_ct
;
1530 ots
= &s
->temps
[args
[0]];
1531 ts
= &s
->temps
[args
[1]];
1532 arg_ct
= &def
->args_ct
[0];
1534 /* XXX: always mark arg dead if IS_DEAD_IARG(0) */
1535 if (ts
->val_type
== TEMP_VAL_REG
) {
1536 if (IS_DEAD_IARG(0) && !ts
->fixed_reg
&& !ots
->fixed_reg
) {
1537 /* the mov can be suppressed */
1538 if (ots
->val_type
== TEMP_VAL_REG
)
1539 s
->reg_to_temp
[ots
->reg
] = -1;
1541 s
->reg_to_temp
[reg
] = -1;
1542 ts
->val_type
= TEMP_VAL_DEAD
;
1544 if (ots
->val_type
== TEMP_VAL_REG
) {
1547 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, s
->reserved_regs
);
1549 if (ts
->reg
!= reg
) {
1550 tcg_out_mov(s
, ots
->type
, reg
, ts
->reg
);
1553 } else if (ts
->val_type
== TEMP_VAL_MEM
) {
1554 if (ots
->val_type
== TEMP_VAL_REG
) {
1557 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, s
->reserved_regs
);
1559 tcg_out_ld(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
1560 } else if (ts
->val_type
== TEMP_VAL_CONST
) {
1561 if (ots
->fixed_reg
) {
1563 tcg_out_movi(s
, ots
->type
, reg
, ts
->val
);
1565 /* propagate constant */
1566 if (ots
->val_type
== TEMP_VAL_REG
)
1567 s
->reg_to_temp
[ots
->reg
] = -1;
1568 ots
->val_type
= TEMP_VAL_CONST
;
1575 s
->reg_to_temp
[reg
] = args
[0];
1577 ots
->val_type
= TEMP_VAL_REG
;
1578 ots
->mem_coherent
= 0;
1581 static void tcg_reg_alloc_op(TCGContext
*s
,
1582 const TCGOpDef
*def
, TCGOpcode opc
,
1584 unsigned int dead_iargs
)
1586 TCGRegSet allocated_regs
;
1587 int i
, k
, nb_iargs
, nb_oargs
, reg
;
1589 const TCGArgConstraint
*arg_ct
;
1591 TCGArg new_args
[TCG_MAX_OP_ARGS
];
1592 int const_args
[TCG_MAX_OP_ARGS
];
1594 nb_oargs
= def
->nb_oargs
;
1595 nb_iargs
= def
->nb_iargs
;
1597 /* copy constants */
1598 memcpy(new_args
+ nb_oargs
+ nb_iargs
,
1599 args
+ nb_oargs
+ nb_iargs
,
1600 sizeof(TCGArg
) * def
->nb_cargs
);
1602 /* satisfy input constraints */
1603 tcg_regset_set(allocated_regs
, s
->reserved_regs
);
1604 for(k
= 0; k
< nb_iargs
; k
++) {
1605 i
= def
->sorted_args
[nb_oargs
+ k
];
1607 arg_ct
= &def
->args_ct
[i
];
1608 ts
= &s
->temps
[arg
];
1609 if (ts
->val_type
== TEMP_VAL_MEM
) {
1610 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1611 tcg_out_ld(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
1612 ts
->val_type
= TEMP_VAL_REG
;
1614 ts
->mem_coherent
= 1;
1615 s
->reg_to_temp
[reg
] = arg
;
1616 } else if (ts
->val_type
== TEMP_VAL_CONST
) {
1617 if (tcg_target_const_match(ts
->val
, arg_ct
)) {
1618 /* constant is OK for instruction */
1620 new_args
[i
] = ts
->val
;
1623 /* need to move to a register */
1624 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1625 tcg_out_movi(s
, ts
->type
, reg
, ts
->val
);
1626 ts
->val_type
= TEMP_VAL_REG
;
1628 ts
->mem_coherent
= 0;
1629 s
->reg_to_temp
[reg
] = arg
;
1632 assert(ts
->val_type
== TEMP_VAL_REG
);
1633 if (arg_ct
->ct
& TCG_CT_IALIAS
) {
1634 if (ts
->fixed_reg
) {
1635 /* if fixed register, we must allocate a new register
1636 if the alias is not the same register */
1637 if (arg
!= args
[arg_ct
->alias_index
])
1638 goto allocate_in_reg
;
1640 /* if the input is aliased to an output and if it is
1641 not dead after the instruction, we must allocate
1642 a new register and move it */
1643 if (!IS_DEAD_IARG(i
- nb_oargs
))
1644 goto allocate_in_reg
;
1648 if (tcg_regset_test_reg(arg_ct
->u
.regs
, reg
)) {
1649 /* nothing to do : the constraint is satisfied */
1652 /* allocate a new register matching the constraint
1653 and move the temporary register into it */
1654 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1655 tcg_out_mov(s
, ts
->type
, reg
, ts
->reg
);
1659 tcg_regset_set_reg(allocated_regs
, reg
);
1663 if (def
->flags
& TCG_OPF_BB_END
) {
1664 tcg_reg_alloc_bb_end(s
, allocated_regs
);
1666 /* mark dead temporaries and free the associated registers */
1667 for(i
= 0; i
< nb_iargs
; i
++) {
1668 arg
= args
[nb_oargs
+ i
];
1669 if (IS_DEAD_IARG(i
)) {
1670 ts
= &s
->temps
[arg
];
1671 if (!ts
->fixed_reg
) {
1672 if (ts
->val_type
== TEMP_VAL_REG
)
1673 s
->reg_to_temp
[ts
->reg
] = -1;
1674 ts
->val_type
= TEMP_VAL_DEAD
;
1679 if (def
->flags
& TCG_OPF_CALL_CLOBBER
) {
1680 /* XXX: permit generic clobber register list ? */
1681 for(reg
= 0; reg
< TCG_TARGET_NB_REGS
; reg
++) {
1682 if (tcg_regset_test_reg(tcg_target_call_clobber_regs
, reg
)) {
1683 tcg_reg_free(s
, reg
);
1686 /* XXX: for load/store we could do that only for the slow path
1687 (i.e. when a memory callback is called) */
1689 /* store globals and free associated registers (we assume the insn
1690 can modify any global. */
1691 save_globals(s
, allocated_regs
);
1694 /* satisfy the output constraints */
1695 tcg_regset_set(allocated_regs
, s
->reserved_regs
);
1696 for(k
= 0; k
< nb_oargs
; k
++) {
1697 i
= def
->sorted_args
[k
];
1699 arg_ct
= &def
->args_ct
[i
];
1700 ts
= &s
->temps
[arg
];
1701 if (arg_ct
->ct
& TCG_CT_ALIAS
) {
1702 reg
= new_args
[arg_ct
->alias_index
];
1704 /* if fixed register, we try to use it */
1706 if (ts
->fixed_reg
&&
1707 tcg_regset_test_reg(arg_ct
->u
.regs
, reg
)) {
1710 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1712 tcg_regset_set_reg(allocated_regs
, reg
);
1713 /* if a fixed register is used, then a move will be done afterwards */
1714 if (!ts
->fixed_reg
) {
1715 if (ts
->val_type
== TEMP_VAL_REG
)
1716 s
->reg_to_temp
[ts
->reg
] = -1;
1717 ts
->val_type
= TEMP_VAL_REG
;
1719 /* temp value is modified, so the value kept in memory is
1720 potentially not the same */
1721 ts
->mem_coherent
= 0;
1722 s
->reg_to_temp
[reg
] = arg
;
1729 /* emit instruction */
1730 tcg_out_op(s
, opc
, new_args
, const_args
);
1732 /* move the outputs in the correct register if needed */
1733 for(i
= 0; i
< nb_oargs
; i
++) {
1734 ts
= &s
->temps
[args
[i
]];
1736 if (ts
->fixed_reg
&& ts
->reg
!= reg
) {
1737 tcg_out_mov(s
, ts
->type
, ts
->reg
, reg
);
1742 #ifdef TCG_TARGET_STACK_GROWSUP
1743 #define STACK_DIR(x) (-(x))
1745 #define STACK_DIR(x) (x)
1748 static int tcg_reg_alloc_call(TCGContext
*s
, const TCGOpDef
*def
,
1749 TCGOpcode opc
, const TCGArg
*args
,
1750 unsigned int dead_iargs
)
1752 int nb_iargs
, nb_oargs
, flags
, nb_regs
, i
, reg
, nb_params
;
1753 TCGArg arg
, func_arg
;
1755 tcg_target_long stack_offset
, call_stack_size
, func_addr
;
1756 int const_func_arg
, allocate_args
;
1757 TCGRegSet allocated_regs
;
1758 const TCGArgConstraint
*arg_ct
;
1762 nb_oargs
= arg
>> 16;
1763 nb_iargs
= arg
& 0xffff;
1764 nb_params
= nb_iargs
- 1;
1766 flags
= args
[nb_oargs
+ nb_iargs
];
1768 nb_regs
= tcg_target_get_call_iarg_regs_count(flags
);
1769 if (nb_regs
> nb_params
)
1770 nb_regs
= nb_params
;
1772 /* assign stack slots first */
1773 /* XXX: preallocate call stack */
1774 call_stack_size
= (nb_params
- nb_regs
) * sizeof(tcg_target_long
);
1775 call_stack_size
= (call_stack_size
+ TCG_TARGET_STACK_ALIGN
- 1) &
1776 ~(TCG_TARGET_STACK_ALIGN
- 1);
1777 allocate_args
= (call_stack_size
> TCG_STATIC_CALL_ARGS_SIZE
);
1778 if (allocate_args
) {
1779 tcg_out_addi(s
, TCG_REG_CALL_STACK
, -STACK_DIR(call_stack_size
));
1782 stack_offset
= TCG_TARGET_CALL_STACK_OFFSET
;
1783 for(i
= nb_regs
; i
< nb_params
; i
++) {
1784 arg
= args
[nb_oargs
+ i
];
1785 #ifdef TCG_TARGET_STACK_GROWSUP
1786 stack_offset
-= sizeof(tcg_target_long
);
1788 if (arg
!= TCG_CALL_DUMMY_ARG
) {
1789 ts
= &s
->temps
[arg
];
1790 if (ts
->val_type
== TEMP_VAL_REG
) {
1791 tcg_out_st(s
, ts
->type
, ts
->reg
, TCG_REG_CALL_STACK
, stack_offset
);
1792 } else if (ts
->val_type
== TEMP_VAL_MEM
) {
1793 reg
= tcg_reg_alloc(s
, tcg_target_available_regs
[ts
->type
],
1795 /* XXX: not correct if reading values from the stack */
1796 tcg_out_ld(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
1797 tcg_out_st(s
, ts
->type
, reg
, TCG_REG_CALL_STACK
, stack_offset
);
1798 } else if (ts
->val_type
== TEMP_VAL_CONST
) {
1799 reg
= tcg_reg_alloc(s
, tcg_target_available_regs
[ts
->type
],
1801 /* XXX: sign extend may be needed on some targets */
1802 tcg_out_movi(s
, ts
->type
, reg
, ts
->val
);
1803 tcg_out_st(s
, ts
->type
, reg
, TCG_REG_CALL_STACK
, stack_offset
);
1808 #ifndef TCG_TARGET_STACK_GROWSUP
1809 stack_offset
+= sizeof(tcg_target_long
);
1813 /* assign input registers */
1814 tcg_regset_set(allocated_regs
, s
->reserved_regs
);
1815 for(i
= 0; i
< nb_regs
; i
++) {
1816 arg
= args
[nb_oargs
+ i
];
1817 if (arg
!= TCG_CALL_DUMMY_ARG
) {
1818 ts
= &s
->temps
[arg
];
1819 reg
= tcg_target_call_iarg_regs
[i
];
1820 tcg_reg_free(s
, reg
);
1821 if (ts
->val_type
== TEMP_VAL_REG
) {
1822 if (ts
->reg
!= reg
) {
1823 tcg_out_mov(s
, ts
->type
, reg
, ts
->reg
);
1825 } else if (ts
->val_type
== TEMP_VAL_MEM
) {
1826 tcg_out_ld(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
1827 } else if (ts
->val_type
== TEMP_VAL_CONST
) {
1828 /* XXX: sign extend ? */
1829 tcg_out_movi(s
, ts
->type
, reg
, ts
->val
);
1833 tcg_regset_set_reg(allocated_regs
, reg
);
1837 /* assign function address */
1838 func_arg
= args
[nb_oargs
+ nb_iargs
- 1];
1839 arg_ct
= &def
->args_ct
[0];
1840 ts
= &s
->temps
[func_arg
];
1841 func_addr
= ts
->val
;
1843 if (ts
->val_type
== TEMP_VAL_MEM
) {
1844 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1845 tcg_out_ld(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
1847 tcg_regset_set_reg(allocated_regs
, reg
);
1848 } else if (ts
->val_type
== TEMP_VAL_REG
) {
1850 if (!tcg_regset_test_reg(arg_ct
->u
.regs
, reg
)) {
1851 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1852 tcg_out_mov(s
, ts
->type
, reg
, ts
->reg
);
1855 tcg_regset_set_reg(allocated_regs
, reg
);
1856 } else if (ts
->val_type
== TEMP_VAL_CONST
) {
1857 if (tcg_target_const_match(func_addr
, arg_ct
)) {
1859 func_arg
= func_addr
;
1861 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1862 tcg_out_movi(s
, ts
->type
, reg
, func_addr
);
1864 tcg_regset_set_reg(allocated_regs
, reg
);
1871 /* mark dead temporaries and free the associated registers */
1872 for(i
= 0; i
< nb_iargs
; i
++) {
1873 arg
= args
[nb_oargs
+ i
];
1874 if (IS_DEAD_IARG(i
)) {
1875 ts
= &s
->temps
[arg
];
1876 if (!ts
->fixed_reg
) {
1877 if (ts
->val_type
== TEMP_VAL_REG
)
1878 s
->reg_to_temp
[ts
->reg
] = -1;
1879 ts
->val_type
= TEMP_VAL_DEAD
;
1884 /* clobber call registers */
1885 for(reg
= 0; reg
< TCG_TARGET_NB_REGS
; reg
++) {
1886 if (tcg_regset_test_reg(tcg_target_call_clobber_regs
, reg
)) {
1887 tcg_reg_free(s
, reg
);
1891 /* store globals and free associated registers (we assume the call
1892 can modify any global. */
1893 if (!(flags
& TCG_CALL_CONST
)) {
1894 save_globals(s
, allocated_regs
);
1897 tcg_out_op(s
, opc
, &func_arg
, &const_func_arg
);
1899 if (allocate_args
) {
1900 tcg_out_addi(s
, TCG_REG_CALL_STACK
, STACK_DIR(call_stack_size
));
1903 /* assign output registers and emit moves if needed */
1904 for(i
= 0; i
< nb_oargs
; i
++) {
1906 ts
= &s
->temps
[arg
];
1907 reg
= tcg_target_call_oarg_regs
[i
];
1908 assert(s
->reg_to_temp
[reg
] == -1);
1909 if (ts
->fixed_reg
) {
1910 if (ts
->reg
!= reg
) {
1911 tcg_out_mov(s
, ts
->type
, ts
->reg
, reg
);
1914 if (ts
->val_type
== TEMP_VAL_REG
)
1915 s
->reg_to_temp
[ts
->reg
] = -1;
1916 ts
->val_type
= TEMP_VAL_REG
;
1918 ts
->mem_coherent
= 0;
1919 s
->reg_to_temp
[reg
] = arg
;
1923 return nb_iargs
+ nb_oargs
+ def
->nb_cargs
+ 1;
1926 #ifdef CONFIG_PROFILER
1928 static int64_t tcg_table_op_count
[NB_OPS
];
1930 static void dump_op_count(void)
1934 f
= fopen("/tmp/op.log", "w");
1935 for(i
= INDEX_op_end
; i
< NB_OPS
; i
++) {
1936 fprintf(f
, "%s %" PRId64
"\n", tcg_op_defs
[i
].name
, tcg_table_op_count
[i
]);
1943 static inline int tcg_gen_code_common(TCGContext
*s
, uint8_t *gen_code_buf
,
1948 const TCGOpDef
*def
;
1949 unsigned int dead_iargs
;
1953 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP
))) {
1955 tcg_dump_ops(s
, logfile
);
1960 #ifdef CONFIG_PROFILER
1961 s
->la_time
-= profile_getclock();
1963 tcg_liveness_analysis(s
);
1964 #ifdef CONFIG_PROFILER
1965 s
->la_time
+= profile_getclock();
1969 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_OPT
))) {
1970 qemu_log("OP after liveness analysis:\n");
1971 tcg_dump_ops(s
, logfile
);
1976 tcg_reg_alloc_start(s
);
1978 s
->code_buf
= gen_code_buf
;
1979 s
->code_ptr
= gen_code_buf
;
1981 args
= gen_opparam_buf
;
1985 opc
= gen_opc_buf
[op_index
];
1986 #ifdef CONFIG_PROFILER
1987 tcg_table_op_count
[opc
]++;
1989 def
= &tcg_op_defs
[opc
];
1991 printf("%s: %d %d %d\n", def
->name
,
1992 def
->nb_oargs
, def
->nb_iargs
, def
->nb_cargs
);
1996 case INDEX_op_mov_i32
:
1997 #if TCG_TARGET_REG_BITS == 64
1998 case INDEX_op_mov_i64
:
2000 dead_iargs
= s
->op_dead_iargs
[op_index
];
2001 tcg_reg_alloc_mov(s
, def
, args
, dead_iargs
);
2003 case INDEX_op_movi_i32
:
2004 #if TCG_TARGET_REG_BITS == 64
2005 case INDEX_op_movi_i64
:
2007 tcg_reg_alloc_movi(s
, args
);
2009 case INDEX_op_debug_insn_start
:
2010 /* debug instruction */
2020 case INDEX_op_discard
:
2023 ts
= &s
->temps
[args
[0]];
2024 /* mark the temporary as dead */
2025 if (!ts
->fixed_reg
) {
2026 if (ts
->val_type
== TEMP_VAL_REG
)
2027 s
->reg_to_temp
[ts
->reg
] = -1;
2028 ts
->val_type
= TEMP_VAL_DEAD
;
2032 case INDEX_op_set_label
:
2033 tcg_reg_alloc_bb_end(s
, s
->reserved_regs
);
2034 tcg_out_label(s
, args
[0], (long)s
->code_ptr
);
2037 dead_iargs
= s
->op_dead_iargs
[op_index
];
2038 args
+= tcg_reg_alloc_call(s
, def
, opc
, args
, dead_iargs
);
2043 /* Note: in order to speed up the code, it would be much
2044 faster to have specialized register allocator functions for
2045 some common argument patterns */
2046 dead_iargs
= s
->op_dead_iargs
[op_index
];
2047 tcg_reg_alloc_op(s
, def
, opc
, args
, dead_iargs
);
2050 args
+= def
->nb_args
;
2052 if (search_pc
>= 0 && search_pc
< s
->code_ptr
- gen_code_buf
) {
2064 int tcg_gen_code(TCGContext
*s
, uint8_t *gen_code_buf
)
2066 #ifdef CONFIG_PROFILER
2069 n
= (gen_opc_ptr
- gen_opc_buf
);
2071 if (n
> s
->op_count_max
)
2072 s
->op_count_max
= n
;
2074 s
->temp_count
+= s
->nb_temps
;
2075 if (s
->nb_temps
> s
->temp_count_max
)
2076 s
->temp_count_max
= s
->nb_temps
;
2080 tcg_gen_code_common(s
, gen_code_buf
, -1);
2082 /* flush instruction cache */
2083 flush_icache_range((unsigned long)gen_code_buf
,
2084 (unsigned long)s
->code_ptr
);
2085 return s
->code_ptr
- gen_code_buf
;
2088 /* Return the index of the micro operation such as the pc after is <
2089 offset bytes from the start of the TB. The contents of gen_code_buf must
2090 not be changed, though writing the same values is ok.
2091 Return -1 if not found. */
2092 int tcg_gen_code_search_pc(TCGContext
*s
, uint8_t *gen_code_buf
, long offset
)
2094 return tcg_gen_code_common(s
, gen_code_buf
, offset
);
2097 #ifdef CONFIG_PROFILER
2098 void tcg_dump_info(FILE *f
,
2099 int (*cpu_fprintf
)(FILE *f
, const char *fmt
, ...))
2101 TCGContext
*s
= &tcg_ctx
;
2104 tot
= s
->interm_time
+ s
->code_time
;
2105 cpu_fprintf(f
, "JIT cycles %" PRId64
" (%0.3f s at 2.4 GHz)\n",
2107 cpu_fprintf(f
, "translated TBs %" PRId64
" (aborted=%" PRId64
" %0.1f%%)\n",
2109 s
->tb_count1
- s
->tb_count
,
2110 s
->tb_count1
? (double)(s
->tb_count1
- s
->tb_count
) / s
->tb_count1
* 100.0 : 0);
2111 cpu_fprintf(f
, "avg ops/TB %0.1f max=%d\n",
2112 s
->tb_count
? (double)s
->op_count
/ s
->tb_count
: 0, s
->op_count_max
);
2113 cpu_fprintf(f
, "deleted ops/TB %0.2f\n",
2115 (double)s
->del_op_count
/ s
->tb_count
: 0);
2116 cpu_fprintf(f
, "avg temps/TB %0.2f max=%d\n",
2118 (double)s
->temp_count
/ s
->tb_count
: 0,
2121 cpu_fprintf(f
, "cycles/op %0.1f\n",
2122 s
->op_count
? (double)tot
/ s
->op_count
: 0);
2123 cpu_fprintf(f
, "cycles/in byte %0.1f\n",
2124 s
->code_in_len
? (double)tot
/ s
->code_in_len
: 0);
2125 cpu_fprintf(f
, "cycles/out byte %0.1f\n",
2126 s
->code_out_len
? (double)tot
/ s
->code_out_len
: 0);
2129 cpu_fprintf(f
, " gen_interm time %0.1f%%\n",
2130 (double)s
->interm_time
/ tot
* 100.0);
2131 cpu_fprintf(f
, " gen_code time %0.1f%%\n",
2132 (double)s
->code_time
/ tot
* 100.0);
2133 cpu_fprintf(f
, "liveness/code time %0.1f%%\n",
2134 (double)s
->la_time
/ (s
->code_time
? s
->code_time
: 1) * 100.0);
2135 cpu_fprintf(f
, "cpu_restore count %" PRId64
"\n",
2137 cpu_fprintf(f
, " avg cycles %0.1f\n",
2138 s
->restore_count
? (double)s
->restore_time
/ s
->restore_count
: 0);
2143 void tcg_dump_info(FILE *f
,
2144 int (*cpu_fprintf
)(FILE *f
, const char *fmt
, ...))
2146 cpu_fprintf(f
, "[TCG profiler not compiled]\n");