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"
51 /* Note: the long term plan is to reduce the dependancies on the QEMU
52 CPU definitions. Currently they are used for qemu_ld/st
54 #define NO_CPU_IO_DEFS
61 #if defined(CONFIG_USE_GUEST_BASE) && !defined(TCG_TARGET_HAS_GUEST_BASE)
62 #error GUEST_BASE not supported on this host.
65 static void patch_reloc(uint8_t *code_ptr
, int type
,
66 tcg_target_long value
, tcg_target_long addend
);
68 static TCGOpDef tcg_op_defs
[] = {
69 #define DEF(s, n, copy_size) { #s, 0, 0, n, n, 0, copy_size },
70 #define DEF2(s, oargs, iargs, cargs, flags) { #s, oargs, iargs, cargs, iargs + oargs + cargs, flags, 0 },
76 static TCGRegSet tcg_target_available_regs
[2];
77 static TCGRegSet tcg_target_call_clobber_regs
;
79 /* XXX: move that inside the context */
80 uint16_t *gen_opc_ptr
;
81 TCGArg
*gen_opparam_ptr
;
83 static inline void tcg_out8(TCGContext
*s
, uint8_t v
)
88 static inline void tcg_out16(TCGContext
*s
, uint16_t v
)
90 *(uint16_t *)s
->code_ptr
= v
;
94 static inline void tcg_out32(TCGContext
*s
, uint32_t v
)
96 *(uint32_t *)s
->code_ptr
= v
;
100 /* label relocation processing */
102 void tcg_out_reloc(TCGContext
*s
, uint8_t *code_ptr
, int type
,
103 int label_index
, long addend
)
108 l
= &s
->labels
[label_index
];
110 /* FIXME: This may break relocations on RISC targets that
111 modify instruction fields in place. The caller may not have
112 written the initial value. */
113 patch_reloc(code_ptr
, type
, l
->u
.value
, addend
);
115 /* add a new relocation entry */
116 r
= tcg_malloc(sizeof(TCGRelocation
));
120 r
->next
= l
->u
.first_reloc
;
121 l
->u
.first_reloc
= r
;
125 static void tcg_out_label(TCGContext
*s
, int label_index
,
126 tcg_target_long value
)
131 l
= &s
->labels
[label_index
];
134 r
= l
->u
.first_reloc
;
136 patch_reloc(r
->ptr
, r
->type
, value
, r
->addend
);
143 int gen_new_label(void)
145 TCGContext
*s
= &tcg_ctx
;
149 if (s
->nb_labels
>= TCG_MAX_LABELS
)
151 idx
= s
->nb_labels
++;
154 l
->u
.first_reloc
= NULL
;
158 #include "tcg-target.c"
160 /* pool based memory allocation */
161 void *tcg_malloc_internal(TCGContext
*s
, int size
)
166 if (size
> TCG_POOL_CHUNK_SIZE
) {
167 /* big malloc: insert a new pool (XXX: could optimize) */
168 p
= qemu_malloc(sizeof(TCGPool
) + size
);
171 s
->pool_current
->next
= p
;
174 p
->next
= s
->pool_current
;
184 pool_size
= TCG_POOL_CHUNK_SIZE
;
185 p
= qemu_malloc(sizeof(TCGPool
) + pool_size
);
189 s
->pool_current
->next
= p
;
198 s
->pool_cur
= p
->data
+ size
;
199 s
->pool_end
= p
->data
+ p
->size
;
203 void tcg_pool_reset(TCGContext
*s
)
205 s
->pool_cur
= s
->pool_end
= NULL
;
206 s
->pool_current
= NULL
;
209 void tcg_context_init(TCGContext
*s
)
211 int op
, total_args
, n
;
213 TCGArgConstraint
*args_ct
;
216 memset(s
, 0, sizeof(*s
));
217 s
->temps
= s
->static_temps
;
220 /* Count total number of arguments and allocate the corresponding
223 for(op
= 0; op
< NB_OPS
; op
++) {
224 def
= &tcg_op_defs
[op
];
225 n
= def
->nb_iargs
+ def
->nb_oargs
;
229 args_ct
= qemu_malloc(sizeof(TCGArgConstraint
) * total_args
);
230 sorted_args
= qemu_malloc(sizeof(int) * total_args
);
232 for(op
= 0; op
< NB_OPS
; op
++) {
233 def
= &tcg_op_defs
[op
];
234 def
->args_ct
= args_ct
;
235 def
->sorted_args
= sorted_args
;
236 n
= def
->nb_iargs
+ def
->nb_oargs
;
243 /* init global prologue and epilogue */
244 s
->code_buf
= code_gen_prologue
;
245 s
->code_ptr
= s
->code_buf
;
246 tcg_target_qemu_prologue(s
);
247 flush_icache_range((unsigned long)s
->code_buf
,
248 (unsigned long)s
->code_ptr
);
251 void tcg_set_frame(TCGContext
*s
, int reg
,
252 tcg_target_long start
, tcg_target_long size
)
254 s
->frame_start
= start
;
255 s
->frame_end
= start
+ size
;
259 void tcg_func_start(TCGContext
*s
)
263 s
->nb_temps
= s
->nb_globals
;
264 for(i
= 0; i
< (TCG_TYPE_COUNT
* 2); i
++)
265 s
->first_free_temp
[i
] = -1;
266 s
->labels
= tcg_malloc(sizeof(TCGLabel
) * TCG_MAX_LABELS
);
268 s
->current_frame_offset
= s
->frame_start
;
270 gen_opc_ptr
= gen_opc_buf
;
271 gen_opparam_ptr
= gen_opparam_buf
;
274 static inline void tcg_temp_alloc(TCGContext
*s
, int n
)
276 if (n
> TCG_MAX_TEMPS
)
280 static inline int tcg_global_reg_new_internal(TCGType type
, int reg
,
283 TCGContext
*s
= &tcg_ctx
;
287 #if TCG_TARGET_REG_BITS == 32
288 if (type
!= TCG_TYPE_I32
)
291 if (tcg_regset_test_reg(s
->reserved_regs
, reg
))
294 tcg_temp_alloc(s
, s
->nb_globals
+ 1);
295 ts
= &s
->temps
[s
->nb_globals
];
296 ts
->base_type
= type
;
302 tcg_regset_set_reg(s
->reserved_regs
, reg
);
306 TCGv_i32
tcg_global_reg_new_i32(int reg
, const char *name
)
310 idx
= tcg_global_reg_new_internal(TCG_TYPE_I32
, reg
, name
);
311 return MAKE_TCGV_I32(idx
);
314 TCGv_i64
tcg_global_reg_new_i64(int reg
, const char *name
)
318 idx
= tcg_global_reg_new_internal(TCG_TYPE_I64
, reg
, name
);
319 return MAKE_TCGV_I64(idx
);
322 static inline int tcg_global_mem_new_internal(TCGType type
, int reg
,
323 tcg_target_long offset
,
326 TCGContext
*s
= &tcg_ctx
;
331 #if TCG_TARGET_REG_BITS == 32
332 if (type
== TCG_TYPE_I64
) {
334 tcg_temp_alloc(s
, s
->nb_globals
+ 2);
335 ts
= &s
->temps
[s
->nb_globals
];
336 ts
->base_type
= type
;
337 ts
->type
= TCG_TYPE_I32
;
339 ts
->mem_allocated
= 1;
341 #ifdef TCG_TARGET_WORDS_BIGENDIAN
342 ts
->mem_offset
= offset
+ 4;
344 ts
->mem_offset
= offset
;
346 pstrcpy(buf
, sizeof(buf
), name
);
347 pstrcat(buf
, sizeof(buf
), "_0");
348 ts
->name
= strdup(buf
);
351 ts
->base_type
= type
;
352 ts
->type
= TCG_TYPE_I32
;
354 ts
->mem_allocated
= 1;
356 #ifdef TCG_TARGET_WORDS_BIGENDIAN
357 ts
->mem_offset
= offset
;
359 ts
->mem_offset
= offset
+ 4;
361 pstrcpy(buf
, sizeof(buf
), name
);
362 pstrcat(buf
, sizeof(buf
), "_1");
363 ts
->name
= strdup(buf
);
369 tcg_temp_alloc(s
, s
->nb_globals
+ 1);
370 ts
= &s
->temps
[s
->nb_globals
];
371 ts
->base_type
= type
;
374 ts
->mem_allocated
= 1;
376 ts
->mem_offset
= offset
;
383 TCGv_i32
tcg_global_mem_new_i32(int reg
, tcg_target_long offset
,
388 idx
= tcg_global_mem_new_internal(TCG_TYPE_I32
, reg
, offset
, name
);
389 return MAKE_TCGV_I32(idx
);
392 TCGv_i64
tcg_global_mem_new_i64(int reg
, tcg_target_long offset
,
397 idx
= tcg_global_mem_new_internal(TCG_TYPE_I64
, reg
, offset
, name
);
398 return MAKE_TCGV_I64(idx
);
401 static inline int tcg_temp_new_internal(TCGType type
, int temp_local
)
403 TCGContext
*s
= &tcg_ctx
;
410 idx
= s
->first_free_temp
[k
];
412 /* There is already an available temp with the
415 s
->first_free_temp
[k
] = ts
->next_free_temp
;
416 ts
->temp_allocated
= 1;
417 assert(ts
->temp_local
== temp_local
);
420 #if TCG_TARGET_REG_BITS == 32
421 if (type
== TCG_TYPE_I64
) {
422 tcg_temp_alloc(s
, s
->nb_temps
+ 2);
423 ts
= &s
->temps
[s
->nb_temps
];
424 ts
->base_type
= type
;
425 ts
->type
= TCG_TYPE_I32
;
426 ts
->temp_allocated
= 1;
427 ts
->temp_local
= temp_local
;
430 ts
->base_type
= TCG_TYPE_I32
;
431 ts
->type
= TCG_TYPE_I32
;
432 ts
->temp_allocated
= 1;
433 ts
->temp_local
= temp_local
;
439 tcg_temp_alloc(s
, s
->nb_temps
+ 1);
440 ts
= &s
->temps
[s
->nb_temps
];
441 ts
->base_type
= type
;
443 ts
->temp_allocated
= 1;
444 ts
->temp_local
= temp_local
;
452 TCGv_i32
tcg_temp_new_internal_i32(int temp_local
)
456 idx
= tcg_temp_new_internal(TCG_TYPE_I32
, temp_local
);
457 return MAKE_TCGV_I32(idx
);
460 TCGv_i64
tcg_temp_new_internal_i64(int temp_local
)
464 idx
= tcg_temp_new_internal(TCG_TYPE_I64
, temp_local
);
465 return MAKE_TCGV_I64(idx
);
468 static inline void tcg_temp_free_internal(int idx
)
470 TCGContext
*s
= &tcg_ctx
;
474 assert(idx
>= s
->nb_globals
&& idx
< s
->nb_temps
);
476 assert(ts
->temp_allocated
!= 0);
477 ts
->temp_allocated
= 0;
481 ts
->next_free_temp
= s
->first_free_temp
[k
];
482 s
->first_free_temp
[k
] = idx
;
485 void tcg_temp_free_i32(TCGv_i32 arg
)
487 tcg_temp_free_internal(GET_TCGV_I32(arg
));
490 void tcg_temp_free_i64(TCGv_i64 arg
)
492 tcg_temp_free_internal(GET_TCGV_I64(arg
));
495 TCGv_i32
tcg_const_i32(int32_t val
)
498 t0
= tcg_temp_new_i32();
499 tcg_gen_movi_i32(t0
, val
);
503 TCGv_i64
tcg_const_i64(int64_t val
)
506 t0
= tcg_temp_new_i64();
507 tcg_gen_movi_i64(t0
, val
);
511 TCGv_i32
tcg_const_local_i32(int32_t val
)
514 t0
= tcg_temp_local_new_i32();
515 tcg_gen_movi_i32(t0
, val
);
519 TCGv_i64
tcg_const_local_i64(int64_t val
)
522 t0
= tcg_temp_local_new_i64();
523 tcg_gen_movi_i64(t0
, val
);
527 void tcg_register_helper(void *func
, const char *name
)
529 TCGContext
*s
= &tcg_ctx
;
531 if ((s
->nb_helpers
+ 1) > s
->allocated_helpers
) {
532 n
= s
->allocated_helpers
;
538 s
->helpers
= realloc(s
->helpers
, n
* sizeof(TCGHelperInfo
));
539 s
->allocated_helpers
= n
;
541 s
->helpers
[s
->nb_helpers
].func
= (tcg_target_ulong
)func
;
542 s
->helpers
[s
->nb_helpers
].name
= name
;
546 /* Note: we convert the 64 bit args to 32 bit and do some alignment
547 and endian swap. Maybe it would be better to do the alignment
548 and endian swap in tcg_reg_alloc_call(). */
549 void tcg_gen_callN(TCGContext
*s
, TCGv_ptr func
, unsigned int flags
,
550 int sizemask
, TCGArg ret
, int nargs
, TCGArg
*args
)
557 *gen_opc_ptr
++ = INDEX_op_call
;
558 nparam
= gen_opparam_ptr
++;
559 call_type
= (flags
& TCG_CALL_TYPE_MASK
);
560 if (ret
!= TCG_CALL_DUMMY_ARG
) {
561 #if TCG_TARGET_REG_BITS < 64
563 #ifdef TCG_TARGET_WORDS_BIGENDIAN
564 *gen_opparam_ptr
++ = ret
+ 1;
565 *gen_opparam_ptr
++ = ret
;
567 *gen_opparam_ptr
++ = ret
;
568 *gen_opparam_ptr
++ = ret
+ 1;
574 *gen_opparam_ptr
++ = ret
;
581 for (i
= 0; i
< nargs
; i
++) {
582 #if TCG_TARGET_REG_BITS < 64
583 if (sizemask
& (2 << i
)) {
584 #ifdef TCG_TARGET_I386
585 /* REGPARM case: if the third parameter is 64 bit, it is
586 allocated on the stack */
587 if (i
== 2 && call_type
== TCG_CALL_TYPE_REGPARM
) {
588 call_type
= TCG_CALL_TYPE_REGPARM_2
;
589 flags
= (flags
& ~TCG_CALL_TYPE_MASK
) | call_type
;
592 #ifdef TCG_TARGET_CALL_ALIGN_ARGS
593 /* some targets want aligned 64 bit args */
595 *gen_opparam_ptr
++ = TCG_CALL_DUMMY_ARG
;
599 /* If stack grows up, then we will be placing successive
600 arguments at lower addresses, which means we need to
601 reverse the order compared to how we would normally
602 treat either big or little-endian. For those arguments
603 that will wind up in registers, this still works for
604 HPPA (the only current STACK_GROWSUP target) since the
605 argument registers are *also* allocated in decreasing
606 order. If another such target is added, this logic may
607 have to get more complicated to differentiate between
608 stack arguments and register arguments. */
609 #if defined(TCG_TARGET_WORDS_BIGENDIAN) != defined(TCG_TARGET_STACK_GROWSUP)
610 *gen_opparam_ptr
++ = args
[i
] + 1;
611 *gen_opparam_ptr
++ = args
[i
];
613 *gen_opparam_ptr
++ = args
[i
];
614 *gen_opparam_ptr
++ = args
[i
] + 1;
620 *gen_opparam_ptr
++ = args
[i
];
624 *gen_opparam_ptr
++ = GET_TCGV_PTR(func
);
626 *gen_opparam_ptr
++ = flags
;
628 *nparam
= (nb_rets
<< 16) | (real_args
+ 1);
630 /* total parameters, needed to go backward in the instruction stream */
631 *gen_opparam_ptr
++ = 1 + nb_rets
+ real_args
+ 3;
634 #if TCG_TARGET_REG_BITS == 32
635 void tcg_gen_shifti_i64(TCGv_i64 ret
, TCGv_i64 arg1
,
636 int c
, int right
, int arith
)
639 tcg_gen_mov_i32(TCGV_LOW(ret
), TCGV_LOW(arg1
));
640 tcg_gen_mov_i32(TCGV_HIGH(ret
), TCGV_HIGH(arg1
));
641 } else if (c
>= 32) {
645 tcg_gen_sari_i32(TCGV_LOW(ret
), TCGV_HIGH(arg1
), c
);
646 tcg_gen_sari_i32(TCGV_HIGH(ret
), TCGV_HIGH(arg1
), 31);
648 tcg_gen_shri_i32(TCGV_LOW(ret
), TCGV_HIGH(arg1
), c
);
649 tcg_gen_movi_i32(TCGV_HIGH(ret
), 0);
652 tcg_gen_shli_i32(TCGV_HIGH(ret
), TCGV_LOW(arg1
), c
);
653 tcg_gen_movi_i32(TCGV_LOW(ret
), 0);
658 t0
= tcg_temp_new_i32();
659 t1
= tcg_temp_new_i32();
661 tcg_gen_shli_i32(t0
, TCGV_HIGH(arg1
), 32 - c
);
663 tcg_gen_sari_i32(t1
, TCGV_HIGH(arg1
), c
);
665 tcg_gen_shri_i32(t1
, TCGV_HIGH(arg1
), c
);
666 tcg_gen_shri_i32(TCGV_LOW(ret
), TCGV_LOW(arg1
), c
);
667 tcg_gen_or_i32(TCGV_LOW(ret
), TCGV_LOW(ret
), t0
);
668 tcg_gen_mov_i32(TCGV_HIGH(ret
), t1
);
670 tcg_gen_shri_i32(t0
, TCGV_LOW(arg1
), 32 - c
);
671 /* Note: ret can be the same as arg1, so we use t1 */
672 tcg_gen_shli_i32(t1
, TCGV_LOW(arg1
), c
);
673 tcg_gen_shli_i32(TCGV_HIGH(ret
), TCGV_HIGH(arg1
), c
);
674 tcg_gen_or_i32(TCGV_HIGH(ret
), TCGV_HIGH(ret
), t0
);
675 tcg_gen_mov_i32(TCGV_LOW(ret
), t1
);
677 tcg_temp_free_i32(t0
);
678 tcg_temp_free_i32(t1
);
684 static void tcg_reg_alloc_start(TCGContext
*s
)
688 for(i
= 0; i
< s
->nb_globals
; i
++) {
691 ts
->val_type
= TEMP_VAL_REG
;
693 ts
->val_type
= TEMP_VAL_MEM
;
696 for(i
= s
->nb_globals
; i
< s
->nb_temps
; i
++) {
698 ts
->val_type
= TEMP_VAL_DEAD
;
699 ts
->mem_allocated
= 0;
702 for(i
= 0; i
< TCG_TARGET_NB_REGS
; i
++) {
703 s
->reg_to_temp
[i
] = -1;
707 static char *tcg_get_arg_str_idx(TCGContext
*s
, char *buf
, int buf_size
,
713 if (idx
< s
->nb_globals
) {
714 pstrcpy(buf
, buf_size
, ts
->name
);
717 snprintf(buf
, buf_size
, "loc%d", idx
- s
->nb_globals
);
719 snprintf(buf
, buf_size
, "tmp%d", idx
- s
->nb_globals
);
724 char *tcg_get_arg_str_i32(TCGContext
*s
, char *buf
, int buf_size
, TCGv_i32 arg
)
726 return tcg_get_arg_str_idx(s
, buf
, buf_size
, GET_TCGV_I32(arg
));
729 char *tcg_get_arg_str_i64(TCGContext
*s
, char *buf
, int buf_size
, TCGv_i64 arg
)
731 return tcg_get_arg_str_idx(s
, buf
, buf_size
, GET_TCGV_I64(arg
));
734 static int helper_cmp(const void *p1
, const void *p2
)
736 const TCGHelperInfo
*th1
= p1
;
737 const TCGHelperInfo
*th2
= p2
;
738 if (th1
->func
< th2
->func
)
740 else if (th1
->func
== th2
->func
)
746 /* find helper definition (Note: A hash table would be better) */
747 static TCGHelperInfo
*tcg_find_helper(TCGContext
*s
, tcg_target_ulong val
)
753 if (unlikely(!s
->helpers_sorted
)) {
754 qsort(s
->helpers
, s
->nb_helpers
, sizeof(TCGHelperInfo
),
756 s
->helpers_sorted
= 1;
761 m_max
= s
->nb_helpers
- 1;
762 while (m_min
<= m_max
) {
763 m
= (m_min
+ m_max
) >> 1;
777 static const char * const cond_name
[] =
779 [TCG_COND_EQ
] = "eq",
780 [TCG_COND_NE
] = "ne",
781 [TCG_COND_LT
] = "lt",
782 [TCG_COND_GE
] = "ge",
783 [TCG_COND_LE
] = "le",
784 [TCG_COND_GT
] = "gt",
785 [TCG_COND_LTU
] = "ltu",
786 [TCG_COND_GEU
] = "geu",
787 [TCG_COND_LEU
] = "leu",
788 [TCG_COND_GTU
] = "gtu"
791 void tcg_dump_ops(TCGContext
*s
, FILE *outfile
)
793 const uint16_t *opc_ptr
;
797 int i
, k
, nb_oargs
, nb_iargs
, nb_cargs
, first_insn
;
802 opc_ptr
= gen_opc_buf
;
803 args
= gen_opparam_buf
;
804 while (opc_ptr
< gen_opc_ptr
) {
806 def
= &tcg_op_defs
[c
];
807 if (c
== INDEX_op_debug_insn_start
) {
809 #if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
810 pc
= ((uint64_t)args
[1] << 32) | args
[0];
815 fprintf(outfile
, "\n");
816 fprintf(outfile
, " ---- 0x%" PRIx64
, pc
);
818 nb_oargs
= def
->nb_oargs
;
819 nb_iargs
= def
->nb_iargs
;
820 nb_cargs
= def
->nb_cargs
;
821 } else if (c
== INDEX_op_call
) {
824 /* variable number of arguments */
826 nb_oargs
= arg
>> 16;
827 nb_iargs
= arg
& 0xffff;
828 nb_cargs
= def
->nb_cargs
;
830 fprintf(outfile
, " %s ", def
->name
);
833 fprintf(outfile
, "%s",
834 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), args
[nb_oargs
+ nb_iargs
- 1]));
836 fprintf(outfile
, ",$0x%" TCG_PRIlx
,
837 args
[nb_oargs
+ nb_iargs
]);
839 fprintf(outfile
, ",$%d", nb_oargs
);
840 for(i
= 0; i
< nb_oargs
; i
++) {
841 fprintf(outfile
, ",");
842 fprintf(outfile
, "%s",
843 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), args
[i
]));
845 for(i
= 0; i
< (nb_iargs
- 1); i
++) {
846 fprintf(outfile
, ",");
847 if (args
[nb_oargs
+ i
] == TCG_CALL_DUMMY_ARG
) {
848 fprintf(outfile
, "<dummy>");
850 fprintf(outfile
, "%s",
851 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), args
[nb_oargs
+ i
]));
854 } else if (c
== INDEX_op_movi_i32
855 #if TCG_TARGET_REG_BITS == 64
856 || c
== INDEX_op_movi_i64
859 tcg_target_ulong val
;
862 nb_oargs
= def
->nb_oargs
;
863 nb_iargs
= def
->nb_iargs
;
864 nb_cargs
= def
->nb_cargs
;
865 fprintf(outfile
, " %s %s,$", def
->name
,
866 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), args
[0]));
868 th
= tcg_find_helper(s
, val
);
870 fprintf(outfile
, "%s", th
->name
);
872 if (c
== INDEX_op_movi_i32
)
873 fprintf(outfile
, "0x%x", (uint32_t)val
);
875 fprintf(outfile
, "0x%" PRIx64
, (uint64_t)val
);
878 fprintf(outfile
, " %s ", def
->name
);
879 if (c
== INDEX_op_nopn
) {
880 /* variable number of arguments */
885 nb_oargs
= def
->nb_oargs
;
886 nb_iargs
= def
->nb_iargs
;
887 nb_cargs
= def
->nb_cargs
;
891 for(i
= 0; i
< nb_oargs
; i
++) {
893 fprintf(outfile
, ",");
894 fprintf(outfile
, "%s",
895 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), args
[k
++]));
897 for(i
= 0; i
< nb_iargs
; i
++) {
899 fprintf(outfile
, ",");
900 fprintf(outfile
, "%s",
901 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), args
[k
++]));
904 case INDEX_op_brcond_i32
:
905 #if TCG_TARGET_REG_BITS == 32
906 case INDEX_op_brcond2_i32
:
907 #elif TCG_TARGET_REG_BITS == 64
908 case INDEX_op_brcond_i64
:
910 case INDEX_op_setcond_i32
:
911 #if TCG_TARGET_REG_BITS == 32
912 case INDEX_op_setcond2_i32
:
913 #elif TCG_TARGET_REG_BITS == 64
914 case INDEX_op_setcond_i64
:
916 if (args
[k
] < ARRAY_SIZE(cond_name
) && cond_name
[args
[k
]])
917 fprintf(outfile
, ",%s", cond_name
[args
[k
++]]);
919 fprintf(outfile
, ",$0x%" TCG_PRIlx
, args
[k
++]);
926 for(; i
< nb_cargs
; i
++) {
928 fprintf(outfile
, ",");
930 fprintf(outfile
, "$0x%" TCG_PRIlx
, arg
);
933 fprintf(outfile
, "\n");
934 args
+= nb_iargs
+ nb_oargs
+ nb_cargs
;
938 /* we give more priority to constraints with less registers */
939 static int get_constraint_priority(const TCGOpDef
*def
, int k
)
941 const TCGArgConstraint
*arg_ct
;
944 arg_ct
= &def
->args_ct
[k
];
945 if (arg_ct
->ct
& TCG_CT_ALIAS
) {
946 /* an alias is equivalent to a single register */
949 if (!(arg_ct
->ct
& TCG_CT_REG
))
952 for(i
= 0; i
< TCG_TARGET_NB_REGS
; i
++) {
953 if (tcg_regset_test_reg(arg_ct
->u
.regs
, i
))
957 return TCG_TARGET_NB_REGS
- n
+ 1;
960 /* sort from highest priority to lowest */
961 static void sort_constraints(TCGOpDef
*def
, int start
, int n
)
963 int i
, j
, p1
, p2
, tmp
;
965 for(i
= 0; i
< n
; i
++)
966 def
->sorted_args
[start
+ i
] = start
+ i
;
969 for(i
= 0; i
< n
- 1; i
++) {
970 for(j
= i
+ 1; j
< n
; j
++) {
971 p1
= get_constraint_priority(def
, def
->sorted_args
[start
+ i
]);
972 p2
= get_constraint_priority(def
, def
->sorted_args
[start
+ j
]);
974 tmp
= def
->sorted_args
[start
+ i
];
975 def
->sorted_args
[start
+ i
] = def
->sorted_args
[start
+ j
];
976 def
->sorted_args
[start
+ j
] = tmp
;
982 void tcg_add_target_add_op_defs(const TCGTargetOpDef
*tdefs
)
990 if (tdefs
->op
== (TCGOpcode
)-1)
993 assert(op
>= 0 && op
< NB_OPS
);
994 def
= &tcg_op_defs
[op
];
995 #if defined(CONFIG_DEBUG_TCG)
996 /* Duplicate entry in op definitions? */
1000 nb_args
= def
->nb_iargs
+ def
->nb_oargs
;
1001 for(i
= 0; i
< nb_args
; i
++) {
1002 ct_str
= tdefs
->args_ct_str
[i
];
1003 /* Incomplete TCGTargetOpDef entry? */
1004 assert(ct_str
!= NULL
);
1005 tcg_regset_clear(def
->args_ct
[i
].u
.regs
);
1006 def
->args_ct
[i
].ct
= 0;
1007 if (ct_str
[0] >= '0' && ct_str
[0] <= '9') {
1009 oarg
= ct_str
[0] - '0';
1010 assert(oarg
< def
->nb_oargs
);
1011 assert(def
->args_ct
[oarg
].ct
& TCG_CT_REG
);
1012 /* TCG_CT_ALIAS is for the output arguments. The input
1013 argument is tagged with TCG_CT_IALIAS. */
1014 def
->args_ct
[i
] = def
->args_ct
[oarg
];
1015 def
->args_ct
[oarg
].ct
= TCG_CT_ALIAS
;
1016 def
->args_ct
[oarg
].alias_index
= i
;
1017 def
->args_ct
[i
].ct
|= TCG_CT_IALIAS
;
1018 def
->args_ct
[i
].alias_index
= oarg
;
1021 if (*ct_str
== '\0')
1025 def
->args_ct
[i
].ct
|= TCG_CT_CONST
;
1029 if (target_parse_constraint(&def
->args_ct
[i
], &ct_str
) < 0) {
1030 fprintf(stderr
, "Invalid constraint '%s' for arg %d of operation '%s'\n",
1031 ct_str
, i
, def
->name
);
1039 /* TCGTargetOpDef entry with too much information? */
1040 assert(i
== TCG_MAX_OP_ARGS
|| tdefs
->args_ct_str
[i
] == NULL
);
1042 /* sort the constraints (XXX: this is just an heuristic) */
1043 sort_constraints(def
, 0, def
->nb_oargs
);
1044 sort_constraints(def
, def
->nb_oargs
, def
->nb_iargs
);
1050 printf("%s: sorted=", def
->name
);
1051 for(i
= 0; i
< def
->nb_oargs
+ def
->nb_iargs
; i
++)
1052 printf(" %d", def
->sorted_args
[i
]);
1059 #if defined(CONFIG_DEBUG_TCG)
1061 for (op
= 0; op
< ARRAY_SIZE(tcg_op_defs
); op
++) {
1062 if (op
< INDEX_op_call
|| op
== INDEX_op_debug_insn_start
) {
1063 /* Wrong entry in op definitions? */
1064 if (tcg_op_defs
[op
].used
) {
1065 fprintf(stderr
, "Invalid op definition for %s\n",
1066 tcg_op_defs
[op
].name
);
1070 /* Missing entry in op definitions? */
1071 if (!tcg_op_defs
[op
].used
) {
1072 fprintf(stderr
, "Missing op definition for %s\n",
1073 tcg_op_defs
[op
].name
);
1084 #ifdef USE_LIVENESS_ANALYSIS
1086 /* set a nop for an operation using 'nb_args' */
1087 static inline void tcg_set_nop(TCGContext
*s
, uint16_t *opc_ptr
,
1088 TCGArg
*args
, int nb_args
)
1091 *opc_ptr
= INDEX_op_nop
;
1093 *opc_ptr
= INDEX_op_nopn
;
1095 args
[nb_args
- 1] = nb_args
;
1099 /* liveness analysis: end of function: globals are live, temps are
1101 /* XXX: at this stage, not used as there would be little gains because
1102 most TBs end with a conditional jump. */
1103 static inline void tcg_la_func_end(TCGContext
*s
, uint8_t *dead_temps
)
1105 memset(dead_temps
, 0, s
->nb_globals
);
1106 memset(dead_temps
+ s
->nb_globals
, 1, s
->nb_temps
- s
->nb_globals
);
1109 /* liveness analysis: end of basic block: globals are live, temps are
1110 dead, local temps are live. */
1111 static inline void tcg_la_bb_end(TCGContext
*s
, uint8_t *dead_temps
)
1116 memset(dead_temps
, 0, s
->nb_globals
);
1117 ts
= &s
->temps
[s
->nb_globals
];
1118 for(i
= s
->nb_globals
; i
< s
->nb_temps
; i
++) {
1127 /* Liveness analysis : update the opc_dead_iargs array to tell if a
1128 given input arguments is dead. Instructions updating dead
1129 temporaries are removed. */
1130 static void tcg_liveness_analysis(TCGContext
*s
)
1132 int i
, op_index
, nb_args
, nb_iargs
, nb_oargs
, arg
, nb_ops
;
1135 const TCGOpDef
*def
;
1136 uint8_t *dead_temps
;
1137 unsigned int dead_iargs
;
1139 gen_opc_ptr
++; /* skip end */
1141 nb_ops
= gen_opc_ptr
- gen_opc_buf
;
1143 s
->op_dead_iargs
= tcg_malloc(nb_ops
* sizeof(uint16_t));
1145 dead_temps
= tcg_malloc(s
->nb_temps
);
1146 memset(dead_temps
, 1, s
->nb_temps
);
1148 args
= gen_opparam_ptr
;
1149 op_index
= nb_ops
- 1;
1150 while (op_index
>= 0) {
1151 op
= gen_opc_buf
[op_index
];
1152 def
= &tcg_op_defs
[op
];
1160 nb_iargs
= args
[0] & 0xffff;
1161 nb_oargs
= args
[0] >> 16;
1163 call_flags
= args
[nb_oargs
+ nb_iargs
];
1165 /* pure functions can be removed if their result is not
1167 if (call_flags
& TCG_CALL_PURE
) {
1168 for(i
= 0; i
< nb_oargs
; i
++) {
1170 if (!dead_temps
[arg
])
1171 goto do_not_remove_call
;
1173 tcg_set_nop(s
, gen_opc_buf
+ op_index
,
1178 /* output args are dead */
1179 for(i
= 0; i
< nb_oargs
; i
++) {
1181 dead_temps
[arg
] = 1;
1184 if (!(call_flags
& TCG_CALL_CONST
)) {
1185 /* globals are live (they may be used by the call) */
1186 memset(dead_temps
, 0, s
->nb_globals
);
1189 /* input args are live */
1191 for(i
= 0; i
< nb_iargs
; i
++) {
1192 arg
= args
[i
+ nb_oargs
];
1193 if (arg
!= TCG_CALL_DUMMY_ARG
) {
1194 if (dead_temps
[arg
]) {
1195 dead_iargs
|= (1 << i
);
1197 dead_temps
[arg
] = 0;
1200 s
->op_dead_iargs
[op_index
] = dead_iargs
;
1205 case INDEX_op_set_label
:
1207 /* mark end of basic block */
1208 tcg_la_bb_end(s
, dead_temps
);
1210 case INDEX_op_debug_insn_start
:
1211 args
-= def
->nb_args
;
1217 case INDEX_op_discard
:
1219 /* mark the temporary as dead */
1220 dead_temps
[args
[0]] = 1;
1224 /* XXX: optimize by hardcoding common cases (e.g. triadic ops) */
1226 args
-= def
->nb_args
;
1227 nb_iargs
= def
->nb_iargs
;
1228 nb_oargs
= def
->nb_oargs
;
1230 /* Test if the operation can be removed because all
1231 its outputs are dead. We assume that nb_oargs == 0
1232 implies side effects */
1233 if (!(def
->flags
& TCG_OPF_SIDE_EFFECTS
) && nb_oargs
!= 0) {
1234 for(i
= 0; i
< nb_oargs
; i
++) {
1236 if (!dead_temps
[arg
])
1239 tcg_set_nop(s
, gen_opc_buf
+ op_index
, args
, def
->nb_args
);
1240 #ifdef CONFIG_PROFILER
1246 /* output args are dead */
1247 for(i
= 0; i
< nb_oargs
; i
++) {
1249 dead_temps
[arg
] = 1;
1252 /* if end of basic block, update */
1253 if (def
->flags
& TCG_OPF_BB_END
) {
1254 tcg_la_bb_end(s
, dead_temps
);
1255 } else if (def
->flags
& TCG_OPF_CALL_CLOBBER
) {
1256 /* globals are live */
1257 memset(dead_temps
, 0, s
->nb_globals
);
1260 /* input args are live */
1262 for(i
= 0; i
< nb_iargs
; i
++) {
1263 arg
= args
[i
+ nb_oargs
];
1264 if (dead_temps
[arg
]) {
1265 dead_iargs
|= (1 << i
);
1267 dead_temps
[arg
] = 0;
1269 s
->op_dead_iargs
[op_index
] = dead_iargs
;
1276 if (args
!= gen_opparam_buf
)
1280 /* dummy liveness analysis */
1281 void tcg_liveness_analysis(TCGContext
*s
)
1284 nb_ops
= gen_opc_ptr
- gen_opc_buf
;
1286 s
->op_dead_iargs
= tcg_malloc(nb_ops
* sizeof(uint16_t));
1287 memset(s
->op_dead_iargs
, 0, nb_ops
* sizeof(uint16_t));
1292 static void dump_regs(TCGContext
*s
)
1298 for(i
= 0; i
< s
->nb_temps
; i
++) {
1300 printf(" %10s: ", tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), i
));
1301 switch(ts
->val_type
) {
1303 printf("%s", tcg_target_reg_names
[ts
->reg
]);
1306 printf("%d(%s)", (int)ts
->mem_offset
, tcg_target_reg_names
[ts
->mem_reg
]);
1308 case TEMP_VAL_CONST
:
1309 printf("$0x%" TCG_PRIlx
, ts
->val
);
1321 for(i
= 0; i
< TCG_TARGET_NB_REGS
; i
++) {
1322 if (s
->reg_to_temp
[i
] >= 0) {
1324 tcg_target_reg_names
[i
],
1325 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), s
->reg_to_temp
[i
]));
1330 static void check_regs(TCGContext
*s
)
1336 for(reg
= 0; reg
< TCG_TARGET_NB_REGS
; reg
++) {
1337 k
= s
->reg_to_temp
[reg
];
1340 if (ts
->val_type
!= TEMP_VAL_REG
||
1342 printf("Inconsistency for register %s:\n",
1343 tcg_target_reg_names
[reg
]);
1348 for(k
= 0; k
< s
->nb_temps
; k
++) {
1350 if (ts
->val_type
== TEMP_VAL_REG
&&
1352 s
->reg_to_temp
[ts
->reg
] != k
) {
1353 printf("Inconsistency for temp %s:\n",
1354 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), k
));
1356 printf("reg state:\n");
1364 static void temp_allocate_frame(TCGContext
*s
, int temp
)
1367 ts
= &s
->temps
[temp
];
1368 s
->current_frame_offset
= (s
->current_frame_offset
+ sizeof(tcg_target_long
) - 1) & ~(sizeof(tcg_target_long
) - 1);
1369 if (s
->current_frame_offset
+ sizeof(tcg_target_long
) > s
->frame_end
)
1371 ts
->mem_offset
= s
->current_frame_offset
;
1372 ts
->mem_reg
= s
->frame_reg
;
1373 ts
->mem_allocated
= 1;
1374 s
->current_frame_offset
+= sizeof(tcg_target_long
);
1377 /* free register 'reg' by spilling the corresponding temporary if necessary */
1378 static void tcg_reg_free(TCGContext
*s
, int reg
)
1383 temp
= s
->reg_to_temp
[reg
];
1385 ts
= &s
->temps
[temp
];
1386 assert(ts
->val_type
== TEMP_VAL_REG
);
1387 if (!ts
->mem_coherent
) {
1388 if (!ts
->mem_allocated
)
1389 temp_allocate_frame(s
, temp
);
1390 tcg_out_st(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
1392 ts
->val_type
= TEMP_VAL_MEM
;
1393 s
->reg_to_temp
[reg
] = -1;
1397 /* Allocate a register belonging to reg1 & ~reg2 */
1398 static int tcg_reg_alloc(TCGContext
*s
, TCGRegSet reg1
, TCGRegSet reg2
)
1403 tcg_regset_andnot(reg_ct
, reg1
, reg2
);
1405 /* first try free registers */
1406 for(i
= 0; i
< ARRAY_SIZE(tcg_target_reg_alloc_order
); i
++) {
1407 reg
= tcg_target_reg_alloc_order
[i
];
1408 if (tcg_regset_test_reg(reg_ct
, reg
) && s
->reg_to_temp
[reg
] == -1)
1412 /* XXX: do better spill choice */
1413 for(i
= 0; i
< ARRAY_SIZE(tcg_target_reg_alloc_order
); i
++) {
1414 reg
= tcg_target_reg_alloc_order
[i
];
1415 if (tcg_regset_test_reg(reg_ct
, reg
)) {
1416 tcg_reg_free(s
, reg
);
1424 /* save a temporary to memory. 'allocated_regs' is used in case a
1425 temporary registers needs to be allocated to store a constant. */
1426 static void temp_save(TCGContext
*s
, int temp
, TCGRegSet allocated_regs
)
1431 ts
= &s
->temps
[temp
];
1432 if (!ts
->fixed_reg
) {
1433 switch(ts
->val_type
) {
1435 tcg_reg_free(s
, ts
->reg
);
1438 ts
->val_type
= TEMP_VAL_MEM
;
1440 case TEMP_VAL_CONST
:
1441 reg
= tcg_reg_alloc(s
, tcg_target_available_regs
[ts
->type
],
1443 if (!ts
->mem_allocated
)
1444 temp_allocate_frame(s
, temp
);
1445 tcg_out_movi(s
, ts
->type
, reg
, ts
->val
);
1446 tcg_out_st(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
1447 ts
->val_type
= TEMP_VAL_MEM
;
1457 /* save globals to their cannonical location and assume they can be
1458 modified be the following code. 'allocated_regs' is used in case a
1459 temporary registers needs to be allocated to store a constant. */
1460 static void save_globals(TCGContext
*s
, TCGRegSet allocated_regs
)
1464 for(i
= 0; i
< s
->nb_globals
; i
++) {
1465 temp_save(s
, i
, allocated_regs
);
1469 /* at the end of a basic block, we assume all temporaries are dead and
1470 all globals are stored at their canonical location. */
1471 static void tcg_reg_alloc_bb_end(TCGContext
*s
, TCGRegSet allocated_regs
)
1476 for(i
= s
->nb_globals
; i
< s
->nb_temps
; i
++) {
1478 if (ts
->temp_local
) {
1479 temp_save(s
, i
, allocated_regs
);
1481 if (ts
->val_type
== TEMP_VAL_REG
) {
1482 s
->reg_to_temp
[ts
->reg
] = -1;
1484 ts
->val_type
= TEMP_VAL_DEAD
;
1488 save_globals(s
, allocated_regs
);
1491 #define IS_DEAD_IARG(n) ((dead_iargs >> (n)) & 1)
1493 static void tcg_reg_alloc_movi(TCGContext
*s
, const TCGArg
*args
)
1496 tcg_target_ulong val
;
1498 ots
= &s
->temps
[args
[0]];
1501 if (ots
->fixed_reg
) {
1502 /* for fixed registers, we do not do any constant
1504 tcg_out_movi(s
, ots
->type
, ots
->reg
, val
);
1506 /* The movi is not explicitly generated here */
1507 if (ots
->val_type
== TEMP_VAL_REG
)
1508 s
->reg_to_temp
[ots
->reg
] = -1;
1509 ots
->val_type
= TEMP_VAL_CONST
;
1514 static void tcg_reg_alloc_mov(TCGContext
*s
, const TCGOpDef
*def
,
1516 unsigned int dead_iargs
)
1520 const TCGArgConstraint
*arg_ct
;
1522 ots
= &s
->temps
[args
[0]];
1523 ts
= &s
->temps
[args
[1]];
1524 arg_ct
= &def
->args_ct
[0];
1526 /* XXX: always mark arg dead if IS_DEAD_IARG(0) */
1527 if (ts
->val_type
== TEMP_VAL_REG
) {
1528 if (IS_DEAD_IARG(0) && !ts
->fixed_reg
&& !ots
->fixed_reg
) {
1529 /* the mov can be suppressed */
1530 if (ots
->val_type
== TEMP_VAL_REG
)
1531 s
->reg_to_temp
[ots
->reg
] = -1;
1533 s
->reg_to_temp
[reg
] = -1;
1534 ts
->val_type
= TEMP_VAL_DEAD
;
1536 if (ots
->val_type
== TEMP_VAL_REG
) {
1539 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, s
->reserved_regs
);
1541 if (ts
->reg
!= reg
) {
1542 tcg_out_mov(s
, reg
, ts
->reg
);
1545 } else if (ts
->val_type
== TEMP_VAL_MEM
) {
1546 if (ots
->val_type
== TEMP_VAL_REG
) {
1549 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, s
->reserved_regs
);
1551 tcg_out_ld(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
1552 } else if (ts
->val_type
== TEMP_VAL_CONST
) {
1553 if (ots
->fixed_reg
) {
1555 tcg_out_movi(s
, ots
->type
, reg
, ts
->val
);
1557 /* propagate constant */
1558 if (ots
->val_type
== TEMP_VAL_REG
)
1559 s
->reg_to_temp
[ots
->reg
] = -1;
1560 ots
->val_type
= TEMP_VAL_CONST
;
1567 s
->reg_to_temp
[reg
] = args
[0];
1569 ots
->val_type
= TEMP_VAL_REG
;
1570 ots
->mem_coherent
= 0;
1573 static void tcg_reg_alloc_op(TCGContext
*s
,
1574 const TCGOpDef
*def
, TCGOpcode opc
,
1576 unsigned int dead_iargs
)
1578 TCGRegSet allocated_regs
;
1579 int i
, k
, nb_iargs
, nb_oargs
, reg
;
1581 const TCGArgConstraint
*arg_ct
;
1583 TCGArg new_args
[TCG_MAX_OP_ARGS
];
1584 int const_args
[TCG_MAX_OP_ARGS
];
1586 nb_oargs
= def
->nb_oargs
;
1587 nb_iargs
= def
->nb_iargs
;
1589 /* copy constants */
1590 memcpy(new_args
+ nb_oargs
+ nb_iargs
,
1591 args
+ nb_oargs
+ nb_iargs
,
1592 sizeof(TCGArg
) * def
->nb_cargs
);
1594 /* satisfy input constraints */
1595 tcg_regset_set(allocated_regs
, s
->reserved_regs
);
1596 for(k
= 0; k
< nb_iargs
; k
++) {
1597 i
= def
->sorted_args
[nb_oargs
+ k
];
1599 arg_ct
= &def
->args_ct
[i
];
1600 ts
= &s
->temps
[arg
];
1601 if (ts
->val_type
== TEMP_VAL_MEM
) {
1602 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1603 tcg_out_ld(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
1604 ts
->val_type
= TEMP_VAL_REG
;
1606 ts
->mem_coherent
= 1;
1607 s
->reg_to_temp
[reg
] = arg
;
1608 } else if (ts
->val_type
== TEMP_VAL_CONST
) {
1609 if (tcg_target_const_match(ts
->val
, arg_ct
)) {
1610 /* constant is OK for instruction */
1612 new_args
[i
] = ts
->val
;
1615 /* need to move to a register */
1616 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1617 tcg_out_movi(s
, ts
->type
, reg
, ts
->val
);
1618 ts
->val_type
= TEMP_VAL_REG
;
1620 ts
->mem_coherent
= 0;
1621 s
->reg_to_temp
[reg
] = arg
;
1624 assert(ts
->val_type
== TEMP_VAL_REG
);
1625 if (arg_ct
->ct
& TCG_CT_IALIAS
) {
1626 if (ts
->fixed_reg
) {
1627 /* if fixed register, we must allocate a new register
1628 if the alias is not the same register */
1629 if (arg
!= args
[arg_ct
->alias_index
])
1630 goto allocate_in_reg
;
1632 /* if the input is aliased to an output and if it is
1633 not dead after the instruction, we must allocate
1634 a new register and move it */
1635 if (!IS_DEAD_IARG(i
- nb_oargs
))
1636 goto allocate_in_reg
;
1640 if (tcg_regset_test_reg(arg_ct
->u
.regs
, reg
)) {
1641 /* nothing to do : the constraint is satisfied */
1644 /* allocate a new register matching the constraint
1645 and move the temporary register into it */
1646 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1647 tcg_out_mov(s
, reg
, ts
->reg
);
1651 tcg_regset_set_reg(allocated_regs
, reg
);
1655 if (def
->flags
& TCG_OPF_BB_END
) {
1656 tcg_reg_alloc_bb_end(s
, allocated_regs
);
1658 /* mark dead temporaries and free the associated registers */
1659 for(i
= 0; i
< nb_iargs
; i
++) {
1660 arg
= args
[nb_oargs
+ i
];
1661 if (IS_DEAD_IARG(i
)) {
1662 ts
= &s
->temps
[arg
];
1663 if (!ts
->fixed_reg
) {
1664 if (ts
->val_type
== TEMP_VAL_REG
)
1665 s
->reg_to_temp
[ts
->reg
] = -1;
1666 ts
->val_type
= TEMP_VAL_DEAD
;
1671 if (def
->flags
& TCG_OPF_CALL_CLOBBER
) {
1672 /* XXX: permit generic clobber register list ? */
1673 for(reg
= 0; reg
< TCG_TARGET_NB_REGS
; reg
++) {
1674 if (tcg_regset_test_reg(tcg_target_call_clobber_regs
, reg
)) {
1675 tcg_reg_free(s
, reg
);
1678 /* XXX: for load/store we could do that only for the slow path
1679 (i.e. when a memory callback is called) */
1681 /* store globals and free associated registers (we assume the insn
1682 can modify any global. */
1683 save_globals(s
, allocated_regs
);
1686 /* satisfy the output constraints */
1687 tcg_regset_set(allocated_regs
, s
->reserved_regs
);
1688 for(k
= 0; k
< nb_oargs
; k
++) {
1689 i
= def
->sorted_args
[k
];
1691 arg_ct
= &def
->args_ct
[i
];
1692 ts
= &s
->temps
[arg
];
1693 if (arg_ct
->ct
& TCG_CT_ALIAS
) {
1694 reg
= new_args
[arg_ct
->alias_index
];
1696 /* if fixed register, we try to use it */
1698 if (ts
->fixed_reg
&&
1699 tcg_regset_test_reg(arg_ct
->u
.regs
, reg
)) {
1702 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1704 tcg_regset_set_reg(allocated_regs
, reg
);
1705 /* if a fixed register is used, then a move will be done afterwards */
1706 if (!ts
->fixed_reg
) {
1707 if (ts
->val_type
== TEMP_VAL_REG
)
1708 s
->reg_to_temp
[ts
->reg
] = -1;
1709 ts
->val_type
= TEMP_VAL_REG
;
1711 /* temp value is modified, so the value kept in memory is
1712 potentially not the same */
1713 ts
->mem_coherent
= 0;
1714 s
->reg_to_temp
[reg
] = arg
;
1721 /* emit instruction */
1722 tcg_out_op(s
, opc
, new_args
, const_args
);
1724 /* move the outputs in the correct register if needed */
1725 for(i
= 0; i
< nb_oargs
; i
++) {
1726 ts
= &s
->temps
[args
[i
]];
1728 if (ts
->fixed_reg
&& ts
->reg
!= reg
) {
1729 tcg_out_mov(s
, ts
->reg
, reg
);
1734 #ifdef TCG_TARGET_STACK_GROWSUP
1735 #define STACK_DIR(x) (-(x))
1737 #define STACK_DIR(x) (x)
1740 static int tcg_reg_alloc_call(TCGContext
*s
, const TCGOpDef
*def
,
1741 TCGOpcode opc
, const TCGArg
*args
,
1742 unsigned int dead_iargs
)
1744 int nb_iargs
, nb_oargs
, flags
, nb_regs
, i
, reg
, nb_params
;
1745 TCGArg arg
, func_arg
;
1747 tcg_target_long stack_offset
, call_stack_size
, func_addr
;
1748 int const_func_arg
, allocate_args
;
1749 TCGRegSet allocated_regs
;
1750 const TCGArgConstraint
*arg_ct
;
1754 nb_oargs
= arg
>> 16;
1755 nb_iargs
= arg
& 0xffff;
1756 nb_params
= nb_iargs
- 1;
1758 flags
= args
[nb_oargs
+ nb_iargs
];
1760 nb_regs
= tcg_target_get_call_iarg_regs_count(flags
);
1761 if (nb_regs
> nb_params
)
1762 nb_regs
= nb_params
;
1764 /* assign stack slots first */
1765 /* XXX: preallocate call stack */
1766 call_stack_size
= (nb_params
- nb_regs
) * sizeof(tcg_target_long
);
1767 call_stack_size
= (call_stack_size
+ TCG_TARGET_STACK_ALIGN
- 1) &
1768 ~(TCG_TARGET_STACK_ALIGN
- 1);
1769 allocate_args
= (call_stack_size
> TCG_STATIC_CALL_ARGS_SIZE
);
1770 if (allocate_args
) {
1771 tcg_out_addi(s
, TCG_REG_CALL_STACK
, -STACK_DIR(call_stack_size
));
1774 stack_offset
= TCG_TARGET_CALL_STACK_OFFSET
;
1775 for(i
= nb_regs
; i
< nb_params
; i
++) {
1776 arg
= args
[nb_oargs
+ i
];
1777 #ifdef TCG_TARGET_STACK_GROWSUP
1778 stack_offset
-= sizeof(tcg_target_long
);
1780 if (arg
!= TCG_CALL_DUMMY_ARG
) {
1781 ts
= &s
->temps
[arg
];
1782 if (ts
->val_type
== TEMP_VAL_REG
) {
1783 tcg_out_st(s
, ts
->type
, ts
->reg
, TCG_REG_CALL_STACK
, stack_offset
);
1784 } else if (ts
->val_type
== TEMP_VAL_MEM
) {
1785 reg
= tcg_reg_alloc(s
, tcg_target_available_regs
[ts
->type
],
1787 /* XXX: not correct if reading values from the stack */
1788 tcg_out_ld(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
1789 tcg_out_st(s
, ts
->type
, reg
, TCG_REG_CALL_STACK
, stack_offset
);
1790 } else if (ts
->val_type
== TEMP_VAL_CONST
) {
1791 reg
= tcg_reg_alloc(s
, tcg_target_available_regs
[ts
->type
],
1793 /* XXX: sign extend may be needed on some targets */
1794 tcg_out_movi(s
, ts
->type
, reg
, ts
->val
);
1795 tcg_out_st(s
, ts
->type
, reg
, TCG_REG_CALL_STACK
, stack_offset
);
1800 #ifndef TCG_TARGET_STACK_GROWSUP
1801 stack_offset
+= sizeof(tcg_target_long
);
1805 /* assign input registers */
1806 tcg_regset_set(allocated_regs
, s
->reserved_regs
);
1807 for(i
= 0; i
< nb_regs
; i
++) {
1808 arg
= args
[nb_oargs
+ i
];
1809 if (arg
!= TCG_CALL_DUMMY_ARG
) {
1810 ts
= &s
->temps
[arg
];
1811 reg
= tcg_target_call_iarg_regs
[i
];
1812 tcg_reg_free(s
, reg
);
1813 if (ts
->val_type
== TEMP_VAL_REG
) {
1814 if (ts
->reg
!= reg
) {
1815 tcg_out_mov(s
, reg
, ts
->reg
);
1817 } else if (ts
->val_type
== TEMP_VAL_MEM
) {
1818 tcg_out_ld(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
1819 } else if (ts
->val_type
== TEMP_VAL_CONST
) {
1820 /* XXX: sign extend ? */
1821 tcg_out_movi(s
, ts
->type
, reg
, ts
->val
);
1825 tcg_regset_set_reg(allocated_regs
, reg
);
1829 /* assign function address */
1830 func_arg
= args
[nb_oargs
+ nb_iargs
- 1];
1831 arg_ct
= &def
->args_ct
[0];
1832 ts
= &s
->temps
[func_arg
];
1833 func_addr
= ts
->val
;
1835 if (ts
->val_type
== TEMP_VAL_MEM
) {
1836 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1837 tcg_out_ld(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
1839 tcg_regset_set_reg(allocated_regs
, reg
);
1840 } else if (ts
->val_type
== TEMP_VAL_REG
) {
1842 if (!tcg_regset_test_reg(arg_ct
->u
.regs
, reg
)) {
1843 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1844 tcg_out_mov(s
, reg
, ts
->reg
);
1847 tcg_regset_set_reg(allocated_regs
, reg
);
1848 } else if (ts
->val_type
== TEMP_VAL_CONST
) {
1849 if (tcg_target_const_match(func_addr
, arg_ct
)) {
1851 func_arg
= func_addr
;
1853 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1854 tcg_out_movi(s
, ts
->type
, reg
, func_addr
);
1856 tcg_regset_set_reg(allocated_regs
, reg
);
1863 /* mark dead temporaries and free the associated registers */
1864 for(i
= 0; i
< nb_iargs
; i
++) {
1865 arg
= args
[nb_oargs
+ i
];
1866 if (IS_DEAD_IARG(i
)) {
1867 ts
= &s
->temps
[arg
];
1868 if (!ts
->fixed_reg
) {
1869 if (ts
->val_type
== TEMP_VAL_REG
)
1870 s
->reg_to_temp
[ts
->reg
] = -1;
1871 ts
->val_type
= TEMP_VAL_DEAD
;
1876 /* clobber call registers */
1877 for(reg
= 0; reg
< TCG_TARGET_NB_REGS
; reg
++) {
1878 if (tcg_regset_test_reg(tcg_target_call_clobber_regs
, reg
)) {
1879 tcg_reg_free(s
, reg
);
1883 /* store globals and free associated registers (we assume the call
1884 can modify any global. */
1885 if (!(flags
& TCG_CALL_CONST
)) {
1886 save_globals(s
, allocated_regs
);
1889 tcg_out_op(s
, opc
, &func_arg
, &const_func_arg
);
1891 if (allocate_args
) {
1892 tcg_out_addi(s
, TCG_REG_CALL_STACK
, STACK_DIR(call_stack_size
));
1895 /* assign output registers and emit moves if needed */
1896 for(i
= 0; i
< nb_oargs
; i
++) {
1898 ts
= &s
->temps
[arg
];
1899 reg
= tcg_target_call_oarg_regs
[i
];
1900 assert(s
->reg_to_temp
[reg
] == -1);
1901 if (ts
->fixed_reg
) {
1902 if (ts
->reg
!= reg
) {
1903 tcg_out_mov(s
, ts
->reg
, reg
);
1906 if (ts
->val_type
== TEMP_VAL_REG
)
1907 s
->reg_to_temp
[ts
->reg
] = -1;
1908 ts
->val_type
= TEMP_VAL_REG
;
1910 ts
->mem_coherent
= 0;
1911 s
->reg_to_temp
[reg
] = arg
;
1915 return nb_iargs
+ nb_oargs
+ def
->nb_cargs
+ 1;
1918 #ifdef CONFIG_PROFILER
1920 static int64_t tcg_table_op_count
[NB_OPS
];
1922 static void dump_op_count(void)
1926 f
= fopen("/tmp/op.log", "w");
1927 for(i
= INDEX_op_end
; i
< NB_OPS
; i
++) {
1928 fprintf(f
, "%s %" PRId64
"\n", tcg_op_defs
[i
].name
, tcg_table_op_count
[i
]);
1935 static inline int tcg_gen_code_common(TCGContext
*s
, uint8_t *gen_code_buf
,
1940 const TCGOpDef
*def
;
1941 unsigned int dead_iargs
;
1945 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP
))) {
1947 tcg_dump_ops(s
, logfile
);
1952 #ifdef CONFIG_PROFILER
1953 s
->la_time
-= profile_getclock();
1955 tcg_liveness_analysis(s
);
1956 #ifdef CONFIG_PROFILER
1957 s
->la_time
+= profile_getclock();
1961 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_OPT
))) {
1962 qemu_log("OP after liveness analysis:\n");
1963 tcg_dump_ops(s
, logfile
);
1968 tcg_reg_alloc_start(s
);
1970 s
->code_buf
= gen_code_buf
;
1971 s
->code_ptr
= gen_code_buf
;
1973 args
= gen_opparam_buf
;
1977 opc
= gen_opc_buf
[op_index
];
1978 #ifdef CONFIG_PROFILER
1979 tcg_table_op_count
[opc
]++;
1981 def
= &tcg_op_defs
[opc
];
1983 printf("%s: %d %d %d\n", def
->name
,
1984 def
->nb_oargs
, def
->nb_iargs
, def
->nb_cargs
);
1988 case INDEX_op_mov_i32
:
1989 #if TCG_TARGET_REG_BITS == 64
1990 case INDEX_op_mov_i64
:
1992 dead_iargs
= s
->op_dead_iargs
[op_index
];
1993 tcg_reg_alloc_mov(s
, def
, args
, dead_iargs
);
1995 case INDEX_op_movi_i32
:
1996 #if TCG_TARGET_REG_BITS == 64
1997 case INDEX_op_movi_i64
:
1999 tcg_reg_alloc_movi(s
, args
);
2001 case INDEX_op_debug_insn_start
:
2002 /* debug instruction */
2012 case INDEX_op_discard
:
2015 ts
= &s
->temps
[args
[0]];
2016 /* mark the temporary as dead */
2017 if (!ts
->fixed_reg
) {
2018 if (ts
->val_type
== TEMP_VAL_REG
)
2019 s
->reg_to_temp
[ts
->reg
] = -1;
2020 ts
->val_type
= TEMP_VAL_DEAD
;
2024 case INDEX_op_set_label
:
2025 tcg_reg_alloc_bb_end(s
, s
->reserved_regs
);
2026 tcg_out_label(s
, args
[0], (long)s
->code_ptr
);
2029 dead_iargs
= s
->op_dead_iargs
[op_index
];
2030 args
+= tcg_reg_alloc_call(s
, def
, opc
, args
, dead_iargs
);
2035 /* Note: in order to speed up the code, it would be much
2036 faster to have specialized register allocator functions for
2037 some common argument patterns */
2038 dead_iargs
= s
->op_dead_iargs
[op_index
];
2039 tcg_reg_alloc_op(s
, def
, opc
, args
, dead_iargs
);
2042 args
+= def
->nb_args
;
2044 if (search_pc
>= 0 && search_pc
< s
->code_ptr
- gen_code_buf
) {
2056 int tcg_gen_code(TCGContext
*s
, uint8_t *gen_code_buf
)
2058 #ifdef CONFIG_PROFILER
2061 n
= (gen_opc_ptr
- gen_opc_buf
);
2063 if (n
> s
->op_count_max
)
2064 s
->op_count_max
= n
;
2066 s
->temp_count
+= s
->nb_temps
;
2067 if (s
->nb_temps
> s
->temp_count_max
)
2068 s
->temp_count_max
= s
->nb_temps
;
2072 tcg_gen_code_common(s
, gen_code_buf
, -1);
2074 /* flush instruction cache */
2075 flush_icache_range((unsigned long)gen_code_buf
,
2076 (unsigned long)s
->code_ptr
);
2077 return s
->code_ptr
- gen_code_buf
;
2080 /* Return the index of the micro operation such as the pc after is <
2081 offset bytes from the start of the TB. The contents of gen_code_buf must
2082 not be changed, though writing the same values is ok.
2083 Return -1 if not found. */
2084 int tcg_gen_code_search_pc(TCGContext
*s
, uint8_t *gen_code_buf
, long offset
)
2086 return tcg_gen_code_common(s
, gen_code_buf
, offset
);
2089 #ifdef CONFIG_PROFILER
2090 void tcg_dump_info(FILE *f
,
2091 int (*cpu_fprintf
)(FILE *f
, const char *fmt
, ...))
2093 TCGContext
*s
= &tcg_ctx
;
2096 tot
= s
->interm_time
+ s
->code_time
;
2097 cpu_fprintf(f
, "JIT cycles %" PRId64
" (%0.3f s at 2.4 GHz)\n",
2099 cpu_fprintf(f
, "translated TBs %" PRId64
" (aborted=%" PRId64
" %0.1f%%)\n",
2101 s
->tb_count1
- s
->tb_count
,
2102 s
->tb_count1
? (double)(s
->tb_count1
- s
->tb_count
) / s
->tb_count1
* 100.0 : 0);
2103 cpu_fprintf(f
, "avg ops/TB %0.1f max=%d\n",
2104 s
->tb_count
? (double)s
->op_count
/ s
->tb_count
: 0, s
->op_count_max
);
2105 cpu_fprintf(f
, "deleted ops/TB %0.2f\n",
2107 (double)s
->del_op_count
/ s
->tb_count
: 0);
2108 cpu_fprintf(f
, "avg temps/TB %0.2f max=%d\n",
2110 (double)s
->temp_count
/ s
->tb_count
: 0,
2113 cpu_fprintf(f
, "cycles/op %0.1f\n",
2114 s
->op_count
? (double)tot
/ s
->op_count
: 0);
2115 cpu_fprintf(f
, "cycles/in byte %0.1f\n",
2116 s
->code_in_len
? (double)tot
/ s
->code_in_len
: 0);
2117 cpu_fprintf(f
, "cycles/out byte %0.1f\n",
2118 s
->code_out_len
? (double)tot
/ s
->code_out_len
: 0);
2121 cpu_fprintf(f
, " gen_interm time %0.1f%%\n",
2122 (double)s
->interm_time
/ tot
* 100.0);
2123 cpu_fprintf(f
, " gen_code time %0.1f%%\n",
2124 (double)s
->code_time
/ tot
* 100.0);
2125 cpu_fprintf(f
, "liveness/code time %0.1f%%\n",
2126 (double)s
->la_time
/ (s
->code_time
? s
->code_time
: 1) * 100.0);
2127 cpu_fprintf(f
, "cpu_restore count %" PRId64
"\n",
2129 cpu_fprintf(f
, " avg cycles %0.1f\n",
2130 s
->restore_count
? (double)s
->restore_time
/ s
->restore_count
: 0);
2135 void tcg_dump_info(FILE *f
,
2136 int (*cpu_fprintf
)(FILE *f
, const char *fmt
, ...))
2138 cpu_fprintf(f
, "[TCG profiler not compiled]\n");