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 patch_reloc(uint8_t *code_ptr
, int type
,
67 tcg_target_long value
, tcg_target_long addend
);
69 static TCGOpDef tcg_op_defs
[] = {
70 #define DEF(s, n, copy_size) { #s, 0, 0, n, n, 0, copy_size },
71 #define DEF2(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 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
;
244 /* init global prologue and epilogue */
245 s
->code_buf
= code_gen_prologue
;
246 s
->code_ptr
= s
->code_buf
;
247 tcg_target_qemu_prologue(s
);
248 flush_icache_range((unsigned long)s
->code_buf
,
249 (unsigned long)s
->code_ptr
);
252 void tcg_set_frame(TCGContext
*s
, int reg
,
253 tcg_target_long start
, tcg_target_long size
)
255 s
->frame_start
= start
;
256 s
->frame_end
= start
+ size
;
260 void tcg_func_start(TCGContext
*s
)
264 s
->nb_temps
= s
->nb_globals
;
265 for(i
= 0; i
< (TCG_TYPE_COUNT
* 2); i
++)
266 s
->first_free_temp
[i
] = -1;
267 s
->labels
= tcg_malloc(sizeof(TCGLabel
) * TCG_MAX_LABELS
);
269 s
->current_frame_offset
= s
->frame_start
;
271 gen_opc_ptr
= gen_opc_buf
;
272 gen_opparam_ptr
= gen_opparam_buf
;
275 static inline void tcg_temp_alloc(TCGContext
*s
, int n
)
277 if (n
> TCG_MAX_TEMPS
)
281 static inline int tcg_global_reg_new_internal(TCGType type
, int reg
,
284 TCGContext
*s
= &tcg_ctx
;
288 #if TCG_TARGET_REG_BITS == 32
289 if (type
!= TCG_TYPE_I32
)
292 if (tcg_regset_test_reg(s
->reserved_regs
, reg
))
295 tcg_temp_alloc(s
, s
->nb_globals
+ 1);
296 ts
= &s
->temps
[s
->nb_globals
];
297 ts
->base_type
= type
;
303 tcg_regset_set_reg(s
->reserved_regs
, reg
);
307 TCGv_i32
tcg_global_reg_new_i32(int reg
, const char *name
)
311 idx
= tcg_global_reg_new_internal(TCG_TYPE_I32
, reg
, name
);
312 return MAKE_TCGV_I32(idx
);
315 TCGv_i64
tcg_global_reg_new_i64(int reg
, const char *name
)
319 idx
= tcg_global_reg_new_internal(TCG_TYPE_I64
, reg
, name
);
320 return MAKE_TCGV_I64(idx
);
323 static inline int tcg_global_mem_new_internal(TCGType type
, int reg
,
324 tcg_target_long offset
,
327 TCGContext
*s
= &tcg_ctx
;
332 #if TCG_TARGET_REG_BITS == 32
333 if (type
== TCG_TYPE_I64
) {
335 tcg_temp_alloc(s
, s
->nb_globals
+ 2);
336 ts
= &s
->temps
[s
->nb_globals
];
337 ts
->base_type
= type
;
338 ts
->type
= TCG_TYPE_I32
;
340 ts
->mem_allocated
= 1;
342 #ifdef TCG_TARGET_WORDS_BIGENDIAN
343 ts
->mem_offset
= offset
+ 4;
345 ts
->mem_offset
= offset
;
347 pstrcpy(buf
, sizeof(buf
), name
);
348 pstrcat(buf
, sizeof(buf
), "_0");
349 ts
->name
= strdup(buf
);
352 ts
->base_type
= type
;
353 ts
->type
= TCG_TYPE_I32
;
355 ts
->mem_allocated
= 1;
357 #ifdef TCG_TARGET_WORDS_BIGENDIAN
358 ts
->mem_offset
= offset
;
360 ts
->mem_offset
= offset
+ 4;
362 pstrcpy(buf
, sizeof(buf
), name
);
363 pstrcat(buf
, sizeof(buf
), "_1");
364 ts
->name
= strdup(buf
);
370 tcg_temp_alloc(s
, s
->nb_globals
+ 1);
371 ts
= &s
->temps
[s
->nb_globals
];
372 ts
->base_type
= type
;
375 ts
->mem_allocated
= 1;
377 ts
->mem_offset
= offset
;
384 TCGv_i32
tcg_global_mem_new_i32(int reg
, tcg_target_long offset
,
389 idx
= tcg_global_mem_new_internal(TCG_TYPE_I32
, reg
, offset
, name
);
390 return MAKE_TCGV_I32(idx
);
393 TCGv_i64
tcg_global_mem_new_i64(int reg
, tcg_target_long offset
,
398 idx
= tcg_global_mem_new_internal(TCG_TYPE_I64
, reg
, offset
, name
);
399 return MAKE_TCGV_I64(idx
);
402 static inline int tcg_temp_new_internal(TCGType type
, int temp_local
)
404 TCGContext
*s
= &tcg_ctx
;
411 idx
= s
->first_free_temp
[k
];
413 /* There is already an available temp with the
416 s
->first_free_temp
[k
] = ts
->next_free_temp
;
417 ts
->temp_allocated
= 1;
418 assert(ts
->temp_local
== temp_local
);
421 #if TCG_TARGET_REG_BITS == 32
422 if (type
== TCG_TYPE_I64
) {
423 tcg_temp_alloc(s
, s
->nb_temps
+ 2);
424 ts
= &s
->temps
[s
->nb_temps
];
425 ts
->base_type
= type
;
426 ts
->type
= TCG_TYPE_I32
;
427 ts
->temp_allocated
= 1;
428 ts
->temp_local
= temp_local
;
431 ts
->base_type
= TCG_TYPE_I32
;
432 ts
->type
= TCG_TYPE_I32
;
433 ts
->temp_allocated
= 1;
434 ts
->temp_local
= temp_local
;
440 tcg_temp_alloc(s
, s
->nb_temps
+ 1);
441 ts
= &s
->temps
[s
->nb_temps
];
442 ts
->base_type
= type
;
444 ts
->temp_allocated
= 1;
445 ts
->temp_local
= temp_local
;
453 TCGv_i32
tcg_temp_new_internal_i32(int temp_local
)
457 idx
= tcg_temp_new_internal(TCG_TYPE_I32
, temp_local
);
458 return MAKE_TCGV_I32(idx
);
461 TCGv_i64
tcg_temp_new_internal_i64(int temp_local
)
465 idx
= tcg_temp_new_internal(TCG_TYPE_I64
, temp_local
);
466 return MAKE_TCGV_I64(idx
);
469 static inline void tcg_temp_free_internal(int idx
)
471 TCGContext
*s
= &tcg_ctx
;
475 assert(idx
>= s
->nb_globals
&& idx
< s
->nb_temps
);
477 assert(ts
->temp_allocated
!= 0);
478 ts
->temp_allocated
= 0;
482 ts
->next_free_temp
= s
->first_free_temp
[k
];
483 s
->first_free_temp
[k
] = idx
;
486 void tcg_temp_free_i32(TCGv_i32 arg
)
488 tcg_temp_free_internal(GET_TCGV_I32(arg
));
491 void tcg_temp_free_i64(TCGv_i64 arg
)
493 tcg_temp_free_internal(GET_TCGV_I64(arg
));
496 TCGv_i32
tcg_const_i32(int32_t val
)
499 t0
= tcg_temp_new_i32();
500 tcg_gen_movi_i32(t0
, val
);
504 TCGv_i64
tcg_const_i64(int64_t val
)
507 t0
= tcg_temp_new_i64();
508 tcg_gen_movi_i64(t0
, val
);
512 TCGv_i32
tcg_const_local_i32(int32_t val
)
515 t0
= tcg_temp_local_new_i32();
516 tcg_gen_movi_i32(t0
, val
);
520 TCGv_i64
tcg_const_local_i64(int64_t val
)
523 t0
= tcg_temp_local_new_i64();
524 tcg_gen_movi_i64(t0
, val
);
528 void tcg_register_helper(void *func
, const char *name
)
530 TCGContext
*s
= &tcg_ctx
;
532 if ((s
->nb_helpers
+ 1) > s
->allocated_helpers
) {
533 n
= s
->allocated_helpers
;
539 s
->helpers
= realloc(s
->helpers
, n
* sizeof(TCGHelperInfo
));
540 s
->allocated_helpers
= n
;
542 s
->helpers
[s
->nb_helpers
].func
= (tcg_target_ulong
)func
;
543 s
->helpers
[s
->nb_helpers
].name
= name
;
547 /* Note: we convert the 64 bit args to 32 bit and do some alignment
548 and endian swap. Maybe it would be better to do the alignment
549 and endian swap in tcg_reg_alloc_call(). */
550 void tcg_gen_callN(TCGContext
*s
, TCGv_ptr func
, unsigned int flags
,
551 int sizemask
, TCGArg ret
, int nargs
, TCGArg
*args
)
558 *gen_opc_ptr
++ = INDEX_op_call
;
559 nparam
= gen_opparam_ptr
++;
560 call_type
= (flags
& TCG_CALL_TYPE_MASK
);
561 if (ret
!= TCG_CALL_DUMMY_ARG
) {
562 #if TCG_TARGET_REG_BITS < 64
564 #ifdef TCG_TARGET_WORDS_BIGENDIAN
565 *gen_opparam_ptr
++ = ret
+ 1;
566 *gen_opparam_ptr
++ = ret
;
568 *gen_opparam_ptr
++ = ret
;
569 *gen_opparam_ptr
++ = ret
+ 1;
575 *gen_opparam_ptr
++ = ret
;
582 for (i
= 0; i
< nargs
; i
++) {
583 #if TCG_TARGET_REG_BITS < 64
584 if (sizemask
& (2 << i
)) {
585 #ifdef TCG_TARGET_I386
586 /* REGPARM case: if the third parameter is 64 bit, it is
587 allocated on the stack */
588 if (i
== 2 && call_type
== TCG_CALL_TYPE_REGPARM
) {
589 call_type
= TCG_CALL_TYPE_REGPARM_2
;
590 flags
= (flags
& ~TCG_CALL_TYPE_MASK
) | call_type
;
593 #ifdef TCG_TARGET_CALL_ALIGN_ARGS
594 /* some targets want aligned 64 bit args */
596 *gen_opparam_ptr
++ = TCG_CALL_DUMMY_ARG
;
600 /* If stack grows up, then we will be placing successive
601 arguments at lower addresses, which means we need to
602 reverse the order compared to how we would normally
603 treat either big or little-endian. For those arguments
604 that will wind up in registers, this still works for
605 HPPA (the only current STACK_GROWSUP target) since the
606 argument registers are *also* allocated in decreasing
607 order. If another such target is added, this logic may
608 have to get more complicated to differentiate between
609 stack arguments and register arguments. */
610 #if defined(TCG_TARGET_WORDS_BIGENDIAN) != defined(TCG_TARGET_STACK_GROWSUP)
611 *gen_opparam_ptr
++ = args
[i
] + 1;
612 *gen_opparam_ptr
++ = args
[i
];
614 *gen_opparam_ptr
++ = args
[i
];
615 *gen_opparam_ptr
++ = args
[i
] + 1;
621 *gen_opparam_ptr
++ = args
[i
];
625 *gen_opparam_ptr
++ = GET_TCGV_PTR(func
);
627 *gen_opparam_ptr
++ = flags
;
629 *nparam
= (nb_rets
<< 16) | (real_args
+ 1);
631 /* total parameters, needed to go backward in the instruction stream */
632 *gen_opparam_ptr
++ = 1 + nb_rets
+ real_args
+ 3;
635 #if TCG_TARGET_REG_BITS == 32
636 void tcg_gen_shifti_i64(TCGv_i64 ret
, TCGv_i64 arg1
,
637 int c
, int right
, int arith
)
640 tcg_gen_mov_i32(TCGV_LOW(ret
), TCGV_LOW(arg1
));
641 tcg_gen_mov_i32(TCGV_HIGH(ret
), TCGV_HIGH(arg1
));
642 } else if (c
>= 32) {
646 tcg_gen_sari_i32(TCGV_LOW(ret
), TCGV_HIGH(arg1
), c
);
647 tcg_gen_sari_i32(TCGV_HIGH(ret
), TCGV_HIGH(arg1
), 31);
649 tcg_gen_shri_i32(TCGV_LOW(ret
), TCGV_HIGH(arg1
), c
);
650 tcg_gen_movi_i32(TCGV_HIGH(ret
), 0);
653 tcg_gen_shli_i32(TCGV_HIGH(ret
), TCGV_LOW(arg1
), c
);
654 tcg_gen_movi_i32(TCGV_LOW(ret
), 0);
659 t0
= tcg_temp_new_i32();
660 t1
= tcg_temp_new_i32();
662 tcg_gen_shli_i32(t0
, TCGV_HIGH(arg1
), 32 - c
);
664 tcg_gen_sari_i32(t1
, TCGV_HIGH(arg1
), c
);
666 tcg_gen_shri_i32(t1
, TCGV_HIGH(arg1
), c
);
667 tcg_gen_shri_i32(TCGV_LOW(ret
), TCGV_LOW(arg1
), c
);
668 tcg_gen_or_i32(TCGV_LOW(ret
), TCGV_LOW(ret
), t0
);
669 tcg_gen_mov_i32(TCGV_HIGH(ret
), t1
);
671 tcg_gen_shri_i32(t0
, TCGV_LOW(arg1
), 32 - c
);
672 /* Note: ret can be the same as arg1, so we use t1 */
673 tcg_gen_shli_i32(t1
, TCGV_LOW(arg1
), c
);
674 tcg_gen_shli_i32(TCGV_HIGH(ret
), TCGV_HIGH(arg1
), c
);
675 tcg_gen_or_i32(TCGV_HIGH(ret
), TCGV_HIGH(ret
), t0
);
676 tcg_gen_mov_i32(TCGV_LOW(ret
), t1
);
678 tcg_temp_free_i32(t0
);
679 tcg_temp_free_i32(t1
);
685 static void tcg_reg_alloc_start(TCGContext
*s
)
689 for(i
= 0; i
< s
->nb_globals
; i
++) {
692 ts
->val_type
= TEMP_VAL_REG
;
694 ts
->val_type
= TEMP_VAL_MEM
;
697 for(i
= s
->nb_globals
; i
< s
->nb_temps
; i
++) {
699 ts
->val_type
= TEMP_VAL_DEAD
;
700 ts
->mem_allocated
= 0;
703 for(i
= 0; i
< TCG_TARGET_NB_REGS
; i
++) {
704 s
->reg_to_temp
[i
] = -1;
708 static char *tcg_get_arg_str_idx(TCGContext
*s
, char *buf
, int buf_size
,
714 if (idx
< s
->nb_globals
) {
715 pstrcpy(buf
, buf_size
, ts
->name
);
718 snprintf(buf
, buf_size
, "loc%d", idx
- s
->nb_globals
);
720 snprintf(buf
, buf_size
, "tmp%d", idx
- s
->nb_globals
);
725 char *tcg_get_arg_str_i32(TCGContext
*s
, char *buf
, int buf_size
, TCGv_i32 arg
)
727 return tcg_get_arg_str_idx(s
, buf
, buf_size
, GET_TCGV_I32(arg
));
730 char *tcg_get_arg_str_i64(TCGContext
*s
, char *buf
, int buf_size
, TCGv_i64 arg
)
732 return tcg_get_arg_str_idx(s
, buf
, buf_size
, GET_TCGV_I64(arg
));
735 static int helper_cmp(const void *p1
, const void *p2
)
737 const TCGHelperInfo
*th1
= p1
;
738 const TCGHelperInfo
*th2
= p2
;
739 if (th1
->func
< th2
->func
)
741 else if (th1
->func
== th2
->func
)
747 /* find helper definition (Note: A hash table would be better) */
748 static TCGHelperInfo
*tcg_find_helper(TCGContext
*s
, tcg_target_ulong val
)
754 if (unlikely(!s
->helpers_sorted
)) {
755 qsort(s
->helpers
, s
->nb_helpers
, sizeof(TCGHelperInfo
),
757 s
->helpers_sorted
= 1;
762 m_max
= s
->nb_helpers
- 1;
763 while (m_min
<= m_max
) {
764 m
= (m_min
+ m_max
) >> 1;
778 static const char * const cond_name
[] =
780 [TCG_COND_EQ
] = "eq",
781 [TCG_COND_NE
] = "ne",
782 [TCG_COND_LT
] = "lt",
783 [TCG_COND_GE
] = "ge",
784 [TCG_COND_LE
] = "le",
785 [TCG_COND_GT
] = "gt",
786 [TCG_COND_LTU
] = "ltu",
787 [TCG_COND_GEU
] = "geu",
788 [TCG_COND_LEU
] = "leu",
789 [TCG_COND_GTU
] = "gtu"
792 void tcg_dump_ops(TCGContext
*s
, FILE *outfile
)
794 const uint16_t *opc_ptr
;
798 int i
, k
, nb_oargs
, nb_iargs
, nb_cargs
, first_insn
;
803 opc_ptr
= gen_opc_buf
;
804 args
= gen_opparam_buf
;
805 while (opc_ptr
< gen_opc_ptr
) {
807 def
= &tcg_op_defs
[c
];
808 if (c
== INDEX_op_debug_insn_start
) {
810 #if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
811 pc
= ((uint64_t)args
[1] << 32) | args
[0];
816 fprintf(outfile
, "\n");
817 fprintf(outfile
, " ---- 0x%" PRIx64
, pc
);
819 nb_oargs
= def
->nb_oargs
;
820 nb_iargs
= def
->nb_iargs
;
821 nb_cargs
= def
->nb_cargs
;
822 } else if (c
== INDEX_op_call
) {
825 /* variable number of arguments */
827 nb_oargs
= arg
>> 16;
828 nb_iargs
= arg
& 0xffff;
829 nb_cargs
= def
->nb_cargs
;
831 fprintf(outfile
, " %s ", def
->name
);
834 fprintf(outfile
, "%s",
835 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), args
[nb_oargs
+ nb_iargs
- 1]));
837 fprintf(outfile
, ",$0x%" TCG_PRIlx
,
838 args
[nb_oargs
+ nb_iargs
]);
840 fprintf(outfile
, ",$%d", nb_oargs
);
841 for(i
= 0; i
< nb_oargs
; i
++) {
842 fprintf(outfile
, ",");
843 fprintf(outfile
, "%s",
844 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), args
[i
]));
846 for(i
= 0; i
< (nb_iargs
- 1); i
++) {
847 fprintf(outfile
, ",");
848 if (args
[nb_oargs
+ i
] == TCG_CALL_DUMMY_ARG
) {
849 fprintf(outfile
, "<dummy>");
851 fprintf(outfile
, "%s",
852 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), args
[nb_oargs
+ i
]));
855 } else if (c
== INDEX_op_movi_i32
856 #if TCG_TARGET_REG_BITS == 64
857 || c
== INDEX_op_movi_i64
860 tcg_target_ulong val
;
863 nb_oargs
= def
->nb_oargs
;
864 nb_iargs
= def
->nb_iargs
;
865 nb_cargs
= def
->nb_cargs
;
866 fprintf(outfile
, " %s %s,$", def
->name
,
867 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), args
[0]));
869 th
= tcg_find_helper(s
, val
);
871 fprintf(outfile
, "%s", th
->name
);
873 if (c
== INDEX_op_movi_i32
)
874 fprintf(outfile
, "0x%x", (uint32_t)val
);
876 fprintf(outfile
, "0x%" PRIx64
, (uint64_t)val
);
879 fprintf(outfile
, " %s ", def
->name
);
880 if (c
== INDEX_op_nopn
) {
881 /* variable number of arguments */
886 nb_oargs
= def
->nb_oargs
;
887 nb_iargs
= def
->nb_iargs
;
888 nb_cargs
= def
->nb_cargs
;
892 for(i
= 0; i
< nb_oargs
; i
++) {
894 fprintf(outfile
, ",");
895 fprintf(outfile
, "%s",
896 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), args
[k
++]));
898 for(i
= 0; i
< nb_iargs
; i
++) {
900 fprintf(outfile
, ",");
901 fprintf(outfile
, "%s",
902 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), args
[k
++]));
905 case INDEX_op_brcond_i32
:
906 #if TCG_TARGET_REG_BITS == 32
907 case INDEX_op_brcond2_i32
:
908 #elif TCG_TARGET_REG_BITS == 64
909 case INDEX_op_brcond_i64
:
911 case INDEX_op_setcond_i32
:
912 #if TCG_TARGET_REG_BITS == 32
913 case INDEX_op_setcond2_i32
:
914 #elif TCG_TARGET_REG_BITS == 64
915 case INDEX_op_setcond_i64
:
917 if (args
[k
] < ARRAY_SIZE(cond_name
) && cond_name
[args
[k
]])
918 fprintf(outfile
, ",%s", cond_name
[args
[k
++]]);
920 fprintf(outfile
, ",$0x%" TCG_PRIlx
, args
[k
++]);
927 for(; i
< nb_cargs
; i
++) {
929 fprintf(outfile
, ",");
931 fprintf(outfile
, "$0x%" TCG_PRIlx
, arg
);
934 fprintf(outfile
, "\n");
935 args
+= nb_iargs
+ nb_oargs
+ nb_cargs
;
939 /* we give more priority to constraints with less registers */
940 static int get_constraint_priority(const TCGOpDef
*def
, int k
)
942 const TCGArgConstraint
*arg_ct
;
945 arg_ct
= &def
->args_ct
[k
];
946 if (arg_ct
->ct
& TCG_CT_ALIAS
) {
947 /* an alias is equivalent to a single register */
950 if (!(arg_ct
->ct
& TCG_CT_REG
))
953 for(i
= 0; i
< TCG_TARGET_NB_REGS
; i
++) {
954 if (tcg_regset_test_reg(arg_ct
->u
.regs
, i
))
958 return TCG_TARGET_NB_REGS
- n
+ 1;
961 /* sort from highest priority to lowest */
962 static void sort_constraints(TCGOpDef
*def
, int start
, int n
)
964 int i
, j
, p1
, p2
, tmp
;
966 for(i
= 0; i
< n
; i
++)
967 def
->sorted_args
[start
+ i
] = start
+ i
;
970 for(i
= 0; i
< n
- 1; i
++) {
971 for(j
= i
+ 1; j
< n
; j
++) {
972 p1
= get_constraint_priority(def
, def
->sorted_args
[start
+ i
]);
973 p2
= get_constraint_priority(def
, def
->sorted_args
[start
+ j
]);
975 tmp
= def
->sorted_args
[start
+ i
];
976 def
->sorted_args
[start
+ i
] = def
->sorted_args
[start
+ j
];
977 def
->sorted_args
[start
+ j
] = tmp
;
983 void tcg_add_target_add_op_defs(const TCGTargetOpDef
*tdefs
)
991 if (tdefs
->op
== (TCGOpcode
)-1)
994 assert(op
>= 0 && op
< NB_OPS
);
995 def
= &tcg_op_defs
[op
];
996 #if defined(CONFIG_DEBUG_TCG)
997 /* Duplicate entry in op definitions? */
1001 nb_args
= def
->nb_iargs
+ def
->nb_oargs
;
1002 for(i
= 0; i
< nb_args
; i
++) {
1003 ct_str
= tdefs
->args_ct_str
[i
];
1004 /* Incomplete TCGTargetOpDef entry? */
1005 assert(ct_str
!= NULL
);
1006 tcg_regset_clear(def
->args_ct
[i
].u
.regs
);
1007 def
->args_ct
[i
].ct
= 0;
1008 if (ct_str
[0] >= '0' && ct_str
[0] <= '9') {
1010 oarg
= ct_str
[0] - '0';
1011 assert(oarg
< def
->nb_oargs
);
1012 assert(def
->args_ct
[oarg
].ct
& TCG_CT_REG
);
1013 /* TCG_CT_ALIAS is for the output arguments. The input
1014 argument is tagged with TCG_CT_IALIAS. */
1015 def
->args_ct
[i
] = def
->args_ct
[oarg
];
1016 def
->args_ct
[oarg
].ct
= TCG_CT_ALIAS
;
1017 def
->args_ct
[oarg
].alias_index
= i
;
1018 def
->args_ct
[i
].ct
|= TCG_CT_IALIAS
;
1019 def
->args_ct
[i
].alias_index
= oarg
;
1022 if (*ct_str
== '\0')
1026 def
->args_ct
[i
].ct
|= TCG_CT_CONST
;
1030 if (target_parse_constraint(&def
->args_ct
[i
], &ct_str
) < 0) {
1031 fprintf(stderr
, "Invalid constraint '%s' for arg %d of operation '%s'\n",
1032 ct_str
, i
, def
->name
);
1040 /* TCGTargetOpDef entry with too much information? */
1041 assert(i
== TCG_MAX_OP_ARGS
|| tdefs
->args_ct_str
[i
] == NULL
);
1043 /* sort the constraints (XXX: this is just an heuristic) */
1044 sort_constraints(def
, 0, def
->nb_oargs
);
1045 sort_constraints(def
, def
->nb_oargs
, def
->nb_iargs
);
1051 printf("%s: sorted=", def
->name
);
1052 for(i
= 0; i
< def
->nb_oargs
+ def
->nb_iargs
; i
++)
1053 printf(" %d", def
->sorted_args
[i
]);
1060 #if defined(CONFIG_DEBUG_TCG)
1062 for (op
= 0; op
< ARRAY_SIZE(tcg_op_defs
); op
++) {
1063 if (op
< INDEX_op_call
|| op
== INDEX_op_debug_insn_start
) {
1064 /* Wrong entry in op definitions? */
1065 if (tcg_op_defs
[op
].used
) {
1066 fprintf(stderr
, "Invalid op definition for %s\n",
1067 tcg_op_defs
[op
].name
);
1071 /* Missing entry in op definitions? */
1072 if (!tcg_op_defs
[op
].used
) {
1073 fprintf(stderr
, "Missing op definition for %s\n",
1074 tcg_op_defs
[op
].name
);
1085 #ifdef USE_LIVENESS_ANALYSIS
1087 /* set a nop for an operation using 'nb_args' */
1088 static inline void tcg_set_nop(TCGContext
*s
, uint16_t *opc_ptr
,
1089 TCGArg
*args
, int nb_args
)
1092 *opc_ptr
= INDEX_op_nop
;
1094 *opc_ptr
= INDEX_op_nopn
;
1096 args
[nb_args
- 1] = nb_args
;
1100 /* liveness analysis: end of function: globals are live, temps are
1102 /* XXX: at this stage, not used as there would be little gains because
1103 most TBs end with a conditional jump. */
1104 static inline void tcg_la_func_end(TCGContext
*s
, uint8_t *dead_temps
)
1106 memset(dead_temps
, 0, s
->nb_globals
);
1107 memset(dead_temps
+ s
->nb_globals
, 1, s
->nb_temps
- s
->nb_globals
);
1110 /* liveness analysis: end of basic block: globals are live, temps are
1111 dead, local temps are live. */
1112 static inline void tcg_la_bb_end(TCGContext
*s
, uint8_t *dead_temps
)
1117 memset(dead_temps
, 0, s
->nb_globals
);
1118 ts
= &s
->temps
[s
->nb_globals
];
1119 for(i
= s
->nb_globals
; i
< s
->nb_temps
; i
++) {
1128 /* Liveness analysis : update the opc_dead_iargs array to tell if a
1129 given input arguments is dead. Instructions updating dead
1130 temporaries are removed. */
1131 static void tcg_liveness_analysis(TCGContext
*s
)
1133 int i
, op_index
, nb_args
, nb_iargs
, nb_oargs
, arg
, nb_ops
;
1136 const TCGOpDef
*def
;
1137 uint8_t *dead_temps
;
1138 unsigned int dead_iargs
;
1140 gen_opc_ptr
++; /* skip end */
1142 nb_ops
= gen_opc_ptr
- gen_opc_buf
;
1144 s
->op_dead_iargs
= tcg_malloc(nb_ops
* sizeof(uint16_t));
1146 dead_temps
= tcg_malloc(s
->nb_temps
);
1147 memset(dead_temps
, 1, s
->nb_temps
);
1149 args
= gen_opparam_ptr
;
1150 op_index
= nb_ops
- 1;
1151 while (op_index
>= 0) {
1152 op
= gen_opc_buf
[op_index
];
1153 def
= &tcg_op_defs
[op
];
1161 nb_iargs
= args
[0] & 0xffff;
1162 nb_oargs
= args
[0] >> 16;
1164 call_flags
= args
[nb_oargs
+ nb_iargs
];
1166 /* pure functions can be removed if their result is not
1168 if (call_flags
& TCG_CALL_PURE
) {
1169 for(i
= 0; i
< nb_oargs
; i
++) {
1171 if (!dead_temps
[arg
])
1172 goto do_not_remove_call
;
1174 tcg_set_nop(s
, gen_opc_buf
+ op_index
,
1179 /* output args are dead */
1180 for(i
= 0; i
< nb_oargs
; i
++) {
1182 dead_temps
[arg
] = 1;
1185 if (!(call_flags
& TCG_CALL_CONST
)) {
1186 /* globals are live (they may be used by the call) */
1187 memset(dead_temps
, 0, s
->nb_globals
);
1190 /* input args are live */
1192 for(i
= 0; i
< nb_iargs
; i
++) {
1193 arg
= args
[i
+ nb_oargs
];
1194 if (arg
!= TCG_CALL_DUMMY_ARG
) {
1195 if (dead_temps
[arg
]) {
1196 dead_iargs
|= (1 << i
);
1198 dead_temps
[arg
] = 0;
1201 s
->op_dead_iargs
[op_index
] = dead_iargs
;
1206 case INDEX_op_set_label
:
1208 /* mark end of basic block */
1209 tcg_la_bb_end(s
, dead_temps
);
1211 case INDEX_op_debug_insn_start
:
1212 args
-= def
->nb_args
;
1218 case INDEX_op_discard
:
1220 /* mark the temporary as dead */
1221 dead_temps
[args
[0]] = 1;
1225 /* XXX: optimize by hardcoding common cases (e.g. triadic ops) */
1227 args
-= def
->nb_args
;
1228 nb_iargs
= def
->nb_iargs
;
1229 nb_oargs
= def
->nb_oargs
;
1231 /* Test if the operation can be removed because all
1232 its outputs are dead. We assume that nb_oargs == 0
1233 implies side effects */
1234 if (!(def
->flags
& TCG_OPF_SIDE_EFFECTS
) && nb_oargs
!= 0) {
1235 for(i
= 0; i
< nb_oargs
; i
++) {
1237 if (!dead_temps
[arg
])
1240 tcg_set_nop(s
, gen_opc_buf
+ op_index
, args
, def
->nb_args
);
1241 #ifdef CONFIG_PROFILER
1247 /* output args are dead */
1248 for(i
= 0; i
< nb_oargs
; i
++) {
1250 dead_temps
[arg
] = 1;
1253 /* if end of basic block, update */
1254 if (def
->flags
& TCG_OPF_BB_END
) {
1255 tcg_la_bb_end(s
, dead_temps
);
1256 } else if (def
->flags
& TCG_OPF_CALL_CLOBBER
) {
1257 /* globals are live */
1258 memset(dead_temps
, 0, s
->nb_globals
);
1261 /* input args are live */
1263 for(i
= 0; i
< nb_iargs
; i
++) {
1264 arg
= args
[i
+ nb_oargs
];
1265 if (dead_temps
[arg
]) {
1266 dead_iargs
|= (1 << i
);
1268 dead_temps
[arg
] = 0;
1270 s
->op_dead_iargs
[op_index
] = dead_iargs
;
1277 if (args
!= gen_opparam_buf
)
1281 /* dummy liveness analysis */
1282 static void tcg_liveness_analysis(TCGContext
*s
)
1285 nb_ops
= gen_opc_ptr
- gen_opc_buf
;
1287 s
->op_dead_iargs
= tcg_malloc(nb_ops
* sizeof(uint16_t));
1288 memset(s
->op_dead_iargs
, 0, nb_ops
* sizeof(uint16_t));
1293 static void dump_regs(TCGContext
*s
)
1299 for(i
= 0; i
< s
->nb_temps
; i
++) {
1301 printf(" %10s: ", tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), i
));
1302 switch(ts
->val_type
) {
1304 printf("%s", tcg_target_reg_names
[ts
->reg
]);
1307 printf("%d(%s)", (int)ts
->mem_offset
, tcg_target_reg_names
[ts
->mem_reg
]);
1309 case TEMP_VAL_CONST
:
1310 printf("$0x%" TCG_PRIlx
, ts
->val
);
1322 for(i
= 0; i
< TCG_TARGET_NB_REGS
; i
++) {
1323 if (s
->reg_to_temp
[i
] >= 0) {
1325 tcg_target_reg_names
[i
],
1326 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), s
->reg_to_temp
[i
]));
1331 static void check_regs(TCGContext
*s
)
1337 for(reg
= 0; reg
< TCG_TARGET_NB_REGS
; reg
++) {
1338 k
= s
->reg_to_temp
[reg
];
1341 if (ts
->val_type
!= TEMP_VAL_REG
||
1343 printf("Inconsistency for register %s:\n",
1344 tcg_target_reg_names
[reg
]);
1349 for(k
= 0; k
< s
->nb_temps
; k
++) {
1351 if (ts
->val_type
== TEMP_VAL_REG
&&
1353 s
->reg_to_temp
[ts
->reg
] != k
) {
1354 printf("Inconsistency for temp %s:\n",
1355 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), k
));
1357 printf("reg state:\n");
1365 static void temp_allocate_frame(TCGContext
*s
, int temp
)
1368 ts
= &s
->temps
[temp
];
1369 s
->current_frame_offset
= (s
->current_frame_offset
+ sizeof(tcg_target_long
) - 1) & ~(sizeof(tcg_target_long
) - 1);
1370 if (s
->current_frame_offset
+ sizeof(tcg_target_long
) > s
->frame_end
)
1372 ts
->mem_offset
= s
->current_frame_offset
;
1373 ts
->mem_reg
= s
->frame_reg
;
1374 ts
->mem_allocated
= 1;
1375 s
->current_frame_offset
+= sizeof(tcg_target_long
);
1378 /* free register 'reg' by spilling the corresponding temporary if necessary */
1379 static void tcg_reg_free(TCGContext
*s
, int reg
)
1384 temp
= s
->reg_to_temp
[reg
];
1386 ts
= &s
->temps
[temp
];
1387 assert(ts
->val_type
== TEMP_VAL_REG
);
1388 if (!ts
->mem_coherent
) {
1389 if (!ts
->mem_allocated
)
1390 temp_allocate_frame(s
, temp
);
1391 tcg_out_st(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
1393 ts
->val_type
= TEMP_VAL_MEM
;
1394 s
->reg_to_temp
[reg
] = -1;
1398 /* Allocate a register belonging to reg1 & ~reg2 */
1399 static int tcg_reg_alloc(TCGContext
*s
, TCGRegSet reg1
, TCGRegSet reg2
)
1404 tcg_regset_andnot(reg_ct
, reg1
, reg2
);
1406 /* first try free registers */
1407 for(i
= 0; i
< ARRAY_SIZE(tcg_target_reg_alloc_order
); i
++) {
1408 reg
= tcg_target_reg_alloc_order
[i
];
1409 if (tcg_regset_test_reg(reg_ct
, reg
) && s
->reg_to_temp
[reg
] == -1)
1413 /* XXX: do better spill choice */
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
)) {
1417 tcg_reg_free(s
, reg
);
1425 /* save a temporary to memory. 'allocated_regs' is used in case a
1426 temporary registers needs to be allocated to store a constant. */
1427 static void temp_save(TCGContext
*s
, int temp
, TCGRegSet allocated_regs
)
1432 ts
= &s
->temps
[temp
];
1433 if (!ts
->fixed_reg
) {
1434 switch(ts
->val_type
) {
1436 tcg_reg_free(s
, ts
->reg
);
1439 ts
->val_type
= TEMP_VAL_MEM
;
1441 case TEMP_VAL_CONST
:
1442 reg
= tcg_reg_alloc(s
, tcg_target_available_regs
[ts
->type
],
1444 if (!ts
->mem_allocated
)
1445 temp_allocate_frame(s
, temp
);
1446 tcg_out_movi(s
, ts
->type
, reg
, ts
->val
);
1447 tcg_out_st(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
1448 ts
->val_type
= TEMP_VAL_MEM
;
1458 /* save globals to their cannonical location and assume they can be
1459 modified be the following code. 'allocated_regs' is used in case a
1460 temporary registers needs to be allocated to store a constant. */
1461 static void save_globals(TCGContext
*s
, TCGRegSet allocated_regs
)
1465 for(i
= 0; i
< s
->nb_globals
; i
++) {
1466 temp_save(s
, i
, allocated_regs
);
1470 /* at the end of a basic block, we assume all temporaries are dead and
1471 all globals are stored at their canonical location. */
1472 static void tcg_reg_alloc_bb_end(TCGContext
*s
, TCGRegSet allocated_regs
)
1477 for(i
= s
->nb_globals
; i
< s
->nb_temps
; i
++) {
1479 if (ts
->temp_local
) {
1480 temp_save(s
, i
, allocated_regs
);
1482 if (ts
->val_type
== TEMP_VAL_REG
) {
1483 s
->reg_to_temp
[ts
->reg
] = -1;
1485 ts
->val_type
= TEMP_VAL_DEAD
;
1489 save_globals(s
, allocated_regs
);
1492 #define IS_DEAD_IARG(n) ((dead_iargs >> (n)) & 1)
1494 static void tcg_reg_alloc_movi(TCGContext
*s
, const TCGArg
*args
)
1497 tcg_target_ulong val
;
1499 ots
= &s
->temps
[args
[0]];
1502 if (ots
->fixed_reg
) {
1503 /* for fixed registers, we do not do any constant
1505 tcg_out_movi(s
, ots
->type
, ots
->reg
, val
);
1507 /* The movi is not explicitly generated here */
1508 if (ots
->val_type
== TEMP_VAL_REG
)
1509 s
->reg_to_temp
[ots
->reg
] = -1;
1510 ots
->val_type
= TEMP_VAL_CONST
;
1515 static void tcg_reg_alloc_mov(TCGContext
*s
, const TCGOpDef
*def
,
1517 unsigned int dead_iargs
)
1521 const TCGArgConstraint
*arg_ct
;
1523 ots
= &s
->temps
[args
[0]];
1524 ts
= &s
->temps
[args
[1]];
1525 arg_ct
= &def
->args_ct
[0];
1527 /* XXX: always mark arg dead if IS_DEAD_IARG(0) */
1528 if (ts
->val_type
== TEMP_VAL_REG
) {
1529 if (IS_DEAD_IARG(0) && !ts
->fixed_reg
&& !ots
->fixed_reg
) {
1530 /* the mov can be suppressed */
1531 if (ots
->val_type
== TEMP_VAL_REG
)
1532 s
->reg_to_temp
[ots
->reg
] = -1;
1534 s
->reg_to_temp
[reg
] = -1;
1535 ts
->val_type
= TEMP_VAL_DEAD
;
1537 if (ots
->val_type
== TEMP_VAL_REG
) {
1540 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, s
->reserved_regs
);
1542 if (ts
->reg
!= reg
) {
1543 tcg_out_mov(s
, reg
, ts
->reg
);
1546 } else if (ts
->val_type
== TEMP_VAL_MEM
) {
1547 if (ots
->val_type
== TEMP_VAL_REG
) {
1550 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, s
->reserved_regs
);
1552 tcg_out_ld(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
1553 } else if (ts
->val_type
== TEMP_VAL_CONST
) {
1554 if (ots
->fixed_reg
) {
1556 tcg_out_movi(s
, ots
->type
, reg
, ts
->val
);
1558 /* propagate constant */
1559 if (ots
->val_type
== TEMP_VAL_REG
)
1560 s
->reg_to_temp
[ots
->reg
] = -1;
1561 ots
->val_type
= TEMP_VAL_CONST
;
1568 s
->reg_to_temp
[reg
] = args
[0];
1570 ots
->val_type
= TEMP_VAL_REG
;
1571 ots
->mem_coherent
= 0;
1574 static void tcg_reg_alloc_op(TCGContext
*s
,
1575 const TCGOpDef
*def
, TCGOpcode opc
,
1577 unsigned int dead_iargs
)
1579 TCGRegSet allocated_regs
;
1580 int i
, k
, nb_iargs
, nb_oargs
, reg
;
1582 const TCGArgConstraint
*arg_ct
;
1584 TCGArg new_args
[TCG_MAX_OP_ARGS
];
1585 int const_args
[TCG_MAX_OP_ARGS
];
1587 nb_oargs
= def
->nb_oargs
;
1588 nb_iargs
= def
->nb_iargs
;
1590 /* copy constants */
1591 memcpy(new_args
+ nb_oargs
+ nb_iargs
,
1592 args
+ nb_oargs
+ nb_iargs
,
1593 sizeof(TCGArg
) * def
->nb_cargs
);
1595 /* satisfy input constraints */
1596 tcg_regset_set(allocated_regs
, s
->reserved_regs
);
1597 for(k
= 0; k
< nb_iargs
; k
++) {
1598 i
= def
->sorted_args
[nb_oargs
+ k
];
1600 arg_ct
= &def
->args_ct
[i
];
1601 ts
= &s
->temps
[arg
];
1602 if (ts
->val_type
== TEMP_VAL_MEM
) {
1603 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1604 tcg_out_ld(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
1605 ts
->val_type
= TEMP_VAL_REG
;
1607 ts
->mem_coherent
= 1;
1608 s
->reg_to_temp
[reg
] = arg
;
1609 } else if (ts
->val_type
== TEMP_VAL_CONST
) {
1610 if (tcg_target_const_match(ts
->val
, arg_ct
)) {
1611 /* constant is OK for instruction */
1613 new_args
[i
] = ts
->val
;
1616 /* need to move to a register */
1617 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1618 tcg_out_movi(s
, ts
->type
, reg
, ts
->val
);
1619 ts
->val_type
= TEMP_VAL_REG
;
1621 ts
->mem_coherent
= 0;
1622 s
->reg_to_temp
[reg
] = arg
;
1625 assert(ts
->val_type
== TEMP_VAL_REG
);
1626 if (arg_ct
->ct
& TCG_CT_IALIAS
) {
1627 if (ts
->fixed_reg
) {
1628 /* if fixed register, we must allocate a new register
1629 if the alias is not the same register */
1630 if (arg
!= args
[arg_ct
->alias_index
])
1631 goto allocate_in_reg
;
1633 /* if the input is aliased to an output and if it is
1634 not dead after the instruction, we must allocate
1635 a new register and move it */
1636 if (!IS_DEAD_IARG(i
- nb_oargs
))
1637 goto allocate_in_reg
;
1641 if (tcg_regset_test_reg(arg_ct
->u
.regs
, reg
)) {
1642 /* nothing to do : the constraint is satisfied */
1645 /* allocate a new register matching the constraint
1646 and move the temporary register into it */
1647 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1648 tcg_out_mov(s
, reg
, ts
->reg
);
1652 tcg_regset_set_reg(allocated_regs
, reg
);
1656 if (def
->flags
& TCG_OPF_BB_END
) {
1657 tcg_reg_alloc_bb_end(s
, allocated_regs
);
1659 /* mark dead temporaries and free the associated registers */
1660 for(i
= 0; i
< nb_iargs
; i
++) {
1661 arg
= args
[nb_oargs
+ i
];
1662 if (IS_DEAD_IARG(i
)) {
1663 ts
= &s
->temps
[arg
];
1664 if (!ts
->fixed_reg
) {
1665 if (ts
->val_type
== TEMP_VAL_REG
)
1666 s
->reg_to_temp
[ts
->reg
] = -1;
1667 ts
->val_type
= TEMP_VAL_DEAD
;
1672 if (def
->flags
& TCG_OPF_CALL_CLOBBER
) {
1673 /* XXX: permit generic clobber register list ? */
1674 for(reg
= 0; reg
< TCG_TARGET_NB_REGS
; reg
++) {
1675 if (tcg_regset_test_reg(tcg_target_call_clobber_regs
, reg
)) {
1676 tcg_reg_free(s
, reg
);
1679 /* XXX: for load/store we could do that only for the slow path
1680 (i.e. when a memory callback is called) */
1682 /* store globals and free associated registers (we assume the insn
1683 can modify any global. */
1684 save_globals(s
, allocated_regs
);
1687 /* satisfy the output constraints */
1688 tcg_regset_set(allocated_regs
, s
->reserved_regs
);
1689 for(k
= 0; k
< nb_oargs
; k
++) {
1690 i
= def
->sorted_args
[k
];
1692 arg_ct
= &def
->args_ct
[i
];
1693 ts
= &s
->temps
[arg
];
1694 if (arg_ct
->ct
& TCG_CT_ALIAS
) {
1695 reg
= new_args
[arg_ct
->alias_index
];
1697 /* if fixed register, we try to use it */
1699 if (ts
->fixed_reg
&&
1700 tcg_regset_test_reg(arg_ct
->u
.regs
, reg
)) {
1703 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1705 tcg_regset_set_reg(allocated_regs
, reg
);
1706 /* if a fixed register is used, then a move will be done afterwards */
1707 if (!ts
->fixed_reg
) {
1708 if (ts
->val_type
== TEMP_VAL_REG
)
1709 s
->reg_to_temp
[ts
->reg
] = -1;
1710 ts
->val_type
= TEMP_VAL_REG
;
1712 /* temp value is modified, so the value kept in memory is
1713 potentially not the same */
1714 ts
->mem_coherent
= 0;
1715 s
->reg_to_temp
[reg
] = arg
;
1722 /* emit instruction */
1723 tcg_out_op(s
, opc
, new_args
, const_args
);
1725 /* move the outputs in the correct register if needed */
1726 for(i
= 0; i
< nb_oargs
; i
++) {
1727 ts
= &s
->temps
[args
[i
]];
1729 if (ts
->fixed_reg
&& ts
->reg
!= reg
) {
1730 tcg_out_mov(s
, ts
->reg
, reg
);
1735 #ifdef TCG_TARGET_STACK_GROWSUP
1736 #define STACK_DIR(x) (-(x))
1738 #define STACK_DIR(x) (x)
1741 static int tcg_reg_alloc_call(TCGContext
*s
, const TCGOpDef
*def
,
1742 TCGOpcode opc
, const TCGArg
*args
,
1743 unsigned int dead_iargs
)
1745 int nb_iargs
, nb_oargs
, flags
, nb_regs
, i
, reg
, nb_params
;
1746 TCGArg arg
, func_arg
;
1748 tcg_target_long stack_offset
, call_stack_size
, func_addr
;
1749 int const_func_arg
, allocate_args
;
1750 TCGRegSet allocated_regs
;
1751 const TCGArgConstraint
*arg_ct
;
1755 nb_oargs
= arg
>> 16;
1756 nb_iargs
= arg
& 0xffff;
1757 nb_params
= nb_iargs
- 1;
1759 flags
= args
[nb_oargs
+ nb_iargs
];
1761 nb_regs
= tcg_target_get_call_iarg_regs_count(flags
);
1762 if (nb_regs
> nb_params
)
1763 nb_regs
= nb_params
;
1765 /* assign stack slots first */
1766 /* XXX: preallocate call stack */
1767 call_stack_size
= (nb_params
- nb_regs
) * sizeof(tcg_target_long
);
1768 call_stack_size
= (call_stack_size
+ TCG_TARGET_STACK_ALIGN
- 1) &
1769 ~(TCG_TARGET_STACK_ALIGN
- 1);
1770 allocate_args
= (call_stack_size
> TCG_STATIC_CALL_ARGS_SIZE
);
1771 if (allocate_args
) {
1772 tcg_out_addi(s
, TCG_REG_CALL_STACK
, -STACK_DIR(call_stack_size
));
1775 stack_offset
= TCG_TARGET_CALL_STACK_OFFSET
;
1776 for(i
= nb_regs
; i
< nb_params
; i
++) {
1777 arg
= args
[nb_oargs
+ i
];
1778 #ifdef TCG_TARGET_STACK_GROWSUP
1779 stack_offset
-= sizeof(tcg_target_long
);
1781 if (arg
!= TCG_CALL_DUMMY_ARG
) {
1782 ts
= &s
->temps
[arg
];
1783 if (ts
->val_type
== TEMP_VAL_REG
) {
1784 tcg_out_st(s
, ts
->type
, ts
->reg
, TCG_REG_CALL_STACK
, stack_offset
);
1785 } else if (ts
->val_type
== TEMP_VAL_MEM
) {
1786 reg
= tcg_reg_alloc(s
, tcg_target_available_regs
[ts
->type
],
1788 /* XXX: not correct if reading values from the stack */
1789 tcg_out_ld(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
1790 tcg_out_st(s
, ts
->type
, reg
, TCG_REG_CALL_STACK
, stack_offset
);
1791 } else if (ts
->val_type
== TEMP_VAL_CONST
) {
1792 reg
= tcg_reg_alloc(s
, tcg_target_available_regs
[ts
->type
],
1794 /* XXX: sign extend may be needed on some targets */
1795 tcg_out_movi(s
, ts
->type
, reg
, ts
->val
);
1796 tcg_out_st(s
, ts
->type
, reg
, TCG_REG_CALL_STACK
, stack_offset
);
1801 #ifndef TCG_TARGET_STACK_GROWSUP
1802 stack_offset
+= sizeof(tcg_target_long
);
1806 /* assign input registers */
1807 tcg_regset_set(allocated_regs
, s
->reserved_regs
);
1808 for(i
= 0; i
< nb_regs
; i
++) {
1809 arg
= args
[nb_oargs
+ i
];
1810 if (arg
!= TCG_CALL_DUMMY_ARG
) {
1811 ts
= &s
->temps
[arg
];
1812 reg
= tcg_target_call_iarg_regs
[i
];
1813 tcg_reg_free(s
, reg
);
1814 if (ts
->val_type
== TEMP_VAL_REG
) {
1815 if (ts
->reg
!= reg
) {
1816 tcg_out_mov(s
, reg
, ts
->reg
);
1818 } else if (ts
->val_type
== TEMP_VAL_MEM
) {
1819 tcg_out_ld(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
1820 } else if (ts
->val_type
== TEMP_VAL_CONST
) {
1821 /* XXX: sign extend ? */
1822 tcg_out_movi(s
, ts
->type
, reg
, ts
->val
);
1826 tcg_regset_set_reg(allocated_regs
, reg
);
1830 /* assign function address */
1831 func_arg
= args
[nb_oargs
+ nb_iargs
- 1];
1832 arg_ct
= &def
->args_ct
[0];
1833 ts
= &s
->temps
[func_arg
];
1834 func_addr
= ts
->val
;
1836 if (ts
->val_type
== TEMP_VAL_MEM
) {
1837 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1838 tcg_out_ld(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
1840 tcg_regset_set_reg(allocated_regs
, reg
);
1841 } else if (ts
->val_type
== TEMP_VAL_REG
) {
1843 if (!tcg_regset_test_reg(arg_ct
->u
.regs
, reg
)) {
1844 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1845 tcg_out_mov(s
, reg
, ts
->reg
);
1848 tcg_regset_set_reg(allocated_regs
, reg
);
1849 } else if (ts
->val_type
== TEMP_VAL_CONST
) {
1850 if (tcg_target_const_match(func_addr
, arg_ct
)) {
1852 func_arg
= func_addr
;
1854 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1855 tcg_out_movi(s
, ts
->type
, reg
, func_addr
);
1857 tcg_regset_set_reg(allocated_regs
, reg
);
1864 /* mark dead temporaries and free the associated registers */
1865 for(i
= 0; i
< nb_iargs
; i
++) {
1866 arg
= args
[nb_oargs
+ i
];
1867 if (IS_DEAD_IARG(i
)) {
1868 ts
= &s
->temps
[arg
];
1869 if (!ts
->fixed_reg
) {
1870 if (ts
->val_type
== TEMP_VAL_REG
)
1871 s
->reg_to_temp
[ts
->reg
] = -1;
1872 ts
->val_type
= TEMP_VAL_DEAD
;
1877 /* clobber call registers */
1878 for(reg
= 0; reg
< TCG_TARGET_NB_REGS
; reg
++) {
1879 if (tcg_regset_test_reg(tcg_target_call_clobber_regs
, reg
)) {
1880 tcg_reg_free(s
, reg
);
1884 /* store globals and free associated registers (we assume the call
1885 can modify any global. */
1886 if (!(flags
& TCG_CALL_CONST
)) {
1887 save_globals(s
, allocated_regs
);
1890 tcg_out_op(s
, opc
, &func_arg
, &const_func_arg
);
1892 if (allocate_args
) {
1893 tcg_out_addi(s
, TCG_REG_CALL_STACK
, STACK_DIR(call_stack_size
));
1896 /* assign output registers and emit moves if needed */
1897 for(i
= 0; i
< nb_oargs
; i
++) {
1899 ts
= &s
->temps
[arg
];
1900 reg
= tcg_target_call_oarg_regs
[i
];
1901 assert(s
->reg_to_temp
[reg
] == -1);
1902 if (ts
->fixed_reg
) {
1903 if (ts
->reg
!= reg
) {
1904 tcg_out_mov(s
, ts
->reg
, reg
);
1907 if (ts
->val_type
== TEMP_VAL_REG
)
1908 s
->reg_to_temp
[ts
->reg
] = -1;
1909 ts
->val_type
= TEMP_VAL_REG
;
1911 ts
->mem_coherent
= 0;
1912 s
->reg_to_temp
[reg
] = arg
;
1916 return nb_iargs
+ nb_oargs
+ def
->nb_cargs
+ 1;
1919 #ifdef CONFIG_PROFILER
1921 static int64_t tcg_table_op_count
[NB_OPS
];
1923 static void dump_op_count(void)
1927 f
= fopen("/tmp/op.log", "w");
1928 for(i
= INDEX_op_end
; i
< NB_OPS
; i
++) {
1929 fprintf(f
, "%s %" PRId64
"\n", tcg_op_defs
[i
].name
, tcg_table_op_count
[i
]);
1936 static inline int tcg_gen_code_common(TCGContext
*s
, uint8_t *gen_code_buf
,
1941 const TCGOpDef
*def
;
1942 unsigned int dead_iargs
;
1946 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP
))) {
1948 tcg_dump_ops(s
, logfile
);
1953 #ifdef CONFIG_PROFILER
1954 s
->la_time
-= profile_getclock();
1956 tcg_liveness_analysis(s
);
1957 #ifdef CONFIG_PROFILER
1958 s
->la_time
+= profile_getclock();
1962 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_OPT
))) {
1963 qemu_log("OP after liveness analysis:\n");
1964 tcg_dump_ops(s
, logfile
);
1969 tcg_reg_alloc_start(s
);
1971 s
->code_buf
= gen_code_buf
;
1972 s
->code_ptr
= gen_code_buf
;
1974 args
= gen_opparam_buf
;
1978 opc
= gen_opc_buf
[op_index
];
1979 #ifdef CONFIG_PROFILER
1980 tcg_table_op_count
[opc
]++;
1982 def
= &tcg_op_defs
[opc
];
1984 printf("%s: %d %d %d\n", def
->name
,
1985 def
->nb_oargs
, def
->nb_iargs
, def
->nb_cargs
);
1989 case INDEX_op_mov_i32
:
1990 #if TCG_TARGET_REG_BITS == 64
1991 case INDEX_op_mov_i64
:
1993 dead_iargs
= s
->op_dead_iargs
[op_index
];
1994 tcg_reg_alloc_mov(s
, def
, args
, dead_iargs
);
1996 case INDEX_op_movi_i32
:
1997 #if TCG_TARGET_REG_BITS == 64
1998 case INDEX_op_movi_i64
:
2000 tcg_reg_alloc_movi(s
, args
);
2002 case INDEX_op_debug_insn_start
:
2003 /* debug instruction */
2013 case INDEX_op_discard
:
2016 ts
= &s
->temps
[args
[0]];
2017 /* mark the temporary as dead */
2018 if (!ts
->fixed_reg
) {
2019 if (ts
->val_type
== TEMP_VAL_REG
)
2020 s
->reg_to_temp
[ts
->reg
] = -1;
2021 ts
->val_type
= TEMP_VAL_DEAD
;
2025 case INDEX_op_set_label
:
2026 tcg_reg_alloc_bb_end(s
, s
->reserved_regs
);
2027 tcg_out_label(s
, args
[0], (long)s
->code_ptr
);
2030 dead_iargs
= s
->op_dead_iargs
[op_index
];
2031 args
+= tcg_reg_alloc_call(s
, def
, opc
, args
, dead_iargs
);
2036 /* Note: in order to speed up the code, it would be much
2037 faster to have specialized register allocator functions for
2038 some common argument patterns */
2039 dead_iargs
= s
->op_dead_iargs
[op_index
];
2040 tcg_reg_alloc_op(s
, def
, opc
, args
, dead_iargs
);
2043 args
+= def
->nb_args
;
2045 if (search_pc
>= 0 && search_pc
< s
->code_ptr
- gen_code_buf
) {
2057 int tcg_gen_code(TCGContext
*s
, uint8_t *gen_code_buf
)
2059 #ifdef CONFIG_PROFILER
2062 n
= (gen_opc_ptr
- gen_opc_buf
);
2064 if (n
> s
->op_count_max
)
2065 s
->op_count_max
= n
;
2067 s
->temp_count
+= s
->nb_temps
;
2068 if (s
->nb_temps
> s
->temp_count_max
)
2069 s
->temp_count_max
= s
->nb_temps
;
2073 tcg_gen_code_common(s
, gen_code_buf
, -1);
2075 /* flush instruction cache */
2076 flush_icache_range((unsigned long)gen_code_buf
,
2077 (unsigned long)s
->code_ptr
);
2078 return s
->code_ptr
- gen_code_buf
;
2081 /* Return the index of the micro operation such as the pc after is <
2082 offset bytes from the start of the TB. The contents of gen_code_buf must
2083 not be changed, though writing the same values is ok.
2084 Return -1 if not found. */
2085 int tcg_gen_code_search_pc(TCGContext
*s
, uint8_t *gen_code_buf
, long offset
)
2087 return tcg_gen_code_common(s
, gen_code_buf
, offset
);
2090 #ifdef CONFIG_PROFILER
2091 void tcg_dump_info(FILE *f
,
2092 int (*cpu_fprintf
)(FILE *f
, const char *fmt
, ...))
2094 TCGContext
*s
= &tcg_ctx
;
2097 tot
= s
->interm_time
+ s
->code_time
;
2098 cpu_fprintf(f
, "JIT cycles %" PRId64
" (%0.3f s at 2.4 GHz)\n",
2100 cpu_fprintf(f
, "translated TBs %" PRId64
" (aborted=%" PRId64
" %0.1f%%)\n",
2102 s
->tb_count1
- s
->tb_count
,
2103 s
->tb_count1
? (double)(s
->tb_count1
- s
->tb_count
) / s
->tb_count1
* 100.0 : 0);
2104 cpu_fprintf(f
, "avg ops/TB %0.1f max=%d\n",
2105 s
->tb_count
? (double)s
->op_count
/ s
->tb_count
: 0, s
->op_count_max
);
2106 cpu_fprintf(f
, "deleted ops/TB %0.2f\n",
2108 (double)s
->del_op_count
/ s
->tb_count
: 0);
2109 cpu_fprintf(f
, "avg temps/TB %0.2f max=%d\n",
2111 (double)s
->temp_count
/ s
->tb_count
: 0,
2114 cpu_fprintf(f
, "cycles/op %0.1f\n",
2115 s
->op_count
? (double)tot
/ s
->op_count
: 0);
2116 cpu_fprintf(f
, "cycles/in byte %0.1f\n",
2117 s
->code_in_len
? (double)tot
/ s
->code_in_len
: 0);
2118 cpu_fprintf(f
, "cycles/out byte %0.1f\n",
2119 s
->code_out_len
? (double)tot
/ s
->code_out_len
: 0);
2122 cpu_fprintf(f
, " gen_interm time %0.1f%%\n",
2123 (double)s
->interm_time
/ tot
* 100.0);
2124 cpu_fprintf(f
, " gen_code time %0.1f%%\n",
2125 (double)s
->code_time
/ tot
* 100.0);
2126 cpu_fprintf(f
, "liveness/code time %0.1f%%\n",
2127 (double)s
->la_time
/ (s
->code_time
? s
->code_time
: 1) * 100.0);
2128 cpu_fprintf(f
, "cpu_restore count %" PRId64
"\n",
2130 cpu_fprintf(f
, " avg cycles %0.1f\n",
2131 s
->restore_count
? (double)s
->restore_time
/ s
->restore_count
: 0);
2136 void tcg_dump_info(FILE *f
,
2137 int (*cpu_fprintf
)(FILE *f
, const char *fmt
, ...))
2139 cpu_fprintf(f
, "[TCG profiler not compiled]\n");