Improve instruction name comments for easier searching
[qemu-kvm/fedora.git] / tcg / tcg.c
bloba75d8dcc2c7b376819f5308ea6da35b62461925d
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 <assert.h>
36 #include <stdarg.h>
37 #include <stdlib.h>
38 #include <stdio.h>
39 #include <string.h>
40 #include <inttypes.h>
41 #ifdef _WIN32
42 #include <malloc.h>
43 #endif
44 #ifdef _AIX
45 #include <alloca.h>
46 #endif
48 #include "qemu-common.h"
49 #include "cache-utils.h"
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"
62 static void patch_reloc(uint8_t *code_ptr, int type,
63 tcg_target_long value, tcg_target_long addend);
65 static TCGOpDef tcg_op_defs[] = {
66 #define DEF(s, n, copy_size) { #s, 0, 0, n, n, 0, copy_size },
67 #define DEF2(s, iargs, oargs, cargs, flags) { #s, iargs, oargs, cargs, iargs + oargs + cargs, flags, 0 },
68 #include "tcg-opc.h"
69 #undef DEF
70 #undef DEF2
73 static TCGRegSet tcg_target_available_regs[2];
74 static TCGRegSet tcg_target_call_clobber_regs;
76 /* XXX: move that inside the context */
77 uint16_t *gen_opc_ptr;
78 TCGArg *gen_opparam_ptr;
80 static inline void tcg_out8(TCGContext *s, uint8_t v)
82 *s->code_ptr++ = v;
85 static inline void tcg_out16(TCGContext *s, uint16_t v)
87 *(uint16_t *)s->code_ptr = v;
88 s->code_ptr += 2;
91 static inline void tcg_out32(TCGContext *s, uint32_t v)
93 *(uint32_t *)s->code_ptr = v;
94 s->code_ptr += 4;
97 /* label relocation processing */
99 void tcg_out_reloc(TCGContext *s, uint8_t *code_ptr, int type,
100 int label_index, long addend)
102 TCGLabel *l;
103 TCGRelocation *r;
105 l = &s->labels[label_index];
106 if (l->has_value) {
107 /* FIXME: This may break relocations on RISC targets that
108 modify instruction fields in place. The caller may not have
109 written the initial value. */
110 patch_reloc(code_ptr, type, l->u.value, addend);
111 } else {
112 /* add a new relocation entry */
113 r = tcg_malloc(sizeof(TCGRelocation));
114 r->type = type;
115 r->ptr = code_ptr;
116 r->addend = addend;
117 r->next = l->u.first_reloc;
118 l->u.first_reloc = r;
122 static void tcg_out_label(TCGContext *s, int label_index,
123 tcg_target_long value)
125 TCGLabel *l;
126 TCGRelocation *r;
128 l = &s->labels[label_index];
129 if (l->has_value)
130 tcg_abort();
131 r = l->u.first_reloc;
132 while (r != NULL) {
133 patch_reloc(r->ptr, r->type, value, r->addend);
134 r = r->next;
136 l->has_value = 1;
137 l->u.value = value;
140 int gen_new_label(void)
142 TCGContext *s = &tcg_ctx;
143 int idx;
144 TCGLabel *l;
146 if (s->nb_labels >= TCG_MAX_LABELS)
147 tcg_abort();
148 idx = s->nb_labels++;
149 l = &s->labels[idx];
150 l->has_value = 0;
151 l->u.first_reloc = NULL;
152 return idx;
155 #include "tcg-target.c"
157 /* pool based memory allocation */
158 void *tcg_malloc_internal(TCGContext *s, int size)
160 TCGPool *p;
161 int pool_size;
163 if (size > TCG_POOL_CHUNK_SIZE) {
164 /* big malloc: insert a new pool (XXX: could optimize) */
165 p = qemu_malloc(sizeof(TCGPool) + size);
166 p->size = size;
167 if (s->pool_current)
168 s->pool_current->next = p;
169 else
170 s->pool_first = p;
171 p->next = s->pool_current;
172 } else {
173 p = s->pool_current;
174 if (!p) {
175 p = s->pool_first;
176 if (!p)
177 goto new_pool;
178 } else {
179 if (!p->next) {
180 new_pool:
181 pool_size = TCG_POOL_CHUNK_SIZE;
182 p = qemu_malloc(sizeof(TCGPool) + pool_size);
183 p->size = pool_size;
184 p->next = NULL;
185 if (s->pool_current)
186 s->pool_current->next = p;
187 else
188 s->pool_first = p;
189 } else {
190 p = p->next;
194 s->pool_current = p;
195 s->pool_cur = p->data + size;
196 s->pool_end = p->data + p->size;
197 return p->data;
200 void tcg_pool_reset(TCGContext *s)
202 s->pool_cur = s->pool_end = NULL;
203 s->pool_current = NULL;
206 void tcg_context_init(TCGContext *s)
208 int op, total_args, n;
209 TCGOpDef *def;
210 TCGArgConstraint *args_ct;
211 int *sorted_args;
213 memset(s, 0, sizeof(*s));
214 s->temps = s->static_temps;
215 s->nb_globals = 0;
217 /* Count total number of arguments and allocate the corresponding
218 space */
219 total_args = 0;
220 for(op = 0; op < NB_OPS; op++) {
221 def = &tcg_op_defs[op];
222 n = def->nb_iargs + def->nb_oargs;
223 total_args += n;
226 args_ct = qemu_malloc(sizeof(TCGArgConstraint) * total_args);
227 sorted_args = qemu_malloc(sizeof(int) * total_args);
229 for(op = 0; op < NB_OPS; op++) {
230 def = &tcg_op_defs[op];
231 def->args_ct = args_ct;
232 def->sorted_args = sorted_args;
233 n = def->nb_iargs + def->nb_oargs;
234 sorted_args += n;
235 args_ct += n;
238 tcg_target_init(s);
240 /* init global prologue and epilogue */
241 s->code_buf = code_gen_prologue;
242 s->code_ptr = s->code_buf;
243 tcg_target_qemu_prologue(s);
244 flush_icache_range((unsigned long)s->code_buf,
245 (unsigned long)s->code_ptr);
248 void tcg_set_frame(TCGContext *s, int reg,
249 tcg_target_long start, tcg_target_long size)
251 s->frame_start = start;
252 s->frame_end = start + size;
253 s->frame_reg = reg;
256 void tcg_func_start(TCGContext *s)
258 int i;
259 tcg_pool_reset(s);
260 s->nb_temps = s->nb_globals;
261 for(i = 0; i < (TCG_TYPE_COUNT * 2); i++)
262 s->first_free_temp[i] = -1;
263 s->labels = tcg_malloc(sizeof(TCGLabel) * TCG_MAX_LABELS);
264 s->nb_labels = 0;
265 s->current_frame_offset = s->frame_start;
267 gen_opc_ptr = gen_opc_buf;
268 gen_opparam_ptr = gen_opparam_buf;
271 static inline void tcg_temp_alloc(TCGContext *s, int n)
273 if (n > TCG_MAX_TEMPS)
274 tcg_abort();
277 static inline int tcg_global_reg_new_internal(TCGType type, int reg,
278 const char *name)
280 TCGContext *s = &tcg_ctx;
281 TCGTemp *ts;
282 int idx;
284 #if TCG_TARGET_REG_BITS == 32
285 if (type != TCG_TYPE_I32)
286 tcg_abort();
287 #endif
288 if (tcg_regset_test_reg(s->reserved_regs, reg))
289 tcg_abort();
290 idx = s->nb_globals;
291 tcg_temp_alloc(s, s->nb_globals + 1);
292 ts = &s->temps[s->nb_globals];
293 ts->base_type = type;
294 ts->type = type;
295 ts->fixed_reg = 1;
296 ts->reg = reg;
297 ts->name = name;
298 s->nb_globals++;
299 tcg_regset_set_reg(s->reserved_regs, reg);
300 return idx;
303 TCGv_i32 tcg_global_reg_new_i32(int reg, const char *name)
305 int idx;
307 idx = tcg_global_reg_new_internal(TCG_TYPE_I32, reg, name);
308 return MAKE_TCGV_I32(idx);
311 TCGv_i64 tcg_global_reg_new_i64(int reg, const char *name)
313 int idx;
315 idx = tcg_global_reg_new_internal(TCG_TYPE_I64, reg, name);
316 return MAKE_TCGV_I64(idx);
319 static inline int tcg_global_mem_new_internal(TCGType type, int reg,
320 tcg_target_long offset,
321 const char *name)
323 TCGContext *s = &tcg_ctx;
324 TCGTemp *ts;
325 int idx;
327 idx = s->nb_globals;
328 #if TCG_TARGET_REG_BITS == 32
329 if (type == TCG_TYPE_I64) {
330 char buf[64];
331 tcg_temp_alloc(s, s->nb_globals + 2);
332 ts = &s->temps[s->nb_globals];
333 ts->base_type = type;
334 ts->type = TCG_TYPE_I32;
335 ts->fixed_reg = 0;
336 ts->mem_allocated = 1;
337 ts->mem_reg = reg;
338 #ifdef TCG_TARGET_WORDS_BIGENDIAN
339 ts->mem_offset = offset + 4;
340 #else
341 ts->mem_offset = offset;
342 #endif
343 pstrcpy(buf, sizeof(buf), name);
344 pstrcat(buf, sizeof(buf), "_0");
345 ts->name = strdup(buf);
346 ts++;
348 ts->base_type = type;
349 ts->type = TCG_TYPE_I32;
350 ts->fixed_reg = 0;
351 ts->mem_allocated = 1;
352 ts->mem_reg = reg;
353 #ifdef TCG_TARGET_WORDS_BIGENDIAN
354 ts->mem_offset = offset;
355 #else
356 ts->mem_offset = offset + 4;
357 #endif
358 pstrcpy(buf, sizeof(buf), name);
359 pstrcat(buf, sizeof(buf), "_1");
360 ts->name = strdup(buf);
362 s->nb_globals += 2;
363 } else
364 #endif
366 tcg_temp_alloc(s, s->nb_globals + 1);
367 ts = &s->temps[s->nb_globals];
368 ts->base_type = type;
369 ts->type = type;
370 ts->fixed_reg = 0;
371 ts->mem_allocated = 1;
372 ts->mem_reg = reg;
373 ts->mem_offset = offset;
374 ts->name = name;
375 s->nb_globals++;
377 return idx;
380 TCGv_i32 tcg_global_mem_new_i32(int reg, tcg_target_long offset,
381 const char *name)
383 int idx;
385 idx = tcg_global_mem_new_internal(TCG_TYPE_I32, reg, offset, name);
386 return MAKE_TCGV_I32(idx);
389 TCGv_i64 tcg_global_mem_new_i64(int reg, tcg_target_long offset,
390 const char *name)
392 int idx;
394 idx = tcg_global_mem_new_internal(TCG_TYPE_I64, reg, offset, name);
395 return MAKE_TCGV_I64(idx);
398 static inline int tcg_temp_new_internal(TCGType type, int temp_local)
400 TCGContext *s = &tcg_ctx;
401 TCGTemp *ts;
402 int idx, k;
404 k = type;
405 if (temp_local)
406 k += TCG_TYPE_COUNT;
407 idx = s->first_free_temp[k];
408 if (idx != -1) {
409 /* There is already an available temp with the
410 right type */
411 ts = &s->temps[idx];
412 s->first_free_temp[k] = ts->next_free_temp;
413 ts->temp_allocated = 1;
414 assert(ts->temp_local == temp_local);
415 } else {
416 idx = s->nb_temps;
417 #if TCG_TARGET_REG_BITS == 32
418 if (type == TCG_TYPE_I64) {
419 tcg_temp_alloc(s, s->nb_temps + 2);
420 ts = &s->temps[s->nb_temps];
421 ts->base_type = type;
422 ts->type = TCG_TYPE_I32;
423 ts->temp_allocated = 1;
424 ts->temp_local = temp_local;
425 ts->name = NULL;
426 ts++;
427 ts->base_type = TCG_TYPE_I32;
428 ts->type = TCG_TYPE_I32;
429 ts->temp_allocated = 1;
430 ts->temp_local = temp_local;
431 ts->name = NULL;
432 s->nb_temps += 2;
433 } else
434 #endif
436 tcg_temp_alloc(s, s->nb_temps + 1);
437 ts = &s->temps[s->nb_temps];
438 ts->base_type = type;
439 ts->type = type;
440 ts->temp_allocated = 1;
441 ts->temp_local = temp_local;
442 ts->name = NULL;
443 s->nb_temps++;
446 return idx;
449 TCGv_i32 tcg_temp_new_internal_i32(int temp_local)
451 int idx;
453 idx = tcg_temp_new_internal(TCG_TYPE_I32, temp_local);
454 return MAKE_TCGV_I32(idx);
457 TCGv_i64 tcg_temp_new_internal_i64(int temp_local)
459 int idx;
461 idx = tcg_temp_new_internal(TCG_TYPE_I64, temp_local);
462 return MAKE_TCGV_I64(idx);
465 static inline void tcg_temp_free_internal(int idx)
467 TCGContext *s = &tcg_ctx;
468 TCGTemp *ts;
469 int k;
471 assert(idx >= s->nb_globals && idx < s->nb_temps);
472 ts = &s->temps[idx];
473 assert(ts->temp_allocated != 0);
474 ts->temp_allocated = 0;
475 k = ts->base_type;
476 if (ts->temp_local)
477 k += TCG_TYPE_COUNT;
478 ts->next_free_temp = s->first_free_temp[k];
479 s->first_free_temp[k] = idx;
482 void tcg_temp_free_i32(TCGv_i32 arg)
484 tcg_temp_free_internal(GET_TCGV_I32(arg));
487 void tcg_temp_free_i64(TCGv_i64 arg)
489 tcg_temp_free_internal(GET_TCGV_I64(arg));
492 TCGv_i32 tcg_const_i32(int32_t val)
494 TCGv_i32 t0;
495 t0 = tcg_temp_new_i32();
496 tcg_gen_movi_i32(t0, val);
497 return t0;
500 TCGv_i64 tcg_const_i64(int64_t val)
502 TCGv_i64 t0;
503 t0 = tcg_temp_new_i64();
504 tcg_gen_movi_i64(t0, val);
505 return t0;
508 TCGv_i32 tcg_const_local_i32(int32_t val)
510 TCGv_i32 t0;
511 t0 = tcg_temp_local_new_i32();
512 tcg_gen_movi_i32(t0, val);
513 return t0;
516 TCGv_i64 tcg_const_local_i64(int64_t val)
518 TCGv_i64 t0;
519 t0 = tcg_temp_local_new_i64();
520 tcg_gen_movi_i64(t0, val);
521 return t0;
524 void tcg_register_helper(void *func, const char *name)
526 TCGContext *s = &tcg_ctx;
527 int n;
528 if ((s->nb_helpers + 1) > s->allocated_helpers) {
529 n = s->allocated_helpers;
530 if (n == 0) {
531 n = 4;
532 } else {
533 n *= 2;
535 s->helpers = realloc(s->helpers, n * sizeof(TCGHelperInfo));
536 s->allocated_helpers = n;
538 s->helpers[s->nb_helpers].func = (tcg_target_ulong)func;
539 s->helpers[s->nb_helpers].name = name;
540 s->nb_helpers++;
543 /* Note: we convert the 64 bit args to 32 bit and do some alignment
544 and endian swap. Maybe it would be better to do the alignment
545 and endian swap in tcg_reg_alloc_call(). */
546 void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags,
547 int sizemask, TCGArg ret, int nargs, TCGArg *args)
549 int call_type;
550 int i;
551 int real_args;
552 int nb_rets;
553 TCGArg *nparam;
554 *gen_opc_ptr++ = INDEX_op_call;
555 nparam = gen_opparam_ptr++;
556 call_type = (flags & TCG_CALL_TYPE_MASK);
557 if (ret != TCG_CALL_DUMMY_ARG) {
558 #if TCG_TARGET_REG_BITS < 64
559 if (sizemask & 1) {
560 #ifdef TCG_TARGET_WORDS_BIGENDIAN
561 *gen_opparam_ptr++ = ret + 1;
562 *gen_opparam_ptr++ = ret;
563 #else
564 *gen_opparam_ptr++ = ret;
565 *gen_opparam_ptr++ = ret + 1;
566 #endif
567 nb_rets = 2;
568 } else
569 #endif
571 *gen_opparam_ptr++ = ret;
572 nb_rets = 1;
574 } else {
575 nb_rets = 0;
577 real_args = 0;
578 for (i = 0; i < nargs; i++) {
579 #if TCG_TARGET_REG_BITS < 64
580 if (sizemask & (2 << i)) {
581 #ifdef TCG_TARGET_I386
582 /* REGPARM case: if the third parameter is 64 bit, it is
583 allocated on the stack */
584 if (i == 2 && call_type == TCG_CALL_TYPE_REGPARM) {
585 call_type = TCG_CALL_TYPE_REGPARM_2;
586 flags = (flags & ~TCG_CALL_TYPE_MASK) | call_type;
588 #endif
589 #ifdef TCG_TARGET_CALL_ALIGN_ARGS
590 /* some targets want aligned 64 bit args */
591 if (real_args & 1) {
592 *gen_opparam_ptr++ = TCG_CALL_DUMMY_ARG;
593 real_args++;
595 #endif
596 #ifdef TCG_TARGET_WORDS_BIGENDIAN
597 *gen_opparam_ptr++ = args[i] + 1;
598 *gen_opparam_ptr++ = args[i];
599 #else
600 *gen_opparam_ptr++ = args[i];
601 *gen_opparam_ptr++ = args[i] + 1;
602 #endif
603 real_args += 2;
604 } else
605 #endif
607 *gen_opparam_ptr++ = args[i];
608 real_args++;
611 *gen_opparam_ptr++ = GET_TCGV_PTR(func);
613 *gen_opparam_ptr++ = flags;
615 *nparam = (nb_rets << 16) | (real_args + 1);
617 /* total parameters, needed to go backward in the instruction stream */
618 *gen_opparam_ptr++ = 1 + nb_rets + real_args + 3;
621 #if TCG_TARGET_REG_BITS == 32
622 void tcg_gen_shifti_i64(TCGv_i64 ret, TCGv_i64 arg1,
623 int c, int right, int arith)
625 if (c == 0) {
626 tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg1));
627 tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
628 } else if (c >= 32) {
629 c -= 32;
630 if (right) {
631 if (arith) {
632 tcg_gen_sari_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
633 tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 31);
634 } else {
635 tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
636 tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
638 } else {
639 tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_LOW(arg1), c);
640 tcg_gen_movi_i32(TCGV_LOW(ret), 0);
642 } else {
643 TCGv_i32 t0, t1;
645 t0 = tcg_temp_new_i32();
646 t1 = tcg_temp_new_i32();
647 if (right) {
648 tcg_gen_shli_i32(t0, TCGV_HIGH(arg1), 32 - c);
649 if (arith)
650 tcg_gen_sari_i32(t1, TCGV_HIGH(arg1), c);
651 else
652 tcg_gen_shri_i32(t1, TCGV_HIGH(arg1), c);
653 tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_LOW(arg1), c);
654 tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(ret), t0);
655 tcg_gen_mov_i32(TCGV_HIGH(ret), t1);
656 } else {
657 tcg_gen_shri_i32(t0, TCGV_LOW(arg1), 32 - c);
658 /* Note: ret can be the same as arg1, so we use t1 */
659 tcg_gen_shli_i32(t1, TCGV_LOW(arg1), c);
660 tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c);
661 tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t0);
662 tcg_gen_mov_i32(TCGV_LOW(ret), t1);
664 tcg_temp_free_i32(t0);
665 tcg_temp_free_i32(t1);
668 #endif
670 static void tcg_reg_alloc_start(TCGContext *s)
672 int i;
673 TCGTemp *ts;
674 for(i = 0; i < s->nb_globals; i++) {
675 ts = &s->temps[i];
676 if (ts->fixed_reg) {
677 ts->val_type = TEMP_VAL_REG;
678 } else {
679 ts->val_type = TEMP_VAL_MEM;
682 for(i = s->nb_globals; i < s->nb_temps; i++) {
683 ts = &s->temps[i];
684 ts->val_type = TEMP_VAL_DEAD;
685 ts->mem_allocated = 0;
686 ts->fixed_reg = 0;
688 for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
689 s->reg_to_temp[i] = -1;
693 static char *tcg_get_arg_str_idx(TCGContext *s, char *buf, int buf_size,
694 int idx)
696 TCGTemp *ts;
698 ts = &s->temps[idx];
699 if (idx < s->nb_globals) {
700 pstrcpy(buf, buf_size, ts->name);
701 } else {
702 if (ts->temp_local)
703 snprintf(buf, buf_size, "loc%d", idx - s->nb_globals);
704 else
705 snprintf(buf, buf_size, "tmp%d", idx - s->nb_globals);
707 return buf;
710 char *tcg_get_arg_str_i32(TCGContext *s, char *buf, int buf_size, TCGv_i32 arg)
712 return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I32(arg));
715 char *tcg_get_arg_str_i64(TCGContext *s, char *buf, int buf_size, TCGv_i64 arg)
717 return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I64(arg));
720 static int helper_cmp(const void *p1, const void *p2)
722 const TCGHelperInfo *th1 = p1;
723 const TCGHelperInfo *th2 = p2;
724 if (th1->func < th2->func)
725 return -1;
726 else if (th1->func == th2->func)
727 return 0;
728 else
729 return 1;
732 /* find helper definition (Note: A hash table would be better) */
733 static TCGHelperInfo *tcg_find_helper(TCGContext *s, tcg_target_ulong val)
735 int m, m_min, m_max;
736 TCGHelperInfo *th;
737 tcg_target_ulong v;
739 if (unlikely(!s->helpers_sorted)) {
740 qsort(s->helpers, s->nb_helpers, sizeof(TCGHelperInfo),
741 helper_cmp);
742 s->helpers_sorted = 1;
745 /* binary search */
746 m_min = 0;
747 m_max = s->nb_helpers - 1;
748 while (m_min <= m_max) {
749 m = (m_min + m_max) >> 1;
750 th = &s->helpers[m];
751 v = th->func;
752 if (v == val)
753 return th;
754 else if (val < v) {
755 m_max = m - 1;
756 } else {
757 m_min = m + 1;
760 return NULL;
763 static const char * const cond_name[] =
765 [TCG_COND_EQ] = "eq",
766 [TCG_COND_NE] = "ne",
767 [TCG_COND_LT] = "lt",
768 [TCG_COND_GE] = "ge",
769 [TCG_COND_LE] = "le",
770 [TCG_COND_GT] = "gt",
771 [TCG_COND_LTU] = "ltu",
772 [TCG_COND_GEU] = "geu",
773 [TCG_COND_LEU] = "leu",
774 [TCG_COND_GTU] = "gtu"
777 void tcg_dump_ops(TCGContext *s, FILE *outfile)
779 const uint16_t *opc_ptr;
780 const TCGArg *args;
781 TCGArg arg;
782 int c, i, k, nb_oargs, nb_iargs, nb_cargs, first_insn;
783 const TCGOpDef *def;
784 char buf[128];
786 first_insn = 1;
787 opc_ptr = gen_opc_buf;
788 args = gen_opparam_buf;
789 while (opc_ptr < gen_opc_ptr) {
790 c = *opc_ptr++;
791 def = &tcg_op_defs[c];
792 if (c == INDEX_op_debug_insn_start) {
793 uint64_t pc;
794 #if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
795 pc = ((uint64_t)args[1] << 32) | args[0];
796 #else
797 pc = args[0];
798 #endif
799 if (!first_insn)
800 fprintf(outfile, "\n");
801 fprintf(outfile, " ---- 0x%" PRIx64, pc);
802 first_insn = 0;
803 nb_oargs = def->nb_oargs;
804 nb_iargs = def->nb_iargs;
805 nb_cargs = def->nb_cargs;
806 } else if (c == INDEX_op_call) {
807 TCGArg arg;
809 /* variable number of arguments */
810 arg = *args++;
811 nb_oargs = arg >> 16;
812 nb_iargs = arg & 0xffff;
813 nb_cargs = def->nb_cargs;
815 fprintf(outfile, " %s ", def->name);
817 /* function name */
818 fprintf(outfile, "%s",
819 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + nb_iargs - 1]));
820 /* flags */
821 fprintf(outfile, ",$0x%" TCG_PRIlx,
822 args[nb_oargs + nb_iargs]);
823 /* nb out args */
824 fprintf(outfile, ",$%d", nb_oargs);
825 for(i = 0; i < nb_oargs; i++) {
826 fprintf(outfile, ",");
827 fprintf(outfile, "%s",
828 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[i]));
830 for(i = 0; i < (nb_iargs - 1); i++) {
831 fprintf(outfile, ",");
832 if (args[nb_oargs + i] == TCG_CALL_DUMMY_ARG) {
833 fprintf(outfile, "<dummy>");
834 } else {
835 fprintf(outfile, "%s",
836 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + i]));
839 } else if (c == INDEX_op_movi_i32
840 #if TCG_TARGET_REG_BITS == 64
841 || c == INDEX_op_movi_i64
842 #endif
844 tcg_target_ulong val;
845 TCGHelperInfo *th;
847 nb_oargs = def->nb_oargs;
848 nb_iargs = def->nb_iargs;
849 nb_cargs = def->nb_cargs;
850 fprintf(outfile, " %s %s,$", def->name,
851 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[0]));
852 val = args[1];
853 th = tcg_find_helper(s, val);
854 if (th) {
855 fprintf(outfile, "%s", th->name);
856 } else {
857 if (c == INDEX_op_movi_i32)
858 fprintf(outfile, "0x%x", (uint32_t)val);
859 else
860 fprintf(outfile, "0x%" PRIx64 , (uint64_t)val);
862 } else {
863 fprintf(outfile, " %s ", def->name);
864 if (c == INDEX_op_nopn) {
865 /* variable number of arguments */
866 nb_cargs = *args;
867 nb_oargs = 0;
868 nb_iargs = 0;
869 } else {
870 nb_oargs = def->nb_oargs;
871 nb_iargs = def->nb_iargs;
872 nb_cargs = def->nb_cargs;
875 k = 0;
876 for(i = 0; i < nb_oargs; i++) {
877 if (k != 0)
878 fprintf(outfile, ",");
879 fprintf(outfile, "%s",
880 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
882 for(i = 0; i < nb_iargs; i++) {
883 if (k != 0)
884 fprintf(outfile, ",");
885 fprintf(outfile, "%s",
886 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
888 if (c == INDEX_op_brcond_i32
889 #if TCG_TARGET_REG_BITS == 32
890 || c == INDEX_op_brcond2_i32
891 #elif TCG_TARGET_REG_BITS == 64
892 || c == INDEX_op_brcond_i64
893 #endif
895 if (args[k] < ARRAY_SIZE(cond_name) && cond_name[args[k]])
896 fprintf(outfile, ",%s", cond_name[args[k++]]);
897 else
898 fprintf(outfile, ",$0x%" TCG_PRIlx, args[k++]);
899 i = 1;
901 else
902 i = 0;
903 for(; i < nb_cargs; i++) {
904 if (k != 0)
905 fprintf(outfile, ",");
906 arg = args[k++];
907 fprintf(outfile, "$0x%" TCG_PRIlx, arg);
910 fprintf(outfile, "\n");
911 args += nb_iargs + nb_oargs + nb_cargs;
915 /* we give more priority to constraints with less registers */
916 static int get_constraint_priority(const TCGOpDef *def, int k)
918 const TCGArgConstraint *arg_ct;
920 int i, n;
921 arg_ct = &def->args_ct[k];
922 if (arg_ct->ct & TCG_CT_ALIAS) {
923 /* an alias is equivalent to a single register */
924 n = 1;
925 } else {
926 if (!(arg_ct->ct & TCG_CT_REG))
927 return 0;
928 n = 0;
929 for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
930 if (tcg_regset_test_reg(arg_ct->u.regs, i))
931 n++;
934 return TCG_TARGET_NB_REGS - n + 1;
937 /* sort from highest priority to lowest */
938 static void sort_constraints(TCGOpDef *def, int start, int n)
940 int i, j, p1, p2, tmp;
942 for(i = 0; i < n; i++)
943 def->sorted_args[start + i] = start + i;
944 if (n <= 1)
945 return;
946 for(i = 0; i < n - 1; i++) {
947 for(j = i + 1; j < n; j++) {
948 p1 = get_constraint_priority(def, def->sorted_args[start + i]);
949 p2 = get_constraint_priority(def, def->sorted_args[start + j]);
950 if (p1 < p2) {
951 tmp = def->sorted_args[start + i];
952 def->sorted_args[start + i] = def->sorted_args[start + j];
953 def->sorted_args[start + j] = tmp;
959 void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs)
961 int op;
962 TCGOpDef *def;
963 const char *ct_str;
964 int i, nb_args;
966 for(;;) {
967 if (tdefs->op < 0)
968 break;
969 op = tdefs->op;
970 assert(op >= 0 && op < NB_OPS);
971 def = &tcg_op_defs[op];
972 nb_args = def->nb_iargs + def->nb_oargs;
973 for(i = 0; i < nb_args; i++) {
974 ct_str = tdefs->args_ct_str[i];
975 tcg_regset_clear(def->args_ct[i].u.regs);
976 def->args_ct[i].ct = 0;
977 if (ct_str[0] >= '0' && ct_str[0] <= '9') {
978 int oarg;
979 oarg = ct_str[0] - '0';
980 assert(oarg < def->nb_oargs);
981 assert(def->args_ct[oarg].ct & TCG_CT_REG);
982 /* TCG_CT_ALIAS is for the output arguments. The input
983 argument is tagged with TCG_CT_IALIAS. */
984 def->args_ct[i] = def->args_ct[oarg];
985 def->args_ct[oarg].ct = TCG_CT_ALIAS;
986 def->args_ct[oarg].alias_index = i;
987 def->args_ct[i].ct |= TCG_CT_IALIAS;
988 def->args_ct[i].alias_index = oarg;
989 } else {
990 for(;;) {
991 if (*ct_str == '\0')
992 break;
993 switch(*ct_str) {
994 case 'i':
995 def->args_ct[i].ct |= TCG_CT_CONST;
996 ct_str++;
997 break;
998 default:
999 if (target_parse_constraint(&def->args_ct[i], &ct_str) < 0) {
1000 fprintf(stderr, "Invalid constraint '%s' for arg %d of operation '%s'\n",
1001 ct_str, i, def->name);
1002 exit(1);
1009 /* sort the constraints (XXX: this is just an heuristic) */
1010 sort_constraints(def, 0, def->nb_oargs);
1011 sort_constraints(def, def->nb_oargs, def->nb_iargs);
1013 #if 0
1015 int i;
1017 printf("%s: sorted=", def->name);
1018 for(i = 0; i < def->nb_oargs + def->nb_iargs; i++)
1019 printf(" %d", def->sorted_args[i]);
1020 printf("\n");
1022 #endif
1023 tdefs++;
1028 #ifdef USE_LIVENESS_ANALYSIS
1030 /* set a nop for an operation using 'nb_args' */
1031 static inline void tcg_set_nop(TCGContext *s, uint16_t *opc_ptr,
1032 TCGArg *args, int nb_args)
1034 if (nb_args == 0) {
1035 *opc_ptr = INDEX_op_nop;
1036 } else {
1037 *opc_ptr = INDEX_op_nopn;
1038 args[0] = nb_args;
1039 args[nb_args - 1] = nb_args;
1043 /* liveness analysis: end of function: globals are live, temps are
1044 dead. */
1045 /* XXX: at this stage, not used as there would be little gains because
1046 most TBs end with a conditional jump. */
1047 static inline void tcg_la_func_end(TCGContext *s, uint8_t *dead_temps)
1049 memset(dead_temps, 0, s->nb_globals);
1050 memset(dead_temps + s->nb_globals, 1, s->nb_temps - s->nb_globals);
1053 /* liveness analysis: end of basic block: globals are live, temps are
1054 dead, local temps are live. */
1055 static inline void tcg_la_bb_end(TCGContext *s, uint8_t *dead_temps)
1057 int i;
1058 TCGTemp *ts;
1060 memset(dead_temps, 0, s->nb_globals);
1061 ts = &s->temps[s->nb_globals];
1062 for(i = s->nb_globals; i < s->nb_temps; i++) {
1063 if (ts->temp_local)
1064 dead_temps[i] = 0;
1065 else
1066 dead_temps[i] = 1;
1067 ts++;
1071 /* Liveness analysis : update the opc_dead_iargs array to tell if a
1072 given input arguments is dead. Instructions updating dead
1073 temporaries are removed. */
1074 static void tcg_liveness_analysis(TCGContext *s)
1076 int i, op_index, op, nb_args, nb_iargs, nb_oargs, arg, nb_ops;
1077 TCGArg *args;
1078 const TCGOpDef *def;
1079 uint8_t *dead_temps;
1080 unsigned int dead_iargs;
1082 gen_opc_ptr++; /* skip end */
1084 nb_ops = gen_opc_ptr - gen_opc_buf;
1086 /* XXX: make it really dynamic */
1087 s->op_dead_iargs = tcg_malloc(OPC_BUF_SIZE * sizeof(uint16_t));
1089 dead_temps = tcg_malloc(s->nb_temps);
1090 memset(dead_temps, 1, s->nb_temps);
1092 args = gen_opparam_ptr;
1093 op_index = nb_ops - 1;
1094 while (op_index >= 0) {
1095 op = gen_opc_buf[op_index];
1096 def = &tcg_op_defs[op];
1097 switch(op) {
1098 case INDEX_op_call:
1100 int call_flags;
1102 nb_args = args[-1];
1103 args -= nb_args;
1104 nb_iargs = args[0] & 0xffff;
1105 nb_oargs = args[0] >> 16;
1106 args++;
1107 call_flags = args[nb_oargs + nb_iargs];
1109 /* pure functions can be removed if their result is not
1110 used */
1111 if (call_flags & TCG_CALL_PURE) {
1112 for(i = 0; i < nb_oargs; i++) {
1113 arg = args[i];
1114 if (!dead_temps[arg])
1115 goto do_not_remove_call;
1117 tcg_set_nop(s, gen_opc_buf + op_index,
1118 args - 1, nb_args);
1119 } else {
1120 do_not_remove_call:
1122 /* output args are dead */
1123 for(i = 0; i < nb_oargs; i++) {
1124 arg = args[i];
1125 dead_temps[arg] = 1;
1128 if (!(call_flags & TCG_CALL_CONST)) {
1129 /* globals are live (they may be used by the call) */
1130 memset(dead_temps, 0, s->nb_globals);
1133 /* input args are live */
1134 dead_iargs = 0;
1135 for(i = 0; i < nb_iargs; i++) {
1136 arg = args[i + nb_oargs];
1137 if (arg != TCG_CALL_DUMMY_ARG) {
1138 if (dead_temps[arg]) {
1139 dead_iargs |= (1 << i);
1141 dead_temps[arg] = 0;
1144 s->op_dead_iargs[op_index] = dead_iargs;
1146 args--;
1148 break;
1149 case INDEX_op_set_label:
1150 args--;
1151 /* mark end of basic block */
1152 tcg_la_bb_end(s, dead_temps);
1153 break;
1154 case INDEX_op_debug_insn_start:
1155 args -= def->nb_args;
1156 break;
1157 case INDEX_op_nopn:
1158 nb_args = args[-1];
1159 args -= nb_args;
1160 break;
1161 case INDEX_op_discard:
1162 args--;
1163 /* mark the temporary as dead */
1164 dead_temps[args[0]] = 1;
1165 break;
1166 case INDEX_op_end:
1167 break;
1168 /* XXX: optimize by hardcoding common cases (e.g. triadic ops) */
1169 default:
1170 args -= def->nb_args;
1171 nb_iargs = def->nb_iargs;
1172 nb_oargs = def->nb_oargs;
1174 /* Test if the operation can be removed because all
1175 its outputs are dead. We assume that nb_oargs == 0
1176 implies side effects */
1177 if (!(def->flags & TCG_OPF_SIDE_EFFECTS) && nb_oargs != 0) {
1178 for(i = 0; i < nb_oargs; i++) {
1179 arg = args[i];
1180 if (!dead_temps[arg])
1181 goto do_not_remove;
1183 tcg_set_nop(s, gen_opc_buf + op_index, args, def->nb_args);
1184 #ifdef CONFIG_PROFILER
1185 s->del_op_count++;
1186 #endif
1187 } else {
1188 do_not_remove:
1190 /* output args are dead */
1191 for(i = 0; i < nb_oargs; i++) {
1192 arg = args[i];
1193 dead_temps[arg] = 1;
1196 /* if end of basic block, update */
1197 if (def->flags & TCG_OPF_BB_END) {
1198 tcg_la_bb_end(s, dead_temps);
1199 } else if (def->flags & TCG_OPF_CALL_CLOBBER) {
1200 /* globals are live */
1201 memset(dead_temps, 0, s->nb_globals);
1204 /* input args are live */
1205 dead_iargs = 0;
1206 for(i = 0; i < nb_iargs; i++) {
1207 arg = args[i + nb_oargs];
1208 if (dead_temps[arg]) {
1209 dead_iargs |= (1 << i);
1211 dead_temps[arg] = 0;
1213 s->op_dead_iargs[op_index] = dead_iargs;
1215 break;
1217 op_index--;
1220 if (args != gen_opparam_buf)
1221 tcg_abort();
1223 #else
1224 /* dummy liveness analysis */
1225 void tcg_liveness_analysis(TCGContext *s)
1227 int nb_ops;
1228 nb_ops = gen_opc_ptr - gen_opc_buf;
1230 s->op_dead_iargs = tcg_malloc(nb_ops * sizeof(uint16_t));
1231 memset(s->op_dead_iargs, 0, nb_ops * sizeof(uint16_t));
1233 #endif
1235 #ifndef NDEBUG
1236 static void dump_regs(TCGContext *s)
1238 TCGTemp *ts;
1239 int i;
1240 char buf[64];
1242 for(i = 0; i < s->nb_temps; i++) {
1243 ts = &s->temps[i];
1244 printf(" %10s: ", tcg_get_arg_str_idx(s, buf, sizeof(buf), i));
1245 switch(ts->val_type) {
1246 case TEMP_VAL_REG:
1247 printf("%s", tcg_target_reg_names[ts->reg]);
1248 break;
1249 case TEMP_VAL_MEM:
1250 printf("%d(%s)", (int)ts->mem_offset, tcg_target_reg_names[ts->mem_reg]);
1251 break;
1252 case TEMP_VAL_CONST:
1253 printf("$0x%" TCG_PRIlx, ts->val);
1254 break;
1255 case TEMP_VAL_DEAD:
1256 printf("D");
1257 break;
1258 default:
1259 printf("???");
1260 break;
1262 printf("\n");
1265 for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
1266 if (s->reg_to_temp[i] >= 0) {
1267 printf("%s: %s\n",
1268 tcg_target_reg_names[i],
1269 tcg_get_arg_str_idx(s, buf, sizeof(buf), s->reg_to_temp[i]));
1274 static void check_regs(TCGContext *s)
1276 int reg, k;
1277 TCGTemp *ts;
1278 char buf[64];
1280 for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1281 k = s->reg_to_temp[reg];
1282 if (k >= 0) {
1283 ts = &s->temps[k];
1284 if (ts->val_type != TEMP_VAL_REG ||
1285 ts->reg != reg) {
1286 printf("Inconsistency for register %s:\n",
1287 tcg_target_reg_names[reg]);
1288 goto fail;
1292 for(k = 0; k < s->nb_temps; k++) {
1293 ts = &s->temps[k];
1294 if (ts->val_type == TEMP_VAL_REG &&
1295 !ts->fixed_reg &&
1296 s->reg_to_temp[ts->reg] != k) {
1297 printf("Inconsistency for temp %s:\n",
1298 tcg_get_arg_str_idx(s, buf, sizeof(buf), k));
1299 fail:
1300 printf("reg state:\n");
1301 dump_regs(s);
1302 tcg_abort();
1306 #endif
1308 static void temp_allocate_frame(TCGContext *s, int temp)
1310 TCGTemp *ts;
1311 ts = &s->temps[temp];
1312 s->current_frame_offset = (s->current_frame_offset + sizeof(tcg_target_long) - 1) & ~(sizeof(tcg_target_long) - 1);
1313 if (s->current_frame_offset + sizeof(tcg_target_long) > s->frame_end)
1314 tcg_abort();
1315 ts->mem_offset = s->current_frame_offset;
1316 ts->mem_reg = s->frame_reg;
1317 ts->mem_allocated = 1;
1318 s->current_frame_offset += sizeof(tcg_target_long);
1321 /* free register 'reg' by spilling the corresponding temporary if necessary */
1322 static void tcg_reg_free(TCGContext *s, int reg)
1324 TCGTemp *ts;
1325 int temp;
1327 temp = s->reg_to_temp[reg];
1328 if (temp != -1) {
1329 ts = &s->temps[temp];
1330 assert(ts->val_type == TEMP_VAL_REG);
1331 if (!ts->mem_coherent) {
1332 if (!ts->mem_allocated)
1333 temp_allocate_frame(s, temp);
1334 tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1336 ts->val_type = TEMP_VAL_MEM;
1337 s->reg_to_temp[reg] = -1;
1341 /* Allocate a register belonging to reg1 & ~reg2 */
1342 static int tcg_reg_alloc(TCGContext *s, TCGRegSet reg1, TCGRegSet reg2)
1344 int i, reg;
1345 TCGRegSet reg_ct;
1347 tcg_regset_andnot(reg_ct, reg1, reg2);
1349 /* first try free registers */
1350 for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1351 reg = tcg_target_reg_alloc_order[i];
1352 if (tcg_regset_test_reg(reg_ct, reg) && s->reg_to_temp[reg] == -1)
1353 return reg;
1356 /* XXX: do better spill choice */
1357 for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1358 reg = tcg_target_reg_alloc_order[i];
1359 if (tcg_regset_test_reg(reg_ct, reg)) {
1360 tcg_reg_free(s, reg);
1361 return reg;
1365 tcg_abort();
1368 /* save a temporary to memory. 'allocated_regs' is used in case a
1369 temporary registers needs to be allocated to store a constant. */
1370 static void temp_save(TCGContext *s, int temp, TCGRegSet allocated_regs)
1372 TCGTemp *ts;
1373 int reg;
1375 ts = &s->temps[temp];
1376 if (!ts->fixed_reg) {
1377 switch(ts->val_type) {
1378 case TEMP_VAL_REG:
1379 tcg_reg_free(s, ts->reg);
1380 break;
1381 case TEMP_VAL_DEAD:
1382 ts->val_type = TEMP_VAL_MEM;
1383 break;
1384 case TEMP_VAL_CONST:
1385 reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type],
1386 allocated_regs);
1387 if (!ts->mem_allocated)
1388 temp_allocate_frame(s, temp);
1389 tcg_out_movi(s, ts->type, reg, ts->val);
1390 tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1391 ts->val_type = TEMP_VAL_MEM;
1392 break;
1393 case TEMP_VAL_MEM:
1394 break;
1395 default:
1396 tcg_abort();
1401 /* save globals to their cannonical location and assume they can be
1402 modified be the following code. 'allocated_regs' is used in case a
1403 temporary registers needs to be allocated to store a constant. */
1404 static void save_globals(TCGContext *s, TCGRegSet allocated_regs)
1406 int i;
1408 for(i = 0; i < s->nb_globals; i++) {
1409 temp_save(s, i, allocated_regs);
1413 /* at the end of a basic block, we assume all temporaries are dead and
1414 all globals are stored at their canonical location. */
1415 static void tcg_reg_alloc_bb_end(TCGContext *s, TCGRegSet allocated_regs)
1417 TCGTemp *ts;
1418 int i;
1420 for(i = s->nb_globals; i < s->nb_temps; i++) {
1421 ts = &s->temps[i];
1422 if (ts->temp_local) {
1423 temp_save(s, i, allocated_regs);
1424 } else {
1425 if (ts->val_type == TEMP_VAL_REG) {
1426 s->reg_to_temp[ts->reg] = -1;
1428 ts->val_type = TEMP_VAL_DEAD;
1432 save_globals(s, allocated_regs);
1435 #define IS_DEAD_IARG(n) ((dead_iargs >> (n)) & 1)
1437 static void tcg_reg_alloc_movi(TCGContext *s, const TCGArg *args)
1439 TCGTemp *ots;
1440 tcg_target_ulong val;
1442 ots = &s->temps[args[0]];
1443 val = args[1];
1445 if (ots->fixed_reg) {
1446 /* for fixed registers, we do not do any constant
1447 propagation */
1448 tcg_out_movi(s, ots->type, ots->reg, val);
1449 } else {
1450 /* The movi is not explicitly generated here */
1451 if (ots->val_type == TEMP_VAL_REG)
1452 s->reg_to_temp[ots->reg] = -1;
1453 ots->val_type = TEMP_VAL_CONST;
1454 ots->val = val;
1458 static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
1459 const TCGArg *args,
1460 unsigned int dead_iargs)
1462 TCGTemp *ts, *ots;
1463 int reg;
1464 const TCGArgConstraint *arg_ct;
1466 ots = &s->temps[args[0]];
1467 ts = &s->temps[args[1]];
1468 arg_ct = &def->args_ct[0];
1470 /* XXX: always mark arg dead if IS_DEAD_IARG(0) */
1471 if (ts->val_type == TEMP_VAL_REG) {
1472 if (IS_DEAD_IARG(0) && !ts->fixed_reg && !ots->fixed_reg) {
1473 /* the mov can be suppressed */
1474 if (ots->val_type == TEMP_VAL_REG)
1475 s->reg_to_temp[ots->reg] = -1;
1476 reg = ts->reg;
1477 s->reg_to_temp[reg] = -1;
1478 ts->val_type = TEMP_VAL_DEAD;
1479 } else {
1480 if (ots->val_type == TEMP_VAL_REG) {
1481 reg = ots->reg;
1482 } else {
1483 reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1485 if (ts->reg != reg) {
1486 tcg_out_mov(s, reg, ts->reg);
1489 } else if (ts->val_type == TEMP_VAL_MEM) {
1490 if (ots->val_type == TEMP_VAL_REG) {
1491 reg = ots->reg;
1492 } else {
1493 reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1495 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1496 } else if (ts->val_type == TEMP_VAL_CONST) {
1497 if (ots->fixed_reg) {
1498 reg = ots->reg;
1499 tcg_out_movi(s, ots->type, reg, ts->val);
1500 } else {
1501 /* propagate constant */
1502 if (ots->val_type == TEMP_VAL_REG)
1503 s->reg_to_temp[ots->reg] = -1;
1504 ots->val_type = TEMP_VAL_CONST;
1505 ots->val = ts->val;
1506 return;
1508 } else {
1509 tcg_abort();
1511 s->reg_to_temp[reg] = args[0];
1512 ots->reg = reg;
1513 ots->val_type = TEMP_VAL_REG;
1514 ots->mem_coherent = 0;
1517 static void tcg_reg_alloc_op(TCGContext *s,
1518 const TCGOpDef *def, int opc,
1519 const TCGArg *args,
1520 unsigned int dead_iargs)
1522 TCGRegSet allocated_regs;
1523 int i, k, nb_iargs, nb_oargs, reg;
1524 TCGArg arg;
1525 const TCGArgConstraint *arg_ct;
1526 TCGTemp *ts;
1527 TCGArg new_args[TCG_MAX_OP_ARGS];
1528 int const_args[TCG_MAX_OP_ARGS];
1530 nb_oargs = def->nb_oargs;
1531 nb_iargs = def->nb_iargs;
1533 /* copy constants */
1534 memcpy(new_args + nb_oargs + nb_iargs,
1535 args + nb_oargs + nb_iargs,
1536 sizeof(TCGArg) * def->nb_cargs);
1538 /* satisfy input constraints */
1539 tcg_regset_set(allocated_regs, s->reserved_regs);
1540 for(k = 0; k < nb_iargs; k++) {
1541 i = def->sorted_args[nb_oargs + k];
1542 arg = args[i];
1543 arg_ct = &def->args_ct[i];
1544 ts = &s->temps[arg];
1545 if (ts->val_type == TEMP_VAL_MEM) {
1546 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1547 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1548 ts->val_type = TEMP_VAL_REG;
1549 ts->reg = reg;
1550 ts->mem_coherent = 1;
1551 s->reg_to_temp[reg] = arg;
1552 } else if (ts->val_type == TEMP_VAL_CONST) {
1553 if (tcg_target_const_match(ts->val, arg_ct)) {
1554 /* constant is OK for instruction */
1555 const_args[i] = 1;
1556 new_args[i] = ts->val;
1557 goto iarg_end;
1558 } else {
1559 /* need to move to a register */
1560 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1561 tcg_out_movi(s, ts->type, reg, ts->val);
1562 ts->val_type = TEMP_VAL_REG;
1563 ts->reg = reg;
1564 ts->mem_coherent = 0;
1565 s->reg_to_temp[reg] = arg;
1568 assert(ts->val_type == TEMP_VAL_REG);
1569 if (arg_ct->ct & TCG_CT_IALIAS) {
1570 if (ts->fixed_reg) {
1571 /* if fixed register, we must allocate a new register
1572 if the alias is not the same register */
1573 if (arg != args[arg_ct->alias_index])
1574 goto allocate_in_reg;
1575 } else {
1576 /* if the input is aliased to an output and if it is
1577 not dead after the instruction, we must allocate
1578 a new register and move it */
1579 if (!IS_DEAD_IARG(i - nb_oargs))
1580 goto allocate_in_reg;
1583 reg = ts->reg;
1584 if (tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1585 /* nothing to do : the constraint is satisfied */
1586 } else {
1587 allocate_in_reg:
1588 /* allocate a new register matching the constraint
1589 and move the temporary register into it */
1590 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1591 tcg_out_mov(s, reg, ts->reg);
1593 new_args[i] = reg;
1594 const_args[i] = 0;
1595 tcg_regset_set_reg(allocated_regs, reg);
1596 iarg_end: ;
1599 if (def->flags & TCG_OPF_BB_END) {
1600 tcg_reg_alloc_bb_end(s, allocated_regs);
1601 } else {
1602 /* mark dead temporaries and free the associated registers */
1603 for(i = 0; i < nb_iargs; i++) {
1604 arg = args[nb_oargs + i];
1605 if (IS_DEAD_IARG(i)) {
1606 ts = &s->temps[arg];
1607 if (!ts->fixed_reg) {
1608 if (ts->val_type == TEMP_VAL_REG)
1609 s->reg_to_temp[ts->reg] = -1;
1610 ts->val_type = TEMP_VAL_DEAD;
1615 if (def->flags & TCG_OPF_CALL_CLOBBER) {
1616 /* XXX: permit generic clobber register list ? */
1617 for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1618 if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
1619 tcg_reg_free(s, reg);
1622 /* XXX: for load/store we could do that only for the slow path
1623 (i.e. when a memory callback is called) */
1625 /* store globals and free associated registers (we assume the insn
1626 can modify any global. */
1627 save_globals(s, allocated_regs);
1630 /* satisfy the output constraints */
1631 tcg_regset_set(allocated_regs, s->reserved_regs);
1632 for(k = 0; k < nb_oargs; k++) {
1633 i = def->sorted_args[k];
1634 arg = args[i];
1635 arg_ct = &def->args_ct[i];
1636 ts = &s->temps[arg];
1637 if (arg_ct->ct & TCG_CT_ALIAS) {
1638 reg = new_args[arg_ct->alias_index];
1639 } else {
1640 /* if fixed register, we try to use it */
1641 reg = ts->reg;
1642 if (ts->fixed_reg &&
1643 tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1644 goto oarg_end;
1646 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1648 tcg_regset_set_reg(allocated_regs, reg);
1649 /* if a fixed register is used, then a move will be done afterwards */
1650 if (!ts->fixed_reg) {
1651 if (ts->val_type == TEMP_VAL_REG)
1652 s->reg_to_temp[ts->reg] = -1;
1653 ts->val_type = TEMP_VAL_REG;
1654 ts->reg = reg;
1655 /* temp value is modified, so the value kept in memory is
1656 potentially not the same */
1657 ts->mem_coherent = 0;
1658 s->reg_to_temp[reg] = arg;
1660 oarg_end:
1661 new_args[i] = reg;
1665 /* emit instruction */
1666 tcg_out_op(s, opc, new_args, const_args);
1668 /* move the outputs in the correct register if needed */
1669 for(i = 0; i < nb_oargs; i++) {
1670 ts = &s->temps[args[i]];
1671 reg = new_args[i];
1672 if (ts->fixed_reg && ts->reg != reg) {
1673 tcg_out_mov(s, ts->reg, reg);
1678 #ifdef TCG_TARGET_STACK_GROWSUP
1679 #define STACK_DIR(x) (-(x))
1680 #else
1681 #define STACK_DIR(x) (x)
1682 #endif
1684 static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
1685 int opc, const TCGArg *args,
1686 unsigned int dead_iargs)
1688 int nb_iargs, nb_oargs, flags, nb_regs, i, reg, nb_params;
1689 TCGArg arg, func_arg;
1690 TCGTemp *ts;
1691 tcg_target_long stack_offset, call_stack_size, func_addr;
1692 int const_func_arg, allocate_args;
1693 TCGRegSet allocated_regs;
1694 const TCGArgConstraint *arg_ct;
1696 arg = *args++;
1698 nb_oargs = arg >> 16;
1699 nb_iargs = arg & 0xffff;
1700 nb_params = nb_iargs - 1;
1702 flags = args[nb_oargs + nb_iargs];
1704 nb_regs = tcg_target_get_call_iarg_regs_count(flags);
1705 if (nb_regs > nb_params)
1706 nb_regs = nb_params;
1708 /* assign stack slots first */
1709 /* XXX: preallocate call stack */
1710 call_stack_size = (nb_params - nb_regs) * sizeof(tcg_target_long);
1711 call_stack_size = (call_stack_size + TCG_TARGET_STACK_ALIGN - 1) &
1712 ~(TCG_TARGET_STACK_ALIGN - 1);
1713 allocate_args = (call_stack_size > TCG_STATIC_CALL_ARGS_SIZE);
1714 if (allocate_args) {
1715 tcg_out_addi(s, TCG_REG_CALL_STACK, -STACK_DIR(call_stack_size));
1718 stack_offset = TCG_TARGET_CALL_STACK_OFFSET;
1719 for(i = nb_regs; i < nb_params; i++) {
1720 arg = args[nb_oargs + i];
1721 #ifdef TCG_TARGET_STACK_GROWSUP
1722 stack_offset -= sizeof(tcg_target_long);
1723 #endif
1724 if (arg != TCG_CALL_DUMMY_ARG) {
1725 ts = &s->temps[arg];
1726 if (ts->val_type == TEMP_VAL_REG) {
1727 tcg_out_st(s, ts->type, ts->reg, TCG_REG_CALL_STACK, stack_offset);
1728 } else if (ts->val_type == TEMP_VAL_MEM) {
1729 reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type],
1730 s->reserved_regs);
1731 /* XXX: not correct if reading values from the stack */
1732 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1733 tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
1734 } else if (ts->val_type == TEMP_VAL_CONST) {
1735 reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type],
1736 s->reserved_regs);
1737 /* XXX: sign extend may be needed on some targets */
1738 tcg_out_movi(s, ts->type, reg, ts->val);
1739 tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
1740 } else {
1741 tcg_abort();
1744 #ifndef TCG_TARGET_STACK_GROWSUP
1745 stack_offset += sizeof(tcg_target_long);
1746 #endif
1749 /* assign input registers */
1750 tcg_regset_set(allocated_regs, s->reserved_regs);
1751 for(i = 0; i < nb_regs; i++) {
1752 arg = args[nb_oargs + i];
1753 if (arg != TCG_CALL_DUMMY_ARG) {
1754 ts = &s->temps[arg];
1755 reg = tcg_target_call_iarg_regs[i];
1756 tcg_reg_free(s, reg);
1757 if (ts->val_type == TEMP_VAL_REG) {
1758 if (ts->reg != reg) {
1759 tcg_out_mov(s, reg, ts->reg);
1761 } else if (ts->val_type == TEMP_VAL_MEM) {
1762 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1763 } else if (ts->val_type == TEMP_VAL_CONST) {
1764 /* XXX: sign extend ? */
1765 tcg_out_movi(s, ts->type, reg, ts->val);
1766 } else {
1767 tcg_abort();
1769 tcg_regset_set_reg(allocated_regs, reg);
1773 /* assign function address */
1774 func_arg = args[nb_oargs + nb_iargs - 1];
1775 arg_ct = &def->args_ct[0];
1776 ts = &s->temps[func_arg];
1777 func_addr = ts->val;
1778 const_func_arg = 0;
1779 if (ts->val_type == TEMP_VAL_MEM) {
1780 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1781 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1782 func_arg = reg;
1783 tcg_regset_set_reg(allocated_regs, reg);
1784 } else if (ts->val_type == TEMP_VAL_REG) {
1785 reg = ts->reg;
1786 if (!tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1787 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1788 tcg_out_mov(s, reg, ts->reg);
1790 func_arg = reg;
1791 tcg_regset_set_reg(allocated_regs, reg);
1792 } else if (ts->val_type == TEMP_VAL_CONST) {
1793 if (tcg_target_const_match(func_addr, arg_ct)) {
1794 const_func_arg = 1;
1795 func_arg = func_addr;
1796 } else {
1797 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1798 tcg_out_movi(s, ts->type, reg, func_addr);
1799 func_arg = reg;
1800 tcg_regset_set_reg(allocated_regs, reg);
1802 } else {
1803 tcg_abort();
1807 /* mark dead temporaries and free the associated registers */
1808 for(i = 0; i < nb_iargs; i++) {
1809 arg = args[nb_oargs + i];
1810 if (IS_DEAD_IARG(i)) {
1811 ts = &s->temps[arg];
1812 if (!ts->fixed_reg) {
1813 if (ts->val_type == TEMP_VAL_REG)
1814 s->reg_to_temp[ts->reg] = -1;
1815 ts->val_type = TEMP_VAL_DEAD;
1820 /* clobber call registers */
1821 for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1822 if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
1823 tcg_reg_free(s, reg);
1827 /* store globals and free associated registers (we assume the call
1828 can modify any global. */
1829 if (!(flags & TCG_CALL_CONST)) {
1830 save_globals(s, allocated_regs);
1833 tcg_out_op(s, opc, &func_arg, &const_func_arg);
1835 if (allocate_args) {
1836 tcg_out_addi(s, TCG_REG_CALL_STACK, STACK_DIR(call_stack_size));
1839 /* assign output registers and emit moves if needed */
1840 for(i = 0; i < nb_oargs; i++) {
1841 arg = args[i];
1842 ts = &s->temps[arg];
1843 reg = tcg_target_call_oarg_regs[i];
1844 assert(s->reg_to_temp[reg] == -1);
1845 if (ts->fixed_reg) {
1846 if (ts->reg != reg) {
1847 tcg_out_mov(s, ts->reg, reg);
1849 } else {
1850 if (ts->val_type == TEMP_VAL_REG)
1851 s->reg_to_temp[ts->reg] = -1;
1852 ts->val_type = TEMP_VAL_REG;
1853 ts->reg = reg;
1854 ts->mem_coherent = 0;
1855 s->reg_to_temp[reg] = arg;
1859 return nb_iargs + nb_oargs + def->nb_cargs + 1;
1862 #ifdef CONFIG_PROFILER
1864 static int64_t tcg_table_op_count[NB_OPS];
1866 void dump_op_count(void)
1868 int i;
1869 FILE *f;
1870 f = fopen("/tmp/op.log", "w");
1871 for(i = INDEX_op_end; i < NB_OPS; i++) {
1872 fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name, tcg_table_op_count[i]);
1874 fclose(f);
1876 #endif
1879 static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
1880 long search_pc)
1882 int opc, op_index;
1883 const TCGOpDef *def;
1884 unsigned int dead_iargs;
1885 const TCGArg *args;
1887 #ifdef DEBUG_DISAS
1888 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
1889 qemu_log("OP:\n");
1890 tcg_dump_ops(s, logfile);
1891 qemu_log("\n");
1893 #endif
1895 #ifdef CONFIG_PROFILER
1896 s->la_time -= profile_getclock();
1897 #endif
1898 tcg_liveness_analysis(s);
1899 #ifdef CONFIG_PROFILER
1900 s->la_time += profile_getclock();
1901 #endif
1903 #ifdef DEBUG_DISAS
1904 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_OPT))) {
1905 qemu_log("OP after la:\n");
1906 tcg_dump_ops(s, logfile);
1907 qemu_log("\n");
1909 #endif
1911 tcg_reg_alloc_start(s);
1913 s->code_buf = gen_code_buf;
1914 s->code_ptr = gen_code_buf;
1916 args = gen_opparam_buf;
1917 op_index = 0;
1919 for(;;) {
1920 opc = gen_opc_buf[op_index];
1921 #ifdef CONFIG_PROFILER
1922 tcg_table_op_count[opc]++;
1923 #endif
1924 def = &tcg_op_defs[opc];
1925 #if 0
1926 printf("%s: %d %d %d\n", def->name,
1927 def->nb_oargs, def->nb_iargs, def->nb_cargs);
1928 // dump_regs(s);
1929 #endif
1930 switch(opc) {
1931 case INDEX_op_mov_i32:
1932 #if TCG_TARGET_REG_BITS == 64
1933 case INDEX_op_mov_i64:
1934 #endif
1935 dead_iargs = s->op_dead_iargs[op_index];
1936 tcg_reg_alloc_mov(s, def, args, dead_iargs);
1937 break;
1938 case INDEX_op_movi_i32:
1939 #if TCG_TARGET_REG_BITS == 64
1940 case INDEX_op_movi_i64:
1941 #endif
1942 tcg_reg_alloc_movi(s, args);
1943 break;
1944 case INDEX_op_debug_insn_start:
1945 /* debug instruction */
1946 break;
1947 case INDEX_op_nop:
1948 case INDEX_op_nop1:
1949 case INDEX_op_nop2:
1950 case INDEX_op_nop3:
1951 break;
1952 case INDEX_op_nopn:
1953 args += args[0];
1954 goto next;
1955 case INDEX_op_discard:
1957 TCGTemp *ts;
1958 ts = &s->temps[args[0]];
1959 /* mark the temporary as dead */
1960 if (!ts->fixed_reg) {
1961 if (ts->val_type == TEMP_VAL_REG)
1962 s->reg_to_temp[ts->reg] = -1;
1963 ts->val_type = TEMP_VAL_DEAD;
1966 break;
1967 case INDEX_op_set_label:
1968 tcg_reg_alloc_bb_end(s, s->reserved_regs);
1969 tcg_out_label(s, args[0], (long)s->code_ptr);
1970 break;
1971 case INDEX_op_call:
1972 dead_iargs = s->op_dead_iargs[op_index];
1973 args += tcg_reg_alloc_call(s, def, opc, args, dead_iargs);
1974 goto next;
1975 case INDEX_op_end:
1976 goto the_end;
1977 default:
1978 /* Note: in order to speed up the code, it would be much
1979 faster to have specialized register allocator functions for
1980 some common argument patterns */
1981 dead_iargs = s->op_dead_iargs[op_index];
1982 tcg_reg_alloc_op(s, def, opc, args, dead_iargs);
1983 break;
1985 args += def->nb_args;
1986 next:
1987 if (search_pc >= 0 && search_pc < s->code_ptr - gen_code_buf) {
1988 return op_index;
1990 op_index++;
1991 #ifndef NDEBUG
1992 check_regs(s);
1993 #endif
1995 the_end:
1996 return -1;
1999 int tcg_gen_code(TCGContext *s, uint8_t *gen_code_buf)
2001 #ifdef CONFIG_PROFILER
2003 int n;
2004 n = (gen_opc_ptr - gen_opc_buf);
2005 s->op_count += n;
2006 if (n > s->op_count_max)
2007 s->op_count_max = n;
2009 s->temp_count += s->nb_temps;
2010 if (s->nb_temps > s->temp_count_max)
2011 s->temp_count_max = s->nb_temps;
2013 #endif
2015 tcg_gen_code_common(s, gen_code_buf, -1);
2017 /* flush instruction cache */
2018 flush_icache_range((unsigned long)gen_code_buf,
2019 (unsigned long)s->code_ptr);
2020 return s->code_ptr - gen_code_buf;
2023 /* Return the index of the micro operation such as the pc after is <
2024 offset bytes from the start of the TB. The contents of gen_code_buf must
2025 not be changed, though writing the same values is ok.
2026 Return -1 if not found. */
2027 int tcg_gen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, long offset)
2029 return tcg_gen_code_common(s, gen_code_buf, offset);
2032 #ifdef CONFIG_PROFILER
2033 void tcg_dump_info(FILE *f,
2034 int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
2036 TCGContext *s = &tcg_ctx;
2037 int64_t tot;
2039 tot = s->interm_time + s->code_time;
2040 cpu_fprintf(f, "JIT cycles %" PRId64 " (%0.3f s at 2.4 GHz)\n",
2041 tot, tot / 2.4e9);
2042 cpu_fprintf(f, "translated TBs %" PRId64 " (aborted=%" PRId64 " %0.1f%%)\n",
2043 s->tb_count,
2044 s->tb_count1 - s->tb_count,
2045 s->tb_count1 ? (double)(s->tb_count1 - s->tb_count) / s->tb_count1 * 100.0 : 0);
2046 cpu_fprintf(f, "avg ops/TB %0.1f max=%d\n",
2047 s->tb_count ? (double)s->op_count / s->tb_count : 0, s->op_count_max);
2048 cpu_fprintf(f, "deleted ops/TB %0.2f\n",
2049 s->tb_count ?
2050 (double)s->del_op_count / s->tb_count : 0);
2051 cpu_fprintf(f, "avg temps/TB %0.2f max=%d\n",
2052 s->tb_count ?
2053 (double)s->temp_count / s->tb_count : 0,
2054 s->temp_count_max);
2056 cpu_fprintf(f, "cycles/op %0.1f\n",
2057 s->op_count ? (double)tot / s->op_count : 0);
2058 cpu_fprintf(f, "cycles/in byte %0.1f\n",
2059 s->code_in_len ? (double)tot / s->code_in_len : 0);
2060 cpu_fprintf(f, "cycles/out byte %0.1f\n",
2061 s->code_out_len ? (double)tot / s->code_out_len : 0);
2062 if (tot == 0)
2063 tot = 1;
2064 cpu_fprintf(f, " gen_interm time %0.1f%%\n",
2065 (double)s->interm_time / tot * 100.0);
2066 cpu_fprintf(f, " gen_code time %0.1f%%\n",
2067 (double)s->code_time / tot * 100.0);
2068 cpu_fprintf(f, "liveness/code time %0.1f%%\n",
2069 (double)s->la_time / (s->code_time ? s->code_time : 1) * 100.0);
2070 cpu_fprintf(f, "cpu_restore count %" PRId64 "\n",
2071 s->restore_count);
2072 cpu_fprintf(f, " avg cycles %0.1f\n",
2073 s->restore_count ? (double)s->restore_time / s->restore_count : 0);
2075 extern void dump_op_count(void);
2076 dump_op_count();
2079 #else
2080 void tcg_dump_info(FILE *f,
2081 int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
2083 cpu_fprintf(f, "[TCG profiler not compiled]\n");
2085 #endif