microblaze hw/: Don't use CPUState
[qemu.git] / tcg / tcg.c
blob531db55f5d414aefe27c53c8a411c3db436182c8
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 #if !defined(CONFIG_DEBUG_TCG) && !defined(NDEBUG)
32 /* define it to suppress various consistency checks (faster) */
33 #define NDEBUG
34 #endif
36 #include "qemu-common.h"
37 #include "cache-utils.h"
38 #include "host-utils.h"
39 #include "qemu-timer.h"
41 /* Note: the long term plan is to reduce the dependancies on the QEMU
42 CPU definitions. Currently they are used for qemu_ld/st
43 instructions */
44 #define NO_CPU_IO_DEFS
45 #include "cpu.h"
47 #include "tcg-op.h"
48 #include "elf.h"
50 #if defined(CONFIG_USE_GUEST_BASE) && !defined(TCG_TARGET_HAS_GUEST_BASE)
51 #error GUEST_BASE not supported on this host.
52 #endif
54 /* Forward declarations for functions declared in tcg-target.c and used here. */
55 static void tcg_target_init(TCGContext *s);
56 static void tcg_target_qemu_prologue(TCGContext *s);
57 static void patch_reloc(uint8_t *code_ptr, int type,
58 tcg_target_long value, tcg_target_long addend);
60 /* Forward declarations for functions declared and used in tcg-target.c. */
61 static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str);
62 static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg1,
63 tcg_target_long arg2);
64 static void tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg);
65 static void tcg_out_movi(TCGContext *s, TCGType type,
66 TCGReg ret, tcg_target_long arg);
67 static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
68 const int *const_args);
69 static void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, TCGReg arg1,
70 tcg_target_long arg2);
71 static int tcg_target_const_match(tcg_target_long val,
72 const TCGArgConstraint *arg_ct);
73 static int tcg_target_get_call_iarg_regs_count(int flags);
75 TCGOpDef tcg_op_defs[] = {
76 #define DEF(s, oargs, iargs, cargs, flags) { #s, oargs, iargs, cargs, iargs + oargs + cargs, flags },
77 #include "tcg-opc.h"
78 #undef DEF
80 const size_t tcg_op_defs_max = ARRAY_SIZE(tcg_op_defs);
82 static TCGRegSet tcg_target_available_regs[2];
83 static TCGRegSet tcg_target_call_clobber_regs;
85 /* XXX: move that inside the context */
86 uint16_t *gen_opc_ptr;
87 TCGArg *gen_opparam_ptr;
89 static inline void tcg_out8(TCGContext *s, uint8_t v)
91 *s->code_ptr++ = v;
94 static inline void tcg_out16(TCGContext *s, uint16_t v)
96 *(uint16_t *)s->code_ptr = v;
97 s->code_ptr += 2;
100 static inline void tcg_out32(TCGContext *s, uint32_t v)
102 *(uint32_t *)s->code_ptr = v;
103 s->code_ptr += 4;
106 /* label relocation processing */
108 static void tcg_out_reloc(TCGContext *s, uint8_t *code_ptr, int type,
109 int label_index, long addend)
111 TCGLabel *l;
112 TCGRelocation *r;
114 l = &s->labels[label_index];
115 if (l->has_value) {
116 /* FIXME: This may break relocations on RISC targets that
117 modify instruction fields in place. The caller may not have
118 written the initial value. */
119 patch_reloc(code_ptr, type, l->u.value, addend);
120 } else {
121 /* add a new relocation entry */
122 r = tcg_malloc(sizeof(TCGRelocation));
123 r->type = type;
124 r->ptr = code_ptr;
125 r->addend = addend;
126 r->next = l->u.first_reloc;
127 l->u.first_reloc = r;
131 static void tcg_out_label(TCGContext *s, int label_index, void *ptr)
133 TCGLabel *l;
134 TCGRelocation *r;
135 tcg_target_long value = (tcg_target_long)ptr;
137 l = &s->labels[label_index];
138 if (l->has_value)
139 tcg_abort();
140 r = l->u.first_reloc;
141 while (r != NULL) {
142 patch_reloc(r->ptr, r->type, value, r->addend);
143 r = r->next;
145 l->has_value = 1;
146 l->u.value = value;
149 int gen_new_label(void)
151 TCGContext *s = &tcg_ctx;
152 int idx;
153 TCGLabel *l;
155 if (s->nb_labels >= TCG_MAX_LABELS)
156 tcg_abort();
157 idx = s->nb_labels++;
158 l = &s->labels[idx];
159 l->has_value = 0;
160 l->u.first_reloc = NULL;
161 return idx;
164 #include "tcg-target.c"
166 /* pool based memory allocation */
167 void *tcg_malloc_internal(TCGContext *s, int size)
169 TCGPool *p;
170 int pool_size;
172 if (size > TCG_POOL_CHUNK_SIZE) {
173 /* big malloc: insert a new pool (XXX: could optimize) */
174 p = g_malloc(sizeof(TCGPool) + size);
175 p->size = size;
176 if (s->pool_current)
177 s->pool_current->next = p;
178 else
179 s->pool_first = p;
180 p->next = s->pool_current;
181 } else {
182 p = s->pool_current;
183 if (!p) {
184 p = s->pool_first;
185 if (!p)
186 goto new_pool;
187 } else {
188 if (!p->next) {
189 new_pool:
190 pool_size = TCG_POOL_CHUNK_SIZE;
191 p = g_malloc(sizeof(TCGPool) + pool_size);
192 p->size = pool_size;
193 p->next = NULL;
194 if (s->pool_current)
195 s->pool_current->next = p;
196 else
197 s->pool_first = p;
198 } else {
199 p = p->next;
203 s->pool_current = p;
204 s->pool_cur = p->data + size;
205 s->pool_end = p->data + p->size;
206 return p->data;
209 void tcg_pool_reset(TCGContext *s)
211 s->pool_cur = s->pool_end = NULL;
212 s->pool_current = NULL;
215 void tcg_context_init(TCGContext *s)
217 int op, total_args, n;
218 TCGOpDef *def;
219 TCGArgConstraint *args_ct;
220 int *sorted_args;
222 memset(s, 0, sizeof(*s));
223 s->temps = s->static_temps;
224 s->nb_globals = 0;
226 /* Count total number of arguments and allocate the corresponding
227 space */
228 total_args = 0;
229 for(op = 0; op < NB_OPS; op++) {
230 def = &tcg_op_defs[op];
231 n = def->nb_iargs + def->nb_oargs;
232 total_args += n;
235 args_ct = g_malloc(sizeof(TCGArgConstraint) * total_args);
236 sorted_args = g_malloc(sizeof(int) * total_args);
238 for(op = 0; op < NB_OPS; op++) {
239 def = &tcg_op_defs[op];
240 def->args_ct = args_ct;
241 def->sorted_args = sorted_args;
242 n = def->nb_iargs + def->nb_oargs;
243 sorted_args += n;
244 args_ct += n;
247 tcg_target_init(s);
250 void tcg_prologue_init(TCGContext *s)
252 /* init global prologue and epilogue */
253 s->code_buf = code_gen_prologue;
254 s->code_ptr = s->code_buf;
255 tcg_target_qemu_prologue(s);
256 flush_icache_range((tcg_target_ulong)s->code_buf,
257 (tcg_target_ulong)s->code_ptr);
260 void tcg_set_frame(TCGContext *s, int reg,
261 tcg_target_long start, tcg_target_long size)
263 s->frame_start = start;
264 s->frame_end = start + size;
265 s->frame_reg = reg;
268 void tcg_func_start(TCGContext *s)
270 int i;
271 tcg_pool_reset(s);
272 s->nb_temps = s->nb_globals;
273 for(i = 0; i < (TCG_TYPE_COUNT * 2); i++)
274 s->first_free_temp[i] = -1;
275 s->labels = tcg_malloc(sizeof(TCGLabel) * TCG_MAX_LABELS);
276 s->nb_labels = 0;
277 s->current_frame_offset = s->frame_start;
279 gen_opc_ptr = gen_opc_buf;
280 gen_opparam_ptr = gen_opparam_buf;
283 static inline void tcg_temp_alloc(TCGContext *s, int n)
285 if (n > TCG_MAX_TEMPS)
286 tcg_abort();
289 static inline int tcg_global_reg_new_internal(TCGType type, int reg,
290 const char *name)
292 TCGContext *s = &tcg_ctx;
293 TCGTemp *ts;
294 int idx;
296 #if TCG_TARGET_REG_BITS == 32
297 if (type != TCG_TYPE_I32)
298 tcg_abort();
299 #endif
300 if (tcg_regset_test_reg(s->reserved_regs, reg))
301 tcg_abort();
302 idx = s->nb_globals;
303 tcg_temp_alloc(s, s->nb_globals + 1);
304 ts = &s->temps[s->nb_globals];
305 ts->base_type = type;
306 ts->type = type;
307 ts->fixed_reg = 1;
308 ts->reg = reg;
309 ts->name = name;
310 s->nb_globals++;
311 tcg_regset_set_reg(s->reserved_regs, reg);
312 return idx;
315 TCGv_i32 tcg_global_reg_new_i32(int reg, const char *name)
317 int idx;
319 idx = tcg_global_reg_new_internal(TCG_TYPE_I32, reg, name);
320 return MAKE_TCGV_I32(idx);
323 TCGv_i64 tcg_global_reg_new_i64(int reg, const char *name)
325 int idx;
327 idx = tcg_global_reg_new_internal(TCG_TYPE_I64, reg, name);
328 return MAKE_TCGV_I64(idx);
331 static inline int tcg_global_mem_new_internal(TCGType type, int reg,
332 tcg_target_long offset,
333 const char *name)
335 TCGContext *s = &tcg_ctx;
336 TCGTemp *ts;
337 int idx;
339 idx = s->nb_globals;
340 #if TCG_TARGET_REG_BITS == 32
341 if (type == TCG_TYPE_I64) {
342 char buf[64];
343 tcg_temp_alloc(s, s->nb_globals + 2);
344 ts = &s->temps[s->nb_globals];
345 ts->base_type = type;
346 ts->type = TCG_TYPE_I32;
347 ts->fixed_reg = 0;
348 ts->mem_allocated = 1;
349 ts->mem_reg = reg;
350 #ifdef TCG_TARGET_WORDS_BIGENDIAN
351 ts->mem_offset = offset + 4;
352 #else
353 ts->mem_offset = offset;
354 #endif
355 pstrcpy(buf, sizeof(buf), name);
356 pstrcat(buf, sizeof(buf), "_0");
357 ts->name = strdup(buf);
358 ts++;
360 ts->base_type = type;
361 ts->type = TCG_TYPE_I32;
362 ts->fixed_reg = 0;
363 ts->mem_allocated = 1;
364 ts->mem_reg = reg;
365 #ifdef TCG_TARGET_WORDS_BIGENDIAN
366 ts->mem_offset = offset;
367 #else
368 ts->mem_offset = offset + 4;
369 #endif
370 pstrcpy(buf, sizeof(buf), name);
371 pstrcat(buf, sizeof(buf), "_1");
372 ts->name = strdup(buf);
374 s->nb_globals += 2;
375 } else
376 #endif
378 tcg_temp_alloc(s, s->nb_globals + 1);
379 ts = &s->temps[s->nb_globals];
380 ts->base_type = type;
381 ts->type = type;
382 ts->fixed_reg = 0;
383 ts->mem_allocated = 1;
384 ts->mem_reg = reg;
385 ts->mem_offset = offset;
386 ts->name = name;
387 s->nb_globals++;
389 return idx;
392 TCGv_i32 tcg_global_mem_new_i32(int reg, tcg_target_long offset,
393 const char *name)
395 int idx;
397 idx = tcg_global_mem_new_internal(TCG_TYPE_I32, reg, offset, name);
398 return MAKE_TCGV_I32(idx);
401 TCGv_i64 tcg_global_mem_new_i64(int reg, tcg_target_long offset,
402 const char *name)
404 int idx;
406 idx = tcg_global_mem_new_internal(TCG_TYPE_I64, reg, offset, name);
407 return MAKE_TCGV_I64(idx);
410 static inline int tcg_temp_new_internal(TCGType type, int temp_local)
412 TCGContext *s = &tcg_ctx;
413 TCGTemp *ts;
414 int idx, k;
416 k = type;
417 if (temp_local)
418 k += TCG_TYPE_COUNT;
419 idx = s->first_free_temp[k];
420 if (idx != -1) {
421 /* There is already an available temp with the
422 right type */
423 ts = &s->temps[idx];
424 s->first_free_temp[k] = ts->next_free_temp;
425 ts->temp_allocated = 1;
426 assert(ts->temp_local == temp_local);
427 } else {
428 idx = s->nb_temps;
429 #if TCG_TARGET_REG_BITS == 32
430 if (type == TCG_TYPE_I64) {
431 tcg_temp_alloc(s, s->nb_temps + 2);
432 ts = &s->temps[s->nb_temps];
433 ts->base_type = type;
434 ts->type = TCG_TYPE_I32;
435 ts->temp_allocated = 1;
436 ts->temp_local = temp_local;
437 ts->name = NULL;
438 ts++;
439 ts->base_type = TCG_TYPE_I32;
440 ts->type = TCG_TYPE_I32;
441 ts->temp_allocated = 1;
442 ts->temp_local = temp_local;
443 ts->name = NULL;
444 s->nb_temps += 2;
445 } else
446 #endif
448 tcg_temp_alloc(s, s->nb_temps + 1);
449 ts = &s->temps[s->nb_temps];
450 ts->base_type = type;
451 ts->type = type;
452 ts->temp_allocated = 1;
453 ts->temp_local = temp_local;
454 ts->name = NULL;
455 s->nb_temps++;
459 #if defined(CONFIG_DEBUG_TCG)
460 s->temps_in_use++;
461 #endif
462 return idx;
465 TCGv_i32 tcg_temp_new_internal_i32(int temp_local)
467 int idx;
469 idx = tcg_temp_new_internal(TCG_TYPE_I32, temp_local);
470 return MAKE_TCGV_I32(idx);
473 TCGv_i64 tcg_temp_new_internal_i64(int temp_local)
475 int idx;
477 idx = tcg_temp_new_internal(TCG_TYPE_I64, temp_local);
478 return MAKE_TCGV_I64(idx);
481 static inline void tcg_temp_free_internal(int idx)
483 TCGContext *s = &tcg_ctx;
484 TCGTemp *ts;
485 int k;
487 #if defined(CONFIG_DEBUG_TCG)
488 s->temps_in_use--;
489 if (s->temps_in_use < 0) {
490 fprintf(stderr, "More temporaries freed than allocated!\n");
492 #endif
494 assert(idx >= s->nb_globals && idx < s->nb_temps);
495 ts = &s->temps[idx];
496 assert(ts->temp_allocated != 0);
497 ts->temp_allocated = 0;
498 k = ts->base_type;
499 if (ts->temp_local)
500 k += TCG_TYPE_COUNT;
501 ts->next_free_temp = s->first_free_temp[k];
502 s->first_free_temp[k] = idx;
505 void tcg_temp_free_i32(TCGv_i32 arg)
507 tcg_temp_free_internal(GET_TCGV_I32(arg));
510 void tcg_temp_free_i64(TCGv_i64 arg)
512 tcg_temp_free_internal(GET_TCGV_I64(arg));
515 TCGv_i32 tcg_const_i32(int32_t val)
517 TCGv_i32 t0;
518 t0 = tcg_temp_new_i32();
519 tcg_gen_movi_i32(t0, val);
520 return t0;
523 TCGv_i64 tcg_const_i64(int64_t val)
525 TCGv_i64 t0;
526 t0 = tcg_temp_new_i64();
527 tcg_gen_movi_i64(t0, val);
528 return t0;
531 TCGv_i32 tcg_const_local_i32(int32_t val)
533 TCGv_i32 t0;
534 t0 = tcg_temp_local_new_i32();
535 tcg_gen_movi_i32(t0, val);
536 return t0;
539 TCGv_i64 tcg_const_local_i64(int64_t val)
541 TCGv_i64 t0;
542 t0 = tcg_temp_local_new_i64();
543 tcg_gen_movi_i64(t0, val);
544 return t0;
547 #if defined(CONFIG_DEBUG_TCG)
548 void tcg_clear_temp_count(void)
550 TCGContext *s = &tcg_ctx;
551 s->temps_in_use = 0;
554 int tcg_check_temp_count(void)
556 TCGContext *s = &tcg_ctx;
557 if (s->temps_in_use) {
558 /* Clear the count so that we don't give another
559 * warning immediately next time around.
561 s->temps_in_use = 0;
562 return 1;
564 return 0;
566 #endif
568 void tcg_register_helper(void *func, const char *name)
570 TCGContext *s = &tcg_ctx;
571 int n;
572 if ((s->nb_helpers + 1) > s->allocated_helpers) {
573 n = s->allocated_helpers;
574 if (n == 0) {
575 n = 4;
576 } else {
577 n *= 2;
579 s->helpers = realloc(s->helpers, n * sizeof(TCGHelperInfo));
580 s->allocated_helpers = n;
582 s->helpers[s->nb_helpers].func = (tcg_target_ulong)func;
583 s->helpers[s->nb_helpers].name = name;
584 s->nb_helpers++;
587 /* Note: we convert the 64 bit args to 32 bit and do some alignment
588 and endian swap. Maybe it would be better to do the alignment
589 and endian swap in tcg_reg_alloc_call(). */
590 void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags,
591 int sizemask, TCGArg ret, int nargs, TCGArg *args)
593 #if defined(TCG_TARGET_I386) && TCG_TARGET_REG_BITS < 64
594 int call_type;
595 #endif
596 int i;
597 int real_args;
598 int nb_rets;
599 TCGArg *nparam;
601 #if defined(TCG_TARGET_EXTEND_ARGS) && TCG_TARGET_REG_BITS == 64
602 for (i = 0; i < nargs; ++i) {
603 int is_64bit = sizemask & (1 << (i+1)*2);
604 int is_signed = sizemask & (2 << (i+1)*2);
605 if (!is_64bit) {
606 TCGv_i64 temp = tcg_temp_new_i64();
607 TCGv_i64 orig = MAKE_TCGV_I64(args[i]);
608 if (is_signed) {
609 tcg_gen_ext32s_i64(temp, orig);
610 } else {
611 tcg_gen_ext32u_i64(temp, orig);
613 args[i] = GET_TCGV_I64(temp);
616 #endif /* TCG_TARGET_EXTEND_ARGS */
618 *gen_opc_ptr++ = INDEX_op_call;
619 nparam = gen_opparam_ptr++;
620 #if defined(TCG_TARGET_I386) && TCG_TARGET_REG_BITS < 64
621 call_type = (flags & TCG_CALL_TYPE_MASK);
622 #endif
623 if (ret != TCG_CALL_DUMMY_ARG) {
624 #if TCG_TARGET_REG_BITS < 64
625 if (sizemask & 1) {
626 #ifdef TCG_TARGET_WORDS_BIGENDIAN
627 *gen_opparam_ptr++ = ret + 1;
628 *gen_opparam_ptr++ = ret;
629 #else
630 *gen_opparam_ptr++ = ret;
631 *gen_opparam_ptr++ = ret + 1;
632 #endif
633 nb_rets = 2;
634 } else
635 #endif
637 *gen_opparam_ptr++ = ret;
638 nb_rets = 1;
640 } else {
641 nb_rets = 0;
643 real_args = 0;
644 for (i = 0; i < nargs; i++) {
645 #if TCG_TARGET_REG_BITS < 64
646 int is_64bit = sizemask & (1 << (i+1)*2);
647 if (is_64bit) {
648 #ifdef TCG_TARGET_I386
649 /* REGPARM case: if the third parameter is 64 bit, it is
650 allocated on the stack */
651 if (i == 2 && call_type == TCG_CALL_TYPE_REGPARM) {
652 call_type = TCG_CALL_TYPE_REGPARM_2;
653 flags = (flags & ~TCG_CALL_TYPE_MASK) | call_type;
655 #endif
656 #ifdef TCG_TARGET_CALL_ALIGN_ARGS
657 /* some targets want aligned 64 bit args */
658 if (real_args & 1) {
659 *gen_opparam_ptr++ = TCG_CALL_DUMMY_ARG;
660 real_args++;
662 #endif
663 /* If stack grows up, then we will be placing successive
664 arguments at lower addresses, which means we need to
665 reverse the order compared to how we would normally
666 treat either big or little-endian. For those arguments
667 that will wind up in registers, this still works for
668 HPPA (the only current STACK_GROWSUP target) since the
669 argument registers are *also* allocated in decreasing
670 order. If another such target is added, this logic may
671 have to get more complicated to differentiate between
672 stack arguments and register arguments. */
673 #if defined(TCG_TARGET_WORDS_BIGENDIAN) != defined(TCG_TARGET_STACK_GROWSUP)
674 *gen_opparam_ptr++ = args[i] + 1;
675 *gen_opparam_ptr++ = args[i];
676 #else
677 *gen_opparam_ptr++ = args[i];
678 *gen_opparam_ptr++ = args[i] + 1;
679 #endif
680 real_args += 2;
681 continue;
683 #endif /* TCG_TARGET_REG_BITS < 64 */
685 *gen_opparam_ptr++ = args[i];
686 real_args++;
688 *gen_opparam_ptr++ = GET_TCGV_PTR(func);
690 *gen_opparam_ptr++ = flags;
692 *nparam = (nb_rets << 16) | (real_args + 1);
694 /* total parameters, needed to go backward in the instruction stream */
695 *gen_opparam_ptr++ = 1 + nb_rets + real_args + 3;
697 #if defined(TCG_TARGET_EXTEND_ARGS) && TCG_TARGET_REG_BITS == 64
698 for (i = 0; i < nargs; ++i) {
699 int is_64bit = sizemask & (1 << (i+1)*2);
700 if (!is_64bit) {
701 TCGv_i64 temp = MAKE_TCGV_I64(args[i]);
702 tcg_temp_free_i64(temp);
705 #endif /* TCG_TARGET_EXTEND_ARGS */
708 #if TCG_TARGET_REG_BITS == 32
709 void tcg_gen_shifti_i64(TCGv_i64 ret, TCGv_i64 arg1,
710 int c, int right, int arith)
712 if (c == 0) {
713 tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg1));
714 tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
715 } else if (c >= 32) {
716 c -= 32;
717 if (right) {
718 if (arith) {
719 tcg_gen_sari_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
720 tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 31);
721 } else {
722 tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
723 tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
725 } else {
726 tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_LOW(arg1), c);
727 tcg_gen_movi_i32(TCGV_LOW(ret), 0);
729 } else {
730 TCGv_i32 t0, t1;
732 t0 = tcg_temp_new_i32();
733 t1 = tcg_temp_new_i32();
734 if (right) {
735 tcg_gen_shli_i32(t0, TCGV_HIGH(arg1), 32 - c);
736 if (arith)
737 tcg_gen_sari_i32(t1, TCGV_HIGH(arg1), c);
738 else
739 tcg_gen_shri_i32(t1, TCGV_HIGH(arg1), c);
740 tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_LOW(arg1), c);
741 tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(ret), t0);
742 tcg_gen_mov_i32(TCGV_HIGH(ret), t1);
743 } else {
744 tcg_gen_shri_i32(t0, TCGV_LOW(arg1), 32 - c);
745 /* Note: ret can be the same as arg1, so we use t1 */
746 tcg_gen_shli_i32(t1, TCGV_LOW(arg1), c);
747 tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c);
748 tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t0);
749 tcg_gen_mov_i32(TCGV_LOW(ret), t1);
751 tcg_temp_free_i32(t0);
752 tcg_temp_free_i32(t1);
755 #endif
758 static void tcg_reg_alloc_start(TCGContext *s)
760 int i;
761 TCGTemp *ts;
762 for(i = 0; i < s->nb_globals; i++) {
763 ts = &s->temps[i];
764 if (ts->fixed_reg) {
765 ts->val_type = TEMP_VAL_REG;
766 } else {
767 ts->val_type = TEMP_VAL_MEM;
770 for(i = s->nb_globals; i < s->nb_temps; i++) {
771 ts = &s->temps[i];
772 ts->val_type = TEMP_VAL_DEAD;
773 ts->mem_allocated = 0;
774 ts->fixed_reg = 0;
776 for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
777 s->reg_to_temp[i] = -1;
781 static char *tcg_get_arg_str_idx(TCGContext *s, char *buf, int buf_size,
782 int idx)
784 TCGTemp *ts;
786 assert(idx >= 0 && idx < s->nb_temps);
787 ts = &s->temps[idx];
788 assert(ts);
789 if (idx < s->nb_globals) {
790 pstrcpy(buf, buf_size, ts->name);
791 } else {
792 if (ts->temp_local)
793 snprintf(buf, buf_size, "loc%d", idx - s->nb_globals);
794 else
795 snprintf(buf, buf_size, "tmp%d", idx - s->nb_globals);
797 return buf;
800 char *tcg_get_arg_str_i32(TCGContext *s, char *buf, int buf_size, TCGv_i32 arg)
802 return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I32(arg));
805 char *tcg_get_arg_str_i64(TCGContext *s, char *buf, int buf_size, TCGv_i64 arg)
807 return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I64(arg));
810 static int helper_cmp(const void *p1, const void *p2)
812 const TCGHelperInfo *th1 = p1;
813 const TCGHelperInfo *th2 = p2;
814 if (th1->func < th2->func)
815 return -1;
816 else if (th1->func == th2->func)
817 return 0;
818 else
819 return 1;
822 /* find helper definition (Note: A hash table would be better) */
823 static TCGHelperInfo *tcg_find_helper(TCGContext *s, tcg_target_ulong val)
825 int m, m_min, m_max;
826 TCGHelperInfo *th;
827 tcg_target_ulong v;
829 if (unlikely(!s->helpers_sorted)) {
830 qsort(s->helpers, s->nb_helpers, sizeof(TCGHelperInfo),
831 helper_cmp);
832 s->helpers_sorted = 1;
835 /* binary search */
836 m_min = 0;
837 m_max = s->nb_helpers - 1;
838 while (m_min <= m_max) {
839 m = (m_min + m_max) >> 1;
840 th = &s->helpers[m];
841 v = th->func;
842 if (v == val)
843 return th;
844 else if (val < v) {
845 m_max = m - 1;
846 } else {
847 m_min = m + 1;
850 return NULL;
853 static const char * const cond_name[] =
855 [TCG_COND_EQ] = "eq",
856 [TCG_COND_NE] = "ne",
857 [TCG_COND_LT] = "lt",
858 [TCG_COND_GE] = "ge",
859 [TCG_COND_LE] = "le",
860 [TCG_COND_GT] = "gt",
861 [TCG_COND_LTU] = "ltu",
862 [TCG_COND_GEU] = "geu",
863 [TCG_COND_LEU] = "leu",
864 [TCG_COND_GTU] = "gtu"
867 void tcg_dump_ops(TCGContext *s, FILE *outfile)
869 const uint16_t *opc_ptr;
870 const TCGArg *args;
871 TCGArg arg;
872 TCGOpcode c;
873 int i, k, nb_oargs, nb_iargs, nb_cargs, first_insn;
874 const TCGOpDef *def;
875 char buf[128];
877 first_insn = 1;
878 opc_ptr = gen_opc_buf;
879 args = gen_opparam_buf;
880 while (opc_ptr < gen_opc_ptr) {
881 c = *opc_ptr++;
882 def = &tcg_op_defs[c];
883 if (c == INDEX_op_debug_insn_start) {
884 uint64_t pc;
885 #if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
886 pc = ((uint64_t)args[1] << 32) | args[0];
887 #else
888 pc = args[0];
889 #endif
890 if (!first_insn)
891 fprintf(outfile, "\n");
892 fprintf(outfile, " ---- 0x%" PRIx64, pc);
893 first_insn = 0;
894 nb_oargs = def->nb_oargs;
895 nb_iargs = def->nb_iargs;
896 nb_cargs = def->nb_cargs;
897 } else if (c == INDEX_op_call) {
898 TCGArg arg;
900 /* variable number of arguments */
901 arg = *args++;
902 nb_oargs = arg >> 16;
903 nb_iargs = arg & 0xffff;
904 nb_cargs = def->nb_cargs;
906 fprintf(outfile, " %s ", def->name);
908 /* function name */
909 fprintf(outfile, "%s",
910 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + nb_iargs - 1]));
911 /* flags */
912 fprintf(outfile, ",$0x%" TCG_PRIlx,
913 args[nb_oargs + nb_iargs]);
914 /* nb out args */
915 fprintf(outfile, ",$%d", nb_oargs);
916 for(i = 0; i < nb_oargs; i++) {
917 fprintf(outfile, ",");
918 fprintf(outfile, "%s",
919 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[i]));
921 for(i = 0; i < (nb_iargs - 1); i++) {
922 fprintf(outfile, ",");
923 if (args[nb_oargs + i] == TCG_CALL_DUMMY_ARG) {
924 fprintf(outfile, "<dummy>");
925 } else {
926 fprintf(outfile, "%s",
927 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + i]));
930 } else if (c == INDEX_op_movi_i32
931 #if TCG_TARGET_REG_BITS == 64
932 || c == INDEX_op_movi_i64
933 #endif
935 tcg_target_ulong val;
936 TCGHelperInfo *th;
938 nb_oargs = def->nb_oargs;
939 nb_iargs = def->nb_iargs;
940 nb_cargs = def->nb_cargs;
941 fprintf(outfile, " %s %s,$", def->name,
942 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[0]));
943 val = args[1];
944 th = tcg_find_helper(s, val);
945 if (th) {
946 fprintf(outfile, "%s", th->name);
947 } else {
948 if (c == INDEX_op_movi_i32)
949 fprintf(outfile, "0x%x", (uint32_t)val);
950 else
951 fprintf(outfile, "0x%" PRIx64 , (uint64_t)val);
953 } else {
954 fprintf(outfile, " %s ", def->name);
955 if (c == INDEX_op_nopn) {
956 /* variable number of arguments */
957 nb_cargs = *args;
958 nb_oargs = 0;
959 nb_iargs = 0;
960 } else {
961 nb_oargs = def->nb_oargs;
962 nb_iargs = def->nb_iargs;
963 nb_cargs = def->nb_cargs;
966 k = 0;
967 for(i = 0; i < nb_oargs; i++) {
968 if (k != 0)
969 fprintf(outfile, ",");
970 fprintf(outfile, "%s",
971 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
973 for(i = 0; i < nb_iargs; i++) {
974 if (k != 0)
975 fprintf(outfile, ",");
976 fprintf(outfile, "%s",
977 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
979 switch (c) {
980 case INDEX_op_brcond_i32:
981 #if TCG_TARGET_REG_BITS == 32
982 case INDEX_op_brcond2_i32:
983 #elif TCG_TARGET_REG_BITS == 64
984 case INDEX_op_brcond_i64:
985 #endif
986 case INDEX_op_setcond_i32:
987 #if TCG_TARGET_REG_BITS == 32
988 case INDEX_op_setcond2_i32:
989 #elif TCG_TARGET_REG_BITS == 64
990 case INDEX_op_setcond_i64:
991 #endif
992 if (args[k] < ARRAY_SIZE(cond_name) && cond_name[args[k]])
993 fprintf(outfile, ",%s", cond_name[args[k++]]);
994 else
995 fprintf(outfile, ",$0x%" TCG_PRIlx, args[k++]);
996 i = 1;
997 break;
998 default:
999 i = 0;
1000 break;
1002 for(; i < nb_cargs; i++) {
1003 if (k != 0)
1004 fprintf(outfile, ",");
1005 arg = args[k++];
1006 fprintf(outfile, "$0x%" TCG_PRIlx, arg);
1009 fprintf(outfile, "\n");
1010 args += nb_iargs + nb_oargs + nb_cargs;
1014 /* we give more priority to constraints with less registers */
1015 static int get_constraint_priority(const TCGOpDef *def, int k)
1017 const TCGArgConstraint *arg_ct;
1019 int i, n;
1020 arg_ct = &def->args_ct[k];
1021 if (arg_ct->ct & TCG_CT_ALIAS) {
1022 /* an alias is equivalent to a single register */
1023 n = 1;
1024 } else {
1025 if (!(arg_ct->ct & TCG_CT_REG))
1026 return 0;
1027 n = 0;
1028 for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
1029 if (tcg_regset_test_reg(arg_ct->u.regs, i))
1030 n++;
1033 return TCG_TARGET_NB_REGS - n + 1;
1036 /* sort from highest priority to lowest */
1037 static void sort_constraints(TCGOpDef *def, int start, int n)
1039 int i, j, p1, p2, tmp;
1041 for(i = 0; i < n; i++)
1042 def->sorted_args[start + i] = start + i;
1043 if (n <= 1)
1044 return;
1045 for(i = 0; i < n - 1; i++) {
1046 for(j = i + 1; j < n; j++) {
1047 p1 = get_constraint_priority(def, def->sorted_args[start + i]);
1048 p2 = get_constraint_priority(def, def->sorted_args[start + j]);
1049 if (p1 < p2) {
1050 tmp = def->sorted_args[start + i];
1051 def->sorted_args[start + i] = def->sorted_args[start + j];
1052 def->sorted_args[start + j] = tmp;
1058 void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs)
1060 TCGOpcode op;
1061 TCGOpDef *def;
1062 const char *ct_str;
1063 int i, nb_args;
1065 for(;;) {
1066 if (tdefs->op == (TCGOpcode)-1)
1067 break;
1068 op = tdefs->op;
1069 assert((unsigned)op < NB_OPS);
1070 def = &tcg_op_defs[op];
1071 #if defined(CONFIG_DEBUG_TCG)
1072 /* Duplicate entry in op definitions? */
1073 assert(!def->used);
1074 def->used = 1;
1075 #endif
1076 nb_args = def->nb_iargs + def->nb_oargs;
1077 for(i = 0; i < nb_args; i++) {
1078 ct_str = tdefs->args_ct_str[i];
1079 /* Incomplete TCGTargetOpDef entry? */
1080 assert(ct_str != NULL);
1081 tcg_regset_clear(def->args_ct[i].u.regs);
1082 def->args_ct[i].ct = 0;
1083 if (ct_str[0] >= '0' && ct_str[0] <= '9') {
1084 int oarg;
1085 oarg = ct_str[0] - '0';
1086 assert(oarg < def->nb_oargs);
1087 assert(def->args_ct[oarg].ct & TCG_CT_REG);
1088 /* TCG_CT_ALIAS is for the output arguments. The input
1089 argument is tagged with TCG_CT_IALIAS. */
1090 def->args_ct[i] = def->args_ct[oarg];
1091 def->args_ct[oarg].ct = TCG_CT_ALIAS;
1092 def->args_ct[oarg].alias_index = i;
1093 def->args_ct[i].ct |= TCG_CT_IALIAS;
1094 def->args_ct[i].alias_index = oarg;
1095 } else {
1096 for(;;) {
1097 if (*ct_str == '\0')
1098 break;
1099 switch(*ct_str) {
1100 case 'i':
1101 def->args_ct[i].ct |= TCG_CT_CONST;
1102 ct_str++;
1103 break;
1104 default:
1105 if (target_parse_constraint(&def->args_ct[i], &ct_str) < 0) {
1106 fprintf(stderr, "Invalid constraint '%s' for arg %d of operation '%s'\n",
1107 ct_str, i, def->name);
1108 exit(1);
1115 /* TCGTargetOpDef entry with too much information? */
1116 assert(i == TCG_MAX_OP_ARGS || tdefs->args_ct_str[i] == NULL);
1118 /* sort the constraints (XXX: this is just an heuristic) */
1119 sort_constraints(def, 0, def->nb_oargs);
1120 sort_constraints(def, def->nb_oargs, def->nb_iargs);
1122 #if 0
1124 int i;
1126 printf("%s: sorted=", def->name);
1127 for(i = 0; i < def->nb_oargs + def->nb_iargs; i++)
1128 printf(" %d", def->sorted_args[i]);
1129 printf("\n");
1131 #endif
1132 tdefs++;
1135 #if defined(CONFIG_DEBUG_TCG)
1136 i = 0;
1137 for (op = 0; op < ARRAY_SIZE(tcg_op_defs); op++) {
1138 const TCGOpDef *def = &tcg_op_defs[op];
1139 if (op < INDEX_op_call
1140 || op == INDEX_op_debug_insn_start
1141 || (def->flags & TCG_OPF_NOT_PRESENT)) {
1142 /* Wrong entry in op definitions? */
1143 if (def->used) {
1144 fprintf(stderr, "Invalid op definition for %s\n", def->name);
1145 i = 1;
1147 } else {
1148 /* Missing entry in op definitions? */
1149 if (!def->used) {
1150 fprintf(stderr, "Missing op definition for %s\n", def->name);
1151 i = 1;
1155 if (i == 1) {
1156 tcg_abort();
1158 #endif
1161 #ifdef USE_LIVENESS_ANALYSIS
1163 /* set a nop for an operation using 'nb_args' */
1164 static inline void tcg_set_nop(TCGContext *s, uint16_t *opc_ptr,
1165 TCGArg *args, int nb_args)
1167 if (nb_args == 0) {
1168 *opc_ptr = INDEX_op_nop;
1169 } else {
1170 *opc_ptr = INDEX_op_nopn;
1171 args[0] = nb_args;
1172 args[nb_args - 1] = nb_args;
1176 /* liveness analysis: end of function: globals are live, temps are
1177 dead. */
1178 /* XXX: at this stage, not used as there would be little gains because
1179 most TBs end with a conditional jump. */
1180 static inline void tcg_la_func_end(TCGContext *s, uint8_t *dead_temps)
1182 memset(dead_temps, 0, s->nb_globals);
1183 memset(dead_temps + s->nb_globals, 1, s->nb_temps - s->nb_globals);
1186 /* liveness analysis: end of basic block: globals are live, temps are
1187 dead, local temps are live. */
1188 static inline void tcg_la_bb_end(TCGContext *s, uint8_t *dead_temps)
1190 int i;
1191 TCGTemp *ts;
1193 memset(dead_temps, 0, s->nb_globals);
1194 ts = &s->temps[s->nb_globals];
1195 for(i = s->nb_globals; i < s->nb_temps; i++) {
1196 if (ts->temp_local)
1197 dead_temps[i] = 0;
1198 else
1199 dead_temps[i] = 1;
1200 ts++;
1204 /* Liveness analysis : update the opc_dead_args array to tell if a
1205 given input arguments is dead. Instructions updating dead
1206 temporaries are removed. */
1207 static void tcg_liveness_analysis(TCGContext *s)
1209 int i, op_index, nb_args, nb_iargs, nb_oargs, arg, nb_ops;
1210 TCGOpcode op;
1211 TCGArg *args;
1212 const TCGOpDef *def;
1213 uint8_t *dead_temps;
1214 unsigned int dead_args;
1216 gen_opc_ptr++; /* skip end */
1218 nb_ops = gen_opc_ptr - gen_opc_buf;
1220 s->op_dead_args = tcg_malloc(nb_ops * sizeof(uint16_t));
1222 dead_temps = tcg_malloc(s->nb_temps);
1223 memset(dead_temps, 1, s->nb_temps);
1225 args = gen_opparam_ptr;
1226 op_index = nb_ops - 1;
1227 while (op_index >= 0) {
1228 op = gen_opc_buf[op_index];
1229 def = &tcg_op_defs[op];
1230 switch(op) {
1231 case INDEX_op_call:
1233 int call_flags;
1235 nb_args = args[-1];
1236 args -= nb_args;
1237 nb_iargs = args[0] & 0xffff;
1238 nb_oargs = args[0] >> 16;
1239 args++;
1240 call_flags = args[nb_oargs + nb_iargs];
1242 /* pure functions can be removed if their result is not
1243 used */
1244 if (call_flags & TCG_CALL_PURE) {
1245 for(i = 0; i < nb_oargs; i++) {
1246 arg = args[i];
1247 if (!dead_temps[arg])
1248 goto do_not_remove_call;
1250 tcg_set_nop(s, gen_opc_buf + op_index,
1251 args - 1, nb_args);
1252 } else {
1253 do_not_remove_call:
1255 /* output args are dead */
1256 dead_args = 0;
1257 for(i = 0; i < nb_oargs; i++) {
1258 arg = args[i];
1259 if (dead_temps[arg]) {
1260 dead_args |= (1 << i);
1262 dead_temps[arg] = 1;
1265 if (!(call_flags & TCG_CALL_CONST)) {
1266 /* globals are live (they may be used by the call) */
1267 memset(dead_temps, 0, s->nb_globals);
1270 /* input args are live */
1271 for(i = nb_oargs; i < nb_iargs + nb_oargs; i++) {
1272 arg = args[i];
1273 if (arg != TCG_CALL_DUMMY_ARG) {
1274 if (dead_temps[arg]) {
1275 dead_args |= (1 << i);
1277 dead_temps[arg] = 0;
1280 s->op_dead_args[op_index] = dead_args;
1282 args--;
1284 break;
1285 case INDEX_op_set_label:
1286 args--;
1287 /* mark end of basic block */
1288 tcg_la_bb_end(s, dead_temps);
1289 break;
1290 case INDEX_op_debug_insn_start:
1291 args -= def->nb_args;
1292 break;
1293 case INDEX_op_nopn:
1294 nb_args = args[-1];
1295 args -= nb_args;
1296 break;
1297 case INDEX_op_discard:
1298 args--;
1299 /* mark the temporary as dead */
1300 dead_temps[args[0]] = 1;
1301 break;
1302 case INDEX_op_end:
1303 break;
1304 /* XXX: optimize by hardcoding common cases (e.g. triadic ops) */
1305 default:
1306 args -= def->nb_args;
1307 nb_iargs = def->nb_iargs;
1308 nb_oargs = def->nb_oargs;
1310 /* Test if the operation can be removed because all
1311 its outputs are dead. We assume that nb_oargs == 0
1312 implies side effects */
1313 if (!(def->flags & TCG_OPF_SIDE_EFFECTS) && nb_oargs != 0) {
1314 for(i = 0; i < nb_oargs; i++) {
1315 arg = args[i];
1316 if (!dead_temps[arg])
1317 goto do_not_remove;
1319 tcg_set_nop(s, gen_opc_buf + op_index, args, def->nb_args);
1320 #ifdef CONFIG_PROFILER
1321 s->del_op_count++;
1322 #endif
1323 } else {
1324 do_not_remove:
1326 /* output args are dead */
1327 dead_args = 0;
1328 for(i = 0; i < nb_oargs; i++) {
1329 arg = args[i];
1330 if (dead_temps[arg]) {
1331 dead_args |= (1 << i);
1333 dead_temps[arg] = 1;
1336 /* if end of basic block, update */
1337 if (def->flags & TCG_OPF_BB_END) {
1338 tcg_la_bb_end(s, dead_temps);
1339 } else if (def->flags & TCG_OPF_CALL_CLOBBER) {
1340 /* globals are live */
1341 memset(dead_temps, 0, s->nb_globals);
1344 /* input args are live */
1345 for(i = nb_oargs; i < nb_oargs + nb_iargs; i++) {
1346 arg = args[i];
1347 if (dead_temps[arg]) {
1348 dead_args |= (1 << i);
1350 dead_temps[arg] = 0;
1352 s->op_dead_args[op_index] = dead_args;
1354 break;
1356 op_index--;
1359 if (args != gen_opparam_buf)
1360 tcg_abort();
1362 #else
1363 /* dummy liveness analysis */
1364 static void tcg_liveness_analysis(TCGContext *s)
1366 int nb_ops;
1367 nb_ops = gen_opc_ptr - gen_opc_buf;
1369 s->op_dead_args = tcg_malloc(nb_ops * sizeof(uint16_t));
1370 memset(s->op_dead_args, 0, nb_ops * sizeof(uint16_t));
1372 #endif
1374 #ifndef NDEBUG
1375 static void dump_regs(TCGContext *s)
1377 TCGTemp *ts;
1378 int i;
1379 char buf[64];
1381 for(i = 0; i < s->nb_temps; i++) {
1382 ts = &s->temps[i];
1383 printf(" %10s: ", tcg_get_arg_str_idx(s, buf, sizeof(buf), i));
1384 switch(ts->val_type) {
1385 case TEMP_VAL_REG:
1386 printf("%s", tcg_target_reg_names[ts->reg]);
1387 break;
1388 case TEMP_VAL_MEM:
1389 printf("%d(%s)", (int)ts->mem_offset, tcg_target_reg_names[ts->mem_reg]);
1390 break;
1391 case TEMP_VAL_CONST:
1392 printf("$0x%" TCG_PRIlx, ts->val);
1393 break;
1394 case TEMP_VAL_DEAD:
1395 printf("D");
1396 break;
1397 default:
1398 printf("???");
1399 break;
1401 printf("\n");
1404 for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
1405 if (s->reg_to_temp[i] >= 0) {
1406 printf("%s: %s\n",
1407 tcg_target_reg_names[i],
1408 tcg_get_arg_str_idx(s, buf, sizeof(buf), s->reg_to_temp[i]));
1413 static void check_regs(TCGContext *s)
1415 int reg, k;
1416 TCGTemp *ts;
1417 char buf[64];
1419 for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1420 k = s->reg_to_temp[reg];
1421 if (k >= 0) {
1422 ts = &s->temps[k];
1423 if (ts->val_type != TEMP_VAL_REG ||
1424 ts->reg != reg) {
1425 printf("Inconsistency for register %s:\n",
1426 tcg_target_reg_names[reg]);
1427 goto fail;
1431 for(k = 0; k < s->nb_temps; k++) {
1432 ts = &s->temps[k];
1433 if (ts->val_type == TEMP_VAL_REG &&
1434 !ts->fixed_reg &&
1435 s->reg_to_temp[ts->reg] != k) {
1436 printf("Inconsistency for temp %s:\n",
1437 tcg_get_arg_str_idx(s, buf, sizeof(buf), k));
1438 fail:
1439 printf("reg state:\n");
1440 dump_regs(s);
1441 tcg_abort();
1445 #endif
1447 static void temp_allocate_frame(TCGContext *s, int temp)
1449 TCGTemp *ts;
1450 ts = &s->temps[temp];
1451 #ifndef __sparc_v9__ /* Sparc64 stack is accessed with offset of 2047 */
1452 s->current_frame_offset = (s->current_frame_offset +
1453 (tcg_target_long)sizeof(tcg_target_long) - 1) &
1454 ~(sizeof(tcg_target_long) - 1);
1455 #endif
1456 if (s->current_frame_offset + (tcg_target_long)sizeof(tcg_target_long) >
1457 s->frame_end) {
1458 tcg_abort();
1460 ts->mem_offset = s->current_frame_offset;
1461 ts->mem_reg = s->frame_reg;
1462 ts->mem_allocated = 1;
1463 s->current_frame_offset += (tcg_target_long)sizeof(tcg_target_long);
1466 /* free register 'reg' by spilling the corresponding temporary if necessary */
1467 static void tcg_reg_free(TCGContext *s, int reg)
1469 TCGTemp *ts;
1470 int temp;
1472 temp = s->reg_to_temp[reg];
1473 if (temp != -1) {
1474 ts = &s->temps[temp];
1475 assert(ts->val_type == TEMP_VAL_REG);
1476 if (!ts->mem_coherent) {
1477 if (!ts->mem_allocated)
1478 temp_allocate_frame(s, temp);
1479 tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1481 ts->val_type = TEMP_VAL_MEM;
1482 s->reg_to_temp[reg] = -1;
1486 /* Allocate a register belonging to reg1 & ~reg2 */
1487 static int tcg_reg_alloc(TCGContext *s, TCGRegSet reg1, TCGRegSet reg2)
1489 int i, reg;
1490 TCGRegSet reg_ct;
1492 tcg_regset_andnot(reg_ct, reg1, reg2);
1494 /* first try free registers */
1495 for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1496 reg = tcg_target_reg_alloc_order[i];
1497 if (tcg_regset_test_reg(reg_ct, reg) && s->reg_to_temp[reg] == -1)
1498 return reg;
1501 /* XXX: do better spill choice */
1502 for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1503 reg = tcg_target_reg_alloc_order[i];
1504 if (tcg_regset_test_reg(reg_ct, reg)) {
1505 tcg_reg_free(s, reg);
1506 return reg;
1510 tcg_abort();
1513 /* save a temporary to memory. 'allocated_regs' is used in case a
1514 temporary registers needs to be allocated to store a constant. */
1515 static void temp_save(TCGContext *s, int temp, TCGRegSet allocated_regs)
1517 TCGTemp *ts;
1518 int reg;
1520 ts = &s->temps[temp];
1521 if (!ts->fixed_reg) {
1522 switch(ts->val_type) {
1523 case TEMP_VAL_REG:
1524 tcg_reg_free(s, ts->reg);
1525 break;
1526 case TEMP_VAL_DEAD:
1527 ts->val_type = TEMP_VAL_MEM;
1528 break;
1529 case TEMP_VAL_CONST:
1530 reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type],
1531 allocated_regs);
1532 if (!ts->mem_allocated)
1533 temp_allocate_frame(s, temp);
1534 tcg_out_movi(s, ts->type, reg, ts->val);
1535 tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1536 ts->val_type = TEMP_VAL_MEM;
1537 break;
1538 case TEMP_VAL_MEM:
1539 break;
1540 default:
1541 tcg_abort();
1546 /* save globals to their canonical location and assume they can be
1547 modified be the following code. 'allocated_regs' is used in case a
1548 temporary registers needs to be allocated to store a constant. */
1549 static void save_globals(TCGContext *s, TCGRegSet allocated_regs)
1551 int i;
1553 for(i = 0; i < s->nb_globals; i++) {
1554 temp_save(s, i, allocated_regs);
1558 /* at the end of a basic block, we assume all temporaries are dead and
1559 all globals are stored at their canonical location. */
1560 static void tcg_reg_alloc_bb_end(TCGContext *s, TCGRegSet allocated_regs)
1562 TCGTemp *ts;
1563 int i;
1565 for(i = s->nb_globals; i < s->nb_temps; i++) {
1566 ts = &s->temps[i];
1567 if (ts->temp_local) {
1568 temp_save(s, i, allocated_regs);
1569 } else {
1570 if (ts->val_type == TEMP_VAL_REG) {
1571 s->reg_to_temp[ts->reg] = -1;
1573 ts->val_type = TEMP_VAL_DEAD;
1577 save_globals(s, allocated_regs);
1580 #define IS_DEAD_ARG(n) ((dead_args >> (n)) & 1)
1582 static void tcg_reg_alloc_movi(TCGContext *s, const TCGArg *args)
1584 TCGTemp *ots;
1585 tcg_target_ulong val;
1587 ots = &s->temps[args[0]];
1588 val = args[1];
1590 if (ots->fixed_reg) {
1591 /* for fixed registers, we do not do any constant
1592 propagation */
1593 tcg_out_movi(s, ots->type, ots->reg, val);
1594 } else {
1595 /* The movi is not explicitly generated here */
1596 if (ots->val_type == TEMP_VAL_REG)
1597 s->reg_to_temp[ots->reg] = -1;
1598 ots->val_type = TEMP_VAL_CONST;
1599 ots->val = val;
1603 static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
1604 const TCGArg *args,
1605 unsigned int dead_args)
1607 TCGTemp *ts, *ots;
1608 int reg;
1609 const TCGArgConstraint *arg_ct;
1611 ots = &s->temps[args[0]];
1612 ts = &s->temps[args[1]];
1613 arg_ct = &def->args_ct[0];
1615 /* XXX: always mark arg dead if IS_DEAD_ARG(1) */
1616 if (ts->val_type == TEMP_VAL_REG) {
1617 if (IS_DEAD_ARG(1) && !ts->fixed_reg && !ots->fixed_reg) {
1618 /* the mov can be suppressed */
1619 if (ots->val_type == TEMP_VAL_REG)
1620 s->reg_to_temp[ots->reg] = -1;
1621 reg = ts->reg;
1622 s->reg_to_temp[reg] = -1;
1623 ts->val_type = TEMP_VAL_DEAD;
1624 } else {
1625 if (ots->val_type == TEMP_VAL_REG) {
1626 reg = ots->reg;
1627 } else {
1628 reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1630 if (ts->reg != reg) {
1631 tcg_out_mov(s, ots->type, reg, ts->reg);
1634 } else if (ts->val_type == TEMP_VAL_MEM) {
1635 if (ots->val_type == TEMP_VAL_REG) {
1636 reg = ots->reg;
1637 } else {
1638 reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1640 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1641 } else if (ts->val_type == TEMP_VAL_CONST) {
1642 if (ots->fixed_reg) {
1643 reg = ots->reg;
1644 tcg_out_movi(s, ots->type, reg, ts->val);
1645 } else {
1646 /* propagate constant */
1647 if (ots->val_type == TEMP_VAL_REG)
1648 s->reg_to_temp[ots->reg] = -1;
1649 ots->val_type = TEMP_VAL_CONST;
1650 ots->val = ts->val;
1651 return;
1653 } else {
1654 tcg_abort();
1656 s->reg_to_temp[reg] = args[0];
1657 ots->reg = reg;
1658 ots->val_type = TEMP_VAL_REG;
1659 ots->mem_coherent = 0;
1662 static void tcg_reg_alloc_op(TCGContext *s,
1663 const TCGOpDef *def, TCGOpcode opc,
1664 const TCGArg *args,
1665 unsigned int dead_args)
1667 TCGRegSet allocated_regs;
1668 int i, k, nb_iargs, nb_oargs, reg;
1669 TCGArg arg;
1670 const TCGArgConstraint *arg_ct;
1671 TCGTemp *ts;
1672 TCGArg new_args[TCG_MAX_OP_ARGS];
1673 int const_args[TCG_MAX_OP_ARGS];
1675 nb_oargs = def->nb_oargs;
1676 nb_iargs = def->nb_iargs;
1678 /* copy constants */
1679 memcpy(new_args + nb_oargs + nb_iargs,
1680 args + nb_oargs + nb_iargs,
1681 sizeof(TCGArg) * def->nb_cargs);
1683 /* satisfy input constraints */
1684 tcg_regset_set(allocated_regs, s->reserved_regs);
1685 for(k = 0; k < nb_iargs; k++) {
1686 i = def->sorted_args[nb_oargs + k];
1687 arg = args[i];
1688 arg_ct = &def->args_ct[i];
1689 ts = &s->temps[arg];
1690 if (ts->val_type == TEMP_VAL_MEM) {
1691 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1692 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1693 ts->val_type = TEMP_VAL_REG;
1694 ts->reg = reg;
1695 ts->mem_coherent = 1;
1696 s->reg_to_temp[reg] = arg;
1697 } else if (ts->val_type == TEMP_VAL_CONST) {
1698 if (tcg_target_const_match(ts->val, arg_ct)) {
1699 /* constant is OK for instruction */
1700 const_args[i] = 1;
1701 new_args[i] = ts->val;
1702 goto iarg_end;
1703 } else {
1704 /* need to move to a register */
1705 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1706 tcg_out_movi(s, ts->type, reg, ts->val);
1707 ts->val_type = TEMP_VAL_REG;
1708 ts->reg = reg;
1709 ts->mem_coherent = 0;
1710 s->reg_to_temp[reg] = arg;
1713 assert(ts->val_type == TEMP_VAL_REG);
1714 if (arg_ct->ct & TCG_CT_IALIAS) {
1715 if (ts->fixed_reg) {
1716 /* if fixed register, we must allocate a new register
1717 if the alias is not the same register */
1718 if (arg != args[arg_ct->alias_index])
1719 goto allocate_in_reg;
1720 } else {
1721 /* if the input is aliased to an output and if it is
1722 not dead after the instruction, we must allocate
1723 a new register and move it */
1724 if (!IS_DEAD_ARG(i)) {
1725 goto allocate_in_reg;
1729 reg = ts->reg;
1730 if (tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1731 /* nothing to do : the constraint is satisfied */
1732 } else {
1733 allocate_in_reg:
1734 /* allocate a new register matching the constraint
1735 and move the temporary register into it */
1736 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1737 tcg_out_mov(s, ts->type, reg, ts->reg);
1739 new_args[i] = reg;
1740 const_args[i] = 0;
1741 tcg_regset_set_reg(allocated_regs, reg);
1742 iarg_end: ;
1745 if (def->flags & TCG_OPF_BB_END) {
1746 tcg_reg_alloc_bb_end(s, allocated_regs);
1747 } else {
1748 /* mark dead temporaries and free the associated registers */
1749 for(i = nb_oargs; i < nb_oargs + nb_iargs; i++) {
1750 arg = args[i];
1751 if (IS_DEAD_ARG(i)) {
1752 ts = &s->temps[arg];
1753 if (!ts->fixed_reg) {
1754 if (ts->val_type == TEMP_VAL_REG)
1755 s->reg_to_temp[ts->reg] = -1;
1756 ts->val_type = TEMP_VAL_DEAD;
1761 if (def->flags & TCG_OPF_CALL_CLOBBER) {
1762 /* XXX: permit generic clobber register list ? */
1763 for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1764 if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
1765 tcg_reg_free(s, reg);
1768 /* XXX: for load/store we could do that only for the slow path
1769 (i.e. when a memory callback is called) */
1771 /* store globals and free associated registers (we assume the insn
1772 can modify any global. */
1773 save_globals(s, allocated_regs);
1776 /* satisfy the output constraints */
1777 tcg_regset_set(allocated_regs, s->reserved_regs);
1778 for(k = 0; k < nb_oargs; k++) {
1779 i = def->sorted_args[k];
1780 arg = args[i];
1781 arg_ct = &def->args_ct[i];
1782 ts = &s->temps[arg];
1783 if (arg_ct->ct & TCG_CT_ALIAS) {
1784 reg = new_args[arg_ct->alias_index];
1785 } else {
1786 /* if fixed register, we try to use it */
1787 reg = ts->reg;
1788 if (ts->fixed_reg &&
1789 tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1790 goto oarg_end;
1792 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1794 tcg_regset_set_reg(allocated_regs, reg);
1795 /* if a fixed register is used, then a move will be done afterwards */
1796 if (!ts->fixed_reg) {
1797 if (ts->val_type == TEMP_VAL_REG)
1798 s->reg_to_temp[ts->reg] = -1;
1799 if (IS_DEAD_ARG(i)) {
1800 ts->val_type = TEMP_VAL_DEAD;
1801 } else {
1802 ts->val_type = TEMP_VAL_REG;
1803 ts->reg = reg;
1804 /* temp value is modified, so the value kept in memory is
1805 potentially not the same */
1806 ts->mem_coherent = 0;
1807 s->reg_to_temp[reg] = arg;
1810 oarg_end:
1811 new_args[i] = reg;
1815 /* emit instruction */
1816 tcg_out_op(s, opc, new_args, const_args);
1818 /* move the outputs in the correct register if needed */
1819 for(i = 0; i < nb_oargs; i++) {
1820 ts = &s->temps[args[i]];
1821 reg = new_args[i];
1822 if (ts->fixed_reg && ts->reg != reg) {
1823 tcg_out_mov(s, ts->type, ts->reg, reg);
1828 #ifdef TCG_TARGET_STACK_GROWSUP
1829 #define STACK_DIR(x) (-(x))
1830 #else
1831 #define STACK_DIR(x) (x)
1832 #endif
1834 static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
1835 TCGOpcode opc, const TCGArg *args,
1836 unsigned int dead_args)
1838 int nb_iargs, nb_oargs, flags, nb_regs, i, reg, nb_params;
1839 TCGArg arg, func_arg;
1840 TCGTemp *ts;
1841 tcg_target_long stack_offset, call_stack_size, func_addr;
1842 int const_func_arg, allocate_args;
1843 TCGRegSet allocated_regs;
1844 const TCGArgConstraint *arg_ct;
1846 arg = *args++;
1848 nb_oargs = arg >> 16;
1849 nb_iargs = arg & 0xffff;
1850 nb_params = nb_iargs - 1;
1852 flags = args[nb_oargs + nb_iargs];
1854 nb_regs = tcg_target_get_call_iarg_regs_count(flags);
1855 if (nb_regs > nb_params)
1856 nb_regs = nb_params;
1858 /* assign stack slots first */
1859 call_stack_size = (nb_params - nb_regs) * sizeof(tcg_target_long);
1860 call_stack_size = (call_stack_size + TCG_TARGET_STACK_ALIGN - 1) &
1861 ~(TCG_TARGET_STACK_ALIGN - 1);
1862 allocate_args = (call_stack_size > TCG_STATIC_CALL_ARGS_SIZE);
1863 if (allocate_args) {
1864 /* XXX: if more than TCG_STATIC_CALL_ARGS_SIZE is needed,
1865 preallocate call stack */
1866 tcg_abort();
1869 stack_offset = TCG_TARGET_CALL_STACK_OFFSET;
1870 for(i = nb_regs; i < nb_params; i++) {
1871 arg = args[nb_oargs + i];
1872 #ifdef TCG_TARGET_STACK_GROWSUP
1873 stack_offset -= sizeof(tcg_target_long);
1874 #endif
1875 if (arg != TCG_CALL_DUMMY_ARG) {
1876 ts = &s->temps[arg];
1877 if (ts->val_type == TEMP_VAL_REG) {
1878 tcg_out_st(s, ts->type, ts->reg, TCG_REG_CALL_STACK, stack_offset);
1879 } else if (ts->val_type == TEMP_VAL_MEM) {
1880 reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type],
1881 s->reserved_regs);
1882 /* XXX: not correct if reading values from the stack */
1883 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1884 tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
1885 } else if (ts->val_type == TEMP_VAL_CONST) {
1886 reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type],
1887 s->reserved_regs);
1888 /* XXX: sign extend may be needed on some targets */
1889 tcg_out_movi(s, ts->type, reg, ts->val);
1890 tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
1891 } else {
1892 tcg_abort();
1895 #ifndef TCG_TARGET_STACK_GROWSUP
1896 stack_offset += sizeof(tcg_target_long);
1897 #endif
1900 /* assign input registers */
1901 tcg_regset_set(allocated_regs, s->reserved_regs);
1902 for(i = 0; i < nb_regs; i++) {
1903 arg = args[nb_oargs + i];
1904 if (arg != TCG_CALL_DUMMY_ARG) {
1905 ts = &s->temps[arg];
1906 reg = tcg_target_call_iarg_regs[i];
1907 tcg_reg_free(s, reg);
1908 if (ts->val_type == TEMP_VAL_REG) {
1909 if (ts->reg != reg) {
1910 tcg_out_mov(s, ts->type, reg, ts->reg);
1912 } else if (ts->val_type == TEMP_VAL_MEM) {
1913 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1914 } else if (ts->val_type == TEMP_VAL_CONST) {
1915 /* XXX: sign extend ? */
1916 tcg_out_movi(s, ts->type, reg, ts->val);
1917 } else {
1918 tcg_abort();
1920 tcg_regset_set_reg(allocated_regs, reg);
1924 /* assign function address */
1925 func_arg = args[nb_oargs + nb_iargs - 1];
1926 arg_ct = &def->args_ct[0];
1927 ts = &s->temps[func_arg];
1928 func_addr = ts->val;
1929 const_func_arg = 0;
1930 if (ts->val_type == TEMP_VAL_MEM) {
1931 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1932 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1933 func_arg = reg;
1934 tcg_regset_set_reg(allocated_regs, reg);
1935 } else if (ts->val_type == TEMP_VAL_REG) {
1936 reg = ts->reg;
1937 if (!tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1938 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1939 tcg_out_mov(s, ts->type, reg, ts->reg);
1941 func_arg = reg;
1942 tcg_regset_set_reg(allocated_regs, reg);
1943 } else if (ts->val_type == TEMP_VAL_CONST) {
1944 if (tcg_target_const_match(func_addr, arg_ct)) {
1945 const_func_arg = 1;
1946 func_arg = func_addr;
1947 } else {
1948 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1949 tcg_out_movi(s, ts->type, reg, func_addr);
1950 func_arg = reg;
1951 tcg_regset_set_reg(allocated_regs, reg);
1953 } else {
1954 tcg_abort();
1958 /* mark dead temporaries and free the associated registers */
1959 for(i = nb_oargs; i < nb_iargs + nb_oargs; i++) {
1960 arg = args[i];
1961 if (IS_DEAD_ARG(i)) {
1962 ts = &s->temps[arg];
1963 if (!ts->fixed_reg) {
1964 if (ts->val_type == TEMP_VAL_REG)
1965 s->reg_to_temp[ts->reg] = -1;
1966 ts->val_type = TEMP_VAL_DEAD;
1971 /* clobber call registers */
1972 for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1973 if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
1974 tcg_reg_free(s, reg);
1978 /* store globals and free associated registers (we assume the call
1979 can modify any global. */
1980 if (!(flags & TCG_CALL_CONST)) {
1981 save_globals(s, allocated_regs);
1984 tcg_out_op(s, opc, &func_arg, &const_func_arg);
1986 /* assign output registers and emit moves if needed */
1987 for(i = 0; i < nb_oargs; i++) {
1988 arg = args[i];
1989 ts = &s->temps[arg];
1990 reg = tcg_target_call_oarg_regs[i];
1991 assert(s->reg_to_temp[reg] == -1);
1992 if (ts->fixed_reg) {
1993 if (ts->reg != reg) {
1994 tcg_out_mov(s, ts->type, ts->reg, reg);
1996 } else {
1997 if (ts->val_type == TEMP_VAL_REG)
1998 s->reg_to_temp[ts->reg] = -1;
1999 if (IS_DEAD_ARG(i)) {
2000 ts->val_type = TEMP_VAL_DEAD;
2001 } else {
2002 ts->val_type = TEMP_VAL_REG;
2003 ts->reg = reg;
2004 ts->mem_coherent = 0;
2005 s->reg_to_temp[reg] = arg;
2010 return nb_iargs + nb_oargs + def->nb_cargs + 1;
2013 #ifdef CONFIG_PROFILER
2015 static int64_t tcg_table_op_count[NB_OPS];
2017 static void dump_op_count(void)
2019 int i;
2020 FILE *f;
2021 f = fopen("/tmp/op.log", "w");
2022 for(i = INDEX_op_end; i < NB_OPS; i++) {
2023 fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name, tcg_table_op_count[i]);
2025 fclose(f);
2027 #endif
2030 static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
2031 long search_pc)
2033 TCGOpcode opc;
2034 int op_index;
2035 const TCGOpDef *def;
2036 unsigned int dead_args;
2037 const TCGArg *args;
2039 #ifdef DEBUG_DISAS
2040 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
2041 qemu_log("OP:\n");
2042 tcg_dump_ops(s, logfile);
2043 qemu_log("\n");
2045 #endif
2047 #ifdef USE_TCG_OPTIMIZATIONS
2048 gen_opparam_ptr =
2049 tcg_optimize(s, gen_opc_ptr, gen_opparam_buf, tcg_op_defs);
2050 #endif
2052 #ifdef CONFIG_PROFILER
2053 s->la_time -= profile_getclock();
2054 #endif
2055 tcg_liveness_analysis(s);
2056 #ifdef CONFIG_PROFILER
2057 s->la_time += profile_getclock();
2058 #endif
2060 #ifdef DEBUG_DISAS
2061 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_OPT))) {
2062 qemu_log("OP after liveness analysis:\n");
2063 tcg_dump_ops(s, logfile);
2064 qemu_log("\n");
2066 #endif
2068 tcg_reg_alloc_start(s);
2070 s->code_buf = gen_code_buf;
2071 s->code_ptr = gen_code_buf;
2073 args = gen_opparam_buf;
2074 op_index = 0;
2076 for(;;) {
2077 opc = gen_opc_buf[op_index];
2078 #ifdef CONFIG_PROFILER
2079 tcg_table_op_count[opc]++;
2080 #endif
2081 def = &tcg_op_defs[opc];
2082 #if 0
2083 printf("%s: %d %d %d\n", def->name,
2084 def->nb_oargs, def->nb_iargs, def->nb_cargs);
2085 // dump_regs(s);
2086 #endif
2087 switch(opc) {
2088 case INDEX_op_mov_i32:
2089 #if TCG_TARGET_REG_BITS == 64
2090 case INDEX_op_mov_i64:
2091 #endif
2092 dead_args = s->op_dead_args[op_index];
2093 tcg_reg_alloc_mov(s, def, args, dead_args);
2094 break;
2095 case INDEX_op_movi_i32:
2096 #if TCG_TARGET_REG_BITS == 64
2097 case INDEX_op_movi_i64:
2098 #endif
2099 tcg_reg_alloc_movi(s, args);
2100 break;
2101 case INDEX_op_debug_insn_start:
2102 /* debug instruction */
2103 break;
2104 case INDEX_op_nop:
2105 case INDEX_op_nop1:
2106 case INDEX_op_nop2:
2107 case INDEX_op_nop3:
2108 break;
2109 case INDEX_op_nopn:
2110 args += args[0];
2111 goto next;
2112 case INDEX_op_discard:
2114 TCGTemp *ts;
2115 ts = &s->temps[args[0]];
2116 /* mark the temporary as dead */
2117 if (!ts->fixed_reg) {
2118 if (ts->val_type == TEMP_VAL_REG)
2119 s->reg_to_temp[ts->reg] = -1;
2120 ts->val_type = TEMP_VAL_DEAD;
2123 break;
2124 case INDEX_op_set_label:
2125 tcg_reg_alloc_bb_end(s, s->reserved_regs);
2126 tcg_out_label(s, args[0], s->code_ptr);
2127 break;
2128 case INDEX_op_call:
2129 dead_args = s->op_dead_args[op_index];
2130 args += tcg_reg_alloc_call(s, def, opc, args, dead_args);
2131 goto next;
2132 case INDEX_op_end:
2133 goto the_end;
2134 default:
2135 /* Sanity check that we've not introduced any unhandled opcodes. */
2136 if (def->flags & TCG_OPF_NOT_PRESENT) {
2137 tcg_abort();
2139 /* Note: in order to speed up the code, it would be much
2140 faster to have specialized register allocator functions for
2141 some common argument patterns */
2142 dead_args = s->op_dead_args[op_index];
2143 tcg_reg_alloc_op(s, def, opc, args, dead_args);
2144 break;
2146 args += def->nb_args;
2147 next:
2148 if (search_pc >= 0 && search_pc < s->code_ptr - gen_code_buf) {
2149 return op_index;
2151 op_index++;
2152 #ifndef NDEBUG
2153 check_regs(s);
2154 #endif
2156 the_end:
2157 return -1;
2160 int tcg_gen_code(TCGContext *s, uint8_t *gen_code_buf)
2162 #ifdef CONFIG_PROFILER
2164 int n;
2165 n = (gen_opc_ptr - gen_opc_buf);
2166 s->op_count += n;
2167 if (n > s->op_count_max)
2168 s->op_count_max = n;
2170 s->temp_count += s->nb_temps;
2171 if (s->nb_temps > s->temp_count_max)
2172 s->temp_count_max = s->nb_temps;
2174 #endif
2176 tcg_gen_code_common(s, gen_code_buf, -1);
2178 /* flush instruction cache */
2179 flush_icache_range((tcg_target_ulong)gen_code_buf,
2180 (tcg_target_ulong)s->code_ptr);
2182 return s->code_ptr - gen_code_buf;
2185 /* Return the index of the micro operation such as the pc after is <
2186 offset bytes from the start of the TB. The contents of gen_code_buf must
2187 not be changed, though writing the same values is ok.
2188 Return -1 if not found. */
2189 int tcg_gen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, long offset)
2191 return tcg_gen_code_common(s, gen_code_buf, offset);
2194 #ifdef CONFIG_PROFILER
2195 void tcg_dump_info(FILE *f, fprintf_function cpu_fprintf)
2197 TCGContext *s = &tcg_ctx;
2198 int64_t tot;
2200 tot = s->interm_time + s->code_time;
2201 cpu_fprintf(f, "JIT cycles %" PRId64 " (%0.3f s at 2.4 GHz)\n",
2202 tot, tot / 2.4e9);
2203 cpu_fprintf(f, "translated TBs %" PRId64 " (aborted=%" PRId64 " %0.1f%%)\n",
2204 s->tb_count,
2205 s->tb_count1 - s->tb_count,
2206 s->tb_count1 ? (double)(s->tb_count1 - s->tb_count) / s->tb_count1 * 100.0 : 0);
2207 cpu_fprintf(f, "avg ops/TB %0.1f max=%d\n",
2208 s->tb_count ? (double)s->op_count / s->tb_count : 0, s->op_count_max);
2209 cpu_fprintf(f, "deleted ops/TB %0.2f\n",
2210 s->tb_count ?
2211 (double)s->del_op_count / s->tb_count : 0);
2212 cpu_fprintf(f, "avg temps/TB %0.2f max=%d\n",
2213 s->tb_count ?
2214 (double)s->temp_count / s->tb_count : 0,
2215 s->temp_count_max);
2217 cpu_fprintf(f, "cycles/op %0.1f\n",
2218 s->op_count ? (double)tot / s->op_count : 0);
2219 cpu_fprintf(f, "cycles/in byte %0.1f\n",
2220 s->code_in_len ? (double)tot / s->code_in_len : 0);
2221 cpu_fprintf(f, "cycles/out byte %0.1f\n",
2222 s->code_out_len ? (double)tot / s->code_out_len : 0);
2223 if (tot == 0)
2224 tot = 1;
2225 cpu_fprintf(f, " gen_interm time %0.1f%%\n",
2226 (double)s->interm_time / tot * 100.0);
2227 cpu_fprintf(f, " gen_code time %0.1f%%\n",
2228 (double)s->code_time / tot * 100.0);
2229 cpu_fprintf(f, "liveness/code time %0.1f%%\n",
2230 (double)s->la_time / (s->code_time ? s->code_time : 1) * 100.0);
2231 cpu_fprintf(f, "cpu_restore count %" PRId64 "\n",
2232 s->restore_count);
2233 cpu_fprintf(f, " avg cycles %0.1f\n",
2234 s->restore_count ? (double)s->restore_time / s->restore_count : 0);
2236 dump_op_count();
2238 #else
2239 void tcg_dump_info(FILE *f, fprintf_function cpu_fprintf)
2241 cpu_fprintf(f, "[TCG profiler not compiled]\n");
2243 #endif