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) */
47 #include "qemu-common.h"
48 #include "cache-utils.h"
50 /* Note: the long term plan is to reduce the dependancies on the QEMU
51 CPU definitions. Currently they are used for qemu_ld/st
53 #define NO_CPU_IO_DEFS
61 static void patch_reloc(uint8_t *code_ptr
, int type
,
62 tcg_target_long value
, tcg_target_long addend
);
64 static TCGOpDef tcg_op_defs
[] = {
65 #define DEF(s, n, copy_size) { #s, 0, 0, n, n, 0, copy_size },
66 #define DEF2(s, iargs, oargs, cargs, flags) { #s, iargs, oargs, cargs, iargs + oargs + cargs, flags, 0 },
72 static TCGRegSet tcg_target_available_regs
[2];
73 static TCGRegSet tcg_target_call_clobber_regs
;
75 /* XXX: move that inside the context */
76 uint16_t *gen_opc_ptr
;
77 TCGArg
*gen_opparam_ptr
;
79 static inline void tcg_out8(TCGContext
*s
, uint8_t v
)
84 static inline void tcg_out16(TCGContext
*s
, uint16_t v
)
86 *(uint16_t *)s
->code_ptr
= v
;
90 static inline void tcg_out32(TCGContext
*s
, uint32_t v
)
92 *(uint32_t *)s
->code_ptr
= v
;
96 /* label relocation processing */
98 void tcg_out_reloc(TCGContext
*s
, uint8_t *code_ptr
, int type
,
99 int label_index
, long addend
)
104 l
= &s
->labels
[label_index
];
106 /* FIXME: This may break relocations on RISC targets that
107 modify instruction fields in place. The caller may not have
108 written the initial value. */
109 patch_reloc(code_ptr
, type
, l
->u
.value
, addend
);
111 /* add a new relocation entry */
112 r
= tcg_malloc(sizeof(TCGRelocation
));
116 r
->next
= l
->u
.first_reloc
;
117 l
->u
.first_reloc
= r
;
121 static void tcg_out_label(TCGContext
*s
, int label_index
,
122 tcg_target_long value
)
127 l
= &s
->labels
[label_index
];
130 r
= l
->u
.first_reloc
;
132 patch_reloc(r
->ptr
, r
->type
, value
, r
->addend
);
139 int gen_new_label(void)
141 TCGContext
*s
= &tcg_ctx
;
145 if (s
->nb_labels
>= TCG_MAX_LABELS
)
147 idx
= s
->nb_labels
++;
150 l
->u
.first_reloc
= NULL
;
154 #include "tcg-target.c"
156 /* pool based memory allocation */
157 void *tcg_malloc_internal(TCGContext
*s
, int size
)
162 if (size
> TCG_POOL_CHUNK_SIZE
) {
163 /* big malloc: insert a new pool (XXX: could optimize) */
164 p
= qemu_malloc(sizeof(TCGPool
) + size
);
167 s
->pool_current
->next
= p
;
170 p
->next
= s
->pool_current
;
180 pool_size
= TCG_POOL_CHUNK_SIZE
;
181 p
= qemu_malloc(sizeof(TCGPool
) + pool_size
);
185 s
->pool_current
->next
= p
;
194 s
->pool_cur
= p
->data
+ size
;
195 s
->pool_end
= p
->data
+ p
->size
;
199 void tcg_pool_reset(TCGContext
*s
)
201 s
->pool_cur
= s
->pool_end
= NULL
;
202 s
->pool_current
= NULL
;
205 void tcg_context_init(TCGContext
*s
)
207 int op
, total_args
, n
;
209 TCGArgConstraint
*args_ct
;
212 memset(s
, 0, sizeof(*s
));
213 s
->temps
= s
->static_temps
;
216 /* Count total number of arguments and allocate the corresponding
219 for(op
= 0; op
< NB_OPS
; op
++) {
220 def
= &tcg_op_defs
[op
];
221 n
= def
->nb_iargs
+ def
->nb_oargs
;
225 args_ct
= qemu_malloc(sizeof(TCGArgConstraint
) * total_args
);
226 sorted_args
= qemu_malloc(sizeof(int) * total_args
);
228 for(op
= 0; op
< NB_OPS
; op
++) {
229 def
= &tcg_op_defs
[op
];
230 def
->args_ct
= args_ct
;
231 def
->sorted_args
= sorted_args
;
232 n
= def
->nb_iargs
+ def
->nb_oargs
;
239 /* init global prologue and epilogue */
240 s
->code_buf
= code_gen_prologue
;
241 s
->code_ptr
= s
->code_buf
;
242 tcg_target_qemu_prologue(s
);
243 flush_icache_range((unsigned long)s
->code_buf
,
244 (unsigned long)s
->code_ptr
);
247 void tcg_set_frame(TCGContext
*s
, int reg
,
248 tcg_target_long start
, tcg_target_long size
)
250 s
->frame_start
= start
;
251 s
->frame_end
= start
+ size
;
255 void tcg_func_start(TCGContext
*s
)
259 s
->nb_temps
= s
->nb_globals
;
260 for(i
= 0; i
< (TCG_TYPE_COUNT
* 2); i
++)
261 s
->first_free_temp
[i
] = -1;
262 s
->labels
= tcg_malloc(sizeof(TCGLabel
) * TCG_MAX_LABELS
);
264 s
->current_frame_offset
= s
->frame_start
;
266 gen_opc_ptr
= gen_opc_buf
;
267 gen_opparam_ptr
= gen_opparam_buf
;
270 static inline void tcg_temp_alloc(TCGContext
*s
, int n
)
272 if (n
> TCG_MAX_TEMPS
)
276 static inline int tcg_global_reg_new_internal(TCGType type
, int reg
,
279 TCGContext
*s
= &tcg_ctx
;
283 #if TCG_TARGET_REG_BITS == 32
284 if (type
!= TCG_TYPE_I32
)
287 if (tcg_regset_test_reg(s
->reserved_regs
, reg
))
290 tcg_temp_alloc(s
, s
->nb_globals
+ 1);
291 ts
= &s
->temps
[s
->nb_globals
];
292 ts
->base_type
= type
;
298 tcg_regset_set_reg(s
->reserved_regs
, reg
);
302 TCGv_i32
tcg_global_reg_new_i32(int reg
, const char *name
)
306 idx
= tcg_global_reg_new_internal(TCG_TYPE_I32
, reg
, name
);
307 return MAKE_TCGV_I32(idx
);
310 TCGv_i64
tcg_global_reg_new_i64(int reg
, const char *name
)
314 idx
= tcg_global_reg_new_internal(TCG_TYPE_I64
, reg
, name
);
315 return MAKE_TCGV_I64(idx
);
318 static inline int tcg_global_mem_new_internal(TCGType type
, int reg
,
319 tcg_target_long offset
,
322 TCGContext
*s
= &tcg_ctx
;
327 #if TCG_TARGET_REG_BITS == 32
328 if (type
== TCG_TYPE_I64
) {
330 tcg_temp_alloc(s
, s
->nb_globals
+ 2);
331 ts
= &s
->temps
[s
->nb_globals
];
332 ts
->base_type
= type
;
333 ts
->type
= TCG_TYPE_I32
;
335 ts
->mem_allocated
= 1;
337 #ifdef TCG_TARGET_WORDS_BIGENDIAN
338 ts
->mem_offset
= offset
+ 4;
340 ts
->mem_offset
= offset
;
342 pstrcpy(buf
, sizeof(buf
), name
);
343 pstrcat(buf
, sizeof(buf
), "_0");
344 ts
->name
= strdup(buf
);
347 ts
->base_type
= type
;
348 ts
->type
= TCG_TYPE_I32
;
350 ts
->mem_allocated
= 1;
352 #ifdef TCG_TARGET_WORDS_BIGENDIAN
353 ts
->mem_offset
= offset
;
355 ts
->mem_offset
= offset
+ 4;
357 pstrcpy(buf
, sizeof(buf
), name
);
358 pstrcat(buf
, sizeof(buf
), "_1");
359 ts
->name
= strdup(buf
);
365 tcg_temp_alloc(s
, s
->nb_globals
+ 1);
366 ts
= &s
->temps
[s
->nb_globals
];
367 ts
->base_type
= type
;
370 ts
->mem_allocated
= 1;
372 ts
->mem_offset
= offset
;
379 TCGv_i32
tcg_global_mem_new_i32(int reg
, tcg_target_long offset
,
384 idx
= tcg_global_mem_new_internal(TCG_TYPE_I32
, reg
, offset
, name
);
385 return MAKE_TCGV_I32(idx
);
388 TCGv_i64
tcg_global_mem_new_i64(int reg
, tcg_target_long offset
,
393 idx
= tcg_global_mem_new_internal(TCG_TYPE_I64
, reg
, offset
, name
);
394 return MAKE_TCGV_I64(idx
);
397 static inline int tcg_temp_new_internal(TCGType type
, int temp_local
)
399 TCGContext
*s
= &tcg_ctx
;
406 idx
= s
->first_free_temp
[k
];
408 /* There is already an available temp with the
411 s
->first_free_temp
[k
] = ts
->next_free_temp
;
412 ts
->temp_allocated
= 1;
413 assert(ts
->temp_local
== temp_local
);
416 #if TCG_TARGET_REG_BITS == 32
417 if (type
== TCG_TYPE_I64
) {
418 tcg_temp_alloc(s
, s
->nb_temps
+ 2);
419 ts
= &s
->temps
[s
->nb_temps
];
420 ts
->base_type
= type
;
421 ts
->type
= TCG_TYPE_I32
;
422 ts
->temp_allocated
= 1;
423 ts
->temp_local
= temp_local
;
426 ts
->base_type
= TCG_TYPE_I32
;
427 ts
->type
= TCG_TYPE_I32
;
428 ts
->temp_allocated
= 1;
429 ts
->temp_local
= temp_local
;
435 tcg_temp_alloc(s
, s
->nb_temps
+ 1);
436 ts
= &s
->temps
[s
->nb_temps
];
437 ts
->base_type
= type
;
439 ts
->temp_allocated
= 1;
440 ts
->temp_local
= temp_local
;
448 TCGv_i32
tcg_temp_new_internal_i32(int temp_local
)
452 idx
= tcg_temp_new_internal(TCG_TYPE_I32
, temp_local
);
453 return MAKE_TCGV_I32(idx
);
456 TCGv_i64
tcg_temp_new_internal_i64(int temp_local
)
460 idx
= tcg_temp_new_internal(TCG_TYPE_I64
, temp_local
);
461 return MAKE_TCGV_I64(idx
);
464 static inline void tcg_temp_free_internal(int idx
)
466 TCGContext
*s
= &tcg_ctx
;
470 assert(idx
>= s
->nb_globals
&& idx
< s
->nb_temps
);
472 assert(ts
->temp_allocated
!= 0);
473 ts
->temp_allocated
= 0;
477 ts
->next_free_temp
= s
->first_free_temp
[k
];
478 s
->first_free_temp
[k
] = idx
;
481 void tcg_temp_free_i32(TCGv_i32 arg
)
483 tcg_temp_free_internal(GET_TCGV_I32(arg
));
486 void tcg_temp_free_i64(TCGv_i64 arg
)
488 tcg_temp_free_internal(GET_TCGV_I64(arg
));
491 TCGv_i32
tcg_const_i32(int32_t val
)
494 t0
= tcg_temp_new_i32();
495 tcg_gen_movi_i32(t0
, val
);
499 TCGv_i64
tcg_const_i64(int64_t val
)
502 t0
= tcg_temp_new_i64();
503 tcg_gen_movi_i64(t0
, val
);
507 TCGv_i32
tcg_const_local_i32(int32_t val
)
510 t0
= tcg_temp_local_new_i32();
511 tcg_gen_movi_i32(t0
, val
);
515 TCGv_i64
tcg_const_local_i64(int64_t val
)
518 t0
= tcg_temp_local_new_i64();
519 tcg_gen_movi_i64(t0
, val
);
523 void tcg_register_helper(void *func
, const char *name
)
525 TCGContext
*s
= &tcg_ctx
;
527 if ((s
->nb_helpers
+ 1) > s
->allocated_helpers
) {
528 n
= s
->allocated_helpers
;
534 s
->helpers
= realloc(s
->helpers
, n
* sizeof(TCGHelperInfo
));
535 s
->allocated_helpers
= n
;
537 s
->helpers
[s
->nb_helpers
].func
= (tcg_target_ulong
)func
;
538 s
->helpers
[s
->nb_helpers
].name
= name
;
542 /* Note: we convert the 64 bit args to 32 bit and do some alignment
543 and endian swap. Maybe it would be better to do the alignment
544 and endian swap in tcg_reg_alloc_call(). */
545 void tcg_gen_callN(TCGContext
*s
, TCGv_ptr func
, unsigned int flags
,
546 int sizemask
, TCGArg ret
, int nargs
, TCGArg
*args
)
553 *gen_opc_ptr
++ = INDEX_op_call
;
554 nparam
= gen_opparam_ptr
++;
555 call_type
= (flags
& TCG_CALL_TYPE_MASK
);
556 if (ret
!= TCG_CALL_DUMMY_ARG
) {
557 #if TCG_TARGET_REG_BITS < 64
559 #ifdef TCG_TARGET_WORDS_BIGENDIAN
560 *gen_opparam_ptr
++ = ret
+ 1;
561 *gen_opparam_ptr
++ = ret
;
563 *gen_opparam_ptr
++ = ret
;
564 *gen_opparam_ptr
++ = ret
+ 1;
570 *gen_opparam_ptr
++ = ret
;
577 for (i
= 0; i
< nargs
; i
++) {
578 #if TCG_TARGET_REG_BITS < 64
579 if (sizemask
& (2 << i
)) {
580 #ifdef TCG_TARGET_I386
581 /* REGPARM case: if the third parameter is 64 bit, it is
582 allocated on the stack */
583 if (i
== 2 && call_type
== TCG_CALL_TYPE_REGPARM
) {
584 call_type
= TCG_CALL_TYPE_REGPARM_2
;
585 flags
= (flags
& ~TCG_CALL_TYPE_MASK
) | call_type
;
588 #ifdef TCG_TARGET_CALL_ALIGN_ARGS
589 /* some targets want aligned 64 bit args */
591 *gen_opparam_ptr
++ = TCG_CALL_DUMMY_ARG
;
595 #ifdef TCG_TARGET_WORDS_BIGENDIAN
596 *gen_opparam_ptr
++ = args
[i
] + 1;
597 *gen_opparam_ptr
++ = args
[i
];
599 *gen_opparam_ptr
++ = args
[i
];
600 *gen_opparam_ptr
++ = args
[i
] + 1;
606 *gen_opparam_ptr
++ = args
[i
];
610 *gen_opparam_ptr
++ = GET_TCGV_PTR(func
);
612 *gen_opparam_ptr
++ = flags
;
614 *nparam
= (nb_rets
<< 16) | (real_args
+ 1);
616 /* total parameters, needed to go backward in the instruction stream */
617 *gen_opparam_ptr
++ = 1 + nb_rets
+ real_args
+ 3;
620 #if TCG_TARGET_REG_BITS == 32
621 void tcg_gen_shifti_i64(TCGv_i64 ret
, TCGv_i64 arg1
,
622 int c
, int right
, int arith
)
625 tcg_gen_mov_i32(TCGV_LOW(ret
), TCGV_LOW(arg1
));
626 tcg_gen_mov_i32(TCGV_HIGH(ret
), TCGV_HIGH(arg1
));
627 } else if (c
>= 32) {
631 tcg_gen_sari_i32(TCGV_LOW(ret
), TCGV_HIGH(arg1
), c
);
632 tcg_gen_sari_i32(TCGV_HIGH(ret
), TCGV_HIGH(arg1
), 31);
634 tcg_gen_shri_i32(TCGV_LOW(ret
), TCGV_HIGH(arg1
), c
);
635 tcg_gen_movi_i32(TCGV_HIGH(ret
), 0);
638 tcg_gen_shli_i32(TCGV_HIGH(ret
), TCGV_LOW(arg1
), c
);
639 tcg_gen_movi_i32(TCGV_LOW(ret
), 0);
644 t0
= tcg_temp_new_i32();
645 t1
= tcg_temp_new_i32();
647 tcg_gen_shli_i32(t0
, TCGV_HIGH(arg1
), 32 - c
);
649 tcg_gen_sari_i32(t1
, TCGV_HIGH(arg1
), c
);
651 tcg_gen_shri_i32(t1
, TCGV_HIGH(arg1
), c
);
652 tcg_gen_shri_i32(TCGV_LOW(ret
), TCGV_LOW(arg1
), c
);
653 tcg_gen_or_i32(TCGV_LOW(ret
), TCGV_LOW(ret
), t0
);
654 tcg_gen_mov_i32(TCGV_HIGH(ret
), t1
);
656 tcg_gen_shri_i32(t0
, TCGV_LOW(arg1
), 32 - c
);
657 /* Note: ret can be the same as arg1, so we use t1 */
658 tcg_gen_shli_i32(t1
, TCGV_LOW(arg1
), c
);
659 tcg_gen_shli_i32(TCGV_HIGH(ret
), TCGV_HIGH(arg1
), c
);
660 tcg_gen_or_i32(TCGV_HIGH(ret
), TCGV_HIGH(ret
), t0
);
661 tcg_gen_mov_i32(TCGV_LOW(ret
), t1
);
663 tcg_temp_free_i32(t0
);
664 tcg_temp_free_i32(t1
);
669 static void tcg_reg_alloc_start(TCGContext
*s
)
673 for(i
= 0; i
< s
->nb_globals
; i
++) {
676 ts
->val_type
= TEMP_VAL_REG
;
678 ts
->val_type
= TEMP_VAL_MEM
;
681 for(i
= s
->nb_globals
; i
< s
->nb_temps
; i
++) {
683 ts
->val_type
= TEMP_VAL_DEAD
;
684 ts
->mem_allocated
= 0;
687 for(i
= 0; i
< TCG_TARGET_NB_REGS
; i
++) {
688 s
->reg_to_temp
[i
] = -1;
692 static char *tcg_get_arg_str_idx(TCGContext
*s
, char *buf
, int buf_size
,
698 if (idx
< s
->nb_globals
) {
699 pstrcpy(buf
, buf_size
, ts
->name
);
702 snprintf(buf
, buf_size
, "loc%d", idx
- s
->nb_globals
);
704 snprintf(buf
, buf_size
, "tmp%d", idx
- s
->nb_globals
);
709 char *tcg_get_arg_str_i32(TCGContext
*s
, char *buf
, int buf_size
, TCGv_i32 arg
)
711 return tcg_get_arg_str_idx(s
, buf
, buf_size
, GET_TCGV_I32(arg
));
714 char *tcg_get_arg_str_i64(TCGContext
*s
, char *buf
, int buf_size
, TCGv_i64 arg
)
716 return tcg_get_arg_str_idx(s
, buf
, buf_size
, GET_TCGV_I64(arg
));
719 static int helper_cmp(const void *p1
, const void *p2
)
721 const TCGHelperInfo
*th1
= p1
;
722 const TCGHelperInfo
*th2
= p2
;
723 if (th1
->func
< th2
->func
)
725 else if (th1
->func
== th2
->func
)
731 /* find helper definition (Note: A hash table would be better) */
732 static TCGHelperInfo
*tcg_find_helper(TCGContext
*s
, tcg_target_ulong val
)
738 if (unlikely(!s
->helpers_sorted
)) {
739 qsort(s
->helpers
, s
->nb_helpers
, sizeof(TCGHelperInfo
),
741 s
->helpers_sorted
= 1;
746 m_max
= s
->nb_helpers
- 1;
747 while (m_min
<= m_max
) {
748 m
= (m_min
+ m_max
) >> 1;
762 static const char * const cond_name
[] =
764 [TCG_COND_EQ
] = "eq",
765 [TCG_COND_NE
] = "ne",
766 [TCG_COND_LT
] = "lt",
767 [TCG_COND_GE
] = "ge",
768 [TCG_COND_LE
] = "le",
769 [TCG_COND_GT
] = "gt",
770 [TCG_COND_LTU
] = "ltu",
771 [TCG_COND_GEU
] = "geu",
772 [TCG_COND_LEU
] = "leu",
773 [TCG_COND_GTU
] = "gtu"
776 void tcg_dump_ops(TCGContext
*s
, FILE *outfile
)
778 const uint16_t *opc_ptr
;
781 int c
, i
, k
, nb_oargs
, nb_iargs
, nb_cargs
, first_insn
;
786 opc_ptr
= gen_opc_buf
;
787 args
= gen_opparam_buf
;
788 while (opc_ptr
< gen_opc_ptr
) {
790 def
= &tcg_op_defs
[c
];
791 if (c
== INDEX_op_debug_insn_start
) {
793 #if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
794 pc
= ((uint64_t)args
[1] << 32) | args
[0];
799 fprintf(outfile
, "\n");
800 fprintf(outfile
, " ---- 0x%" PRIx64
, pc
);
802 nb_oargs
= def
->nb_oargs
;
803 nb_iargs
= def
->nb_iargs
;
804 nb_cargs
= def
->nb_cargs
;
805 } else if (c
== INDEX_op_call
) {
808 /* variable number of arguments */
810 nb_oargs
= arg
>> 16;
811 nb_iargs
= arg
& 0xffff;
812 nb_cargs
= def
->nb_cargs
;
814 fprintf(outfile
, " %s ", def
->name
);
817 fprintf(outfile
, "%s",
818 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), args
[nb_oargs
+ nb_iargs
- 1]));
820 fprintf(outfile
, ",$0x%" TCG_PRIlx
,
821 args
[nb_oargs
+ nb_iargs
]);
823 fprintf(outfile
, ",$%d", nb_oargs
);
824 for(i
= 0; i
< nb_oargs
; i
++) {
825 fprintf(outfile
, ",");
826 fprintf(outfile
, "%s",
827 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), args
[i
]));
829 for(i
= 0; i
< (nb_iargs
- 1); i
++) {
830 fprintf(outfile
, ",");
831 if (args
[nb_oargs
+ i
] == TCG_CALL_DUMMY_ARG
) {
832 fprintf(outfile
, "<dummy>");
834 fprintf(outfile
, "%s",
835 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), args
[nb_oargs
+ i
]));
838 } else if (c
== INDEX_op_movi_i32
839 #if TCG_TARGET_REG_BITS == 64
840 || c
== INDEX_op_movi_i64
843 tcg_target_ulong val
;
846 nb_oargs
= def
->nb_oargs
;
847 nb_iargs
= def
->nb_iargs
;
848 nb_cargs
= def
->nb_cargs
;
849 fprintf(outfile
, " %s %s,$", def
->name
,
850 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), args
[0]));
852 th
= tcg_find_helper(s
, val
);
854 fprintf(outfile
, "%s", th
->name
);
856 if (c
== INDEX_op_movi_i32
)
857 fprintf(outfile
, "0x%x", (uint32_t)val
);
859 fprintf(outfile
, "0x%" PRIx64
, (uint64_t)val
);
862 fprintf(outfile
, " %s ", def
->name
);
863 if (c
== INDEX_op_nopn
) {
864 /* variable number of arguments */
869 nb_oargs
= def
->nb_oargs
;
870 nb_iargs
= def
->nb_iargs
;
871 nb_cargs
= def
->nb_cargs
;
875 for(i
= 0; i
< nb_oargs
; i
++) {
877 fprintf(outfile
, ",");
878 fprintf(outfile
, "%s",
879 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), args
[k
++]));
881 for(i
= 0; i
< nb_iargs
; i
++) {
883 fprintf(outfile
, ",");
884 fprintf(outfile
, "%s",
885 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), args
[k
++]));
887 if (c
== INDEX_op_brcond_i32
888 #if TCG_TARGET_REG_BITS == 32
889 || c
== INDEX_op_brcond2_i32
890 #elif TCG_TARGET_REG_BITS == 64
891 || c
== INDEX_op_brcond_i64
894 if (args
[k
] < ARRAY_SIZE(cond_name
) && cond_name
[args
[k
]])
895 fprintf(outfile
, ",%s", cond_name
[args
[k
++]]);
897 fprintf(outfile
, ",$0x%" TCG_PRIlx
, args
[k
++]);
902 for(; i
< nb_cargs
; i
++) {
904 fprintf(outfile
, ",");
906 fprintf(outfile
, "$0x%" TCG_PRIlx
, arg
);
909 fprintf(outfile
, "\n");
910 args
+= nb_iargs
+ nb_oargs
+ nb_cargs
;
914 /* we give more priority to constraints with less registers */
915 static int get_constraint_priority(const TCGOpDef
*def
, int k
)
917 const TCGArgConstraint
*arg_ct
;
920 arg_ct
= &def
->args_ct
[k
];
921 if (arg_ct
->ct
& TCG_CT_ALIAS
) {
922 /* an alias is equivalent to a single register */
925 if (!(arg_ct
->ct
& TCG_CT_REG
))
928 for(i
= 0; i
< TCG_TARGET_NB_REGS
; i
++) {
929 if (tcg_regset_test_reg(arg_ct
->u
.regs
, i
))
933 return TCG_TARGET_NB_REGS
- n
+ 1;
936 /* sort from highest priority to lowest */
937 static void sort_constraints(TCGOpDef
*def
, int start
, int n
)
939 int i
, j
, p1
, p2
, tmp
;
941 for(i
= 0; i
< n
; i
++)
942 def
->sorted_args
[start
+ i
] = start
+ i
;
945 for(i
= 0; i
< n
- 1; i
++) {
946 for(j
= i
+ 1; j
< n
; j
++) {
947 p1
= get_constraint_priority(def
, def
->sorted_args
[start
+ i
]);
948 p2
= get_constraint_priority(def
, def
->sorted_args
[start
+ j
]);
950 tmp
= def
->sorted_args
[start
+ i
];
951 def
->sorted_args
[start
+ i
] = def
->sorted_args
[start
+ j
];
952 def
->sorted_args
[start
+ j
] = tmp
;
958 void tcg_add_target_add_op_defs(const TCGTargetOpDef
*tdefs
)
969 assert(op
>= 0 && op
< NB_OPS
);
970 def
= &tcg_op_defs
[op
];
971 nb_args
= def
->nb_iargs
+ def
->nb_oargs
;
972 for(i
= 0; i
< nb_args
; i
++) {
973 ct_str
= tdefs
->args_ct_str
[i
];
974 tcg_regset_clear(def
->args_ct
[i
].u
.regs
);
975 def
->args_ct
[i
].ct
= 0;
976 if (ct_str
[0] >= '0' && ct_str
[0] <= '9') {
978 oarg
= ct_str
[0] - '0';
979 assert(oarg
< def
->nb_oargs
);
980 assert(def
->args_ct
[oarg
].ct
& TCG_CT_REG
);
981 /* TCG_CT_ALIAS is for the output arguments. The input
982 argument is tagged with TCG_CT_IALIAS. */
983 def
->args_ct
[i
] = def
->args_ct
[oarg
];
984 def
->args_ct
[oarg
].ct
= TCG_CT_ALIAS
;
985 def
->args_ct
[oarg
].alias_index
= i
;
986 def
->args_ct
[i
].ct
|= TCG_CT_IALIAS
;
987 def
->args_ct
[i
].alias_index
= oarg
;
994 def
->args_ct
[i
].ct
|= TCG_CT_CONST
;
998 if (target_parse_constraint(&def
->args_ct
[i
], &ct_str
) < 0) {
999 fprintf(stderr
, "Invalid constraint '%s' for arg %d of operation '%s'\n",
1000 ct_str
, i
, def
->name
);
1008 /* sort the constraints (XXX: this is just an heuristic) */
1009 sort_constraints(def
, 0, def
->nb_oargs
);
1010 sort_constraints(def
, def
->nb_oargs
, def
->nb_iargs
);
1016 printf("%s: sorted=", def
->name
);
1017 for(i
= 0; i
< def
->nb_oargs
+ def
->nb_iargs
; i
++)
1018 printf(" %d", def
->sorted_args
[i
]);
1027 #ifdef USE_LIVENESS_ANALYSIS
1029 /* set a nop for an operation using 'nb_args' */
1030 static inline void tcg_set_nop(TCGContext
*s
, uint16_t *opc_ptr
,
1031 TCGArg
*args
, int nb_args
)
1034 *opc_ptr
= INDEX_op_nop
;
1036 *opc_ptr
= INDEX_op_nopn
;
1038 args
[nb_args
- 1] = nb_args
;
1042 /* liveness analysis: end of function: globals are live, temps are
1044 /* XXX: at this stage, not used as there would be little gains because
1045 most TBs end with a conditional jump. */
1046 static inline void tcg_la_func_end(TCGContext
*s
, uint8_t *dead_temps
)
1048 memset(dead_temps
, 0, s
->nb_globals
);
1049 memset(dead_temps
+ s
->nb_globals
, 1, s
->nb_temps
- s
->nb_globals
);
1052 /* liveness analysis: end of basic block: globals are live, temps are
1053 dead, local temps are live. */
1054 static inline void tcg_la_bb_end(TCGContext
*s
, uint8_t *dead_temps
)
1059 memset(dead_temps
, 0, s
->nb_globals
);
1060 ts
= &s
->temps
[s
->nb_globals
];
1061 for(i
= s
->nb_globals
; i
< s
->nb_temps
; i
++) {
1070 /* Liveness analysis : update the opc_dead_iargs array to tell if a
1071 given input arguments is dead. Instructions updating dead
1072 temporaries are removed. */
1073 static void tcg_liveness_analysis(TCGContext
*s
)
1075 int i
, op_index
, op
, nb_args
, nb_iargs
, nb_oargs
, arg
, nb_ops
;
1077 const TCGOpDef
*def
;
1078 uint8_t *dead_temps
;
1079 unsigned int dead_iargs
;
1081 gen_opc_ptr
++; /* skip end */
1083 nb_ops
= gen_opc_ptr
- gen_opc_buf
;
1085 /* XXX: make it really dynamic */
1086 s
->op_dead_iargs
= tcg_malloc(OPC_BUF_SIZE
* sizeof(uint16_t));
1088 dead_temps
= tcg_malloc(s
->nb_temps
);
1089 memset(dead_temps
, 1, s
->nb_temps
);
1091 args
= gen_opparam_ptr
;
1092 op_index
= nb_ops
- 1;
1093 while (op_index
>= 0) {
1094 op
= gen_opc_buf
[op_index
];
1095 def
= &tcg_op_defs
[op
];
1103 nb_iargs
= args
[0] & 0xffff;
1104 nb_oargs
= args
[0] >> 16;
1106 call_flags
= args
[nb_oargs
+ nb_iargs
];
1108 /* pure functions can be removed if their result is not
1110 if (call_flags
& TCG_CALL_PURE
) {
1111 for(i
= 0; i
< nb_oargs
; i
++) {
1113 if (!dead_temps
[arg
])
1114 goto do_not_remove_call
;
1116 tcg_set_nop(s
, gen_opc_buf
+ op_index
,
1121 /* output args are dead */
1122 for(i
= 0; i
< nb_oargs
; i
++) {
1124 dead_temps
[arg
] = 1;
1127 if (!(call_flags
& TCG_CALL_CONST
)) {
1128 /* globals are live (they may be used by the call) */
1129 memset(dead_temps
, 0, s
->nb_globals
);
1132 /* input args are live */
1134 for(i
= 0; i
< nb_iargs
; i
++) {
1135 arg
= args
[i
+ nb_oargs
];
1136 if (arg
!= TCG_CALL_DUMMY_ARG
) {
1137 if (dead_temps
[arg
]) {
1138 dead_iargs
|= (1 << i
);
1140 dead_temps
[arg
] = 0;
1143 s
->op_dead_iargs
[op_index
] = dead_iargs
;
1148 case INDEX_op_set_label
:
1150 /* mark end of basic block */
1151 tcg_la_bb_end(s
, dead_temps
);
1153 case INDEX_op_debug_insn_start
:
1154 args
-= def
->nb_args
;
1160 case INDEX_op_discard
:
1162 /* mark the temporary as dead */
1163 dead_temps
[args
[0]] = 1;
1167 /* XXX: optimize by hardcoding common cases (e.g. triadic ops) */
1169 args
-= def
->nb_args
;
1170 nb_iargs
= def
->nb_iargs
;
1171 nb_oargs
= def
->nb_oargs
;
1173 /* Test if the operation can be removed because all
1174 its outputs are dead. We assume that nb_oargs == 0
1175 implies side effects */
1176 if (!(def
->flags
& TCG_OPF_SIDE_EFFECTS
) && nb_oargs
!= 0) {
1177 for(i
= 0; i
< nb_oargs
; i
++) {
1179 if (!dead_temps
[arg
])
1182 tcg_set_nop(s
, gen_opc_buf
+ op_index
, args
, def
->nb_args
);
1183 #ifdef CONFIG_PROFILER
1189 /* output args are dead */
1190 for(i
= 0; i
< nb_oargs
; i
++) {
1192 dead_temps
[arg
] = 1;
1195 /* if end of basic block, update */
1196 if (def
->flags
& TCG_OPF_BB_END
) {
1197 tcg_la_bb_end(s
, dead_temps
);
1198 } else if (def
->flags
& TCG_OPF_CALL_CLOBBER
) {
1199 /* globals are live */
1200 memset(dead_temps
, 0, s
->nb_globals
);
1203 /* input args are live */
1205 for(i
= 0; i
< nb_iargs
; i
++) {
1206 arg
= args
[i
+ nb_oargs
];
1207 if (dead_temps
[arg
]) {
1208 dead_iargs
|= (1 << i
);
1210 dead_temps
[arg
] = 0;
1212 s
->op_dead_iargs
[op_index
] = dead_iargs
;
1219 if (args
!= gen_opparam_buf
)
1223 /* dummy liveness analysis */
1224 void tcg_liveness_analysis(TCGContext
*s
)
1227 nb_ops
= gen_opc_ptr
- gen_opc_buf
;
1229 s
->op_dead_iargs
= tcg_malloc(nb_ops
* sizeof(uint16_t));
1230 memset(s
->op_dead_iargs
, 0, nb_ops
* sizeof(uint16_t));
1235 static void dump_regs(TCGContext
*s
)
1241 for(i
= 0; i
< s
->nb_temps
; i
++) {
1243 printf(" %10s: ", tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), i
));
1244 switch(ts
->val_type
) {
1246 printf("%s", tcg_target_reg_names
[ts
->reg
]);
1249 printf("%d(%s)", (int)ts
->mem_offset
, tcg_target_reg_names
[ts
->mem_reg
]);
1251 case TEMP_VAL_CONST
:
1252 printf("$0x%" TCG_PRIlx
, ts
->val
);
1264 for(i
= 0; i
< TCG_TARGET_NB_REGS
; i
++) {
1265 if (s
->reg_to_temp
[i
] >= 0) {
1267 tcg_target_reg_names
[i
],
1268 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), s
->reg_to_temp
[i
]));
1273 static void check_regs(TCGContext
*s
)
1279 for(reg
= 0; reg
< TCG_TARGET_NB_REGS
; reg
++) {
1280 k
= s
->reg_to_temp
[reg
];
1283 if (ts
->val_type
!= TEMP_VAL_REG
||
1285 printf("Inconsistency for register %s:\n",
1286 tcg_target_reg_names
[reg
]);
1291 for(k
= 0; k
< s
->nb_temps
; k
++) {
1293 if (ts
->val_type
== TEMP_VAL_REG
&&
1295 s
->reg_to_temp
[ts
->reg
] != k
) {
1296 printf("Inconsistency for temp %s:\n",
1297 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), k
));
1299 printf("reg state:\n");
1307 static void temp_allocate_frame(TCGContext
*s
, int temp
)
1310 ts
= &s
->temps
[temp
];
1311 s
->current_frame_offset
= (s
->current_frame_offset
+ sizeof(tcg_target_long
) - 1) & ~(sizeof(tcg_target_long
) - 1);
1312 if (s
->current_frame_offset
+ sizeof(tcg_target_long
) > s
->frame_end
)
1314 ts
->mem_offset
= s
->current_frame_offset
;
1315 ts
->mem_reg
= s
->frame_reg
;
1316 ts
->mem_allocated
= 1;
1317 s
->current_frame_offset
+= sizeof(tcg_target_long
);
1320 /* free register 'reg' by spilling the corresponding temporary if necessary */
1321 static void tcg_reg_free(TCGContext
*s
, int reg
)
1326 temp
= s
->reg_to_temp
[reg
];
1328 ts
= &s
->temps
[temp
];
1329 assert(ts
->val_type
== TEMP_VAL_REG
);
1330 if (!ts
->mem_coherent
) {
1331 if (!ts
->mem_allocated
)
1332 temp_allocate_frame(s
, temp
);
1333 tcg_out_st(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
1335 ts
->val_type
= TEMP_VAL_MEM
;
1336 s
->reg_to_temp
[reg
] = -1;
1340 /* Allocate a register belonging to reg1 & ~reg2 */
1341 static int tcg_reg_alloc(TCGContext
*s
, TCGRegSet reg1
, TCGRegSet reg2
)
1346 tcg_regset_andnot(reg_ct
, reg1
, reg2
);
1348 /* first try free registers */
1349 for(i
= 0; i
< ARRAY_SIZE(tcg_target_reg_alloc_order
); i
++) {
1350 reg
= tcg_target_reg_alloc_order
[i
];
1351 if (tcg_regset_test_reg(reg_ct
, reg
) && s
->reg_to_temp
[reg
] == -1)
1355 /* XXX: do better spill choice */
1356 for(i
= 0; i
< ARRAY_SIZE(tcg_target_reg_alloc_order
); i
++) {
1357 reg
= tcg_target_reg_alloc_order
[i
];
1358 if (tcg_regset_test_reg(reg_ct
, reg
)) {
1359 tcg_reg_free(s
, reg
);
1367 /* save a temporary to memory. 'allocated_regs' is used in case a
1368 temporary registers needs to be allocated to store a constant. */
1369 static void temp_save(TCGContext
*s
, int temp
, TCGRegSet allocated_regs
)
1374 ts
= &s
->temps
[temp
];
1375 if (!ts
->fixed_reg
) {
1376 switch(ts
->val_type
) {
1378 tcg_reg_free(s
, ts
->reg
);
1381 ts
->val_type
= TEMP_VAL_MEM
;
1383 case TEMP_VAL_CONST
:
1384 reg
= tcg_reg_alloc(s
, tcg_target_available_regs
[ts
->type
],
1386 if (!ts
->mem_allocated
)
1387 temp_allocate_frame(s
, temp
);
1388 tcg_out_movi(s
, ts
->type
, reg
, ts
->val
);
1389 tcg_out_st(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
1390 ts
->val_type
= TEMP_VAL_MEM
;
1400 /* save globals to their cannonical location and assume they can be
1401 modified be the following code. 'allocated_regs' is used in case a
1402 temporary registers needs to be allocated to store a constant. */
1403 static void save_globals(TCGContext
*s
, TCGRegSet allocated_regs
)
1407 for(i
= 0; i
< s
->nb_globals
; i
++) {
1408 temp_save(s
, i
, allocated_regs
);
1412 /* at the end of a basic block, we assume all temporaries are dead and
1413 all globals are stored at their canonical location. */
1414 static void tcg_reg_alloc_bb_end(TCGContext
*s
, TCGRegSet allocated_regs
)
1419 for(i
= s
->nb_globals
; i
< s
->nb_temps
; i
++) {
1421 if (ts
->temp_local
) {
1422 temp_save(s
, i
, allocated_regs
);
1424 if (ts
->val_type
== TEMP_VAL_REG
) {
1425 s
->reg_to_temp
[ts
->reg
] = -1;
1427 ts
->val_type
= TEMP_VAL_DEAD
;
1431 save_globals(s
, allocated_regs
);
1434 #define IS_DEAD_IARG(n) ((dead_iargs >> (n)) & 1)
1436 static void tcg_reg_alloc_movi(TCGContext
*s
, const TCGArg
*args
)
1439 tcg_target_ulong val
;
1441 ots
= &s
->temps
[args
[0]];
1444 if (ots
->fixed_reg
) {
1445 /* for fixed registers, we do not do any constant
1447 tcg_out_movi(s
, ots
->type
, ots
->reg
, val
);
1449 /* The movi is not explicitly generated here */
1450 if (ots
->val_type
== TEMP_VAL_REG
)
1451 s
->reg_to_temp
[ots
->reg
] = -1;
1452 ots
->val_type
= TEMP_VAL_CONST
;
1457 static void tcg_reg_alloc_mov(TCGContext
*s
, const TCGOpDef
*def
,
1459 unsigned int dead_iargs
)
1463 const TCGArgConstraint
*arg_ct
;
1465 ots
= &s
->temps
[args
[0]];
1466 ts
= &s
->temps
[args
[1]];
1467 arg_ct
= &def
->args_ct
[0];
1469 /* XXX: always mark arg dead if IS_DEAD_IARG(0) */
1470 if (ts
->val_type
== TEMP_VAL_REG
) {
1471 if (IS_DEAD_IARG(0) && !ts
->fixed_reg
&& !ots
->fixed_reg
) {
1472 /* the mov can be suppressed */
1473 if (ots
->val_type
== TEMP_VAL_REG
)
1474 s
->reg_to_temp
[ots
->reg
] = -1;
1476 s
->reg_to_temp
[reg
] = -1;
1477 ts
->val_type
= TEMP_VAL_DEAD
;
1479 if (ots
->val_type
== TEMP_VAL_REG
) {
1482 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, s
->reserved_regs
);
1484 if (ts
->reg
!= reg
) {
1485 tcg_out_mov(s
, reg
, ts
->reg
);
1488 } else if (ts
->val_type
== TEMP_VAL_MEM
) {
1489 if (ots
->val_type
== TEMP_VAL_REG
) {
1492 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, s
->reserved_regs
);
1494 tcg_out_ld(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
1495 } else if (ts
->val_type
== TEMP_VAL_CONST
) {
1496 if (ots
->fixed_reg
) {
1498 tcg_out_movi(s
, ots
->type
, reg
, ts
->val
);
1500 /* propagate constant */
1501 if (ots
->val_type
== TEMP_VAL_REG
)
1502 s
->reg_to_temp
[ots
->reg
] = -1;
1503 ots
->val_type
= TEMP_VAL_CONST
;
1510 s
->reg_to_temp
[reg
] = args
[0];
1512 ots
->val_type
= TEMP_VAL_REG
;
1513 ots
->mem_coherent
= 0;
1516 static void tcg_reg_alloc_op(TCGContext
*s
,
1517 const TCGOpDef
*def
, int opc
,
1519 unsigned int dead_iargs
)
1521 TCGRegSet allocated_regs
;
1522 int i
, k
, nb_iargs
, nb_oargs
, reg
;
1524 const TCGArgConstraint
*arg_ct
;
1526 TCGArg new_args
[TCG_MAX_OP_ARGS
];
1527 int const_args
[TCG_MAX_OP_ARGS
];
1529 nb_oargs
= def
->nb_oargs
;
1530 nb_iargs
= def
->nb_iargs
;
1532 /* copy constants */
1533 memcpy(new_args
+ nb_oargs
+ nb_iargs
,
1534 args
+ nb_oargs
+ nb_iargs
,
1535 sizeof(TCGArg
) * def
->nb_cargs
);
1537 /* satisfy input constraints */
1538 tcg_regset_set(allocated_regs
, s
->reserved_regs
);
1539 for(k
= 0; k
< nb_iargs
; k
++) {
1540 i
= def
->sorted_args
[nb_oargs
+ k
];
1542 arg_ct
= &def
->args_ct
[i
];
1543 ts
= &s
->temps
[arg
];
1544 if (ts
->val_type
== TEMP_VAL_MEM
) {
1545 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1546 tcg_out_ld(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
1547 ts
->val_type
= TEMP_VAL_REG
;
1549 ts
->mem_coherent
= 1;
1550 s
->reg_to_temp
[reg
] = arg
;
1551 } else if (ts
->val_type
== TEMP_VAL_CONST
) {
1552 if (tcg_target_const_match(ts
->val
, arg_ct
)) {
1553 /* constant is OK for instruction */
1555 new_args
[i
] = ts
->val
;
1558 /* need to move to a register */
1559 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1560 tcg_out_movi(s
, ts
->type
, reg
, ts
->val
);
1561 ts
->val_type
= TEMP_VAL_REG
;
1563 ts
->mem_coherent
= 0;
1564 s
->reg_to_temp
[reg
] = arg
;
1567 assert(ts
->val_type
== TEMP_VAL_REG
);
1568 if (arg_ct
->ct
& TCG_CT_IALIAS
) {
1569 if (ts
->fixed_reg
) {
1570 /* if fixed register, we must allocate a new register
1571 if the alias is not the same register */
1572 if (arg
!= args
[arg_ct
->alias_index
])
1573 goto allocate_in_reg
;
1575 /* if the input is aliased to an output and if it is
1576 not dead after the instruction, we must allocate
1577 a new register and move it */
1578 if (!IS_DEAD_IARG(i
- nb_oargs
))
1579 goto allocate_in_reg
;
1583 if (tcg_regset_test_reg(arg_ct
->u
.regs
, reg
)) {
1584 /* nothing to do : the constraint is satisfied */
1587 /* allocate a new register matching the constraint
1588 and move the temporary register into it */
1589 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1590 tcg_out_mov(s
, reg
, ts
->reg
);
1594 tcg_regset_set_reg(allocated_regs
, reg
);
1598 if (def
->flags
& TCG_OPF_BB_END
) {
1599 tcg_reg_alloc_bb_end(s
, allocated_regs
);
1601 /* mark dead temporaries and free the associated registers */
1602 for(i
= 0; i
< nb_iargs
; i
++) {
1603 arg
= args
[nb_oargs
+ i
];
1604 if (IS_DEAD_IARG(i
)) {
1605 ts
= &s
->temps
[arg
];
1606 if (!ts
->fixed_reg
) {
1607 if (ts
->val_type
== TEMP_VAL_REG
)
1608 s
->reg_to_temp
[ts
->reg
] = -1;
1609 ts
->val_type
= TEMP_VAL_DEAD
;
1614 if (def
->flags
& TCG_OPF_CALL_CLOBBER
) {
1615 /* XXX: permit generic clobber register list ? */
1616 for(reg
= 0; reg
< TCG_TARGET_NB_REGS
; reg
++) {
1617 if (tcg_regset_test_reg(tcg_target_call_clobber_regs
, reg
)) {
1618 tcg_reg_free(s
, reg
);
1621 /* XXX: for load/store we could do that only for the slow path
1622 (i.e. when a memory callback is called) */
1624 /* store globals and free associated registers (we assume the insn
1625 can modify any global. */
1626 save_globals(s
, allocated_regs
);
1629 /* satisfy the output constraints */
1630 tcg_regset_set(allocated_regs
, s
->reserved_regs
);
1631 for(k
= 0; k
< nb_oargs
; k
++) {
1632 i
= def
->sorted_args
[k
];
1634 arg_ct
= &def
->args_ct
[i
];
1635 ts
= &s
->temps
[arg
];
1636 if (arg_ct
->ct
& TCG_CT_ALIAS
) {
1637 reg
= new_args
[arg_ct
->alias_index
];
1639 /* if fixed register, we try to use it */
1641 if (ts
->fixed_reg
&&
1642 tcg_regset_test_reg(arg_ct
->u
.regs
, reg
)) {
1645 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1647 tcg_regset_set_reg(allocated_regs
, reg
);
1648 /* if a fixed register is used, then a move will be done afterwards */
1649 if (!ts
->fixed_reg
) {
1650 if (ts
->val_type
== TEMP_VAL_REG
)
1651 s
->reg_to_temp
[ts
->reg
] = -1;
1652 ts
->val_type
= TEMP_VAL_REG
;
1654 /* temp value is modified, so the value kept in memory is
1655 potentially not the same */
1656 ts
->mem_coherent
= 0;
1657 s
->reg_to_temp
[reg
] = arg
;
1664 /* emit instruction */
1665 tcg_out_op(s
, opc
, new_args
, const_args
);
1667 /* move the outputs in the correct register if needed */
1668 for(i
= 0; i
< nb_oargs
; i
++) {
1669 ts
= &s
->temps
[args
[i
]];
1671 if (ts
->fixed_reg
&& ts
->reg
!= reg
) {
1672 tcg_out_mov(s
, ts
->reg
, reg
);
1677 #ifdef TCG_TARGET_STACK_GROWSUP
1678 #define STACK_DIR(x) (-(x))
1680 #define STACK_DIR(x) (x)
1683 static int tcg_reg_alloc_call(TCGContext
*s
, const TCGOpDef
*def
,
1684 int opc
, const TCGArg
*args
,
1685 unsigned int dead_iargs
)
1687 int nb_iargs
, nb_oargs
, flags
, nb_regs
, i
, reg
, nb_params
;
1688 TCGArg arg
, func_arg
;
1690 tcg_target_long stack_offset
, call_stack_size
, func_addr
;
1691 int const_func_arg
, allocate_args
;
1692 TCGRegSet allocated_regs
;
1693 const TCGArgConstraint
*arg_ct
;
1697 nb_oargs
= arg
>> 16;
1698 nb_iargs
= arg
& 0xffff;
1699 nb_params
= nb_iargs
- 1;
1701 flags
= args
[nb_oargs
+ nb_iargs
];
1703 nb_regs
= tcg_target_get_call_iarg_regs_count(flags
);
1704 if (nb_regs
> nb_params
)
1705 nb_regs
= nb_params
;
1707 /* assign stack slots first */
1708 /* XXX: preallocate call stack */
1709 call_stack_size
= (nb_params
- nb_regs
) * sizeof(tcg_target_long
);
1710 call_stack_size
= (call_stack_size
+ TCG_TARGET_STACK_ALIGN
- 1) &
1711 ~(TCG_TARGET_STACK_ALIGN
- 1);
1712 allocate_args
= (call_stack_size
> TCG_STATIC_CALL_ARGS_SIZE
);
1713 if (allocate_args
) {
1714 tcg_out_addi(s
, TCG_REG_CALL_STACK
, -STACK_DIR(call_stack_size
));
1717 stack_offset
= TCG_TARGET_CALL_STACK_OFFSET
;
1718 for(i
= nb_regs
; i
< nb_params
; i
++) {
1719 arg
= args
[nb_oargs
+ i
];
1720 #ifdef TCG_TARGET_STACK_GROWSUP
1721 stack_offset
-= sizeof(tcg_target_long
);
1723 if (arg
!= TCG_CALL_DUMMY_ARG
) {
1724 ts
= &s
->temps
[arg
];
1725 if (ts
->val_type
== TEMP_VAL_REG
) {
1726 tcg_out_st(s
, ts
->type
, ts
->reg
, TCG_REG_CALL_STACK
, stack_offset
);
1727 } else if (ts
->val_type
== TEMP_VAL_MEM
) {
1728 reg
= tcg_reg_alloc(s
, tcg_target_available_regs
[ts
->type
],
1730 /* XXX: not correct if reading values from the stack */
1731 tcg_out_ld(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
1732 tcg_out_st(s
, ts
->type
, reg
, TCG_REG_CALL_STACK
, stack_offset
);
1733 } else if (ts
->val_type
== TEMP_VAL_CONST
) {
1734 reg
= tcg_reg_alloc(s
, tcg_target_available_regs
[ts
->type
],
1736 /* XXX: sign extend may be needed on some targets */
1737 tcg_out_movi(s
, ts
->type
, reg
, ts
->val
);
1738 tcg_out_st(s
, ts
->type
, reg
, TCG_REG_CALL_STACK
, stack_offset
);
1743 #ifndef TCG_TARGET_STACK_GROWSUP
1744 stack_offset
+= sizeof(tcg_target_long
);
1748 /* assign input registers */
1749 tcg_regset_set(allocated_regs
, s
->reserved_regs
);
1750 for(i
= 0; i
< nb_regs
; i
++) {
1751 arg
= args
[nb_oargs
+ i
];
1752 if (arg
!= TCG_CALL_DUMMY_ARG
) {
1753 ts
= &s
->temps
[arg
];
1754 reg
= tcg_target_call_iarg_regs
[i
];
1755 tcg_reg_free(s
, reg
);
1756 if (ts
->val_type
== TEMP_VAL_REG
) {
1757 if (ts
->reg
!= reg
) {
1758 tcg_out_mov(s
, reg
, ts
->reg
);
1760 } else if (ts
->val_type
== TEMP_VAL_MEM
) {
1761 tcg_out_ld(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
1762 } else if (ts
->val_type
== TEMP_VAL_CONST
) {
1763 /* XXX: sign extend ? */
1764 tcg_out_movi(s
, ts
->type
, reg
, ts
->val
);
1768 tcg_regset_set_reg(allocated_regs
, reg
);
1772 /* assign function address */
1773 func_arg
= args
[nb_oargs
+ nb_iargs
- 1];
1774 arg_ct
= &def
->args_ct
[0];
1775 ts
= &s
->temps
[func_arg
];
1776 func_addr
= ts
->val
;
1778 if (ts
->val_type
== TEMP_VAL_MEM
) {
1779 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1780 tcg_out_ld(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
1782 tcg_regset_set_reg(allocated_regs
, reg
);
1783 } else if (ts
->val_type
== TEMP_VAL_REG
) {
1785 if (!tcg_regset_test_reg(arg_ct
->u
.regs
, reg
)) {
1786 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1787 tcg_out_mov(s
, reg
, ts
->reg
);
1790 tcg_regset_set_reg(allocated_regs
, reg
);
1791 } else if (ts
->val_type
== TEMP_VAL_CONST
) {
1792 if (tcg_target_const_match(func_addr
, arg_ct
)) {
1794 func_arg
= func_addr
;
1796 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1797 tcg_out_movi(s
, ts
->type
, reg
, func_addr
);
1799 tcg_regset_set_reg(allocated_regs
, reg
);
1806 /* mark dead temporaries and free the associated registers */
1807 for(i
= 0; i
< nb_iargs
; i
++) {
1808 arg
= args
[nb_oargs
+ i
];
1809 if (IS_DEAD_IARG(i
)) {
1810 ts
= &s
->temps
[arg
];
1811 if (!ts
->fixed_reg
) {
1812 if (ts
->val_type
== TEMP_VAL_REG
)
1813 s
->reg_to_temp
[ts
->reg
] = -1;
1814 ts
->val_type
= TEMP_VAL_DEAD
;
1819 /* clobber call registers */
1820 for(reg
= 0; reg
< TCG_TARGET_NB_REGS
; reg
++) {
1821 if (tcg_regset_test_reg(tcg_target_call_clobber_regs
, reg
)) {
1822 tcg_reg_free(s
, reg
);
1826 /* store globals and free associated registers (we assume the call
1827 can modify any global. */
1828 if (!(flags
& TCG_CALL_CONST
)) {
1829 save_globals(s
, allocated_regs
);
1832 tcg_out_op(s
, opc
, &func_arg
, &const_func_arg
);
1834 if (allocate_args
) {
1835 tcg_out_addi(s
, TCG_REG_CALL_STACK
, STACK_DIR(call_stack_size
));
1838 /* assign output registers and emit moves if needed */
1839 for(i
= 0; i
< nb_oargs
; i
++) {
1841 ts
= &s
->temps
[arg
];
1842 reg
= tcg_target_call_oarg_regs
[i
];
1843 assert(s
->reg_to_temp
[reg
] == -1);
1844 if (ts
->fixed_reg
) {
1845 if (ts
->reg
!= reg
) {
1846 tcg_out_mov(s
, ts
->reg
, reg
);
1849 if (ts
->val_type
== TEMP_VAL_REG
)
1850 s
->reg_to_temp
[ts
->reg
] = -1;
1851 ts
->val_type
= TEMP_VAL_REG
;
1853 ts
->mem_coherent
= 0;
1854 s
->reg_to_temp
[reg
] = arg
;
1858 return nb_iargs
+ nb_oargs
+ def
->nb_cargs
+ 1;
1861 #ifdef CONFIG_PROFILER
1863 static int64_t tcg_table_op_count
[NB_OPS
];
1865 void dump_op_count(void)
1869 f
= fopen("/tmp/op.log", "w");
1870 for(i
= INDEX_op_end
; i
< NB_OPS
; i
++) {
1871 fprintf(f
, "%s %" PRId64
"\n", tcg_op_defs
[i
].name
, tcg_table_op_count
[i
]);
1878 static inline int tcg_gen_code_common(TCGContext
*s
, uint8_t *gen_code_buf
,
1882 const TCGOpDef
*def
;
1883 unsigned int dead_iargs
;
1887 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP
))) {
1889 tcg_dump_ops(s
, logfile
);
1894 #ifdef CONFIG_PROFILER
1895 s
->la_time
-= profile_getclock();
1897 tcg_liveness_analysis(s
);
1898 #ifdef CONFIG_PROFILER
1899 s
->la_time
+= profile_getclock();
1903 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_OPT
))) {
1904 qemu_log("OP after la:\n");
1905 tcg_dump_ops(s
, logfile
);
1910 tcg_reg_alloc_start(s
);
1912 s
->code_buf
= gen_code_buf
;
1913 s
->code_ptr
= gen_code_buf
;
1915 args
= gen_opparam_buf
;
1919 opc
= gen_opc_buf
[op_index
];
1920 #ifdef CONFIG_PROFILER
1921 tcg_table_op_count
[opc
]++;
1923 def
= &tcg_op_defs
[opc
];
1925 printf("%s: %d %d %d\n", def
->name
,
1926 def
->nb_oargs
, def
->nb_iargs
, def
->nb_cargs
);
1930 case INDEX_op_mov_i32
:
1931 #if TCG_TARGET_REG_BITS == 64
1932 case INDEX_op_mov_i64
:
1934 dead_iargs
= s
->op_dead_iargs
[op_index
];
1935 tcg_reg_alloc_mov(s
, def
, args
, dead_iargs
);
1937 case INDEX_op_movi_i32
:
1938 #if TCG_TARGET_REG_BITS == 64
1939 case INDEX_op_movi_i64
:
1941 tcg_reg_alloc_movi(s
, args
);
1943 case INDEX_op_debug_insn_start
:
1944 /* debug instruction */
1954 case INDEX_op_discard
:
1957 ts
= &s
->temps
[args
[0]];
1958 /* mark the temporary as dead */
1959 if (!ts
->fixed_reg
) {
1960 if (ts
->val_type
== TEMP_VAL_REG
)
1961 s
->reg_to_temp
[ts
->reg
] = -1;
1962 ts
->val_type
= TEMP_VAL_DEAD
;
1966 case INDEX_op_set_label
:
1967 tcg_reg_alloc_bb_end(s
, s
->reserved_regs
);
1968 tcg_out_label(s
, args
[0], (long)s
->code_ptr
);
1971 dead_iargs
= s
->op_dead_iargs
[op_index
];
1972 args
+= tcg_reg_alloc_call(s
, def
, opc
, args
, dead_iargs
);
1977 /* Note: in order to speed up the code, it would be much
1978 faster to have specialized register allocator functions for
1979 some common argument patterns */
1980 dead_iargs
= s
->op_dead_iargs
[op_index
];
1981 tcg_reg_alloc_op(s
, def
, opc
, args
, dead_iargs
);
1984 args
+= def
->nb_args
;
1986 if (search_pc
>= 0 && search_pc
< s
->code_ptr
- gen_code_buf
) {
1998 int tcg_gen_code(TCGContext
*s
, uint8_t *gen_code_buf
)
2000 #ifdef CONFIG_PROFILER
2003 n
= (gen_opc_ptr
- gen_opc_buf
);
2005 if (n
> s
->op_count_max
)
2006 s
->op_count_max
= n
;
2008 s
->temp_count
+= s
->nb_temps
;
2009 if (s
->nb_temps
> s
->temp_count_max
)
2010 s
->temp_count_max
= s
->nb_temps
;
2014 tcg_gen_code_common(s
, gen_code_buf
, -1);
2016 /* flush instruction cache */
2017 flush_icache_range((unsigned long)gen_code_buf
,
2018 (unsigned long)s
->code_ptr
);
2019 return s
->code_ptr
- gen_code_buf
;
2022 /* Return the index of the micro operation such as the pc after is <
2023 offset bytes from the start of the TB. The contents of gen_code_buf must
2024 not be changed, though writing the same values is ok.
2025 Return -1 if not found. */
2026 int tcg_gen_code_search_pc(TCGContext
*s
, uint8_t *gen_code_buf
, long offset
)
2028 return tcg_gen_code_common(s
, gen_code_buf
, offset
);
2031 #ifdef CONFIG_PROFILER
2032 void tcg_dump_info(FILE *f
,
2033 int (*cpu_fprintf
)(FILE *f
, const char *fmt
, ...))
2035 TCGContext
*s
= &tcg_ctx
;
2038 tot
= s
->interm_time
+ s
->code_time
;
2039 cpu_fprintf(f
, "JIT cycles %" PRId64
" (%0.3f s at 2.4 GHz)\n",
2041 cpu_fprintf(f
, "translated TBs %" PRId64
" (aborted=%" PRId64
" %0.1f%%)\n",
2043 s
->tb_count1
- s
->tb_count
,
2044 s
->tb_count1
? (double)(s
->tb_count1
- s
->tb_count
) / s
->tb_count1
* 100.0 : 0);
2045 cpu_fprintf(f
, "avg ops/TB %0.1f max=%d\n",
2046 s
->tb_count
? (double)s
->op_count
/ s
->tb_count
: 0, s
->op_count_max
);
2047 cpu_fprintf(f
, "deleted ops/TB %0.2f\n",
2049 (double)s
->del_op_count
/ s
->tb_count
: 0);
2050 cpu_fprintf(f
, "avg temps/TB %0.2f max=%d\n",
2052 (double)s
->temp_count
/ s
->tb_count
: 0,
2055 cpu_fprintf(f
, "cycles/op %0.1f\n",
2056 s
->op_count
? (double)tot
/ s
->op_count
: 0);
2057 cpu_fprintf(f
, "cycles/in byte %0.1f\n",
2058 s
->code_in_len
? (double)tot
/ s
->code_in_len
: 0);
2059 cpu_fprintf(f
, "cycles/out byte %0.1f\n",
2060 s
->code_out_len
? (double)tot
/ s
->code_out_len
: 0);
2063 cpu_fprintf(f
, " gen_interm time %0.1f%%\n",
2064 (double)s
->interm_time
/ tot
* 100.0);
2065 cpu_fprintf(f
, " gen_code time %0.1f%%\n",
2066 (double)s
->code_time
/ tot
* 100.0);
2067 cpu_fprintf(f
, "liveness/code time %0.1f%%\n",
2068 (double)s
->la_time
/ (s
->code_time
? s
->code_time
: 1) * 100.0);
2069 cpu_fprintf(f
, "cpu_restore count %" PRId64
"\n",
2071 cpu_fprintf(f
, " avg cycles %0.1f\n",
2072 s
->restore_count
? (double)s
->restore_time
/ s
->restore_count
: 0);
2074 extern void dump_op_count(void);
2079 void tcg_dump_info(FILE *f
,
2080 int (*cpu_fprintf
)(FILE *f
, const char *fmt
, ...))
2082 cpu_fprintf(f
, "[TCG profiler not compiled]\n");