fix compilation with stderr trace backend
[qemu/ar7.git] / tcg / tcg.c
blob411f971289ac11f4c9ec4bdd0b77c588cbbc595f
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 static void tcg_target_init(TCGContext *s);
67 static void tcg_target_qemu_prologue(TCGContext *s);
68 static void patch_reloc(uint8_t *code_ptr, int type,
69 tcg_target_long value, tcg_target_long addend);
71 TCGOpDef tcg_op_defs[] = {
72 #define DEF(s, oargs, iargs, cargs, flags) { #s, oargs, iargs, cargs, iargs + oargs + cargs, flags },
73 #include "tcg-opc.h"
74 #undef DEF
77 static TCGRegSet tcg_target_available_regs[2];
78 static TCGRegSet tcg_target_call_clobber_regs;
80 /* XXX: move that inside the context */
81 uint16_t *gen_opc_ptr;
82 TCGArg *gen_opparam_ptr;
84 static inline void tcg_out8(TCGContext *s, uint8_t v)
86 *s->code_ptr++ = v;
89 static inline void tcg_out16(TCGContext *s, uint16_t v)
91 *(uint16_t *)s->code_ptr = v;
92 s->code_ptr += 2;
95 static inline void tcg_out32(TCGContext *s, uint32_t v)
97 *(uint32_t *)s->code_ptr = v;
98 s->code_ptr += 4;
101 /* label relocation processing */
103 static void tcg_out_reloc(TCGContext *s, uint8_t *code_ptr, int type,
104 int label_index, long addend)
106 TCGLabel *l;
107 TCGRelocation *r;
109 l = &s->labels[label_index];
110 if (l->has_value) {
111 /* FIXME: This may break relocations on RISC targets that
112 modify instruction fields in place. The caller may not have
113 written the initial value. */
114 patch_reloc(code_ptr, type, l->u.value, addend);
115 } else {
116 /* add a new relocation entry */
117 r = tcg_malloc(sizeof(TCGRelocation));
118 r->type = type;
119 r->ptr = code_ptr;
120 r->addend = addend;
121 r->next = l->u.first_reloc;
122 l->u.first_reloc = r;
126 static void tcg_out_label(TCGContext *s, int label_index,
127 tcg_target_long value)
129 TCGLabel *l;
130 TCGRelocation *r;
132 l = &s->labels[label_index];
133 if (l->has_value)
134 tcg_abort();
135 r = l->u.first_reloc;
136 while (r != NULL) {
137 patch_reloc(r->ptr, r->type, value, r->addend);
138 r = r->next;
140 l->has_value = 1;
141 l->u.value = value;
144 int gen_new_label(void)
146 TCGContext *s = &tcg_ctx;
147 int idx;
148 TCGLabel *l;
150 if (s->nb_labels >= TCG_MAX_LABELS)
151 tcg_abort();
152 idx = s->nb_labels++;
153 l = &s->labels[idx];
154 l->has_value = 0;
155 l->u.first_reloc = NULL;
156 return idx;
159 #include "tcg-target.c"
161 /* pool based memory allocation */
162 void *tcg_malloc_internal(TCGContext *s, int size)
164 TCGPool *p;
165 int pool_size;
167 if (size > TCG_POOL_CHUNK_SIZE) {
168 /* big malloc: insert a new pool (XXX: could optimize) */
169 p = g_malloc(sizeof(TCGPool) + size);
170 p->size = size;
171 if (s->pool_current)
172 s->pool_current->next = p;
173 else
174 s->pool_first = p;
175 p->next = s->pool_current;
176 } else {
177 p = s->pool_current;
178 if (!p) {
179 p = s->pool_first;
180 if (!p)
181 goto new_pool;
182 } else {
183 if (!p->next) {
184 new_pool:
185 pool_size = TCG_POOL_CHUNK_SIZE;
186 p = g_malloc(sizeof(TCGPool) + pool_size);
187 p->size = pool_size;
188 p->next = NULL;
189 if (s->pool_current)
190 s->pool_current->next = p;
191 else
192 s->pool_first = p;
193 } else {
194 p = p->next;
198 s->pool_current = p;
199 s->pool_cur = p->data + size;
200 s->pool_end = p->data + p->size;
201 return p->data;
204 void tcg_pool_reset(TCGContext *s)
206 s->pool_cur = s->pool_end = NULL;
207 s->pool_current = NULL;
210 void tcg_context_init(TCGContext *s)
212 int op, total_args, n;
213 TCGOpDef *def;
214 TCGArgConstraint *args_ct;
215 int *sorted_args;
217 memset(s, 0, sizeof(*s));
218 s->temps = s->static_temps;
219 s->nb_globals = 0;
221 /* Count total number of arguments and allocate the corresponding
222 space */
223 total_args = 0;
224 for(op = 0; op < NB_OPS; op++) {
225 def = &tcg_op_defs[op];
226 n = def->nb_iargs + def->nb_oargs;
227 total_args += n;
230 args_ct = g_malloc(sizeof(TCGArgConstraint) * total_args);
231 sorted_args = g_malloc(sizeof(int) * total_args);
233 for(op = 0; op < NB_OPS; op++) {
234 def = &tcg_op_defs[op];
235 def->args_ct = args_ct;
236 def->sorted_args = sorted_args;
237 n = def->nb_iargs + def->nb_oargs;
238 sorted_args += n;
239 args_ct += n;
242 tcg_target_init(s);
245 void tcg_prologue_init(TCGContext *s)
247 /* init global prologue and epilogue */
248 s->code_buf = code_gen_prologue;
249 s->code_ptr = s->code_buf;
250 tcg_target_qemu_prologue(s);
251 flush_icache_range((unsigned long)s->code_buf,
252 (unsigned long)s->code_ptr);
255 void tcg_set_frame(TCGContext *s, int reg,
256 tcg_target_long start, tcg_target_long size)
258 s->frame_start = start;
259 s->frame_end = start + size;
260 s->frame_reg = reg;
263 void tcg_func_start(TCGContext *s)
265 int i;
266 tcg_pool_reset(s);
267 s->nb_temps = s->nb_globals;
268 for(i = 0; i < (TCG_TYPE_COUNT * 2); i++)
269 s->first_free_temp[i] = -1;
270 s->labels = tcg_malloc(sizeof(TCGLabel) * TCG_MAX_LABELS);
271 s->nb_labels = 0;
272 s->current_frame_offset = s->frame_start;
274 gen_opc_ptr = gen_opc_buf;
275 gen_opparam_ptr = gen_opparam_buf;
278 static inline void tcg_temp_alloc(TCGContext *s, int n)
280 if (n > TCG_MAX_TEMPS)
281 tcg_abort();
284 static inline int tcg_global_reg_new_internal(TCGType type, int reg,
285 const char *name)
287 TCGContext *s = &tcg_ctx;
288 TCGTemp *ts;
289 int idx;
291 #if TCG_TARGET_REG_BITS == 32
292 if (type != TCG_TYPE_I32)
293 tcg_abort();
294 #endif
295 if (tcg_regset_test_reg(s->reserved_regs, reg))
296 tcg_abort();
297 idx = s->nb_globals;
298 tcg_temp_alloc(s, s->nb_globals + 1);
299 ts = &s->temps[s->nb_globals];
300 ts->base_type = type;
301 ts->type = type;
302 ts->fixed_reg = 1;
303 ts->reg = reg;
304 ts->name = name;
305 s->nb_globals++;
306 tcg_regset_set_reg(s->reserved_regs, reg);
307 return idx;
310 TCGv_i32 tcg_global_reg_new_i32(int reg, const char *name)
312 int idx;
314 idx = tcg_global_reg_new_internal(TCG_TYPE_I32, reg, name);
315 return MAKE_TCGV_I32(idx);
318 TCGv_i64 tcg_global_reg_new_i64(int reg, const char *name)
320 int idx;
322 idx = tcg_global_reg_new_internal(TCG_TYPE_I64, reg, name);
323 return MAKE_TCGV_I64(idx);
326 static inline int tcg_global_mem_new_internal(TCGType type, int reg,
327 tcg_target_long offset,
328 const char *name)
330 TCGContext *s = &tcg_ctx;
331 TCGTemp *ts;
332 int idx;
334 idx = s->nb_globals;
335 #if TCG_TARGET_REG_BITS == 32
336 if (type == TCG_TYPE_I64) {
337 char buf[64];
338 tcg_temp_alloc(s, s->nb_globals + 2);
339 ts = &s->temps[s->nb_globals];
340 ts->base_type = type;
341 ts->type = TCG_TYPE_I32;
342 ts->fixed_reg = 0;
343 ts->mem_allocated = 1;
344 ts->mem_reg = reg;
345 #ifdef TCG_TARGET_WORDS_BIGENDIAN
346 ts->mem_offset = offset + 4;
347 #else
348 ts->mem_offset = offset;
349 #endif
350 pstrcpy(buf, sizeof(buf), name);
351 pstrcat(buf, sizeof(buf), "_0");
352 ts->name = strdup(buf);
353 ts++;
355 ts->base_type = type;
356 ts->type = TCG_TYPE_I32;
357 ts->fixed_reg = 0;
358 ts->mem_allocated = 1;
359 ts->mem_reg = reg;
360 #ifdef TCG_TARGET_WORDS_BIGENDIAN
361 ts->mem_offset = offset;
362 #else
363 ts->mem_offset = offset + 4;
364 #endif
365 pstrcpy(buf, sizeof(buf), name);
366 pstrcat(buf, sizeof(buf), "_1");
367 ts->name = strdup(buf);
369 s->nb_globals += 2;
370 } else
371 #endif
373 tcg_temp_alloc(s, s->nb_globals + 1);
374 ts = &s->temps[s->nb_globals];
375 ts->base_type = type;
376 ts->type = type;
377 ts->fixed_reg = 0;
378 ts->mem_allocated = 1;
379 ts->mem_reg = reg;
380 ts->mem_offset = offset;
381 ts->name = name;
382 s->nb_globals++;
384 return idx;
387 TCGv_i32 tcg_global_mem_new_i32(int reg, tcg_target_long offset,
388 const char *name)
390 int idx;
392 idx = tcg_global_mem_new_internal(TCG_TYPE_I32, reg, offset, name);
393 return MAKE_TCGV_I32(idx);
396 TCGv_i64 tcg_global_mem_new_i64(int reg, tcg_target_long offset,
397 const char *name)
399 int idx;
401 idx = tcg_global_mem_new_internal(TCG_TYPE_I64, reg, offset, name);
402 return MAKE_TCGV_I64(idx);
405 static inline int tcg_temp_new_internal(TCGType type, int temp_local)
407 TCGContext *s = &tcg_ctx;
408 TCGTemp *ts;
409 int idx, k;
411 k = type;
412 if (temp_local)
413 k += TCG_TYPE_COUNT;
414 idx = s->first_free_temp[k];
415 if (idx != -1) {
416 /* There is already an available temp with the
417 right type */
418 ts = &s->temps[idx];
419 s->first_free_temp[k] = ts->next_free_temp;
420 ts->temp_allocated = 1;
421 assert(ts->temp_local == temp_local);
422 } else {
423 idx = s->nb_temps;
424 #if TCG_TARGET_REG_BITS == 32
425 if (type == TCG_TYPE_I64) {
426 tcg_temp_alloc(s, s->nb_temps + 2);
427 ts = &s->temps[s->nb_temps];
428 ts->base_type = type;
429 ts->type = TCG_TYPE_I32;
430 ts->temp_allocated = 1;
431 ts->temp_local = temp_local;
432 ts->name = NULL;
433 ts++;
434 ts->base_type = TCG_TYPE_I32;
435 ts->type = TCG_TYPE_I32;
436 ts->temp_allocated = 1;
437 ts->temp_local = temp_local;
438 ts->name = NULL;
439 s->nb_temps += 2;
440 } else
441 #endif
443 tcg_temp_alloc(s, s->nb_temps + 1);
444 ts = &s->temps[s->nb_temps];
445 ts->base_type = type;
446 ts->type = type;
447 ts->temp_allocated = 1;
448 ts->temp_local = temp_local;
449 ts->name = NULL;
450 s->nb_temps++;
454 #if defined(CONFIG_DEBUG_TCG)
455 s->temps_in_use++;
456 #endif
457 return idx;
460 TCGv_i32 tcg_temp_new_internal_i32(int temp_local)
462 int idx;
464 idx = tcg_temp_new_internal(TCG_TYPE_I32, temp_local);
465 return MAKE_TCGV_I32(idx);
468 TCGv_i64 tcg_temp_new_internal_i64(int temp_local)
470 int idx;
472 idx = tcg_temp_new_internal(TCG_TYPE_I64, temp_local);
473 return MAKE_TCGV_I64(idx);
476 static inline void tcg_temp_free_internal(int idx)
478 TCGContext *s = &tcg_ctx;
479 TCGTemp *ts;
480 int k;
482 #if defined(CONFIG_DEBUG_TCG)
483 s->temps_in_use--;
484 if (s->temps_in_use < 0) {
485 fprintf(stderr, "More temporaries freed than allocated!\n");
487 #endif
489 assert(idx >= s->nb_globals && idx < s->nb_temps);
490 ts = &s->temps[idx];
491 assert(ts->temp_allocated != 0);
492 ts->temp_allocated = 0;
493 k = ts->base_type;
494 if (ts->temp_local)
495 k += TCG_TYPE_COUNT;
496 ts->next_free_temp = s->first_free_temp[k];
497 s->first_free_temp[k] = idx;
500 void tcg_temp_free_i32(TCGv_i32 arg)
502 tcg_temp_free_internal(GET_TCGV_I32(arg));
505 void tcg_temp_free_i64(TCGv_i64 arg)
507 tcg_temp_free_internal(GET_TCGV_I64(arg));
510 TCGv_i32 tcg_const_i32(int32_t val)
512 TCGv_i32 t0;
513 t0 = tcg_temp_new_i32();
514 tcg_gen_movi_i32(t0, val);
515 return t0;
518 TCGv_i64 tcg_const_i64(int64_t val)
520 TCGv_i64 t0;
521 t0 = tcg_temp_new_i64();
522 tcg_gen_movi_i64(t0, val);
523 return t0;
526 TCGv_i32 tcg_const_local_i32(int32_t val)
528 TCGv_i32 t0;
529 t0 = tcg_temp_local_new_i32();
530 tcg_gen_movi_i32(t0, val);
531 return t0;
534 TCGv_i64 tcg_const_local_i64(int64_t val)
536 TCGv_i64 t0;
537 t0 = tcg_temp_local_new_i64();
538 tcg_gen_movi_i64(t0, val);
539 return t0;
542 #if defined(CONFIG_DEBUG_TCG)
543 void tcg_clear_temp_count(void)
545 TCGContext *s = &tcg_ctx;
546 s->temps_in_use = 0;
549 int tcg_check_temp_count(void)
551 TCGContext *s = &tcg_ctx;
552 if (s->temps_in_use) {
553 /* Clear the count so that we don't give another
554 * warning immediately next time around.
556 s->temps_in_use = 0;
557 return 1;
559 return 0;
561 #endif
563 void tcg_register_helper(void *func, const char *name)
565 TCGContext *s = &tcg_ctx;
566 int n;
567 if ((s->nb_helpers + 1) > s->allocated_helpers) {
568 n = s->allocated_helpers;
569 if (n == 0) {
570 n = 4;
571 } else {
572 n *= 2;
574 s->helpers = realloc(s->helpers, n * sizeof(TCGHelperInfo));
575 s->allocated_helpers = n;
577 s->helpers[s->nb_helpers].func = (tcg_target_ulong)func;
578 s->helpers[s->nb_helpers].name = name;
579 s->nb_helpers++;
582 /* Note: we convert the 64 bit args to 32 bit and do some alignment
583 and endian swap. Maybe it would be better to do the alignment
584 and endian swap in tcg_reg_alloc_call(). */
585 void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags,
586 int sizemask, TCGArg ret, int nargs, TCGArg *args)
588 #if defined(TCG_TARGET_I386) && TCG_TARGET_REG_BITS < 64
589 int call_type;
590 #endif
591 int i;
592 int real_args;
593 int nb_rets;
594 TCGArg *nparam;
596 #if defined(TCG_TARGET_EXTEND_ARGS) && TCG_TARGET_REG_BITS == 64
597 for (i = 0; i < nargs; ++i) {
598 int is_64bit = sizemask & (1 << (i+1)*2);
599 int is_signed = sizemask & (2 << (i+1)*2);
600 if (!is_64bit) {
601 TCGv_i64 temp = tcg_temp_new_i64();
602 TCGv_i64 orig = MAKE_TCGV_I64(args[i]);
603 if (is_signed) {
604 tcg_gen_ext32s_i64(temp, orig);
605 } else {
606 tcg_gen_ext32u_i64(temp, orig);
608 args[i] = GET_TCGV_I64(temp);
611 #endif /* TCG_TARGET_EXTEND_ARGS */
613 *gen_opc_ptr++ = INDEX_op_call;
614 nparam = gen_opparam_ptr++;
615 #if defined(TCG_TARGET_I386) && TCG_TARGET_REG_BITS < 64
616 call_type = (flags & TCG_CALL_TYPE_MASK);
617 #endif
618 if (ret != TCG_CALL_DUMMY_ARG) {
619 #if TCG_TARGET_REG_BITS < 64
620 if (sizemask & 1) {
621 #ifdef TCG_TARGET_WORDS_BIGENDIAN
622 *gen_opparam_ptr++ = ret + 1;
623 *gen_opparam_ptr++ = ret;
624 #else
625 *gen_opparam_ptr++ = ret;
626 *gen_opparam_ptr++ = ret + 1;
627 #endif
628 nb_rets = 2;
629 } else
630 #endif
632 *gen_opparam_ptr++ = ret;
633 nb_rets = 1;
635 } else {
636 nb_rets = 0;
638 real_args = 0;
639 for (i = 0; i < nargs; i++) {
640 #if TCG_TARGET_REG_BITS < 64
641 int is_64bit = sizemask & (1 << (i+1)*2);
642 if (is_64bit) {
643 #ifdef TCG_TARGET_I386
644 /* REGPARM case: if the third parameter is 64 bit, it is
645 allocated on the stack */
646 if (i == 2 && call_type == TCG_CALL_TYPE_REGPARM) {
647 call_type = TCG_CALL_TYPE_REGPARM_2;
648 flags = (flags & ~TCG_CALL_TYPE_MASK) | call_type;
650 #endif
651 #ifdef TCG_TARGET_CALL_ALIGN_ARGS
652 /* some targets want aligned 64 bit args */
653 if (real_args & 1) {
654 *gen_opparam_ptr++ = TCG_CALL_DUMMY_ARG;
655 real_args++;
657 #endif
658 /* If stack grows up, then we will be placing successive
659 arguments at lower addresses, which means we need to
660 reverse the order compared to how we would normally
661 treat either big or little-endian. For those arguments
662 that will wind up in registers, this still works for
663 HPPA (the only current STACK_GROWSUP target) since the
664 argument registers are *also* allocated in decreasing
665 order. If another such target is added, this logic may
666 have to get more complicated to differentiate between
667 stack arguments and register arguments. */
668 #if defined(TCG_TARGET_WORDS_BIGENDIAN) != defined(TCG_TARGET_STACK_GROWSUP)
669 *gen_opparam_ptr++ = args[i] + 1;
670 *gen_opparam_ptr++ = args[i];
671 #else
672 *gen_opparam_ptr++ = args[i];
673 *gen_opparam_ptr++ = args[i] + 1;
674 #endif
675 real_args += 2;
676 continue;
678 #endif /* TCG_TARGET_REG_BITS < 64 */
680 *gen_opparam_ptr++ = args[i];
681 real_args++;
683 *gen_opparam_ptr++ = GET_TCGV_PTR(func);
685 *gen_opparam_ptr++ = flags;
687 *nparam = (nb_rets << 16) | (real_args + 1);
689 /* total parameters, needed to go backward in the instruction stream */
690 *gen_opparam_ptr++ = 1 + nb_rets + real_args + 3;
692 #if defined(TCG_TARGET_EXTEND_ARGS) && TCG_TARGET_REG_BITS == 64
693 for (i = 0; i < nargs; ++i) {
694 int is_64bit = sizemask & (1 << (i+1)*2);
695 if (!is_64bit) {
696 TCGv_i64 temp = MAKE_TCGV_I64(args[i]);
697 tcg_temp_free_i64(temp);
700 #endif /* TCG_TARGET_EXTEND_ARGS */
703 #if TCG_TARGET_REG_BITS == 32
704 void tcg_gen_shifti_i64(TCGv_i64 ret, TCGv_i64 arg1,
705 int c, int right, int arith)
707 if (c == 0) {
708 tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg1));
709 tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
710 } else if (c >= 32) {
711 c -= 32;
712 if (right) {
713 if (arith) {
714 tcg_gen_sari_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
715 tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 31);
716 } else {
717 tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
718 tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
720 } else {
721 tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_LOW(arg1), c);
722 tcg_gen_movi_i32(TCGV_LOW(ret), 0);
724 } else {
725 TCGv_i32 t0, t1;
727 t0 = tcg_temp_new_i32();
728 t1 = tcg_temp_new_i32();
729 if (right) {
730 tcg_gen_shli_i32(t0, TCGV_HIGH(arg1), 32 - c);
731 if (arith)
732 tcg_gen_sari_i32(t1, TCGV_HIGH(arg1), c);
733 else
734 tcg_gen_shri_i32(t1, TCGV_HIGH(arg1), c);
735 tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_LOW(arg1), c);
736 tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(ret), t0);
737 tcg_gen_mov_i32(TCGV_HIGH(ret), t1);
738 } else {
739 tcg_gen_shri_i32(t0, TCGV_LOW(arg1), 32 - c);
740 /* Note: ret can be the same as arg1, so we use t1 */
741 tcg_gen_shli_i32(t1, TCGV_LOW(arg1), c);
742 tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c);
743 tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t0);
744 tcg_gen_mov_i32(TCGV_LOW(ret), t1);
746 tcg_temp_free_i32(t0);
747 tcg_temp_free_i32(t1);
750 #endif
753 static void tcg_reg_alloc_start(TCGContext *s)
755 int i;
756 TCGTemp *ts;
757 for(i = 0; i < s->nb_globals; i++) {
758 ts = &s->temps[i];
759 if (ts->fixed_reg) {
760 ts->val_type = TEMP_VAL_REG;
761 } else {
762 ts->val_type = TEMP_VAL_MEM;
765 for(i = s->nb_globals; i < s->nb_temps; i++) {
766 ts = &s->temps[i];
767 ts->val_type = TEMP_VAL_DEAD;
768 ts->mem_allocated = 0;
769 ts->fixed_reg = 0;
771 for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
772 s->reg_to_temp[i] = -1;
776 static char *tcg_get_arg_str_idx(TCGContext *s, char *buf, int buf_size,
777 int idx)
779 TCGTemp *ts;
781 ts = &s->temps[idx];
782 if (idx < s->nb_globals) {
783 pstrcpy(buf, buf_size, ts->name);
784 } else {
785 if (ts->temp_local)
786 snprintf(buf, buf_size, "loc%d", idx - s->nb_globals);
787 else
788 snprintf(buf, buf_size, "tmp%d", idx - s->nb_globals);
790 return buf;
793 char *tcg_get_arg_str_i32(TCGContext *s, char *buf, int buf_size, TCGv_i32 arg)
795 return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I32(arg));
798 char *tcg_get_arg_str_i64(TCGContext *s, char *buf, int buf_size, TCGv_i64 arg)
800 return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I64(arg));
803 static int helper_cmp(const void *p1, const void *p2)
805 const TCGHelperInfo *th1 = p1;
806 const TCGHelperInfo *th2 = p2;
807 if (th1->func < th2->func)
808 return -1;
809 else if (th1->func == th2->func)
810 return 0;
811 else
812 return 1;
815 /* find helper definition (Note: A hash table would be better) */
816 static TCGHelperInfo *tcg_find_helper(TCGContext *s, tcg_target_ulong val)
818 int m, m_min, m_max;
819 TCGHelperInfo *th;
820 tcg_target_ulong v;
822 if (unlikely(!s->helpers_sorted)) {
823 qsort(s->helpers, s->nb_helpers, sizeof(TCGHelperInfo),
824 helper_cmp);
825 s->helpers_sorted = 1;
828 /* binary search */
829 m_min = 0;
830 m_max = s->nb_helpers - 1;
831 while (m_min <= m_max) {
832 m = (m_min + m_max) >> 1;
833 th = &s->helpers[m];
834 v = th->func;
835 if (v == val)
836 return th;
837 else if (val < v) {
838 m_max = m - 1;
839 } else {
840 m_min = m + 1;
843 return NULL;
846 static const char * const cond_name[] =
848 [TCG_COND_EQ] = "eq",
849 [TCG_COND_NE] = "ne",
850 [TCG_COND_LT] = "lt",
851 [TCG_COND_GE] = "ge",
852 [TCG_COND_LE] = "le",
853 [TCG_COND_GT] = "gt",
854 [TCG_COND_LTU] = "ltu",
855 [TCG_COND_GEU] = "geu",
856 [TCG_COND_LEU] = "leu",
857 [TCG_COND_GTU] = "gtu"
860 void tcg_dump_ops(TCGContext *s, FILE *outfile)
862 const uint16_t *opc_ptr;
863 const TCGArg *args;
864 TCGArg arg;
865 TCGOpcode c;
866 int i, k, nb_oargs, nb_iargs, nb_cargs, first_insn;
867 const TCGOpDef *def;
868 char buf[128];
870 first_insn = 1;
871 opc_ptr = gen_opc_buf;
872 args = gen_opparam_buf;
873 while (opc_ptr < gen_opc_ptr) {
874 c = *opc_ptr++;
875 def = &tcg_op_defs[c];
876 if (c == INDEX_op_debug_insn_start) {
877 uint64_t pc;
878 #if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
879 pc = ((uint64_t)args[1] << 32) | args[0];
880 #else
881 pc = args[0];
882 #endif
883 if (!first_insn)
884 fprintf(outfile, "\n");
885 fprintf(outfile, " ---- 0x%" PRIx64, pc);
886 first_insn = 0;
887 nb_oargs = def->nb_oargs;
888 nb_iargs = def->nb_iargs;
889 nb_cargs = def->nb_cargs;
890 } else if (c == INDEX_op_call) {
891 TCGArg arg;
893 /* variable number of arguments */
894 arg = *args++;
895 nb_oargs = arg >> 16;
896 nb_iargs = arg & 0xffff;
897 nb_cargs = def->nb_cargs;
899 fprintf(outfile, " %s ", def->name);
901 /* function name */
902 fprintf(outfile, "%s",
903 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + nb_iargs - 1]));
904 /* flags */
905 fprintf(outfile, ",$0x%" TCG_PRIlx,
906 args[nb_oargs + nb_iargs]);
907 /* nb out args */
908 fprintf(outfile, ",$%d", nb_oargs);
909 for(i = 0; i < nb_oargs; i++) {
910 fprintf(outfile, ",");
911 fprintf(outfile, "%s",
912 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[i]));
914 for(i = 0; i < (nb_iargs - 1); i++) {
915 fprintf(outfile, ",");
916 if (args[nb_oargs + i] == TCG_CALL_DUMMY_ARG) {
917 fprintf(outfile, "<dummy>");
918 } else {
919 fprintf(outfile, "%s",
920 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + i]));
923 } else if (c == INDEX_op_movi_i32
924 #if TCG_TARGET_REG_BITS == 64
925 || c == INDEX_op_movi_i64
926 #endif
928 tcg_target_ulong val;
929 TCGHelperInfo *th;
931 nb_oargs = def->nb_oargs;
932 nb_iargs = def->nb_iargs;
933 nb_cargs = def->nb_cargs;
934 fprintf(outfile, " %s %s,$", def->name,
935 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[0]));
936 val = args[1];
937 th = tcg_find_helper(s, val);
938 if (th) {
939 fprintf(outfile, "%s", th->name);
940 } else {
941 if (c == INDEX_op_movi_i32)
942 fprintf(outfile, "0x%x", (uint32_t)val);
943 else
944 fprintf(outfile, "0x%" PRIx64 , (uint64_t)val);
946 } else {
947 fprintf(outfile, " %s ", def->name);
948 if (c == INDEX_op_nopn) {
949 /* variable number of arguments */
950 nb_cargs = *args;
951 nb_oargs = 0;
952 nb_iargs = 0;
953 } else {
954 nb_oargs = def->nb_oargs;
955 nb_iargs = def->nb_iargs;
956 nb_cargs = def->nb_cargs;
959 k = 0;
960 for(i = 0; i < nb_oargs; i++) {
961 if (k != 0)
962 fprintf(outfile, ",");
963 fprintf(outfile, "%s",
964 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
966 for(i = 0; i < nb_iargs; i++) {
967 if (k != 0)
968 fprintf(outfile, ",");
969 fprintf(outfile, "%s",
970 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
972 switch (c) {
973 case INDEX_op_brcond_i32:
974 #if TCG_TARGET_REG_BITS == 32
975 case INDEX_op_brcond2_i32:
976 #elif TCG_TARGET_REG_BITS == 64
977 case INDEX_op_brcond_i64:
978 #endif
979 case INDEX_op_setcond_i32:
980 #if TCG_TARGET_REG_BITS == 32
981 case INDEX_op_setcond2_i32:
982 #elif TCG_TARGET_REG_BITS == 64
983 case INDEX_op_setcond_i64:
984 #endif
985 if (args[k] < ARRAY_SIZE(cond_name) && cond_name[args[k]])
986 fprintf(outfile, ",%s", cond_name[args[k++]]);
987 else
988 fprintf(outfile, ",$0x%" TCG_PRIlx, args[k++]);
989 i = 1;
990 break;
991 default:
992 i = 0;
993 break;
995 for(; i < nb_cargs; i++) {
996 if (k != 0)
997 fprintf(outfile, ",");
998 arg = args[k++];
999 fprintf(outfile, "$0x%" TCG_PRIlx, arg);
1002 fprintf(outfile, "\n");
1003 args += nb_iargs + nb_oargs + nb_cargs;
1007 /* we give more priority to constraints with less registers */
1008 static int get_constraint_priority(const TCGOpDef *def, int k)
1010 const TCGArgConstraint *arg_ct;
1012 int i, n;
1013 arg_ct = &def->args_ct[k];
1014 if (arg_ct->ct & TCG_CT_ALIAS) {
1015 /* an alias is equivalent to a single register */
1016 n = 1;
1017 } else {
1018 if (!(arg_ct->ct & TCG_CT_REG))
1019 return 0;
1020 n = 0;
1021 for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
1022 if (tcg_regset_test_reg(arg_ct->u.regs, i))
1023 n++;
1026 return TCG_TARGET_NB_REGS - n + 1;
1029 /* sort from highest priority to lowest */
1030 static void sort_constraints(TCGOpDef *def, int start, int n)
1032 int i, j, p1, p2, tmp;
1034 for(i = 0; i < n; i++)
1035 def->sorted_args[start + i] = start + i;
1036 if (n <= 1)
1037 return;
1038 for(i = 0; i < n - 1; i++) {
1039 for(j = i + 1; j < n; j++) {
1040 p1 = get_constraint_priority(def, def->sorted_args[start + i]);
1041 p2 = get_constraint_priority(def, def->sorted_args[start + j]);
1042 if (p1 < p2) {
1043 tmp = def->sorted_args[start + i];
1044 def->sorted_args[start + i] = def->sorted_args[start + j];
1045 def->sorted_args[start + j] = tmp;
1051 void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs)
1053 TCGOpcode op;
1054 TCGOpDef *def;
1055 const char *ct_str;
1056 int i, nb_args;
1058 for(;;) {
1059 if (tdefs->op == (TCGOpcode)-1)
1060 break;
1061 op = tdefs->op;
1062 assert((unsigned)op < NB_OPS);
1063 def = &tcg_op_defs[op];
1064 #if defined(CONFIG_DEBUG_TCG)
1065 /* Duplicate entry in op definitions? */
1066 assert(!def->used);
1067 def->used = 1;
1068 #endif
1069 nb_args = def->nb_iargs + def->nb_oargs;
1070 for(i = 0; i < nb_args; i++) {
1071 ct_str = tdefs->args_ct_str[i];
1072 /* Incomplete TCGTargetOpDef entry? */
1073 assert(ct_str != NULL);
1074 tcg_regset_clear(def->args_ct[i].u.regs);
1075 def->args_ct[i].ct = 0;
1076 if (ct_str[0] >= '0' && ct_str[0] <= '9') {
1077 int oarg;
1078 oarg = ct_str[0] - '0';
1079 assert(oarg < def->nb_oargs);
1080 assert(def->args_ct[oarg].ct & TCG_CT_REG);
1081 /* TCG_CT_ALIAS is for the output arguments. The input
1082 argument is tagged with TCG_CT_IALIAS. */
1083 def->args_ct[i] = def->args_ct[oarg];
1084 def->args_ct[oarg].ct = TCG_CT_ALIAS;
1085 def->args_ct[oarg].alias_index = i;
1086 def->args_ct[i].ct |= TCG_CT_IALIAS;
1087 def->args_ct[i].alias_index = oarg;
1088 } else {
1089 for(;;) {
1090 if (*ct_str == '\0')
1091 break;
1092 switch(*ct_str) {
1093 case 'i':
1094 def->args_ct[i].ct |= TCG_CT_CONST;
1095 ct_str++;
1096 break;
1097 default:
1098 if (target_parse_constraint(&def->args_ct[i], &ct_str) < 0) {
1099 fprintf(stderr, "Invalid constraint '%s' for arg %d of operation '%s'\n",
1100 ct_str, i, def->name);
1101 exit(1);
1108 /* TCGTargetOpDef entry with too much information? */
1109 assert(i == TCG_MAX_OP_ARGS || tdefs->args_ct_str[i] == NULL);
1111 /* sort the constraints (XXX: this is just an heuristic) */
1112 sort_constraints(def, 0, def->nb_oargs);
1113 sort_constraints(def, def->nb_oargs, def->nb_iargs);
1115 #if 0
1117 int i;
1119 printf("%s: sorted=", def->name);
1120 for(i = 0; i < def->nb_oargs + def->nb_iargs; i++)
1121 printf(" %d", def->sorted_args[i]);
1122 printf("\n");
1124 #endif
1125 tdefs++;
1128 #if defined(CONFIG_DEBUG_TCG)
1129 i = 0;
1130 for (op = 0; op < ARRAY_SIZE(tcg_op_defs); op++) {
1131 const TCGOpDef *def = &tcg_op_defs[op];
1132 if (op < INDEX_op_call
1133 || op == INDEX_op_debug_insn_start
1134 || (def->flags & TCG_OPF_NOT_PRESENT)) {
1135 /* Wrong entry in op definitions? */
1136 if (def->used) {
1137 fprintf(stderr, "Invalid op definition for %s\n", def->name);
1138 i = 1;
1140 } else {
1141 /* Missing entry in op definitions? */
1142 if (!def->used) {
1143 fprintf(stderr, "Missing op definition for %s\n", def->name);
1144 i = 1;
1148 if (i == 1) {
1149 tcg_abort();
1151 #endif
1154 #ifdef USE_LIVENESS_ANALYSIS
1156 /* set a nop for an operation using 'nb_args' */
1157 static inline void tcg_set_nop(TCGContext *s, uint16_t *opc_ptr,
1158 TCGArg *args, int nb_args)
1160 if (nb_args == 0) {
1161 *opc_ptr = INDEX_op_nop;
1162 } else {
1163 *opc_ptr = INDEX_op_nopn;
1164 args[0] = nb_args;
1165 args[nb_args - 1] = nb_args;
1169 /* liveness analysis: end of function: globals are live, temps are
1170 dead. */
1171 /* XXX: at this stage, not used as there would be little gains because
1172 most TBs end with a conditional jump. */
1173 static inline void tcg_la_func_end(TCGContext *s, uint8_t *dead_temps)
1175 memset(dead_temps, 0, s->nb_globals);
1176 memset(dead_temps + s->nb_globals, 1, s->nb_temps - s->nb_globals);
1179 /* liveness analysis: end of basic block: globals are live, temps are
1180 dead, local temps are live. */
1181 static inline void tcg_la_bb_end(TCGContext *s, uint8_t *dead_temps)
1183 int i;
1184 TCGTemp *ts;
1186 memset(dead_temps, 0, s->nb_globals);
1187 ts = &s->temps[s->nb_globals];
1188 for(i = s->nb_globals; i < s->nb_temps; i++) {
1189 if (ts->temp_local)
1190 dead_temps[i] = 0;
1191 else
1192 dead_temps[i] = 1;
1193 ts++;
1197 /* Liveness analysis : update the opc_dead_args array to tell if a
1198 given input arguments is dead. Instructions updating dead
1199 temporaries are removed. */
1200 static void tcg_liveness_analysis(TCGContext *s)
1202 int i, op_index, nb_args, nb_iargs, nb_oargs, arg, nb_ops;
1203 TCGOpcode op;
1204 TCGArg *args;
1205 const TCGOpDef *def;
1206 uint8_t *dead_temps;
1207 unsigned int dead_args;
1209 gen_opc_ptr++; /* skip end */
1211 nb_ops = gen_opc_ptr - gen_opc_buf;
1213 s->op_dead_args = tcg_malloc(nb_ops * sizeof(uint16_t));
1215 dead_temps = tcg_malloc(s->nb_temps);
1216 memset(dead_temps, 1, s->nb_temps);
1218 args = gen_opparam_ptr;
1219 op_index = nb_ops - 1;
1220 while (op_index >= 0) {
1221 op = gen_opc_buf[op_index];
1222 def = &tcg_op_defs[op];
1223 switch(op) {
1224 case INDEX_op_call:
1226 int call_flags;
1228 nb_args = args[-1];
1229 args -= nb_args;
1230 nb_iargs = args[0] & 0xffff;
1231 nb_oargs = args[0] >> 16;
1232 args++;
1233 call_flags = args[nb_oargs + nb_iargs];
1235 /* pure functions can be removed if their result is not
1236 used */
1237 if (call_flags & TCG_CALL_PURE) {
1238 for(i = 0; i < nb_oargs; i++) {
1239 arg = args[i];
1240 if (!dead_temps[arg])
1241 goto do_not_remove_call;
1243 tcg_set_nop(s, gen_opc_buf + op_index,
1244 args - 1, nb_args);
1245 } else {
1246 do_not_remove_call:
1248 /* output args are dead */
1249 dead_args = 0;
1250 for(i = 0; i < nb_oargs; i++) {
1251 arg = args[i];
1252 if (dead_temps[arg]) {
1253 dead_args |= (1 << i);
1255 dead_temps[arg] = 1;
1258 if (!(call_flags & TCG_CALL_CONST)) {
1259 /* globals are live (they may be used by the call) */
1260 memset(dead_temps, 0, s->nb_globals);
1263 /* input args are live */
1264 for(i = nb_oargs; i < nb_iargs + nb_oargs; i++) {
1265 arg = args[i];
1266 if (arg != TCG_CALL_DUMMY_ARG) {
1267 if (dead_temps[arg]) {
1268 dead_args |= (1 << i);
1270 dead_temps[arg] = 0;
1273 s->op_dead_args[op_index] = dead_args;
1275 args--;
1277 break;
1278 case INDEX_op_set_label:
1279 args--;
1280 /* mark end of basic block */
1281 tcg_la_bb_end(s, dead_temps);
1282 break;
1283 case INDEX_op_debug_insn_start:
1284 args -= def->nb_args;
1285 break;
1286 case INDEX_op_nopn:
1287 nb_args = args[-1];
1288 args -= nb_args;
1289 break;
1290 case INDEX_op_discard:
1291 args--;
1292 /* mark the temporary as dead */
1293 dead_temps[args[0]] = 1;
1294 break;
1295 case INDEX_op_end:
1296 break;
1297 /* XXX: optimize by hardcoding common cases (e.g. triadic ops) */
1298 default:
1299 args -= def->nb_args;
1300 nb_iargs = def->nb_iargs;
1301 nb_oargs = def->nb_oargs;
1303 /* Test if the operation can be removed because all
1304 its outputs are dead. We assume that nb_oargs == 0
1305 implies side effects */
1306 if (!(def->flags & TCG_OPF_SIDE_EFFECTS) && nb_oargs != 0) {
1307 for(i = 0; i < nb_oargs; i++) {
1308 arg = args[i];
1309 if (!dead_temps[arg])
1310 goto do_not_remove;
1312 tcg_set_nop(s, gen_opc_buf + op_index, args, def->nb_args);
1313 #ifdef CONFIG_PROFILER
1314 s->del_op_count++;
1315 #endif
1316 } else {
1317 do_not_remove:
1319 /* output args are dead */
1320 dead_args = 0;
1321 for(i = 0; i < nb_oargs; i++) {
1322 arg = args[i];
1323 if (dead_temps[arg]) {
1324 dead_args |= (1 << i);
1326 dead_temps[arg] = 1;
1329 /* if end of basic block, update */
1330 if (def->flags & TCG_OPF_BB_END) {
1331 tcg_la_bb_end(s, dead_temps);
1332 } else if (def->flags & TCG_OPF_CALL_CLOBBER) {
1333 /* globals are live */
1334 memset(dead_temps, 0, s->nb_globals);
1337 /* input args are live */
1338 for(i = nb_oargs; i < nb_oargs + nb_iargs; i++) {
1339 arg = args[i];
1340 if (dead_temps[arg]) {
1341 dead_args |= (1 << i);
1343 dead_temps[arg] = 0;
1345 s->op_dead_args[op_index] = dead_args;
1347 break;
1349 op_index--;
1352 if (args != gen_opparam_buf)
1353 tcg_abort();
1355 #else
1356 /* dummy liveness analysis */
1357 static void tcg_liveness_analysis(TCGContext *s)
1359 int nb_ops;
1360 nb_ops = gen_opc_ptr - gen_opc_buf;
1362 s->op_dead_args = tcg_malloc(nb_ops * sizeof(uint16_t));
1363 memset(s->op_dead_args, 0, nb_ops * sizeof(uint16_t));
1365 #endif
1367 #ifndef NDEBUG
1368 static void dump_regs(TCGContext *s)
1370 TCGTemp *ts;
1371 int i;
1372 char buf[64];
1374 for(i = 0; i < s->nb_temps; i++) {
1375 ts = &s->temps[i];
1376 printf(" %10s: ", tcg_get_arg_str_idx(s, buf, sizeof(buf), i));
1377 switch(ts->val_type) {
1378 case TEMP_VAL_REG:
1379 printf("%s", tcg_target_reg_names[ts->reg]);
1380 break;
1381 case TEMP_VAL_MEM:
1382 printf("%d(%s)", (int)ts->mem_offset, tcg_target_reg_names[ts->mem_reg]);
1383 break;
1384 case TEMP_VAL_CONST:
1385 printf("$0x%" TCG_PRIlx, ts->val);
1386 break;
1387 case TEMP_VAL_DEAD:
1388 printf("D");
1389 break;
1390 default:
1391 printf("???");
1392 break;
1394 printf("\n");
1397 for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
1398 if (s->reg_to_temp[i] >= 0) {
1399 printf("%s: %s\n",
1400 tcg_target_reg_names[i],
1401 tcg_get_arg_str_idx(s, buf, sizeof(buf), s->reg_to_temp[i]));
1406 static void check_regs(TCGContext *s)
1408 int reg, k;
1409 TCGTemp *ts;
1410 char buf[64];
1412 for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1413 k = s->reg_to_temp[reg];
1414 if (k >= 0) {
1415 ts = &s->temps[k];
1416 if (ts->val_type != TEMP_VAL_REG ||
1417 ts->reg != reg) {
1418 printf("Inconsistency for register %s:\n",
1419 tcg_target_reg_names[reg]);
1420 goto fail;
1424 for(k = 0; k < s->nb_temps; k++) {
1425 ts = &s->temps[k];
1426 if (ts->val_type == TEMP_VAL_REG &&
1427 !ts->fixed_reg &&
1428 s->reg_to_temp[ts->reg] != k) {
1429 printf("Inconsistency for temp %s:\n",
1430 tcg_get_arg_str_idx(s, buf, sizeof(buf), k));
1431 fail:
1432 printf("reg state:\n");
1433 dump_regs(s);
1434 tcg_abort();
1438 #endif
1440 static void temp_allocate_frame(TCGContext *s, int temp)
1442 TCGTemp *ts;
1443 ts = &s->temps[temp];
1444 #ifndef __sparc_v9__ /* Sparc64 stack is accessed with offset of 2047 */
1445 s->current_frame_offset = (s->current_frame_offset +
1446 (tcg_target_long)sizeof(tcg_target_long) - 1) &
1447 ~(sizeof(tcg_target_long) - 1);
1448 #endif
1449 if (s->current_frame_offset + (tcg_target_long)sizeof(tcg_target_long) >
1450 s->frame_end) {
1451 tcg_abort();
1453 ts->mem_offset = s->current_frame_offset;
1454 ts->mem_reg = s->frame_reg;
1455 ts->mem_allocated = 1;
1456 s->current_frame_offset += (tcg_target_long)sizeof(tcg_target_long);
1459 /* free register 'reg' by spilling the corresponding temporary if necessary */
1460 static void tcg_reg_free(TCGContext *s, int reg)
1462 TCGTemp *ts;
1463 int temp;
1465 temp = s->reg_to_temp[reg];
1466 if (temp != -1) {
1467 ts = &s->temps[temp];
1468 assert(ts->val_type == TEMP_VAL_REG);
1469 if (!ts->mem_coherent) {
1470 if (!ts->mem_allocated)
1471 temp_allocate_frame(s, temp);
1472 tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1474 ts->val_type = TEMP_VAL_MEM;
1475 s->reg_to_temp[reg] = -1;
1479 /* Allocate a register belonging to reg1 & ~reg2 */
1480 static int tcg_reg_alloc(TCGContext *s, TCGRegSet reg1, TCGRegSet reg2)
1482 int i, reg;
1483 TCGRegSet reg_ct;
1485 tcg_regset_andnot(reg_ct, reg1, reg2);
1487 /* first try free registers */
1488 for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1489 reg = tcg_target_reg_alloc_order[i];
1490 if (tcg_regset_test_reg(reg_ct, reg) && s->reg_to_temp[reg] == -1)
1491 return reg;
1494 /* XXX: do better spill choice */
1495 for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1496 reg = tcg_target_reg_alloc_order[i];
1497 if (tcg_regset_test_reg(reg_ct, reg)) {
1498 tcg_reg_free(s, reg);
1499 return reg;
1503 tcg_abort();
1506 /* save a temporary to memory. 'allocated_regs' is used in case a
1507 temporary registers needs to be allocated to store a constant. */
1508 static void temp_save(TCGContext *s, int temp, TCGRegSet allocated_regs)
1510 TCGTemp *ts;
1511 int reg;
1513 ts = &s->temps[temp];
1514 if (!ts->fixed_reg) {
1515 switch(ts->val_type) {
1516 case TEMP_VAL_REG:
1517 tcg_reg_free(s, ts->reg);
1518 break;
1519 case TEMP_VAL_DEAD:
1520 ts->val_type = TEMP_VAL_MEM;
1521 break;
1522 case TEMP_VAL_CONST:
1523 reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type],
1524 allocated_regs);
1525 if (!ts->mem_allocated)
1526 temp_allocate_frame(s, temp);
1527 tcg_out_movi(s, ts->type, reg, ts->val);
1528 tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1529 ts->val_type = TEMP_VAL_MEM;
1530 break;
1531 case TEMP_VAL_MEM:
1532 break;
1533 default:
1534 tcg_abort();
1539 /* save globals to their cannonical location and assume they can be
1540 modified be the following code. 'allocated_regs' is used in case a
1541 temporary registers needs to be allocated to store a constant. */
1542 static void save_globals(TCGContext *s, TCGRegSet allocated_regs)
1544 int i;
1546 for(i = 0; i < s->nb_globals; i++) {
1547 temp_save(s, i, allocated_regs);
1551 /* at the end of a basic block, we assume all temporaries are dead and
1552 all globals are stored at their canonical location. */
1553 static void tcg_reg_alloc_bb_end(TCGContext *s, TCGRegSet allocated_regs)
1555 TCGTemp *ts;
1556 int i;
1558 for(i = s->nb_globals; i < s->nb_temps; i++) {
1559 ts = &s->temps[i];
1560 if (ts->temp_local) {
1561 temp_save(s, i, allocated_regs);
1562 } else {
1563 if (ts->val_type == TEMP_VAL_REG) {
1564 s->reg_to_temp[ts->reg] = -1;
1566 ts->val_type = TEMP_VAL_DEAD;
1570 save_globals(s, allocated_regs);
1573 #define IS_DEAD_ARG(n) ((dead_args >> (n)) & 1)
1575 static void tcg_reg_alloc_movi(TCGContext *s, const TCGArg *args)
1577 TCGTemp *ots;
1578 tcg_target_ulong val;
1580 ots = &s->temps[args[0]];
1581 val = args[1];
1583 if (ots->fixed_reg) {
1584 /* for fixed registers, we do not do any constant
1585 propagation */
1586 tcg_out_movi(s, ots->type, ots->reg, val);
1587 } else {
1588 /* The movi is not explicitly generated here */
1589 if (ots->val_type == TEMP_VAL_REG)
1590 s->reg_to_temp[ots->reg] = -1;
1591 ots->val_type = TEMP_VAL_CONST;
1592 ots->val = val;
1596 static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
1597 const TCGArg *args,
1598 unsigned int dead_args)
1600 TCGTemp *ts, *ots;
1601 int reg;
1602 const TCGArgConstraint *arg_ct;
1604 ots = &s->temps[args[0]];
1605 ts = &s->temps[args[1]];
1606 arg_ct = &def->args_ct[0];
1608 /* XXX: always mark arg dead if IS_DEAD_ARG(1) */
1609 if (ts->val_type == TEMP_VAL_REG) {
1610 if (IS_DEAD_ARG(1) && !ts->fixed_reg && !ots->fixed_reg) {
1611 /* the mov can be suppressed */
1612 if (ots->val_type == TEMP_VAL_REG)
1613 s->reg_to_temp[ots->reg] = -1;
1614 reg = ts->reg;
1615 s->reg_to_temp[reg] = -1;
1616 ts->val_type = TEMP_VAL_DEAD;
1617 } else {
1618 if (ots->val_type == TEMP_VAL_REG) {
1619 reg = ots->reg;
1620 } else {
1621 reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1623 if (ts->reg != reg) {
1624 tcg_out_mov(s, ots->type, reg, ts->reg);
1627 } else if (ts->val_type == TEMP_VAL_MEM) {
1628 if (ots->val_type == TEMP_VAL_REG) {
1629 reg = ots->reg;
1630 } else {
1631 reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1633 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1634 } else if (ts->val_type == TEMP_VAL_CONST) {
1635 if (ots->fixed_reg) {
1636 reg = ots->reg;
1637 tcg_out_movi(s, ots->type, reg, ts->val);
1638 } else {
1639 /* propagate constant */
1640 if (ots->val_type == TEMP_VAL_REG)
1641 s->reg_to_temp[ots->reg] = -1;
1642 ots->val_type = TEMP_VAL_CONST;
1643 ots->val = ts->val;
1644 return;
1646 } else {
1647 tcg_abort();
1649 s->reg_to_temp[reg] = args[0];
1650 ots->reg = reg;
1651 ots->val_type = TEMP_VAL_REG;
1652 ots->mem_coherent = 0;
1655 static void tcg_reg_alloc_op(TCGContext *s,
1656 const TCGOpDef *def, TCGOpcode opc,
1657 const TCGArg *args,
1658 unsigned int dead_args)
1660 TCGRegSet allocated_regs;
1661 int i, k, nb_iargs, nb_oargs, reg;
1662 TCGArg arg;
1663 const TCGArgConstraint *arg_ct;
1664 TCGTemp *ts;
1665 TCGArg new_args[TCG_MAX_OP_ARGS];
1666 int const_args[TCG_MAX_OP_ARGS];
1668 nb_oargs = def->nb_oargs;
1669 nb_iargs = def->nb_iargs;
1671 /* copy constants */
1672 memcpy(new_args + nb_oargs + nb_iargs,
1673 args + nb_oargs + nb_iargs,
1674 sizeof(TCGArg) * def->nb_cargs);
1676 /* satisfy input constraints */
1677 tcg_regset_set(allocated_regs, s->reserved_regs);
1678 for(k = 0; k < nb_iargs; k++) {
1679 i = def->sorted_args[nb_oargs + k];
1680 arg = args[i];
1681 arg_ct = &def->args_ct[i];
1682 ts = &s->temps[arg];
1683 if (ts->val_type == TEMP_VAL_MEM) {
1684 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1685 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1686 ts->val_type = TEMP_VAL_REG;
1687 ts->reg = reg;
1688 ts->mem_coherent = 1;
1689 s->reg_to_temp[reg] = arg;
1690 } else if (ts->val_type == TEMP_VAL_CONST) {
1691 if (tcg_target_const_match(ts->val, arg_ct)) {
1692 /* constant is OK for instruction */
1693 const_args[i] = 1;
1694 new_args[i] = ts->val;
1695 goto iarg_end;
1696 } else {
1697 /* need to move to a register */
1698 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1699 tcg_out_movi(s, ts->type, reg, ts->val);
1700 ts->val_type = TEMP_VAL_REG;
1701 ts->reg = reg;
1702 ts->mem_coherent = 0;
1703 s->reg_to_temp[reg] = arg;
1706 assert(ts->val_type == TEMP_VAL_REG);
1707 if (arg_ct->ct & TCG_CT_IALIAS) {
1708 if (ts->fixed_reg) {
1709 /* if fixed register, we must allocate a new register
1710 if the alias is not the same register */
1711 if (arg != args[arg_ct->alias_index])
1712 goto allocate_in_reg;
1713 } else {
1714 /* if the input is aliased to an output and if it is
1715 not dead after the instruction, we must allocate
1716 a new register and move it */
1717 if (!IS_DEAD_ARG(i)) {
1718 goto allocate_in_reg;
1722 reg = ts->reg;
1723 if (tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1724 /* nothing to do : the constraint is satisfied */
1725 } else {
1726 allocate_in_reg:
1727 /* allocate a new register matching the constraint
1728 and move the temporary register into it */
1729 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1730 tcg_out_mov(s, ts->type, reg, ts->reg);
1732 new_args[i] = reg;
1733 const_args[i] = 0;
1734 tcg_regset_set_reg(allocated_regs, reg);
1735 iarg_end: ;
1738 if (def->flags & TCG_OPF_BB_END) {
1739 tcg_reg_alloc_bb_end(s, allocated_regs);
1740 } else {
1741 /* mark dead temporaries and free the associated registers */
1742 for(i = nb_oargs; i < nb_oargs + nb_iargs; i++) {
1743 arg = args[i];
1744 if (IS_DEAD_ARG(i)) {
1745 ts = &s->temps[arg];
1746 if (!ts->fixed_reg) {
1747 if (ts->val_type == TEMP_VAL_REG)
1748 s->reg_to_temp[ts->reg] = -1;
1749 ts->val_type = TEMP_VAL_DEAD;
1754 if (def->flags & TCG_OPF_CALL_CLOBBER) {
1755 /* XXX: permit generic clobber register list ? */
1756 for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1757 if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
1758 tcg_reg_free(s, reg);
1761 /* XXX: for load/store we could do that only for the slow path
1762 (i.e. when a memory callback is called) */
1764 /* store globals and free associated registers (we assume the insn
1765 can modify any global. */
1766 save_globals(s, allocated_regs);
1769 /* satisfy the output constraints */
1770 tcg_regset_set(allocated_regs, s->reserved_regs);
1771 for(k = 0; k < nb_oargs; k++) {
1772 i = def->sorted_args[k];
1773 arg = args[i];
1774 arg_ct = &def->args_ct[i];
1775 ts = &s->temps[arg];
1776 if (arg_ct->ct & TCG_CT_ALIAS) {
1777 reg = new_args[arg_ct->alias_index];
1778 } else {
1779 /* if fixed register, we try to use it */
1780 reg = ts->reg;
1781 if (ts->fixed_reg &&
1782 tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1783 goto oarg_end;
1785 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1787 tcg_regset_set_reg(allocated_regs, reg);
1788 /* if a fixed register is used, then a move will be done afterwards */
1789 if (!ts->fixed_reg) {
1790 if (ts->val_type == TEMP_VAL_REG)
1791 s->reg_to_temp[ts->reg] = -1;
1792 if (IS_DEAD_ARG(i)) {
1793 ts->val_type = TEMP_VAL_DEAD;
1794 } else {
1795 ts->val_type = TEMP_VAL_REG;
1796 ts->reg = reg;
1797 /* temp value is modified, so the value kept in memory is
1798 potentially not the same */
1799 ts->mem_coherent = 0;
1800 s->reg_to_temp[reg] = arg;
1803 oarg_end:
1804 new_args[i] = reg;
1808 /* emit instruction */
1809 tcg_out_op(s, opc, new_args, const_args);
1811 /* move the outputs in the correct register if needed */
1812 for(i = 0; i < nb_oargs; i++) {
1813 ts = &s->temps[args[i]];
1814 reg = new_args[i];
1815 if (ts->fixed_reg && ts->reg != reg) {
1816 tcg_out_mov(s, ts->type, ts->reg, reg);
1821 #ifdef TCG_TARGET_STACK_GROWSUP
1822 #define STACK_DIR(x) (-(x))
1823 #else
1824 #define STACK_DIR(x) (x)
1825 #endif
1827 static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
1828 TCGOpcode opc, const TCGArg *args,
1829 unsigned int dead_args)
1831 int nb_iargs, nb_oargs, flags, nb_regs, i, reg, nb_params;
1832 TCGArg arg, func_arg;
1833 TCGTemp *ts;
1834 tcg_target_long stack_offset, call_stack_size, func_addr;
1835 int const_func_arg, allocate_args;
1836 TCGRegSet allocated_regs;
1837 const TCGArgConstraint *arg_ct;
1839 arg = *args++;
1841 nb_oargs = arg >> 16;
1842 nb_iargs = arg & 0xffff;
1843 nb_params = nb_iargs - 1;
1845 flags = args[nb_oargs + nb_iargs];
1847 nb_regs = tcg_target_get_call_iarg_regs_count(flags);
1848 if (nb_regs > nb_params)
1849 nb_regs = nb_params;
1851 /* assign stack slots first */
1852 call_stack_size = (nb_params - nb_regs) * sizeof(tcg_target_long);
1853 call_stack_size = (call_stack_size + TCG_TARGET_STACK_ALIGN - 1) &
1854 ~(TCG_TARGET_STACK_ALIGN - 1);
1855 allocate_args = (call_stack_size > TCG_STATIC_CALL_ARGS_SIZE);
1856 if (allocate_args) {
1857 /* XXX: if more than TCG_STATIC_CALL_ARGS_SIZE is needed,
1858 preallocate call stack */
1859 tcg_abort();
1862 stack_offset = TCG_TARGET_CALL_STACK_OFFSET;
1863 for(i = nb_regs; i < nb_params; i++) {
1864 arg = args[nb_oargs + i];
1865 #ifdef TCG_TARGET_STACK_GROWSUP
1866 stack_offset -= sizeof(tcg_target_long);
1867 #endif
1868 if (arg != TCG_CALL_DUMMY_ARG) {
1869 ts = &s->temps[arg];
1870 if (ts->val_type == TEMP_VAL_REG) {
1871 tcg_out_st(s, ts->type, ts->reg, TCG_REG_CALL_STACK, stack_offset);
1872 } else if (ts->val_type == TEMP_VAL_MEM) {
1873 reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type],
1874 s->reserved_regs);
1875 /* XXX: not correct if reading values from the stack */
1876 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1877 tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
1878 } else if (ts->val_type == TEMP_VAL_CONST) {
1879 reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type],
1880 s->reserved_regs);
1881 /* XXX: sign extend may be needed on some targets */
1882 tcg_out_movi(s, ts->type, reg, ts->val);
1883 tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
1884 } else {
1885 tcg_abort();
1888 #ifndef TCG_TARGET_STACK_GROWSUP
1889 stack_offset += sizeof(tcg_target_long);
1890 #endif
1893 /* assign input registers */
1894 tcg_regset_set(allocated_regs, s->reserved_regs);
1895 for(i = 0; i < nb_regs; i++) {
1896 arg = args[nb_oargs + i];
1897 if (arg != TCG_CALL_DUMMY_ARG) {
1898 ts = &s->temps[arg];
1899 reg = tcg_target_call_iarg_regs[i];
1900 tcg_reg_free(s, reg);
1901 if (ts->val_type == TEMP_VAL_REG) {
1902 if (ts->reg != reg) {
1903 tcg_out_mov(s, ts->type, reg, ts->reg);
1905 } else if (ts->val_type == TEMP_VAL_MEM) {
1906 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1907 } else if (ts->val_type == TEMP_VAL_CONST) {
1908 /* XXX: sign extend ? */
1909 tcg_out_movi(s, ts->type, reg, ts->val);
1910 } else {
1911 tcg_abort();
1913 tcg_regset_set_reg(allocated_regs, reg);
1917 /* assign function address */
1918 func_arg = args[nb_oargs + nb_iargs - 1];
1919 arg_ct = &def->args_ct[0];
1920 ts = &s->temps[func_arg];
1921 func_addr = ts->val;
1922 const_func_arg = 0;
1923 if (ts->val_type == TEMP_VAL_MEM) {
1924 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1925 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1926 func_arg = reg;
1927 tcg_regset_set_reg(allocated_regs, reg);
1928 } else if (ts->val_type == TEMP_VAL_REG) {
1929 reg = ts->reg;
1930 if (!tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1931 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1932 tcg_out_mov(s, ts->type, reg, ts->reg);
1934 func_arg = reg;
1935 tcg_regset_set_reg(allocated_regs, reg);
1936 } else if (ts->val_type == TEMP_VAL_CONST) {
1937 if (tcg_target_const_match(func_addr, arg_ct)) {
1938 const_func_arg = 1;
1939 func_arg = func_addr;
1940 } else {
1941 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1942 tcg_out_movi(s, ts->type, reg, func_addr);
1943 func_arg = reg;
1944 tcg_regset_set_reg(allocated_regs, reg);
1946 } else {
1947 tcg_abort();
1951 /* mark dead temporaries and free the associated registers */
1952 for(i = nb_oargs; i < nb_iargs + nb_oargs; i++) {
1953 arg = args[i];
1954 if (IS_DEAD_ARG(i)) {
1955 ts = &s->temps[arg];
1956 if (!ts->fixed_reg) {
1957 if (ts->val_type == TEMP_VAL_REG)
1958 s->reg_to_temp[ts->reg] = -1;
1959 ts->val_type = TEMP_VAL_DEAD;
1964 /* clobber call registers */
1965 for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1966 if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
1967 tcg_reg_free(s, reg);
1971 /* store globals and free associated registers (we assume the call
1972 can modify any global. */
1973 if (!(flags & TCG_CALL_CONST)) {
1974 save_globals(s, allocated_regs);
1977 tcg_out_op(s, opc, &func_arg, &const_func_arg);
1979 /* assign output registers and emit moves if needed */
1980 for(i = 0; i < nb_oargs; i++) {
1981 arg = args[i];
1982 ts = &s->temps[arg];
1983 reg = tcg_target_call_oarg_regs[i];
1984 assert(s->reg_to_temp[reg] == -1);
1985 if (ts->fixed_reg) {
1986 if (ts->reg != reg) {
1987 tcg_out_mov(s, ts->type, ts->reg, reg);
1989 } else {
1990 if (ts->val_type == TEMP_VAL_REG)
1991 s->reg_to_temp[ts->reg] = -1;
1992 if (IS_DEAD_ARG(i)) {
1993 ts->val_type = TEMP_VAL_DEAD;
1994 } else {
1995 ts->val_type = TEMP_VAL_REG;
1996 ts->reg = reg;
1997 ts->mem_coherent = 0;
1998 s->reg_to_temp[reg] = arg;
2003 return nb_iargs + nb_oargs + def->nb_cargs + 1;
2006 #ifdef CONFIG_PROFILER
2008 static int64_t tcg_table_op_count[NB_OPS];
2010 static void dump_op_count(void)
2012 int i;
2013 FILE *f;
2014 f = fopen("/tmp/op.log", "w");
2015 for(i = INDEX_op_end; i < NB_OPS; i++) {
2016 fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name, tcg_table_op_count[i]);
2018 fclose(f);
2020 #endif
2023 static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
2024 long search_pc)
2026 TCGOpcode opc;
2027 int op_index;
2028 const TCGOpDef *def;
2029 unsigned int dead_args;
2030 const TCGArg *args;
2032 #ifdef DEBUG_DISAS
2033 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
2034 qemu_log("OP:\n");
2035 tcg_dump_ops(s, logfile);
2036 qemu_log("\n");
2038 #endif
2040 #ifdef USE_TCG_OPTIMIZATIONS
2041 gen_opparam_ptr =
2042 tcg_optimize(s, gen_opc_ptr, gen_opparam_buf, tcg_op_defs);
2043 #endif
2045 #ifdef CONFIG_PROFILER
2046 s->la_time -= profile_getclock();
2047 #endif
2048 tcg_liveness_analysis(s);
2049 #ifdef CONFIG_PROFILER
2050 s->la_time += profile_getclock();
2051 #endif
2053 #ifdef DEBUG_DISAS
2054 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_OPT))) {
2055 qemu_log("OP after liveness analysis:\n");
2056 tcg_dump_ops(s, logfile);
2057 qemu_log("\n");
2059 #endif
2061 tcg_reg_alloc_start(s);
2063 s->code_buf = gen_code_buf;
2064 s->code_ptr = gen_code_buf;
2066 args = gen_opparam_buf;
2067 op_index = 0;
2069 for(;;) {
2070 opc = gen_opc_buf[op_index];
2071 #ifdef CONFIG_PROFILER
2072 tcg_table_op_count[opc]++;
2073 #endif
2074 def = &tcg_op_defs[opc];
2075 #if 0
2076 printf("%s: %d %d %d\n", def->name,
2077 def->nb_oargs, def->nb_iargs, def->nb_cargs);
2078 // dump_regs(s);
2079 #endif
2080 switch(opc) {
2081 case INDEX_op_mov_i32:
2082 #if TCG_TARGET_REG_BITS == 64
2083 case INDEX_op_mov_i64:
2084 #endif
2085 dead_args = s->op_dead_args[op_index];
2086 tcg_reg_alloc_mov(s, def, args, dead_args);
2087 break;
2088 case INDEX_op_movi_i32:
2089 #if TCG_TARGET_REG_BITS == 64
2090 case INDEX_op_movi_i64:
2091 #endif
2092 tcg_reg_alloc_movi(s, args);
2093 break;
2094 case INDEX_op_debug_insn_start:
2095 /* debug instruction */
2096 break;
2097 case INDEX_op_nop:
2098 case INDEX_op_nop1:
2099 case INDEX_op_nop2:
2100 case INDEX_op_nop3:
2101 break;
2102 case INDEX_op_nopn:
2103 args += args[0];
2104 goto next;
2105 case INDEX_op_discard:
2107 TCGTemp *ts;
2108 ts = &s->temps[args[0]];
2109 /* mark the temporary as dead */
2110 if (!ts->fixed_reg) {
2111 if (ts->val_type == TEMP_VAL_REG)
2112 s->reg_to_temp[ts->reg] = -1;
2113 ts->val_type = TEMP_VAL_DEAD;
2116 break;
2117 case INDEX_op_set_label:
2118 tcg_reg_alloc_bb_end(s, s->reserved_regs);
2119 tcg_out_label(s, args[0], (long)s->code_ptr);
2120 break;
2121 case INDEX_op_call:
2122 dead_args = s->op_dead_args[op_index];
2123 args += tcg_reg_alloc_call(s, def, opc, args, dead_args);
2124 goto next;
2125 case INDEX_op_end:
2126 goto the_end;
2127 default:
2128 /* Sanity check that we've not introduced any unhandled opcodes. */
2129 if (def->flags & TCG_OPF_NOT_PRESENT) {
2130 tcg_abort();
2132 /* Note: in order to speed up the code, it would be much
2133 faster to have specialized register allocator functions for
2134 some common argument patterns */
2135 dead_args = s->op_dead_args[op_index];
2136 tcg_reg_alloc_op(s, def, opc, args, dead_args);
2137 break;
2139 args += def->nb_args;
2140 next:
2141 if (search_pc >= 0 && search_pc < s->code_ptr - gen_code_buf) {
2142 return op_index;
2144 op_index++;
2145 #ifndef NDEBUG
2146 check_regs(s);
2147 #endif
2149 the_end:
2150 return -1;
2153 int tcg_gen_code(TCGContext *s, uint8_t *gen_code_buf)
2155 #ifdef CONFIG_PROFILER
2157 int n;
2158 n = (gen_opc_ptr - gen_opc_buf);
2159 s->op_count += n;
2160 if (n > s->op_count_max)
2161 s->op_count_max = n;
2163 s->temp_count += s->nb_temps;
2164 if (s->nb_temps > s->temp_count_max)
2165 s->temp_count_max = s->nb_temps;
2167 #endif
2169 tcg_gen_code_common(s, gen_code_buf, -1);
2171 /* flush instruction cache */
2172 flush_icache_range((unsigned long)gen_code_buf,
2173 (unsigned long)s->code_ptr);
2174 return s->code_ptr - gen_code_buf;
2177 /* Return the index of the micro operation such as the pc after is <
2178 offset bytes from the start of the TB. The contents of gen_code_buf must
2179 not be changed, though writing the same values is ok.
2180 Return -1 if not found. */
2181 int tcg_gen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, long offset)
2183 return tcg_gen_code_common(s, gen_code_buf, offset);
2186 #ifdef CONFIG_PROFILER
2187 void tcg_dump_info(FILE *f, fprintf_function cpu_fprintf)
2189 TCGContext *s = &tcg_ctx;
2190 int64_t tot;
2192 tot = s->interm_time + s->code_time;
2193 cpu_fprintf(f, "JIT cycles %" PRId64 " (%0.3f s at 2.4 GHz)\n",
2194 tot, tot / 2.4e9);
2195 cpu_fprintf(f, "translated TBs %" PRId64 " (aborted=%" PRId64 " %0.1f%%)\n",
2196 s->tb_count,
2197 s->tb_count1 - s->tb_count,
2198 s->tb_count1 ? (double)(s->tb_count1 - s->tb_count) / s->tb_count1 * 100.0 : 0);
2199 cpu_fprintf(f, "avg ops/TB %0.1f max=%d\n",
2200 s->tb_count ? (double)s->op_count / s->tb_count : 0, s->op_count_max);
2201 cpu_fprintf(f, "deleted ops/TB %0.2f\n",
2202 s->tb_count ?
2203 (double)s->del_op_count / s->tb_count : 0);
2204 cpu_fprintf(f, "avg temps/TB %0.2f max=%d\n",
2205 s->tb_count ?
2206 (double)s->temp_count / s->tb_count : 0,
2207 s->temp_count_max);
2209 cpu_fprintf(f, "cycles/op %0.1f\n",
2210 s->op_count ? (double)tot / s->op_count : 0);
2211 cpu_fprintf(f, "cycles/in byte %0.1f\n",
2212 s->code_in_len ? (double)tot / s->code_in_len : 0);
2213 cpu_fprintf(f, "cycles/out byte %0.1f\n",
2214 s->code_out_len ? (double)tot / s->code_out_len : 0);
2215 if (tot == 0)
2216 tot = 1;
2217 cpu_fprintf(f, " gen_interm time %0.1f%%\n",
2218 (double)s->interm_time / tot * 100.0);
2219 cpu_fprintf(f, " gen_code time %0.1f%%\n",
2220 (double)s->code_time / tot * 100.0);
2221 cpu_fprintf(f, "liveness/code time %0.1f%%\n",
2222 (double)s->la_time / (s->code_time ? s->code_time : 1) * 100.0);
2223 cpu_fprintf(f, "cpu_restore count %" PRId64 "\n",
2224 s->restore_count);
2225 cpu_fprintf(f, " avg cycles %0.1f\n",
2226 s->restore_count ? (double)s->restore_time / s->restore_count : 0);
2228 dump_op_count();
2230 #else
2231 void tcg_dump_info(FILE *f, fprintf_function cpu_fprintf)
2233 cpu_fprintf(f, "[TCG profiler not compiled]\n");
2235 #endif