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 suppress various consistency checks (faster) */
28 /* define it to use liveness analysis (better code) */
29 #define USE_LIVENESS_ANALYSIS
45 #include "qemu-common.h"
46 #include "cache-utils.h"
48 /* Note: the long term plan is to reduce the dependancies on the QEMU
49 CPU definitions. Currently they are used for qemu_ld/st
51 #define NO_CPU_IO_DEFS
59 static void patch_reloc(uint8_t *code_ptr
, int type
,
60 tcg_target_long value
, tcg_target_long addend
);
62 static TCGOpDef tcg_op_defs
[] = {
63 #define DEF(s, n, copy_size) { #s, 0, 0, n, n, 0, copy_size },
64 #define DEF2(s, iargs, oargs, cargs, flags) { #s, iargs, oargs, cargs, iargs + oargs + cargs, flags, 0 },
70 static TCGRegSet tcg_target_available_regs
[2];
71 static TCGRegSet tcg_target_call_clobber_regs
;
73 /* XXX: move that inside the context */
74 uint16_t *gen_opc_ptr
;
75 TCGArg
*gen_opparam_ptr
;
77 static inline void tcg_out8(TCGContext
*s
, uint8_t v
)
82 static inline void tcg_out16(TCGContext
*s
, uint16_t v
)
84 *(uint16_t *)s
->code_ptr
= v
;
88 static inline void tcg_out32(TCGContext
*s
, uint32_t v
)
90 *(uint32_t *)s
->code_ptr
= v
;
94 /* label relocation processing */
96 void tcg_out_reloc(TCGContext
*s
, uint8_t *code_ptr
, int type
,
97 int label_index
, long addend
)
102 l
= &s
->labels
[label_index
];
104 /* FIXME: This may break relocations on RISC targets that
105 modify instruction fields in place. The caller may not have
106 written the initial value. */
107 patch_reloc(code_ptr
, type
, l
->u
.value
, addend
);
109 /* add a new relocation entry */
110 r
= tcg_malloc(sizeof(TCGRelocation
));
114 r
->next
= l
->u
.first_reloc
;
115 l
->u
.first_reloc
= r
;
119 static void tcg_out_label(TCGContext
*s
, int label_index
,
120 tcg_target_long value
)
125 l
= &s
->labels
[label_index
];
128 r
= l
->u
.first_reloc
;
130 patch_reloc(r
->ptr
, r
->type
, value
, r
->addend
);
137 int gen_new_label(void)
139 TCGContext
*s
= &tcg_ctx
;
143 if (s
->nb_labels
>= TCG_MAX_LABELS
)
145 idx
= s
->nb_labels
++;
148 l
->u
.first_reloc
= NULL
;
152 #include "tcg-target.c"
154 /* pool based memory allocation */
155 void *tcg_malloc_internal(TCGContext
*s
, int size
)
160 if (size
> TCG_POOL_CHUNK_SIZE
) {
161 /* big malloc: insert a new pool (XXX: could optimize) */
162 p
= qemu_malloc(sizeof(TCGPool
) + size
);
165 s
->pool_current
->next
= p
;
168 p
->next
= s
->pool_current
;
178 pool_size
= TCG_POOL_CHUNK_SIZE
;
179 p
= qemu_malloc(sizeof(TCGPool
) + pool_size
);
183 s
->pool_current
->next
= p
;
192 s
->pool_cur
= p
->data
+ size
;
193 s
->pool_end
= p
->data
+ p
->size
;
197 void tcg_pool_reset(TCGContext
*s
)
199 s
->pool_cur
= s
->pool_end
= NULL
;
200 s
->pool_current
= NULL
;
203 void tcg_context_init(TCGContext
*s
)
205 int op
, total_args
, n
;
207 TCGArgConstraint
*args_ct
;
210 memset(s
, 0, sizeof(*s
));
211 s
->temps
= s
->static_temps
;
214 /* Count total number of arguments and allocate the corresponding
217 for(op
= 0; op
< NB_OPS
; op
++) {
218 def
= &tcg_op_defs
[op
];
219 n
= def
->nb_iargs
+ def
->nb_oargs
;
223 args_ct
= qemu_malloc(sizeof(TCGArgConstraint
) * total_args
);
224 sorted_args
= qemu_malloc(sizeof(int) * total_args
);
226 for(op
= 0; op
< NB_OPS
; op
++) {
227 def
= &tcg_op_defs
[op
];
228 def
->args_ct
= args_ct
;
229 def
->sorted_args
= sorted_args
;
230 n
= def
->nb_iargs
+ def
->nb_oargs
;
237 /* init global prologue and epilogue */
238 s
->code_buf
= code_gen_prologue
;
239 s
->code_ptr
= s
->code_buf
;
240 tcg_target_qemu_prologue(s
);
241 flush_icache_range((unsigned long)s
->code_buf
,
242 (unsigned long)s
->code_ptr
);
245 void tcg_set_frame(TCGContext
*s
, int reg
,
246 tcg_target_long start
, tcg_target_long size
)
248 s
->frame_start
= start
;
249 s
->frame_end
= start
+ size
;
253 void tcg_func_start(TCGContext
*s
)
257 s
->nb_temps
= s
->nb_globals
;
258 for(i
= 0; i
< (TCG_TYPE_COUNT
* 2); i
++)
259 s
->first_free_temp
[i
] = -1;
260 s
->labels
= tcg_malloc(sizeof(TCGLabel
) * TCG_MAX_LABELS
);
262 s
->current_frame_offset
= s
->frame_start
;
264 gen_opc_ptr
= gen_opc_buf
;
265 gen_opparam_ptr
= gen_opparam_buf
;
268 static inline void tcg_temp_alloc(TCGContext
*s
, int n
)
270 if (n
> TCG_MAX_TEMPS
)
274 static inline int tcg_global_reg_new_internal(TCGType type
, int reg
,
277 TCGContext
*s
= &tcg_ctx
;
281 #if TCG_TARGET_REG_BITS == 32
282 if (type
!= TCG_TYPE_I32
)
285 if (tcg_regset_test_reg(s
->reserved_regs
, reg
))
288 tcg_temp_alloc(s
, s
->nb_globals
+ 1);
289 ts
= &s
->temps
[s
->nb_globals
];
290 ts
->base_type
= type
;
296 tcg_regset_set_reg(s
->reserved_regs
, reg
);
300 TCGv_i32
tcg_global_reg_new_i32(int reg
, const char *name
)
304 idx
= tcg_global_reg_new_internal(TCG_TYPE_I32
, reg
, name
);
305 return MAKE_TCGV_I32(idx
);
308 TCGv_i64
tcg_global_reg_new_i64(int reg
, const char *name
)
312 idx
= tcg_global_reg_new_internal(TCG_TYPE_I64
, reg
, name
);
313 return MAKE_TCGV_I64(idx
);
316 static inline int tcg_global_mem_new_internal(TCGType type
, int reg
,
317 tcg_target_long offset
,
320 TCGContext
*s
= &tcg_ctx
;
325 #if TCG_TARGET_REG_BITS == 32
326 if (type
== TCG_TYPE_I64
) {
328 tcg_temp_alloc(s
, s
->nb_globals
+ 2);
329 ts
= &s
->temps
[s
->nb_globals
];
330 ts
->base_type
= type
;
331 ts
->type
= TCG_TYPE_I32
;
333 ts
->mem_allocated
= 1;
335 #ifdef TCG_TARGET_WORDS_BIGENDIAN
336 ts
->mem_offset
= offset
+ 4;
338 ts
->mem_offset
= offset
;
340 pstrcpy(buf
, sizeof(buf
), name
);
341 pstrcat(buf
, sizeof(buf
), "_0");
342 ts
->name
= strdup(buf
);
345 ts
->base_type
= type
;
346 ts
->type
= TCG_TYPE_I32
;
348 ts
->mem_allocated
= 1;
350 #ifdef TCG_TARGET_WORDS_BIGENDIAN
351 ts
->mem_offset
= offset
;
353 ts
->mem_offset
= offset
+ 4;
355 pstrcpy(buf
, sizeof(buf
), name
);
356 pstrcat(buf
, sizeof(buf
), "_1");
357 ts
->name
= strdup(buf
);
363 tcg_temp_alloc(s
, s
->nb_globals
+ 1);
364 ts
= &s
->temps
[s
->nb_globals
];
365 ts
->base_type
= type
;
368 ts
->mem_allocated
= 1;
370 ts
->mem_offset
= offset
;
377 TCGv_i32
tcg_global_mem_new_i32(int reg
, tcg_target_long offset
,
382 idx
= tcg_global_mem_new_internal(TCG_TYPE_I32
, reg
, offset
, name
);
383 return MAKE_TCGV_I32(idx
);
386 TCGv_i64
tcg_global_mem_new_i64(int reg
, tcg_target_long offset
,
391 idx
= tcg_global_mem_new_internal(TCG_TYPE_I64
, reg
, offset
, name
);
392 return MAKE_TCGV_I64(idx
);
395 static inline int tcg_temp_new_internal(TCGType type
, int temp_local
)
397 TCGContext
*s
= &tcg_ctx
;
404 idx
= s
->first_free_temp
[k
];
406 /* There is already an available temp with the
409 s
->first_free_temp
[k
] = ts
->next_free_temp
;
410 ts
->temp_allocated
= 1;
411 assert(ts
->temp_local
== temp_local
);
414 #if TCG_TARGET_REG_BITS == 32
415 if (type
== TCG_TYPE_I64
) {
416 tcg_temp_alloc(s
, s
->nb_temps
+ 2);
417 ts
= &s
->temps
[s
->nb_temps
];
418 ts
->base_type
= type
;
419 ts
->type
= TCG_TYPE_I32
;
420 ts
->temp_allocated
= 1;
421 ts
->temp_local
= temp_local
;
424 ts
->base_type
= TCG_TYPE_I32
;
425 ts
->type
= TCG_TYPE_I32
;
426 ts
->temp_allocated
= 1;
427 ts
->temp_local
= temp_local
;
433 tcg_temp_alloc(s
, s
->nb_temps
+ 1);
434 ts
= &s
->temps
[s
->nb_temps
];
435 ts
->base_type
= type
;
437 ts
->temp_allocated
= 1;
438 ts
->temp_local
= temp_local
;
446 TCGv_i32
tcg_temp_new_internal_i32(int temp_local
)
450 idx
= tcg_temp_new_internal(TCG_TYPE_I32
, temp_local
);
451 return MAKE_TCGV_I32(idx
);
454 TCGv_i64
tcg_temp_new_internal_i64(int temp_local
)
458 idx
= tcg_temp_new_internal(TCG_TYPE_I64
, temp_local
);
459 return MAKE_TCGV_I64(idx
);
462 static inline void tcg_temp_free_internal(int idx
)
464 TCGContext
*s
= &tcg_ctx
;
468 assert(idx
>= s
->nb_globals
&& idx
< s
->nb_temps
);
470 assert(ts
->temp_allocated
!= 0);
471 ts
->temp_allocated
= 0;
475 ts
->next_free_temp
= s
->first_free_temp
[k
];
476 s
->first_free_temp
[k
] = idx
;
479 void tcg_temp_free_i32(TCGv_i32 arg
)
481 tcg_temp_free_internal(GET_TCGV_I32(arg
));
484 void tcg_temp_free_i64(TCGv_i64 arg
)
486 tcg_temp_free_internal(GET_TCGV_I64(arg
));
489 TCGv_i32
tcg_const_i32(int32_t val
)
492 t0
= tcg_temp_new_i32();
493 tcg_gen_movi_i32(t0
, val
);
497 TCGv_i64
tcg_const_i64(int64_t val
)
500 t0
= tcg_temp_new_i64();
501 tcg_gen_movi_i64(t0
, val
);
505 TCGv_i32
tcg_const_local_i32(int32_t val
)
508 t0
= tcg_temp_local_new_i32();
509 tcg_gen_movi_i32(t0
, val
);
513 TCGv_i64
tcg_const_local_i64(int64_t val
)
516 t0
= tcg_temp_local_new_i64();
517 tcg_gen_movi_i64(t0
, val
);
521 void tcg_register_helper(void *func
, const char *name
)
523 TCGContext
*s
= &tcg_ctx
;
525 if ((s
->nb_helpers
+ 1) > s
->allocated_helpers
) {
526 n
= s
->allocated_helpers
;
532 s
->helpers
= realloc(s
->helpers
, n
* sizeof(TCGHelperInfo
));
533 s
->allocated_helpers
= n
;
535 s
->helpers
[s
->nb_helpers
].func
= (tcg_target_ulong
)func
;
536 s
->helpers
[s
->nb_helpers
].name
= name
;
540 /* Note: we convert the 64 bit args to 32 bit and do some alignment
541 and endian swap. Maybe it would be better to do the alignment
542 and endian swap in tcg_reg_alloc_call(). */
543 void tcg_gen_callN(TCGContext
*s
, TCGv_ptr func
, unsigned int flags
,
544 int sizemask
, TCGArg ret
, int nargs
, TCGArg
*args
)
551 *gen_opc_ptr
++ = INDEX_op_call
;
552 nparam
= gen_opparam_ptr
++;
553 call_type
= (flags
& TCG_CALL_TYPE_MASK
);
554 if (ret
!= TCG_CALL_DUMMY_ARG
) {
555 #if TCG_TARGET_REG_BITS < 64
557 #ifdef TCG_TARGET_WORDS_BIGENDIAN
558 *gen_opparam_ptr
++ = ret
+ 1;
559 *gen_opparam_ptr
++ = ret
;
561 *gen_opparam_ptr
++ = ret
;
562 *gen_opparam_ptr
++ = ret
+ 1;
568 *gen_opparam_ptr
++ = ret
;
575 for (i
= 0; i
< nargs
; i
++) {
576 #if TCG_TARGET_REG_BITS < 64
577 if (sizemask
& (2 << i
)) {
578 #ifdef TCG_TARGET_I386
579 /* REGPARM case: if the third parameter is 64 bit, it is
580 allocated on the stack */
581 if (i
== 2 && call_type
== TCG_CALL_TYPE_REGPARM
) {
582 call_type
= TCG_CALL_TYPE_REGPARM_2
;
583 flags
= (flags
& ~TCG_CALL_TYPE_MASK
) | call_type
;
586 #ifdef TCG_TARGET_CALL_ALIGN_ARGS
587 /* some targets want aligned 64 bit args */
589 *gen_opparam_ptr
++ = TCG_CALL_DUMMY_ARG
;
593 #ifdef TCG_TARGET_WORDS_BIGENDIAN
594 *gen_opparam_ptr
++ = args
[i
] + 1;
595 *gen_opparam_ptr
++ = args
[i
];
597 *gen_opparam_ptr
++ = args
[i
];
598 *gen_opparam_ptr
++ = args
[i
] + 1;
604 *gen_opparam_ptr
++ = args
[i
];
608 *gen_opparam_ptr
++ = GET_TCGV_PTR(func
);
610 *gen_opparam_ptr
++ = flags
;
612 *nparam
= (nb_rets
<< 16) | (real_args
+ 1);
614 /* total parameters, needed to go backward in the instruction stream */
615 *gen_opparam_ptr
++ = 1 + nb_rets
+ real_args
+ 3;
618 #if TCG_TARGET_REG_BITS == 32
619 void tcg_gen_shifti_i64(TCGv_i64 ret
, TCGv_i64 arg1
,
620 int c
, int right
, int arith
)
623 tcg_gen_mov_i32(TCGV_LOW(ret
), TCGV_LOW(arg1
));
624 tcg_gen_mov_i32(TCGV_HIGH(ret
), TCGV_HIGH(arg1
));
625 } else if (c
>= 32) {
629 tcg_gen_sari_i32(TCGV_LOW(ret
), TCGV_HIGH(arg1
), c
);
630 tcg_gen_sari_i32(TCGV_HIGH(ret
), TCGV_HIGH(arg1
), 31);
632 tcg_gen_shri_i32(TCGV_LOW(ret
), TCGV_HIGH(arg1
), c
);
633 tcg_gen_movi_i32(TCGV_HIGH(ret
), 0);
636 tcg_gen_shli_i32(TCGV_HIGH(ret
), TCGV_LOW(arg1
), c
);
637 tcg_gen_movi_i32(TCGV_LOW(ret
), 0);
642 t0
= tcg_temp_new_i32();
643 t1
= tcg_temp_new_i32();
645 tcg_gen_shli_i32(t0
, TCGV_HIGH(arg1
), 32 - c
);
647 tcg_gen_sari_i32(t1
, TCGV_HIGH(arg1
), c
);
649 tcg_gen_shri_i32(t1
, TCGV_HIGH(arg1
), c
);
650 tcg_gen_shri_i32(TCGV_LOW(ret
), TCGV_LOW(arg1
), c
);
651 tcg_gen_or_i32(TCGV_LOW(ret
), TCGV_LOW(ret
), t0
);
652 tcg_gen_mov_i32(TCGV_HIGH(ret
), t1
);
654 tcg_gen_shri_i32(t0
, TCGV_LOW(arg1
), 32 - c
);
655 /* Note: ret can be the same as arg1, so we use t1 */
656 tcg_gen_shli_i32(t1
, TCGV_LOW(arg1
), c
);
657 tcg_gen_shli_i32(TCGV_HIGH(ret
), TCGV_HIGH(arg1
), c
);
658 tcg_gen_or_i32(TCGV_HIGH(ret
), TCGV_HIGH(ret
), t0
);
659 tcg_gen_mov_i32(TCGV_LOW(ret
), t1
);
661 tcg_temp_free_i32(t0
);
662 tcg_temp_free_i32(t1
);
667 static void tcg_reg_alloc_start(TCGContext
*s
)
671 for(i
= 0; i
< s
->nb_globals
; i
++) {
674 ts
->val_type
= TEMP_VAL_REG
;
676 ts
->val_type
= TEMP_VAL_MEM
;
679 for(i
= s
->nb_globals
; i
< s
->nb_temps
; i
++) {
681 ts
->val_type
= TEMP_VAL_DEAD
;
682 ts
->mem_allocated
= 0;
685 for(i
= 0; i
< TCG_TARGET_NB_REGS
; i
++) {
686 s
->reg_to_temp
[i
] = -1;
690 static char *tcg_get_arg_str_idx(TCGContext
*s
, char *buf
, int buf_size
,
696 if (idx
< s
->nb_globals
) {
697 pstrcpy(buf
, buf_size
, ts
->name
);
700 snprintf(buf
, buf_size
, "loc%d", idx
- s
->nb_globals
);
702 snprintf(buf
, buf_size
, "tmp%d", idx
- s
->nb_globals
);
707 char *tcg_get_arg_str_i32(TCGContext
*s
, char *buf
, int buf_size
, TCGv_i32 arg
)
709 return tcg_get_arg_str_idx(s
, buf
, buf_size
, GET_TCGV_I32(arg
));
712 char *tcg_get_arg_str_i64(TCGContext
*s
, char *buf
, int buf_size
, TCGv_i64 arg
)
714 return tcg_get_arg_str_idx(s
, buf
, buf_size
, GET_TCGV_I64(arg
));
717 static int helper_cmp(const void *p1
, const void *p2
)
719 const TCGHelperInfo
*th1
= p1
;
720 const TCGHelperInfo
*th2
= p2
;
721 if (th1
->func
< th2
->func
)
723 else if (th1
->func
== th2
->func
)
729 /* find helper definition (Note: A hash table would be better) */
730 static TCGHelperInfo
*tcg_find_helper(TCGContext
*s
, tcg_target_ulong val
)
736 if (unlikely(!s
->helpers_sorted
)) {
737 qsort(s
->helpers
, s
->nb_helpers
, sizeof(TCGHelperInfo
),
739 s
->helpers_sorted
= 1;
744 m_max
= s
->nb_helpers
- 1;
745 while (m_min
<= m_max
) {
746 m
= (m_min
+ m_max
) >> 1;
760 static const char * const cond_name
[] =
762 [TCG_COND_EQ
] = "eq",
763 [TCG_COND_NE
] = "ne",
764 [TCG_COND_LT
] = "lt",
765 [TCG_COND_GE
] = "ge",
766 [TCG_COND_LE
] = "le",
767 [TCG_COND_GT
] = "gt",
768 [TCG_COND_LTU
] = "ltu",
769 [TCG_COND_GEU
] = "geu",
770 [TCG_COND_LEU
] = "leu",
771 [TCG_COND_GTU
] = "gtu"
774 void tcg_dump_ops(TCGContext
*s
, FILE *outfile
)
776 const uint16_t *opc_ptr
;
779 int c
, i
, k
, nb_oargs
, nb_iargs
, nb_cargs
, first_insn
;
784 opc_ptr
= gen_opc_buf
;
785 args
= gen_opparam_buf
;
786 while (opc_ptr
< gen_opc_ptr
) {
788 def
= &tcg_op_defs
[c
];
789 if (c
== INDEX_op_debug_insn_start
) {
791 #if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
792 pc
= ((uint64_t)args
[1] << 32) | args
[0];
797 fprintf(outfile
, "\n");
798 fprintf(outfile
, " ---- 0x%" PRIx64
, pc
);
800 nb_oargs
= def
->nb_oargs
;
801 nb_iargs
= def
->nb_iargs
;
802 nb_cargs
= def
->nb_cargs
;
803 } else if (c
== INDEX_op_call
) {
806 /* variable number of arguments */
808 nb_oargs
= arg
>> 16;
809 nb_iargs
= arg
& 0xffff;
810 nb_cargs
= def
->nb_cargs
;
812 fprintf(outfile
, " %s ", def
->name
);
815 fprintf(outfile
, "%s",
816 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), args
[nb_oargs
+ nb_iargs
- 1]));
818 fprintf(outfile
, ",$0x%" TCG_PRIlx
,
819 args
[nb_oargs
+ nb_iargs
]);
821 fprintf(outfile
, ",$%d", nb_oargs
);
822 for(i
= 0; i
< nb_oargs
; i
++) {
823 fprintf(outfile
, ",");
824 fprintf(outfile
, "%s",
825 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), args
[i
]));
827 for(i
= 0; i
< (nb_iargs
- 1); i
++) {
828 fprintf(outfile
, ",");
829 if (args
[nb_oargs
+ i
] == TCG_CALL_DUMMY_ARG
) {
830 fprintf(outfile
, "<dummy>");
832 fprintf(outfile
, "%s",
833 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), args
[nb_oargs
+ i
]));
836 } else if (c
== INDEX_op_movi_i32
837 #if TCG_TARGET_REG_BITS == 64
838 || c
== INDEX_op_movi_i64
841 tcg_target_ulong val
;
844 nb_oargs
= def
->nb_oargs
;
845 nb_iargs
= def
->nb_iargs
;
846 nb_cargs
= def
->nb_cargs
;
847 fprintf(outfile
, " %s %s,$", def
->name
,
848 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), args
[0]));
850 th
= tcg_find_helper(s
, val
);
852 fprintf(outfile
, "%s", th
->name
);
854 if (c
== INDEX_op_movi_i32
)
855 fprintf(outfile
, "0x%x", (uint32_t)val
);
857 fprintf(outfile
, "0x%" PRIx64
, (uint64_t)val
);
860 fprintf(outfile
, " %s ", def
->name
);
861 if (c
== INDEX_op_nopn
) {
862 /* variable number of arguments */
867 nb_oargs
= def
->nb_oargs
;
868 nb_iargs
= def
->nb_iargs
;
869 nb_cargs
= def
->nb_cargs
;
873 for(i
= 0; i
< nb_oargs
; i
++) {
875 fprintf(outfile
, ",");
876 fprintf(outfile
, "%s",
877 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), args
[k
++]));
879 for(i
= 0; i
< nb_iargs
; i
++) {
881 fprintf(outfile
, ",");
882 fprintf(outfile
, "%s",
883 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), args
[k
++]));
885 if (c
== INDEX_op_brcond_i32
886 #if TCG_TARGET_REG_BITS == 32
887 || c
== INDEX_op_brcond2_i32
888 #elif TCG_TARGET_REG_BITS == 64
889 || c
== INDEX_op_brcond_i64
892 if (args
[k
] < ARRAY_SIZE(cond_name
) && cond_name
[args
[k
]])
893 fprintf(outfile
, ",%s", cond_name
[args
[k
++]]);
895 fprintf(outfile
, ",$0x%" TCG_PRIlx
, args
[k
++]);
900 for(; i
< nb_cargs
; i
++) {
902 fprintf(outfile
, ",");
904 fprintf(outfile
, "$0x%" TCG_PRIlx
, arg
);
907 fprintf(outfile
, "\n");
908 args
+= nb_iargs
+ nb_oargs
+ nb_cargs
;
912 /* we give more priority to constraints with less registers */
913 static int get_constraint_priority(const TCGOpDef
*def
, int k
)
915 const TCGArgConstraint
*arg_ct
;
918 arg_ct
= &def
->args_ct
[k
];
919 if (arg_ct
->ct
& TCG_CT_ALIAS
) {
920 /* an alias is equivalent to a single register */
923 if (!(arg_ct
->ct
& TCG_CT_REG
))
926 for(i
= 0; i
< TCG_TARGET_NB_REGS
; i
++) {
927 if (tcg_regset_test_reg(arg_ct
->u
.regs
, i
))
931 return TCG_TARGET_NB_REGS
- n
+ 1;
934 /* sort from highest priority to lowest */
935 static void sort_constraints(TCGOpDef
*def
, int start
, int n
)
937 int i
, j
, p1
, p2
, tmp
;
939 for(i
= 0; i
< n
; i
++)
940 def
->sorted_args
[start
+ i
] = start
+ i
;
943 for(i
= 0; i
< n
- 1; i
++) {
944 for(j
= i
+ 1; j
< n
; j
++) {
945 p1
= get_constraint_priority(def
, def
->sorted_args
[start
+ i
]);
946 p2
= get_constraint_priority(def
, def
->sorted_args
[start
+ j
]);
948 tmp
= def
->sorted_args
[start
+ i
];
949 def
->sorted_args
[start
+ i
] = def
->sorted_args
[start
+ j
];
950 def
->sorted_args
[start
+ j
] = tmp
;
956 void tcg_add_target_add_op_defs(const TCGTargetOpDef
*tdefs
)
967 assert(op
>= 0 && op
< NB_OPS
);
968 def
= &tcg_op_defs
[op
];
969 nb_args
= def
->nb_iargs
+ def
->nb_oargs
;
970 for(i
= 0; i
< nb_args
; i
++) {
971 ct_str
= tdefs
->args_ct_str
[i
];
972 tcg_regset_clear(def
->args_ct
[i
].u
.regs
);
973 def
->args_ct
[i
].ct
= 0;
974 if (ct_str
[0] >= '0' && ct_str
[0] <= '9') {
976 oarg
= ct_str
[0] - '0';
977 assert(oarg
< def
->nb_oargs
);
978 assert(def
->args_ct
[oarg
].ct
& TCG_CT_REG
);
979 /* TCG_CT_ALIAS is for the output arguments. The input
980 argument is tagged with TCG_CT_IALIAS. */
981 def
->args_ct
[i
] = def
->args_ct
[oarg
];
982 def
->args_ct
[oarg
].ct
= TCG_CT_ALIAS
;
983 def
->args_ct
[oarg
].alias_index
= i
;
984 def
->args_ct
[i
].ct
|= TCG_CT_IALIAS
;
985 def
->args_ct
[i
].alias_index
= oarg
;
992 def
->args_ct
[i
].ct
|= TCG_CT_CONST
;
996 if (target_parse_constraint(&def
->args_ct
[i
], &ct_str
) < 0) {
997 fprintf(stderr
, "Invalid constraint '%s' for arg %d of operation '%s'\n",
998 ct_str
, i
, def
->name
);
1006 /* sort the constraints (XXX: this is just an heuristic) */
1007 sort_constraints(def
, 0, def
->nb_oargs
);
1008 sort_constraints(def
, def
->nb_oargs
, def
->nb_iargs
);
1014 printf("%s: sorted=", def
->name
);
1015 for(i
= 0; i
< def
->nb_oargs
+ def
->nb_iargs
; i
++)
1016 printf(" %d", def
->sorted_args
[i
]);
1025 #ifdef USE_LIVENESS_ANALYSIS
1027 /* set a nop for an operation using 'nb_args' */
1028 static inline void tcg_set_nop(TCGContext
*s
, uint16_t *opc_ptr
,
1029 TCGArg
*args
, int nb_args
)
1032 *opc_ptr
= INDEX_op_nop
;
1034 *opc_ptr
= INDEX_op_nopn
;
1036 args
[nb_args
- 1] = nb_args
;
1040 /* liveness analysis: end of function: globals are live, temps are
1042 /* XXX: at this stage, not used as there would be little gains because
1043 most TBs end with a conditional jump. */
1044 static inline void tcg_la_func_end(TCGContext
*s
, uint8_t *dead_temps
)
1046 memset(dead_temps
, 0, s
->nb_globals
);
1047 memset(dead_temps
+ s
->nb_globals
, 1, s
->nb_temps
- s
->nb_globals
);
1050 /* liveness analysis: end of basic block: globals are live, temps are
1051 dead, local temps are live. */
1052 static inline void tcg_la_bb_end(TCGContext
*s
, uint8_t *dead_temps
)
1057 memset(dead_temps
, 0, s
->nb_globals
);
1058 ts
= &s
->temps
[s
->nb_globals
];
1059 for(i
= s
->nb_globals
; i
< s
->nb_temps
; i
++) {
1068 /* Liveness analysis : update the opc_dead_iargs array to tell if a
1069 given input arguments is dead. Instructions updating dead
1070 temporaries are removed. */
1071 static void tcg_liveness_analysis(TCGContext
*s
)
1073 int i
, op_index
, op
, nb_args
, nb_iargs
, nb_oargs
, arg
, nb_ops
;
1075 const TCGOpDef
*def
;
1076 uint8_t *dead_temps
;
1077 unsigned int dead_iargs
;
1079 gen_opc_ptr
++; /* skip end */
1081 nb_ops
= gen_opc_ptr
- gen_opc_buf
;
1083 /* XXX: make it really dynamic */
1084 s
->op_dead_iargs
= tcg_malloc(OPC_BUF_SIZE
* sizeof(uint16_t));
1086 dead_temps
= tcg_malloc(s
->nb_temps
);
1087 memset(dead_temps
, 1, s
->nb_temps
);
1089 args
= gen_opparam_ptr
;
1090 op_index
= nb_ops
- 1;
1091 while (op_index
>= 0) {
1092 op
= gen_opc_buf
[op_index
];
1093 def
= &tcg_op_defs
[op
];
1101 nb_iargs
= args
[0] & 0xffff;
1102 nb_oargs
= args
[0] >> 16;
1104 call_flags
= args
[nb_oargs
+ nb_iargs
];
1106 /* pure functions can be removed if their result is not
1108 if (call_flags
& TCG_CALL_PURE
) {
1109 for(i
= 0; i
< nb_oargs
; i
++) {
1111 if (!dead_temps
[arg
])
1112 goto do_not_remove_call
;
1114 tcg_set_nop(s
, gen_opc_buf
+ op_index
,
1119 /* output args are dead */
1120 for(i
= 0; i
< nb_oargs
; i
++) {
1122 dead_temps
[arg
] = 1;
1125 /* globals are live (they may be used by the call) */
1126 memset(dead_temps
, 0, s
->nb_globals
);
1128 /* input args are live */
1130 for(i
= 0; i
< nb_iargs
; i
++) {
1131 arg
= args
[i
+ nb_oargs
];
1132 if (arg
!= TCG_CALL_DUMMY_ARG
) {
1133 if (dead_temps
[arg
]) {
1134 dead_iargs
|= (1 << i
);
1136 dead_temps
[arg
] = 0;
1139 s
->op_dead_iargs
[op_index
] = dead_iargs
;
1144 case INDEX_op_set_label
:
1146 /* mark end of basic block */
1147 tcg_la_bb_end(s
, dead_temps
);
1149 case INDEX_op_debug_insn_start
:
1150 args
-= def
->nb_args
;
1156 case INDEX_op_discard
:
1158 /* mark the temporary as dead */
1159 dead_temps
[args
[0]] = 1;
1163 /* XXX: optimize by hardcoding common cases (e.g. triadic ops) */
1165 args
-= def
->nb_args
;
1166 nb_iargs
= def
->nb_iargs
;
1167 nb_oargs
= def
->nb_oargs
;
1169 /* Test if the operation can be removed because all
1170 its outputs are dead. We assume that nb_oargs == 0
1171 implies side effects */
1172 if (!(def
->flags
& TCG_OPF_SIDE_EFFECTS
) && nb_oargs
!= 0) {
1173 for(i
= 0; i
< nb_oargs
; i
++) {
1175 if (!dead_temps
[arg
])
1178 tcg_set_nop(s
, gen_opc_buf
+ op_index
, args
, def
->nb_args
);
1179 #ifdef CONFIG_PROFILER
1185 /* output args are dead */
1186 for(i
= 0; i
< nb_oargs
; i
++) {
1188 dead_temps
[arg
] = 1;
1191 /* if end of basic block, update */
1192 if (def
->flags
& TCG_OPF_BB_END
) {
1193 tcg_la_bb_end(s
, dead_temps
);
1194 } else if (def
->flags
& TCG_OPF_CALL_CLOBBER
) {
1195 /* globals are live */
1196 memset(dead_temps
, 0, s
->nb_globals
);
1199 /* input args are live */
1201 for(i
= 0; i
< nb_iargs
; i
++) {
1202 arg
= args
[i
+ nb_oargs
];
1203 if (dead_temps
[arg
]) {
1204 dead_iargs
|= (1 << i
);
1206 dead_temps
[arg
] = 0;
1208 s
->op_dead_iargs
[op_index
] = dead_iargs
;
1215 if (args
!= gen_opparam_buf
)
1219 /* dummy liveness analysis */
1220 void tcg_liveness_analysis(TCGContext
*s
)
1223 nb_ops
= gen_opc_ptr
- gen_opc_buf
;
1225 s
->op_dead_iargs
= tcg_malloc(nb_ops
* sizeof(uint16_t));
1226 memset(s
->op_dead_iargs
, 0, nb_ops
* sizeof(uint16_t));
1231 static void dump_regs(TCGContext
*s
)
1237 for(i
= 0; i
< s
->nb_temps
; i
++) {
1239 printf(" %10s: ", tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), i
));
1240 switch(ts
->val_type
) {
1242 printf("%s", tcg_target_reg_names
[ts
->reg
]);
1245 printf("%d(%s)", (int)ts
->mem_offset
, tcg_target_reg_names
[ts
->mem_reg
]);
1247 case TEMP_VAL_CONST
:
1248 printf("$0x%" TCG_PRIlx
, ts
->val
);
1260 for(i
= 0; i
< TCG_TARGET_NB_REGS
; i
++) {
1261 if (s
->reg_to_temp
[i
] >= 0) {
1263 tcg_target_reg_names
[i
],
1264 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), s
->reg_to_temp
[i
]));
1269 static void check_regs(TCGContext
*s
)
1275 for(reg
= 0; reg
< TCG_TARGET_NB_REGS
; reg
++) {
1276 k
= s
->reg_to_temp
[reg
];
1279 if (ts
->val_type
!= TEMP_VAL_REG
||
1281 printf("Inconsistency for register %s:\n",
1282 tcg_target_reg_names
[reg
]);
1287 for(k
= 0; k
< s
->nb_temps
; k
++) {
1289 if (ts
->val_type
== TEMP_VAL_REG
&&
1291 s
->reg_to_temp
[ts
->reg
] != k
) {
1292 printf("Inconsistency for temp %s:\n",
1293 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), k
));
1295 printf("reg state:\n");
1303 static void temp_allocate_frame(TCGContext
*s
, int temp
)
1306 ts
= &s
->temps
[temp
];
1307 s
->current_frame_offset
= (s
->current_frame_offset
+ sizeof(tcg_target_long
) - 1) & ~(sizeof(tcg_target_long
) - 1);
1308 if (s
->current_frame_offset
+ sizeof(tcg_target_long
) > s
->frame_end
)
1310 ts
->mem_offset
= s
->current_frame_offset
;
1311 ts
->mem_reg
= s
->frame_reg
;
1312 ts
->mem_allocated
= 1;
1313 s
->current_frame_offset
+= sizeof(tcg_target_long
);
1316 /* free register 'reg' by spilling the corresponding temporary if necessary */
1317 static void tcg_reg_free(TCGContext
*s
, int reg
)
1322 temp
= s
->reg_to_temp
[reg
];
1324 ts
= &s
->temps
[temp
];
1325 assert(ts
->val_type
== TEMP_VAL_REG
);
1326 if (!ts
->mem_coherent
) {
1327 if (!ts
->mem_allocated
)
1328 temp_allocate_frame(s
, temp
);
1329 tcg_out_st(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
1331 ts
->val_type
= TEMP_VAL_MEM
;
1332 s
->reg_to_temp
[reg
] = -1;
1336 /* Allocate a register belonging to reg1 & ~reg2 */
1337 static int tcg_reg_alloc(TCGContext
*s
, TCGRegSet reg1
, TCGRegSet reg2
)
1342 tcg_regset_andnot(reg_ct
, reg1
, reg2
);
1344 /* first try free registers */
1345 for(i
= 0; i
< ARRAY_SIZE(tcg_target_reg_alloc_order
); i
++) {
1346 reg
= tcg_target_reg_alloc_order
[i
];
1347 if (tcg_regset_test_reg(reg_ct
, reg
) && s
->reg_to_temp
[reg
] == -1)
1351 /* XXX: do better spill choice */
1352 for(i
= 0; i
< ARRAY_SIZE(tcg_target_reg_alloc_order
); i
++) {
1353 reg
= tcg_target_reg_alloc_order
[i
];
1354 if (tcg_regset_test_reg(reg_ct
, reg
)) {
1355 tcg_reg_free(s
, reg
);
1363 /* save a temporary to memory. 'allocated_regs' is used in case a
1364 temporary registers needs to be allocated to store a constant. */
1365 static void temp_save(TCGContext
*s
, int temp
, TCGRegSet allocated_regs
)
1370 ts
= &s
->temps
[temp
];
1371 if (!ts
->fixed_reg
) {
1372 switch(ts
->val_type
) {
1374 tcg_reg_free(s
, ts
->reg
);
1377 ts
->val_type
= TEMP_VAL_MEM
;
1379 case TEMP_VAL_CONST
:
1380 reg
= tcg_reg_alloc(s
, tcg_target_available_regs
[ts
->type
],
1382 if (!ts
->mem_allocated
)
1383 temp_allocate_frame(s
, temp
);
1384 tcg_out_movi(s
, ts
->type
, reg
, ts
->val
);
1385 tcg_out_st(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
1386 ts
->val_type
= TEMP_VAL_MEM
;
1396 /* save globals to their cannonical location and assume they can be
1397 modified be the following code. 'allocated_regs' is used in case a
1398 temporary registers needs to be allocated to store a constant. */
1399 static void save_globals(TCGContext
*s
, TCGRegSet allocated_regs
)
1403 for(i
= 0; i
< s
->nb_globals
; i
++) {
1404 temp_save(s
, i
, allocated_regs
);
1408 /* at the end of a basic block, we assume all temporaries are dead and
1409 all globals are stored at their canonical location. */
1410 static void tcg_reg_alloc_bb_end(TCGContext
*s
, TCGRegSet allocated_regs
)
1415 for(i
= s
->nb_globals
; i
< s
->nb_temps
; i
++) {
1417 if (ts
->temp_local
) {
1418 temp_save(s
, i
, allocated_regs
);
1420 if (ts
->val_type
== TEMP_VAL_REG
) {
1421 s
->reg_to_temp
[ts
->reg
] = -1;
1423 ts
->val_type
= TEMP_VAL_DEAD
;
1427 save_globals(s
, allocated_regs
);
1430 #define IS_DEAD_IARG(n) ((dead_iargs >> (n)) & 1)
1432 static void tcg_reg_alloc_movi(TCGContext
*s
, const TCGArg
*args
)
1435 tcg_target_ulong val
;
1437 ots
= &s
->temps
[args
[0]];
1440 if (ots
->fixed_reg
) {
1441 /* for fixed registers, we do not do any constant
1443 tcg_out_movi(s
, ots
->type
, ots
->reg
, val
);
1445 /* The movi is not explicitly generated here */
1446 if (ots
->val_type
== TEMP_VAL_REG
)
1447 s
->reg_to_temp
[ots
->reg
] = -1;
1448 ots
->val_type
= TEMP_VAL_CONST
;
1453 static void tcg_reg_alloc_mov(TCGContext
*s
, const TCGOpDef
*def
,
1455 unsigned int dead_iargs
)
1459 const TCGArgConstraint
*arg_ct
;
1461 ots
= &s
->temps
[args
[0]];
1462 ts
= &s
->temps
[args
[1]];
1463 arg_ct
= &def
->args_ct
[0];
1465 /* XXX: always mark arg dead if IS_DEAD_IARG(0) */
1466 if (ts
->val_type
== TEMP_VAL_REG
) {
1467 if (IS_DEAD_IARG(0) && !ts
->fixed_reg
&& !ots
->fixed_reg
) {
1468 /* the mov can be suppressed */
1469 if (ots
->val_type
== TEMP_VAL_REG
)
1470 s
->reg_to_temp
[ots
->reg
] = -1;
1472 s
->reg_to_temp
[reg
] = -1;
1473 ts
->val_type
= TEMP_VAL_DEAD
;
1475 if (ots
->val_type
== TEMP_VAL_REG
) {
1478 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, s
->reserved_regs
);
1480 if (ts
->reg
!= reg
) {
1481 tcg_out_mov(s
, reg
, ts
->reg
);
1484 } else if (ts
->val_type
== TEMP_VAL_MEM
) {
1485 if (ots
->val_type
== TEMP_VAL_REG
) {
1488 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, s
->reserved_regs
);
1490 tcg_out_ld(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
1491 } else if (ts
->val_type
== TEMP_VAL_CONST
) {
1492 if (ots
->fixed_reg
) {
1494 tcg_out_movi(s
, ots
->type
, reg
, ts
->val
);
1496 /* propagate constant */
1497 if (ots
->val_type
== TEMP_VAL_REG
)
1498 s
->reg_to_temp
[ots
->reg
] = -1;
1499 ots
->val_type
= TEMP_VAL_CONST
;
1506 s
->reg_to_temp
[reg
] = args
[0];
1508 ots
->val_type
= TEMP_VAL_REG
;
1509 ots
->mem_coherent
= 0;
1512 static void tcg_reg_alloc_op(TCGContext
*s
,
1513 const TCGOpDef
*def
, int opc
,
1515 unsigned int dead_iargs
)
1517 TCGRegSet allocated_regs
;
1518 int i
, k
, nb_iargs
, nb_oargs
, reg
;
1520 const TCGArgConstraint
*arg_ct
;
1522 TCGArg new_args
[TCG_MAX_OP_ARGS
];
1523 int const_args
[TCG_MAX_OP_ARGS
];
1525 nb_oargs
= def
->nb_oargs
;
1526 nb_iargs
= def
->nb_iargs
;
1528 /* copy constants */
1529 memcpy(new_args
+ nb_oargs
+ nb_iargs
,
1530 args
+ nb_oargs
+ nb_iargs
,
1531 sizeof(TCGArg
) * def
->nb_cargs
);
1533 /* satisfy input constraints */
1534 tcg_regset_set(allocated_regs
, s
->reserved_regs
);
1535 for(k
= 0; k
< nb_iargs
; k
++) {
1536 i
= def
->sorted_args
[nb_oargs
+ k
];
1538 arg_ct
= &def
->args_ct
[i
];
1539 ts
= &s
->temps
[arg
];
1540 if (ts
->val_type
== TEMP_VAL_MEM
) {
1541 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1542 tcg_out_ld(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
1543 ts
->val_type
= TEMP_VAL_REG
;
1545 ts
->mem_coherent
= 1;
1546 s
->reg_to_temp
[reg
] = arg
;
1547 } else if (ts
->val_type
== TEMP_VAL_CONST
) {
1548 if (tcg_target_const_match(ts
->val
, arg_ct
)) {
1549 /* constant is OK for instruction */
1551 new_args
[i
] = ts
->val
;
1554 /* need to move to a register */
1555 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1556 tcg_out_movi(s
, ts
->type
, reg
, ts
->val
);
1557 ts
->val_type
= TEMP_VAL_REG
;
1559 ts
->mem_coherent
= 0;
1560 s
->reg_to_temp
[reg
] = arg
;
1563 assert(ts
->val_type
== TEMP_VAL_REG
);
1564 if (arg_ct
->ct
& TCG_CT_IALIAS
) {
1565 if (ts
->fixed_reg
) {
1566 /* if fixed register, we must allocate a new register
1567 if the alias is not the same register */
1568 if (arg
!= args
[arg_ct
->alias_index
])
1569 goto allocate_in_reg
;
1571 /* if the input is aliased to an output and if it is
1572 not dead after the instruction, we must allocate
1573 a new register and move it */
1574 if (!IS_DEAD_IARG(i
- nb_oargs
))
1575 goto allocate_in_reg
;
1579 if (tcg_regset_test_reg(arg_ct
->u
.regs
, reg
)) {
1580 /* nothing to do : the constraint is satisfied */
1583 /* allocate a new register matching the constraint
1584 and move the temporary register into it */
1585 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1586 tcg_out_mov(s
, reg
, ts
->reg
);
1590 tcg_regset_set_reg(allocated_regs
, reg
);
1594 if (def
->flags
& TCG_OPF_BB_END
) {
1595 tcg_reg_alloc_bb_end(s
, allocated_regs
);
1597 /* mark dead temporaries and free the associated registers */
1598 for(i
= 0; i
< nb_iargs
; i
++) {
1599 arg
= args
[nb_oargs
+ i
];
1600 if (IS_DEAD_IARG(i
)) {
1601 ts
= &s
->temps
[arg
];
1602 if (!ts
->fixed_reg
) {
1603 if (ts
->val_type
== TEMP_VAL_REG
)
1604 s
->reg_to_temp
[ts
->reg
] = -1;
1605 ts
->val_type
= TEMP_VAL_DEAD
;
1610 if (def
->flags
& TCG_OPF_CALL_CLOBBER
) {
1611 /* XXX: permit generic clobber register list ? */
1612 for(reg
= 0; reg
< TCG_TARGET_NB_REGS
; reg
++) {
1613 if (tcg_regset_test_reg(tcg_target_call_clobber_regs
, reg
)) {
1614 tcg_reg_free(s
, reg
);
1617 /* XXX: for load/store we could do that only for the slow path
1618 (i.e. when a memory callback is called) */
1620 /* store globals and free associated registers (we assume the insn
1621 can modify any global. */
1622 save_globals(s
, allocated_regs
);
1625 /* satisfy the output constraints */
1626 tcg_regset_set(allocated_regs
, s
->reserved_regs
);
1627 for(k
= 0; k
< nb_oargs
; k
++) {
1628 i
= def
->sorted_args
[k
];
1630 arg_ct
= &def
->args_ct
[i
];
1631 ts
= &s
->temps
[arg
];
1632 if (arg_ct
->ct
& TCG_CT_ALIAS
) {
1633 reg
= new_args
[arg_ct
->alias_index
];
1635 /* if fixed register, we try to use it */
1637 if (ts
->fixed_reg
&&
1638 tcg_regset_test_reg(arg_ct
->u
.regs
, reg
)) {
1641 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1643 tcg_regset_set_reg(allocated_regs
, reg
);
1644 /* if a fixed register is used, then a move will be done afterwards */
1645 if (!ts
->fixed_reg
) {
1646 if (ts
->val_type
== TEMP_VAL_REG
)
1647 s
->reg_to_temp
[ts
->reg
] = -1;
1648 ts
->val_type
= TEMP_VAL_REG
;
1650 /* temp value is modified, so the value kept in memory is
1651 potentially not the same */
1652 ts
->mem_coherent
= 0;
1653 s
->reg_to_temp
[reg
] = arg
;
1660 /* emit instruction */
1661 tcg_out_op(s
, opc
, new_args
, const_args
);
1663 /* move the outputs in the correct register if needed */
1664 for(i
= 0; i
< nb_oargs
; i
++) {
1665 ts
= &s
->temps
[args
[i
]];
1667 if (ts
->fixed_reg
&& ts
->reg
!= reg
) {
1668 tcg_out_mov(s
, ts
->reg
, reg
);
1673 #ifdef TCG_TARGET_STACK_GROWSUP
1674 #define STACK_DIR(x) (-(x))
1676 #define STACK_DIR(x) (x)
1679 static int tcg_reg_alloc_call(TCGContext
*s
, const TCGOpDef
*def
,
1680 int opc
, const TCGArg
*args
,
1681 unsigned int dead_iargs
)
1683 int nb_iargs
, nb_oargs
, flags
, nb_regs
, i
, reg
, nb_params
;
1684 TCGArg arg
, func_arg
;
1686 tcg_target_long stack_offset
, call_stack_size
, func_addr
;
1687 int const_func_arg
, allocate_args
;
1688 TCGRegSet allocated_regs
;
1689 const TCGArgConstraint
*arg_ct
;
1693 nb_oargs
= arg
>> 16;
1694 nb_iargs
= arg
& 0xffff;
1695 nb_params
= nb_iargs
- 1;
1697 flags
= args
[nb_oargs
+ nb_iargs
];
1699 nb_regs
= tcg_target_get_call_iarg_regs_count(flags
);
1700 if (nb_regs
> nb_params
)
1701 nb_regs
= nb_params
;
1703 /* assign stack slots first */
1704 /* XXX: preallocate call stack */
1705 call_stack_size
= (nb_params
- nb_regs
) * sizeof(tcg_target_long
);
1706 call_stack_size
= (call_stack_size
+ TCG_TARGET_STACK_ALIGN
- 1) &
1707 ~(TCG_TARGET_STACK_ALIGN
- 1);
1708 allocate_args
= (call_stack_size
> TCG_STATIC_CALL_ARGS_SIZE
);
1709 if (allocate_args
) {
1710 tcg_out_addi(s
, TCG_REG_CALL_STACK
, -STACK_DIR(call_stack_size
));
1713 stack_offset
= TCG_TARGET_CALL_STACK_OFFSET
;
1714 for(i
= nb_regs
; i
< nb_params
; i
++) {
1715 arg
= args
[nb_oargs
+ i
];
1716 #ifdef TCG_TARGET_STACK_GROWSUP
1717 stack_offset
-= sizeof(tcg_target_long
);
1719 if (arg
!= TCG_CALL_DUMMY_ARG
) {
1720 ts
= &s
->temps
[arg
];
1721 if (ts
->val_type
== TEMP_VAL_REG
) {
1722 tcg_out_st(s
, ts
->type
, ts
->reg
, TCG_REG_CALL_STACK
, stack_offset
);
1723 } else if (ts
->val_type
== TEMP_VAL_MEM
) {
1724 reg
= tcg_reg_alloc(s
, tcg_target_available_regs
[ts
->type
],
1726 /* XXX: not correct if reading values from the stack */
1727 tcg_out_ld(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
1728 tcg_out_st(s
, ts
->type
, reg
, TCG_REG_CALL_STACK
, stack_offset
);
1729 } else if (ts
->val_type
== TEMP_VAL_CONST
) {
1730 reg
= tcg_reg_alloc(s
, tcg_target_available_regs
[ts
->type
],
1732 /* XXX: sign extend may be needed on some targets */
1733 tcg_out_movi(s
, ts
->type
, reg
, ts
->val
);
1734 tcg_out_st(s
, ts
->type
, reg
, TCG_REG_CALL_STACK
, stack_offset
);
1739 #ifndef TCG_TARGET_STACK_GROWSUP
1740 stack_offset
+= sizeof(tcg_target_long
);
1744 /* assign input registers */
1745 tcg_regset_set(allocated_regs
, s
->reserved_regs
);
1746 for(i
= 0; i
< nb_regs
; i
++) {
1747 arg
= args
[nb_oargs
+ i
];
1748 if (arg
!= TCG_CALL_DUMMY_ARG
) {
1749 ts
= &s
->temps
[arg
];
1750 reg
= tcg_target_call_iarg_regs
[i
];
1751 tcg_reg_free(s
, reg
);
1752 if (ts
->val_type
== TEMP_VAL_REG
) {
1753 if (ts
->reg
!= reg
) {
1754 tcg_out_mov(s
, reg
, ts
->reg
);
1756 } else if (ts
->val_type
== TEMP_VAL_MEM
) {
1757 tcg_out_ld(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
1758 } else if (ts
->val_type
== TEMP_VAL_CONST
) {
1759 /* XXX: sign extend ? */
1760 tcg_out_movi(s
, ts
->type
, reg
, ts
->val
);
1764 tcg_regset_set_reg(allocated_regs
, reg
);
1768 /* assign function address */
1769 func_arg
= args
[nb_oargs
+ nb_iargs
- 1];
1770 arg_ct
= &def
->args_ct
[0];
1771 ts
= &s
->temps
[func_arg
];
1772 func_addr
= ts
->val
;
1774 if (ts
->val_type
== TEMP_VAL_MEM
) {
1775 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1776 tcg_out_ld(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
1778 tcg_regset_set_reg(allocated_regs
, reg
);
1779 } else if (ts
->val_type
== TEMP_VAL_REG
) {
1781 if (!tcg_regset_test_reg(arg_ct
->u
.regs
, reg
)) {
1782 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1783 tcg_out_mov(s
, reg
, ts
->reg
);
1786 tcg_regset_set_reg(allocated_regs
, reg
);
1787 } else if (ts
->val_type
== TEMP_VAL_CONST
) {
1788 if (tcg_target_const_match(func_addr
, arg_ct
)) {
1790 func_arg
= func_addr
;
1792 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1793 tcg_out_movi(s
, ts
->type
, reg
, func_addr
);
1795 tcg_regset_set_reg(allocated_regs
, reg
);
1802 /* mark dead temporaries and free the associated registers */
1803 for(i
= 0; i
< nb_iargs
; i
++) {
1804 arg
= args
[nb_oargs
+ i
];
1805 if (IS_DEAD_IARG(i
)) {
1806 ts
= &s
->temps
[arg
];
1807 if (!ts
->fixed_reg
) {
1808 if (ts
->val_type
== TEMP_VAL_REG
)
1809 s
->reg_to_temp
[ts
->reg
] = -1;
1810 ts
->val_type
= TEMP_VAL_DEAD
;
1815 /* clobber call registers */
1816 for(reg
= 0; reg
< TCG_TARGET_NB_REGS
; reg
++) {
1817 if (tcg_regset_test_reg(tcg_target_call_clobber_regs
, reg
)) {
1818 tcg_reg_free(s
, reg
);
1822 /* store globals and free associated registers (we assume the call
1823 can modify any global. */
1824 save_globals(s
, allocated_regs
);
1826 tcg_out_op(s
, opc
, &func_arg
, &const_func_arg
);
1828 if (allocate_args
) {
1829 tcg_out_addi(s
, TCG_REG_CALL_STACK
, STACK_DIR(call_stack_size
));
1832 /* assign output registers and emit moves if needed */
1833 for(i
= 0; i
< nb_oargs
; i
++) {
1835 ts
= &s
->temps
[arg
];
1836 reg
= tcg_target_call_oarg_regs
[i
];
1837 assert(s
->reg_to_temp
[reg
] == -1);
1838 if (ts
->fixed_reg
) {
1839 if (ts
->reg
!= reg
) {
1840 tcg_out_mov(s
, ts
->reg
, reg
);
1843 if (ts
->val_type
== TEMP_VAL_REG
)
1844 s
->reg_to_temp
[ts
->reg
] = -1;
1845 ts
->val_type
= TEMP_VAL_REG
;
1847 ts
->mem_coherent
= 0;
1848 s
->reg_to_temp
[reg
] = arg
;
1852 return nb_iargs
+ nb_oargs
+ def
->nb_cargs
+ 1;
1855 #ifdef CONFIG_PROFILER
1857 static int64_t tcg_table_op_count
[NB_OPS
];
1859 void dump_op_count(void)
1863 f
= fopen("/tmp/op.log", "w");
1864 for(i
= INDEX_op_end
; i
< NB_OPS
; i
++) {
1865 fprintf(f
, "%s %" PRId64
"\n", tcg_op_defs
[i
].name
, tcg_table_op_count
[i
]);
1872 static inline int tcg_gen_code_common(TCGContext
*s
, uint8_t *gen_code_buf
,
1876 const TCGOpDef
*def
;
1877 unsigned int dead_iargs
;
1881 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP
))) {
1883 tcg_dump_ops(s
, logfile
);
1888 #ifdef CONFIG_PROFILER
1889 s
->la_time
-= profile_getclock();
1891 tcg_liveness_analysis(s
);
1892 #ifdef CONFIG_PROFILER
1893 s
->la_time
+= profile_getclock();
1897 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_OPT
))) {
1898 qemu_log("OP after la:\n");
1899 tcg_dump_ops(s
, logfile
);
1904 tcg_reg_alloc_start(s
);
1906 s
->code_buf
= gen_code_buf
;
1907 s
->code_ptr
= gen_code_buf
;
1909 args
= gen_opparam_buf
;
1913 opc
= gen_opc_buf
[op_index
];
1914 #ifdef CONFIG_PROFILER
1915 tcg_table_op_count
[opc
]++;
1917 def
= &tcg_op_defs
[opc
];
1919 printf("%s: %d %d %d\n", def
->name
,
1920 def
->nb_oargs
, def
->nb_iargs
, def
->nb_cargs
);
1924 case INDEX_op_mov_i32
:
1925 #if TCG_TARGET_REG_BITS == 64
1926 case INDEX_op_mov_i64
:
1928 dead_iargs
= s
->op_dead_iargs
[op_index
];
1929 tcg_reg_alloc_mov(s
, def
, args
, dead_iargs
);
1931 case INDEX_op_movi_i32
:
1932 #if TCG_TARGET_REG_BITS == 64
1933 case INDEX_op_movi_i64
:
1935 tcg_reg_alloc_movi(s
, args
);
1937 case INDEX_op_debug_insn_start
:
1938 /* debug instruction */
1948 case INDEX_op_discard
:
1951 ts
= &s
->temps
[args
[0]];
1952 /* mark the temporary as dead */
1953 if (!ts
->fixed_reg
) {
1954 if (ts
->val_type
== TEMP_VAL_REG
)
1955 s
->reg_to_temp
[ts
->reg
] = -1;
1956 ts
->val_type
= TEMP_VAL_DEAD
;
1960 case INDEX_op_set_label
:
1961 tcg_reg_alloc_bb_end(s
, s
->reserved_regs
);
1962 tcg_out_label(s
, args
[0], (long)s
->code_ptr
);
1965 dead_iargs
= s
->op_dead_iargs
[op_index
];
1966 args
+= tcg_reg_alloc_call(s
, def
, opc
, args
, dead_iargs
);
1971 /* Note: in order to speed up the code, it would be much
1972 faster to have specialized register allocator functions for
1973 some common argument patterns */
1974 dead_iargs
= s
->op_dead_iargs
[op_index
];
1975 tcg_reg_alloc_op(s
, def
, opc
, args
, dead_iargs
);
1978 args
+= def
->nb_args
;
1980 if (search_pc
>= 0 && search_pc
< s
->code_ptr
- gen_code_buf
) {
1992 int tcg_gen_code(TCGContext
*s
, uint8_t *gen_code_buf
)
1994 #ifdef CONFIG_PROFILER
1997 n
= (gen_opc_ptr
- gen_opc_buf
);
1999 if (n
> s
->op_count_max
)
2000 s
->op_count_max
= n
;
2002 s
->temp_count
+= s
->nb_temps
;
2003 if (s
->nb_temps
> s
->temp_count_max
)
2004 s
->temp_count_max
= s
->nb_temps
;
2008 tcg_gen_code_common(s
, gen_code_buf
, -1);
2010 /* flush instruction cache */
2011 flush_icache_range((unsigned long)gen_code_buf
,
2012 (unsigned long)s
->code_ptr
);
2013 return s
->code_ptr
- gen_code_buf
;
2016 /* Return the index of the micro operation such as the pc after is <
2017 offset bytes from the start of the TB. The contents of gen_code_buf must
2018 not be changed, though writing the same values is ok.
2019 Return -1 if not found. */
2020 int tcg_gen_code_search_pc(TCGContext
*s
, uint8_t *gen_code_buf
, long offset
)
2022 return tcg_gen_code_common(s
, gen_code_buf
, offset
);
2025 #ifdef CONFIG_PROFILER
2026 void tcg_dump_info(FILE *f
,
2027 int (*cpu_fprintf
)(FILE *f
, const char *fmt
, ...))
2029 TCGContext
*s
= &tcg_ctx
;
2032 tot
= s
->interm_time
+ s
->code_time
;
2033 cpu_fprintf(f
, "JIT cycles %" PRId64
" (%0.3f s at 2.4 GHz)\n",
2035 cpu_fprintf(f
, "translated TBs %" PRId64
" (aborted=%" PRId64
" %0.1f%%)\n",
2037 s
->tb_count1
- s
->tb_count
,
2038 s
->tb_count1
? (double)(s
->tb_count1
- s
->tb_count
) / s
->tb_count1
* 100.0 : 0);
2039 cpu_fprintf(f
, "avg ops/TB %0.1f max=%d\n",
2040 s
->tb_count
? (double)s
->op_count
/ s
->tb_count
: 0, s
->op_count_max
);
2041 cpu_fprintf(f
, "deleted ops/TB %0.2f\n",
2043 (double)s
->del_op_count
/ s
->tb_count
: 0);
2044 cpu_fprintf(f
, "avg temps/TB %0.2f max=%d\n",
2046 (double)s
->temp_count
/ s
->tb_count
: 0,
2049 cpu_fprintf(f
, "cycles/op %0.1f\n",
2050 s
->op_count
? (double)tot
/ s
->op_count
: 0);
2051 cpu_fprintf(f
, "cycles/in byte %0.1f\n",
2052 s
->code_in_len
? (double)tot
/ s
->code_in_len
: 0);
2053 cpu_fprintf(f
, "cycles/out byte %0.1f\n",
2054 s
->code_out_len
? (double)tot
/ s
->code_out_len
: 0);
2057 cpu_fprintf(f
, " gen_interm time %0.1f%%\n",
2058 (double)s
->interm_time
/ tot
* 100.0);
2059 cpu_fprintf(f
, " gen_code time %0.1f%%\n",
2060 (double)s
->code_time
/ tot
* 100.0);
2061 cpu_fprintf(f
, "liveness/code time %0.1f%%\n",
2062 (double)s
->la_time
/ (s
->code_time
? s
->code_time
: 1) * 100.0);
2063 cpu_fprintf(f
, "cpu_restore count %" PRId64
"\n",
2065 cpu_fprintf(f
, " avg cycles %0.1f\n",
2066 s
->restore_count
? (double)s
->restore_time
/ s
->restore_count
: 0);
2068 extern void dump_op_count(void);
2073 void tcg_dump_info(FILE *f
,
2074 int (*cpu_fprintf
)(FILE *f
, const char *fmt
, ...))
2076 cpu_fprintf(f
, "[TCG profiler not compiled]\n");