hw/9pfs: Documentation changes related to proxy fs
[qemu/ar7.git] / tcg / tcg.c
blobd43fa4a9b32b4d2034f1bfb17418f550d7a6783c
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, TCGReg ret, TCGReg arg1,
75 tcg_target_long arg2);
76 static void tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg);
77 static void tcg_out_movi(TCGContext *s, TCGType type,
78 TCGReg 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, TCGReg arg, TCGReg 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
92 const size_t tcg_op_defs_max = ARRAY_SIZE(tcg_op_defs);
94 static TCGRegSet tcg_target_available_regs[2];
95 static TCGRegSet tcg_target_call_clobber_regs;
97 /* XXX: move that inside the context */
98 uint16_t *gen_opc_ptr;
99 TCGArg *gen_opparam_ptr;
101 static inline void tcg_out8(TCGContext *s, uint8_t v)
103 *s->code_ptr++ = v;
106 static inline void tcg_out16(TCGContext *s, uint16_t v)
108 *(uint16_t *)s->code_ptr = v;
109 s->code_ptr += 2;
112 static inline void tcg_out32(TCGContext *s, uint32_t v)
114 *(uint32_t *)s->code_ptr = v;
115 s->code_ptr += 4;
118 /* label relocation processing */
120 static void tcg_out_reloc(TCGContext *s, uint8_t *code_ptr, int type,
121 int label_index, long addend)
123 TCGLabel *l;
124 TCGRelocation *r;
126 l = &s->labels[label_index];
127 if (l->has_value) {
128 /* FIXME: This may break relocations on RISC targets that
129 modify instruction fields in place. The caller may not have
130 written the initial value. */
131 patch_reloc(code_ptr, type, l->u.value, addend);
132 } else {
133 /* add a new relocation entry */
134 r = tcg_malloc(sizeof(TCGRelocation));
135 r->type = type;
136 r->ptr = code_ptr;
137 r->addend = addend;
138 r->next = l->u.first_reloc;
139 l->u.first_reloc = r;
143 static void tcg_out_label(TCGContext *s, int label_index,
144 tcg_target_long value)
146 TCGLabel *l;
147 TCGRelocation *r;
149 l = &s->labels[label_index];
150 if (l->has_value)
151 tcg_abort();
152 r = l->u.first_reloc;
153 while (r != NULL) {
154 patch_reloc(r->ptr, r->type, value, r->addend);
155 r = r->next;
157 l->has_value = 1;
158 l->u.value = value;
161 int gen_new_label(void)
163 TCGContext *s = &tcg_ctx;
164 int idx;
165 TCGLabel *l;
167 if (s->nb_labels >= TCG_MAX_LABELS)
168 tcg_abort();
169 idx = s->nb_labels++;
170 l = &s->labels[idx];
171 l->has_value = 0;
172 l->u.first_reloc = NULL;
173 return idx;
176 #include "tcg-target.c"
178 /* pool based memory allocation */
179 void *tcg_malloc_internal(TCGContext *s, int size)
181 TCGPool *p;
182 int pool_size;
184 if (size > TCG_POOL_CHUNK_SIZE) {
185 /* big malloc: insert a new pool (XXX: could optimize) */
186 p = g_malloc(sizeof(TCGPool) + size);
187 p->size = size;
188 if (s->pool_current)
189 s->pool_current->next = p;
190 else
191 s->pool_first = p;
192 p->next = s->pool_current;
193 } else {
194 p = s->pool_current;
195 if (!p) {
196 p = s->pool_first;
197 if (!p)
198 goto new_pool;
199 } else {
200 if (!p->next) {
201 new_pool:
202 pool_size = TCG_POOL_CHUNK_SIZE;
203 p = g_malloc(sizeof(TCGPool) + pool_size);
204 p->size = pool_size;
205 p->next = NULL;
206 if (s->pool_current)
207 s->pool_current->next = p;
208 else
209 s->pool_first = p;
210 } else {
211 p = p->next;
215 s->pool_current = p;
216 s->pool_cur = p->data + size;
217 s->pool_end = p->data + p->size;
218 return p->data;
221 void tcg_pool_reset(TCGContext *s)
223 s->pool_cur = s->pool_end = NULL;
224 s->pool_current = NULL;
227 void tcg_context_init(TCGContext *s)
229 int op, total_args, n;
230 TCGOpDef *def;
231 TCGArgConstraint *args_ct;
232 int *sorted_args;
234 memset(s, 0, sizeof(*s));
235 s->temps = s->static_temps;
236 s->nb_globals = 0;
238 /* Count total number of arguments and allocate the corresponding
239 space */
240 total_args = 0;
241 for(op = 0; op < NB_OPS; op++) {
242 def = &tcg_op_defs[op];
243 n = def->nb_iargs + def->nb_oargs;
244 total_args += n;
247 args_ct = g_malloc(sizeof(TCGArgConstraint) * total_args);
248 sorted_args = g_malloc(sizeof(int) * total_args);
250 for(op = 0; op < NB_OPS; op++) {
251 def = &tcg_op_defs[op];
252 def->args_ct = args_ct;
253 def->sorted_args = sorted_args;
254 n = def->nb_iargs + def->nb_oargs;
255 sorted_args += n;
256 args_ct += n;
259 tcg_target_init(s);
262 void tcg_prologue_init(TCGContext *s)
264 /* init global prologue and epilogue */
265 s->code_buf = code_gen_prologue;
266 s->code_ptr = s->code_buf;
267 tcg_target_qemu_prologue(s);
268 flush_icache_range((unsigned long)s->code_buf,
269 (unsigned long)s->code_ptr);
272 void tcg_set_frame(TCGContext *s, int reg,
273 tcg_target_long start, tcg_target_long size)
275 s->frame_start = start;
276 s->frame_end = start + size;
277 s->frame_reg = reg;
280 void tcg_func_start(TCGContext *s)
282 int i;
283 tcg_pool_reset(s);
284 s->nb_temps = s->nb_globals;
285 for(i = 0; i < (TCG_TYPE_COUNT * 2); i++)
286 s->first_free_temp[i] = -1;
287 s->labels = tcg_malloc(sizeof(TCGLabel) * TCG_MAX_LABELS);
288 s->nb_labels = 0;
289 s->current_frame_offset = s->frame_start;
291 gen_opc_ptr = gen_opc_buf;
292 gen_opparam_ptr = gen_opparam_buf;
295 static inline void tcg_temp_alloc(TCGContext *s, int n)
297 if (n > TCG_MAX_TEMPS)
298 tcg_abort();
301 static inline int tcg_global_reg_new_internal(TCGType type, int reg,
302 const char *name)
304 TCGContext *s = &tcg_ctx;
305 TCGTemp *ts;
306 int idx;
308 #if TCG_TARGET_REG_BITS == 32
309 if (type != TCG_TYPE_I32)
310 tcg_abort();
311 #endif
312 if (tcg_regset_test_reg(s->reserved_regs, reg))
313 tcg_abort();
314 idx = s->nb_globals;
315 tcg_temp_alloc(s, s->nb_globals + 1);
316 ts = &s->temps[s->nb_globals];
317 ts->base_type = type;
318 ts->type = type;
319 ts->fixed_reg = 1;
320 ts->reg = reg;
321 ts->name = name;
322 s->nb_globals++;
323 tcg_regset_set_reg(s->reserved_regs, reg);
324 return idx;
327 TCGv_i32 tcg_global_reg_new_i32(int reg, const char *name)
329 int idx;
331 idx = tcg_global_reg_new_internal(TCG_TYPE_I32, reg, name);
332 return MAKE_TCGV_I32(idx);
335 TCGv_i64 tcg_global_reg_new_i64(int reg, const char *name)
337 int idx;
339 idx = tcg_global_reg_new_internal(TCG_TYPE_I64, reg, name);
340 return MAKE_TCGV_I64(idx);
343 static inline int tcg_global_mem_new_internal(TCGType type, int reg,
344 tcg_target_long offset,
345 const char *name)
347 TCGContext *s = &tcg_ctx;
348 TCGTemp *ts;
349 int idx;
351 idx = s->nb_globals;
352 #if TCG_TARGET_REG_BITS == 32
353 if (type == TCG_TYPE_I64) {
354 char buf[64];
355 tcg_temp_alloc(s, s->nb_globals + 2);
356 ts = &s->temps[s->nb_globals];
357 ts->base_type = type;
358 ts->type = TCG_TYPE_I32;
359 ts->fixed_reg = 0;
360 ts->mem_allocated = 1;
361 ts->mem_reg = reg;
362 #ifdef TCG_TARGET_WORDS_BIGENDIAN
363 ts->mem_offset = offset + 4;
364 #else
365 ts->mem_offset = offset;
366 #endif
367 pstrcpy(buf, sizeof(buf), name);
368 pstrcat(buf, sizeof(buf), "_0");
369 ts->name = strdup(buf);
370 ts++;
372 ts->base_type = type;
373 ts->type = TCG_TYPE_I32;
374 ts->fixed_reg = 0;
375 ts->mem_allocated = 1;
376 ts->mem_reg = reg;
377 #ifdef TCG_TARGET_WORDS_BIGENDIAN
378 ts->mem_offset = offset;
379 #else
380 ts->mem_offset = offset + 4;
381 #endif
382 pstrcpy(buf, sizeof(buf), name);
383 pstrcat(buf, sizeof(buf), "_1");
384 ts->name = strdup(buf);
386 s->nb_globals += 2;
387 } else
388 #endif
390 tcg_temp_alloc(s, s->nb_globals + 1);
391 ts = &s->temps[s->nb_globals];
392 ts->base_type = type;
393 ts->type = type;
394 ts->fixed_reg = 0;
395 ts->mem_allocated = 1;
396 ts->mem_reg = reg;
397 ts->mem_offset = offset;
398 ts->name = name;
399 s->nb_globals++;
401 return idx;
404 TCGv_i32 tcg_global_mem_new_i32(int reg, tcg_target_long offset,
405 const char *name)
407 int idx;
409 idx = tcg_global_mem_new_internal(TCG_TYPE_I32, reg, offset, name);
410 return MAKE_TCGV_I32(idx);
413 TCGv_i64 tcg_global_mem_new_i64(int reg, tcg_target_long offset,
414 const char *name)
416 int idx;
418 idx = tcg_global_mem_new_internal(TCG_TYPE_I64, reg, offset, name);
419 return MAKE_TCGV_I64(idx);
422 static inline int tcg_temp_new_internal(TCGType type, int temp_local)
424 TCGContext *s = &tcg_ctx;
425 TCGTemp *ts;
426 int idx, k;
428 k = type;
429 if (temp_local)
430 k += TCG_TYPE_COUNT;
431 idx = s->first_free_temp[k];
432 if (idx != -1) {
433 /* There is already an available temp with the
434 right type */
435 ts = &s->temps[idx];
436 s->first_free_temp[k] = ts->next_free_temp;
437 ts->temp_allocated = 1;
438 assert(ts->temp_local == temp_local);
439 } else {
440 idx = s->nb_temps;
441 #if TCG_TARGET_REG_BITS == 32
442 if (type == TCG_TYPE_I64) {
443 tcg_temp_alloc(s, s->nb_temps + 2);
444 ts = &s->temps[s->nb_temps];
445 ts->base_type = type;
446 ts->type = TCG_TYPE_I32;
447 ts->temp_allocated = 1;
448 ts->temp_local = temp_local;
449 ts->name = NULL;
450 ts++;
451 ts->base_type = TCG_TYPE_I32;
452 ts->type = TCG_TYPE_I32;
453 ts->temp_allocated = 1;
454 ts->temp_local = temp_local;
455 ts->name = NULL;
456 s->nb_temps += 2;
457 } else
458 #endif
460 tcg_temp_alloc(s, s->nb_temps + 1);
461 ts = &s->temps[s->nb_temps];
462 ts->base_type = type;
463 ts->type = type;
464 ts->temp_allocated = 1;
465 ts->temp_local = temp_local;
466 ts->name = NULL;
467 s->nb_temps++;
471 #if defined(CONFIG_DEBUG_TCG)
472 s->temps_in_use++;
473 #endif
474 return idx;
477 TCGv_i32 tcg_temp_new_internal_i32(int temp_local)
479 int idx;
481 idx = tcg_temp_new_internal(TCG_TYPE_I32, temp_local);
482 return MAKE_TCGV_I32(idx);
485 TCGv_i64 tcg_temp_new_internal_i64(int temp_local)
487 int idx;
489 idx = tcg_temp_new_internal(TCG_TYPE_I64, temp_local);
490 return MAKE_TCGV_I64(idx);
493 static inline void tcg_temp_free_internal(int idx)
495 TCGContext *s = &tcg_ctx;
496 TCGTemp *ts;
497 int k;
499 #if defined(CONFIG_DEBUG_TCG)
500 s->temps_in_use--;
501 if (s->temps_in_use < 0) {
502 fprintf(stderr, "More temporaries freed than allocated!\n");
504 #endif
506 assert(idx >= s->nb_globals && idx < s->nb_temps);
507 ts = &s->temps[idx];
508 assert(ts->temp_allocated != 0);
509 ts->temp_allocated = 0;
510 k = ts->base_type;
511 if (ts->temp_local)
512 k += TCG_TYPE_COUNT;
513 ts->next_free_temp = s->first_free_temp[k];
514 s->first_free_temp[k] = idx;
517 void tcg_temp_free_i32(TCGv_i32 arg)
519 tcg_temp_free_internal(GET_TCGV_I32(arg));
522 void tcg_temp_free_i64(TCGv_i64 arg)
524 tcg_temp_free_internal(GET_TCGV_I64(arg));
527 TCGv_i32 tcg_const_i32(int32_t val)
529 TCGv_i32 t0;
530 t0 = tcg_temp_new_i32();
531 tcg_gen_movi_i32(t0, val);
532 return t0;
535 TCGv_i64 tcg_const_i64(int64_t val)
537 TCGv_i64 t0;
538 t0 = tcg_temp_new_i64();
539 tcg_gen_movi_i64(t0, val);
540 return t0;
543 TCGv_i32 tcg_const_local_i32(int32_t val)
545 TCGv_i32 t0;
546 t0 = tcg_temp_local_new_i32();
547 tcg_gen_movi_i32(t0, val);
548 return t0;
551 TCGv_i64 tcg_const_local_i64(int64_t val)
553 TCGv_i64 t0;
554 t0 = tcg_temp_local_new_i64();
555 tcg_gen_movi_i64(t0, val);
556 return t0;
559 #if defined(CONFIG_DEBUG_TCG)
560 void tcg_clear_temp_count(void)
562 TCGContext *s = &tcg_ctx;
563 s->temps_in_use = 0;
566 int tcg_check_temp_count(void)
568 TCGContext *s = &tcg_ctx;
569 if (s->temps_in_use) {
570 /* Clear the count so that we don't give another
571 * warning immediately next time around.
573 s->temps_in_use = 0;
574 return 1;
576 return 0;
578 #endif
580 void tcg_register_helper(void *func, const char *name)
582 TCGContext *s = &tcg_ctx;
583 int n;
584 if ((s->nb_helpers + 1) > s->allocated_helpers) {
585 n = s->allocated_helpers;
586 if (n == 0) {
587 n = 4;
588 } else {
589 n *= 2;
591 s->helpers = realloc(s->helpers, n * sizeof(TCGHelperInfo));
592 s->allocated_helpers = n;
594 s->helpers[s->nb_helpers].func = (tcg_target_ulong)func;
595 s->helpers[s->nb_helpers].name = name;
596 s->nb_helpers++;
599 /* Note: we convert the 64 bit args to 32 bit and do some alignment
600 and endian swap. Maybe it would be better to do the alignment
601 and endian swap in tcg_reg_alloc_call(). */
602 void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags,
603 int sizemask, TCGArg ret, int nargs, TCGArg *args)
605 #if defined(TCG_TARGET_I386) && TCG_TARGET_REG_BITS < 64
606 int call_type;
607 #endif
608 int i;
609 int real_args;
610 int nb_rets;
611 TCGArg *nparam;
613 #if defined(TCG_TARGET_EXTEND_ARGS) && TCG_TARGET_REG_BITS == 64
614 for (i = 0; i < nargs; ++i) {
615 int is_64bit = sizemask & (1 << (i+1)*2);
616 int is_signed = sizemask & (2 << (i+1)*2);
617 if (!is_64bit) {
618 TCGv_i64 temp = tcg_temp_new_i64();
619 TCGv_i64 orig = MAKE_TCGV_I64(args[i]);
620 if (is_signed) {
621 tcg_gen_ext32s_i64(temp, orig);
622 } else {
623 tcg_gen_ext32u_i64(temp, orig);
625 args[i] = GET_TCGV_I64(temp);
628 #endif /* TCG_TARGET_EXTEND_ARGS */
630 *gen_opc_ptr++ = INDEX_op_call;
631 nparam = gen_opparam_ptr++;
632 #if defined(TCG_TARGET_I386) && TCG_TARGET_REG_BITS < 64
633 call_type = (flags & TCG_CALL_TYPE_MASK);
634 #endif
635 if (ret != TCG_CALL_DUMMY_ARG) {
636 #if TCG_TARGET_REG_BITS < 64
637 if (sizemask & 1) {
638 #ifdef TCG_TARGET_WORDS_BIGENDIAN
639 *gen_opparam_ptr++ = ret + 1;
640 *gen_opparam_ptr++ = ret;
641 #else
642 *gen_opparam_ptr++ = ret;
643 *gen_opparam_ptr++ = ret + 1;
644 #endif
645 nb_rets = 2;
646 } else
647 #endif
649 *gen_opparam_ptr++ = ret;
650 nb_rets = 1;
652 } else {
653 nb_rets = 0;
655 real_args = 0;
656 for (i = 0; i < nargs; i++) {
657 #if TCG_TARGET_REG_BITS < 64
658 int is_64bit = sizemask & (1 << (i+1)*2);
659 if (is_64bit) {
660 #ifdef TCG_TARGET_I386
661 /* REGPARM case: if the third parameter is 64 bit, it is
662 allocated on the stack */
663 if (i == 2 && call_type == TCG_CALL_TYPE_REGPARM) {
664 call_type = TCG_CALL_TYPE_REGPARM_2;
665 flags = (flags & ~TCG_CALL_TYPE_MASK) | call_type;
667 #endif
668 #ifdef TCG_TARGET_CALL_ALIGN_ARGS
669 /* some targets want aligned 64 bit args */
670 if (real_args & 1) {
671 *gen_opparam_ptr++ = TCG_CALL_DUMMY_ARG;
672 real_args++;
674 #endif
675 /* If stack grows up, then we will be placing successive
676 arguments at lower addresses, which means we need to
677 reverse the order compared to how we would normally
678 treat either big or little-endian. For those arguments
679 that will wind up in registers, this still works for
680 HPPA (the only current STACK_GROWSUP target) since the
681 argument registers are *also* allocated in decreasing
682 order. If another such target is added, this logic may
683 have to get more complicated to differentiate between
684 stack arguments and register arguments. */
685 #if defined(TCG_TARGET_WORDS_BIGENDIAN) != defined(TCG_TARGET_STACK_GROWSUP)
686 *gen_opparam_ptr++ = args[i] + 1;
687 *gen_opparam_ptr++ = args[i];
688 #else
689 *gen_opparam_ptr++ = args[i];
690 *gen_opparam_ptr++ = args[i] + 1;
691 #endif
692 real_args += 2;
693 continue;
695 #endif /* TCG_TARGET_REG_BITS < 64 */
697 *gen_opparam_ptr++ = args[i];
698 real_args++;
700 *gen_opparam_ptr++ = GET_TCGV_PTR(func);
702 *gen_opparam_ptr++ = flags;
704 *nparam = (nb_rets << 16) | (real_args + 1);
706 /* total parameters, needed to go backward in the instruction stream */
707 *gen_opparam_ptr++ = 1 + nb_rets + real_args + 3;
709 #if defined(TCG_TARGET_EXTEND_ARGS) && TCG_TARGET_REG_BITS == 64
710 for (i = 0; i < nargs; ++i) {
711 int is_64bit = sizemask & (1 << (i+1)*2);
712 if (!is_64bit) {
713 TCGv_i64 temp = MAKE_TCGV_I64(args[i]);
714 tcg_temp_free_i64(temp);
717 #endif /* TCG_TARGET_EXTEND_ARGS */
720 #if TCG_TARGET_REG_BITS == 32
721 void tcg_gen_shifti_i64(TCGv_i64 ret, TCGv_i64 arg1,
722 int c, int right, int arith)
724 if (c == 0) {
725 tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg1));
726 tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
727 } else if (c >= 32) {
728 c -= 32;
729 if (right) {
730 if (arith) {
731 tcg_gen_sari_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
732 tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 31);
733 } else {
734 tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
735 tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
737 } else {
738 tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_LOW(arg1), c);
739 tcg_gen_movi_i32(TCGV_LOW(ret), 0);
741 } else {
742 TCGv_i32 t0, t1;
744 t0 = tcg_temp_new_i32();
745 t1 = tcg_temp_new_i32();
746 if (right) {
747 tcg_gen_shli_i32(t0, TCGV_HIGH(arg1), 32 - c);
748 if (arith)
749 tcg_gen_sari_i32(t1, TCGV_HIGH(arg1), c);
750 else
751 tcg_gen_shri_i32(t1, TCGV_HIGH(arg1), c);
752 tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_LOW(arg1), c);
753 tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(ret), t0);
754 tcg_gen_mov_i32(TCGV_HIGH(ret), t1);
755 } else {
756 tcg_gen_shri_i32(t0, TCGV_LOW(arg1), 32 - c);
757 /* Note: ret can be the same as arg1, so we use t1 */
758 tcg_gen_shli_i32(t1, TCGV_LOW(arg1), c);
759 tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c);
760 tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t0);
761 tcg_gen_mov_i32(TCGV_LOW(ret), t1);
763 tcg_temp_free_i32(t0);
764 tcg_temp_free_i32(t1);
767 #endif
770 static void tcg_reg_alloc_start(TCGContext *s)
772 int i;
773 TCGTemp *ts;
774 for(i = 0; i < s->nb_globals; i++) {
775 ts = &s->temps[i];
776 if (ts->fixed_reg) {
777 ts->val_type = TEMP_VAL_REG;
778 } else {
779 ts->val_type = TEMP_VAL_MEM;
782 for(i = s->nb_globals; i < s->nb_temps; i++) {
783 ts = &s->temps[i];
784 ts->val_type = TEMP_VAL_DEAD;
785 ts->mem_allocated = 0;
786 ts->fixed_reg = 0;
788 for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
789 s->reg_to_temp[i] = -1;
793 static char *tcg_get_arg_str_idx(TCGContext *s, char *buf, int buf_size,
794 int idx)
796 TCGTemp *ts;
798 assert(idx >= 0 && idx < s->nb_temps);
799 ts = &s->temps[idx];
800 assert(ts);
801 if (idx < s->nb_globals) {
802 pstrcpy(buf, buf_size, ts->name);
803 } else {
804 if (ts->temp_local)
805 snprintf(buf, buf_size, "loc%d", idx - s->nb_globals);
806 else
807 snprintf(buf, buf_size, "tmp%d", idx - s->nb_globals);
809 return buf;
812 char *tcg_get_arg_str_i32(TCGContext *s, char *buf, int buf_size, TCGv_i32 arg)
814 return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I32(arg));
817 char *tcg_get_arg_str_i64(TCGContext *s, char *buf, int buf_size, TCGv_i64 arg)
819 return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I64(arg));
822 static int helper_cmp(const void *p1, const void *p2)
824 const TCGHelperInfo *th1 = p1;
825 const TCGHelperInfo *th2 = p2;
826 if (th1->func < th2->func)
827 return -1;
828 else if (th1->func == th2->func)
829 return 0;
830 else
831 return 1;
834 /* find helper definition (Note: A hash table would be better) */
835 static TCGHelperInfo *tcg_find_helper(TCGContext *s, tcg_target_ulong val)
837 int m, m_min, m_max;
838 TCGHelperInfo *th;
839 tcg_target_ulong v;
841 if (unlikely(!s->helpers_sorted)) {
842 qsort(s->helpers, s->nb_helpers, sizeof(TCGHelperInfo),
843 helper_cmp);
844 s->helpers_sorted = 1;
847 /* binary search */
848 m_min = 0;
849 m_max = s->nb_helpers - 1;
850 while (m_min <= m_max) {
851 m = (m_min + m_max) >> 1;
852 th = &s->helpers[m];
853 v = th->func;
854 if (v == val)
855 return th;
856 else if (val < v) {
857 m_max = m - 1;
858 } else {
859 m_min = m + 1;
862 return NULL;
865 static const char * const cond_name[] =
867 [TCG_COND_EQ] = "eq",
868 [TCG_COND_NE] = "ne",
869 [TCG_COND_LT] = "lt",
870 [TCG_COND_GE] = "ge",
871 [TCG_COND_LE] = "le",
872 [TCG_COND_GT] = "gt",
873 [TCG_COND_LTU] = "ltu",
874 [TCG_COND_GEU] = "geu",
875 [TCG_COND_LEU] = "leu",
876 [TCG_COND_GTU] = "gtu"
879 void tcg_dump_ops(TCGContext *s, FILE *outfile)
881 const uint16_t *opc_ptr;
882 const TCGArg *args;
883 TCGArg arg;
884 TCGOpcode c;
885 int i, k, nb_oargs, nb_iargs, nb_cargs, first_insn;
886 const TCGOpDef *def;
887 char buf[128];
889 first_insn = 1;
890 opc_ptr = gen_opc_buf;
891 args = gen_opparam_buf;
892 while (opc_ptr < gen_opc_ptr) {
893 c = *opc_ptr++;
894 def = &tcg_op_defs[c];
895 if (c == INDEX_op_debug_insn_start) {
896 uint64_t pc;
897 #if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
898 pc = ((uint64_t)args[1] << 32) | args[0];
899 #else
900 pc = args[0];
901 #endif
902 if (!first_insn)
903 fprintf(outfile, "\n");
904 fprintf(outfile, " ---- 0x%" PRIx64, pc);
905 first_insn = 0;
906 nb_oargs = def->nb_oargs;
907 nb_iargs = def->nb_iargs;
908 nb_cargs = def->nb_cargs;
909 } else if (c == INDEX_op_call) {
910 TCGArg arg;
912 /* variable number of arguments */
913 arg = *args++;
914 nb_oargs = arg >> 16;
915 nb_iargs = arg & 0xffff;
916 nb_cargs = def->nb_cargs;
918 fprintf(outfile, " %s ", def->name);
920 /* function name */
921 fprintf(outfile, "%s",
922 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + nb_iargs - 1]));
923 /* flags */
924 fprintf(outfile, ",$0x%" TCG_PRIlx,
925 args[nb_oargs + nb_iargs]);
926 /* nb out args */
927 fprintf(outfile, ",$%d", nb_oargs);
928 for(i = 0; i < nb_oargs; i++) {
929 fprintf(outfile, ",");
930 fprintf(outfile, "%s",
931 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[i]));
933 for(i = 0; i < (nb_iargs - 1); i++) {
934 fprintf(outfile, ",");
935 if (args[nb_oargs + i] == TCG_CALL_DUMMY_ARG) {
936 fprintf(outfile, "<dummy>");
937 } else {
938 fprintf(outfile, "%s",
939 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + i]));
942 } else if (c == INDEX_op_movi_i32
943 #if TCG_TARGET_REG_BITS == 64
944 || c == INDEX_op_movi_i64
945 #endif
947 tcg_target_ulong val;
948 TCGHelperInfo *th;
950 nb_oargs = def->nb_oargs;
951 nb_iargs = def->nb_iargs;
952 nb_cargs = def->nb_cargs;
953 fprintf(outfile, " %s %s,$", def->name,
954 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[0]));
955 val = args[1];
956 th = tcg_find_helper(s, val);
957 if (th) {
958 fprintf(outfile, "%s", th->name);
959 } else {
960 if (c == INDEX_op_movi_i32)
961 fprintf(outfile, "0x%x", (uint32_t)val);
962 else
963 fprintf(outfile, "0x%" PRIx64 , (uint64_t)val);
965 } else {
966 fprintf(outfile, " %s ", def->name);
967 if (c == INDEX_op_nopn) {
968 /* variable number of arguments */
969 nb_cargs = *args;
970 nb_oargs = 0;
971 nb_iargs = 0;
972 } else {
973 nb_oargs = def->nb_oargs;
974 nb_iargs = def->nb_iargs;
975 nb_cargs = def->nb_cargs;
978 k = 0;
979 for(i = 0; i < nb_oargs; i++) {
980 if (k != 0)
981 fprintf(outfile, ",");
982 fprintf(outfile, "%s",
983 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
985 for(i = 0; i < nb_iargs; i++) {
986 if (k != 0)
987 fprintf(outfile, ",");
988 fprintf(outfile, "%s",
989 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
991 switch (c) {
992 case INDEX_op_brcond_i32:
993 #if TCG_TARGET_REG_BITS == 32
994 case INDEX_op_brcond2_i32:
995 #elif TCG_TARGET_REG_BITS == 64
996 case INDEX_op_brcond_i64:
997 #endif
998 case INDEX_op_setcond_i32:
999 #if TCG_TARGET_REG_BITS == 32
1000 case INDEX_op_setcond2_i32:
1001 #elif TCG_TARGET_REG_BITS == 64
1002 case INDEX_op_setcond_i64:
1003 #endif
1004 if (args[k] < ARRAY_SIZE(cond_name) && cond_name[args[k]])
1005 fprintf(outfile, ",%s", cond_name[args[k++]]);
1006 else
1007 fprintf(outfile, ",$0x%" TCG_PRIlx, args[k++]);
1008 i = 1;
1009 break;
1010 default:
1011 i = 0;
1012 break;
1014 for(; i < nb_cargs; i++) {
1015 if (k != 0)
1016 fprintf(outfile, ",");
1017 arg = args[k++];
1018 fprintf(outfile, "$0x%" TCG_PRIlx, arg);
1021 fprintf(outfile, "\n");
1022 args += nb_iargs + nb_oargs + nb_cargs;
1026 /* we give more priority to constraints with less registers */
1027 static int get_constraint_priority(const TCGOpDef *def, int k)
1029 const TCGArgConstraint *arg_ct;
1031 int i, n;
1032 arg_ct = &def->args_ct[k];
1033 if (arg_ct->ct & TCG_CT_ALIAS) {
1034 /* an alias is equivalent to a single register */
1035 n = 1;
1036 } else {
1037 if (!(arg_ct->ct & TCG_CT_REG))
1038 return 0;
1039 n = 0;
1040 for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
1041 if (tcg_regset_test_reg(arg_ct->u.regs, i))
1042 n++;
1045 return TCG_TARGET_NB_REGS - n + 1;
1048 /* sort from highest priority to lowest */
1049 static void sort_constraints(TCGOpDef *def, int start, int n)
1051 int i, j, p1, p2, tmp;
1053 for(i = 0; i < n; i++)
1054 def->sorted_args[start + i] = start + i;
1055 if (n <= 1)
1056 return;
1057 for(i = 0; i < n - 1; i++) {
1058 for(j = i + 1; j < n; j++) {
1059 p1 = get_constraint_priority(def, def->sorted_args[start + i]);
1060 p2 = get_constraint_priority(def, def->sorted_args[start + j]);
1061 if (p1 < p2) {
1062 tmp = def->sorted_args[start + i];
1063 def->sorted_args[start + i] = def->sorted_args[start + j];
1064 def->sorted_args[start + j] = tmp;
1070 void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs)
1072 TCGOpcode op;
1073 TCGOpDef *def;
1074 const char *ct_str;
1075 int i, nb_args;
1077 for(;;) {
1078 if (tdefs->op == (TCGOpcode)-1)
1079 break;
1080 op = tdefs->op;
1081 assert((unsigned)op < NB_OPS);
1082 def = &tcg_op_defs[op];
1083 #if defined(CONFIG_DEBUG_TCG)
1084 /* Duplicate entry in op definitions? */
1085 assert(!def->used);
1086 def->used = 1;
1087 #endif
1088 nb_args = def->nb_iargs + def->nb_oargs;
1089 for(i = 0; i < nb_args; i++) {
1090 ct_str = tdefs->args_ct_str[i];
1091 /* Incomplete TCGTargetOpDef entry? */
1092 assert(ct_str != NULL);
1093 tcg_regset_clear(def->args_ct[i].u.regs);
1094 def->args_ct[i].ct = 0;
1095 if (ct_str[0] >= '0' && ct_str[0] <= '9') {
1096 int oarg;
1097 oarg = ct_str[0] - '0';
1098 assert(oarg < def->nb_oargs);
1099 assert(def->args_ct[oarg].ct & TCG_CT_REG);
1100 /* TCG_CT_ALIAS is for the output arguments. The input
1101 argument is tagged with TCG_CT_IALIAS. */
1102 def->args_ct[i] = def->args_ct[oarg];
1103 def->args_ct[oarg].ct = TCG_CT_ALIAS;
1104 def->args_ct[oarg].alias_index = i;
1105 def->args_ct[i].ct |= TCG_CT_IALIAS;
1106 def->args_ct[i].alias_index = oarg;
1107 } else {
1108 for(;;) {
1109 if (*ct_str == '\0')
1110 break;
1111 switch(*ct_str) {
1112 case 'i':
1113 def->args_ct[i].ct |= TCG_CT_CONST;
1114 ct_str++;
1115 break;
1116 default:
1117 if (target_parse_constraint(&def->args_ct[i], &ct_str) < 0) {
1118 fprintf(stderr, "Invalid constraint '%s' for arg %d of operation '%s'\n",
1119 ct_str, i, def->name);
1120 exit(1);
1127 /* TCGTargetOpDef entry with too much information? */
1128 assert(i == TCG_MAX_OP_ARGS || tdefs->args_ct_str[i] == NULL);
1130 /* sort the constraints (XXX: this is just an heuristic) */
1131 sort_constraints(def, 0, def->nb_oargs);
1132 sort_constraints(def, def->nb_oargs, def->nb_iargs);
1134 #if 0
1136 int i;
1138 printf("%s: sorted=", def->name);
1139 for(i = 0; i < def->nb_oargs + def->nb_iargs; i++)
1140 printf(" %d", def->sorted_args[i]);
1141 printf("\n");
1143 #endif
1144 tdefs++;
1147 #if defined(CONFIG_DEBUG_TCG)
1148 i = 0;
1149 for (op = 0; op < ARRAY_SIZE(tcg_op_defs); op++) {
1150 const TCGOpDef *def = &tcg_op_defs[op];
1151 if (op < INDEX_op_call
1152 || op == INDEX_op_debug_insn_start
1153 || (def->flags & TCG_OPF_NOT_PRESENT)) {
1154 /* Wrong entry in op definitions? */
1155 if (def->used) {
1156 fprintf(stderr, "Invalid op definition for %s\n", def->name);
1157 i = 1;
1159 } else {
1160 /* Missing entry in op definitions? */
1161 if (!def->used) {
1162 fprintf(stderr, "Missing op definition for %s\n", def->name);
1163 i = 1;
1167 if (i == 1) {
1168 tcg_abort();
1170 #endif
1173 #ifdef USE_LIVENESS_ANALYSIS
1175 /* set a nop for an operation using 'nb_args' */
1176 static inline void tcg_set_nop(TCGContext *s, uint16_t *opc_ptr,
1177 TCGArg *args, int nb_args)
1179 if (nb_args == 0) {
1180 *opc_ptr = INDEX_op_nop;
1181 } else {
1182 *opc_ptr = INDEX_op_nopn;
1183 args[0] = nb_args;
1184 args[nb_args - 1] = nb_args;
1188 /* liveness analysis: end of function: globals are live, temps are
1189 dead. */
1190 /* XXX: at this stage, not used as there would be little gains because
1191 most TBs end with a conditional jump. */
1192 static inline void tcg_la_func_end(TCGContext *s, uint8_t *dead_temps)
1194 memset(dead_temps, 0, s->nb_globals);
1195 memset(dead_temps + s->nb_globals, 1, s->nb_temps - s->nb_globals);
1198 /* liveness analysis: end of basic block: globals are live, temps are
1199 dead, local temps are live. */
1200 static inline void tcg_la_bb_end(TCGContext *s, uint8_t *dead_temps)
1202 int i;
1203 TCGTemp *ts;
1205 memset(dead_temps, 0, s->nb_globals);
1206 ts = &s->temps[s->nb_globals];
1207 for(i = s->nb_globals; i < s->nb_temps; i++) {
1208 if (ts->temp_local)
1209 dead_temps[i] = 0;
1210 else
1211 dead_temps[i] = 1;
1212 ts++;
1216 /* Liveness analysis : update the opc_dead_args array to tell if a
1217 given input arguments is dead. Instructions updating dead
1218 temporaries are removed. */
1219 static void tcg_liveness_analysis(TCGContext *s)
1221 int i, op_index, nb_args, nb_iargs, nb_oargs, arg, nb_ops;
1222 TCGOpcode op;
1223 TCGArg *args;
1224 const TCGOpDef *def;
1225 uint8_t *dead_temps;
1226 unsigned int dead_args;
1228 gen_opc_ptr++; /* skip end */
1230 nb_ops = gen_opc_ptr - gen_opc_buf;
1232 s->op_dead_args = tcg_malloc(nb_ops * sizeof(uint16_t));
1234 dead_temps = tcg_malloc(s->nb_temps);
1235 memset(dead_temps, 1, s->nb_temps);
1237 args = gen_opparam_ptr;
1238 op_index = nb_ops - 1;
1239 while (op_index >= 0) {
1240 op = gen_opc_buf[op_index];
1241 def = &tcg_op_defs[op];
1242 switch(op) {
1243 case INDEX_op_call:
1245 int call_flags;
1247 nb_args = args[-1];
1248 args -= nb_args;
1249 nb_iargs = args[0] & 0xffff;
1250 nb_oargs = args[0] >> 16;
1251 args++;
1252 call_flags = args[nb_oargs + nb_iargs];
1254 /* pure functions can be removed if their result is not
1255 used */
1256 if (call_flags & TCG_CALL_PURE) {
1257 for(i = 0; i < nb_oargs; i++) {
1258 arg = args[i];
1259 if (!dead_temps[arg])
1260 goto do_not_remove_call;
1262 tcg_set_nop(s, gen_opc_buf + op_index,
1263 args - 1, nb_args);
1264 } else {
1265 do_not_remove_call:
1267 /* output args are dead */
1268 dead_args = 0;
1269 for(i = 0; i < nb_oargs; i++) {
1270 arg = args[i];
1271 if (dead_temps[arg]) {
1272 dead_args |= (1 << i);
1274 dead_temps[arg] = 1;
1277 if (!(call_flags & TCG_CALL_CONST)) {
1278 /* globals are live (they may be used by the call) */
1279 memset(dead_temps, 0, s->nb_globals);
1282 /* input args are live */
1283 for(i = nb_oargs; i < nb_iargs + nb_oargs; i++) {
1284 arg = args[i];
1285 if (arg != TCG_CALL_DUMMY_ARG) {
1286 if (dead_temps[arg]) {
1287 dead_args |= (1 << i);
1289 dead_temps[arg] = 0;
1292 s->op_dead_args[op_index] = dead_args;
1294 args--;
1296 break;
1297 case INDEX_op_set_label:
1298 args--;
1299 /* mark end of basic block */
1300 tcg_la_bb_end(s, dead_temps);
1301 break;
1302 case INDEX_op_debug_insn_start:
1303 args -= def->nb_args;
1304 break;
1305 case INDEX_op_nopn:
1306 nb_args = args[-1];
1307 args -= nb_args;
1308 break;
1309 case INDEX_op_discard:
1310 args--;
1311 /* mark the temporary as dead */
1312 dead_temps[args[0]] = 1;
1313 break;
1314 case INDEX_op_end:
1315 break;
1316 /* XXX: optimize by hardcoding common cases (e.g. triadic ops) */
1317 default:
1318 args -= def->nb_args;
1319 nb_iargs = def->nb_iargs;
1320 nb_oargs = def->nb_oargs;
1322 /* Test if the operation can be removed because all
1323 its outputs are dead. We assume that nb_oargs == 0
1324 implies side effects */
1325 if (!(def->flags & TCG_OPF_SIDE_EFFECTS) && nb_oargs != 0) {
1326 for(i = 0; i < nb_oargs; i++) {
1327 arg = args[i];
1328 if (!dead_temps[arg])
1329 goto do_not_remove;
1331 tcg_set_nop(s, gen_opc_buf + op_index, args, def->nb_args);
1332 #ifdef CONFIG_PROFILER
1333 s->del_op_count++;
1334 #endif
1335 } else {
1336 do_not_remove:
1338 /* output args are dead */
1339 dead_args = 0;
1340 for(i = 0; i < nb_oargs; i++) {
1341 arg = args[i];
1342 if (dead_temps[arg]) {
1343 dead_args |= (1 << i);
1345 dead_temps[arg] = 1;
1348 /* if end of basic block, update */
1349 if (def->flags & TCG_OPF_BB_END) {
1350 tcg_la_bb_end(s, dead_temps);
1351 } else if (def->flags & TCG_OPF_CALL_CLOBBER) {
1352 /* globals are live */
1353 memset(dead_temps, 0, s->nb_globals);
1356 /* input args are live */
1357 for(i = nb_oargs; i < nb_oargs + nb_iargs; i++) {
1358 arg = args[i];
1359 if (dead_temps[arg]) {
1360 dead_args |= (1 << i);
1362 dead_temps[arg] = 0;
1364 s->op_dead_args[op_index] = dead_args;
1366 break;
1368 op_index--;
1371 if (args != gen_opparam_buf)
1372 tcg_abort();
1374 #else
1375 /* dummy liveness analysis */
1376 static void tcg_liveness_analysis(TCGContext *s)
1378 int nb_ops;
1379 nb_ops = gen_opc_ptr - gen_opc_buf;
1381 s->op_dead_args = tcg_malloc(nb_ops * sizeof(uint16_t));
1382 memset(s->op_dead_args, 0, nb_ops * sizeof(uint16_t));
1384 #endif
1386 #ifndef NDEBUG
1387 static void dump_regs(TCGContext *s)
1389 TCGTemp *ts;
1390 int i;
1391 char buf[64];
1393 for(i = 0; i < s->nb_temps; i++) {
1394 ts = &s->temps[i];
1395 printf(" %10s: ", tcg_get_arg_str_idx(s, buf, sizeof(buf), i));
1396 switch(ts->val_type) {
1397 case TEMP_VAL_REG:
1398 printf("%s", tcg_target_reg_names[ts->reg]);
1399 break;
1400 case TEMP_VAL_MEM:
1401 printf("%d(%s)", (int)ts->mem_offset, tcg_target_reg_names[ts->mem_reg]);
1402 break;
1403 case TEMP_VAL_CONST:
1404 printf("$0x%" TCG_PRIlx, ts->val);
1405 break;
1406 case TEMP_VAL_DEAD:
1407 printf("D");
1408 break;
1409 default:
1410 printf("???");
1411 break;
1413 printf("\n");
1416 for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
1417 if (s->reg_to_temp[i] >= 0) {
1418 printf("%s: %s\n",
1419 tcg_target_reg_names[i],
1420 tcg_get_arg_str_idx(s, buf, sizeof(buf), s->reg_to_temp[i]));
1425 static void check_regs(TCGContext *s)
1427 int reg, k;
1428 TCGTemp *ts;
1429 char buf[64];
1431 for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1432 k = s->reg_to_temp[reg];
1433 if (k >= 0) {
1434 ts = &s->temps[k];
1435 if (ts->val_type != TEMP_VAL_REG ||
1436 ts->reg != reg) {
1437 printf("Inconsistency for register %s:\n",
1438 tcg_target_reg_names[reg]);
1439 goto fail;
1443 for(k = 0; k < s->nb_temps; k++) {
1444 ts = &s->temps[k];
1445 if (ts->val_type == TEMP_VAL_REG &&
1446 !ts->fixed_reg &&
1447 s->reg_to_temp[ts->reg] != k) {
1448 printf("Inconsistency for temp %s:\n",
1449 tcg_get_arg_str_idx(s, buf, sizeof(buf), k));
1450 fail:
1451 printf("reg state:\n");
1452 dump_regs(s);
1453 tcg_abort();
1457 #endif
1459 static void temp_allocate_frame(TCGContext *s, int temp)
1461 TCGTemp *ts;
1462 ts = &s->temps[temp];
1463 #ifndef __sparc_v9__ /* Sparc64 stack is accessed with offset of 2047 */
1464 s->current_frame_offset = (s->current_frame_offset +
1465 (tcg_target_long)sizeof(tcg_target_long) - 1) &
1466 ~(sizeof(tcg_target_long) - 1);
1467 #endif
1468 if (s->current_frame_offset + (tcg_target_long)sizeof(tcg_target_long) >
1469 s->frame_end) {
1470 tcg_abort();
1472 ts->mem_offset = s->current_frame_offset;
1473 ts->mem_reg = s->frame_reg;
1474 ts->mem_allocated = 1;
1475 s->current_frame_offset += (tcg_target_long)sizeof(tcg_target_long);
1478 /* free register 'reg' by spilling the corresponding temporary if necessary */
1479 static void tcg_reg_free(TCGContext *s, int reg)
1481 TCGTemp *ts;
1482 int temp;
1484 temp = s->reg_to_temp[reg];
1485 if (temp != -1) {
1486 ts = &s->temps[temp];
1487 assert(ts->val_type == TEMP_VAL_REG);
1488 if (!ts->mem_coherent) {
1489 if (!ts->mem_allocated)
1490 temp_allocate_frame(s, temp);
1491 tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1493 ts->val_type = TEMP_VAL_MEM;
1494 s->reg_to_temp[reg] = -1;
1498 /* Allocate a register belonging to reg1 & ~reg2 */
1499 static int tcg_reg_alloc(TCGContext *s, TCGRegSet reg1, TCGRegSet reg2)
1501 int i, reg;
1502 TCGRegSet reg_ct;
1504 tcg_regset_andnot(reg_ct, reg1, reg2);
1506 /* first try free registers */
1507 for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1508 reg = tcg_target_reg_alloc_order[i];
1509 if (tcg_regset_test_reg(reg_ct, reg) && s->reg_to_temp[reg] == -1)
1510 return reg;
1513 /* XXX: do better spill choice */
1514 for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1515 reg = tcg_target_reg_alloc_order[i];
1516 if (tcg_regset_test_reg(reg_ct, reg)) {
1517 tcg_reg_free(s, reg);
1518 return reg;
1522 tcg_abort();
1525 /* save a temporary to memory. 'allocated_regs' is used in case a
1526 temporary registers needs to be allocated to store a constant. */
1527 static void temp_save(TCGContext *s, int temp, TCGRegSet allocated_regs)
1529 TCGTemp *ts;
1530 int reg;
1532 ts = &s->temps[temp];
1533 if (!ts->fixed_reg) {
1534 switch(ts->val_type) {
1535 case TEMP_VAL_REG:
1536 tcg_reg_free(s, ts->reg);
1537 break;
1538 case TEMP_VAL_DEAD:
1539 ts->val_type = TEMP_VAL_MEM;
1540 break;
1541 case TEMP_VAL_CONST:
1542 reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type],
1543 allocated_regs);
1544 if (!ts->mem_allocated)
1545 temp_allocate_frame(s, temp);
1546 tcg_out_movi(s, ts->type, reg, ts->val);
1547 tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1548 ts->val_type = TEMP_VAL_MEM;
1549 break;
1550 case TEMP_VAL_MEM:
1551 break;
1552 default:
1553 tcg_abort();
1558 /* save globals to their canonical location and assume they can be
1559 modified be the following code. 'allocated_regs' is used in case a
1560 temporary registers needs to be allocated to store a constant. */
1561 static void save_globals(TCGContext *s, TCGRegSet allocated_regs)
1563 int i;
1565 for(i = 0; i < s->nb_globals; i++) {
1566 temp_save(s, i, allocated_regs);
1570 /* at the end of a basic block, we assume all temporaries are dead and
1571 all globals are stored at their canonical location. */
1572 static void tcg_reg_alloc_bb_end(TCGContext *s, TCGRegSet allocated_regs)
1574 TCGTemp *ts;
1575 int i;
1577 for(i = s->nb_globals; i < s->nb_temps; i++) {
1578 ts = &s->temps[i];
1579 if (ts->temp_local) {
1580 temp_save(s, i, allocated_regs);
1581 } else {
1582 if (ts->val_type == TEMP_VAL_REG) {
1583 s->reg_to_temp[ts->reg] = -1;
1585 ts->val_type = TEMP_VAL_DEAD;
1589 save_globals(s, allocated_regs);
1592 #define IS_DEAD_ARG(n) ((dead_args >> (n)) & 1)
1594 static void tcg_reg_alloc_movi(TCGContext *s, const TCGArg *args)
1596 TCGTemp *ots;
1597 tcg_target_ulong val;
1599 ots = &s->temps[args[0]];
1600 val = args[1];
1602 if (ots->fixed_reg) {
1603 /* for fixed registers, we do not do any constant
1604 propagation */
1605 tcg_out_movi(s, ots->type, ots->reg, val);
1606 } else {
1607 /* The movi is not explicitly generated here */
1608 if (ots->val_type == TEMP_VAL_REG)
1609 s->reg_to_temp[ots->reg] = -1;
1610 ots->val_type = TEMP_VAL_CONST;
1611 ots->val = val;
1615 static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
1616 const TCGArg *args,
1617 unsigned int dead_args)
1619 TCGTemp *ts, *ots;
1620 int reg;
1621 const TCGArgConstraint *arg_ct;
1623 ots = &s->temps[args[0]];
1624 ts = &s->temps[args[1]];
1625 arg_ct = &def->args_ct[0];
1627 /* XXX: always mark arg dead if IS_DEAD_ARG(1) */
1628 if (ts->val_type == TEMP_VAL_REG) {
1629 if (IS_DEAD_ARG(1) && !ts->fixed_reg && !ots->fixed_reg) {
1630 /* the mov can be suppressed */
1631 if (ots->val_type == TEMP_VAL_REG)
1632 s->reg_to_temp[ots->reg] = -1;
1633 reg = ts->reg;
1634 s->reg_to_temp[reg] = -1;
1635 ts->val_type = TEMP_VAL_DEAD;
1636 } else {
1637 if (ots->val_type == TEMP_VAL_REG) {
1638 reg = ots->reg;
1639 } else {
1640 reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1642 if (ts->reg != reg) {
1643 tcg_out_mov(s, ots->type, reg, ts->reg);
1646 } else if (ts->val_type == TEMP_VAL_MEM) {
1647 if (ots->val_type == TEMP_VAL_REG) {
1648 reg = ots->reg;
1649 } else {
1650 reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1652 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1653 } else if (ts->val_type == TEMP_VAL_CONST) {
1654 if (ots->fixed_reg) {
1655 reg = ots->reg;
1656 tcg_out_movi(s, ots->type, reg, ts->val);
1657 } else {
1658 /* propagate constant */
1659 if (ots->val_type == TEMP_VAL_REG)
1660 s->reg_to_temp[ots->reg] = -1;
1661 ots->val_type = TEMP_VAL_CONST;
1662 ots->val = ts->val;
1663 return;
1665 } else {
1666 tcg_abort();
1668 s->reg_to_temp[reg] = args[0];
1669 ots->reg = reg;
1670 ots->val_type = TEMP_VAL_REG;
1671 ots->mem_coherent = 0;
1674 static void tcg_reg_alloc_op(TCGContext *s,
1675 const TCGOpDef *def, TCGOpcode opc,
1676 const TCGArg *args,
1677 unsigned int dead_args)
1679 TCGRegSet allocated_regs;
1680 int i, k, nb_iargs, nb_oargs, reg;
1681 TCGArg arg;
1682 const TCGArgConstraint *arg_ct;
1683 TCGTemp *ts;
1684 TCGArg new_args[TCG_MAX_OP_ARGS];
1685 int const_args[TCG_MAX_OP_ARGS];
1687 nb_oargs = def->nb_oargs;
1688 nb_iargs = def->nb_iargs;
1690 /* copy constants */
1691 memcpy(new_args + nb_oargs + nb_iargs,
1692 args + nb_oargs + nb_iargs,
1693 sizeof(TCGArg) * def->nb_cargs);
1695 /* satisfy input constraints */
1696 tcg_regset_set(allocated_regs, s->reserved_regs);
1697 for(k = 0; k < nb_iargs; k++) {
1698 i = def->sorted_args[nb_oargs + k];
1699 arg = args[i];
1700 arg_ct = &def->args_ct[i];
1701 ts = &s->temps[arg];
1702 if (ts->val_type == TEMP_VAL_MEM) {
1703 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1704 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1705 ts->val_type = TEMP_VAL_REG;
1706 ts->reg = reg;
1707 ts->mem_coherent = 1;
1708 s->reg_to_temp[reg] = arg;
1709 } else if (ts->val_type == TEMP_VAL_CONST) {
1710 if (tcg_target_const_match(ts->val, arg_ct)) {
1711 /* constant is OK for instruction */
1712 const_args[i] = 1;
1713 new_args[i] = ts->val;
1714 goto iarg_end;
1715 } else {
1716 /* need to move to a register */
1717 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1718 tcg_out_movi(s, ts->type, reg, ts->val);
1719 ts->val_type = TEMP_VAL_REG;
1720 ts->reg = reg;
1721 ts->mem_coherent = 0;
1722 s->reg_to_temp[reg] = arg;
1725 assert(ts->val_type == TEMP_VAL_REG);
1726 if (arg_ct->ct & TCG_CT_IALIAS) {
1727 if (ts->fixed_reg) {
1728 /* if fixed register, we must allocate a new register
1729 if the alias is not the same register */
1730 if (arg != args[arg_ct->alias_index])
1731 goto allocate_in_reg;
1732 } else {
1733 /* if the input is aliased to an output and if it is
1734 not dead after the instruction, we must allocate
1735 a new register and move it */
1736 if (!IS_DEAD_ARG(i)) {
1737 goto allocate_in_reg;
1741 reg = ts->reg;
1742 if (tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1743 /* nothing to do : the constraint is satisfied */
1744 } else {
1745 allocate_in_reg:
1746 /* allocate a new register matching the constraint
1747 and move the temporary register into it */
1748 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1749 tcg_out_mov(s, ts->type, reg, ts->reg);
1751 new_args[i] = reg;
1752 const_args[i] = 0;
1753 tcg_regset_set_reg(allocated_regs, reg);
1754 iarg_end: ;
1757 if (def->flags & TCG_OPF_BB_END) {
1758 tcg_reg_alloc_bb_end(s, allocated_regs);
1759 } else {
1760 /* mark dead temporaries and free the associated registers */
1761 for(i = nb_oargs; i < nb_oargs + nb_iargs; i++) {
1762 arg = args[i];
1763 if (IS_DEAD_ARG(i)) {
1764 ts = &s->temps[arg];
1765 if (!ts->fixed_reg) {
1766 if (ts->val_type == TEMP_VAL_REG)
1767 s->reg_to_temp[ts->reg] = -1;
1768 ts->val_type = TEMP_VAL_DEAD;
1773 if (def->flags & TCG_OPF_CALL_CLOBBER) {
1774 /* XXX: permit generic clobber register list ? */
1775 for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1776 if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
1777 tcg_reg_free(s, reg);
1780 /* XXX: for load/store we could do that only for the slow path
1781 (i.e. when a memory callback is called) */
1783 /* store globals and free associated registers (we assume the insn
1784 can modify any global. */
1785 save_globals(s, allocated_regs);
1788 /* satisfy the output constraints */
1789 tcg_regset_set(allocated_regs, s->reserved_regs);
1790 for(k = 0; k < nb_oargs; k++) {
1791 i = def->sorted_args[k];
1792 arg = args[i];
1793 arg_ct = &def->args_ct[i];
1794 ts = &s->temps[arg];
1795 if (arg_ct->ct & TCG_CT_ALIAS) {
1796 reg = new_args[arg_ct->alias_index];
1797 } else {
1798 /* if fixed register, we try to use it */
1799 reg = ts->reg;
1800 if (ts->fixed_reg &&
1801 tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1802 goto oarg_end;
1804 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1806 tcg_regset_set_reg(allocated_regs, reg);
1807 /* if a fixed register is used, then a move will be done afterwards */
1808 if (!ts->fixed_reg) {
1809 if (ts->val_type == TEMP_VAL_REG)
1810 s->reg_to_temp[ts->reg] = -1;
1811 if (IS_DEAD_ARG(i)) {
1812 ts->val_type = TEMP_VAL_DEAD;
1813 } else {
1814 ts->val_type = TEMP_VAL_REG;
1815 ts->reg = reg;
1816 /* temp value is modified, so the value kept in memory is
1817 potentially not the same */
1818 ts->mem_coherent = 0;
1819 s->reg_to_temp[reg] = arg;
1822 oarg_end:
1823 new_args[i] = reg;
1827 /* emit instruction */
1828 tcg_out_op(s, opc, new_args, const_args);
1830 /* move the outputs in the correct register if needed */
1831 for(i = 0; i < nb_oargs; i++) {
1832 ts = &s->temps[args[i]];
1833 reg = new_args[i];
1834 if (ts->fixed_reg && ts->reg != reg) {
1835 tcg_out_mov(s, ts->type, ts->reg, reg);
1840 #ifdef TCG_TARGET_STACK_GROWSUP
1841 #define STACK_DIR(x) (-(x))
1842 #else
1843 #define STACK_DIR(x) (x)
1844 #endif
1846 static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
1847 TCGOpcode opc, const TCGArg *args,
1848 unsigned int dead_args)
1850 int nb_iargs, nb_oargs, flags, nb_regs, i, reg, nb_params;
1851 TCGArg arg, func_arg;
1852 TCGTemp *ts;
1853 tcg_target_long stack_offset, call_stack_size, func_addr;
1854 int const_func_arg, allocate_args;
1855 TCGRegSet allocated_regs;
1856 const TCGArgConstraint *arg_ct;
1858 arg = *args++;
1860 nb_oargs = arg >> 16;
1861 nb_iargs = arg & 0xffff;
1862 nb_params = nb_iargs - 1;
1864 flags = args[nb_oargs + nb_iargs];
1866 nb_regs = tcg_target_get_call_iarg_regs_count(flags);
1867 if (nb_regs > nb_params)
1868 nb_regs = nb_params;
1870 /* assign stack slots first */
1871 call_stack_size = (nb_params - nb_regs) * sizeof(tcg_target_long);
1872 call_stack_size = (call_stack_size + TCG_TARGET_STACK_ALIGN - 1) &
1873 ~(TCG_TARGET_STACK_ALIGN - 1);
1874 allocate_args = (call_stack_size > TCG_STATIC_CALL_ARGS_SIZE);
1875 if (allocate_args) {
1876 /* XXX: if more than TCG_STATIC_CALL_ARGS_SIZE is needed,
1877 preallocate call stack */
1878 tcg_abort();
1881 stack_offset = TCG_TARGET_CALL_STACK_OFFSET;
1882 for(i = nb_regs; i < nb_params; i++) {
1883 arg = args[nb_oargs + i];
1884 #ifdef TCG_TARGET_STACK_GROWSUP
1885 stack_offset -= sizeof(tcg_target_long);
1886 #endif
1887 if (arg != TCG_CALL_DUMMY_ARG) {
1888 ts = &s->temps[arg];
1889 if (ts->val_type == TEMP_VAL_REG) {
1890 tcg_out_st(s, ts->type, ts->reg, TCG_REG_CALL_STACK, stack_offset);
1891 } else if (ts->val_type == TEMP_VAL_MEM) {
1892 reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type],
1893 s->reserved_regs);
1894 /* XXX: not correct if reading values from the stack */
1895 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1896 tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
1897 } else if (ts->val_type == TEMP_VAL_CONST) {
1898 reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type],
1899 s->reserved_regs);
1900 /* XXX: sign extend may be needed on some targets */
1901 tcg_out_movi(s, ts->type, reg, ts->val);
1902 tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
1903 } else {
1904 tcg_abort();
1907 #ifndef TCG_TARGET_STACK_GROWSUP
1908 stack_offset += sizeof(tcg_target_long);
1909 #endif
1912 /* assign input registers */
1913 tcg_regset_set(allocated_regs, s->reserved_regs);
1914 for(i = 0; i < nb_regs; i++) {
1915 arg = args[nb_oargs + i];
1916 if (arg != TCG_CALL_DUMMY_ARG) {
1917 ts = &s->temps[arg];
1918 reg = tcg_target_call_iarg_regs[i];
1919 tcg_reg_free(s, reg);
1920 if (ts->val_type == TEMP_VAL_REG) {
1921 if (ts->reg != reg) {
1922 tcg_out_mov(s, ts->type, reg, ts->reg);
1924 } else if (ts->val_type == TEMP_VAL_MEM) {
1925 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1926 } else if (ts->val_type == TEMP_VAL_CONST) {
1927 /* XXX: sign extend ? */
1928 tcg_out_movi(s, ts->type, reg, ts->val);
1929 } else {
1930 tcg_abort();
1932 tcg_regset_set_reg(allocated_regs, reg);
1936 /* assign function address */
1937 func_arg = args[nb_oargs + nb_iargs - 1];
1938 arg_ct = &def->args_ct[0];
1939 ts = &s->temps[func_arg];
1940 func_addr = ts->val;
1941 const_func_arg = 0;
1942 if (ts->val_type == TEMP_VAL_MEM) {
1943 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1944 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1945 func_arg = reg;
1946 tcg_regset_set_reg(allocated_regs, reg);
1947 } else if (ts->val_type == TEMP_VAL_REG) {
1948 reg = ts->reg;
1949 if (!tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1950 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1951 tcg_out_mov(s, ts->type, reg, ts->reg);
1953 func_arg = reg;
1954 tcg_regset_set_reg(allocated_regs, reg);
1955 } else if (ts->val_type == TEMP_VAL_CONST) {
1956 if (tcg_target_const_match(func_addr, arg_ct)) {
1957 const_func_arg = 1;
1958 func_arg = func_addr;
1959 } else {
1960 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1961 tcg_out_movi(s, ts->type, reg, func_addr);
1962 func_arg = reg;
1963 tcg_regset_set_reg(allocated_regs, reg);
1965 } else {
1966 tcg_abort();
1970 /* mark dead temporaries and free the associated registers */
1971 for(i = nb_oargs; i < nb_iargs + nb_oargs; i++) {
1972 arg = args[i];
1973 if (IS_DEAD_ARG(i)) {
1974 ts = &s->temps[arg];
1975 if (!ts->fixed_reg) {
1976 if (ts->val_type == TEMP_VAL_REG)
1977 s->reg_to_temp[ts->reg] = -1;
1978 ts->val_type = TEMP_VAL_DEAD;
1983 /* clobber call registers */
1984 for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1985 if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
1986 tcg_reg_free(s, reg);
1990 /* store globals and free associated registers (we assume the call
1991 can modify any global. */
1992 if (!(flags & TCG_CALL_CONST)) {
1993 save_globals(s, allocated_regs);
1996 tcg_out_op(s, opc, &func_arg, &const_func_arg);
1998 /* assign output registers and emit moves if needed */
1999 for(i = 0; i < nb_oargs; i++) {
2000 arg = args[i];
2001 ts = &s->temps[arg];
2002 reg = tcg_target_call_oarg_regs[i];
2003 assert(s->reg_to_temp[reg] == -1);
2004 if (ts->fixed_reg) {
2005 if (ts->reg != reg) {
2006 tcg_out_mov(s, ts->type, ts->reg, reg);
2008 } else {
2009 if (ts->val_type == TEMP_VAL_REG)
2010 s->reg_to_temp[ts->reg] = -1;
2011 if (IS_DEAD_ARG(i)) {
2012 ts->val_type = TEMP_VAL_DEAD;
2013 } else {
2014 ts->val_type = TEMP_VAL_REG;
2015 ts->reg = reg;
2016 ts->mem_coherent = 0;
2017 s->reg_to_temp[reg] = arg;
2022 return nb_iargs + nb_oargs + def->nb_cargs + 1;
2025 #ifdef CONFIG_PROFILER
2027 static int64_t tcg_table_op_count[NB_OPS];
2029 static void dump_op_count(void)
2031 int i;
2032 FILE *f;
2033 f = fopen("/tmp/op.log", "w");
2034 for(i = INDEX_op_end; i < NB_OPS; i++) {
2035 fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name, tcg_table_op_count[i]);
2037 fclose(f);
2039 #endif
2042 static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
2043 long search_pc)
2045 TCGOpcode opc;
2046 int op_index;
2047 const TCGOpDef *def;
2048 unsigned int dead_args;
2049 const TCGArg *args;
2051 #ifdef DEBUG_DISAS
2052 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
2053 qemu_log("OP:\n");
2054 tcg_dump_ops(s, logfile);
2055 qemu_log("\n");
2057 #endif
2059 #ifdef USE_TCG_OPTIMIZATIONS
2060 gen_opparam_ptr =
2061 tcg_optimize(s, gen_opc_ptr, gen_opparam_buf, tcg_op_defs);
2062 #endif
2064 #ifdef CONFIG_PROFILER
2065 s->la_time -= profile_getclock();
2066 #endif
2067 tcg_liveness_analysis(s);
2068 #ifdef CONFIG_PROFILER
2069 s->la_time += profile_getclock();
2070 #endif
2072 #ifdef DEBUG_DISAS
2073 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_OPT))) {
2074 qemu_log("OP after liveness analysis:\n");
2075 tcg_dump_ops(s, logfile);
2076 qemu_log("\n");
2078 #endif
2080 tcg_reg_alloc_start(s);
2082 s->code_buf = gen_code_buf;
2083 s->code_ptr = gen_code_buf;
2085 args = gen_opparam_buf;
2086 op_index = 0;
2088 for(;;) {
2089 opc = gen_opc_buf[op_index];
2090 #ifdef CONFIG_PROFILER
2091 tcg_table_op_count[opc]++;
2092 #endif
2093 def = &tcg_op_defs[opc];
2094 #if 0
2095 printf("%s: %d %d %d\n", def->name,
2096 def->nb_oargs, def->nb_iargs, def->nb_cargs);
2097 // dump_regs(s);
2098 #endif
2099 switch(opc) {
2100 case INDEX_op_mov_i32:
2101 #if TCG_TARGET_REG_BITS == 64
2102 case INDEX_op_mov_i64:
2103 #endif
2104 dead_args = s->op_dead_args[op_index];
2105 tcg_reg_alloc_mov(s, def, args, dead_args);
2106 break;
2107 case INDEX_op_movi_i32:
2108 #if TCG_TARGET_REG_BITS == 64
2109 case INDEX_op_movi_i64:
2110 #endif
2111 tcg_reg_alloc_movi(s, args);
2112 break;
2113 case INDEX_op_debug_insn_start:
2114 /* debug instruction */
2115 break;
2116 case INDEX_op_nop:
2117 case INDEX_op_nop1:
2118 case INDEX_op_nop2:
2119 case INDEX_op_nop3:
2120 break;
2121 case INDEX_op_nopn:
2122 args += args[0];
2123 goto next;
2124 case INDEX_op_discard:
2126 TCGTemp *ts;
2127 ts = &s->temps[args[0]];
2128 /* mark the temporary as dead */
2129 if (!ts->fixed_reg) {
2130 if (ts->val_type == TEMP_VAL_REG)
2131 s->reg_to_temp[ts->reg] = -1;
2132 ts->val_type = TEMP_VAL_DEAD;
2135 break;
2136 case INDEX_op_set_label:
2137 tcg_reg_alloc_bb_end(s, s->reserved_regs);
2138 tcg_out_label(s, args[0], (long)s->code_ptr);
2139 break;
2140 case INDEX_op_call:
2141 dead_args = s->op_dead_args[op_index];
2142 args += tcg_reg_alloc_call(s, def, opc, args, dead_args);
2143 goto next;
2144 case INDEX_op_end:
2145 goto the_end;
2146 default:
2147 /* Sanity check that we've not introduced any unhandled opcodes. */
2148 if (def->flags & TCG_OPF_NOT_PRESENT) {
2149 tcg_abort();
2151 /* Note: in order to speed up the code, it would be much
2152 faster to have specialized register allocator functions for
2153 some common argument patterns */
2154 dead_args = s->op_dead_args[op_index];
2155 tcg_reg_alloc_op(s, def, opc, args, dead_args);
2156 break;
2158 args += def->nb_args;
2159 next:
2160 if (search_pc >= 0 && search_pc < s->code_ptr - gen_code_buf) {
2161 return op_index;
2163 op_index++;
2164 #ifndef NDEBUG
2165 check_regs(s);
2166 #endif
2168 the_end:
2169 return -1;
2172 int tcg_gen_code(TCGContext *s, uint8_t *gen_code_buf)
2174 #ifdef CONFIG_PROFILER
2176 int n;
2177 n = (gen_opc_ptr - gen_opc_buf);
2178 s->op_count += n;
2179 if (n > s->op_count_max)
2180 s->op_count_max = n;
2182 s->temp_count += s->nb_temps;
2183 if (s->nb_temps > s->temp_count_max)
2184 s->temp_count_max = s->nb_temps;
2186 #endif
2188 tcg_gen_code_common(s, gen_code_buf, -1);
2190 /* flush instruction cache */
2191 flush_icache_range((unsigned long)gen_code_buf,
2192 (unsigned long)s->code_ptr);
2193 return s->code_ptr - gen_code_buf;
2196 /* Return the index of the micro operation such as the pc after is <
2197 offset bytes from the start of the TB. The contents of gen_code_buf must
2198 not be changed, though writing the same values is ok.
2199 Return -1 if not found. */
2200 int tcg_gen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, long offset)
2202 return tcg_gen_code_common(s, gen_code_buf, offset);
2205 #ifdef CONFIG_PROFILER
2206 void tcg_dump_info(FILE *f, fprintf_function cpu_fprintf)
2208 TCGContext *s = &tcg_ctx;
2209 int64_t tot;
2211 tot = s->interm_time + s->code_time;
2212 cpu_fprintf(f, "JIT cycles %" PRId64 " (%0.3f s at 2.4 GHz)\n",
2213 tot, tot / 2.4e9);
2214 cpu_fprintf(f, "translated TBs %" PRId64 " (aborted=%" PRId64 " %0.1f%%)\n",
2215 s->tb_count,
2216 s->tb_count1 - s->tb_count,
2217 s->tb_count1 ? (double)(s->tb_count1 - s->tb_count) / s->tb_count1 * 100.0 : 0);
2218 cpu_fprintf(f, "avg ops/TB %0.1f max=%d\n",
2219 s->tb_count ? (double)s->op_count / s->tb_count : 0, s->op_count_max);
2220 cpu_fprintf(f, "deleted ops/TB %0.2f\n",
2221 s->tb_count ?
2222 (double)s->del_op_count / s->tb_count : 0);
2223 cpu_fprintf(f, "avg temps/TB %0.2f max=%d\n",
2224 s->tb_count ?
2225 (double)s->temp_count / s->tb_count : 0,
2226 s->temp_count_max);
2228 cpu_fprintf(f, "cycles/op %0.1f\n",
2229 s->op_count ? (double)tot / s->op_count : 0);
2230 cpu_fprintf(f, "cycles/in byte %0.1f\n",
2231 s->code_in_len ? (double)tot / s->code_in_len : 0);
2232 cpu_fprintf(f, "cycles/out byte %0.1f\n",
2233 s->code_out_len ? (double)tot / s->code_out_len : 0);
2234 if (tot == 0)
2235 tot = 1;
2236 cpu_fprintf(f, " gen_interm time %0.1f%%\n",
2237 (double)s->interm_time / tot * 100.0);
2238 cpu_fprintf(f, " gen_code time %0.1f%%\n",
2239 (double)s->code_time / tot * 100.0);
2240 cpu_fprintf(f, "liveness/code time %0.1f%%\n",
2241 (double)s->la_time / (s->code_time ? s->code_time : 1) * 100.0);
2242 cpu_fprintf(f, "cpu_restore count %" PRId64 "\n",
2243 s->restore_count);
2244 cpu_fprintf(f, " avg cycles %0.1f\n",
2245 s->restore_count ? (double)s->restore_time / s->restore_count : 0);
2247 dump_op_count();
2249 #else
2250 void tcg_dump_info(FILE *f, fprintf_function cpu_fprintf)
2252 cpu_fprintf(f, "[TCG profiler not compiled]\n");
2254 #endif