Allow adjustment of http block device's readahead size, via a new
[qemu/aliguori-queue.git] / tcg / tcg.c
blob299bff6f0372d6074f4a436fcbdec22b1070fdb9
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 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"
50 /* Note: the long term plan is to reduce the dependancies on the QEMU
51 CPU definitions. Currently they are used for qemu_ld/st
52 instructions */
53 #define NO_CPU_IO_DEFS
54 #include "cpu.h"
55 #include "exec-all.h"
57 #include "tcg-op.h"
58 #include "elf.h"
61 static void patch_reloc(uint8_t *code_ptr, int type,
62 tcg_target_long value, tcg_target_long addend);
64 static TCGOpDef tcg_op_defs[] = {
65 #define DEF(s, n, copy_size) { #s, 0, 0, n, n, 0, copy_size },
66 #define DEF2(s, iargs, oargs, cargs, flags) { #s, iargs, oargs, cargs, iargs + oargs + cargs, flags, 0 },
67 #include "tcg-opc.h"
68 #undef DEF
69 #undef DEF2
72 static TCGRegSet tcg_target_available_regs[2];
73 static TCGRegSet tcg_target_call_clobber_regs;
75 /* XXX: move that inside the context */
76 uint16_t *gen_opc_ptr;
77 TCGArg *gen_opparam_ptr;
79 static inline void tcg_out8(TCGContext *s, uint8_t v)
81 *s->code_ptr++ = v;
84 static inline void tcg_out16(TCGContext *s, uint16_t v)
86 *(uint16_t *)s->code_ptr = v;
87 s->code_ptr += 2;
90 static inline void tcg_out32(TCGContext *s, uint32_t v)
92 *(uint32_t *)s->code_ptr = v;
93 s->code_ptr += 4;
96 /* label relocation processing */
98 void tcg_out_reloc(TCGContext *s, uint8_t *code_ptr, int type,
99 int label_index, long addend)
101 TCGLabel *l;
102 TCGRelocation *r;
104 l = &s->labels[label_index];
105 if (l->has_value) {
106 /* FIXME: This may break relocations on RISC targets that
107 modify instruction fields in place. The caller may not have
108 written the initial value. */
109 patch_reloc(code_ptr, type, l->u.value, addend);
110 } else {
111 /* add a new relocation entry */
112 r = tcg_malloc(sizeof(TCGRelocation));
113 r->type = type;
114 r->ptr = code_ptr;
115 r->addend = addend;
116 r->next = l->u.first_reloc;
117 l->u.first_reloc = r;
121 static void tcg_out_label(TCGContext *s, int label_index,
122 tcg_target_long value)
124 TCGLabel *l;
125 TCGRelocation *r;
127 l = &s->labels[label_index];
128 if (l->has_value)
129 tcg_abort();
130 r = l->u.first_reloc;
131 while (r != NULL) {
132 patch_reloc(r->ptr, r->type, value, r->addend);
133 r = r->next;
135 l->has_value = 1;
136 l->u.value = value;
139 int gen_new_label(void)
141 TCGContext *s = &tcg_ctx;
142 int idx;
143 TCGLabel *l;
145 if (s->nb_labels >= TCG_MAX_LABELS)
146 tcg_abort();
147 idx = s->nb_labels++;
148 l = &s->labels[idx];
149 l->has_value = 0;
150 l->u.first_reloc = NULL;
151 return idx;
154 #include "tcg-target.c"
156 /* pool based memory allocation */
157 void *tcg_malloc_internal(TCGContext *s, int size)
159 TCGPool *p;
160 int pool_size;
162 if (size > TCG_POOL_CHUNK_SIZE) {
163 /* big malloc: insert a new pool (XXX: could optimize) */
164 p = qemu_malloc(sizeof(TCGPool) + size);
165 p->size = size;
166 if (s->pool_current)
167 s->pool_current->next = p;
168 else
169 s->pool_first = p;
170 p->next = s->pool_current;
171 } else {
172 p = s->pool_current;
173 if (!p) {
174 p = s->pool_first;
175 if (!p)
176 goto new_pool;
177 } else {
178 if (!p->next) {
179 new_pool:
180 pool_size = TCG_POOL_CHUNK_SIZE;
181 p = qemu_malloc(sizeof(TCGPool) + pool_size);
182 p->size = pool_size;
183 p->next = NULL;
184 if (s->pool_current)
185 s->pool_current->next = p;
186 else
187 s->pool_first = p;
188 } else {
189 p = p->next;
193 s->pool_current = p;
194 s->pool_cur = p->data + size;
195 s->pool_end = p->data + p->size;
196 return p->data;
199 void tcg_pool_reset(TCGContext *s)
201 s->pool_cur = s->pool_end = NULL;
202 s->pool_current = NULL;
205 void tcg_context_init(TCGContext *s)
207 int op, total_args, n;
208 TCGOpDef *def;
209 TCGArgConstraint *args_ct;
210 int *sorted_args;
212 memset(s, 0, sizeof(*s));
213 s->temps = s->static_temps;
214 s->nb_globals = 0;
216 /* Count total number of arguments and allocate the corresponding
217 space */
218 total_args = 0;
219 for(op = 0; op < NB_OPS; op++) {
220 def = &tcg_op_defs[op];
221 n = def->nb_iargs + def->nb_oargs;
222 total_args += n;
225 args_ct = qemu_malloc(sizeof(TCGArgConstraint) * total_args);
226 sorted_args = qemu_malloc(sizeof(int) * total_args);
228 for(op = 0; op < NB_OPS; op++) {
229 def = &tcg_op_defs[op];
230 def->args_ct = args_ct;
231 def->sorted_args = sorted_args;
232 n = def->nb_iargs + def->nb_oargs;
233 sorted_args += n;
234 args_ct += n;
237 tcg_target_init(s);
239 /* init global prologue and epilogue */
240 s->code_buf = code_gen_prologue;
241 s->code_ptr = s->code_buf;
242 tcg_target_qemu_prologue(s);
243 flush_icache_range((unsigned long)s->code_buf,
244 (unsigned long)s->code_ptr);
247 void tcg_set_frame(TCGContext *s, int reg,
248 tcg_target_long start, tcg_target_long size)
250 s->frame_start = start;
251 s->frame_end = start + size;
252 s->frame_reg = reg;
255 void tcg_func_start(TCGContext *s)
257 int i;
258 tcg_pool_reset(s);
259 s->nb_temps = s->nb_globals;
260 for(i = 0; i < (TCG_TYPE_COUNT * 2); i++)
261 s->first_free_temp[i] = -1;
262 s->labels = tcg_malloc(sizeof(TCGLabel) * TCG_MAX_LABELS);
263 s->nb_labels = 0;
264 s->current_frame_offset = s->frame_start;
266 gen_opc_ptr = gen_opc_buf;
267 gen_opparam_ptr = gen_opparam_buf;
270 static inline void tcg_temp_alloc(TCGContext *s, int n)
272 if (n > TCG_MAX_TEMPS)
273 tcg_abort();
276 static inline int tcg_global_reg_new_internal(TCGType type, int reg,
277 const char *name)
279 TCGContext *s = &tcg_ctx;
280 TCGTemp *ts;
281 int idx;
283 #if TCG_TARGET_REG_BITS == 32
284 if (type != TCG_TYPE_I32)
285 tcg_abort();
286 #endif
287 if (tcg_regset_test_reg(s->reserved_regs, reg))
288 tcg_abort();
289 idx = s->nb_globals;
290 tcg_temp_alloc(s, s->nb_globals + 1);
291 ts = &s->temps[s->nb_globals];
292 ts->base_type = type;
293 ts->type = type;
294 ts->fixed_reg = 1;
295 ts->reg = reg;
296 ts->name = name;
297 s->nb_globals++;
298 tcg_regset_set_reg(s->reserved_regs, reg);
299 return idx;
302 TCGv_i32 tcg_global_reg_new_i32(int reg, const char *name)
304 int idx;
306 idx = tcg_global_reg_new_internal(TCG_TYPE_I32, reg, name);
307 return MAKE_TCGV_I32(idx);
310 TCGv_i64 tcg_global_reg_new_i64(int reg, const char *name)
312 int idx;
314 idx = tcg_global_reg_new_internal(TCG_TYPE_I64, reg, name);
315 return MAKE_TCGV_I64(idx);
318 static inline int tcg_global_mem_new_internal(TCGType type, int reg,
319 tcg_target_long offset,
320 const char *name)
322 TCGContext *s = &tcg_ctx;
323 TCGTemp *ts;
324 int idx;
326 idx = s->nb_globals;
327 #if TCG_TARGET_REG_BITS == 32
328 if (type == TCG_TYPE_I64) {
329 char buf[64];
330 tcg_temp_alloc(s, s->nb_globals + 2);
331 ts = &s->temps[s->nb_globals];
332 ts->base_type = type;
333 ts->type = TCG_TYPE_I32;
334 ts->fixed_reg = 0;
335 ts->mem_allocated = 1;
336 ts->mem_reg = reg;
337 #ifdef TCG_TARGET_WORDS_BIGENDIAN
338 ts->mem_offset = offset + 4;
339 #else
340 ts->mem_offset = offset;
341 #endif
342 pstrcpy(buf, sizeof(buf), name);
343 pstrcat(buf, sizeof(buf), "_0");
344 ts->name = strdup(buf);
345 ts++;
347 ts->base_type = type;
348 ts->type = TCG_TYPE_I32;
349 ts->fixed_reg = 0;
350 ts->mem_allocated = 1;
351 ts->mem_reg = reg;
352 #ifdef TCG_TARGET_WORDS_BIGENDIAN
353 ts->mem_offset = offset;
354 #else
355 ts->mem_offset = offset + 4;
356 #endif
357 pstrcpy(buf, sizeof(buf), name);
358 pstrcat(buf, sizeof(buf), "_1");
359 ts->name = strdup(buf);
361 s->nb_globals += 2;
362 } else
363 #endif
365 tcg_temp_alloc(s, s->nb_globals + 1);
366 ts = &s->temps[s->nb_globals];
367 ts->base_type = type;
368 ts->type = type;
369 ts->fixed_reg = 0;
370 ts->mem_allocated = 1;
371 ts->mem_reg = reg;
372 ts->mem_offset = offset;
373 ts->name = name;
374 s->nb_globals++;
376 return idx;
379 TCGv_i32 tcg_global_mem_new_i32(int reg, tcg_target_long offset,
380 const char *name)
382 int idx;
384 idx = tcg_global_mem_new_internal(TCG_TYPE_I32, reg, offset, name);
385 return MAKE_TCGV_I32(idx);
388 TCGv_i64 tcg_global_mem_new_i64(int reg, tcg_target_long offset,
389 const char *name)
391 int idx;
393 idx = tcg_global_mem_new_internal(TCG_TYPE_I64, reg, offset, name);
394 return MAKE_TCGV_I64(idx);
397 static inline int tcg_temp_new_internal(TCGType type, int temp_local)
399 TCGContext *s = &tcg_ctx;
400 TCGTemp *ts;
401 int idx, k;
403 k = type;
404 if (temp_local)
405 k += TCG_TYPE_COUNT;
406 idx = s->first_free_temp[k];
407 if (idx != -1) {
408 /* There is already an available temp with the
409 right type */
410 ts = &s->temps[idx];
411 s->first_free_temp[k] = ts->next_free_temp;
412 ts->temp_allocated = 1;
413 assert(ts->temp_local == temp_local);
414 } else {
415 idx = s->nb_temps;
416 #if TCG_TARGET_REG_BITS == 32
417 if (type == TCG_TYPE_I64) {
418 tcg_temp_alloc(s, s->nb_temps + 2);
419 ts = &s->temps[s->nb_temps];
420 ts->base_type = type;
421 ts->type = TCG_TYPE_I32;
422 ts->temp_allocated = 1;
423 ts->temp_local = temp_local;
424 ts->name = NULL;
425 ts++;
426 ts->base_type = TCG_TYPE_I32;
427 ts->type = TCG_TYPE_I32;
428 ts->temp_allocated = 1;
429 ts->temp_local = temp_local;
430 ts->name = NULL;
431 s->nb_temps += 2;
432 } else
433 #endif
435 tcg_temp_alloc(s, s->nb_temps + 1);
436 ts = &s->temps[s->nb_temps];
437 ts->base_type = type;
438 ts->type = type;
439 ts->temp_allocated = 1;
440 ts->temp_local = temp_local;
441 ts->name = NULL;
442 s->nb_temps++;
445 return idx;
448 TCGv_i32 tcg_temp_new_internal_i32(int temp_local)
450 int idx;
452 idx = tcg_temp_new_internal(TCG_TYPE_I32, temp_local);
453 return MAKE_TCGV_I32(idx);
456 TCGv_i64 tcg_temp_new_internal_i64(int temp_local)
458 int idx;
460 idx = tcg_temp_new_internal(TCG_TYPE_I64, temp_local);
461 return MAKE_TCGV_I64(idx);
464 static inline void tcg_temp_free_internal(int idx)
466 TCGContext *s = &tcg_ctx;
467 TCGTemp *ts;
468 int k;
470 assert(idx >= s->nb_globals && idx < s->nb_temps);
471 ts = &s->temps[idx];
472 assert(ts->temp_allocated != 0);
473 ts->temp_allocated = 0;
474 k = ts->base_type;
475 if (ts->temp_local)
476 k += TCG_TYPE_COUNT;
477 ts->next_free_temp = s->first_free_temp[k];
478 s->first_free_temp[k] = idx;
481 void tcg_temp_free_i32(TCGv_i32 arg)
483 tcg_temp_free_internal(GET_TCGV_I32(arg));
486 void tcg_temp_free_i64(TCGv_i64 arg)
488 tcg_temp_free_internal(GET_TCGV_I64(arg));
491 TCGv_i32 tcg_const_i32(int32_t val)
493 TCGv_i32 t0;
494 t0 = tcg_temp_new_i32();
495 tcg_gen_movi_i32(t0, val);
496 return t0;
499 TCGv_i64 tcg_const_i64(int64_t val)
501 TCGv_i64 t0;
502 t0 = tcg_temp_new_i64();
503 tcg_gen_movi_i64(t0, val);
504 return t0;
507 TCGv_i32 tcg_const_local_i32(int32_t val)
509 TCGv_i32 t0;
510 t0 = tcg_temp_local_new_i32();
511 tcg_gen_movi_i32(t0, val);
512 return t0;
515 TCGv_i64 tcg_const_local_i64(int64_t val)
517 TCGv_i64 t0;
518 t0 = tcg_temp_local_new_i64();
519 tcg_gen_movi_i64(t0, val);
520 return t0;
523 void tcg_register_helper(void *func, const char *name)
525 TCGContext *s = &tcg_ctx;
526 int n;
527 if ((s->nb_helpers + 1) > s->allocated_helpers) {
528 n = s->allocated_helpers;
529 if (n == 0) {
530 n = 4;
531 } else {
532 n *= 2;
534 s->helpers = realloc(s->helpers, n * sizeof(TCGHelperInfo));
535 s->allocated_helpers = n;
537 s->helpers[s->nb_helpers].func = (tcg_target_ulong)func;
538 s->helpers[s->nb_helpers].name = name;
539 s->nb_helpers++;
542 /* Note: we convert the 64 bit args to 32 bit and do some alignment
543 and endian swap. Maybe it would be better to do the alignment
544 and endian swap in tcg_reg_alloc_call(). */
545 void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags,
546 int sizemask, TCGArg ret, int nargs, TCGArg *args)
548 int call_type;
549 int i;
550 int real_args;
551 int nb_rets;
552 TCGArg *nparam;
553 *gen_opc_ptr++ = INDEX_op_call;
554 nparam = gen_opparam_ptr++;
555 call_type = (flags & TCG_CALL_TYPE_MASK);
556 if (ret != TCG_CALL_DUMMY_ARG) {
557 #if TCG_TARGET_REG_BITS < 64
558 if (sizemask & 1) {
559 #ifdef TCG_TARGET_WORDS_BIGENDIAN
560 *gen_opparam_ptr++ = ret + 1;
561 *gen_opparam_ptr++ = ret;
562 #else
563 *gen_opparam_ptr++ = ret;
564 *gen_opparam_ptr++ = ret + 1;
565 #endif
566 nb_rets = 2;
567 } else
568 #endif
570 *gen_opparam_ptr++ = ret;
571 nb_rets = 1;
573 } else {
574 nb_rets = 0;
576 real_args = 0;
577 for (i = 0; i < nargs; i++) {
578 #if TCG_TARGET_REG_BITS < 64
579 if (sizemask & (2 << i)) {
580 #ifdef TCG_TARGET_I386
581 /* REGPARM case: if the third parameter is 64 bit, it is
582 allocated on the stack */
583 if (i == 2 && call_type == TCG_CALL_TYPE_REGPARM) {
584 call_type = TCG_CALL_TYPE_REGPARM_2;
585 flags = (flags & ~TCG_CALL_TYPE_MASK) | call_type;
587 #endif
588 #ifdef TCG_TARGET_CALL_ALIGN_ARGS
589 /* some targets want aligned 64 bit args */
590 if (real_args & 1) {
591 *gen_opparam_ptr++ = TCG_CALL_DUMMY_ARG;
592 real_args++;
594 #endif
595 #ifdef TCG_TARGET_WORDS_BIGENDIAN
596 *gen_opparam_ptr++ = args[i] + 1;
597 *gen_opparam_ptr++ = args[i];
598 #else
599 *gen_opparam_ptr++ = args[i];
600 *gen_opparam_ptr++ = args[i] + 1;
601 #endif
602 real_args += 2;
603 } else
604 #endif
606 *gen_opparam_ptr++ = args[i];
607 real_args++;
610 *gen_opparam_ptr++ = GET_TCGV_PTR(func);
612 *gen_opparam_ptr++ = flags;
614 *nparam = (nb_rets << 16) | (real_args + 1);
616 /* total parameters, needed to go backward in the instruction stream */
617 *gen_opparam_ptr++ = 1 + nb_rets + real_args + 3;
620 #if TCG_TARGET_REG_BITS == 32
621 void tcg_gen_shifti_i64(TCGv_i64 ret, TCGv_i64 arg1,
622 int c, int right, int arith)
624 if (c == 0) {
625 tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg1));
626 tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
627 } else if (c >= 32) {
628 c -= 32;
629 if (right) {
630 if (arith) {
631 tcg_gen_sari_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
632 tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 31);
633 } else {
634 tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
635 tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
637 } else {
638 tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_LOW(arg1), c);
639 tcg_gen_movi_i32(TCGV_LOW(ret), 0);
641 } else {
642 TCGv_i32 t0, t1;
644 t0 = tcg_temp_new_i32();
645 t1 = tcg_temp_new_i32();
646 if (right) {
647 tcg_gen_shli_i32(t0, TCGV_HIGH(arg1), 32 - c);
648 if (arith)
649 tcg_gen_sari_i32(t1, TCGV_HIGH(arg1), c);
650 else
651 tcg_gen_shri_i32(t1, TCGV_HIGH(arg1), c);
652 tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_LOW(arg1), c);
653 tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(ret), t0);
654 tcg_gen_mov_i32(TCGV_HIGH(ret), t1);
655 } else {
656 tcg_gen_shri_i32(t0, TCGV_LOW(arg1), 32 - c);
657 /* Note: ret can be the same as arg1, so we use t1 */
658 tcg_gen_shli_i32(t1, TCGV_LOW(arg1), c);
659 tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c);
660 tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t0);
661 tcg_gen_mov_i32(TCGV_LOW(ret), t1);
663 tcg_temp_free_i32(t0);
664 tcg_temp_free_i32(t1);
667 #endif
669 static void tcg_reg_alloc_start(TCGContext *s)
671 int i;
672 TCGTemp *ts;
673 for(i = 0; i < s->nb_globals; i++) {
674 ts = &s->temps[i];
675 if (ts->fixed_reg) {
676 ts->val_type = TEMP_VAL_REG;
677 } else {
678 ts->val_type = TEMP_VAL_MEM;
681 for(i = s->nb_globals; i < s->nb_temps; i++) {
682 ts = &s->temps[i];
683 ts->val_type = TEMP_VAL_DEAD;
684 ts->mem_allocated = 0;
685 ts->fixed_reg = 0;
687 for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
688 s->reg_to_temp[i] = -1;
692 static char *tcg_get_arg_str_idx(TCGContext *s, char *buf, int buf_size,
693 int idx)
695 TCGTemp *ts;
697 ts = &s->temps[idx];
698 if (idx < s->nb_globals) {
699 pstrcpy(buf, buf_size, ts->name);
700 } else {
701 if (ts->temp_local)
702 snprintf(buf, buf_size, "loc%d", idx - s->nb_globals);
703 else
704 snprintf(buf, buf_size, "tmp%d", idx - s->nb_globals);
706 return buf;
709 char *tcg_get_arg_str_i32(TCGContext *s, char *buf, int buf_size, TCGv_i32 arg)
711 return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I32(arg));
714 char *tcg_get_arg_str_i64(TCGContext *s, char *buf, int buf_size, TCGv_i64 arg)
716 return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I64(arg));
719 static int helper_cmp(const void *p1, const void *p2)
721 const TCGHelperInfo *th1 = p1;
722 const TCGHelperInfo *th2 = p2;
723 if (th1->func < th2->func)
724 return -1;
725 else if (th1->func == th2->func)
726 return 0;
727 else
728 return 1;
731 /* find helper definition (Note: A hash table would be better) */
732 static TCGHelperInfo *tcg_find_helper(TCGContext *s, tcg_target_ulong val)
734 int m, m_min, m_max;
735 TCGHelperInfo *th;
736 tcg_target_ulong v;
738 if (unlikely(!s->helpers_sorted)) {
739 qsort(s->helpers, s->nb_helpers, sizeof(TCGHelperInfo),
740 helper_cmp);
741 s->helpers_sorted = 1;
744 /* binary search */
745 m_min = 0;
746 m_max = s->nb_helpers - 1;
747 while (m_min <= m_max) {
748 m = (m_min + m_max) >> 1;
749 th = &s->helpers[m];
750 v = th->func;
751 if (v == val)
752 return th;
753 else if (val < v) {
754 m_max = m - 1;
755 } else {
756 m_min = m + 1;
759 return NULL;
762 static const char * const cond_name[] =
764 [TCG_COND_EQ] = "eq",
765 [TCG_COND_NE] = "ne",
766 [TCG_COND_LT] = "lt",
767 [TCG_COND_GE] = "ge",
768 [TCG_COND_LE] = "le",
769 [TCG_COND_GT] = "gt",
770 [TCG_COND_LTU] = "ltu",
771 [TCG_COND_GEU] = "geu",
772 [TCG_COND_LEU] = "leu",
773 [TCG_COND_GTU] = "gtu"
776 void tcg_dump_ops(TCGContext *s, FILE *outfile)
778 const uint16_t *opc_ptr;
779 const TCGArg *args;
780 TCGArg arg;
781 int c, i, k, nb_oargs, nb_iargs, nb_cargs, first_insn;
782 const TCGOpDef *def;
783 char buf[128];
785 first_insn = 1;
786 opc_ptr = gen_opc_buf;
787 args = gen_opparam_buf;
788 while (opc_ptr < gen_opc_ptr) {
789 c = *opc_ptr++;
790 def = &tcg_op_defs[c];
791 if (c == INDEX_op_debug_insn_start) {
792 uint64_t pc;
793 #if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
794 pc = ((uint64_t)args[1] << 32) | args[0];
795 #else
796 pc = args[0];
797 #endif
798 if (!first_insn)
799 fprintf(outfile, "\n");
800 fprintf(outfile, " ---- 0x%" PRIx64, pc);
801 first_insn = 0;
802 nb_oargs = def->nb_oargs;
803 nb_iargs = def->nb_iargs;
804 nb_cargs = def->nb_cargs;
805 } else if (c == INDEX_op_call) {
806 TCGArg arg;
808 /* variable number of arguments */
809 arg = *args++;
810 nb_oargs = arg >> 16;
811 nb_iargs = arg & 0xffff;
812 nb_cargs = def->nb_cargs;
814 fprintf(outfile, " %s ", def->name);
816 /* function name */
817 fprintf(outfile, "%s",
818 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + nb_iargs - 1]));
819 /* flags */
820 fprintf(outfile, ",$0x%" TCG_PRIlx,
821 args[nb_oargs + nb_iargs]);
822 /* nb out args */
823 fprintf(outfile, ",$%d", nb_oargs);
824 for(i = 0; i < nb_oargs; i++) {
825 fprintf(outfile, ",");
826 fprintf(outfile, "%s",
827 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[i]));
829 for(i = 0; i < (nb_iargs - 1); i++) {
830 fprintf(outfile, ",");
831 if (args[nb_oargs + i] == TCG_CALL_DUMMY_ARG) {
832 fprintf(outfile, "<dummy>");
833 } else {
834 fprintf(outfile, "%s",
835 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + i]));
838 } else if (c == INDEX_op_movi_i32
839 #if TCG_TARGET_REG_BITS == 64
840 || c == INDEX_op_movi_i64
841 #endif
843 tcg_target_ulong val;
844 TCGHelperInfo *th;
846 nb_oargs = def->nb_oargs;
847 nb_iargs = def->nb_iargs;
848 nb_cargs = def->nb_cargs;
849 fprintf(outfile, " %s %s,$", def->name,
850 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[0]));
851 val = args[1];
852 th = tcg_find_helper(s, val);
853 if (th) {
854 fprintf(outfile, "%s", th->name);
855 } else {
856 if (c == INDEX_op_movi_i32)
857 fprintf(outfile, "0x%x", (uint32_t)val);
858 else
859 fprintf(outfile, "0x%" PRIx64 , (uint64_t)val);
861 } else {
862 fprintf(outfile, " %s ", def->name);
863 if (c == INDEX_op_nopn) {
864 /* variable number of arguments */
865 nb_cargs = *args;
866 nb_oargs = 0;
867 nb_iargs = 0;
868 } else {
869 nb_oargs = def->nb_oargs;
870 nb_iargs = def->nb_iargs;
871 nb_cargs = def->nb_cargs;
874 k = 0;
875 for(i = 0; i < nb_oargs; i++) {
876 if (k != 0)
877 fprintf(outfile, ",");
878 fprintf(outfile, "%s",
879 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
881 for(i = 0; i < nb_iargs; i++) {
882 if (k != 0)
883 fprintf(outfile, ",");
884 fprintf(outfile, "%s",
885 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
887 if (c == INDEX_op_brcond_i32
888 #if TCG_TARGET_REG_BITS == 32
889 || c == INDEX_op_brcond2_i32
890 #elif TCG_TARGET_REG_BITS == 64
891 || c == INDEX_op_brcond_i64
892 #endif
894 if (args[k] < ARRAY_SIZE(cond_name) && cond_name[args[k]])
895 fprintf(outfile, ",%s", cond_name[args[k++]]);
896 else
897 fprintf(outfile, ",$0x%" TCG_PRIlx, args[k++]);
898 i = 1;
900 else
901 i = 0;
902 for(; i < nb_cargs; i++) {
903 if (k != 0)
904 fprintf(outfile, ",");
905 arg = args[k++];
906 fprintf(outfile, "$0x%" TCG_PRIlx, arg);
909 fprintf(outfile, "\n");
910 args += nb_iargs + nb_oargs + nb_cargs;
914 /* we give more priority to constraints with less registers */
915 static int get_constraint_priority(const TCGOpDef *def, int k)
917 const TCGArgConstraint *arg_ct;
919 int i, n;
920 arg_ct = &def->args_ct[k];
921 if (arg_ct->ct & TCG_CT_ALIAS) {
922 /* an alias is equivalent to a single register */
923 n = 1;
924 } else {
925 if (!(arg_ct->ct & TCG_CT_REG))
926 return 0;
927 n = 0;
928 for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
929 if (tcg_regset_test_reg(arg_ct->u.regs, i))
930 n++;
933 return TCG_TARGET_NB_REGS - n + 1;
936 /* sort from highest priority to lowest */
937 static void sort_constraints(TCGOpDef *def, int start, int n)
939 int i, j, p1, p2, tmp;
941 for(i = 0; i < n; i++)
942 def->sorted_args[start + i] = start + i;
943 if (n <= 1)
944 return;
945 for(i = 0; i < n - 1; i++) {
946 for(j = i + 1; j < n; j++) {
947 p1 = get_constraint_priority(def, def->sorted_args[start + i]);
948 p2 = get_constraint_priority(def, def->sorted_args[start + j]);
949 if (p1 < p2) {
950 tmp = def->sorted_args[start + i];
951 def->sorted_args[start + i] = def->sorted_args[start + j];
952 def->sorted_args[start + j] = tmp;
958 void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs)
960 int op;
961 TCGOpDef *def;
962 const char *ct_str;
963 int i, nb_args;
965 for(;;) {
966 if (tdefs->op < 0)
967 break;
968 op = tdefs->op;
969 assert(op >= 0 && op < NB_OPS);
970 def = &tcg_op_defs[op];
971 nb_args = def->nb_iargs + def->nb_oargs;
972 for(i = 0; i < nb_args; i++) {
973 ct_str = tdefs->args_ct_str[i];
974 tcg_regset_clear(def->args_ct[i].u.regs);
975 def->args_ct[i].ct = 0;
976 if (ct_str[0] >= '0' && ct_str[0] <= '9') {
977 int oarg;
978 oarg = ct_str[0] - '0';
979 assert(oarg < def->nb_oargs);
980 assert(def->args_ct[oarg].ct & TCG_CT_REG);
981 /* TCG_CT_ALIAS is for the output arguments. The input
982 argument is tagged with TCG_CT_IALIAS. */
983 def->args_ct[i] = def->args_ct[oarg];
984 def->args_ct[oarg].ct = TCG_CT_ALIAS;
985 def->args_ct[oarg].alias_index = i;
986 def->args_ct[i].ct |= TCG_CT_IALIAS;
987 def->args_ct[i].alias_index = oarg;
988 } else {
989 for(;;) {
990 if (*ct_str == '\0')
991 break;
992 switch(*ct_str) {
993 case 'i':
994 def->args_ct[i].ct |= TCG_CT_CONST;
995 ct_str++;
996 break;
997 default:
998 if (target_parse_constraint(&def->args_ct[i], &ct_str) < 0) {
999 fprintf(stderr, "Invalid constraint '%s' for arg %d of operation '%s'\n",
1000 ct_str, i, def->name);
1001 exit(1);
1008 /* sort the constraints (XXX: this is just an heuristic) */
1009 sort_constraints(def, 0, def->nb_oargs);
1010 sort_constraints(def, def->nb_oargs, def->nb_iargs);
1012 #if 0
1014 int i;
1016 printf("%s: sorted=", def->name);
1017 for(i = 0; i < def->nb_oargs + def->nb_iargs; i++)
1018 printf(" %d", def->sorted_args[i]);
1019 printf("\n");
1021 #endif
1022 tdefs++;
1027 #ifdef USE_LIVENESS_ANALYSIS
1029 /* set a nop for an operation using 'nb_args' */
1030 static inline void tcg_set_nop(TCGContext *s, uint16_t *opc_ptr,
1031 TCGArg *args, int nb_args)
1033 if (nb_args == 0) {
1034 *opc_ptr = INDEX_op_nop;
1035 } else {
1036 *opc_ptr = INDEX_op_nopn;
1037 args[0] = nb_args;
1038 args[nb_args - 1] = nb_args;
1042 /* liveness analysis: end of function: globals are live, temps are
1043 dead. */
1044 /* XXX: at this stage, not used as there would be little gains because
1045 most TBs end with a conditional jump. */
1046 static inline void tcg_la_func_end(TCGContext *s, uint8_t *dead_temps)
1048 memset(dead_temps, 0, s->nb_globals);
1049 memset(dead_temps + s->nb_globals, 1, s->nb_temps - s->nb_globals);
1052 /* liveness analysis: end of basic block: globals are live, temps are
1053 dead, local temps are live. */
1054 static inline void tcg_la_bb_end(TCGContext *s, uint8_t *dead_temps)
1056 int i;
1057 TCGTemp *ts;
1059 memset(dead_temps, 0, s->nb_globals);
1060 ts = &s->temps[s->nb_globals];
1061 for(i = s->nb_globals; i < s->nb_temps; i++) {
1062 if (ts->temp_local)
1063 dead_temps[i] = 0;
1064 else
1065 dead_temps[i] = 1;
1066 ts++;
1070 /* Liveness analysis : update the opc_dead_iargs array to tell if a
1071 given input arguments is dead. Instructions updating dead
1072 temporaries are removed. */
1073 static void tcg_liveness_analysis(TCGContext *s)
1075 int i, op_index, op, nb_args, nb_iargs, nb_oargs, arg, nb_ops;
1076 TCGArg *args;
1077 const TCGOpDef *def;
1078 uint8_t *dead_temps;
1079 unsigned int dead_iargs;
1081 gen_opc_ptr++; /* skip end */
1083 nb_ops = gen_opc_ptr - gen_opc_buf;
1085 /* XXX: make it really dynamic */
1086 s->op_dead_iargs = tcg_malloc(OPC_BUF_SIZE * sizeof(uint16_t));
1088 dead_temps = tcg_malloc(s->nb_temps);
1089 memset(dead_temps, 1, s->nb_temps);
1091 args = gen_opparam_ptr;
1092 op_index = nb_ops - 1;
1093 while (op_index >= 0) {
1094 op = gen_opc_buf[op_index];
1095 def = &tcg_op_defs[op];
1096 switch(op) {
1097 case INDEX_op_call:
1099 int call_flags;
1101 nb_args = args[-1];
1102 args -= nb_args;
1103 nb_iargs = args[0] & 0xffff;
1104 nb_oargs = args[0] >> 16;
1105 args++;
1106 call_flags = args[nb_oargs + nb_iargs];
1108 /* pure functions can be removed if their result is not
1109 used */
1110 if (call_flags & TCG_CALL_PURE) {
1111 for(i = 0; i < nb_oargs; i++) {
1112 arg = args[i];
1113 if (!dead_temps[arg])
1114 goto do_not_remove_call;
1116 tcg_set_nop(s, gen_opc_buf + op_index,
1117 args - 1, nb_args);
1118 } else {
1119 do_not_remove_call:
1121 /* output args are dead */
1122 for(i = 0; i < nb_oargs; i++) {
1123 arg = args[i];
1124 dead_temps[arg] = 1;
1127 if (!(call_flags & TCG_CALL_CONST)) {
1128 /* globals are live (they may be used by the call) */
1129 memset(dead_temps, 0, s->nb_globals);
1132 /* input args are live */
1133 dead_iargs = 0;
1134 for(i = 0; i < nb_iargs; i++) {
1135 arg = args[i + nb_oargs];
1136 if (arg != TCG_CALL_DUMMY_ARG) {
1137 if (dead_temps[arg]) {
1138 dead_iargs |= (1 << i);
1140 dead_temps[arg] = 0;
1143 s->op_dead_iargs[op_index] = dead_iargs;
1145 args--;
1147 break;
1148 case INDEX_op_set_label:
1149 args--;
1150 /* mark end of basic block */
1151 tcg_la_bb_end(s, dead_temps);
1152 break;
1153 case INDEX_op_debug_insn_start:
1154 args -= def->nb_args;
1155 break;
1156 case INDEX_op_nopn:
1157 nb_args = args[-1];
1158 args -= nb_args;
1159 break;
1160 case INDEX_op_discard:
1161 args--;
1162 /* mark the temporary as dead */
1163 dead_temps[args[0]] = 1;
1164 break;
1165 case INDEX_op_end:
1166 break;
1167 /* XXX: optimize by hardcoding common cases (e.g. triadic ops) */
1168 default:
1169 args -= def->nb_args;
1170 nb_iargs = def->nb_iargs;
1171 nb_oargs = def->nb_oargs;
1173 /* Test if the operation can be removed because all
1174 its outputs are dead. We assume that nb_oargs == 0
1175 implies side effects */
1176 if (!(def->flags & TCG_OPF_SIDE_EFFECTS) && nb_oargs != 0) {
1177 for(i = 0; i < nb_oargs; i++) {
1178 arg = args[i];
1179 if (!dead_temps[arg])
1180 goto do_not_remove;
1182 tcg_set_nop(s, gen_opc_buf + op_index, args, def->nb_args);
1183 #ifdef CONFIG_PROFILER
1184 s->del_op_count++;
1185 #endif
1186 } else {
1187 do_not_remove:
1189 /* output args are dead */
1190 for(i = 0; i < nb_oargs; i++) {
1191 arg = args[i];
1192 dead_temps[arg] = 1;
1195 /* if end of basic block, update */
1196 if (def->flags & TCG_OPF_BB_END) {
1197 tcg_la_bb_end(s, dead_temps);
1198 } else if (def->flags & TCG_OPF_CALL_CLOBBER) {
1199 /* globals are live */
1200 memset(dead_temps, 0, s->nb_globals);
1203 /* input args are live */
1204 dead_iargs = 0;
1205 for(i = 0; i < nb_iargs; i++) {
1206 arg = args[i + nb_oargs];
1207 if (dead_temps[arg]) {
1208 dead_iargs |= (1 << i);
1210 dead_temps[arg] = 0;
1212 s->op_dead_iargs[op_index] = dead_iargs;
1214 break;
1216 op_index--;
1219 if (args != gen_opparam_buf)
1220 tcg_abort();
1222 #else
1223 /* dummy liveness analysis */
1224 void tcg_liveness_analysis(TCGContext *s)
1226 int nb_ops;
1227 nb_ops = gen_opc_ptr - gen_opc_buf;
1229 s->op_dead_iargs = tcg_malloc(nb_ops * sizeof(uint16_t));
1230 memset(s->op_dead_iargs, 0, nb_ops * sizeof(uint16_t));
1232 #endif
1234 #ifndef NDEBUG
1235 static void dump_regs(TCGContext *s)
1237 TCGTemp *ts;
1238 int i;
1239 char buf[64];
1241 for(i = 0; i < s->nb_temps; i++) {
1242 ts = &s->temps[i];
1243 printf(" %10s: ", tcg_get_arg_str_idx(s, buf, sizeof(buf), i));
1244 switch(ts->val_type) {
1245 case TEMP_VAL_REG:
1246 printf("%s", tcg_target_reg_names[ts->reg]);
1247 break;
1248 case TEMP_VAL_MEM:
1249 printf("%d(%s)", (int)ts->mem_offset, tcg_target_reg_names[ts->mem_reg]);
1250 break;
1251 case TEMP_VAL_CONST:
1252 printf("$0x%" TCG_PRIlx, ts->val);
1253 break;
1254 case TEMP_VAL_DEAD:
1255 printf("D");
1256 break;
1257 default:
1258 printf("???");
1259 break;
1261 printf("\n");
1264 for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
1265 if (s->reg_to_temp[i] >= 0) {
1266 printf("%s: %s\n",
1267 tcg_target_reg_names[i],
1268 tcg_get_arg_str_idx(s, buf, sizeof(buf), s->reg_to_temp[i]));
1273 static void check_regs(TCGContext *s)
1275 int reg, k;
1276 TCGTemp *ts;
1277 char buf[64];
1279 for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1280 k = s->reg_to_temp[reg];
1281 if (k >= 0) {
1282 ts = &s->temps[k];
1283 if (ts->val_type != TEMP_VAL_REG ||
1284 ts->reg != reg) {
1285 printf("Inconsistency for register %s:\n",
1286 tcg_target_reg_names[reg]);
1287 goto fail;
1291 for(k = 0; k < s->nb_temps; k++) {
1292 ts = &s->temps[k];
1293 if (ts->val_type == TEMP_VAL_REG &&
1294 !ts->fixed_reg &&
1295 s->reg_to_temp[ts->reg] != k) {
1296 printf("Inconsistency for temp %s:\n",
1297 tcg_get_arg_str_idx(s, buf, sizeof(buf), k));
1298 fail:
1299 printf("reg state:\n");
1300 dump_regs(s);
1301 tcg_abort();
1305 #endif
1307 static void temp_allocate_frame(TCGContext *s, int temp)
1309 TCGTemp *ts;
1310 ts = &s->temps[temp];
1311 s->current_frame_offset = (s->current_frame_offset + sizeof(tcg_target_long) - 1) & ~(sizeof(tcg_target_long) - 1);
1312 if (s->current_frame_offset + sizeof(tcg_target_long) > s->frame_end)
1313 tcg_abort();
1314 ts->mem_offset = s->current_frame_offset;
1315 ts->mem_reg = s->frame_reg;
1316 ts->mem_allocated = 1;
1317 s->current_frame_offset += sizeof(tcg_target_long);
1320 /* free register 'reg' by spilling the corresponding temporary if necessary */
1321 static void tcg_reg_free(TCGContext *s, int reg)
1323 TCGTemp *ts;
1324 int temp;
1326 temp = s->reg_to_temp[reg];
1327 if (temp != -1) {
1328 ts = &s->temps[temp];
1329 assert(ts->val_type == TEMP_VAL_REG);
1330 if (!ts->mem_coherent) {
1331 if (!ts->mem_allocated)
1332 temp_allocate_frame(s, temp);
1333 tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1335 ts->val_type = TEMP_VAL_MEM;
1336 s->reg_to_temp[reg] = -1;
1340 /* Allocate a register belonging to reg1 & ~reg2 */
1341 static int tcg_reg_alloc(TCGContext *s, TCGRegSet reg1, TCGRegSet reg2)
1343 int i, reg;
1344 TCGRegSet reg_ct;
1346 tcg_regset_andnot(reg_ct, reg1, reg2);
1348 /* first try free registers */
1349 for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1350 reg = tcg_target_reg_alloc_order[i];
1351 if (tcg_regset_test_reg(reg_ct, reg) && s->reg_to_temp[reg] == -1)
1352 return reg;
1355 /* XXX: do better spill choice */
1356 for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1357 reg = tcg_target_reg_alloc_order[i];
1358 if (tcg_regset_test_reg(reg_ct, reg)) {
1359 tcg_reg_free(s, reg);
1360 return reg;
1364 tcg_abort();
1367 /* save a temporary to memory. 'allocated_regs' is used in case a
1368 temporary registers needs to be allocated to store a constant. */
1369 static void temp_save(TCGContext *s, int temp, TCGRegSet allocated_regs)
1371 TCGTemp *ts;
1372 int reg;
1374 ts = &s->temps[temp];
1375 if (!ts->fixed_reg) {
1376 switch(ts->val_type) {
1377 case TEMP_VAL_REG:
1378 tcg_reg_free(s, ts->reg);
1379 break;
1380 case TEMP_VAL_DEAD:
1381 ts->val_type = TEMP_VAL_MEM;
1382 break;
1383 case TEMP_VAL_CONST:
1384 reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type],
1385 allocated_regs);
1386 if (!ts->mem_allocated)
1387 temp_allocate_frame(s, temp);
1388 tcg_out_movi(s, ts->type, reg, ts->val);
1389 tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1390 ts->val_type = TEMP_VAL_MEM;
1391 break;
1392 case TEMP_VAL_MEM:
1393 break;
1394 default:
1395 tcg_abort();
1400 /* save globals to their cannonical location and assume they can be
1401 modified be the following code. 'allocated_regs' is used in case a
1402 temporary registers needs to be allocated to store a constant. */
1403 static void save_globals(TCGContext *s, TCGRegSet allocated_regs)
1405 int i;
1407 for(i = 0; i < s->nb_globals; i++) {
1408 temp_save(s, i, allocated_regs);
1412 /* at the end of a basic block, we assume all temporaries are dead and
1413 all globals are stored at their canonical location. */
1414 static void tcg_reg_alloc_bb_end(TCGContext *s, TCGRegSet allocated_regs)
1416 TCGTemp *ts;
1417 int i;
1419 for(i = s->nb_globals; i < s->nb_temps; i++) {
1420 ts = &s->temps[i];
1421 if (ts->temp_local) {
1422 temp_save(s, i, allocated_regs);
1423 } else {
1424 if (ts->val_type == TEMP_VAL_REG) {
1425 s->reg_to_temp[ts->reg] = -1;
1427 ts->val_type = TEMP_VAL_DEAD;
1431 save_globals(s, allocated_regs);
1434 #define IS_DEAD_IARG(n) ((dead_iargs >> (n)) & 1)
1436 static void tcg_reg_alloc_movi(TCGContext *s, const TCGArg *args)
1438 TCGTemp *ots;
1439 tcg_target_ulong val;
1441 ots = &s->temps[args[0]];
1442 val = args[1];
1444 if (ots->fixed_reg) {
1445 /* for fixed registers, we do not do any constant
1446 propagation */
1447 tcg_out_movi(s, ots->type, ots->reg, val);
1448 } else {
1449 /* The movi is not explicitly generated here */
1450 if (ots->val_type == TEMP_VAL_REG)
1451 s->reg_to_temp[ots->reg] = -1;
1452 ots->val_type = TEMP_VAL_CONST;
1453 ots->val = val;
1457 static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
1458 const TCGArg *args,
1459 unsigned int dead_iargs)
1461 TCGTemp *ts, *ots;
1462 int reg;
1463 const TCGArgConstraint *arg_ct;
1465 ots = &s->temps[args[0]];
1466 ts = &s->temps[args[1]];
1467 arg_ct = &def->args_ct[0];
1469 /* XXX: always mark arg dead if IS_DEAD_IARG(0) */
1470 if (ts->val_type == TEMP_VAL_REG) {
1471 if (IS_DEAD_IARG(0) && !ts->fixed_reg && !ots->fixed_reg) {
1472 /* the mov can be suppressed */
1473 if (ots->val_type == TEMP_VAL_REG)
1474 s->reg_to_temp[ots->reg] = -1;
1475 reg = ts->reg;
1476 s->reg_to_temp[reg] = -1;
1477 ts->val_type = TEMP_VAL_DEAD;
1478 } else {
1479 if (ots->val_type == TEMP_VAL_REG) {
1480 reg = ots->reg;
1481 } else {
1482 reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1484 if (ts->reg != reg) {
1485 tcg_out_mov(s, reg, ts->reg);
1488 } else if (ts->val_type == TEMP_VAL_MEM) {
1489 if (ots->val_type == TEMP_VAL_REG) {
1490 reg = ots->reg;
1491 } else {
1492 reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1494 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1495 } else if (ts->val_type == TEMP_VAL_CONST) {
1496 if (ots->fixed_reg) {
1497 reg = ots->reg;
1498 tcg_out_movi(s, ots->type, reg, ts->val);
1499 } else {
1500 /* propagate constant */
1501 if (ots->val_type == TEMP_VAL_REG)
1502 s->reg_to_temp[ots->reg] = -1;
1503 ots->val_type = TEMP_VAL_CONST;
1504 ots->val = ts->val;
1505 return;
1507 } else {
1508 tcg_abort();
1510 s->reg_to_temp[reg] = args[0];
1511 ots->reg = reg;
1512 ots->val_type = TEMP_VAL_REG;
1513 ots->mem_coherent = 0;
1516 static void tcg_reg_alloc_op(TCGContext *s,
1517 const TCGOpDef *def, int opc,
1518 const TCGArg *args,
1519 unsigned int dead_iargs)
1521 TCGRegSet allocated_regs;
1522 int i, k, nb_iargs, nb_oargs, reg;
1523 TCGArg arg;
1524 const TCGArgConstraint *arg_ct;
1525 TCGTemp *ts;
1526 TCGArg new_args[TCG_MAX_OP_ARGS];
1527 int const_args[TCG_MAX_OP_ARGS];
1529 nb_oargs = def->nb_oargs;
1530 nb_iargs = def->nb_iargs;
1532 /* copy constants */
1533 memcpy(new_args + nb_oargs + nb_iargs,
1534 args + nb_oargs + nb_iargs,
1535 sizeof(TCGArg) * def->nb_cargs);
1537 /* satisfy input constraints */
1538 tcg_regset_set(allocated_regs, s->reserved_regs);
1539 for(k = 0; k < nb_iargs; k++) {
1540 i = def->sorted_args[nb_oargs + k];
1541 arg = args[i];
1542 arg_ct = &def->args_ct[i];
1543 ts = &s->temps[arg];
1544 if (ts->val_type == TEMP_VAL_MEM) {
1545 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1546 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1547 ts->val_type = TEMP_VAL_REG;
1548 ts->reg = reg;
1549 ts->mem_coherent = 1;
1550 s->reg_to_temp[reg] = arg;
1551 } else if (ts->val_type == TEMP_VAL_CONST) {
1552 if (tcg_target_const_match(ts->val, arg_ct)) {
1553 /* constant is OK for instruction */
1554 const_args[i] = 1;
1555 new_args[i] = ts->val;
1556 goto iarg_end;
1557 } else {
1558 /* need to move to a register */
1559 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1560 tcg_out_movi(s, ts->type, reg, ts->val);
1561 ts->val_type = TEMP_VAL_REG;
1562 ts->reg = reg;
1563 ts->mem_coherent = 0;
1564 s->reg_to_temp[reg] = arg;
1567 assert(ts->val_type == TEMP_VAL_REG);
1568 if (arg_ct->ct & TCG_CT_IALIAS) {
1569 if (ts->fixed_reg) {
1570 /* if fixed register, we must allocate a new register
1571 if the alias is not the same register */
1572 if (arg != args[arg_ct->alias_index])
1573 goto allocate_in_reg;
1574 } else {
1575 /* if the input is aliased to an output and if it is
1576 not dead after the instruction, we must allocate
1577 a new register and move it */
1578 if (!IS_DEAD_IARG(i - nb_oargs))
1579 goto allocate_in_reg;
1582 reg = ts->reg;
1583 if (tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1584 /* nothing to do : the constraint is satisfied */
1585 } else {
1586 allocate_in_reg:
1587 /* allocate a new register matching the constraint
1588 and move the temporary register into it */
1589 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1590 tcg_out_mov(s, reg, ts->reg);
1592 new_args[i] = reg;
1593 const_args[i] = 0;
1594 tcg_regset_set_reg(allocated_regs, reg);
1595 iarg_end: ;
1598 if (def->flags & TCG_OPF_BB_END) {
1599 tcg_reg_alloc_bb_end(s, allocated_regs);
1600 } else {
1601 /* mark dead temporaries and free the associated registers */
1602 for(i = 0; i < nb_iargs; i++) {
1603 arg = args[nb_oargs + i];
1604 if (IS_DEAD_IARG(i)) {
1605 ts = &s->temps[arg];
1606 if (!ts->fixed_reg) {
1607 if (ts->val_type == TEMP_VAL_REG)
1608 s->reg_to_temp[ts->reg] = -1;
1609 ts->val_type = TEMP_VAL_DEAD;
1614 if (def->flags & TCG_OPF_CALL_CLOBBER) {
1615 /* XXX: permit generic clobber register list ? */
1616 for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1617 if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
1618 tcg_reg_free(s, reg);
1621 /* XXX: for load/store we could do that only for the slow path
1622 (i.e. when a memory callback is called) */
1624 /* store globals and free associated registers (we assume the insn
1625 can modify any global. */
1626 save_globals(s, allocated_regs);
1629 /* satisfy the output constraints */
1630 tcg_regset_set(allocated_regs, s->reserved_regs);
1631 for(k = 0; k < nb_oargs; k++) {
1632 i = def->sorted_args[k];
1633 arg = args[i];
1634 arg_ct = &def->args_ct[i];
1635 ts = &s->temps[arg];
1636 if (arg_ct->ct & TCG_CT_ALIAS) {
1637 reg = new_args[arg_ct->alias_index];
1638 } else {
1639 /* if fixed register, we try to use it */
1640 reg = ts->reg;
1641 if (ts->fixed_reg &&
1642 tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1643 goto oarg_end;
1645 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1647 tcg_regset_set_reg(allocated_regs, reg);
1648 /* if a fixed register is used, then a move will be done afterwards */
1649 if (!ts->fixed_reg) {
1650 if (ts->val_type == TEMP_VAL_REG)
1651 s->reg_to_temp[ts->reg] = -1;
1652 ts->val_type = TEMP_VAL_REG;
1653 ts->reg = reg;
1654 /* temp value is modified, so the value kept in memory is
1655 potentially not the same */
1656 ts->mem_coherent = 0;
1657 s->reg_to_temp[reg] = arg;
1659 oarg_end:
1660 new_args[i] = reg;
1664 /* emit instruction */
1665 tcg_out_op(s, opc, new_args, const_args);
1667 /* move the outputs in the correct register if needed */
1668 for(i = 0; i < nb_oargs; i++) {
1669 ts = &s->temps[args[i]];
1670 reg = new_args[i];
1671 if (ts->fixed_reg && ts->reg != reg) {
1672 tcg_out_mov(s, ts->reg, reg);
1677 #ifdef TCG_TARGET_STACK_GROWSUP
1678 #define STACK_DIR(x) (-(x))
1679 #else
1680 #define STACK_DIR(x) (x)
1681 #endif
1683 static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
1684 int opc, const TCGArg *args,
1685 unsigned int dead_iargs)
1687 int nb_iargs, nb_oargs, flags, nb_regs, i, reg, nb_params;
1688 TCGArg arg, func_arg;
1689 TCGTemp *ts;
1690 tcg_target_long stack_offset, call_stack_size, func_addr;
1691 int const_func_arg, allocate_args;
1692 TCGRegSet allocated_regs;
1693 const TCGArgConstraint *arg_ct;
1695 arg = *args++;
1697 nb_oargs = arg >> 16;
1698 nb_iargs = arg & 0xffff;
1699 nb_params = nb_iargs - 1;
1701 flags = args[nb_oargs + nb_iargs];
1703 nb_regs = tcg_target_get_call_iarg_regs_count(flags);
1704 if (nb_regs > nb_params)
1705 nb_regs = nb_params;
1707 /* assign stack slots first */
1708 /* XXX: preallocate call stack */
1709 call_stack_size = (nb_params - nb_regs) * sizeof(tcg_target_long);
1710 call_stack_size = (call_stack_size + TCG_TARGET_STACK_ALIGN - 1) &
1711 ~(TCG_TARGET_STACK_ALIGN - 1);
1712 allocate_args = (call_stack_size > TCG_STATIC_CALL_ARGS_SIZE);
1713 if (allocate_args) {
1714 tcg_out_addi(s, TCG_REG_CALL_STACK, -STACK_DIR(call_stack_size));
1717 stack_offset = TCG_TARGET_CALL_STACK_OFFSET;
1718 for(i = nb_regs; i < nb_params; i++) {
1719 arg = args[nb_oargs + i];
1720 #ifdef TCG_TARGET_STACK_GROWSUP
1721 stack_offset -= sizeof(tcg_target_long);
1722 #endif
1723 if (arg != TCG_CALL_DUMMY_ARG) {
1724 ts = &s->temps[arg];
1725 if (ts->val_type == TEMP_VAL_REG) {
1726 tcg_out_st(s, ts->type, ts->reg, TCG_REG_CALL_STACK, stack_offset);
1727 } else if (ts->val_type == TEMP_VAL_MEM) {
1728 reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type],
1729 s->reserved_regs);
1730 /* XXX: not correct if reading values from the stack */
1731 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1732 tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
1733 } else if (ts->val_type == TEMP_VAL_CONST) {
1734 reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type],
1735 s->reserved_regs);
1736 /* XXX: sign extend may be needed on some targets */
1737 tcg_out_movi(s, ts->type, reg, ts->val);
1738 tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
1739 } else {
1740 tcg_abort();
1743 #ifndef TCG_TARGET_STACK_GROWSUP
1744 stack_offset += sizeof(tcg_target_long);
1745 #endif
1748 /* assign input registers */
1749 tcg_regset_set(allocated_regs, s->reserved_regs);
1750 for(i = 0; i < nb_regs; i++) {
1751 arg = args[nb_oargs + i];
1752 if (arg != TCG_CALL_DUMMY_ARG) {
1753 ts = &s->temps[arg];
1754 reg = tcg_target_call_iarg_regs[i];
1755 tcg_reg_free(s, reg);
1756 if (ts->val_type == TEMP_VAL_REG) {
1757 if (ts->reg != reg) {
1758 tcg_out_mov(s, reg, ts->reg);
1760 } else if (ts->val_type == TEMP_VAL_MEM) {
1761 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1762 } else if (ts->val_type == TEMP_VAL_CONST) {
1763 /* XXX: sign extend ? */
1764 tcg_out_movi(s, ts->type, reg, ts->val);
1765 } else {
1766 tcg_abort();
1768 tcg_regset_set_reg(allocated_regs, reg);
1772 /* assign function address */
1773 func_arg = args[nb_oargs + nb_iargs - 1];
1774 arg_ct = &def->args_ct[0];
1775 ts = &s->temps[func_arg];
1776 func_addr = ts->val;
1777 const_func_arg = 0;
1778 if (ts->val_type == TEMP_VAL_MEM) {
1779 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1780 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1781 func_arg = reg;
1782 tcg_regset_set_reg(allocated_regs, reg);
1783 } else if (ts->val_type == TEMP_VAL_REG) {
1784 reg = ts->reg;
1785 if (!tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1786 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1787 tcg_out_mov(s, reg, ts->reg);
1789 func_arg = reg;
1790 tcg_regset_set_reg(allocated_regs, reg);
1791 } else if (ts->val_type == TEMP_VAL_CONST) {
1792 if (tcg_target_const_match(func_addr, arg_ct)) {
1793 const_func_arg = 1;
1794 func_arg = func_addr;
1795 } else {
1796 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1797 tcg_out_movi(s, ts->type, reg, func_addr);
1798 func_arg = reg;
1799 tcg_regset_set_reg(allocated_regs, reg);
1801 } else {
1802 tcg_abort();
1806 /* mark dead temporaries and free the associated registers */
1807 for(i = 0; i < nb_iargs; i++) {
1808 arg = args[nb_oargs + i];
1809 if (IS_DEAD_IARG(i)) {
1810 ts = &s->temps[arg];
1811 if (!ts->fixed_reg) {
1812 if (ts->val_type == TEMP_VAL_REG)
1813 s->reg_to_temp[ts->reg] = -1;
1814 ts->val_type = TEMP_VAL_DEAD;
1819 /* clobber call registers */
1820 for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1821 if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
1822 tcg_reg_free(s, reg);
1826 /* store globals and free associated registers (we assume the call
1827 can modify any global. */
1828 if (!(flags & TCG_CALL_CONST)) {
1829 save_globals(s, allocated_regs);
1832 tcg_out_op(s, opc, &func_arg, &const_func_arg);
1834 if (allocate_args) {
1835 tcg_out_addi(s, TCG_REG_CALL_STACK, STACK_DIR(call_stack_size));
1838 /* assign output registers and emit moves if needed */
1839 for(i = 0; i < nb_oargs; i++) {
1840 arg = args[i];
1841 ts = &s->temps[arg];
1842 reg = tcg_target_call_oarg_regs[i];
1843 assert(s->reg_to_temp[reg] == -1);
1844 if (ts->fixed_reg) {
1845 if (ts->reg != reg) {
1846 tcg_out_mov(s, ts->reg, reg);
1848 } else {
1849 if (ts->val_type == TEMP_VAL_REG)
1850 s->reg_to_temp[ts->reg] = -1;
1851 ts->val_type = TEMP_VAL_REG;
1852 ts->reg = reg;
1853 ts->mem_coherent = 0;
1854 s->reg_to_temp[reg] = arg;
1858 return nb_iargs + nb_oargs + def->nb_cargs + 1;
1861 #ifdef CONFIG_PROFILER
1863 static int64_t tcg_table_op_count[NB_OPS];
1865 void dump_op_count(void)
1867 int i;
1868 FILE *f;
1869 f = fopen("/tmp/op.log", "w");
1870 for(i = INDEX_op_end; i < NB_OPS; i++) {
1871 fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name, tcg_table_op_count[i]);
1873 fclose(f);
1875 #endif
1878 static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
1879 long search_pc)
1881 int opc, op_index;
1882 const TCGOpDef *def;
1883 unsigned int dead_iargs;
1884 const TCGArg *args;
1886 #ifdef DEBUG_DISAS
1887 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
1888 qemu_log("OP:\n");
1889 tcg_dump_ops(s, logfile);
1890 qemu_log("\n");
1892 #endif
1894 #ifdef CONFIG_PROFILER
1895 s->la_time -= profile_getclock();
1896 #endif
1897 tcg_liveness_analysis(s);
1898 #ifdef CONFIG_PROFILER
1899 s->la_time += profile_getclock();
1900 #endif
1902 #ifdef DEBUG_DISAS
1903 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_OPT))) {
1904 qemu_log("OP after la:\n");
1905 tcg_dump_ops(s, logfile);
1906 qemu_log("\n");
1908 #endif
1910 tcg_reg_alloc_start(s);
1912 s->code_buf = gen_code_buf;
1913 s->code_ptr = gen_code_buf;
1915 args = gen_opparam_buf;
1916 op_index = 0;
1918 for(;;) {
1919 opc = gen_opc_buf[op_index];
1920 #ifdef CONFIG_PROFILER
1921 tcg_table_op_count[opc]++;
1922 #endif
1923 def = &tcg_op_defs[opc];
1924 #if 0
1925 printf("%s: %d %d %d\n", def->name,
1926 def->nb_oargs, def->nb_iargs, def->nb_cargs);
1927 // dump_regs(s);
1928 #endif
1929 switch(opc) {
1930 case INDEX_op_mov_i32:
1931 #if TCG_TARGET_REG_BITS == 64
1932 case INDEX_op_mov_i64:
1933 #endif
1934 dead_iargs = s->op_dead_iargs[op_index];
1935 tcg_reg_alloc_mov(s, def, args, dead_iargs);
1936 break;
1937 case INDEX_op_movi_i32:
1938 #if TCG_TARGET_REG_BITS == 64
1939 case INDEX_op_movi_i64:
1940 #endif
1941 tcg_reg_alloc_movi(s, args);
1942 break;
1943 case INDEX_op_debug_insn_start:
1944 /* debug instruction */
1945 break;
1946 case INDEX_op_nop:
1947 case INDEX_op_nop1:
1948 case INDEX_op_nop2:
1949 case INDEX_op_nop3:
1950 break;
1951 case INDEX_op_nopn:
1952 args += args[0];
1953 goto next;
1954 case INDEX_op_discard:
1956 TCGTemp *ts;
1957 ts = &s->temps[args[0]];
1958 /* mark the temporary as dead */
1959 if (!ts->fixed_reg) {
1960 if (ts->val_type == TEMP_VAL_REG)
1961 s->reg_to_temp[ts->reg] = -1;
1962 ts->val_type = TEMP_VAL_DEAD;
1965 break;
1966 case INDEX_op_set_label:
1967 tcg_reg_alloc_bb_end(s, s->reserved_regs);
1968 tcg_out_label(s, args[0], (long)s->code_ptr);
1969 break;
1970 case INDEX_op_call:
1971 dead_iargs = s->op_dead_iargs[op_index];
1972 args += tcg_reg_alloc_call(s, def, opc, args, dead_iargs);
1973 goto next;
1974 case INDEX_op_end:
1975 goto the_end;
1976 default:
1977 /* Note: in order to speed up the code, it would be much
1978 faster to have specialized register allocator functions for
1979 some common argument patterns */
1980 dead_iargs = s->op_dead_iargs[op_index];
1981 tcg_reg_alloc_op(s, def, opc, args, dead_iargs);
1982 break;
1984 args += def->nb_args;
1985 next:
1986 if (search_pc >= 0 && search_pc < s->code_ptr - gen_code_buf) {
1987 return op_index;
1989 op_index++;
1990 #ifndef NDEBUG
1991 check_regs(s);
1992 #endif
1994 the_end:
1995 return -1;
1998 int tcg_gen_code(TCGContext *s, uint8_t *gen_code_buf)
2000 #ifdef CONFIG_PROFILER
2002 int n;
2003 n = (gen_opc_ptr - gen_opc_buf);
2004 s->op_count += n;
2005 if (n > s->op_count_max)
2006 s->op_count_max = n;
2008 s->temp_count += s->nb_temps;
2009 if (s->nb_temps > s->temp_count_max)
2010 s->temp_count_max = s->nb_temps;
2012 #endif
2014 tcg_gen_code_common(s, gen_code_buf, -1);
2016 /* flush instruction cache */
2017 flush_icache_range((unsigned long)gen_code_buf,
2018 (unsigned long)s->code_ptr);
2019 return s->code_ptr - gen_code_buf;
2022 /* Return the index of the micro operation such as the pc after is <
2023 offset bytes from the start of the TB. The contents of gen_code_buf must
2024 not be changed, though writing the same values is ok.
2025 Return -1 if not found. */
2026 int tcg_gen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, long offset)
2028 return tcg_gen_code_common(s, gen_code_buf, offset);
2031 #ifdef CONFIG_PROFILER
2032 void tcg_dump_info(FILE *f,
2033 int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
2035 TCGContext *s = &tcg_ctx;
2036 int64_t tot;
2038 tot = s->interm_time + s->code_time;
2039 cpu_fprintf(f, "JIT cycles %" PRId64 " (%0.3f s at 2.4 GHz)\n",
2040 tot, tot / 2.4e9);
2041 cpu_fprintf(f, "translated TBs %" PRId64 " (aborted=%" PRId64 " %0.1f%%)\n",
2042 s->tb_count,
2043 s->tb_count1 - s->tb_count,
2044 s->tb_count1 ? (double)(s->tb_count1 - s->tb_count) / s->tb_count1 * 100.0 : 0);
2045 cpu_fprintf(f, "avg ops/TB %0.1f max=%d\n",
2046 s->tb_count ? (double)s->op_count / s->tb_count : 0, s->op_count_max);
2047 cpu_fprintf(f, "deleted ops/TB %0.2f\n",
2048 s->tb_count ?
2049 (double)s->del_op_count / s->tb_count : 0);
2050 cpu_fprintf(f, "avg temps/TB %0.2f max=%d\n",
2051 s->tb_count ?
2052 (double)s->temp_count / s->tb_count : 0,
2053 s->temp_count_max);
2055 cpu_fprintf(f, "cycles/op %0.1f\n",
2056 s->op_count ? (double)tot / s->op_count : 0);
2057 cpu_fprintf(f, "cycles/in byte %0.1f\n",
2058 s->code_in_len ? (double)tot / s->code_in_len : 0);
2059 cpu_fprintf(f, "cycles/out byte %0.1f\n",
2060 s->code_out_len ? (double)tot / s->code_out_len : 0);
2061 if (tot == 0)
2062 tot = 1;
2063 cpu_fprintf(f, " gen_interm time %0.1f%%\n",
2064 (double)s->interm_time / tot * 100.0);
2065 cpu_fprintf(f, " gen_code time %0.1f%%\n",
2066 (double)s->code_time / tot * 100.0);
2067 cpu_fprintf(f, "liveness/code time %0.1f%%\n",
2068 (double)s->la_time / (s->code_time ? s->code_time : 1) * 100.0);
2069 cpu_fprintf(f, "cpu_restore count %" PRId64 "\n",
2070 s->restore_count);
2071 cpu_fprintf(f, " avg cycles %0.1f\n",
2072 s->restore_count ? (double)s->restore_time / s->restore_count : 0);
2074 extern void dump_op_count(void);
2075 dump_op_count();
2078 #else
2079 void tcg_dump_info(FILE *f,
2080 int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
2082 cpu_fprintf(f, "[TCG profiler not compiled]\n");
2084 #endif