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
31 /* define it to suppress various consistency checks (faster) */
48 #include "qemu-common.h"
49 #include "cache-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
62 static void patch_reloc(uint8_t *code_ptr
, int type
,
63 tcg_target_long value
, tcg_target_long addend
);
65 static TCGOpDef tcg_op_defs
[] = {
66 #define DEF(s, n, copy_size) { #s, 0, 0, n, n, 0, copy_size },
67 #define DEF2(s, iargs, oargs, cargs, flags) { #s, iargs, oargs, cargs, iargs + oargs + cargs, flags, 0 },
73 static TCGRegSet tcg_target_available_regs
[2];
74 static TCGRegSet tcg_target_call_clobber_regs
;
76 /* XXX: move that inside the context */
77 uint16_t *gen_opc_ptr
;
78 TCGArg
*gen_opparam_ptr
;
80 static inline void tcg_out8(TCGContext
*s
, uint8_t v
)
85 static inline void tcg_out16(TCGContext
*s
, uint16_t v
)
87 *(uint16_t *)s
->code_ptr
= v
;
91 static inline void tcg_out32(TCGContext
*s
, uint32_t v
)
93 *(uint32_t *)s
->code_ptr
= v
;
97 /* label relocation processing */
99 void tcg_out_reloc(TCGContext
*s
, uint8_t *code_ptr
, int type
,
100 int label_index
, long addend
)
105 l
= &s
->labels
[label_index
];
107 /* FIXME: This may break relocations on RISC targets that
108 modify instruction fields in place. The caller may not have
109 written the initial value. */
110 patch_reloc(code_ptr
, type
, l
->u
.value
, addend
);
112 /* add a new relocation entry */
113 r
= tcg_malloc(sizeof(TCGRelocation
));
117 r
->next
= l
->u
.first_reloc
;
118 l
->u
.first_reloc
= r
;
122 static void tcg_out_label(TCGContext
*s
, int label_index
,
123 tcg_target_long value
)
128 l
= &s
->labels
[label_index
];
131 r
= l
->u
.first_reloc
;
133 patch_reloc(r
->ptr
, r
->type
, value
, r
->addend
);
140 int gen_new_label(void)
142 TCGContext
*s
= &tcg_ctx
;
146 if (s
->nb_labels
>= TCG_MAX_LABELS
)
148 idx
= s
->nb_labels
++;
151 l
->u
.first_reloc
= NULL
;
155 #include "tcg-target.c"
157 /* pool based memory allocation */
158 void *tcg_malloc_internal(TCGContext
*s
, int size
)
163 if (size
> TCG_POOL_CHUNK_SIZE
) {
164 /* big malloc: insert a new pool (XXX: could optimize) */
165 p
= qemu_malloc(sizeof(TCGPool
) + size
);
168 s
->pool_current
->next
= p
;
171 p
->next
= s
->pool_current
;
181 pool_size
= TCG_POOL_CHUNK_SIZE
;
182 p
= qemu_malloc(sizeof(TCGPool
) + pool_size
);
186 s
->pool_current
->next
= p
;
195 s
->pool_cur
= p
->data
+ size
;
196 s
->pool_end
= p
->data
+ p
->size
;
200 void tcg_pool_reset(TCGContext
*s
)
202 s
->pool_cur
= s
->pool_end
= NULL
;
203 s
->pool_current
= NULL
;
206 void tcg_context_init(TCGContext
*s
)
208 int op
, total_args
, n
;
210 TCGArgConstraint
*args_ct
;
213 memset(s
, 0, sizeof(*s
));
214 s
->temps
= s
->static_temps
;
217 /* Count total number of arguments and allocate the corresponding
220 for(op
= 0; op
< NB_OPS
; op
++) {
221 def
= &tcg_op_defs
[op
];
222 n
= def
->nb_iargs
+ def
->nb_oargs
;
226 args_ct
= qemu_malloc(sizeof(TCGArgConstraint
) * total_args
);
227 sorted_args
= qemu_malloc(sizeof(int) * total_args
);
229 for(op
= 0; op
< NB_OPS
; op
++) {
230 def
= &tcg_op_defs
[op
];
231 def
->args_ct
= args_ct
;
232 def
->sorted_args
= sorted_args
;
233 n
= def
->nb_iargs
+ def
->nb_oargs
;
240 /* init global prologue and epilogue */
241 s
->code_buf
= code_gen_prologue
;
242 s
->code_ptr
= s
->code_buf
;
243 tcg_target_qemu_prologue(s
);
244 flush_icache_range((unsigned long)s
->code_buf
,
245 (unsigned long)s
->code_ptr
);
248 void tcg_set_frame(TCGContext
*s
, int reg
,
249 tcg_target_long start
, tcg_target_long size
)
251 s
->frame_start
= start
;
252 s
->frame_end
= start
+ size
;
256 void tcg_func_start(TCGContext
*s
)
260 s
->nb_temps
= s
->nb_globals
;
261 for(i
= 0; i
< (TCG_TYPE_COUNT
* 2); i
++)
262 s
->first_free_temp
[i
] = -1;
263 s
->labels
= tcg_malloc(sizeof(TCGLabel
) * TCG_MAX_LABELS
);
265 s
->current_frame_offset
= s
->frame_start
;
267 gen_opc_ptr
= gen_opc_buf
;
268 gen_opparam_ptr
= gen_opparam_buf
;
271 static inline void tcg_temp_alloc(TCGContext
*s
, int n
)
273 if (n
> TCG_MAX_TEMPS
)
277 static inline int tcg_global_reg_new_internal(TCGType type
, int reg
,
280 TCGContext
*s
= &tcg_ctx
;
284 #if TCG_TARGET_REG_BITS == 32
285 if (type
!= TCG_TYPE_I32
)
288 if (tcg_regset_test_reg(s
->reserved_regs
, reg
))
291 tcg_temp_alloc(s
, s
->nb_globals
+ 1);
292 ts
= &s
->temps
[s
->nb_globals
];
293 ts
->base_type
= type
;
299 tcg_regset_set_reg(s
->reserved_regs
, reg
);
303 TCGv_i32
tcg_global_reg_new_i32(int reg
, const char *name
)
307 idx
= tcg_global_reg_new_internal(TCG_TYPE_I32
, reg
, name
);
308 return MAKE_TCGV_I32(idx
);
311 TCGv_i64
tcg_global_reg_new_i64(int reg
, const char *name
)
315 idx
= tcg_global_reg_new_internal(TCG_TYPE_I64
, reg
, name
);
316 return MAKE_TCGV_I64(idx
);
319 static inline int tcg_global_mem_new_internal(TCGType type
, int reg
,
320 tcg_target_long offset
,
323 TCGContext
*s
= &tcg_ctx
;
328 #if TCG_TARGET_REG_BITS == 32
329 if (type
== TCG_TYPE_I64
) {
331 tcg_temp_alloc(s
, s
->nb_globals
+ 2);
332 ts
= &s
->temps
[s
->nb_globals
];
333 ts
->base_type
= type
;
334 ts
->type
= TCG_TYPE_I32
;
336 ts
->mem_allocated
= 1;
338 #ifdef TCG_TARGET_WORDS_BIGENDIAN
339 ts
->mem_offset
= offset
+ 4;
341 ts
->mem_offset
= offset
;
343 pstrcpy(buf
, sizeof(buf
), name
);
344 pstrcat(buf
, sizeof(buf
), "_0");
345 ts
->name
= strdup(buf
);
348 ts
->base_type
= type
;
349 ts
->type
= TCG_TYPE_I32
;
351 ts
->mem_allocated
= 1;
353 #ifdef TCG_TARGET_WORDS_BIGENDIAN
354 ts
->mem_offset
= offset
;
356 ts
->mem_offset
= offset
+ 4;
358 pstrcpy(buf
, sizeof(buf
), name
);
359 pstrcat(buf
, sizeof(buf
), "_1");
360 ts
->name
= strdup(buf
);
366 tcg_temp_alloc(s
, s
->nb_globals
+ 1);
367 ts
= &s
->temps
[s
->nb_globals
];
368 ts
->base_type
= type
;
371 ts
->mem_allocated
= 1;
373 ts
->mem_offset
= offset
;
380 TCGv_i32
tcg_global_mem_new_i32(int reg
, tcg_target_long offset
,
385 idx
= tcg_global_mem_new_internal(TCG_TYPE_I32
, reg
, offset
, name
);
386 return MAKE_TCGV_I32(idx
);
389 TCGv_i64
tcg_global_mem_new_i64(int reg
, tcg_target_long offset
,
394 idx
= tcg_global_mem_new_internal(TCG_TYPE_I64
, reg
, offset
, name
);
395 return MAKE_TCGV_I64(idx
);
398 static inline int tcg_temp_new_internal(TCGType type
, int temp_local
)
400 TCGContext
*s
= &tcg_ctx
;
407 idx
= s
->first_free_temp
[k
];
409 /* There is already an available temp with the
412 s
->first_free_temp
[k
] = ts
->next_free_temp
;
413 ts
->temp_allocated
= 1;
414 assert(ts
->temp_local
== temp_local
);
417 #if TCG_TARGET_REG_BITS == 32
418 if (type
== TCG_TYPE_I64
) {
419 tcg_temp_alloc(s
, s
->nb_temps
+ 2);
420 ts
= &s
->temps
[s
->nb_temps
];
421 ts
->base_type
= type
;
422 ts
->type
= TCG_TYPE_I32
;
423 ts
->temp_allocated
= 1;
424 ts
->temp_local
= temp_local
;
427 ts
->base_type
= TCG_TYPE_I32
;
428 ts
->type
= TCG_TYPE_I32
;
429 ts
->temp_allocated
= 1;
430 ts
->temp_local
= temp_local
;
436 tcg_temp_alloc(s
, s
->nb_temps
+ 1);
437 ts
= &s
->temps
[s
->nb_temps
];
438 ts
->base_type
= type
;
440 ts
->temp_allocated
= 1;
441 ts
->temp_local
= temp_local
;
449 TCGv_i32
tcg_temp_new_internal_i32(int temp_local
)
453 idx
= tcg_temp_new_internal(TCG_TYPE_I32
, temp_local
);
454 return MAKE_TCGV_I32(idx
);
457 TCGv_i64
tcg_temp_new_internal_i64(int temp_local
)
461 idx
= tcg_temp_new_internal(TCG_TYPE_I64
, temp_local
);
462 return MAKE_TCGV_I64(idx
);
465 static inline void tcg_temp_free_internal(int idx
)
467 TCGContext
*s
= &tcg_ctx
;
471 assert(idx
>= s
->nb_globals
&& idx
< s
->nb_temps
);
473 assert(ts
->temp_allocated
!= 0);
474 ts
->temp_allocated
= 0;
478 ts
->next_free_temp
= s
->first_free_temp
[k
];
479 s
->first_free_temp
[k
] = idx
;
482 void tcg_temp_free_i32(TCGv_i32 arg
)
484 tcg_temp_free_internal(GET_TCGV_I32(arg
));
487 void tcg_temp_free_i64(TCGv_i64 arg
)
489 tcg_temp_free_internal(GET_TCGV_I64(arg
));
492 TCGv_i32
tcg_const_i32(int32_t val
)
495 t0
= tcg_temp_new_i32();
496 tcg_gen_movi_i32(t0
, val
);
500 TCGv_i64
tcg_const_i64(int64_t val
)
503 t0
= tcg_temp_new_i64();
504 tcg_gen_movi_i64(t0
, val
);
508 TCGv_i32
tcg_const_local_i32(int32_t val
)
511 t0
= tcg_temp_local_new_i32();
512 tcg_gen_movi_i32(t0
, val
);
516 TCGv_i64
tcg_const_local_i64(int64_t val
)
519 t0
= tcg_temp_local_new_i64();
520 tcg_gen_movi_i64(t0
, val
);
524 void tcg_register_helper(void *func
, const char *name
)
526 TCGContext
*s
= &tcg_ctx
;
528 if ((s
->nb_helpers
+ 1) > s
->allocated_helpers
) {
529 n
= s
->allocated_helpers
;
535 s
->helpers
= realloc(s
->helpers
, n
* sizeof(TCGHelperInfo
));
536 s
->allocated_helpers
= n
;
538 s
->helpers
[s
->nb_helpers
].func
= (tcg_target_ulong
)func
;
539 s
->helpers
[s
->nb_helpers
].name
= name
;
543 /* Note: we convert the 64 bit args to 32 bit and do some alignment
544 and endian swap. Maybe it would be better to do the alignment
545 and endian swap in tcg_reg_alloc_call(). */
546 void tcg_gen_callN(TCGContext
*s
, TCGv_ptr func
, unsigned int flags
,
547 int sizemask
, TCGArg ret
, int nargs
, TCGArg
*args
)
554 *gen_opc_ptr
++ = INDEX_op_call
;
555 nparam
= gen_opparam_ptr
++;
556 call_type
= (flags
& TCG_CALL_TYPE_MASK
);
557 if (ret
!= TCG_CALL_DUMMY_ARG
) {
558 #if TCG_TARGET_REG_BITS < 64
560 #ifdef TCG_TARGET_WORDS_BIGENDIAN
561 *gen_opparam_ptr
++ = ret
+ 1;
562 *gen_opparam_ptr
++ = ret
;
564 *gen_opparam_ptr
++ = ret
;
565 *gen_opparam_ptr
++ = ret
+ 1;
571 *gen_opparam_ptr
++ = ret
;
578 for (i
= 0; i
< nargs
; i
++) {
579 #if TCG_TARGET_REG_BITS < 64
580 if (sizemask
& (2 << i
)) {
581 #ifdef TCG_TARGET_I386
582 /* REGPARM case: if the third parameter is 64 bit, it is
583 allocated on the stack */
584 if (i
== 2 && call_type
== TCG_CALL_TYPE_REGPARM
) {
585 call_type
= TCG_CALL_TYPE_REGPARM_2
;
586 flags
= (flags
& ~TCG_CALL_TYPE_MASK
) | call_type
;
589 #ifdef TCG_TARGET_CALL_ALIGN_ARGS
590 /* some targets want aligned 64 bit args */
592 *gen_opparam_ptr
++ = TCG_CALL_DUMMY_ARG
;
596 #ifdef TCG_TARGET_WORDS_BIGENDIAN
597 *gen_opparam_ptr
++ = args
[i
] + 1;
598 *gen_opparam_ptr
++ = args
[i
];
600 *gen_opparam_ptr
++ = args
[i
];
601 *gen_opparam_ptr
++ = args
[i
] + 1;
607 *gen_opparam_ptr
++ = args
[i
];
611 *gen_opparam_ptr
++ = GET_TCGV_PTR(func
);
613 *gen_opparam_ptr
++ = flags
;
615 *nparam
= (nb_rets
<< 16) | (real_args
+ 1);
617 /* total parameters, needed to go backward in the instruction stream */
618 *gen_opparam_ptr
++ = 1 + nb_rets
+ real_args
+ 3;
621 #if TCG_TARGET_REG_BITS == 32
622 void tcg_gen_shifti_i64(TCGv_i64 ret
, TCGv_i64 arg1
,
623 int c
, int right
, int arith
)
626 tcg_gen_mov_i32(TCGV_LOW(ret
), TCGV_LOW(arg1
));
627 tcg_gen_mov_i32(TCGV_HIGH(ret
), TCGV_HIGH(arg1
));
628 } else if (c
>= 32) {
632 tcg_gen_sari_i32(TCGV_LOW(ret
), TCGV_HIGH(arg1
), c
);
633 tcg_gen_sari_i32(TCGV_HIGH(ret
), TCGV_HIGH(arg1
), 31);
635 tcg_gen_shri_i32(TCGV_LOW(ret
), TCGV_HIGH(arg1
), c
);
636 tcg_gen_movi_i32(TCGV_HIGH(ret
), 0);
639 tcg_gen_shli_i32(TCGV_HIGH(ret
), TCGV_LOW(arg1
), c
);
640 tcg_gen_movi_i32(TCGV_LOW(ret
), 0);
645 t0
= tcg_temp_new_i32();
646 t1
= tcg_temp_new_i32();
648 tcg_gen_shli_i32(t0
, TCGV_HIGH(arg1
), 32 - c
);
650 tcg_gen_sari_i32(t1
, TCGV_HIGH(arg1
), c
);
652 tcg_gen_shri_i32(t1
, TCGV_HIGH(arg1
), c
);
653 tcg_gen_shri_i32(TCGV_LOW(ret
), TCGV_LOW(arg1
), c
);
654 tcg_gen_or_i32(TCGV_LOW(ret
), TCGV_LOW(ret
), t0
);
655 tcg_gen_mov_i32(TCGV_HIGH(ret
), t1
);
657 tcg_gen_shri_i32(t0
, TCGV_LOW(arg1
), 32 - c
);
658 /* Note: ret can be the same as arg1, so we use t1 */
659 tcg_gen_shli_i32(t1
, TCGV_LOW(arg1
), c
);
660 tcg_gen_shli_i32(TCGV_HIGH(ret
), TCGV_HIGH(arg1
), c
);
661 tcg_gen_or_i32(TCGV_HIGH(ret
), TCGV_HIGH(ret
), t0
);
662 tcg_gen_mov_i32(TCGV_LOW(ret
), t1
);
664 tcg_temp_free_i32(t0
);
665 tcg_temp_free_i32(t1
);
670 static void tcg_reg_alloc_start(TCGContext
*s
)
674 for(i
= 0; i
< s
->nb_globals
; i
++) {
677 ts
->val_type
= TEMP_VAL_REG
;
679 ts
->val_type
= TEMP_VAL_MEM
;
682 for(i
= s
->nb_globals
; i
< s
->nb_temps
; i
++) {
684 ts
->val_type
= TEMP_VAL_DEAD
;
685 ts
->mem_allocated
= 0;
688 for(i
= 0; i
< TCG_TARGET_NB_REGS
; i
++) {
689 s
->reg_to_temp
[i
] = -1;
693 static char *tcg_get_arg_str_idx(TCGContext
*s
, char *buf
, int buf_size
,
699 if (idx
< s
->nb_globals
) {
700 pstrcpy(buf
, buf_size
, ts
->name
);
703 snprintf(buf
, buf_size
, "loc%d", idx
- s
->nb_globals
);
705 snprintf(buf
, buf_size
, "tmp%d", idx
- s
->nb_globals
);
710 char *tcg_get_arg_str_i32(TCGContext
*s
, char *buf
, int buf_size
, TCGv_i32 arg
)
712 return tcg_get_arg_str_idx(s
, buf
, buf_size
, GET_TCGV_I32(arg
));
715 char *tcg_get_arg_str_i64(TCGContext
*s
, char *buf
, int buf_size
, TCGv_i64 arg
)
717 return tcg_get_arg_str_idx(s
, buf
, buf_size
, GET_TCGV_I64(arg
));
720 static int helper_cmp(const void *p1
, const void *p2
)
722 const TCGHelperInfo
*th1
= p1
;
723 const TCGHelperInfo
*th2
= p2
;
724 if (th1
->func
< th2
->func
)
726 else if (th1
->func
== th2
->func
)
732 /* find helper definition (Note: A hash table would be better) */
733 static TCGHelperInfo
*tcg_find_helper(TCGContext
*s
, tcg_target_ulong val
)
739 if (unlikely(!s
->helpers_sorted
)) {
740 qsort(s
->helpers
, s
->nb_helpers
, sizeof(TCGHelperInfo
),
742 s
->helpers_sorted
= 1;
747 m_max
= s
->nb_helpers
- 1;
748 while (m_min
<= m_max
) {
749 m
= (m_min
+ m_max
) >> 1;
763 static const char * const cond_name
[] =
765 [TCG_COND_EQ
] = "eq",
766 [TCG_COND_NE
] = "ne",
767 [TCG_COND_LT
] = "lt",
768 [TCG_COND_GE
] = "ge",
769 [TCG_COND_LE
] = "le",
770 [TCG_COND_GT
] = "gt",
771 [TCG_COND_LTU
] = "ltu",
772 [TCG_COND_GEU
] = "geu",
773 [TCG_COND_LEU
] = "leu",
774 [TCG_COND_GTU
] = "gtu"
777 void tcg_dump_ops(TCGContext
*s
, FILE *outfile
)
779 const uint16_t *opc_ptr
;
782 int c
, i
, k
, nb_oargs
, nb_iargs
, nb_cargs
, first_insn
;
787 opc_ptr
= gen_opc_buf
;
788 args
= gen_opparam_buf
;
789 while (opc_ptr
< gen_opc_ptr
) {
791 def
= &tcg_op_defs
[c
];
792 if (c
== INDEX_op_debug_insn_start
) {
794 #if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
795 pc
= ((uint64_t)args
[1] << 32) | args
[0];
800 fprintf(outfile
, "\n");
801 fprintf(outfile
, " ---- 0x%" PRIx64
, pc
);
803 nb_oargs
= def
->nb_oargs
;
804 nb_iargs
= def
->nb_iargs
;
805 nb_cargs
= def
->nb_cargs
;
806 } else if (c
== INDEX_op_call
) {
809 /* variable number of arguments */
811 nb_oargs
= arg
>> 16;
812 nb_iargs
= arg
& 0xffff;
813 nb_cargs
= def
->nb_cargs
;
815 fprintf(outfile
, " %s ", def
->name
);
818 fprintf(outfile
, "%s",
819 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), args
[nb_oargs
+ nb_iargs
- 1]));
821 fprintf(outfile
, ",$0x%" TCG_PRIlx
,
822 args
[nb_oargs
+ nb_iargs
]);
824 fprintf(outfile
, ",$%d", nb_oargs
);
825 for(i
= 0; i
< nb_oargs
; i
++) {
826 fprintf(outfile
, ",");
827 fprintf(outfile
, "%s",
828 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), args
[i
]));
830 for(i
= 0; i
< (nb_iargs
- 1); i
++) {
831 fprintf(outfile
, ",");
832 if (args
[nb_oargs
+ i
] == TCG_CALL_DUMMY_ARG
) {
833 fprintf(outfile
, "<dummy>");
835 fprintf(outfile
, "%s",
836 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), args
[nb_oargs
+ i
]));
839 } else if (c
== INDEX_op_movi_i32
840 #if TCG_TARGET_REG_BITS == 64
841 || c
== INDEX_op_movi_i64
844 tcg_target_ulong val
;
847 nb_oargs
= def
->nb_oargs
;
848 nb_iargs
= def
->nb_iargs
;
849 nb_cargs
= def
->nb_cargs
;
850 fprintf(outfile
, " %s %s,$", def
->name
,
851 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), args
[0]));
853 th
= tcg_find_helper(s
, val
);
855 fprintf(outfile
, "%s", th
->name
);
857 if (c
== INDEX_op_movi_i32
)
858 fprintf(outfile
, "0x%x", (uint32_t)val
);
860 fprintf(outfile
, "0x%" PRIx64
, (uint64_t)val
);
863 fprintf(outfile
, " %s ", def
->name
);
864 if (c
== INDEX_op_nopn
) {
865 /* variable number of arguments */
870 nb_oargs
= def
->nb_oargs
;
871 nb_iargs
= def
->nb_iargs
;
872 nb_cargs
= def
->nb_cargs
;
876 for(i
= 0; i
< nb_oargs
; i
++) {
878 fprintf(outfile
, ",");
879 fprintf(outfile
, "%s",
880 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), args
[k
++]));
882 for(i
= 0; i
< nb_iargs
; i
++) {
884 fprintf(outfile
, ",");
885 fprintf(outfile
, "%s",
886 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), args
[k
++]));
888 if (c
== INDEX_op_brcond_i32
889 #if TCG_TARGET_REG_BITS == 32
890 || c
== INDEX_op_brcond2_i32
891 #elif TCG_TARGET_REG_BITS == 64
892 || c
== INDEX_op_brcond_i64
895 if (args
[k
] < ARRAY_SIZE(cond_name
) && cond_name
[args
[k
]])
896 fprintf(outfile
, ",%s", cond_name
[args
[k
++]]);
898 fprintf(outfile
, ",$0x%" TCG_PRIlx
, args
[k
++]);
903 for(; i
< nb_cargs
; i
++) {
905 fprintf(outfile
, ",");
907 fprintf(outfile
, "$0x%" TCG_PRIlx
, arg
);
910 fprintf(outfile
, "\n");
911 args
+= nb_iargs
+ nb_oargs
+ nb_cargs
;
915 /* we give more priority to constraints with less registers */
916 static int get_constraint_priority(const TCGOpDef
*def
, int k
)
918 const TCGArgConstraint
*arg_ct
;
921 arg_ct
= &def
->args_ct
[k
];
922 if (arg_ct
->ct
& TCG_CT_ALIAS
) {
923 /* an alias is equivalent to a single register */
926 if (!(arg_ct
->ct
& TCG_CT_REG
))
929 for(i
= 0; i
< TCG_TARGET_NB_REGS
; i
++) {
930 if (tcg_regset_test_reg(arg_ct
->u
.regs
, i
))
934 return TCG_TARGET_NB_REGS
- n
+ 1;
937 /* sort from highest priority to lowest */
938 static void sort_constraints(TCGOpDef
*def
, int start
, int n
)
940 int i
, j
, p1
, p2
, tmp
;
942 for(i
= 0; i
< n
; i
++)
943 def
->sorted_args
[start
+ i
] = start
+ i
;
946 for(i
= 0; i
< n
- 1; i
++) {
947 for(j
= i
+ 1; j
< n
; j
++) {
948 p1
= get_constraint_priority(def
, def
->sorted_args
[start
+ i
]);
949 p2
= get_constraint_priority(def
, def
->sorted_args
[start
+ j
]);
951 tmp
= def
->sorted_args
[start
+ i
];
952 def
->sorted_args
[start
+ i
] = def
->sorted_args
[start
+ j
];
953 def
->sorted_args
[start
+ j
] = tmp
;
959 void tcg_add_target_add_op_defs(const TCGTargetOpDef
*tdefs
)
970 assert(op
>= 0 && op
< NB_OPS
);
971 def
= &tcg_op_defs
[op
];
972 nb_args
= def
->nb_iargs
+ def
->nb_oargs
;
973 for(i
= 0; i
< nb_args
; i
++) {
974 ct_str
= tdefs
->args_ct_str
[i
];
975 tcg_regset_clear(def
->args_ct
[i
].u
.regs
);
976 def
->args_ct
[i
].ct
= 0;
977 if (ct_str
[0] >= '0' && ct_str
[0] <= '9') {
979 oarg
= ct_str
[0] - '0';
980 assert(oarg
< def
->nb_oargs
);
981 assert(def
->args_ct
[oarg
].ct
& TCG_CT_REG
);
982 /* TCG_CT_ALIAS is for the output arguments. The input
983 argument is tagged with TCG_CT_IALIAS. */
984 def
->args_ct
[i
] = def
->args_ct
[oarg
];
985 def
->args_ct
[oarg
].ct
= TCG_CT_ALIAS
;
986 def
->args_ct
[oarg
].alias_index
= i
;
987 def
->args_ct
[i
].ct
|= TCG_CT_IALIAS
;
988 def
->args_ct
[i
].alias_index
= oarg
;
995 def
->args_ct
[i
].ct
|= TCG_CT_CONST
;
999 if (target_parse_constraint(&def
->args_ct
[i
], &ct_str
) < 0) {
1000 fprintf(stderr
, "Invalid constraint '%s' for arg %d of operation '%s'\n",
1001 ct_str
, i
, def
->name
);
1009 /* sort the constraints (XXX: this is just an heuristic) */
1010 sort_constraints(def
, 0, def
->nb_oargs
);
1011 sort_constraints(def
, def
->nb_oargs
, def
->nb_iargs
);
1017 printf("%s: sorted=", def
->name
);
1018 for(i
= 0; i
< def
->nb_oargs
+ def
->nb_iargs
; i
++)
1019 printf(" %d", def
->sorted_args
[i
]);
1028 #ifdef USE_LIVENESS_ANALYSIS
1030 /* set a nop for an operation using 'nb_args' */
1031 static inline void tcg_set_nop(TCGContext
*s
, uint16_t *opc_ptr
,
1032 TCGArg
*args
, int nb_args
)
1035 *opc_ptr
= INDEX_op_nop
;
1037 *opc_ptr
= INDEX_op_nopn
;
1039 args
[nb_args
- 1] = nb_args
;
1043 /* liveness analysis: end of function: globals are live, temps are
1045 /* XXX: at this stage, not used as there would be little gains because
1046 most TBs end with a conditional jump. */
1047 static inline void tcg_la_func_end(TCGContext
*s
, uint8_t *dead_temps
)
1049 memset(dead_temps
, 0, s
->nb_globals
);
1050 memset(dead_temps
+ s
->nb_globals
, 1, s
->nb_temps
- s
->nb_globals
);
1053 /* liveness analysis: end of basic block: globals are live, temps are
1054 dead, local temps are live. */
1055 static inline void tcg_la_bb_end(TCGContext
*s
, uint8_t *dead_temps
)
1060 memset(dead_temps
, 0, s
->nb_globals
);
1061 ts
= &s
->temps
[s
->nb_globals
];
1062 for(i
= s
->nb_globals
; i
< s
->nb_temps
; i
++) {
1071 /* Liveness analysis : update the opc_dead_iargs array to tell if a
1072 given input arguments is dead. Instructions updating dead
1073 temporaries are removed. */
1074 static void tcg_liveness_analysis(TCGContext
*s
)
1076 int i
, op_index
, op
, nb_args
, nb_iargs
, nb_oargs
, arg
, nb_ops
;
1078 const TCGOpDef
*def
;
1079 uint8_t *dead_temps
;
1080 unsigned int dead_iargs
;
1082 gen_opc_ptr
++; /* skip end */
1084 nb_ops
= gen_opc_ptr
- gen_opc_buf
;
1086 /* XXX: make it really dynamic */
1087 s
->op_dead_iargs
= tcg_malloc(OPC_BUF_SIZE
* sizeof(uint16_t));
1089 dead_temps
= tcg_malloc(s
->nb_temps
);
1090 memset(dead_temps
, 1, s
->nb_temps
);
1092 args
= gen_opparam_ptr
;
1093 op_index
= nb_ops
- 1;
1094 while (op_index
>= 0) {
1095 op
= gen_opc_buf
[op_index
];
1096 def
= &tcg_op_defs
[op
];
1104 nb_iargs
= args
[0] & 0xffff;
1105 nb_oargs
= args
[0] >> 16;
1107 call_flags
= args
[nb_oargs
+ nb_iargs
];
1109 /* pure functions can be removed if their result is not
1111 if (call_flags
& TCG_CALL_PURE
) {
1112 for(i
= 0; i
< nb_oargs
; i
++) {
1114 if (!dead_temps
[arg
])
1115 goto do_not_remove_call
;
1117 tcg_set_nop(s
, gen_opc_buf
+ op_index
,
1122 /* output args are dead */
1123 for(i
= 0; i
< nb_oargs
; i
++) {
1125 dead_temps
[arg
] = 1;
1128 if (!(call_flags
& TCG_CALL_CONST
)) {
1129 /* globals are live (they may be used by the call) */
1130 memset(dead_temps
, 0, s
->nb_globals
);
1133 /* input args are live */
1135 for(i
= 0; i
< nb_iargs
; i
++) {
1136 arg
= args
[i
+ nb_oargs
];
1137 if (arg
!= TCG_CALL_DUMMY_ARG
) {
1138 if (dead_temps
[arg
]) {
1139 dead_iargs
|= (1 << i
);
1141 dead_temps
[arg
] = 0;
1144 s
->op_dead_iargs
[op_index
] = dead_iargs
;
1149 case INDEX_op_set_label
:
1151 /* mark end of basic block */
1152 tcg_la_bb_end(s
, dead_temps
);
1154 case INDEX_op_debug_insn_start
:
1155 args
-= def
->nb_args
;
1161 case INDEX_op_discard
:
1163 /* mark the temporary as dead */
1164 dead_temps
[args
[0]] = 1;
1168 /* XXX: optimize by hardcoding common cases (e.g. triadic ops) */
1170 args
-= def
->nb_args
;
1171 nb_iargs
= def
->nb_iargs
;
1172 nb_oargs
= def
->nb_oargs
;
1174 /* Test if the operation can be removed because all
1175 its outputs are dead. We assume that nb_oargs == 0
1176 implies side effects */
1177 if (!(def
->flags
& TCG_OPF_SIDE_EFFECTS
) && nb_oargs
!= 0) {
1178 for(i
= 0; i
< nb_oargs
; i
++) {
1180 if (!dead_temps
[arg
])
1183 tcg_set_nop(s
, gen_opc_buf
+ op_index
, args
, def
->nb_args
);
1184 #ifdef CONFIG_PROFILER
1190 /* output args are dead */
1191 for(i
= 0; i
< nb_oargs
; i
++) {
1193 dead_temps
[arg
] = 1;
1196 /* if end of basic block, update */
1197 if (def
->flags
& TCG_OPF_BB_END
) {
1198 tcg_la_bb_end(s
, dead_temps
);
1199 } else if (def
->flags
& TCG_OPF_CALL_CLOBBER
) {
1200 /* globals are live */
1201 memset(dead_temps
, 0, s
->nb_globals
);
1204 /* input args are live */
1206 for(i
= 0; i
< nb_iargs
; i
++) {
1207 arg
= args
[i
+ nb_oargs
];
1208 if (dead_temps
[arg
]) {
1209 dead_iargs
|= (1 << i
);
1211 dead_temps
[arg
] = 0;
1213 s
->op_dead_iargs
[op_index
] = dead_iargs
;
1220 if (args
!= gen_opparam_buf
)
1224 /* dummy liveness analysis */
1225 void tcg_liveness_analysis(TCGContext
*s
)
1228 nb_ops
= gen_opc_ptr
- gen_opc_buf
;
1230 s
->op_dead_iargs
= tcg_malloc(nb_ops
* sizeof(uint16_t));
1231 memset(s
->op_dead_iargs
, 0, nb_ops
* sizeof(uint16_t));
1236 static void dump_regs(TCGContext
*s
)
1242 for(i
= 0; i
< s
->nb_temps
; i
++) {
1244 printf(" %10s: ", tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), i
));
1245 switch(ts
->val_type
) {
1247 printf("%s", tcg_target_reg_names
[ts
->reg
]);
1250 printf("%d(%s)", (int)ts
->mem_offset
, tcg_target_reg_names
[ts
->mem_reg
]);
1252 case TEMP_VAL_CONST
:
1253 printf("$0x%" TCG_PRIlx
, ts
->val
);
1265 for(i
= 0; i
< TCG_TARGET_NB_REGS
; i
++) {
1266 if (s
->reg_to_temp
[i
] >= 0) {
1268 tcg_target_reg_names
[i
],
1269 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), s
->reg_to_temp
[i
]));
1274 static void check_regs(TCGContext
*s
)
1280 for(reg
= 0; reg
< TCG_TARGET_NB_REGS
; reg
++) {
1281 k
= s
->reg_to_temp
[reg
];
1284 if (ts
->val_type
!= TEMP_VAL_REG
||
1286 printf("Inconsistency for register %s:\n",
1287 tcg_target_reg_names
[reg
]);
1292 for(k
= 0; k
< s
->nb_temps
; k
++) {
1294 if (ts
->val_type
== TEMP_VAL_REG
&&
1296 s
->reg_to_temp
[ts
->reg
] != k
) {
1297 printf("Inconsistency for temp %s:\n",
1298 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), k
));
1300 printf("reg state:\n");
1308 static void temp_allocate_frame(TCGContext
*s
, int temp
)
1311 ts
= &s
->temps
[temp
];
1312 s
->current_frame_offset
= (s
->current_frame_offset
+ sizeof(tcg_target_long
) - 1) & ~(sizeof(tcg_target_long
) - 1);
1313 if (s
->current_frame_offset
+ sizeof(tcg_target_long
) > s
->frame_end
)
1315 ts
->mem_offset
= s
->current_frame_offset
;
1316 ts
->mem_reg
= s
->frame_reg
;
1317 ts
->mem_allocated
= 1;
1318 s
->current_frame_offset
+= sizeof(tcg_target_long
);
1321 /* free register 'reg' by spilling the corresponding temporary if necessary */
1322 static void tcg_reg_free(TCGContext
*s
, int reg
)
1327 temp
= s
->reg_to_temp
[reg
];
1329 ts
= &s
->temps
[temp
];
1330 assert(ts
->val_type
== TEMP_VAL_REG
);
1331 if (!ts
->mem_coherent
) {
1332 if (!ts
->mem_allocated
)
1333 temp_allocate_frame(s
, temp
);
1334 tcg_out_st(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
1336 ts
->val_type
= TEMP_VAL_MEM
;
1337 s
->reg_to_temp
[reg
] = -1;
1341 /* Allocate a register belonging to reg1 & ~reg2 */
1342 static int tcg_reg_alloc(TCGContext
*s
, TCGRegSet reg1
, TCGRegSet reg2
)
1347 tcg_regset_andnot(reg_ct
, reg1
, reg2
);
1349 /* first try free registers */
1350 for(i
= 0; i
< ARRAY_SIZE(tcg_target_reg_alloc_order
); i
++) {
1351 reg
= tcg_target_reg_alloc_order
[i
];
1352 if (tcg_regset_test_reg(reg_ct
, reg
) && s
->reg_to_temp
[reg
] == -1)
1356 /* XXX: do better spill choice */
1357 for(i
= 0; i
< ARRAY_SIZE(tcg_target_reg_alloc_order
); i
++) {
1358 reg
= tcg_target_reg_alloc_order
[i
];
1359 if (tcg_regset_test_reg(reg_ct
, reg
)) {
1360 tcg_reg_free(s
, reg
);
1368 /* save a temporary to memory. 'allocated_regs' is used in case a
1369 temporary registers needs to be allocated to store a constant. */
1370 static void temp_save(TCGContext
*s
, int temp
, TCGRegSet allocated_regs
)
1375 ts
= &s
->temps
[temp
];
1376 if (!ts
->fixed_reg
) {
1377 switch(ts
->val_type
) {
1379 tcg_reg_free(s
, ts
->reg
);
1382 ts
->val_type
= TEMP_VAL_MEM
;
1384 case TEMP_VAL_CONST
:
1385 reg
= tcg_reg_alloc(s
, tcg_target_available_regs
[ts
->type
],
1387 if (!ts
->mem_allocated
)
1388 temp_allocate_frame(s
, temp
);
1389 tcg_out_movi(s
, ts
->type
, reg
, ts
->val
);
1390 tcg_out_st(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
1391 ts
->val_type
= TEMP_VAL_MEM
;
1401 /* save globals to their cannonical location and assume they can be
1402 modified be the following code. 'allocated_regs' is used in case a
1403 temporary registers needs to be allocated to store a constant. */
1404 static void save_globals(TCGContext
*s
, TCGRegSet allocated_regs
)
1408 for(i
= 0; i
< s
->nb_globals
; i
++) {
1409 temp_save(s
, i
, allocated_regs
);
1413 /* at the end of a basic block, we assume all temporaries are dead and
1414 all globals are stored at their canonical location. */
1415 static void tcg_reg_alloc_bb_end(TCGContext
*s
, TCGRegSet allocated_regs
)
1420 for(i
= s
->nb_globals
; i
< s
->nb_temps
; i
++) {
1422 if (ts
->temp_local
) {
1423 temp_save(s
, i
, allocated_regs
);
1425 if (ts
->val_type
== TEMP_VAL_REG
) {
1426 s
->reg_to_temp
[ts
->reg
] = -1;
1428 ts
->val_type
= TEMP_VAL_DEAD
;
1432 save_globals(s
, allocated_regs
);
1435 #define IS_DEAD_IARG(n) ((dead_iargs >> (n)) & 1)
1437 static void tcg_reg_alloc_movi(TCGContext
*s
, const TCGArg
*args
)
1440 tcg_target_ulong val
;
1442 ots
= &s
->temps
[args
[0]];
1445 if (ots
->fixed_reg
) {
1446 /* for fixed registers, we do not do any constant
1448 tcg_out_movi(s
, ots
->type
, ots
->reg
, val
);
1450 /* The movi is not explicitly generated here */
1451 if (ots
->val_type
== TEMP_VAL_REG
)
1452 s
->reg_to_temp
[ots
->reg
] = -1;
1453 ots
->val_type
= TEMP_VAL_CONST
;
1458 static void tcg_reg_alloc_mov(TCGContext
*s
, const TCGOpDef
*def
,
1460 unsigned int dead_iargs
)
1464 const TCGArgConstraint
*arg_ct
;
1466 ots
= &s
->temps
[args
[0]];
1467 ts
= &s
->temps
[args
[1]];
1468 arg_ct
= &def
->args_ct
[0];
1470 /* XXX: always mark arg dead if IS_DEAD_IARG(0) */
1471 if (ts
->val_type
== TEMP_VAL_REG
) {
1472 if (IS_DEAD_IARG(0) && !ts
->fixed_reg
&& !ots
->fixed_reg
) {
1473 /* the mov can be suppressed */
1474 if (ots
->val_type
== TEMP_VAL_REG
)
1475 s
->reg_to_temp
[ots
->reg
] = -1;
1477 s
->reg_to_temp
[reg
] = -1;
1478 ts
->val_type
= TEMP_VAL_DEAD
;
1480 if (ots
->val_type
== TEMP_VAL_REG
) {
1483 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, s
->reserved_regs
);
1485 if (ts
->reg
!= reg
) {
1486 tcg_out_mov(s
, reg
, ts
->reg
);
1489 } else if (ts
->val_type
== TEMP_VAL_MEM
) {
1490 if (ots
->val_type
== TEMP_VAL_REG
) {
1493 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, s
->reserved_regs
);
1495 tcg_out_ld(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
1496 } else if (ts
->val_type
== TEMP_VAL_CONST
) {
1497 if (ots
->fixed_reg
) {
1499 tcg_out_movi(s
, ots
->type
, reg
, ts
->val
);
1501 /* propagate constant */
1502 if (ots
->val_type
== TEMP_VAL_REG
)
1503 s
->reg_to_temp
[ots
->reg
] = -1;
1504 ots
->val_type
= TEMP_VAL_CONST
;
1511 s
->reg_to_temp
[reg
] = args
[0];
1513 ots
->val_type
= TEMP_VAL_REG
;
1514 ots
->mem_coherent
= 0;
1517 static void tcg_reg_alloc_op(TCGContext
*s
,
1518 const TCGOpDef
*def
, int opc
,
1520 unsigned int dead_iargs
)
1522 TCGRegSet allocated_regs
;
1523 int i
, k
, nb_iargs
, nb_oargs
, reg
;
1525 const TCGArgConstraint
*arg_ct
;
1527 TCGArg new_args
[TCG_MAX_OP_ARGS
];
1528 int const_args
[TCG_MAX_OP_ARGS
];
1530 nb_oargs
= def
->nb_oargs
;
1531 nb_iargs
= def
->nb_iargs
;
1533 /* copy constants */
1534 memcpy(new_args
+ nb_oargs
+ nb_iargs
,
1535 args
+ nb_oargs
+ nb_iargs
,
1536 sizeof(TCGArg
) * def
->nb_cargs
);
1538 /* satisfy input constraints */
1539 tcg_regset_set(allocated_regs
, s
->reserved_regs
);
1540 for(k
= 0; k
< nb_iargs
; k
++) {
1541 i
= def
->sorted_args
[nb_oargs
+ k
];
1543 arg_ct
= &def
->args_ct
[i
];
1544 ts
= &s
->temps
[arg
];
1545 if (ts
->val_type
== TEMP_VAL_MEM
) {
1546 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1547 tcg_out_ld(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
1548 ts
->val_type
= TEMP_VAL_REG
;
1550 ts
->mem_coherent
= 1;
1551 s
->reg_to_temp
[reg
] = arg
;
1552 } else if (ts
->val_type
== TEMP_VAL_CONST
) {
1553 if (tcg_target_const_match(ts
->val
, arg_ct
)) {
1554 /* constant is OK for instruction */
1556 new_args
[i
] = ts
->val
;
1559 /* need to move to a register */
1560 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1561 tcg_out_movi(s
, ts
->type
, reg
, ts
->val
);
1562 ts
->val_type
= TEMP_VAL_REG
;
1564 ts
->mem_coherent
= 0;
1565 s
->reg_to_temp
[reg
] = arg
;
1568 assert(ts
->val_type
== TEMP_VAL_REG
);
1569 if (arg_ct
->ct
& TCG_CT_IALIAS
) {
1570 if (ts
->fixed_reg
) {
1571 /* if fixed register, we must allocate a new register
1572 if the alias is not the same register */
1573 if (arg
!= args
[arg_ct
->alias_index
])
1574 goto allocate_in_reg
;
1576 /* if the input is aliased to an output and if it is
1577 not dead after the instruction, we must allocate
1578 a new register and move it */
1579 if (!IS_DEAD_IARG(i
- nb_oargs
))
1580 goto allocate_in_reg
;
1584 if (tcg_regset_test_reg(arg_ct
->u
.regs
, reg
)) {
1585 /* nothing to do : the constraint is satisfied */
1588 /* allocate a new register matching the constraint
1589 and move the temporary register into it */
1590 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1591 tcg_out_mov(s
, reg
, ts
->reg
);
1595 tcg_regset_set_reg(allocated_regs
, reg
);
1599 if (def
->flags
& TCG_OPF_BB_END
) {
1600 tcg_reg_alloc_bb_end(s
, allocated_regs
);
1602 /* mark dead temporaries and free the associated registers */
1603 for(i
= 0; i
< nb_iargs
; i
++) {
1604 arg
= args
[nb_oargs
+ i
];
1605 if (IS_DEAD_IARG(i
)) {
1606 ts
= &s
->temps
[arg
];
1607 if (!ts
->fixed_reg
) {
1608 if (ts
->val_type
== TEMP_VAL_REG
)
1609 s
->reg_to_temp
[ts
->reg
] = -1;
1610 ts
->val_type
= TEMP_VAL_DEAD
;
1615 if (def
->flags
& TCG_OPF_CALL_CLOBBER
) {
1616 /* XXX: permit generic clobber register list ? */
1617 for(reg
= 0; reg
< TCG_TARGET_NB_REGS
; reg
++) {
1618 if (tcg_regset_test_reg(tcg_target_call_clobber_regs
, reg
)) {
1619 tcg_reg_free(s
, reg
);
1622 /* XXX: for load/store we could do that only for the slow path
1623 (i.e. when a memory callback is called) */
1625 /* store globals and free associated registers (we assume the insn
1626 can modify any global. */
1627 save_globals(s
, allocated_regs
);
1630 /* satisfy the output constraints */
1631 tcg_regset_set(allocated_regs
, s
->reserved_regs
);
1632 for(k
= 0; k
< nb_oargs
; k
++) {
1633 i
= def
->sorted_args
[k
];
1635 arg_ct
= &def
->args_ct
[i
];
1636 ts
= &s
->temps
[arg
];
1637 if (arg_ct
->ct
& TCG_CT_ALIAS
) {
1638 reg
= new_args
[arg_ct
->alias_index
];
1640 /* if fixed register, we try to use it */
1642 if (ts
->fixed_reg
&&
1643 tcg_regset_test_reg(arg_ct
->u
.regs
, reg
)) {
1646 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1648 tcg_regset_set_reg(allocated_regs
, reg
);
1649 /* if a fixed register is used, then a move will be done afterwards */
1650 if (!ts
->fixed_reg
) {
1651 if (ts
->val_type
== TEMP_VAL_REG
)
1652 s
->reg_to_temp
[ts
->reg
] = -1;
1653 ts
->val_type
= TEMP_VAL_REG
;
1655 /* temp value is modified, so the value kept in memory is
1656 potentially not the same */
1657 ts
->mem_coherent
= 0;
1658 s
->reg_to_temp
[reg
] = arg
;
1665 /* emit instruction */
1666 tcg_out_op(s
, opc
, new_args
, const_args
);
1668 /* move the outputs in the correct register if needed */
1669 for(i
= 0; i
< nb_oargs
; i
++) {
1670 ts
= &s
->temps
[args
[i
]];
1672 if (ts
->fixed_reg
&& ts
->reg
!= reg
) {
1673 tcg_out_mov(s
, ts
->reg
, reg
);
1678 #ifdef TCG_TARGET_STACK_GROWSUP
1679 #define STACK_DIR(x) (-(x))
1681 #define STACK_DIR(x) (x)
1684 static int tcg_reg_alloc_call(TCGContext
*s
, const TCGOpDef
*def
,
1685 int opc
, const TCGArg
*args
,
1686 unsigned int dead_iargs
)
1688 int nb_iargs
, nb_oargs
, flags
, nb_regs
, i
, reg
, nb_params
;
1689 TCGArg arg
, func_arg
;
1691 tcg_target_long stack_offset
, call_stack_size
, func_addr
;
1692 int const_func_arg
, allocate_args
;
1693 TCGRegSet allocated_regs
;
1694 const TCGArgConstraint
*arg_ct
;
1698 nb_oargs
= arg
>> 16;
1699 nb_iargs
= arg
& 0xffff;
1700 nb_params
= nb_iargs
- 1;
1702 flags
= args
[nb_oargs
+ nb_iargs
];
1704 nb_regs
= tcg_target_get_call_iarg_regs_count(flags
);
1705 if (nb_regs
> nb_params
)
1706 nb_regs
= nb_params
;
1708 /* assign stack slots first */
1709 /* XXX: preallocate call stack */
1710 call_stack_size
= (nb_params
- nb_regs
) * sizeof(tcg_target_long
);
1711 call_stack_size
= (call_stack_size
+ TCG_TARGET_STACK_ALIGN
- 1) &
1712 ~(TCG_TARGET_STACK_ALIGN
- 1);
1713 allocate_args
= (call_stack_size
> TCG_STATIC_CALL_ARGS_SIZE
);
1714 if (allocate_args
) {
1715 tcg_out_addi(s
, TCG_REG_CALL_STACK
, -STACK_DIR(call_stack_size
));
1718 stack_offset
= TCG_TARGET_CALL_STACK_OFFSET
;
1719 for(i
= nb_regs
; i
< nb_params
; i
++) {
1720 arg
= args
[nb_oargs
+ i
];
1721 #ifdef TCG_TARGET_STACK_GROWSUP
1722 stack_offset
-= sizeof(tcg_target_long
);
1724 if (arg
!= TCG_CALL_DUMMY_ARG
) {
1725 ts
= &s
->temps
[arg
];
1726 if (ts
->val_type
== TEMP_VAL_REG
) {
1727 tcg_out_st(s
, ts
->type
, ts
->reg
, TCG_REG_CALL_STACK
, stack_offset
);
1728 } else if (ts
->val_type
== TEMP_VAL_MEM
) {
1729 reg
= tcg_reg_alloc(s
, tcg_target_available_regs
[ts
->type
],
1731 /* XXX: not correct if reading values from the stack */
1732 tcg_out_ld(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
1733 tcg_out_st(s
, ts
->type
, reg
, TCG_REG_CALL_STACK
, stack_offset
);
1734 } else if (ts
->val_type
== TEMP_VAL_CONST
) {
1735 reg
= tcg_reg_alloc(s
, tcg_target_available_regs
[ts
->type
],
1737 /* XXX: sign extend may be needed on some targets */
1738 tcg_out_movi(s
, ts
->type
, reg
, ts
->val
);
1739 tcg_out_st(s
, ts
->type
, reg
, TCG_REG_CALL_STACK
, stack_offset
);
1744 #ifndef TCG_TARGET_STACK_GROWSUP
1745 stack_offset
+= sizeof(tcg_target_long
);
1749 /* assign input registers */
1750 tcg_regset_set(allocated_regs
, s
->reserved_regs
);
1751 for(i
= 0; i
< nb_regs
; i
++) {
1752 arg
= args
[nb_oargs
+ i
];
1753 if (arg
!= TCG_CALL_DUMMY_ARG
) {
1754 ts
= &s
->temps
[arg
];
1755 reg
= tcg_target_call_iarg_regs
[i
];
1756 tcg_reg_free(s
, reg
);
1757 if (ts
->val_type
== TEMP_VAL_REG
) {
1758 if (ts
->reg
!= reg
) {
1759 tcg_out_mov(s
, reg
, ts
->reg
);
1761 } else if (ts
->val_type
== TEMP_VAL_MEM
) {
1762 tcg_out_ld(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
1763 } else if (ts
->val_type
== TEMP_VAL_CONST
) {
1764 /* XXX: sign extend ? */
1765 tcg_out_movi(s
, ts
->type
, reg
, ts
->val
);
1769 tcg_regset_set_reg(allocated_regs
, reg
);
1773 /* assign function address */
1774 func_arg
= args
[nb_oargs
+ nb_iargs
- 1];
1775 arg_ct
= &def
->args_ct
[0];
1776 ts
= &s
->temps
[func_arg
];
1777 func_addr
= ts
->val
;
1779 if (ts
->val_type
== TEMP_VAL_MEM
) {
1780 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1781 tcg_out_ld(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
1783 tcg_regset_set_reg(allocated_regs
, reg
);
1784 } else if (ts
->val_type
== TEMP_VAL_REG
) {
1786 if (!tcg_regset_test_reg(arg_ct
->u
.regs
, reg
)) {
1787 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1788 tcg_out_mov(s
, reg
, ts
->reg
);
1791 tcg_regset_set_reg(allocated_regs
, reg
);
1792 } else if (ts
->val_type
== TEMP_VAL_CONST
) {
1793 if (tcg_target_const_match(func_addr
, arg_ct
)) {
1795 func_arg
= func_addr
;
1797 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1798 tcg_out_movi(s
, ts
->type
, reg
, func_addr
);
1800 tcg_regset_set_reg(allocated_regs
, reg
);
1807 /* mark dead temporaries and free the associated registers */
1808 for(i
= 0; i
< nb_iargs
; i
++) {
1809 arg
= args
[nb_oargs
+ i
];
1810 if (IS_DEAD_IARG(i
)) {
1811 ts
= &s
->temps
[arg
];
1812 if (!ts
->fixed_reg
) {
1813 if (ts
->val_type
== TEMP_VAL_REG
)
1814 s
->reg_to_temp
[ts
->reg
] = -1;
1815 ts
->val_type
= TEMP_VAL_DEAD
;
1820 /* clobber call registers */
1821 for(reg
= 0; reg
< TCG_TARGET_NB_REGS
; reg
++) {
1822 if (tcg_regset_test_reg(tcg_target_call_clobber_regs
, reg
)) {
1823 tcg_reg_free(s
, reg
);
1827 /* store globals and free associated registers (we assume the call
1828 can modify any global. */
1829 if (!(flags
& TCG_CALL_CONST
)) {
1830 save_globals(s
, allocated_regs
);
1833 tcg_out_op(s
, opc
, &func_arg
, &const_func_arg
);
1835 if (allocate_args
) {
1836 tcg_out_addi(s
, TCG_REG_CALL_STACK
, STACK_DIR(call_stack_size
));
1839 /* assign output registers and emit moves if needed */
1840 for(i
= 0; i
< nb_oargs
; i
++) {
1842 ts
= &s
->temps
[arg
];
1843 reg
= tcg_target_call_oarg_regs
[i
];
1844 assert(s
->reg_to_temp
[reg
] == -1);
1845 if (ts
->fixed_reg
) {
1846 if (ts
->reg
!= reg
) {
1847 tcg_out_mov(s
, ts
->reg
, reg
);
1850 if (ts
->val_type
== TEMP_VAL_REG
)
1851 s
->reg_to_temp
[ts
->reg
] = -1;
1852 ts
->val_type
= TEMP_VAL_REG
;
1854 ts
->mem_coherent
= 0;
1855 s
->reg_to_temp
[reg
] = arg
;
1859 return nb_iargs
+ nb_oargs
+ def
->nb_cargs
+ 1;
1862 #ifdef CONFIG_PROFILER
1864 static int64_t tcg_table_op_count
[NB_OPS
];
1866 void dump_op_count(void)
1870 f
= fopen("/tmp/op.log", "w");
1871 for(i
= INDEX_op_end
; i
< NB_OPS
; i
++) {
1872 fprintf(f
, "%s %" PRId64
"\n", tcg_op_defs
[i
].name
, tcg_table_op_count
[i
]);
1879 static inline int tcg_gen_code_common(TCGContext
*s
, uint8_t *gen_code_buf
,
1883 const TCGOpDef
*def
;
1884 unsigned int dead_iargs
;
1888 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP
))) {
1890 tcg_dump_ops(s
, logfile
);
1895 #ifdef CONFIG_PROFILER
1896 s
->la_time
-= profile_getclock();
1898 tcg_liveness_analysis(s
);
1899 #ifdef CONFIG_PROFILER
1900 s
->la_time
+= profile_getclock();
1904 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_OPT
))) {
1905 qemu_log("OP after la:\n");
1906 tcg_dump_ops(s
, logfile
);
1911 tcg_reg_alloc_start(s
);
1913 s
->code_buf
= gen_code_buf
;
1914 s
->code_ptr
= gen_code_buf
;
1916 args
= gen_opparam_buf
;
1920 opc
= gen_opc_buf
[op_index
];
1921 #ifdef CONFIG_PROFILER
1922 tcg_table_op_count
[opc
]++;
1924 def
= &tcg_op_defs
[opc
];
1926 printf("%s: %d %d %d\n", def
->name
,
1927 def
->nb_oargs
, def
->nb_iargs
, def
->nb_cargs
);
1931 case INDEX_op_mov_i32
:
1932 #if TCG_TARGET_REG_BITS == 64
1933 case INDEX_op_mov_i64
:
1935 dead_iargs
= s
->op_dead_iargs
[op_index
];
1936 tcg_reg_alloc_mov(s
, def
, args
, dead_iargs
);
1938 case INDEX_op_movi_i32
:
1939 #if TCG_TARGET_REG_BITS == 64
1940 case INDEX_op_movi_i64
:
1942 tcg_reg_alloc_movi(s
, args
);
1944 case INDEX_op_debug_insn_start
:
1945 /* debug instruction */
1955 case INDEX_op_discard
:
1958 ts
= &s
->temps
[args
[0]];
1959 /* mark the temporary as dead */
1960 if (!ts
->fixed_reg
) {
1961 if (ts
->val_type
== TEMP_VAL_REG
)
1962 s
->reg_to_temp
[ts
->reg
] = -1;
1963 ts
->val_type
= TEMP_VAL_DEAD
;
1967 case INDEX_op_set_label
:
1968 tcg_reg_alloc_bb_end(s
, s
->reserved_regs
);
1969 tcg_out_label(s
, args
[0], (long)s
->code_ptr
);
1972 dead_iargs
= s
->op_dead_iargs
[op_index
];
1973 args
+= tcg_reg_alloc_call(s
, def
, opc
, args
, dead_iargs
);
1978 /* Note: in order to speed up the code, it would be much
1979 faster to have specialized register allocator functions for
1980 some common argument patterns */
1981 dead_iargs
= s
->op_dead_iargs
[op_index
];
1982 tcg_reg_alloc_op(s
, def
, opc
, args
, dead_iargs
);
1985 args
+= def
->nb_args
;
1987 if (search_pc
>= 0 && search_pc
< s
->code_ptr
- gen_code_buf
) {
1999 int tcg_gen_code(TCGContext
*s
, uint8_t *gen_code_buf
)
2001 #ifdef CONFIG_PROFILER
2004 n
= (gen_opc_ptr
- gen_opc_buf
);
2006 if (n
> s
->op_count_max
)
2007 s
->op_count_max
= n
;
2009 s
->temp_count
+= s
->nb_temps
;
2010 if (s
->nb_temps
> s
->temp_count_max
)
2011 s
->temp_count_max
= s
->nb_temps
;
2015 tcg_gen_code_common(s
, gen_code_buf
, -1);
2017 /* flush instruction cache */
2018 flush_icache_range((unsigned long)gen_code_buf
,
2019 (unsigned long)s
->code_ptr
);
2020 return s
->code_ptr
- gen_code_buf
;
2023 /* Return the index of the micro operation such as the pc after is <
2024 offset bytes from the start of the TB. The contents of gen_code_buf must
2025 not be changed, though writing the same values is ok.
2026 Return -1 if not found. */
2027 int tcg_gen_code_search_pc(TCGContext
*s
, uint8_t *gen_code_buf
, long offset
)
2029 return tcg_gen_code_common(s
, gen_code_buf
, offset
);
2032 #ifdef CONFIG_PROFILER
2033 void tcg_dump_info(FILE *f
,
2034 int (*cpu_fprintf
)(FILE *f
, const char *fmt
, ...))
2036 TCGContext
*s
= &tcg_ctx
;
2039 tot
= s
->interm_time
+ s
->code_time
;
2040 cpu_fprintf(f
, "JIT cycles %" PRId64
" (%0.3f s at 2.4 GHz)\n",
2042 cpu_fprintf(f
, "translated TBs %" PRId64
" (aborted=%" PRId64
" %0.1f%%)\n",
2044 s
->tb_count1
- s
->tb_count
,
2045 s
->tb_count1
? (double)(s
->tb_count1
- s
->tb_count
) / s
->tb_count1
* 100.0 : 0);
2046 cpu_fprintf(f
, "avg ops/TB %0.1f max=%d\n",
2047 s
->tb_count
? (double)s
->op_count
/ s
->tb_count
: 0, s
->op_count_max
);
2048 cpu_fprintf(f
, "deleted ops/TB %0.2f\n",
2050 (double)s
->del_op_count
/ s
->tb_count
: 0);
2051 cpu_fprintf(f
, "avg temps/TB %0.2f max=%d\n",
2053 (double)s
->temp_count
/ s
->tb_count
: 0,
2056 cpu_fprintf(f
, "cycles/op %0.1f\n",
2057 s
->op_count
? (double)tot
/ s
->op_count
: 0);
2058 cpu_fprintf(f
, "cycles/in byte %0.1f\n",
2059 s
->code_in_len
? (double)tot
/ s
->code_in_len
: 0);
2060 cpu_fprintf(f
, "cycles/out byte %0.1f\n",
2061 s
->code_out_len
? (double)tot
/ s
->code_out_len
: 0);
2064 cpu_fprintf(f
, " gen_interm time %0.1f%%\n",
2065 (double)s
->interm_time
/ tot
* 100.0);
2066 cpu_fprintf(f
, " gen_code time %0.1f%%\n",
2067 (double)s
->code_time
/ tot
* 100.0);
2068 cpu_fprintf(f
, "liveness/code time %0.1f%%\n",
2069 (double)s
->la_time
/ (s
->code_time
? s
->code_time
: 1) * 100.0);
2070 cpu_fprintf(f
, "cpu_restore count %" PRId64
"\n",
2072 cpu_fprintf(f
, " avg cycles %0.1f\n",
2073 s
->restore_count
? (double)s
->restore_time
/ s
->restore_count
: 0);
2075 extern void dump_op_count(void);
2080 void tcg_dump_info(FILE *f
,
2081 int (*cpu_fprintf
)(FILE *f
, const char *fmt
, ...))
2083 cpu_fprintf(f
, "[TCG profiler not compiled]\n");