macio.c: include parent PCIDevice state in VMStateDescription
[qemu/ar7.git] / tcg / tcg.c
blob3841e9951c949fb966d6cbe726fcb39e3e17b94a
1 /*
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
22 * THE SOFTWARE.
25 /* define it to use liveness analysis (better code) */
26 #define USE_LIVENESS_ANALYSIS
27 #define USE_TCG_OPTIMIZATIONS
29 #include "config.h"
31 /* Define to jump the ELF file used to communicate with GDB. */
32 #undef DEBUG_JIT
34 #if !defined(CONFIG_DEBUG_TCG) && !defined(NDEBUG)
35 /* define it to suppress various consistency checks (faster) */
36 #define NDEBUG
37 #endif
39 #include "qemu-common.h"
40 #include "qemu/host-utils.h"
41 #include "qemu/timer.h"
43 /* Note: the long term plan is to reduce the dependencies on the QEMU
44 CPU definitions. Currently they are used for qemu_ld/st
45 instructions */
46 #define NO_CPU_IO_DEFS
47 #include "cpu.h"
49 #include "tcg-op.h"
51 #if UINTPTR_MAX == UINT32_MAX
52 # define ELF_CLASS ELFCLASS32
53 #else
54 # define ELF_CLASS ELFCLASS64
55 #endif
56 #ifdef HOST_WORDS_BIGENDIAN
57 # define ELF_DATA ELFDATA2MSB
58 #else
59 # define ELF_DATA ELFDATA2LSB
60 #endif
62 #include "elf.h"
64 /* Forward declarations for functions declared in tcg-target.c and used here. */
65 static void tcg_target_init(TCGContext *s);
66 static void tcg_target_qemu_prologue(TCGContext *s);
67 static void patch_reloc(tcg_insn_unit *code_ptr, int type,
68 intptr_t value, intptr_t addend);
70 /* The CIE and FDE header definitions will be common to all hosts. */
71 typedef struct {
72 uint32_t len __attribute__((aligned((sizeof(void *)))));
73 uint32_t id;
74 uint8_t version;
75 char augmentation[1];
76 uint8_t code_align;
77 uint8_t data_align;
78 uint8_t return_column;
79 } DebugFrameCIE;
81 typedef struct QEMU_PACKED {
82 uint32_t len __attribute__((aligned((sizeof(void *)))));
83 uint32_t cie_offset;
84 uintptr_t func_start;
85 uintptr_t func_len;
86 } DebugFrameFDEHeader;
88 typedef struct QEMU_PACKED {
89 DebugFrameCIE cie;
90 DebugFrameFDEHeader fde;
91 } DebugFrameHeader;
93 static void tcg_register_jit_int(void *buf, size_t size,
94 const void *debug_frame,
95 size_t debug_frame_size)
96 __attribute__((unused));
98 /* Forward declarations for functions declared and used in tcg-target.c. */
99 static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str);
100 static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg1,
101 intptr_t arg2);
102 static void tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg);
103 static void tcg_out_movi(TCGContext *s, TCGType type,
104 TCGReg ret, tcg_target_long arg);
105 static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
106 const int *const_args);
107 static void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, TCGReg arg1,
108 intptr_t arg2);
109 static void tcg_out_call(TCGContext *s, tcg_insn_unit *target);
110 static int tcg_target_const_match(tcg_target_long val, TCGType type,
111 const TCGArgConstraint *arg_ct);
112 static void tcg_out_tb_init(TCGContext *s);
113 static void tcg_out_tb_finalize(TCGContext *s);
116 TCGOpDef tcg_op_defs[] = {
117 #define DEF(s, oargs, iargs, cargs, flags) { #s, oargs, iargs, cargs, iargs + oargs + cargs, flags },
118 #include "tcg-opc.h"
119 #undef DEF
121 const size_t tcg_op_defs_max = ARRAY_SIZE(tcg_op_defs);
123 static TCGRegSet tcg_target_available_regs[2];
124 static TCGRegSet tcg_target_call_clobber_regs;
126 #if TCG_TARGET_INSN_UNIT_SIZE == 1
127 static __attribute__((unused)) inline void tcg_out8(TCGContext *s, uint8_t v)
129 *s->code_ptr++ = v;
132 static __attribute__((unused)) inline void tcg_patch8(tcg_insn_unit *p,
133 uint8_t v)
135 *p = v;
137 #endif
139 #if TCG_TARGET_INSN_UNIT_SIZE <= 2
140 static __attribute__((unused)) inline void tcg_out16(TCGContext *s, uint16_t v)
142 if (TCG_TARGET_INSN_UNIT_SIZE == 2) {
143 *s->code_ptr++ = v;
144 } else {
145 tcg_insn_unit *p = s->code_ptr;
146 memcpy(p, &v, sizeof(v));
147 s->code_ptr = p + (2 / TCG_TARGET_INSN_UNIT_SIZE);
151 static __attribute__((unused)) inline void tcg_patch16(tcg_insn_unit *p,
152 uint16_t v)
154 if (TCG_TARGET_INSN_UNIT_SIZE == 2) {
155 *p = v;
156 } else {
157 memcpy(p, &v, sizeof(v));
160 #endif
162 #if TCG_TARGET_INSN_UNIT_SIZE <= 4
163 static __attribute__((unused)) inline void tcg_out32(TCGContext *s, uint32_t v)
165 if (TCG_TARGET_INSN_UNIT_SIZE == 4) {
166 *s->code_ptr++ = v;
167 } else {
168 tcg_insn_unit *p = s->code_ptr;
169 memcpy(p, &v, sizeof(v));
170 s->code_ptr = p + (4 / TCG_TARGET_INSN_UNIT_SIZE);
174 static __attribute__((unused)) inline void tcg_patch32(tcg_insn_unit *p,
175 uint32_t v)
177 if (TCG_TARGET_INSN_UNIT_SIZE == 4) {
178 *p = v;
179 } else {
180 memcpy(p, &v, sizeof(v));
183 #endif
185 #if TCG_TARGET_INSN_UNIT_SIZE <= 8
186 static __attribute__((unused)) inline void tcg_out64(TCGContext *s, uint64_t v)
188 if (TCG_TARGET_INSN_UNIT_SIZE == 8) {
189 *s->code_ptr++ = v;
190 } else {
191 tcg_insn_unit *p = s->code_ptr;
192 memcpy(p, &v, sizeof(v));
193 s->code_ptr = p + (8 / TCG_TARGET_INSN_UNIT_SIZE);
197 static __attribute__((unused)) inline void tcg_patch64(tcg_insn_unit *p,
198 uint64_t v)
200 if (TCG_TARGET_INSN_UNIT_SIZE == 8) {
201 *p = v;
202 } else {
203 memcpy(p, &v, sizeof(v));
206 #endif
208 /* label relocation processing */
210 static void tcg_out_reloc(TCGContext *s, tcg_insn_unit *code_ptr, int type,
211 int label_index, intptr_t addend)
213 TCGLabel *l;
214 TCGRelocation *r;
216 l = &s->labels[label_index];
217 if (l->has_value) {
218 /* FIXME: This may break relocations on RISC targets that
219 modify instruction fields in place. The caller may not have
220 written the initial value. */
221 patch_reloc(code_ptr, type, l->u.value, addend);
222 } else {
223 /* add a new relocation entry */
224 r = tcg_malloc(sizeof(TCGRelocation));
225 r->type = type;
226 r->ptr = code_ptr;
227 r->addend = addend;
228 r->next = l->u.first_reloc;
229 l->u.first_reloc = r;
233 static void tcg_out_label(TCGContext *s, int label_index, tcg_insn_unit *ptr)
235 TCGLabel *l = &s->labels[label_index];
236 intptr_t value = (intptr_t)ptr;
237 TCGRelocation *r;
239 assert(!l->has_value);
241 for (r = l->u.first_reloc; r != NULL; r = r->next) {
242 patch_reloc(r->ptr, r->type, value, r->addend);
245 l->has_value = 1;
246 l->u.value_ptr = ptr;
249 int gen_new_label(void)
251 TCGContext *s = &tcg_ctx;
252 int idx;
253 TCGLabel *l;
255 if (s->nb_labels >= TCG_MAX_LABELS)
256 tcg_abort();
257 idx = s->nb_labels++;
258 l = &s->labels[idx];
259 l->has_value = 0;
260 l->u.first_reloc = NULL;
261 return idx;
264 #include "tcg-target.c"
266 /* pool based memory allocation */
267 void *tcg_malloc_internal(TCGContext *s, int size)
269 TCGPool *p;
270 int pool_size;
272 if (size > TCG_POOL_CHUNK_SIZE) {
273 /* big malloc: insert a new pool (XXX: could optimize) */
274 p = g_malloc(sizeof(TCGPool) + size);
275 p->size = size;
276 p->next = s->pool_first_large;
277 s->pool_first_large = p;
278 return p->data;
279 } else {
280 p = s->pool_current;
281 if (!p) {
282 p = s->pool_first;
283 if (!p)
284 goto new_pool;
285 } else {
286 if (!p->next) {
287 new_pool:
288 pool_size = TCG_POOL_CHUNK_SIZE;
289 p = g_malloc(sizeof(TCGPool) + pool_size);
290 p->size = pool_size;
291 p->next = NULL;
292 if (s->pool_current)
293 s->pool_current->next = p;
294 else
295 s->pool_first = p;
296 } else {
297 p = p->next;
301 s->pool_current = p;
302 s->pool_cur = p->data + size;
303 s->pool_end = p->data + p->size;
304 return p->data;
307 void tcg_pool_reset(TCGContext *s)
309 TCGPool *p, *t;
310 for (p = s->pool_first_large; p; p = t) {
311 t = p->next;
312 g_free(p);
314 s->pool_first_large = NULL;
315 s->pool_cur = s->pool_end = NULL;
316 s->pool_current = NULL;
319 typedef struct TCGHelperInfo {
320 void *func;
321 const char *name;
322 unsigned flags;
323 unsigned sizemask;
324 } TCGHelperInfo;
326 #include "exec/helper-proto.h"
328 static const TCGHelperInfo all_helpers[] = {
329 #include "exec/helper-tcg.h"
332 void tcg_context_init(TCGContext *s)
334 int op, total_args, n, i;
335 TCGOpDef *def;
336 TCGArgConstraint *args_ct;
337 int *sorted_args;
338 GHashTable *helper_table;
340 memset(s, 0, sizeof(*s));
341 s->nb_globals = 0;
343 /* Count total number of arguments and allocate the corresponding
344 space */
345 total_args = 0;
346 for(op = 0; op < NB_OPS; op++) {
347 def = &tcg_op_defs[op];
348 n = def->nb_iargs + def->nb_oargs;
349 total_args += n;
352 args_ct = g_malloc(sizeof(TCGArgConstraint) * total_args);
353 sorted_args = g_malloc(sizeof(int) * total_args);
355 for(op = 0; op < NB_OPS; op++) {
356 def = &tcg_op_defs[op];
357 def->args_ct = args_ct;
358 def->sorted_args = sorted_args;
359 n = def->nb_iargs + def->nb_oargs;
360 sorted_args += n;
361 args_ct += n;
364 /* Register helpers. */
365 /* Use g_direct_hash/equal for direct pointer comparisons on func. */
366 s->helpers = helper_table = g_hash_table_new(NULL, NULL);
368 for (i = 0; i < ARRAY_SIZE(all_helpers); ++i) {
369 g_hash_table_insert(helper_table, (gpointer)all_helpers[i].func,
370 (gpointer)&all_helpers[i]);
373 tcg_target_init(s);
376 void tcg_prologue_init(TCGContext *s)
378 /* init global prologue and epilogue */
379 s->code_buf = s->code_gen_prologue;
380 s->code_ptr = s->code_buf;
381 tcg_target_qemu_prologue(s);
382 flush_icache_range((uintptr_t)s->code_buf, (uintptr_t)s->code_ptr);
384 #ifdef DEBUG_DISAS
385 if (qemu_loglevel_mask(CPU_LOG_TB_OUT_ASM)) {
386 size_t size = tcg_current_code_size(s);
387 qemu_log("PROLOGUE: [size=%zu]\n", size);
388 log_disas(s->code_buf, size);
389 qemu_log("\n");
390 qemu_log_flush();
392 #endif
395 void tcg_set_frame(TCGContext *s, int reg, intptr_t start, intptr_t size)
397 s->frame_start = start;
398 s->frame_end = start + size;
399 s->frame_reg = reg;
402 void tcg_func_start(TCGContext *s)
404 tcg_pool_reset(s);
405 s->nb_temps = s->nb_globals;
407 /* No temps have been previously allocated for size or locality. */
408 memset(s->free_temps, 0, sizeof(s->free_temps));
410 s->nb_labels = 0;
411 s->current_frame_offset = s->frame_start;
413 #ifdef CONFIG_DEBUG_TCG
414 s->goto_tb_issue_mask = 0;
415 #endif
417 s->gen_first_op_idx = 0;
418 s->gen_last_op_idx = -1;
419 s->gen_next_op_idx = 0;
420 s->gen_next_parm_idx = 0;
422 s->be = tcg_malloc(sizeof(TCGBackendData));
425 static inline void tcg_temp_alloc(TCGContext *s, int n)
427 if (n > TCG_MAX_TEMPS)
428 tcg_abort();
431 static inline int tcg_global_reg_new_internal(TCGType type, int reg,
432 const char *name)
434 TCGContext *s = &tcg_ctx;
435 TCGTemp *ts;
436 int idx;
438 #if TCG_TARGET_REG_BITS == 32
439 if (type != TCG_TYPE_I32)
440 tcg_abort();
441 #endif
442 if (tcg_regset_test_reg(s->reserved_regs, reg))
443 tcg_abort();
444 idx = s->nb_globals;
445 tcg_temp_alloc(s, s->nb_globals + 1);
446 ts = &s->temps[s->nb_globals];
447 ts->base_type = type;
448 ts->type = type;
449 ts->fixed_reg = 1;
450 ts->reg = reg;
451 ts->name = name;
452 s->nb_globals++;
453 tcg_regset_set_reg(s->reserved_regs, reg);
454 return idx;
457 TCGv_i32 tcg_global_reg_new_i32(int reg, const char *name)
459 int idx;
461 idx = tcg_global_reg_new_internal(TCG_TYPE_I32, reg, name);
462 return MAKE_TCGV_I32(idx);
465 TCGv_i64 tcg_global_reg_new_i64(int reg, const char *name)
467 int idx;
469 idx = tcg_global_reg_new_internal(TCG_TYPE_I64, reg, name);
470 return MAKE_TCGV_I64(idx);
473 static inline int tcg_global_mem_new_internal(TCGType type, int reg,
474 intptr_t offset,
475 const char *name)
477 TCGContext *s = &tcg_ctx;
478 TCGTemp *ts;
479 int idx;
481 idx = s->nb_globals;
482 #if TCG_TARGET_REG_BITS == 32
483 if (type == TCG_TYPE_I64) {
484 char buf[64];
485 tcg_temp_alloc(s, s->nb_globals + 2);
486 ts = &s->temps[s->nb_globals];
487 ts->base_type = type;
488 ts->type = TCG_TYPE_I32;
489 ts->fixed_reg = 0;
490 ts->mem_allocated = 1;
491 ts->mem_reg = reg;
492 #ifdef HOST_WORDS_BIGENDIAN
493 ts->mem_offset = offset + 4;
494 #else
495 ts->mem_offset = offset;
496 #endif
497 pstrcpy(buf, sizeof(buf), name);
498 pstrcat(buf, sizeof(buf), "_0");
499 ts->name = strdup(buf);
500 ts++;
502 ts->base_type = type;
503 ts->type = TCG_TYPE_I32;
504 ts->fixed_reg = 0;
505 ts->mem_allocated = 1;
506 ts->mem_reg = reg;
507 #ifdef HOST_WORDS_BIGENDIAN
508 ts->mem_offset = offset;
509 #else
510 ts->mem_offset = offset + 4;
511 #endif
512 pstrcpy(buf, sizeof(buf), name);
513 pstrcat(buf, sizeof(buf), "_1");
514 ts->name = strdup(buf);
516 s->nb_globals += 2;
517 } else
518 #endif
520 tcg_temp_alloc(s, s->nb_globals + 1);
521 ts = &s->temps[s->nb_globals];
522 ts->base_type = type;
523 ts->type = type;
524 ts->fixed_reg = 0;
525 ts->mem_allocated = 1;
526 ts->mem_reg = reg;
527 ts->mem_offset = offset;
528 ts->name = name;
529 s->nb_globals++;
531 return idx;
534 TCGv_i32 tcg_global_mem_new_i32(int reg, intptr_t offset, const char *name)
536 int idx = tcg_global_mem_new_internal(TCG_TYPE_I32, reg, offset, name);
537 return MAKE_TCGV_I32(idx);
540 TCGv_i64 tcg_global_mem_new_i64(int reg, intptr_t offset, const char *name)
542 int idx = tcg_global_mem_new_internal(TCG_TYPE_I64, reg, offset, name);
543 return MAKE_TCGV_I64(idx);
546 static inline int tcg_temp_new_internal(TCGType type, int temp_local)
548 TCGContext *s = &tcg_ctx;
549 TCGTemp *ts;
550 int idx, k;
552 k = type + (temp_local ? TCG_TYPE_COUNT : 0);
553 idx = find_first_bit(s->free_temps[k].l, TCG_MAX_TEMPS);
554 if (idx < TCG_MAX_TEMPS) {
555 /* There is already an available temp with the right type. */
556 clear_bit(idx, s->free_temps[k].l);
558 ts = &s->temps[idx];
559 ts->temp_allocated = 1;
560 assert(ts->base_type == type);
561 assert(ts->temp_local == temp_local);
562 } else {
563 idx = s->nb_temps;
564 #if TCG_TARGET_REG_BITS == 32
565 if (type == TCG_TYPE_I64) {
566 tcg_temp_alloc(s, s->nb_temps + 2);
567 ts = &s->temps[s->nb_temps];
568 ts->base_type = type;
569 ts->type = TCG_TYPE_I32;
570 ts->temp_allocated = 1;
571 ts->temp_local = temp_local;
572 ts->name = NULL;
573 ts++;
574 ts->base_type = type;
575 ts->type = TCG_TYPE_I32;
576 ts->temp_allocated = 1;
577 ts->temp_local = temp_local;
578 ts->name = NULL;
579 s->nb_temps += 2;
580 } else
581 #endif
583 tcg_temp_alloc(s, s->nb_temps + 1);
584 ts = &s->temps[s->nb_temps];
585 ts->base_type = type;
586 ts->type = type;
587 ts->temp_allocated = 1;
588 ts->temp_local = temp_local;
589 ts->name = NULL;
590 s->nb_temps++;
594 #if defined(CONFIG_DEBUG_TCG)
595 s->temps_in_use++;
596 #endif
597 return idx;
600 TCGv_i32 tcg_temp_new_internal_i32(int temp_local)
602 int idx;
604 idx = tcg_temp_new_internal(TCG_TYPE_I32, temp_local);
605 return MAKE_TCGV_I32(idx);
608 TCGv_i64 tcg_temp_new_internal_i64(int temp_local)
610 int idx;
612 idx = tcg_temp_new_internal(TCG_TYPE_I64, temp_local);
613 return MAKE_TCGV_I64(idx);
616 static void tcg_temp_free_internal(int idx)
618 TCGContext *s = &tcg_ctx;
619 TCGTemp *ts;
620 int k;
622 #if defined(CONFIG_DEBUG_TCG)
623 s->temps_in_use--;
624 if (s->temps_in_use < 0) {
625 fprintf(stderr, "More temporaries freed than allocated!\n");
627 #endif
629 assert(idx >= s->nb_globals && idx < s->nb_temps);
630 ts = &s->temps[idx];
631 assert(ts->temp_allocated != 0);
632 ts->temp_allocated = 0;
634 k = ts->base_type + (ts->temp_local ? TCG_TYPE_COUNT : 0);
635 set_bit(idx, s->free_temps[k].l);
638 void tcg_temp_free_i32(TCGv_i32 arg)
640 tcg_temp_free_internal(GET_TCGV_I32(arg));
643 void tcg_temp_free_i64(TCGv_i64 arg)
645 tcg_temp_free_internal(GET_TCGV_I64(arg));
648 TCGv_i32 tcg_const_i32(int32_t val)
650 TCGv_i32 t0;
651 t0 = tcg_temp_new_i32();
652 tcg_gen_movi_i32(t0, val);
653 return t0;
656 TCGv_i64 tcg_const_i64(int64_t val)
658 TCGv_i64 t0;
659 t0 = tcg_temp_new_i64();
660 tcg_gen_movi_i64(t0, val);
661 return t0;
664 TCGv_i32 tcg_const_local_i32(int32_t val)
666 TCGv_i32 t0;
667 t0 = tcg_temp_local_new_i32();
668 tcg_gen_movi_i32(t0, val);
669 return t0;
672 TCGv_i64 tcg_const_local_i64(int64_t val)
674 TCGv_i64 t0;
675 t0 = tcg_temp_local_new_i64();
676 tcg_gen_movi_i64(t0, val);
677 return t0;
680 #if defined(CONFIG_DEBUG_TCG)
681 void tcg_clear_temp_count(void)
683 TCGContext *s = &tcg_ctx;
684 s->temps_in_use = 0;
687 int tcg_check_temp_count(void)
689 TCGContext *s = &tcg_ctx;
690 if (s->temps_in_use) {
691 /* Clear the count so that we don't give another
692 * warning immediately next time around.
694 s->temps_in_use = 0;
695 return 1;
697 return 0;
699 #endif
701 /* Note: we convert the 64 bit args to 32 bit and do some alignment
702 and endian swap. Maybe it would be better to do the alignment
703 and endian swap in tcg_reg_alloc_call(). */
704 void tcg_gen_callN(TCGContext *s, void *func, TCGArg ret,
705 int nargs, TCGArg *args)
707 int i, real_args, nb_rets, pi, pi_first;
708 unsigned sizemask, flags;
709 TCGHelperInfo *info;
711 info = g_hash_table_lookup(s->helpers, (gpointer)func);
712 flags = info->flags;
713 sizemask = info->sizemask;
715 #if defined(__sparc__) && !defined(__arch64__) \
716 && !defined(CONFIG_TCG_INTERPRETER)
717 /* We have 64-bit values in one register, but need to pass as two
718 separate parameters. Split them. */
719 int orig_sizemask = sizemask;
720 int orig_nargs = nargs;
721 TCGv_i64 retl, reth;
723 TCGV_UNUSED_I64(retl);
724 TCGV_UNUSED_I64(reth);
725 if (sizemask != 0) {
726 TCGArg *split_args = __builtin_alloca(sizeof(TCGArg) * nargs * 2);
727 for (i = real_args = 0; i < nargs; ++i) {
728 int is_64bit = sizemask & (1 << (i+1)*2);
729 if (is_64bit) {
730 TCGv_i64 orig = MAKE_TCGV_I64(args[i]);
731 TCGv_i32 h = tcg_temp_new_i32();
732 TCGv_i32 l = tcg_temp_new_i32();
733 tcg_gen_extr_i64_i32(l, h, orig);
734 split_args[real_args++] = GET_TCGV_I32(h);
735 split_args[real_args++] = GET_TCGV_I32(l);
736 } else {
737 split_args[real_args++] = args[i];
740 nargs = real_args;
741 args = split_args;
742 sizemask = 0;
744 #elif defined(TCG_TARGET_EXTEND_ARGS) && TCG_TARGET_REG_BITS == 64
745 for (i = 0; i < nargs; ++i) {
746 int is_64bit = sizemask & (1 << (i+1)*2);
747 int is_signed = sizemask & (2 << (i+1)*2);
748 if (!is_64bit) {
749 TCGv_i64 temp = tcg_temp_new_i64();
750 TCGv_i64 orig = MAKE_TCGV_I64(args[i]);
751 if (is_signed) {
752 tcg_gen_ext32s_i64(temp, orig);
753 } else {
754 tcg_gen_ext32u_i64(temp, orig);
756 args[i] = GET_TCGV_I64(temp);
759 #endif /* TCG_TARGET_EXTEND_ARGS */
761 pi_first = pi = s->gen_next_parm_idx;
762 if (ret != TCG_CALL_DUMMY_ARG) {
763 #if defined(__sparc__) && !defined(__arch64__) \
764 && !defined(CONFIG_TCG_INTERPRETER)
765 if (orig_sizemask & 1) {
766 /* The 32-bit ABI is going to return the 64-bit value in
767 the %o0/%o1 register pair. Prepare for this by using
768 two return temporaries, and reassemble below. */
769 retl = tcg_temp_new_i64();
770 reth = tcg_temp_new_i64();
771 s->gen_opparam_buf[pi++] = GET_TCGV_I64(reth);
772 s->gen_opparam_buf[pi++] = GET_TCGV_I64(retl);
773 nb_rets = 2;
774 } else {
775 s->gen_opparam_buf[pi++] = ret;
776 nb_rets = 1;
778 #else
779 if (TCG_TARGET_REG_BITS < 64 && (sizemask & 1)) {
780 #ifdef HOST_WORDS_BIGENDIAN
781 s->gen_opparam_buf[pi++] = ret + 1;
782 s->gen_opparam_buf[pi++] = ret;
783 #else
784 s->gen_opparam_buf[pi++] = ret;
785 s->gen_opparam_buf[pi++] = ret + 1;
786 #endif
787 nb_rets = 2;
788 } else {
789 s->gen_opparam_buf[pi++] = ret;
790 nb_rets = 1;
792 #endif
793 } else {
794 nb_rets = 0;
796 real_args = 0;
797 for (i = 0; i < nargs; i++) {
798 int is_64bit = sizemask & (1 << (i+1)*2);
799 if (TCG_TARGET_REG_BITS < 64 && is_64bit) {
800 #ifdef TCG_TARGET_CALL_ALIGN_ARGS
801 /* some targets want aligned 64 bit args */
802 if (real_args & 1) {
803 s->gen_opparam_buf[pi++] = TCG_CALL_DUMMY_ARG;
804 real_args++;
806 #endif
807 /* If stack grows up, then we will be placing successive
808 arguments at lower addresses, which means we need to
809 reverse the order compared to how we would normally
810 treat either big or little-endian. For those arguments
811 that will wind up in registers, this still works for
812 HPPA (the only current STACK_GROWSUP target) since the
813 argument registers are *also* allocated in decreasing
814 order. If another such target is added, this logic may
815 have to get more complicated to differentiate between
816 stack arguments and register arguments. */
817 #if defined(HOST_WORDS_BIGENDIAN) != defined(TCG_TARGET_STACK_GROWSUP)
818 s->gen_opparam_buf[pi++] = args[i] + 1;
819 s->gen_opparam_buf[pi++] = args[i];
820 #else
821 s->gen_opparam_buf[pi++] = args[i];
822 s->gen_opparam_buf[pi++] = args[i] + 1;
823 #endif
824 real_args += 2;
825 continue;
828 s->gen_opparam_buf[pi++] = args[i];
829 real_args++;
831 s->gen_opparam_buf[pi++] = (uintptr_t)func;
832 s->gen_opparam_buf[pi++] = flags;
834 i = s->gen_next_op_idx;
835 tcg_debug_assert(i < OPC_BUF_SIZE);
836 tcg_debug_assert(pi <= OPPARAM_BUF_SIZE);
838 /* Set links for sequential allocation during translation. */
839 s->gen_op_buf[i] = (TCGOp){
840 .opc = INDEX_op_call,
841 .callo = nb_rets,
842 .calli = real_args,
843 .args = pi_first,
844 .prev = i - 1,
845 .next = i + 1
848 /* Make sure the calli field didn't overflow. */
849 tcg_debug_assert(s->gen_op_buf[i].calli == real_args);
851 s->gen_last_op_idx = i;
852 s->gen_next_op_idx = i + 1;
853 s->gen_next_parm_idx = pi;
855 #if defined(__sparc__) && !defined(__arch64__) \
856 && !defined(CONFIG_TCG_INTERPRETER)
857 /* Free all of the parts we allocated above. */
858 for (i = real_args = 0; i < orig_nargs; ++i) {
859 int is_64bit = orig_sizemask & (1 << (i+1)*2);
860 if (is_64bit) {
861 TCGv_i32 h = MAKE_TCGV_I32(args[real_args++]);
862 TCGv_i32 l = MAKE_TCGV_I32(args[real_args++]);
863 tcg_temp_free_i32(h);
864 tcg_temp_free_i32(l);
865 } else {
866 real_args++;
869 if (orig_sizemask & 1) {
870 /* The 32-bit ABI returned two 32-bit pieces. Re-assemble them.
871 Note that describing these as TCGv_i64 eliminates an unnecessary
872 zero-extension that tcg_gen_concat_i32_i64 would create. */
873 tcg_gen_concat32_i64(MAKE_TCGV_I64(ret), retl, reth);
874 tcg_temp_free_i64(retl);
875 tcg_temp_free_i64(reth);
877 #elif defined(TCG_TARGET_EXTEND_ARGS) && TCG_TARGET_REG_BITS == 64
878 for (i = 0; i < nargs; ++i) {
879 int is_64bit = sizemask & (1 << (i+1)*2);
880 if (!is_64bit) {
881 TCGv_i64 temp = MAKE_TCGV_I64(args[i]);
882 tcg_temp_free_i64(temp);
885 #endif /* TCG_TARGET_EXTEND_ARGS */
888 static void tcg_reg_alloc_start(TCGContext *s)
890 int i;
891 TCGTemp *ts;
892 for(i = 0; i < s->nb_globals; i++) {
893 ts = &s->temps[i];
894 if (ts->fixed_reg) {
895 ts->val_type = TEMP_VAL_REG;
896 } else {
897 ts->val_type = TEMP_VAL_MEM;
900 for(i = s->nb_globals; i < s->nb_temps; i++) {
901 ts = &s->temps[i];
902 if (ts->temp_local) {
903 ts->val_type = TEMP_VAL_MEM;
904 } else {
905 ts->val_type = TEMP_VAL_DEAD;
907 ts->mem_allocated = 0;
908 ts->fixed_reg = 0;
910 for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
911 s->reg_to_temp[i] = -1;
915 static char *tcg_get_arg_str_idx(TCGContext *s, char *buf, int buf_size,
916 int idx)
918 TCGTemp *ts;
920 assert(idx >= 0 && idx < s->nb_temps);
921 ts = &s->temps[idx];
922 if (idx < s->nb_globals) {
923 pstrcpy(buf, buf_size, ts->name);
924 } else {
925 if (ts->temp_local)
926 snprintf(buf, buf_size, "loc%d", idx - s->nb_globals);
927 else
928 snprintf(buf, buf_size, "tmp%d", idx - s->nb_globals);
930 return buf;
933 char *tcg_get_arg_str_i32(TCGContext *s, char *buf, int buf_size, TCGv_i32 arg)
935 return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I32(arg));
938 char *tcg_get_arg_str_i64(TCGContext *s, char *buf, int buf_size, TCGv_i64 arg)
940 return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I64(arg));
943 /* Find helper name. */
944 static inline const char *tcg_find_helper(TCGContext *s, uintptr_t val)
946 const char *ret = NULL;
947 if (s->helpers) {
948 TCGHelperInfo *info = g_hash_table_lookup(s->helpers, (gpointer)val);
949 if (info) {
950 ret = info->name;
953 return ret;
956 static const char * const cond_name[] =
958 [TCG_COND_NEVER] = "never",
959 [TCG_COND_ALWAYS] = "always",
960 [TCG_COND_EQ] = "eq",
961 [TCG_COND_NE] = "ne",
962 [TCG_COND_LT] = "lt",
963 [TCG_COND_GE] = "ge",
964 [TCG_COND_LE] = "le",
965 [TCG_COND_GT] = "gt",
966 [TCG_COND_LTU] = "ltu",
967 [TCG_COND_GEU] = "geu",
968 [TCG_COND_LEU] = "leu",
969 [TCG_COND_GTU] = "gtu"
972 static const char * const ldst_name[] =
974 [MO_UB] = "ub",
975 [MO_SB] = "sb",
976 [MO_LEUW] = "leuw",
977 [MO_LESW] = "lesw",
978 [MO_LEUL] = "leul",
979 [MO_LESL] = "lesl",
980 [MO_LEQ] = "leq",
981 [MO_BEUW] = "beuw",
982 [MO_BESW] = "besw",
983 [MO_BEUL] = "beul",
984 [MO_BESL] = "besl",
985 [MO_BEQ] = "beq",
988 void tcg_dump_ops(TCGContext *s)
990 char buf[128];
991 TCGOp *op;
992 int oi;
994 for (oi = s->gen_first_op_idx; oi >= 0; oi = op->next) {
995 int i, k, nb_oargs, nb_iargs, nb_cargs;
996 const TCGOpDef *def;
997 const TCGArg *args;
998 TCGOpcode c;
1000 op = &s->gen_op_buf[oi];
1001 c = op->opc;
1002 def = &tcg_op_defs[c];
1003 args = &s->gen_opparam_buf[op->args];
1005 if (c == INDEX_op_debug_insn_start) {
1006 uint64_t pc;
1007 #if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
1008 pc = ((uint64_t)args[1] << 32) | args[0];
1009 #else
1010 pc = args[0];
1011 #endif
1012 if (oi != s->gen_first_op_idx) {
1013 qemu_log("\n");
1015 qemu_log(" ---- 0x%" PRIx64, pc);
1016 } else if (c == INDEX_op_call) {
1017 /* variable number of arguments */
1018 nb_oargs = op->callo;
1019 nb_iargs = op->calli;
1020 nb_cargs = def->nb_cargs;
1022 /* function name, flags, out args */
1023 qemu_log(" %s %s,$0x%" TCG_PRIlx ",$%d", def->name,
1024 tcg_find_helper(s, args[nb_oargs + nb_iargs]),
1025 args[nb_oargs + nb_iargs + 1], nb_oargs);
1026 for (i = 0; i < nb_oargs; i++) {
1027 qemu_log(",%s", tcg_get_arg_str_idx(s, buf, sizeof(buf),
1028 args[i]));
1030 for (i = 0; i < nb_iargs; i++) {
1031 TCGArg arg = args[nb_oargs + i];
1032 const char *t = "<dummy>";
1033 if (arg != TCG_CALL_DUMMY_ARG) {
1034 t = tcg_get_arg_str_idx(s, buf, sizeof(buf), arg);
1036 qemu_log(",%s", t);
1038 } else {
1039 qemu_log(" %s ", def->name);
1041 nb_oargs = def->nb_oargs;
1042 nb_iargs = def->nb_iargs;
1043 nb_cargs = def->nb_cargs;
1045 k = 0;
1046 for (i = 0; i < nb_oargs; i++) {
1047 if (k != 0) {
1048 qemu_log(",");
1050 qemu_log("%s", tcg_get_arg_str_idx(s, buf, sizeof(buf),
1051 args[k++]));
1053 for (i = 0; i < nb_iargs; i++) {
1054 if (k != 0) {
1055 qemu_log(",");
1057 qemu_log("%s", tcg_get_arg_str_idx(s, buf, sizeof(buf),
1058 args[k++]));
1060 switch (c) {
1061 case INDEX_op_brcond_i32:
1062 case INDEX_op_setcond_i32:
1063 case INDEX_op_movcond_i32:
1064 case INDEX_op_brcond2_i32:
1065 case INDEX_op_setcond2_i32:
1066 case INDEX_op_brcond_i64:
1067 case INDEX_op_setcond_i64:
1068 case INDEX_op_movcond_i64:
1069 if (args[k] < ARRAY_SIZE(cond_name) && cond_name[args[k]]) {
1070 qemu_log(",%s", cond_name[args[k++]]);
1071 } else {
1072 qemu_log(",$0x%" TCG_PRIlx, args[k++]);
1074 i = 1;
1075 break;
1076 case INDEX_op_qemu_ld_i32:
1077 case INDEX_op_qemu_st_i32:
1078 case INDEX_op_qemu_ld_i64:
1079 case INDEX_op_qemu_st_i64:
1080 if (args[k] < ARRAY_SIZE(ldst_name) && ldst_name[args[k]]) {
1081 qemu_log(",%s", ldst_name[args[k++]]);
1082 } else {
1083 qemu_log(",$0x%" TCG_PRIlx, args[k++]);
1085 i = 1;
1086 break;
1087 default:
1088 i = 0;
1089 break;
1091 for (; i < nb_cargs; i++) {
1092 if (k != 0) {
1093 qemu_log(",");
1095 qemu_log("$0x%" TCG_PRIlx, args[k++]);
1098 qemu_log("\n");
1102 /* we give more priority to constraints with less registers */
1103 static int get_constraint_priority(const TCGOpDef *def, int k)
1105 const TCGArgConstraint *arg_ct;
1107 int i, n;
1108 arg_ct = &def->args_ct[k];
1109 if (arg_ct->ct & TCG_CT_ALIAS) {
1110 /* an alias is equivalent to a single register */
1111 n = 1;
1112 } else {
1113 if (!(arg_ct->ct & TCG_CT_REG))
1114 return 0;
1115 n = 0;
1116 for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
1117 if (tcg_regset_test_reg(arg_ct->u.regs, i))
1118 n++;
1121 return TCG_TARGET_NB_REGS - n + 1;
1124 /* sort from highest priority to lowest */
1125 static void sort_constraints(TCGOpDef *def, int start, int n)
1127 int i, j, p1, p2, tmp;
1129 for(i = 0; i < n; i++)
1130 def->sorted_args[start + i] = start + i;
1131 if (n <= 1)
1132 return;
1133 for(i = 0; i < n - 1; i++) {
1134 for(j = i + 1; j < n; j++) {
1135 p1 = get_constraint_priority(def, def->sorted_args[start + i]);
1136 p2 = get_constraint_priority(def, def->sorted_args[start + j]);
1137 if (p1 < p2) {
1138 tmp = def->sorted_args[start + i];
1139 def->sorted_args[start + i] = def->sorted_args[start + j];
1140 def->sorted_args[start + j] = tmp;
1146 void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs)
1148 TCGOpcode op;
1149 TCGOpDef *def;
1150 const char *ct_str;
1151 int i, nb_args;
1153 for(;;) {
1154 if (tdefs->op == (TCGOpcode)-1)
1155 break;
1156 op = tdefs->op;
1157 assert((unsigned)op < NB_OPS);
1158 def = &tcg_op_defs[op];
1159 #if defined(CONFIG_DEBUG_TCG)
1160 /* Duplicate entry in op definitions? */
1161 assert(!def->used);
1162 def->used = 1;
1163 #endif
1164 nb_args = def->nb_iargs + def->nb_oargs;
1165 for(i = 0; i < nb_args; i++) {
1166 ct_str = tdefs->args_ct_str[i];
1167 /* Incomplete TCGTargetOpDef entry? */
1168 assert(ct_str != NULL);
1169 tcg_regset_clear(def->args_ct[i].u.regs);
1170 def->args_ct[i].ct = 0;
1171 if (ct_str[0] >= '0' && ct_str[0] <= '9') {
1172 int oarg;
1173 oarg = ct_str[0] - '0';
1174 assert(oarg < def->nb_oargs);
1175 assert(def->args_ct[oarg].ct & TCG_CT_REG);
1176 /* TCG_CT_ALIAS is for the output arguments. The input
1177 argument is tagged with TCG_CT_IALIAS. */
1178 def->args_ct[i] = def->args_ct[oarg];
1179 def->args_ct[oarg].ct = TCG_CT_ALIAS;
1180 def->args_ct[oarg].alias_index = i;
1181 def->args_ct[i].ct |= TCG_CT_IALIAS;
1182 def->args_ct[i].alias_index = oarg;
1183 } else {
1184 for(;;) {
1185 if (*ct_str == '\0')
1186 break;
1187 switch(*ct_str) {
1188 case 'i':
1189 def->args_ct[i].ct |= TCG_CT_CONST;
1190 ct_str++;
1191 break;
1192 default:
1193 if (target_parse_constraint(&def->args_ct[i], &ct_str) < 0) {
1194 fprintf(stderr, "Invalid constraint '%s' for arg %d of operation '%s'\n",
1195 ct_str, i, def->name);
1196 exit(1);
1203 /* TCGTargetOpDef entry with too much information? */
1204 assert(i == TCG_MAX_OP_ARGS || tdefs->args_ct_str[i] == NULL);
1206 /* sort the constraints (XXX: this is just an heuristic) */
1207 sort_constraints(def, 0, def->nb_oargs);
1208 sort_constraints(def, def->nb_oargs, def->nb_iargs);
1210 #if 0
1212 int i;
1214 printf("%s: sorted=", def->name);
1215 for(i = 0; i < def->nb_oargs + def->nb_iargs; i++)
1216 printf(" %d", def->sorted_args[i]);
1217 printf("\n");
1219 #endif
1220 tdefs++;
1223 #if defined(CONFIG_DEBUG_TCG)
1224 i = 0;
1225 for (op = 0; op < ARRAY_SIZE(tcg_op_defs); op++) {
1226 const TCGOpDef *def = &tcg_op_defs[op];
1227 if (def->flags & TCG_OPF_NOT_PRESENT) {
1228 /* Wrong entry in op definitions? */
1229 if (def->used) {
1230 fprintf(stderr, "Invalid op definition for %s\n", def->name);
1231 i = 1;
1233 } else {
1234 /* Missing entry in op definitions? */
1235 if (!def->used) {
1236 fprintf(stderr, "Missing op definition for %s\n", def->name);
1237 i = 1;
1241 if (i == 1) {
1242 tcg_abort();
1244 #endif
1247 void tcg_op_remove(TCGContext *s, TCGOp *op)
1249 int next = op->next;
1250 int prev = op->prev;
1252 if (next >= 0) {
1253 s->gen_op_buf[next].prev = prev;
1254 } else {
1255 s->gen_last_op_idx = prev;
1257 if (prev >= 0) {
1258 s->gen_op_buf[prev].next = next;
1259 } else {
1260 s->gen_first_op_idx = next;
1263 memset(op, -1, sizeof(*op));
1265 #ifdef CONFIG_PROFILER
1266 s->del_op_count++;
1267 #endif
1270 #ifdef USE_LIVENESS_ANALYSIS
1271 /* liveness analysis: end of function: all temps are dead, and globals
1272 should be in memory. */
1273 static inline void tcg_la_func_end(TCGContext *s, uint8_t *dead_temps,
1274 uint8_t *mem_temps)
1276 memset(dead_temps, 1, s->nb_temps);
1277 memset(mem_temps, 1, s->nb_globals);
1278 memset(mem_temps + s->nb_globals, 0, s->nb_temps - s->nb_globals);
1281 /* liveness analysis: end of basic block: all temps are dead, globals
1282 and local temps should be in memory. */
1283 static inline void tcg_la_bb_end(TCGContext *s, uint8_t *dead_temps,
1284 uint8_t *mem_temps)
1286 int i;
1288 memset(dead_temps, 1, s->nb_temps);
1289 memset(mem_temps, 1, s->nb_globals);
1290 for(i = s->nb_globals; i < s->nb_temps; i++) {
1291 mem_temps[i] = s->temps[i].temp_local;
1295 /* Liveness analysis : update the opc_dead_args array to tell if a
1296 given input arguments is dead. Instructions updating dead
1297 temporaries are removed. */
1298 static void tcg_liveness_analysis(TCGContext *s)
1300 uint8_t *dead_temps, *mem_temps;
1301 int oi, oi_prev, nb_ops;
1303 nb_ops = s->gen_next_op_idx;
1304 s->op_dead_args = tcg_malloc(nb_ops * sizeof(uint16_t));
1305 s->op_sync_args = tcg_malloc(nb_ops * sizeof(uint8_t));
1307 dead_temps = tcg_malloc(s->nb_temps);
1308 mem_temps = tcg_malloc(s->nb_temps);
1309 tcg_la_func_end(s, dead_temps, mem_temps);
1311 for (oi = s->gen_last_op_idx; oi >= 0; oi = oi_prev) {
1312 int i, nb_iargs, nb_oargs;
1313 TCGOpcode opc_new, opc_new2;
1314 bool have_opc_new2;
1315 uint16_t dead_args;
1316 uint8_t sync_args;
1317 TCGArg arg;
1319 TCGOp * const op = &s->gen_op_buf[oi];
1320 TCGArg * const args = &s->gen_opparam_buf[op->args];
1321 TCGOpcode opc = op->opc;
1322 const TCGOpDef *def = &tcg_op_defs[opc];
1324 oi_prev = op->prev;
1326 switch (opc) {
1327 case INDEX_op_call:
1329 int call_flags;
1331 nb_oargs = op->callo;
1332 nb_iargs = op->calli;
1333 call_flags = args[nb_oargs + nb_iargs + 1];
1335 /* pure functions can be removed if their result is unused */
1336 if (call_flags & TCG_CALL_NO_SIDE_EFFECTS) {
1337 for (i = 0; i < nb_oargs; i++) {
1338 arg = args[i];
1339 if (!dead_temps[arg] || mem_temps[arg]) {
1340 goto do_not_remove_call;
1343 goto do_remove;
1344 } else {
1345 do_not_remove_call:
1347 /* output args are dead */
1348 dead_args = 0;
1349 sync_args = 0;
1350 for (i = 0; i < nb_oargs; i++) {
1351 arg = args[i];
1352 if (dead_temps[arg]) {
1353 dead_args |= (1 << i);
1355 if (mem_temps[arg]) {
1356 sync_args |= (1 << i);
1358 dead_temps[arg] = 1;
1359 mem_temps[arg] = 0;
1362 if (!(call_flags & TCG_CALL_NO_READ_GLOBALS)) {
1363 /* globals should be synced to memory */
1364 memset(mem_temps, 1, s->nb_globals);
1366 if (!(call_flags & (TCG_CALL_NO_WRITE_GLOBALS |
1367 TCG_CALL_NO_READ_GLOBALS))) {
1368 /* globals should go back to memory */
1369 memset(dead_temps, 1, s->nb_globals);
1372 /* input args are live */
1373 for (i = nb_oargs; i < nb_iargs + nb_oargs; i++) {
1374 arg = args[i];
1375 if (arg != TCG_CALL_DUMMY_ARG) {
1376 if (dead_temps[arg]) {
1377 dead_args |= (1 << i);
1379 dead_temps[arg] = 0;
1382 s->op_dead_args[oi] = dead_args;
1383 s->op_sync_args[oi] = sync_args;
1386 break;
1387 case INDEX_op_debug_insn_start:
1388 break;
1389 case INDEX_op_discard:
1390 /* mark the temporary as dead */
1391 dead_temps[args[0]] = 1;
1392 mem_temps[args[0]] = 0;
1393 break;
1395 case INDEX_op_add2_i32:
1396 opc_new = INDEX_op_add_i32;
1397 goto do_addsub2;
1398 case INDEX_op_sub2_i32:
1399 opc_new = INDEX_op_sub_i32;
1400 goto do_addsub2;
1401 case INDEX_op_add2_i64:
1402 opc_new = INDEX_op_add_i64;
1403 goto do_addsub2;
1404 case INDEX_op_sub2_i64:
1405 opc_new = INDEX_op_sub_i64;
1406 do_addsub2:
1407 nb_iargs = 4;
1408 nb_oargs = 2;
1409 /* Test if the high part of the operation is dead, but not
1410 the low part. The result can be optimized to a simple
1411 add or sub. This happens often for x86_64 guest when the
1412 cpu mode is set to 32 bit. */
1413 if (dead_temps[args[1]] && !mem_temps[args[1]]) {
1414 if (dead_temps[args[0]] && !mem_temps[args[0]]) {
1415 goto do_remove;
1417 /* Replace the opcode and adjust the args in place,
1418 leaving 3 unused args at the end. */
1419 op->opc = opc = opc_new;
1420 args[1] = args[2];
1421 args[2] = args[4];
1422 /* Fall through and mark the single-word operation live. */
1423 nb_iargs = 2;
1424 nb_oargs = 1;
1426 goto do_not_remove;
1428 case INDEX_op_mulu2_i32:
1429 opc_new = INDEX_op_mul_i32;
1430 opc_new2 = INDEX_op_muluh_i32;
1431 have_opc_new2 = TCG_TARGET_HAS_muluh_i32;
1432 goto do_mul2;
1433 case INDEX_op_muls2_i32:
1434 opc_new = INDEX_op_mul_i32;
1435 opc_new2 = INDEX_op_mulsh_i32;
1436 have_opc_new2 = TCG_TARGET_HAS_mulsh_i32;
1437 goto do_mul2;
1438 case INDEX_op_mulu2_i64:
1439 opc_new = INDEX_op_mul_i64;
1440 opc_new2 = INDEX_op_muluh_i64;
1441 have_opc_new2 = TCG_TARGET_HAS_muluh_i64;
1442 goto do_mul2;
1443 case INDEX_op_muls2_i64:
1444 opc_new = INDEX_op_mul_i64;
1445 opc_new2 = INDEX_op_mulsh_i64;
1446 have_opc_new2 = TCG_TARGET_HAS_mulsh_i64;
1447 goto do_mul2;
1448 do_mul2:
1449 nb_iargs = 2;
1450 nb_oargs = 2;
1451 if (dead_temps[args[1]] && !mem_temps[args[1]]) {
1452 if (dead_temps[args[0]] && !mem_temps[args[0]]) {
1453 /* Both parts of the operation are dead. */
1454 goto do_remove;
1456 /* The high part of the operation is dead; generate the low. */
1457 op->opc = opc = opc_new;
1458 args[1] = args[2];
1459 args[2] = args[3];
1460 } else if (have_opc_new2 && dead_temps[args[0]]
1461 && !mem_temps[args[0]]) {
1462 /* The low part of the operation is dead; generate the high. */
1463 op->opc = opc = opc_new2;
1464 args[0] = args[1];
1465 args[1] = args[2];
1466 args[2] = args[3];
1467 } else {
1468 goto do_not_remove;
1470 /* Mark the single-word operation live. */
1471 nb_oargs = 1;
1472 goto do_not_remove;
1474 default:
1475 /* XXX: optimize by hardcoding common cases (e.g. triadic ops) */
1476 nb_iargs = def->nb_iargs;
1477 nb_oargs = def->nb_oargs;
1479 /* Test if the operation can be removed because all
1480 its outputs are dead. We assume that nb_oargs == 0
1481 implies side effects */
1482 if (!(def->flags & TCG_OPF_SIDE_EFFECTS) && nb_oargs != 0) {
1483 for (i = 0; i < nb_oargs; i++) {
1484 arg = args[i];
1485 if (!dead_temps[arg] || mem_temps[arg]) {
1486 goto do_not_remove;
1489 do_remove:
1490 tcg_op_remove(s, op);
1491 } else {
1492 do_not_remove:
1493 /* output args are dead */
1494 dead_args = 0;
1495 sync_args = 0;
1496 for (i = 0; i < nb_oargs; i++) {
1497 arg = args[i];
1498 if (dead_temps[arg]) {
1499 dead_args |= (1 << i);
1501 if (mem_temps[arg]) {
1502 sync_args |= (1 << i);
1504 dead_temps[arg] = 1;
1505 mem_temps[arg] = 0;
1508 /* if end of basic block, update */
1509 if (def->flags & TCG_OPF_BB_END) {
1510 tcg_la_bb_end(s, dead_temps, mem_temps);
1511 } else if (def->flags & TCG_OPF_SIDE_EFFECTS) {
1512 /* globals should be synced to memory */
1513 memset(mem_temps, 1, s->nb_globals);
1516 /* input args are live */
1517 for (i = nb_oargs; i < nb_oargs + nb_iargs; i++) {
1518 arg = args[i];
1519 if (dead_temps[arg]) {
1520 dead_args |= (1 << i);
1522 dead_temps[arg] = 0;
1524 s->op_dead_args[oi] = dead_args;
1525 s->op_sync_args[oi] = sync_args;
1527 break;
1531 #else
1532 /* dummy liveness analysis */
1533 static void tcg_liveness_analysis(TCGContext *s)
1535 int nb_ops;
1536 nb_ops = s->gen_opc_ptr - s->gen_opc_buf;
1538 s->op_dead_args = tcg_malloc(nb_ops * sizeof(uint16_t));
1539 memset(s->op_dead_args, 0, nb_ops * sizeof(uint16_t));
1540 s->op_sync_args = tcg_malloc(nb_ops * sizeof(uint8_t));
1541 memset(s->op_sync_args, 0, nb_ops * sizeof(uint8_t));
1543 #endif
1545 #ifndef NDEBUG
1546 static void dump_regs(TCGContext *s)
1548 TCGTemp *ts;
1549 int i;
1550 char buf[64];
1552 for(i = 0; i < s->nb_temps; i++) {
1553 ts = &s->temps[i];
1554 printf(" %10s: ", tcg_get_arg_str_idx(s, buf, sizeof(buf), i));
1555 switch(ts->val_type) {
1556 case TEMP_VAL_REG:
1557 printf("%s", tcg_target_reg_names[ts->reg]);
1558 break;
1559 case TEMP_VAL_MEM:
1560 printf("%d(%s)", (int)ts->mem_offset, tcg_target_reg_names[ts->mem_reg]);
1561 break;
1562 case TEMP_VAL_CONST:
1563 printf("$0x%" TCG_PRIlx, ts->val);
1564 break;
1565 case TEMP_VAL_DEAD:
1566 printf("D");
1567 break;
1568 default:
1569 printf("???");
1570 break;
1572 printf("\n");
1575 for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
1576 if (s->reg_to_temp[i] >= 0) {
1577 printf("%s: %s\n",
1578 tcg_target_reg_names[i],
1579 tcg_get_arg_str_idx(s, buf, sizeof(buf), s->reg_to_temp[i]));
1584 static void check_regs(TCGContext *s)
1586 int reg, k;
1587 TCGTemp *ts;
1588 char buf[64];
1590 for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1591 k = s->reg_to_temp[reg];
1592 if (k >= 0) {
1593 ts = &s->temps[k];
1594 if (ts->val_type != TEMP_VAL_REG ||
1595 ts->reg != reg) {
1596 printf("Inconsistency for register %s:\n",
1597 tcg_target_reg_names[reg]);
1598 goto fail;
1602 for(k = 0; k < s->nb_temps; k++) {
1603 ts = &s->temps[k];
1604 if (ts->val_type == TEMP_VAL_REG &&
1605 !ts->fixed_reg &&
1606 s->reg_to_temp[ts->reg] != k) {
1607 printf("Inconsistency for temp %s:\n",
1608 tcg_get_arg_str_idx(s, buf, sizeof(buf), k));
1609 fail:
1610 printf("reg state:\n");
1611 dump_regs(s);
1612 tcg_abort();
1616 #endif
1618 static void temp_allocate_frame(TCGContext *s, int temp)
1620 TCGTemp *ts;
1621 ts = &s->temps[temp];
1622 #if !(defined(__sparc__) && TCG_TARGET_REG_BITS == 64)
1623 /* Sparc64 stack is accessed with offset of 2047 */
1624 s->current_frame_offset = (s->current_frame_offset +
1625 (tcg_target_long)sizeof(tcg_target_long) - 1) &
1626 ~(sizeof(tcg_target_long) - 1);
1627 #endif
1628 if (s->current_frame_offset + (tcg_target_long)sizeof(tcg_target_long) >
1629 s->frame_end) {
1630 tcg_abort();
1632 ts->mem_offset = s->current_frame_offset;
1633 ts->mem_reg = s->frame_reg;
1634 ts->mem_allocated = 1;
1635 s->current_frame_offset += sizeof(tcg_target_long);
1638 /* sync register 'reg' by saving it to the corresponding temporary */
1639 static inline void tcg_reg_sync(TCGContext *s, int reg)
1641 TCGTemp *ts;
1642 int temp;
1644 temp = s->reg_to_temp[reg];
1645 ts = &s->temps[temp];
1646 assert(ts->val_type == TEMP_VAL_REG);
1647 if (!ts->mem_coherent && !ts->fixed_reg) {
1648 if (!ts->mem_allocated) {
1649 temp_allocate_frame(s, temp);
1651 tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1653 ts->mem_coherent = 1;
1656 /* free register 'reg' by spilling the corresponding temporary if necessary */
1657 static void tcg_reg_free(TCGContext *s, int reg)
1659 int temp;
1661 temp = s->reg_to_temp[reg];
1662 if (temp != -1) {
1663 tcg_reg_sync(s, reg);
1664 s->temps[temp].val_type = TEMP_VAL_MEM;
1665 s->reg_to_temp[reg] = -1;
1669 /* Allocate a register belonging to reg1 & ~reg2 */
1670 static int tcg_reg_alloc(TCGContext *s, TCGRegSet reg1, TCGRegSet reg2)
1672 int i, reg;
1673 TCGRegSet reg_ct;
1675 tcg_regset_andnot(reg_ct, reg1, reg2);
1677 /* first try free registers */
1678 for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1679 reg = tcg_target_reg_alloc_order[i];
1680 if (tcg_regset_test_reg(reg_ct, reg) && s->reg_to_temp[reg] == -1)
1681 return reg;
1684 /* XXX: do better spill choice */
1685 for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1686 reg = tcg_target_reg_alloc_order[i];
1687 if (tcg_regset_test_reg(reg_ct, reg)) {
1688 tcg_reg_free(s, reg);
1689 return reg;
1693 tcg_abort();
1696 /* mark a temporary as dead. */
1697 static inline void temp_dead(TCGContext *s, int temp)
1699 TCGTemp *ts;
1701 ts = &s->temps[temp];
1702 if (!ts->fixed_reg) {
1703 if (ts->val_type == TEMP_VAL_REG) {
1704 s->reg_to_temp[ts->reg] = -1;
1706 if (temp < s->nb_globals || ts->temp_local) {
1707 ts->val_type = TEMP_VAL_MEM;
1708 } else {
1709 ts->val_type = TEMP_VAL_DEAD;
1714 /* sync a temporary to memory. 'allocated_regs' is used in case a
1715 temporary registers needs to be allocated to store a constant. */
1716 static inline void temp_sync(TCGContext *s, int temp, TCGRegSet allocated_regs)
1718 TCGTemp *ts;
1720 ts = &s->temps[temp];
1721 if (!ts->fixed_reg) {
1722 switch(ts->val_type) {
1723 case TEMP_VAL_CONST:
1724 ts->reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type],
1725 allocated_regs);
1726 ts->val_type = TEMP_VAL_REG;
1727 s->reg_to_temp[ts->reg] = temp;
1728 ts->mem_coherent = 0;
1729 tcg_out_movi(s, ts->type, ts->reg, ts->val);
1730 /* fallthrough*/
1731 case TEMP_VAL_REG:
1732 tcg_reg_sync(s, ts->reg);
1733 break;
1734 case TEMP_VAL_DEAD:
1735 case TEMP_VAL_MEM:
1736 break;
1737 default:
1738 tcg_abort();
1743 /* save a temporary to memory. 'allocated_regs' is used in case a
1744 temporary registers needs to be allocated to store a constant. */
1745 static inline void temp_save(TCGContext *s, int temp, TCGRegSet allocated_regs)
1747 #ifdef USE_LIVENESS_ANALYSIS
1748 /* The liveness analysis already ensures that globals are back
1749 in memory. Keep an assert for safety. */
1750 assert(s->temps[temp].val_type == TEMP_VAL_MEM || s->temps[temp].fixed_reg);
1751 #else
1752 temp_sync(s, temp, allocated_regs);
1753 temp_dead(s, temp);
1754 #endif
1757 /* save globals to their canonical location and assume they can be
1758 modified be the following code. 'allocated_regs' is used in case a
1759 temporary registers needs to be allocated to store a constant. */
1760 static void save_globals(TCGContext *s, TCGRegSet allocated_regs)
1762 int i;
1764 for(i = 0; i < s->nb_globals; i++) {
1765 temp_save(s, i, allocated_regs);
1769 /* sync globals to their canonical location and assume they can be
1770 read by the following code. 'allocated_regs' is used in case a
1771 temporary registers needs to be allocated to store a constant. */
1772 static void sync_globals(TCGContext *s, TCGRegSet allocated_regs)
1774 int i;
1776 for (i = 0; i < s->nb_globals; i++) {
1777 #ifdef USE_LIVENESS_ANALYSIS
1778 assert(s->temps[i].val_type != TEMP_VAL_REG || s->temps[i].fixed_reg ||
1779 s->temps[i].mem_coherent);
1780 #else
1781 temp_sync(s, i, allocated_regs);
1782 #endif
1786 /* at the end of a basic block, we assume all temporaries are dead and
1787 all globals are stored at their canonical location. */
1788 static void tcg_reg_alloc_bb_end(TCGContext *s, TCGRegSet allocated_regs)
1790 TCGTemp *ts;
1791 int i;
1793 for(i = s->nb_globals; i < s->nb_temps; i++) {
1794 ts = &s->temps[i];
1795 if (ts->temp_local) {
1796 temp_save(s, i, allocated_regs);
1797 } else {
1798 #ifdef USE_LIVENESS_ANALYSIS
1799 /* The liveness analysis already ensures that temps are dead.
1800 Keep an assert for safety. */
1801 assert(ts->val_type == TEMP_VAL_DEAD);
1802 #else
1803 temp_dead(s, i);
1804 #endif
1808 save_globals(s, allocated_regs);
1811 #define IS_DEAD_ARG(n) ((dead_args >> (n)) & 1)
1812 #define NEED_SYNC_ARG(n) ((sync_args >> (n)) & 1)
1814 static void tcg_reg_alloc_movi(TCGContext *s, const TCGArg *args,
1815 uint16_t dead_args, uint8_t sync_args)
1817 TCGTemp *ots;
1818 tcg_target_ulong val;
1820 ots = &s->temps[args[0]];
1821 val = args[1];
1823 if (ots->fixed_reg) {
1824 /* for fixed registers, we do not do any constant
1825 propagation */
1826 tcg_out_movi(s, ots->type, ots->reg, val);
1827 } else {
1828 /* The movi is not explicitly generated here */
1829 if (ots->val_type == TEMP_VAL_REG)
1830 s->reg_to_temp[ots->reg] = -1;
1831 ots->val_type = TEMP_VAL_CONST;
1832 ots->val = val;
1834 if (NEED_SYNC_ARG(0)) {
1835 temp_sync(s, args[0], s->reserved_regs);
1837 if (IS_DEAD_ARG(0)) {
1838 temp_dead(s, args[0]);
1842 static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
1843 const TCGArg *args, uint16_t dead_args,
1844 uint8_t sync_args)
1846 TCGRegSet allocated_regs;
1847 TCGTemp *ts, *ots;
1848 TCGType otype, itype;
1850 tcg_regset_set(allocated_regs, s->reserved_regs);
1851 ots = &s->temps[args[0]];
1852 ts = &s->temps[args[1]];
1854 /* Note that otype != itype for no-op truncation. */
1855 otype = ots->type;
1856 itype = ts->type;
1858 /* If the source value is not in a register, and we're going to be
1859 forced to have it in a register in order to perform the copy,
1860 then copy the SOURCE value into its own register first. That way
1861 we don't have to reload SOURCE the next time it is used. */
1862 if (((NEED_SYNC_ARG(0) || ots->fixed_reg) && ts->val_type != TEMP_VAL_REG)
1863 || ts->val_type == TEMP_VAL_MEM) {
1864 ts->reg = tcg_reg_alloc(s, tcg_target_available_regs[itype],
1865 allocated_regs);
1866 if (ts->val_type == TEMP_VAL_MEM) {
1867 tcg_out_ld(s, itype, ts->reg, ts->mem_reg, ts->mem_offset);
1868 ts->mem_coherent = 1;
1869 } else if (ts->val_type == TEMP_VAL_CONST) {
1870 tcg_out_movi(s, itype, ts->reg, ts->val);
1872 s->reg_to_temp[ts->reg] = args[1];
1873 ts->val_type = TEMP_VAL_REG;
1876 if (IS_DEAD_ARG(0) && !ots->fixed_reg) {
1877 /* mov to a non-saved dead register makes no sense (even with
1878 liveness analysis disabled). */
1879 assert(NEED_SYNC_ARG(0));
1880 /* The code above should have moved the temp to a register. */
1881 assert(ts->val_type == TEMP_VAL_REG);
1882 if (!ots->mem_allocated) {
1883 temp_allocate_frame(s, args[0]);
1885 tcg_out_st(s, otype, ts->reg, ots->mem_reg, ots->mem_offset);
1886 if (IS_DEAD_ARG(1)) {
1887 temp_dead(s, args[1]);
1889 temp_dead(s, args[0]);
1890 } else if (ts->val_type == TEMP_VAL_CONST) {
1891 /* propagate constant */
1892 if (ots->val_type == TEMP_VAL_REG) {
1893 s->reg_to_temp[ots->reg] = -1;
1895 ots->val_type = TEMP_VAL_CONST;
1896 ots->val = ts->val;
1897 } else {
1898 /* The code in the first if block should have moved the
1899 temp to a register. */
1900 assert(ts->val_type == TEMP_VAL_REG);
1901 if (IS_DEAD_ARG(1) && !ts->fixed_reg && !ots->fixed_reg) {
1902 /* the mov can be suppressed */
1903 if (ots->val_type == TEMP_VAL_REG) {
1904 s->reg_to_temp[ots->reg] = -1;
1906 ots->reg = ts->reg;
1907 temp_dead(s, args[1]);
1908 } else {
1909 if (ots->val_type != TEMP_VAL_REG) {
1910 /* When allocating a new register, make sure to not spill the
1911 input one. */
1912 tcg_regset_set_reg(allocated_regs, ts->reg);
1913 ots->reg = tcg_reg_alloc(s, tcg_target_available_regs[otype],
1914 allocated_regs);
1916 tcg_out_mov(s, otype, ots->reg, ts->reg);
1918 ots->val_type = TEMP_VAL_REG;
1919 ots->mem_coherent = 0;
1920 s->reg_to_temp[ots->reg] = args[0];
1921 if (NEED_SYNC_ARG(0)) {
1922 tcg_reg_sync(s, ots->reg);
1927 static void tcg_reg_alloc_op(TCGContext *s,
1928 const TCGOpDef *def, TCGOpcode opc,
1929 const TCGArg *args, uint16_t dead_args,
1930 uint8_t sync_args)
1932 TCGRegSet allocated_regs;
1933 int i, k, nb_iargs, nb_oargs, reg;
1934 TCGArg arg;
1935 const TCGArgConstraint *arg_ct;
1936 TCGTemp *ts;
1937 TCGArg new_args[TCG_MAX_OP_ARGS];
1938 int const_args[TCG_MAX_OP_ARGS];
1940 nb_oargs = def->nb_oargs;
1941 nb_iargs = def->nb_iargs;
1943 /* copy constants */
1944 memcpy(new_args + nb_oargs + nb_iargs,
1945 args + nb_oargs + nb_iargs,
1946 sizeof(TCGArg) * def->nb_cargs);
1948 /* satisfy input constraints */
1949 tcg_regset_set(allocated_regs, s->reserved_regs);
1950 for(k = 0; k < nb_iargs; k++) {
1951 i = def->sorted_args[nb_oargs + k];
1952 arg = args[i];
1953 arg_ct = &def->args_ct[i];
1954 ts = &s->temps[arg];
1955 if (ts->val_type == TEMP_VAL_MEM) {
1956 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1957 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1958 ts->val_type = TEMP_VAL_REG;
1959 ts->reg = reg;
1960 ts->mem_coherent = 1;
1961 s->reg_to_temp[reg] = arg;
1962 } else if (ts->val_type == TEMP_VAL_CONST) {
1963 if (tcg_target_const_match(ts->val, ts->type, arg_ct)) {
1964 /* constant is OK for instruction */
1965 const_args[i] = 1;
1966 new_args[i] = ts->val;
1967 goto iarg_end;
1968 } else {
1969 /* need to move to a register */
1970 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1971 tcg_out_movi(s, ts->type, reg, ts->val);
1972 ts->val_type = TEMP_VAL_REG;
1973 ts->reg = reg;
1974 ts->mem_coherent = 0;
1975 s->reg_to_temp[reg] = arg;
1978 assert(ts->val_type == TEMP_VAL_REG);
1979 if (arg_ct->ct & TCG_CT_IALIAS) {
1980 if (ts->fixed_reg) {
1981 /* if fixed register, we must allocate a new register
1982 if the alias is not the same register */
1983 if (arg != args[arg_ct->alias_index])
1984 goto allocate_in_reg;
1985 } else {
1986 /* if the input is aliased to an output and if it is
1987 not dead after the instruction, we must allocate
1988 a new register and move it */
1989 if (!IS_DEAD_ARG(i)) {
1990 goto allocate_in_reg;
1994 reg = ts->reg;
1995 if (tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1996 /* nothing to do : the constraint is satisfied */
1997 } else {
1998 allocate_in_reg:
1999 /* allocate a new register matching the constraint
2000 and move the temporary register into it */
2001 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
2002 tcg_out_mov(s, ts->type, reg, ts->reg);
2004 new_args[i] = reg;
2005 const_args[i] = 0;
2006 tcg_regset_set_reg(allocated_regs, reg);
2007 iarg_end: ;
2010 /* mark dead temporaries and free the associated registers */
2011 for (i = nb_oargs; i < nb_oargs + nb_iargs; i++) {
2012 if (IS_DEAD_ARG(i)) {
2013 temp_dead(s, args[i]);
2017 if (def->flags & TCG_OPF_BB_END) {
2018 tcg_reg_alloc_bb_end(s, allocated_regs);
2019 } else {
2020 if (def->flags & TCG_OPF_CALL_CLOBBER) {
2021 /* XXX: permit generic clobber register list ? */
2022 for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
2023 if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
2024 tcg_reg_free(s, reg);
2028 if (def->flags & TCG_OPF_SIDE_EFFECTS) {
2029 /* sync globals if the op has side effects and might trigger
2030 an exception. */
2031 sync_globals(s, allocated_regs);
2034 /* satisfy the output constraints */
2035 tcg_regset_set(allocated_regs, s->reserved_regs);
2036 for(k = 0; k < nb_oargs; k++) {
2037 i = def->sorted_args[k];
2038 arg = args[i];
2039 arg_ct = &def->args_ct[i];
2040 ts = &s->temps[arg];
2041 if (arg_ct->ct & TCG_CT_ALIAS) {
2042 reg = new_args[arg_ct->alias_index];
2043 } else {
2044 /* if fixed register, we try to use it */
2045 reg = ts->reg;
2046 if (ts->fixed_reg &&
2047 tcg_regset_test_reg(arg_ct->u.regs, reg)) {
2048 goto oarg_end;
2050 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
2052 tcg_regset_set_reg(allocated_regs, reg);
2053 /* if a fixed register is used, then a move will be done afterwards */
2054 if (!ts->fixed_reg) {
2055 if (ts->val_type == TEMP_VAL_REG) {
2056 s->reg_to_temp[ts->reg] = -1;
2058 ts->val_type = TEMP_VAL_REG;
2059 ts->reg = reg;
2060 /* temp value is modified, so the value kept in memory is
2061 potentially not the same */
2062 ts->mem_coherent = 0;
2063 s->reg_to_temp[reg] = arg;
2065 oarg_end:
2066 new_args[i] = reg;
2070 /* emit instruction */
2071 tcg_out_op(s, opc, new_args, const_args);
2073 /* move the outputs in the correct register if needed */
2074 for(i = 0; i < nb_oargs; i++) {
2075 ts = &s->temps[args[i]];
2076 reg = new_args[i];
2077 if (ts->fixed_reg && ts->reg != reg) {
2078 tcg_out_mov(s, ts->type, ts->reg, reg);
2080 if (NEED_SYNC_ARG(i)) {
2081 tcg_reg_sync(s, reg);
2083 if (IS_DEAD_ARG(i)) {
2084 temp_dead(s, args[i]);
2089 #ifdef TCG_TARGET_STACK_GROWSUP
2090 #define STACK_DIR(x) (-(x))
2091 #else
2092 #define STACK_DIR(x) (x)
2093 #endif
2095 static void tcg_reg_alloc_call(TCGContext *s, int nb_oargs, int nb_iargs,
2096 const TCGArg * const args, uint16_t dead_args,
2097 uint8_t sync_args)
2099 int flags, nb_regs, i, reg;
2100 TCGArg arg;
2101 TCGTemp *ts;
2102 intptr_t stack_offset;
2103 size_t call_stack_size;
2104 tcg_insn_unit *func_addr;
2105 int allocate_args;
2106 TCGRegSet allocated_regs;
2108 func_addr = (tcg_insn_unit *)(intptr_t)args[nb_oargs + nb_iargs];
2109 flags = args[nb_oargs + nb_iargs + 1];
2111 nb_regs = ARRAY_SIZE(tcg_target_call_iarg_regs);
2112 if (nb_regs > nb_iargs) {
2113 nb_regs = nb_iargs;
2116 /* assign stack slots first */
2117 call_stack_size = (nb_iargs - nb_regs) * sizeof(tcg_target_long);
2118 call_stack_size = (call_stack_size + TCG_TARGET_STACK_ALIGN - 1) &
2119 ~(TCG_TARGET_STACK_ALIGN - 1);
2120 allocate_args = (call_stack_size > TCG_STATIC_CALL_ARGS_SIZE);
2121 if (allocate_args) {
2122 /* XXX: if more than TCG_STATIC_CALL_ARGS_SIZE is needed,
2123 preallocate call stack */
2124 tcg_abort();
2127 stack_offset = TCG_TARGET_CALL_STACK_OFFSET;
2128 for(i = nb_regs; i < nb_iargs; i++) {
2129 arg = args[nb_oargs + i];
2130 #ifdef TCG_TARGET_STACK_GROWSUP
2131 stack_offset -= sizeof(tcg_target_long);
2132 #endif
2133 if (arg != TCG_CALL_DUMMY_ARG) {
2134 ts = &s->temps[arg];
2135 if (ts->val_type == TEMP_VAL_REG) {
2136 tcg_out_st(s, ts->type, ts->reg, TCG_REG_CALL_STACK, stack_offset);
2137 } else if (ts->val_type == TEMP_VAL_MEM) {
2138 reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type],
2139 s->reserved_regs);
2140 /* XXX: not correct if reading values from the stack */
2141 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
2142 tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
2143 } else if (ts->val_type == TEMP_VAL_CONST) {
2144 reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type],
2145 s->reserved_regs);
2146 /* XXX: sign extend may be needed on some targets */
2147 tcg_out_movi(s, ts->type, reg, ts->val);
2148 tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
2149 } else {
2150 tcg_abort();
2153 #ifndef TCG_TARGET_STACK_GROWSUP
2154 stack_offset += sizeof(tcg_target_long);
2155 #endif
2158 /* assign input registers */
2159 tcg_regset_set(allocated_regs, s->reserved_regs);
2160 for(i = 0; i < nb_regs; i++) {
2161 arg = args[nb_oargs + i];
2162 if (arg != TCG_CALL_DUMMY_ARG) {
2163 ts = &s->temps[arg];
2164 reg = tcg_target_call_iarg_regs[i];
2165 tcg_reg_free(s, reg);
2166 if (ts->val_type == TEMP_VAL_REG) {
2167 if (ts->reg != reg) {
2168 tcg_out_mov(s, ts->type, reg, ts->reg);
2170 } else if (ts->val_type == TEMP_VAL_MEM) {
2171 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
2172 } else if (ts->val_type == TEMP_VAL_CONST) {
2173 /* XXX: sign extend ? */
2174 tcg_out_movi(s, ts->type, reg, ts->val);
2175 } else {
2176 tcg_abort();
2178 tcg_regset_set_reg(allocated_regs, reg);
2182 /* mark dead temporaries and free the associated registers */
2183 for(i = nb_oargs; i < nb_iargs + nb_oargs; i++) {
2184 if (IS_DEAD_ARG(i)) {
2185 temp_dead(s, args[i]);
2189 /* clobber call registers */
2190 for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
2191 if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
2192 tcg_reg_free(s, reg);
2196 /* Save globals if they might be written by the helper, sync them if
2197 they might be read. */
2198 if (flags & TCG_CALL_NO_READ_GLOBALS) {
2199 /* Nothing to do */
2200 } else if (flags & TCG_CALL_NO_WRITE_GLOBALS) {
2201 sync_globals(s, allocated_regs);
2202 } else {
2203 save_globals(s, allocated_regs);
2206 tcg_out_call(s, func_addr);
2208 /* assign output registers and emit moves if needed */
2209 for(i = 0; i < nb_oargs; i++) {
2210 arg = args[i];
2211 ts = &s->temps[arg];
2212 reg = tcg_target_call_oarg_regs[i];
2213 assert(s->reg_to_temp[reg] == -1);
2215 if (ts->fixed_reg) {
2216 if (ts->reg != reg) {
2217 tcg_out_mov(s, ts->type, ts->reg, reg);
2219 } else {
2220 if (ts->val_type == TEMP_VAL_REG) {
2221 s->reg_to_temp[ts->reg] = -1;
2223 ts->val_type = TEMP_VAL_REG;
2224 ts->reg = reg;
2225 ts->mem_coherent = 0;
2226 s->reg_to_temp[reg] = arg;
2227 if (NEED_SYNC_ARG(i)) {
2228 tcg_reg_sync(s, reg);
2230 if (IS_DEAD_ARG(i)) {
2231 temp_dead(s, args[i]);
2237 #ifdef CONFIG_PROFILER
2239 static int64_t tcg_table_op_count[NB_OPS];
2241 void tcg_dump_op_count(FILE *f, fprintf_function cpu_fprintf)
2243 int i;
2245 for (i = 0; i < NB_OPS; i++) {
2246 cpu_fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name,
2247 tcg_table_op_count[i]);
2250 #else
2251 void tcg_dump_op_count(FILE *f, fprintf_function cpu_fprintf)
2253 cpu_fprintf(f, "[TCG profiler not compiled]\n");
2255 #endif
2258 static inline int tcg_gen_code_common(TCGContext *s,
2259 tcg_insn_unit *gen_code_buf,
2260 long search_pc)
2262 int oi, oi_next;
2264 #ifdef DEBUG_DISAS
2265 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
2266 qemu_log("OP:\n");
2267 tcg_dump_ops(s);
2268 qemu_log("\n");
2270 #endif
2272 #ifdef CONFIG_PROFILER
2273 s->opt_time -= profile_getclock();
2274 #endif
2276 #ifdef USE_TCG_OPTIMIZATIONS
2277 tcg_optimize(s);
2278 #endif
2280 #ifdef CONFIG_PROFILER
2281 s->opt_time += profile_getclock();
2282 s->la_time -= profile_getclock();
2283 #endif
2285 tcg_liveness_analysis(s);
2287 #ifdef CONFIG_PROFILER
2288 s->la_time += profile_getclock();
2289 #endif
2291 #ifdef DEBUG_DISAS
2292 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_OPT))) {
2293 qemu_log("OP after optimization and liveness analysis:\n");
2294 tcg_dump_ops(s);
2295 qemu_log("\n");
2297 #endif
2299 tcg_reg_alloc_start(s);
2301 s->code_buf = gen_code_buf;
2302 s->code_ptr = gen_code_buf;
2304 tcg_out_tb_init(s);
2306 for (oi = s->gen_first_op_idx; oi >= 0; oi = oi_next) {
2307 TCGOp * const op = &s->gen_op_buf[oi];
2308 TCGArg * const args = &s->gen_opparam_buf[op->args];
2309 TCGOpcode opc = op->opc;
2310 const TCGOpDef *def = &tcg_op_defs[opc];
2311 uint16_t dead_args = s->op_dead_args[oi];
2312 uint8_t sync_args = s->op_sync_args[oi];
2314 oi_next = op->next;
2315 #ifdef CONFIG_PROFILER
2316 tcg_table_op_count[opc]++;
2317 #endif
2319 switch (opc) {
2320 case INDEX_op_mov_i32:
2321 case INDEX_op_mov_i64:
2322 tcg_reg_alloc_mov(s, def, args, dead_args, sync_args);
2323 break;
2324 case INDEX_op_movi_i32:
2325 case INDEX_op_movi_i64:
2326 tcg_reg_alloc_movi(s, args, dead_args, sync_args);
2327 break;
2328 case INDEX_op_debug_insn_start:
2329 break;
2330 case INDEX_op_discard:
2331 temp_dead(s, args[0]);
2332 break;
2333 case INDEX_op_set_label:
2334 tcg_reg_alloc_bb_end(s, s->reserved_regs);
2335 tcg_out_label(s, args[0], s->code_ptr);
2336 break;
2337 case INDEX_op_call:
2338 tcg_reg_alloc_call(s, op->callo, op->calli, args,
2339 dead_args, sync_args);
2340 break;
2341 default:
2342 /* Sanity check that we've not introduced any unhandled opcodes. */
2343 if (def->flags & TCG_OPF_NOT_PRESENT) {
2344 tcg_abort();
2346 /* Note: in order to speed up the code, it would be much
2347 faster to have specialized register allocator functions for
2348 some common argument patterns */
2349 tcg_reg_alloc_op(s, def, opc, args, dead_args, sync_args);
2350 break;
2352 if (search_pc >= 0 && search_pc < tcg_current_code_size(s)) {
2353 return oi;
2355 #ifndef NDEBUG
2356 check_regs(s);
2357 #endif
2360 /* Generate TB finalization at the end of block */
2361 tcg_out_tb_finalize(s);
2362 return -1;
2365 int tcg_gen_code(TCGContext *s, tcg_insn_unit *gen_code_buf)
2367 #ifdef CONFIG_PROFILER
2369 int n;
2371 n = s->gen_last_op_idx + 1;
2372 s->op_count += n;
2373 if (n > s->op_count_max) {
2374 s->op_count_max = n;
2377 n = s->nb_temps;
2378 s->temp_count += n;
2379 if (n > s->temp_count_max) {
2380 s->temp_count_max = n;
2383 #endif
2385 tcg_gen_code_common(s, gen_code_buf, -1);
2387 /* flush instruction cache */
2388 flush_icache_range((uintptr_t)s->code_buf, (uintptr_t)s->code_ptr);
2390 return tcg_current_code_size(s);
2393 /* Return the index of the micro operation such as the pc after is <
2394 offset bytes from the start of the TB. The contents of gen_code_buf must
2395 not be changed, though writing the same values is ok.
2396 Return -1 if not found. */
2397 int tcg_gen_code_search_pc(TCGContext *s, tcg_insn_unit *gen_code_buf,
2398 long offset)
2400 return tcg_gen_code_common(s, gen_code_buf, offset);
2403 #ifdef CONFIG_PROFILER
2404 void tcg_dump_info(FILE *f, fprintf_function cpu_fprintf)
2406 TCGContext *s = &tcg_ctx;
2407 int64_t tot;
2409 tot = s->interm_time + s->code_time;
2410 cpu_fprintf(f, "JIT cycles %" PRId64 " (%0.3f s at 2.4 GHz)\n",
2411 tot, tot / 2.4e9);
2412 cpu_fprintf(f, "translated TBs %" PRId64 " (aborted=%" PRId64 " %0.1f%%)\n",
2413 s->tb_count,
2414 s->tb_count1 - s->tb_count,
2415 s->tb_count1 ? (double)(s->tb_count1 - s->tb_count) / s->tb_count1 * 100.0 : 0);
2416 cpu_fprintf(f, "avg ops/TB %0.1f max=%d\n",
2417 s->tb_count ? (double)s->op_count / s->tb_count : 0, s->op_count_max);
2418 cpu_fprintf(f, "deleted ops/TB %0.2f\n",
2419 s->tb_count ?
2420 (double)s->del_op_count / s->tb_count : 0);
2421 cpu_fprintf(f, "avg temps/TB %0.2f max=%d\n",
2422 s->tb_count ?
2423 (double)s->temp_count / s->tb_count : 0,
2424 s->temp_count_max);
2426 cpu_fprintf(f, "cycles/op %0.1f\n",
2427 s->op_count ? (double)tot / s->op_count : 0);
2428 cpu_fprintf(f, "cycles/in byte %0.1f\n",
2429 s->code_in_len ? (double)tot / s->code_in_len : 0);
2430 cpu_fprintf(f, "cycles/out byte %0.1f\n",
2431 s->code_out_len ? (double)tot / s->code_out_len : 0);
2432 if (tot == 0)
2433 tot = 1;
2434 cpu_fprintf(f, " gen_interm time %0.1f%%\n",
2435 (double)s->interm_time / tot * 100.0);
2436 cpu_fprintf(f, " gen_code time %0.1f%%\n",
2437 (double)s->code_time / tot * 100.0);
2438 cpu_fprintf(f, "optim./code time %0.1f%%\n",
2439 (double)s->opt_time / (s->code_time ? s->code_time : 1)
2440 * 100.0);
2441 cpu_fprintf(f, "liveness/code time %0.1f%%\n",
2442 (double)s->la_time / (s->code_time ? s->code_time : 1) * 100.0);
2443 cpu_fprintf(f, "cpu_restore count %" PRId64 "\n",
2444 s->restore_count);
2445 cpu_fprintf(f, " avg cycles %0.1f\n",
2446 s->restore_count ? (double)s->restore_time / s->restore_count : 0);
2448 #else
2449 void tcg_dump_info(FILE *f, fprintf_function cpu_fprintf)
2451 cpu_fprintf(f, "[TCG profiler not compiled]\n");
2453 #endif
2455 #ifdef ELF_HOST_MACHINE
2456 /* In order to use this feature, the backend needs to do three things:
2458 (1) Define ELF_HOST_MACHINE to indicate both what value to
2459 put into the ELF image and to indicate support for the feature.
2461 (2) Define tcg_register_jit. This should create a buffer containing
2462 the contents of a .debug_frame section that describes the post-
2463 prologue unwind info for the tcg machine.
2465 (3) Call tcg_register_jit_int, with the constructed .debug_frame.
2468 /* Begin GDB interface. THE FOLLOWING MUST MATCH GDB DOCS. */
2469 typedef enum {
2470 JIT_NOACTION = 0,
2471 JIT_REGISTER_FN,
2472 JIT_UNREGISTER_FN
2473 } jit_actions_t;
2475 struct jit_code_entry {
2476 struct jit_code_entry *next_entry;
2477 struct jit_code_entry *prev_entry;
2478 const void *symfile_addr;
2479 uint64_t symfile_size;
2482 struct jit_descriptor {
2483 uint32_t version;
2484 uint32_t action_flag;
2485 struct jit_code_entry *relevant_entry;
2486 struct jit_code_entry *first_entry;
2489 void __jit_debug_register_code(void) __attribute__((noinline));
2490 void __jit_debug_register_code(void)
2492 asm("");
2495 /* Must statically initialize the version, because GDB may check
2496 the version before we can set it. */
2497 struct jit_descriptor __jit_debug_descriptor = { 1, 0, 0, 0 };
2499 /* End GDB interface. */
2501 static int find_string(const char *strtab, const char *str)
2503 const char *p = strtab + 1;
2505 while (1) {
2506 if (strcmp(p, str) == 0) {
2507 return p - strtab;
2509 p += strlen(p) + 1;
2513 static void tcg_register_jit_int(void *buf_ptr, size_t buf_size,
2514 const void *debug_frame,
2515 size_t debug_frame_size)
2517 struct __attribute__((packed)) DebugInfo {
2518 uint32_t len;
2519 uint16_t version;
2520 uint32_t abbrev;
2521 uint8_t ptr_size;
2522 uint8_t cu_die;
2523 uint16_t cu_lang;
2524 uintptr_t cu_low_pc;
2525 uintptr_t cu_high_pc;
2526 uint8_t fn_die;
2527 char fn_name[16];
2528 uintptr_t fn_low_pc;
2529 uintptr_t fn_high_pc;
2530 uint8_t cu_eoc;
2533 struct ElfImage {
2534 ElfW(Ehdr) ehdr;
2535 ElfW(Phdr) phdr;
2536 ElfW(Shdr) shdr[7];
2537 ElfW(Sym) sym[2];
2538 struct DebugInfo di;
2539 uint8_t da[24];
2540 char str[80];
2543 struct ElfImage *img;
2545 static const struct ElfImage img_template = {
2546 .ehdr = {
2547 .e_ident[EI_MAG0] = ELFMAG0,
2548 .e_ident[EI_MAG1] = ELFMAG1,
2549 .e_ident[EI_MAG2] = ELFMAG2,
2550 .e_ident[EI_MAG3] = ELFMAG3,
2551 .e_ident[EI_CLASS] = ELF_CLASS,
2552 .e_ident[EI_DATA] = ELF_DATA,
2553 .e_ident[EI_VERSION] = EV_CURRENT,
2554 .e_type = ET_EXEC,
2555 .e_machine = ELF_HOST_MACHINE,
2556 .e_version = EV_CURRENT,
2557 .e_phoff = offsetof(struct ElfImage, phdr),
2558 .e_shoff = offsetof(struct ElfImage, shdr),
2559 .e_ehsize = sizeof(ElfW(Shdr)),
2560 .e_phentsize = sizeof(ElfW(Phdr)),
2561 .e_phnum = 1,
2562 .e_shentsize = sizeof(ElfW(Shdr)),
2563 .e_shnum = ARRAY_SIZE(img->shdr),
2564 .e_shstrndx = ARRAY_SIZE(img->shdr) - 1,
2565 #ifdef ELF_HOST_FLAGS
2566 .e_flags = ELF_HOST_FLAGS,
2567 #endif
2568 #ifdef ELF_OSABI
2569 .e_ident[EI_OSABI] = ELF_OSABI,
2570 #endif
2572 .phdr = {
2573 .p_type = PT_LOAD,
2574 .p_flags = PF_X,
2576 .shdr = {
2577 [0] = { .sh_type = SHT_NULL },
2578 /* Trick: The contents of code_gen_buffer are not present in
2579 this fake ELF file; that got allocated elsewhere. Therefore
2580 we mark .text as SHT_NOBITS (similar to .bss) so that readers
2581 will not look for contents. We can record any address. */
2582 [1] = { /* .text */
2583 .sh_type = SHT_NOBITS,
2584 .sh_flags = SHF_EXECINSTR | SHF_ALLOC,
2586 [2] = { /* .debug_info */
2587 .sh_type = SHT_PROGBITS,
2588 .sh_offset = offsetof(struct ElfImage, di),
2589 .sh_size = sizeof(struct DebugInfo),
2591 [3] = { /* .debug_abbrev */
2592 .sh_type = SHT_PROGBITS,
2593 .sh_offset = offsetof(struct ElfImage, da),
2594 .sh_size = sizeof(img->da),
2596 [4] = { /* .debug_frame */
2597 .sh_type = SHT_PROGBITS,
2598 .sh_offset = sizeof(struct ElfImage),
2600 [5] = { /* .symtab */
2601 .sh_type = SHT_SYMTAB,
2602 .sh_offset = offsetof(struct ElfImage, sym),
2603 .sh_size = sizeof(img->sym),
2604 .sh_info = 1,
2605 .sh_link = ARRAY_SIZE(img->shdr) - 1,
2606 .sh_entsize = sizeof(ElfW(Sym)),
2608 [6] = { /* .strtab */
2609 .sh_type = SHT_STRTAB,
2610 .sh_offset = offsetof(struct ElfImage, str),
2611 .sh_size = sizeof(img->str),
2614 .sym = {
2615 [1] = { /* code_gen_buffer */
2616 .st_info = ELF_ST_INFO(STB_GLOBAL, STT_FUNC),
2617 .st_shndx = 1,
2620 .di = {
2621 .len = sizeof(struct DebugInfo) - 4,
2622 .version = 2,
2623 .ptr_size = sizeof(void *),
2624 .cu_die = 1,
2625 .cu_lang = 0x8001, /* DW_LANG_Mips_Assembler */
2626 .fn_die = 2,
2627 .fn_name = "code_gen_buffer"
2629 .da = {
2630 1, /* abbrev number (the cu) */
2631 0x11, 1, /* DW_TAG_compile_unit, has children */
2632 0x13, 0x5, /* DW_AT_language, DW_FORM_data2 */
2633 0x11, 0x1, /* DW_AT_low_pc, DW_FORM_addr */
2634 0x12, 0x1, /* DW_AT_high_pc, DW_FORM_addr */
2635 0, 0, /* end of abbrev */
2636 2, /* abbrev number (the fn) */
2637 0x2e, 0, /* DW_TAG_subprogram, no children */
2638 0x3, 0x8, /* DW_AT_name, DW_FORM_string */
2639 0x11, 0x1, /* DW_AT_low_pc, DW_FORM_addr */
2640 0x12, 0x1, /* DW_AT_high_pc, DW_FORM_addr */
2641 0, 0, /* end of abbrev */
2642 0 /* no more abbrev */
2644 .str = "\0" ".text\0" ".debug_info\0" ".debug_abbrev\0"
2645 ".debug_frame\0" ".symtab\0" ".strtab\0" "code_gen_buffer",
2648 /* We only need a single jit entry; statically allocate it. */
2649 static struct jit_code_entry one_entry;
2651 uintptr_t buf = (uintptr_t)buf_ptr;
2652 size_t img_size = sizeof(struct ElfImage) + debug_frame_size;
2653 DebugFrameHeader *dfh;
2655 img = g_malloc(img_size);
2656 *img = img_template;
2658 img->phdr.p_vaddr = buf;
2659 img->phdr.p_paddr = buf;
2660 img->phdr.p_memsz = buf_size;
2662 img->shdr[1].sh_name = find_string(img->str, ".text");
2663 img->shdr[1].sh_addr = buf;
2664 img->shdr[1].sh_size = buf_size;
2666 img->shdr[2].sh_name = find_string(img->str, ".debug_info");
2667 img->shdr[3].sh_name = find_string(img->str, ".debug_abbrev");
2669 img->shdr[4].sh_name = find_string(img->str, ".debug_frame");
2670 img->shdr[4].sh_size = debug_frame_size;
2672 img->shdr[5].sh_name = find_string(img->str, ".symtab");
2673 img->shdr[6].sh_name = find_string(img->str, ".strtab");
2675 img->sym[1].st_name = find_string(img->str, "code_gen_buffer");
2676 img->sym[1].st_value = buf;
2677 img->sym[1].st_size = buf_size;
2679 img->di.cu_low_pc = buf;
2680 img->di.cu_high_pc = buf + buf_size;
2681 img->di.fn_low_pc = buf;
2682 img->di.fn_high_pc = buf + buf_size;
2684 dfh = (DebugFrameHeader *)(img + 1);
2685 memcpy(dfh, debug_frame, debug_frame_size);
2686 dfh->fde.func_start = buf;
2687 dfh->fde.func_len = buf_size;
2689 #ifdef DEBUG_JIT
2690 /* Enable this block to be able to debug the ELF image file creation.
2691 One can use readelf, objdump, or other inspection utilities. */
2693 FILE *f = fopen("/tmp/qemu.jit", "w+b");
2694 if (f) {
2695 if (fwrite(img, img_size, 1, f) != img_size) {
2696 /* Avoid stupid unused return value warning for fwrite. */
2698 fclose(f);
2701 #endif
2703 one_entry.symfile_addr = img;
2704 one_entry.symfile_size = img_size;
2706 __jit_debug_descriptor.action_flag = JIT_REGISTER_FN;
2707 __jit_debug_descriptor.relevant_entry = &one_entry;
2708 __jit_debug_descriptor.first_entry = &one_entry;
2709 __jit_debug_register_code();
2711 #else
2712 /* No support for the feature. Provide the entry point expected by exec.c,
2713 and implement the internal function we declared earlier. */
2715 static void tcg_register_jit_int(void *buf, size_t size,
2716 const void *debug_frame,
2717 size_t debug_frame_size)
2721 void tcg_register_jit(void *buf, size_t buf_size)
2724 #endif /* ELF_HOST_MACHINE */