Fix the size of the property fields.
[qemu/navara.git] / tcg / tcg.c
blobbea9bc84e7d691fe75e9ea99f101dcaf6fe5f74b
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
28 #include "config.h"
30 #ifndef CONFIG_DEBUG_TCG
31 /* define it to suppress various consistency checks (faster) */
32 #define NDEBUG
33 #endif
35 #include <stdarg.h>
36 #include <stdlib.h>
37 #include <stdio.h>
38 #include <string.h>
39 #include <inttypes.h>
40 #ifdef _WIN32
41 #include <malloc.h>
42 #endif
43 #ifdef _AIX
44 #include <alloca.h>
45 #endif
47 #include "qemu-common.h"
48 #include "cache-utils.h"
49 #include "host-utils.h"
51 /* Note: the long term plan is to reduce the dependancies on the QEMU
52 CPU definitions. Currently they are used for qemu_ld/st
53 instructions */
54 #define NO_CPU_IO_DEFS
55 #include "cpu.h"
56 #include "exec-all.h"
58 #include "tcg-op.h"
59 #include "elf.h"
61 #if defined(CONFIG_USE_GUEST_BASE) && !defined(TCG_TARGET_HAS_GUEST_BASE)
62 #error GUEST_BASE not supported on this host.
63 #endif
65 static void patch_reloc(uint8_t *code_ptr, int type,
66 tcg_target_long value, tcg_target_long addend);
68 static TCGOpDef tcg_op_defs[] = {
69 #define DEF(s, n, copy_size) { #s, 0, 0, n, n, 0, copy_size },
70 #define DEF2(s, iargs, oargs, cargs, flags) { #s, iargs, oargs, cargs, iargs + oargs + cargs, flags, 0 },
71 #include "tcg-opc.h"
72 #undef DEF
73 #undef DEF2
76 static TCGRegSet tcg_target_available_regs[2];
77 static TCGRegSet tcg_target_call_clobber_regs;
79 /* XXX: move that inside the context */
80 uint16_t *gen_opc_ptr;
81 TCGArg *gen_opparam_ptr;
83 static inline void tcg_out8(TCGContext *s, uint8_t v)
85 *s->code_ptr++ = v;
88 static inline void tcg_out16(TCGContext *s, uint16_t v)
90 *(uint16_t *)s->code_ptr = v;
91 s->code_ptr += 2;
94 static inline void tcg_out32(TCGContext *s, uint32_t v)
96 *(uint32_t *)s->code_ptr = v;
97 s->code_ptr += 4;
100 /* label relocation processing */
102 void tcg_out_reloc(TCGContext *s, uint8_t *code_ptr, int type,
103 int label_index, long addend)
105 TCGLabel *l;
106 TCGRelocation *r;
108 l = &s->labels[label_index];
109 if (l->has_value) {
110 /* FIXME: This may break relocations on RISC targets that
111 modify instruction fields in place. The caller may not have
112 written the initial value. */
113 patch_reloc(code_ptr, type, l->u.value, addend);
114 } else {
115 /* add a new relocation entry */
116 r = tcg_malloc(sizeof(TCGRelocation));
117 r->type = type;
118 r->ptr = code_ptr;
119 r->addend = addend;
120 r->next = l->u.first_reloc;
121 l->u.first_reloc = r;
125 static void tcg_out_label(TCGContext *s, int label_index,
126 tcg_target_long value)
128 TCGLabel *l;
129 TCGRelocation *r;
131 l = &s->labels[label_index];
132 if (l->has_value)
133 tcg_abort();
134 r = l->u.first_reloc;
135 while (r != NULL) {
136 patch_reloc(r->ptr, r->type, value, r->addend);
137 r = r->next;
139 l->has_value = 1;
140 l->u.value = value;
143 int gen_new_label(void)
145 TCGContext *s = &tcg_ctx;
146 int idx;
147 TCGLabel *l;
149 if (s->nb_labels >= TCG_MAX_LABELS)
150 tcg_abort();
151 idx = s->nb_labels++;
152 l = &s->labels[idx];
153 l->has_value = 0;
154 l->u.first_reloc = NULL;
155 return idx;
158 #include "tcg-target.c"
160 /* pool based memory allocation */
161 void *tcg_malloc_internal(TCGContext *s, int size)
163 TCGPool *p;
164 int pool_size;
166 if (size > TCG_POOL_CHUNK_SIZE) {
167 /* big malloc: insert a new pool (XXX: could optimize) */
168 p = qemu_malloc(sizeof(TCGPool) + size);
169 p->size = size;
170 if (s->pool_current)
171 s->pool_current->next = p;
172 else
173 s->pool_first = p;
174 p->next = s->pool_current;
175 } else {
176 p = s->pool_current;
177 if (!p) {
178 p = s->pool_first;
179 if (!p)
180 goto new_pool;
181 } else {
182 if (!p->next) {
183 new_pool:
184 pool_size = TCG_POOL_CHUNK_SIZE;
185 p = qemu_malloc(sizeof(TCGPool) + pool_size);
186 p->size = pool_size;
187 p->next = NULL;
188 if (s->pool_current)
189 s->pool_current->next = p;
190 else
191 s->pool_first = p;
192 } else {
193 p = p->next;
197 s->pool_current = p;
198 s->pool_cur = p->data + size;
199 s->pool_end = p->data + p->size;
200 return p->data;
203 void tcg_pool_reset(TCGContext *s)
205 s->pool_cur = s->pool_end = NULL;
206 s->pool_current = NULL;
209 void tcg_context_init(TCGContext *s)
211 int op, total_args, n;
212 TCGOpDef *def;
213 TCGArgConstraint *args_ct;
214 int *sorted_args;
216 memset(s, 0, sizeof(*s));
217 s->temps = s->static_temps;
218 s->nb_globals = 0;
220 /* Count total number of arguments and allocate the corresponding
221 space */
222 total_args = 0;
223 for(op = 0; op < NB_OPS; op++) {
224 def = &tcg_op_defs[op];
225 n = def->nb_iargs + def->nb_oargs;
226 total_args += n;
229 args_ct = qemu_malloc(sizeof(TCGArgConstraint) * total_args);
230 sorted_args = qemu_malloc(sizeof(int) * total_args);
232 for(op = 0; op < NB_OPS; op++) {
233 def = &tcg_op_defs[op];
234 def->args_ct = args_ct;
235 def->sorted_args = sorted_args;
236 n = def->nb_iargs + def->nb_oargs;
237 sorted_args += n;
238 args_ct += n;
241 tcg_target_init(s);
243 /* init global prologue and epilogue */
244 s->code_buf = code_gen_prologue;
245 s->code_ptr = s->code_buf;
246 tcg_target_qemu_prologue(s);
247 flush_icache_range((uintptr_t)s->code_buf,
248 (uintptr_t)s->code_ptr);
251 void tcg_set_frame(TCGContext *s, int reg,
252 tcg_target_long start, tcg_target_long size)
254 s->frame_start = start;
255 s->frame_end = start + size;
256 s->frame_reg = reg;
259 void tcg_func_start(TCGContext *s)
261 int i;
262 tcg_pool_reset(s);
263 s->nb_temps = s->nb_globals;
264 for(i = 0; i < (TCG_TYPE_COUNT * 2); i++)
265 s->first_free_temp[i] = -1;
266 s->labels = tcg_malloc(sizeof(TCGLabel) * TCG_MAX_LABELS);
267 s->nb_labels = 0;
268 s->current_frame_offset = s->frame_start;
270 gen_opc_ptr = gen_opc_buf;
271 gen_opparam_ptr = gen_opparam_buf;
274 static inline void tcg_temp_alloc(TCGContext *s, int n)
276 if (n > TCG_MAX_TEMPS)
277 tcg_abort();
280 static inline int tcg_global_reg_new_internal(TCGType type, int reg,
281 const char *name)
283 TCGContext *s = &tcg_ctx;
284 TCGTemp *ts;
285 int idx;
287 #if TCG_TARGET_REG_BITS == 32
288 if (type != TCG_TYPE_I32)
289 tcg_abort();
290 #endif
291 if (tcg_regset_test_reg(s->reserved_regs, reg))
292 tcg_abort();
293 idx = s->nb_globals;
294 tcg_temp_alloc(s, s->nb_globals + 1);
295 ts = &s->temps[s->nb_globals];
296 ts->base_type = type;
297 ts->type = type;
298 ts->fixed_reg = 1;
299 ts->reg = reg;
300 ts->name = name;
301 s->nb_globals++;
302 tcg_regset_set_reg(s->reserved_regs, reg);
303 return idx;
306 TCGv_i32 tcg_global_reg_new_i32(int reg, const char *name)
308 int idx;
310 idx = tcg_global_reg_new_internal(TCG_TYPE_I32, reg, name);
311 return MAKE_TCGV_I32(idx);
314 TCGv_i64 tcg_global_reg_new_i64(int reg, const char *name)
316 int idx;
318 idx = tcg_global_reg_new_internal(TCG_TYPE_I64, reg, name);
319 return MAKE_TCGV_I64(idx);
322 static inline int tcg_global_mem_new_internal(TCGType type, int reg,
323 tcg_target_long offset,
324 const char *name)
326 TCGContext *s = &tcg_ctx;
327 TCGTemp *ts;
328 int idx;
330 idx = s->nb_globals;
331 #if TCG_TARGET_REG_BITS == 32
332 if (type == TCG_TYPE_I64) {
333 char buf[64];
334 tcg_temp_alloc(s, s->nb_globals + 2);
335 ts = &s->temps[s->nb_globals];
336 ts->base_type = type;
337 ts->type = TCG_TYPE_I32;
338 ts->fixed_reg = 0;
339 ts->mem_allocated = 1;
340 ts->mem_reg = reg;
341 #ifdef TCG_TARGET_WORDS_BIGENDIAN
342 ts->mem_offset = offset + 4;
343 #else
344 ts->mem_offset = offset;
345 #endif
346 pstrcpy(buf, sizeof(buf), name);
347 pstrcat(buf, sizeof(buf), "_0");
348 ts->name = strdup(buf);
349 ts++;
351 ts->base_type = type;
352 ts->type = TCG_TYPE_I32;
353 ts->fixed_reg = 0;
354 ts->mem_allocated = 1;
355 ts->mem_reg = reg;
356 #ifdef TCG_TARGET_WORDS_BIGENDIAN
357 ts->mem_offset = offset;
358 #else
359 ts->mem_offset = offset + 4;
360 #endif
361 pstrcpy(buf, sizeof(buf), name);
362 pstrcat(buf, sizeof(buf), "_1");
363 ts->name = strdup(buf);
365 s->nb_globals += 2;
366 } else
367 #endif
369 tcg_temp_alloc(s, s->nb_globals + 1);
370 ts = &s->temps[s->nb_globals];
371 ts->base_type = type;
372 ts->type = type;
373 ts->fixed_reg = 0;
374 ts->mem_allocated = 1;
375 ts->mem_reg = reg;
376 ts->mem_offset = offset;
377 ts->name = name;
378 s->nb_globals++;
380 return idx;
383 TCGv_i32 tcg_global_mem_new_i32(int reg, tcg_target_long offset,
384 const char *name)
386 int idx;
388 idx = tcg_global_mem_new_internal(TCG_TYPE_I32, reg, offset, name);
389 return MAKE_TCGV_I32(idx);
392 TCGv_i64 tcg_global_mem_new_i64(int reg, tcg_target_long offset,
393 const char *name)
395 int idx;
397 idx = tcg_global_mem_new_internal(TCG_TYPE_I64, reg, offset, name);
398 return MAKE_TCGV_I64(idx);
401 static inline int tcg_temp_new_internal(TCGType type, int temp_local)
403 TCGContext *s = &tcg_ctx;
404 TCGTemp *ts;
405 int idx, k;
407 k = type;
408 if (temp_local)
409 k += TCG_TYPE_COUNT;
410 idx = s->first_free_temp[k];
411 if (idx != -1) {
412 /* There is already an available temp with the
413 right type */
414 ts = &s->temps[idx];
415 s->first_free_temp[k] = ts->next_free_temp;
416 ts->temp_allocated = 1;
417 assert(ts->temp_local == temp_local);
418 } else {
419 idx = s->nb_temps;
420 #if TCG_TARGET_REG_BITS == 32
421 if (type == TCG_TYPE_I64) {
422 tcg_temp_alloc(s, s->nb_temps + 2);
423 ts = &s->temps[s->nb_temps];
424 ts->base_type = type;
425 ts->type = TCG_TYPE_I32;
426 ts->temp_allocated = 1;
427 ts->temp_local = temp_local;
428 ts->name = NULL;
429 ts++;
430 ts->base_type = TCG_TYPE_I32;
431 ts->type = TCG_TYPE_I32;
432 ts->temp_allocated = 1;
433 ts->temp_local = temp_local;
434 ts->name = NULL;
435 s->nb_temps += 2;
436 } else
437 #endif
439 tcg_temp_alloc(s, s->nb_temps + 1);
440 ts = &s->temps[s->nb_temps];
441 ts->base_type = type;
442 ts->type = type;
443 ts->temp_allocated = 1;
444 ts->temp_local = temp_local;
445 ts->name = NULL;
446 s->nb_temps++;
449 return idx;
452 TCGv_i32 tcg_temp_new_internal_i32(int temp_local)
454 int idx;
456 idx = tcg_temp_new_internal(TCG_TYPE_I32, temp_local);
457 return MAKE_TCGV_I32(idx);
460 TCGv_i64 tcg_temp_new_internal_i64(int temp_local)
462 int idx;
464 idx = tcg_temp_new_internal(TCG_TYPE_I64, temp_local);
465 return MAKE_TCGV_I64(idx);
468 static inline void tcg_temp_free_internal(int idx)
470 TCGContext *s = &tcg_ctx;
471 TCGTemp *ts;
472 int k;
474 assert(idx >= s->nb_globals && idx < s->nb_temps);
475 ts = &s->temps[idx];
476 assert(ts->temp_allocated != 0);
477 ts->temp_allocated = 0;
478 k = ts->base_type;
479 if (ts->temp_local)
480 k += TCG_TYPE_COUNT;
481 ts->next_free_temp = s->first_free_temp[k];
482 s->first_free_temp[k] = idx;
485 void tcg_temp_free_i32(TCGv_i32 arg)
487 tcg_temp_free_internal(GET_TCGV_I32(arg));
490 void tcg_temp_free_i64(TCGv_i64 arg)
492 tcg_temp_free_internal(GET_TCGV_I64(arg));
495 TCGv_i32 tcg_const_i32(int32_t val)
497 TCGv_i32 t0;
498 t0 = tcg_temp_new_i32();
499 tcg_gen_movi_i32(t0, val);
500 return t0;
503 TCGv_i64 tcg_const_i64(int64_t val)
505 TCGv_i64 t0;
506 t0 = tcg_temp_new_i64();
507 tcg_gen_movi_i64(t0, val);
508 return t0;
511 TCGv_i32 tcg_const_local_i32(int32_t val)
513 TCGv_i32 t0;
514 t0 = tcg_temp_local_new_i32();
515 tcg_gen_movi_i32(t0, val);
516 return t0;
519 TCGv_i64 tcg_const_local_i64(int64_t val)
521 TCGv_i64 t0;
522 t0 = tcg_temp_local_new_i64();
523 tcg_gen_movi_i64(t0, val);
524 return t0;
527 void tcg_register_helper(void *func, const char *name)
529 TCGContext *s = &tcg_ctx;
530 int n;
531 if ((s->nb_helpers + 1) > s->allocated_helpers) {
532 n = s->allocated_helpers;
533 if (n == 0) {
534 n = 4;
535 } else {
536 n *= 2;
538 s->helpers = realloc(s->helpers, n * sizeof(TCGHelperInfo));
539 s->allocated_helpers = n;
541 s->helpers[s->nb_helpers].func = (tcg_target_ulong)func;
542 s->helpers[s->nb_helpers].name = name;
543 s->nb_helpers++;
546 /* Note: we convert the 64 bit args to 32 bit and do some alignment
547 and endian swap. Maybe it would be better to do the alignment
548 and endian swap in tcg_reg_alloc_call(). */
549 void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags,
550 int sizemask, TCGArg ret, int nargs, TCGArg *args)
552 int call_type;
553 int i;
554 int real_args;
555 int nb_rets;
556 TCGArg *nparam;
557 *gen_opc_ptr++ = INDEX_op_call;
558 nparam = gen_opparam_ptr++;
559 call_type = (flags & TCG_CALL_TYPE_MASK);
560 if (ret != TCG_CALL_DUMMY_ARG) {
561 #if TCG_TARGET_REG_BITS < 64
562 if (sizemask & 1) {
563 #ifdef TCG_TARGET_WORDS_BIGENDIAN
564 *gen_opparam_ptr++ = ret + 1;
565 *gen_opparam_ptr++ = ret;
566 #else
567 *gen_opparam_ptr++ = ret;
568 *gen_opparam_ptr++ = ret + 1;
569 #endif
570 nb_rets = 2;
571 } else
572 #endif
574 *gen_opparam_ptr++ = ret;
575 nb_rets = 1;
577 } else {
578 nb_rets = 0;
580 real_args = 0;
581 for (i = 0; i < nargs; i++) {
582 #if TCG_TARGET_REG_BITS < 64
583 if (sizemask & (2 << i)) {
584 #ifdef TCG_TARGET_I386
585 /* REGPARM case: if the third parameter is 64 bit, it is
586 allocated on the stack */
587 if (i == 2 && call_type == TCG_CALL_TYPE_REGPARM) {
588 call_type = TCG_CALL_TYPE_REGPARM_2;
589 flags = (flags & ~TCG_CALL_TYPE_MASK) | call_type;
591 #endif
592 #ifdef TCG_TARGET_CALL_ALIGN_ARGS
593 /* some targets want aligned 64 bit args */
594 if (real_args & 1) {
595 *gen_opparam_ptr++ = TCG_CALL_DUMMY_ARG;
596 real_args++;
598 #endif
599 #ifdef TCG_TARGET_WORDS_BIGENDIAN
600 *gen_opparam_ptr++ = args[i] + 1;
601 *gen_opparam_ptr++ = args[i];
602 #else
603 *gen_opparam_ptr++ = args[i];
604 *gen_opparam_ptr++ = args[i] + 1;
605 #endif
606 real_args += 2;
607 } else
608 #endif
610 *gen_opparam_ptr++ = args[i];
611 real_args++;
614 *gen_opparam_ptr++ = GET_TCGV_PTR(func);
616 *gen_opparam_ptr++ = flags;
618 *nparam = (nb_rets << 16) | (real_args + 1);
620 /* total parameters, needed to go backward in the instruction stream */
621 *gen_opparam_ptr++ = 1 + nb_rets + real_args + 3;
624 #if TCG_TARGET_REG_BITS == 32
625 void tcg_gen_shifti_i64(TCGv_i64 ret, TCGv_i64 arg1,
626 int c, int right, int arith)
628 if (c == 0) {
629 tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg1));
630 tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
631 } else if (c >= 32) {
632 c -= 32;
633 if (right) {
634 if (arith) {
635 tcg_gen_sari_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
636 tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 31);
637 } else {
638 tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
639 tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
641 } else {
642 tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_LOW(arg1), c);
643 tcg_gen_movi_i32(TCGV_LOW(ret), 0);
645 } else {
646 TCGv_i32 t0, t1;
648 t0 = tcg_temp_new_i32();
649 t1 = tcg_temp_new_i32();
650 if (right) {
651 tcg_gen_shli_i32(t0, TCGV_HIGH(arg1), 32 - c);
652 if (arith)
653 tcg_gen_sari_i32(t1, TCGV_HIGH(arg1), c);
654 else
655 tcg_gen_shri_i32(t1, TCGV_HIGH(arg1), c);
656 tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_LOW(arg1), c);
657 tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(ret), t0);
658 tcg_gen_mov_i32(TCGV_HIGH(ret), t1);
659 } else {
660 tcg_gen_shri_i32(t0, TCGV_LOW(arg1), 32 - c);
661 /* Note: ret can be the same as arg1, so we use t1 */
662 tcg_gen_shli_i32(t1, TCGV_LOW(arg1), c);
663 tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c);
664 tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t0);
665 tcg_gen_mov_i32(TCGV_LOW(ret), t1);
667 tcg_temp_free_i32(t0);
668 tcg_temp_free_i32(t1);
671 #endif
673 static void tcg_reg_alloc_start(TCGContext *s)
675 int i;
676 TCGTemp *ts;
677 for(i = 0; i < s->nb_globals; i++) {
678 ts = &s->temps[i];
679 if (ts->fixed_reg) {
680 ts->val_type = TEMP_VAL_REG;
681 } else {
682 ts->val_type = TEMP_VAL_MEM;
685 for(i = s->nb_globals; i < s->nb_temps; i++) {
686 ts = &s->temps[i];
687 ts->val_type = TEMP_VAL_DEAD;
688 ts->mem_allocated = 0;
689 ts->fixed_reg = 0;
691 for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
692 s->reg_to_temp[i] = -1;
696 static char *tcg_get_arg_str_idx(TCGContext *s, char *buf, int buf_size,
697 int idx)
699 TCGTemp *ts;
701 ts = &s->temps[idx];
702 if (idx < s->nb_globals) {
703 pstrcpy(buf, buf_size, ts->name);
704 } else {
705 if (ts->temp_local)
706 snprintf(buf, buf_size, "loc%d", idx - s->nb_globals);
707 else
708 snprintf(buf, buf_size, "tmp%d", idx - s->nb_globals);
710 return buf;
713 char *tcg_get_arg_str_i32(TCGContext *s, char *buf, int buf_size, TCGv_i32 arg)
715 return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I32(arg));
718 char *tcg_get_arg_str_i64(TCGContext *s, char *buf, int buf_size, TCGv_i64 arg)
720 return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I64(arg));
723 static int helper_cmp(const void *p1, const void *p2)
725 const TCGHelperInfo *th1 = p1;
726 const TCGHelperInfo *th2 = p2;
727 if (th1->func < th2->func)
728 return -1;
729 else if (th1->func == th2->func)
730 return 0;
731 else
732 return 1;
735 /* find helper definition (Note: A hash table would be better) */
736 static TCGHelperInfo *tcg_find_helper(TCGContext *s, tcg_target_ulong val)
738 int m, m_min, m_max;
739 TCGHelperInfo *th;
740 tcg_target_ulong v;
742 if (unlikely(!s->helpers_sorted)) {
743 qsort(s->helpers, s->nb_helpers, sizeof(TCGHelperInfo),
744 helper_cmp);
745 s->helpers_sorted = 1;
748 /* binary search */
749 m_min = 0;
750 m_max = s->nb_helpers - 1;
751 while (m_min <= m_max) {
752 m = (m_min + m_max) >> 1;
753 th = &s->helpers[m];
754 v = th->func;
755 if (v == val)
756 return th;
757 else if (val < v) {
758 m_max = m - 1;
759 } else {
760 m_min = m + 1;
763 return NULL;
766 static const char * const cond_name[] =
768 [TCG_COND_EQ] = "eq",
769 [TCG_COND_NE] = "ne",
770 [TCG_COND_LT] = "lt",
771 [TCG_COND_GE] = "ge",
772 [TCG_COND_LE] = "le",
773 [TCG_COND_GT] = "gt",
774 [TCG_COND_LTU] = "ltu",
775 [TCG_COND_GEU] = "geu",
776 [TCG_COND_LEU] = "leu",
777 [TCG_COND_GTU] = "gtu"
780 void tcg_dump_ops(TCGContext *s, FILE *outfile)
782 const uint16_t *opc_ptr;
783 const TCGArg *args;
784 TCGArg arg;
785 int c, i, k, nb_oargs, nb_iargs, nb_cargs, first_insn;
786 const TCGOpDef *def;
787 char buf[128];
789 first_insn = 1;
790 opc_ptr = gen_opc_buf;
791 args = gen_opparam_buf;
792 while (opc_ptr < gen_opc_ptr) {
793 c = *opc_ptr++;
794 def = &tcg_op_defs[c];
795 if (c == INDEX_op_debug_insn_start) {
796 uint64_t pc;
797 #if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
798 pc = ((uint64_t)args[1] << 32) | args[0];
799 #else
800 pc = args[0];
801 #endif
802 if (!first_insn)
803 fprintf(outfile, "\n");
804 fprintf(outfile, " ---- 0x%" PRIx64, pc);
805 first_insn = 0;
806 nb_oargs = def->nb_oargs;
807 nb_iargs = def->nb_iargs;
808 nb_cargs = def->nb_cargs;
809 } else if (c == INDEX_op_call) {
810 TCGArg arg;
812 /* variable number of arguments */
813 arg = *args++;
814 nb_oargs = arg >> 16;
815 nb_iargs = arg & 0xffff;
816 nb_cargs = def->nb_cargs;
818 fprintf(outfile, " %s ", def->name);
820 /* function name */
821 fprintf(outfile, "%s",
822 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + nb_iargs - 1]));
823 /* flags */
824 fprintf(outfile, ",$0x%" TCG_PRIlx,
825 args[nb_oargs + nb_iargs]);
826 /* nb out args */
827 fprintf(outfile, ",$%d", nb_oargs);
828 for(i = 0; i < nb_oargs; i++) {
829 fprintf(outfile, ",");
830 fprintf(outfile, "%s",
831 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[i]));
833 for(i = 0; i < (nb_iargs - 1); i++) {
834 fprintf(outfile, ",");
835 if (args[nb_oargs + i] == TCG_CALL_DUMMY_ARG) {
836 fprintf(outfile, "<dummy>");
837 } else {
838 fprintf(outfile, "%s",
839 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + i]));
842 } else if (c == INDEX_op_movi_i32
843 #if TCG_TARGET_REG_BITS == 64
844 || c == INDEX_op_movi_i64
845 #endif
847 tcg_target_ulong val;
848 TCGHelperInfo *th;
850 nb_oargs = def->nb_oargs;
851 nb_iargs = def->nb_iargs;
852 nb_cargs = def->nb_cargs;
853 fprintf(outfile, " %s %s,$", def->name,
854 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[0]));
855 val = args[1];
856 th = tcg_find_helper(s, val);
857 if (th) {
858 fprintf(outfile, "%s", th->name);
859 } else {
860 if (c == INDEX_op_movi_i32)
861 fprintf(outfile, "0x%x", (uint32_t)val);
862 else
863 fprintf(outfile, "0x%" PRIx64 , (uint64_t)val);
865 } else {
866 fprintf(outfile, " %s ", def->name);
867 if (c == INDEX_op_nopn) {
868 /* variable number of arguments */
869 nb_cargs = *args;
870 nb_oargs = 0;
871 nb_iargs = 0;
872 } else {
873 nb_oargs = def->nb_oargs;
874 nb_iargs = def->nb_iargs;
875 nb_cargs = def->nb_cargs;
878 k = 0;
879 for(i = 0; i < nb_oargs; i++) {
880 if (k != 0)
881 fprintf(outfile, ",");
882 fprintf(outfile, "%s",
883 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
885 for(i = 0; i < nb_iargs; i++) {
886 if (k != 0)
887 fprintf(outfile, ",");
888 fprintf(outfile, "%s",
889 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
891 if (c == INDEX_op_brcond_i32
892 #if TCG_TARGET_REG_BITS == 32
893 || c == INDEX_op_brcond2_i32
894 #elif TCG_TARGET_REG_BITS == 64
895 || c == INDEX_op_brcond_i64
896 #endif
898 if (args[k] < ARRAY_SIZE(cond_name) && cond_name[args[k]])
899 fprintf(outfile, ",%s", cond_name[args[k++]]);
900 else
901 fprintf(outfile, ",$0x%" TCG_PRIlx, args[k++]);
902 i = 1;
904 else
905 i = 0;
906 for(; i < nb_cargs; i++) {
907 if (k != 0)
908 fprintf(outfile, ",");
909 arg = args[k++];
910 fprintf(outfile, "$0x%" TCG_PRIlx, arg);
913 fprintf(outfile, "\n");
914 args += nb_iargs + nb_oargs + nb_cargs;
918 /* we give more priority to constraints with less registers */
919 static int get_constraint_priority(const TCGOpDef *def, int k)
921 const TCGArgConstraint *arg_ct;
923 int i, n;
924 arg_ct = &def->args_ct[k];
925 if (arg_ct->ct & TCG_CT_ALIAS) {
926 /* an alias is equivalent to a single register */
927 n = 1;
928 } else {
929 if (!(arg_ct->ct & TCG_CT_REG))
930 return 0;
931 n = 0;
932 for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
933 if (tcg_regset_test_reg(arg_ct->u.regs, i))
934 n++;
937 return TCG_TARGET_NB_REGS - n + 1;
940 /* sort from highest priority to lowest */
941 static void sort_constraints(TCGOpDef *def, int start, int n)
943 int i, j, p1, p2, tmp;
945 for(i = 0; i < n; i++)
946 def->sorted_args[start + i] = start + i;
947 if (n <= 1)
948 return;
949 for(i = 0; i < n - 1; i++) {
950 for(j = i + 1; j < n; j++) {
951 p1 = get_constraint_priority(def, def->sorted_args[start + i]);
952 p2 = get_constraint_priority(def, def->sorted_args[start + j]);
953 if (p1 < p2) {
954 tmp = def->sorted_args[start + i];
955 def->sorted_args[start + i] = def->sorted_args[start + j];
956 def->sorted_args[start + j] = tmp;
962 void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs)
964 int op;
965 TCGOpDef *def;
966 const char *ct_str;
967 int i, nb_args;
969 for(;;) {
970 if (tdefs->op < 0)
971 break;
972 op = tdefs->op;
973 assert(op >= 0 && op < NB_OPS);
974 def = &tcg_op_defs[op];
975 nb_args = def->nb_iargs + def->nb_oargs;
976 for(i = 0; i < nb_args; i++) {
977 ct_str = tdefs->args_ct_str[i];
978 tcg_regset_clear(def->args_ct[i].u.regs);
979 def->args_ct[i].ct = 0;
980 if (ct_str[0] >= '0' && ct_str[0] <= '9') {
981 int oarg;
982 oarg = ct_str[0] - '0';
983 assert(oarg < def->nb_oargs);
984 assert(def->args_ct[oarg].ct & TCG_CT_REG);
985 /* TCG_CT_ALIAS is for the output arguments. The input
986 argument is tagged with TCG_CT_IALIAS. */
987 def->args_ct[i] = def->args_ct[oarg];
988 def->args_ct[oarg].ct = TCG_CT_ALIAS;
989 def->args_ct[oarg].alias_index = i;
990 def->args_ct[i].ct |= TCG_CT_IALIAS;
991 def->args_ct[i].alias_index = oarg;
992 } else {
993 for(;;) {
994 if (*ct_str == '\0')
995 break;
996 switch(*ct_str) {
997 case 'i':
998 def->args_ct[i].ct |= TCG_CT_CONST;
999 ct_str++;
1000 break;
1001 default:
1002 if (target_parse_constraint(&def->args_ct[i], &ct_str) < 0) {
1003 fprintf(stderr, "Invalid constraint '%s' for arg %d of operation '%s'\n",
1004 ct_str, i, def->name);
1005 exit(1);
1012 /* sort the constraints (XXX: this is just an heuristic) */
1013 sort_constraints(def, 0, def->nb_oargs);
1014 sort_constraints(def, def->nb_oargs, def->nb_iargs);
1016 #if 0
1018 int i;
1020 printf("%s: sorted=", def->name);
1021 for(i = 0; i < def->nb_oargs + def->nb_iargs; i++)
1022 printf(" %d", def->sorted_args[i]);
1023 printf("\n");
1025 #endif
1026 tdefs++;
1030 static void tcg_const_analysis(TCGContext *s)
1032 int nb_cargs, nb_iargs, nb_oargs, dest, src, src2, del_args, i;
1033 TCGArg *args;
1034 uint16_t op;
1035 uint16_t *opc_ptr;
1036 const TCGOpDef *def;
1037 uint8_t *const_temps;
1038 tcg_target_ulong *temp_values;
1039 tcg_target_ulong val;
1040 tcg_target_ulong dest_val, src_val, src2_val;
1042 const_temps = tcg_malloc(s->nb_temps);
1043 memset(const_temps, 0, s->nb_temps);
1044 temp_values = tcg_malloc(s->nb_temps * sizeof(uint32_t));
1046 opc_ptr = gen_opc_buf;
1047 args = gen_opparam_buf;
1048 while (opc_ptr < gen_opc_ptr) {
1049 op = *opc_ptr;
1050 def = &tcg_op_defs[op];
1051 nb_oargs = def->nb_oargs;
1052 nb_iargs = def->nb_iargs;
1053 nb_cargs = def->nb_cargs;
1054 del_args = 0;
1056 switch(op) {
1057 case INDEX_op_movi_i32:
1058 #if TCG_TARGET_REG_BITS == 64
1059 case INDEX_op_movi_i64:
1060 #endif
1061 dest = args[0];
1062 val = args[1];
1063 const_temps[dest] = 1;
1064 temp_values[dest] = val;
1065 break;
1066 case INDEX_op_mov_i32:
1067 #if TCG_TARGET_REG_BITS == 64
1068 case INDEX_op_mov_i64:
1069 #endif
1070 dest = args[0];
1071 src = args[1];
1072 const_temps[dest] = const_temps[src];
1073 temp_values[dest] = temp_values[src];
1074 break;
1075 #ifdef TCG_TARGET_HAS_not_i32
1076 case INDEX_op_not_i32:
1077 dest = args[0];
1078 src = args[1];
1079 if (const_temps[src]) {
1080 const_temps[dest] = 1;
1081 *opc_ptr = INDEX_op_movi_i32;
1082 args[1] = temp_values[dest] = ~temp_values[src] & 0xffffffff;
1083 } else {
1084 const_temps[dest] = 0;
1086 break;
1087 #endif
1088 #ifdef TCG_TARGET_HAS_not_i64
1089 case INDEX_op_not_i64:
1090 dest = args[0];
1091 src = args[1];
1092 if (const_temps[src]) {
1093 const_temps[dest] = 1;
1094 *opc_ptr = INDEX_op_movi_i64;
1095 args[1] = temp_values[dest] = ~temp_values[src];
1096 } else {
1097 const_temps[dest] = 0;
1099 break;
1100 #endif
1101 case INDEX_op_add_i32:
1102 case INDEX_op_sub_i32:
1103 case INDEX_op_mul_i32:
1104 case INDEX_op_and_i32:
1105 case INDEX_op_or_i32:
1106 case INDEX_op_xor_i32:
1107 case INDEX_op_shl_i32:
1108 case INDEX_op_shr_i32:
1109 dest = args[0];
1110 src = args[1];
1111 src2 = args[2];
1112 if (const_temps[src] && const_temps[src2]) {
1113 src_val = temp_values[src];
1114 src2_val = temp_values[src2];
1115 const_temps[dest] = 1;
1116 switch (op) {
1117 case INDEX_op_add_i32: dest_val = src_val + src2_val; break;
1118 case INDEX_op_sub_i32: dest_val = src_val - src2_val; break;
1119 case INDEX_op_mul_i32: dest_val = src_val * src2_val; break;
1120 case INDEX_op_and_i32: dest_val = src_val & src2_val; break;
1121 case INDEX_op_or_i32: dest_val = src_val | src2_val; break;
1122 case INDEX_op_xor_i32: dest_val = src_val ^ src2_val; break;
1123 case INDEX_op_shl_i32: dest_val = src_val << src2_val; break;
1124 case INDEX_op_shr_i32: dest_val = src_val >> src2_val; break;
1125 default: tcg_abort(); return;
1127 *opc_ptr = INDEX_op_movi_i32;
1128 args[1] = temp_values[dest] = dest_val & 0xffffffff;
1129 del_args = 1;
1130 } else {
1131 const_temps[dest] = 0;
1133 break;
1134 #if TCG_TARGET_REG_BITS == 64
1135 case INDEX_op_add_i64:
1136 case INDEX_op_sub_i64:
1137 case INDEX_op_mul_i64:
1138 case INDEX_op_and_i64:
1139 case INDEX_op_or_i64:
1140 case INDEX_op_xor_i64:
1141 case INDEX_op_shl_i64:
1142 case INDEX_op_shr_i64:
1143 dest = args[0];
1144 src = args[1];
1145 src2 = args[2];
1146 if (const_temps[src] && const_temps[src2]) {
1147 src_val = temp_values[src];
1148 src2_val = temp_values[src2];
1149 const_temps[dest] = 1;
1150 switch (op) {
1151 case INDEX_op_add_i64: dest_val = src_val + src2_val; break;
1152 case INDEX_op_sub_i64: dest_val = src_val - src2_val; break;
1153 case INDEX_op_mul_i64: dest_val = src_val * src2_val; break;
1154 case INDEX_op_and_i64: dest_val = src_val & src2_val; break;
1155 case INDEX_op_or_i64: dest_val = src_val | src2_val; break;
1156 case INDEX_op_xor_i64: dest_val = src_val ^ src2_val; break;
1157 case INDEX_op_shl_i64: dest_val = src_val << src2_val; break;
1158 case INDEX_op_shr_i64: dest_val = src_val >> src2_val; break;
1159 default: tcg_abort(); return;
1161 *opc_ptr = INDEX_op_movi_i64;
1162 args[1] = temp_values[dest] = dest_val;
1163 del_args = 1;
1164 } else {
1165 const_temps[dest] = 0;
1167 break;
1168 #endif
1169 case INDEX_op_call:
1170 nb_oargs = args[0] >> 16;
1171 nb_iargs = args[0] & 0xffff;
1172 nb_cargs = def->nb_cargs;
1173 args++;
1174 for (i = 0; i < nb_oargs; i++) {
1175 const_temps[args[i]] = 0;
1177 break;
1178 case INDEX_op_nopn:
1179 /* variable number of arguments */
1180 nb_cargs = args[0];
1181 break;
1182 case INDEX_op_set_label:
1183 memset(const_temps, 0, s->nb_temps);
1184 break;
1185 default:
1186 if (def->flags & TCG_OPF_BB_END) {
1187 memset(const_temps, 0, s->nb_temps);
1188 } else {
1189 for (i = 0; i < nb_oargs; i++) {
1190 const_temps[args[i]] = 0;
1193 break;
1195 opc_ptr++;
1196 args += nb_iargs + nb_oargs + nb_cargs - del_args;
1197 if (del_args > 0) {
1198 gen_opparam_ptr -= del_args;
1199 memmove(args, args + del_args, (gen_opparam_ptr - args) * sizeof(*args));
1203 if (args != gen_opparam_ptr)
1204 tcg_abort();
1207 #ifdef USE_LIVENESS_ANALYSIS
1209 /* set a nop for an operation using 'nb_args' */
1210 static inline void tcg_set_nop(TCGContext *s, uint16_t *opc_ptr,
1211 TCGArg *args, int nb_args)
1213 if (nb_args == 0) {
1214 *opc_ptr = INDEX_op_nop;
1215 } else {
1216 *opc_ptr = INDEX_op_nopn;
1217 args[0] = nb_args;
1218 args[nb_args - 1] = nb_args;
1222 /* liveness analysis: end of function: globals are live, temps are
1223 dead. */
1224 /* XXX: at this stage, not used as there would be little gains because
1225 most TBs end with a conditional jump. */
1226 static inline void tcg_la_func_end(TCGContext *s, uint8_t *dead_temps)
1228 memset(dead_temps, 0, s->nb_globals);
1229 memset(dead_temps + s->nb_globals, 1, s->nb_temps - s->nb_globals);
1232 /* liveness analysis: end of basic block: globals are live, temps are
1233 dead, local temps are live. */
1234 static inline void tcg_la_bb_end(TCGContext *s, uint8_t *dead_temps)
1236 int i;
1237 TCGTemp *ts;
1239 memset(dead_temps, 0, s->nb_globals);
1240 ts = &s->temps[s->nb_globals];
1241 for(i = s->nb_globals; i < s->nb_temps; i++) {
1242 if (ts->temp_local)
1243 dead_temps[i] = 0;
1244 else
1245 dead_temps[i] = 1;
1246 ts++;
1250 /* Liveness analysis : update the opc_dead_iargs array to tell if a
1251 given input arguments is dead. Instructions updating dead
1252 temporaries are removed. */
1253 static void tcg_liveness_analysis(TCGContext *s)
1255 int i, op_index, op, nb_args, nb_iargs, nb_oargs, arg, nb_ops;
1256 TCGArg *args;
1257 const TCGOpDef *def;
1258 uint8_t *dead_temps;
1259 unsigned int dead_iargs;
1261 gen_opc_ptr++; /* skip end */
1263 nb_ops = gen_opc_ptr - gen_opc_buf;
1265 /* XXX: make it really dynamic */
1266 s->op_dead_iargs = tcg_malloc(OPC_BUF_SIZE * sizeof(uint16_t));
1268 dead_temps = tcg_malloc(s->nb_temps);
1269 memset(dead_temps, 1, s->nb_temps);
1271 args = gen_opparam_ptr;
1272 op_index = nb_ops - 1;
1273 while (op_index >= 0) {
1274 op = gen_opc_buf[op_index];
1275 def = &tcg_op_defs[op];
1276 switch(op) {
1277 case INDEX_op_call:
1279 int call_flags;
1281 nb_args = args[-1];
1282 args -= nb_args;
1283 nb_iargs = args[0] & 0xffff;
1284 nb_oargs = args[0] >> 16;
1285 args++;
1286 call_flags = args[nb_oargs + nb_iargs];
1288 /* pure functions can be removed if their result is not
1289 used */
1290 if (call_flags & TCG_CALL_PURE) {
1291 for(i = 0; i < nb_oargs; i++) {
1292 arg = args[i];
1293 if (!dead_temps[arg])
1294 goto do_not_remove_call;
1296 tcg_set_nop(s, gen_opc_buf + op_index,
1297 args - 1, nb_args);
1298 } else {
1299 do_not_remove_call:
1301 /* output args are dead */
1302 for(i = 0; i < nb_oargs; i++) {
1303 arg = args[i];
1304 dead_temps[arg] = 1;
1307 if (!(call_flags & TCG_CALL_CONST)) {
1308 /* globals are live (they may be used by the call) */
1309 memset(dead_temps, 0, s->nb_globals);
1312 /* input args are live */
1313 dead_iargs = 0;
1314 for(i = 0; i < nb_iargs; i++) {
1315 arg = args[i + nb_oargs];
1316 if (arg != TCG_CALL_DUMMY_ARG) {
1317 if (dead_temps[arg]) {
1318 dead_iargs |= (1 << i);
1320 dead_temps[arg] = 0;
1323 s->op_dead_iargs[op_index] = dead_iargs;
1325 args--;
1327 break;
1328 case INDEX_op_set_label:
1329 args--;
1330 /* mark end of basic block */
1331 tcg_la_bb_end(s, dead_temps);
1332 break;
1333 case INDEX_op_debug_insn_start:
1334 args -= def->nb_args;
1335 break;
1336 case INDEX_op_nopn:
1337 nb_args = args[-1];
1338 args -= nb_args;
1339 break;
1340 case INDEX_op_discard:
1341 args--;
1342 /* mark the temporary as dead */
1343 dead_temps[args[0]] = 1;
1344 break;
1345 case INDEX_op_end:
1346 break;
1347 /* XXX: optimize by hardcoding common cases (e.g. triadic ops) */
1348 default:
1349 args -= def->nb_args;
1350 nb_iargs = def->nb_iargs;
1351 nb_oargs = def->nb_oargs;
1353 /* Test if the operation can be removed because all
1354 its outputs are dead. We assume that nb_oargs == 0
1355 implies side effects */
1356 if (!(def->flags & TCG_OPF_SIDE_EFFECTS) && nb_oargs != 0) {
1357 for(i = 0; i < nb_oargs; i++) {
1358 arg = args[i];
1359 if (!dead_temps[arg])
1360 goto do_not_remove;
1362 tcg_set_nop(s, gen_opc_buf + op_index, args, def->nb_args);
1363 #ifdef CONFIG_PROFILER
1364 s->del_op_count++;
1365 #endif
1366 } else {
1367 do_not_remove:
1369 /* output args are dead */
1370 for(i = 0; i < nb_oargs; i++) {
1371 arg = args[i];
1372 dead_temps[arg] = 1;
1375 /* if end of basic block, update */
1376 if (def->flags & TCG_OPF_BB_END) {
1377 tcg_la_bb_end(s, dead_temps);
1378 } else if (def->flags & TCG_OPF_CALL_CLOBBER) {
1379 /* globals are live */
1380 memset(dead_temps, 0, s->nb_globals);
1383 /* input args are live */
1384 dead_iargs = 0;
1385 for(i = 0; i < nb_iargs; i++) {
1386 arg = args[i + nb_oargs];
1387 if (dead_temps[arg]) {
1388 dead_iargs |= (1 << i);
1390 dead_temps[arg] = 0;
1392 s->op_dead_iargs[op_index] = dead_iargs;
1394 break;
1396 op_index--;
1399 if (args != gen_opparam_buf)
1400 tcg_abort();
1402 #else
1403 /* dummy liveness analysis */
1404 void tcg_liveness_analysis(TCGContext *s)
1406 int nb_ops;
1407 nb_ops = gen_opc_ptr - gen_opc_buf;
1409 s->op_dead_iargs = tcg_malloc(nb_ops * sizeof(uint16_t));
1410 memset(s->op_dead_iargs, 0, nb_ops * sizeof(uint16_t));
1412 #endif
1414 #ifndef NDEBUG
1415 static void dump_regs(TCGContext *s)
1417 TCGTemp *ts;
1418 int i;
1419 char buf[64];
1421 for(i = 0; i < s->nb_temps; i++) {
1422 ts = &s->temps[i];
1423 printf(" %10s: ", tcg_get_arg_str_idx(s, buf, sizeof(buf), i));
1424 switch(ts->val_type) {
1425 case TEMP_VAL_REG:
1426 printf("%s", tcg_target_reg_names[ts->reg]);
1427 break;
1428 case TEMP_VAL_MEM:
1429 printf("%d(%s)", (int)ts->mem_offset, tcg_target_reg_names[ts->mem_reg]);
1430 break;
1431 case TEMP_VAL_CONST:
1432 printf("$0x%" TCG_PRIlx, ts->val);
1433 break;
1434 case TEMP_VAL_DEAD:
1435 printf("D");
1436 break;
1437 default:
1438 printf("???");
1439 break;
1441 printf("\n");
1444 for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
1445 if (s->reg_to_temp[i] >= 0) {
1446 printf("%s: %s\n",
1447 tcg_target_reg_names[i],
1448 tcg_get_arg_str_idx(s, buf, sizeof(buf), s->reg_to_temp[i]));
1453 static void check_regs(TCGContext *s)
1455 int reg, k;
1456 TCGTemp *ts;
1457 char buf[64];
1459 for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1460 k = s->reg_to_temp[reg];
1461 if (k >= 0) {
1462 ts = &s->temps[k];
1463 if (ts->val_type != TEMP_VAL_REG ||
1464 ts->reg != reg) {
1465 printf("Inconsistency for register %s:\n",
1466 tcg_target_reg_names[reg]);
1467 goto fail;
1471 for(k = 0; k < s->nb_temps; k++) {
1472 ts = &s->temps[k];
1473 if (ts->val_type == TEMP_VAL_REG &&
1474 !ts->fixed_reg &&
1475 s->reg_to_temp[ts->reg] != k) {
1476 printf("Inconsistency for temp %s:\n",
1477 tcg_get_arg_str_idx(s, buf, sizeof(buf), k));
1478 fail:
1479 printf("reg state:\n");
1480 dump_regs(s);
1481 tcg_abort();
1485 #endif
1487 static void temp_allocate_frame(TCGContext *s, int temp)
1489 TCGTemp *ts;
1490 ts = &s->temps[temp];
1491 s->current_frame_offset = (s->current_frame_offset + sizeof(tcg_target_long) - 1) & ~(sizeof(tcg_target_long) - 1);
1492 if (s->current_frame_offset + sizeof(tcg_target_long) > s->frame_end)
1493 tcg_abort();
1494 ts->mem_offset = s->current_frame_offset;
1495 ts->mem_reg = s->frame_reg;
1496 ts->mem_allocated = 1;
1497 s->current_frame_offset += sizeof(tcg_target_long);
1500 /* free register 'reg' by spilling the corresponding temporary if necessary */
1501 static void tcg_reg_free(TCGContext *s, int reg)
1503 TCGTemp *ts;
1504 int temp;
1506 temp = s->reg_to_temp[reg];
1507 if (temp != -1) {
1508 ts = &s->temps[temp];
1509 assert(ts->val_type == TEMP_VAL_REG);
1510 if (!ts->mem_coherent) {
1511 if (!ts->mem_allocated)
1512 temp_allocate_frame(s, temp);
1513 tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1515 ts->val_type = TEMP_VAL_MEM;
1516 s->reg_to_temp[reg] = -1;
1520 /* Allocate a register belonging to reg1 & ~reg2 */
1521 static int tcg_reg_alloc(TCGContext *s, TCGRegSet reg1, TCGRegSet reg2)
1523 int i, reg;
1524 TCGRegSet reg_ct;
1526 tcg_regset_andnot(reg_ct, reg1, reg2);
1528 /* first try free registers */
1529 for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1530 reg = tcg_target_reg_alloc_order[i];
1531 if (tcg_regset_test_reg(reg_ct, reg) && s->reg_to_temp[reg] == -1)
1532 return reg;
1535 /* XXX: do better spill choice */
1536 for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1537 reg = tcg_target_reg_alloc_order[i];
1538 if (tcg_regset_test_reg(reg_ct, reg)) {
1539 tcg_reg_free(s, reg);
1540 return reg;
1544 tcg_abort();
1547 /* save a temporary to memory. 'allocated_regs' is used in case a
1548 temporary registers needs to be allocated to store a constant. */
1549 static void temp_save(TCGContext *s, int temp, TCGRegSet allocated_regs)
1551 TCGTemp *ts;
1552 int reg;
1554 ts = &s->temps[temp];
1555 if (!ts->fixed_reg) {
1556 switch(ts->val_type) {
1557 case TEMP_VAL_REG:
1558 tcg_reg_free(s, ts->reg);
1559 break;
1560 case TEMP_VAL_DEAD:
1561 ts->val_type = TEMP_VAL_MEM;
1562 break;
1563 case TEMP_VAL_CONST:
1564 reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type],
1565 allocated_regs);
1566 if (!ts->mem_allocated)
1567 temp_allocate_frame(s, temp);
1568 tcg_out_movi(s, ts->type, reg, ts->val);
1569 tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1570 ts->val_type = TEMP_VAL_MEM;
1571 break;
1572 case TEMP_VAL_MEM:
1573 break;
1574 default:
1575 tcg_abort();
1580 /* save globals to their cannonical location and assume they can be
1581 modified be the following code. 'allocated_regs' is used in case a
1582 temporary registers needs to be allocated to store a constant. */
1583 static void save_globals(TCGContext *s, TCGRegSet allocated_regs)
1585 int i;
1587 for(i = 0; i < s->nb_globals; i++) {
1588 temp_save(s, i, allocated_regs);
1592 /* at the end of a basic block, we assume all temporaries are dead and
1593 all globals are stored at their canonical location. */
1594 static void tcg_reg_alloc_bb_end(TCGContext *s, TCGRegSet allocated_regs)
1596 TCGTemp *ts;
1597 int i;
1599 for(i = s->nb_globals; i < s->nb_temps; i++) {
1600 ts = &s->temps[i];
1601 if (ts->temp_local) {
1602 temp_save(s, i, allocated_regs);
1603 } else {
1604 if (ts->val_type == TEMP_VAL_REG) {
1605 s->reg_to_temp[ts->reg] = -1;
1607 ts->val_type = TEMP_VAL_DEAD;
1611 save_globals(s, allocated_regs);
1614 #define IS_DEAD_IARG(n) ((dead_iargs >> (n)) & 1)
1616 static void tcg_reg_alloc_movi(TCGContext *s, const TCGArg *args)
1618 TCGTemp *ots;
1619 tcg_target_ulong val;
1621 ots = &s->temps[args[0]];
1622 val = args[1];
1624 if (ots->fixed_reg) {
1625 /* for fixed registers, we do not do any constant
1626 propagation */
1627 tcg_out_movi(s, ots->type, ots->reg, val);
1628 } else {
1629 /* The movi is not explicitly generated here */
1630 if (ots->val_type == TEMP_VAL_REG)
1631 s->reg_to_temp[ots->reg] = -1;
1632 ots->val_type = TEMP_VAL_CONST;
1633 ots->val = val;
1637 static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
1638 const TCGArg *args,
1639 unsigned int dead_iargs)
1641 TCGTemp *ts, *ots;
1642 int reg;
1643 const TCGArgConstraint *arg_ct;
1645 ots = &s->temps[args[0]];
1646 ts = &s->temps[args[1]];
1647 arg_ct = &def->args_ct[0];
1649 /* XXX: always mark arg dead if IS_DEAD_IARG(0) */
1650 if (ts->val_type == TEMP_VAL_REG) {
1651 if (IS_DEAD_IARG(0) && !ts->fixed_reg && !ots->fixed_reg) {
1652 /* the mov can be suppressed */
1653 if (ots->val_type == TEMP_VAL_REG)
1654 s->reg_to_temp[ots->reg] = -1;
1655 reg = ts->reg;
1656 s->reg_to_temp[reg] = -1;
1657 ts->val_type = TEMP_VAL_DEAD;
1658 } else {
1659 if (ots->val_type == TEMP_VAL_REG) {
1660 reg = ots->reg;
1661 } else {
1662 reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1664 if (ts->reg != reg) {
1665 tcg_out_mov(s, reg, ts->reg);
1668 } else if (ts->val_type == TEMP_VAL_MEM) {
1669 if (ots->val_type == TEMP_VAL_REG) {
1670 reg = ots->reg;
1671 } else {
1672 reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1674 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1675 } else if (ts->val_type == TEMP_VAL_CONST) {
1676 if (ots->fixed_reg) {
1677 reg = ots->reg;
1678 tcg_out_movi(s, ots->type, reg, ts->val);
1679 } else {
1680 /* propagate constant */
1681 if (ots->val_type == TEMP_VAL_REG)
1682 s->reg_to_temp[ots->reg] = -1;
1683 ots->val_type = TEMP_VAL_CONST;
1684 ots->val = ts->val;
1685 return;
1687 } else {
1688 tcg_abort();
1690 s->reg_to_temp[reg] = args[0];
1691 ots->reg = reg;
1692 ots->val_type = TEMP_VAL_REG;
1693 ots->mem_coherent = 0;
1696 static void tcg_reg_alloc_op(TCGContext *s,
1697 const TCGOpDef *def, int opc,
1698 const TCGArg *args,
1699 unsigned int dead_iargs)
1701 TCGRegSet allocated_regs;
1702 int i, k, nb_iargs, nb_oargs, reg;
1703 TCGArg arg;
1704 const TCGArgConstraint *arg_ct;
1705 TCGTemp *ts;
1706 TCGArg new_args[TCG_MAX_OP_ARGS];
1707 int const_args[TCG_MAX_OP_ARGS];
1709 nb_oargs = def->nb_oargs;
1710 nb_iargs = def->nb_iargs;
1712 /* copy constants */
1713 memcpy(new_args + nb_oargs + nb_iargs,
1714 args + nb_oargs + nb_iargs,
1715 sizeof(TCGArg) * def->nb_cargs);
1717 /* satisfy input constraints */
1718 tcg_regset_set(allocated_regs, s->reserved_regs);
1719 for(k = 0; k < nb_iargs; k++) {
1720 i = def->sorted_args[nb_oargs + k];
1721 arg = args[i];
1722 arg_ct = &def->args_ct[i];
1723 ts = &s->temps[arg];
1724 if (ts->val_type == TEMP_VAL_MEM) {
1725 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1726 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1727 ts->val_type = TEMP_VAL_REG;
1728 ts->reg = reg;
1729 ts->mem_coherent = 1;
1730 s->reg_to_temp[reg] = arg;
1731 } else if (ts->val_type == TEMP_VAL_CONST) {
1732 if (tcg_target_const_match(ts->val, arg_ct)) {
1733 /* constant is OK for instruction */
1734 const_args[i] = 1;
1735 new_args[i] = ts->val;
1736 goto iarg_end;
1737 } else {
1738 /* need to move to a register */
1739 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1740 tcg_out_movi(s, ts->type, reg, ts->val);
1741 ts->val_type = TEMP_VAL_REG;
1742 ts->reg = reg;
1743 ts->mem_coherent = 0;
1744 s->reg_to_temp[reg] = arg;
1747 assert(ts->val_type == TEMP_VAL_REG);
1748 if (arg_ct->ct & TCG_CT_IALIAS) {
1749 if (ts->fixed_reg) {
1750 /* if fixed register, we must allocate a new register
1751 if the alias is not the same register */
1752 if (arg != args[arg_ct->alias_index])
1753 goto allocate_in_reg;
1754 } else {
1755 /* if the input is aliased to an output and if it is
1756 not dead after the instruction, we must allocate
1757 a new register and move it */
1758 if (!IS_DEAD_IARG(i - nb_oargs))
1759 goto allocate_in_reg;
1762 reg = ts->reg;
1763 if (tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1764 /* nothing to do : the constraint is satisfied */
1765 } else {
1766 allocate_in_reg:
1767 /* allocate a new register matching the constraint
1768 and move the temporary register into it */
1769 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1770 tcg_out_mov(s, reg, ts->reg);
1772 new_args[i] = reg;
1773 const_args[i] = 0;
1774 tcg_regset_set_reg(allocated_regs, reg);
1775 iarg_end: ;
1778 if (def->flags & TCG_OPF_BB_END) {
1779 tcg_reg_alloc_bb_end(s, allocated_regs);
1780 } else {
1781 /* mark dead temporaries and free the associated registers */
1782 for(i = 0; i < nb_iargs; i++) {
1783 arg = args[nb_oargs + i];
1784 if (IS_DEAD_IARG(i)) {
1785 ts = &s->temps[arg];
1786 if (!ts->fixed_reg) {
1787 if (ts->val_type == TEMP_VAL_REG)
1788 s->reg_to_temp[ts->reg] = -1;
1789 ts->val_type = TEMP_VAL_DEAD;
1794 if (def->flags & TCG_OPF_CALL_CLOBBER) {
1795 /* XXX: permit generic clobber register list ? */
1796 for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1797 if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
1798 tcg_reg_free(s, reg);
1801 /* XXX: for load/store we could do that only for the slow path
1802 (i.e. when a memory callback is called) */
1804 /* store globals and free associated registers (we assume the insn
1805 can modify any global. */
1806 save_globals(s, allocated_regs);
1809 /* satisfy the output constraints */
1810 tcg_regset_set(allocated_regs, s->reserved_regs);
1811 for(k = 0; k < nb_oargs; k++) {
1812 i = def->sorted_args[k];
1813 arg = args[i];
1814 arg_ct = &def->args_ct[i];
1815 ts = &s->temps[arg];
1816 if (arg_ct->ct & TCG_CT_ALIAS) {
1817 reg = new_args[arg_ct->alias_index];
1818 } else {
1819 /* if fixed register, we try to use it */
1820 reg = ts->reg;
1821 if (ts->fixed_reg &&
1822 tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1823 goto oarg_end;
1825 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1827 tcg_regset_set_reg(allocated_regs, reg);
1828 /* if a fixed register is used, then a move will be done afterwards */
1829 if (!ts->fixed_reg) {
1830 if (ts->val_type == TEMP_VAL_REG)
1831 s->reg_to_temp[ts->reg] = -1;
1832 ts->val_type = TEMP_VAL_REG;
1833 ts->reg = reg;
1834 /* temp value is modified, so the value kept in memory is
1835 potentially not the same */
1836 ts->mem_coherent = 0;
1837 s->reg_to_temp[reg] = arg;
1839 oarg_end:
1840 new_args[i] = reg;
1844 /* emit instruction */
1845 tcg_out_op(s, opc, new_args, const_args);
1847 /* move the outputs in the correct register if needed */
1848 for(i = 0; i < nb_oargs; i++) {
1849 ts = &s->temps[args[i]];
1850 reg = new_args[i];
1851 if (ts->fixed_reg && ts->reg != reg) {
1852 tcg_out_mov(s, ts->reg, reg);
1857 #ifdef TCG_TARGET_STACK_GROWSUP
1858 #define STACK_DIR(x) (-(x))
1859 #else
1860 #define STACK_DIR(x) (x)
1861 #endif
1863 static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
1864 int opc, const TCGArg *args,
1865 unsigned int dead_iargs)
1867 int nb_iargs, nb_oargs, flags, nb_regs, i, reg, nb_params;
1868 TCGArg arg, func_arg;
1869 TCGTemp *ts;
1870 tcg_target_long stack_offset, call_stack_size, func_addr;
1871 int const_func_arg, allocate_args;
1872 TCGRegSet allocated_regs;
1873 const TCGArgConstraint *arg_ct;
1875 arg = *args++;
1877 nb_oargs = arg >> 16;
1878 nb_iargs = arg & 0xffff;
1879 nb_params = nb_iargs - 1;
1881 flags = args[nb_oargs + nb_iargs];
1883 nb_regs = tcg_target_get_call_iarg_regs_count(flags);
1884 if (nb_regs > nb_params)
1885 nb_regs = nb_params;
1887 /* assign stack slots first */
1888 /* XXX: preallocate call stack */
1889 call_stack_size = (nb_params - nb_regs) * sizeof(tcg_target_long);
1890 call_stack_size = (call_stack_size + TCG_TARGET_STACK_ALIGN - 1) &
1891 ~(TCG_TARGET_STACK_ALIGN - 1);
1892 allocate_args = (call_stack_size > TCG_STATIC_CALL_ARGS_SIZE);
1893 if (allocate_args) {
1894 tcg_out_addi(s, TCG_REG_CALL_STACK, -STACK_DIR(call_stack_size));
1897 stack_offset = TCG_TARGET_CALL_STACK_OFFSET;
1898 for(i = nb_regs; i < nb_params; i++) {
1899 arg = args[nb_oargs + i];
1900 #ifdef TCG_TARGET_STACK_GROWSUP
1901 stack_offset -= sizeof(tcg_target_long);
1902 #endif
1903 if (arg != TCG_CALL_DUMMY_ARG) {
1904 ts = &s->temps[arg];
1905 if (ts->val_type == TEMP_VAL_REG) {
1906 tcg_out_st(s, ts->type, ts->reg, TCG_REG_CALL_STACK, stack_offset);
1907 } else if (ts->val_type == TEMP_VAL_MEM) {
1908 reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type],
1909 s->reserved_regs);
1910 /* XXX: not correct if reading values from the stack */
1911 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1912 tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
1913 } else if (ts->val_type == TEMP_VAL_CONST) {
1914 reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type],
1915 s->reserved_regs);
1916 /* XXX: sign extend may be needed on some targets */
1917 tcg_out_movi(s, ts->type, reg, ts->val);
1918 tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
1919 } else {
1920 tcg_abort();
1923 #ifndef TCG_TARGET_STACK_GROWSUP
1924 stack_offset += sizeof(tcg_target_long);
1925 #endif
1928 /* assign input registers */
1929 tcg_regset_set(allocated_regs, s->reserved_regs);
1930 for(i = 0; i < nb_regs; i++) {
1931 arg = args[nb_oargs + i];
1932 if (arg != TCG_CALL_DUMMY_ARG) {
1933 ts = &s->temps[arg];
1934 reg = tcg_target_call_iarg_regs[i];
1935 tcg_reg_free(s, reg);
1936 if (ts->val_type == TEMP_VAL_REG) {
1937 if (ts->reg != reg) {
1938 tcg_out_mov(s, reg, ts->reg);
1940 } else if (ts->val_type == TEMP_VAL_MEM) {
1941 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1942 } else if (ts->val_type == TEMP_VAL_CONST) {
1943 /* XXX: sign extend ? */
1944 tcg_out_movi(s, ts->type, reg, ts->val);
1945 } else {
1946 tcg_abort();
1948 tcg_regset_set_reg(allocated_regs, reg);
1952 /* assign function address */
1953 func_arg = args[nb_oargs + nb_iargs - 1];
1954 arg_ct = &def->args_ct[0];
1955 ts = &s->temps[func_arg];
1956 func_addr = ts->val;
1957 const_func_arg = 0;
1958 if (ts->val_type == TEMP_VAL_MEM) {
1959 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1960 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1961 func_arg = reg;
1962 tcg_regset_set_reg(allocated_regs, reg);
1963 } else if (ts->val_type == TEMP_VAL_REG) {
1964 reg = ts->reg;
1965 if (!tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1966 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1967 tcg_out_mov(s, reg, ts->reg);
1969 func_arg = reg;
1970 tcg_regset_set_reg(allocated_regs, reg);
1971 } else if (ts->val_type == TEMP_VAL_CONST) {
1972 if (tcg_target_const_match(func_addr, arg_ct)) {
1973 const_func_arg = 1;
1974 func_arg = func_addr;
1975 } else {
1976 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1977 tcg_out_movi(s, ts->type, reg, func_addr);
1978 func_arg = reg;
1979 tcg_regset_set_reg(allocated_regs, reg);
1981 } else {
1982 tcg_abort();
1986 /* mark dead temporaries and free the associated registers */
1987 for(i = 0; i < nb_iargs; i++) {
1988 arg = args[nb_oargs + i];
1989 if (IS_DEAD_IARG(i)) {
1990 ts = &s->temps[arg];
1991 if (!ts->fixed_reg) {
1992 if (ts->val_type == TEMP_VAL_REG)
1993 s->reg_to_temp[ts->reg] = -1;
1994 ts->val_type = TEMP_VAL_DEAD;
1999 /* clobber call registers */
2000 for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
2001 if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
2002 tcg_reg_free(s, reg);
2006 /* store globals and free associated registers (we assume the call
2007 can modify any global. */
2008 if (!(flags & TCG_CALL_CONST)) {
2009 save_globals(s, allocated_regs);
2012 tcg_out_op(s, opc, &func_arg, &const_func_arg);
2014 if (allocate_args) {
2015 tcg_out_addi(s, TCG_REG_CALL_STACK, STACK_DIR(call_stack_size));
2018 /* assign output registers and emit moves if needed */
2019 for(i = 0; i < nb_oargs; i++) {
2020 arg = args[i];
2021 ts = &s->temps[arg];
2022 reg = tcg_target_call_oarg_regs[i];
2023 assert(s->reg_to_temp[reg] == -1);
2024 if (ts->fixed_reg) {
2025 if (ts->reg != reg) {
2026 tcg_out_mov(s, ts->reg, reg);
2028 } else {
2029 if (ts->val_type == TEMP_VAL_REG)
2030 s->reg_to_temp[ts->reg] = -1;
2031 ts->val_type = TEMP_VAL_REG;
2032 ts->reg = reg;
2033 ts->mem_coherent = 0;
2034 s->reg_to_temp[reg] = arg;
2038 return nb_iargs + nb_oargs + def->nb_cargs + 1;
2041 #ifdef CONFIG_PROFILER
2043 static int64_t tcg_table_op_count[NB_OPS];
2045 static void dump_op_count(void)
2047 int i;
2048 FILE *f;
2049 f = fopen("/tmp/op.log", "w");
2050 for(i = INDEX_op_end; i < NB_OPS; i++) {
2051 fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name, tcg_table_op_count[i]);
2053 fclose(f);
2055 #endif
2058 static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
2059 long search_pc)
2061 int opc, op_index;
2062 const TCGOpDef *def;
2063 unsigned int dead_iargs;
2064 const TCGArg *args;
2066 #ifdef DEBUG_DISAS
2067 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
2068 qemu_log("OP:\n");
2069 tcg_dump_ops(s, logfile);
2070 qemu_log("\n");
2072 #endif
2074 #ifdef CONFIG_PROFILER
2075 s->const_time -= profile_getclock();
2076 #endif
2077 tcg_const_analysis(s);
2078 #ifdef CONFIG_PROFILER
2079 s->const_time += profile_getclock();
2080 #endif
2082 #ifdef CONFIG_PROFILER
2083 s->la_time -= profile_getclock();
2084 #endif
2085 tcg_liveness_analysis(s);
2086 #ifdef CONFIG_PROFILER
2087 s->la_time += profile_getclock();
2088 #endif
2090 #ifdef DEBUG_DISAS
2091 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_OPT))) {
2092 qemu_log("OP after la:\n");
2093 tcg_dump_ops(s, logfile);
2094 qemu_log("\n");
2096 #endif
2098 tcg_reg_alloc_start(s);
2100 s->code_buf = gen_code_buf;
2101 s->code_ptr = gen_code_buf;
2103 args = gen_opparam_buf;
2104 op_index = 0;
2106 for(;;) {
2107 opc = gen_opc_buf[op_index];
2108 #ifdef CONFIG_PROFILER
2109 tcg_table_op_count[opc]++;
2110 #endif
2111 def = &tcg_op_defs[opc];
2112 #if 0
2113 printf("%s: %d %d %d\n", def->name,
2114 def->nb_oargs, def->nb_iargs, def->nb_cargs);
2115 // dump_regs(s);
2116 #endif
2117 switch(opc) {
2118 case INDEX_op_mov_i32:
2119 #if TCG_TARGET_REG_BITS == 64
2120 case INDEX_op_mov_i64:
2121 #endif
2122 dead_iargs = s->op_dead_iargs[op_index];
2123 tcg_reg_alloc_mov(s, def, args, dead_iargs);
2124 break;
2125 case INDEX_op_movi_i32:
2126 #if TCG_TARGET_REG_BITS == 64
2127 case INDEX_op_movi_i64:
2128 #endif
2129 tcg_reg_alloc_movi(s, args);
2130 break;
2131 case INDEX_op_debug_insn_start:
2132 /* debug instruction */
2133 break;
2134 case INDEX_op_nop:
2135 case INDEX_op_nop1:
2136 case INDEX_op_nop2:
2137 case INDEX_op_nop3:
2138 break;
2139 case INDEX_op_nopn:
2140 args += args[0];
2141 goto next;
2142 case INDEX_op_discard:
2144 TCGTemp *ts;
2145 ts = &s->temps[args[0]];
2146 /* mark the temporary as dead */
2147 if (!ts->fixed_reg) {
2148 if (ts->val_type == TEMP_VAL_REG)
2149 s->reg_to_temp[ts->reg] = -1;
2150 ts->val_type = TEMP_VAL_DEAD;
2153 break;
2154 case INDEX_op_set_label:
2155 tcg_reg_alloc_bb_end(s, s->reserved_regs);
2156 tcg_out_label(s, args[0], (intptr_t)s->code_ptr);
2157 break;
2158 case INDEX_op_call:
2159 dead_iargs = s->op_dead_iargs[op_index];
2160 args += tcg_reg_alloc_call(s, def, opc, args, dead_iargs);
2161 goto next;
2162 case INDEX_op_end:
2163 goto the_end;
2164 default:
2165 /* Note: in order to speed up the code, it would be much
2166 faster to have specialized register allocator functions for
2167 some common argument patterns */
2168 dead_iargs = s->op_dead_iargs[op_index];
2169 tcg_reg_alloc_op(s, def, opc, args, dead_iargs);
2170 break;
2172 args += def->nb_args;
2173 next:
2174 if (search_pc >= 0 && search_pc < s->code_ptr - gen_code_buf) {
2175 return op_index;
2177 op_index++;
2178 #ifndef NDEBUG
2179 check_regs(s);
2180 #endif
2182 the_end:
2183 return -1;
2186 int tcg_gen_code(TCGContext *s, uint8_t *gen_code_buf)
2188 #ifdef CONFIG_PROFILER
2190 int n;
2191 n = (gen_opc_ptr - gen_opc_buf);
2192 s->op_count += n;
2193 if (n > s->op_count_max)
2194 s->op_count_max = n;
2196 s->temp_count += s->nb_temps;
2197 if (s->nb_temps > s->temp_count_max)
2198 s->temp_count_max = s->nb_temps;
2200 #endif
2202 tcg_gen_code_common(s, gen_code_buf, -1);
2204 /* flush instruction cache */
2205 flush_icache_range((uintptr_t)gen_code_buf,
2206 (uintptr_t)s->code_ptr);
2207 return s->code_ptr - gen_code_buf;
2210 /* Return the index of the micro operation such as the pc after is <
2211 offset bytes from the start of the TB. The contents of gen_code_buf must
2212 not be changed, though writing the same values is ok.
2213 Return -1 if not found. */
2214 int tcg_gen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, long offset)
2216 return tcg_gen_code_common(s, gen_code_buf, offset);
2219 #ifdef CONFIG_PROFILER
2220 void tcg_dump_info(FILE *f,
2221 int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
2223 TCGContext *s = &tcg_ctx;
2224 int64_t tot;
2226 tot = s->interm_time + s->code_time;
2227 cpu_fprintf(f, "JIT cycles %" PRId64 " (%0.3f s at 2.4 GHz)\n",
2228 tot, tot / 2.4e9);
2229 cpu_fprintf(f, "translated TBs %" PRId64 " (aborted=%" PRId64 " %0.1f%%)\n",
2230 s->tb_count,
2231 s->tb_count1 - s->tb_count,
2232 s->tb_count1 ? (double)(s->tb_count1 - s->tb_count) / s->tb_count1 * 100.0 : 0);
2233 cpu_fprintf(f, "avg ops/TB %0.1f max=%d\n",
2234 s->tb_count ? (double)s->op_count / s->tb_count : 0, s->op_count_max);
2235 cpu_fprintf(f, "deleted ops/TB %0.2f\n",
2236 s->tb_count ?
2237 (double)s->del_op_count / s->tb_count : 0);
2238 cpu_fprintf(f, "avg temps/TB %0.2f max=%d\n",
2239 s->tb_count ?
2240 (double)s->temp_count / s->tb_count : 0,
2241 s->temp_count_max);
2243 cpu_fprintf(f, "cycles/op %0.1f\n",
2244 s->op_count ? (double)tot / s->op_count : 0);
2245 cpu_fprintf(f, "cycles/in byte %0.1f\n",
2246 s->code_in_len ? (double)tot / s->code_in_len : 0);
2247 cpu_fprintf(f, "cycles/out byte %0.1f\n",
2248 s->code_out_len ? (double)tot / s->code_out_len : 0);
2249 if (tot == 0)
2250 tot = 1;
2251 cpu_fprintf(f, " gen_interm time %0.1f%%\n",
2252 (double)s->interm_time / tot * 100.0);
2253 cpu_fprintf(f, " gen_code time %0.1f%%\n",
2254 (double)s->code_time / tot * 100.0);
2255 cpu_fprintf(f, "const/code time %0.1f%%\n",
2256 (double)s->const_time / (s->code_time ? s->code_time : 1) * 100.0);
2257 cpu_fprintf(f, "liveness/code time %0.1f%%\n",
2258 (double)s->la_time / (s->code_time ? s->code_time : 1) * 100.0);
2259 cpu_fprintf(f, "cpu_restore count %" PRId64 "\n",
2260 s->restore_count);
2261 cpu_fprintf(f, " avg cycles %0.1f\n",
2262 s->restore_count ? (double)s->restore_time / s->restore_count : 0);
2264 dump_op_count();
2266 #else
2267 void tcg_dump_info(FILE *f,
2268 int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
2270 cpu_fprintf(f, "[TCG profiler not compiled]\n");
2272 #endif