tcg.c revision b9317727862dd690cc67bb51f71991c404f9e4f6
1/*
2 * Tiny Code Generator for QEMU
3 *
4 * Copyright (c) 2008 Fabrice Bellard
5 *
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:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
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.
23 */
24
25/* define it to use liveness analysis (better code) */
26#define USE_LIVENESS_ANALYSIS
27
28#include "config.h"
29
30#ifndef CONFIG_DEBUG_TCG
31/* define it to suppress various consistency checks (faster) */
32#define NDEBUG
33#endif
34
35#include <stdarg.h>
36#include <stdlib.h>
37#include <stdio.h>
38#include <string.h>
39#include <inttypes.h>
40#ifdef _WIN32
41#include <malloc.h>
42#endif
43#ifdef _AIX
44#include <alloca.h>
45#endif
46
47#include "qemu-common.h"
48#include "cache-utils.h"
49#include "host-utils.h"
50
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"
57
58#include "tcg-op.h"
59#include "elf.h"
60
61#if defined(CONFIG_USE_GUEST_BASE) && !defined(TCG_TARGET_HAS_GUEST_BASE)
62#error GUEST_BASE not supported on this host.
63#endif
64
65static void patch_reloc(uint8_t *code_ptr, int type,
66                        tcg_target_long value, tcg_target_long addend);
67
68static TCGOpDef tcg_op_defs[] = {
69#define DEF(s, n, copy_size) { #s, 0, 0, n, n, 0, copy_size },
70#define DEF2(s, oargs, iargs, cargs, flags) { #s, oargs, iargs, cargs, iargs + oargs + cargs, flags, 0 },
71#include "tcg-opc.h"
72#undef DEF
73#undef DEF2
74};
75
76static TCGRegSet tcg_target_available_regs[2];
77static TCGRegSet tcg_target_call_clobber_regs;
78
79/* XXX: move that inside the context */
80uint16_t *gen_opc_ptr;
81TCGArg *gen_opparam_ptr;
82
83#ifdef CONFIG_MEMCHECK
84/*
85 * Memchecker addition in this module is intended to build a map that matches
86 * translated PC to a guest PC. Map is built in tcg_gen_code_common routine,
87 * and is saved into temporary gen_opc_tpc2gpc_ptr array, that later will be
88 * copied into the TranslationBlock that represents the translated code.
89 */
90#include "memcheck/memcheck_api.h"
91#endif  // CONFIG_MEMCHECK
92
93static inline void tcg_out8(TCGContext *s, uint8_t v)
94{
95    *s->code_ptr++ = v;
96}
97
98static inline void tcg_out16(TCGContext *s, uint16_t v)
99{
100    *(uint16_t *)s->code_ptr = v;
101    s->code_ptr += 2;
102}
103
104static inline void tcg_out32(TCGContext *s, uint32_t v)
105{
106    *(uint32_t *)s->code_ptr = v;
107    s->code_ptr += 4;
108}
109
110/* label relocation processing */
111
112void tcg_out_reloc(TCGContext *s, uint8_t *code_ptr, int type,
113                   int label_index, long addend)
114{
115    TCGLabel *l;
116    TCGRelocation *r;
117
118    l = &s->labels[label_index];
119    if (l->has_value) {
120        /* FIXME: This may break relocations on RISC targets that
121           modify instruction fields in place.  The caller may not have
122           written the initial value.  */
123        patch_reloc(code_ptr, type, l->u.value, addend);
124    } else {
125        /* add a new relocation entry */
126        r = tcg_malloc(sizeof(TCGRelocation));
127        r->type = type;
128        r->ptr = code_ptr;
129        r->addend = addend;
130        r->next = l->u.first_reloc;
131        l->u.first_reloc = r;
132    }
133}
134
135static void tcg_out_label(TCGContext *s, int label_index,
136                          tcg_target_long value)
137{
138    TCGLabel *l;
139    TCGRelocation *r;
140
141    l = &s->labels[label_index];
142    if (l->has_value)
143        tcg_abort();
144    r = l->u.first_reloc;
145    while (r != NULL) {
146        patch_reloc(r->ptr, r->type, value, r->addend);
147        r = r->next;
148    }
149    l->has_value = 1;
150    l->u.value = value;
151}
152
153int gen_new_label(void)
154{
155    TCGContext *s = &tcg_ctx;
156    int idx;
157    TCGLabel *l;
158
159    if (s->nb_labels >= TCG_MAX_LABELS)
160        tcg_abort();
161    idx = s->nb_labels++;
162    l = &s->labels[idx];
163    l->has_value = 0;
164    l->u.first_reloc = NULL;
165    return idx;
166}
167
168#include "tcg-target.c"
169
170/* pool based memory allocation */
171void *tcg_malloc_internal(TCGContext *s, int size)
172{
173    TCGPool *p;
174    int pool_size;
175
176    if (size > TCG_POOL_CHUNK_SIZE) {
177        /* big malloc: insert a new pool (XXX: could optimize) */
178        p = qemu_malloc(sizeof(TCGPool) + size);
179        p->size = size;
180        if (s->pool_current)
181            s->pool_current->next = p;
182        else
183            s->pool_first = p;
184        p->next = s->pool_current;
185    } else {
186        p = s->pool_current;
187        if (!p) {
188            p = s->pool_first;
189            if (!p)
190                goto new_pool;
191        } else {
192            if (!p->next) {
193            new_pool:
194                pool_size = TCG_POOL_CHUNK_SIZE;
195                p = qemu_malloc(sizeof(TCGPool) + pool_size);
196                p->size = pool_size;
197                p->next = NULL;
198                if (s->pool_current)
199                    s->pool_current->next = p;
200                else
201                    s->pool_first = p;
202            } else {
203                p = p->next;
204            }
205        }
206    }
207    s->pool_current = p;
208    s->pool_cur = p->data + size;
209    s->pool_end = p->data + p->size;
210    return p->data;
211}
212
213void tcg_pool_reset(TCGContext *s)
214{
215    s->pool_cur = s->pool_end = NULL;
216    s->pool_current = NULL;
217}
218
219void tcg_context_init(TCGContext *s)
220{
221    int op, total_args, n;
222    TCGOpDef *def;
223    TCGArgConstraint *args_ct;
224    int *sorted_args;
225
226    memset(s, 0, sizeof(*s));
227    s->temps = s->static_temps;
228    s->nb_globals = 0;
229
230    /* Count total number of arguments and allocate the corresponding
231       space */
232    total_args = 0;
233    for(op = 0; op < NB_OPS; op++) {
234        def = &tcg_op_defs[op];
235        n = def->nb_iargs + def->nb_oargs;
236        total_args += n;
237    }
238
239    args_ct = qemu_malloc(sizeof(TCGArgConstraint) * total_args);
240    sorted_args = qemu_malloc(sizeof(int) * total_args);
241
242    for(op = 0; op < NB_OPS; op++) {
243        def = &tcg_op_defs[op];
244        def->args_ct = args_ct;
245        def->sorted_args = sorted_args;
246        n = def->nb_iargs + def->nb_oargs;
247        sorted_args += n;
248        args_ct += n;
249    }
250
251    tcg_target_init(s);
252
253    /* init global prologue and epilogue */
254    s->code_buf = code_gen_prologue;
255    s->code_ptr = s->code_buf;
256    tcg_target_qemu_prologue(s);
257    flush_icache_range((unsigned long)s->code_buf,
258                       (unsigned long)s->code_ptr);
259}
260
261void tcg_set_frame(TCGContext *s, int reg,
262                   tcg_target_long start, tcg_target_long size)
263{
264    s->frame_start = start;
265    s->frame_end = start + size;
266    s->frame_reg = reg;
267}
268
269void tcg_func_start(TCGContext *s)
270{
271    int i;
272    tcg_pool_reset(s);
273    s->nb_temps = s->nb_globals;
274    for(i = 0; i < (TCG_TYPE_COUNT * 2); i++)
275        s->first_free_temp[i] = -1;
276    s->labels = tcg_malloc(sizeof(TCGLabel) * TCG_MAX_LABELS);
277    s->nb_labels = 0;
278    s->current_frame_offset = s->frame_start;
279
280    gen_opc_ptr = gen_opc_buf;
281    gen_opparam_ptr = gen_opparam_buf;
282}
283
284static inline void tcg_temp_alloc(TCGContext *s, int n)
285{
286    if (n > TCG_MAX_TEMPS)
287        tcg_abort();
288}
289
290static inline int tcg_global_reg_new_internal(TCGType type, int reg,
291                                              const char *name)
292{
293    TCGContext *s = &tcg_ctx;
294    TCGTemp *ts;
295    int idx;
296
297#if TCG_TARGET_REG_BITS == 32
298    if (type != TCG_TYPE_I32)
299        tcg_abort();
300#endif
301    if (tcg_regset_test_reg(s->reserved_regs, reg))
302        tcg_abort();
303    idx = s->nb_globals;
304    tcg_temp_alloc(s, s->nb_globals + 1);
305    ts = &s->temps[s->nb_globals];
306    ts->base_type = type;
307    ts->type = type;
308    ts->fixed_reg = 1;
309    ts->reg = reg;
310    ts->name = name;
311    s->nb_globals++;
312    tcg_regset_set_reg(s->reserved_regs, reg);
313    return idx;
314}
315
316TCGv_i32 tcg_global_reg_new_i32(int reg, const char *name)
317{
318    int idx;
319
320    idx = tcg_global_reg_new_internal(TCG_TYPE_I32, reg, name);
321    return MAKE_TCGV_I32(idx);
322}
323
324TCGv_i64 tcg_global_reg_new_i64(int reg, const char *name)
325{
326    int idx;
327
328    idx = tcg_global_reg_new_internal(TCG_TYPE_I64, reg, name);
329    return MAKE_TCGV_I64(idx);
330}
331
332static inline int tcg_global_mem_new_internal(TCGType type, int reg,
333                                              tcg_target_long offset,
334                                              const char *name)
335{
336    TCGContext *s = &tcg_ctx;
337    TCGTemp *ts;
338    int idx;
339
340    idx = s->nb_globals;
341#if TCG_TARGET_REG_BITS == 32
342    if (type == TCG_TYPE_I64) {
343        char buf[64];
344        tcg_temp_alloc(s, s->nb_globals + 2);
345        ts = &s->temps[s->nb_globals];
346        ts->base_type = type;
347        ts->type = TCG_TYPE_I32;
348        ts->fixed_reg = 0;
349        ts->mem_allocated = 1;
350        ts->mem_reg = reg;
351#ifdef TCG_TARGET_WORDS_BIGENDIAN
352        ts->mem_offset = offset + 4;
353#else
354        ts->mem_offset = offset;
355#endif
356        pstrcpy(buf, sizeof(buf), name);
357        pstrcat(buf, sizeof(buf), "_0");
358        ts->name = strdup(buf);
359        ts++;
360
361        ts->base_type = type;
362        ts->type = TCG_TYPE_I32;
363        ts->fixed_reg = 0;
364        ts->mem_allocated = 1;
365        ts->mem_reg = reg;
366#ifdef TCG_TARGET_WORDS_BIGENDIAN
367        ts->mem_offset = offset;
368#else
369        ts->mem_offset = offset + 4;
370#endif
371        pstrcpy(buf, sizeof(buf), name);
372        pstrcat(buf, sizeof(buf), "_1");
373        ts->name = strdup(buf);
374
375        s->nb_globals += 2;
376    } else
377#endif
378    {
379        tcg_temp_alloc(s, s->nb_globals + 1);
380        ts = &s->temps[s->nb_globals];
381        ts->base_type = type;
382        ts->type = type;
383        ts->fixed_reg = 0;
384        ts->mem_allocated = 1;
385        ts->mem_reg = reg;
386        ts->mem_offset = offset;
387        ts->name = name;
388        s->nb_globals++;
389    }
390    return idx;
391}
392
393TCGv_i32 tcg_global_mem_new_i32(int reg, tcg_target_long offset,
394                                const char *name)
395{
396    int idx;
397
398    idx = tcg_global_mem_new_internal(TCG_TYPE_I32, reg, offset, name);
399    return MAKE_TCGV_I32(idx);
400}
401
402TCGv_i64 tcg_global_mem_new_i64(int reg, tcg_target_long offset,
403                                const char *name)
404{
405    int idx;
406
407    idx = tcg_global_mem_new_internal(TCG_TYPE_I64, reg, offset, name);
408    return MAKE_TCGV_I64(idx);
409}
410
411static inline int tcg_temp_new_internal(TCGType type, int temp_local)
412{
413    TCGContext *s = &tcg_ctx;
414    TCGTemp *ts;
415    int idx, k;
416
417    k = type;
418    if (temp_local)
419        k += TCG_TYPE_COUNT;
420    idx = s->first_free_temp[k];
421    if (idx != -1) {
422        /* There is already an available temp with the
423           right type */
424        ts = &s->temps[idx];
425        s->first_free_temp[k] = ts->next_free_temp;
426        ts->temp_allocated = 1;
427        assert(ts->temp_local == temp_local);
428    } else {
429        idx = s->nb_temps;
430#if TCG_TARGET_REG_BITS == 32
431        if (type == TCG_TYPE_I64) {
432            tcg_temp_alloc(s, s->nb_temps + 2);
433            ts = &s->temps[s->nb_temps];
434            ts->base_type = type;
435            ts->type = TCG_TYPE_I32;
436            ts->temp_allocated = 1;
437            ts->temp_local = temp_local;
438            ts->name = NULL;
439            ts++;
440            ts->base_type = TCG_TYPE_I32;
441            ts->type = TCG_TYPE_I32;
442            ts->temp_allocated = 1;
443            ts->temp_local = temp_local;
444            ts->name = NULL;
445            s->nb_temps += 2;
446        } else
447#endif
448        {
449            tcg_temp_alloc(s, s->nb_temps + 1);
450            ts = &s->temps[s->nb_temps];
451            ts->base_type = type;
452            ts->type = type;
453            ts->temp_allocated = 1;
454            ts->temp_local = temp_local;
455            ts->name = NULL;
456            s->nb_temps++;
457        }
458    }
459    return idx;
460}
461
462TCGv_i32 tcg_temp_new_internal_i32(int temp_local)
463{
464    int idx;
465
466    idx = tcg_temp_new_internal(TCG_TYPE_I32, temp_local);
467    return MAKE_TCGV_I32(idx);
468}
469
470TCGv_i64 tcg_temp_new_internal_i64(int temp_local)
471{
472    int idx;
473
474    idx = tcg_temp_new_internal(TCG_TYPE_I64, temp_local);
475    return MAKE_TCGV_I64(idx);
476}
477
478static inline void tcg_temp_free_internal(int idx)
479{
480    TCGContext *s = &tcg_ctx;
481    TCGTemp *ts;
482    int k;
483
484    assert(idx >= s->nb_globals && idx < s->nb_temps);
485    ts = &s->temps[idx];
486    assert(ts->temp_allocated != 0);
487    ts->temp_allocated = 0;
488    k = ts->base_type;
489    if (ts->temp_local)
490        k += TCG_TYPE_COUNT;
491    ts->next_free_temp = s->first_free_temp[k];
492    s->first_free_temp[k] = idx;
493}
494
495void tcg_temp_free_i32(TCGv_i32 arg)
496{
497    tcg_temp_free_internal(GET_TCGV_I32(arg));
498}
499
500void tcg_temp_free_i64(TCGv_i64 arg)
501{
502    tcg_temp_free_internal(GET_TCGV_I64(arg));
503}
504
505TCGv_i32 tcg_const_i32(int32_t val)
506{
507    TCGv_i32 t0;
508    t0 = tcg_temp_new_i32();
509    tcg_gen_movi_i32(t0, val);
510    return t0;
511}
512
513TCGv_i64 tcg_const_i64(int64_t val)
514{
515    TCGv_i64 t0;
516    t0 = tcg_temp_new_i64();
517    tcg_gen_movi_i64(t0, val);
518    return t0;
519}
520
521TCGv_i32 tcg_const_local_i32(int32_t val)
522{
523    TCGv_i32 t0;
524    t0 = tcg_temp_local_new_i32();
525    tcg_gen_movi_i32(t0, val);
526    return t0;
527}
528
529TCGv_i64 tcg_const_local_i64(int64_t val)
530{
531    TCGv_i64 t0;
532    t0 = tcg_temp_local_new_i64();
533    tcg_gen_movi_i64(t0, val);
534    return t0;
535}
536
537void tcg_register_helper(void *func, const char *name)
538{
539    TCGContext *s = &tcg_ctx;
540    int n;
541    if ((s->nb_helpers + 1) > s->allocated_helpers) {
542        n = s->allocated_helpers;
543        if (n == 0) {
544            n = 4;
545        } else {
546            n *= 2;
547        }
548        s->helpers = realloc(s->helpers, n * sizeof(TCGHelperInfo));
549        s->allocated_helpers = n;
550    }
551    s->helpers[s->nb_helpers].func = (tcg_target_ulong)func;
552    s->helpers[s->nb_helpers].name = name;
553    s->nb_helpers++;
554}
555
556/* Note: we convert the 64 bit args to 32 bit and do some alignment
557   and endian swap. Maybe it would be better to do the alignment
558   and endian swap in tcg_reg_alloc_call(). */
559void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags,
560                   int sizemask, TCGArg ret, int nargs, TCGArg *args)
561{
562    int call_type;
563    int i;
564    int real_args;
565    int nb_rets;
566    TCGArg *nparam;
567    *gen_opc_ptr++ = INDEX_op_call;
568    nparam = gen_opparam_ptr++;
569    call_type = (flags & TCG_CALL_TYPE_MASK);
570    if (ret != TCG_CALL_DUMMY_ARG) {
571#if TCG_TARGET_REG_BITS < 64
572        if (sizemask & 1) {
573#ifdef TCG_TARGET_WORDS_BIGENDIAN
574            *gen_opparam_ptr++ = ret + 1;
575            *gen_opparam_ptr++ = ret;
576#else
577            *gen_opparam_ptr++ = ret;
578            *gen_opparam_ptr++ = ret + 1;
579#endif
580            nb_rets = 2;
581        } else
582#endif
583        {
584            *gen_opparam_ptr++ = ret;
585            nb_rets = 1;
586        }
587    } else {
588        nb_rets = 0;
589    }
590    real_args = 0;
591    for (i = 0; i < nargs; i++) {
592#if TCG_TARGET_REG_BITS < 64
593        if (sizemask & (2 << i)) {
594#ifdef TCG_TARGET_I386
595            /* REGPARM case: if the third parameter is 64 bit, it is
596               allocated on the stack */
597            if (i == 2 && call_type == TCG_CALL_TYPE_REGPARM) {
598                call_type = TCG_CALL_TYPE_REGPARM_2;
599                flags = (flags & ~TCG_CALL_TYPE_MASK) | call_type;
600            }
601#endif
602#ifdef TCG_TARGET_CALL_ALIGN_ARGS
603            /* some targets want aligned 64 bit args */
604            if (real_args & 1) {
605                *gen_opparam_ptr++ = TCG_CALL_DUMMY_ARG;
606                real_args++;
607            }
608#endif
609#ifdef TCG_TARGET_WORDS_BIGENDIAN
610            *gen_opparam_ptr++ = args[i] + 1;
611            *gen_opparam_ptr++ = args[i];
612#else
613            *gen_opparam_ptr++ = args[i];
614            *gen_opparam_ptr++ = args[i] + 1;
615#endif
616            real_args += 2;
617        } else
618#endif
619        {
620            *gen_opparam_ptr++ = args[i];
621            real_args++;
622        }
623    }
624    *gen_opparam_ptr++ = GET_TCGV_PTR(func);
625
626    *gen_opparam_ptr++ = flags;
627
628    *nparam = (nb_rets << 16) | (real_args + 1);
629
630    /* total parameters, needed to go backward in the instruction stream */
631    *gen_opparam_ptr++ = 1 + nb_rets + real_args + 3;
632}
633
634#if TCG_TARGET_REG_BITS == 32
635void tcg_gen_shifti_i64(TCGv_i64 ret, TCGv_i64 arg1,
636                        int c, int right, int arith)
637{
638    if (c == 0) {
639        tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg1));
640        tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
641    } else if (c >= 32) {
642        c -= 32;
643        if (right) {
644            if (arith) {
645                tcg_gen_sari_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
646                tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 31);
647            } else {
648                tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
649                tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
650            }
651        } else {
652            tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_LOW(arg1), c);
653            tcg_gen_movi_i32(TCGV_LOW(ret), 0);
654        }
655    } else {
656        TCGv_i32 t0, t1;
657
658        t0 = tcg_temp_new_i32();
659        t1 = tcg_temp_new_i32();
660        if (right) {
661            tcg_gen_shli_i32(t0, TCGV_HIGH(arg1), 32 - c);
662            if (arith)
663                tcg_gen_sari_i32(t1, TCGV_HIGH(arg1), c);
664            else
665                tcg_gen_shri_i32(t1, TCGV_HIGH(arg1), c);
666            tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_LOW(arg1), c);
667            tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(ret), t0);
668            tcg_gen_mov_i32(TCGV_HIGH(ret), t1);
669        } else {
670            tcg_gen_shri_i32(t0, TCGV_LOW(arg1), 32 - c);
671            /* Note: ret can be the same as arg1, so we use t1 */
672            tcg_gen_shli_i32(t1, TCGV_LOW(arg1), c);
673            tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c);
674            tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t0);
675            tcg_gen_mov_i32(TCGV_LOW(ret), t1);
676        }
677        tcg_temp_free_i32(t0);
678        tcg_temp_free_i32(t1);
679    }
680}
681#endif
682
683static void tcg_reg_alloc_start(TCGContext *s)
684{
685    int i;
686    TCGTemp *ts;
687    for(i = 0; i < s->nb_globals; i++) {
688        ts = &s->temps[i];
689        if (ts->fixed_reg) {
690            ts->val_type = TEMP_VAL_REG;
691        } else {
692            ts->val_type = TEMP_VAL_MEM;
693        }
694    }
695    for(i = s->nb_globals; i < s->nb_temps; i++) {
696        ts = &s->temps[i];
697        ts->val_type = TEMP_VAL_DEAD;
698        ts->mem_allocated = 0;
699        ts->fixed_reg = 0;
700    }
701    for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
702        s->reg_to_temp[i] = -1;
703    }
704}
705
706static char *tcg_get_arg_str_idx(TCGContext *s, char *buf, int buf_size,
707                                 int idx)
708{
709    TCGTemp *ts;
710
711    ts = &s->temps[idx];
712    if (idx < s->nb_globals) {
713        pstrcpy(buf, buf_size, ts->name);
714    } else {
715        if (ts->temp_local)
716            snprintf(buf, buf_size, "loc%d", idx - s->nb_globals);
717        else
718            snprintf(buf, buf_size, "tmp%d", idx - s->nb_globals);
719    }
720    return buf;
721}
722
723char *tcg_get_arg_str_i32(TCGContext *s, char *buf, int buf_size, TCGv_i32 arg)
724{
725    return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I32(arg));
726}
727
728char *tcg_get_arg_str_i64(TCGContext *s, char *buf, int buf_size, TCGv_i64 arg)
729{
730    return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I64(arg));
731}
732
733static int helper_cmp(const void *p1, const void *p2)
734{
735    const TCGHelperInfo *th1 = p1;
736    const TCGHelperInfo *th2 = p2;
737    if (th1->func < th2->func)
738        return -1;
739    else if (th1->func == th2->func)
740        return 0;
741    else
742        return 1;
743}
744
745/* find helper definition (Note: A hash table would be better) */
746static TCGHelperInfo *tcg_find_helper(TCGContext *s, tcg_target_ulong val)
747{
748    int m, m_min, m_max;
749    TCGHelperInfo *th;
750    tcg_target_ulong v;
751
752    if (unlikely(!s->helpers_sorted)) {
753        qsort(s->helpers, s->nb_helpers, sizeof(TCGHelperInfo),
754              helper_cmp);
755        s->helpers_sorted = 1;
756    }
757
758    /* binary search */
759    m_min = 0;
760    m_max = s->nb_helpers - 1;
761    while (m_min <= m_max) {
762        m = (m_min + m_max) >> 1;
763        th = &s->helpers[m];
764        v = th->func;
765        if (v == val)
766            return th;
767        else if (val < v) {
768            m_max = m - 1;
769        } else {
770            m_min = m + 1;
771        }
772    }
773    return NULL;
774}
775
776static const char * const cond_name[] =
777{
778    [TCG_COND_EQ] = "eq",
779    [TCG_COND_NE] = "ne",
780    [TCG_COND_LT] = "lt",
781    [TCG_COND_GE] = "ge",
782    [TCG_COND_LE] = "le",
783    [TCG_COND_GT] = "gt",
784    [TCG_COND_LTU] = "ltu",
785    [TCG_COND_GEU] = "geu",
786    [TCG_COND_LEU] = "leu",
787    [TCG_COND_GTU] = "gtu"
788};
789
790void tcg_dump_ops(TCGContext *s, FILE *outfile)
791{
792    const uint16_t *opc_ptr;
793    const TCGArg *args;
794    TCGArg arg;
795    int c, i, k, nb_oargs, nb_iargs, nb_cargs, first_insn;
796    const TCGOpDef *def;
797    char buf[128];
798
799    first_insn = 1;
800    opc_ptr = gen_opc_buf;
801    args = gen_opparam_buf;
802    while (opc_ptr < gen_opc_ptr) {
803        c = *opc_ptr++;
804        def = &tcg_op_defs[c];
805        if (c == INDEX_op_debug_insn_start) {
806            uint64_t pc;
807#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
808            pc = ((uint64_t)args[1] << 32) | args[0];
809#else
810            pc = args[0];
811#endif
812            if (!first_insn)
813                fprintf(outfile, "\n");
814            fprintf(outfile, " ---- 0x%" PRIx64, pc);
815            first_insn = 0;
816            nb_oargs = def->nb_oargs;
817            nb_iargs = def->nb_iargs;
818            nb_cargs = def->nb_cargs;
819        } else if (c == INDEX_op_call) {
820            TCGArg arg;
821
822            /* variable number of arguments */
823            arg = *args++;
824            nb_oargs = arg >> 16;
825            nb_iargs = arg & 0xffff;
826            nb_cargs = def->nb_cargs;
827
828            fprintf(outfile, " %s ", def->name);
829
830            /* function name */
831            fprintf(outfile, "%s",
832                    tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + nb_iargs - 1]));
833            /* flags */
834            fprintf(outfile, ",$0x%" TCG_PRIlx,
835                    args[nb_oargs + nb_iargs]);
836            /* nb out args */
837            fprintf(outfile, ",$%d", nb_oargs);
838            for(i = 0; i < nb_oargs; i++) {
839                fprintf(outfile, ",");
840                fprintf(outfile, "%s",
841                        tcg_get_arg_str_idx(s, buf, sizeof(buf), args[i]));
842            }
843            for(i = 0; i < (nb_iargs - 1); i++) {
844                fprintf(outfile, ",");
845                if (args[nb_oargs + i] == TCG_CALL_DUMMY_ARG) {
846                    fprintf(outfile, "<dummy>");
847                } else {
848                    fprintf(outfile, "%s",
849                            tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + i]));
850                }
851            }
852        } else if (c == INDEX_op_movi_i32
853#if TCG_TARGET_REG_BITS == 64
854                   || c == INDEX_op_movi_i64
855#endif
856                   ) {
857            tcg_target_ulong val;
858            TCGHelperInfo *th;
859
860            nb_oargs = def->nb_oargs;
861            nb_iargs = def->nb_iargs;
862            nb_cargs = def->nb_cargs;
863            fprintf(outfile, " %s %s,$", def->name,
864                    tcg_get_arg_str_idx(s, buf, sizeof(buf), args[0]));
865            val = args[1];
866            th = tcg_find_helper(s, val);
867            if (th) {
868                fprintf(outfile, "%s", th->name);
869            } else {
870                if (c == INDEX_op_movi_i32)
871                    fprintf(outfile, "0x%x", (uint32_t)val);
872                else
873                    fprintf(outfile, "0x%" PRIx64 , (uint64_t)val);
874            }
875        } else {
876            fprintf(outfile, " %s ", def->name);
877            if (c == INDEX_op_nopn) {
878                /* variable number of arguments */
879                nb_cargs = *args;
880                nb_oargs = 0;
881                nb_iargs = 0;
882            } else {
883                nb_oargs = def->nb_oargs;
884                nb_iargs = def->nb_iargs;
885                nb_cargs = def->nb_cargs;
886            }
887
888            k = 0;
889            for(i = 0; i < nb_oargs; i++) {
890                if (k != 0)
891                    fprintf(outfile, ",");
892                fprintf(outfile, "%s",
893                        tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
894            }
895            for(i = 0; i < nb_iargs; i++) {
896                if (k != 0)
897                    fprintf(outfile, ",");
898                fprintf(outfile, "%s",
899                        tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
900            }
901            switch (c) {
902            case INDEX_op_brcond_i32:
903#if TCG_TARGET_REG_BITS == 32
904            case INDEX_op_brcond2_i32:
905#elif TCG_TARGET_REG_BITS == 64
906            case INDEX_op_brcond_i64:
907#endif
908            case INDEX_op_setcond_i32:
909#if TCG_TARGET_REG_BITS == 32
910            case INDEX_op_setcond2_i32:
911#elif TCG_TARGET_REG_BITS == 64
912            case INDEX_op_setcond_i64:
913#endif
914                if (args[k] < ARRAY_SIZE(cond_name) && cond_name[args[k]])
915                    fprintf(outfile, ",%s", cond_name[args[k++]]);
916                else
917                    fprintf(outfile, ",$0x%" TCG_PRIlx, args[k++]);
918                i = 1;
919                break;
920            default:
921                i = 0;
922                break;
923            }
924            for(; i < nb_cargs; i++) {
925                if (k != 0)
926                    fprintf(outfile, ",");
927                arg = args[k++];
928                fprintf(outfile, "$0x%" TCG_PRIlx, arg);
929            }
930        }
931        fprintf(outfile, "\n");
932        args += nb_iargs + nb_oargs + nb_cargs;
933    }
934}
935
936/* we give more priority to constraints with less registers */
937static int get_constraint_priority(const TCGOpDef *def, int k)
938{
939    const TCGArgConstraint *arg_ct;
940
941    int i, n;
942    arg_ct = &def->args_ct[k];
943    if (arg_ct->ct & TCG_CT_ALIAS) {
944        /* an alias is equivalent to a single register */
945        n = 1;
946    } else {
947        if (!(arg_ct->ct & TCG_CT_REG))
948            return 0;
949        n = 0;
950        for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
951            if (tcg_regset_test_reg(arg_ct->u.regs, i))
952                n++;
953        }
954    }
955    return TCG_TARGET_NB_REGS - n + 1;
956}
957
958/* sort from highest priority to lowest */
959static void sort_constraints(TCGOpDef *def, int start, int n)
960{
961    int i, j, p1, p2, tmp;
962
963    for(i = 0; i < n; i++)
964        def->sorted_args[start + i] = start + i;
965    if (n <= 1)
966        return;
967    for(i = 0; i < n - 1; i++) {
968        for(j = i + 1; j < n; j++) {
969            p1 = get_constraint_priority(def, def->sorted_args[start + i]);
970            p2 = get_constraint_priority(def, def->sorted_args[start + j]);
971            if (p1 < p2) {
972                tmp = def->sorted_args[start + i];
973                def->sorted_args[start + i] = def->sorted_args[start + j];
974                def->sorted_args[start + j] = tmp;
975            }
976        }
977    }
978}
979
980void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs)
981{
982    int op;
983    TCGOpDef *def;
984    const char *ct_str;
985    int i, nb_args;
986
987    for(;;) {
988        if (tdefs->op < 0)
989            break;
990        op = tdefs->op;
991        assert(op >= 0 && op < NB_OPS);
992        def = &tcg_op_defs[op];
993#if defined(CONFIG_DEBUG_TCG)
994        /* Duplicate entry in op definitions? */
995        assert(!def->used);
996        def->used = 1;
997#endif
998        nb_args = def->nb_iargs + def->nb_oargs;
999        for(i = 0; i < nb_args; i++) {
1000            ct_str = tdefs->args_ct_str[i];
1001            /* Incomplete TCGTargetOpDef entry? */
1002            assert(ct_str != NULL);
1003            tcg_regset_clear(def->args_ct[i].u.regs);
1004            def->args_ct[i].ct = 0;
1005            if (ct_str[0] >= '0' && ct_str[0] <= '9') {
1006                int oarg;
1007                oarg = ct_str[0] - '0';
1008                assert(oarg < def->nb_oargs);
1009                assert(def->args_ct[oarg].ct & TCG_CT_REG);
1010                /* TCG_CT_ALIAS is for the output arguments. The input
1011                   argument is tagged with TCG_CT_IALIAS. */
1012                def->args_ct[i] = def->args_ct[oarg];
1013                def->args_ct[oarg].ct = TCG_CT_ALIAS;
1014                def->args_ct[oarg].alias_index = i;
1015                def->args_ct[i].ct |= TCG_CT_IALIAS;
1016                def->args_ct[i].alias_index = oarg;
1017            } else {
1018                for(;;) {
1019                    if (*ct_str == '\0')
1020                        break;
1021                    switch(*ct_str) {
1022                    case 'i':
1023                        def->args_ct[i].ct |= TCG_CT_CONST;
1024                        ct_str++;
1025                        break;
1026                    default:
1027                        if (target_parse_constraint(&def->args_ct[i], &ct_str) < 0) {
1028                            fprintf(stderr, "Invalid constraint '%s' for arg %d of operation '%s'\n",
1029                                    ct_str, i, def->name);
1030                            exit(1);
1031                        }
1032                    }
1033                }
1034            }
1035        }
1036
1037        /* TCGTargetOpDef entry with too much information? */
1038        assert(i == TCG_MAX_OP_ARGS || tdefs->args_ct_str[i] == NULL);
1039
1040        /* sort the constraints (XXX: this is just an heuristic) */
1041        sort_constraints(def, 0, def->nb_oargs);
1042        sort_constraints(def, def->nb_oargs, def->nb_iargs);
1043
1044#if 0
1045        {
1046            int i;
1047
1048            printf("%s: sorted=", def->name);
1049            for(i = 0; i < def->nb_oargs + def->nb_iargs; i++)
1050                printf(" %d", def->sorted_args[i]);
1051            printf("\n");
1052        }
1053#endif
1054        tdefs++;
1055    }
1056
1057#if defined(CONFIG_DEBUG_TCG)
1058    for (op = 0; op < ARRAY_SIZE(tcg_op_defs); op++) {
1059        if (op < INDEX_op_call || op == INDEX_op_debug_insn_start) {
1060            /* Wrong entry in op definitions? */
1061            assert(!tcg_op_defs[op].used);
1062        } else {
1063            /* Missing entry in op definitions? */
1064            assert(tcg_op_defs[op].used);
1065        }
1066    }
1067#endif
1068}
1069
1070#ifdef USE_LIVENESS_ANALYSIS
1071
1072/* set a nop for an operation using 'nb_args' */
1073static inline void tcg_set_nop(TCGContext *s, uint16_t *opc_ptr,
1074                               TCGArg *args, int nb_args)
1075{
1076    if (nb_args == 0) {
1077        *opc_ptr = INDEX_op_nop;
1078    } else {
1079        *opc_ptr = INDEX_op_nopn;
1080        args[0] = nb_args;
1081        args[nb_args - 1] = nb_args;
1082    }
1083}
1084
1085/* liveness analysis: end of function: globals are live, temps are
1086   dead. */
1087/* XXX: at this stage, not used as there would be little gains because
1088   most TBs end with a conditional jump. */
1089static inline void tcg_la_func_end(TCGContext *s, uint8_t *dead_temps)
1090{
1091    memset(dead_temps, 0, s->nb_globals);
1092    memset(dead_temps + s->nb_globals, 1, s->nb_temps - s->nb_globals);
1093}
1094
1095/* liveness analysis: end of basic block: globals are live, temps are
1096   dead, local temps are live. */
1097static inline void tcg_la_bb_end(TCGContext *s, uint8_t *dead_temps)
1098{
1099    int i;
1100    TCGTemp *ts;
1101
1102    memset(dead_temps, 0, s->nb_globals);
1103    ts = &s->temps[s->nb_globals];
1104    for(i = s->nb_globals; i < s->nb_temps; i++) {
1105        if (ts->temp_local)
1106            dead_temps[i] = 0;
1107        else
1108            dead_temps[i] = 1;
1109        ts++;
1110    }
1111}
1112
1113/* Liveness analysis : update the opc_dead_iargs array to tell if a
1114   given input arguments is dead. Instructions updating dead
1115   temporaries are removed. */
1116static void tcg_liveness_analysis(TCGContext *s)
1117{
1118    int i, op_index, op, nb_args, nb_iargs, nb_oargs, arg, nb_ops;
1119    TCGArg *args;
1120    const TCGOpDef *def;
1121    uint8_t *dead_temps;
1122    unsigned int dead_iargs;
1123
1124    /* sanity check */
1125    if (gen_opc_ptr - gen_opc_buf > OPC_BUF_SIZE) {
1126        fprintf(stderr, "PANIC: too many opcodes generated (%d > %d)\n",
1127                gen_opc_ptr - gen_opc_buf, OPC_BUF_SIZE);
1128        tcg_abort();
1129    }
1130
1131    gen_opc_ptr++; /* skip end */
1132
1133    nb_ops = gen_opc_ptr - gen_opc_buf;
1134
1135    s->op_dead_iargs = tcg_malloc(nb_ops * sizeof(uint16_t));
1136
1137    dead_temps = tcg_malloc(s->nb_temps);
1138    memset(dead_temps, 1, s->nb_temps);
1139
1140    args = gen_opparam_ptr;
1141    op_index = nb_ops - 1;
1142    while (op_index >= 0) {
1143        op = gen_opc_buf[op_index];
1144        def = &tcg_op_defs[op];
1145        switch(op) {
1146        case INDEX_op_call:
1147            {
1148                int call_flags;
1149
1150                nb_args = args[-1];
1151                args -= nb_args;
1152                nb_iargs = args[0] & 0xffff;
1153                nb_oargs = args[0] >> 16;
1154                args++;
1155                call_flags = args[nb_oargs + nb_iargs];
1156
1157                /* pure functions can be removed if their result is not
1158                   used */
1159                if (call_flags & TCG_CALL_PURE) {
1160                    for(i = 0; i < nb_oargs; i++) {
1161                        arg = args[i];
1162                        if (!dead_temps[arg])
1163                            goto do_not_remove_call;
1164                    }
1165                    tcg_set_nop(s, gen_opc_buf + op_index,
1166                                args - 1, nb_args);
1167                } else {
1168                do_not_remove_call:
1169
1170                    /* output args are dead */
1171                    for(i = 0; i < nb_oargs; i++) {
1172                        arg = args[i];
1173                        dead_temps[arg] = 1;
1174                    }
1175
1176                    if (!(call_flags & TCG_CALL_CONST)) {
1177                        /* globals are live (they may be used by the call) */
1178                        memset(dead_temps, 0, s->nb_globals);
1179                    }
1180
1181                    /* input args are live */
1182                    dead_iargs = 0;
1183                    for(i = 0; i < nb_iargs; i++) {
1184                        arg = args[i + nb_oargs];
1185                        if (arg != TCG_CALL_DUMMY_ARG) {
1186                            if (dead_temps[arg]) {
1187                                dead_iargs |= (1 << i);
1188                            }
1189                            dead_temps[arg] = 0;
1190                        }
1191                    }
1192                    s->op_dead_iargs[op_index] = dead_iargs;
1193                }
1194                args--;
1195            }
1196            break;
1197        case INDEX_op_set_label:
1198            args--;
1199            /* mark end of basic block */
1200            tcg_la_bb_end(s, dead_temps);
1201            break;
1202        case INDEX_op_debug_insn_start:
1203            args -= def->nb_args;
1204            break;
1205        case INDEX_op_nopn:
1206            nb_args = args[-1];
1207            args -= nb_args;
1208            break;
1209        case INDEX_op_discard:
1210            args--;
1211            /* mark the temporary as dead */
1212            dead_temps[args[0]] = 1;
1213            break;
1214        case INDEX_op_end:
1215            break;
1216            /* XXX: optimize by hardcoding common cases (e.g. triadic ops) */
1217        default:
1218            args -= def->nb_args;
1219            nb_iargs = def->nb_iargs;
1220            nb_oargs = def->nb_oargs;
1221
1222            /* Test if the operation can be removed because all
1223               its outputs are dead. We assume that nb_oargs == 0
1224               implies side effects */
1225            if (!(def->flags & TCG_OPF_SIDE_EFFECTS) && nb_oargs != 0) {
1226                for(i = 0; i < nb_oargs; i++) {
1227                    arg = args[i];
1228                    if (!dead_temps[arg])
1229                        goto do_not_remove;
1230                }
1231                tcg_set_nop(s, gen_opc_buf + op_index, args, def->nb_args);
1232#ifdef CONFIG_PROFILER
1233                s->del_op_count++;
1234#endif
1235            } else {
1236            do_not_remove:
1237
1238                /* output args are dead */
1239                for(i = 0; i < nb_oargs; i++) {
1240                    arg = args[i];
1241                    dead_temps[arg] = 1;
1242                }
1243
1244                /* if end of basic block, update */
1245                if (def->flags & TCG_OPF_BB_END) {
1246                    tcg_la_bb_end(s, dead_temps);
1247                } else if (def->flags & TCG_OPF_CALL_CLOBBER) {
1248                    /* globals are live */
1249                    memset(dead_temps, 0, s->nb_globals);
1250                }
1251
1252                /* input args are live */
1253                dead_iargs = 0;
1254                for(i = 0; i < nb_iargs; i++) {
1255                    arg = args[i + nb_oargs];
1256                    if (dead_temps[arg]) {
1257                        dead_iargs |= (1 << i);
1258                    }
1259                    dead_temps[arg] = 0;
1260                }
1261                s->op_dead_iargs[op_index] = dead_iargs;
1262            }
1263            break;
1264        }
1265        op_index--;
1266    }
1267
1268    if (args != gen_opparam_buf)
1269        tcg_abort();
1270}
1271#else
1272/* dummy liveness analysis */
1273void tcg_liveness_analysis(TCGContext *s)
1274{
1275    int nb_ops;
1276    nb_ops = gen_opc_ptr - gen_opc_buf;
1277
1278    s->op_dead_iargs = tcg_malloc(nb_ops * sizeof(uint16_t));
1279    memset(s->op_dead_iargs, 0, nb_ops * sizeof(uint16_t));
1280}
1281#endif
1282
1283#ifndef NDEBUG
1284static void dump_regs(TCGContext *s)
1285{
1286    TCGTemp *ts;
1287    int i;
1288    char buf[64];
1289
1290    for(i = 0; i < s->nb_temps; i++) {
1291        ts = &s->temps[i];
1292        printf("  %10s: ", tcg_get_arg_str_idx(s, buf, sizeof(buf), i));
1293        switch(ts->val_type) {
1294        case TEMP_VAL_REG:
1295            printf("%s", tcg_target_reg_names[ts->reg]);
1296            break;
1297        case TEMP_VAL_MEM:
1298            printf("%d(%s)", (int)ts->mem_offset, tcg_target_reg_names[ts->mem_reg]);
1299            break;
1300        case TEMP_VAL_CONST:
1301            printf("$0x%" TCG_PRIlx, ts->val);
1302            break;
1303        case TEMP_VAL_DEAD:
1304            printf("D");
1305            break;
1306        default:
1307            printf("???");
1308            break;
1309        }
1310        printf("\n");
1311    }
1312
1313    for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
1314        if (s->reg_to_temp[i] >= 0) {
1315            printf("%s: %s\n",
1316                   tcg_target_reg_names[i],
1317                   tcg_get_arg_str_idx(s, buf, sizeof(buf), s->reg_to_temp[i]));
1318        }
1319    }
1320}
1321
1322static void check_regs(TCGContext *s)
1323{
1324    int reg, k;
1325    TCGTemp *ts;
1326    char buf[64];
1327
1328    for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1329        k = s->reg_to_temp[reg];
1330        if (k >= 0) {
1331            ts = &s->temps[k];
1332            if (ts->val_type != TEMP_VAL_REG ||
1333                ts->reg != reg) {
1334                printf("Inconsistency for register %s:\n",
1335                       tcg_target_reg_names[reg]);
1336                goto fail;
1337            }
1338        }
1339    }
1340    for(k = 0; k < s->nb_temps; k++) {
1341        ts = &s->temps[k];
1342        if (ts->val_type == TEMP_VAL_REG &&
1343            !ts->fixed_reg &&
1344            s->reg_to_temp[ts->reg] != k) {
1345                printf("Inconsistency for temp %s:\n",
1346                       tcg_get_arg_str_idx(s, buf, sizeof(buf), k));
1347        fail:
1348                printf("reg state:\n");
1349                dump_regs(s);
1350                tcg_abort();
1351        }
1352    }
1353}
1354#endif
1355
1356static void temp_allocate_frame(TCGContext *s, int temp)
1357{
1358    TCGTemp *ts;
1359    ts = &s->temps[temp];
1360    s->current_frame_offset = (s->current_frame_offset + sizeof(tcg_target_long) - 1) & ~(sizeof(tcg_target_long) - 1);
1361    if (s->current_frame_offset + sizeof(tcg_target_long) > s->frame_end)
1362        tcg_abort();
1363    ts->mem_offset = s->current_frame_offset;
1364    ts->mem_reg = s->frame_reg;
1365    ts->mem_allocated = 1;
1366    s->current_frame_offset += sizeof(tcg_target_long);
1367}
1368
1369/* free register 'reg' by spilling the corresponding temporary if necessary */
1370static void tcg_reg_free(TCGContext *s, int reg)
1371{
1372    TCGTemp *ts;
1373    int temp;
1374
1375    temp = s->reg_to_temp[reg];
1376    if (temp != -1) {
1377        ts = &s->temps[temp];
1378        assert(ts->val_type == TEMP_VAL_REG);
1379        if (!ts->mem_coherent) {
1380            if (!ts->mem_allocated)
1381                temp_allocate_frame(s, temp);
1382            tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1383        }
1384        ts->val_type = TEMP_VAL_MEM;
1385        s->reg_to_temp[reg] = -1;
1386    }
1387}
1388
1389/* Allocate a register belonging to reg1 & ~reg2 */
1390static int tcg_reg_alloc(TCGContext *s, TCGRegSet reg1, TCGRegSet reg2)
1391{
1392    int i, reg;
1393    TCGRegSet reg_ct;
1394
1395    tcg_regset_andnot(reg_ct, reg1, reg2);
1396
1397    /* first try free registers */
1398    for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1399        reg = tcg_target_reg_alloc_order[i];
1400        if (tcg_regset_test_reg(reg_ct, reg) && s->reg_to_temp[reg] == -1)
1401            return reg;
1402    }
1403
1404    /* XXX: do better spill choice */
1405    for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1406        reg = tcg_target_reg_alloc_order[i];
1407        if (tcg_regset_test_reg(reg_ct, reg)) {
1408            tcg_reg_free(s, reg);
1409            return reg;
1410        }
1411    }
1412
1413    tcg_abort();
1414}
1415
1416/* save a temporary to memory. 'allocated_regs' is used in case a
1417   temporary registers needs to be allocated to store a constant. */
1418static void temp_save(TCGContext *s, int temp, TCGRegSet allocated_regs)
1419{
1420    TCGTemp *ts;
1421    int reg;
1422
1423    ts = &s->temps[temp];
1424    if (!ts->fixed_reg) {
1425        switch(ts->val_type) {
1426        case TEMP_VAL_REG:
1427            tcg_reg_free(s, ts->reg);
1428            break;
1429        case TEMP_VAL_DEAD:
1430            ts->val_type = TEMP_VAL_MEM;
1431            break;
1432        case TEMP_VAL_CONST:
1433            reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type],
1434                                allocated_regs);
1435            if (!ts->mem_allocated)
1436                temp_allocate_frame(s, temp);
1437            tcg_out_movi(s, ts->type, reg, ts->val);
1438            tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1439            ts->val_type = TEMP_VAL_MEM;
1440            break;
1441        case TEMP_VAL_MEM:
1442            break;
1443        default:
1444            tcg_abort();
1445        }
1446    }
1447}
1448
1449/* save globals to their cannonical location and assume they can be
1450   modified be the following code. 'allocated_regs' is used in case a
1451   temporary registers needs to be allocated to store a constant. */
1452static void save_globals(TCGContext *s, TCGRegSet allocated_regs)
1453{
1454    int i;
1455
1456    for(i = 0; i < s->nb_globals; i++) {
1457        temp_save(s, i, allocated_regs);
1458    }
1459}
1460
1461/* at the end of a basic block, we assume all temporaries are dead and
1462   all globals are stored at their canonical location. */
1463static void tcg_reg_alloc_bb_end(TCGContext *s, TCGRegSet allocated_regs)
1464{
1465    TCGTemp *ts;
1466    int i;
1467
1468    for(i = s->nb_globals; i < s->nb_temps; i++) {
1469        ts = &s->temps[i];
1470        if (ts->temp_local) {
1471            temp_save(s, i, allocated_regs);
1472        } else {
1473            if (ts->val_type == TEMP_VAL_REG) {
1474                s->reg_to_temp[ts->reg] = -1;
1475            }
1476            ts->val_type = TEMP_VAL_DEAD;
1477        }
1478    }
1479
1480    save_globals(s, allocated_regs);
1481}
1482
1483#define IS_DEAD_IARG(n) ((dead_iargs >> (n)) & 1)
1484
1485static void tcg_reg_alloc_movi(TCGContext *s, const TCGArg *args)
1486{
1487    TCGTemp *ots;
1488    tcg_target_ulong val;
1489
1490    ots = &s->temps[args[0]];
1491    val = args[1];
1492
1493    if (ots->fixed_reg) {
1494        /* for fixed registers, we do not do any constant
1495           propagation */
1496        tcg_out_movi(s, ots->type, ots->reg, val);
1497    } else {
1498        /* The movi is not explicitly generated here */
1499        if (ots->val_type == TEMP_VAL_REG)
1500            s->reg_to_temp[ots->reg] = -1;
1501        ots->val_type = TEMP_VAL_CONST;
1502        ots->val = val;
1503    }
1504}
1505
1506static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
1507                              const TCGArg *args,
1508                              unsigned int dead_iargs)
1509{
1510    TCGTemp *ts, *ots;
1511    int reg;
1512    const TCGArgConstraint *arg_ct;
1513
1514    ots = &s->temps[args[0]];
1515    ts = &s->temps[args[1]];
1516    arg_ct = &def->args_ct[0];
1517
1518    /* XXX: always mark arg dead if IS_DEAD_IARG(0) */
1519    if (ts->val_type == TEMP_VAL_REG) {
1520        if (IS_DEAD_IARG(0) && !ts->fixed_reg && !ots->fixed_reg) {
1521            /* the mov can be suppressed */
1522            if (ots->val_type == TEMP_VAL_REG)
1523                s->reg_to_temp[ots->reg] = -1;
1524            reg = ts->reg;
1525            s->reg_to_temp[reg] = -1;
1526            ts->val_type = TEMP_VAL_DEAD;
1527        } else {
1528            if (ots->val_type == TEMP_VAL_REG) {
1529                reg = ots->reg;
1530            } else {
1531                reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1532            }
1533            if (ts->reg != reg) {
1534                tcg_out_mov(s, reg, ts->reg);
1535            }
1536        }
1537    } else if (ts->val_type == TEMP_VAL_MEM) {
1538        if (ots->val_type == TEMP_VAL_REG) {
1539            reg = ots->reg;
1540        } else {
1541            reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1542        }
1543        tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1544    } else if (ts->val_type == TEMP_VAL_CONST) {
1545        if (ots->fixed_reg) {
1546            reg = ots->reg;
1547            tcg_out_movi(s, ots->type, reg, ts->val);
1548        } else {
1549            /* propagate constant */
1550            if (ots->val_type == TEMP_VAL_REG)
1551                s->reg_to_temp[ots->reg] = -1;
1552            ots->val_type = TEMP_VAL_CONST;
1553            ots->val = ts->val;
1554            return;
1555        }
1556    } else {
1557        tcg_abort();
1558    }
1559    s->reg_to_temp[reg] = args[0];
1560    ots->reg = reg;
1561    ots->val_type = TEMP_VAL_REG;
1562    ots->mem_coherent = 0;
1563}
1564
1565static void tcg_reg_alloc_op(TCGContext *s,
1566                             const TCGOpDef *def, int opc,
1567                             const TCGArg *args,
1568                             unsigned int dead_iargs)
1569{
1570    TCGRegSet allocated_regs;
1571    int i, k, nb_iargs, nb_oargs, reg;
1572    TCGArg arg;
1573    const TCGArgConstraint *arg_ct;
1574    TCGTemp *ts;
1575    TCGArg new_args[TCG_MAX_OP_ARGS];
1576    int const_args[TCG_MAX_OP_ARGS];
1577
1578    nb_oargs = def->nb_oargs;
1579    nb_iargs = def->nb_iargs;
1580
1581    /* copy constants */
1582    memcpy(new_args + nb_oargs + nb_iargs,
1583           args + nb_oargs + nb_iargs,
1584           sizeof(TCGArg) * def->nb_cargs);
1585
1586    /* satisfy input constraints */
1587    tcg_regset_set(allocated_regs, s->reserved_regs);
1588    for(k = 0; k < nb_iargs; k++) {
1589        i = def->sorted_args[nb_oargs + k];
1590        arg = args[i];
1591        arg_ct = &def->args_ct[i];
1592        ts = &s->temps[arg];
1593        if (ts->val_type == TEMP_VAL_MEM) {
1594            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1595            tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1596            ts->val_type = TEMP_VAL_REG;
1597            ts->reg = reg;
1598            ts->mem_coherent = 1;
1599            s->reg_to_temp[reg] = arg;
1600        } else if (ts->val_type == TEMP_VAL_CONST) {
1601            if (tcg_target_const_match(ts->val, arg_ct)) {
1602                /* constant is OK for instruction */
1603                const_args[i] = 1;
1604                new_args[i] = ts->val;
1605                goto iarg_end;
1606            } else {
1607                /* need to move to a register */
1608                reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1609                tcg_out_movi(s, ts->type, reg, ts->val);
1610                ts->val_type = TEMP_VAL_REG;
1611                ts->reg = reg;
1612                ts->mem_coherent = 0;
1613                s->reg_to_temp[reg] = arg;
1614            }
1615        }
1616        assert(ts->val_type == TEMP_VAL_REG);
1617        if (arg_ct->ct & TCG_CT_IALIAS) {
1618            if (ts->fixed_reg) {
1619                /* if fixed register, we must allocate a new register
1620                   if the alias is not the same register */
1621                if (arg != args[arg_ct->alias_index])
1622                    goto allocate_in_reg;
1623            } else {
1624                /* if the input is aliased to an output and if it is
1625                   not dead after the instruction, we must allocate
1626                   a new register and move it */
1627                if (!IS_DEAD_IARG(i - nb_oargs))
1628                    goto allocate_in_reg;
1629            }
1630        }
1631        reg = ts->reg;
1632        if (tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1633            /* nothing to do : the constraint is satisfied */
1634        } else {
1635        allocate_in_reg:
1636            /* allocate a new register matching the constraint
1637               and move the temporary register into it */
1638            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1639            tcg_out_mov(s, reg, ts->reg);
1640        }
1641        new_args[i] = reg;
1642        const_args[i] = 0;
1643        tcg_regset_set_reg(allocated_regs, reg);
1644    iarg_end: ;
1645    }
1646
1647    if (def->flags & TCG_OPF_BB_END) {
1648        tcg_reg_alloc_bb_end(s, allocated_regs);
1649    } else {
1650        /* mark dead temporaries and free the associated registers */
1651        for(i = 0; i < nb_iargs; i++) {
1652            arg = args[nb_oargs + i];
1653            if (IS_DEAD_IARG(i)) {
1654                ts = &s->temps[arg];
1655                if (!ts->fixed_reg) {
1656                    if (ts->val_type == TEMP_VAL_REG)
1657                        s->reg_to_temp[ts->reg] = -1;
1658                    ts->val_type = TEMP_VAL_DEAD;
1659                }
1660            }
1661        }
1662
1663        if (def->flags & TCG_OPF_CALL_CLOBBER) {
1664            /* XXX: permit generic clobber register list ? */
1665            for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1666                if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
1667                    tcg_reg_free(s, reg);
1668                }
1669            }
1670            /* XXX: for load/store we could do that only for the slow path
1671               (i.e. when a memory callback is called) */
1672
1673            /* store globals and free associated registers (we assume the insn
1674               can modify any global. */
1675            save_globals(s, allocated_regs);
1676        }
1677
1678        /* satisfy the output constraints */
1679        tcg_regset_set(allocated_regs, s->reserved_regs);
1680        for(k = 0; k < nb_oargs; k++) {
1681            i = def->sorted_args[k];
1682            arg = args[i];
1683            arg_ct = &def->args_ct[i];
1684            ts = &s->temps[arg];
1685            if (arg_ct->ct & TCG_CT_ALIAS) {
1686                reg = new_args[arg_ct->alias_index];
1687            } else {
1688                /* if fixed register, we try to use it */
1689                reg = ts->reg;
1690                if (ts->fixed_reg &&
1691                    tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1692                    goto oarg_end;
1693                }
1694                reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1695            }
1696            tcg_regset_set_reg(allocated_regs, reg);
1697            /* if a fixed register is used, then a move will be done afterwards */
1698            if (!ts->fixed_reg) {
1699                if (ts->val_type == TEMP_VAL_REG)
1700                    s->reg_to_temp[ts->reg] = -1;
1701                ts->val_type = TEMP_VAL_REG;
1702                ts->reg = reg;
1703                /* temp value is modified, so the value kept in memory is
1704                   potentially not the same */
1705                ts->mem_coherent = 0;
1706                s->reg_to_temp[reg] = arg;
1707            }
1708        oarg_end:
1709            new_args[i] = reg;
1710        }
1711    }
1712
1713    /* emit instruction */
1714    tcg_out_op(s, opc, new_args, const_args);
1715
1716    /* move the outputs in the correct register if needed */
1717    for(i = 0; i < nb_oargs; i++) {
1718        ts = &s->temps[args[i]];
1719        reg = new_args[i];
1720        if (ts->fixed_reg && ts->reg != reg) {
1721            tcg_out_mov(s, ts->reg, reg);
1722        }
1723    }
1724}
1725
1726#ifdef TCG_TARGET_STACK_GROWSUP
1727#define STACK_DIR(x) (-(x))
1728#else
1729#define STACK_DIR(x) (x)
1730#endif
1731
1732static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
1733                              int opc, const TCGArg *args,
1734                              unsigned int dead_iargs)
1735{
1736    int nb_iargs, nb_oargs, flags, nb_regs, i, reg, nb_params;
1737    TCGArg arg, func_arg;
1738    TCGTemp *ts;
1739    tcg_target_long stack_offset, call_stack_size, func_addr;
1740    int const_func_arg, allocate_args;
1741    TCGRegSet allocated_regs;
1742    const TCGArgConstraint *arg_ct;
1743
1744    arg = *args++;
1745
1746    nb_oargs = arg >> 16;
1747    nb_iargs = arg & 0xffff;
1748    nb_params = nb_iargs - 1;
1749
1750    flags = args[nb_oargs + nb_iargs];
1751
1752    nb_regs = tcg_target_get_call_iarg_regs_count(flags);
1753    if (nb_regs > nb_params)
1754        nb_regs = nb_params;
1755
1756    /* assign stack slots first */
1757    /* XXX: preallocate call stack */
1758    call_stack_size = (nb_params - nb_regs) * sizeof(tcg_target_long);
1759    call_stack_size = (call_stack_size + TCG_TARGET_STACK_ALIGN - 1) &
1760        ~(TCG_TARGET_STACK_ALIGN - 1);
1761    allocate_args = (call_stack_size > TCG_STATIC_CALL_ARGS_SIZE);
1762    if (allocate_args) {
1763        tcg_out_addi(s, TCG_REG_CALL_STACK, -STACK_DIR(call_stack_size));
1764    }
1765
1766    stack_offset = TCG_TARGET_CALL_STACK_OFFSET;
1767    for(i = nb_regs; i < nb_params; i++) {
1768        arg = args[nb_oargs + i];
1769#ifdef TCG_TARGET_STACK_GROWSUP
1770        stack_offset -= sizeof(tcg_target_long);
1771#endif
1772        if (arg != TCG_CALL_DUMMY_ARG) {
1773            ts = &s->temps[arg];
1774            if (ts->val_type == TEMP_VAL_REG) {
1775                tcg_out_st(s, ts->type, ts->reg, TCG_REG_CALL_STACK, stack_offset);
1776            } else if (ts->val_type == TEMP_VAL_MEM) {
1777                reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type],
1778                                    s->reserved_regs);
1779                /* XXX: not correct if reading values from the stack */
1780                tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1781                tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
1782            } else if (ts->val_type == TEMP_VAL_CONST) {
1783                reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type],
1784                                    s->reserved_regs);
1785                /* XXX: sign extend may be needed on some targets */
1786                tcg_out_movi(s, ts->type, reg, ts->val);
1787                tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
1788            } else {
1789                tcg_abort();
1790            }
1791        }
1792#ifndef TCG_TARGET_STACK_GROWSUP
1793        stack_offset += sizeof(tcg_target_long);
1794#endif
1795    }
1796
1797    /* assign input registers */
1798    tcg_regset_set(allocated_regs, s->reserved_regs);
1799    for(i = 0; i < nb_regs; i++) {
1800        arg = args[nb_oargs + i];
1801        if (arg != TCG_CALL_DUMMY_ARG) {
1802            ts = &s->temps[arg];
1803            reg = tcg_target_call_iarg_regs[i];
1804            tcg_reg_free(s, reg);
1805            if (ts->val_type == TEMP_VAL_REG) {
1806                if (ts->reg != reg) {
1807                    tcg_out_mov(s, reg, ts->reg);
1808                }
1809            } else if (ts->val_type == TEMP_VAL_MEM) {
1810                tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1811            } else if (ts->val_type == TEMP_VAL_CONST) {
1812                /* XXX: sign extend ? */
1813                tcg_out_movi(s, ts->type, reg, ts->val);
1814            } else {
1815                tcg_abort();
1816            }
1817            tcg_regset_set_reg(allocated_regs, reg);
1818        }
1819    }
1820
1821    /* assign function address */
1822    func_arg = args[nb_oargs + nb_iargs - 1];
1823    arg_ct = &def->args_ct[0];
1824    ts = &s->temps[func_arg];
1825    func_addr = ts->val;
1826    const_func_arg = 0;
1827    if (ts->val_type == TEMP_VAL_MEM) {
1828        reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1829        tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1830        func_arg = reg;
1831        tcg_regset_set_reg(allocated_regs, reg);
1832    } else if (ts->val_type == TEMP_VAL_REG) {
1833        reg = ts->reg;
1834        if (!tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1835            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1836            tcg_out_mov(s, reg, ts->reg);
1837        }
1838        func_arg = reg;
1839        tcg_regset_set_reg(allocated_regs, reg);
1840    } else if (ts->val_type == TEMP_VAL_CONST) {
1841        if (tcg_target_const_match(func_addr, arg_ct)) {
1842            const_func_arg = 1;
1843            func_arg = func_addr;
1844        } else {
1845            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1846            tcg_out_movi(s, ts->type, reg, func_addr);
1847            func_arg = reg;
1848            tcg_regset_set_reg(allocated_regs, reg);
1849        }
1850    } else {
1851        tcg_abort();
1852    }
1853
1854
1855    /* mark dead temporaries and free the associated registers */
1856    for(i = 0; i < nb_iargs; i++) {
1857        arg = args[nb_oargs + i];
1858        if (IS_DEAD_IARG(i)) {
1859            ts = &s->temps[arg];
1860            if (!ts->fixed_reg) {
1861                if (ts->val_type == TEMP_VAL_REG)
1862                    s->reg_to_temp[ts->reg] = -1;
1863                ts->val_type = TEMP_VAL_DEAD;
1864            }
1865        }
1866    }
1867
1868    /* clobber call registers */
1869    for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1870        if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
1871            tcg_reg_free(s, reg);
1872        }
1873    }
1874
1875    /* store globals and free associated registers (we assume the call
1876       can modify any global. */
1877    if (!(flags & TCG_CALL_CONST)) {
1878        save_globals(s, allocated_regs);
1879    }
1880
1881    tcg_out_op(s, opc, &func_arg, &const_func_arg);
1882
1883    if (allocate_args) {
1884        tcg_out_addi(s, TCG_REG_CALL_STACK, STACK_DIR(call_stack_size));
1885    }
1886
1887    /* assign output registers and emit moves if needed */
1888    for(i = 0; i < nb_oargs; i++) {
1889        arg = args[i];
1890        ts = &s->temps[arg];
1891        reg = tcg_target_call_oarg_regs[i];
1892        assert(s->reg_to_temp[reg] == -1);
1893        if (ts->fixed_reg) {
1894            if (ts->reg != reg) {
1895                tcg_out_mov(s, ts->reg, reg);
1896            }
1897        } else {
1898            if (ts->val_type == TEMP_VAL_REG)
1899                s->reg_to_temp[ts->reg] = -1;
1900            ts->val_type = TEMP_VAL_REG;
1901            ts->reg = reg;
1902            ts->mem_coherent = 0;
1903            s->reg_to_temp[reg] = arg;
1904        }
1905    }
1906
1907    return nb_iargs + nb_oargs + def->nb_cargs + 1;
1908}
1909
1910#ifdef CONFIG_PROFILER
1911
1912static int64_t tcg_table_op_count[NB_OPS];
1913
1914void dump_op_count(void)
1915{
1916    int i;
1917    FILE *f;
1918    f = fopen("/tmp/op.log", "w");
1919    for(i = INDEX_op_end; i < NB_OPS; i++) {
1920        fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name, tcg_table_op_count[i]);
1921    }
1922    fclose(f);
1923}
1924#endif
1925
1926
1927static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
1928                                      long search_pc)
1929{
1930    int opc, op_index;
1931    const TCGOpDef *def;
1932    unsigned int dead_iargs;
1933    const TCGArg *args;
1934#ifdef CONFIG_MEMCHECK
1935    unsigned int tpc2gpc_index = 0;
1936#endif  // CONFIG_MEMCHECK
1937
1938#ifdef DEBUG_DISAS
1939    if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
1940        qemu_log("OP:\n");
1941        tcg_dump_ops(s, logfile);
1942        qemu_log("\n");
1943    }
1944#endif
1945
1946#ifdef CONFIG_PROFILER
1947    s->la_time -= profile_getclock();
1948#endif
1949    tcg_liveness_analysis(s);
1950#ifdef CONFIG_PROFILER
1951    s->la_time += profile_getclock();
1952#endif
1953
1954#ifdef DEBUG_DISAS
1955    if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_OPT))) {
1956        qemu_log("OP after liveness analysis:\n");
1957        tcg_dump_ops(s, logfile);
1958        qemu_log("\n");
1959    }
1960#endif
1961
1962    tcg_reg_alloc_start(s);
1963
1964    s->code_buf = gen_code_buf;
1965    s->code_ptr = gen_code_buf;
1966
1967    args = gen_opparam_buf;
1968    op_index = 0;
1969
1970#ifdef CONFIG_MEMCHECK
1971    gen_opc_tpc2gpc_pairs = 0;
1972#endif  // CONFIG_MEMCHECK
1973
1974    for(;;) {
1975#ifdef CONFIG_MEMCHECK
1976        /* On condition that memcheck is enabled, and operation index reached
1977         * new operation in the guest code, save (pc_tb, pc_guest) pair into
1978         * gen_opc_tpc2gpc array. Note that we do that only on condition that
1979         * search_pc is < 0. This way we make sure that this is "normal"
1980         * translation, called from tcg_gen_code, and not from
1981         * tcg_gen_code_search_pc. */
1982        if (memcheck_enabled && search_pc < 0 &&
1983            gen_opc_instr_start[op_index]) {
1984            gen_opc_tpc2gpc_ptr[tpc2gpc_index] = (target_ulong)s->code_ptr;
1985            tpc2gpc_index++;
1986            gen_opc_tpc2gpc_ptr[tpc2gpc_index] = gen_opc_pc[op_index];
1987            tpc2gpc_index++;
1988            gen_opc_tpc2gpc_pairs++;
1989        }
1990#endif  // CONFIG_MEMCHECK
1991        opc = gen_opc_buf[op_index];
1992#ifdef CONFIG_PROFILER
1993        tcg_table_op_count[opc]++;
1994#endif
1995        def = &tcg_op_defs[opc];
1996#if 0
1997        printf("%s: %d %d %d\n", def->name,
1998               def->nb_oargs, def->nb_iargs, def->nb_cargs);
1999        //        dump_regs(s);
2000#endif
2001        switch(opc) {
2002        case INDEX_op_mov_i32:
2003#if TCG_TARGET_REG_BITS == 64
2004        case INDEX_op_mov_i64:
2005#endif
2006            dead_iargs = s->op_dead_iargs[op_index];
2007            tcg_reg_alloc_mov(s, def, args, dead_iargs);
2008            break;
2009        case INDEX_op_movi_i32:
2010#if TCG_TARGET_REG_BITS == 64
2011        case INDEX_op_movi_i64:
2012#endif
2013            tcg_reg_alloc_movi(s, args);
2014            break;
2015        case INDEX_op_debug_insn_start:
2016            /* debug instruction */
2017            break;
2018        case INDEX_op_nop:
2019        case INDEX_op_nop1:
2020        case INDEX_op_nop2:
2021        case INDEX_op_nop3:
2022            break;
2023        case INDEX_op_nopn:
2024            args += args[0];
2025            goto next;
2026        case INDEX_op_discard:
2027            {
2028                TCGTemp *ts;
2029                ts = &s->temps[args[0]];
2030                /* mark the temporary as dead */
2031                if (!ts->fixed_reg) {
2032                    if (ts->val_type == TEMP_VAL_REG)
2033                        s->reg_to_temp[ts->reg] = -1;
2034                    ts->val_type = TEMP_VAL_DEAD;
2035                }
2036            }
2037            break;
2038        case INDEX_op_set_label:
2039            tcg_reg_alloc_bb_end(s, s->reserved_regs);
2040            tcg_out_label(s, args[0], (long)s->code_ptr);
2041            break;
2042        case INDEX_op_call:
2043            dead_iargs = s->op_dead_iargs[op_index];
2044            args += tcg_reg_alloc_call(s, def, opc, args, dead_iargs);
2045            goto next;
2046        case INDEX_op_end:
2047            goto the_end;
2048        default:
2049            /* Note: in order to speed up the code, it would be much
2050               faster to have specialized register allocator functions for
2051               some common argument patterns */
2052            dead_iargs = s->op_dead_iargs[op_index];
2053            tcg_reg_alloc_op(s, def, opc, args, dead_iargs);
2054            break;
2055        }
2056        args += def->nb_args;
2057    next:
2058        if (search_pc >= 0 && search_pc < s->code_ptr - gen_code_buf) {
2059            return op_index;
2060        }
2061        op_index++;
2062#ifndef NDEBUG
2063        check_regs(s);
2064#endif
2065    }
2066 the_end:
2067    return -1;
2068}
2069
2070int tcg_gen_code(TCGContext *s, uint8_t *gen_code_buf)
2071{
2072#ifdef CONFIG_PROFILER
2073    {
2074        int n;
2075        n = (gen_opc_ptr - gen_opc_buf);
2076        s->op_count += n;
2077        if (n > s->op_count_max)
2078            s->op_count_max = n;
2079
2080        s->temp_count += s->nb_temps;
2081        if (s->nb_temps > s->temp_count_max)
2082            s->temp_count_max = s->nb_temps;
2083    }
2084#endif
2085
2086    /* sanity check */
2087    if (gen_opc_ptr - gen_opc_buf > OPC_BUF_SIZE) {
2088        fprintf(stderr, "PANIC: too many opcodes generated (%d > %d)\n",
2089                gen_opc_ptr - gen_opc_buf, OPC_BUF_SIZE);
2090        tcg_abort();
2091    }
2092
2093    tcg_gen_code_common(s, gen_code_buf, -1);
2094
2095    /* flush instruction cache */
2096    flush_icache_range((unsigned long)gen_code_buf,
2097                       (unsigned long)s->code_ptr);
2098    return s->code_ptr -  gen_code_buf;
2099}
2100
2101/* Return the index of the micro operation such as the pc after is <
2102   offset bytes from the start of the TB.  The contents of gen_code_buf must
2103   not be changed, though writing the same values is ok.
2104   Return -1 if not found. */
2105int tcg_gen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, long offset)
2106{
2107    return tcg_gen_code_common(s, gen_code_buf, offset);
2108}
2109
2110#ifdef CONFIG_PROFILER
2111void tcg_dump_info(FILE *f,
2112                   int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
2113{
2114    TCGContext *s = &tcg_ctx;
2115    int64_t tot;
2116
2117    tot = s->interm_time + s->code_time;
2118    cpu_fprintf(f, "JIT cycles          %" PRId64 " (%0.3f s at 2.4 GHz)\n",
2119                tot, tot / 2.4e9);
2120    cpu_fprintf(f, "translated TBs      %" PRId64 " (aborted=%" PRId64 " %0.1f%%)\n",
2121                s->tb_count,
2122                s->tb_count1 - s->tb_count,
2123                s->tb_count1 ? (double)(s->tb_count1 - s->tb_count) / s->tb_count1 * 100.0 : 0);
2124    cpu_fprintf(f, "avg ops/TB          %0.1f max=%d\n",
2125                s->tb_count ? (double)s->op_count / s->tb_count : 0, s->op_count_max);
2126    cpu_fprintf(f, "deleted ops/TB      %0.2f\n",
2127                s->tb_count ?
2128                (double)s->del_op_count / s->tb_count : 0);
2129    cpu_fprintf(f, "avg temps/TB        %0.2f max=%d\n",
2130                s->tb_count ?
2131                (double)s->temp_count / s->tb_count : 0,
2132                s->temp_count_max);
2133
2134    cpu_fprintf(f, "cycles/op           %0.1f\n",
2135                s->op_count ? (double)tot / s->op_count : 0);
2136    cpu_fprintf(f, "cycles/in byte      %0.1f\n",
2137                s->code_in_len ? (double)tot / s->code_in_len : 0);
2138    cpu_fprintf(f, "cycles/out byte     %0.1f\n",
2139                s->code_out_len ? (double)tot / s->code_out_len : 0);
2140    if (tot == 0)
2141        tot = 1;
2142    cpu_fprintf(f, "  gen_interm time   %0.1f%%\n",
2143                (double)s->interm_time / tot * 100.0);
2144    cpu_fprintf(f, "  gen_code time     %0.1f%%\n",
2145                (double)s->code_time / tot * 100.0);
2146    cpu_fprintf(f, "liveness/code time  %0.1f%%\n",
2147                (double)s->la_time / (s->code_time ? s->code_time : 1) * 100.0);
2148    cpu_fprintf(f, "cpu_restore count   %" PRId64 "\n",
2149                s->restore_count);
2150    cpu_fprintf(f, "  avg cycles        %0.1f\n",
2151                s->restore_count ? (double)s->restore_time / s->restore_count : 0);
2152
2153    dump_op_count();
2154}
2155#else
2156void tcg_dump_info(FILE *f,
2157                   int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
2158{
2159    cpu_fprintf(f, "[TCG profiler not compiled]\n");
2160}
2161#endif
2162