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
27 #define USE_TCG_OPTIMIZATIONS
31 /* Define to jump the ELF file used to communicate with GDB. */
34 #if !defined(CONFIG_DEBUG_TCG) && !defined(NDEBUG)
35 /* define it to suppress various consistency checks (faster) */
39 #include "qemu-common.h"
40 #include "qemu/cache-utils.h"
41 #include "qemu/host-utils.h"
42 #include "qemu/timer.h"
44 /* Note: the long term plan is to reduce the dependencies on the QEMU
45 CPU definitions. Currently they are used for qemu_ld/st
47 #define NO_CPU_IO_DEFS
52 #if UINTPTR_MAX == UINT32_MAX
53 # define ELF_CLASS ELFCLASS32
55 # define ELF_CLASS ELFCLASS64
57 #ifdef HOST_WORDS_BIGENDIAN
58 # define ELF_DATA ELFDATA2MSB
60 # define ELF_DATA ELFDATA2LSB
65 /* Forward declarations for functions declared in tcg-target.c and used here. */
66 static void tcg_target_init(TCGContext
*s
);
67 static void tcg_target_qemu_prologue(TCGContext
*s
);
68 static void patch_reloc(tcg_insn_unit
*code_ptr
, int type
,
69 intptr_t value
, intptr_t addend
);
71 /* The CIE and FDE header definitions will be common to all hosts. */
73 uint32_t len
__attribute__((aligned((sizeof(void *)))));
79 uint8_t return_column
;
82 typedef struct QEMU_PACKED
{
83 uint32_t len
__attribute__((aligned((sizeof(void *)))));
87 } DebugFrameFDEHeader
;
89 static void tcg_register_jit_int(void *buf
, size_t size
,
90 void *debug_frame
, size_t debug_frame_size
)
91 __attribute__((unused
));
93 /* Forward declarations for functions declared and used in tcg-target.c. */
94 static int target_parse_constraint(TCGArgConstraint
*ct
, const char **pct_str
);
95 static void tcg_out_ld(TCGContext
*s
, TCGType type
, TCGReg ret
, TCGReg arg1
,
97 static void tcg_out_mov(TCGContext
*s
, TCGType type
, TCGReg ret
, TCGReg arg
);
98 static void tcg_out_movi(TCGContext
*s
, TCGType type
,
99 TCGReg ret
, tcg_target_long arg
);
100 static void tcg_out_op(TCGContext
*s
, TCGOpcode opc
, const TCGArg
*args
,
101 const int *const_args
);
102 static void tcg_out_st(TCGContext
*s
, TCGType type
, TCGReg arg
, TCGReg arg1
,
104 static int tcg_target_const_match(tcg_target_long val
, TCGType type
,
105 const TCGArgConstraint
*arg_ct
);
106 static void tcg_out_tb_init(TCGContext
*s
);
107 static void tcg_out_tb_finalize(TCGContext
*s
);
110 TCGOpDef tcg_op_defs
[] = {
111 #define DEF(s, oargs, iargs, cargs, flags) { #s, oargs, iargs, cargs, iargs + oargs + cargs, flags },
115 const size_t tcg_op_defs_max
= ARRAY_SIZE(tcg_op_defs
);
117 static TCGRegSet tcg_target_available_regs
[2];
118 static TCGRegSet tcg_target_call_clobber_regs
;
120 #if TCG_TARGET_INSN_UNIT_SIZE == 1
121 static inline void tcg_out8(TCGContext
*s
, uint8_t v
)
126 static inline void tcg_patch8(tcg_insn_unit
*p
, uint8_t v
)
132 #if TCG_TARGET_INSN_UNIT_SIZE <= 2
133 static inline void tcg_out16(TCGContext
*s
, uint16_t v
)
135 if (TCG_TARGET_INSN_UNIT_SIZE
== 2) {
138 tcg_insn_unit
*p
= s
->code_ptr
;
139 memcpy(p
, &v
, sizeof(v
));
140 s
->code_ptr
= p
+ (2 / TCG_TARGET_INSN_UNIT_SIZE
);
144 static inline void tcg_patch16(tcg_insn_unit
*p
, uint16_t v
)
146 if (TCG_TARGET_INSN_UNIT_SIZE
== 2) {
149 memcpy(p
, &v
, sizeof(v
));
154 #if TCG_TARGET_INSN_UNIT_SIZE <= 4
155 static inline void tcg_out32(TCGContext
*s
, uint32_t v
)
157 if (TCG_TARGET_INSN_UNIT_SIZE
== 4) {
160 tcg_insn_unit
*p
= s
->code_ptr
;
161 memcpy(p
, &v
, sizeof(v
));
162 s
->code_ptr
= p
+ (4 / TCG_TARGET_INSN_UNIT_SIZE
);
166 static inline void tcg_patch32(tcg_insn_unit
*p
, uint32_t v
)
168 if (TCG_TARGET_INSN_UNIT_SIZE
== 4) {
171 memcpy(p
, &v
, sizeof(v
));
176 #if TCG_TARGET_INSN_UNIT_SIZE <= 8
177 static inline void tcg_out64(TCGContext
*s
, uint64_t v
)
179 if (TCG_TARGET_INSN_UNIT_SIZE
== 8) {
182 tcg_insn_unit
*p
= s
->code_ptr
;
183 memcpy(p
, &v
, sizeof(v
));
184 s
->code_ptr
= p
+ (8 / TCG_TARGET_INSN_UNIT_SIZE
);
188 static inline void tcg_patch64(tcg_insn_unit
*p
, uint64_t v
)
190 if (TCG_TARGET_INSN_UNIT_SIZE
== 8) {
193 memcpy(p
, &v
, sizeof(v
));
198 /* label relocation processing */
200 static void tcg_out_reloc(TCGContext
*s
, tcg_insn_unit
*code_ptr
, int type
,
201 int label_index
, intptr_t addend
)
206 l
= &s
->labels
[label_index
];
208 /* FIXME: This may break relocations on RISC targets that
209 modify instruction fields in place. The caller may not have
210 written the initial value. */
211 patch_reloc(code_ptr
, type
, l
->u
.value
, addend
);
213 /* add a new relocation entry */
214 r
= tcg_malloc(sizeof(TCGRelocation
));
218 r
->next
= l
->u
.first_reloc
;
219 l
->u
.first_reloc
= r
;
223 static void tcg_out_label(TCGContext
*s
, int label_index
, tcg_insn_unit
*ptr
)
225 TCGLabel
*l
= &s
->labels
[label_index
];
226 intptr_t value
= (intptr_t)ptr
;
229 assert(!l
->has_value
);
231 for (r
= l
->u
.first_reloc
; r
!= NULL
; r
= r
->next
) {
232 patch_reloc(r
->ptr
, r
->type
, value
, r
->addend
);
236 l
->u
.value_ptr
= ptr
;
239 int gen_new_label(void)
241 TCGContext
*s
= &tcg_ctx
;
245 if (s
->nb_labels
>= TCG_MAX_LABELS
)
247 idx
= s
->nb_labels
++;
250 l
->u
.first_reloc
= NULL
;
254 #include "tcg-target.c"
256 /* pool based memory allocation */
257 void *tcg_malloc_internal(TCGContext
*s
, int size
)
262 if (size
> TCG_POOL_CHUNK_SIZE
) {
263 /* big malloc: insert a new pool (XXX: could optimize) */
264 p
= g_malloc(sizeof(TCGPool
) + size
);
266 p
->next
= s
->pool_first_large
;
267 s
->pool_first_large
= p
;
278 pool_size
= TCG_POOL_CHUNK_SIZE
;
279 p
= g_malloc(sizeof(TCGPool
) + pool_size
);
283 s
->pool_current
->next
= p
;
292 s
->pool_cur
= p
->data
+ size
;
293 s
->pool_end
= p
->data
+ p
->size
;
297 void tcg_pool_reset(TCGContext
*s
)
300 for (p
= s
->pool_first_large
; p
; p
= t
) {
304 s
->pool_first_large
= NULL
;
305 s
->pool_cur
= s
->pool_end
= NULL
;
306 s
->pool_current
= NULL
;
311 typedef struct TCGHelperInfo
{
316 static const TCGHelperInfo all_helpers
[] = {
320 /* Include tcg-runtime.c functions. */
321 { tcg_helper_div_i32
, "div_i32" },
322 { tcg_helper_rem_i32
, "rem_i32" },
323 { tcg_helper_divu_i32
, "divu_i32" },
324 { tcg_helper_remu_i32
, "remu_i32" },
326 { tcg_helper_shl_i64
, "shl_i64" },
327 { tcg_helper_shr_i64
, "shr_i64" },
328 { tcg_helper_sar_i64
, "sar_i64" },
329 { tcg_helper_div_i64
, "div_i64" },
330 { tcg_helper_rem_i64
, "rem_i64" },
331 { tcg_helper_divu_i64
, "divu_i64" },
332 { tcg_helper_remu_i64
, "remu_i64" },
333 { tcg_helper_mulsh_i64
, "mulsh_i64" },
334 { tcg_helper_muluh_i64
, "muluh_i64" },
337 void tcg_context_init(TCGContext
*s
)
339 int op
, total_args
, n
, i
;
341 TCGArgConstraint
*args_ct
;
343 GHashTable
*helper_table
;
345 memset(s
, 0, sizeof(*s
));
348 /* Count total number of arguments and allocate the corresponding
351 for(op
= 0; op
< NB_OPS
; op
++) {
352 def
= &tcg_op_defs
[op
];
353 n
= def
->nb_iargs
+ def
->nb_oargs
;
357 args_ct
= g_malloc(sizeof(TCGArgConstraint
) * total_args
);
358 sorted_args
= g_malloc(sizeof(int) * total_args
);
360 for(op
= 0; op
< NB_OPS
; op
++) {
361 def
= &tcg_op_defs
[op
];
362 def
->args_ct
= args_ct
;
363 def
->sorted_args
= sorted_args
;
364 n
= def
->nb_iargs
+ def
->nb_oargs
;
369 /* Register helpers. */
370 /* Use g_direct_hash/equal for direct pointer comparisons on func. */
371 s
->helpers
= helper_table
= g_hash_table_new(NULL
, NULL
);
373 for (i
= 0; i
< ARRAY_SIZE(all_helpers
); ++i
) {
374 g_hash_table_insert(helper_table
, (gpointer
)all_helpers
[i
].func
,
375 (gpointer
)all_helpers
[i
].name
);
381 void tcg_prologue_init(TCGContext
*s
)
383 /* init global prologue and epilogue */
384 s
->code_buf
= s
->code_gen_prologue
;
385 s
->code_ptr
= s
->code_buf
;
386 tcg_target_qemu_prologue(s
);
387 flush_icache_range((uintptr_t)s
->code_buf
, (uintptr_t)s
->code_ptr
);
390 if (qemu_loglevel_mask(CPU_LOG_TB_OUT_ASM
)) {
391 size_t size
= tcg_current_code_size(s
);
392 qemu_log("PROLOGUE: [size=%zu]\n", size
);
393 log_disas(s
->code_buf
, size
);
400 void tcg_set_frame(TCGContext
*s
, int reg
, intptr_t start
, intptr_t size
)
402 s
->frame_start
= start
;
403 s
->frame_end
= start
+ size
;
407 void tcg_func_start(TCGContext
*s
)
410 s
->nb_temps
= s
->nb_globals
;
412 /* No temps have been previously allocated for size or locality. */
413 memset(s
->free_temps
, 0, sizeof(s
->free_temps
));
415 s
->labels
= tcg_malloc(sizeof(TCGLabel
) * TCG_MAX_LABELS
);
417 s
->current_frame_offset
= s
->frame_start
;
419 #ifdef CONFIG_DEBUG_TCG
420 s
->goto_tb_issue_mask
= 0;
423 s
->gen_opc_ptr
= s
->gen_opc_buf
;
424 s
->gen_opparam_ptr
= s
->gen_opparam_buf
;
426 s
->be
= tcg_malloc(sizeof(TCGBackendData
));
429 static inline void tcg_temp_alloc(TCGContext
*s
, int n
)
431 if (n
> TCG_MAX_TEMPS
)
435 static inline int tcg_global_reg_new_internal(TCGType type
, int reg
,
438 TCGContext
*s
= &tcg_ctx
;
442 #if TCG_TARGET_REG_BITS == 32
443 if (type
!= TCG_TYPE_I32
)
446 if (tcg_regset_test_reg(s
->reserved_regs
, reg
))
449 tcg_temp_alloc(s
, s
->nb_globals
+ 1);
450 ts
= &s
->temps
[s
->nb_globals
];
451 ts
->base_type
= type
;
457 tcg_regset_set_reg(s
->reserved_regs
, reg
);
461 TCGv_i32
tcg_global_reg_new_i32(int reg
, const char *name
)
465 idx
= tcg_global_reg_new_internal(TCG_TYPE_I32
, reg
, name
);
466 return MAKE_TCGV_I32(idx
);
469 TCGv_i64
tcg_global_reg_new_i64(int reg
, const char *name
)
473 idx
= tcg_global_reg_new_internal(TCG_TYPE_I64
, reg
, name
);
474 return MAKE_TCGV_I64(idx
);
477 static inline int tcg_global_mem_new_internal(TCGType type
, int reg
,
481 TCGContext
*s
= &tcg_ctx
;
486 #if TCG_TARGET_REG_BITS == 32
487 if (type
== TCG_TYPE_I64
) {
489 tcg_temp_alloc(s
, s
->nb_globals
+ 2);
490 ts
= &s
->temps
[s
->nb_globals
];
491 ts
->base_type
= type
;
492 ts
->type
= TCG_TYPE_I32
;
494 ts
->mem_allocated
= 1;
496 #ifdef HOST_WORDS_BIGENDIAN
497 ts
->mem_offset
= offset
+ 4;
499 ts
->mem_offset
= offset
;
501 pstrcpy(buf
, sizeof(buf
), name
);
502 pstrcat(buf
, sizeof(buf
), "_0");
503 ts
->name
= strdup(buf
);
506 ts
->base_type
= type
;
507 ts
->type
= TCG_TYPE_I32
;
509 ts
->mem_allocated
= 1;
511 #ifdef HOST_WORDS_BIGENDIAN
512 ts
->mem_offset
= offset
;
514 ts
->mem_offset
= offset
+ 4;
516 pstrcpy(buf
, sizeof(buf
), name
);
517 pstrcat(buf
, sizeof(buf
), "_1");
518 ts
->name
= strdup(buf
);
524 tcg_temp_alloc(s
, s
->nb_globals
+ 1);
525 ts
= &s
->temps
[s
->nb_globals
];
526 ts
->base_type
= type
;
529 ts
->mem_allocated
= 1;
531 ts
->mem_offset
= offset
;
538 TCGv_i32
tcg_global_mem_new_i32(int reg
, intptr_t offset
, const char *name
)
540 int idx
= tcg_global_mem_new_internal(TCG_TYPE_I32
, reg
, offset
, name
);
541 return MAKE_TCGV_I32(idx
);
544 TCGv_i64
tcg_global_mem_new_i64(int reg
, intptr_t offset
, const char *name
)
546 int idx
= tcg_global_mem_new_internal(TCG_TYPE_I64
, reg
, offset
, name
);
547 return MAKE_TCGV_I64(idx
);
550 static inline int tcg_temp_new_internal(TCGType type
, int temp_local
)
552 TCGContext
*s
= &tcg_ctx
;
556 k
= type
+ (temp_local
? TCG_TYPE_COUNT
: 0);
557 idx
= find_first_bit(s
->free_temps
[k
].l
, TCG_MAX_TEMPS
);
558 if (idx
< TCG_MAX_TEMPS
) {
559 /* There is already an available temp with the right type. */
560 clear_bit(idx
, s
->free_temps
[k
].l
);
563 ts
->temp_allocated
= 1;
564 assert(ts
->base_type
== type
);
565 assert(ts
->temp_local
== temp_local
);
568 #if TCG_TARGET_REG_BITS == 32
569 if (type
== TCG_TYPE_I64
) {
570 tcg_temp_alloc(s
, s
->nb_temps
+ 2);
571 ts
= &s
->temps
[s
->nb_temps
];
572 ts
->base_type
= type
;
573 ts
->type
= TCG_TYPE_I32
;
574 ts
->temp_allocated
= 1;
575 ts
->temp_local
= temp_local
;
578 ts
->base_type
= type
;
579 ts
->type
= TCG_TYPE_I32
;
580 ts
->temp_allocated
= 1;
581 ts
->temp_local
= temp_local
;
587 tcg_temp_alloc(s
, s
->nb_temps
+ 1);
588 ts
= &s
->temps
[s
->nb_temps
];
589 ts
->base_type
= type
;
591 ts
->temp_allocated
= 1;
592 ts
->temp_local
= temp_local
;
598 #if defined(CONFIG_DEBUG_TCG)
604 TCGv_i32
tcg_temp_new_internal_i32(int temp_local
)
608 idx
= tcg_temp_new_internal(TCG_TYPE_I32
, temp_local
);
609 return MAKE_TCGV_I32(idx
);
612 TCGv_i64
tcg_temp_new_internal_i64(int temp_local
)
616 idx
= tcg_temp_new_internal(TCG_TYPE_I64
, temp_local
);
617 return MAKE_TCGV_I64(idx
);
620 static void tcg_temp_free_internal(int idx
)
622 TCGContext
*s
= &tcg_ctx
;
626 #if defined(CONFIG_DEBUG_TCG)
628 if (s
->temps_in_use
< 0) {
629 fprintf(stderr
, "More temporaries freed than allocated!\n");
633 assert(idx
>= s
->nb_globals
&& idx
< s
->nb_temps
);
635 assert(ts
->temp_allocated
!= 0);
636 ts
->temp_allocated
= 0;
638 k
= ts
->base_type
+ (ts
->temp_local
? TCG_TYPE_COUNT
: 0);
639 set_bit(idx
, s
->free_temps
[k
].l
);
642 void tcg_temp_free_i32(TCGv_i32 arg
)
644 tcg_temp_free_internal(GET_TCGV_I32(arg
));
647 void tcg_temp_free_i64(TCGv_i64 arg
)
649 tcg_temp_free_internal(GET_TCGV_I64(arg
));
652 TCGv_i32
tcg_const_i32(int32_t val
)
655 t0
= tcg_temp_new_i32();
656 tcg_gen_movi_i32(t0
, val
);
660 TCGv_i64
tcg_const_i64(int64_t val
)
663 t0
= tcg_temp_new_i64();
664 tcg_gen_movi_i64(t0
, val
);
668 TCGv_i32
tcg_const_local_i32(int32_t val
)
671 t0
= tcg_temp_local_new_i32();
672 tcg_gen_movi_i32(t0
, val
);
676 TCGv_i64
tcg_const_local_i64(int64_t val
)
679 t0
= tcg_temp_local_new_i64();
680 tcg_gen_movi_i64(t0
, val
);
684 #if defined(CONFIG_DEBUG_TCG)
685 void tcg_clear_temp_count(void)
687 TCGContext
*s
= &tcg_ctx
;
691 int tcg_check_temp_count(void)
693 TCGContext
*s
= &tcg_ctx
;
694 if (s
->temps_in_use
) {
695 /* Clear the count so that we don't give another
696 * warning immediately next time around.
705 /* Note: we convert the 64 bit args to 32 bit and do some alignment
706 and endian swap. Maybe it would be better to do the alignment
707 and endian swap in tcg_reg_alloc_call(). */
708 void tcg_gen_callN(TCGContext
*s
, TCGv_ptr func
, unsigned int flags
,
709 int sizemask
, TCGArg ret
, int nargs
, TCGArg
*args
)
716 #if defined(__sparc__) && !defined(__arch64__) \
717 && !defined(CONFIG_TCG_INTERPRETER)
718 /* We have 64-bit values in one register, but need to pass as two
719 separate parameters. Split them. */
720 int orig_sizemask
= sizemask
;
721 int orig_nargs
= nargs
;
724 TCGV_UNUSED_I64(retl
);
725 TCGV_UNUSED_I64(reth
);
727 TCGArg
*split_args
= __builtin_alloca(sizeof(TCGArg
) * nargs
* 2);
728 for (i
= real_args
= 0; i
< nargs
; ++i
) {
729 int is_64bit
= sizemask
& (1 << (i
+1)*2);
731 TCGv_i64 orig
= MAKE_TCGV_I64(args
[i
]);
732 TCGv_i32 h
= tcg_temp_new_i32();
733 TCGv_i32 l
= tcg_temp_new_i32();
734 tcg_gen_extr_i64_i32(l
, h
, orig
);
735 split_args
[real_args
++] = GET_TCGV_I32(h
);
736 split_args
[real_args
++] = GET_TCGV_I32(l
);
738 split_args
[real_args
++] = args
[i
];
745 #elif defined(TCG_TARGET_EXTEND_ARGS) && TCG_TARGET_REG_BITS == 64
746 for (i
= 0; i
< nargs
; ++i
) {
747 int is_64bit
= sizemask
& (1 << (i
+1)*2);
748 int is_signed
= sizemask
& (2 << (i
+1)*2);
750 TCGv_i64 temp
= tcg_temp_new_i64();
751 TCGv_i64 orig
= MAKE_TCGV_I64(args
[i
]);
753 tcg_gen_ext32s_i64(temp
, orig
);
755 tcg_gen_ext32u_i64(temp
, orig
);
757 args
[i
] = GET_TCGV_I64(temp
);
760 #endif /* TCG_TARGET_EXTEND_ARGS */
762 *s
->gen_opc_ptr
++ = INDEX_op_call
;
763 nparam
= s
->gen_opparam_ptr
++;
764 if (ret
!= TCG_CALL_DUMMY_ARG
) {
765 #if defined(__sparc__) && !defined(__arch64__) \
766 && !defined(CONFIG_TCG_INTERPRETER)
767 if (orig_sizemask
& 1) {
768 /* The 32-bit ABI is going to return the 64-bit value in
769 the %o0/%o1 register pair. Prepare for this by using
770 two return temporaries, and reassemble below. */
771 retl
= tcg_temp_new_i64();
772 reth
= tcg_temp_new_i64();
773 *s
->gen_opparam_ptr
++ = GET_TCGV_I64(reth
);
774 *s
->gen_opparam_ptr
++ = GET_TCGV_I64(retl
);
777 *s
->gen_opparam_ptr
++ = ret
;
781 if (TCG_TARGET_REG_BITS
< 64 && (sizemask
& 1)) {
782 #ifdef HOST_WORDS_BIGENDIAN
783 *s
->gen_opparam_ptr
++ = ret
+ 1;
784 *s
->gen_opparam_ptr
++ = ret
;
786 *s
->gen_opparam_ptr
++ = ret
;
787 *s
->gen_opparam_ptr
++ = ret
+ 1;
791 *s
->gen_opparam_ptr
++ = ret
;
799 for (i
= 0; i
< nargs
; i
++) {
800 #if TCG_TARGET_REG_BITS < 64
801 int is_64bit
= sizemask
& (1 << (i
+1)*2);
803 #ifdef TCG_TARGET_CALL_ALIGN_ARGS
804 /* some targets want aligned 64 bit args */
806 *s
->gen_opparam_ptr
++ = TCG_CALL_DUMMY_ARG
;
810 /* If stack grows up, then we will be placing successive
811 arguments at lower addresses, which means we need to
812 reverse the order compared to how we would normally
813 treat either big or little-endian. For those arguments
814 that will wind up in registers, this still works for
815 HPPA (the only current STACK_GROWSUP target) since the
816 argument registers are *also* allocated in decreasing
817 order. If another such target is added, this logic may
818 have to get more complicated to differentiate between
819 stack arguments and register arguments. */
820 #if defined(HOST_WORDS_BIGENDIAN) != defined(TCG_TARGET_STACK_GROWSUP)
821 *s
->gen_opparam_ptr
++ = args
[i
] + 1;
822 *s
->gen_opparam_ptr
++ = args
[i
];
824 *s
->gen_opparam_ptr
++ = args
[i
];
825 *s
->gen_opparam_ptr
++ = args
[i
] + 1;
830 #endif /* TCG_TARGET_REG_BITS < 64 */
832 *s
->gen_opparam_ptr
++ = args
[i
];
835 *s
->gen_opparam_ptr
++ = GET_TCGV_PTR(func
);
837 *s
->gen_opparam_ptr
++ = flags
;
839 *nparam
= (nb_rets
<< 16) | (real_args
+ 1);
841 /* total parameters, needed to go backward in the instruction stream */
842 *s
->gen_opparam_ptr
++ = 1 + nb_rets
+ real_args
+ 3;
844 #if defined(__sparc__) && !defined(__arch64__) \
845 && !defined(CONFIG_TCG_INTERPRETER)
846 /* Free all of the parts we allocated above. */
847 for (i
= real_args
= 0; i
< orig_nargs
; ++i
) {
848 int is_64bit
= orig_sizemask
& (1 << (i
+1)*2);
850 TCGv_i32 h
= MAKE_TCGV_I32(args
[real_args
++]);
851 TCGv_i32 l
= MAKE_TCGV_I32(args
[real_args
++]);
852 tcg_temp_free_i32(h
);
853 tcg_temp_free_i32(l
);
858 if (orig_sizemask
& 1) {
859 /* The 32-bit ABI returned two 32-bit pieces. Re-assemble them.
860 Note that describing these as TCGv_i64 eliminates an unnecessary
861 zero-extension that tcg_gen_concat_i32_i64 would create. */
862 tcg_gen_concat32_i64(MAKE_TCGV_I64(ret
), retl
, reth
);
863 tcg_temp_free_i64(retl
);
864 tcg_temp_free_i64(reth
);
866 #elif defined(TCG_TARGET_EXTEND_ARGS) && TCG_TARGET_REG_BITS == 64
867 for (i
= 0; i
< nargs
; ++i
) {
868 int is_64bit
= sizemask
& (1 << (i
+1)*2);
870 TCGv_i64 temp
= MAKE_TCGV_I64(args
[i
]);
871 tcg_temp_free_i64(temp
);
874 #endif /* TCG_TARGET_EXTEND_ARGS */
877 #if TCG_TARGET_REG_BITS == 32
878 void tcg_gen_shifti_i64(TCGv_i64 ret
, TCGv_i64 arg1
,
879 int c
, int right
, int arith
)
882 tcg_gen_mov_i32(TCGV_LOW(ret
), TCGV_LOW(arg1
));
883 tcg_gen_mov_i32(TCGV_HIGH(ret
), TCGV_HIGH(arg1
));
884 } else if (c
>= 32) {
888 tcg_gen_sari_i32(TCGV_LOW(ret
), TCGV_HIGH(arg1
), c
);
889 tcg_gen_sari_i32(TCGV_HIGH(ret
), TCGV_HIGH(arg1
), 31);
891 tcg_gen_shri_i32(TCGV_LOW(ret
), TCGV_HIGH(arg1
), c
);
892 tcg_gen_movi_i32(TCGV_HIGH(ret
), 0);
895 tcg_gen_shli_i32(TCGV_HIGH(ret
), TCGV_LOW(arg1
), c
);
896 tcg_gen_movi_i32(TCGV_LOW(ret
), 0);
901 t0
= tcg_temp_new_i32();
902 t1
= tcg_temp_new_i32();
904 tcg_gen_shli_i32(t0
, TCGV_HIGH(arg1
), 32 - c
);
906 tcg_gen_sari_i32(t1
, TCGV_HIGH(arg1
), c
);
908 tcg_gen_shri_i32(t1
, TCGV_HIGH(arg1
), c
);
909 tcg_gen_shri_i32(TCGV_LOW(ret
), TCGV_LOW(arg1
), c
);
910 tcg_gen_or_i32(TCGV_LOW(ret
), TCGV_LOW(ret
), t0
);
911 tcg_gen_mov_i32(TCGV_HIGH(ret
), t1
);
913 tcg_gen_shri_i32(t0
, TCGV_LOW(arg1
), 32 - c
);
914 /* Note: ret can be the same as arg1, so we use t1 */
915 tcg_gen_shli_i32(t1
, TCGV_LOW(arg1
), c
);
916 tcg_gen_shli_i32(TCGV_HIGH(ret
), TCGV_HIGH(arg1
), c
);
917 tcg_gen_or_i32(TCGV_HIGH(ret
), TCGV_HIGH(ret
), t0
);
918 tcg_gen_mov_i32(TCGV_LOW(ret
), t1
);
920 tcg_temp_free_i32(t0
);
921 tcg_temp_free_i32(t1
);
926 static inline TCGMemOp
tcg_canonicalize_memop(TCGMemOp op
, bool is64
, bool st
)
928 switch (op
& MO_SIZE
) {
951 static const TCGOpcode old_ld_opc
[8] = {
952 [MO_UB
] = INDEX_op_qemu_ld8u
,
953 [MO_SB
] = INDEX_op_qemu_ld8s
,
954 [MO_UW
] = INDEX_op_qemu_ld16u
,
955 [MO_SW
] = INDEX_op_qemu_ld16s
,
956 #if TCG_TARGET_REG_BITS == 32
957 [MO_UL
] = INDEX_op_qemu_ld32
,
958 [MO_SL
] = INDEX_op_qemu_ld32
,
960 [MO_UL
] = INDEX_op_qemu_ld32u
,
961 [MO_SL
] = INDEX_op_qemu_ld32s
,
963 [MO_Q
] = INDEX_op_qemu_ld64
,
966 static const TCGOpcode old_st_opc
[4] = {
967 [MO_UB
] = INDEX_op_qemu_st8
,
968 [MO_UW
] = INDEX_op_qemu_st16
,
969 [MO_UL
] = INDEX_op_qemu_st32
,
970 [MO_Q
] = INDEX_op_qemu_st64
,
973 void tcg_gen_qemu_ld_i32(TCGv_i32 val
, TCGv addr
, TCGArg idx
, TCGMemOp memop
)
975 memop
= tcg_canonicalize_memop(memop
, 0, 0);
977 if (TCG_TARGET_HAS_new_ldst
) {
978 *tcg_ctx
.gen_opc_ptr
++ = INDEX_op_qemu_ld_i32
;
979 tcg_add_param_i32(val
);
980 tcg_add_param_tl(addr
);
981 *tcg_ctx
.gen_opparam_ptr
++ = memop
;
982 *tcg_ctx
.gen_opparam_ptr
++ = idx
;
986 /* The old opcodes only support target-endian memory operations. */
987 assert((memop
& MO_BSWAP
) == MO_TE
|| (memop
& MO_SIZE
) == MO_8
);
988 assert(old_ld_opc
[memop
& MO_SSIZE
] != 0);
990 if (TCG_TARGET_REG_BITS
== 32) {
991 *tcg_ctx
.gen_opc_ptr
++ = old_ld_opc
[memop
& MO_SSIZE
];
992 tcg_add_param_i32(val
);
993 tcg_add_param_tl(addr
);
994 *tcg_ctx
.gen_opparam_ptr
++ = idx
;
996 TCGv_i64 val64
= tcg_temp_new_i64();
998 *tcg_ctx
.gen_opc_ptr
++ = old_ld_opc
[memop
& MO_SSIZE
];
999 tcg_add_param_i64(val64
);
1000 tcg_add_param_tl(addr
);
1001 *tcg_ctx
.gen_opparam_ptr
++ = idx
;
1003 tcg_gen_trunc_i64_i32(val
, val64
);
1004 tcg_temp_free_i64(val64
);
1008 void tcg_gen_qemu_st_i32(TCGv_i32 val
, TCGv addr
, TCGArg idx
, TCGMemOp memop
)
1010 memop
= tcg_canonicalize_memop(memop
, 0, 1);
1012 if (TCG_TARGET_HAS_new_ldst
) {
1013 *tcg_ctx
.gen_opc_ptr
++ = INDEX_op_qemu_st_i32
;
1014 tcg_add_param_i32(val
);
1015 tcg_add_param_tl(addr
);
1016 *tcg_ctx
.gen_opparam_ptr
++ = memop
;
1017 *tcg_ctx
.gen_opparam_ptr
++ = idx
;
1021 /* The old opcodes only support target-endian memory operations. */
1022 assert((memop
& MO_BSWAP
) == MO_TE
|| (memop
& MO_SIZE
) == MO_8
);
1023 assert(old_st_opc
[memop
& MO_SIZE
] != 0);
1025 if (TCG_TARGET_REG_BITS
== 32) {
1026 *tcg_ctx
.gen_opc_ptr
++ = old_st_opc
[memop
& MO_SIZE
];
1027 tcg_add_param_i32(val
);
1028 tcg_add_param_tl(addr
);
1029 *tcg_ctx
.gen_opparam_ptr
++ = idx
;
1031 TCGv_i64 val64
= tcg_temp_new_i64();
1033 tcg_gen_extu_i32_i64(val64
, val
);
1035 *tcg_ctx
.gen_opc_ptr
++ = old_st_opc
[memop
& MO_SIZE
];
1036 tcg_add_param_i64(val64
);
1037 tcg_add_param_tl(addr
);
1038 *tcg_ctx
.gen_opparam_ptr
++ = idx
;
1040 tcg_temp_free_i64(val64
);
1044 void tcg_gen_qemu_ld_i64(TCGv_i64 val
, TCGv addr
, TCGArg idx
, TCGMemOp memop
)
1046 memop
= tcg_canonicalize_memop(memop
, 1, 0);
1048 #if TCG_TARGET_REG_BITS == 32
1049 if ((memop
& MO_SIZE
) < MO_64
) {
1050 tcg_gen_qemu_ld_i32(TCGV_LOW(val
), addr
, idx
, memop
);
1051 if (memop
& MO_SIGN
) {
1052 tcg_gen_sari_i32(TCGV_HIGH(val
), TCGV_LOW(val
), 31);
1054 tcg_gen_movi_i32(TCGV_HIGH(val
), 0);
1060 if (TCG_TARGET_HAS_new_ldst
) {
1061 *tcg_ctx
.gen_opc_ptr
++ = INDEX_op_qemu_ld_i64
;
1062 tcg_add_param_i64(val
);
1063 tcg_add_param_tl(addr
);
1064 *tcg_ctx
.gen_opparam_ptr
++ = memop
;
1065 *tcg_ctx
.gen_opparam_ptr
++ = idx
;
1069 /* The old opcodes only support target-endian memory operations. */
1070 assert((memop
& MO_BSWAP
) == MO_TE
|| (memop
& MO_SIZE
) == MO_8
);
1071 assert(old_ld_opc
[memop
& MO_SSIZE
] != 0);
1073 *tcg_ctx
.gen_opc_ptr
++ = old_ld_opc
[memop
& MO_SSIZE
];
1074 tcg_add_param_i64(val
);
1075 tcg_add_param_tl(addr
);
1076 *tcg_ctx
.gen_opparam_ptr
++ = idx
;
1079 void tcg_gen_qemu_st_i64(TCGv_i64 val
, TCGv addr
, TCGArg idx
, TCGMemOp memop
)
1081 memop
= tcg_canonicalize_memop(memop
, 1, 1);
1083 #if TCG_TARGET_REG_BITS == 32
1084 if ((memop
& MO_SIZE
) < MO_64
) {
1085 tcg_gen_qemu_st_i32(TCGV_LOW(val
), addr
, idx
, memop
);
1090 if (TCG_TARGET_HAS_new_ldst
) {
1091 *tcg_ctx
.gen_opc_ptr
++ = INDEX_op_qemu_st_i64
;
1092 tcg_add_param_i64(val
);
1093 tcg_add_param_tl(addr
);
1094 *tcg_ctx
.gen_opparam_ptr
++ = memop
;
1095 *tcg_ctx
.gen_opparam_ptr
++ = idx
;
1099 /* The old opcodes only support target-endian memory operations. */
1100 assert((memop
& MO_BSWAP
) == MO_TE
|| (memop
& MO_SIZE
) == MO_8
);
1101 assert(old_st_opc
[memop
& MO_SIZE
] != 0);
1103 *tcg_ctx
.gen_opc_ptr
++ = old_st_opc
[memop
& MO_SIZE
];
1104 tcg_add_param_i64(val
);
1105 tcg_add_param_tl(addr
);
1106 *tcg_ctx
.gen_opparam_ptr
++ = idx
;
1109 static void tcg_reg_alloc_start(TCGContext
*s
)
1113 for(i
= 0; i
< s
->nb_globals
; i
++) {
1115 if (ts
->fixed_reg
) {
1116 ts
->val_type
= TEMP_VAL_REG
;
1118 ts
->val_type
= TEMP_VAL_MEM
;
1121 for(i
= s
->nb_globals
; i
< s
->nb_temps
; i
++) {
1123 if (ts
->temp_local
) {
1124 ts
->val_type
= TEMP_VAL_MEM
;
1126 ts
->val_type
= TEMP_VAL_DEAD
;
1128 ts
->mem_allocated
= 0;
1131 for(i
= 0; i
< TCG_TARGET_NB_REGS
; i
++) {
1132 s
->reg_to_temp
[i
] = -1;
1136 static char *tcg_get_arg_str_idx(TCGContext
*s
, char *buf
, int buf_size
,
1141 assert(idx
>= 0 && idx
< s
->nb_temps
);
1142 ts
= &s
->temps
[idx
];
1143 if (idx
< s
->nb_globals
) {
1144 pstrcpy(buf
, buf_size
, ts
->name
);
1147 snprintf(buf
, buf_size
, "loc%d", idx
- s
->nb_globals
);
1149 snprintf(buf
, buf_size
, "tmp%d", idx
- s
->nb_globals
);
1154 char *tcg_get_arg_str_i32(TCGContext
*s
, char *buf
, int buf_size
, TCGv_i32 arg
)
1156 return tcg_get_arg_str_idx(s
, buf
, buf_size
, GET_TCGV_I32(arg
));
1159 char *tcg_get_arg_str_i64(TCGContext
*s
, char *buf
, int buf_size
, TCGv_i64 arg
)
1161 return tcg_get_arg_str_idx(s
, buf
, buf_size
, GET_TCGV_I64(arg
));
1164 /* Find helper name. */
1165 static inline const char *tcg_find_helper(TCGContext
*s
, uintptr_t val
)
1167 const char *ret
= NULL
;
1169 ret
= g_hash_table_lookup(s
->helpers
, (gpointer
)val
);
1174 static const char * const cond_name
[] =
1176 [TCG_COND_NEVER
] = "never",
1177 [TCG_COND_ALWAYS
] = "always",
1178 [TCG_COND_EQ
] = "eq",
1179 [TCG_COND_NE
] = "ne",
1180 [TCG_COND_LT
] = "lt",
1181 [TCG_COND_GE
] = "ge",
1182 [TCG_COND_LE
] = "le",
1183 [TCG_COND_GT
] = "gt",
1184 [TCG_COND_LTU
] = "ltu",
1185 [TCG_COND_GEU
] = "geu",
1186 [TCG_COND_LEU
] = "leu",
1187 [TCG_COND_GTU
] = "gtu"
1190 static const char * const ldst_name
[] =
1206 void tcg_dump_ops(TCGContext
*s
)
1208 const uint16_t *opc_ptr
;
1212 int i
, k
, nb_oargs
, nb_iargs
, nb_cargs
, first_insn
;
1213 const TCGOpDef
*def
;
1217 opc_ptr
= s
->gen_opc_buf
;
1218 args
= s
->gen_opparam_buf
;
1219 while (opc_ptr
< s
->gen_opc_ptr
) {
1221 def
= &tcg_op_defs
[c
];
1222 if (c
== INDEX_op_debug_insn_start
) {
1224 #if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
1225 pc
= ((uint64_t)args
[1] << 32) | args
[0];
1232 qemu_log(" ---- 0x%" PRIx64
, pc
);
1234 nb_oargs
= def
->nb_oargs
;
1235 nb_iargs
= def
->nb_iargs
;
1236 nb_cargs
= def
->nb_cargs
;
1237 } else if (c
== INDEX_op_call
) {
1240 /* variable number of arguments */
1242 nb_oargs
= arg
>> 16;
1243 nb_iargs
= arg
& 0xffff;
1244 nb_cargs
= def
->nb_cargs
;
1246 qemu_log(" %s ", def
->name
);
1250 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
),
1251 args
[nb_oargs
+ nb_iargs
- 1]));
1253 qemu_log(",$0x%" TCG_PRIlx
, args
[nb_oargs
+ nb_iargs
]);
1255 qemu_log(",$%d", nb_oargs
);
1256 for(i
= 0; i
< nb_oargs
; i
++) {
1258 qemu_log("%s", tcg_get_arg_str_idx(s
, buf
, sizeof(buf
),
1261 for(i
= 0; i
< (nb_iargs
- 1); i
++) {
1263 if (args
[nb_oargs
+ i
] == TCG_CALL_DUMMY_ARG
) {
1264 qemu_log("<dummy>");
1266 qemu_log("%s", tcg_get_arg_str_idx(s
, buf
, sizeof(buf
),
1267 args
[nb_oargs
+ i
]));
1270 } else if (c
== INDEX_op_movi_i32
|| c
== INDEX_op_movi_i64
) {
1271 tcg_target_ulong val
;
1274 nb_oargs
= def
->nb_oargs
;
1275 nb_iargs
= def
->nb_iargs
;
1276 nb_cargs
= def
->nb_cargs
;
1277 qemu_log(" %s %s,$", def
->name
,
1278 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), args
[0]));
1280 name
= tcg_find_helper(s
, val
);
1282 qemu_log("%s", name
);
1284 if (c
== INDEX_op_movi_i32
) {
1285 qemu_log("0x%x", (uint32_t)val
);
1287 qemu_log("0x%" PRIx64
, (uint64_t)val
);
1291 qemu_log(" %s ", def
->name
);
1292 if (c
== INDEX_op_nopn
) {
1293 /* variable number of arguments */
1298 nb_oargs
= def
->nb_oargs
;
1299 nb_iargs
= def
->nb_iargs
;
1300 nb_cargs
= def
->nb_cargs
;
1304 for(i
= 0; i
< nb_oargs
; i
++) {
1308 qemu_log("%s", tcg_get_arg_str_idx(s
, buf
, sizeof(buf
),
1311 for(i
= 0; i
< nb_iargs
; i
++) {
1315 qemu_log("%s", tcg_get_arg_str_idx(s
, buf
, sizeof(buf
),
1319 case INDEX_op_brcond_i32
:
1320 case INDEX_op_setcond_i32
:
1321 case INDEX_op_movcond_i32
:
1322 case INDEX_op_brcond2_i32
:
1323 case INDEX_op_setcond2_i32
:
1324 case INDEX_op_brcond_i64
:
1325 case INDEX_op_setcond_i64
:
1326 case INDEX_op_movcond_i64
:
1327 if (args
[k
] < ARRAY_SIZE(cond_name
) && cond_name
[args
[k
]]) {
1328 qemu_log(",%s", cond_name
[args
[k
++]]);
1330 qemu_log(",$0x%" TCG_PRIlx
, args
[k
++]);
1334 case INDEX_op_qemu_ld_i32
:
1335 case INDEX_op_qemu_st_i32
:
1336 case INDEX_op_qemu_ld_i64
:
1337 case INDEX_op_qemu_st_i64
:
1338 if (args
[k
] < ARRAY_SIZE(ldst_name
) && ldst_name
[args
[k
]]) {
1339 qemu_log(",%s", ldst_name
[args
[k
++]]);
1341 qemu_log(",$0x%" TCG_PRIlx
, args
[k
++]);
1349 for(; i
< nb_cargs
; i
++) {
1354 qemu_log("$0x%" TCG_PRIlx
, arg
);
1358 args
+= nb_iargs
+ nb_oargs
+ nb_cargs
;
1362 /* we give more priority to constraints with less registers */
1363 static int get_constraint_priority(const TCGOpDef
*def
, int k
)
1365 const TCGArgConstraint
*arg_ct
;
1368 arg_ct
= &def
->args_ct
[k
];
1369 if (arg_ct
->ct
& TCG_CT_ALIAS
) {
1370 /* an alias is equivalent to a single register */
1373 if (!(arg_ct
->ct
& TCG_CT_REG
))
1376 for(i
= 0; i
< TCG_TARGET_NB_REGS
; i
++) {
1377 if (tcg_regset_test_reg(arg_ct
->u
.regs
, i
))
1381 return TCG_TARGET_NB_REGS
- n
+ 1;
1384 /* sort from highest priority to lowest */
1385 static void sort_constraints(TCGOpDef
*def
, int start
, int n
)
1387 int i
, j
, p1
, p2
, tmp
;
1389 for(i
= 0; i
< n
; i
++)
1390 def
->sorted_args
[start
+ i
] = start
+ i
;
1393 for(i
= 0; i
< n
- 1; i
++) {
1394 for(j
= i
+ 1; j
< n
; j
++) {
1395 p1
= get_constraint_priority(def
, def
->sorted_args
[start
+ i
]);
1396 p2
= get_constraint_priority(def
, def
->sorted_args
[start
+ j
]);
1398 tmp
= def
->sorted_args
[start
+ i
];
1399 def
->sorted_args
[start
+ i
] = def
->sorted_args
[start
+ j
];
1400 def
->sorted_args
[start
+ j
] = tmp
;
1406 void tcg_add_target_add_op_defs(const TCGTargetOpDef
*tdefs
)
1414 if (tdefs
->op
== (TCGOpcode
)-1)
1417 assert((unsigned)op
< NB_OPS
);
1418 def
= &tcg_op_defs
[op
];
1419 #if defined(CONFIG_DEBUG_TCG)
1420 /* Duplicate entry in op definitions? */
1424 nb_args
= def
->nb_iargs
+ def
->nb_oargs
;
1425 for(i
= 0; i
< nb_args
; i
++) {
1426 ct_str
= tdefs
->args_ct_str
[i
];
1427 /* Incomplete TCGTargetOpDef entry? */
1428 assert(ct_str
!= NULL
);
1429 tcg_regset_clear(def
->args_ct
[i
].u
.regs
);
1430 def
->args_ct
[i
].ct
= 0;
1431 if (ct_str
[0] >= '0' && ct_str
[0] <= '9') {
1433 oarg
= ct_str
[0] - '0';
1434 assert(oarg
< def
->nb_oargs
);
1435 assert(def
->args_ct
[oarg
].ct
& TCG_CT_REG
);
1436 /* TCG_CT_ALIAS is for the output arguments. The input
1437 argument is tagged with TCG_CT_IALIAS. */
1438 def
->args_ct
[i
] = def
->args_ct
[oarg
];
1439 def
->args_ct
[oarg
].ct
= TCG_CT_ALIAS
;
1440 def
->args_ct
[oarg
].alias_index
= i
;
1441 def
->args_ct
[i
].ct
|= TCG_CT_IALIAS
;
1442 def
->args_ct
[i
].alias_index
= oarg
;
1445 if (*ct_str
== '\0')
1449 def
->args_ct
[i
].ct
|= TCG_CT_CONST
;
1453 if (target_parse_constraint(&def
->args_ct
[i
], &ct_str
) < 0) {
1454 fprintf(stderr
, "Invalid constraint '%s' for arg %d of operation '%s'\n",
1455 ct_str
, i
, def
->name
);
1463 /* TCGTargetOpDef entry with too much information? */
1464 assert(i
== TCG_MAX_OP_ARGS
|| tdefs
->args_ct_str
[i
] == NULL
);
1466 /* sort the constraints (XXX: this is just an heuristic) */
1467 sort_constraints(def
, 0, def
->nb_oargs
);
1468 sort_constraints(def
, def
->nb_oargs
, def
->nb_iargs
);
1474 printf("%s: sorted=", def
->name
);
1475 for(i
= 0; i
< def
->nb_oargs
+ def
->nb_iargs
; i
++)
1476 printf(" %d", def
->sorted_args
[i
]);
1483 #if defined(CONFIG_DEBUG_TCG)
1485 for (op
= 0; op
< ARRAY_SIZE(tcg_op_defs
); op
++) {
1486 const TCGOpDef
*def
= &tcg_op_defs
[op
];
1487 if (def
->flags
& TCG_OPF_NOT_PRESENT
) {
1488 /* Wrong entry in op definitions? */
1490 fprintf(stderr
, "Invalid op definition for %s\n", def
->name
);
1494 /* Missing entry in op definitions? */
1496 fprintf(stderr
, "Missing op definition for %s\n", def
->name
);
1507 #ifdef USE_LIVENESS_ANALYSIS
1509 /* set a nop for an operation using 'nb_args' */
1510 static inline void tcg_set_nop(TCGContext
*s
, uint16_t *opc_ptr
,
1511 TCGArg
*args
, int nb_args
)
1514 *opc_ptr
= INDEX_op_nop
;
1516 *opc_ptr
= INDEX_op_nopn
;
1518 args
[nb_args
- 1] = nb_args
;
1522 /* liveness analysis: end of function: all temps are dead, and globals
1523 should be in memory. */
1524 static inline void tcg_la_func_end(TCGContext
*s
, uint8_t *dead_temps
,
1527 memset(dead_temps
, 1, s
->nb_temps
);
1528 memset(mem_temps
, 1, s
->nb_globals
);
1529 memset(mem_temps
+ s
->nb_globals
, 0, s
->nb_temps
- s
->nb_globals
);
1532 /* liveness analysis: end of basic block: all temps are dead, globals
1533 and local temps should be in memory. */
1534 static inline void tcg_la_bb_end(TCGContext
*s
, uint8_t *dead_temps
,
1539 memset(dead_temps
, 1, s
->nb_temps
);
1540 memset(mem_temps
, 1, s
->nb_globals
);
1541 for(i
= s
->nb_globals
; i
< s
->nb_temps
; i
++) {
1542 mem_temps
[i
] = s
->temps
[i
].temp_local
;
1546 /* Liveness analysis : update the opc_dead_args array to tell if a
1547 given input arguments is dead. Instructions updating dead
1548 temporaries are removed. */
1549 static void tcg_liveness_analysis(TCGContext
*s
)
1551 int i
, op_index
, nb_args
, nb_iargs
, nb_oargs
, arg
, nb_ops
;
1552 TCGOpcode op
, op_new
, op_new2
;
1554 const TCGOpDef
*def
;
1555 uint8_t *dead_temps
, *mem_temps
;
1560 s
->gen_opc_ptr
++; /* skip end */
1562 nb_ops
= s
->gen_opc_ptr
- s
->gen_opc_buf
;
1564 s
->op_dead_args
= tcg_malloc(nb_ops
* sizeof(uint16_t));
1565 s
->op_sync_args
= tcg_malloc(nb_ops
* sizeof(uint8_t));
1567 dead_temps
= tcg_malloc(s
->nb_temps
);
1568 mem_temps
= tcg_malloc(s
->nb_temps
);
1569 tcg_la_func_end(s
, dead_temps
, mem_temps
);
1571 args
= s
->gen_opparam_ptr
;
1572 op_index
= nb_ops
- 1;
1573 while (op_index
>= 0) {
1574 op
= s
->gen_opc_buf
[op_index
];
1575 def
= &tcg_op_defs
[op
];
1583 nb_iargs
= args
[0] & 0xffff;
1584 nb_oargs
= args
[0] >> 16;
1586 call_flags
= args
[nb_oargs
+ nb_iargs
];
1588 /* pure functions can be removed if their result is not
1590 if (call_flags
& TCG_CALL_NO_SIDE_EFFECTS
) {
1591 for(i
= 0; i
< nb_oargs
; i
++) {
1593 if (!dead_temps
[arg
] || mem_temps
[arg
]) {
1594 goto do_not_remove_call
;
1597 tcg_set_nop(s
, s
->gen_opc_buf
+ op_index
,
1602 /* output args are dead */
1605 for(i
= 0; i
< nb_oargs
; i
++) {
1607 if (dead_temps
[arg
]) {
1608 dead_args
|= (1 << i
);
1610 if (mem_temps
[arg
]) {
1611 sync_args
|= (1 << i
);
1613 dead_temps
[arg
] = 1;
1617 if (!(call_flags
& TCG_CALL_NO_READ_GLOBALS
)) {
1618 /* globals should be synced to memory */
1619 memset(mem_temps
, 1, s
->nb_globals
);
1621 if (!(call_flags
& (TCG_CALL_NO_WRITE_GLOBALS
|
1622 TCG_CALL_NO_READ_GLOBALS
))) {
1623 /* globals should go back to memory */
1624 memset(dead_temps
, 1, s
->nb_globals
);
1627 /* input args are live */
1628 for(i
= nb_oargs
; i
< nb_iargs
+ nb_oargs
; i
++) {
1630 if (arg
!= TCG_CALL_DUMMY_ARG
) {
1631 if (dead_temps
[arg
]) {
1632 dead_args
|= (1 << i
);
1634 dead_temps
[arg
] = 0;
1637 s
->op_dead_args
[op_index
] = dead_args
;
1638 s
->op_sync_args
[op_index
] = sync_args
;
1643 case INDEX_op_debug_insn_start
:
1644 args
-= def
->nb_args
;
1650 case INDEX_op_discard
:
1652 /* mark the temporary as dead */
1653 dead_temps
[args
[0]] = 1;
1654 mem_temps
[args
[0]] = 0;
1659 case INDEX_op_add2_i32
:
1660 op_new
= INDEX_op_add_i32
;
1662 case INDEX_op_sub2_i32
:
1663 op_new
= INDEX_op_sub_i32
;
1665 case INDEX_op_add2_i64
:
1666 op_new
= INDEX_op_add_i64
;
1668 case INDEX_op_sub2_i64
:
1669 op_new
= INDEX_op_sub_i64
;
1674 /* Test if the high part of the operation is dead, but not
1675 the low part. The result can be optimized to a simple
1676 add or sub. This happens often for x86_64 guest when the
1677 cpu mode is set to 32 bit. */
1678 if (dead_temps
[args
[1]] && !mem_temps
[args
[1]]) {
1679 if (dead_temps
[args
[0]] && !mem_temps
[args
[0]]) {
1682 /* Create the single operation plus nop. */
1683 s
->gen_opc_buf
[op_index
] = op
= op_new
;
1686 assert(s
->gen_opc_buf
[op_index
+ 1] == INDEX_op_nop
);
1687 tcg_set_nop(s
, s
->gen_opc_buf
+ op_index
+ 1, args
+ 3, 3);
1688 /* Fall through and mark the single-word operation live. */
1694 case INDEX_op_mulu2_i32
:
1695 op_new
= INDEX_op_mul_i32
;
1696 op_new2
= INDEX_op_muluh_i32
;
1697 have_op_new2
= TCG_TARGET_HAS_muluh_i32
;
1699 case INDEX_op_muls2_i32
:
1700 op_new
= INDEX_op_mul_i32
;
1701 op_new2
= INDEX_op_mulsh_i32
;
1702 have_op_new2
= TCG_TARGET_HAS_mulsh_i32
;
1704 case INDEX_op_mulu2_i64
:
1705 op_new
= INDEX_op_mul_i64
;
1706 op_new2
= INDEX_op_muluh_i64
;
1707 have_op_new2
= TCG_TARGET_HAS_muluh_i64
;
1709 case INDEX_op_muls2_i64
:
1710 op_new
= INDEX_op_mul_i64
;
1711 op_new2
= INDEX_op_mulsh_i64
;
1712 have_op_new2
= TCG_TARGET_HAS_mulsh_i64
;
1718 if (dead_temps
[args
[1]] && !mem_temps
[args
[1]]) {
1719 if (dead_temps
[args
[0]] && !mem_temps
[args
[0]]) {
1720 /* Both parts of the operation are dead. */
1723 /* The high part of the operation is dead; generate the low. */
1724 s
->gen_opc_buf
[op_index
] = op
= op_new
;
1727 } else if (have_op_new2
&& dead_temps
[args
[0]]
1728 && !mem_temps
[args
[0]]) {
1729 /* The low part of the operation is dead; generate the high. */
1730 s
->gen_opc_buf
[op_index
] = op
= op_new2
;
1737 assert(s
->gen_opc_buf
[op_index
+ 1] == INDEX_op_nop
);
1738 tcg_set_nop(s
, s
->gen_opc_buf
+ op_index
+ 1, args
+ 3, 1);
1739 /* Mark the single-word operation live. */
1744 /* XXX: optimize by hardcoding common cases (e.g. triadic ops) */
1745 args
-= def
->nb_args
;
1746 nb_iargs
= def
->nb_iargs
;
1747 nb_oargs
= def
->nb_oargs
;
1749 /* Test if the operation can be removed because all
1750 its outputs are dead. We assume that nb_oargs == 0
1751 implies side effects */
1752 if (!(def
->flags
& TCG_OPF_SIDE_EFFECTS
) && nb_oargs
!= 0) {
1753 for(i
= 0; i
< nb_oargs
; i
++) {
1755 if (!dead_temps
[arg
] || mem_temps
[arg
]) {
1760 tcg_set_nop(s
, s
->gen_opc_buf
+ op_index
, args
, def
->nb_args
);
1761 #ifdef CONFIG_PROFILER
1767 /* output args are dead */
1770 for(i
= 0; i
< nb_oargs
; i
++) {
1772 if (dead_temps
[arg
]) {
1773 dead_args
|= (1 << i
);
1775 if (mem_temps
[arg
]) {
1776 sync_args
|= (1 << i
);
1778 dead_temps
[arg
] = 1;
1782 /* if end of basic block, update */
1783 if (def
->flags
& TCG_OPF_BB_END
) {
1784 tcg_la_bb_end(s
, dead_temps
, mem_temps
);
1785 } else if (def
->flags
& TCG_OPF_SIDE_EFFECTS
) {
1786 /* globals should be synced to memory */
1787 memset(mem_temps
, 1, s
->nb_globals
);
1790 /* input args are live */
1791 for(i
= nb_oargs
; i
< nb_oargs
+ nb_iargs
; i
++) {
1793 if (dead_temps
[arg
]) {
1794 dead_args
|= (1 << i
);
1796 dead_temps
[arg
] = 0;
1798 s
->op_dead_args
[op_index
] = dead_args
;
1799 s
->op_sync_args
[op_index
] = sync_args
;
1806 if (args
!= s
->gen_opparam_buf
) {
1811 /* dummy liveness analysis */
1812 static void tcg_liveness_analysis(TCGContext
*s
)
1815 nb_ops
= s
->gen_opc_ptr
- s
->gen_opc_buf
;
1817 s
->op_dead_args
= tcg_malloc(nb_ops
* sizeof(uint16_t));
1818 memset(s
->op_dead_args
, 0, nb_ops
* sizeof(uint16_t));
1819 s
->op_sync_args
= tcg_malloc(nb_ops
* sizeof(uint8_t));
1820 memset(s
->op_sync_args
, 0, nb_ops
* sizeof(uint8_t));
1825 static void dump_regs(TCGContext
*s
)
1831 for(i
= 0; i
< s
->nb_temps
; i
++) {
1833 printf(" %10s: ", tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), i
));
1834 switch(ts
->val_type
) {
1836 printf("%s", tcg_target_reg_names
[ts
->reg
]);
1839 printf("%d(%s)", (int)ts
->mem_offset
, tcg_target_reg_names
[ts
->mem_reg
]);
1841 case TEMP_VAL_CONST
:
1842 printf("$0x%" TCG_PRIlx
, ts
->val
);
1854 for(i
= 0; i
< TCG_TARGET_NB_REGS
; i
++) {
1855 if (s
->reg_to_temp
[i
] >= 0) {
1857 tcg_target_reg_names
[i
],
1858 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), s
->reg_to_temp
[i
]));
1863 static void check_regs(TCGContext
*s
)
1869 for(reg
= 0; reg
< TCG_TARGET_NB_REGS
; reg
++) {
1870 k
= s
->reg_to_temp
[reg
];
1873 if (ts
->val_type
!= TEMP_VAL_REG
||
1875 printf("Inconsistency for register %s:\n",
1876 tcg_target_reg_names
[reg
]);
1881 for(k
= 0; k
< s
->nb_temps
; k
++) {
1883 if (ts
->val_type
== TEMP_VAL_REG
&&
1885 s
->reg_to_temp
[ts
->reg
] != k
) {
1886 printf("Inconsistency for temp %s:\n",
1887 tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), k
));
1889 printf("reg state:\n");
1897 static void temp_allocate_frame(TCGContext
*s
, int temp
)
1900 ts
= &s
->temps
[temp
];
1901 #if !(defined(__sparc__) && TCG_TARGET_REG_BITS == 64)
1902 /* Sparc64 stack is accessed with offset of 2047 */
1903 s
->current_frame_offset
= (s
->current_frame_offset
+
1904 (tcg_target_long
)sizeof(tcg_target_long
) - 1) &
1905 ~(sizeof(tcg_target_long
) - 1);
1907 if (s
->current_frame_offset
+ (tcg_target_long
)sizeof(tcg_target_long
) >
1911 ts
->mem_offset
= s
->current_frame_offset
;
1912 ts
->mem_reg
= s
->frame_reg
;
1913 ts
->mem_allocated
= 1;
1914 s
->current_frame_offset
+= sizeof(tcg_target_long
);
1917 /* sync register 'reg' by saving it to the corresponding temporary */
1918 static inline void tcg_reg_sync(TCGContext
*s
, int reg
)
1923 temp
= s
->reg_to_temp
[reg
];
1924 ts
= &s
->temps
[temp
];
1925 assert(ts
->val_type
== TEMP_VAL_REG
);
1926 if (!ts
->mem_coherent
&& !ts
->fixed_reg
) {
1927 if (!ts
->mem_allocated
) {
1928 temp_allocate_frame(s
, temp
);
1930 tcg_out_st(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
1932 ts
->mem_coherent
= 1;
1935 /* free register 'reg' by spilling the corresponding temporary if necessary */
1936 static void tcg_reg_free(TCGContext
*s
, int reg
)
1940 temp
= s
->reg_to_temp
[reg
];
1942 tcg_reg_sync(s
, reg
);
1943 s
->temps
[temp
].val_type
= TEMP_VAL_MEM
;
1944 s
->reg_to_temp
[reg
] = -1;
1948 /* Allocate a register belonging to reg1 & ~reg2 */
1949 static int tcg_reg_alloc(TCGContext
*s
, TCGRegSet reg1
, TCGRegSet reg2
)
1954 tcg_regset_andnot(reg_ct
, reg1
, reg2
);
1956 /* first try free registers */
1957 for(i
= 0; i
< ARRAY_SIZE(tcg_target_reg_alloc_order
); i
++) {
1958 reg
= tcg_target_reg_alloc_order
[i
];
1959 if (tcg_regset_test_reg(reg_ct
, reg
) && s
->reg_to_temp
[reg
] == -1)
1963 /* XXX: do better spill choice */
1964 for(i
= 0; i
< ARRAY_SIZE(tcg_target_reg_alloc_order
); i
++) {
1965 reg
= tcg_target_reg_alloc_order
[i
];
1966 if (tcg_regset_test_reg(reg_ct
, reg
)) {
1967 tcg_reg_free(s
, reg
);
1975 /* mark a temporary as dead. */
1976 static inline void temp_dead(TCGContext
*s
, int temp
)
1980 ts
= &s
->temps
[temp
];
1981 if (!ts
->fixed_reg
) {
1982 if (ts
->val_type
== TEMP_VAL_REG
) {
1983 s
->reg_to_temp
[ts
->reg
] = -1;
1985 if (temp
< s
->nb_globals
|| ts
->temp_local
) {
1986 ts
->val_type
= TEMP_VAL_MEM
;
1988 ts
->val_type
= TEMP_VAL_DEAD
;
1993 /* sync a temporary to memory. 'allocated_regs' is used in case a
1994 temporary registers needs to be allocated to store a constant. */
1995 static inline void temp_sync(TCGContext
*s
, int temp
, TCGRegSet allocated_regs
)
1999 ts
= &s
->temps
[temp
];
2000 if (!ts
->fixed_reg
) {
2001 switch(ts
->val_type
) {
2002 case TEMP_VAL_CONST
:
2003 ts
->reg
= tcg_reg_alloc(s
, tcg_target_available_regs
[ts
->type
],
2005 ts
->val_type
= TEMP_VAL_REG
;
2006 s
->reg_to_temp
[ts
->reg
] = temp
;
2007 ts
->mem_coherent
= 0;
2008 tcg_out_movi(s
, ts
->type
, ts
->reg
, ts
->val
);
2011 tcg_reg_sync(s
, ts
->reg
);
2022 /* save a temporary to memory. 'allocated_regs' is used in case a
2023 temporary registers needs to be allocated to store a constant. */
2024 static inline void temp_save(TCGContext
*s
, int temp
, TCGRegSet allocated_regs
)
2026 #ifdef USE_LIVENESS_ANALYSIS
2027 /* The liveness analysis already ensures that globals are back
2028 in memory. Keep an assert for safety. */
2029 assert(s
->temps
[temp
].val_type
== TEMP_VAL_MEM
|| s
->temps
[temp
].fixed_reg
);
2031 temp_sync(s
, temp
, allocated_regs
);
2036 /* save globals to their canonical location and assume they can be
2037 modified be the following code. 'allocated_regs' is used in case a
2038 temporary registers needs to be allocated to store a constant. */
2039 static void save_globals(TCGContext
*s
, TCGRegSet allocated_regs
)
2043 for(i
= 0; i
< s
->nb_globals
; i
++) {
2044 temp_save(s
, i
, allocated_regs
);
2048 /* sync globals to their canonical location and assume they can be
2049 read by the following code. 'allocated_regs' is used in case a
2050 temporary registers needs to be allocated to store a constant. */
2051 static void sync_globals(TCGContext
*s
, TCGRegSet allocated_regs
)
2055 for (i
= 0; i
< s
->nb_globals
; i
++) {
2056 #ifdef USE_LIVENESS_ANALYSIS
2057 assert(s
->temps
[i
].val_type
!= TEMP_VAL_REG
|| s
->temps
[i
].fixed_reg
||
2058 s
->temps
[i
].mem_coherent
);
2060 temp_sync(s
, i
, allocated_regs
);
2065 /* at the end of a basic block, we assume all temporaries are dead and
2066 all globals are stored at their canonical location. */
2067 static void tcg_reg_alloc_bb_end(TCGContext
*s
, TCGRegSet allocated_regs
)
2072 for(i
= s
->nb_globals
; i
< s
->nb_temps
; i
++) {
2074 if (ts
->temp_local
) {
2075 temp_save(s
, i
, allocated_regs
);
2077 #ifdef USE_LIVENESS_ANALYSIS
2078 /* The liveness analysis already ensures that temps are dead.
2079 Keep an assert for safety. */
2080 assert(ts
->val_type
== TEMP_VAL_DEAD
);
2087 save_globals(s
, allocated_regs
);
2090 #define IS_DEAD_ARG(n) ((dead_args >> (n)) & 1)
2091 #define NEED_SYNC_ARG(n) ((sync_args >> (n)) & 1)
2093 static void tcg_reg_alloc_movi(TCGContext
*s
, const TCGArg
*args
,
2094 uint16_t dead_args
, uint8_t sync_args
)
2097 tcg_target_ulong val
;
2099 ots
= &s
->temps
[args
[0]];
2102 if (ots
->fixed_reg
) {
2103 /* for fixed registers, we do not do any constant
2105 tcg_out_movi(s
, ots
->type
, ots
->reg
, val
);
2107 /* The movi is not explicitly generated here */
2108 if (ots
->val_type
== TEMP_VAL_REG
)
2109 s
->reg_to_temp
[ots
->reg
] = -1;
2110 ots
->val_type
= TEMP_VAL_CONST
;
2113 if (NEED_SYNC_ARG(0)) {
2114 temp_sync(s
, args
[0], s
->reserved_regs
);
2116 if (IS_DEAD_ARG(0)) {
2117 temp_dead(s
, args
[0]);
2121 static void tcg_reg_alloc_mov(TCGContext
*s
, const TCGOpDef
*def
,
2122 const TCGArg
*args
, uint16_t dead_args
,
2125 TCGRegSet allocated_regs
;
2127 const TCGArgConstraint
*arg_ct
, *oarg_ct
;
2129 tcg_regset_set(allocated_regs
, s
->reserved_regs
);
2130 ots
= &s
->temps
[args
[0]];
2131 ts
= &s
->temps
[args
[1]];
2132 oarg_ct
= &def
->args_ct
[0];
2133 arg_ct
= &def
->args_ct
[1];
2135 /* If the source value is not in a register, and we're going to be
2136 forced to have it in a register in order to perform the copy,
2137 then copy the SOURCE value into its own register first. That way
2138 we don't have to reload SOURCE the next time it is used. */
2139 if (((NEED_SYNC_ARG(0) || ots
->fixed_reg
) && ts
->val_type
!= TEMP_VAL_REG
)
2140 || ts
->val_type
== TEMP_VAL_MEM
) {
2141 ts
->reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
2142 if (ts
->val_type
== TEMP_VAL_MEM
) {
2143 tcg_out_ld(s
, ts
->type
, ts
->reg
, ts
->mem_reg
, ts
->mem_offset
);
2144 ts
->mem_coherent
= 1;
2145 } else if (ts
->val_type
== TEMP_VAL_CONST
) {
2146 tcg_out_movi(s
, ts
->type
, ts
->reg
, ts
->val
);
2148 s
->reg_to_temp
[ts
->reg
] = args
[1];
2149 ts
->val_type
= TEMP_VAL_REG
;
2152 if (IS_DEAD_ARG(0) && !ots
->fixed_reg
) {
2153 /* mov to a non-saved dead register makes no sense (even with
2154 liveness analysis disabled). */
2155 assert(NEED_SYNC_ARG(0));
2156 /* The code above should have moved the temp to a register. */
2157 assert(ts
->val_type
== TEMP_VAL_REG
);
2158 if (!ots
->mem_allocated
) {
2159 temp_allocate_frame(s
, args
[0]);
2161 tcg_out_st(s
, ots
->type
, ts
->reg
, ots
->mem_reg
, ots
->mem_offset
);
2162 if (IS_DEAD_ARG(1)) {
2163 temp_dead(s
, args
[1]);
2165 temp_dead(s
, args
[0]);
2166 } else if (ts
->val_type
== TEMP_VAL_CONST
) {
2167 /* propagate constant */
2168 if (ots
->val_type
== TEMP_VAL_REG
) {
2169 s
->reg_to_temp
[ots
->reg
] = -1;
2171 ots
->val_type
= TEMP_VAL_CONST
;
2174 /* The code in the first if block should have moved the
2175 temp to a register. */
2176 assert(ts
->val_type
== TEMP_VAL_REG
);
2177 if (IS_DEAD_ARG(1) && !ts
->fixed_reg
&& !ots
->fixed_reg
) {
2178 /* the mov can be suppressed */
2179 if (ots
->val_type
== TEMP_VAL_REG
) {
2180 s
->reg_to_temp
[ots
->reg
] = -1;
2183 temp_dead(s
, args
[1]);
2185 if (ots
->val_type
!= TEMP_VAL_REG
) {
2186 /* When allocating a new register, make sure to not spill the
2188 tcg_regset_set_reg(allocated_regs
, ts
->reg
);
2189 ots
->reg
= tcg_reg_alloc(s
, oarg_ct
->u
.regs
, allocated_regs
);
2191 tcg_out_mov(s
, ots
->type
, ots
->reg
, ts
->reg
);
2193 ots
->val_type
= TEMP_VAL_REG
;
2194 ots
->mem_coherent
= 0;
2195 s
->reg_to_temp
[ots
->reg
] = args
[0];
2196 if (NEED_SYNC_ARG(0)) {
2197 tcg_reg_sync(s
, ots
->reg
);
2202 static void tcg_reg_alloc_op(TCGContext
*s
,
2203 const TCGOpDef
*def
, TCGOpcode opc
,
2204 const TCGArg
*args
, uint16_t dead_args
,
2207 TCGRegSet allocated_regs
;
2208 int i
, k
, nb_iargs
, nb_oargs
, reg
;
2210 const TCGArgConstraint
*arg_ct
;
2212 TCGArg new_args
[TCG_MAX_OP_ARGS
];
2213 int const_args
[TCG_MAX_OP_ARGS
];
2215 nb_oargs
= def
->nb_oargs
;
2216 nb_iargs
= def
->nb_iargs
;
2218 /* copy constants */
2219 memcpy(new_args
+ nb_oargs
+ nb_iargs
,
2220 args
+ nb_oargs
+ nb_iargs
,
2221 sizeof(TCGArg
) * def
->nb_cargs
);
2223 /* satisfy input constraints */
2224 tcg_regset_set(allocated_regs
, s
->reserved_regs
);
2225 for(k
= 0; k
< nb_iargs
; k
++) {
2226 i
= def
->sorted_args
[nb_oargs
+ k
];
2228 arg_ct
= &def
->args_ct
[i
];
2229 ts
= &s
->temps
[arg
];
2230 if (ts
->val_type
== TEMP_VAL_MEM
) {
2231 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
2232 tcg_out_ld(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
2233 ts
->val_type
= TEMP_VAL_REG
;
2235 ts
->mem_coherent
= 1;
2236 s
->reg_to_temp
[reg
] = arg
;
2237 } else if (ts
->val_type
== TEMP_VAL_CONST
) {
2238 if (tcg_target_const_match(ts
->val
, ts
->type
, arg_ct
)) {
2239 /* constant is OK for instruction */
2241 new_args
[i
] = ts
->val
;
2244 /* need to move to a register */
2245 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
2246 tcg_out_movi(s
, ts
->type
, reg
, ts
->val
);
2247 ts
->val_type
= TEMP_VAL_REG
;
2249 ts
->mem_coherent
= 0;
2250 s
->reg_to_temp
[reg
] = arg
;
2253 assert(ts
->val_type
== TEMP_VAL_REG
);
2254 if (arg_ct
->ct
& TCG_CT_IALIAS
) {
2255 if (ts
->fixed_reg
) {
2256 /* if fixed register, we must allocate a new register
2257 if the alias is not the same register */
2258 if (arg
!= args
[arg_ct
->alias_index
])
2259 goto allocate_in_reg
;
2261 /* if the input is aliased to an output and if it is
2262 not dead after the instruction, we must allocate
2263 a new register and move it */
2264 if (!IS_DEAD_ARG(i
)) {
2265 goto allocate_in_reg
;
2270 if (tcg_regset_test_reg(arg_ct
->u
.regs
, reg
)) {
2271 /* nothing to do : the constraint is satisfied */
2274 /* allocate a new register matching the constraint
2275 and move the temporary register into it */
2276 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
2277 tcg_out_mov(s
, ts
->type
, reg
, ts
->reg
);
2281 tcg_regset_set_reg(allocated_regs
, reg
);
2285 /* mark dead temporaries and free the associated registers */
2286 for (i
= nb_oargs
; i
< nb_oargs
+ nb_iargs
; i
++) {
2287 if (IS_DEAD_ARG(i
)) {
2288 temp_dead(s
, args
[i
]);
2292 if (def
->flags
& TCG_OPF_BB_END
) {
2293 tcg_reg_alloc_bb_end(s
, allocated_regs
);
2295 if (def
->flags
& TCG_OPF_CALL_CLOBBER
) {
2296 /* XXX: permit generic clobber register list ? */
2297 for(reg
= 0; reg
< TCG_TARGET_NB_REGS
; reg
++) {
2298 if (tcg_regset_test_reg(tcg_target_call_clobber_regs
, reg
)) {
2299 tcg_reg_free(s
, reg
);
2303 if (def
->flags
& TCG_OPF_SIDE_EFFECTS
) {
2304 /* sync globals if the op has side effects and might trigger
2306 sync_globals(s
, allocated_regs
);
2309 /* satisfy the output constraints */
2310 tcg_regset_set(allocated_regs
, s
->reserved_regs
);
2311 for(k
= 0; k
< nb_oargs
; k
++) {
2312 i
= def
->sorted_args
[k
];
2314 arg_ct
= &def
->args_ct
[i
];
2315 ts
= &s
->temps
[arg
];
2316 if (arg_ct
->ct
& TCG_CT_ALIAS
) {
2317 reg
= new_args
[arg_ct
->alias_index
];
2319 /* if fixed register, we try to use it */
2321 if (ts
->fixed_reg
&&
2322 tcg_regset_test_reg(arg_ct
->u
.regs
, reg
)) {
2325 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
2327 tcg_regset_set_reg(allocated_regs
, reg
);
2328 /* if a fixed register is used, then a move will be done afterwards */
2329 if (!ts
->fixed_reg
) {
2330 if (ts
->val_type
== TEMP_VAL_REG
) {
2331 s
->reg_to_temp
[ts
->reg
] = -1;
2333 ts
->val_type
= TEMP_VAL_REG
;
2335 /* temp value is modified, so the value kept in memory is
2336 potentially not the same */
2337 ts
->mem_coherent
= 0;
2338 s
->reg_to_temp
[reg
] = arg
;
2345 /* emit instruction */
2346 tcg_out_op(s
, opc
, new_args
, const_args
);
2348 /* move the outputs in the correct register if needed */
2349 for(i
= 0; i
< nb_oargs
; i
++) {
2350 ts
= &s
->temps
[args
[i
]];
2352 if (ts
->fixed_reg
&& ts
->reg
!= reg
) {
2353 tcg_out_mov(s
, ts
->type
, ts
->reg
, reg
);
2355 if (NEED_SYNC_ARG(i
)) {
2356 tcg_reg_sync(s
, reg
);
2358 if (IS_DEAD_ARG(i
)) {
2359 temp_dead(s
, args
[i
]);
2364 #ifdef TCG_TARGET_STACK_GROWSUP
2365 #define STACK_DIR(x) (-(x))
2367 #define STACK_DIR(x) (x)
2370 static int tcg_reg_alloc_call(TCGContext
*s
, const TCGOpDef
*def
,
2371 TCGOpcode opc
, const TCGArg
*args
,
2372 uint16_t dead_args
, uint8_t sync_args
)
2374 int nb_iargs
, nb_oargs
, flags
, nb_regs
, i
, reg
, nb_params
;
2375 TCGArg arg
, func_arg
;
2377 intptr_t stack_offset
;
2378 size_t call_stack_size
;
2379 uintptr_t func_addr
;
2380 int const_func_arg
, allocate_args
;
2381 TCGRegSet allocated_regs
;
2382 const TCGArgConstraint
*arg_ct
;
2386 nb_oargs
= arg
>> 16;
2387 nb_iargs
= arg
& 0xffff;
2388 nb_params
= nb_iargs
- 1;
2390 flags
= args
[nb_oargs
+ nb_iargs
];
2392 nb_regs
= ARRAY_SIZE(tcg_target_call_iarg_regs
);
2393 if (nb_regs
> nb_params
)
2394 nb_regs
= nb_params
;
2396 /* assign stack slots first */
2397 call_stack_size
= (nb_params
- nb_regs
) * sizeof(tcg_target_long
);
2398 call_stack_size
= (call_stack_size
+ TCG_TARGET_STACK_ALIGN
- 1) &
2399 ~(TCG_TARGET_STACK_ALIGN
- 1);
2400 allocate_args
= (call_stack_size
> TCG_STATIC_CALL_ARGS_SIZE
);
2401 if (allocate_args
) {
2402 /* XXX: if more than TCG_STATIC_CALL_ARGS_SIZE is needed,
2403 preallocate call stack */
2407 stack_offset
= TCG_TARGET_CALL_STACK_OFFSET
;
2408 for(i
= nb_regs
; i
< nb_params
; i
++) {
2409 arg
= args
[nb_oargs
+ i
];
2410 #ifdef TCG_TARGET_STACK_GROWSUP
2411 stack_offset
-= sizeof(tcg_target_long
);
2413 if (arg
!= TCG_CALL_DUMMY_ARG
) {
2414 ts
= &s
->temps
[arg
];
2415 if (ts
->val_type
== TEMP_VAL_REG
) {
2416 tcg_out_st(s
, ts
->type
, ts
->reg
, TCG_REG_CALL_STACK
, stack_offset
);
2417 } else if (ts
->val_type
== TEMP_VAL_MEM
) {
2418 reg
= tcg_reg_alloc(s
, tcg_target_available_regs
[ts
->type
],
2420 /* XXX: not correct if reading values from the stack */
2421 tcg_out_ld(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
2422 tcg_out_st(s
, ts
->type
, reg
, TCG_REG_CALL_STACK
, stack_offset
);
2423 } else if (ts
->val_type
== TEMP_VAL_CONST
) {
2424 reg
= tcg_reg_alloc(s
, tcg_target_available_regs
[ts
->type
],
2426 /* XXX: sign extend may be needed on some targets */
2427 tcg_out_movi(s
, ts
->type
, reg
, ts
->val
);
2428 tcg_out_st(s
, ts
->type
, reg
, TCG_REG_CALL_STACK
, stack_offset
);
2433 #ifndef TCG_TARGET_STACK_GROWSUP
2434 stack_offset
+= sizeof(tcg_target_long
);
2438 /* assign input registers */
2439 tcg_regset_set(allocated_regs
, s
->reserved_regs
);
2440 for(i
= 0; i
< nb_regs
; i
++) {
2441 arg
= args
[nb_oargs
+ i
];
2442 if (arg
!= TCG_CALL_DUMMY_ARG
) {
2443 ts
= &s
->temps
[arg
];
2444 reg
= tcg_target_call_iarg_regs
[i
];
2445 tcg_reg_free(s
, reg
);
2446 if (ts
->val_type
== TEMP_VAL_REG
) {
2447 if (ts
->reg
!= reg
) {
2448 tcg_out_mov(s
, ts
->type
, reg
, ts
->reg
);
2450 } else if (ts
->val_type
== TEMP_VAL_MEM
) {
2451 tcg_out_ld(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
2452 } else if (ts
->val_type
== TEMP_VAL_CONST
) {
2453 /* XXX: sign extend ? */
2454 tcg_out_movi(s
, ts
->type
, reg
, ts
->val
);
2458 tcg_regset_set_reg(allocated_regs
, reg
);
2462 /* assign function address */
2463 func_arg
= args
[nb_oargs
+ nb_iargs
- 1];
2464 arg_ct
= &def
->args_ct
[0];
2465 ts
= &s
->temps
[func_arg
];
2466 func_addr
= ts
->val
;
2468 if (ts
->val_type
== TEMP_VAL_MEM
) {
2469 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
2470 tcg_out_ld(s
, ts
->type
, reg
, ts
->mem_reg
, ts
->mem_offset
);
2472 tcg_regset_set_reg(allocated_regs
, reg
);
2473 } else if (ts
->val_type
== TEMP_VAL_REG
) {
2475 if (!tcg_regset_test_reg(arg_ct
->u
.regs
, reg
)) {
2476 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
2477 tcg_out_mov(s
, ts
->type
, reg
, ts
->reg
);
2480 tcg_regset_set_reg(allocated_regs
, reg
);
2481 } else if (ts
->val_type
== TEMP_VAL_CONST
) {
2482 if (tcg_target_const_match(func_addr
, ts
->type
, arg_ct
)) {
2484 func_arg
= func_addr
;
2486 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
);
2487 tcg_out_movi(s
, ts
->type
, reg
, func_addr
);
2489 tcg_regset_set_reg(allocated_regs
, reg
);
2496 /* mark dead temporaries and free the associated registers */
2497 for(i
= nb_oargs
; i
< nb_iargs
+ nb_oargs
; i
++) {
2498 if (IS_DEAD_ARG(i
)) {
2499 temp_dead(s
, args
[i
]);
2503 /* clobber call registers */
2504 for(reg
= 0; reg
< TCG_TARGET_NB_REGS
; reg
++) {
2505 if (tcg_regset_test_reg(tcg_target_call_clobber_regs
, reg
)) {
2506 tcg_reg_free(s
, reg
);
2510 /* Save globals if they might be written by the helper, sync them if
2511 they might be read. */
2512 if (flags
& TCG_CALL_NO_READ_GLOBALS
) {
2514 } else if (flags
& TCG_CALL_NO_WRITE_GLOBALS
) {
2515 sync_globals(s
, allocated_regs
);
2517 save_globals(s
, allocated_regs
);
2520 tcg_out_op(s
, opc
, &func_arg
, &const_func_arg
);
2522 /* assign output registers and emit moves if needed */
2523 for(i
= 0; i
< nb_oargs
; i
++) {
2525 ts
= &s
->temps
[arg
];
2526 reg
= tcg_target_call_oarg_regs
[i
];
2527 assert(s
->reg_to_temp
[reg
] == -1);
2529 if (ts
->fixed_reg
) {
2530 if (ts
->reg
!= reg
) {
2531 tcg_out_mov(s
, ts
->type
, ts
->reg
, reg
);
2534 if (ts
->val_type
== TEMP_VAL_REG
) {
2535 s
->reg_to_temp
[ts
->reg
] = -1;
2537 ts
->val_type
= TEMP_VAL_REG
;
2539 ts
->mem_coherent
= 0;
2540 s
->reg_to_temp
[reg
] = arg
;
2541 if (NEED_SYNC_ARG(i
)) {
2542 tcg_reg_sync(s
, reg
);
2544 if (IS_DEAD_ARG(i
)) {
2545 temp_dead(s
, args
[i
]);
2550 return nb_iargs
+ nb_oargs
+ def
->nb_cargs
+ 1;
2553 #ifdef CONFIG_PROFILER
2555 static int64_t tcg_table_op_count
[NB_OPS
];
2557 static void dump_op_count(void)
2561 f
= fopen("/tmp/op.log", "w");
2562 for(i
= INDEX_op_end
; i
< NB_OPS
; i
++) {
2563 fprintf(f
, "%s %" PRId64
"\n", tcg_op_defs
[i
].name
, tcg_table_op_count
[i
]);
2570 static inline int tcg_gen_code_common(TCGContext
*s
,
2571 tcg_insn_unit
*gen_code_buf
,
2576 const TCGOpDef
*def
;
2580 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP
))) {
2587 #ifdef CONFIG_PROFILER
2588 s
->opt_time
-= profile_getclock();
2591 #ifdef USE_TCG_OPTIMIZATIONS
2592 s
->gen_opparam_ptr
=
2593 tcg_optimize(s
, s
->gen_opc_ptr
, s
->gen_opparam_buf
, tcg_op_defs
);
2596 #ifdef CONFIG_PROFILER
2597 s
->opt_time
+= profile_getclock();
2598 s
->la_time
-= profile_getclock();
2601 tcg_liveness_analysis(s
);
2603 #ifdef CONFIG_PROFILER
2604 s
->la_time
+= profile_getclock();
2608 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_OPT
))) {
2609 qemu_log("OP after optimization and liveness analysis:\n");
2615 tcg_reg_alloc_start(s
);
2617 s
->code_buf
= gen_code_buf
;
2618 s
->code_ptr
= gen_code_buf
;
2622 args
= s
->gen_opparam_buf
;
2626 opc
= s
->gen_opc_buf
[op_index
];
2627 #ifdef CONFIG_PROFILER
2628 tcg_table_op_count
[opc
]++;
2630 def
= &tcg_op_defs
[opc
];
2632 printf("%s: %d %d %d\n", def
->name
,
2633 def
->nb_oargs
, def
->nb_iargs
, def
->nb_cargs
);
2637 case INDEX_op_mov_i32
:
2638 case INDEX_op_mov_i64
:
2639 tcg_reg_alloc_mov(s
, def
, args
, s
->op_dead_args
[op_index
],
2640 s
->op_sync_args
[op_index
]);
2642 case INDEX_op_movi_i32
:
2643 case INDEX_op_movi_i64
:
2644 tcg_reg_alloc_movi(s
, args
, s
->op_dead_args
[op_index
],
2645 s
->op_sync_args
[op_index
]);
2647 case INDEX_op_debug_insn_start
:
2648 /* debug instruction */
2658 case INDEX_op_discard
:
2659 temp_dead(s
, args
[0]);
2661 case INDEX_op_set_label
:
2662 tcg_reg_alloc_bb_end(s
, s
->reserved_regs
);
2663 tcg_out_label(s
, args
[0], s
->code_ptr
);
2666 args
+= tcg_reg_alloc_call(s
, def
, opc
, args
,
2667 s
->op_dead_args
[op_index
],
2668 s
->op_sync_args
[op_index
]);
2673 /* Sanity check that we've not introduced any unhandled opcodes. */
2674 if (def
->flags
& TCG_OPF_NOT_PRESENT
) {
2677 /* Note: in order to speed up the code, it would be much
2678 faster to have specialized register allocator functions for
2679 some common argument patterns */
2680 tcg_reg_alloc_op(s
, def
, opc
, args
, s
->op_dead_args
[op_index
],
2681 s
->op_sync_args
[op_index
]);
2684 args
+= def
->nb_args
;
2686 if (search_pc
>= 0 && search_pc
< tcg_current_code_size(s
)) {
2695 /* Generate TB finalization at the end of block */
2696 tcg_out_tb_finalize(s
);
2700 int tcg_gen_code(TCGContext
*s
, tcg_insn_unit
*gen_code_buf
)
2702 #ifdef CONFIG_PROFILER
2705 n
= (s
->gen_opc_ptr
- s
->gen_opc_buf
);
2707 if (n
> s
->op_count_max
)
2708 s
->op_count_max
= n
;
2710 s
->temp_count
+= s
->nb_temps
;
2711 if (s
->nb_temps
> s
->temp_count_max
)
2712 s
->temp_count_max
= s
->nb_temps
;
2716 tcg_gen_code_common(s
, gen_code_buf
, -1);
2718 /* flush instruction cache */
2719 flush_icache_range((uintptr_t)s
->code_buf
, (uintptr_t)s
->code_ptr
);
2721 return tcg_current_code_size(s
);
2724 /* Return the index of the micro operation such as the pc after is <
2725 offset bytes from the start of the TB. The contents of gen_code_buf must
2726 not be changed, though writing the same values is ok.
2727 Return -1 if not found. */
2728 int tcg_gen_code_search_pc(TCGContext
*s
, tcg_insn_unit
*gen_code_buf
,
2731 return tcg_gen_code_common(s
, gen_code_buf
, offset
);
2734 #ifdef CONFIG_PROFILER
2735 void tcg_dump_info(FILE *f
, fprintf_function cpu_fprintf
)
2737 TCGContext
*s
= &tcg_ctx
;
2740 tot
= s
->interm_time
+ s
->code_time
;
2741 cpu_fprintf(f
, "JIT cycles %" PRId64
" (%0.3f s at 2.4 GHz)\n",
2743 cpu_fprintf(f
, "translated TBs %" PRId64
" (aborted=%" PRId64
" %0.1f%%)\n",
2745 s
->tb_count1
- s
->tb_count
,
2746 s
->tb_count1
? (double)(s
->tb_count1
- s
->tb_count
) / s
->tb_count1
* 100.0 : 0);
2747 cpu_fprintf(f
, "avg ops/TB %0.1f max=%d\n",
2748 s
->tb_count
? (double)s
->op_count
/ s
->tb_count
: 0, s
->op_count_max
);
2749 cpu_fprintf(f
, "deleted ops/TB %0.2f\n",
2751 (double)s
->del_op_count
/ s
->tb_count
: 0);
2752 cpu_fprintf(f
, "avg temps/TB %0.2f max=%d\n",
2754 (double)s
->temp_count
/ s
->tb_count
: 0,
2757 cpu_fprintf(f
, "cycles/op %0.1f\n",
2758 s
->op_count
? (double)tot
/ s
->op_count
: 0);
2759 cpu_fprintf(f
, "cycles/in byte %0.1f\n",
2760 s
->code_in_len
? (double)tot
/ s
->code_in_len
: 0);
2761 cpu_fprintf(f
, "cycles/out byte %0.1f\n",
2762 s
->code_out_len
? (double)tot
/ s
->code_out_len
: 0);
2765 cpu_fprintf(f
, " gen_interm time %0.1f%%\n",
2766 (double)s
->interm_time
/ tot
* 100.0);
2767 cpu_fprintf(f
, " gen_code time %0.1f%%\n",
2768 (double)s
->code_time
/ tot
* 100.0);
2769 cpu_fprintf(f
, "optim./code time %0.1f%%\n",
2770 (double)s
->opt_time
/ (s
->code_time
? s
->code_time
: 1)
2772 cpu_fprintf(f
, "liveness/code time %0.1f%%\n",
2773 (double)s
->la_time
/ (s
->code_time
? s
->code_time
: 1) * 100.0);
2774 cpu_fprintf(f
, "cpu_restore count %" PRId64
"\n",
2776 cpu_fprintf(f
, " avg cycles %0.1f\n",
2777 s
->restore_count
? (double)s
->restore_time
/ s
->restore_count
: 0);
2782 void tcg_dump_info(FILE *f
, fprintf_function cpu_fprintf
)
2784 cpu_fprintf(f
, "[TCG profiler not compiled]\n");
2788 #ifdef ELF_HOST_MACHINE
2789 /* In order to use this feature, the backend needs to do three things:
2791 (1) Define ELF_HOST_MACHINE to indicate both what value to
2792 put into the ELF image and to indicate support for the feature.
2794 (2) Define tcg_register_jit. This should create a buffer containing
2795 the contents of a .debug_frame section that describes the post-
2796 prologue unwind info for the tcg machine.
2798 (3) Call tcg_register_jit_int, with the constructed .debug_frame.
2801 /* Begin GDB interface. THE FOLLOWING MUST MATCH GDB DOCS. */
2808 struct jit_code_entry
{
2809 struct jit_code_entry
*next_entry
;
2810 struct jit_code_entry
*prev_entry
;
2811 const void *symfile_addr
;
2812 uint64_t symfile_size
;
2815 struct jit_descriptor
{
2817 uint32_t action_flag
;
2818 struct jit_code_entry
*relevant_entry
;
2819 struct jit_code_entry
*first_entry
;
2822 void __jit_debug_register_code(void) __attribute__((noinline
));
2823 void __jit_debug_register_code(void)
2828 /* Must statically initialize the version, because GDB may check
2829 the version before we can set it. */
2830 struct jit_descriptor __jit_debug_descriptor
= { 1, 0, 0, 0 };
2832 /* End GDB interface. */
2834 static int find_string(const char *strtab
, const char *str
)
2836 const char *p
= strtab
+ 1;
2839 if (strcmp(p
, str
) == 0) {
2846 static void tcg_register_jit_int(void *buf_ptr
, size_t buf_size
,
2847 void *debug_frame
, size_t debug_frame_size
)
2849 struct __attribute__((packed
)) DebugInfo
{
2856 uintptr_t cu_low_pc
;
2857 uintptr_t cu_high_pc
;
2860 uintptr_t fn_low_pc
;
2861 uintptr_t fn_high_pc
;
2870 struct DebugInfo di
;
2875 struct ElfImage
*img
;
2877 static const struct ElfImage img_template
= {
2879 .e_ident
[EI_MAG0
] = ELFMAG0
,
2880 .e_ident
[EI_MAG1
] = ELFMAG1
,
2881 .e_ident
[EI_MAG2
] = ELFMAG2
,
2882 .e_ident
[EI_MAG3
] = ELFMAG3
,
2883 .e_ident
[EI_CLASS
] = ELF_CLASS
,
2884 .e_ident
[EI_DATA
] = ELF_DATA
,
2885 .e_ident
[EI_VERSION
] = EV_CURRENT
,
2887 .e_machine
= ELF_HOST_MACHINE
,
2888 .e_version
= EV_CURRENT
,
2889 .e_phoff
= offsetof(struct ElfImage
, phdr
),
2890 .e_shoff
= offsetof(struct ElfImage
, shdr
),
2891 .e_ehsize
= sizeof(ElfW(Shdr
)),
2892 .e_phentsize
= sizeof(ElfW(Phdr
)),
2894 .e_shentsize
= sizeof(ElfW(Shdr
)),
2895 .e_shnum
= ARRAY_SIZE(img
->shdr
),
2896 .e_shstrndx
= ARRAY_SIZE(img
->shdr
) - 1,
2897 #ifdef ELF_HOST_FLAGS
2898 .e_flags
= ELF_HOST_FLAGS
,
2901 .e_ident
[EI_OSABI
] = ELF_OSABI
,
2909 [0] = { .sh_type
= SHT_NULL
},
2910 /* Trick: The contents of code_gen_buffer are not present in
2911 this fake ELF file; that got allocated elsewhere. Therefore
2912 we mark .text as SHT_NOBITS (similar to .bss) so that readers
2913 will not look for contents. We can record any address. */
2915 .sh_type
= SHT_NOBITS
,
2916 .sh_flags
= SHF_EXECINSTR
| SHF_ALLOC
,
2918 [2] = { /* .debug_info */
2919 .sh_type
= SHT_PROGBITS
,
2920 .sh_offset
= offsetof(struct ElfImage
, di
),
2921 .sh_size
= sizeof(struct DebugInfo
),
2923 [3] = { /* .debug_abbrev */
2924 .sh_type
= SHT_PROGBITS
,
2925 .sh_offset
= offsetof(struct ElfImage
, da
),
2926 .sh_size
= sizeof(img
->da
),
2928 [4] = { /* .debug_frame */
2929 .sh_type
= SHT_PROGBITS
,
2930 .sh_offset
= sizeof(struct ElfImage
),
2932 [5] = { /* .symtab */
2933 .sh_type
= SHT_SYMTAB
,
2934 .sh_offset
= offsetof(struct ElfImage
, sym
),
2935 .sh_size
= sizeof(img
->sym
),
2937 .sh_link
= ARRAY_SIZE(img
->shdr
) - 1,
2938 .sh_entsize
= sizeof(ElfW(Sym
)),
2940 [6] = { /* .strtab */
2941 .sh_type
= SHT_STRTAB
,
2942 .sh_offset
= offsetof(struct ElfImage
, str
),
2943 .sh_size
= sizeof(img
->str
),
2947 [1] = { /* code_gen_buffer */
2948 .st_info
= ELF_ST_INFO(STB_GLOBAL
, STT_FUNC
),
2953 .len
= sizeof(struct DebugInfo
) - 4,
2955 .ptr_size
= sizeof(void *),
2957 .cu_lang
= 0x8001, /* DW_LANG_Mips_Assembler */
2959 .fn_name
= "code_gen_buffer"
2962 1, /* abbrev number (the cu) */
2963 0x11, 1, /* DW_TAG_compile_unit, has children */
2964 0x13, 0x5, /* DW_AT_language, DW_FORM_data2 */
2965 0x11, 0x1, /* DW_AT_low_pc, DW_FORM_addr */
2966 0x12, 0x1, /* DW_AT_high_pc, DW_FORM_addr */
2967 0, 0, /* end of abbrev */
2968 2, /* abbrev number (the fn) */
2969 0x2e, 0, /* DW_TAG_subprogram, no children */
2970 0x3, 0x8, /* DW_AT_name, DW_FORM_string */
2971 0x11, 0x1, /* DW_AT_low_pc, DW_FORM_addr */
2972 0x12, 0x1, /* DW_AT_high_pc, DW_FORM_addr */
2973 0, 0, /* end of abbrev */
2974 0 /* no more abbrev */
2976 .str
= "\0" ".text\0" ".debug_info\0" ".debug_abbrev\0"
2977 ".debug_frame\0" ".symtab\0" ".strtab\0" "code_gen_buffer",
2980 /* We only need a single jit entry; statically allocate it. */
2981 static struct jit_code_entry one_entry
;
2983 uintptr_t buf
= (uintptr_t)buf_ptr
;
2984 size_t img_size
= sizeof(struct ElfImage
) + debug_frame_size
;
2986 img
= g_malloc(img_size
);
2987 *img
= img_template
;
2988 memcpy(img
+ 1, debug_frame
, debug_frame_size
);
2990 img
->phdr
.p_vaddr
= buf
;
2991 img
->phdr
.p_paddr
= buf
;
2992 img
->phdr
.p_memsz
= buf_size
;
2994 img
->shdr
[1].sh_name
= find_string(img
->str
, ".text");
2995 img
->shdr
[1].sh_addr
= buf
;
2996 img
->shdr
[1].sh_size
= buf_size
;
2998 img
->shdr
[2].sh_name
= find_string(img
->str
, ".debug_info");
2999 img
->shdr
[3].sh_name
= find_string(img
->str
, ".debug_abbrev");
3001 img
->shdr
[4].sh_name
= find_string(img
->str
, ".debug_frame");
3002 img
->shdr
[4].sh_size
= debug_frame_size
;
3004 img
->shdr
[5].sh_name
= find_string(img
->str
, ".symtab");
3005 img
->shdr
[6].sh_name
= find_string(img
->str
, ".strtab");
3007 img
->sym
[1].st_name
= find_string(img
->str
, "code_gen_buffer");
3008 img
->sym
[1].st_value
= buf
;
3009 img
->sym
[1].st_size
= buf_size
;
3011 img
->di
.cu_low_pc
= buf
;
3012 img
->di
.cu_high_pc
= buf
+ buf_size
;
3013 img
->di
.fn_low_pc
= buf
;
3014 img
->di
.fn_high_pc
= buf
+ buf_size
;
3017 /* Enable this block to be able to debug the ELF image file creation.
3018 One can use readelf, objdump, or other inspection utilities. */
3020 FILE *f
= fopen("/tmp/qemu.jit", "w+b");
3022 if (fwrite(img
, img_size
, 1, f
) != img_size
) {
3023 /* Avoid stupid unused return value warning for fwrite. */
3030 one_entry
.symfile_addr
= img
;
3031 one_entry
.symfile_size
= img_size
;
3033 __jit_debug_descriptor
.action_flag
= JIT_REGISTER_FN
;
3034 __jit_debug_descriptor
.relevant_entry
= &one_entry
;
3035 __jit_debug_descriptor
.first_entry
= &one_entry
;
3036 __jit_debug_register_code();
3039 /* No support for the feature. Provide the entry point expected by exec.c,
3040 and implement the internal function we declared earlier. */
3042 static void tcg_register_jit_int(void *buf
, size_t size
,
3043 void *debug_frame
, size_t debug_frame_size
)
3047 void tcg_register_jit(void *buf
, size_t buf_size
)
3050 #endif /* ELF_HOST_MACHINE */