softfloat: fix for C99
[qemu/wangdongxu.git] / tcg / tcg.c
blobad2e983c2baef31a94206975fcc36abdfc3c29fb
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 p->next = s->pool_first_large;
177 s->pool_first_large = p;
178 return p->data;
179 } else {
180 p = s->pool_current;
181 if (!p) {
182 p = s->pool_first;
183 if (!p)
184 goto new_pool;
185 } else {
186 if (!p->next) {
187 new_pool:
188 pool_size = TCG_POOL_CHUNK_SIZE;
189 p = g_malloc(sizeof(TCGPool) + pool_size);
190 p->size = pool_size;
191 p->next = NULL;
192 if (s->pool_current)
193 s->pool_current->next = p;
194 else
195 s->pool_first = p;
196 } else {
197 p = p->next;
201 s->pool_current = p;
202 s->pool_cur = p->data + size;
203 s->pool_end = p->data + p->size;
204 return p->data;
207 void tcg_pool_reset(TCGContext *s)
209 TCGPool *p, *t;
210 for (p = s->pool_first_large; p; p = t) {
211 t = p->next;
212 g_free(p);
214 s->pool_first_large = NULL;
215 s->pool_cur = s->pool_end = NULL;
216 s->pool_current = NULL;
219 void tcg_context_init(TCGContext *s)
221 int op, total_args, n;
222 TCGOpDef *def;
223 TCGArgConstraint *args_ct;
224 int *sorted_args;
226 memset(s, 0, sizeof(*s));
227 s->temps = s->static_temps;
228 s->nb_globals = 0;
230 /* Count total number of arguments and allocate the corresponding
231 space */
232 total_args = 0;
233 for(op = 0; op < NB_OPS; op++) {
234 def = &tcg_op_defs[op];
235 n = def->nb_iargs + def->nb_oargs;
236 total_args += n;
239 args_ct = g_malloc(sizeof(TCGArgConstraint) * total_args);
240 sorted_args = g_malloc(sizeof(int) * total_args);
242 for(op = 0; op < NB_OPS; op++) {
243 def = &tcg_op_defs[op];
244 def->args_ct = args_ct;
245 def->sorted_args = sorted_args;
246 n = def->nb_iargs + def->nb_oargs;
247 sorted_args += n;
248 args_ct += n;
251 tcg_target_init(s);
254 void tcg_prologue_init(TCGContext *s)
256 /* init global prologue and epilogue */
257 s->code_buf = code_gen_prologue;
258 s->code_ptr = s->code_buf;
259 tcg_target_qemu_prologue(s);
260 flush_icache_range((tcg_target_ulong)s->code_buf,
261 (tcg_target_ulong)s->code_ptr);
264 void tcg_set_frame(TCGContext *s, int reg,
265 tcg_target_long start, tcg_target_long size)
267 s->frame_start = start;
268 s->frame_end = start + size;
269 s->frame_reg = reg;
272 void tcg_func_start(TCGContext *s)
274 int i;
275 tcg_pool_reset(s);
276 s->nb_temps = s->nb_globals;
277 for(i = 0; i < (TCG_TYPE_COUNT * 2); i++)
278 s->first_free_temp[i] = -1;
279 s->labels = tcg_malloc(sizeof(TCGLabel) * TCG_MAX_LABELS);
280 s->nb_labels = 0;
281 s->current_frame_offset = s->frame_start;
283 gen_opc_ptr = gen_opc_buf;
284 gen_opparam_ptr = gen_opparam_buf;
287 static inline void tcg_temp_alloc(TCGContext *s, int n)
289 if (n > TCG_MAX_TEMPS)
290 tcg_abort();
293 static inline int tcg_global_reg_new_internal(TCGType type, int reg,
294 const char *name)
296 TCGContext *s = &tcg_ctx;
297 TCGTemp *ts;
298 int idx;
300 #if TCG_TARGET_REG_BITS == 32
301 if (type != TCG_TYPE_I32)
302 tcg_abort();
303 #endif
304 if (tcg_regset_test_reg(s->reserved_regs, reg))
305 tcg_abort();
306 idx = s->nb_globals;
307 tcg_temp_alloc(s, s->nb_globals + 1);
308 ts = &s->temps[s->nb_globals];
309 ts->base_type = type;
310 ts->type = type;
311 ts->fixed_reg = 1;
312 ts->reg = reg;
313 ts->name = name;
314 s->nb_globals++;
315 tcg_regset_set_reg(s->reserved_regs, reg);
316 return idx;
319 TCGv_i32 tcg_global_reg_new_i32(int reg, const char *name)
321 int idx;
323 idx = tcg_global_reg_new_internal(TCG_TYPE_I32, reg, name);
324 return MAKE_TCGV_I32(idx);
327 TCGv_i64 tcg_global_reg_new_i64(int reg, const char *name)
329 int idx;
331 idx = tcg_global_reg_new_internal(TCG_TYPE_I64, reg, name);
332 return MAKE_TCGV_I64(idx);
335 static inline int tcg_global_mem_new_internal(TCGType type, int reg,
336 tcg_target_long offset,
337 const char *name)
339 TCGContext *s = &tcg_ctx;
340 TCGTemp *ts;
341 int idx;
343 idx = s->nb_globals;
344 #if TCG_TARGET_REG_BITS == 32
345 if (type == TCG_TYPE_I64) {
346 char buf[64];
347 tcg_temp_alloc(s, s->nb_globals + 2);
348 ts = &s->temps[s->nb_globals];
349 ts->base_type = type;
350 ts->type = TCG_TYPE_I32;
351 ts->fixed_reg = 0;
352 ts->mem_allocated = 1;
353 ts->mem_reg = reg;
354 #ifdef TCG_TARGET_WORDS_BIGENDIAN
355 ts->mem_offset = offset + 4;
356 #else
357 ts->mem_offset = offset;
358 #endif
359 pstrcpy(buf, sizeof(buf), name);
360 pstrcat(buf, sizeof(buf), "_0");
361 ts->name = strdup(buf);
362 ts++;
364 ts->base_type = type;
365 ts->type = TCG_TYPE_I32;
366 ts->fixed_reg = 0;
367 ts->mem_allocated = 1;
368 ts->mem_reg = reg;
369 #ifdef TCG_TARGET_WORDS_BIGENDIAN
370 ts->mem_offset = offset;
371 #else
372 ts->mem_offset = offset + 4;
373 #endif
374 pstrcpy(buf, sizeof(buf), name);
375 pstrcat(buf, sizeof(buf), "_1");
376 ts->name = strdup(buf);
378 s->nb_globals += 2;
379 } else
380 #endif
382 tcg_temp_alloc(s, s->nb_globals + 1);
383 ts = &s->temps[s->nb_globals];
384 ts->base_type = type;
385 ts->type = type;
386 ts->fixed_reg = 0;
387 ts->mem_allocated = 1;
388 ts->mem_reg = reg;
389 ts->mem_offset = offset;
390 ts->name = name;
391 s->nb_globals++;
393 return idx;
396 TCGv_i32 tcg_global_mem_new_i32(int reg, tcg_target_long offset,
397 const char *name)
399 int idx;
401 idx = tcg_global_mem_new_internal(TCG_TYPE_I32, reg, offset, name);
402 return MAKE_TCGV_I32(idx);
405 TCGv_i64 tcg_global_mem_new_i64(int reg, tcg_target_long offset,
406 const char *name)
408 int idx;
410 idx = tcg_global_mem_new_internal(TCG_TYPE_I64, reg, offset, name);
411 return MAKE_TCGV_I64(idx);
414 static inline int tcg_temp_new_internal(TCGType type, int temp_local)
416 TCGContext *s = &tcg_ctx;
417 TCGTemp *ts;
418 int idx, k;
420 k = type;
421 if (temp_local)
422 k += TCG_TYPE_COUNT;
423 idx = s->first_free_temp[k];
424 if (idx != -1) {
425 /* There is already an available temp with the
426 right type */
427 ts = &s->temps[idx];
428 s->first_free_temp[k] = ts->next_free_temp;
429 ts->temp_allocated = 1;
430 assert(ts->temp_local == temp_local);
431 } else {
432 idx = s->nb_temps;
433 #if TCG_TARGET_REG_BITS == 32
434 if (type == TCG_TYPE_I64) {
435 tcg_temp_alloc(s, s->nb_temps + 2);
436 ts = &s->temps[s->nb_temps];
437 ts->base_type = type;
438 ts->type = TCG_TYPE_I32;
439 ts->temp_allocated = 1;
440 ts->temp_local = temp_local;
441 ts->name = NULL;
442 ts++;
443 ts->base_type = TCG_TYPE_I32;
444 ts->type = TCG_TYPE_I32;
445 ts->temp_allocated = 1;
446 ts->temp_local = temp_local;
447 ts->name = NULL;
448 s->nb_temps += 2;
449 } else
450 #endif
452 tcg_temp_alloc(s, s->nb_temps + 1);
453 ts = &s->temps[s->nb_temps];
454 ts->base_type = type;
455 ts->type = type;
456 ts->temp_allocated = 1;
457 ts->temp_local = temp_local;
458 ts->name = NULL;
459 s->nb_temps++;
463 #if defined(CONFIG_DEBUG_TCG)
464 s->temps_in_use++;
465 #endif
466 return idx;
469 TCGv_i32 tcg_temp_new_internal_i32(int temp_local)
471 int idx;
473 idx = tcg_temp_new_internal(TCG_TYPE_I32, temp_local);
474 return MAKE_TCGV_I32(idx);
477 TCGv_i64 tcg_temp_new_internal_i64(int temp_local)
479 int idx;
481 idx = tcg_temp_new_internal(TCG_TYPE_I64, temp_local);
482 return MAKE_TCGV_I64(idx);
485 static inline void tcg_temp_free_internal(int idx)
487 TCGContext *s = &tcg_ctx;
488 TCGTemp *ts;
489 int k;
491 #if defined(CONFIG_DEBUG_TCG)
492 s->temps_in_use--;
493 if (s->temps_in_use < 0) {
494 fprintf(stderr, "More temporaries freed than allocated!\n");
496 #endif
498 assert(idx >= s->nb_globals && idx < s->nb_temps);
499 ts = &s->temps[idx];
500 assert(ts->temp_allocated != 0);
501 ts->temp_allocated = 0;
502 k = ts->base_type;
503 if (ts->temp_local)
504 k += TCG_TYPE_COUNT;
505 ts->next_free_temp = s->first_free_temp[k];
506 s->first_free_temp[k] = idx;
509 void tcg_temp_free_i32(TCGv_i32 arg)
511 tcg_temp_free_internal(GET_TCGV_I32(arg));
514 void tcg_temp_free_i64(TCGv_i64 arg)
516 tcg_temp_free_internal(GET_TCGV_I64(arg));
519 TCGv_i32 tcg_const_i32(int32_t val)
521 TCGv_i32 t0;
522 t0 = tcg_temp_new_i32();
523 tcg_gen_movi_i32(t0, val);
524 return t0;
527 TCGv_i64 tcg_const_i64(int64_t val)
529 TCGv_i64 t0;
530 t0 = tcg_temp_new_i64();
531 tcg_gen_movi_i64(t0, val);
532 return t0;
535 TCGv_i32 tcg_const_local_i32(int32_t val)
537 TCGv_i32 t0;
538 t0 = tcg_temp_local_new_i32();
539 tcg_gen_movi_i32(t0, val);
540 return t0;
543 TCGv_i64 tcg_const_local_i64(int64_t val)
545 TCGv_i64 t0;
546 t0 = tcg_temp_local_new_i64();
547 tcg_gen_movi_i64(t0, val);
548 return t0;
551 #if defined(CONFIG_DEBUG_TCG)
552 void tcg_clear_temp_count(void)
554 TCGContext *s = &tcg_ctx;
555 s->temps_in_use = 0;
558 int tcg_check_temp_count(void)
560 TCGContext *s = &tcg_ctx;
561 if (s->temps_in_use) {
562 /* Clear the count so that we don't give another
563 * warning immediately next time around.
565 s->temps_in_use = 0;
566 return 1;
568 return 0;
570 #endif
572 void tcg_register_helper(void *func, const char *name)
574 TCGContext *s = &tcg_ctx;
575 int n;
576 if ((s->nb_helpers + 1) > s->allocated_helpers) {
577 n = s->allocated_helpers;
578 if (n == 0) {
579 n = 4;
580 } else {
581 n *= 2;
583 s->helpers = realloc(s->helpers, n * sizeof(TCGHelperInfo));
584 s->allocated_helpers = n;
586 s->helpers[s->nb_helpers].func = (tcg_target_ulong)func;
587 s->helpers[s->nb_helpers].name = name;
588 s->nb_helpers++;
591 /* Note: we convert the 64 bit args to 32 bit and do some alignment
592 and endian swap. Maybe it would be better to do the alignment
593 and endian swap in tcg_reg_alloc_call(). */
594 void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags,
595 int sizemask, TCGArg ret, int nargs, TCGArg *args)
597 #if defined(TCG_TARGET_I386) && TCG_TARGET_REG_BITS < 64
598 int call_type;
599 #endif
600 int i;
601 int real_args;
602 int nb_rets;
603 TCGArg *nparam;
605 #if defined(TCG_TARGET_EXTEND_ARGS) && TCG_TARGET_REG_BITS == 64
606 for (i = 0; i < nargs; ++i) {
607 int is_64bit = sizemask & (1 << (i+1)*2);
608 int is_signed = sizemask & (2 << (i+1)*2);
609 if (!is_64bit) {
610 TCGv_i64 temp = tcg_temp_new_i64();
611 TCGv_i64 orig = MAKE_TCGV_I64(args[i]);
612 if (is_signed) {
613 tcg_gen_ext32s_i64(temp, orig);
614 } else {
615 tcg_gen_ext32u_i64(temp, orig);
617 args[i] = GET_TCGV_I64(temp);
620 #endif /* TCG_TARGET_EXTEND_ARGS */
622 *gen_opc_ptr++ = INDEX_op_call;
623 nparam = gen_opparam_ptr++;
624 #if defined(TCG_TARGET_I386) && TCG_TARGET_REG_BITS < 64
625 call_type = (flags & TCG_CALL_TYPE_MASK);
626 #endif
627 if (ret != TCG_CALL_DUMMY_ARG) {
628 #if TCG_TARGET_REG_BITS < 64
629 if (sizemask & 1) {
630 #ifdef TCG_TARGET_WORDS_BIGENDIAN
631 *gen_opparam_ptr++ = ret + 1;
632 *gen_opparam_ptr++ = ret;
633 #else
634 *gen_opparam_ptr++ = ret;
635 *gen_opparam_ptr++ = ret + 1;
636 #endif
637 nb_rets = 2;
638 } else
639 #endif
641 *gen_opparam_ptr++ = ret;
642 nb_rets = 1;
644 } else {
645 nb_rets = 0;
647 real_args = 0;
648 for (i = 0; i < nargs; i++) {
649 #if TCG_TARGET_REG_BITS < 64
650 int is_64bit = sizemask & (1 << (i+1)*2);
651 if (is_64bit) {
652 #ifdef TCG_TARGET_I386
653 /* REGPARM case: if the third parameter is 64 bit, it is
654 allocated on the stack */
655 if (i == 2 && call_type == TCG_CALL_TYPE_REGPARM) {
656 call_type = TCG_CALL_TYPE_REGPARM_2;
657 flags = (flags & ~TCG_CALL_TYPE_MASK) | call_type;
659 #endif
660 #ifdef TCG_TARGET_CALL_ALIGN_ARGS
661 /* some targets want aligned 64 bit args */
662 if (real_args & 1) {
663 *gen_opparam_ptr++ = TCG_CALL_DUMMY_ARG;
664 real_args++;
666 #endif
667 /* If stack grows up, then we will be placing successive
668 arguments at lower addresses, which means we need to
669 reverse the order compared to how we would normally
670 treat either big or little-endian. For those arguments
671 that will wind up in registers, this still works for
672 HPPA (the only current STACK_GROWSUP target) since the
673 argument registers are *also* allocated in decreasing
674 order. If another such target is added, this logic may
675 have to get more complicated to differentiate between
676 stack arguments and register arguments. */
677 #if defined(TCG_TARGET_WORDS_BIGENDIAN) != defined(TCG_TARGET_STACK_GROWSUP)
678 *gen_opparam_ptr++ = args[i] + 1;
679 *gen_opparam_ptr++ = args[i];
680 #else
681 *gen_opparam_ptr++ = args[i];
682 *gen_opparam_ptr++ = args[i] + 1;
683 #endif
684 real_args += 2;
685 continue;
687 #endif /* TCG_TARGET_REG_BITS < 64 */
689 *gen_opparam_ptr++ = args[i];
690 real_args++;
692 *gen_opparam_ptr++ = GET_TCGV_PTR(func);
694 *gen_opparam_ptr++ = flags;
696 *nparam = (nb_rets << 16) | (real_args + 1);
698 /* total parameters, needed to go backward in the instruction stream */
699 *gen_opparam_ptr++ = 1 + nb_rets + real_args + 3;
701 #if defined(TCG_TARGET_EXTEND_ARGS) && TCG_TARGET_REG_BITS == 64
702 for (i = 0; i < nargs; ++i) {
703 int is_64bit = sizemask & (1 << (i+1)*2);
704 if (!is_64bit) {
705 TCGv_i64 temp = MAKE_TCGV_I64(args[i]);
706 tcg_temp_free_i64(temp);
709 #endif /* TCG_TARGET_EXTEND_ARGS */
712 #if TCG_TARGET_REG_BITS == 32
713 void tcg_gen_shifti_i64(TCGv_i64 ret, TCGv_i64 arg1,
714 int c, int right, int arith)
716 if (c == 0) {
717 tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg1));
718 tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
719 } else if (c >= 32) {
720 c -= 32;
721 if (right) {
722 if (arith) {
723 tcg_gen_sari_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
724 tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 31);
725 } else {
726 tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
727 tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
729 } else {
730 tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_LOW(arg1), c);
731 tcg_gen_movi_i32(TCGV_LOW(ret), 0);
733 } else {
734 TCGv_i32 t0, t1;
736 t0 = tcg_temp_new_i32();
737 t1 = tcg_temp_new_i32();
738 if (right) {
739 tcg_gen_shli_i32(t0, TCGV_HIGH(arg1), 32 - c);
740 if (arith)
741 tcg_gen_sari_i32(t1, TCGV_HIGH(arg1), c);
742 else
743 tcg_gen_shri_i32(t1, TCGV_HIGH(arg1), c);
744 tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_LOW(arg1), c);
745 tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(ret), t0);
746 tcg_gen_mov_i32(TCGV_HIGH(ret), t1);
747 } else {
748 tcg_gen_shri_i32(t0, TCGV_LOW(arg1), 32 - c);
749 /* Note: ret can be the same as arg1, so we use t1 */
750 tcg_gen_shli_i32(t1, TCGV_LOW(arg1), c);
751 tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c);
752 tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t0);
753 tcg_gen_mov_i32(TCGV_LOW(ret), t1);
755 tcg_temp_free_i32(t0);
756 tcg_temp_free_i32(t1);
759 #endif
762 static void tcg_reg_alloc_start(TCGContext *s)
764 int i;
765 TCGTemp *ts;
766 for(i = 0; i < s->nb_globals; i++) {
767 ts = &s->temps[i];
768 if (ts->fixed_reg) {
769 ts->val_type = TEMP_VAL_REG;
770 } else {
771 ts->val_type = TEMP_VAL_MEM;
774 for(i = s->nb_globals; i < s->nb_temps; i++) {
775 ts = &s->temps[i];
776 ts->val_type = TEMP_VAL_DEAD;
777 ts->mem_allocated = 0;
778 ts->fixed_reg = 0;
780 for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
781 s->reg_to_temp[i] = -1;
785 static char *tcg_get_arg_str_idx(TCGContext *s, char *buf, int buf_size,
786 int idx)
788 TCGTemp *ts;
790 assert(idx >= 0 && idx < s->nb_temps);
791 ts = &s->temps[idx];
792 assert(ts);
793 if (idx < s->nb_globals) {
794 pstrcpy(buf, buf_size, ts->name);
795 } else {
796 if (ts->temp_local)
797 snprintf(buf, buf_size, "loc%d", idx - s->nb_globals);
798 else
799 snprintf(buf, buf_size, "tmp%d", idx - s->nb_globals);
801 return buf;
804 char *tcg_get_arg_str_i32(TCGContext *s, char *buf, int buf_size, TCGv_i32 arg)
806 return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I32(arg));
809 char *tcg_get_arg_str_i64(TCGContext *s, char *buf, int buf_size, TCGv_i64 arg)
811 return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I64(arg));
814 static int helper_cmp(const void *p1, const void *p2)
816 const TCGHelperInfo *th1 = p1;
817 const TCGHelperInfo *th2 = p2;
818 if (th1->func < th2->func)
819 return -1;
820 else if (th1->func == th2->func)
821 return 0;
822 else
823 return 1;
826 /* find helper definition (Note: A hash table would be better) */
827 static TCGHelperInfo *tcg_find_helper(TCGContext *s, tcg_target_ulong val)
829 int m, m_min, m_max;
830 TCGHelperInfo *th;
831 tcg_target_ulong v;
833 if (unlikely(!s->helpers_sorted)) {
834 qsort(s->helpers, s->nb_helpers, sizeof(TCGHelperInfo),
835 helper_cmp);
836 s->helpers_sorted = 1;
839 /* binary search */
840 m_min = 0;
841 m_max = s->nb_helpers - 1;
842 while (m_min <= m_max) {
843 m = (m_min + m_max) >> 1;
844 th = &s->helpers[m];
845 v = th->func;
846 if (v == val)
847 return th;
848 else if (val < v) {
849 m_max = m - 1;
850 } else {
851 m_min = m + 1;
854 return NULL;
857 static const char * const cond_name[] =
859 [TCG_COND_EQ] = "eq",
860 [TCG_COND_NE] = "ne",
861 [TCG_COND_LT] = "lt",
862 [TCG_COND_GE] = "ge",
863 [TCG_COND_LE] = "le",
864 [TCG_COND_GT] = "gt",
865 [TCG_COND_LTU] = "ltu",
866 [TCG_COND_GEU] = "geu",
867 [TCG_COND_LEU] = "leu",
868 [TCG_COND_GTU] = "gtu"
871 void tcg_dump_ops(TCGContext *s, FILE *outfile)
873 const uint16_t *opc_ptr;
874 const TCGArg *args;
875 TCGArg arg;
876 TCGOpcode c;
877 int i, k, nb_oargs, nb_iargs, nb_cargs, first_insn;
878 const TCGOpDef *def;
879 char buf[128];
881 first_insn = 1;
882 opc_ptr = gen_opc_buf;
883 args = gen_opparam_buf;
884 while (opc_ptr < gen_opc_ptr) {
885 c = *opc_ptr++;
886 def = &tcg_op_defs[c];
887 if (c == INDEX_op_debug_insn_start) {
888 uint64_t pc;
889 #if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
890 pc = ((uint64_t)args[1] << 32) | args[0];
891 #else
892 pc = args[0];
893 #endif
894 if (!first_insn)
895 fprintf(outfile, "\n");
896 fprintf(outfile, " ---- 0x%" PRIx64, pc);
897 first_insn = 0;
898 nb_oargs = def->nb_oargs;
899 nb_iargs = def->nb_iargs;
900 nb_cargs = def->nb_cargs;
901 } else if (c == INDEX_op_call) {
902 TCGArg arg;
904 /* variable number of arguments */
905 arg = *args++;
906 nb_oargs = arg >> 16;
907 nb_iargs = arg & 0xffff;
908 nb_cargs = def->nb_cargs;
910 fprintf(outfile, " %s ", def->name);
912 /* function name */
913 fprintf(outfile, "%s",
914 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + nb_iargs - 1]));
915 /* flags */
916 fprintf(outfile, ",$0x%" TCG_PRIlx,
917 args[nb_oargs + nb_iargs]);
918 /* nb out args */
919 fprintf(outfile, ",$%d", nb_oargs);
920 for(i = 0; i < nb_oargs; i++) {
921 fprintf(outfile, ",");
922 fprintf(outfile, "%s",
923 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[i]));
925 for(i = 0; i < (nb_iargs - 1); i++) {
926 fprintf(outfile, ",");
927 if (args[nb_oargs + i] == TCG_CALL_DUMMY_ARG) {
928 fprintf(outfile, "<dummy>");
929 } else {
930 fprintf(outfile, "%s",
931 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + i]));
934 } else if (c == INDEX_op_movi_i32
935 #if TCG_TARGET_REG_BITS == 64
936 || c == INDEX_op_movi_i64
937 #endif
939 tcg_target_ulong val;
940 TCGHelperInfo *th;
942 nb_oargs = def->nb_oargs;
943 nb_iargs = def->nb_iargs;
944 nb_cargs = def->nb_cargs;
945 fprintf(outfile, " %s %s,$", def->name,
946 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[0]));
947 val = args[1];
948 th = tcg_find_helper(s, val);
949 if (th) {
950 fprintf(outfile, "%s", th->name);
951 } else {
952 if (c == INDEX_op_movi_i32)
953 fprintf(outfile, "0x%x", (uint32_t)val);
954 else
955 fprintf(outfile, "0x%" PRIx64 , (uint64_t)val);
957 } else {
958 fprintf(outfile, " %s ", def->name);
959 if (c == INDEX_op_nopn) {
960 /* variable number of arguments */
961 nb_cargs = *args;
962 nb_oargs = 0;
963 nb_iargs = 0;
964 } else {
965 nb_oargs = def->nb_oargs;
966 nb_iargs = def->nb_iargs;
967 nb_cargs = def->nb_cargs;
970 k = 0;
971 for(i = 0; i < nb_oargs; i++) {
972 if (k != 0)
973 fprintf(outfile, ",");
974 fprintf(outfile, "%s",
975 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
977 for(i = 0; i < nb_iargs; i++) {
978 if (k != 0)
979 fprintf(outfile, ",");
980 fprintf(outfile, "%s",
981 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
983 switch (c) {
984 case INDEX_op_brcond_i32:
985 #if TCG_TARGET_REG_BITS == 32
986 case INDEX_op_brcond2_i32:
987 #elif TCG_TARGET_REG_BITS == 64
988 case INDEX_op_brcond_i64:
989 #endif
990 case INDEX_op_setcond_i32:
991 #if TCG_TARGET_REG_BITS == 32
992 case INDEX_op_setcond2_i32:
993 #elif TCG_TARGET_REG_BITS == 64
994 case INDEX_op_setcond_i64:
995 #endif
996 if (args[k] < ARRAY_SIZE(cond_name) && cond_name[args[k]])
997 fprintf(outfile, ",%s", cond_name[args[k++]]);
998 else
999 fprintf(outfile, ",$0x%" TCG_PRIlx, args[k++]);
1000 i = 1;
1001 break;
1002 default:
1003 i = 0;
1004 break;
1006 for(; i < nb_cargs; i++) {
1007 if (k != 0)
1008 fprintf(outfile, ",");
1009 arg = args[k++];
1010 fprintf(outfile, "$0x%" TCG_PRIlx, arg);
1013 fprintf(outfile, "\n");
1014 args += nb_iargs + nb_oargs + nb_cargs;
1018 /* we give more priority to constraints with less registers */
1019 static int get_constraint_priority(const TCGOpDef *def, int k)
1021 const TCGArgConstraint *arg_ct;
1023 int i, n;
1024 arg_ct = &def->args_ct[k];
1025 if (arg_ct->ct & TCG_CT_ALIAS) {
1026 /* an alias is equivalent to a single register */
1027 n = 1;
1028 } else {
1029 if (!(arg_ct->ct & TCG_CT_REG))
1030 return 0;
1031 n = 0;
1032 for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
1033 if (tcg_regset_test_reg(arg_ct->u.regs, i))
1034 n++;
1037 return TCG_TARGET_NB_REGS - n + 1;
1040 /* sort from highest priority to lowest */
1041 static void sort_constraints(TCGOpDef *def, int start, int n)
1043 int i, j, p1, p2, tmp;
1045 for(i = 0; i < n; i++)
1046 def->sorted_args[start + i] = start + i;
1047 if (n <= 1)
1048 return;
1049 for(i = 0; i < n - 1; i++) {
1050 for(j = i + 1; j < n; j++) {
1051 p1 = get_constraint_priority(def, def->sorted_args[start + i]);
1052 p2 = get_constraint_priority(def, def->sorted_args[start + j]);
1053 if (p1 < p2) {
1054 tmp = def->sorted_args[start + i];
1055 def->sorted_args[start + i] = def->sorted_args[start + j];
1056 def->sorted_args[start + j] = tmp;
1062 void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs)
1064 TCGOpcode op;
1065 TCGOpDef *def;
1066 const char *ct_str;
1067 int i, nb_args;
1069 for(;;) {
1070 if (tdefs->op == (TCGOpcode)-1)
1071 break;
1072 op = tdefs->op;
1073 assert((unsigned)op < NB_OPS);
1074 def = &tcg_op_defs[op];
1075 #if defined(CONFIG_DEBUG_TCG)
1076 /* Duplicate entry in op definitions? */
1077 assert(!def->used);
1078 def->used = 1;
1079 #endif
1080 nb_args = def->nb_iargs + def->nb_oargs;
1081 for(i = 0; i < nb_args; i++) {
1082 ct_str = tdefs->args_ct_str[i];
1083 /* Incomplete TCGTargetOpDef entry? */
1084 assert(ct_str != NULL);
1085 tcg_regset_clear(def->args_ct[i].u.regs);
1086 def->args_ct[i].ct = 0;
1087 if (ct_str[0] >= '0' && ct_str[0] <= '9') {
1088 int oarg;
1089 oarg = ct_str[0] - '0';
1090 assert(oarg < def->nb_oargs);
1091 assert(def->args_ct[oarg].ct & TCG_CT_REG);
1092 /* TCG_CT_ALIAS is for the output arguments. The input
1093 argument is tagged with TCG_CT_IALIAS. */
1094 def->args_ct[i] = def->args_ct[oarg];
1095 def->args_ct[oarg].ct = TCG_CT_ALIAS;
1096 def->args_ct[oarg].alias_index = i;
1097 def->args_ct[i].ct |= TCG_CT_IALIAS;
1098 def->args_ct[i].alias_index = oarg;
1099 } else {
1100 for(;;) {
1101 if (*ct_str == '\0')
1102 break;
1103 switch(*ct_str) {
1104 case 'i':
1105 def->args_ct[i].ct |= TCG_CT_CONST;
1106 ct_str++;
1107 break;
1108 default:
1109 if (target_parse_constraint(&def->args_ct[i], &ct_str) < 0) {
1110 fprintf(stderr, "Invalid constraint '%s' for arg %d of operation '%s'\n",
1111 ct_str, i, def->name);
1112 exit(1);
1119 /* TCGTargetOpDef entry with too much information? */
1120 assert(i == TCG_MAX_OP_ARGS || tdefs->args_ct_str[i] == NULL);
1122 /* sort the constraints (XXX: this is just an heuristic) */
1123 sort_constraints(def, 0, def->nb_oargs);
1124 sort_constraints(def, def->nb_oargs, def->nb_iargs);
1126 #if 0
1128 int i;
1130 printf("%s: sorted=", def->name);
1131 for(i = 0; i < def->nb_oargs + def->nb_iargs; i++)
1132 printf(" %d", def->sorted_args[i]);
1133 printf("\n");
1135 #endif
1136 tdefs++;
1139 #if defined(CONFIG_DEBUG_TCG)
1140 i = 0;
1141 for (op = 0; op < ARRAY_SIZE(tcg_op_defs); op++) {
1142 const TCGOpDef *def = &tcg_op_defs[op];
1143 if (op < INDEX_op_call
1144 || op == INDEX_op_debug_insn_start
1145 || (def->flags & TCG_OPF_NOT_PRESENT)) {
1146 /* Wrong entry in op definitions? */
1147 if (def->used) {
1148 fprintf(stderr, "Invalid op definition for %s\n", def->name);
1149 i = 1;
1151 } else {
1152 /* Missing entry in op definitions? */
1153 if (!def->used) {
1154 fprintf(stderr, "Missing op definition for %s\n", def->name);
1155 i = 1;
1159 if (i == 1) {
1160 tcg_abort();
1162 #endif
1165 #ifdef USE_LIVENESS_ANALYSIS
1167 /* set a nop for an operation using 'nb_args' */
1168 static inline void tcg_set_nop(TCGContext *s, uint16_t *opc_ptr,
1169 TCGArg *args, int nb_args)
1171 if (nb_args == 0) {
1172 *opc_ptr = INDEX_op_nop;
1173 } else {
1174 *opc_ptr = INDEX_op_nopn;
1175 args[0] = nb_args;
1176 args[nb_args - 1] = nb_args;
1180 /* liveness analysis: end of function: globals are live, temps are
1181 dead. */
1182 /* XXX: at this stage, not used as there would be little gains because
1183 most TBs end with a conditional jump. */
1184 static inline void tcg_la_func_end(TCGContext *s, uint8_t *dead_temps)
1186 memset(dead_temps, 0, s->nb_globals);
1187 memset(dead_temps + s->nb_globals, 1, s->nb_temps - s->nb_globals);
1190 /* liveness analysis: end of basic block: globals are live, temps are
1191 dead, local temps are live. */
1192 static inline void tcg_la_bb_end(TCGContext *s, uint8_t *dead_temps)
1194 int i;
1195 TCGTemp *ts;
1197 memset(dead_temps, 0, s->nb_globals);
1198 ts = &s->temps[s->nb_globals];
1199 for(i = s->nb_globals; i < s->nb_temps; i++) {
1200 if (ts->temp_local)
1201 dead_temps[i] = 0;
1202 else
1203 dead_temps[i] = 1;
1204 ts++;
1208 /* Liveness analysis : update the opc_dead_args array to tell if a
1209 given input arguments is dead. Instructions updating dead
1210 temporaries are removed. */
1211 static void tcg_liveness_analysis(TCGContext *s)
1213 int i, op_index, nb_args, nb_iargs, nb_oargs, arg, nb_ops;
1214 TCGOpcode op;
1215 TCGArg *args;
1216 const TCGOpDef *def;
1217 uint8_t *dead_temps;
1218 unsigned int dead_args;
1220 gen_opc_ptr++; /* skip end */
1222 nb_ops = gen_opc_ptr - gen_opc_buf;
1224 s->op_dead_args = tcg_malloc(nb_ops * sizeof(uint16_t));
1226 dead_temps = tcg_malloc(s->nb_temps);
1227 memset(dead_temps, 1, s->nb_temps);
1229 args = gen_opparam_ptr;
1230 op_index = nb_ops - 1;
1231 while (op_index >= 0) {
1232 op = gen_opc_buf[op_index];
1233 def = &tcg_op_defs[op];
1234 switch(op) {
1235 case INDEX_op_call:
1237 int call_flags;
1239 nb_args = args[-1];
1240 args -= nb_args;
1241 nb_iargs = args[0] & 0xffff;
1242 nb_oargs = args[0] >> 16;
1243 args++;
1244 call_flags = args[nb_oargs + nb_iargs];
1246 /* pure functions can be removed if their result is not
1247 used */
1248 if (call_flags & TCG_CALL_PURE) {
1249 for(i = 0; i < nb_oargs; i++) {
1250 arg = args[i];
1251 if (!dead_temps[arg])
1252 goto do_not_remove_call;
1254 tcg_set_nop(s, gen_opc_buf + op_index,
1255 args - 1, nb_args);
1256 } else {
1257 do_not_remove_call:
1259 /* output args are dead */
1260 dead_args = 0;
1261 for(i = 0; i < nb_oargs; i++) {
1262 arg = args[i];
1263 if (dead_temps[arg]) {
1264 dead_args |= (1 << i);
1266 dead_temps[arg] = 1;
1269 if (!(call_flags & TCG_CALL_CONST)) {
1270 /* globals are live (they may be used by the call) */
1271 memset(dead_temps, 0, s->nb_globals);
1274 /* input args are live */
1275 for(i = nb_oargs; i < nb_iargs + nb_oargs; i++) {
1276 arg = args[i];
1277 if (arg != TCG_CALL_DUMMY_ARG) {
1278 if (dead_temps[arg]) {
1279 dead_args |= (1 << i);
1281 dead_temps[arg] = 0;
1284 s->op_dead_args[op_index] = dead_args;
1286 args--;
1288 break;
1289 case INDEX_op_set_label:
1290 args--;
1291 /* mark end of basic block */
1292 tcg_la_bb_end(s, dead_temps);
1293 break;
1294 case INDEX_op_debug_insn_start:
1295 args -= def->nb_args;
1296 break;
1297 case INDEX_op_nopn:
1298 nb_args = args[-1];
1299 args -= nb_args;
1300 break;
1301 case INDEX_op_discard:
1302 args--;
1303 /* mark the temporary as dead */
1304 dead_temps[args[0]] = 1;
1305 break;
1306 case INDEX_op_end:
1307 break;
1308 /* XXX: optimize by hardcoding common cases (e.g. triadic ops) */
1309 default:
1310 args -= def->nb_args;
1311 nb_iargs = def->nb_iargs;
1312 nb_oargs = def->nb_oargs;
1314 /* Test if the operation can be removed because all
1315 its outputs are dead. We assume that nb_oargs == 0
1316 implies side effects */
1317 if (!(def->flags & TCG_OPF_SIDE_EFFECTS) && nb_oargs != 0) {
1318 for(i = 0; i < nb_oargs; i++) {
1319 arg = args[i];
1320 if (!dead_temps[arg])
1321 goto do_not_remove;
1323 tcg_set_nop(s, gen_opc_buf + op_index, args, def->nb_args);
1324 #ifdef CONFIG_PROFILER
1325 s->del_op_count++;
1326 #endif
1327 } else {
1328 do_not_remove:
1330 /* output args are dead */
1331 dead_args = 0;
1332 for(i = 0; i < nb_oargs; i++) {
1333 arg = args[i];
1334 if (dead_temps[arg]) {
1335 dead_args |= (1 << i);
1337 dead_temps[arg] = 1;
1340 /* if end of basic block, update */
1341 if (def->flags & TCG_OPF_BB_END) {
1342 tcg_la_bb_end(s, dead_temps);
1343 } else if (def->flags & TCG_OPF_CALL_CLOBBER) {
1344 /* globals are live */
1345 memset(dead_temps, 0, s->nb_globals);
1348 /* input args are live */
1349 for(i = nb_oargs; i < nb_oargs + nb_iargs; i++) {
1350 arg = args[i];
1351 if (dead_temps[arg]) {
1352 dead_args |= (1 << i);
1354 dead_temps[arg] = 0;
1356 s->op_dead_args[op_index] = dead_args;
1358 break;
1360 op_index--;
1363 if (args != gen_opparam_buf)
1364 tcg_abort();
1366 #else
1367 /* dummy liveness analysis */
1368 static void tcg_liveness_analysis(TCGContext *s)
1370 int nb_ops;
1371 nb_ops = gen_opc_ptr - gen_opc_buf;
1373 s->op_dead_args = tcg_malloc(nb_ops * sizeof(uint16_t));
1374 memset(s->op_dead_args, 0, nb_ops * sizeof(uint16_t));
1376 #endif
1378 #ifndef NDEBUG
1379 static void dump_regs(TCGContext *s)
1381 TCGTemp *ts;
1382 int i;
1383 char buf[64];
1385 for(i = 0; i < s->nb_temps; i++) {
1386 ts = &s->temps[i];
1387 printf(" %10s: ", tcg_get_arg_str_idx(s, buf, sizeof(buf), i));
1388 switch(ts->val_type) {
1389 case TEMP_VAL_REG:
1390 printf("%s", tcg_target_reg_names[ts->reg]);
1391 break;
1392 case TEMP_VAL_MEM:
1393 printf("%d(%s)", (int)ts->mem_offset, tcg_target_reg_names[ts->mem_reg]);
1394 break;
1395 case TEMP_VAL_CONST:
1396 printf("$0x%" TCG_PRIlx, ts->val);
1397 break;
1398 case TEMP_VAL_DEAD:
1399 printf("D");
1400 break;
1401 default:
1402 printf("???");
1403 break;
1405 printf("\n");
1408 for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
1409 if (s->reg_to_temp[i] >= 0) {
1410 printf("%s: %s\n",
1411 tcg_target_reg_names[i],
1412 tcg_get_arg_str_idx(s, buf, sizeof(buf), s->reg_to_temp[i]));
1417 static void check_regs(TCGContext *s)
1419 int reg, k;
1420 TCGTemp *ts;
1421 char buf[64];
1423 for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1424 k = s->reg_to_temp[reg];
1425 if (k >= 0) {
1426 ts = &s->temps[k];
1427 if (ts->val_type != TEMP_VAL_REG ||
1428 ts->reg != reg) {
1429 printf("Inconsistency for register %s:\n",
1430 tcg_target_reg_names[reg]);
1431 goto fail;
1435 for(k = 0; k < s->nb_temps; k++) {
1436 ts = &s->temps[k];
1437 if (ts->val_type == TEMP_VAL_REG &&
1438 !ts->fixed_reg &&
1439 s->reg_to_temp[ts->reg] != k) {
1440 printf("Inconsistency for temp %s:\n",
1441 tcg_get_arg_str_idx(s, buf, sizeof(buf), k));
1442 fail:
1443 printf("reg state:\n");
1444 dump_regs(s);
1445 tcg_abort();
1449 #endif
1451 static void temp_allocate_frame(TCGContext *s, int temp)
1453 TCGTemp *ts;
1454 ts = &s->temps[temp];
1455 #ifndef __sparc_v9__ /* Sparc64 stack is accessed with offset of 2047 */
1456 s->current_frame_offset = (s->current_frame_offset +
1457 (tcg_target_long)sizeof(tcg_target_long) - 1) &
1458 ~(sizeof(tcg_target_long) - 1);
1459 #endif
1460 if (s->current_frame_offset + (tcg_target_long)sizeof(tcg_target_long) >
1461 s->frame_end) {
1462 tcg_abort();
1464 ts->mem_offset = s->current_frame_offset;
1465 ts->mem_reg = s->frame_reg;
1466 ts->mem_allocated = 1;
1467 s->current_frame_offset += (tcg_target_long)sizeof(tcg_target_long);
1470 /* free register 'reg' by spilling the corresponding temporary if necessary */
1471 static void tcg_reg_free(TCGContext *s, int reg)
1473 TCGTemp *ts;
1474 int temp;
1476 temp = s->reg_to_temp[reg];
1477 if (temp != -1) {
1478 ts = &s->temps[temp];
1479 assert(ts->val_type == TEMP_VAL_REG);
1480 if (!ts->mem_coherent) {
1481 if (!ts->mem_allocated)
1482 temp_allocate_frame(s, temp);
1483 tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1485 ts->val_type = TEMP_VAL_MEM;
1486 s->reg_to_temp[reg] = -1;
1490 /* Allocate a register belonging to reg1 & ~reg2 */
1491 static int tcg_reg_alloc(TCGContext *s, TCGRegSet reg1, TCGRegSet reg2)
1493 int i, reg;
1494 TCGRegSet reg_ct;
1496 tcg_regset_andnot(reg_ct, reg1, reg2);
1498 /* first try free registers */
1499 for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1500 reg = tcg_target_reg_alloc_order[i];
1501 if (tcg_regset_test_reg(reg_ct, reg) && s->reg_to_temp[reg] == -1)
1502 return reg;
1505 /* XXX: do better spill choice */
1506 for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1507 reg = tcg_target_reg_alloc_order[i];
1508 if (tcg_regset_test_reg(reg_ct, reg)) {
1509 tcg_reg_free(s, reg);
1510 return reg;
1514 tcg_abort();
1517 /* save a temporary to memory. 'allocated_regs' is used in case a
1518 temporary registers needs to be allocated to store a constant. */
1519 static void temp_save(TCGContext *s, int temp, TCGRegSet allocated_regs)
1521 TCGTemp *ts;
1522 int reg;
1524 ts = &s->temps[temp];
1525 if (!ts->fixed_reg) {
1526 switch(ts->val_type) {
1527 case TEMP_VAL_REG:
1528 tcg_reg_free(s, ts->reg);
1529 break;
1530 case TEMP_VAL_DEAD:
1531 ts->val_type = TEMP_VAL_MEM;
1532 break;
1533 case TEMP_VAL_CONST:
1534 reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type],
1535 allocated_regs);
1536 if (!ts->mem_allocated)
1537 temp_allocate_frame(s, temp);
1538 tcg_out_movi(s, ts->type, reg, ts->val);
1539 tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1540 ts->val_type = TEMP_VAL_MEM;
1541 break;
1542 case TEMP_VAL_MEM:
1543 break;
1544 default:
1545 tcg_abort();
1550 /* save globals to their canonical location and assume they can be
1551 modified be the following code. 'allocated_regs' is used in case a
1552 temporary registers needs to be allocated to store a constant. */
1553 static void save_globals(TCGContext *s, TCGRegSet allocated_regs)
1555 int i;
1557 for(i = 0; i < s->nb_globals; i++) {
1558 temp_save(s, i, allocated_regs);
1562 /* at the end of a basic block, we assume all temporaries are dead and
1563 all globals are stored at their canonical location. */
1564 static void tcg_reg_alloc_bb_end(TCGContext *s, TCGRegSet allocated_regs)
1566 TCGTemp *ts;
1567 int i;
1569 for(i = s->nb_globals; i < s->nb_temps; i++) {
1570 ts = &s->temps[i];
1571 if (ts->temp_local) {
1572 temp_save(s, i, allocated_regs);
1573 } else {
1574 if (ts->val_type == TEMP_VAL_REG) {
1575 s->reg_to_temp[ts->reg] = -1;
1577 ts->val_type = TEMP_VAL_DEAD;
1581 save_globals(s, allocated_regs);
1584 #define IS_DEAD_ARG(n) ((dead_args >> (n)) & 1)
1586 static void tcg_reg_alloc_movi(TCGContext *s, const TCGArg *args)
1588 TCGTemp *ots;
1589 tcg_target_ulong val;
1591 ots = &s->temps[args[0]];
1592 val = args[1];
1594 if (ots->fixed_reg) {
1595 /* for fixed registers, we do not do any constant
1596 propagation */
1597 tcg_out_movi(s, ots->type, ots->reg, val);
1598 } else {
1599 /* The movi is not explicitly generated here */
1600 if (ots->val_type == TEMP_VAL_REG)
1601 s->reg_to_temp[ots->reg] = -1;
1602 ots->val_type = TEMP_VAL_CONST;
1603 ots->val = val;
1607 static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
1608 const TCGArg *args,
1609 unsigned int dead_args)
1611 TCGTemp *ts, *ots;
1612 int reg;
1613 const TCGArgConstraint *arg_ct;
1615 ots = &s->temps[args[0]];
1616 ts = &s->temps[args[1]];
1617 arg_ct = &def->args_ct[0];
1619 /* XXX: always mark arg dead if IS_DEAD_ARG(1) */
1620 if (ts->val_type == TEMP_VAL_REG) {
1621 if (IS_DEAD_ARG(1) && !ts->fixed_reg && !ots->fixed_reg) {
1622 /* the mov can be suppressed */
1623 if (ots->val_type == TEMP_VAL_REG)
1624 s->reg_to_temp[ots->reg] = -1;
1625 reg = ts->reg;
1626 s->reg_to_temp[reg] = -1;
1627 ts->val_type = TEMP_VAL_DEAD;
1628 } else {
1629 if (ots->val_type == TEMP_VAL_REG) {
1630 reg = ots->reg;
1631 } else {
1632 reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1634 if (ts->reg != reg) {
1635 tcg_out_mov(s, ots->type, reg, ts->reg);
1638 } else if (ts->val_type == TEMP_VAL_MEM) {
1639 if (ots->val_type == TEMP_VAL_REG) {
1640 reg = ots->reg;
1641 } else {
1642 reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1644 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1645 } else if (ts->val_type == TEMP_VAL_CONST) {
1646 if (ots->fixed_reg) {
1647 reg = ots->reg;
1648 tcg_out_movi(s, ots->type, reg, ts->val);
1649 } else {
1650 /* propagate constant */
1651 if (ots->val_type == TEMP_VAL_REG)
1652 s->reg_to_temp[ots->reg] = -1;
1653 ots->val_type = TEMP_VAL_CONST;
1654 ots->val = ts->val;
1655 return;
1657 } else {
1658 tcg_abort();
1660 s->reg_to_temp[reg] = args[0];
1661 ots->reg = reg;
1662 ots->val_type = TEMP_VAL_REG;
1663 ots->mem_coherent = 0;
1666 static void tcg_reg_alloc_op(TCGContext *s,
1667 const TCGOpDef *def, TCGOpcode opc,
1668 const TCGArg *args,
1669 unsigned int dead_args)
1671 TCGRegSet allocated_regs;
1672 int i, k, nb_iargs, nb_oargs, reg;
1673 TCGArg arg;
1674 const TCGArgConstraint *arg_ct;
1675 TCGTemp *ts;
1676 TCGArg new_args[TCG_MAX_OP_ARGS];
1677 int const_args[TCG_MAX_OP_ARGS];
1679 nb_oargs = def->nb_oargs;
1680 nb_iargs = def->nb_iargs;
1682 /* copy constants */
1683 memcpy(new_args + nb_oargs + nb_iargs,
1684 args + nb_oargs + nb_iargs,
1685 sizeof(TCGArg) * def->nb_cargs);
1687 /* satisfy input constraints */
1688 tcg_regset_set(allocated_regs, s->reserved_regs);
1689 for(k = 0; k < nb_iargs; k++) {
1690 i = def->sorted_args[nb_oargs + k];
1691 arg = args[i];
1692 arg_ct = &def->args_ct[i];
1693 ts = &s->temps[arg];
1694 if (ts->val_type == TEMP_VAL_MEM) {
1695 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1696 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1697 ts->val_type = TEMP_VAL_REG;
1698 ts->reg = reg;
1699 ts->mem_coherent = 1;
1700 s->reg_to_temp[reg] = arg;
1701 } else if (ts->val_type == TEMP_VAL_CONST) {
1702 if (tcg_target_const_match(ts->val, arg_ct)) {
1703 /* constant is OK for instruction */
1704 const_args[i] = 1;
1705 new_args[i] = ts->val;
1706 goto iarg_end;
1707 } else {
1708 /* need to move to a register */
1709 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1710 tcg_out_movi(s, ts->type, reg, ts->val);
1711 ts->val_type = TEMP_VAL_REG;
1712 ts->reg = reg;
1713 ts->mem_coherent = 0;
1714 s->reg_to_temp[reg] = arg;
1717 assert(ts->val_type == TEMP_VAL_REG);
1718 if (arg_ct->ct & TCG_CT_IALIAS) {
1719 if (ts->fixed_reg) {
1720 /* if fixed register, we must allocate a new register
1721 if the alias is not the same register */
1722 if (arg != args[arg_ct->alias_index])
1723 goto allocate_in_reg;
1724 } else {
1725 /* if the input is aliased to an output and if it is
1726 not dead after the instruction, we must allocate
1727 a new register and move it */
1728 if (!IS_DEAD_ARG(i)) {
1729 goto allocate_in_reg;
1733 reg = ts->reg;
1734 if (tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1735 /* nothing to do : the constraint is satisfied */
1736 } else {
1737 allocate_in_reg:
1738 /* allocate a new register matching the constraint
1739 and move the temporary register into it */
1740 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1741 tcg_out_mov(s, ts->type, reg, ts->reg);
1743 new_args[i] = reg;
1744 const_args[i] = 0;
1745 tcg_regset_set_reg(allocated_regs, reg);
1746 iarg_end: ;
1749 if (def->flags & TCG_OPF_BB_END) {
1750 tcg_reg_alloc_bb_end(s, allocated_regs);
1751 } else {
1752 /* mark dead temporaries and free the associated registers */
1753 for(i = nb_oargs; i < nb_oargs + nb_iargs; i++) {
1754 arg = args[i];
1755 if (IS_DEAD_ARG(i)) {
1756 ts = &s->temps[arg];
1757 if (!ts->fixed_reg) {
1758 if (ts->val_type == TEMP_VAL_REG)
1759 s->reg_to_temp[ts->reg] = -1;
1760 ts->val_type = TEMP_VAL_DEAD;
1765 if (def->flags & TCG_OPF_CALL_CLOBBER) {
1766 /* XXX: permit generic clobber register list ? */
1767 for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1768 if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
1769 tcg_reg_free(s, reg);
1772 /* XXX: for load/store we could do that only for the slow path
1773 (i.e. when a memory callback is called) */
1775 /* store globals and free associated registers (we assume the insn
1776 can modify any global. */
1777 save_globals(s, allocated_regs);
1780 /* satisfy the output constraints */
1781 tcg_regset_set(allocated_regs, s->reserved_regs);
1782 for(k = 0; k < nb_oargs; k++) {
1783 i = def->sorted_args[k];
1784 arg = args[i];
1785 arg_ct = &def->args_ct[i];
1786 ts = &s->temps[arg];
1787 if (arg_ct->ct & TCG_CT_ALIAS) {
1788 reg = new_args[arg_ct->alias_index];
1789 } else {
1790 /* if fixed register, we try to use it */
1791 reg = ts->reg;
1792 if (ts->fixed_reg &&
1793 tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1794 goto oarg_end;
1796 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1798 tcg_regset_set_reg(allocated_regs, reg);
1799 /* if a fixed register is used, then a move will be done afterwards */
1800 if (!ts->fixed_reg) {
1801 if (ts->val_type == TEMP_VAL_REG)
1802 s->reg_to_temp[ts->reg] = -1;
1803 if (IS_DEAD_ARG(i)) {
1804 ts->val_type = TEMP_VAL_DEAD;
1805 } else {
1806 ts->val_type = TEMP_VAL_REG;
1807 ts->reg = reg;
1808 /* temp value is modified, so the value kept in memory is
1809 potentially not the same */
1810 ts->mem_coherent = 0;
1811 s->reg_to_temp[reg] = arg;
1814 oarg_end:
1815 new_args[i] = reg;
1819 /* emit instruction */
1820 tcg_out_op(s, opc, new_args, const_args);
1822 /* move the outputs in the correct register if needed */
1823 for(i = 0; i < nb_oargs; i++) {
1824 ts = &s->temps[args[i]];
1825 reg = new_args[i];
1826 if (ts->fixed_reg && ts->reg != reg) {
1827 tcg_out_mov(s, ts->type, ts->reg, reg);
1832 #ifdef TCG_TARGET_STACK_GROWSUP
1833 #define STACK_DIR(x) (-(x))
1834 #else
1835 #define STACK_DIR(x) (x)
1836 #endif
1838 static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
1839 TCGOpcode opc, const TCGArg *args,
1840 unsigned int dead_args)
1842 int nb_iargs, nb_oargs, flags, nb_regs, i, reg, nb_params;
1843 TCGArg arg, func_arg;
1844 TCGTemp *ts;
1845 tcg_target_long stack_offset, call_stack_size, func_addr;
1846 int const_func_arg, allocate_args;
1847 TCGRegSet allocated_regs;
1848 const TCGArgConstraint *arg_ct;
1850 arg = *args++;
1852 nb_oargs = arg >> 16;
1853 nb_iargs = arg & 0xffff;
1854 nb_params = nb_iargs - 1;
1856 flags = args[nb_oargs + nb_iargs];
1858 nb_regs = tcg_target_get_call_iarg_regs_count(flags);
1859 if (nb_regs > nb_params)
1860 nb_regs = nb_params;
1862 /* assign stack slots first */
1863 call_stack_size = (nb_params - nb_regs) * sizeof(tcg_target_long);
1864 call_stack_size = (call_stack_size + TCG_TARGET_STACK_ALIGN - 1) &
1865 ~(TCG_TARGET_STACK_ALIGN - 1);
1866 allocate_args = (call_stack_size > TCG_STATIC_CALL_ARGS_SIZE);
1867 if (allocate_args) {
1868 /* XXX: if more than TCG_STATIC_CALL_ARGS_SIZE is needed,
1869 preallocate call stack */
1870 tcg_abort();
1873 stack_offset = TCG_TARGET_CALL_STACK_OFFSET;
1874 for(i = nb_regs; i < nb_params; i++) {
1875 arg = args[nb_oargs + i];
1876 #ifdef TCG_TARGET_STACK_GROWSUP
1877 stack_offset -= sizeof(tcg_target_long);
1878 #endif
1879 if (arg != TCG_CALL_DUMMY_ARG) {
1880 ts = &s->temps[arg];
1881 if (ts->val_type == TEMP_VAL_REG) {
1882 tcg_out_st(s, ts->type, ts->reg, TCG_REG_CALL_STACK, stack_offset);
1883 } else if (ts->val_type == TEMP_VAL_MEM) {
1884 reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type],
1885 s->reserved_regs);
1886 /* XXX: not correct if reading values from the stack */
1887 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1888 tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
1889 } else if (ts->val_type == TEMP_VAL_CONST) {
1890 reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type],
1891 s->reserved_regs);
1892 /* XXX: sign extend may be needed on some targets */
1893 tcg_out_movi(s, ts->type, reg, ts->val);
1894 tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
1895 } else {
1896 tcg_abort();
1899 #ifndef TCG_TARGET_STACK_GROWSUP
1900 stack_offset += sizeof(tcg_target_long);
1901 #endif
1904 /* assign input registers */
1905 tcg_regset_set(allocated_regs, s->reserved_regs);
1906 for(i = 0; i < nb_regs; i++) {
1907 arg = args[nb_oargs + i];
1908 if (arg != TCG_CALL_DUMMY_ARG) {
1909 ts = &s->temps[arg];
1910 reg = tcg_target_call_iarg_regs[i];
1911 tcg_reg_free(s, reg);
1912 if (ts->val_type == TEMP_VAL_REG) {
1913 if (ts->reg != reg) {
1914 tcg_out_mov(s, ts->type, reg, ts->reg);
1916 } else if (ts->val_type == TEMP_VAL_MEM) {
1917 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1918 } else if (ts->val_type == TEMP_VAL_CONST) {
1919 /* XXX: sign extend ? */
1920 tcg_out_movi(s, ts->type, reg, ts->val);
1921 } else {
1922 tcg_abort();
1924 tcg_regset_set_reg(allocated_regs, reg);
1928 /* assign function address */
1929 func_arg = args[nb_oargs + nb_iargs - 1];
1930 arg_ct = &def->args_ct[0];
1931 ts = &s->temps[func_arg];
1932 func_addr = ts->val;
1933 const_func_arg = 0;
1934 if (ts->val_type == TEMP_VAL_MEM) {
1935 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1936 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1937 func_arg = reg;
1938 tcg_regset_set_reg(allocated_regs, reg);
1939 } else if (ts->val_type == TEMP_VAL_REG) {
1940 reg = ts->reg;
1941 if (!tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1942 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1943 tcg_out_mov(s, ts->type, reg, ts->reg);
1945 func_arg = reg;
1946 tcg_regset_set_reg(allocated_regs, reg);
1947 } else if (ts->val_type == TEMP_VAL_CONST) {
1948 if (tcg_target_const_match(func_addr, arg_ct)) {
1949 const_func_arg = 1;
1950 func_arg = func_addr;
1951 } else {
1952 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1953 tcg_out_movi(s, ts->type, reg, func_addr);
1954 func_arg = reg;
1955 tcg_regset_set_reg(allocated_regs, reg);
1957 } else {
1958 tcg_abort();
1962 /* mark dead temporaries and free the associated registers */
1963 for(i = nb_oargs; i < nb_iargs + nb_oargs; i++) {
1964 arg = args[i];
1965 if (IS_DEAD_ARG(i)) {
1966 ts = &s->temps[arg];
1967 if (!ts->fixed_reg) {
1968 if (ts->val_type == TEMP_VAL_REG)
1969 s->reg_to_temp[ts->reg] = -1;
1970 ts->val_type = TEMP_VAL_DEAD;
1975 /* clobber call registers */
1976 for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1977 if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
1978 tcg_reg_free(s, reg);
1982 /* store globals and free associated registers (we assume the call
1983 can modify any global. */
1984 if (!(flags & TCG_CALL_CONST)) {
1985 save_globals(s, allocated_regs);
1988 tcg_out_op(s, opc, &func_arg, &const_func_arg);
1990 /* assign output registers and emit moves if needed */
1991 for(i = 0; i < nb_oargs; i++) {
1992 arg = args[i];
1993 ts = &s->temps[arg];
1994 reg = tcg_target_call_oarg_regs[i];
1995 assert(s->reg_to_temp[reg] == -1);
1996 if (ts->fixed_reg) {
1997 if (ts->reg != reg) {
1998 tcg_out_mov(s, ts->type, ts->reg, reg);
2000 } else {
2001 if (ts->val_type == TEMP_VAL_REG)
2002 s->reg_to_temp[ts->reg] = -1;
2003 if (IS_DEAD_ARG(i)) {
2004 ts->val_type = TEMP_VAL_DEAD;
2005 } else {
2006 ts->val_type = TEMP_VAL_REG;
2007 ts->reg = reg;
2008 ts->mem_coherent = 0;
2009 s->reg_to_temp[reg] = arg;
2014 return nb_iargs + nb_oargs + def->nb_cargs + 1;
2017 #ifdef CONFIG_PROFILER
2019 static int64_t tcg_table_op_count[NB_OPS];
2021 static void dump_op_count(void)
2023 int i;
2024 FILE *f;
2025 f = fopen("/tmp/op.log", "w");
2026 for(i = INDEX_op_end; i < NB_OPS; i++) {
2027 fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name, tcg_table_op_count[i]);
2029 fclose(f);
2031 #endif
2034 static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
2035 long search_pc)
2037 TCGOpcode opc;
2038 int op_index;
2039 const TCGOpDef *def;
2040 unsigned int dead_args;
2041 const TCGArg *args;
2043 #ifdef DEBUG_DISAS
2044 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
2045 qemu_log("OP:\n");
2046 tcg_dump_ops(s, logfile);
2047 qemu_log("\n");
2049 #endif
2051 #ifdef USE_TCG_OPTIMIZATIONS
2052 gen_opparam_ptr =
2053 tcg_optimize(s, gen_opc_ptr, gen_opparam_buf, tcg_op_defs);
2054 #endif
2056 #ifdef CONFIG_PROFILER
2057 s->la_time -= profile_getclock();
2058 #endif
2059 tcg_liveness_analysis(s);
2060 #ifdef CONFIG_PROFILER
2061 s->la_time += profile_getclock();
2062 #endif
2064 #ifdef DEBUG_DISAS
2065 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_OPT))) {
2066 qemu_log("OP after liveness analysis:\n");
2067 tcg_dump_ops(s, logfile);
2068 qemu_log("\n");
2070 #endif
2072 tcg_reg_alloc_start(s);
2074 s->code_buf = gen_code_buf;
2075 s->code_ptr = gen_code_buf;
2077 args = gen_opparam_buf;
2078 op_index = 0;
2080 for(;;) {
2081 opc = gen_opc_buf[op_index];
2082 #ifdef CONFIG_PROFILER
2083 tcg_table_op_count[opc]++;
2084 #endif
2085 def = &tcg_op_defs[opc];
2086 #if 0
2087 printf("%s: %d %d %d\n", def->name,
2088 def->nb_oargs, def->nb_iargs, def->nb_cargs);
2089 // dump_regs(s);
2090 #endif
2091 switch(opc) {
2092 case INDEX_op_mov_i32:
2093 #if TCG_TARGET_REG_BITS == 64
2094 case INDEX_op_mov_i64:
2095 #endif
2096 dead_args = s->op_dead_args[op_index];
2097 tcg_reg_alloc_mov(s, def, args, dead_args);
2098 break;
2099 case INDEX_op_movi_i32:
2100 #if TCG_TARGET_REG_BITS == 64
2101 case INDEX_op_movi_i64:
2102 #endif
2103 tcg_reg_alloc_movi(s, args);
2104 break;
2105 case INDEX_op_debug_insn_start:
2106 /* debug instruction */
2107 break;
2108 case INDEX_op_nop:
2109 case INDEX_op_nop1:
2110 case INDEX_op_nop2:
2111 case INDEX_op_nop3:
2112 break;
2113 case INDEX_op_nopn:
2114 args += args[0];
2115 goto next;
2116 case INDEX_op_discard:
2118 TCGTemp *ts;
2119 ts = &s->temps[args[0]];
2120 /* mark the temporary as dead */
2121 if (!ts->fixed_reg) {
2122 if (ts->val_type == TEMP_VAL_REG)
2123 s->reg_to_temp[ts->reg] = -1;
2124 ts->val_type = TEMP_VAL_DEAD;
2127 break;
2128 case INDEX_op_set_label:
2129 tcg_reg_alloc_bb_end(s, s->reserved_regs);
2130 tcg_out_label(s, args[0], s->code_ptr);
2131 break;
2132 case INDEX_op_call:
2133 dead_args = s->op_dead_args[op_index];
2134 args += tcg_reg_alloc_call(s, def, opc, args, dead_args);
2135 goto next;
2136 case INDEX_op_end:
2137 goto the_end;
2138 default:
2139 /* Sanity check that we've not introduced any unhandled opcodes. */
2140 if (def->flags & TCG_OPF_NOT_PRESENT) {
2141 tcg_abort();
2143 /* Note: in order to speed up the code, it would be much
2144 faster to have specialized register allocator functions for
2145 some common argument patterns */
2146 dead_args = s->op_dead_args[op_index];
2147 tcg_reg_alloc_op(s, def, opc, args, dead_args);
2148 break;
2150 args += def->nb_args;
2151 next:
2152 if (search_pc >= 0 && search_pc < s->code_ptr - gen_code_buf) {
2153 return op_index;
2155 op_index++;
2156 #ifndef NDEBUG
2157 check_regs(s);
2158 #endif
2160 the_end:
2161 return -1;
2164 int tcg_gen_code(TCGContext *s, uint8_t *gen_code_buf)
2166 #ifdef CONFIG_PROFILER
2168 int n;
2169 n = (gen_opc_ptr - gen_opc_buf);
2170 s->op_count += n;
2171 if (n > s->op_count_max)
2172 s->op_count_max = n;
2174 s->temp_count += s->nb_temps;
2175 if (s->nb_temps > s->temp_count_max)
2176 s->temp_count_max = s->nb_temps;
2178 #endif
2180 tcg_gen_code_common(s, gen_code_buf, -1);
2182 /* flush instruction cache */
2183 flush_icache_range((tcg_target_ulong)gen_code_buf,
2184 (tcg_target_ulong)s->code_ptr);
2186 return s->code_ptr - gen_code_buf;
2189 /* Return the index of the micro operation such as the pc after is <
2190 offset bytes from the start of the TB. The contents of gen_code_buf must
2191 not be changed, though writing the same values is ok.
2192 Return -1 if not found. */
2193 int tcg_gen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, long offset)
2195 return tcg_gen_code_common(s, gen_code_buf, offset);
2198 #ifdef CONFIG_PROFILER
2199 void tcg_dump_info(FILE *f, fprintf_function cpu_fprintf)
2201 TCGContext *s = &tcg_ctx;
2202 int64_t tot;
2204 tot = s->interm_time + s->code_time;
2205 cpu_fprintf(f, "JIT cycles %" PRId64 " (%0.3f s at 2.4 GHz)\n",
2206 tot, tot / 2.4e9);
2207 cpu_fprintf(f, "translated TBs %" PRId64 " (aborted=%" PRId64 " %0.1f%%)\n",
2208 s->tb_count,
2209 s->tb_count1 - s->tb_count,
2210 s->tb_count1 ? (double)(s->tb_count1 - s->tb_count) / s->tb_count1 * 100.0 : 0);
2211 cpu_fprintf(f, "avg ops/TB %0.1f max=%d\n",
2212 s->tb_count ? (double)s->op_count / s->tb_count : 0, s->op_count_max);
2213 cpu_fprintf(f, "deleted ops/TB %0.2f\n",
2214 s->tb_count ?
2215 (double)s->del_op_count / s->tb_count : 0);
2216 cpu_fprintf(f, "avg temps/TB %0.2f max=%d\n",
2217 s->tb_count ?
2218 (double)s->temp_count / s->tb_count : 0,
2219 s->temp_count_max);
2221 cpu_fprintf(f, "cycles/op %0.1f\n",
2222 s->op_count ? (double)tot / s->op_count : 0);
2223 cpu_fprintf(f, "cycles/in byte %0.1f\n",
2224 s->code_in_len ? (double)tot / s->code_in_len : 0);
2225 cpu_fprintf(f, "cycles/out byte %0.1f\n",
2226 s->code_out_len ? (double)tot / s->code_out_len : 0);
2227 if (tot == 0)
2228 tot = 1;
2229 cpu_fprintf(f, " gen_interm time %0.1f%%\n",
2230 (double)s->interm_time / tot * 100.0);
2231 cpu_fprintf(f, " gen_code time %0.1f%%\n",
2232 (double)s->code_time / tot * 100.0);
2233 cpu_fprintf(f, "liveness/code time %0.1f%%\n",
2234 (double)s->la_time / (s->code_time ? s->code_time : 1) * 100.0);
2235 cpu_fprintf(f, "cpu_restore count %" PRId64 "\n",
2236 s->restore_count);
2237 cpu_fprintf(f, " avg cycles %0.1f\n",
2238 s->restore_count ? (double)s->restore_time / s->restore_count : 0);
2240 dump_op_count();
2242 #else
2243 void tcg_dump_info(FILE *f, fprintf_function cpu_fprintf)
2245 cpu_fprintf(f, "[TCG profiler not compiled]\n");
2247 #endif