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_TCG_OPTIMIZATIONS
28 #include "qemu/osdep.h"
30 /* Define to jump the ELF file used to communicate with GDB. */
33 #include "qemu/cutils.h"
34 #include "qemu/host-utils.h"
35 #include "qemu/timer.h"
37 /* Note: the long term plan is to reduce the dependencies on the QEMU
38 CPU definitions. Currently they are used for qemu_ld/st
40 #define NO_CPU_IO_DEFS
43 #include "exec/cpu-common.h"
44 #include "exec/exec-all.h"
48 #if UINTPTR_MAX == UINT32_MAX
49 # define ELF_CLASS ELFCLASS32
51 # define ELF_CLASS ELFCLASS64
53 #ifdef HOST_WORDS_BIGENDIAN
54 # define ELF_DATA ELFDATA2MSB
56 # define ELF_DATA ELFDATA2LSB
62 /* Forward declarations for functions declared in tcg-target.inc.c and
64 static void tcg_target_init(TCGContext
*s
);
65 static void tcg_target_qemu_prologue(TCGContext
*s
);
66 static void patch_reloc(tcg_insn_unit
*code_ptr
, int type
,
67 intptr_t value
, intptr_t addend
);
69 /* The CIE and FDE header definitions will be common to all hosts. */
71 uint32_t len
__attribute__((aligned((sizeof(void *)))));
77 uint8_t return_column
;
80 typedef struct QEMU_PACKED
{
81 uint32_t len
__attribute__((aligned((sizeof(void *)))));
85 } DebugFrameFDEHeader
;
87 typedef struct QEMU_PACKED
{
89 DebugFrameFDEHeader fde
;
92 static void tcg_register_jit_int(void *buf
, size_t size
,
93 const void *debug_frame
,
94 size_t debug_frame_size
)
95 __attribute__((unused
));
97 /* Forward declarations for functions declared and used in tcg-target.inc.c. */
98 static int target_parse_constraint(TCGArgConstraint
*ct
, const char **pct_str
);
99 static void tcg_out_ld(TCGContext
*s
, TCGType type
, TCGReg ret
, TCGReg arg1
,
101 static void tcg_out_mov(TCGContext
*s
, TCGType type
, TCGReg ret
, TCGReg arg
);
102 static void tcg_out_movi(TCGContext
*s
, TCGType type
,
103 TCGReg ret
, tcg_target_long arg
);
104 static void tcg_out_op(TCGContext
*s
, TCGOpcode opc
, const TCGArg
*args
,
105 const int *const_args
);
106 static void tcg_out_st(TCGContext
*s
, TCGType type
, TCGReg arg
, TCGReg arg1
,
108 static bool tcg_out_sti(TCGContext
*s
, TCGType type
, TCGArg val
,
109 TCGReg base
, intptr_t ofs
);
110 static void tcg_out_call(TCGContext
*s
, tcg_insn_unit
*target
);
111 static int tcg_target_const_match(tcg_target_long val
, TCGType type
,
112 const TCGArgConstraint
*arg_ct
);
113 static void tcg_out_tb_init(TCGContext
*s
);
114 static bool tcg_out_tb_finalize(TCGContext
*s
);
118 static TCGRegSet tcg_target_available_regs
[2];
119 static TCGRegSet tcg_target_call_clobber_regs
;
121 #if TCG_TARGET_INSN_UNIT_SIZE == 1
122 static __attribute__((unused
)) inline void tcg_out8(TCGContext
*s
, uint8_t v
)
127 static __attribute__((unused
)) inline void tcg_patch8(tcg_insn_unit
*p
,
134 #if TCG_TARGET_INSN_UNIT_SIZE <= 2
135 static __attribute__((unused
)) inline void tcg_out16(TCGContext
*s
, uint16_t v
)
137 if (TCG_TARGET_INSN_UNIT_SIZE
== 2) {
140 tcg_insn_unit
*p
= s
->code_ptr
;
141 memcpy(p
, &v
, sizeof(v
));
142 s
->code_ptr
= p
+ (2 / TCG_TARGET_INSN_UNIT_SIZE
);
146 static __attribute__((unused
)) inline void tcg_patch16(tcg_insn_unit
*p
,
149 if (TCG_TARGET_INSN_UNIT_SIZE
== 2) {
152 memcpy(p
, &v
, sizeof(v
));
157 #if TCG_TARGET_INSN_UNIT_SIZE <= 4
158 static __attribute__((unused
)) inline void tcg_out32(TCGContext
*s
, uint32_t v
)
160 if (TCG_TARGET_INSN_UNIT_SIZE
== 4) {
163 tcg_insn_unit
*p
= s
->code_ptr
;
164 memcpy(p
, &v
, sizeof(v
));
165 s
->code_ptr
= p
+ (4 / TCG_TARGET_INSN_UNIT_SIZE
);
169 static __attribute__((unused
)) inline void tcg_patch32(tcg_insn_unit
*p
,
172 if (TCG_TARGET_INSN_UNIT_SIZE
== 4) {
175 memcpy(p
, &v
, sizeof(v
));
180 #if TCG_TARGET_INSN_UNIT_SIZE <= 8
181 static __attribute__((unused
)) inline void tcg_out64(TCGContext
*s
, uint64_t v
)
183 if (TCG_TARGET_INSN_UNIT_SIZE
== 8) {
186 tcg_insn_unit
*p
= s
->code_ptr
;
187 memcpy(p
, &v
, sizeof(v
));
188 s
->code_ptr
= p
+ (8 / TCG_TARGET_INSN_UNIT_SIZE
);
192 static __attribute__((unused
)) inline void tcg_patch64(tcg_insn_unit
*p
,
195 if (TCG_TARGET_INSN_UNIT_SIZE
== 8) {
198 memcpy(p
, &v
, sizeof(v
));
203 /* label relocation processing */
205 static void tcg_out_reloc(TCGContext
*s
, tcg_insn_unit
*code_ptr
, int type
,
206 TCGLabel
*l
, intptr_t addend
)
211 /* FIXME: This may break relocations on RISC targets that
212 modify instruction fields in place. The caller may not have
213 written the initial value. */
214 patch_reloc(code_ptr
, type
, l
->u
.value
, addend
);
216 /* add a new relocation entry */
217 r
= tcg_malloc(sizeof(TCGRelocation
));
221 r
->next
= l
->u
.first_reloc
;
222 l
->u
.first_reloc
= r
;
226 static void tcg_out_label(TCGContext
*s
, TCGLabel
*l
, tcg_insn_unit
*ptr
)
228 intptr_t value
= (intptr_t)ptr
;
231 tcg_debug_assert(!l
->has_value
);
233 for (r
= l
->u
.first_reloc
; r
!= NULL
; r
= r
->next
) {
234 patch_reloc(r
->ptr
, r
->type
, value
, r
->addend
);
238 l
->u
.value_ptr
= ptr
;
241 TCGLabel
*gen_new_label(void)
243 TCGContext
*s
= &tcg_ctx
;
244 TCGLabel
*l
= tcg_malloc(sizeof(TCGLabel
));
253 #include "tcg-target.inc.c"
255 /* pool based memory allocation */
256 void *tcg_malloc_internal(TCGContext
*s
, int size
)
261 if (size
> TCG_POOL_CHUNK_SIZE
) {
262 /* big malloc: insert a new pool (XXX: could optimize) */
263 p
= g_malloc(sizeof(TCGPool
) + size
);
265 p
->next
= s
->pool_first_large
;
266 s
->pool_first_large
= p
;
277 pool_size
= TCG_POOL_CHUNK_SIZE
;
278 p
= g_malloc(sizeof(TCGPool
) + pool_size
);
282 s
->pool_current
->next
= p
;
291 s
->pool_cur
= p
->data
+ size
;
292 s
->pool_end
= p
->data
+ p
->size
;
296 void tcg_pool_reset(TCGContext
*s
)
299 for (p
= s
->pool_first_large
; p
; p
= t
) {
303 s
->pool_first_large
= NULL
;
304 s
->pool_cur
= s
->pool_end
= NULL
;
305 s
->pool_current
= NULL
;
308 typedef struct TCGHelperInfo
{
315 #include "exec/helper-proto.h"
317 static const TCGHelperInfo all_helpers
[] = {
318 #include "exec/helper-tcg.h"
321 static int indirect_reg_alloc_order
[ARRAY_SIZE(tcg_target_reg_alloc_order
)];
323 void tcg_context_init(TCGContext
*s
)
325 int op
, total_args
, n
, i
;
327 TCGArgConstraint
*args_ct
;
329 GHashTable
*helper_table
;
331 memset(s
, 0, sizeof(*s
));
334 /* Count total number of arguments and allocate the corresponding
337 for(op
= 0; op
< NB_OPS
; op
++) {
338 def
= &tcg_op_defs
[op
];
339 n
= def
->nb_iargs
+ def
->nb_oargs
;
343 args_ct
= g_malloc(sizeof(TCGArgConstraint
) * total_args
);
344 sorted_args
= g_malloc(sizeof(int) * total_args
);
346 for(op
= 0; op
< NB_OPS
; op
++) {
347 def
= &tcg_op_defs
[op
];
348 def
->args_ct
= args_ct
;
349 def
->sorted_args
= sorted_args
;
350 n
= def
->nb_iargs
+ def
->nb_oargs
;
355 /* Register helpers. */
356 /* Use g_direct_hash/equal for direct pointer comparisons on func. */
357 s
->helpers
= helper_table
= g_hash_table_new(NULL
, NULL
);
359 for (i
= 0; i
< ARRAY_SIZE(all_helpers
); ++i
) {
360 g_hash_table_insert(helper_table
, (gpointer
)all_helpers
[i
].func
,
361 (gpointer
)&all_helpers
[i
]);
366 /* Reverse the order of the saved registers, assuming they're all at
367 the start of tcg_target_reg_alloc_order. */
368 for (n
= 0; n
< ARRAY_SIZE(tcg_target_reg_alloc_order
); ++n
) {
369 int r
= tcg_target_reg_alloc_order
[n
];
370 if (tcg_regset_test_reg(tcg_target_call_clobber_regs
, r
)) {
374 for (i
= 0; i
< n
; ++i
) {
375 indirect_reg_alloc_order
[i
] = tcg_target_reg_alloc_order
[n
- 1 - i
];
377 for (; i
< ARRAY_SIZE(tcg_target_reg_alloc_order
); ++i
) {
378 indirect_reg_alloc_order
[i
] = tcg_target_reg_alloc_order
[i
];
382 void tcg_prologue_init(TCGContext
*s
)
384 size_t prologue_size
, total_size
;
387 /* Put the prologue at the beginning of code_gen_buffer. */
388 buf0
= s
->code_gen_buffer
;
391 s
->code_gen_prologue
= buf0
;
393 /* Generate the prologue. */
394 tcg_target_qemu_prologue(s
);
396 flush_icache_range((uintptr_t)buf0
, (uintptr_t)buf1
);
398 /* Deduct the prologue from the buffer. */
399 prologue_size
= tcg_current_code_size(s
);
400 s
->code_gen_ptr
= buf1
;
401 s
->code_gen_buffer
= buf1
;
403 total_size
= s
->code_gen_buffer_size
- prologue_size
;
404 s
->code_gen_buffer_size
= total_size
;
406 /* Compute a high-water mark, at which we voluntarily flush the buffer
407 and start over. The size here is arbitrary, significantly larger
408 than we expect the code generation for any one opcode to require. */
409 s
->code_gen_highwater
= s
->code_gen_buffer
+ (total_size
- 1024);
411 tcg_register_jit(s
->code_gen_buffer
, total_size
);
414 if (qemu_loglevel_mask(CPU_LOG_TB_OUT_ASM
)) {
415 qemu_log("PROLOGUE: [size=%zu]\n", prologue_size
);
416 log_disas(buf0
, prologue_size
);
423 void tcg_func_start(TCGContext
*s
)
426 s
->nb_temps
= s
->nb_globals
;
428 /* No temps have been previously allocated for size or locality. */
429 memset(s
->free_temps
, 0, sizeof(s
->free_temps
));
432 s
->current_frame_offset
= s
->frame_start
;
434 #ifdef CONFIG_DEBUG_TCG
435 s
->goto_tb_issue_mask
= 0;
438 s
->gen_op_buf
[0].next
= 1;
439 s
->gen_op_buf
[0].prev
= 0;
440 s
->gen_next_op_idx
= 1;
441 s
->gen_next_parm_idx
= 0;
443 s
->be
= tcg_malloc(sizeof(TCGBackendData
));
446 static inline int temp_idx(TCGContext
*s
, TCGTemp
*ts
)
448 ptrdiff_t n
= ts
- s
->temps
;
449 tcg_debug_assert(n
>= 0 && n
< s
->nb_temps
);
453 static inline TCGTemp
*tcg_temp_alloc(TCGContext
*s
)
455 int n
= s
->nb_temps
++;
456 tcg_debug_assert(n
< TCG_MAX_TEMPS
);
457 return memset(&s
->temps
[n
], 0, sizeof(TCGTemp
));
460 static inline TCGTemp
*tcg_global_alloc(TCGContext
*s
)
462 tcg_debug_assert(s
->nb_globals
== s
->nb_temps
);
464 return tcg_temp_alloc(s
);
467 static int tcg_global_reg_new_internal(TCGContext
*s
, TCGType type
,
468 TCGReg reg
, const char *name
)
472 if (TCG_TARGET_REG_BITS
== 32 && type
!= TCG_TYPE_I32
) {
476 ts
= tcg_global_alloc(s
);
477 ts
->base_type
= type
;
482 tcg_regset_set_reg(s
->reserved_regs
, reg
);
484 return temp_idx(s
, ts
);
487 void tcg_set_frame(TCGContext
*s
, TCGReg reg
, intptr_t start
, intptr_t size
)
490 s
->frame_start
= start
;
491 s
->frame_end
= start
+ size
;
492 idx
= tcg_global_reg_new_internal(s
, TCG_TYPE_PTR
, reg
, "_frame");
493 s
->frame_temp
= &s
->temps
[idx
];
496 TCGv_i32
tcg_global_reg_new_i32(TCGReg reg
, const char *name
)
498 TCGContext
*s
= &tcg_ctx
;
501 if (tcg_regset_test_reg(s
->reserved_regs
, reg
)) {
504 idx
= tcg_global_reg_new_internal(s
, TCG_TYPE_I32
, reg
, name
);
505 return MAKE_TCGV_I32(idx
);
508 TCGv_i64
tcg_global_reg_new_i64(TCGReg reg
, const char *name
)
510 TCGContext
*s
= &tcg_ctx
;
513 if (tcg_regset_test_reg(s
->reserved_regs
, reg
)) {
516 idx
= tcg_global_reg_new_internal(s
, TCG_TYPE_I64
, reg
, name
);
517 return MAKE_TCGV_I64(idx
);
520 int tcg_global_mem_new_internal(TCGType type
, TCGv_ptr base
,
521 intptr_t offset
, const char *name
)
523 TCGContext
*s
= &tcg_ctx
;
524 TCGTemp
*base_ts
= &s
->temps
[GET_TCGV_PTR(base
)];
525 TCGTemp
*ts
= tcg_global_alloc(s
);
526 int indirect_reg
= 0, bigendian
= 0;
527 #ifdef HOST_WORDS_BIGENDIAN
531 if (!base_ts
->fixed_reg
) {
532 /* We do not support double-indirect registers. */
533 tcg_debug_assert(!base_ts
->indirect_reg
);
534 base_ts
->indirect_base
= 1;
535 s
->nb_indirects
+= (TCG_TARGET_REG_BITS
== 32 && type
== TCG_TYPE_I64
540 if (TCG_TARGET_REG_BITS
== 32 && type
== TCG_TYPE_I64
) {
541 TCGTemp
*ts2
= tcg_global_alloc(s
);
544 ts
->base_type
= TCG_TYPE_I64
;
545 ts
->type
= TCG_TYPE_I32
;
546 ts
->indirect_reg
= indirect_reg
;
547 ts
->mem_allocated
= 1;
548 ts
->mem_base
= base_ts
;
549 ts
->mem_offset
= offset
+ bigendian
* 4;
550 pstrcpy(buf
, sizeof(buf
), name
);
551 pstrcat(buf
, sizeof(buf
), "_0");
552 ts
->name
= strdup(buf
);
554 tcg_debug_assert(ts2
== ts
+ 1);
555 ts2
->base_type
= TCG_TYPE_I64
;
556 ts2
->type
= TCG_TYPE_I32
;
557 ts2
->indirect_reg
= indirect_reg
;
558 ts2
->mem_allocated
= 1;
559 ts2
->mem_base
= base_ts
;
560 ts2
->mem_offset
= offset
+ (1 - bigendian
) * 4;
561 pstrcpy(buf
, sizeof(buf
), name
);
562 pstrcat(buf
, sizeof(buf
), "_1");
563 ts2
->name
= strdup(buf
);
565 ts
->base_type
= type
;
567 ts
->indirect_reg
= indirect_reg
;
568 ts
->mem_allocated
= 1;
569 ts
->mem_base
= base_ts
;
570 ts
->mem_offset
= offset
;
573 return temp_idx(s
, ts
);
576 static int tcg_temp_new_internal(TCGType type
, int temp_local
)
578 TCGContext
*s
= &tcg_ctx
;
582 k
= type
+ (temp_local
? TCG_TYPE_COUNT
: 0);
583 idx
= find_first_bit(s
->free_temps
[k
].l
, TCG_MAX_TEMPS
);
584 if (idx
< TCG_MAX_TEMPS
) {
585 /* There is already an available temp with the right type. */
586 clear_bit(idx
, s
->free_temps
[k
].l
);
589 ts
->temp_allocated
= 1;
590 tcg_debug_assert(ts
->base_type
== type
);
591 tcg_debug_assert(ts
->temp_local
== temp_local
);
593 ts
= tcg_temp_alloc(s
);
594 if (TCG_TARGET_REG_BITS
== 32 && type
== TCG_TYPE_I64
) {
595 TCGTemp
*ts2
= tcg_temp_alloc(s
);
597 ts
->base_type
= type
;
598 ts
->type
= TCG_TYPE_I32
;
599 ts
->temp_allocated
= 1;
600 ts
->temp_local
= temp_local
;
602 tcg_debug_assert(ts2
== ts
+ 1);
603 ts2
->base_type
= TCG_TYPE_I64
;
604 ts2
->type
= TCG_TYPE_I32
;
605 ts2
->temp_allocated
= 1;
606 ts2
->temp_local
= temp_local
;
608 ts
->base_type
= type
;
610 ts
->temp_allocated
= 1;
611 ts
->temp_local
= temp_local
;
613 idx
= temp_idx(s
, ts
);
616 #if defined(CONFIG_DEBUG_TCG)
622 TCGv_i32
tcg_temp_new_internal_i32(int temp_local
)
626 idx
= tcg_temp_new_internal(TCG_TYPE_I32
, temp_local
);
627 return MAKE_TCGV_I32(idx
);
630 TCGv_i64
tcg_temp_new_internal_i64(int temp_local
)
634 idx
= tcg_temp_new_internal(TCG_TYPE_I64
, temp_local
);
635 return MAKE_TCGV_I64(idx
);
638 static void tcg_temp_free_internal(int idx
)
640 TCGContext
*s
= &tcg_ctx
;
644 #if defined(CONFIG_DEBUG_TCG)
646 if (s
->temps_in_use
< 0) {
647 fprintf(stderr
, "More temporaries freed than allocated!\n");
651 tcg_debug_assert(idx
>= s
->nb_globals
&& idx
< s
->nb_temps
);
653 tcg_debug_assert(ts
->temp_allocated
!= 0);
654 ts
->temp_allocated
= 0;
656 k
= ts
->base_type
+ (ts
->temp_local
? TCG_TYPE_COUNT
: 0);
657 set_bit(idx
, s
->free_temps
[k
].l
);
660 void tcg_temp_free_i32(TCGv_i32 arg
)
662 tcg_temp_free_internal(GET_TCGV_I32(arg
));
665 void tcg_temp_free_i64(TCGv_i64 arg
)
667 tcg_temp_free_internal(GET_TCGV_I64(arg
));
670 TCGv_i32
tcg_const_i32(int32_t val
)
673 t0
= tcg_temp_new_i32();
674 tcg_gen_movi_i32(t0
, val
);
678 TCGv_i64
tcg_const_i64(int64_t val
)
681 t0
= tcg_temp_new_i64();
682 tcg_gen_movi_i64(t0
, val
);
686 TCGv_i32
tcg_const_local_i32(int32_t val
)
689 t0
= tcg_temp_local_new_i32();
690 tcg_gen_movi_i32(t0
, val
);
694 TCGv_i64
tcg_const_local_i64(int64_t val
)
697 t0
= tcg_temp_local_new_i64();
698 tcg_gen_movi_i64(t0
, val
);
702 #if defined(CONFIG_DEBUG_TCG)
703 void tcg_clear_temp_count(void)
705 TCGContext
*s
= &tcg_ctx
;
709 int tcg_check_temp_count(void)
711 TCGContext
*s
= &tcg_ctx
;
712 if (s
->temps_in_use
) {
713 /* Clear the count so that we don't give another
714 * warning immediately next time around.
723 /* Note: we convert the 64 bit args to 32 bit and do some alignment
724 and endian swap. Maybe it would be better to do the alignment
725 and endian swap in tcg_reg_alloc_call(). */
726 void tcg_gen_callN(TCGContext
*s
, void *func
, TCGArg ret
,
727 int nargs
, TCGArg
*args
)
729 int i
, real_args
, nb_rets
, pi
, pi_first
;
730 unsigned sizemask
, flags
;
733 info
= g_hash_table_lookup(s
->helpers
, (gpointer
)func
);
735 sizemask
= info
->sizemask
;
737 #if defined(__sparc__) && !defined(__arch64__) \
738 && !defined(CONFIG_TCG_INTERPRETER)
739 /* We have 64-bit values in one register, but need to pass as two
740 separate parameters. Split them. */
741 int orig_sizemask
= sizemask
;
742 int orig_nargs
= nargs
;
745 TCGV_UNUSED_I64(retl
);
746 TCGV_UNUSED_I64(reth
);
748 TCGArg
*split_args
= __builtin_alloca(sizeof(TCGArg
) * nargs
* 2);
749 for (i
= real_args
= 0; i
< nargs
; ++i
) {
750 int is_64bit
= sizemask
& (1 << (i
+1)*2);
752 TCGv_i64 orig
= MAKE_TCGV_I64(args
[i
]);
753 TCGv_i32 h
= tcg_temp_new_i32();
754 TCGv_i32 l
= tcg_temp_new_i32();
755 tcg_gen_extr_i64_i32(l
, h
, orig
);
756 split_args
[real_args
++] = GET_TCGV_I32(h
);
757 split_args
[real_args
++] = GET_TCGV_I32(l
);
759 split_args
[real_args
++] = args
[i
];
766 #elif defined(TCG_TARGET_EXTEND_ARGS) && TCG_TARGET_REG_BITS == 64
767 for (i
= 0; i
< nargs
; ++i
) {
768 int is_64bit
= sizemask
& (1 << (i
+1)*2);
769 int is_signed
= sizemask
& (2 << (i
+1)*2);
771 TCGv_i64 temp
= tcg_temp_new_i64();
772 TCGv_i64 orig
= MAKE_TCGV_I64(args
[i
]);
774 tcg_gen_ext32s_i64(temp
, orig
);
776 tcg_gen_ext32u_i64(temp
, orig
);
778 args
[i
] = GET_TCGV_I64(temp
);
781 #endif /* TCG_TARGET_EXTEND_ARGS */
783 pi_first
= pi
= s
->gen_next_parm_idx
;
784 if (ret
!= TCG_CALL_DUMMY_ARG
) {
785 #if defined(__sparc__) && !defined(__arch64__) \
786 && !defined(CONFIG_TCG_INTERPRETER)
787 if (orig_sizemask
& 1) {
788 /* The 32-bit ABI is going to return the 64-bit value in
789 the %o0/%o1 register pair. Prepare for this by using
790 two return temporaries, and reassemble below. */
791 retl
= tcg_temp_new_i64();
792 reth
= tcg_temp_new_i64();
793 s
->gen_opparam_buf
[pi
++] = GET_TCGV_I64(reth
);
794 s
->gen_opparam_buf
[pi
++] = GET_TCGV_I64(retl
);
797 s
->gen_opparam_buf
[pi
++] = ret
;
801 if (TCG_TARGET_REG_BITS
< 64 && (sizemask
& 1)) {
802 #ifdef HOST_WORDS_BIGENDIAN
803 s
->gen_opparam_buf
[pi
++] = ret
+ 1;
804 s
->gen_opparam_buf
[pi
++] = ret
;
806 s
->gen_opparam_buf
[pi
++] = ret
;
807 s
->gen_opparam_buf
[pi
++] = ret
+ 1;
811 s
->gen_opparam_buf
[pi
++] = ret
;
819 for (i
= 0; i
< nargs
; i
++) {
820 int is_64bit
= sizemask
& (1 << (i
+1)*2);
821 if (TCG_TARGET_REG_BITS
< 64 && is_64bit
) {
822 #ifdef TCG_TARGET_CALL_ALIGN_ARGS
823 /* some targets want aligned 64 bit args */
825 s
->gen_opparam_buf
[pi
++] = TCG_CALL_DUMMY_ARG
;
829 /* If stack grows up, then we will be placing successive
830 arguments at lower addresses, which means we need to
831 reverse the order compared to how we would normally
832 treat either big or little-endian. For those arguments
833 that will wind up in registers, this still works for
834 HPPA (the only current STACK_GROWSUP target) since the
835 argument registers are *also* allocated in decreasing
836 order. If another such target is added, this logic may
837 have to get more complicated to differentiate between
838 stack arguments and register arguments. */
839 #if defined(HOST_WORDS_BIGENDIAN) != defined(TCG_TARGET_STACK_GROWSUP)
840 s
->gen_opparam_buf
[pi
++] = args
[i
] + 1;
841 s
->gen_opparam_buf
[pi
++] = args
[i
];
843 s
->gen_opparam_buf
[pi
++] = args
[i
];
844 s
->gen_opparam_buf
[pi
++] = args
[i
] + 1;
850 s
->gen_opparam_buf
[pi
++] = args
[i
];
853 s
->gen_opparam_buf
[pi
++] = (uintptr_t)func
;
854 s
->gen_opparam_buf
[pi
++] = flags
;
856 i
= s
->gen_next_op_idx
;
857 tcg_debug_assert(i
< OPC_BUF_SIZE
);
858 tcg_debug_assert(pi
<= OPPARAM_BUF_SIZE
);
860 /* Set links for sequential allocation during translation. */
861 s
->gen_op_buf
[i
] = (TCGOp
){
862 .opc
= INDEX_op_call
,
870 /* Make sure the calli field didn't overflow. */
871 tcg_debug_assert(s
->gen_op_buf
[i
].calli
== real_args
);
873 s
->gen_op_buf
[0].prev
= i
;
874 s
->gen_next_op_idx
= i
+ 1;
875 s
->gen_next_parm_idx
= pi
;
877 #if defined(__sparc__) && !defined(__arch64__) \
878 && !defined(CONFIG_TCG_INTERPRETER)
879 /* Free all of the parts we allocated above. */
880 for (i
= real_args
= 0; i
< orig_nargs
; ++i
) {
881 int is_64bit
= orig_sizemask
& (1 << (i
+1)*2);
883 TCGv_i32 h
= MAKE_TCGV_I32(args
[real_args
++]);
884 TCGv_i32 l
= MAKE_TCGV_I32(args
[real_args
++]);
885 tcg_temp_free_i32(h
);
886 tcg_temp_free_i32(l
);
891 if (orig_sizemask
& 1) {
892 /* The 32-bit ABI returned two 32-bit pieces. Re-assemble them.
893 Note that describing these as TCGv_i64 eliminates an unnecessary
894 zero-extension that tcg_gen_concat_i32_i64 would create. */
895 tcg_gen_concat32_i64(MAKE_TCGV_I64(ret
), retl
, reth
);
896 tcg_temp_free_i64(retl
);
897 tcg_temp_free_i64(reth
);
899 #elif defined(TCG_TARGET_EXTEND_ARGS) && TCG_TARGET_REG_BITS == 64
900 for (i
= 0; i
< nargs
; ++i
) {
901 int is_64bit
= sizemask
& (1 << (i
+1)*2);
903 TCGv_i64 temp
= MAKE_TCGV_I64(args
[i
]);
904 tcg_temp_free_i64(temp
);
907 #endif /* TCG_TARGET_EXTEND_ARGS */
910 static void tcg_reg_alloc_start(TCGContext
*s
)
914 for(i
= 0; i
< s
->nb_globals
; i
++) {
917 ts
->val_type
= TEMP_VAL_REG
;
919 ts
->val_type
= TEMP_VAL_MEM
;
922 for(i
= s
->nb_globals
; i
< s
->nb_temps
; i
++) {
924 if (ts
->temp_local
) {
925 ts
->val_type
= TEMP_VAL_MEM
;
927 ts
->val_type
= TEMP_VAL_DEAD
;
929 ts
->mem_allocated
= 0;
933 memset(s
->reg_to_temp
, 0, sizeof(s
->reg_to_temp
));
936 static char *tcg_get_arg_str_ptr(TCGContext
*s
, char *buf
, int buf_size
,
939 int idx
= temp_idx(s
, ts
);
941 if (idx
< s
->nb_globals
) {
942 pstrcpy(buf
, buf_size
, ts
->name
);
943 } else if (ts
->temp_local
) {
944 snprintf(buf
, buf_size
, "loc%d", idx
- s
->nb_globals
);
946 snprintf(buf
, buf_size
, "tmp%d", idx
- s
->nb_globals
);
951 static char *tcg_get_arg_str_idx(TCGContext
*s
, char *buf
,
952 int buf_size
, int idx
)
954 tcg_debug_assert(idx
>= 0 && idx
< s
->nb_temps
);
955 return tcg_get_arg_str_ptr(s
, buf
, buf_size
, &s
->temps
[idx
]);
958 /* Find helper name. */
959 static inline const char *tcg_find_helper(TCGContext
*s
, uintptr_t val
)
961 const char *ret
= NULL
;
963 TCGHelperInfo
*info
= g_hash_table_lookup(s
->helpers
, (gpointer
)val
);
971 static const char * const cond_name
[] =
973 [TCG_COND_NEVER
] = "never",
974 [TCG_COND_ALWAYS
] = "always",
975 [TCG_COND_EQ
] = "eq",
976 [TCG_COND_NE
] = "ne",
977 [TCG_COND_LT
] = "lt",
978 [TCG_COND_GE
] = "ge",
979 [TCG_COND_LE
] = "le",
980 [TCG_COND_GT
] = "gt",
981 [TCG_COND_LTU
] = "ltu",
982 [TCG_COND_GEU
] = "geu",
983 [TCG_COND_LEU
] = "leu",
984 [TCG_COND_GTU
] = "gtu"
987 static const char * const ldst_name
[] =
1003 static const char * const alignment_name
[(MO_AMASK
>> MO_ASHIFT
) + 1] = {
1005 [MO_UNALN
>> MO_ASHIFT
] = "un+",
1006 [MO_ALIGN
>> MO_ASHIFT
] = "",
1008 [MO_UNALN
>> MO_ASHIFT
] = "",
1009 [MO_ALIGN
>> MO_ASHIFT
] = "al+",
1011 [MO_ALIGN_2
>> MO_ASHIFT
] = "al2+",
1012 [MO_ALIGN_4
>> MO_ASHIFT
] = "al4+",
1013 [MO_ALIGN_8
>> MO_ASHIFT
] = "al8+",
1014 [MO_ALIGN_16
>> MO_ASHIFT
] = "al16+",
1015 [MO_ALIGN_32
>> MO_ASHIFT
] = "al32+",
1016 [MO_ALIGN_64
>> MO_ASHIFT
] = "al64+",
1019 void tcg_dump_ops(TCGContext
*s
)
1025 for (oi
= s
->gen_op_buf
[0].next
; oi
!= 0; oi
= op
->next
) {
1026 int i
, k
, nb_oargs
, nb_iargs
, nb_cargs
;
1027 const TCGOpDef
*def
;
1032 op
= &s
->gen_op_buf
[oi
];
1034 def
= &tcg_op_defs
[c
];
1035 args
= &s
->gen_opparam_buf
[op
->args
];
1037 if (c
== INDEX_op_insn_start
) {
1038 col
+= qemu_log("%s ----", oi
!= s
->gen_op_buf
[0].next
? "\n" : "");
1040 for (i
= 0; i
< TARGET_INSN_START_WORDS
; ++i
) {
1042 #if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
1043 a
= ((target_ulong
)args
[i
* 2 + 1] << 32) | args
[i
* 2];
1047 col
+= qemu_log(" " TARGET_FMT_lx
, a
);
1049 } else if (c
== INDEX_op_call
) {
1050 /* variable number of arguments */
1051 nb_oargs
= op
->callo
;
1052 nb_iargs
= op
->calli
;
1053 nb_cargs
= def
->nb_cargs
;
1055 /* function name, flags, out args */
1056 col
+= qemu_log(" %s %s,$0x%" TCG_PRIlx
",$%d", def
->name
,
1057 tcg_find_helper(s
, args
[nb_oargs
+ nb_iargs
]),
1058 args
[nb_oargs
+ nb_iargs
+ 1], nb_oargs
);
1059 for (i
= 0; i
< nb_oargs
; i
++) {
1060 col
+= qemu_log(",%s", tcg_get_arg_str_idx(s
, buf
, sizeof(buf
),
1063 for (i
= 0; i
< nb_iargs
; i
++) {
1064 TCGArg arg
= args
[nb_oargs
+ i
];
1065 const char *t
= "<dummy>";
1066 if (arg
!= TCG_CALL_DUMMY_ARG
) {
1067 t
= tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), arg
);
1069 col
+= qemu_log(",%s", t
);
1072 col
+= qemu_log(" %s ", def
->name
);
1074 nb_oargs
= def
->nb_oargs
;
1075 nb_iargs
= def
->nb_iargs
;
1076 nb_cargs
= def
->nb_cargs
;
1079 for (i
= 0; i
< nb_oargs
; i
++) {
1081 col
+= qemu_log(",");
1083 col
+= qemu_log("%s", tcg_get_arg_str_idx(s
, buf
, sizeof(buf
),
1086 for (i
= 0; i
< nb_iargs
; i
++) {
1088 col
+= qemu_log(",");
1090 col
+= qemu_log("%s", tcg_get_arg_str_idx(s
, buf
, sizeof(buf
),
1094 case INDEX_op_brcond_i32
:
1095 case INDEX_op_setcond_i32
:
1096 case INDEX_op_movcond_i32
:
1097 case INDEX_op_brcond2_i32
:
1098 case INDEX_op_setcond2_i32
:
1099 case INDEX_op_brcond_i64
:
1100 case INDEX_op_setcond_i64
:
1101 case INDEX_op_movcond_i64
:
1102 if (args
[k
] < ARRAY_SIZE(cond_name
) && cond_name
[args
[k
]]) {
1103 col
+= qemu_log(",%s", cond_name
[args
[k
++]]);
1105 col
+= qemu_log(",$0x%" TCG_PRIlx
, args
[k
++]);
1109 case INDEX_op_qemu_ld_i32
:
1110 case INDEX_op_qemu_st_i32
:
1111 case INDEX_op_qemu_ld_i64
:
1112 case INDEX_op_qemu_st_i64
:
1114 TCGMemOpIdx oi
= args
[k
++];
1115 TCGMemOp op
= get_memop(oi
);
1116 unsigned ix
= get_mmuidx(oi
);
1118 if (op
& ~(MO_AMASK
| MO_BSWAP
| MO_SSIZE
)) {
1119 col
+= qemu_log(",$0x%x,%u", op
, ix
);
1121 const char *s_al
, *s_op
;
1122 s_al
= alignment_name
[(op
& MO_AMASK
) >> MO_ASHIFT
];
1123 s_op
= ldst_name
[op
& (MO_BSWAP
| MO_SSIZE
)];
1124 col
+= qemu_log(",%s%s,%u", s_al
, s_op
, ix
);
1134 case INDEX_op_set_label
:
1136 case INDEX_op_brcond_i32
:
1137 case INDEX_op_brcond_i64
:
1138 case INDEX_op_brcond2_i32
:
1139 col
+= qemu_log("%s$L%d", k
? "," : "", arg_label(args
[k
])->id
);
1145 for (; i
< nb_cargs
; i
++, k
++) {
1146 col
+= qemu_log("%s$0x%" TCG_PRIlx
, k
? "," : "", args
[k
]);
1150 unsigned life
= op
->life
;
1152 for (; col
< 48; ++col
) {
1153 putc(' ', qemu_logfile
);
1156 if (life
& (SYNC_ARG
* 3)) {
1158 for (i
= 0; i
< 2; ++i
) {
1159 if (life
& (SYNC_ARG
<< i
)) {
1167 for (i
= 0; life
; ++i
, life
>>= 1) {
1178 /* we give more priority to constraints with less registers */
1179 static int get_constraint_priority(const TCGOpDef
*def
, int k
)
1181 const TCGArgConstraint
*arg_ct
;
1184 arg_ct
= &def
->args_ct
[k
];
1185 if (arg_ct
->ct
& TCG_CT_ALIAS
) {
1186 /* an alias is equivalent to a single register */
1189 if (!(arg_ct
->ct
& TCG_CT_REG
))
1192 for(i
= 0; i
< TCG_TARGET_NB_REGS
; i
++) {
1193 if (tcg_regset_test_reg(arg_ct
->u
.regs
, i
))
1197 return TCG_TARGET_NB_REGS
- n
+ 1;
1200 /* sort from highest priority to lowest */
1201 static void sort_constraints(TCGOpDef
*def
, int start
, int n
)
1203 int i
, j
, p1
, p2
, tmp
;
1205 for(i
= 0; i
< n
; i
++)
1206 def
->sorted_args
[start
+ i
] = start
+ i
;
1209 for(i
= 0; i
< n
- 1; i
++) {
1210 for(j
= i
+ 1; j
< n
; j
++) {
1211 p1
= get_constraint_priority(def
, def
->sorted_args
[start
+ i
]);
1212 p2
= get_constraint_priority(def
, def
->sorted_args
[start
+ j
]);
1214 tmp
= def
->sorted_args
[start
+ i
];
1215 def
->sorted_args
[start
+ i
] = def
->sorted_args
[start
+ j
];
1216 def
->sorted_args
[start
+ j
] = tmp
;
1222 void tcg_add_target_add_op_defs(const TCGTargetOpDef
*tdefs
)
1230 if (tdefs
->op
== (TCGOpcode
)-1)
1233 tcg_debug_assert((unsigned)op
< NB_OPS
);
1234 def
= &tcg_op_defs
[op
];
1235 #if defined(CONFIG_DEBUG_TCG)
1236 /* Duplicate entry in op definitions? */
1237 tcg_debug_assert(!def
->used
);
1240 nb_args
= def
->nb_iargs
+ def
->nb_oargs
;
1241 for(i
= 0; i
< nb_args
; i
++) {
1242 ct_str
= tdefs
->args_ct_str
[i
];
1243 /* Incomplete TCGTargetOpDef entry? */
1244 tcg_debug_assert(ct_str
!= NULL
);
1245 tcg_regset_clear(def
->args_ct
[i
].u
.regs
);
1246 def
->args_ct
[i
].ct
= 0;
1247 if (ct_str
[0] >= '0' && ct_str
[0] <= '9') {
1249 oarg
= ct_str
[0] - '0';
1250 tcg_debug_assert(oarg
< def
->nb_oargs
);
1251 tcg_debug_assert(def
->args_ct
[oarg
].ct
& TCG_CT_REG
);
1252 /* TCG_CT_ALIAS is for the output arguments. The input
1253 argument is tagged with TCG_CT_IALIAS. */
1254 def
->args_ct
[i
] = def
->args_ct
[oarg
];
1255 def
->args_ct
[oarg
].ct
= TCG_CT_ALIAS
;
1256 def
->args_ct
[oarg
].alias_index
= i
;
1257 def
->args_ct
[i
].ct
|= TCG_CT_IALIAS
;
1258 def
->args_ct
[i
].alias_index
= oarg
;
1261 if (*ct_str
== '\0')
1265 def
->args_ct
[i
].ct
|= TCG_CT_CONST
;
1269 if (target_parse_constraint(&def
->args_ct
[i
], &ct_str
) < 0) {
1270 fprintf(stderr
, "Invalid constraint '%s' for arg %d of operation '%s'\n",
1271 ct_str
, i
, def
->name
);
1279 /* TCGTargetOpDef entry with too much information? */
1280 tcg_debug_assert(i
== TCG_MAX_OP_ARGS
|| tdefs
->args_ct_str
[i
] == NULL
);
1282 /* sort the constraints (XXX: this is just an heuristic) */
1283 sort_constraints(def
, 0, def
->nb_oargs
);
1284 sort_constraints(def
, def
->nb_oargs
, def
->nb_iargs
);
1290 printf("%s: sorted=", def
->name
);
1291 for(i
= 0; i
< def
->nb_oargs
+ def
->nb_iargs
; i
++)
1292 printf(" %d", def
->sorted_args
[i
]);
1299 #if defined(CONFIG_DEBUG_TCG)
1301 for (op
= 0; op
< tcg_op_defs_max
; op
++) {
1302 const TCGOpDef
*def
= &tcg_op_defs
[op
];
1303 if (def
->flags
& TCG_OPF_NOT_PRESENT
) {
1304 /* Wrong entry in op definitions? */
1306 fprintf(stderr
, "Invalid op definition for %s\n", def
->name
);
1310 /* Missing entry in op definitions? */
1312 fprintf(stderr
, "Missing op definition for %s\n", def
->name
);
1323 void tcg_op_remove(TCGContext
*s
, TCGOp
*op
)
1325 int next
= op
->next
;
1326 int prev
= op
->prev
;
1328 /* We should never attempt to remove the list terminator. */
1329 tcg_debug_assert(op
!= &s
->gen_op_buf
[0]);
1331 s
->gen_op_buf
[next
].prev
= prev
;
1332 s
->gen_op_buf
[prev
].next
= next
;
1334 memset(op
, 0, sizeof(*op
));
1336 #ifdef CONFIG_PROFILER
1341 TCGOp
*tcg_op_insert_before(TCGContext
*s
, TCGOp
*old_op
,
1342 TCGOpcode opc
, int nargs
)
1344 int oi
= s
->gen_next_op_idx
;
1345 int pi
= s
->gen_next_parm_idx
;
1346 int prev
= old_op
->prev
;
1347 int next
= old_op
- s
->gen_op_buf
;
1350 tcg_debug_assert(oi
< OPC_BUF_SIZE
);
1351 tcg_debug_assert(pi
+ nargs
<= OPPARAM_BUF_SIZE
);
1352 s
->gen_next_op_idx
= oi
+ 1;
1353 s
->gen_next_parm_idx
= pi
+ nargs
;
1355 new_op
= &s
->gen_op_buf
[oi
];
1362 s
->gen_op_buf
[prev
].next
= oi
;
1368 TCGOp
*tcg_op_insert_after(TCGContext
*s
, TCGOp
*old_op
,
1369 TCGOpcode opc
, int nargs
)
1371 int oi
= s
->gen_next_op_idx
;
1372 int pi
= s
->gen_next_parm_idx
;
1373 int prev
= old_op
- s
->gen_op_buf
;
1374 int next
= old_op
->next
;
1377 tcg_debug_assert(oi
< OPC_BUF_SIZE
);
1378 tcg_debug_assert(pi
+ nargs
<= OPPARAM_BUF_SIZE
);
1379 s
->gen_next_op_idx
= oi
+ 1;
1380 s
->gen_next_parm_idx
= pi
+ nargs
;
1382 new_op
= &s
->gen_op_buf
[oi
];
1389 s
->gen_op_buf
[next
].prev
= oi
;
1398 #define IS_DEAD_ARG(n) (arg_life & (DEAD_ARG << (n)))
1399 #define NEED_SYNC_ARG(n) (arg_life & (SYNC_ARG << (n)))
1401 /* liveness analysis: end of function: all temps are dead, and globals
1402 should be in memory. */
1403 static inline void tcg_la_func_end(TCGContext
*s
, uint8_t *temp_state
)
1405 memset(temp_state
, TS_DEAD
| TS_MEM
, s
->nb_globals
);
1406 memset(temp_state
+ s
->nb_globals
, TS_DEAD
, s
->nb_temps
- s
->nb_globals
);
1409 /* liveness analysis: end of basic block: all temps are dead, globals
1410 and local temps should be in memory. */
1411 static inline void tcg_la_bb_end(TCGContext
*s
, uint8_t *temp_state
)
1415 tcg_la_func_end(s
, temp_state
);
1416 for (i
= s
->nb_globals
, n
= s
->nb_temps
; i
< n
; i
++) {
1417 if (s
->temps
[i
].temp_local
) {
1418 temp_state
[i
] |= TS_MEM
;
1423 /* Liveness analysis : update the opc_arg_life array to tell if a
1424 given input arguments is dead. Instructions updating dead
1425 temporaries are removed. */
1426 static void liveness_pass_1(TCGContext
*s
, uint8_t *temp_state
)
1428 int nb_globals
= s
->nb_globals
;
1431 tcg_la_func_end(s
, temp_state
);
1433 for (oi
= s
->gen_op_buf
[0].prev
; oi
!= 0; oi
= oi_prev
) {
1434 int i
, nb_iargs
, nb_oargs
;
1435 TCGOpcode opc_new
, opc_new2
;
1437 TCGLifeData arg_life
= 0;
1440 TCGOp
* const op
= &s
->gen_op_buf
[oi
];
1441 TCGArg
* const args
= &s
->gen_opparam_buf
[op
->args
];
1442 TCGOpcode opc
= op
->opc
;
1443 const TCGOpDef
*def
= &tcg_op_defs
[opc
];
1452 nb_oargs
= op
->callo
;
1453 nb_iargs
= op
->calli
;
1454 call_flags
= args
[nb_oargs
+ nb_iargs
+ 1];
1456 /* pure functions can be removed if their result is unused */
1457 if (call_flags
& TCG_CALL_NO_SIDE_EFFECTS
) {
1458 for (i
= 0; i
< nb_oargs
; i
++) {
1460 if (temp_state
[arg
] != TS_DEAD
) {
1461 goto do_not_remove_call
;
1468 /* output args are dead */
1469 for (i
= 0; i
< nb_oargs
; i
++) {
1471 if (temp_state
[arg
] & TS_DEAD
) {
1472 arg_life
|= DEAD_ARG
<< i
;
1474 if (temp_state
[arg
] & TS_MEM
) {
1475 arg_life
|= SYNC_ARG
<< i
;
1477 temp_state
[arg
] = TS_DEAD
;
1480 if (!(call_flags
& (TCG_CALL_NO_WRITE_GLOBALS
|
1481 TCG_CALL_NO_READ_GLOBALS
))) {
1482 /* globals should go back to memory */
1483 memset(temp_state
, TS_DEAD
| TS_MEM
, nb_globals
);
1484 } else if (!(call_flags
& TCG_CALL_NO_READ_GLOBALS
)) {
1485 /* globals should be synced to memory */
1486 for (i
= 0; i
< nb_globals
; i
++) {
1487 temp_state
[i
] |= TS_MEM
;
1491 /* record arguments that die in this helper */
1492 for (i
= nb_oargs
; i
< nb_iargs
+ nb_oargs
; i
++) {
1494 if (arg
!= TCG_CALL_DUMMY_ARG
) {
1495 if (temp_state
[arg
] & TS_DEAD
) {
1496 arg_life
|= DEAD_ARG
<< i
;
1500 /* input arguments are live for preceding opcodes */
1501 for (i
= nb_oargs
; i
< nb_iargs
+ nb_oargs
; i
++) {
1503 if (arg
!= TCG_CALL_DUMMY_ARG
) {
1504 temp_state
[arg
] &= ~TS_DEAD
;
1510 case INDEX_op_insn_start
:
1512 case INDEX_op_discard
:
1513 /* mark the temporary as dead */
1514 temp_state
[args
[0]] = TS_DEAD
;
1517 case INDEX_op_add2_i32
:
1518 opc_new
= INDEX_op_add_i32
;
1520 case INDEX_op_sub2_i32
:
1521 opc_new
= INDEX_op_sub_i32
;
1523 case INDEX_op_add2_i64
:
1524 opc_new
= INDEX_op_add_i64
;
1526 case INDEX_op_sub2_i64
:
1527 opc_new
= INDEX_op_sub_i64
;
1531 /* Test if the high part of the operation is dead, but not
1532 the low part. The result can be optimized to a simple
1533 add or sub. This happens often for x86_64 guest when the
1534 cpu mode is set to 32 bit. */
1535 if (temp_state
[args
[1]] == TS_DEAD
) {
1536 if (temp_state
[args
[0]] == TS_DEAD
) {
1539 /* Replace the opcode and adjust the args in place,
1540 leaving 3 unused args at the end. */
1541 op
->opc
= opc
= opc_new
;
1544 /* Fall through and mark the single-word operation live. */
1550 case INDEX_op_mulu2_i32
:
1551 opc_new
= INDEX_op_mul_i32
;
1552 opc_new2
= INDEX_op_muluh_i32
;
1553 have_opc_new2
= TCG_TARGET_HAS_muluh_i32
;
1555 case INDEX_op_muls2_i32
:
1556 opc_new
= INDEX_op_mul_i32
;
1557 opc_new2
= INDEX_op_mulsh_i32
;
1558 have_opc_new2
= TCG_TARGET_HAS_mulsh_i32
;
1560 case INDEX_op_mulu2_i64
:
1561 opc_new
= INDEX_op_mul_i64
;
1562 opc_new2
= INDEX_op_muluh_i64
;
1563 have_opc_new2
= TCG_TARGET_HAS_muluh_i64
;
1565 case INDEX_op_muls2_i64
:
1566 opc_new
= INDEX_op_mul_i64
;
1567 opc_new2
= INDEX_op_mulsh_i64
;
1568 have_opc_new2
= TCG_TARGET_HAS_mulsh_i64
;
1573 if (temp_state
[args
[1]] == TS_DEAD
) {
1574 if (temp_state
[args
[0]] == TS_DEAD
) {
1575 /* Both parts of the operation are dead. */
1578 /* The high part of the operation is dead; generate the low. */
1579 op
->opc
= opc
= opc_new
;
1582 } else if (temp_state
[args
[0]] == TS_DEAD
&& have_opc_new2
) {
1583 /* The low part of the operation is dead; generate the high. */
1584 op
->opc
= opc
= opc_new2
;
1591 /* Mark the single-word operation live. */
1596 /* XXX: optimize by hardcoding common cases (e.g. triadic ops) */
1597 nb_iargs
= def
->nb_iargs
;
1598 nb_oargs
= def
->nb_oargs
;
1600 /* Test if the operation can be removed because all
1601 its outputs are dead. We assume that nb_oargs == 0
1602 implies side effects */
1603 if (!(def
->flags
& TCG_OPF_SIDE_EFFECTS
) && nb_oargs
!= 0) {
1604 for (i
= 0; i
< nb_oargs
; i
++) {
1605 if (temp_state
[args
[i
]] != TS_DEAD
) {
1610 tcg_op_remove(s
, op
);
1613 /* output args are dead */
1614 for (i
= 0; i
< nb_oargs
; i
++) {
1616 if (temp_state
[arg
] & TS_DEAD
) {
1617 arg_life
|= DEAD_ARG
<< i
;
1619 if (temp_state
[arg
] & TS_MEM
) {
1620 arg_life
|= SYNC_ARG
<< i
;
1622 temp_state
[arg
] = TS_DEAD
;
1625 /* if end of basic block, update */
1626 if (def
->flags
& TCG_OPF_BB_END
) {
1627 tcg_la_bb_end(s
, temp_state
);
1628 } else if (def
->flags
& TCG_OPF_SIDE_EFFECTS
) {
1629 /* globals should be synced to memory */
1630 for (i
= 0; i
< nb_globals
; i
++) {
1631 temp_state
[i
] |= TS_MEM
;
1635 /* record arguments that die in this opcode */
1636 for (i
= nb_oargs
; i
< nb_oargs
+ nb_iargs
; i
++) {
1638 if (temp_state
[arg
] & TS_DEAD
) {
1639 arg_life
|= DEAD_ARG
<< i
;
1642 /* input arguments are live for preceding opcodes */
1643 for (i
= nb_oargs
; i
< nb_oargs
+ nb_iargs
; i
++) {
1644 temp_state
[args
[i
]] &= ~TS_DEAD
;
1649 op
->life
= arg_life
;
1653 /* Liveness analysis: Convert indirect regs to direct temporaries. */
1654 static bool liveness_pass_2(TCGContext
*s
, uint8_t *temp_state
)
1656 int nb_globals
= s
->nb_globals
;
1659 bool changes
= false;
1661 dir_temps
= tcg_malloc(nb_globals
* sizeof(int16_t));
1662 memset(dir_temps
, 0, nb_globals
* sizeof(int16_t));
1664 /* Create a temporary for each indirect global. */
1665 for (i
= 0; i
< nb_globals
; ++i
) {
1666 TCGTemp
*its
= &s
->temps
[i
];
1667 if (its
->indirect_reg
) {
1668 TCGTemp
*dts
= tcg_temp_alloc(s
);
1669 dts
->type
= its
->type
;
1670 dts
->base_type
= its
->base_type
;
1671 dir_temps
[i
] = temp_idx(s
, dts
);
1675 memset(temp_state
, TS_DEAD
, nb_globals
);
1677 for (oi
= s
->gen_op_buf
[0].next
; oi
!= 0; oi
= oi_next
) {
1678 TCGOp
*op
= &s
->gen_op_buf
[oi
];
1679 TCGArg
*args
= &s
->gen_opparam_buf
[op
->args
];
1680 TCGOpcode opc
= op
->opc
;
1681 const TCGOpDef
*def
= &tcg_op_defs
[opc
];
1682 TCGLifeData arg_life
= op
->life
;
1683 int nb_iargs
, nb_oargs
, call_flags
;
1688 if (opc
== INDEX_op_call
) {
1689 nb_oargs
= op
->callo
;
1690 nb_iargs
= op
->calli
;
1691 call_flags
= args
[nb_oargs
+ nb_iargs
+ 1];
1693 nb_iargs
= def
->nb_iargs
;
1694 nb_oargs
= def
->nb_oargs
;
1696 /* Set flags similar to how calls require. */
1697 if (def
->flags
& TCG_OPF_BB_END
) {
1698 /* Like writing globals: save_globals */
1700 } else if (def
->flags
& TCG_OPF_SIDE_EFFECTS
) {
1701 /* Like reading globals: sync_globals */
1702 call_flags
= TCG_CALL_NO_WRITE_GLOBALS
;
1704 /* No effect on globals. */
1705 call_flags
= (TCG_CALL_NO_READ_GLOBALS
|
1706 TCG_CALL_NO_WRITE_GLOBALS
);
1710 /* Make sure that input arguments are available. */
1711 for (i
= nb_oargs
; i
< nb_iargs
+ nb_oargs
; i
++) {
1713 /* Note this unsigned test catches TCG_CALL_ARG_DUMMY too. */
1714 if (arg
< nb_globals
) {
1715 dir
= dir_temps
[arg
];
1716 if (dir
!= 0 && temp_state
[arg
] == TS_DEAD
) {
1717 TCGTemp
*its
= &s
->temps
[arg
];
1718 TCGOpcode lopc
= (its
->type
== TCG_TYPE_I32
1721 TCGOp
*lop
= tcg_op_insert_before(s
, op
, lopc
, 3);
1722 TCGArg
*largs
= &s
->gen_opparam_buf
[lop
->args
];
1725 largs
[1] = temp_idx(s
, its
->mem_base
);
1726 largs
[2] = its
->mem_offset
;
1728 /* Loaded, but synced with memory. */
1729 temp_state
[arg
] = TS_MEM
;
1734 /* Perform input replacement, and mark inputs that became dead.
1735 No action is required except keeping temp_state up to date
1736 so that we reload when needed. */
1737 for (i
= nb_oargs
; i
< nb_iargs
+ nb_oargs
; i
++) {
1739 if (arg
< nb_globals
) {
1740 dir
= dir_temps
[arg
];
1744 if (IS_DEAD_ARG(i
)) {
1745 temp_state
[arg
] = TS_DEAD
;
1751 /* Liveness analysis should ensure that the following are
1752 all correct, for call sites and basic block end points. */
1753 if (call_flags
& TCG_CALL_NO_READ_GLOBALS
) {
1755 } else if (call_flags
& TCG_CALL_NO_WRITE_GLOBALS
) {
1756 for (i
= 0; i
< nb_globals
; ++i
) {
1757 /* Liveness should see that globals are synced back,
1758 that is, either TS_DEAD or TS_MEM. */
1759 tcg_debug_assert(dir_temps
[i
] == 0
1760 || temp_state
[i
] != 0);
1763 for (i
= 0; i
< nb_globals
; ++i
) {
1764 /* Liveness should see that globals are saved back,
1765 that is, TS_DEAD, waiting to be reloaded. */
1766 tcg_debug_assert(dir_temps
[i
] == 0
1767 || temp_state
[i
] == TS_DEAD
);
1771 /* Outputs become available. */
1772 for (i
= 0; i
< nb_oargs
; i
++) {
1774 if (arg
>= nb_globals
) {
1777 dir
= dir_temps
[arg
];
1784 /* The output is now live and modified. */
1785 temp_state
[arg
] = 0;
1787 /* Sync outputs upon their last write. */
1788 if (NEED_SYNC_ARG(i
)) {
1789 TCGTemp
*its
= &s
->temps
[arg
];
1790 TCGOpcode sopc
= (its
->type
== TCG_TYPE_I32
1793 TCGOp
*sop
= tcg_op_insert_after(s
, op
, sopc
, 3);
1794 TCGArg
*sargs
= &s
->gen_opparam_buf
[sop
->args
];
1797 sargs
[1] = temp_idx(s
, its
->mem_base
);
1798 sargs
[2] = its
->mem_offset
;
1800 temp_state
[arg
] = TS_MEM
;
1802 /* Drop outputs that are dead. */
1803 if (IS_DEAD_ARG(i
)) {
1804 temp_state
[arg
] = TS_DEAD
;
1812 #ifdef CONFIG_DEBUG_TCG
1813 static void dump_regs(TCGContext
*s
)
1819 for(i
= 0; i
< s
->nb_temps
; i
++) {
1821 printf(" %10s: ", tcg_get_arg_str_idx(s
, buf
, sizeof(buf
), i
));
1822 switch(ts
->val_type
) {
1824 printf("%s", tcg_target_reg_names
[ts
->reg
]);
1827 printf("%d(%s)", (int)ts
->mem_offset
,
1828 tcg_target_reg_names
[ts
->mem_base
->reg
]);
1830 case TEMP_VAL_CONST
:
1831 printf("$0x%" TCG_PRIlx
, ts
->val
);
1843 for(i
= 0; i
< TCG_TARGET_NB_REGS
; i
++) {
1844 if (s
->reg_to_temp
[i
] != NULL
) {
1846 tcg_target_reg_names
[i
],
1847 tcg_get_arg_str_ptr(s
, buf
, sizeof(buf
), s
->reg_to_temp
[i
]));
1852 static void check_regs(TCGContext
*s
)
1859 for (reg
= 0; reg
< TCG_TARGET_NB_REGS
; reg
++) {
1860 ts
= s
->reg_to_temp
[reg
];
1862 if (ts
->val_type
!= TEMP_VAL_REG
|| ts
->reg
!= reg
) {
1863 printf("Inconsistency for register %s:\n",
1864 tcg_target_reg_names
[reg
]);
1869 for (k
= 0; k
< s
->nb_temps
; k
++) {
1871 if (ts
->val_type
== TEMP_VAL_REG
&& !ts
->fixed_reg
1872 && s
->reg_to_temp
[ts
->reg
] != ts
) {
1873 printf("Inconsistency for temp %s:\n",
1874 tcg_get_arg_str_ptr(s
, buf
, sizeof(buf
), ts
));
1876 printf("reg state:\n");
1884 static void temp_allocate_frame(TCGContext
*s
, int temp
)
1887 ts
= &s
->temps
[temp
];
1888 #if !(defined(__sparc__) && TCG_TARGET_REG_BITS == 64)
1889 /* Sparc64 stack is accessed with offset of 2047 */
1890 s
->current_frame_offset
= (s
->current_frame_offset
+
1891 (tcg_target_long
)sizeof(tcg_target_long
) - 1) &
1892 ~(sizeof(tcg_target_long
) - 1);
1894 if (s
->current_frame_offset
+ (tcg_target_long
)sizeof(tcg_target_long
) >
1898 ts
->mem_offset
= s
->current_frame_offset
;
1899 ts
->mem_base
= s
->frame_temp
;
1900 ts
->mem_allocated
= 1;
1901 s
->current_frame_offset
+= sizeof(tcg_target_long
);
1904 static void temp_load(TCGContext
*, TCGTemp
*, TCGRegSet
, TCGRegSet
);
1906 /* Mark a temporary as free or dead. If 'free_or_dead' is negative,
1907 mark it free; otherwise mark it dead. */
1908 static void temp_free_or_dead(TCGContext
*s
, TCGTemp
*ts
, int free_or_dead
)
1910 if (ts
->fixed_reg
) {
1913 if (ts
->val_type
== TEMP_VAL_REG
) {
1914 s
->reg_to_temp
[ts
->reg
] = NULL
;
1916 ts
->val_type
= (free_or_dead
< 0
1918 || temp_idx(s
, ts
) < s
->nb_globals
1919 ? TEMP_VAL_MEM
: TEMP_VAL_DEAD
);
1922 /* Mark a temporary as dead. */
1923 static inline void temp_dead(TCGContext
*s
, TCGTemp
*ts
)
1925 temp_free_or_dead(s
, ts
, 1);
1928 /* Sync a temporary to memory. 'allocated_regs' is used in case a temporary
1929 registers needs to be allocated to store a constant. If 'free_or_dead'
1930 is non-zero, subsequently release the temporary; if it is positive, the
1931 temp is dead; if it is negative, the temp is free. */
1932 static void temp_sync(TCGContext
*s
, TCGTemp
*ts
,
1933 TCGRegSet allocated_regs
, int free_or_dead
)
1935 if (ts
->fixed_reg
) {
1938 if (!ts
->mem_coherent
) {
1939 if (!ts
->mem_allocated
) {
1940 temp_allocate_frame(s
, temp_idx(s
, ts
));
1942 switch (ts
->val_type
) {
1943 case TEMP_VAL_CONST
:
1944 /* If we're going to free the temp immediately, then we won't
1945 require it later in a register, so attempt to store the
1946 constant to memory directly. */
1948 && tcg_out_sti(s
, ts
->type
, ts
->val
,
1949 ts
->mem_base
->reg
, ts
->mem_offset
)) {
1952 temp_load(s
, ts
, tcg_target_available_regs
[ts
->type
],
1957 tcg_out_st(s
, ts
->type
, ts
->reg
,
1958 ts
->mem_base
->reg
, ts
->mem_offset
);
1968 ts
->mem_coherent
= 1;
1971 temp_free_or_dead(s
, ts
, free_or_dead
);
1975 /* free register 'reg' by spilling the corresponding temporary if necessary */
1976 static void tcg_reg_free(TCGContext
*s
, TCGReg reg
, TCGRegSet allocated_regs
)
1978 TCGTemp
*ts
= s
->reg_to_temp
[reg
];
1980 temp_sync(s
, ts
, allocated_regs
, -1);
1984 /* Allocate a register belonging to reg1 & ~reg2 */
1985 static TCGReg
tcg_reg_alloc(TCGContext
*s
, TCGRegSet desired_regs
,
1986 TCGRegSet allocated_regs
, bool rev
)
1988 int i
, n
= ARRAY_SIZE(tcg_target_reg_alloc_order
);
1993 tcg_regset_andnot(reg_ct
, desired_regs
, allocated_regs
);
1994 order
= rev
? indirect_reg_alloc_order
: tcg_target_reg_alloc_order
;
1996 /* first try free registers */
1997 for(i
= 0; i
< n
; i
++) {
1999 if (tcg_regset_test_reg(reg_ct
, reg
) && s
->reg_to_temp
[reg
] == NULL
)
2003 /* XXX: do better spill choice */
2004 for(i
= 0; i
< n
; i
++) {
2006 if (tcg_regset_test_reg(reg_ct
, reg
)) {
2007 tcg_reg_free(s
, reg
, allocated_regs
);
2015 /* Make sure the temporary is in a register. If needed, allocate the register
2016 from DESIRED while avoiding ALLOCATED. */
2017 static void temp_load(TCGContext
*s
, TCGTemp
*ts
, TCGRegSet desired_regs
,
2018 TCGRegSet allocated_regs
)
2022 switch (ts
->val_type
) {
2025 case TEMP_VAL_CONST
:
2026 reg
= tcg_reg_alloc(s
, desired_regs
, allocated_regs
, ts
->indirect_base
);
2027 tcg_out_movi(s
, ts
->type
, reg
, ts
->val
);
2028 ts
->mem_coherent
= 0;
2031 reg
= tcg_reg_alloc(s
, desired_regs
, allocated_regs
, ts
->indirect_base
);
2032 tcg_out_ld(s
, ts
->type
, reg
, ts
->mem_base
->reg
, ts
->mem_offset
);
2033 ts
->mem_coherent
= 1;
2040 ts
->val_type
= TEMP_VAL_REG
;
2041 s
->reg_to_temp
[reg
] = ts
;
2044 /* Save a temporary to memory. 'allocated_regs' is used in case a
2045 temporary registers needs to be allocated to store a constant. */
2046 static void temp_save(TCGContext
*s
, TCGTemp
*ts
, TCGRegSet allocated_regs
)
2048 /* The liveness analysis already ensures that globals are back
2049 in memory. Keep an tcg_debug_assert for safety. */
2050 tcg_debug_assert(ts
->val_type
== TEMP_VAL_MEM
|| ts
->fixed_reg
);
2053 /* save globals to their canonical location and assume they can be
2054 modified be the following code. 'allocated_regs' is used in case a
2055 temporary registers needs to be allocated to store a constant. */
2056 static void save_globals(TCGContext
*s
, TCGRegSet allocated_regs
)
2060 for (i
= 0; i
< s
->nb_globals
; i
++) {
2061 temp_save(s
, &s
->temps
[i
], allocated_regs
);
2065 /* sync globals to their canonical location and assume they can be
2066 read by the following code. 'allocated_regs' is used in case a
2067 temporary registers needs to be allocated to store a constant. */
2068 static void sync_globals(TCGContext
*s
, TCGRegSet allocated_regs
)
2072 for (i
= 0; i
< s
->nb_globals
; i
++) {
2073 TCGTemp
*ts
= &s
->temps
[i
];
2074 tcg_debug_assert(ts
->val_type
!= TEMP_VAL_REG
2076 || ts
->mem_coherent
);
2080 /* at the end of a basic block, we assume all temporaries are dead and
2081 all globals are stored at their canonical location. */
2082 static void tcg_reg_alloc_bb_end(TCGContext
*s
, TCGRegSet allocated_regs
)
2086 for (i
= s
->nb_globals
; i
< s
->nb_temps
; i
++) {
2087 TCGTemp
*ts
= &s
->temps
[i
];
2088 if (ts
->temp_local
) {
2089 temp_save(s
, ts
, allocated_regs
);
2091 /* The liveness analysis already ensures that temps are dead.
2092 Keep an tcg_debug_assert for safety. */
2093 tcg_debug_assert(ts
->val_type
== TEMP_VAL_DEAD
);
2097 save_globals(s
, allocated_regs
);
2100 static void tcg_reg_alloc_movi(TCGContext
*s
, const TCGArg
*args
,
2101 TCGLifeData arg_life
)
2104 tcg_target_ulong val
;
2106 ots
= &s
->temps
[args
[0]];
2109 if (ots
->fixed_reg
) {
2110 /* For fixed registers, we do not do any constant propagation. */
2111 tcg_out_movi(s
, ots
->type
, ots
->reg
, val
);
2115 /* The movi is not explicitly generated here. */
2116 if (ots
->val_type
== TEMP_VAL_REG
) {
2117 s
->reg_to_temp
[ots
->reg
] = NULL
;
2119 ots
->val_type
= TEMP_VAL_CONST
;
2121 ots
->mem_coherent
= 0;
2122 if (NEED_SYNC_ARG(0)) {
2123 temp_sync(s
, ots
, s
->reserved_regs
, IS_DEAD_ARG(0));
2124 } else if (IS_DEAD_ARG(0)) {
2129 static void tcg_reg_alloc_mov(TCGContext
*s
, const TCGOpDef
*def
,
2130 const TCGArg
*args
, TCGLifeData arg_life
)
2132 TCGRegSet allocated_regs
;
2134 TCGType otype
, itype
;
2136 tcg_regset_set(allocated_regs
, s
->reserved_regs
);
2137 ots
= &s
->temps
[args
[0]];
2138 ts
= &s
->temps
[args
[1]];
2140 /* Note that otype != itype for no-op truncation. */
2144 /* If the source value is not in a register, and we're going to be
2145 forced to have it in a register in order to perform the copy,
2146 then copy the SOURCE value into its own register first. That way
2147 we don't have to reload SOURCE the next time it is used. */
2148 if (((NEED_SYNC_ARG(0) || ots
->fixed_reg
) && ts
->val_type
!= TEMP_VAL_REG
)
2149 || ts
->val_type
== TEMP_VAL_MEM
) {
2150 temp_load(s
, ts
, tcg_target_available_regs
[itype
], allocated_regs
);
2153 if (IS_DEAD_ARG(0) && !ots
->fixed_reg
) {
2154 /* mov to a non-saved dead register makes no sense (even with
2155 liveness analysis disabled). */
2156 tcg_debug_assert(NEED_SYNC_ARG(0));
2157 /* The code above should have moved the temp to a register. */
2158 tcg_debug_assert(ts
->val_type
== TEMP_VAL_REG
);
2159 if (!ots
->mem_allocated
) {
2160 temp_allocate_frame(s
, args
[0]);
2162 tcg_out_st(s
, otype
, ts
->reg
, ots
->mem_base
->reg
, ots
->mem_offset
);
2163 if (IS_DEAD_ARG(1)) {
2167 } else if (ts
->val_type
== TEMP_VAL_CONST
) {
2168 /* propagate constant */
2169 if (ots
->val_type
== TEMP_VAL_REG
) {
2170 s
->reg_to_temp
[ots
->reg
] = NULL
;
2172 ots
->val_type
= TEMP_VAL_CONST
;
2174 if (IS_DEAD_ARG(1)) {
2178 /* The code in the first if block should have moved the
2179 temp to a register. */
2180 tcg_debug_assert(ts
->val_type
== TEMP_VAL_REG
);
2181 if (IS_DEAD_ARG(1) && !ts
->fixed_reg
&& !ots
->fixed_reg
) {
2182 /* the mov can be suppressed */
2183 if (ots
->val_type
== TEMP_VAL_REG
) {
2184 s
->reg_to_temp
[ots
->reg
] = NULL
;
2189 if (ots
->val_type
!= TEMP_VAL_REG
) {
2190 /* When allocating a new register, make sure to not spill the
2192 tcg_regset_set_reg(allocated_regs
, ts
->reg
);
2193 ots
->reg
= tcg_reg_alloc(s
, tcg_target_available_regs
[otype
],
2194 allocated_regs
, ots
->indirect_base
);
2196 tcg_out_mov(s
, otype
, ots
->reg
, ts
->reg
);
2198 ots
->val_type
= TEMP_VAL_REG
;
2199 ots
->mem_coherent
= 0;
2200 s
->reg_to_temp
[ots
->reg
] = ots
;
2201 if (NEED_SYNC_ARG(0)) {
2202 temp_sync(s
, ots
, allocated_regs
, 0);
2207 static void tcg_reg_alloc_op(TCGContext
*s
,
2208 const TCGOpDef
*def
, TCGOpcode opc
,
2209 const TCGArg
*args
, TCGLifeData arg_life
)
2211 TCGRegSet allocated_regs
;
2212 int i
, k
, nb_iargs
, nb_oargs
;
2215 const TCGArgConstraint
*arg_ct
;
2217 TCGArg new_args
[TCG_MAX_OP_ARGS
];
2218 int const_args
[TCG_MAX_OP_ARGS
];
2220 nb_oargs
= def
->nb_oargs
;
2221 nb_iargs
= def
->nb_iargs
;
2223 /* copy constants */
2224 memcpy(new_args
+ nb_oargs
+ nb_iargs
,
2225 args
+ nb_oargs
+ nb_iargs
,
2226 sizeof(TCGArg
) * def
->nb_cargs
);
2228 /* satisfy input constraints */
2229 tcg_regset_set(allocated_regs
, s
->reserved_regs
);
2230 for(k
= 0; k
< nb_iargs
; k
++) {
2231 i
= def
->sorted_args
[nb_oargs
+ k
];
2233 arg_ct
= &def
->args_ct
[i
];
2234 ts
= &s
->temps
[arg
];
2236 if (ts
->val_type
== TEMP_VAL_CONST
2237 && tcg_target_const_match(ts
->val
, ts
->type
, arg_ct
)) {
2238 /* constant is OK for instruction */
2240 new_args
[i
] = ts
->val
;
2244 temp_load(s
, ts
, arg_ct
->u
.regs
, allocated_regs
);
2246 if (arg_ct
->ct
& TCG_CT_IALIAS
) {
2247 if (ts
->fixed_reg
) {
2248 /* if fixed register, we must allocate a new register
2249 if the alias is not the same register */
2250 if (arg
!= args
[arg_ct
->alias_index
])
2251 goto allocate_in_reg
;
2253 /* if the input is aliased to an output and if it is
2254 not dead after the instruction, we must allocate
2255 a new register and move it */
2256 if (!IS_DEAD_ARG(i
)) {
2257 goto allocate_in_reg
;
2259 /* check if the current register has already been allocated
2260 for another input aliased to an output */
2262 for (k2
= 0 ; k2
< k
; k2
++) {
2263 i2
= def
->sorted_args
[nb_oargs
+ k2
];
2264 if ((def
->args_ct
[i2
].ct
& TCG_CT_IALIAS
) &&
2265 (new_args
[i2
] == ts
->reg
)) {
2266 goto allocate_in_reg
;
2272 if (tcg_regset_test_reg(arg_ct
->u
.regs
, reg
)) {
2273 /* nothing to do : the constraint is satisfied */
2276 /* allocate a new register matching the constraint
2277 and move the temporary register into it */
2278 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
,
2280 tcg_out_mov(s
, ts
->type
, reg
, ts
->reg
);
2284 tcg_regset_set_reg(allocated_regs
, reg
);
2288 /* mark dead temporaries and free the associated registers */
2289 for (i
= nb_oargs
; i
< nb_oargs
+ nb_iargs
; i
++) {
2290 if (IS_DEAD_ARG(i
)) {
2291 temp_dead(s
, &s
->temps
[args
[i
]]);
2295 if (def
->flags
& TCG_OPF_BB_END
) {
2296 tcg_reg_alloc_bb_end(s
, allocated_regs
);
2298 if (def
->flags
& TCG_OPF_CALL_CLOBBER
) {
2299 /* XXX: permit generic clobber register list ? */
2300 for (i
= 0; i
< TCG_TARGET_NB_REGS
; i
++) {
2301 if (tcg_regset_test_reg(tcg_target_call_clobber_regs
, i
)) {
2302 tcg_reg_free(s
, i
, allocated_regs
);
2306 if (def
->flags
& TCG_OPF_SIDE_EFFECTS
) {
2307 /* sync globals if the op has side effects and might trigger
2309 sync_globals(s
, allocated_regs
);
2312 /* satisfy the output constraints */
2313 tcg_regset_set(allocated_regs
, s
->reserved_regs
);
2314 for(k
= 0; k
< nb_oargs
; k
++) {
2315 i
= def
->sorted_args
[k
];
2317 arg_ct
= &def
->args_ct
[i
];
2318 ts
= &s
->temps
[arg
];
2319 if (arg_ct
->ct
& TCG_CT_ALIAS
) {
2320 reg
= new_args
[arg_ct
->alias_index
];
2322 /* if fixed register, we try to use it */
2324 if (ts
->fixed_reg
&&
2325 tcg_regset_test_reg(arg_ct
->u
.regs
, reg
)) {
2328 reg
= tcg_reg_alloc(s
, arg_ct
->u
.regs
, allocated_regs
,
2331 tcg_regset_set_reg(allocated_regs
, reg
);
2332 /* if a fixed register is used, then a move will be done afterwards */
2333 if (!ts
->fixed_reg
) {
2334 if (ts
->val_type
== TEMP_VAL_REG
) {
2335 s
->reg_to_temp
[ts
->reg
] = NULL
;
2337 ts
->val_type
= TEMP_VAL_REG
;
2339 /* temp value is modified, so the value kept in memory is
2340 potentially not the same */
2341 ts
->mem_coherent
= 0;
2342 s
->reg_to_temp
[reg
] = ts
;
2349 /* emit instruction */
2350 tcg_out_op(s
, opc
, new_args
, const_args
);
2352 /* move the outputs in the correct register if needed */
2353 for(i
= 0; i
< nb_oargs
; i
++) {
2354 ts
= &s
->temps
[args
[i
]];
2356 if (ts
->fixed_reg
&& ts
->reg
!= reg
) {
2357 tcg_out_mov(s
, ts
->type
, ts
->reg
, reg
);
2359 if (NEED_SYNC_ARG(i
)) {
2360 temp_sync(s
, ts
, allocated_regs
, IS_DEAD_ARG(i
));
2361 } else if (IS_DEAD_ARG(i
)) {
2367 #ifdef TCG_TARGET_STACK_GROWSUP
2368 #define STACK_DIR(x) (-(x))
2370 #define STACK_DIR(x) (x)
2373 static void tcg_reg_alloc_call(TCGContext
*s
, int nb_oargs
, int nb_iargs
,
2374 const TCGArg
* const args
, TCGLifeData arg_life
)
2376 int flags
, nb_regs
, i
;
2380 intptr_t stack_offset
;
2381 size_t call_stack_size
;
2382 tcg_insn_unit
*func_addr
;
2384 TCGRegSet allocated_regs
;
2386 func_addr
= (tcg_insn_unit
*)(intptr_t)args
[nb_oargs
+ nb_iargs
];
2387 flags
= args
[nb_oargs
+ nb_iargs
+ 1];
2389 nb_regs
= ARRAY_SIZE(tcg_target_call_iarg_regs
);
2390 if (nb_regs
> nb_iargs
) {
2394 /* assign stack slots first */
2395 call_stack_size
= (nb_iargs
- nb_regs
) * sizeof(tcg_target_long
);
2396 call_stack_size
= (call_stack_size
+ TCG_TARGET_STACK_ALIGN
- 1) &
2397 ~(TCG_TARGET_STACK_ALIGN
- 1);
2398 allocate_args
= (call_stack_size
> TCG_STATIC_CALL_ARGS_SIZE
);
2399 if (allocate_args
) {
2400 /* XXX: if more than TCG_STATIC_CALL_ARGS_SIZE is needed,
2401 preallocate call stack */
2405 stack_offset
= TCG_TARGET_CALL_STACK_OFFSET
;
2406 for(i
= nb_regs
; i
< nb_iargs
; i
++) {
2407 arg
= args
[nb_oargs
+ i
];
2408 #ifdef TCG_TARGET_STACK_GROWSUP
2409 stack_offset
-= sizeof(tcg_target_long
);
2411 if (arg
!= TCG_CALL_DUMMY_ARG
) {
2412 ts
= &s
->temps
[arg
];
2413 temp_load(s
, ts
, tcg_target_available_regs
[ts
->type
],
2415 tcg_out_st(s
, ts
->type
, ts
->reg
, TCG_REG_CALL_STACK
, stack_offset
);
2417 #ifndef TCG_TARGET_STACK_GROWSUP
2418 stack_offset
+= sizeof(tcg_target_long
);
2422 /* assign input registers */
2423 tcg_regset_set(allocated_regs
, s
->reserved_regs
);
2424 for(i
= 0; i
< nb_regs
; i
++) {
2425 arg
= args
[nb_oargs
+ i
];
2426 if (arg
!= TCG_CALL_DUMMY_ARG
) {
2427 ts
= &s
->temps
[arg
];
2428 reg
= tcg_target_call_iarg_regs
[i
];
2429 tcg_reg_free(s
, reg
, allocated_regs
);
2431 if (ts
->val_type
== TEMP_VAL_REG
) {
2432 if (ts
->reg
!= reg
) {
2433 tcg_out_mov(s
, ts
->type
, reg
, ts
->reg
);
2438 tcg_regset_clear(arg_set
);
2439 tcg_regset_set_reg(arg_set
, reg
);
2440 temp_load(s
, ts
, arg_set
, allocated_regs
);
2443 tcg_regset_set_reg(allocated_regs
, reg
);
2447 /* mark dead temporaries and free the associated registers */
2448 for(i
= nb_oargs
; i
< nb_iargs
+ nb_oargs
; i
++) {
2449 if (IS_DEAD_ARG(i
)) {
2450 temp_dead(s
, &s
->temps
[args
[i
]]);
2454 /* clobber call registers */
2455 for (i
= 0; i
< TCG_TARGET_NB_REGS
; i
++) {
2456 if (tcg_regset_test_reg(tcg_target_call_clobber_regs
, i
)) {
2457 tcg_reg_free(s
, i
, allocated_regs
);
2461 /* Save globals if they might be written by the helper, sync them if
2462 they might be read. */
2463 if (flags
& TCG_CALL_NO_READ_GLOBALS
) {
2465 } else if (flags
& TCG_CALL_NO_WRITE_GLOBALS
) {
2466 sync_globals(s
, allocated_regs
);
2468 save_globals(s
, allocated_regs
);
2471 tcg_out_call(s
, func_addr
);
2473 /* assign output registers and emit moves if needed */
2474 for(i
= 0; i
< nb_oargs
; i
++) {
2476 ts
= &s
->temps
[arg
];
2477 reg
= tcg_target_call_oarg_regs
[i
];
2478 tcg_debug_assert(s
->reg_to_temp
[reg
] == NULL
);
2480 if (ts
->fixed_reg
) {
2481 if (ts
->reg
!= reg
) {
2482 tcg_out_mov(s
, ts
->type
, ts
->reg
, reg
);
2485 if (ts
->val_type
== TEMP_VAL_REG
) {
2486 s
->reg_to_temp
[ts
->reg
] = NULL
;
2488 ts
->val_type
= TEMP_VAL_REG
;
2490 ts
->mem_coherent
= 0;
2491 s
->reg_to_temp
[reg
] = ts
;
2492 if (NEED_SYNC_ARG(i
)) {
2493 temp_sync(s
, ts
, allocated_regs
, IS_DEAD_ARG(i
));
2494 } else if (IS_DEAD_ARG(i
)) {
2501 #ifdef CONFIG_PROFILER
2503 static int64_t tcg_table_op_count
[NB_OPS
];
2505 void tcg_dump_op_count(FILE *f
, fprintf_function cpu_fprintf
)
2509 for (i
= 0; i
< NB_OPS
; i
++) {
2510 cpu_fprintf(f
, "%s %" PRId64
"\n", tcg_op_defs
[i
].name
,
2511 tcg_table_op_count
[i
]);
2515 void tcg_dump_op_count(FILE *f
, fprintf_function cpu_fprintf
)
2517 cpu_fprintf(f
, "[TCG profiler not compiled]\n");
2522 int tcg_gen_code(TCGContext
*s
, TranslationBlock
*tb
)
2524 int i
, oi
, oi_next
, num_insns
;
2526 #ifdef CONFIG_PROFILER
2530 n
= s
->gen_op_buf
[0].prev
+ 1;
2532 if (n
> s
->op_count_max
) {
2533 s
->op_count_max
= n
;
2538 if (n
> s
->temp_count_max
) {
2539 s
->temp_count_max
= n
;
2545 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP
)
2546 && qemu_log_in_addr_range(tb
->pc
))) {
2553 #ifdef CONFIG_PROFILER
2554 s
->opt_time
-= profile_getclock();
2557 #ifdef USE_TCG_OPTIMIZATIONS
2561 #ifdef CONFIG_PROFILER
2562 s
->opt_time
+= profile_getclock();
2563 s
->la_time
-= profile_getclock();
2567 uint8_t *temp_state
= tcg_malloc(s
->nb_temps
+ s
->nb_indirects
);
2569 liveness_pass_1(s
, temp_state
);
2571 if (s
->nb_indirects
> 0) {
2573 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_IND
)
2574 && qemu_log_in_addr_range(tb
->pc
))) {
2575 qemu_log("OP before indirect lowering:\n");
2580 /* Replace indirect temps with direct temps. */
2581 if (liveness_pass_2(s
, temp_state
)) {
2582 /* If changes were made, re-run liveness. */
2583 liveness_pass_1(s
, temp_state
);
2588 #ifdef CONFIG_PROFILER
2589 s
->la_time
+= profile_getclock();
2593 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_OPT
)
2594 && qemu_log_in_addr_range(tb
->pc
))) {
2595 qemu_log("OP after optimization and liveness analysis:\n");
2601 tcg_reg_alloc_start(s
);
2603 s
->code_buf
= tb
->tc_ptr
;
2604 s
->code_ptr
= tb
->tc_ptr
;
2609 for (oi
= s
->gen_op_buf
[0].next
; oi
!= 0; oi
= oi_next
) {
2610 TCGOp
* const op
= &s
->gen_op_buf
[oi
];
2611 TCGArg
* const args
= &s
->gen_opparam_buf
[op
->args
];
2612 TCGOpcode opc
= op
->opc
;
2613 const TCGOpDef
*def
= &tcg_op_defs
[opc
];
2614 TCGLifeData arg_life
= op
->life
;
2617 #ifdef CONFIG_PROFILER
2618 tcg_table_op_count
[opc
]++;
2622 case INDEX_op_mov_i32
:
2623 case INDEX_op_mov_i64
:
2624 tcg_reg_alloc_mov(s
, def
, args
, arg_life
);
2626 case INDEX_op_movi_i32
:
2627 case INDEX_op_movi_i64
:
2628 tcg_reg_alloc_movi(s
, args
, arg_life
);
2630 case INDEX_op_insn_start
:
2631 if (num_insns
>= 0) {
2632 s
->gen_insn_end_off
[num_insns
] = tcg_current_code_size(s
);
2635 for (i
= 0; i
< TARGET_INSN_START_WORDS
; ++i
) {
2637 #if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
2638 a
= ((target_ulong
)args
[i
* 2 + 1] << 32) | args
[i
* 2];
2642 s
->gen_insn_data
[num_insns
][i
] = a
;
2645 case INDEX_op_discard
:
2646 temp_dead(s
, &s
->temps
[args
[0]]);
2648 case INDEX_op_set_label
:
2649 tcg_reg_alloc_bb_end(s
, s
->reserved_regs
);
2650 tcg_out_label(s
, arg_label(args
[0]), s
->code_ptr
);
2653 tcg_reg_alloc_call(s
, op
->callo
, op
->calli
, args
, arg_life
);
2656 /* Sanity check that we've not introduced any unhandled opcodes. */
2657 if (def
->flags
& TCG_OPF_NOT_PRESENT
) {
2660 /* Note: in order to speed up the code, it would be much
2661 faster to have specialized register allocator functions for
2662 some common argument patterns */
2663 tcg_reg_alloc_op(s
, def
, opc
, args
, arg_life
);
2666 #ifdef CONFIG_DEBUG_TCG
2669 /* Test for (pending) buffer overflow. The assumption is that any
2670 one operation beginning below the high water mark cannot overrun
2671 the buffer completely. Thus we can test for overflow after
2672 generating code without having to check during generation. */
2673 if (unlikely((void *)s
->code_ptr
> s
->code_gen_highwater
)) {
2677 tcg_debug_assert(num_insns
>= 0);
2678 s
->gen_insn_end_off
[num_insns
] = tcg_current_code_size(s
);
2680 /* Generate TB finalization at the end of block */
2681 if (!tcg_out_tb_finalize(s
)) {
2685 /* flush instruction cache */
2686 flush_icache_range((uintptr_t)s
->code_buf
, (uintptr_t)s
->code_ptr
);
2688 return tcg_current_code_size(s
);
2691 #ifdef CONFIG_PROFILER
2692 void tcg_dump_info(FILE *f
, fprintf_function cpu_fprintf
)
2694 TCGContext
*s
= &tcg_ctx
;
2695 int64_t tb_count
= s
->tb_count
;
2696 int64_t tb_div_count
= tb_count
? tb_count
: 1;
2697 int64_t tot
= s
->interm_time
+ s
->code_time
;
2699 cpu_fprintf(f
, "JIT cycles %" PRId64
" (%0.3f s at 2.4 GHz)\n",
2701 cpu_fprintf(f
, "translated TBs %" PRId64
" (aborted=%" PRId64
" %0.1f%%)\n",
2702 tb_count
, s
->tb_count1
- tb_count
,
2703 (double)(s
->tb_count1
- s
->tb_count
)
2704 / (s
->tb_count1
? s
->tb_count1
: 1) * 100.0);
2705 cpu_fprintf(f
, "avg ops/TB %0.1f max=%d\n",
2706 (double)s
->op_count
/ tb_div_count
, s
->op_count_max
);
2707 cpu_fprintf(f
, "deleted ops/TB %0.2f\n",
2708 (double)s
->del_op_count
/ tb_div_count
);
2709 cpu_fprintf(f
, "avg temps/TB %0.2f max=%d\n",
2710 (double)s
->temp_count
/ tb_div_count
, s
->temp_count_max
);
2711 cpu_fprintf(f
, "avg host code/TB %0.1f\n",
2712 (double)s
->code_out_len
/ tb_div_count
);
2713 cpu_fprintf(f
, "avg search data/TB %0.1f\n",
2714 (double)s
->search_out_len
/ tb_div_count
);
2716 cpu_fprintf(f
, "cycles/op %0.1f\n",
2717 s
->op_count
? (double)tot
/ s
->op_count
: 0);
2718 cpu_fprintf(f
, "cycles/in byte %0.1f\n",
2719 s
->code_in_len
? (double)tot
/ s
->code_in_len
: 0);
2720 cpu_fprintf(f
, "cycles/out byte %0.1f\n",
2721 s
->code_out_len
? (double)tot
/ s
->code_out_len
: 0);
2722 cpu_fprintf(f
, "cycles/search byte %0.1f\n",
2723 s
->search_out_len
? (double)tot
/ s
->search_out_len
: 0);
2727 cpu_fprintf(f
, " gen_interm time %0.1f%%\n",
2728 (double)s
->interm_time
/ tot
* 100.0);
2729 cpu_fprintf(f
, " gen_code time %0.1f%%\n",
2730 (double)s
->code_time
/ tot
* 100.0);
2731 cpu_fprintf(f
, "optim./code time %0.1f%%\n",
2732 (double)s
->opt_time
/ (s
->code_time
? s
->code_time
: 1)
2734 cpu_fprintf(f
, "liveness/code time %0.1f%%\n",
2735 (double)s
->la_time
/ (s
->code_time
? s
->code_time
: 1) * 100.0);
2736 cpu_fprintf(f
, "cpu_restore count %" PRId64
"\n",
2738 cpu_fprintf(f
, " avg cycles %0.1f\n",
2739 s
->restore_count
? (double)s
->restore_time
/ s
->restore_count
: 0);
2742 void tcg_dump_info(FILE *f
, fprintf_function cpu_fprintf
)
2744 cpu_fprintf(f
, "[TCG profiler not compiled]\n");
2748 #ifdef ELF_HOST_MACHINE
2749 /* In order to use this feature, the backend needs to do three things:
2751 (1) Define ELF_HOST_MACHINE to indicate both what value to
2752 put into the ELF image and to indicate support for the feature.
2754 (2) Define tcg_register_jit. This should create a buffer containing
2755 the contents of a .debug_frame section that describes the post-
2756 prologue unwind info for the tcg machine.
2758 (3) Call tcg_register_jit_int, with the constructed .debug_frame.
2761 /* Begin GDB interface. THE FOLLOWING MUST MATCH GDB DOCS. */
2768 struct jit_code_entry
{
2769 struct jit_code_entry
*next_entry
;
2770 struct jit_code_entry
*prev_entry
;
2771 const void *symfile_addr
;
2772 uint64_t symfile_size
;
2775 struct jit_descriptor
{
2777 uint32_t action_flag
;
2778 struct jit_code_entry
*relevant_entry
;
2779 struct jit_code_entry
*first_entry
;
2782 void __jit_debug_register_code(void) __attribute__((noinline
));
2783 void __jit_debug_register_code(void)
2788 /* Must statically initialize the version, because GDB may check
2789 the version before we can set it. */
2790 struct jit_descriptor __jit_debug_descriptor
= { 1, 0, 0, 0 };
2792 /* End GDB interface. */
2794 static int find_string(const char *strtab
, const char *str
)
2796 const char *p
= strtab
+ 1;
2799 if (strcmp(p
, str
) == 0) {
2806 static void tcg_register_jit_int(void *buf_ptr
, size_t buf_size
,
2807 const void *debug_frame
,
2808 size_t debug_frame_size
)
2810 struct __attribute__((packed
)) DebugInfo
{
2817 uintptr_t cu_low_pc
;
2818 uintptr_t cu_high_pc
;
2821 uintptr_t fn_low_pc
;
2822 uintptr_t fn_high_pc
;
2831 struct DebugInfo di
;
2836 struct ElfImage
*img
;
2838 static const struct ElfImage img_template
= {
2840 .e_ident
[EI_MAG0
] = ELFMAG0
,
2841 .e_ident
[EI_MAG1
] = ELFMAG1
,
2842 .e_ident
[EI_MAG2
] = ELFMAG2
,
2843 .e_ident
[EI_MAG3
] = ELFMAG3
,
2844 .e_ident
[EI_CLASS
] = ELF_CLASS
,
2845 .e_ident
[EI_DATA
] = ELF_DATA
,
2846 .e_ident
[EI_VERSION
] = EV_CURRENT
,
2848 .e_machine
= ELF_HOST_MACHINE
,
2849 .e_version
= EV_CURRENT
,
2850 .e_phoff
= offsetof(struct ElfImage
, phdr
),
2851 .e_shoff
= offsetof(struct ElfImage
, shdr
),
2852 .e_ehsize
= sizeof(ElfW(Shdr
)),
2853 .e_phentsize
= sizeof(ElfW(Phdr
)),
2855 .e_shentsize
= sizeof(ElfW(Shdr
)),
2856 .e_shnum
= ARRAY_SIZE(img
->shdr
),
2857 .e_shstrndx
= ARRAY_SIZE(img
->shdr
) - 1,
2858 #ifdef ELF_HOST_FLAGS
2859 .e_flags
= ELF_HOST_FLAGS
,
2862 .e_ident
[EI_OSABI
] = ELF_OSABI
,
2870 [0] = { .sh_type
= SHT_NULL
},
2871 /* Trick: The contents of code_gen_buffer are not present in
2872 this fake ELF file; that got allocated elsewhere. Therefore
2873 we mark .text as SHT_NOBITS (similar to .bss) so that readers
2874 will not look for contents. We can record any address. */
2876 .sh_type
= SHT_NOBITS
,
2877 .sh_flags
= SHF_EXECINSTR
| SHF_ALLOC
,
2879 [2] = { /* .debug_info */
2880 .sh_type
= SHT_PROGBITS
,
2881 .sh_offset
= offsetof(struct ElfImage
, di
),
2882 .sh_size
= sizeof(struct DebugInfo
),
2884 [3] = { /* .debug_abbrev */
2885 .sh_type
= SHT_PROGBITS
,
2886 .sh_offset
= offsetof(struct ElfImage
, da
),
2887 .sh_size
= sizeof(img
->da
),
2889 [4] = { /* .debug_frame */
2890 .sh_type
= SHT_PROGBITS
,
2891 .sh_offset
= sizeof(struct ElfImage
),
2893 [5] = { /* .symtab */
2894 .sh_type
= SHT_SYMTAB
,
2895 .sh_offset
= offsetof(struct ElfImage
, sym
),
2896 .sh_size
= sizeof(img
->sym
),
2898 .sh_link
= ARRAY_SIZE(img
->shdr
) - 1,
2899 .sh_entsize
= sizeof(ElfW(Sym
)),
2901 [6] = { /* .strtab */
2902 .sh_type
= SHT_STRTAB
,
2903 .sh_offset
= offsetof(struct ElfImage
, str
),
2904 .sh_size
= sizeof(img
->str
),
2908 [1] = { /* code_gen_buffer */
2909 .st_info
= ELF_ST_INFO(STB_GLOBAL
, STT_FUNC
),
2914 .len
= sizeof(struct DebugInfo
) - 4,
2916 .ptr_size
= sizeof(void *),
2918 .cu_lang
= 0x8001, /* DW_LANG_Mips_Assembler */
2920 .fn_name
= "code_gen_buffer"
2923 1, /* abbrev number (the cu) */
2924 0x11, 1, /* DW_TAG_compile_unit, has children */
2925 0x13, 0x5, /* DW_AT_language, DW_FORM_data2 */
2926 0x11, 0x1, /* DW_AT_low_pc, DW_FORM_addr */
2927 0x12, 0x1, /* DW_AT_high_pc, DW_FORM_addr */
2928 0, 0, /* end of abbrev */
2929 2, /* abbrev number (the fn) */
2930 0x2e, 0, /* DW_TAG_subprogram, no children */
2931 0x3, 0x8, /* DW_AT_name, DW_FORM_string */
2932 0x11, 0x1, /* DW_AT_low_pc, DW_FORM_addr */
2933 0x12, 0x1, /* DW_AT_high_pc, DW_FORM_addr */
2934 0, 0, /* end of abbrev */
2935 0 /* no more abbrev */
2937 .str
= "\0" ".text\0" ".debug_info\0" ".debug_abbrev\0"
2938 ".debug_frame\0" ".symtab\0" ".strtab\0" "code_gen_buffer",
2941 /* We only need a single jit entry; statically allocate it. */
2942 static struct jit_code_entry one_entry
;
2944 uintptr_t buf
= (uintptr_t)buf_ptr
;
2945 size_t img_size
= sizeof(struct ElfImage
) + debug_frame_size
;
2946 DebugFrameHeader
*dfh
;
2948 img
= g_malloc(img_size
);
2949 *img
= img_template
;
2951 img
->phdr
.p_vaddr
= buf
;
2952 img
->phdr
.p_paddr
= buf
;
2953 img
->phdr
.p_memsz
= buf_size
;
2955 img
->shdr
[1].sh_name
= find_string(img
->str
, ".text");
2956 img
->shdr
[1].sh_addr
= buf
;
2957 img
->shdr
[1].sh_size
= buf_size
;
2959 img
->shdr
[2].sh_name
= find_string(img
->str
, ".debug_info");
2960 img
->shdr
[3].sh_name
= find_string(img
->str
, ".debug_abbrev");
2962 img
->shdr
[4].sh_name
= find_string(img
->str
, ".debug_frame");
2963 img
->shdr
[4].sh_size
= debug_frame_size
;
2965 img
->shdr
[5].sh_name
= find_string(img
->str
, ".symtab");
2966 img
->shdr
[6].sh_name
= find_string(img
->str
, ".strtab");
2968 img
->sym
[1].st_name
= find_string(img
->str
, "code_gen_buffer");
2969 img
->sym
[1].st_value
= buf
;
2970 img
->sym
[1].st_size
= buf_size
;
2972 img
->di
.cu_low_pc
= buf
;
2973 img
->di
.cu_high_pc
= buf
+ buf_size
;
2974 img
->di
.fn_low_pc
= buf
;
2975 img
->di
.fn_high_pc
= buf
+ buf_size
;
2977 dfh
= (DebugFrameHeader
*)(img
+ 1);
2978 memcpy(dfh
, debug_frame
, debug_frame_size
);
2979 dfh
->fde
.func_start
= buf
;
2980 dfh
->fde
.func_len
= buf_size
;
2983 /* Enable this block to be able to debug the ELF image file creation.
2984 One can use readelf, objdump, or other inspection utilities. */
2986 FILE *f
= fopen("/tmp/qemu.jit", "w+b");
2988 if (fwrite(img
, img_size
, 1, f
) != img_size
) {
2989 /* Avoid stupid unused return value warning for fwrite. */
2996 one_entry
.symfile_addr
= img
;
2997 one_entry
.symfile_size
= img_size
;
2999 __jit_debug_descriptor
.action_flag
= JIT_REGISTER_FN
;
3000 __jit_debug_descriptor
.relevant_entry
= &one_entry
;
3001 __jit_debug_descriptor
.first_entry
= &one_entry
;
3002 __jit_debug_register_code();
3005 /* No support for the feature. Provide the entry point expected by exec.c,
3006 and implement the internal function we declared earlier. */
3008 static void tcg_register_jit_int(void *buf
, size_t size
,
3009 const void *debug_frame
,
3010 size_t debug_frame_size
)
3014 void tcg_register_jit(void *buf
, size_t buf_size
)
3017 #endif /* ELF_HOST_MACHINE */