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
42 #include "qemu-common.h"
44 /* Note: the long term plan is to reduce the dependancies on the QEMU
45 CPU definitions. Currently they are used for qemu_ld/st
47 #define NO_CPU_IO_DEFS
55 static void patch_reloc(uint8_t *code_ptr
, int type
,
56 tcg_target_long value
, tcg_target_long addend
);
58 TCGOpDef tcg_op_defs
[] = {
59 #define DEF(s, n, copy_size) { #s, 0, 0, n, n, 0, copy_size },
60 #define DEF2(s, iargs, oargs, cargs, flags) { #s, iargs, oargs, cargs, iargs + oargs + cargs, flags, 0 },
66 TCGRegSet tcg_target_available_regs
[2];
67 TCGRegSet tcg_target_call_clobber_regs
;
69 /* XXX: move that inside the context */
70 uint16_t *gen_opc_ptr
;
71 TCGArg
*gen_opparam_ptr
;
73 static inline void tcg_out8(TCGContext
*s
, uint8_t v
)
78 static inline void tcg_out16(TCGContext
*s
, uint16_t v
)
80 *(uint16_t *)s
->code_ptr
= v
;
84 static inline void tcg_out32(TCGContext
*s
, uint32_t v
)
86 *(uint32_t *)s
->code_ptr
= v
;
90 /* label relocation processing */
92 void tcg_out_reloc(TCGContext
*s
, uint8_t *code_ptr
, int type
,
93 int label_index
, long addend
)
98 l
= &s
->labels
[label_index
];
100 /* FIXME: This may break relocations on RISC targets that
101 modify instruction fields in place. The caller may not have
102 written the initial value. */
103 patch_reloc(code_ptr
, type
, l
->u
.value
, addend
);
105 /* add a new relocation entry */
106 r
= tcg_malloc(sizeof(TCGRelocation
));
110 r
->next
= l
->u
.first_reloc
;
111 l
->u
.first_reloc
= r
;
115 static void tcg_out_label(TCGContext
*s
, int label_index
,
116 tcg_target_long value
)
121 l
= &s
->labels
[label_index
];
124 r
= l
->u
.first_reloc
;
126 patch_reloc(r
->ptr
, r
->type
, value
, r
->addend
);
133 int gen_new_label(void)
135 TCGContext
*s
= &tcg_ctx
;
139 if (s
->nb_labels
>= TCG_MAX_LABELS
)
141 idx
= s
->nb_labels
++;
144 l
->u
.first_reloc
= NULL
;
148 #include "tcg-target.c"
150 /* pool based memory allocation */
151 void *tcg_malloc_internal(TCGContext
*s
, int size
)
156 if (size
> TCG_POOL_CHUNK_SIZE
) {
157 /* big malloc: insert a new pool (XXX: could optimize) */
158 p
= qemu_malloc(sizeof(TCGPool
) + size
);
161 s
->pool_current
->next
= p
;
164 p
->next
= s
->pool_current
;
174 pool_size
= TCG_POOL_CHUNK_SIZE
;
175 p
= qemu_malloc(sizeof(TCGPool
) + pool_size
);
179 s
->pool_current
->next
= p
;
188 s
->pool_cur
= p
->data
+ size
;
189 s
->pool_end
= p
->data
+ p
->size
;
193 void tcg_pool_reset(TCGContext
*s
)
195 s
->pool_cur
= s
->pool_end
= NULL
;
196 s
->pool_current
= NULL
;
199 /* free all the pool */
200 void tcg_pool_free(TCGContext
*s
)
204 for(p
= s
->pool_first
; p
!= NULL
; p
= p1
) {
208 s
->pool_first
= NULL
;
209 s
->pool_cur
= s
->pool_end
= NULL
;
212 void tcg_context_init(TCGContext
*s
)
214 int op
, total_args
, n
;
216 TCGArgConstraint
*args_ct
;
219 memset(s
, 0, sizeof(*s
));
220 s
->temps
= s
->static_temps
;
223 /* Count total number of arguments and allocate the corresponding
226 for(op
= 0; op
< NB_OPS
; op
++) {
227 def
= &tcg_op_defs
[op
];
228 n
= def
->nb_iargs
+ def
->nb_oargs
;
232 args_ct
= qemu_malloc(sizeof(TCGArgConstraint
) * total_args
);
233 sorted_args
= qemu_malloc(sizeof(int) * total_args
);
235 for(op
= 0; op
< NB_OPS
; op
++) {
236 def
= &tcg_op_defs
[op
];
237 def
->args_ct
= args_ct
;
238 def
->sorted_args
= sorted_args
;
239 n
= def
->nb_iargs
+ def
->nb_oargs
;
246 /* init global prologue and epilogue */
247 s
->code_buf
= code_gen_prologue
;
248 s
->code_ptr
= s
->code_buf
;
249 tcg_target_qemu_prologue(s
);
250 flush_icache_range((unsigned long)s
->code_buf
,
251 (unsigned long)s
->code_ptr
);
254 void tcg_set_frame(TCGContext
*s
, int reg
,
255 tcg_target_long start
, tcg_target_long size
)
257 s
->frame_start
= start
;
258 s
->frame_end
= start
+ size
;
262 void tcg_set_macro_func(TCGContext
*s
, TCGMacroFunc
*func
)
264 s
->macro_func
= func
;
267 void tcg_func_start(TCGContext
*s
)
270 s
->nb_temps
= s
->nb_globals
;
271 s
->labels
= tcg_malloc(sizeof(TCGLabel
) * TCG_MAX_LABELS
);
273 s
->current_frame_offset
= s
->frame_start
;
275 gen_opc_ptr
= gen_opc_buf
;
276 gen_opparam_ptr
= gen_opparam_buf
;
279 static inline void tcg_temp_alloc(TCGContext
*s
, int n
)
281 if (n
> TCG_MAX_TEMPS
)
285 TCGv
tcg_global_reg_new(TCGType type
, int reg
, const char *name
)
287 TCGContext
*s
= &tcg_ctx
;
291 #if TCG_TARGET_REG_BITS == 32
292 if (type
!= TCG_TYPE_I32
)
295 if (tcg_regset_test_reg(s
->reserved_regs
, reg
))
298 tcg_temp_alloc(s
, s
->nb_globals
+ 1);
299 ts
= &s
->temps
[s
->nb_globals
];
300 ts
->base_type
= type
;
304 ts
->val_type
= TEMP_VAL_REG
;
307 tcg_regset_set_reg(s
->reserved_regs
, reg
);
308 return MAKE_TCGV(idx
);
311 #if TCG_TARGET_REG_BITS == 32
312 /* temporary hack to avoid register shortage for tcg_qemu_st64() */
313 TCGv
tcg_global_reg2_new_hack(TCGType type
, int reg1
, int reg2
,
316 TCGContext
*s
= &tcg_ctx
;
321 if (type
!= TCG_TYPE_I64
)
324 tcg_temp_alloc(s
, s
->nb_globals
+ 2);
325 ts
= &s
->temps
[s
->nb_globals
];
326 ts
->base_type
= type
;
327 ts
->type
= TCG_TYPE_I32
;
330 ts
->val_type
= TEMP_VAL_REG
;
331 pstrcpy(buf
, sizeof(buf
), name
);
332 pstrcat(buf
, sizeof(buf
), "_0");
333 ts
->name
= strdup(buf
);
336 ts
->base_type
= type
;
337 ts
->type
= TCG_TYPE_I32
;
340 ts
->val_type
= TEMP_VAL_REG
;
341 pstrcpy(buf
, sizeof(buf
), name
);
342 pstrcat(buf
, sizeof(buf
), "_1");
343 ts
->name
= strdup(buf
);
346 return MAKE_TCGV(idx
);
350 TCGv
tcg_global_mem_new(TCGType type
, int reg
, tcg_target_long offset
,
353 TCGContext
*s
= &tcg_ctx
;
358 #if TCG_TARGET_REG_BITS == 32
359 if (type
== TCG_TYPE_I64
) {
361 tcg_temp_alloc(s
, s
->nb_globals
+ 1);
362 ts
= &s
->temps
[s
->nb_globals
];
363 ts
->base_type
= type
;
364 ts
->type
= TCG_TYPE_I32
;
366 ts
->mem_allocated
= 1;
368 #ifdef TCG_TARGET_WORDS_BIGENDIAN
369 ts
->mem_offset
= offset
+ 4;
371 ts
->mem_offset
= offset
;
373 ts
->val_type
= TEMP_VAL_MEM
;
374 pstrcpy(buf
, sizeof(buf
), name
);
375 pstrcat(buf
, sizeof(buf
), "_0");
376 ts
->name
= strdup(buf
);
379 ts
->base_type
= type
;
380 ts
->type
= TCG_TYPE_I32
;
382 ts
->mem_allocated
= 1;
384 #ifdef TCG_TARGET_WORDS_BIGENDIAN
385 ts
->mem_offset
= offset
;
387 ts
->mem_offset
= offset
+ 4;
389 ts
->val_type
= TEMP_VAL_MEM
;
390 pstrcpy(buf
, sizeof(buf
), name
);
391 pstrcat(buf
, sizeof(buf
), "_1");
392 ts
->name
= strdup(buf
);
398 tcg_temp_alloc(s
, s
->nb_globals
+ 1);
399 ts
= &s
->temps
[s
->nb_globals
];
400 ts
->base_type
= type
;
403 ts
->mem_allocated
= 1;
405 ts
->mem_offset
= offset
;
406 ts
->val_type
= TEMP_VAL_MEM
;
410 return MAKE_TCGV(idx
);
413 TCGv
tcg_temp_new(TCGType type
)
415 TCGContext
*s
= &tcg_ctx
;
420 #if TCG_TARGET_REG_BITS == 32
421 if (type
== TCG_TYPE_I64
) {
422 tcg_temp_alloc(s
, s
->nb_temps
+ 1);
423 ts
= &s
->temps
[s
->nb_temps
];
424 ts
->base_type
= type
;
425 ts
->type
= TCG_TYPE_I32
;
427 ts
->val_type
= TEMP_VAL_DEAD
;
428 ts
->mem_allocated
= 0;
431 ts
->base_type
= TCG_TYPE_I32
;
432 ts
->type
= TCG_TYPE_I32
;
433 ts
->val_type
= TEMP_VAL_DEAD
;
435 ts
->mem_allocated
= 0;
441 tcg_temp_alloc(s
, s
->nb_temps
+ 1);
442 ts
= &s
->temps
[s
->nb_temps
];
443 ts
->base_type
= type
;
446 ts
->val_type
= TEMP_VAL_DEAD
;
447 ts
->mem_allocated
= 0;
451 return MAKE_TCGV(idx
);
454 TCGv
tcg_const_i32(int32_t val
)
456 TCGContext
*s
= &tcg_ctx
;
461 tcg_temp_alloc(s
, idx
+ 1);
463 ts
->base_type
= ts
->type
= TCG_TYPE_I32
;
464 ts
->val_type
= TEMP_VAL_CONST
;
468 return MAKE_TCGV(idx
);
471 TCGv
tcg_const_i64(int64_t val
)
473 TCGContext
*s
= &tcg_ctx
;
478 #if TCG_TARGET_REG_BITS == 32
479 tcg_temp_alloc(s
, idx
+ 2);
481 ts
->base_type
= TCG_TYPE_I64
;
482 ts
->type
= TCG_TYPE_I32
;
483 ts
->val_type
= TEMP_VAL_CONST
;
487 ts
->base_type
= TCG_TYPE_I32
;
488 ts
->type
= TCG_TYPE_I32
;
489 ts
->val_type
= TEMP_VAL_CONST
;
494 tcg_temp_alloc(s
, idx
+ 1);
496 ts
->base_type
= ts
->type
= TCG_TYPE_I64
;
497 ts
->val_type
= TEMP_VAL_CONST
;
502 return MAKE_TCGV(idx
);
505 void tcg_register_helper(void *func
, const char *name
)
507 TCGContext
*s
= &tcg_ctx
;
509 if ((s
->nb_helpers
+ 1) > s
->allocated_helpers
) {
510 n
= s
->allocated_helpers
;
516 s
->helpers
= realloc(s
->helpers
, n
* sizeof(TCGHelperInfo
));
517 s
->allocated_helpers
= n
;
519 s
->helpers
[s
->nb_helpers
].func
= (tcg_target_ulong
)func
;
520 s
->helpers
[s
->nb_helpers
].name
= name
;
524 static inline TCGType
tcg_get_base_type(TCGContext
*s
, TCGv arg
)
526 return s
->temps
[GET_TCGV(arg
)].base_type
;
529 static void tcg_gen_call_internal(TCGContext
*s
, TCGv func
,
531 unsigned int nb_rets
, const TCGv
*rets
,
532 unsigned int nb_params
, const TCGv
*params
)
535 *gen_opc_ptr
++ = INDEX_op_call
;
536 *gen_opparam_ptr
++ = (nb_rets
<< 16) | (nb_params
+ 1);
537 for(i
= 0; i
< nb_rets
; i
++) {
538 *gen_opparam_ptr
++ = GET_TCGV(rets
[i
]);
540 for(i
= 0; i
< nb_params
; i
++) {
541 *gen_opparam_ptr
++ = GET_TCGV(params
[i
]);
543 *gen_opparam_ptr
++ = GET_TCGV(func
);
545 *gen_opparam_ptr
++ = flags
;
546 /* total parameters, needed to go backward in the instruction stream */
547 *gen_opparam_ptr
++ = 1 + nb_rets
+ nb_params
+ 3;
551 #if TCG_TARGET_REG_BITS < 64
552 /* Note: we convert the 64 bit args to 32 bit and do some alignment
553 and endian swap. Maybe it would be better to do the alignment
554 and endian swap in tcg_reg_alloc_call(). */
555 void tcg_gen_call(TCGContext
*s
, TCGv func
, unsigned int flags
,
556 unsigned int nb_rets
, const TCGv
*rets
,
557 unsigned int nb_params
, const TCGv
*args1
)
559 TCGv ret
, *args2
, rets_2
[2], arg
;
564 if (tcg_get_base_type(s
, ret
) == TCG_TYPE_I64
) {
566 #ifdef TCG_TARGET_WORDS_BIGENDIAN
567 rets_2
[0] = TCGV_HIGH(ret
);
571 rets_2
[1] = TCGV_HIGH(ret
);
576 args2
= alloca((nb_params
* 3) * sizeof(TCGv
));
578 call_type
= (flags
& TCG_CALL_TYPE_MASK
);
579 for(i
= 0; i
< nb_params
; i
++) {
581 if (tcg_get_base_type(s
, arg
) == TCG_TYPE_I64
) {
582 #ifdef TCG_TARGET_I386
583 /* REGPARM case: if the third parameter is 64 bit, it is
584 allocated on the stack */
585 if (j
== 2 && call_type
== TCG_CALL_TYPE_REGPARM
) {
586 call_type
= TCG_CALL_TYPE_REGPARM_2
;
587 flags
= (flags
& ~TCG_CALL_TYPE_MASK
) | call_type
;
590 args2
[j
++] = TCGV_HIGH(arg
);
592 #ifdef TCG_TARGET_CALL_ALIGN_ARGS
593 /* some targets want aligned 64 bit args */
595 args2
[j
++] = TCG_CALL_DUMMY_ARG
;
598 #ifdef TCG_TARGET_WORDS_BIGENDIAN
599 args2
[j
++] = TCGV_HIGH(arg
);
603 args2
[j
++] = TCGV_HIGH(arg
);
610 tcg_gen_call_internal(s
, func
, flags
,
611 nb_rets
, rets
, j
, args2
);
614 void tcg_gen_call(TCGContext
*s
, TCGv func
, unsigned int flags
,
615 unsigned int nb_rets
, const TCGv
*rets
,
616 unsigned int nb_params
, const TCGv
*args1
)
618 tcg_gen_call_internal(s
, func
, flags
,
619 nb_rets
, rets
, nb_params
, args1
);
623 #if TCG_TARGET_REG_BITS == 32
624 void tcg_gen_shifti_i64(TCGv ret
, TCGv arg1
,
625 int c
, int right
, int arith
)
628 tcg_gen_mov_i32(ret
, arg1
);
629 tcg_gen_mov_i32(TCGV_HIGH(ret
), TCGV_HIGH(arg1
));
630 } else if (c
>= 32) {
634 tcg_gen_sari_i32(ret
, TCGV_HIGH(arg1
), c
);
635 tcg_gen_sari_i32(TCGV_HIGH(ret
), TCGV_HIGH(arg1
), 31);
637 tcg_gen_shri_i32(ret
, TCGV_HIGH(arg1
), c
);
638 tcg_gen_movi_i32(TCGV_HIGH(ret
), 0);
641 tcg_gen_shli_i32(TCGV_HIGH(ret
), arg1
, c
);
642 tcg_gen_movi_i32(ret
, 0);
647 t0
= tcg_temp_new(TCG_TYPE_I32
);
648 t1
= tcg_temp_new(TCG_TYPE_I32
);
650 tcg_gen_shli_i32(t0
, TCGV_HIGH(arg1
), 32 - c
);
652 tcg_gen_sari_i32(t1
, TCGV_HIGH(arg1
), c
);
654 tcg_gen_shri_i32(t1
, TCGV_HIGH(arg1
), c
);
655 tcg_gen_shri_i32(ret
, arg1
, c
);
656 tcg_gen_or_i32(ret
, ret
, t0
);
657 tcg_gen_mov_i32(TCGV_HIGH(ret
), t1
);
659 tcg_gen_shri_i32(t0
, arg1
, 32 - c
);
660 /* Note: ret can be the same as arg1, so we use t1 */
661 tcg_gen_shli_i32(t1
, arg1
, c
);
662 tcg_gen_shli_i32(TCGV_HIGH(ret
), TCGV_HIGH(arg1
), c
);
663 tcg_gen_or_i32(TCGV_HIGH(ret
), TCGV_HIGH(ret
), t0
);
664 tcg_gen_mov_i32(ret
, t1
);
670 void tcg_reg_alloc_start(TCGContext
*s
)
674 for(i
= 0; i
< s
->nb_globals
; i
++) {
677 ts
->val_type
= TEMP_VAL_REG
;
679 ts
->val_type
= TEMP_VAL_MEM
;
682 for(i
= 0; i
< TCG_TARGET_NB_REGS
; i
++) {
683 s
->reg_to_temp
[i
] = -1;
687 static char *tcg_get_arg_str_idx(TCGContext
*s
, char *buf
, int buf_size
,
693 if (idx
< s
->nb_globals
) {
694 pstrcpy(buf
, buf_size
, ts
->name
);
696 if (ts
->val_type
== TEMP_VAL_CONST
) {
697 snprintf(buf
, buf_size
, "$0x%" TCG_PRIlx
, ts
->val
);
699 snprintf(buf
, buf_size
, "tmp%d", idx
- s
->nb_globals
);
705 char *tcg_get_arg_str(TCGContext
*s
, char *buf
, int buf_size
, TCGv arg
)
707 return tcg_get_arg_str_idx(s
, buf
, buf_size
, GET_TCGV(arg
));
710 /* find helper definition (XXX: inefficient) */
711 static TCGHelperInfo
*tcg_find_helper(TCGContext
*s
, tcg_target_ulong val
)
714 for(i
= 0; i
< s
->nb_helpers
; i
++) {
715 if (s
->helpers
[i
].func
== val
)
716 return &s
->helpers
[i
];
721 static const char *tcg_get_helper_str_idx(TCGContext
*s
, char *buf
, int buf_size
,
728 if (ts
->val_type
== TEMP_VAL_CONST
) {
729 /* find helper name (XXX: inefficient) */
730 th
= tcg_find_helper(s
, ts
->val
);
732 pstrcpy(buf
, buf_size
, "$");
733 pstrcat(buf
, buf_size
, th
->name
);
737 return tcg_get_arg_str_idx(s
, buf
, buf_size
, idx
);
741 void tcg_dump_ops(TCGContext
*s
, FILE *outfile
)
743 const uint16_t *opc_ptr
;
746 int c
, i
, k
, nb_oargs
, nb_iargs
, nb_cargs
, first_insn
;
751 opc_ptr
= gen_opc_buf
;
752 args
= gen_opparam_buf
;
753 while (opc_ptr
< gen_opc_ptr
) {
755 def
= &tcg_op_defs
[c
];
756 if (c
== INDEX_op_debug_insn_start
) {
758 #if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
759 pc
= ((uint64_t)args
[1] << 32) | args
[0];
764 fprintf(outfile
, "\n");
765 fprintf(outfile
, " ---- 0x%" PRIx64
, pc
);
767 nb_oargs
= def
->nb_oargs
;
768 nb_iargs
= def
->nb_iargs
;
769 nb_cargs
= def
->nb_cargs
;
770 } else if (c
== INDEX_op_call
) {
773 /* variable number of arguments */
775 nb_oargs
= arg
>> 16;
776 nb_iargs
= arg
& 0xffff;
777 nb_cargs
= def
->nb_cargs
;
779 fprintf(outfile
, " %s ", def
->name
);
782 fprintf(outfile
, "%s",
783 tcg_get_helper_str_idx(s
, buf
, sizeof(buf
), args
[nb_oargs
+ nb_iargs
- 1]));
785 fprintf(outfile
, ",$0x%" TCG_PRIlx
,
786 args
[nb_oargs
+ nb_iargs
]);
788 fprintf(outfile
, ",$%d", nb_oargs
);
789 for(i
= 0; i
< nb_oargs
; i
++) {
790 fprintf(outfile
, ",");
791 fprintf(outfile
, "%s",
792 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), args
[i
]));
794 for(i
= 0; i
< (nb_iargs
- 1); i
++) {
795 fprintf(outfile
, ",");
796 if (args
[nb_oargs
+ i
] == TCG_CALL_DUMMY_ARG
) {
797 fprintf(outfile
, "<dummy>");
799 fprintf(outfile
, "%s",
800 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), args
[nb_oargs
+ i
]));
804 fprintf(outfile
, " %s ", def
->name
);
805 if (c
== INDEX_op_nopn
) {
806 /* variable number of arguments */
811 nb_oargs
= def
->nb_oargs
;
812 nb_iargs
= def
->nb_iargs
;
813 nb_cargs
= def
->nb_cargs
;
817 for(i
= 0; i
< nb_oargs
; i
++) {
819 fprintf(outfile
, ",");
820 fprintf(outfile
, "%s",
821 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), args
[k
++]));
823 for(i
= 0; i
< nb_iargs
; i
++) {
825 fprintf(outfile
, ",");
826 fprintf(outfile
, "%s",
827 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), args
[k
++]));
829 for(i
= 0; i
< nb_cargs
; i
++) {
831 fprintf(outfile
, ",");
833 fprintf(outfile
, "$0x%" TCG_PRIlx
, arg
);
836 fprintf(outfile
, "\n");
837 args
+= nb_iargs
+ nb_oargs
+ nb_cargs
;
841 /* we give more priority to constraints with less registers */
842 static int get_constraint_priority(const TCGOpDef
*def
, int k
)
844 const TCGArgConstraint
*arg_ct
;
847 arg_ct
= &def
->args_ct
[k
];
848 if (arg_ct
->ct
& TCG_CT_ALIAS
) {
849 /* an alias is equivalent to a single register */
852 if (!(arg_ct
->ct
& TCG_CT_REG
))
855 for(i
= 0; i
< TCG_TARGET_NB_REGS
; i
++) {
856 if (tcg_regset_test_reg(arg_ct
->u
.regs
, i
))
860 return TCG_TARGET_NB_REGS
- n
+ 1;
863 /* sort from highest priority to lowest */
864 static void sort_constraints(TCGOpDef
*def
, int start
, int n
)
866 int i
, j
, p1
, p2
, tmp
;
868 for(i
= 0; i
< n
; i
++)
869 def
->sorted_args
[start
+ i
] = start
+ i
;
872 for(i
= 0; i
< n
- 1; i
++) {
873 for(j
= i
+ 1; j
< n
; j
++) {
874 p1
= get_constraint_priority(def
, def
->sorted_args
[start
+ i
]);
875 p2
= get_constraint_priority(def
, def
->sorted_args
[start
+ j
]);
877 tmp
= def
->sorted_args
[start
+ i
];
878 def
->sorted_args
[start
+ i
] = def
->sorted_args
[start
+ j
];
879 def
->sorted_args
[start
+ j
] = tmp
;
885 void tcg_add_target_add_op_defs(const TCGTargetOpDef
*tdefs
)
896 assert(op
>= 0 && op
< NB_OPS
);
897 def
= &tcg_op_defs
[op
];
898 nb_args
= def
->nb_iargs
+ def
->nb_oargs
;
899 for(i
= 0; i
< nb_args
; i
++) {
900 ct_str
= tdefs
->args_ct_str
[i
];
901 tcg_regset_clear(def
->args_ct
[i
].u
.regs
);
902 def
->args_ct
[i
].ct
= 0;
903 if (ct_str
[0] >= '0' && ct_str
[0] <= '9') {
905 oarg
= ct_str
[0] - '0';
906 assert(oarg
< def
->nb_oargs
);
907 assert(def
->args_ct
[oarg
].ct
& TCG_CT_REG
);
908 /* TCG_CT_ALIAS is for the output arguments. The input
909 argument is tagged with TCG_CT_IALIAS. */
910 def
->args_ct
[i
] = def
->args_ct
[oarg
];
911 def
->args_ct
[oarg
].ct
= TCG_CT_ALIAS
;
912 def
->args_ct
[oarg
].alias_index
= i
;
913 def
->args_ct
[i
].ct
|= TCG_CT_IALIAS
;
914 def
->args_ct
[i
].alias_index
= oarg
;
921 def
->args_ct
[i
].ct
|= TCG_CT_CONST
;
925 if (target_parse_constraint(&def
->args_ct
[i
], &ct_str
) < 0) {
926 fprintf(stderr
, "Invalid constraint '%s' for arg %d of operation '%s'\n",
927 ct_str
, i
, def
->name
);
935 /* sort the constraints (XXX: this is just an heuristic) */
936 sort_constraints(def
, 0, def
->nb_oargs
);
937 sort_constraints(def
, def
->nb_oargs
, def
->nb_iargs
);
943 printf("%s: sorted=", def
->name
);
944 for(i
= 0; i
< def
->nb_oargs
+ def
->nb_iargs
; i
++)
945 printf(" %d", def
->sorted_args
[i
]);
954 #ifdef USE_LIVENESS_ANALYSIS
956 /* set a nop for an operation using 'nb_args' */
957 static inline void tcg_set_nop(TCGContext
*s
, uint16_t *opc_ptr
,
958 TCGArg
*args
, int nb_args
)
961 *opc_ptr
= INDEX_op_nop
;
963 *opc_ptr
= INDEX_op_nopn
;
965 args
[nb_args
- 1] = nb_args
;
969 /* liveness analysis: end of basic block: globals are live, temps are dead */
970 static inline void tcg_la_bb_end(TCGContext
*s
, uint8_t *dead_temps
)
972 memset(dead_temps
, 0, s
->nb_globals
);
973 memset(dead_temps
+ s
->nb_globals
, 1, s
->nb_temps
- s
->nb_globals
);
976 /* Liveness analysis : update the opc_dead_iargs array to tell if a
977 given input arguments is dead. Instructions updating dead
978 temporaries are removed. */
979 void tcg_liveness_analysis(TCGContext
*s
)
981 int i
, op_index
, op
, nb_args
, nb_iargs
, nb_oargs
, arg
, nb_ops
;
985 unsigned int dead_iargs
;
987 gen_opc_ptr
++; /* skip end */
989 nb_ops
= gen_opc_ptr
- gen_opc_buf
;
991 /* XXX: make it really dynamic */
992 s
->op_dead_iargs
= tcg_malloc(OPC_BUF_SIZE
* sizeof(uint16_t));
994 dead_temps
= tcg_malloc(s
->nb_temps
);
995 memset(dead_temps
, 1, s
->nb_temps
);
997 args
= gen_opparam_ptr
;
998 op_index
= nb_ops
- 1;
999 while (op_index
>= 0) {
1000 op
= gen_opc_buf
[op_index
];
1001 def
= &tcg_op_defs
[op
];
1009 nb_iargs
= args
[0] & 0xffff;
1010 nb_oargs
= args
[0] >> 16;
1012 call_flags
= args
[nb_oargs
+ nb_iargs
];
1014 /* pure functions can be removed if their result is not
1016 if (call_flags
& TCG_CALL_PURE
) {
1017 for(i
= 0; i
< nb_oargs
; i
++) {
1019 if (!dead_temps
[arg
])
1020 goto do_not_remove_call
;
1022 tcg_set_nop(s
, gen_opc_buf
+ op_index
,
1027 /* output args are dead */
1028 for(i
= 0; i
< nb_oargs
; i
++) {
1030 dead_temps
[arg
] = 1;
1033 /* globals are live (they may be used by the call) */
1034 memset(dead_temps
, 0, s
->nb_globals
);
1036 /* input args are live */
1038 for(i
= 0; i
< nb_iargs
; i
++) {
1039 arg
= args
[i
+ nb_oargs
];
1040 if (arg
!= TCG_CALL_DUMMY_ARG
) {
1041 if (dead_temps
[arg
]) {
1042 dead_iargs
|= (1 << i
);
1044 dead_temps
[arg
] = 0;
1047 s
->op_dead_iargs
[op_index
] = dead_iargs
;
1052 case INDEX_op_set_label
:
1054 /* mark end of basic block */
1055 tcg_la_bb_end(s
, dead_temps
);
1057 case INDEX_op_debug_insn_start
:
1058 args
-= def
->nb_args
;
1064 case INDEX_op_discard
:
1066 /* mark the temporary as dead */
1067 dead_temps
[args
[0]] = 1;
1069 case INDEX_op_macro_2
:
1071 int dead_args
[2], macro_id
;
1072 int saved_op_index
, saved_arg_index
;
1073 int macro_op_index
, macro_arg_index
;
1074 int macro_end_op_index
, macro_end_arg_index
;
1079 dead_args
[0] = dead_temps
[args
[0]];
1080 dead_args
[1] = dead_temps
[args
[1]];
1083 /* call the macro function which generate code
1084 depending on the live outputs */
1085 saved_op_index
= op_index
;
1086 saved_arg_index
= args
- gen_opparam_buf
;
1088 /* add a macro start instruction */
1089 *gen_opc_ptr
++ = INDEX_op_macro_start
;
1090 *gen_opparam_ptr
++ = saved_op_index
;
1091 *gen_opparam_ptr
++ = saved_arg_index
;
1093 macro_op_index
= gen_opc_ptr
- gen_opc_buf
;
1094 macro_arg_index
= gen_opparam_ptr
- gen_opparam_buf
;
1096 last_nb_temps
= s
->nb_temps
;
1098 s
->macro_func(s
, macro_id
, dead_args
);
1100 /* realloc temp info (XXX: make it faster) */
1101 if (s
->nb_temps
> last_nb_temps
) {
1102 uint8_t *new_dead_temps
;
1104 new_dead_temps
= tcg_malloc(s
->nb_temps
);
1105 memcpy(new_dead_temps
, dead_temps
, last_nb_temps
);
1106 memset(new_dead_temps
+ last_nb_temps
, 1,
1107 s
->nb_temps
- last_nb_temps
);
1108 dead_temps
= new_dead_temps
;
1111 macro_end_op_index
= gen_opc_ptr
- gen_opc_buf
;
1112 macro_end_arg_index
= gen_opparam_ptr
- gen_opparam_buf
;
1114 /* end of macro: add a goto to the next instruction */
1115 *gen_opc_ptr
++ = INDEX_op_macro_end
;
1116 *gen_opparam_ptr
++ = op_index
+ 1;
1117 *gen_opparam_ptr
++ = saved_arg_index
+ nb_args
;
1119 /* modify the macro operation to be a macro_goto */
1120 gen_opc_buf
[op_index
] = INDEX_op_macro_goto
;
1121 args
[0] = macro_op_index
;
1122 args
[1] = macro_arg_index
;
1123 args
[2] = 0; /* dummy third arg to match the
1126 /* set the next instruction to the end of the macro */
1127 op_index
= macro_end_op_index
;
1128 args
= macro_end_arg_index
+ gen_opparam_buf
;
1131 case INDEX_op_macro_start
:
1134 args
= gen_opparam_buf
+ args
[1];
1136 case INDEX_op_macro_goto
:
1137 case INDEX_op_macro_end
:
1138 tcg_abort(); /* should never happen in liveness analysis */
1141 /* XXX: optimize by hardcoding common cases (e.g. triadic ops) */
1143 if (op
> INDEX_op_end
) {
1144 args
-= def
->nb_args
;
1145 nb_iargs
= def
->nb_iargs
;
1146 nb_oargs
= def
->nb_oargs
;
1148 /* Test if the operation can be removed because all
1149 its outputs are dead. We assume that nb_oargs == 0
1150 implies side effects */
1151 if (!(def
->flags
& TCG_OPF_SIDE_EFFECTS
) && nb_oargs
!= 0) {
1152 for(i
= 0; i
< nb_oargs
; i
++) {
1154 if (!dead_temps
[arg
])
1157 tcg_set_nop(s
, gen_opc_buf
+ op_index
, args
, def
->nb_args
);
1158 #ifdef CONFIG_PROFILER
1164 /* output args are dead */
1165 for(i
= 0; i
< nb_oargs
; i
++) {
1167 dead_temps
[arg
] = 1;
1170 /* if end of basic block, update */
1171 if (def
->flags
& TCG_OPF_BB_END
) {
1172 tcg_la_bb_end(s
, dead_temps
);
1173 } else if (def
->flags
& TCG_OPF_CALL_CLOBBER
) {
1174 /* globals are live */
1175 memset(dead_temps
, 0, s
->nb_globals
);
1178 /* input args are live */
1180 for(i
= 0; i
< nb_iargs
; i
++) {
1181 arg
= args
[i
+ nb_oargs
];
1182 if (dead_temps
[arg
]) {
1183 dead_iargs
|= (1 << i
);
1185 dead_temps
[arg
] = 0;
1187 s
->op_dead_iargs
[op_index
] = dead_iargs
;
1190 /* legacy dyngen operations */
1191 args
-= def
->nb_args
;
1192 /* mark end of basic block */
1193 tcg_la_bb_end(s
, dead_temps
);
1200 if (args
!= gen_opparam_buf
)
1204 /* dummy liveness analysis */
1205 void tcg_liveness_analysis(TCGContext
*s
)
1208 nb_ops
= gen_opc_ptr
- gen_opc_buf
;
1210 s
->op_dead_iargs
= tcg_malloc(nb_ops
* sizeof(uint16_t));
1211 memset(s
->op_dead_iargs
, 0, nb_ops
* sizeof(uint16_t));
1216 static void dump_regs(TCGContext
*s
)
1222 for(i
= 0; i
< s
->nb_temps
; i
++) {
1224 printf(" %10s: ", tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), i
));
1225 switch(ts
->val_type
) {
1227 printf("%s", tcg_target_reg_names
[ts
->reg
]);
1230 printf("%d(%s)", (int)ts
->mem_offset
, tcg_target_reg_names
[ts
->mem_reg
]);
1232 case TEMP_VAL_CONST
:
1233 printf("$0x%" TCG_PRIlx
, ts
->val
);
1245 for(i
= 0; i
< TCG_TARGET_NB_REGS
; i
++) {
1246 if (s
->reg_to_temp
[i
] >= 0) {
1248 tcg_target_reg_names
[i
],
1249 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), s
->reg_to_temp
[i
]));
1254 static void check_regs(TCGContext
*s
)
1260 for(reg
= 0; reg
< TCG_TARGET_NB_REGS
; reg
++) {
1261 k
= s
->reg_to_temp
[reg
];
1264 if (ts
->val_type
!= TEMP_VAL_REG
||
1266 printf("Inconsistency for register %s:\n",
1267 tcg_target_reg_names
[reg
]);
1272 for(k
= 0; k
< s
->nb_temps
; k
++) {
1274 if (ts
->val_type
== TEMP_VAL_REG
&&
1276 s
->reg_to_temp
[ts
->reg
] != k
) {
1277 printf("Inconsistency for temp %s:\n",
1278 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), k
));
1280 printf("reg state:\n");
1284 if (ts
->val_type
== TEMP_VAL_CONST
&& k
< s
->nb_globals
) {
1285 printf("constant forbidden in global %s\n",
1286 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), k
));
1293 static void temp_allocate_frame(TCGContext
*s
, int temp
)
1296 ts
= &s
->temps
[temp
];
1297 s
->current_frame_offset
= (s
->current_frame_offset
+ sizeof(tcg_target_long
) - 1) & ~(sizeof(tcg_target_long
) - 1);
1298 if (s
->current_frame_offset
+ sizeof(tcg_target_long
) > s
->frame_end
)
1300 ts
->mem_offset
= s
->current_frame_offset
;
1301 ts
->mem_reg
= s
->frame_reg
;
1302 ts
->mem_allocated
= 1;
1303 s
->current_frame_offset
+= sizeof(tcg_target_long
);
1306 /* free register 'reg' by spilling the corresponding temporary if necessary */
1307 static void tcg_reg_free(TCGContext
*s
, int reg
)
1312 temp
= s
->reg_to_temp
[reg
];
1314 ts
= &s
->temps
[temp
];
1315 assert(ts
->val_type
== TEMP_VAL_REG
);
1316 if (!ts
->mem_coherent
) {
1317 if (!ts
->mem_allocated
)
1318 temp_allocate_frame(s
, temp
);
1319 tcg_out_st(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
1321 ts
->val_type
= TEMP_VAL_MEM
;
1322 s
->reg_to_temp
[reg
] = -1;
1326 /* Allocate a register belonging to reg1 & ~reg2 */
1327 static int tcg_reg_alloc(TCGContext
*s
, TCGRegSet reg1
, TCGRegSet reg2
)
1332 tcg_regset_andnot(reg_ct
, reg1
, reg2
);
1334 /* first try free registers */
1335 for(i
= 0; i
< ARRAY_SIZE(tcg_target_reg_alloc_order
); i
++) {
1336 reg
= tcg_target_reg_alloc_order
[i
];
1337 if (tcg_regset_test_reg(reg_ct
, reg
) && s
->reg_to_temp
[reg
] == -1)
1341 /* XXX: do better spill choice */
1342 for(i
= 0; i
< ARRAY_SIZE(tcg_target_reg_alloc_order
); i
++) {
1343 reg
= tcg_target_reg_alloc_order
[i
];
1344 if (tcg_regset_test_reg(reg_ct
, reg
)) {
1345 tcg_reg_free(s
, reg
);
1353 /* save globals to their cannonical location and assume they can be
1354 modified be the following code. */
1355 static void save_globals(TCGContext
*s
)
1360 for(i
= 0; i
< s
->nb_globals
; i
++) {
1362 if (!ts
->fixed_reg
) {
1363 if (ts
->val_type
== TEMP_VAL_REG
) {
1364 tcg_reg_free(s
, ts
->reg
);
1365 } else if (ts
->val_type
== TEMP_VAL_DEAD
) {
1366 ts
->val_type
= TEMP_VAL_MEM
;
1372 /* at the end of a basic block, we assume all temporaries are dead and
1373 all globals are stored at their canonical location */
1374 /* XXX: optimize by handling constants in another array ? */
1375 void tcg_reg_alloc_bb_end(TCGContext
*s
)
1382 for(i
= s
->nb_globals
; i
< s
->nb_temps
; i
++) {
1384 if (ts
->val_type
!= TEMP_VAL_CONST
) {
1385 if (ts
->val_type
== TEMP_VAL_REG
) {
1386 s
->reg_to_temp
[ts
->reg
] = -1;
1388 ts
->val_type
= TEMP_VAL_DEAD
;
1393 #define IS_DEAD_IARG(n) ((dead_iargs >> (n)) & 1)
1395 static void tcg_reg_alloc_mov(TCGContext
*s
, const TCGOpDef
*def
,
1397 unsigned int dead_iargs
)
1401 const TCGArgConstraint
*arg_ct
;
1403 ots
= &s
->temps
[args
[0]];
1404 ts
= &s
->temps
[args
[1]];
1405 arg_ct
= &def
->args_ct
[0];
1407 if (ts
->val_type
== TEMP_VAL_REG
) {
1408 if (IS_DEAD_IARG(0) && !ts
->fixed_reg
&& !ots
->fixed_reg
) {
1409 /* the mov can be suppressed */
1410 if (ots
->val_type
== TEMP_VAL_REG
)
1411 s
->reg_to_temp
[ots
->reg
] = -1;
1413 s
->reg_to_temp
[reg
] = -1;
1414 ts
->val_type
= TEMP_VAL_DEAD
;
1416 if (ots
->val_type
== TEMP_VAL_REG
) {
1419 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, s
->reserved_regs
);
1421 if (ts
->reg
!= reg
) {
1422 tcg_out_mov(s
, reg
, ts
->reg
);
1425 } else if (ts
->val_type
== TEMP_VAL_MEM
) {
1426 if (ots
->val_type
== TEMP_VAL_REG
) {
1429 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, s
->reserved_regs
);
1431 tcg_out_ld(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
1432 } else if (ts
->val_type
== TEMP_VAL_CONST
) {
1433 if (ots
->val_type
== TEMP_VAL_REG
) {
1436 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, s
->reserved_regs
);
1438 tcg_out_movi(s
, ots
->type
, reg
, ts
->val
);
1442 s
->reg_to_temp
[reg
] = args
[0];
1444 ots
->val_type
= TEMP_VAL_REG
;
1445 ots
->mem_coherent
= 0;
1448 static void tcg_reg_alloc_op(TCGContext
*s
,
1449 const TCGOpDef
*def
, int opc
,
1451 unsigned int dead_iargs
)
1453 TCGRegSet allocated_regs
;
1454 int i
, k
, nb_iargs
, nb_oargs
, reg
;
1456 const TCGArgConstraint
*arg_ct
;
1458 TCGArg new_args
[TCG_MAX_OP_ARGS
];
1459 int const_args
[TCG_MAX_OP_ARGS
];
1461 nb_oargs
= def
->nb_oargs
;
1462 nb_iargs
= def
->nb_iargs
;
1464 /* copy constants */
1465 memcpy(new_args
+ nb_oargs
+ nb_iargs
,
1466 args
+ nb_oargs
+ nb_iargs
,
1467 sizeof(TCGArg
) * def
->nb_cargs
);
1469 /* satisfy input constraints */
1470 tcg_regset_set(allocated_regs
, s
->reserved_regs
);
1471 for(k
= 0; k
< nb_iargs
; k
++) {
1472 i
= def
->sorted_args
[nb_oargs
+ k
];
1474 arg_ct
= &def
->args_ct
[i
];
1475 ts
= &s
->temps
[arg
];
1476 if (ts
->val_type
== TEMP_VAL_MEM
) {
1477 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1478 tcg_out_ld(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
1479 ts
->val_type
= TEMP_VAL_REG
;
1481 ts
->mem_coherent
= 1;
1482 s
->reg_to_temp
[reg
] = arg
;
1483 } else if (ts
->val_type
== TEMP_VAL_CONST
) {
1484 if (tcg_target_const_match(ts
->val
, arg_ct
)) {
1485 /* constant is OK for instruction */
1487 new_args
[i
] = ts
->val
;
1490 /* need to move to a register*/
1491 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1492 tcg_out_movi(s
, ts
->type
, reg
, ts
->val
);
1496 assert(ts
->val_type
== TEMP_VAL_REG
);
1497 if (arg_ct
->ct
& TCG_CT_IALIAS
) {
1498 if (ts
->fixed_reg
) {
1499 /* if fixed register, we must allocate a new register
1500 if the alias is not the same register */
1501 if (arg
!= args
[arg_ct
->alias_index
])
1502 goto allocate_in_reg
;
1504 /* if the input is aliased to an output and if it is
1505 not dead after the instruction, we must allocate
1506 a new register and move it */
1507 if (!IS_DEAD_IARG(i
- nb_oargs
))
1508 goto allocate_in_reg
;
1512 if (tcg_regset_test_reg(arg_ct
->u
.regs
, reg
)) {
1513 /* nothing to do : the constraint is satisfied */
1516 /* allocate a new register matching the constraint
1517 and move the temporary register into it */
1518 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1519 tcg_out_mov(s
, reg
, ts
->reg
);
1524 tcg_regset_set_reg(allocated_regs
, reg
);
1528 /* mark dead temporaries and free the associated registers */
1529 for(i
= 0; i
< nb_iargs
; i
++) {
1530 arg
= args
[nb_oargs
+ i
];
1531 if (IS_DEAD_IARG(i
)) {
1532 ts
= &s
->temps
[arg
];
1533 if (ts
->val_type
!= TEMP_VAL_CONST
&& !ts
->fixed_reg
) {
1534 if (ts
->val_type
== TEMP_VAL_REG
)
1535 s
->reg_to_temp
[ts
->reg
] = -1;
1536 ts
->val_type
= TEMP_VAL_DEAD
;
1541 if (def
->flags
& TCG_OPF_CALL_CLOBBER
) {
1542 /* XXX: permit generic clobber register list ? */
1543 for(reg
= 0; reg
< TCG_TARGET_NB_REGS
; reg
++) {
1544 if (tcg_regset_test_reg(tcg_target_call_clobber_regs
, reg
)) {
1545 tcg_reg_free(s
, reg
);
1548 /* XXX: for load/store we could do that only for the slow path
1549 (i.e. when a memory callback is called) */
1551 /* store globals and free associated registers (we assume the insn
1552 can modify any global. */
1556 /* satisfy the output constraints */
1557 tcg_regset_set(allocated_regs
, s
->reserved_regs
);
1558 for(k
= 0; k
< nb_oargs
; k
++) {
1559 i
= def
->sorted_args
[k
];
1561 arg_ct
= &def
->args_ct
[i
];
1562 ts
= &s
->temps
[arg
];
1563 if (arg_ct
->ct
& TCG_CT_ALIAS
) {
1564 reg
= new_args
[arg_ct
->alias_index
];
1566 /* if fixed register, we try to use it */
1568 if (ts
->fixed_reg
&&
1569 tcg_regset_test_reg(arg_ct
->u
.regs
, reg
)) {
1572 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1574 tcg_regset_set_reg(allocated_regs
, reg
);
1575 /* if a fixed register is used, then a move will be done afterwards */
1576 if (!ts
->fixed_reg
) {
1577 if (ts
->val_type
== TEMP_VAL_REG
)
1578 s
->reg_to_temp
[ts
->reg
] = -1;
1579 ts
->val_type
= TEMP_VAL_REG
;
1581 /* temp value is modified, so the value kept in memory is
1582 potentially not the same */
1583 ts
->mem_coherent
= 0;
1584 s
->reg_to_temp
[reg
] = arg
;
1590 if (def
->flags
& TCG_OPF_BB_END
)
1591 tcg_reg_alloc_bb_end(s
);
1593 /* emit instruction */
1594 tcg_out_op(s
, opc
, new_args
, const_args
);
1596 /* move the outputs in the correct register if needed */
1597 for(i
= 0; i
< nb_oargs
; i
++) {
1598 ts
= &s
->temps
[args
[i
]];
1600 if (ts
->fixed_reg
&& ts
->reg
!= reg
) {
1601 tcg_out_mov(s
, ts
->reg
, reg
);
1606 #ifdef TCG_TARGET_STACK_GROWSUP
1607 #define STACK_DIR(x) (-(x))
1609 #define STACK_DIR(x) (x)
1612 static int tcg_reg_alloc_call(TCGContext
*s
, const TCGOpDef
*def
,
1613 int opc
, const TCGArg
*args
,
1614 unsigned int dead_iargs
)
1616 int nb_iargs
, nb_oargs
, flags
, nb_regs
, i
, reg
, nb_params
;
1617 TCGArg arg
, func_arg
;
1619 tcg_target_long stack_offset
, call_stack_size
, func_addr
;
1620 int const_func_arg
, allocate_args
;
1621 TCGRegSet allocated_regs
;
1622 const TCGArgConstraint
*arg_ct
;
1626 nb_oargs
= arg
>> 16;
1627 nb_iargs
= arg
& 0xffff;
1628 nb_params
= nb_iargs
- 1;
1630 flags
= args
[nb_oargs
+ nb_iargs
];
1632 nb_regs
= tcg_target_get_call_iarg_regs_count(flags
);
1633 if (nb_regs
> nb_params
)
1634 nb_regs
= nb_params
;
1636 /* assign stack slots first */
1637 /* XXX: preallocate call stack */
1638 call_stack_size
= (nb_params
- nb_regs
) * sizeof(tcg_target_long
);
1639 call_stack_size
= (call_stack_size
+ TCG_TARGET_STACK_ALIGN
- 1) &
1640 ~(TCG_TARGET_STACK_ALIGN
- 1);
1641 allocate_args
= (call_stack_size
> TCG_STATIC_CALL_ARGS_SIZE
);
1642 if (allocate_args
) {
1643 tcg_out_addi(s
, TCG_REG_CALL_STACK
, -STACK_DIR(call_stack_size
));
1646 stack_offset
= TCG_TARGET_CALL_STACK_OFFSET
;
1647 for(i
= nb_regs
; i
< nb_params
; i
++) {
1648 arg
= args
[nb_oargs
+ i
];
1649 #ifdef TCG_TARGET_STACK_GROWSUP
1650 stack_offset
-= sizeof(tcg_target_long
);
1652 if (arg
!= TCG_CALL_DUMMY_ARG
) {
1653 ts
= &s
->temps
[arg
];
1654 if (ts
->val_type
== TEMP_VAL_REG
) {
1655 tcg_out_st(s
, ts
->type
, ts
->reg
, TCG_REG_CALL_STACK
, stack_offset
);
1656 } else if (ts
->val_type
== TEMP_VAL_MEM
) {
1657 reg
= tcg_reg_alloc(s
, tcg_target_available_regs
[ts
->type
],
1659 /* XXX: not correct if reading values from the stack */
1660 tcg_out_ld(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
1661 tcg_out_st(s
, ts
->type
, reg
, TCG_REG_CALL_STACK
, stack_offset
);
1662 } else if (ts
->val_type
== TEMP_VAL_CONST
) {
1663 reg
= tcg_reg_alloc(s
, tcg_target_available_regs
[ts
->type
],
1665 /* XXX: sign extend may be needed on some targets */
1666 tcg_out_movi(s
, ts
->type
, reg
, ts
->val
);
1667 tcg_out_st(s
, ts
->type
, reg
, TCG_REG_CALL_STACK
, stack_offset
);
1672 #ifndef TCG_TARGET_STACK_GROWSUP
1673 stack_offset
+= sizeof(tcg_target_long
);
1677 /* assign input registers */
1678 tcg_regset_set(allocated_regs
, s
->reserved_regs
);
1679 for(i
= 0; i
< nb_regs
; i
++) {
1680 arg
= args
[nb_oargs
+ i
];
1681 if (arg
!= TCG_CALL_DUMMY_ARG
) {
1682 ts
= &s
->temps
[arg
];
1683 reg
= tcg_target_call_iarg_regs
[i
];
1684 tcg_reg_free(s
, reg
);
1685 if (ts
->val_type
== TEMP_VAL_REG
) {
1686 if (ts
->reg
!= reg
) {
1687 tcg_out_mov(s
, reg
, ts
->reg
);
1689 } else if (ts
->val_type
== TEMP_VAL_MEM
) {
1690 tcg_out_ld(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
1691 } else if (ts
->val_type
== TEMP_VAL_CONST
) {
1692 /* XXX: sign extend ? */
1693 tcg_out_movi(s
, ts
->type
, reg
, ts
->val
);
1697 tcg_regset_set_reg(allocated_regs
, reg
);
1701 /* assign function address */
1702 func_arg
= args
[nb_oargs
+ nb_iargs
- 1];
1703 arg_ct
= &def
->args_ct
[0];
1704 ts
= &s
->temps
[func_arg
];
1705 func_addr
= ts
->val
;
1707 if (ts
->val_type
== TEMP_VAL_MEM
) {
1708 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1709 tcg_out_ld(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
1711 } else if (ts
->val_type
== TEMP_VAL_REG
) {
1713 if (!tcg_regset_test_reg(arg_ct
->u
.regs
, reg
)) {
1714 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1715 tcg_out_mov(s
, reg
, ts
->reg
);
1718 } else if (ts
->val_type
== TEMP_VAL_CONST
) {
1719 if (tcg_target_const_match(func_addr
, arg_ct
)) {
1721 func_arg
= func_addr
;
1723 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
1724 tcg_out_movi(s
, ts
->type
, reg
, func_addr
);
1731 /* mark dead temporaries and free the associated registers */
1732 for(i
= 0; i
< nb_iargs
; i
++) {
1733 arg
= args
[nb_oargs
+ i
];
1734 if (IS_DEAD_IARG(i
)) {
1735 ts
= &s
->temps
[arg
];
1736 if (ts
->val_type
!= TEMP_VAL_CONST
&& !ts
->fixed_reg
) {
1737 if (ts
->val_type
== TEMP_VAL_REG
)
1738 s
->reg_to_temp
[ts
->reg
] = -1;
1739 ts
->val_type
= TEMP_VAL_DEAD
;
1744 /* clobber call registers */
1745 for(reg
= 0; reg
< TCG_TARGET_NB_REGS
; reg
++) {
1746 if (tcg_regset_test_reg(tcg_target_call_clobber_regs
, reg
)) {
1747 tcg_reg_free(s
, reg
);
1751 /* store globals and free associated registers (we assume the call
1752 can modify any global. */
1755 tcg_out_op(s
, opc
, &func_arg
, &const_func_arg
);
1757 if (allocate_args
) {
1758 tcg_out_addi(s
, TCG_REG_CALL_STACK
, STACK_DIR(call_stack_size
));
1761 /* assign output registers and emit moves if needed */
1762 for(i
= 0; i
< nb_oargs
; i
++) {
1764 ts
= &s
->temps
[arg
];
1765 reg
= tcg_target_call_oarg_regs
[i
];
1766 tcg_reg_free(s
, reg
);
1767 if (ts
->fixed_reg
) {
1768 if (ts
->reg
!= reg
) {
1769 tcg_out_mov(s
, ts
->reg
, reg
);
1772 if (ts
->val_type
== TEMP_VAL_REG
)
1773 s
->reg_to_temp
[ts
->reg
] = -1;
1774 ts
->val_type
= TEMP_VAL_REG
;
1776 ts
->mem_coherent
= 0;
1777 s
->reg_to_temp
[reg
] = arg
;
1781 return nb_iargs
+ nb_oargs
+ def
->nb_cargs
+ 1;
1784 #ifdef CONFIG_PROFILER
1786 static int64_t dyngen_table_op_count
[NB_OPS
];
1788 void dump_op_count(void)
1792 f
= fopen("/tmp/op1.log", "w");
1793 for(i
= 0; i
< INDEX_op_end
; i
++) {
1794 fprintf(f
, "%s %" PRId64
"\n", tcg_op_defs
[i
].name
, dyngen_table_op_count
[i
]);
1797 f
= fopen("/tmp/op2.log", "w");
1798 for(i
= INDEX_op_end
; i
< NB_OPS
; i
++) {
1799 fprintf(f
, "%s %" PRId64
"\n", tcg_op_defs
[i
].name
, dyngen_table_op_count
[i
]);
1806 static inline int tcg_gen_code_common(TCGContext
*s
, uint8_t *gen_code_buf
,
1809 int opc
, op_index
, macro_op_index
;
1810 const TCGOpDef
*def
;
1811 unsigned int dead_iargs
;
1815 if (unlikely(loglevel
& CPU_LOG_TB_OP
)) {
1816 fprintf(logfile
, "OP:\n");
1817 tcg_dump_ops(s
, logfile
);
1818 fprintf(logfile
, "\n");
1822 #ifdef CONFIG_PROFILER
1823 s
->la_time
-= profile_getclock();
1825 tcg_liveness_analysis(s
);
1826 #ifdef CONFIG_PROFILER
1827 s
->la_time
+= profile_getclock();
1831 if (unlikely(loglevel
& CPU_LOG_TB_OP_OPT
)) {
1832 fprintf(logfile
, "OP after la:\n");
1833 tcg_dump_ops(s
, logfile
);
1834 fprintf(logfile
, "\n");
1838 tcg_reg_alloc_start(s
);
1840 s
->code_buf
= gen_code_buf
;
1841 s
->code_ptr
= gen_code_buf
;
1843 macro_op_index
= -1;
1844 args
= gen_opparam_buf
;
1848 opc
= gen_opc_buf
[op_index
];
1849 #ifdef CONFIG_PROFILER
1850 dyngen_table_op_count
[opc
]++;
1852 def
= &tcg_op_defs
[opc
];
1854 printf("%s: %d %d %d\n", def
->name
,
1855 def
->nb_oargs
, def
->nb_iargs
, def
->nb_cargs
);
1859 case INDEX_op_mov_i32
:
1860 #if TCG_TARGET_REG_BITS == 64
1861 case INDEX_op_mov_i64
:
1863 dead_iargs
= s
->op_dead_iargs
[op_index
];
1864 tcg_reg_alloc_mov(s
, def
, args
, dead_iargs
);
1866 case INDEX_op_debug_insn_start
:
1867 /* debug instruction */
1877 case INDEX_op_discard
:
1880 ts
= &s
->temps
[args
[0]];
1881 /* mark the temporary as dead */
1882 if (ts
->val_type
!= TEMP_VAL_CONST
&& !ts
->fixed_reg
) {
1883 if (ts
->val_type
== TEMP_VAL_REG
)
1884 s
->reg_to_temp
[ts
->reg
] = -1;
1885 ts
->val_type
= TEMP_VAL_DEAD
;
1889 case INDEX_op_macro_goto
:
1890 macro_op_index
= op_index
; /* only used for exceptions */
1891 op_index
= args
[0] - 1;
1892 args
= gen_opparam_buf
+ args
[1];
1894 case INDEX_op_macro_end
:
1895 macro_op_index
= -1; /* only used for exceptions */
1896 op_index
= args
[0] - 1;
1897 args
= gen_opparam_buf
+ args
[1];
1899 case INDEX_op_macro_start
:
1900 /* must never happen here */
1902 case INDEX_op_set_label
:
1903 tcg_reg_alloc_bb_end(s
);
1904 tcg_out_label(s
, args
[0], (long)s
->code_ptr
);
1907 dead_iargs
= s
->op_dead_iargs
[op_index
];
1908 args
+= tcg_reg_alloc_call(s
, def
, opc
, args
, dead_iargs
);
1913 #ifdef CONFIG_DYNGEN_OP
1914 case 0 ... INDEX_op_end
- 1:
1915 /* legacy dyngen ops */
1916 #ifdef CONFIG_PROFILER
1919 tcg_reg_alloc_bb_end(s
);
1920 if (search_pc
>= 0) {
1921 s
->code_ptr
+= def
->copy_size
;
1922 args
+= def
->nb_args
;
1924 args
= dyngen_op(s
, opc
, args
);
1929 /* Note: in order to speed up the code, it would be much
1930 faster to have specialized register allocator functions for
1931 some common argument patterns */
1932 dead_iargs
= s
->op_dead_iargs
[op_index
];
1933 tcg_reg_alloc_op(s
, def
, opc
, args
, dead_iargs
);
1936 args
+= def
->nb_args
;
1938 if (search_pc
>= 0 && search_pc
< s
->code_ptr
- gen_code_buf
) {
1939 if (macro_op_index
>= 0)
1940 return macro_op_index
;
1953 int dyngen_code(TCGContext
*s
, uint8_t *gen_code_buf
)
1955 #ifdef CONFIG_PROFILER
1958 n
= (gen_opc_ptr
- gen_opc_buf
);
1960 if (n
> s
->op_count_max
)
1961 s
->op_count_max
= n
;
1963 s
->temp_count
+= s
->nb_temps
;
1964 if (s
->nb_temps
> s
->temp_count_max
)
1965 s
->temp_count_max
= s
->nb_temps
;
1969 tcg_gen_code_common(s
, gen_code_buf
, -1);
1971 /* flush instruction cache */
1972 flush_icache_range((unsigned long)gen_code_buf
,
1973 (unsigned long)s
->code_ptr
);
1974 return s
->code_ptr
- gen_code_buf
;
1977 /* Return the index of the micro operation such as the pc after is <
1978 offset bytes from the start of the TB. The contents of gen_code_buf must
1979 not be changed, though writing the same values is ok.
1980 Return -1 if not found. */
1981 int dyngen_code_search_pc(TCGContext
*s
, uint8_t *gen_code_buf
, long offset
)
1983 return tcg_gen_code_common(s
, gen_code_buf
, offset
);
1986 #ifdef CONFIG_PROFILER
1987 void tcg_dump_info(FILE *f
,
1988 int (*cpu_fprintf
)(FILE *f
, const char *fmt
, ...))
1990 TCGContext
*s
= &tcg_ctx
;
1993 tot
= s
->interm_time
+ s
->code_time
;
1994 cpu_fprintf(f
, "JIT cycles %" PRId64
" (%0.3f s at 2.4 GHz)\n",
1996 cpu_fprintf(f
, "translated TBs %" PRId64
" (aborted=%" PRId64
" %0.1f%%)\n",
1998 s
->tb_count1
- s
->tb_count
,
1999 s
->tb_count1
? (double)(s
->tb_count1
- s
->tb_count
) / s
->tb_count1
* 100.0 : 0);
2000 cpu_fprintf(f
, "avg ops/TB %0.1f max=%d\n",
2001 s
->tb_count
? (double)s
->op_count
/ s
->tb_count
: 0, s
->op_count_max
);
2002 cpu_fprintf(f
, "old ops/total ops %0.1f%%\n",
2003 s
->op_count
? (double)s
->old_op_count
/ s
->op_count
* 100.0 : 0);
2004 cpu_fprintf(f
, "deleted ops/TB %0.2f\n",
2006 (double)s
->del_op_count
/ s
->tb_count
: 0);
2007 cpu_fprintf(f
, "avg temps/TB %0.2f max=%d\n",
2009 (double)s
->temp_count
/ s
->tb_count
: 0,
2012 cpu_fprintf(f
, "cycles/op %0.1f\n",
2013 s
->op_count
? (double)tot
/ s
->op_count
: 0);
2014 cpu_fprintf(f
, "cycles/in byte %0.1f\n",
2015 s
->code_in_len
? (double)tot
/ s
->code_in_len
: 0);
2016 cpu_fprintf(f
, "cycles/out byte %0.1f\n",
2017 s
->code_out_len
? (double)tot
/ s
->code_out_len
: 0);
2020 cpu_fprintf(f
, " gen_interm time %0.1f%%\n",
2021 (double)s
->interm_time
/ tot
* 100.0);
2022 cpu_fprintf(f
, " gen_code time %0.1f%%\n",
2023 (double)s
->code_time
/ tot
* 100.0);
2024 cpu_fprintf(f
, "liveness/code time %0.1f%%\n",
2025 (double)s
->la_time
/ (s
->code_time
? s
->code_time
: 1) * 100.0);
2026 cpu_fprintf(f
, "cpu_restore count %" PRId64
"\n",
2028 cpu_fprintf(f
, " avg cycles %0.1f\n",
2029 s
->restore_count
? (double)s
->restore_time
/ s
->restore_count
: 0);
2031 extern void dump_op_count(void);
2036 void dump_tcg_info(FILE *f
,
2037 int (*cpu_fprintf
)(FILE *f
, const char *fmt
, ...))
2039 cpu_fprintf("[TCG profiler not compiled]\n");