Fix typo: buf -> bus
[qemu/ar7.git] / tcg / tcg.c
blob30f3aefe69a2c7899428627bb6d1845fda324211
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 <stdarg.h>
37 #include <stdlib.h>
38 #include <stdio.h>
39 #include <string.h>
40 #include <inttypes.h>
41 #ifdef _WIN32
42 #include <malloc.h>
43 #endif
44 #ifdef _AIX
45 #include <alloca.h>
46 #endif
48 #include "qemu-common.h"
49 #include "cache-utils.h"
50 #include "host-utils.h"
51 #include "qemu-timer.h"
53 /* Note: the long term plan is to reduce the dependancies on the QEMU
54 CPU definitions. Currently they are used for qemu_ld/st
55 instructions */
56 #define NO_CPU_IO_DEFS
57 #include "cpu.h"
59 #include "tcg-op.h"
60 #include "elf.h"
62 #if defined(CONFIG_USE_GUEST_BASE) && !defined(TCG_TARGET_HAS_GUEST_BASE)
63 #error GUEST_BASE not supported on this host.
64 #endif
66 /* Forward declarations for functions declared in tcg-target.c and used here. */
67 static void tcg_target_init(TCGContext *s);
68 static void tcg_target_qemu_prologue(TCGContext *s);
69 static void patch_reloc(uint8_t *code_ptr, int type,
70 tcg_target_long value, tcg_target_long addend);
72 /* Forward declarations for functions declared and used in tcg-target.c. */
73 static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str);
74 static void tcg_out_ld(TCGContext *s, TCGType type, int ret, int arg1,
75 tcg_target_long arg2);
76 static void tcg_out_mov(TCGContext *s, TCGType type, int ret, int arg);
77 static void tcg_out_movi(TCGContext *s, TCGType type,
78 int ret, tcg_target_long arg);
79 static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
80 const int *const_args);
81 static void tcg_out_st(TCGContext *s, TCGType type, int arg, int arg1,
82 tcg_target_long arg2);
83 static int tcg_target_const_match(tcg_target_long val,
84 const TCGArgConstraint *arg_ct);
85 static int tcg_target_get_call_iarg_regs_count(int flags);
87 TCGOpDef tcg_op_defs[] = {
88 #define DEF(s, oargs, iargs, cargs, flags) { #s, oargs, iargs, cargs, iargs + oargs + cargs, flags },
89 #include "tcg-opc.h"
90 #undef DEF
93 static TCGRegSet tcg_target_available_regs[2];
94 static TCGRegSet tcg_target_call_clobber_regs;
96 /* XXX: move that inside the context */
97 uint16_t *gen_opc_ptr;
98 TCGArg *gen_opparam_ptr;
100 static inline void tcg_out8(TCGContext *s, uint8_t v)
102 *s->code_ptr++ = v;
105 static inline void tcg_out16(TCGContext *s, uint16_t v)
107 *(uint16_t *)s->code_ptr = v;
108 s->code_ptr += 2;
111 static inline void tcg_out32(TCGContext *s, uint32_t v)
113 *(uint32_t *)s->code_ptr = v;
114 s->code_ptr += 4;
117 /* label relocation processing */
119 static void tcg_out_reloc(TCGContext *s, uint8_t *code_ptr, int type,
120 int label_index, long addend)
122 TCGLabel *l;
123 TCGRelocation *r;
125 l = &s->labels[label_index];
126 if (l->has_value) {
127 /* FIXME: This may break relocations on RISC targets that
128 modify instruction fields in place. The caller may not have
129 written the initial value. */
130 patch_reloc(code_ptr, type, l->u.value, addend);
131 } else {
132 /* add a new relocation entry */
133 r = tcg_malloc(sizeof(TCGRelocation));
134 r->type = type;
135 r->ptr = code_ptr;
136 r->addend = addend;
137 r->next = l->u.first_reloc;
138 l->u.first_reloc = r;
142 static void tcg_out_label(TCGContext *s, int label_index,
143 tcg_target_long value)
145 TCGLabel *l;
146 TCGRelocation *r;
148 l = &s->labels[label_index];
149 if (l->has_value)
150 tcg_abort();
151 r = l->u.first_reloc;
152 while (r != NULL) {
153 patch_reloc(r->ptr, r->type, value, r->addend);
154 r = r->next;
156 l->has_value = 1;
157 l->u.value = value;
160 int gen_new_label(void)
162 TCGContext *s = &tcg_ctx;
163 int idx;
164 TCGLabel *l;
166 if (s->nb_labels >= TCG_MAX_LABELS)
167 tcg_abort();
168 idx = s->nb_labels++;
169 l = &s->labels[idx];
170 l->has_value = 0;
171 l->u.first_reloc = NULL;
172 return idx;
175 #include "tcg-target.c"
177 /* pool based memory allocation */
178 void *tcg_malloc_internal(TCGContext *s, int size)
180 TCGPool *p;
181 int pool_size;
183 if (size > TCG_POOL_CHUNK_SIZE) {
184 /* big malloc: insert a new pool (XXX: could optimize) */
185 p = g_malloc(sizeof(TCGPool) + size);
186 p->size = size;
187 if (s->pool_current)
188 s->pool_current->next = p;
189 else
190 s->pool_first = p;
191 p->next = s->pool_current;
192 } else {
193 p = s->pool_current;
194 if (!p) {
195 p = s->pool_first;
196 if (!p)
197 goto new_pool;
198 } else {
199 if (!p->next) {
200 new_pool:
201 pool_size = TCG_POOL_CHUNK_SIZE;
202 p = g_malloc(sizeof(TCGPool) + pool_size);
203 p->size = pool_size;
204 p->next = NULL;
205 if (s->pool_current)
206 s->pool_current->next = p;
207 else
208 s->pool_first = p;
209 } else {
210 p = p->next;
214 s->pool_current = p;
215 s->pool_cur = p->data + size;
216 s->pool_end = p->data + p->size;
217 return p->data;
220 void tcg_pool_reset(TCGContext *s)
222 s->pool_cur = s->pool_end = NULL;
223 s->pool_current = NULL;
226 void tcg_context_init(TCGContext *s)
228 int op, total_args, n;
229 TCGOpDef *def;
230 TCGArgConstraint *args_ct;
231 int *sorted_args;
233 memset(s, 0, sizeof(*s));
234 s->temps = s->static_temps;
235 s->nb_globals = 0;
237 /* Count total number of arguments and allocate the corresponding
238 space */
239 total_args = 0;
240 for(op = 0; op < NB_OPS; op++) {
241 def = &tcg_op_defs[op];
242 n = def->nb_iargs + def->nb_oargs;
243 total_args += n;
246 args_ct = g_malloc(sizeof(TCGArgConstraint) * total_args);
247 sorted_args = g_malloc(sizeof(int) * total_args);
249 for(op = 0; op < NB_OPS; op++) {
250 def = &tcg_op_defs[op];
251 def->args_ct = args_ct;
252 def->sorted_args = sorted_args;
253 n = def->nb_iargs + def->nb_oargs;
254 sorted_args += n;
255 args_ct += n;
258 tcg_target_init(s);
261 void tcg_prologue_init(TCGContext *s)
263 /* init global prologue and epilogue */
264 s->code_buf = code_gen_prologue;
265 s->code_ptr = s->code_buf;
266 tcg_target_qemu_prologue(s);
267 flush_icache_range((unsigned long)s->code_buf,
268 (unsigned long)s->code_ptr);
271 void tcg_set_frame(TCGContext *s, int reg,
272 tcg_target_long start, tcg_target_long size)
274 s->frame_start = start;
275 s->frame_end = start + size;
276 s->frame_reg = reg;
279 void tcg_func_start(TCGContext *s)
281 int i;
282 tcg_pool_reset(s);
283 s->nb_temps = s->nb_globals;
284 for(i = 0; i < (TCG_TYPE_COUNT * 2); i++)
285 s->first_free_temp[i] = -1;
286 s->labels = tcg_malloc(sizeof(TCGLabel) * TCG_MAX_LABELS);
287 s->nb_labels = 0;
288 s->current_frame_offset = s->frame_start;
290 gen_opc_ptr = gen_opc_buf;
291 gen_opparam_ptr = gen_opparam_buf;
294 static inline void tcg_temp_alloc(TCGContext *s, int n)
296 if (n > TCG_MAX_TEMPS)
297 tcg_abort();
300 static inline int tcg_global_reg_new_internal(TCGType type, int reg,
301 const char *name)
303 TCGContext *s = &tcg_ctx;
304 TCGTemp *ts;
305 int idx;
307 #if TCG_TARGET_REG_BITS == 32
308 if (type != TCG_TYPE_I32)
309 tcg_abort();
310 #endif
311 if (tcg_regset_test_reg(s->reserved_regs, reg))
312 tcg_abort();
313 idx = s->nb_globals;
314 tcg_temp_alloc(s, s->nb_globals + 1);
315 ts = &s->temps[s->nb_globals];
316 ts->base_type = type;
317 ts->type = type;
318 ts->fixed_reg = 1;
319 ts->reg = reg;
320 ts->name = name;
321 s->nb_globals++;
322 tcg_regset_set_reg(s->reserved_regs, reg);
323 return idx;
326 TCGv_i32 tcg_global_reg_new_i32(int reg, const char *name)
328 int idx;
330 idx = tcg_global_reg_new_internal(TCG_TYPE_I32, reg, name);
331 return MAKE_TCGV_I32(idx);
334 TCGv_i64 tcg_global_reg_new_i64(int reg, const char *name)
336 int idx;
338 idx = tcg_global_reg_new_internal(TCG_TYPE_I64, reg, name);
339 return MAKE_TCGV_I64(idx);
342 static inline int tcg_global_mem_new_internal(TCGType type, int reg,
343 tcg_target_long offset,
344 const char *name)
346 TCGContext *s = &tcg_ctx;
347 TCGTemp *ts;
348 int idx;
350 idx = s->nb_globals;
351 #if TCG_TARGET_REG_BITS == 32
352 if (type == TCG_TYPE_I64) {
353 char buf[64];
354 tcg_temp_alloc(s, s->nb_globals + 2);
355 ts = &s->temps[s->nb_globals];
356 ts->base_type = type;
357 ts->type = TCG_TYPE_I32;
358 ts->fixed_reg = 0;
359 ts->mem_allocated = 1;
360 ts->mem_reg = reg;
361 #ifdef TCG_TARGET_WORDS_BIGENDIAN
362 ts->mem_offset = offset + 4;
363 #else
364 ts->mem_offset = offset;
365 #endif
366 pstrcpy(buf, sizeof(buf), name);
367 pstrcat(buf, sizeof(buf), "_0");
368 ts->name = strdup(buf);
369 ts++;
371 ts->base_type = type;
372 ts->type = TCG_TYPE_I32;
373 ts->fixed_reg = 0;
374 ts->mem_allocated = 1;
375 ts->mem_reg = reg;
376 #ifdef TCG_TARGET_WORDS_BIGENDIAN
377 ts->mem_offset = offset;
378 #else
379 ts->mem_offset = offset + 4;
380 #endif
381 pstrcpy(buf, sizeof(buf), name);
382 pstrcat(buf, sizeof(buf), "_1");
383 ts->name = strdup(buf);
385 s->nb_globals += 2;
386 } else
387 #endif
389 tcg_temp_alloc(s, s->nb_globals + 1);
390 ts = &s->temps[s->nb_globals];
391 ts->base_type = type;
392 ts->type = type;
393 ts->fixed_reg = 0;
394 ts->mem_allocated = 1;
395 ts->mem_reg = reg;
396 ts->mem_offset = offset;
397 ts->name = name;
398 s->nb_globals++;
400 return idx;
403 TCGv_i32 tcg_global_mem_new_i32(int reg, tcg_target_long offset,
404 const char *name)
406 int idx;
408 idx = tcg_global_mem_new_internal(TCG_TYPE_I32, reg, offset, name);
409 return MAKE_TCGV_I32(idx);
412 TCGv_i64 tcg_global_mem_new_i64(int reg, tcg_target_long offset,
413 const char *name)
415 int idx;
417 idx = tcg_global_mem_new_internal(TCG_TYPE_I64, reg, offset, name);
418 return MAKE_TCGV_I64(idx);
421 static inline int tcg_temp_new_internal(TCGType type, int temp_local)
423 TCGContext *s = &tcg_ctx;
424 TCGTemp *ts;
425 int idx, k;
427 k = type;
428 if (temp_local)
429 k += TCG_TYPE_COUNT;
430 idx = s->first_free_temp[k];
431 if (idx != -1) {
432 /* There is already an available temp with the
433 right type */
434 ts = &s->temps[idx];
435 s->first_free_temp[k] = ts->next_free_temp;
436 ts->temp_allocated = 1;
437 assert(ts->temp_local == temp_local);
438 } else {
439 idx = s->nb_temps;
440 #if TCG_TARGET_REG_BITS == 32
441 if (type == TCG_TYPE_I64) {
442 tcg_temp_alloc(s, s->nb_temps + 2);
443 ts = &s->temps[s->nb_temps];
444 ts->base_type = type;
445 ts->type = TCG_TYPE_I32;
446 ts->temp_allocated = 1;
447 ts->temp_local = temp_local;
448 ts->name = NULL;
449 ts++;
450 ts->base_type = TCG_TYPE_I32;
451 ts->type = TCG_TYPE_I32;
452 ts->temp_allocated = 1;
453 ts->temp_local = temp_local;
454 ts->name = NULL;
455 s->nb_temps += 2;
456 } else
457 #endif
459 tcg_temp_alloc(s, s->nb_temps + 1);
460 ts = &s->temps[s->nb_temps];
461 ts->base_type = type;
462 ts->type = type;
463 ts->temp_allocated = 1;
464 ts->temp_local = temp_local;
465 ts->name = NULL;
466 s->nb_temps++;
470 #if defined(CONFIG_DEBUG_TCG)
471 s->temps_in_use++;
472 #endif
473 return idx;
476 TCGv_i32 tcg_temp_new_internal_i32(int temp_local)
478 int idx;
480 idx = tcg_temp_new_internal(TCG_TYPE_I32, temp_local);
481 return MAKE_TCGV_I32(idx);
484 TCGv_i64 tcg_temp_new_internal_i64(int temp_local)
486 int idx;
488 idx = tcg_temp_new_internal(TCG_TYPE_I64, temp_local);
489 return MAKE_TCGV_I64(idx);
492 static inline void tcg_temp_free_internal(int idx)
494 TCGContext *s = &tcg_ctx;
495 TCGTemp *ts;
496 int k;
498 #if defined(CONFIG_DEBUG_TCG)
499 s->temps_in_use--;
500 if (s->temps_in_use < 0) {
501 fprintf(stderr, "More temporaries freed than allocated!\n");
503 #endif
505 assert(idx >= s->nb_globals && idx < s->nb_temps);
506 ts = &s->temps[idx];
507 assert(ts->temp_allocated != 0);
508 ts->temp_allocated = 0;
509 k = ts->base_type;
510 if (ts->temp_local)
511 k += TCG_TYPE_COUNT;
512 ts->next_free_temp = s->first_free_temp[k];
513 s->first_free_temp[k] = idx;
516 void tcg_temp_free_i32(TCGv_i32 arg)
518 tcg_temp_free_internal(GET_TCGV_I32(arg));
521 void tcg_temp_free_i64(TCGv_i64 arg)
523 tcg_temp_free_internal(GET_TCGV_I64(arg));
526 TCGv_i32 tcg_const_i32(int32_t val)
528 TCGv_i32 t0;
529 t0 = tcg_temp_new_i32();
530 tcg_gen_movi_i32(t0, val);
531 return t0;
534 TCGv_i64 tcg_const_i64(int64_t val)
536 TCGv_i64 t0;
537 t0 = tcg_temp_new_i64();
538 tcg_gen_movi_i64(t0, val);
539 return t0;
542 TCGv_i32 tcg_const_local_i32(int32_t val)
544 TCGv_i32 t0;
545 t0 = tcg_temp_local_new_i32();
546 tcg_gen_movi_i32(t0, val);
547 return t0;
550 TCGv_i64 tcg_const_local_i64(int64_t val)
552 TCGv_i64 t0;
553 t0 = tcg_temp_local_new_i64();
554 tcg_gen_movi_i64(t0, val);
555 return t0;
558 #if defined(CONFIG_DEBUG_TCG)
559 void tcg_clear_temp_count(void)
561 TCGContext *s = &tcg_ctx;
562 s->temps_in_use = 0;
565 int tcg_check_temp_count(void)
567 TCGContext *s = &tcg_ctx;
568 if (s->temps_in_use) {
569 /* Clear the count so that we don't give another
570 * warning immediately next time around.
572 s->temps_in_use = 0;
573 return 1;
575 return 0;
577 #endif
579 void tcg_register_helper(void *func, const char *name)
581 TCGContext *s = &tcg_ctx;
582 int n;
583 if ((s->nb_helpers + 1) > s->allocated_helpers) {
584 n = s->allocated_helpers;
585 if (n == 0) {
586 n = 4;
587 } else {
588 n *= 2;
590 s->helpers = realloc(s->helpers, n * sizeof(TCGHelperInfo));
591 s->allocated_helpers = n;
593 s->helpers[s->nb_helpers].func = (tcg_target_ulong)func;
594 s->helpers[s->nb_helpers].name = name;
595 s->nb_helpers++;
598 /* Note: we convert the 64 bit args to 32 bit and do some alignment
599 and endian swap. Maybe it would be better to do the alignment
600 and endian swap in tcg_reg_alloc_call(). */
601 void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags,
602 int sizemask, TCGArg ret, int nargs, TCGArg *args)
604 #if defined(TCG_TARGET_I386) && TCG_TARGET_REG_BITS < 64
605 int call_type;
606 #endif
607 int i;
608 int real_args;
609 int nb_rets;
610 TCGArg *nparam;
612 #if defined(TCG_TARGET_EXTEND_ARGS) && TCG_TARGET_REG_BITS == 64
613 for (i = 0; i < nargs; ++i) {
614 int is_64bit = sizemask & (1 << (i+1)*2);
615 int is_signed = sizemask & (2 << (i+1)*2);
616 if (!is_64bit) {
617 TCGv_i64 temp = tcg_temp_new_i64();
618 TCGv_i64 orig = MAKE_TCGV_I64(args[i]);
619 if (is_signed) {
620 tcg_gen_ext32s_i64(temp, orig);
621 } else {
622 tcg_gen_ext32u_i64(temp, orig);
624 args[i] = GET_TCGV_I64(temp);
627 #endif /* TCG_TARGET_EXTEND_ARGS */
629 *gen_opc_ptr++ = INDEX_op_call;
630 nparam = gen_opparam_ptr++;
631 #if defined(TCG_TARGET_I386) && TCG_TARGET_REG_BITS < 64
632 call_type = (flags & TCG_CALL_TYPE_MASK);
633 #endif
634 if (ret != TCG_CALL_DUMMY_ARG) {
635 #if TCG_TARGET_REG_BITS < 64
636 if (sizemask & 1) {
637 #ifdef TCG_TARGET_WORDS_BIGENDIAN
638 *gen_opparam_ptr++ = ret + 1;
639 *gen_opparam_ptr++ = ret;
640 #else
641 *gen_opparam_ptr++ = ret;
642 *gen_opparam_ptr++ = ret + 1;
643 #endif
644 nb_rets = 2;
645 } else
646 #endif
648 *gen_opparam_ptr++ = ret;
649 nb_rets = 1;
651 } else {
652 nb_rets = 0;
654 real_args = 0;
655 for (i = 0; i < nargs; i++) {
656 #if TCG_TARGET_REG_BITS < 64
657 int is_64bit = sizemask & (1 << (i+1)*2);
658 if (is_64bit) {
659 #ifdef TCG_TARGET_I386
660 /* REGPARM case: if the third parameter is 64 bit, it is
661 allocated on the stack */
662 if (i == 2 && call_type == TCG_CALL_TYPE_REGPARM) {
663 call_type = TCG_CALL_TYPE_REGPARM_2;
664 flags = (flags & ~TCG_CALL_TYPE_MASK) | call_type;
666 #endif
667 #ifdef TCG_TARGET_CALL_ALIGN_ARGS
668 /* some targets want aligned 64 bit args */
669 if (real_args & 1) {
670 *gen_opparam_ptr++ = TCG_CALL_DUMMY_ARG;
671 real_args++;
673 #endif
674 /* If stack grows up, then we will be placing successive
675 arguments at lower addresses, which means we need to
676 reverse the order compared to how we would normally
677 treat either big or little-endian. For those arguments
678 that will wind up in registers, this still works for
679 HPPA (the only current STACK_GROWSUP target) since the
680 argument registers are *also* allocated in decreasing
681 order. If another such target is added, this logic may
682 have to get more complicated to differentiate between
683 stack arguments and register arguments. */
684 #if defined(TCG_TARGET_WORDS_BIGENDIAN) != defined(TCG_TARGET_STACK_GROWSUP)
685 *gen_opparam_ptr++ = args[i] + 1;
686 *gen_opparam_ptr++ = args[i];
687 #else
688 *gen_opparam_ptr++ = args[i];
689 *gen_opparam_ptr++ = args[i] + 1;
690 #endif
691 real_args += 2;
692 continue;
694 #endif /* TCG_TARGET_REG_BITS < 64 */
696 *gen_opparam_ptr++ = args[i];
697 real_args++;
699 *gen_opparam_ptr++ = GET_TCGV_PTR(func);
701 *gen_opparam_ptr++ = flags;
703 *nparam = (nb_rets << 16) | (real_args + 1);
705 /* total parameters, needed to go backward in the instruction stream */
706 *gen_opparam_ptr++ = 1 + nb_rets + real_args + 3;
708 #if defined(TCG_TARGET_EXTEND_ARGS) && TCG_TARGET_REG_BITS == 64
709 for (i = 0; i < nargs; ++i) {
710 int is_64bit = sizemask & (1 << (i+1)*2);
711 if (!is_64bit) {
712 TCGv_i64 temp = MAKE_TCGV_I64(args[i]);
713 tcg_temp_free_i64(temp);
716 #endif /* TCG_TARGET_EXTEND_ARGS */
719 #if TCG_TARGET_REG_BITS == 32
720 void tcg_gen_shifti_i64(TCGv_i64 ret, TCGv_i64 arg1,
721 int c, int right, int arith)
723 if (c == 0) {
724 tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg1));
725 tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
726 } else if (c >= 32) {
727 c -= 32;
728 if (right) {
729 if (arith) {
730 tcg_gen_sari_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
731 tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 31);
732 } else {
733 tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
734 tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
736 } else {
737 tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_LOW(arg1), c);
738 tcg_gen_movi_i32(TCGV_LOW(ret), 0);
740 } else {
741 TCGv_i32 t0, t1;
743 t0 = tcg_temp_new_i32();
744 t1 = tcg_temp_new_i32();
745 if (right) {
746 tcg_gen_shli_i32(t0, TCGV_HIGH(arg1), 32 - c);
747 if (arith)
748 tcg_gen_sari_i32(t1, TCGV_HIGH(arg1), c);
749 else
750 tcg_gen_shri_i32(t1, TCGV_HIGH(arg1), c);
751 tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_LOW(arg1), c);
752 tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(ret), t0);
753 tcg_gen_mov_i32(TCGV_HIGH(ret), t1);
754 } else {
755 tcg_gen_shri_i32(t0, TCGV_LOW(arg1), 32 - c);
756 /* Note: ret can be the same as arg1, so we use t1 */
757 tcg_gen_shli_i32(t1, TCGV_LOW(arg1), c);
758 tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c);
759 tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t0);
760 tcg_gen_mov_i32(TCGV_LOW(ret), t1);
762 tcg_temp_free_i32(t0);
763 tcg_temp_free_i32(t1);
766 #endif
769 static void tcg_reg_alloc_start(TCGContext *s)
771 int i;
772 TCGTemp *ts;
773 for(i = 0; i < s->nb_globals; i++) {
774 ts = &s->temps[i];
775 if (ts->fixed_reg) {
776 ts->val_type = TEMP_VAL_REG;
777 } else {
778 ts->val_type = TEMP_VAL_MEM;
781 for(i = s->nb_globals; i < s->nb_temps; i++) {
782 ts = &s->temps[i];
783 ts->val_type = TEMP_VAL_DEAD;
784 ts->mem_allocated = 0;
785 ts->fixed_reg = 0;
787 for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
788 s->reg_to_temp[i] = -1;
792 static char *tcg_get_arg_str_idx(TCGContext *s, char *buf, int buf_size,
793 int idx)
795 TCGTemp *ts;
797 assert(idx >= 0 && idx < s->nb_temps);
798 ts = &s->temps[idx];
799 assert(ts);
800 if (idx < s->nb_globals) {
801 pstrcpy(buf, buf_size, ts->name);
802 } else {
803 if (ts->temp_local)
804 snprintf(buf, buf_size, "loc%d", idx - s->nb_globals);
805 else
806 snprintf(buf, buf_size, "tmp%d", idx - s->nb_globals);
808 return buf;
811 char *tcg_get_arg_str_i32(TCGContext *s, char *buf, int buf_size, TCGv_i32 arg)
813 return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I32(arg));
816 char *tcg_get_arg_str_i64(TCGContext *s, char *buf, int buf_size, TCGv_i64 arg)
818 return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I64(arg));
821 static int helper_cmp(const void *p1, const void *p2)
823 const TCGHelperInfo *th1 = p1;
824 const TCGHelperInfo *th2 = p2;
825 if (th1->func < th2->func)
826 return -1;
827 else if (th1->func == th2->func)
828 return 0;
829 else
830 return 1;
833 /* find helper definition (Note: A hash table would be better) */
834 static TCGHelperInfo *tcg_find_helper(TCGContext *s, tcg_target_ulong val)
836 int m, m_min, m_max;
837 TCGHelperInfo *th;
838 tcg_target_ulong v;
840 if (unlikely(!s->helpers_sorted)) {
841 qsort(s->helpers, s->nb_helpers, sizeof(TCGHelperInfo),
842 helper_cmp);
843 s->helpers_sorted = 1;
846 /* binary search */
847 m_min = 0;
848 m_max = s->nb_helpers - 1;
849 while (m_min <= m_max) {
850 m = (m_min + m_max) >> 1;
851 th = &s->helpers[m];
852 v = th->func;
853 if (v == val)
854 return th;
855 else if (val < v) {
856 m_max = m - 1;
857 } else {
858 m_min = m + 1;
861 return NULL;
864 static const char * const cond_name[] =
866 [TCG_COND_EQ] = "eq",
867 [TCG_COND_NE] = "ne",
868 [TCG_COND_LT] = "lt",
869 [TCG_COND_GE] = "ge",
870 [TCG_COND_LE] = "le",
871 [TCG_COND_GT] = "gt",
872 [TCG_COND_LTU] = "ltu",
873 [TCG_COND_GEU] = "geu",
874 [TCG_COND_LEU] = "leu",
875 [TCG_COND_GTU] = "gtu"
878 void tcg_dump_ops(TCGContext *s, FILE *outfile)
880 const uint16_t *opc_ptr;
881 const TCGArg *args;
882 TCGArg arg;
883 TCGOpcode c;
884 int i, k, nb_oargs, nb_iargs, nb_cargs, first_insn;
885 const TCGOpDef *def;
886 char buf[128];
888 first_insn = 1;
889 opc_ptr = gen_opc_buf;
890 args = gen_opparam_buf;
891 while (opc_ptr < gen_opc_ptr) {
892 c = *opc_ptr++;
893 def = &tcg_op_defs[c];
894 if (c == INDEX_op_debug_insn_start) {
895 uint64_t pc;
896 #if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
897 pc = ((uint64_t)args[1] << 32) | args[0];
898 #else
899 pc = args[0];
900 #endif
901 if (!first_insn)
902 fprintf(outfile, "\n");
903 fprintf(outfile, " ---- 0x%" PRIx64, pc);
904 first_insn = 0;
905 nb_oargs = def->nb_oargs;
906 nb_iargs = def->nb_iargs;
907 nb_cargs = def->nb_cargs;
908 } else if (c == INDEX_op_call) {
909 TCGArg arg;
911 /* variable number of arguments */
912 arg = *args++;
913 nb_oargs = arg >> 16;
914 nb_iargs = arg & 0xffff;
915 nb_cargs = def->nb_cargs;
917 fprintf(outfile, " %s ", def->name);
919 /* function name */
920 fprintf(outfile, "%s",
921 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + nb_iargs - 1]));
922 /* flags */
923 fprintf(outfile, ",$0x%" TCG_PRIlx,
924 args[nb_oargs + nb_iargs]);
925 /* nb out args */
926 fprintf(outfile, ",$%d", nb_oargs);
927 for(i = 0; i < nb_oargs; i++) {
928 fprintf(outfile, ",");
929 fprintf(outfile, "%s",
930 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[i]));
932 for(i = 0; i < (nb_iargs - 1); i++) {
933 fprintf(outfile, ",");
934 if (args[nb_oargs + i] == TCG_CALL_DUMMY_ARG) {
935 fprintf(outfile, "<dummy>");
936 } else {
937 fprintf(outfile, "%s",
938 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + i]));
941 } else if (c == INDEX_op_movi_i32
942 #if TCG_TARGET_REG_BITS == 64
943 || c == INDEX_op_movi_i64
944 #endif
946 tcg_target_ulong val;
947 TCGHelperInfo *th;
949 nb_oargs = def->nb_oargs;
950 nb_iargs = def->nb_iargs;
951 nb_cargs = def->nb_cargs;
952 fprintf(outfile, " %s %s,$", def->name,
953 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[0]));
954 val = args[1];
955 th = tcg_find_helper(s, val);
956 if (th) {
957 fprintf(outfile, "%s", th->name);
958 } else {
959 if (c == INDEX_op_movi_i32)
960 fprintf(outfile, "0x%x", (uint32_t)val);
961 else
962 fprintf(outfile, "0x%" PRIx64 , (uint64_t)val);
964 } else {
965 fprintf(outfile, " %s ", def->name);
966 if (c == INDEX_op_nopn) {
967 /* variable number of arguments */
968 nb_cargs = *args;
969 nb_oargs = 0;
970 nb_iargs = 0;
971 } else {
972 nb_oargs = def->nb_oargs;
973 nb_iargs = def->nb_iargs;
974 nb_cargs = def->nb_cargs;
977 k = 0;
978 for(i = 0; i < nb_oargs; i++) {
979 if (k != 0)
980 fprintf(outfile, ",");
981 fprintf(outfile, "%s",
982 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
984 for(i = 0; i < nb_iargs; i++) {
985 if (k != 0)
986 fprintf(outfile, ",");
987 fprintf(outfile, "%s",
988 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
990 switch (c) {
991 case INDEX_op_brcond_i32:
992 #if TCG_TARGET_REG_BITS == 32
993 case INDEX_op_brcond2_i32:
994 #elif TCG_TARGET_REG_BITS == 64
995 case INDEX_op_brcond_i64:
996 #endif
997 case INDEX_op_setcond_i32:
998 #if TCG_TARGET_REG_BITS == 32
999 case INDEX_op_setcond2_i32:
1000 #elif TCG_TARGET_REG_BITS == 64
1001 case INDEX_op_setcond_i64:
1002 #endif
1003 if (args[k] < ARRAY_SIZE(cond_name) && cond_name[args[k]])
1004 fprintf(outfile, ",%s", cond_name[args[k++]]);
1005 else
1006 fprintf(outfile, ",$0x%" TCG_PRIlx, args[k++]);
1007 i = 1;
1008 break;
1009 default:
1010 i = 0;
1011 break;
1013 for(; i < nb_cargs; i++) {
1014 if (k != 0)
1015 fprintf(outfile, ",");
1016 arg = args[k++];
1017 fprintf(outfile, "$0x%" TCG_PRIlx, arg);
1020 fprintf(outfile, "\n");
1021 args += nb_iargs + nb_oargs + nb_cargs;
1025 /* we give more priority to constraints with less registers */
1026 static int get_constraint_priority(const TCGOpDef *def, int k)
1028 const TCGArgConstraint *arg_ct;
1030 int i, n;
1031 arg_ct = &def->args_ct[k];
1032 if (arg_ct->ct & TCG_CT_ALIAS) {
1033 /* an alias is equivalent to a single register */
1034 n = 1;
1035 } else {
1036 if (!(arg_ct->ct & TCG_CT_REG))
1037 return 0;
1038 n = 0;
1039 for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
1040 if (tcg_regset_test_reg(arg_ct->u.regs, i))
1041 n++;
1044 return TCG_TARGET_NB_REGS - n + 1;
1047 /* sort from highest priority to lowest */
1048 static void sort_constraints(TCGOpDef *def, int start, int n)
1050 int i, j, p1, p2, tmp;
1052 for(i = 0; i < n; i++)
1053 def->sorted_args[start + i] = start + i;
1054 if (n <= 1)
1055 return;
1056 for(i = 0; i < n - 1; i++) {
1057 for(j = i + 1; j < n; j++) {
1058 p1 = get_constraint_priority(def, def->sorted_args[start + i]);
1059 p2 = get_constraint_priority(def, def->sorted_args[start + j]);
1060 if (p1 < p2) {
1061 tmp = def->sorted_args[start + i];
1062 def->sorted_args[start + i] = def->sorted_args[start + j];
1063 def->sorted_args[start + j] = tmp;
1069 void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs)
1071 TCGOpcode op;
1072 TCGOpDef *def;
1073 const char *ct_str;
1074 int i, nb_args;
1076 for(;;) {
1077 if (tdefs->op == (TCGOpcode)-1)
1078 break;
1079 op = tdefs->op;
1080 assert((unsigned)op < NB_OPS);
1081 def = &tcg_op_defs[op];
1082 #if defined(CONFIG_DEBUG_TCG)
1083 /* Duplicate entry in op definitions? */
1084 assert(!def->used);
1085 def->used = 1;
1086 #endif
1087 nb_args = def->nb_iargs + def->nb_oargs;
1088 for(i = 0; i < nb_args; i++) {
1089 ct_str = tdefs->args_ct_str[i];
1090 /* Incomplete TCGTargetOpDef entry? */
1091 assert(ct_str != NULL);
1092 tcg_regset_clear(def->args_ct[i].u.regs);
1093 def->args_ct[i].ct = 0;
1094 if (ct_str[0] >= '0' && ct_str[0] <= '9') {
1095 int oarg;
1096 oarg = ct_str[0] - '0';
1097 assert(oarg < def->nb_oargs);
1098 assert(def->args_ct[oarg].ct & TCG_CT_REG);
1099 /* TCG_CT_ALIAS is for the output arguments. The input
1100 argument is tagged with TCG_CT_IALIAS. */
1101 def->args_ct[i] = def->args_ct[oarg];
1102 def->args_ct[oarg].ct = TCG_CT_ALIAS;
1103 def->args_ct[oarg].alias_index = i;
1104 def->args_ct[i].ct |= TCG_CT_IALIAS;
1105 def->args_ct[i].alias_index = oarg;
1106 } else {
1107 for(;;) {
1108 if (*ct_str == '\0')
1109 break;
1110 switch(*ct_str) {
1111 case 'i':
1112 def->args_ct[i].ct |= TCG_CT_CONST;
1113 ct_str++;
1114 break;
1115 default:
1116 if (target_parse_constraint(&def->args_ct[i], &ct_str) < 0) {
1117 fprintf(stderr, "Invalid constraint '%s' for arg %d of operation '%s'\n",
1118 ct_str, i, def->name);
1119 exit(1);
1126 /* TCGTargetOpDef entry with too much information? */
1127 assert(i == TCG_MAX_OP_ARGS || tdefs->args_ct_str[i] == NULL);
1129 /* sort the constraints (XXX: this is just an heuristic) */
1130 sort_constraints(def, 0, def->nb_oargs);
1131 sort_constraints(def, def->nb_oargs, def->nb_iargs);
1133 #if 0
1135 int i;
1137 printf("%s: sorted=", def->name);
1138 for(i = 0; i < def->nb_oargs + def->nb_iargs; i++)
1139 printf(" %d", def->sorted_args[i]);
1140 printf("\n");
1142 #endif
1143 tdefs++;
1146 #if defined(CONFIG_DEBUG_TCG)
1147 i = 0;
1148 for (op = 0; op < ARRAY_SIZE(tcg_op_defs); op++) {
1149 const TCGOpDef *def = &tcg_op_defs[op];
1150 if (op < INDEX_op_call
1151 || op == INDEX_op_debug_insn_start
1152 || (def->flags & TCG_OPF_NOT_PRESENT)) {
1153 /* Wrong entry in op definitions? */
1154 if (def->used) {
1155 fprintf(stderr, "Invalid op definition for %s\n", def->name);
1156 i = 1;
1158 } else {
1159 /* Missing entry in op definitions? */
1160 if (!def->used) {
1161 fprintf(stderr, "Missing op definition for %s\n", def->name);
1162 i = 1;
1166 if (i == 1) {
1167 tcg_abort();
1169 #endif
1172 #ifdef USE_LIVENESS_ANALYSIS
1174 /* set a nop for an operation using 'nb_args' */
1175 static inline void tcg_set_nop(TCGContext *s, uint16_t *opc_ptr,
1176 TCGArg *args, int nb_args)
1178 if (nb_args == 0) {
1179 *opc_ptr = INDEX_op_nop;
1180 } else {
1181 *opc_ptr = INDEX_op_nopn;
1182 args[0] = nb_args;
1183 args[nb_args - 1] = nb_args;
1187 /* liveness analysis: end of function: globals are live, temps are
1188 dead. */
1189 /* XXX: at this stage, not used as there would be little gains because
1190 most TBs end with a conditional jump. */
1191 static inline void tcg_la_func_end(TCGContext *s, uint8_t *dead_temps)
1193 memset(dead_temps, 0, s->nb_globals);
1194 memset(dead_temps + s->nb_globals, 1, s->nb_temps - s->nb_globals);
1197 /* liveness analysis: end of basic block: globals are live, temps are
1198 dead, local temps are live. */
1199 static inline void tcg_la_bb_end(TCGContext *s, uint8_t *dead_temps)
1201 int i;
1202 TCGTemp *ts;
1204 memset(dead_temps, 0, s->nb_globals);
1205 ts = &s->temps[s->nb_globals];
1206 for(i = s->nb_globals; i < s->nb_temps; i++) {
1207 if (ts->temp_local)
1208 dead_temps[i] = 0;
1209 else
1210 dead_temps[i] = 1;
1211 ts++;
1215 /* Liveness analysis : update the opc_dead_args array to tell if a
1216 given input arguments is dead. Instructions updating dead
1217 temporaries are removed. */
1218 static void tcg_liveness_analysis(TCGContext *s)
1220 int i, op_index, nb_args, nb_iargs, nb_oargs, arg, nb_ops;
1221 TCGOpcode op;
1222 TCGArg *args;
1223 const TCGOpDef *def;
1224 uint8_t *dead_temps;
1225 unsigned int dead_args;
1227 gen_opc_ptr++; /* skip end */
1229 nb_ops = gen_opc_ptr - gen_opc_buf;
1231 s->op_dead_args = tcg_malloc(nb_ops * sizeof(uint16_t));
1233 dead_temps = tcg_malloc(s->nb_temps);
1234 memset(dead_temps, 1, s->nb_temps);
1236 args = gen_opparam_ptr;
1237 op_index = nb_ops - 1;
1238 while (op_index >= 0) {
1239 op = gen_opc_buf[op_index];
1240 def = &tcg_op_defs[op];
1241 switch(op) {
1242 case INDEX_op_call:
1244 int call_flags;
1246 nb_args = args[-1];
1247 args -= nb_args;
1248 nb_iargs = args[0] & 0xffff;
1249 nb_oargs = args[0] >> 16;
1250 args++;
1251 call_flags = args[nb_oargs + nb_iargs];
1253 /* pure functions can be removed if their result is not
1254 used */
1255 if (call_flags & TCG_CALL_PURE) {
1256 for(i = 0; i < nb_oargs; i++) {
1257 arg = args[i];
1258 if (!dead_temps[arg])
1259 goto do_not_remove_call;
1261 tcg_set_nop(s, gen_opc_buf + op_index,
1262 args - 1, nb_args);
1263 } else {
1264 do_not_remove_call:
1266 /* output args are dead */
1267 dead_args = 0;
1268 for(i = 0; i < nb_oargs; i++) {
1269 arg = args[i];
1270 if (dead_temps[arg]) {
1271 dead_args |= (1 << i);
1273 dead_temps[arg] = 1;
1276 if (!(call_flags & TCG_CALL_CONST)) {
1277 /* globals are live (they may be used by the call) */
1278 memset(dead_temps, 0, s->nb_globals);
1281 /* input args are live */
1282 for(i = nb_oargs; i < nb_iargs + nb_oargs; i++) {
1283 arg = args[i];
1284 if (arg != TCG_CALL_DUMMY_ARG) {
1285 if (dead_temps[arg]) {
1286 dead_args |= (1 << i);
1288 dead_temps[arg] = 0;
1291 s->op_dead_args[op_index] = dead_args;
1293 args--;
1295 break;
1296 case INDEX_op_set_label:
1297 args--;
1298 /* mark end of basic block */
1299 tcg_la_bb_end(s, dead_temps);
1300 break;
1301 case INDEX_op_debug_insn_start:
1302 args -= def->nb_args;
1303 break;
1304 case INDEX_op_nopn:
1305 nb_args = args[-1];
1306 args -= nb_args;
1307 break;
1308 case INDEX_op_discard:
1309 args--;
1310 /* mark the temporary as dead */
1311 dead_temps[args[0]] = 1;
1312 break;
1313 case INDEX_op_end:
1314 break;
1315 /* XXX: optimize by hardcoding common cases (e.g. triadic ops) */
1316 default:
1317 args -= def->nb_args;
1318 nb_iargs = def->nb_iargs;
1319 nb_oargs = def->nb_oargs;
1321 /* Test if the operation can be removed because all
1322 its outputs are dead. We assume that nb_oargs == 0
1323 implies side effects */
1324 if (!(def->flags & TCG_OPF_SIDE_EFFECTS) && nb_oargs != 0) {
1325 for(i = 0; i < nb_oargs; i++) {
1326 arg = args[i];
1327 if (!dead_temps[arg])
1328 goto do_not_remove;
1330 tcg_set_nop(s, gen_opc_buf + op_index, args, def->nb_args);
1331 #ifdef CONFIG_PROFILER
1332 s->del_op_count++;
1333 #endif
1334 } else {
1335 do_not_remove:
1337 /* output args are dead */
1338 dead_args = 0;
1339 for(i = 0; i < nb_oargs; i++) {
1340 arg = args[i];
1341 if (dead_temps[arg]) {
1342 dead_args |= (1 << i);
1344 dead_temps[arg] = 1;
1347 /* if end of basic block, update */
1348 if (def->flags & TCG_OPF_BB_END) {
1349 tcg_la_bb_end(s, dead_temps);
1350 } else if (def->flags & TCG_OPF_CALL_CLOBBER) {
1351 /* globals are live */
1352 memset(dead_temps, 0, s->nb_globals);
1355 /* input args are live */
1356 for(i = nb_oargs; i < nb_oargs + nb_iargs; i++) {
1357 arg = args[i];
1358 if (dead_temps[arg]) {
1359 dead_args |= (1 << i);
1361 dead_temps[arg] = 0;
1363 s->op_dead_args[op_index] = dead_args;
1365 break;
1367 op_index--;
1370 if (args != gen_opparam_buf)
1371 tcg_abort();
1373 #else
1374 /* dummy liveness analysis */
1375 static void tcg_liveness_analysis(TCGContext *s)
1377 int nb_ops;
1378 nb_ops = gen_opc_ptr - gen_opc_buf;
1380 s->op_dead_args = tcg_malloc(nb_ops * sizeof(uint16_t));
1381 memset(s->op_dead_args, 0, nb_ops * sizeof(uint16_t));
1383 #endif
1385 #ifndef NDEBUG
1386 static void dump_regs(TCGContext *s)
1388 TCGTemp *ts;
1389 int i;
1390 char buf[64];
1392 for(i = 0; i < s->nb_temps; i++) {
1393 ts = &s->temps[i];
1394 printf(" %10s: ", tcg_get_arg_str_idx(s, buf, sizeof(buf), i));
1395 switch(ts->val_type) {
1396 case TEMP_VAL_REG:
1397 printf("%s", tcg_target_reg_names[ts->reg]);
1398 break;
1399 case TEMP_VAL_MEM:
1400 printf("%d(%s)", (int)ts->mem_offset, tcg_target_reg_names[ts->mem_reg]);
1401 break;
1402 case TEMP_VAL_CONST:
1403 printf("$0x%" TCG_PRIlx, ts->val);
1404 break;
1405 case TEMP_VAL_DEAD:
1406 printf("D");
1407 break;
1408 default:
1409 printf("???");
1410 break;
1412 printf("\n");
1415 for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
1416 if (s->reg_to_temp[i] >= 0) {
1417 printf("%s: %s\n",
1418 tcg_target_reg_names[i],
1419 tcg_get_arg_str_idx(s, buf, sizeof(buf), s->reg_to_temp[i]));
1424 static void check_regs(TCGContext *s)
1426 int reg, k;
1427 TCGTemp *ts;
1428 char buf[64];
1430 for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1431 k = s->reg_to_temp[reg];
1432 if (k >= 0) {
1433 ts = &s->temps[k];
1434 if (ts->val_type != TEMP_VAL_REG ||
1435 ts->reg != reg) {
1436 printf("Inconsistency for register %s:\n",
1437 tcg_target_reg_names[reg]);
1438 goto fail;
1442 for(k = 0; k < s->nb_temps; k++) {
1443 ts = &s->temps[k];
1444 if (ts->val_type == TEMP_VAL_REG &&
1445 !ts->fixed_reg &&
1446 s->reg_to_temp[ts->reg] != k) {
1447 printf("Inconsistency for temp %s:\n",
1448 tcg_get_arg_str_idx(s, buf, sizeof(buf), k));
1449 fail:
1450 printf("reg state:\n");
1451 dump_regs(s);
1452 tcg_abort();
1456 #endif
1458 static void temp_allocate_frame(TCGContext *s, int temp)
1460 TCGTemp *ts;
1461 ts = &s->temps[temp];
1462 #ifndef __sparc_v9__ /* Sparc64 stack is accessed with offset of 2047 */
1463 s->current_frame_offset = (s->current_frame_offset +
1464 (tcg_target_long)sizeof(tcg_target_long) - 1) &
1465 ~(sizeof(tcg_target_long) - 1);
1466 #endif
1467 if (s->current_frame_offset + (tcg_target_long)sizeof(tcg_target_long) >
1468 s->frame_end) {
1469 tcg_abort();
1471 ts->mem_offset = s->current_frame_offset;
1472 ts->mem_reg = s->frame_reg;
1473 ts->mem_allocated = 1;
1474 s->current_frame_offset += (tcg_target_long)sizeof(tcg_target_long);
1477 /* free register 'reg' by spilling the corresponding temporary if necessary */
1478 static void tcg_reg_free(TCGContext *s, int reg)
1480 TCGTemp *ts;
1481 int temp;
1483 temp = s->reg_to_temp[reg];
1484 if (temp != -1) {
1485 ts = &s->temps[temp];
1486 assert(ts->val_type == TEMP_VAL_REG);
1487 if (!ts->mem_coherent) {
1488 if (!ts->mem_allocated)
1489 temp_allocate_frame(s, temp);
1490 tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1492 ts->val_type = TEMP_VAL_MEM;
1493 s->reg_to_temp[reg] = -1;
1497 /* Allocate a register belonging to reg1 & ~reg2 */
1498 static int tcg_reg_alloc(TCGContext *s, TCGRegSet reg1, TCGRegSet reg2)
1500 int i, reg;
1501 TCGRegSet reg_ct;
1503 tcg_regset_andnot(reg_ct, reg1, reg2);
1505 /* first try free registers */
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) && s->reg_to_temp[reg] == -1)
1509 return reg;
1512 /* XXX: do better spill choice */
1513 for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1514 reg = tcg_target_reg_alloc_order[i];
1515 if (tcg_regset_test_reg(reg_ct, reg)) {
1516 tcg_reg_free(s, reg);
1517 return reg;
1521 tcg_abort();
1524 /* save a temporary to memory. 'allocated_regs' is used in case a
1525 temporary registers needs to be allocated to store a constant. */
1526 static void temp_save(TCGContext *s, int temp, TCGRegSet allocated_regs)
1528 TCGTemp *ts;
1529 int reg;
1531 ts = &s->temps[temp];
1532 if (!ts->fixed_reg) {
1533 switch(ts->val_type) {
1534 case TEMP_VAL_REG:
1535 tcg_reg_free(s, ts->reg);
1536 break;
1537 case TEMP_VAL_DEAD:
1538 ts->val_type = TEMP_VAL_MEM;
1539 break;
1540 case TEMP_VAL_CONST:
1541 reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type],
1542 allocated_regs);
1543 if (!ts->mem_allocated)
1544 temp_allocate_frame(s, temp);
1545 tcg_out_movi(s, ts->type, reg, ts->val);
1546 tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1547 ts->val_type = TEMP_VAL_MEM;
1548 break;
1549 case TEMP_VAL_MEM:
1550 break;
1551 default:
1552 tcg_abort();
1557 /* save globals to their cannonical location and assume they can be
1558 modified be the following code. 'allocated_regs' is used in case a
1559 temporary registers needs to be allocated to store a constant. */
1560 static void save_globals(TCGContext *s, TCGRegSet allocated_regs)
1562 int i;
1564 for(i = 0; i < s->nb_globals; i++) {
1565 temp_save(s, i, allocated_regs);
1569 /* at the end of a basic block, we assume all temporaries are dead and
1570 all globals are stored at their canonical location. */
1571 static void tcg_reg_alloc_bb_end(TCGContext *s, TCGRegSet allocated_regs)
1573 TCGTemp *ts;
1574 int i;
1576 for(i = s->nb_globals; i < s->nb_temps; i++) {
1577 ts = &s->temps[i];
1578 if (ts->temp_local) {
1579 temp_save(s, i, allocated_regs);
1580 } else {
1581 if (ts->val_type == TEMP_VAL_REG) {
1582 s->reg_to_temp[ts->reg] = -1;
1584 ts->val_type = TEMP_VAL_DEAD;
1588 save_globals(s, allocated_regs);
1591 #define IS_DEAD_ARG(n) ((dead_args >> (n)) & 1)
1593 static void tcg_reg_alloc_movi(TCGContext *s, const TCGArg *args)
1595 TCGTemp *ots;
1596 tcg_target_ulong val;
1598 ots = &s->temps[args[0]];
1599 val = args[1];
1601 if (ots->fixed_reg) {
1602 /* for fixed registers, we do not do any constant
1603 propagation */
1604 tcg_out_movi(s, ots->type, ots->reg, val);
1605 } else {
1606 /* The movi is not explicitly generated here */
1607 if (ots->val_type == TEMP_VAL_REG)
1608 s->reg_to_temp[ots->reg] = -1;
1609 ots->val_type = TEMP_VAL_CONST;
1610 ots->val = val;
1614 static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
1615 const TCGArg *args,
1616 unsigned int dead_args)
1618 TCGTemp *ts, *ots;
1619 int reg;
1620 const TCGArgConstraint *arg_ct;
1622 ots = &s->temps[args[0]];
1623 ts = &s->temps[args[1]];
1624 arg_ct = &def->args_ct[0];
1626 /* XXX: always mark arg dead if IS_DEAD_ARG(1) */
1627 if (ts->val_type == TEMP_VAL_REG) {
1628 if (IS_DEAD_ARG(1) && !ts->fixed_reg && !ots->fixed_reg) {
1629 /* the mov can be suppressed */
1630 if (ots->val_type == TEMP_VAL_REG)
1631 s->reg_to_temp[ots->reg] = -1;
1632 reg = ts->reg;
1633 s->reg_to_temp[reg] = -1;
1634 ts->val_type = TEMP_VAL_DEAD;
1635 } else {
1636 if (ots->val_type == TEMP_VAL_REG) {
1637 reg = ots->reg;
1638 } else {
1639 reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1641 if (ts->reg != reg) {
1642 tcg_out_mov(s, ots->type, reg, ts->reg);
1645 } else if (ts->val_type == TEMP_VAL_MEM) {
1646 if (ots->val_type == TEMP_VAL_REG) {
1647 reg = ots->reg;
1648 } else {
1649 reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1651 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1652 } else if (ts->val_type == TEMP_VAL_CONST) {
1653 if (ots->fixed_reg) {
1654 reg = ots->reg;
1655 tcg_out_movi(s, ots->type, reg, ts->val);
1656 } else {
1657 /* propagate constant */
1658 if (ots->val_type == TEMP_VAL_REG)
1659 s->reg_to_temp[ots->reg] = -1;
1660 ots->val_type = TEMP_VAL_CONST;
1661 ots->val = ts->val;
1662 return;
1664 } else {
1665 tcg_abort();
1667 s->reg_to_temp[reg] = args[0];
1668 ots->reg = reg;
1669 ots->val_type = TEMP_VAL_REG;
1670 ots->mem_coherent = 0;
1673 static void tcg_reg_alloc_op(TCGContext *s,
1674 const TCGOpDef *def, TCGOpcode opc,
1675 const TCGArg *args,
1676 unsigned int dead_args)
1678 TCGRegSet allocated_regs;
1679 int i, k, nb_iargs, nb_oargs, reg;
1680 TCGArg arg;
1681 const TCGArgConstraint *arg_ct;
1682 TCGTemp *ts;
1683 TCGArg new_args[TCG_MAX_OP_ARGS];
1684 int const_args[TCG_MAX_OP_ARGS];
1686 nb_oargs = def->nb_oargs;
1687 nb_iargs = def->nb_iargs;
1689 /* copy constants */
1690 memcpy(new_args + nb_oargs + nb_iargs,
1691 args + nb_oargs + nb_iargs,
1692 sizeof(TCGArg) * def->nb_cargs);
1694 /* satisfy input constraints */
1695 tcg_regset_set(allocated_regs, s->reserved_regs);
1696 for(k = 0; k < nb_iargs; k++) {
1697 i = def->sorted_args[nb_oargs + k];
1698 arg = args[i];
1699 arg_ct = &def->args_ct[i];
1700 ts = &s->temps[arg];
1701 if (ts->val_type == TEMP_VAL_MEM) {
1702 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1703 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1704 ts->val_type = TEMP_VAL_REG;
1705 ts->reg = reg;
1706 ts->mem_coherent = 1;
1707 s->reg_to_temp[reg] = arg;
1708 } else if (ts->val_type == TEMP_VAL_CONST) {
1709 if (tcg_target_const_match(ts->val, arg_ct)) {
1710 /* constant is OK for instruction */
1711 const_args[i] = 1;
1712 new_args[i] = ts->val;
1713 goto iarg_end;
1714 } else {
1715 /* need to move to a register */
1716 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1717 tcg_out_movi(s, ts->type, reg, ts->val);
1718 ts->val_type = TEMP_VAL_REG;
1719 ts->reg = reg;
1720 ts->mem_coherent = 0;
1721 s->reg_to_temp[reg] = arg;
1724 assert(ts->val_type == TEMP_VAL_REG);
1725 if (arg_ct->ct & TCG_CT_IALIAS) {
1726 if (ts->fixed_reg) {
1727 /* if fixed register, we must allocate a new register
1728 if the alias is not the same register */
1729 if (arg != args[arg_ct->alias_index])
1730 goto allocate_in_reg;
1731 } else {
1732 /* if the input is aliased to an output and if it is
1733 not dead after the instruction, we must allocate
1734 a new register and move it */
1735 if (!IS_DEAD_ARG(i)) {
1736 goto allocate_in_reg;
1740 reg = ts->reg;
1741 if (tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1742 /* nothing to do : the constraint is satisfied */
1743 } else {
1744 allocate_in_reg:
1745 /* allocate a new register matching the constraint
1746 and move the temporary register into it */
1747 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1748 tcg_out_mov(s, ts->type, reg, ts->reg);
1750 new_args[i] = reg;
1751 const_args[i] = 0;
1752 tcg_regset_set_reg(allocated_regs, reg);
1753 iarg_end: ;
1756 if (def->flags & TCG_OPF_BB_END) {
1757 tcg_reg_alloc_bb_end(s, allocated_regs);
1758 } else {
1759 /* mark dead temporaries and free the associated registers */
1760 for(i = nb_oargs; i < nb_oargs + nb_iargs; i++) {
1761 arg = args[i];
1762 if (IS_DEAD_ARG(i)) {
1763 ts = &s->temps[arg];
1764 if (!ts->fixed_reg) {
1765 if (ts->val_type == TEMP_VAL_REG)
1766 s->reg_to_temp[ts->reg] = -1;
1767 ts->val_type = TEMP_VAL_DEAD;
1772 if (def->flags & TCG_OPF_CALL_CLOBBER) {
1773 /* XXX: permit generic clobber register list ? */
1774 for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1775 if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
1776 tcg_reg_free(s, reg);
1779 /* XXX: for load/store we could do that only for the slow path
1780 (i.e. when a memory callback is called) */
1782 /* store globals and free associated registers (we assume the insn
1783 can modify any global. */
1784 save_globals(s, allocated_regs);
1787 /* satisfy the output constraints */
1788 tcg_regset_set(allocated_regs, s->reserved_regs);
1789 for(k = 0; k < nb_oargs; k++) {
1790 i = def->sorted_args[k];
1791 arg = args[i];
1792 arg_ct = &def->args_ct[i];
1793 ts = &s->temps[arg];
1794 if (arg_ct->ct & TCG_CT_ALIAS) {
1795 reg = new_args[arg_ct->alias_index];
1796 } else {
1797 /* if fixed register, we try to use it */
1798 reg = ts->reg;
1799 if (ts->fixed_reg &&
1800 tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1801 goto oarg_end;
1803 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1805 tcg_regset_set_reg(allocated_regs, reg);
1806 /* if a fixed register is used, then a move will be done afterwards */
1807 if (!ts->fixed_reg) {
1808 if (ts->val_type == TEMP_VAL_REG)
1809 s->reg_to_temp[ts->reg] = -1;
1810 if (IS_DEAD_ARG(i)) {
1811 ts->val_type = TEMP_VAL_DEAD;
1812 } else {
1813 ts->val_type = TEMP_VAL_REG;
1814 ts->reg = reg;
1815 /* temp value is modified, so the value kept in memory is
1816 potentially not the same */
1817 ts->mem_coherent = 0;
1818 s->reg_to_temp[reg] = arg;
1821 oarg_end:
1822 new_args[i] = reg;
1826 /* emit instruction */
1827 tcg_out_op(s, opc, new_args, const_args);
1829 /* move the outputs in the correct register if needed */
1830 for(i = 0; i < nb_oargs; i++) {
1831 ts = &s->temps[args[i]];
1832 reg = new_args[i];
1833 if (ts->fixed_reg && ts->reg != reg) {
1834 tcg_out_mov(s, ts->type, ts->reg, reg);
1839 #ifdef TCG_TARGET_STACK_GROWSUP
1840 #define STACK_DIR(x) (-(x))
1841 #else
1842 #define STACK_DIR(x) (x)
1843 #endif
1845 static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
1846 TCGOpcode opc, const TCGArg *args,
1847 unsigned int dead_args)
1849 int nb_iargs, nb_oargs, flags, nb_regs, i, reg, nb_params;
1850 TCGArg arg, func_arg;
1851 TCGTemp *ts;
1852 tcg_target_long stack_offset, call_stack_size, func_addr;
1853 int const_func_arg, allocate_args;
1854 TCGRegSet allocated_regs;
1855 const TCGArgConstraint *arg_ct;
1857 arg = *args++;
1859 nb_oargs = arg >> 16;
1860 nb_iargs = arg & 0xffff;
1861 nb_params = nb_iargs - 1;
1863 flags = args[nb_oargs + nb_iargs];
1865 nb_regs = tcg_target_get_call_iarg_regs_count(flags);
1866 if (nb_regs > nb_params)
1867 nb_regs = nb_params;
1869 /* assign stack slots first */
1870 call_stack_size = (nb_params - nb_regs) * sizeof(tcg_target_long);
1871 call_stack_size = (call_stack_size + TCG_TARGET_STACK_ALIGN - 1) &
1872 ~(TCG_TARGET_STACK_ALIGN - 1);
1873 allocate_args = (call_stack_size > TCG_STATIC_CALL_ARGS_SIZE);
1874 if (allocate_args) {
1875 /* XXX: if more than TCG_STATIC_CALL_ARGS_SIZE is needed,
1876 preallocate call stack */
1877 tcg_abort();
1880 stack_offset = TCG_TARGET_CALL_STACK_OFFSET;
1881 for(i = nb_regs; i < nb_params; i++) {
1882 arg = args[nb_oargs + i];
1883 #ifdef TCG_TARGET_STACK_GROWSUP
1884 stack_offset -= sizeof(tcg_target_long);
1885 #endif
1886 if (arg != TCG_CALL_DUMMY_ARG) {
1887 ts = &s->temps[arg];
1888 if (ts->val_type == TEMP_VAL_REG) {
1889 tcg_out_st(s, ts->type, ts->reg, TCG_REG_CALL_STACK, stack_offset);
1890 } else if (ts->val_type == TEMP_VAL_MEM) {
1891 reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type],
1892 s->reserved_regs);
1893 /* XXX: not correct if reading values from the stack */
1894 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1895 tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
1896 } else if (ts->val_type == TEMP_VAL_CONST) {
1897 reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type],
1898 s->reserved_regs);
1899 /* XXX: sign extend may be needed on some targets */
1900 tcg_out_movi(s, ts->type, reg, ts->val);
1901 tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
1902 } else {
1903 tcg_abort();
1906 #ifndef TCG_TARGET_STACK_GROWSUP
1907 stack_offset += sizeof(tcg_target_long);
1908 #endif
1911 /* assign input registers */
1912 tcg_regset_set(allocated_regs, s->reserved_regs);
1913 for(i = 0; i < nb_regs; i++) {
1914 arg = args[nb_oargs + i];
1915 if (arg != TCG_CALL_DUMMY_ARG) {
1916 ts = &s->temps[arg];
1917 reg = tcg_target_call_iarg_regs[i];
1918 tcg_reg_free(s, reg);
1919 if (ts->val_type == TEMP_VAL_REG) {
1920 if (ts->reg != reg) {
1921 tcg_out_mov(s, ts->type, reg, ts->reg);
1923 } else if (ts->val_type == TEMP_VAL_MEM) {
1924 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1925 } else if (ts->val_type == TEMP_VAL_CONST) {
1926 /* XXX: sign extend ? */
1927 tcg_out_movi(s, ts->type, reg, ts->val);
1928 } else {
1929 tcg_abort();
1931 tcg_regset_set_reg(allocated_regs, reg);
1935 /* assign function address */
1936 func_arg = args[nb_oargs + nb_iargs - 1];
1937 arg_ct = &def->args_ct[0];
1938 ts = &s->temps[func_arg];
1939 func_addr = ts->val;
1940 const_func_arg = 0;
1941 if (ts->val_type == TEMP_VAL_MEM) {
1942 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1943 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1944 func_arg = reg;
1945 tcg_regset_set_reg(allocated_regs, reg);
1946 } else if (ts->val_type == TEMP_VAL_REG) {
1947 reg = ts->reg;
1948 if (!tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1949 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1950 tcg_out_mov(s, ts->type, reg, ts->reg);
1952 func_arg = reg;
1953 tcg_regset_set_reg(allocated_regs, reg);
1954 } else if (ts->val_type == TEMP_VAL_CONST) {
1955 if (tcg_target_const_match(func_addr, arg_ct)) {
1956 const_func_arg = 1;
1957 func_arg = func_addr;
1958 } else {
1959 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1960 tcg_out_movi(s, ts->type, reg, func_addr);
1961 func_arg = reg;
1962 tcg_regset_set_reg(allocated_regs, reg);
1964 } else {
1965 tcg_abort();
1969 /* mark dead temporaries and free the associated registers */
1970 for(i = nb_oargs; i < nb_iargs + nb_oargs; i++) {
1971 arg = args[i];
1972 if (IS_DEAD_ARG(i)) {
1973 ts = &s->temps[arg];
1974 if (!ts->fixed_reg) {
1975 if (ts->val_type == TEMP_VAL_REG)
1976 s->reg_to_temp[ts->reg] = -1;
1977 ts->val_type = TEMP_VAL_DEAD;
1982 /* clobber call registers */
1983 for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1984 if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
1985 tcg_reg_free(s, reg);
1989 /* store globals and free associated registers (we assume the call
1990 can modify any global. */
1991 if (!(flags & TCG_CALL_CONST)) {
1992 save_globals(s, allocated_regs);
1995 tcg_out_op(s, opc, &func_arg, &const_func_arg);
1997 /* assign output registers and emit moves if needed */
1998 for(i = 0; i < nb_oargs; i++) {
1999 arg = args[i];
2000 ts = &s->temps[arg];
2001 reg = tcg_target_call_oarg_regs[i];
2002 assert(s->reg_to_temp[reg] == -1);
2003 if (ts->fixed_reg) {
2004 if (ts->reg != reg) {
2005 tcg_out_mov(s, ts->type, ts->reg, reg);
2007 } else {
2008 if (ts->val_type == TEMP_VAL_REG)
2009 s->reg_to_temp[ts->reg] = -1;
2010 if (IS_DEAD_ARG(i)) {
2011 ts->val_type = TEMP_VAL_DEAD;
2012 } else {
2013 ts->val_type = TEMP_VAL_REG;
2014 ts->reg = reg;
2015 ts->mem_coherent = 0;
2016 s->reg_to_temp[reg] = arg;
2021 return nb_iargs + nb_oargs + def->nb_cargs + 1;
2024 #ifdef CONFIG_PROFILER
2026 static int64_t tcg_table_op_count[NB_OPS];
2028 static void dump_op_count(void)
2030 int i;
2031 FILE *f;
2032 f = fopen("/tmp/op.log", "w");
2033 for(i = INDEX_op_end; i < NB_OPS; i++) {
2034 fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name, tcg_table_op_count[i]);
2036 fclose(f);
2038 #endif
2041 static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
2042 long search_pc)
2044 TCGOpcode opc;
2045 int op_index;
2046 const TCGOpDef *def;
2047 unsigned int dead_args;
2048 const TCGArg *args;
2050 #ifdef DEBUG_DISAS
2051 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
2052 qemu_log("OP:\n");
2053 tcg_dump_ops(s, logfile);
2054 qemu_log("\n");
2056 #endif
2058 #ifdef USE_TCG_OPTIMIZATIONS
2059 gen_opparam_ptr =
2060 tcg_optimize(s, gen_opc_ptr, gen_opparam_buf, tcg_op_defs);
2061 #endif
2063 #ifdef CONFIG_PROFILER
2064 s->la_time -= profile_getclock();
2065 #endif
2066 tcg_liveness_analysis(s);
2067 #ifdef CONFIG_PROFILER
2068 s->la_time += profile_getclock();
2069 #endif
2071 #ifdef DEBUG_DISAS
2072 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_OPT))) {
2073 qemu_log("OP after liveness analysis:\n");
2074 tcg_dump_ops(s, logfile);
2075 qemu_log("\n");
2077 #endif
2079 tcg_reg_alloc_start(s);
2081 s->code_buf = gen_code_buf;
2082 s->code_ptr = gen_code_buf;
2084 args = gen_opparam_buf;
2085 op_index = 0;
2087 for(;;) {
2088 opc = gen_opc_buf[op_index];
2089 #ifdef CONFIG_PROFILER
2090 tcg_table_op_count[opc]++;
2091 #endif
2092 def = &tcg_op_defs[opc];
2093 #if 0
2094 printf("%s: %d %d %d\n", def->name,
2095 def->nb_oargs, def->nb_iargs, def->nb_cargs);
2096 // dump_regs(s);
2097 #endif
2098 switch(opc) {
2099 case INDEX_op_mov_i32:
2100 #if TCG_TARGET_REG_BITS == 64
2101 case INDEX_op_mov_i64:
2102 #endif
2103 dead_args = s->op_dead_args[op_index];
2104 tcg_reg_alloc_mov(s, def, args, dead_args);
2105 break;
2106 case INDEX_op_movi_i32:
2107 #if TCG_TARGET_REG_BITS == 64
2108 case INDEX_op_movi_i64:
2109 #endif
2110 tcg_reg_alloc_movi(s, args);
2111 break;
2112 case INDEX_op_debug_insn_start:
2113 /* debug instruction */
2114 break;
2115 case INDEX_op_nop:
2116 case INDEX_op_nop1:
2117 case INDEX_op_nop2:
2118 case INDEX_op_nop3:
2119 break;
2120 case INDEX_op_nopn:
2121 args += args[0];
2122 goto next;
2123 case INDEX_op_discard:
2125 TCGTemp *ts;
2126 ts = &s->temps[args[0]];
2127 /* mark the temporary as dead */
2128 if (!ts->fixed_reg) {
2129 if (ts->val_type == TEMP_VAL_REG)
2130 s->reg_to_temp[ts->reg] = -1;
2131 ts->val_type = TEMP_VAL_DEAD;
2134 break;
2135 case INDEX_op_set_label:
2136 tcg_reg_alloc_bb_end(s, s->reserved_regs);
2137 tcg_out_label(s, args[0], (long)s->code_ptr);
2138 break;
2139 case INDEX_op_call:
2140 dead_args = s->op_dead_args[op_index];
2141 args += tcg_reg_alloc_call(s, def, opc, args, dead_args);
2142 goto next;
2143 case INDEX_op_end:
2144 goto the_end;
2145 default:
2146 /* Sanity check that we've not introduced any unhandled opcodes. */
2147 if (def->flags & TCG_OPF_NOT_PRESENT) {
2148 tcg_abort();
2150 /* Note: in order to speed up the code, it would be much
2151 faster to have specialized register allocator functions for
2152 some common argument patterns */
2153 dead_args = s->op_dead_args[op_index];
2154 tcg_reg_alloc_op(s, def, opc, args, dead_args);
2155 break;
2157 args += def->nb_args;
2158 next:
2159 if (search_pc >= 0 && search_pc < s->code_ptr - gen_code_buf) {
2160 return op_index;
2162 op_index++;
2163 #ifndef NDEBUG
2164 check_regs(s);
2165 #endif
2167 the_end:
2168 return -1;
2171 int tcg_gen_code(TCGContext *s, uint8_t *gen_code_buf)
2173 #ifdef CONFIG_PROFILER
2175 int n;
2176 n = (gen_opc_ptr - gen_opc_buf);
2177 s->op_count += n;
2178 if (n > s->op_count_max)
2179 s->op_count_max = n;
2181 s->temp_count += s->nb_temps;
2182 if (s->nb_temps > s->temp_count_max)
2183 s->temp_count_max = s->nb_temps;
2185 #endif
2187 tcg_gen_code_common(s, gen_code_buf, -1);
2189 /* flush instruction cache */
2190 flush_icache_range((unsigned long)gen_code_buf,
2191 (unsigned long)s->code_ptr);
2192 return s->code_ptr - gen_code_buf;
2195 /* Return the index of the micro operation such as the pc after is <
2196 offset bytes from the start of the TB. The contents of gen_code_buf must
2197 not be changed, though writing the same values is ok.
2198 Return -1 if not found. */
2199 int tcg_gen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, long offset)
2201 return tcg_gen_code_common(s, gen_code_buf, offset);
2204 #ifdef CONFIG_PROFILER
2205 void tcg_dump_info(FILE *f, fprintf_function cpu_fprintf)
2207 TCGContext *s = &tcg_ctx;
2208 int64_t tot;
2210 tot = s->interm_time + s->code_time;
2211 cpu_fprintf(f, "JIT cycles %" PRId64 " (%0.3f s at 2.4 GHz)\n",
2212 tot, tot / 2.4e9);
2213 cpu_fprintf(f, "translated TBs %" PRId64 " (aborted=%" PRId64 " %0.1f%%)\n",
2214 s->tb_count,
2215 s->tb_count1 - s->tb_count,
2216 s->tb_count1 ? (double)(s->tb_count1 - s->tb_count) / s->tb_count1 * 100.0 : 0);
2217 cpu_fprintf(f, "avg ops/TB %0.1f max=%d\n",
2218 s->tb_count ? (double)s->op_count / s->tb_count : 0, s->op_count_max);
2219 cpu_fprintf(f, "deleted ops/TB %0.2f\n",
2220 s->tb_count ?
2221 (double)s->del_op_count / s->tb_count : 0);
2222 cpu_fprintf(f, "avg temps/TB %0.2f max=%d\n",
2223 s->tb_count ?
2224 (double)s->temp_count / s->tb_count : 0,
2225 s->temp_count_max);
2227 cpu_fprintf(f, "cycles/op %0.1f\n",
2228 s->op_count ? (double)tot / s->op_count : 0);
2229 cpu_fprintf(f, "cycles/in byte %0.1f\n",
2230 s->code_in_len ? (double)tot / s->code_in_len : 0);
2231 cpu_fprintf(f, "cycles/out byte %0.1f\n",
2232 s->code_out_len ? (double)tot / s->code_out_len : 0);
2233 if (tot == 0)
2234 tot = 1;
2235 cpu_fprintf(f, " gen_interm time %0.1f%%\n",
2236 (double)s->interm_time / tot * 100.0);
2237 cpu_fprintf(f, " gen_code time %0.1f%%\n",
2238 (double)s->code_time / tot * 100.0);
2239 cpu_fprintf(f, "liveness/code time %0.1f%%\n",
2240 (double)s->la_time / (s->code_time ? s->code_time : 1) * 100.0);
2241 cpu_fprintf(f, "cpu_restore count %" PRId64 "\n",
2242 s->restore_count);
2243 cpu_fprintf(f, " avg cycles %0.1f\n",
2244 s->restore_count ? (double)s->restore_time / s->restore_count : 0);
2246 dump_op_count();
2248 #else
2249 void tcg_dump_info(FILE *f, fprintf_function cpu_fprintf)
2251 cpu_fprintf(f, "[TCG profiler not compiled]\n");
2253 #endif