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
25 /* define it to suppress various consistency checks (faster) */
28 /* define it to use liveness analysis (better code) */
29 #define USE_LIVENESS_ANALYSIS
42 #include "qemu-common.h"
44 /* Note: the long term plan is to reduce the dependancies on the QEMU
45 CPU definitions. Currently they are used for qemu_ld/st
47 #define NO_CPU_IO_DEFS
55 static void patch_reloc(uint8_t *code_ptr, int type,
56 tcg_target_long value, tcg_target_long addend);
58 TCGOpDef tcg_op_defs[] = {
59 #define DEF(s, n, copy_size) { #s, 0, 0, n, n, 0, copy_size },
60 #define DEF2(s, iargs, oargs, cargs, flags) { #s, iargs, oargs, cargs, iargs + oargs + cargs, flags, 0 },
66 TCGRegSet tcg_target_available_regs[2];
67 TCGRegSet tcg_target_call_clobber_regs;
69 /* XXX: move that inside the context */
70 uint16_t *gen_opc_ptr;
71 TCGArg *gen_opparam_ptr;
73 static inline void tcg_out8(TCGContext *s, uint8_t v)
78 static inline void tcg_out16(TCGContext *s, uint16_t v)
80 *(uint16_t *)s->code_ptr = v;
84 static inline void tcg_out32(TCGContext *s, uint32_t v)
86 *(uint32_t *)s->code_ptr = v;
90 /* label relocation processing */
92 void tcg_out_reloc(TCGContext *s, uint8_t *code_ptr, int type,
93 int label_index, long addend)
98 l = &s->labels[label_index];
100 /* FIXME: This may break relocations on RISC targets that
101 modify instruction fields in place. The caller may not have
102 written the initial value. */
103 patch_reloc(code_ptr, type, l->u.value, addend);
105 /* add a new relocation entry */
106 r = tcg_malloc(sizeof(TCGRelocation));
110 r->next = l->u.first_reloc;
111 l->u.first_reloc = r;
115 static void tcg_out_label(TCGContext *s, int label_index,
116 tcg_target_long value)
121 l = &s->labels[label_index];
124 r = l->u.first_reloc;
126 patch_reloc(r->ptr, r->type, value, r->addend);
133 int gen_new_label(void)
135 TCGContext *s = &tcg_ctx;
139 if (s->nb_labels >= TCG_MAX_LABELS)
141 idx = s->nb_labels++;
144 l->u.first_reloc = NULL;
148 #include "tcg-target.c"
150 /* pool based memory allocation */
151 void *tcg_malloc_internal(TCGContext *s, int size)
156 if (size > TCG_POOL_CHUNK_SIZE) {
157 /* big malloc: insert a new pool (XXX: could optimize) */
158 p = qemu_malloc(sizeof(TCGPool) + size);
161 s->pool_current->next = p;
164 p->next = s->pool_current;
174 pool_size = TCG_POOL_CHUNK_SIZE;
175 p = qemu_malloc(sizeof(TCGPool) + pool_size);
179 s->pool_current->next = p;
188 s->pool_cur = p->data + size;
189 s->pool_end = p->data + p->size;
193 void tcg_pool_reset(TCGContext *s)
195 s->pool_cur = s->pool_end = NULL;
196 s->pool_current = NULL;
199 /* free all the pool */
200 void tcg_pool_free(TCGContext *s)
204 for(p = s->pool_first; p != NULL; p = p1) {
208 s->pool_first = NULL;
209 s->pool_cur = s->pool_end = NULL;
212 void tcg_context_init(TCGContext *s)
214 int op, total_args, n;
216 TCGArgConstraint *args_ct;
219 memset(s, 0, sizeof(*s));
220 s->temps = s->static_temps;
223 /* Count total number of arguments and allocate the corresponding
226 for(op = 0; op < NB_OPS; op++) {
227 def = &tcg_op_defs[op];
228 n = def->nb_iargs + def->nb_oargs;
232 args_ct = qemu_malloc(sizeof(TCGArgConstraint) * total_args);
233 sorted_args = qemu_malloc(sizeof(int) * total_args);
235 for(op = 0; op < NB_OPS; op++) {
236 def = &tcg_op_defs[op];
237 def->args_ct = args_ct;
238 def->sorted_args = sorted_args;
239 n = def->nb_iargs + def->nb_oargs;
246 /* init global prologue and epilogue */
247 s->code_buf = code_gen_prologue;
248 s->code_ptr = s->code_buf;
249 tcg_target_qemu_prologue(s);
250 flush_icache_range((unsigned long)s->code_buf,
251 (unsigned long)s->code_ptr);
254 void tcg_set_frame(TCGContext *s, int reg,
255 tcg_target_long start, tcg_target_long size)
257 s->frame_start = start;
258 s->frame_end = start + size;
262 void tcg_set_macro_func(TCGContext *s, TCGMacroFunc *func)
264 s->macro_func = func;
267 void tcg_func_start(TCGContext *s)
271 s->nb_temps = s->nb_globals;
272 for(i = 0; i < (TCG_TYPE_COUNT * 2); i++)
273 s->first_free_temp[i] = -1;
274 s->labels = tcg_malloc(sizeof(TCGLabel) * TCG_MAX_LABELS);
276 s->current_frame_offset = s->frame_start;
278 gen_opc_ptr = gen_opc_buf;
279 gen_opparam_ptr = gen_opparam_buf;
282 static inline void tcg_temp_alloc(TCGContext *s, int n)
284 if (n > TCG_MAX_TEMPS)
288 TCGv tcg_global_reg_new(TCGType type, int reg, const char *name)
290 TCGContext *s = &tcg_ctx;
294 #if TCG_TARGET_REG_BITS == 32
295 if (type != TCG_TYPE_I32)
298 if (tcg_regset_test_reg(s->reserved_regs, reg))
301 tcg_temp_alloc(s, s->nb_globals + 1);
302 ts = &s->temps[s->nb_globals];
303 ts->base_type = type;
309 tcg_regset_set_reg(s->reserved_regs, reg);
310 return MAKE_TCGV(idx);
313 #if TCG_TARGET_REG_BITS == 32
314 /* temporary hack to avoid register shortage for tcg_qemu_st64() */
315 TCGv tcg_global_reg2_new_hack(TCGType type, int reg1, int reg2,
318 TCGContext *s = &tcg_ctx;
323 if (type != TCG_TYPE_I64)
326 tcg_temp_alloc(s, s->nb_globals + 2);
327 ts = &s->temps[s->nb_globals];
328 ts->base_type = type;
329 ts->type = TCG_TYPE_I32;
332 pstrcpy(buf, sizeof(buf), name);
333 pstrcat(buf, sizeof(buf), "_0");
334 ts->name = strdup(buf);
337 ts->base_type = type;
338 ts->type = TCG_TYPE_I32;
341 pstrcpy(buf, sizeof(buf), name);
342 pstrcat(buf, sizeof(buf), "_1");
343 ts->name = strdup(buf);
346 return MAKE_TCGV(idx);
350 TCGv tcg_global_mem_new(TCGType type, int reg, tcg_target_long offset,
353 TCGContext *s = &tcg_ctx;
358 #if TCG_TARGET_REG_BITS == 32
359 if (type == TCG_TYPE_I64) {
361 tcg_temp_alloc(s, s->nb_globals + 1);
362 ts = &s->temps[s->nb_globals];
363 ts->base_type = type;
364 ts->type = TCG_TYPE_I32;
366 ts->mem_allocated = 1;
368 #ifdef TCG_TARGET_WORDS_BIGENDIAN
369 ts->mem_offset = offset + 4;
371 ts->mem_offset = offset;
373 pstrcpy(buf, sizeof(buf), name);
374 pstrcat(buf, sizeof(buf), "_0");
375 ts->name = strdup(buf);
378 ts->base_type = type;
379 ts->type = TCG_TYPE_I32;
381 ts->mem_allocated = 1;
383 #ifdef TCG_TARGET_WORDS_BIGENDIAN
384 ts->mem_offset = offset;
386 ts->mem_offset = offset + 4;
388 pstrcpy(buf, sizeof(buf), name);
389 pstrcat(buf, sizeof(buf), "_1");
390 ts->name = strdup(buf);
396 tcg_temp_alloc(s, s->nb_globals + 1);
397 ts = &s->temps[s->nb_globals];
398 ts->base_type = type;
401 ts->mem_allocated = 1;
403 ts->mem_offset = offset;
407 return MAKE_TCGV(idx);
410 TCGv tcg_temp_new_internal(TCGType type, int temp_local)
412 TCGContext *s = &tcg_ctx;
419 idx = s->first_free_temp[k];
421 /* There is already an available temp with the
424 s->first_free_temp[k] = ts->next_free_temp;
425 ts->temp_allocated = 1;
426 assert(ts->temp_local == temp_local);
429 #if TCG_TARGET_REG_BITS == 32
430 if (type == TCG_TYPE_I64) {
431 tcg_temp_alloc(s, s->nb_temps + 1);
432 ts = &s->temps[s->nb_temps];
433 ts->base_type = type;
434 ts->type = TCG_TYPE_I32;
435 ts->temp_allocated = 1;
436 ts->temp_local = temp_local;
439 ts->base_type = TCG_TYPE_I32;
440 ts->type = TCG_TYPE_I32;
441 ts->temp_allocated = 1;
442 ts->temp_local = temp_local;
448 tcg_temp_alloc(s, s->nb_temps + 1);
449 ts = &s->temps[s->nb_temps];
450 ts->base_type = type;
452 ts->temp_allocated = 1;
453 ts->temp_local = temp_local;
458 return MAKE_TCGV(idx);
461 void tcg_temp_free(TCGv arg)
463 TCGContext *s = &tcg_ctx;
465 int idx = GET_TCGV(arg);
468 assert(idx >= s->nb_globals && idx < s->nb_temps);
470 assert(ts->temp_allocated != 0);
471 ts->temp_allocated = 0;
475 ts->next_free_temp = s->first_free_temp[k];
476 s->first_free_temp[k] = idx;
480 TCGv tcg_const_i32(int32_t val)
483 t0 = tcg_temp_new(TCG_TYPE_I32);
484 tcg_gen_movi_i32(t0, val);
488 TCGv tcg_const_i64(int64_t val)
491 t0 = tcg_temp_new(TCG_TYPE_I64);
492 tcg_gen_movi_i64(t0, val);
496 void tcg_register_helper(void *func, const char *name)
498 TCGContext *s = &tcg_ctx;
500 if ((s->nb_helpers + 1) > s->allocated_helpers) {
501 n = s->allocated_helpers;
507 s->helpers = realloc(s->helpers, n * sizeof(TCGHelperInfo));
508 s->allocated_helpers = n;
510 s->helpers[s->nb_helpers].func = (tcg_target_ulong)func;
511 s->helpers[s->nb_helpers].name = name;
515 static inline TCGType tcg_get_base_type(TCGContext *s, TCGv arg)
517 return s->temps[GET_TCGV(arg)].base_type;
520 static void tcg_gen_call_internal(TCGContext *s, TCGv func,
522 unsigned int nb_rets, const TCGv *rets,
523 unsigned int nb_params, const TCGv *params)
526 *gen_opc_ptr++ = INDEX_op_call;
527 *gen_opparam_ptr++ = (nb_rets << 16) | (nb_params + 1);
528 for(i = 0; i < nb_rets; i++) {
529 *gen_opparam_ptr++ = GET_TCGV(rets[i]);
531 for(i = 0; i < nb_params; i++) {
532 *gen_opparam_ptr++ = GET_TCGV(params[i]);
534 *gen_opparam_ptr++ = GET_TCGV(func);
536 *gen_opparam_ptr++ = flags;
537 /* total parameters, needed to go backward in the instruction stream */
538 *gen_opparam_ptr++ = 1 + nb_rets + nb_params + 3;
542 #if TCG_TARGET_REG_BITS < 64
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_call(TCGContext *s, TCGv func, unsigned int flags,
547 unsigned int nb_rets, const TCGv *rets,
548 unsigned int nb_params, const TCGv *args1)
550 TCGv ret, *args2, rets_2[2], arg;
555 if (tcg_get_base_type(s, ret) == TCG_TYPE_I64) {
557 #ifdef TCG_TARGET_WORDS_BIGENDIAN
558 rets_2[0] = TCGV_HIGH(ret);
562 rets_2[1] = TCGV_HIGH(ret);
567 args2 = alloca((nb_params * 3) * sizeof(TCGv));
569 call_type = (flags & TCG_CALL_TYPE_MASK);
570 for(i = 0; i < nb_params; i++) {
572 if (tcg_get_base_type(s, arg) == TCG_TYPE_I64) {
573 #ifdef TCG_TARGET_I386
574 /* REGPARM case: if the third parameter is 64 bit, it is
575 allocated on the stack */
576 if (j == 2 && call_type == TCG_CALL_TYPE_REGPARM) {
577 call_type = TCG_CALL_TYPE_REGPARM_2;
578 flags = (flags & ~TCG_CALL_TYPE_MASK) | call_type;
581 args2[j++] = TCGV_HIGH(arg);
583 #ifdef TCG_TARGET_CALL_ALIGN_ARGS
584 /* some targets want aligned 64 bit args */
586 args2[j++] = TCG_CALL_DUMMY_ARG;
589 #ifdef TCG_TARGET_WORDS_BIGENDIAN
590 args2[j++] = TCGV_HIGH(arg);
594 args2[j++] = TCGV_HIGH(arg);
601 tcg_gen_call_internal(s, func, flags,
602 nb_rets, rets, j, args2);
605 void tcg_gen_call(TCGContext *s, TCGv func, unsigned int flags,
606 unsigned int nb_rets, const TCGv *rets,
607 unsigned int nb_params, const TCGv *args1)
609 tcg_gen_call_internal(s, func, flags,
610 nb_rets, rets, nb_params, args1);
614 #if TCG_TARGET_REG_BITS == 32
615 void tcg_gen_shifti_i64(TCGv ret, TCGv arg1,
616 int c, int right, int arith)
619 tcg_gen_mov_i32(ret, arg1);
620 tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
621 } else if (c >= 32) {
625 tcg_gen_sari_i32(ret, TCGV_HIGH(arg1), c);
626 tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 31);
628 tcg_gen_shri_i32(ret, TCGV_HIGH(arg1), c);
629 tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
632 tcg_gen_shli_i32(TCGV_HIGH(ret), arg1, c);
633 tcg_gen_movi_i32(ret, 0);
638 t0 = tcg_temp_new(TCG_TYPE_I32);
639 t1 = tcg_temp_new(TCG_TYPE_I32);
641 tcg_gen_shli_i32(t0, TCGV_HIGH(arg1), 32 - c);
643 tcg_gen_sari_i32(t1, TCGV_HIGH(arg1), c);
645 tcg_gen_shri_i32(t1, TCGV_HIGH(arg1), c);
646 tcg_gen_shri_i32(ret, arg1, c);
647 tcg_gen_or_i32(ret, ret, t0);
648 tcg_gen_mov_i32(TCGV_HIGH(ret), t1);
650 tcg_gen_shri_i32(t0, arg1, 32 - c);
651 /* Note: ret can be the same as arg1, so we use t1 */
652 tcg_gen_shli_i32(t1, arg1, c);
653 tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c);
654 tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t0);
655 tcg_gen_mov_i32(ret, t1);
663 void tcg_reg_alloc_start(TCGContext *s)
667 for(i = 0; i < s->nb_globals; i++) {
670 ts->val_type = TEMP_VAL_REG;
672 ts->val_type = TEMP_VAL_MEM;
675 for(i = s->nb_globals; i < s->nb_temps; i++) {
677 ts->val_type = TEMP_VAL_DEAD;
678 ts->mem_allocated = 0;
681 for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
682 s->reg_to_temp[i] = -1;
686 static char *tcg_get_arg_str_idx(TCGContext *s, char *buf, int buf_size,
692 if (idx < s->nb_globals) {
693 pstrcpy(buf, buf_size, ts->name);
696 snprintf(buf, buf_size, "loc%d", idx - s->nb_globals);
698 snprintf(buf, buf_size, "tmp%d", idx - s->nb_globals);
703 char *tcg_get_arg_str(TCGContext *s, char *buf, int buf_size, TCGv arg)
705 return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV(arg));
708 static int helper_cmp(const void *p1, const void *p2)
710 const TCGHelperInfo *th1 = p1;
711 const TCGHelperInfo *th2 = p2;
712 if (th1->func < th2->func)
714 else if (th1->func == th2->func)
720 /* find helper definition (Note: A hash table would be better) */
721 static TCGHelperInfo *tcg_find_helper(TCGContext *s, tcg_target_ulong val)
727 if (unlikely(!s->helpers_sorted)) {
728 qsort(s->helpers, s->nb_helpers, sizeof(TCGHelperInfo),
730 s->helpers_sorted = 1;
735 m_max = s->nb_helpers - 1;
736 while (m_min <= m_max) {
737 m = (m_min + m_max) >> 1;
751 void tcg_dump_ops(TCGContext *s, FILE *outfile)
753 const uint16_t *opc_ptr;
756 int c, i, k, nb_oargs, nb_iargs, nb_cargs, first_insn;
761 opc_ptr = gen_opc_buf;
762 args = gen_opparam_buf;
763 while (opc_ptr < gen_opc_ptr) {
765 def = &tcg_op_defs[c];
766 if (c == INDEX_op_debug_insn_start) {
768 #if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
769 pc = ((uint64_t)args[1] << 32) | args[0];
774 fprintf(outfile, "\n");
775 fprintf(outfile, " ---- 0x%" PRIx64, pc);
777 nb_oargs = def->nb_oargs;
778 nb_iargs = def->nb_iargs;
779 nb_cargs = def->nb_cargs;
780 } else if (c == INDEX_op_call) {
783 /* variable number of arguments */
785 nb_oargs = arg >> 16;
786 nb_iargs = arg & 0xffff;
787 nb_cargs = def->nb_cargs;
789 fprintf(outfile, " %s ", def->name);
792 fprintf(outfile, "%s",
793 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + nb_iargs - 1]));
795 fprintf(outfile, ",$0x%" TCG_PRIlx,
796 args[nb_oargs + nb_iargs]);
798 fprintf(outfile, ",$%d", nb_oargs);
799 for(i = 0; i < nb_oargs; i++) {
800 fprintf(outfile, ",");
801 fprintf(outfile, "%s",
802 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[i]));
804 for(i = 0; i < (nb_iargs - 1); i++) {
805 fprintf(outfile, ",");
806 if (args[nb_oargs + i] == TCG_CALL_DUMMY_ARG) {
807 fprintf(outfile, "<dummy>");
809 fprintf(outfile, "%s",
810 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + i]));
813 } else if (c == INDEX_op_movi_i32
814 #if TCG_TARGET_REG_BITS == 64
815 || c == INDEX_op_movi_i64
818 tcg_target_ulong val;
821 nb_oargs = def->nb_oargs;
822 nb_iargs = def->nb_iargs;
823 nb_cargs = def->nb_cargs;
824 fprintf(outfile, " %s %s,$", def->name,
825 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[0]));
827 th = tcg_find_helper(s, val);
829 fprintf(outfile, th->name);
831 if (c == INDEX_op_movi_i32)
832 fprintf(outfile, "0x%x", (uint32_t)val);
834 fprintf(outfile, "0x%" PRIx64 , (uint64_t)val);
837 fprintf(outfile, " %s ", def->name);
838 if (c == INDEX_op_nopn) {
839 /* variable number of arguments */
844 nb_oargs = def->nb_oargs;
845 nb_iargs = def->nb_iargs;
846 nb_cargs = def->nb_cargs;
850 for(i = 0; i < nb_oargs; i++) {
852 fprintf(outfile, ",");
853 fprintf(outfile, "%s",
854 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
856 for(i = 0; i < nb_iargs; i++) {
858 fprintf(outfile, ",");
859 fprintf(outfile, "%s",
860 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
862 for(i = 0; i < nb_cargs; i++) {
864 fprintf(outfile, ",");
866 fprintf(outfile, "$0x%" TCG_PRIlx, arg);
869 fprintf(outfile, "\n");
870 args += nb_iargs + nb_oargs + nb_cargs;
874 /* we give more priority to constraints with less registers */
875 static int get_constraint_priority(const TCGOpDef *def, int k)
877 const TCGArgConstraint *arg_ct;
880 arg_ct = &def->args_ct[k];
881 if (arg_ct->ct & TCG_CT_ALIAS) {
882 /* an alias is equivalent to a single register */
885 if (!(arg_ct->ct & TCG_CT_REG))
888 for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
889 if (tcg_regset_test_reg(arg_ct->u.regs, i))
893 return TCG_TARGET_NB_REGS - n + 1;
896 /* sort from highest priority to lowest */
897 static void sort_constraints(TCGOpDef *def, int start, int n)
899 int i, j, p1, p2, tmp;
901 for(i = 0; i < n; i++)
902 def->sorted_args[start + i] = start + i;
905 for(i = 0; i < n - 1; i++) {
906 for(j = i + 1; j < n; j++) {
907 p1 = get_constraint_priority(def, def->sorted_args[start + i]);
908 p2 = get_constraint_priority(def, def->sorted_args[start + j]);
910 tmp = def->sorted_args[start + i];
911 def->sorted_args[start + i] = def->sorted_args[start + j];
912 def->sorted_args[start + j] = tmp;
918 void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs)
929 assert(op >= 0 && op < NB_OPS);
930 def = &tcg_op_defs[op];
931 nb_args = def->nb_iargs + def->nb_oargs;
932 for(i = 0; i < nb_args; i++) {
933 ct_str = tdefs->args_ct_str[i];
934 tcg_regset_clear(def->args_ct[i].u.regs);
935 def->args_ct[i].ct = 0;
936 if (ct_str[0] >= '0' && ct_str[0] <= '9') {
938 oarg = ct_str[0] - '0';
939 assert(oarg < def->nb_oargs);
940 assert(def->args_ct[oarg].ct & TCG_CT_REG);
941 /* TCG_CT_ALIAS is for the output arguments. The input
942 argument is tagged with TCG_CT_IALIAS. */
943 def->args_ct[i] = def->args_ct[oarg];
944 def->args_ct[oarg].ct = TCG_CT_ALIAS;
945 def->args_ct[oarg].alias_index = i;
946 def->args_ct[i].ct |= TCG_CT_IALIAS;
947 def->args_ct[i].alias_index = oarg;
954 def->args_ct[i].ct |= TCG_CT_CONST;
958 if (target_parse_constraint(&def->args_ct[i], &ct_str) < 0) {
959 fprintf(stderr, "Invalid constraint '%s' for arg %d of operation '%s'\n",
960 ct_str, i, def->name);
968 /* sort the constraints (XXX: this is just an heuristic) */
969 sort_constraints(def, 0, def->nb_oargs);
970 sort_constraints(def, def->nb_oargs, def->nb_iargs);
976 printf("%s: sorted=", def->name);
977 for(i = 0; i < def->nb_oargs + def->nb_iargs; i++)
978 printf(" %d", def->sorted_args[i]);
987 #ifdef USE_LIVENESS_ANALYSIS
989 /* set a nop for an operation using 'nb_args' */
990 static inline void tcg_set_nop(TCGContext *s, uint16_t *opc_ptr,
991 TCGArg *args, int nb_args)
994 *opc_ptr = INDEX_op_nop;
996 *opc_ptr = INDEX_op_nopn;
998 args[nb_args - 1] = nb_args;
1002 /* liveness analysis: end of function: globals are live, temps are
1004 /* XXX: at this stage, not used as there would be little gains because
1005 most TBs end with a conditional jump. */
1006 static inline void tcg_la_func_end(TCGContext *s, uint8_t *dead_temps)
1008 memset(dead_temps, 0, s->nb_globals);
1009 memset(dead_temps + s->nb_globals, 1, s->nb_temps - s->nb_globals);
1012 /* liveness analysis: end of basic block: globals are live, temps are
1013 dead, local temps are live. */
1014 static inline void tcg_la_bb_end(TCGContext *s, uint8_t *dead_temps)
1019 memset(dead_temps, 0, s->nb_globals);
1020 ts = &s->temps[s->nb_globals];
1021 for(i = s->nb_globals; i < s->nb_temps; i++) {
1030 /* Liveness analysis : update the opc_dead_iargs array to tell if a
1031 given input arguments is dead. Instructions updating dead
1032 temporaries are removed. */
1033 void tcg_liveness_analysis(TCGContext *s)
1035 int i, op_index, op, nb_args, nb_iargs, nb_oargs, arg, nb_ops;
1037 const TCGOpDef *def;
1038 uint8_t *dead_temps;
1039 unsigned int dead_iargs;
1041 gen_opc_ptr++; /* skip end */
1043 nb_ops = gen_opc_ptr - gen_opc_buf;
1045 /* XXX: make it really dynamic */
1046 s->op_dead_iargs = tcg_malloc(OPC_BUF_SIZE * sizeof(uint16_t));
1048 dead_temps = tcg_malloc(s->nb_temps);
1049 memset(dead_temps, 1, s->nb_temps);
1051 args = gen_opparam_ptr;
1052 op_index = nb_ops - 1;
1053 while (op_index >= 0) {
1054 op = gen_opc_buf[op_index];
1055 def = &tcg_op_defs[op];
1063 nb_iargs = args[0] & 0xffff;
1064 nb_oargs = args[0] >> 16;
1066 call_flags = args[nb_oargs + nb_iargs];
1068 /* pure functions can be removed if their result is not
1070 if (call_flags & TCG_CALL_PURE) {
1071 for(i = 0; i < nb_oargs; i++) {
1073 if (!dead_temps[arg])
1074 goto do_not_remove_call;
1076 tcg_set_nop(s, gen_opc_buf + op_index,
1081 /* output args are dead */
1082 for(i = 0; i < nb_oargs; i++) {
1084 dead_temps[arg] = 1;
1087 /* globals are live (they may be used by the call) */
1088 memset(dead_temps, 0, s->nb_globals);
1090 /* input args are live */
1092 for(i = 0; i < nb_iargs; i++) {
1093 arg = args[i + nb_oargs];
1094 if (arg != TCG_CALL_DUMMY_ARG) {
1095 if (dead_temps[arg]) {
1096 dead_iargs |= (1 << i);
1098 dead_temps[arg] = 0;
1101 s->op_dead_iargs[op_index] = dead_iargs;
1106 case INDEX_op_set_label:
1108 /* mark end of basic block */
1109 tcg_la_bb_end(s, dead_temps);
1111 case INDEX_op_debug_insn_start:
1112 args -= def->nb_args;
1118 case INDEX_op_discard:
1120 /* mark the temporary as dead */
1121 dead_temps[args[0]] = 1;
1123 case INDEX_op_macro_2:
1125 int dead_args[2], macro_id;
1126 int saved_op_index, saved_arg_index;
1127 int macro_op_index, macro_arg_index;
1128 int macro_end_op_index, macro_end_arg_index;
1133 dead_args[0] = dead_temps[args[0]];
1134 dead_args[1] = dead_temps[args[1]];
1137 /* call the macro function which generate code
1138 depending on the live outputs */
1139 saved_op_index = op_index;
1140 saved_arg_index = args - gen_opparam_buf;
1142 /* add a macro start instruction */
1143 *gen_opc_ptr++ = INDEX_op_macro_start;
1144 *gen_opparam_ptr++ = saved_op_index;
1145 *gen_opparam_ptr++ = saved_arg_index;
1147 macro_op_index = gen_opc_ptr - gen_opc_buf;
1148 macro_arg_index = gen_opparam_ptr - gen_opparam_buf;
1150 last_nb_temps = s->nb_temps;
1152 s->macro_func(s, macro_id, dead_args);
1154 /* realloc temp info (XXX: make it faster) */
1155 if (s->nb_temps > last_nb_temps) {
1156 uint8_t *new_dead_temps;
1158 new_dead_temps = tcg_malloc(s->nb_temps);
1159 memcpy(new_dead_temps, dead_temps, last_nb_temps);
1160 memset(new_dead_temps + last_nb_temps, 1,
1161 s->nb_temps - last_nb_temps);
1162 dead_temps = new_dead_temps;
1165 macro_end_op_index = gen_opc_ptr - gen_opc_buf;
1166 macro_end_arg_index = gen_opparam_ptr - gen_opparam_buf;
1168 /* end of macro: add a goto to the next instruction */
1169 *gen_opc_ptr++ = INDEX_op_macro_end;
1170 *gen_opparam_ptr++ = op_index + 1;
1171 *gen_opparam_ptr++ = saved_arg_index + nb_args;
1173 /* modify the macro operation to be a macro_goto */
1174 gen_opc_buf[op_index] = INDEX_op_macro_goto;
1175 args[0] = macro_op_index;
1176 args[1] = macro_arg_index;
1177 args[2] = 0; /* dummy third arg to match the
1180 /* set the next instruction to the end of the macro */
1181 op_index = macro_end_op_index;
1182 args = macro_end_arg_index + gen_opparam_buf;
1185 case INDEX_op_macro_start:
1188 args = gen_opparam_buf + args[1];
1190 case INDEX_op_macro_goto:
1191 case INDEX_op_macro_end:
1192 tcg_abort(); /* should never happen in liveness analysis */
1195 /* XXX: optimize by hardcoding common cases (e.g. triadic ops) */
1197 if (op > INDEX_op_end) {
1198 args -= def->nb_args;
1199 nb_iargs = def->nb_iargs;
1200 nb_oargs = def->nb_oargs;
1202 /* Test if the operation can be removed because all
1203 its outputs are dead. We assume that nb_oargs == 0
1204 implies side effects */
1205 if (!(def->flags & TCG_OPF_SIDE_EFFECTS) && nb_oargs != 0) {
1206 for(i = 0; i < nb_oargs; i++) {
1208 if (!dead_temps[arg])
1211 tcg_set_nop(s, gen_opc_buf + op_index, args, def->nb_args);
1212 #ifdef CONFIG_PROFILER
1218 /* output args are dead */
1219 for(i = 0; i < nb_oargs; i++) {
1221 dead_temps[arg] = 1;
1224 /* if end of basic block, update */
1225 if (def->flags & TCG_OPF_BB_END) {
1226 tcg_la_bb_end(s, dead_temps);
1227 } else if (def->flags & TCG_OPF_CALL_CLOBBER) {
1228 /* globals are live */
1229 memset(dead_temps, 0, s->nb_globals);
1232 /* input args are live */
1234 for(i = 0; i < nb_iargs; i++) {
1235 arg = args[i + nb_oargs];
1236 if (dead_temps[arg]) {
1237 dead_iargs |= (1 << i);
1239 dead_temps[arg] = 0;
1241 s->op_dead_iargs[op_index] = dead_iargs;
1244 /* legacy dyngen operations */
1245 args -= def->nb_args;
1246 /* mark end of basic block */
1247 tcg_la_bb_end(s, dead_temps);
1254 if (args != gen_opparam_buf)
1258 /* dummy liveness analysis */
1259 void tcg_liveness_analysis(TCGContext *s)
1262 nb_ops = gen_opc_ptr - gen_opc_buf;
1264 s->op_dead_iargs = tcg_malloc(nb_ops * sizeof(uint16_t));
1265 memset(s->op_dead_iargs, 0, nb_ops * sizeof(uint16_t));
1270 static void dump_regs(TCGContext *s)
1276 for(i = 0; i < s->nb_temps; i++) {
1278 printf(" %10s: ", tcg_get_arg_str_idx(s, buf, sizeof(buf), i));
1279 switch(ts->val_type) {
1281 printf("%s", tcg_target_reg_names[ts->reg]);
1284 printf("%d(%s)", (int)ts->mem_offset, tcg_target_reg_names[ts->mem_reg]);
1286 case TEMP_VAL_CONST:
1287 printf("$0x%" TCG_PRIlx, ts->val);
1299 for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
1300 if (s->reg_to_temp[i] >= 0) {
1302 tcg_target_reg_names[i],
1303 tcg_get_arg_str_idx(s, buf, sizeof(buf), s->reg_to_temp[i]));
1308 static void check_regs(TCGContext *s)
1314 for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1315 k = s->reg_to_temp[reg];
1318 if (ts->val_type != TEMP_VAL_REG ||
1320 printf("Inconsistency for register %s:\n",
1321 tcg_target_reg_names[reg]);
1326 for(k = 0; k < s->nb_temps; k++) {
1328 if (ts->val_type == TEMP_VAL_REG &&
1330 s->reg_to_temp[ts->reg] != k) {
1331 printf("Inconsistency for temp %s:\n",
1332 tcg_get_arg_str_idx(s, buf, sizeof(buf), k));
1334 printf("reg state:\n");
1342 static void temp_allocate_frame(TCGContext *s, int temp)
1345 ts = &s->temps[temp];
1346 s->current_frame_offset = (s->current_frame_offset + sizeof(tcg_target_long) - 1) & ~(sizeof(tcg_target_long) - 1);
1347 if (s->current_frame_offset + sizeof(tcg_target_long) > s->frame_end)
1349 ts->mem_offset = s->current_frame_offset;
1350 ts->mem_reg = s->frame_reg;
1351 ts->mem_allocated = 1;
1352 s->current_frame_offset += sizeof(tcg_target_long);
1355 /* free register 'reg' by spilling the corresponding temporary if necessary */
1356 static void tcg_reg_free(TCGContext *s, int reg)
1361 temp = s->reg_to_temp[reg];
1363 ts = &s->temps[temp];
1364 assert(ts->val_type == TEMP_VAL_REG);
1365 if (!ts->mem_coherent) {
1366 if (!ts->mem_allocated)
1367 temp_allocate_frame(s, temp);
1368 tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1370 ts->val_type = TEMP_VAL_MEM;
1371 s->reg_to_temp[reg] = -1;
1375 /* Allocate a register belonging to reg1 & ~reg2 */
1376 static int tcg_reg_alloc(TCGContext *s, TCGRegSet reg1, TCGRegSet reg2)
1381 tcg_regset_andnot(reg_ct, reg1, reg2);
1383 /* first try free registers */
1384 for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1385 reg = tcg_target_reg_alloc_order[i];
1386 if (tcg_regset_test_reg(reg_ct, reg) && s->reg_to_temp[reg] == -1)
1390 /* XXX: do better spill choice */
1391 for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1392 reg = tcg_target_reg_alloc_order[i];
1393 if (tcg_regset_test_reg(reg_ct, reg)) {
1394 tcg_reg_free(s, reg);
1402 /* save a temporary to memory. 'allocated_regs' is used in case a
1403 temporary registers needs to be allocated to store a constant. */
1404 static void temp_save(TCGContext *s, int temp, TCGRegSet allocated_regs)
1409 ts = &s->temps[temp];
1410 if (!ts->fixed_reg) {
1411 switch(ts->val_type) {
1413 tcg_reg_free(s, ts->reg);
1416 ts->val_type = TEMP_VAL_MEM;
1418 case TEMP_VAL_CONST:
1419 reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type],
1421 if (!ts->mem_allocated)
1422 temp_allocate_frame(s, temp);
1423 tcg_out_movi(s, ts->type, reg, ts->val);
1424 tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1425 ts->val_type = TEMP_VAL_MEM;
1435 /* save globals to their cannonical location and assume they can be
1436 modified be the following code. 'allocated_regs' is used in case a
1437 temporary registers needs to be allocated to store a constant. */
1438 static void save_globals(TCGContext *s, TCGRegSet allocated_regs)
1442 for(i = 0; i < s->nb_globals; i++) {
1443 temp_save(s, i, allocated_regs);
1447 /* at the end of a basic block, we assume all temporaries are dead and
1448 all globals are stored at their canonical location. */
1449 static void tcg_reg_alloc_bb_end(TCGContext *s, TCGRegSet allocated_regs)
1454 for(i = s->nb_globals; i < s->nb_temps; i++) {
1456 if (ts->temp_local) {
1457 temp_save(s, i, allocated_regs);
1459 if (ts->val_type == TEMP_VAL_REG) {
1460 s->reg_to_temp[ts->reg] = -1;
1462 ts->val_type = TEMP_VAL_DEAD;
1466 save_globals(s, allocated_regs);
1469 #define IS_DEAD_IARG(n) ((dead_iargs >> (n)) & 1)
1471 static void tcg_reg_alloc_movi(TCGContext *s, const TCGArg *args)
1474 tcg_target_ulong val;
1476 ots = &s->temps[args[0]];
1479 if (ots->fixed_reg) {
1480 /* for fixed registers, we do not do any constant
1482 tcg_out_movi(s, ots->type, ots->reg, val);
1484 /* The movi is not explicitely generated here */
1485 if (ots->val_type == TEMP_VAL_REG)
1486 s->reg_to_temp[ots->reg] = -1;
1487 ots->val_type = TEMP_VAL_CONST;
1492 static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
1494 unsigned int dead_iargs)
1498 const TCGArgConstraint *arg_ct;
1500 ots = &s->temps[args[0]];
1501 ts = &s->temps[args[1]];
1502 arg_ct = &def->args_ct[0];
1504 /* XXX: always mark arg dead if IS_DEAD_IARG(0) */
1505 if (ts->val_type == TEMP_VAL_REG) {
1506 if (IS_DEAD_IARG(0) && !ts->fixed_reg && !ots->fixed_reg) {
1507 /* the mov can be suppressed */
1508 if (ots->val_type == TEMP_VAL_REG)
1509 s->reg_to_temp[ots->reg] = -1;
1511 s->reg_to_temp[reg] = -1;
1512 ts->val_type = TEMP_VAL_DEAD;
1514 if (ots->val_type == TEMP_VAL_REG) {
1517 reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1519 if (ts->reg != reg) {
1520 tcg_out_mov(s, reg, ts->reg);
1523 } else if (ts->val_type == TEMP_VAL_MEM) {
1524 if (ots->val_type == TEMP_VAL_REG) {
1527 reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1529 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1530 } else if (ts->val_type == TEMP_VAL_CONST) {
1531 if (ots->fixed_reg) {
1533 tcg_out_movi(s, ots->type, reg, ts->val);
1535 /* propagate constant */
1536 if (ots->val_type == TEMP_VAL_REG)
1537 s->reg_to_temp[ots->reg] = -1;
1538 ots->val_type = TEMP_VAL_CONST;
1545 s->reg_to_temp[reg] = args[0];
1547 ots->val_type = TEMP_VAL_REG;
1548 ots->mem_coherent = 0;
1551 static void tcg_reg_alloc_op(TCGContext *s,
1552 const TCGOpDef *def, int opc,
1554 unsigned int dead_iargs)
1556 TCGRegSet allocated_regs;
1557 int i, k, nb_iargs, nb_oargs, reg;
1559 const TCGArgConstraint *arg_ct;
1561 TCGArg new_args[TCG_MAX_OP_ARGS];
1562 int const_args[TCG_MAX_OP_ARGS];
1564 nb_oargs = def->nb_oargs;
1565 nb_iargs = def->nb_iargs;
1567 /* copy constants */
1568 memcpy(new_args + nb_oargs + nb_iargs,
1569 args + nb_oargs + nb_iargs,
1570 sizeof(TCGArg) * def->nb_cargs);
1572 /* satisfy input constraints */
1573 tcg_regset_set(allocated_regs, s->reserved_regs);
1574 for(k = 0; k < nb_iargs; k++) {
1575 i = def->sorted_args[nb_oargs + k];
1577 arg_ct = &def->args_ct[i];
1578 ts = &s->temps[arg];
1579 if (ts->val_type == TEMP_VAL_MEM) {
1580 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1581 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1582 ts->val_type = TEMP_VAL_REG;
1584 ts->mem_coherent = 1;
1585 s->reg_to_temp[reg] = arg;
1586 } else if (ts->val_type == TEMP_VAL_CONST) {
1587 if (tcg_target_const_match(ts->val, arg_ct)) {
1588 /* constant is OK for instruction */
1590 new_args[i] = ts->val;
1593 /* need to move to a register */
1594 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1595 tcg_out_movi(s, ts->type, reg, ts->val);
1596 ts->val_type = TEMP_VAL_REG;
1598 ts->mem_coherent = 0;
1599 s->reg_to_temp[reg] = arg;
1602 assert(ts->val_type == TEMP_VAL_REG);
1603 if (arg_ct->ct & TCG_CT_IALIAS) {
1604 if (ts->fixed_reg) {
1605 /* if fixed register, we must allocate a new register
1606 if the alias is not the same register */
1607 if (arg != args[arg_ct->alias_index])
1608 goto allocate_in_reg;
1610 /* if the input is aliased to an output and if it is
1611 not dead after the instruction, we must allocate
1612 a new register and move it */
1613 if (!IS_DEAD_IARG(i - nb_oargs))
1614 goto allocate_in_reg;
1618 if (tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1619 /* nothing to do : the constraint is satisfied */
1622 /* allocate a new register matching the constraint
1623 and move the temporary register into it */
1624 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1625 tcg_out_mov(s, reg, ts->reg);
1629 tcg_regset_set_reg(allocated_regs, reg);
1633 if (def->flags & TCG_OPF_BB_END) {
1634 tcg_reg_alloc_bb_end(s, allocated_regs);
1636 /* mark dead temporaries and free the associated registers */
1637 for(i = 0; i < nb_iargs; i++) {
1638 arg = args[nb_oargs + i];
1639 if (IS_DEAD_IARG(i)) {
1640 ts = &s->temps[arg];
1641 if (!ts->fixed_reg) {
1642 if (ts->val_type == TEMP_VAL_REG)
1643 s->reg_to_temp[ts->reg] = -1;
1644 ts->val_type = TEMP_VAL_DEAD;
1649 if (def->flags & TCG_OPF_CALL_CLOBBER) {
1650 /* XXX: permit generic clobber register list ? */
1651 for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1652 if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
1653 tcg_reg_free(s, reg);
1656 /* XXX: for load/store we could do that only for the slow path
1657 (i.e. when a memory callback is called) */
1659 /* store globals and free associated registers (we assume the insn
1660 can modify any global. */
1661 save_globals(s, allocated_regs);
1664 /* satisfy the output constraints */
1665 tcg_regset_set(allocated_regs, s->reserved_regs);
1666 for(k = 0; k < nb_oargs; k++) {
1667 i = def->sorted_args[k];
1669 arg_ct = &def->args_ct[i];
1670 ts = &s->temps[arg];
1671 if (arg_ct->ct & TCG_CT_ALIAS) {
1672 reg = new_args[arg_ct->alias_index];
1674 /* if fixed register, we try to use it */
1676 if (ts->fixed_reg &&
1677 tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1680 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1682 tcg_regset_set_reg(allocated_regs, reg);
1683 /* if a fixed register is used, then a move will be done afterwards */
1684 if (!ts->fixed_reg) {
1685 if (ts->val_type == TEMP_VAL_REG)
1686 s->reg_to_temp[ts->reg] = -1;
1687 ts->val_type = TEMP_VAL_REG;
1689 /* temp value is modified, so the value kept in memory is
1690 potentially not the same */
1691 ts->mem_coherent = 0;
1692 s->reg_to_temp[reg] = arg;
1699 /* emit instruction */
1700 tcg_out_op(s, opc, new_args, const_args);
1702 /* move the outputs in the correct register if needed */
1703 for(i = 0; i < nb_oargs; i++) {
1704 ts = &s->temps[args[i]];
1706 if (ts->fixed_reg && ts->reg != reg) {
1707 tcg_out_mov(s, ts->reg, reg);
1712 #ifdef TCG_TARGET_STACK_GROWSUP
1713 #define STACK_DIR(x) (-(x))
1715 #define STACK_DIR(x) (x)
1718 static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
1719 int opc, const TCGArg *args,
1720 unsigned int dead_iargs)
1722 int nb_iargs, nb_oargs, flags, nb_regs, i, reg, nb_params;
1723 TCGArg arg, func_arg;
1725 tcg_target_long stack_offset, call_stack_size, func_addr;
1726 int const_func_arg, allocate_args;
1727 TCGRegSet allocated_regs;
1728 const TCGArgConstraint *arg_ct;
1732 nb_oargs = arg >> 16;
1733 nb_iargs = arg & 0xffff;
1734 nb_params = nb_iargs - 1;
1736 flags = args[nb_oargs + nb_iargs];
1738 nb_regs = tcg_target_get_call_iarg_regs_count(flags);
1739 if (nb_regs > nb_params)
1740 nb_regs = nb_params;
1742 /* assign stack slots first */
1743 /* XXX: preallocate call stack */
1744 call_stack_size = (nb_params - nb_regs) * sizeof(tcg_target_long);
1745 call_stack_size = (call_stack_size + TCG_TARGET_STACK_ALIGN - 1) &
1746 ~(TCG_TARGET_STACK_ALIGN - 1);
1747 allocate_args = (call_stack_size > TCG_STATIC_CALL_ARGS_SIZE);
1748 if (allocate_args) {
1749 tcg_out_addi(s, TCG_REG_CALL_STACK, -STACK_DIR(call_stack_size));
1752 stack_offset = TCG_TARGET_CALL_STACK_OFFSET;
1753 for(i = nb_regs; i < nb_params; i++) {
1754 arg = args[nb_oargs + i];
1755 #ifdef TCG_TARGET_STACK_GROWSUP
1756 stack_offset -= sizeof(tcg_target_long);
1758 if (arg != TCG_CALL_DUMMY_ARG) {
1759 ts = &s->temps[arg];
1760 if (ts->val_type == TEMP_VAL_REG) {
1761 tcg_out_st(s, ts->type, ts->reg, TCG_REG_CALL_STACK, stack_offset);
1762 } else if (ts->val_type == TEMP_VAL_MEM) {
1763 reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type],
1765 /* XXX: not correct if reading values from the stack */
1766 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1767 tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
1768 } else if (ts->val_type == TEMP_VAL_CONST) {
1769 reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type],
1771 /* XXX: sign extend may be needed on some targets */
1772 tcg_out_movi(s, ts->type, reg, ts->val);
1773 tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
1778 #ifndef TCG_TARGET_STACK_GROWSUP
1779 stack_offset += sizeof(tcg_target_long);
1783 /* assign input registers */
1784 tcg_regset_set(allocated_regs, s->reserved_regs);
1785 for(i = 0; i < nb_regs; i++) {
1786 arg = args[nb_oargs + i];
1787 if (arg != TCG_CALL_DUMMY_ARG) {
1788 ts = &s->temps[arg];
1789 reg = tcg_target_call_iarg_regs[i];
1790 tcg_reg_free(s, reg);
1791 if (ts->val_type == TEMP_VAL_REG) {
1792 if (ts->reg != reg) {
1793 tcg_out_mov(s, reg, ts->reg);
1795 } else if (ts->val_type == TEMP_VAL_MEM) {
1796 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1797 } else if (ts->val_type == TEMP_VAL_CONST) {
1798 /* XXX: sign extend ? */
1799 tcg_out_movi(s, ts->type, reg, ts->val);
1803 tcg_regset_set_reg(allocated_regs, reg);
1807 /* assign function address */
1808 func_arg = args[nb_oargs + nb_iargs - 1];
1809 arg_ct = &def->args_ct[0];
1810 ts = &s->temps[func_arg];
1811 func_addr = ts->val;
1813 if (ts->val_type == TEMP_VAL_MEM) {
1814 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1815 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1817 tcg_regset_set_reg(allocated_regs, reg);
1818 } else if (ts->val_type == TEMP_VAL_REG) {
1820 if (!tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1821 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1822 tcg_out_mov(s, reg, ts->reg);
1825 tcg_regset_set_reg(allocated_regs, reg);
1826 } else if (ts->val_type == TEMP_VAL_CONST) {
1827 if (tcg_target_const_match(func_addr, arg_ct)) {
1829 func_arg = func_addr;
1831 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1832 tcg_out_movi(s, ts->type, reg, func_addr);
1834 tcg_regset_set_reg(allocated_regs, reg);
1841 /* mark dead temporaries and free the associated registers */
1842 for(i = 0; i < nb_iargs; i++) {
1843 arg = args[nb_oargs + i];
1844 if (IS_DEAD_IARG(i)) {
1845 ts = &s->temps[arg];
1846 if (!ts->fixed_reg) {
1847 if (ts->val_type == TEMP_VAL_REG)
1848 s->reg_to_temp[ts->reg] = -1;
1849 ts->val_type = TEMP_VAL_DEAD;
1854 /* clobber call registers */
1855 for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1856 if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
1857 tcg_reg_free(s, reg);
1861 /* store globals and free associated registers (we assume the call
1862 can modify any global. */
1863 save_globals(s, allocated_regs);
1865 tcg_out_op(s, opc, &func_arg, &const_func_arg);
1867 if (allocate_args) {
1868 tcg_out_addi(s, TCG_REG_CALL_STACK, STACK_DIR(call_stack_size));
1871 /* assign output registers and emit moves if needed */
1872 for(i = 0; i < nb_oargs; i++) {
1874 ts = &s->temps[arg];
1875 reg = tcg_target_call_oarg_regs[i];
1876 assert(s->reg_to_temp[reg] == -1);
1877 if (ts->fixed_reg) {
1878 if (ts->reg != reg) {
1879 tcg_out_mov(s, ts->reg, reg);
1882 if (ts->val_type == TEMP_VAL_REG)
1883 s->reg_to_temp[ts->reg] = -1;
1884 ts->val_type = TEMP_VAL_REG;
1886 ts->mem_coherent = 0;
1887 s->reg_to_temp[reg] = arg;
1891 return nb_iargs + nb_oargs + def->nb_cargs + 1;
1894 #ifdef CONFIG_PROFILER
1896 static int64_t dyngen_table_op_count[NB_OPS];
1898 void dump_op_count(void)
1902 f = fopen("/tmp/op1.log", "w");
1903 for(i = 0; i < INDEX_op_end; i++) {
1904 fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name, dyngen_table_op_count[i]);
1907 f = fopen("/tmp/op2.log", "w");
1908 for(i = INDEX_op_end; i < NB_OPS; i++) {
1909 fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name, dyngen_table_op_count[i]);
1916 static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
1919 int opc, op_index, macro_op_index;
1920 const TCGOpDef *def;
1921 unsigned int dead_iargs;
1925 if (unlikely(loglevel & CPU_LOG_TB_OP)) {
1926 fprintf(logfile, "OP:\n");
1927 tcg_dump_ops(s, logfile);
1928 fprintf(logfile, "\n");
1932 #ifdef CONFIG_PROFILER
1933 s->la_time -= profile_getclock();
1935 tcg_liveness_analysis(s);
1936 #ifdef CONFIG_PROFILER
1937 s->la_time += profile_getclock();
1941 if (unlikely(loglevel & CPU_LOG_TB_OP_OPT)) {
1942 fprintf(logfile, "OP after la:\n");
1943 tcg_dump_ops(s, logfile);
1944 fprintf(logfile, "\n");
1948 tcg_reg_alloc_start(s);
1950 s->code_buf = gen_code_buf;
1951 s->code_ptr = gen_code_buf;
1953 macro_op_index = -1;
1954 args = gen_opparam_buf;
1958 opc = gen_opc_buf[op_index];
1959 #ifdef CONFIG_PROFILER
1960 dyngen_table_op_count[opc]++;
1962 def = &tcg_op_defs[opc];
1964 printf("%s: %d %d %d\n", def->name,
1965 def->nb_oargs, def->nb_iargs, def->nb_cargs);
1969 case INDEX_op_mov_i32:
1970 #if TCG_TARGET_REG_BITS == 64
1971 case INDEX_op_mov_i64:
1973 dead_iargs = s->op_dead_iargs[op_index];
1974 tcg_reg_alloc_mov(s, def, args, dead_iargs);
1976 case INDEX_op_movi_i32:
1977 #if TCG_TARGET_REG_BITS == 64
1978 case INDEX_op_movi_i64:
1980 tcg_reg_alloc_movi(s, args);
1982 case INDEX_op_debug_insn_start:
1983 /* debug instruction */
1993 case INDEX_op_discard:
1996 ts = &s->temps[args[0]];
1997 /* mark the temporary as dead */
1998 if (!ts->fixed_reg) {
1999 if (ts->val_type == TEMP_VAL_REG)
2000 s->reg_to_temp[ts->reg] = -1;
2001 ts->val_type = TEMP_VAL_DEAD;
2005 case INDEX_op_macro_goto:
2006 macro_op_index = op_index; /* only used for exceptions */
2007 op_index = args[0] - 1;
2008 args = gen_opparam_buf + args[1];
2010 case INDEX_op_macro_end:
2011 macro_op_index = -1; /* only used for exceptions */
2012 op_index = args[0] - 1;
2013 args = gen_opparam_buf + args[1];
2015 case INDEX_op_macro_start:
2016 /* must never happen here */
2018 case INDEX_op_set_label:
2019 tcg_reg_alloc_bb_end(s, s->reserved_regs);
2020 tcg_out_label(s, args[0], (long)s->code_ptr);
2023 dead_iargs = s->op_dead_iargs[op_index];
2024 args += tcg_reg_alloc_call(s, def, opc, args, dead_iargs);
2029 #ifdef CONFIG_DYNGEN_OP
2030 case 0 ... INDEX_op_end - 1:
2031 /* legacy dyngen ops */
2032 #ifdef CONFIG_PROFILER
2035 tcg_reg_alloc_bb_end(s, s->reserved_regs);
2036 if (search_pc >= 0) {
2037 s->code_ptr += def->copy_size;
2038 args += def->nb_args;
2040 args = dyngen_op(s, opc, args);
2045 /* Note: in order to speed up the code, it would be much
2046 faster to have specialized register allocator functions for
2047 some common argument patterns */
2048 dead_iargs = s->op_dead_iargs[op_index];
2049 tcg_reg_alloc_op(s, def, opc, args, dead_iargs);
2052 args += def->nb_args;
2054 if (search_pc >= 0 && search_pc < s->code_ptr - gen_code_buf) {
2055 if (macro_op_index >= 0)
2056 return macro_op_index;
2069 int dyngen_code(TCGContext *s, uint8_t *gen_code_buf)
2071 #ifdef CONFIG_PROFILER
2074 n = (gen_opc_ptr - gen_opc_buf);
2076 if (n > s->op_count_max)
2077 s->op_count_max = n;
2079 s->temp_count += s->nb_temps;
2080 if (s->nb_temps > s->temp_count_max)
2081 s->temp_count_max = s->nb_temps;
2085 tcg_gen_code_common(s, gen_code_buf, -1);
2087 /* flush instruction cache */
2088 flush_icache_range((unsigned long)gen_code_buf,
2089 (unsigned long)s->code_ptr);
2090 return s->code_ptr - gen_code_buf;
2093 /* Return the index of the micro operation such as the pc after is <
2094 offset bytes from the start of the TB. The contents of gen_code_buf must
2095 not be changed, though writing the same values is ok.
2096 Return -1 if not found. */
2097 int dyngen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, long offset)
2099 return tcg_gen_code_common(s, gen_code_buf, offset);
2102 #ifdef CONFIG_PROFILER
2103 void tcg_dump_info(FILE *f,
2104 int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
2106 TCGContext *s = &tcg_ctx;
2109 tot = s->interm_time + s->code_time;
2110 cpu_fprintf(f, "JIT cycles %" PRId64 " (%0.3f s at 2.4 GHz)\n",
2112 cpu_fprintf(f, "translated TBs %" PRId64 " (aborted=%" PRId64 " %0.1f%%)\n",
2114 s->tb_count1 - s->tb_count,
2115 s->tb_count1 ? (double)(s->tb_count1 - s->tb_count) / s->tb_count1 * 100.0 : 0);
2116 cpu_fprintf(f, "avg ops/TB %0.1f max=%d\n",
2117 s->tb_count ? (double)s->op_count / s->tb_count : 0, s->op_count_max);
2118 cpu_fprintf(f, "old ops/total ops %0.1f%%\n",
2119 s->op_count ? (double)s->old_op_count / s->op_count * 100.0 : 0);
2120 cpu_fprintf(f, "deleted ops/TB %0.2f\n",
2122 (double)s->del_op_count / s->tb_count : 0);
2123 cpu_fprintf(f, "avg temps/TB %0.2f max=%d\n",
2125 (double)s->temp_count / s->tb_count : 0,
2128 cpu_fprintf(f, "cycles/op %0.1f\n",
2129 s->op_count ? (double)tot / s->op_count : 0);
2130 cpu_fprintf(f, "cycles/in byte %0.1f\n",
2131 s->code_in_len ? (double)tot / s->code_in_len : 0);
2132 cpu_fprintf(f, "cycles/out byte %0.1f\n",
2133 s->code_out_len ? (double)tot / s->code_out_len : 0);
2136 cpu_fprintf(f, " gen_interm time %0.1f%%\n",
2137 (double)s->interm_time / tot * 100.0);
2138 cpu_fprintf(f, " gen_code time %0.1f%%\n",
2139 (double)s->code_time / tot * 100.0);
2140 cpu_fprintf(f, "liveness/code time %0.1f%%\n",
2141 (double)s->la_time / (s->code_time ? s->code_time : 1) * 100.0);
2142 cpu_fprintf(f, "cpu_restore count %" PRId64 "\n",
2144 cpu_fprintf(f, " avg cycles %0.1f\n",
2145 s->restore_count ? (double)s->restore_time / s->restore_count : 0);
2147 extern void dump_op_count(void);
2152 void tcg_dump_info(FILE *f,
2153 int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
2155 cpu_fprintf(f, "[TCG profiler not compiled]\n");