Statistics
| Branch: | Revision:

root / tcg / tcg.c @ d73685e3

History | View | Annotate | Download (75.6 kB)

1 c896fe29 bellard
/*
2 c896fe29 bellard
 * Tiny Code Generator for QEMU
3 c896fe29 bellard
 *
4 c896fe29 bellard
 * Copyright (c) 2008 Fabrice Bellard
5 c896fe29 bellard
 *
6 c896fe29 bellard
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 c896fe29 bellard
 * of this software and associated documentation files (the "Software"), to deal
8 c896fe29 bellard
 * in the Software without restriction, including without limitation the rights
9 c896fe29 bellard
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 c896fe29 bellard
 * copies of the Software, and to permit persons to whom the Software is
11 c896fe29 bellard
 * furnished to do so, subject to the following conditions:
12 c896fe29 bellard
 *
13 c896fe29 bellard
 * The above copyright notice and this permission notice shall be included in
14 c896fe29 bellard
 * all copies or substantial portions of the Software.
15 c896fe29 bellard
 *
16 c896fe29 bellard
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 c896fe29 bellard
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 c896fe29 bellard
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 c896fe29 bellard
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 c896fe29 bellard
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 c896fe29 bellard
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 c896fe29 bellard
 * THE SOFTWARE.
23 c896fe29 bellard
 */
24 c896fe29 bellard
25 c896fe29 bellard
/* define it to use liveness analysis (better code) */
26 c896fe29 bellard
#define USE_LIVENESS_ANALYSIS
27 8f2e8c07 Kirill Batuzov
#define USE_TCG_OPTIMIZATIONS
28 c896fe29 bellard
29 cca82982 aurel32
#include "config.h"
30 cca82982 aurel32
31 813da627 Richard Henderson
/* Define to jump the ELF file used to communicate with GDB.  */
32 813da627 Richard Henderson
#undef DEBUG_JIT
33 813da627 Richard Henderson
34 a6c6f76c Blue Swirl
#if !defined(CONFIG_DEBUG_TCG) && !defined(NDEBUG)
35 cca82982 aurel32
/* define it to suppress various consistency checks (faster) */
36 cca82982 aurel32
#define NDEBUG
37 cca82982 aurel32
#endif
38 cca82982 aurel32
39 ca10f867 aurel32
#include "qemu-common.h"
40 902b3d5c malc
#include "cache-utils.h"
41 379f6698 Paul Brook
#include "host-utils.h"
42 2d8ebcf9 Richard Henderson
#include "qemu-timer.h"
43 c896fe29 bellard
44 c896fe29 bellard
/* Note: the long term plan is to reduce the dependancies on the QEMU
45 c896fe29 bellard
   CPU definitions. Currently they are used for qemu_ld/st
46 c896fe29 bellard
   instructions */
47 c896fe29 bellard
#define NO_CPU_IO_DEFS
48 c896fe29 bellard
#include "cpu.h"
49 c896fe29 bellard
50 c896fe29 bellard
#include "tcg-op.h"
51 813da627 Richard Henderson
52 813da627 Richard Henderson
#if TCG_TARGET_REG_BITS == 64
53 813da627 Richard Henderson
# define ELF_CLASS  ELFCLASS64
54 813da627 Richard Henderson
#else
55 813da627 Richard Henderson
# define ELF_CLASS  ELFCLASS32
56 813da627 Richard Henderson
#endif
57 813da627 Richard Henderson
#ifdef HOST_WORDS_BIGENDIAN
58 813da627 Richard Henderson
# define ELF_DATA   ELFDATA2MSB
59 813da627 Richard Henderson
#else
60 813da627 Richard Henderson
# define ELF_DATA   ELFDATA2LSB
61 813da627 Richard Henderson
#endif
62 813da627 Richard Henderson
63 c896fe29 bellard
#include "elf.h"
64 c896fe29 bellard
65 379f6698 Paul Brook
#if defined(CONFIG_USE_GUEST_BASE) && !defined(TCG_TARGET_HAS_GUEST_BASE)
66 379f6698 Paul Brook
#error GUEST_BASE not supported on this host.
67 379f6698 Paul Brook
#endif
68 c896fe29 bellard
69 c0ad3001 Stefan Weil
/* Forward declarations for functions declared in tcg-target.c and used here. */
70 e4d58b41 Richard Henderson
static void tcg_target_init(TCGContext *s);
71 e4d58b41 Richard Henderson
static void tcg_target_qemu_prologue(TCGContext *s);
72 c896fe29 bellard
static void patch_reloc(uint8_t *code_ptr, int type, 
73 f54b3f92 aurel32
                        tcg_target_long value, tcg_target_long addend);
74 c896fe29 bellard
75 813da627 Richard Henderson
static void tcg_register_jit_int(void *buf, size_t size,
76 813da627 Richard Henderson
                                 void *debug_frame, size_t debug_frame_size)
77 813da627 Richard Henderson
    __attribute__((unused));
78 813da627 Richard Henderson
79 c0ad3001 Stefan Weil
/* Forward declarations for functions declared and used in tcg-target.c. */
80 c0ad3001 Stefan Weil
static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str);
81 2a534aff Richard Henderson
static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg1,
82 c0ad3001 Stefan Weil
                       tcg_target_long arg2);
83 2a534aff Richard Henderson
static void tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg);
84 c0ad3001 Stefan Weil
static void tcg_out_movi(TCGContext *s, TCGType type,
85 2a534aff Richard Henderson
                         TCGReg ret, tcg_target_long arg);
86 c0ad3001 Stefan Weil
static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
87 c0ad3001 Stefan Weil
                       const int *const_args);
88 2a534aff Richard Henderson
static void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, TCGReg arg1,
89 c0ad3001 Stefan Weil
                       tcg_target_long arg2);
90 c0ad3001 Stefan Weil
static int tcg_target_const_match(tcg_target_long val,
91 c0ad3001 Stefan Weil
                                  const TCGArgConstraint *arg_ct);
92 c0ad3001 Stefan Weil
static int tcg_target_get_call_iarg_regs_count(int flags);
93 c0ad3001 Stefan Weil
94 8399ad59 Richard Henderson
TCGOpDef tcg_op_defs[] = {
95 0e2029a0 Aurelien Jarno
#define DEF(s, oargs, iargs, cargs, flags) { #s, oargs, iargs, cargs, iargs + oargs + cargs, flags },
96 c896fe29 bellard
#include "tcg-opc.h"
97 c896fe29 bellard
#undef DEF
98 c896fe29 bellard
};
99 2a24374a Stefan Weil
const size_t tcg_op_defs_max = ARRAY_SIZE(tcg_op_defs);
100 c896fe29 bellard
101 b1d8e52e blueswir1
static TCGRegSet tcg_target_available_regs[2];
102 b1d8e52e blueswir1
static TCGRegSet tcg_target_call_clobber_regs;
103 c896fe29 bellard
104 c896fe29 bellard
/* XXX: move that inside the context */
105 c896fe29 bellard
uint16_t *gen_opc_ptr;
106 c896fe29 bellard
TCGArg *gen_opparam_ptr;
107 c896fe29 bellard
108 c896fe29 bellard
static inline void tcg_out8(TCGContext *s, uint8_t v)
109 c896fe29 bellard
{
110 c896fe29 bellard
    *s->code_ptr++ = v;
111 c896fe29 bellard
}
112 c896fe29 bellard
113 c896fe29 bellard
static inline void tcg_out16(TCGContext *s, uint16_t v)
114 c896fe29 bellard
{
115 c896fe29 bellard
    *(uint16_t *)s->code_ptr = v;
116 c896fe29 bellard
    s->code_ptr += 2;
117 c896fe29 bellard
}
118 c896fe29 bellard
119 c896fe29 bellard
static inline void tcg_out32(TCGContext *s, uint32_t v)
120 c896fe29 bellard
{
121 c896fe29 bellard
    *(uint32_t *)s->code_ptr = v;
122 c896fe29 bellard
    s->code_ptr += 4;
123 c896fe29 bellard
}
124 c896fe29 bellard
125 c896fe29 bellard
/* label relocation processing */
126 c896fe29 bellard
127 a5ad5916 Stefan Weil
static void tcg_out_reloc(TCGContext *s, uint8_t *code_ptr, int type,
128 a5ad5916 Stefan Weil
                          int label_index, long addend)
129 c896fe29 bellard
{
130 c896fe29 bellard
    TCGLabel *l;
131 c896fe29 bellard
    TCGRelocation *r;
132 c896fe29 bellard
133 c896fe29 bellard
    l = &s->labels[label_index];
134 c896fe29 bellard
    if (l->has_value) {
135 623e265c pbrook
        /* FIXME: This may break relocations on RISC targets that
136 623e265c pbrook
           modify instruction fields in place.  The caller may not have 
137 623e265c pbrook
           written the initial value.  */
138 f54b3f92 aurel32
        patch_reloc(code_ptr, type, l->u.value, addend);
139 c896fe29 bellard
    } else {
140 c896fe29 bellard
        /* add a new relocation entry */
141 c896fe29 bellard
        r = tcg_malloc(sizeof(TCGRelocation));
142 c896fe29 bellard
        r->type = type;
143 c896fe29 bellard
        r->ptr = code_ptr;
144 c896fe29 bellard
        r->addend = addend;
145 c896fe29 bellard
        r->next = l->u.first_reloc;
146 c896fe29 bellard
        l->u.first_reloc = r;
147 c896fe29 bellard
    }
148 c896fe29 bellard
}
149 c896fe29 bellard
150 9d6fca70 Stefan Weil
static void tcg_out_label(TCGContext *s, int label_index, void *ptr)
151 c896fe29 bellard
{
152 c896fe29 bellard
    TCGLabel *l;
153 c896fe29 bellard
    TCGRelocation *r;
154 9d6fca70 Stefan Weil
    tcg_target_long value = (tcg_target_long)ptr;
155 c896fe29 bellard
156 c896fe29 bellard
    l = &s->labels[label_index];
157 c896fe29 bellard
    if (l->has_value)
158 c896fe29 bellard
        tcg_abort();
159 c896fe29 bellard
    r = l->u.first_reloc;
160 c896fe29 bellard
    while (r != NULL) {
161 f54b3f92 aurel32
        patch_reloc(r->ptr, r->type, value, r->addend);
162 c896fe29 bellard
        r = r->next;
163 c896fe29 bellard
    }
164 c896fe29 bellard
    l->has_value = 1;
165 c896fe29 bellard
    l->u.value = value;
166 c896fe29 bellard
}
167 c896fe29 bellard
168 c896fe29 bellard
int gen_new_label(void)
169 c896fe29 bellard
{
170 c896fe29 bellard
    TCGContext *s = &tcg_ctx;
171 c896fe29 bellard
    int idx;
172 c896fe29 bellard
    TCGLabel *l;
173 c896fe29 bellard
174 c896fe29 bellard
    if (s->nb_labels >= TCG_MAX_LABELS)
175 c896fe29 bellard
        tcg_abort();
176 c896fe29 bellard
    idx = s->nb_labels++;
177 c896fe29 bellard
    l = &s->labels[idx];
178 c896fe29 bellard
    l->has_value = 0;
179 c896fe29 bellard
    l->u.first_reloc = NULL;
180 c896fe29 bellard
    return idx;
181 c896fe29 bellard
}
182 c896fe29 bellard
183 c896fe29 bellard
#include "tcg-target.c"
184 c896fe29 bellard
185 c896fe29 bellard
/* pool based memory allocation */
186 c896fe29 bellard
void *tcg_malloc_internal(TCGContext *s, int size)
187 c896fe29 bellard
{
188 c896fe29 bellard
    TCGPool *p;
189 c896fe29 bellard
    int pool_size;
190 c896fe29 bellard
    
191 c896fe29 bellard
    if (size > TCG_POOL_CHUNK_SIZE) {
192 c896fe29 bellard
        /* big malloc: insert a new pool (XXX: could optimize) */
193 7267c094 Anthony Liguori
        p = g_malloc(sizeof(TCGPool) + size);
194 c896fe29 bellard
        p->size = size;
195 4055299e Kirill Batuzov
        p->next = s->pool_first_large;
196 4055299e Kirill Batuzov
        s->pool_first_large = p;
197 4055299e Kirill Batuzov
        return p->data;
198 c896fe29 bellard
    } else {
199 c896fe29 bellard
        p = s->pool_current;
200 c896fe29 bellard
        if (!p) {
201 c896fe29 bellard
            p = s->pool_first;
202 c896fe29 bellard
            if (!p)
203 c896fe29 bellard
                goto new_pool;
204 c896fe29 bellard
        } else {
205 c896fe29 bellard
            if (!p->next) {
206 c896fe29 bellard
            new_pool:
207 c896fe29 bellard
                pool_size = TCG_POOL_CHUNK_SIZE;
208 7267c094 Anthony Liguori
                p = g_malloc(sizeof(TCGPool) + pool_size);
209 c896fe29 bellard
                p->size = pool_size;
210 c896fe29 bellard
                p->next = NULL;
211 c896fe29 bellard
                if (s->pool_current) 
212 c896fe29 bellard
                    s->pool_current->next = p;
213 c896fe29 bellard
                else
214 c896fe29 bellard
                    s->pool_first = p;
215 c896fe29 bellard
            } else {
216 c896fe29 bellard
                p = p->next;
217 c896fe29 bellard
            }
218 c896fe29 bellard
        }
219 c896fe29 bellard
    }
220 c896fe29 bellard
    s->pool_current = p;
221 c896fe29 bellard
    s->pool_cur = p->data + size;
222 c896fe29 bellard
    s->pool_end = p->data + p->size;
223 c896fe29 bellard
    return p->data;
224 c896fe29 bellard
}
225 c896fe29 bellard
226 c896fe29 bellard
void tcg_pool_reset(TCGContext *s)
227 c896fe29 bellard
{
228 4055299e Kirill Batuzov
    TCGPool *p, *t;
229 4055299e Kirill Batuzov
    for (p = s->pool_first_large; p; p = t) {
230 4055299e Kirill Batuzov
        t = p->next;
231 4055299e Kirill Batuzov
        g_free(p);
232 4055299e Kirill Batuzov
    }
233 4055299e Kirill Batuzov
    s->pool_first_large = NULL;
234 c896fe29 bellard
    s->pool_cur = s->pool_end = NULL;
235 c896fe29 bellard
    s->pool_current = NULL;
236 c896fe29 bellard
}
237 c896fe29 bellard
238 c896fe29 bellard
void tcg_context_init(TCGContext *s)
239 c896fe29 bellard
{
240 c896fe29 bellard
    int op, total_args, n;
241 c896fe29 bellard
    TCGOpDef *def;
242 c896fe29 bellard
    TCGArgConstraint *args_ct;
243 c896fe29 bellard
    int *sorted_args;
244 c896fe29 bellard
245 c896fe29 bellard
    memset(s, 0, sizeof(*s));
246 c896fe29 bellard
    s->temps = s->static_temps;
247 c896fe29 bellard
    s->nb_globals = 0;
248 c896fe29 bellard
    
249 c896fe29 bellard
    /* Count total number of arguments and allocate the corresponding
250 c896fe29 bellard
       space */
251 c896fe29 bellard
    total_args = 0;
252 c896fe29 bellard
    for(op = 0; op < NB_OPS; op++) {
253 c896fe29 bellard
        def = &tcg_op_defs[op];
254 c896fe29 bellard
        n = def->nb_iargs + def->nb_oargs;
255 c896fe29 bellard
        total_args += n;
256 c896fe29 bellard
    }
257 c896fe29 bellard
258 7267c094 Anthony Liguori
    args_ct = g_malloc(sizeof(TCGArgConstraint) * total_args);
259 7267c094 Anthony Liguori
    sorted_args = g_malloc(sizeof(int) * total_args);
260 c896fe29 bellard
261 c896fe29 bellard
    for(op = 0; op < NB_OPS; op++) {
262 c896fe29 bellard
        def = &tcg_op_defs[op];
263 c896fe29 bellard
        def->args_ct = args_ct;
264 c896fe29 bellard
        def->sorted_args = sorted_args;
265 c896fe29 bellard
        n = def->nb_iargs + def->nb_oargs;
266 c896fe29 bellard
        sorted_args += n;
267 c896fe29 bellard
        args_ct += n;
268 c896fe29 bellard
    }
269 c896fe29 bellard
    
270 c896fe29 bellard
    tcg_target_init(s);
271 9002ec79 Richard Henderson
}
272 b03cce8e bellard
273 9002ec79 Richard Henderson
void tcg_prologue_init(TCGContext *s)
274 9002ec79 Richard Henderson
{
275 b03cce8e bellard
    /* init global prologue and epilogue */
276 b03cce8e bellard
    s->code_buf = code_gen_prologue;
277 b03cce8e bellard
    s->code_ptr = s->code_buf;
278 b03cce8e bellard
    tcg_target_qemu_prologue(s);
279 2aeabc08 Stefan Weil
    flush_icache_range((tcg_target_ulong)s->code_buf,
280 2aeabc08 Stefan Weil
                       (tcg_target_ulong)s->code_ptr);
281 c896fe29 bellard
}
282 c896fe29 bellard
283 c896fe29 bellard
void tcg_set_frame(TCGContext *s, int reg,
284 c896fe29 bellard
                   tcg_target_long start, tcg_target_long size)
285 c896fe29 bellard
{
286 c896fe29 bellard
    s->frame_start = start;
287 c896fe29 bellard
    s->frame_end = start + size;
288 c896fe29 bellard
    s->frame_reg = reg;
289 c896fe29 bellard
}
290 c896fe29 bellard
291 c896fe29 bellard
void tcg_func_start(TCGContext *s)
292 c896fe29 bellard
{
293 e8996ee0 bellard
    int i;
294 c896fe29 bellard
    tcg_pool_reset(s);
295 c896fe29 bellard
    s->nb_temps = s->nb_globals;
296 641d5fbe bellard
    for(i = 0; i < (TCG_TYPE_COUNT * 2); i++)
297 e8996ee0 bellard
        s->first_free_temp[i] = -1;
298 c896fe29 bellard
    s->labels = tcg_malloc(sizeof(TCGLabel) * TCG_MAX_LABELS);
299 c896fe29 bellard
    s->nb_labels = 0;
300 c896fe29 bellard
    s->current_frame_offset = s->frame_start;
301 c896fe29 bellard
302 c896fe29 bellard
    gen_opc_ptr = gen_opc_buf;
303 c896fe29 bellard
    gen_opparam_ptr = gen_opparam_buf;
304 c896fe29 bellard
}
305 c896fe29 bellard
306 c896fe29 bellard
static inline void tcg_temp_alloc(TCGContext *s, int n)
307 c896fe29 bellard
{
308 c896fe29 bellard
    if (n > TCG_MAX_TEMPS)
309 c896fe29 bellard
        tcg_abort();
310 c896fe29 bellard
}
311 c896fe29 bellard
312 a7812ae4 pbrook
static inline int tcg_global_reg_new_internal(TCGType type, int reg,
313 a7812ae4 pbrook
                                              const char *name)
314 c896fe29 bellard
{
315 c896fe29 bellard
    TCGContext *s = &tcg_ctx;
316 c896fe29 bellard
    TCGTemp *ts;
317 c896fe29 bellard
    int idx;
318 c896fe29 bellard
319 c896fe29 bellard
#if TCG_TARGET_REG_BITS == 32
320 c896fe29 bellard
    if (type != TCG_TYPE_I32)
321 c896fe29 bellard
        tcg_abort();
322 c896fe29 bellard
#endif
323 c896fe29 bellard
    if (tcg_regset_test_reg(s->reserved_regs, reg))
324 c896fe29 bellard
        tcg_abort();
325 c896fe29 bellard
    idx = s->nb_globals;
326 c896fe29 bellard
    tcg_temp_alloc(s, s->nb_globals + 1);
327 c896fe29 bellard
    ts = &s->temps[s->nb_globals];
328 c896fe29 bellard
    ts->base_type = type;
329 c896fe29 bellard
    ts->type = type;
330 c896fe29 bellard
    ts->fixed_reg = 1;
331 c896fe29 bellard
    ts->reg = reg;
332 c896fe29 bellard
    ts->name = name;
333 c896fe29 bellard
    s->nb_globals++;
334 c896fe29 bellard
    tcg_regset_set_reg(s->reserved_regs, reg);
335 a7812ae4 pbrook
    return idx;
336 a7812ae4 pbrook
}
337 a7812ae4 pbrook
338 a7812ae4 pbrook
TCGv_i32 tcg_global_reg_new_i32(int reg, const char *name)
339 a7812ae4 pbrook
{
340 a7812ae4 pbrook
    int idx;
341 a7812ae4 pbrook
342 a7812ae4 pbrook
    idx = tcg_global_reg_new_internal(TCG_TYPE_I32, reg, name);
343 a7812ae4 pbrook
    return MAKE_TCGV_I32(idx);
344 a7812ae4 pbrook
}
345 a7812ae4 pbrook
346 a7812ae4 pbrook
TCGv_i64 tcg_global_reg_new_i64(int reg, const char *name)
347 a7812ae4 pbrook
{
348 a7812ae4 pbrook
    int idx;
349 a7812ae4 pbrook
350 a7812ae4 pbrook
    idx = tcg_global_reg_new_internal(TCG_TYPE_I64, reg, name);
351 a7812ae4 pbrook
    return MAKE_TCGV_I64(idx);
352 c896fe29 bellard
}
353 c896fe29 bellard
354 a7812ae4 pbrook
static inline int tcg_global_mem_new_internal(TCGType type, int reg,
355 a7812ae4 pbrook
                                              tcg_target_long offset,
356 a7812ae4 pbrook
                                              const char *name)
357 c896fe29 bellard
{
358 c896fe29 bellard
    TCGContext *s = &tcg_ctx;
359 c896fe29 bellard
    TCGTemp *ts;
360 c896fe29 bellard
    int idx;
361 c896fe29 bellard
362 c896fe29 bellard
    idx = s->nb_globals;
363 c896fe29 bellard
#if TCG_TARGET_REG_BITS == 32
364 c896fe29 bellard
    if (type == TCG_TYPE_I64) {
365 c896fe29 bellard
        char buf[64];
366 c588979b ths
        tcg_temp_alloc(s, s->nb_globals + 2);
367 c896fe29 bellard
        ts = &s->temps[s->nb_globals];
368 c896fe29 bellard
        ts->base_type = type;
369 c896fe29 bellard
        ts->type = TCG_TYPE_I32;
370 c896fe29 bellard
        ts->fixed_reg = 0;
371 c896fe29 bellard
        ts->mem_allocated = 1;
372 c896fe29 bellard
        ts->mem_reg = reg;
373 c896fe29 bellard
#ifdef TCG_TARGET_WORDS_BIGENDIAN
374 c896fe29 bellard
        ts->mem_offset = offset + 4;
375 c896fe29 bellard
#else
376 c896fe29 bellard
        ts->mem_offset = offset;
377 c896fe29 bellard
#endif
378 c896fe29 bellard
        pstrcpy(buf, sizeof(buf), name);
379 c896fe29 bellard
        pstrcat(buf, sizeof(buf), "_0");
380 c896fe29 bellard
        ts->name = strdup(buf);
381 c896fe29 bellard
        ts++;
382 c896fe29 bellard
383 c896fe29 bellard
        ts->base_type = type;
384 c896fe29 bellard
        ts->type = TCG_TYPE_I32;
385 c896fe29 bellard
        ts->fixed_reg = 0;
386 c896fe29 bellard
        ts->mem_allocated = 1;
387 c896fe29 bellard
        ts->mem_reg = reg;
388 c896fe29 bellard
#ifdef TCG_TARGET_WORDS_BIGENDIAN
389 c896fe29 bellard
        ts->mem_offset = offset;
390 c896fe29 bellard
#else
391 c896fe29 bellard
        ts->mem_offset = offset + 4;
392 c896fe29 bellard
#endif
393 c896fe29 bellard
        pstrcpy(buf, sizeof(buf), name);
394 c896fe29 bellard
        pstrcat(buf, sizeof(buf), "_1");
395 c896fe29 bellard
        ts->name = strdup(buf);
396 c896fe29 bellard
397 c896fe29 bellard
        s->nb_globals += 2;
398 c896fe29 bellard
    } else
399 c896fe29 bellard
#endif
400 c896fe29 bellard
    {
401 c896fe29 bellard
        tcg_temp_alloc(s, s->nb_globals + 1);
402 c896fe29 bellard
        ts = &s->temps[s->nb_globals];
403 c896fe29 bellard
        ts->base_type = type;
404 c896fe29 bellard
        ts->type = type;
405 c896fe29 bellard
        ts->fixed_reg = 0;
406 c896fe29 bellard
        ts->mem_allocated = 1;
407 c896fe29 bellard
        ts->mem_reg = reg;
408 c896fe29 bellard
        ts->mem_offset = offset;
409 c896fe29 bellard
        ts->name = name;
410 c896fe29 bellard
        s->nb_globals++;
411 c896fe29 bellard
    }
412 a7812ae4 pbrook
    return idx;
413 a7812ae4 pbrook
}
414 a7812ae4 pbrook
415 a7812ae4 pbrook
TCGv_i32 tcg_global_mem_new_i32(int reg, tcg_target_long offset,
416 a7812ae4 pbrook
                                const char *name)
417 a7812ae4 pbrook
{
418 a7812ae4 pbrook
    int idx;
419 a7812ae4 pbrook
420 a7812ae4 pbrook
    idx = tcg_global_mem_new_internal(TCG_TYPE_I32, reg, offset, name);
421 a7812ae4 pbrook
    return MAKE_TCGV_I32(idx);
422 a7812ae4 pbrook
}
423 a7812ae4 pbrook
424 a7812ae4 pbrook
TCGv_i64 tcg_global_mem_new_i64(int reg, tcg_target_long offset,
425 a7812ae4 pbrook
                                const char *name)
426 a7812ae4 pbrook
{
427 a7812ae4 pbrook
    int idx;
428 a7812ae4 pbrook
429 a7812ae4 pbrook
    idx = tcg_global_mem_new_internal(TCG_TYPE_I64, reg, offset, name);
430 a7812ae4 pbrook
    return MAKE_TCGV_I64(idx);
431 c896fe29 bellard
}
432 c896fe29 bellard
433 a7812ae4 pbrook
static inline int tcg_temp_new_internal(TCGType type, int temp_local)
434 c896fe29 bellard
{
435 c896fe29 bellard
    TCGContext *s = &tcg_ctx;
436 c896fe29 bellard
    TCGTemp *ts;
437 641d5fbe bellard
    int idx, k;
438 c896fe29 bellard
439 641d5fbe bellard
    k = type;
440 641d5fbe bellard
    if (temp_local)
441 641d5fbe bellard
        k += TCG_TYPE_COUNT;
442 641d5fbe bellard
    idx = s->first_free_temp[k];
443 e8996ee0 bellard
    if (idx != -1) {
444 e8996ee0 bellard
        /* There is already an available temp with the
445 e8996ee0 bellard
           right type */
446 e8996ee0 bellard
        ts = &s->temps[idx];
447 641d5fbe bellard
        s->first_free_temp[k] = ts->next_free_temp;
448 e8996ee0 bellard
        ts->temp_allocated = 1;
449 641d5fbe bellard
        assert(ts->temp_local == temp_local);
450 e8996ee0 bellard
    } else {
451 e8996ee0 bellard
        idx = s->nb_temps;
452 c896fe29 bellard
#if TCG_TARGET_REG_BITS == 32
453 e8996ee0 bellard
        if (type == TCG_TYPE_I64) {
454 8df1ca4b ths
            tcg_temp_alloc(s, s->nb_temps + 2);
455 e8996ee0 bellard
            ts = &s->temps[s->nb_temps];
456 e8996ee0 bellard
            ts->base_type = type;
457 e8996ee0 bellard
            ts->type = TCG_TYPE_I32;
458 e8996ee0 bellard
            ts->temp_allocated = 1;
459 641d5fbe bellard
            ts->temp_local = temp_local;
460 e8996ee0 bellard
            ts->name = NULL;
461 e8996ee0 bellard
            ts++;
462 e8996ee0 bellard
            ts->base_type = TCG_TYPE_I32;
463 e8996ee0 bellard
            ts->type = TCG_TYPE_I32;
464 e8996ee0 bellard
            ts->temp_allocated = 1;
465 641d5fbe bellard
            ts->temp_local = temp_local;
466 e8996ee0 bellard
            ts->name = NULL;
467 e8996ee0 bellard
            s->nb_temps += 2;
468 e8996ee0 bellard
        } else
469 c896fe29 bellard
#endif
470 e8996ee0 bellard
        {
471 e8996ee0 bellard
            tcg_temp_alloc(s, s->nb_temps + 1);
472 e8996ee0 bellard
            ts = &s->temps[s->nb_temps];
473 e8996ee0 bellard
            ts->base_type = type;
474 e8996ee0 bellard
            ts->type = type;
475 e8996ee0 bellard
            ts->temp_allocated = 1;
476 641d5fbe bellard
            ts->temp_local = temp_local;
477 e8996ee0 bellard
            ts->name = NULL;
478 e8996ee0 bellard
            s->nb_temps++;
479 e8996ee0 bellard
        }
480 c896fe29 bellard
    }
481 27bfd83c Peter Maydell
482 27bfd83c Peter Maydell
#if defined(CONFIG_DEBUG_TCG)
483 27bfd83c Peter Maydell
    s->temps_in_use++;
484 27bfd83c Peter Maydell
#endif
485 a7812ae4 pbrook
    return idx;
486 c896fe29 bellard
}
487 c896fe29 bellard
488 a7812ae4 pbrook
TCGv_i32 tcg_temp_new_internal_i32(int temp_local)
489 a7812ae4 pbrook
{
490 a7812ae4 pbrook
    int idx;
491 a7812ae4 pbrook
492 a7812ae4 pbrook
    idx = tcg_temp_new_internal(TCG_TYPE_I32, temp_local);
493 a7812ae4 pbrook
    return MAKE_TCGV_I32(idx);
494 a7812ae4 pbrook
}
495 a7812ae4 pbrook
496 a7812ae4 pbrook
TCGv_i64 tcg_temp_new_internal_i64(int temp_local)
497 a7812ae4 pbrook
{
498 a7812ae4 pbrook
    int idx;
499 a7812ae4 pbrook
500 a7812ae4 pbrook
    idx = tcg_temp_new_internal(TCG_TYPE_I64, temp_local);
501 a7812ae4 pbrook
    return MAKE_TCGV_I64(idx);
502 a7812ae4 pbrook
}
503 a7812ae4 pbrook
504 a7812ae4 pbrook
static inline void tcg_temp_free_internal(int idx)
505 c896fe29 bellard
{
506 c896fe29 bellard
    TCGContext *s = &tcg_ctx;
507 c896fe29 bellard
    TCGTemp *ts;
508 641d5fbe bellard
    int k;
509 c896fe29 bellard
510 27bfd83c Peter Maydell
#if defined(CONFIG_DEBUG_TCG)
511 27bfd83c Peter Maydell
    s->temps_in_use--;
512 27bfd83c Peter Maydell
    if (s->temps_in_use < 0) {
513 27bfd83c Peter Maydell
        fprintf(stderr, "More temporaries freed than allocated!\n");
514 27bfd83c Peter Maydell
    }
515 27bfd83c Peter Maydell
#endif
516 27bfd83c Peter Maydell
517 e8996ee0 bellard
    assert(idx >= s->nb_globals && idx < s->nb_temps);
518 c896fe29 bellard
    ts = &s->temps[idx];
519 e8996ee0 bellard
    assert(ts->temp_allocated != 0);
520 e8996ee0 bellard
    ts->temp_allocated = 0;
521 641d5fbe bellard
    k = ts->base_type;
522 641d5fbe bellard
    if (ts->temp_local)
523 641d5fbe bellard
        k += TCG_TYPE_COUNT;
524 641d5fbe bellard
    ts->next_free_temp = s->first_free_temp[k];
525 641d5fbe bellard
    s->first_free_temp[k] = idx;
526 c896fe29 bellard
}
527 c896fe29 bellard
528 a7812ae4 pbrook
void tcg_temp_free_i32(TCGv_i32 arg)
529 a7812ae4 pbrook
{
530 a7812ae4 pbrook
    tcg_temp_free_internal(GET_TCGV_I32(arg));
531 a7812ae4 pbrook
}
532 a7812ae4 pbrook
533 a7812ae4 pbrook
void tcg_temp_free_i64(TCGv_i64 arg)
534 a7812ae4 pbrook
{
535 a7812ae4 pbrook
    tcg_temp_free_internal(GET_TCGV_I64(arg));
536 a7812ae4 pbrook
}
537 e8996ee0 bellard
538 a7812ae4 pbrook
TCGv_i32 tcg_const_i32(int32_t val)
539 c896fe29 bellard
{
540 a7812ae4 pbrook
    TCGv_i32 t0;
541 a7812ae4 pbrook
    t0 = tcg_temp_new_i32();
542 e8996ee0 bellard
    tcg_gen_movi_i32(t0, val);
543 e8996ee0 bellard
    return t0;
544 e8996ee0 bellard
}
545 c896fe29 bellard
546 a7812ae4 pbrook
TCGv_i64 tcg_const_i64(int64_t val)
547 e8996ee0 bellard
{
548 a7812ae4 pbrook
    TCGv_i64 t0;
549 a7812ae4 pbrook
    t0 = tcg_temp_new_i64();
550 e8996ee0 bellard
    tcg_gen_movi_i64(t0, val);
551 e8996ee0 bellard
    return t0;
552 c896fe29 bellard
}
553 c896fe29 bellard
554 a7812ae4 pbrook
TCGv_i32 tcg_const_local_i32(int32_t val)
555 bdffd4a9 aurel32
{
556 a7812ae4 pbrook
    TCGv_i32 t0;
557 a7812ae4 pbrook
    t0 = tcg_temp_local_new_i32();
558 bdffd4a9 aurel32
    tcg_gen_movi_i32(t0, val);
559 bdffd4a9 aurel32
    return t0;
560 bdffd4a9 aurel32
}
561 bdffd4a9 aurel32
562 a7812ae4 pbrook
TCGv_i64 tcg_const_local_i64(int64_t val)
563 bdffd4a9 aurel32
{
564 a7812ae4 pbrook
    TCGv_i64 t0;
565 a7812ae4 pbrook
    t0 = tcg_temp_local_new_i64();
566 bdffd4a9 aurel32
    tcg_gen_movi_i64(t0, val);
567 bdffd4a9 aurel32
    return t0;
568 bdffd4a9 aurel32
}
569 bdffd4a9 aurel32
570 27bfd83c Peter Maydell
#if defined(CONFIG_DEBUG_TCG)
571 27bfd83c Peter Maydell
void tcg_clear_temp_count(void)
572 27bfd83c Peter Maydell
{
573 27bfd83c Peter Maydell
    TCGContext *s = &tcg_ctx;
574 27bfd83c Peter Maydell
    s->temps_in_use = 0;
575 27bfd83c Peter Maydell
}
576 27bfd83c Peter Maydell
577 27bfd83c Peter Maydell
int tcg_check_temp_count(void)
578 27bfd83c Peter Maydell
{
579 27bfd83c Peter Maydell
    TCGContext *s = &tcg_ctx;
580 27bfd83c Peter Maydell
    if (s->temps_in_use) {
581 27bfd83c Peter Maydell
        /* Clear the count so that we don't give another
582 27bfd83c Peter Maydell
         * warning immediately next time around.
583 27bfd83c Peter Maydell
         */
584 27bfd83c Peter Maydell
        s->temps_in_use = 0;
585 27bfd83c Peter Maydell
        return 1;
586 27bfd83c Peter Maydell
    }
587 27bfd83c Peter Maydell
    return 0;
588 27bfd83c Peter Maydell
}
589 27bfd83c Peter Maydell
#endif
590 27bfd83c Peter Maydell
591 c896fe29 bellard
void tcg_register_helper(void *func, const char *name)
592 c896fe29 bellard
{
593 c896fe29 bellard
    TCGContext *s = &tcg_ctx;
594 c896fe29 bellard
    int n;
595 c896fe29 bellard
    if ((s->nb_helpers + 1) > s->allocated_helpers) {
596 c896fe29 bellard
        n = s->allocated_helpers;
597 c896fe29 bellard
        if (n == 0) {
598 c896fe29 bellard
            n = 4;
599 c896fe29 bellard
        } else {
600 c896fe29 bellard
            n *= 2;
601 c896fe29 bellard
        }
602 c896fe29 bellard
        s->helpers = realloc(s->helpers, n * sizeof(TCGHelperInfo));
603 c896fe29 bellard
        s->allocated_helpers = n;
604 c896fe29 bellard
    }
605 4dc81f28 bellard
    s->helpers[s->nb_helpers].func = (tcg_target_ulong)func;
606 c896fe29 bellard
    s->helpers[s->nb_helpers].name = name;
607 c896fe29 bellard
    s->nb_helpers++;
608 c896fe29 bellard
}
609 c896fe29 bellard
610 39cf05d3 bellard
/* Note: we convert the 64 bit args to 32 bit and do some alignment
611 39cf05d3 bellard
   and endian swap. Maybe it would be better to do the alignment
612 39cf05d3 bellard
   and endian swap in tcg_reg_alloc_call(). */
613 a7812ae4 pbrook
void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags,
614 a7812ae4 pbrook
                   int sizemask, TCGArg ret, int nargs, TCGArg *args)
615 c896fe29 bellard
{
616 a7812ae4 pbrook
    int i;
617 a7812ae4 pbrook
    int real_args;
618 a7812ae4 pbrook
    int nb_rets;
619 a7812ae4 pbrook
    TCGArg *nparam;
620 2bece2c8 Richard Henderson
621 2bece2c8 Richard Henderson
#if defined(TCG_TARGET_EXTEND_ARGS) && TCG_TARGET_REG_BITS == 64
622 2bece2c8 Richard Henderson
    for (i = 0; i < nargs; ++i) {
623 2bece2c8 Richard Henderson
        int is_64bit = sizemask & (1 << (i+1)*2);
624 2bece2c8 Richard Henderson
        int is_signed = sizemask & (2 << (i+1)*2);
625 2bece2c8 Richard Henderson
        if (!is_64bit) {
626 2bece2c8 Richard Henderson
            TCGv_i64 temp = tcg_temp_new_i64();
627 2bece2c8 Richard Henderson
            TCGv_i64 orig = MAKE_TCGV_I64(args[i]);
628 2bece2c8 Richard Henderson
            if (is_signed) {
629 2bece2c8 Richard Henderson
                tcg_gen_ext32s_i64(temp, orig);
630 2bece2c8 Richard Henderson
            } else {
631 2bece2c8 Richard Henderson
                tcg_gen_ext32u_i64(temp, orig);
632 2bece2c8 Richard Henderson
            }
633 2bece2c8 Richard Henderson
            args[i] = GET_TCGV_I64(temp);
634 2bece2c8 Richard Henderson
        }
635 2bece2c8 Richard Henderson
    }
636 2bece2c8 Richard Henderson
#endif /* TCG_TARGET_EXTEND_ARGS */
637 2bece2c8 Richard Henderson
638 a7812ae4 pbrook
    *gen_opc_ptr++ = INDEX_op_call;
639 a7812ae4 pbrook
    nparam = gen_opparam_ptr++;
640 a7812ae4 pbrook
    if (ret != TCG_CALL_DUMMY_ARG) {
641 a7812ae4 pbrook
#if TCG_TARGET_REG_BITS < 64
642 a7812ae4 pbrook
        if (sizemask & 1) {
643 39cf05d3 bellard
#ifdef TCG_TARGET_WORDS_BIGENDIAN
644 a7812ae4 pbrook
            *gen_opparam_ptr++ = ret + 1;
645 a7812ae4 pbrook
            *gen_opparam_ptr++ = ret;
646 39cf05d3 bellard
#else
647 a7812ae4 pbrook
            *gen_opparam_ptr++ = ret;
648 a7812ae4 pbrook
            *gen_opparam_ptr++ = ret + 1;
649 39cf05d3 bellard
#endif
650 a7812ae4 pbrook
            nb_rets = 2;
651 a7812ae4 pbrook
        } else
652 a7812ae4 pbrook
#endif
653 a7812ae4 pbrook
        {
654 a7812ae4 pbrook
            *gen_opparam_ptr++ = ret;
655 a7812ae4 pbrook
            nb_rets = 1;
656 c896fe29 bellard
        }
657 a7812ae4 pbrook
    } else {
658 a7812ae4 pbrook
        nb_rets = 0;
659 c896fe29 bellard
    }
660 a7812ae4 pbrook
    real_args = 0;
661 a7812ae4 pbrook
    for (i = 0; i < nargs; i++) {
662 a7812ae4 pbrook
#if TCG_TARGET_REG_BITS < 64
663 2bece2c8 Richard Henderson
        int is_64bit = sizemask & (1 << (i+1)*2);
664 2bece2c8 Richard Henderson
        if (is_64bit) {
665 39cf05d3 bellard
#ifdef TCG_TARGET_CALL_ALIGN_ARGS
666 39cf05d3 bellard
            /* some targets want aligned 64 bit args */
667 ebd486d5 malc
            if (real_args & 1) {
668 a7812ae4 pbrook
                *gen_opparam_ptr++ = TCG_CALL_DUMMY_ARG;
669 ebd486d5 malc
                real_args++;
670 39cf05d3 bellard
            }
671 39cf05d3 bellard
#endif
672 3f90f252 Richard Henderson
            /* If stack grows up, then we will be placing successive
673 3f90f252 Richard Henderson
               arguments at lower addresses, which means we need to
674 3f90f252 Richard Henderson
               reverse the order compared to how we would normally
675 3f90f252 Richard Henderson
               treat either big or little-endian.  For those arguments
676 3f90f252 Richard Henderson
               that will wind up in registers, this still works for
677 3f90f252 Richard Henderson
               HPPA (the only current STACK_GROWSUP target) since the
678 3f90f252 Richard Henderson
               argument registers are *also* allocated in decreasing
679 3f90f252 Richard Henderson
               order.  If another such target is added, this logic may
680 3f90f252 Richard Henderson
               have to get more complicated to differentiate between
681 3f90f252 Richard Henderson
               stack arguments and register arguments.  */
682 3f90f252 Richard Henderson
#if defined(TCG_TARGET_WORDS_BIGENDIAN) != defined(TCG_TARGET_STACK_GROWSUP)
683 a7812ae4 pbrook
            *gen_opparam_ptr++ = args[i] + 1;
684 a7812ae4 pbrook
            *gen_opparam_ptr++ = args[i];
685 c896fe29 bellard
#else
686 a7812ae4 pbrook
            *gen_opparam_ptr++ = args[i];
687 a7812ae4 pbrook
            *gen_opparam_ptr++ = args[i] + 1;
688 c896fe29 bellard
#endif
689 a7812ae4 pbrook
            real_args += 2;
690 2bece2c8 Richard Henderson
            continue;
691 c896fe29 bellard
        }
692 2bece2c8 Richard Henderson
#endif /* TCG_TARGET_REG_BITS < 64 */
693 2bece2c8 Richard Henderson
694 2bece2c8 Richard Henderson
        *gen_opparam_ptr++ = args[i];
695 2bece2c8 Richard Henderson
        real_args++;
696 c896fe29 bellard
    }
697 a7812ae4 pbrook
    *gen_opparam_ptr++ = GET_TCGV_PTR(func);
698 a7812ae4 pbrook
699 a7812ae4 pbrook
    *gen_opparam_ptr++ = flags;
700 a7812ae4 pbrook
701 a7812ae4 pbrook
    *nparam = (nb_rets << 16) | (real_args + 1);
702 a7812ae4 pbrook
703 a7812ae4 pbrook
    /* total parameters, needed to go backward in the instruction stream */
704 a7812ae4 pbrook
    *gen_opparam_ptr++ = 1 + nb_rets + real_args + 3;
705 2bece2c8 Richard Henderson
706 2bece2c8 Richard Henderson
#if defined(TCG_TARGET_EXTEND_ARGS) && TCG_TARGET_REG_BITS == 64
707 2bece2c8 Richard Henderson
    for (i = 0; i < nargs; ++i) {
708 2bece2c8 Richard Henderson
        int is_64bit = sizemask & (1 << (i+1)*2);
709 2bece2c8 Richard Henderson
        if (!is_64bit) {
710 2bece2c8 Richard Henderson
            TCGv_i64 temp = MAKE_TCGV_I64(args[i]);
711 2bece2c8 Richard Henderson
            tcg_temp_free_i64(temp);
712 2bece2c8 Richard Henderson
        }
713 2bece2c8 Richard Henderson
    }
714 2bece2c8 Richard Henderson
#endif /* TCG_TARGET_EXTEND_ARGS */
715 c896fe29 bellard
}
716 c896fe29 bellard
717 ac56dd48 pbrook
#if TCG_TARGET_REG_BITS == 32
718 a7812ae4 pbrook
void tcg_gen_shifti_i64(TCGv_i64 ret, TCGv_i64 arg1,
719 c896fe29 bellard
                        int c, int right, int arith)
720 c896fe29 bellard
{
721 cf60bce4 bellard
    if (c == 0) {
722 a7812ae4 pbrook
        tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg1));
723 cf60bce4 bellard
        tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
724 cf60bce4 bellard
    } else if (c >= 32) {
725 c896fe29 bellard
        c -= 32;
726 c896fe29 bellard
        if (right) {
727 c896fe29 bellard
            if (arith) {
728 a7812ae4 pbrook
                tcg_gen_sari_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
729 ac56dd48 pbrook
                tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 31);
730 c896fe29 bellard
            } else {
731 a7812ae4 pbrook
                tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
732 ac56dd48 pbrook
                tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
733 c896fe29 bellard
            }
734 c896fe29 bellard
        } else {
735 a7812ae4 pbrook
            tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_LOW(arg1), c);
736 a7812ae4 pbrook
            tcg_gen_movi_i32(TCGV_LOW(ret), 0);
737 c896fe29 bellard
        }
738 c896fe29 bellard
    } else {
739 a7812ae4 pbrook
        TCGv_i32 t0, t1;
740 c896fe29 bellard
741 a7812ae4 pbrook
        t0 = tcg_temp_new_i32();
742 a7812ae4 pbrook
        t1 = tcg_temp_new_i32();
743 c896fe29 bellard
        if (right) {
744 ac56dd48 pbrook
            tcg_gen_shli_i32(t0, TCGV_HIGH(arg1), 32 - c);
745 c896fe29 bellard
            if (arith)
746 ac56dd48 pbrook
                tcg_gen_sari_i32(t1, TCGV_HIGH(arg1), c);
747 a7812ae4 pbrook
            else
748 ac56dd48 pbrook
                tcg_gen_shri_i32(t1, TCGV_HIGH(arg1), c);
749 a7812ae4 pbrook
            tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_LOW(arg1), c);
750 a7812ae4 pbrook
            tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(ret), t0);
751 ac56dd48 pbrook
            tcg_gen_mov_i32(TCGV_HIGH(ret), t1);
752 c896fe29 bellard
        } else {
753 a7812ae4 pbrook
            tcg_gen_shri_i32(t0, TCGV_LOW(arg1), 32 - c);
754 c896fe29 bellard
            /* Note: ret can be the same as arg1, so we use t1 */
755 a7812ae4 pbrook
            tcg_gen_shli_i32(t1, TCGV_LOW(arg1), c);
756 ac56dd48 pbrook
            tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c);
757 ac56dd48 pbrook
            tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t0);
758 a7812ae4 pbrook
            tcg_gen_mov_i32(TCGV_LOW(ret), t1);
759 c896fe29 bellard
        }
760 a7812ae4 pbrook
        tcg_temp_free_i32(t0);
761 a7812ae4 pbrook
        tcg_temp_free_i32(t1);
762 c896fe29 bellard
    }
763 c896fe29 bellard
}
764 ac56dd48 pbrook
#endif
765 c896fe29 bellard
766 be210acb Richard Henderson
767 8fcd3692 blueswir1
static void tcg_reg_alloc_start(TCGContext *s)
768 c896fe29 bellard
{
769 c896fe29 bellard
    int i;
770 c896fe29 bellard
    TCGTemp *ts;
771 c896fe29 bellard
    for(i = 0; i < s->nb_globals; i++) {
772 c896fe29 bellard
        ts = &s->temps[i];
773 c896fe29 bellard
        if (ts->fixed_reg) {
774 c896fe29 bellard
            ts->val_type = TEMP_VAL_REG;
775 c896fe29 bellard
        } else {
776 c896fe29 bellard
            ts->val_type = TEMP_VAL_MEM;
777 c896fe29 bellard
        }
778 c896fe29 bellard
    }
779 e8996ee0 bellard
    for(i = s->nb_globals; i < s->nb_temps; i++) {
780 e8996ee0 bellard
        ts = &s->temps[i];
781 e8996ee0 bellard
        ts->val_type = TEMP_VAL_DEAD;
782 e8996ee0 bellard
        ts->mem_allocated = 0;
783 e8996ee0 bellard
        ts->fixed_reg = 0;
784 e8996ee0 bellard
    }
785 c896fe29 bellard
    for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
786 c896fe29 bellard
        s->reg_to_temp[i] = -1;
787 c896fe29 bellard
    }
788 c896fe29 bellard
}
789 c896fe29 bellard
790 ac56dd48 pbrook
static char *tcg_get_arg_str_idx(TCGContext *s, char *buf, int buf_size,
791 ac56dd48 pbrook
                                 int idx)
792 c896fe29 bellard
{
793 c896fe29 bellard
    TCGTemp *ts;
794 ac56dd48 pbrook
795 7f6f0ae5 Stefan Weil
    assert(idx >= 0 && idx < s->nb_temps);
796 ac56dd48 pbrook
    ts = &s->temps[idx];
797 7f6f0ae5 Stefan Weil
    assert(ts);
798 ac56dd48 pbrook
    if (idx < s->nb_globals) {
799 ac56dd48 pbrook
        pstrcpy(buf, buf_size, ts->name);
800 c896fe29 bellard
    } else {
801 641d5fbe bellard
        if (ts->temp_local) 
802 641d5fbe bellard
            snprintf(buf, buf_size, "loc%d", idx - s->nb_globals);
803 641d5fbe bellard
        else
804 641d5fbe bellard
            snprintf(buf, buf_size, "tmp%d", idx - s->nb_globals);
805 c896fe29 bellard
    }
806 c896fe29 bellard
    return buf;
807 c896fe29 bellard
}
808 c896fe29 bellard
809 a7812ae4 pbrook
char *tcg_get_arg_str_i32(TCGContext *s, char *buf, int buf_size, TCGv_i32 arg)
810 a7812ae4 pbrook
{
811 a7812ae4 pbrook
    return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I32(arg));
812 a7812ae4 pbrook
}
813 a7812ae4 pbrook
814 a7812ae4 pbrook
char *tcg_get_arg_str_i64(TCGContext *s, char *buf, int buf_size, TCGv_i64 arg)
815 ac56dd48 pbrook
{
816 a810a2de blueswir1
    return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I64(arg));
817 ac56dd48 pbrook
}
818 ac56dd48 pbrook
819 e8996ee0 bellard
static int helper_cmp(const void *p1, const void *p2)
820 4dc81f28 bellard
{
821 e8996ee0 bellard
    const TCGHelperInfo *th1 = p1;
822 e8996ee0 bellard
    const TCGHelperInfo *th2 = p2;
823 e8996ee0 bellard
    if (th1->func < th2->func)
824 e8996ee0 bellard
        return -1;
825 e8996ee0 bellard
    else if (th1->func == th2->func)
826 e8996ee0 bellard
        return 0;
827 e8996ee0 bellard
    else
828 e8996ee0 bellard
        return 1;
829 4dc81f28 bellard
}
830 4dc81f28 bellard
831 e8996ee0 bellard
/* find helper definition (Note: A hash table would be better) */
832 e8996ee0 bellard
static TCGHelperInfo *tcg_find_helper(TCGContext *s, tcg_target_ulong val)
833 4dc81f28 bellard
{
834 e8996ee0 bellard
    int m, m_min, m_max;
835 4dc81f28 bellard
    TCGHelperInfo *th;
836 e8996ee0 bellard
    tcg_target_ulong v;
837 4dc81f28 bellard
838 e8996ee0 bellard
    if (unlikely(!s->helpers_sorted)) {
839 e8996ee0 bellard
        qsort(s->helpers, s->nb_helpers, sizeof(TCGHelperInfo), 
840 e8996ee0 bellard
              helper_cmp);
841 e8996ee0 bellard
        s->helpers_sorted = 1;
842 e8996ee0 bellard
    }
843 e8996ee0 bellard
844 e8996ee0 bellard
    /* binary search */
845 e8996ee0 bellard
    m_min = 0;
846 e8996ee0 bellard
    m_max = s->nb_helpers - 1;
847 e8996ee0 bellard
    while (m_min <= m_max) {
848 e8996ee0 bellard
        m = (m_min + m_max) >> 1;
849 e8996ee0 bellard
        th = &s->helpers[m];
850 e8996ee0 bellard
        v = th->func;
851 e8996ee0 bellard
        if (v == val)
852 e8996ee0 bellard
            return th;
853 e8996ee0 bellard
        else if (val < v) {
854 e8996ee0 bellard
            m_max = m - 1;
855 e8996ee0 bellard
        } else {
856 e8996ee0 bellard
            m_min = m + 1;
857 4dc81f28 bellard
        }
858 4dc81f28 bellard
    }
859 e8996ee0 bellard
    return NULL;
860 4dc81f28 bellard
}
861 4dc81f28 bellard
862 f48f3ede blueswir1
static const char * const cond_name[] =
863 f48f3ede blueswir1
{
864 f48f3ede blueswir1
    [TCG_COND_EQ] = "eq",
865 f48f3ede blueswir1
    [TCG_COND_NE] = "ne",
866 f48f3ede blueswir1
    [TCG_COND_LT] = "lt",
867 f48f3ede blueswir1
    [TCG_COND_GE] = "ge",
868 f48f3ede blueswir1
    [TCG_COND_LE] = "le",
869 f48f3ede blueswir1
    [TCG_COND_GT] = "gt",
870 f48f3ede blueswir1
    [TCG_COND_LTU] = "ltu",
871 f48f3ede blueswir1
    [TCG_COND_GEU] = "geu",
872 f48f3ede blueswir1
    [TCG_COND_LEU] = "leu",
873 f48f3ede blueswir1
    [TCG_COND_GTU] = "gtu"
874 f48f3ede blueswir1
};
875 f48f3ede blueswir1
876 eeacee4d Blue Swirl
void tcg_dump_ops(TCGContext *s)
877 c896fe29 bellard
{
878 c896fe29 bellard
    const uint16_t *opc_ptr;
879 c896fe29 bellard
    const TCGArg *args;
880 c896fe29 bellard
    TCGArg arg;
881 a9751609 Richard Henderson
    TCGOpcode c;
882 a9751609 Richard Henderson
    int i, k, nb_oargs, nb_iargs, nb_cargs, first_insn;
883 c896fe29 bellard
    const TCGOpDef *def;
884 c896fe29 bellard
    char buf[128];
885 c896fe29 bellard
886 7e4597d7 bellard
    first_insn = 1;
887 c896fe29 bellard
    opc_ptr = gen_opc_buf;
888 c896fe29 bellard
    args = gen_opparam_buf;
889 c896fe29 bellard
    while (opc_ptr < gen_opc_ptr) {
890 c896fe29 bellard
        c = *opc_ptr++;
891 c896fe29 bellard
        def = &tcg_op_defs[c];
892 7e4597d7 bellard
        if (c == INDEX_op_debug_insn_start) {
893 7e4597d7 bellard
            uint64_t pc;
894 7e4597d7 bellard
#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
895 7e4597d7 bellard
            pc = ((uint64_t)args[1] << 32) | args[0];
896 7e4597d7 bellard
#else
897 7e4597d7 bellard
            pc = args[0];
898 7e4597d7 bellard
#endif
899 eeacee4d Blue Swirl
            if (!first_insn) {
900 eeacee4d Blue Swirl
                qemu_log("\n");
901 eeacee4d Blue Swirl
            }
902 eeacee4d Blue Swirl
            qemu_log(" ---- 0x%" PRIx64, pc);
903 7e4597d7 bellard
            first_insn = 0;
904 7e4597d7 bellard
            nb_oargs = def->nb_oargs;
905 7e4597d7 bellard
            nb_iargs = def->nb_iargs;
906 7e4597d7 bellard
            nb_cargs = def->nb_cargs;
907 7e4597d7 bellard
        } else if (c == INDEX_op_call) {
908 c896fe29 bellard
            TCGArg arg;
909 4dc81f28 bellard
910 c896fe29 bellard
            /* variable number of arguments */
911 c896fe29 bellard
            arg = *args++;
912 c896fe29 bellard
            nb_oargs = arg >> 16;
913 c896fe29 bellard
            nb_iargs = arg & 0xffff;
914 c896fe29 bellard
            nb_cargs = def->nb_cargs;
915 c896fe29 bellard
916 eeacee4d Blue Swirl
            qemu_log(" %s ", def->name);
917 7e4597d7 bellard
918 b03cce8e bellard
            /* function name */
919 eeacee4d Blue Swirl
            qemu_log("%s",
920 eeacee4d Blue Swirl
                     tcg_get_arg_str_idx(s, buf, sizeof(buf),
921 eeacee4d Blue Swirl
                                         args[nb_oargs + nb_iargs - 1]));
922 b03cce8e bellard
            /* flags */
923 eeacee4d Blue Swirl
            qemu_log(",$0x%" TCG_PRIlx, args[nb_oargs + nb_iargs]);
924 b03cce8e bellard
            /* nb out args */
925 eeacee4d Blue Swirl
            qemu_log(",$%d", nb_oargs);
926 b03cce8e bellard
            for(i = 0; i < nb_oargs; i++) {
927 eeacee4d Blue Swirl
                qemu_log(",");
928 eeacee4d Blue Swirl
                qemu_log("%s", tcg_get_arg_str_idx(s, buf, sizeof(buf),
929 eeacee4d Blue Swirl
                                                   args[i]));
930 b03cce8e bellard
            }
931 b03cce8e bellard
            for(i = 0; i < (nb_iargs - 1); i++) {
932 eeacee4d Blue Swirl
                qemu_log(",");
933 39cf05d3 bellard
                if (args[nb_oargs + i] == TCG_CALL_DUMMY_ARG) {
934 eeacee4d Blue Swirl
                    qemu_log("<dummy>");
935 39cf05d3 bellard
                } else {
936 eeacee4d Blue Swirl
                    qemu_log("%s", tcg_get_arg_str_idx(s, buf, sizeof(buf),
937 eeacee4d Blue Swirl
                                                       args[nb_oargs + i]));
938 39cf05d3 bellard
                }
939 b03cce8e bellard
            }
940 fba3161f Aurelien Jarno
        } else if (c == INDEX_op_movi_i32 || c == INDEX_op_movi_i64) {
941 e8996ee0 bellard
            tcg_target_ulong val;
942 e8996ee0 bellard
            TCGHelperInfo *th;
943 e8996ee0 bellard
944 e8996ee0 bellard
            nb_oargs = def->nb_oargs;
945 e8996ee0 bellard
            nb_iargs = def->nb_iargs;
946 e8996ee0 bellard
            nb_cargs = def->nb_cargs;
947 eeacee4d Blue Swirl
            qemu_log(" %s %s,$", def->name,
948 eeacee4d Blue Swirl
                     tcg_get_arg_str_idx(s, buf, sizeof(buf), args[0]));
949 e8996ee0 bellard
            val = args[1];
950 e8996ee0 bellard
            th = tcg_find_helper(s, val);
951 e8996ee0 bellard
            if (th) {
952 eeacee4d Blue Swirl
                qemu_log("%s", th->name);
953 e8996ee0 bellard
            } else {
954 eeacee4d Blue Swirl
                if (c == INDEX_op_movi_i32) {
955 eeacee4d Blue Swirl
                    qemu_log("0x%x", (uint32_t)val);
956 eeacee4d Blue Swirl
                } else {
957 eeacee4d Blue Swirl
                    qemu_log("0x%" PRIx64 , (uint64_t)val);
958 eeacee4d Blue Swirl
                }
959 e8996ee0 bellard
            }
960 b03cce8e bellard
        } else {
961 eeacee4d Blue Swirl
            qemu_log(" %s ", def->name);
962 b03cce8e bellard
            if (c == INDEX_op_nopn) {
963 b03cce8e bellard
                /* variable number of arguments */
964 b03cce8e bellard
                nb_cargs = *args;
965 b03cce8e bellard
                nb_oargs = 0;
966 b03cce8e bellard
                nb_iargs = 0;
967 b03cce8e bellard
            } else {
968 b03cce8e bellard
                nb_oargs = def->nb_oargs;
969 b03cce8e bellard
                nb_iargs = def->nb_iargs;
970 b03cce8e bellard
                nb_cargs = def->nb_cargs;
971 b03cce8e bellard
            }
972 b03cce8e bellard
            
973 b03cce8e bellard
            k = 0;
974 b03cce8e bellard
            for(i = 0; i < nb_oargs; i++) {
975 eeacee4d Blue Swirl
                if (k != 0) {
976 eeacee4d Blue Swirl
                    qemu_log(",");
977 eeacee4d Blue Swirl
                }
978 eeacee4d Blue Swirl
                qemu_log("%s", tcg_get_arg_str_idx(s, buf, sizeof(buf),
979 eeacee4d Blue Swirl
                                                   args[k++]));
980 b03cce8e bellard
            }
981 b03cce8e bellard
            for(i = 0; i < nb_iargs; i++) {
982 eeacee4d Blue Swirl
                if (k != 0) {
983 eeacee4d Blue Swirl
                    qemu_log(",");
984 eeacee4d Blue Swirl
                }
985 eeacee4d Blue Swirl
                qemu_log("%s", tcg_get_arg_str_idx(s, buf, sizeof(buf),
986 eeacee4d Blue Swirl
                                                   args[k++]));
987 b03cce8e bellard
            }
988 be210acb Richard Henderson
            switch (c) {
989 be210acb Richard Henderson
            case INDEX_op_brcond_i32:
990 be210acb Richard Henderson
            case INDEX_op_setcond_i32:
991 ffc5ea09 Richard Henderson
            case INDEX_op_movcond_i32:
992 ffc5ea09 Richard Henderson
            case INDEX_op_brcond2_i32:
993 be210acb Richard Henderson
            case INDEX_op_setcond2_i32:
994 ffc5ea09 Richard Henderson
            case INDEX_op_brcond_i64:
995 be210acb Richard Henderson
            case INDEX_op_setcond_i64:
996 ffc5ea09 Richard Henderson
            case INDEX_op_movcond_i64:
997 eeacee4d Blue Swirl
                if (args[k] < ARRAY_SIZE(cond_name) && cond_name[args[k]]) {
998 eeacee4d Blue Swirl
                    qemu_log(",%s", cond_name[args[k++]]);
999 eeacee4d Blue Swirl
                } else {
1000 eeacee4d Blue Swirl
                    qemu_log(",$0x%" TCG_PRIlx, args[k++]);
1001 eeacee4d Blue Swirl
                }
1002 f48f3ede blueswir1
                i = 1;
1003 be210acb Richard Henderson
                break;
1004 be210acb Richard Henderson
            default:
1005 f48f3ede blueswir1
                i = 0;
1006 be210acb Richard Henderson
                break;
1007 be210acb Richard Henderson
            }
1008 f48f3ede blueswir1
            for(; i < nb_cargs; i++) {
1009 eeacee4d Blue Swirl
                if (k != 0) {
1010 eeacee4d Blue Swirl
                    qemu_log(",");
1011 eeacee4d Blue Swirl
                }
1012 b03cce8e bellard
                arg = args[k++];
1013 eeacee4d Blue Swirl
                qemu_log("$0x%" TCG_PRIlx, arg);
1014 b03cce8e bellard
            }
1015 c896fe29 bellard
        }
1016 eeacee4d Blue Swirl
        qemu_log("\n");
1017 c896fe29 bellard
        args += nb_iargs + nb_oargs + nb_cargs;
1018 c896fe29 bellard
    }
1019 c896fe29 bellard
}
1020 c896fe29 bellard
1021 c896fe29 bellard
/* we give more priority to constraints with less registers */
1022 c896fe29 bellard
static int get_constraint_priority(const TCGOpDef *def, int k)
1023 c896fe29 bellard
{
1024 c896fe29 bellard
    const TCGArgConstraint *arg_ct;
1025 c896fe29 bellard
1026 c896fe29 bellard
    int i, n;
1027 c896fe29 bellard
    arg_ct = &def->args_ct[k];
1028 c896fe29 bellard
    if (arg_ct->ct & TCG_CT_ALIAS) {
1029 c896fe29 bellard
        /* an alias is equivalent to a single register */
1030 c896fe29 bellard
        n = 1;
1031 c896fe29 bellard
    } else {
1032 c896fe29 bellard
        if (!(arg_ct->ct & TCG_CT_REG))
1033 c896fe29 bellard
            return 0;
1034 c896fe29 bellard
        n = 0;
1035 c896fe29 bellard
        for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
1036 c896fe29 bellard
            if (tcg_regset_test_reg(arg_ct->u.regs, i))
1037 c896fe29 bellard
                n++;
1038 c896fe29 bellard
        }
1039 c896fe29 bellard
    }
1040 c896fe29 bellard
    return TCG_TARGET_NB_REGS - n + 1;
1041 c896fe29 bellard
}
1042 c896fe29 bellard
1043 c896fe29 bellard
/* sort from highest priority to lowest */
1044 c896fe29 bellard
static void sort_constraints(TCGOpDef *def, int start, int n)
1045 c896fe29 bellard
{
1046 c896fe29 bellard
    int i, j, p1, p2, tmp;
1047 c896fe29 bellard
1048 c896fe29 bellard
    for(i = 0; i < n; i++)
1049 c896fe29 bellard
        def->sorted_args[start + i] = start + i;
1050 c896fe29 bellard
    if (n <= 1)
1051 c896fe29 bellard
        return;
1052 c896fe29 bellard
    for(i = 0; i < n - 1; i++) {
1053 c896fe29 bellard
        for(j = i + 1; j < n; j++) {
1054 c896fe29 bellard
            p1 = get_constraint_priority(def, def->sorted_args[start + i]);
1055 c896fe29 bellard
            p2 = get_constraint_priority(def, def->sorted_args[start + j]);
1056 c896fe29 bellard
            if (p1 < p2) {
1057 c896fe29 bellard
                tmp = def->sorted_args[start + i];
1058 c896fe29 bellard
                def->sorted_args[start + i] = def->sorted_args[start + j];
1059 c896fe29 bellard
                def->sorted_args[start + j] = tmp;
1060 c896fe29 bellard
            }
1061 c896fe29 bellard
        }
1062 c896fe29 bellard
    }
1063 c896fe29 bellard
}
1064 c896fe29 bellard
1065 c896fe29 bellard
void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs)
1066 c896fe29 bellard
{
1067 a9751609 Richard Henderson
    TCGOpcode op;
1068 c896fe29 bellard
    TCGOpDef *def;
1069 c896fe29 bellard
    const char *ct_str;
1070 c896fe29 bellard
    int i, nb_args;
1071 c896fe29 bellard
1072 c896fe29 bellard
    for(;;) {
1073 a9751609 Richard Henderson
        if (tdefs->op == (TCGOpcode)-1)
1074 c896fe29 bellard
            break;
1075 c896fe29 bellard
        op = tdefs->op;
1076 c3b08d0e Stefan Weil
        assert((unsigned)op < NB_OPS);
1077 c896fe29 bellard
        def = &tcg_op_defs[op];
1078 c68aaa18 Stefan Weil
#if defined(CONFIG_DEBUG_TCG)
1079 c68aaa18 Stefan Weil
        /* Duplicate entry in op definitions? */
1080 c68aaa18 Stefan Weil
        assert(!def->used);
1081 c68aaa18 Stefan Weil
        def->used = 1;
1082 c68aaa18 Stefan Weil
#endif
1083 c896fe29 bellard
        nb_args = def->nb_iargs + def->nb_oargs;
1084 c896fe29 bellard
        for(i = 0; i < nb_args; i++) {
1085 c896fe29 bellard
            ct_str = tdefs->args_ct_str[i];
1086 c68aaa18 Stefan Weil
            /* Incomplete TCGTargetOpDef entry? */
1087 c68aaa18 Stefan Weil
            assert(ct_str != NULL);
1088 c896fe29 bellard
            tcg_regset_clear(def->args_ct[i].u.regs);
1089 c896fe29 bellard
            def->args_ct[i].ct = 0;
1090 c896fe29 bellard
            if (ct_str[0] >= '0' && ct_str[0] <= '9') {
1091 c896fe29 bellard
                int oarg;
1092 c896fe29 bellard
                oarg = ct_str[0] - '0';
1093 c896fe29 bellard
                assert(oarg < def->nb_oargs);
1094 c896fe29 bellard
                assert(def->args_ct[oarg].ct & TCG_CT_REG);
1095 c896fe29 bellard
                /* TCG_CT_ALIAS is for the output arguments. The input
1096 5ff9d6a4 bellard
                   argument is tagged with TCG_CT_IALIAS. */
1097 c896fe29 bellard
                def->args_ct[i] = def->args_ct[oarg];
1098 5ff9d6a4 bellard
                def->args_ct[oarg].ct = TCG_CT_ALIAS;
1099 5ff9d6a4 bellard
                def->args_ct[oarg].alias_index = i;
1100 c896fe29 bellard
                def->args_ct[i].ct |= TCG_CT_IALIAS;
1101 5ff9d6a4 bellard
                def->args_ct[i].alias_index = oarg;
1102 c896fe29 bellard
            } else {
1103 c896fe29 bellard
                for(;;) {
1104 c896fe29 bellard
                    if (*ct_str == '\0')
1105 c896fe29 bellard
                        break;
1106 c896fe29 bellard
                    switch(*ct_str) {
1107 c896fe29 bellard
                    case 'i':
1108 c896fe29 bellard
                        def->args_ct[i].ct |= TCG_CT_CONST;
1109 c896fe29 bellard
                        ct_str++;
1110 c896fe29 bellard
                        break;
1111 c896fe29 bellard
                    default:
1112 c896fe29 bellard
                        if (target_parse_constraint(&def->args_ct[i], &ct_str) < 0) {
1113 c896fe29 bellard
                            fprintf(stderr, "Invalid constraint '%s' for arg %d of operation '%s'\n",
1114 c896fe29 bellard
                                    ct_str, i, def->name);
1115 c896fe29 bellard
                            exit(1);
1116 c896fe29 bellard
                        }
1117 c896fe29 bellard
                    }
1118 c896fe29 bellard
                }
1119 c896fe29 bellard
            }
1120 c896fe29 bellard
        }
1121 c896fe29 bellard
1122 c68aaa18 Stefan Weil
        /* TCGTargetOpDef entry with too much information? */
1123 c68aaa18 Stefan Weil
        assert(i == TCG_MAX_OP_ARGS || tdefs->args_ct_str[i] == NULL);
1124 c68aaa18 Stefan Weil
1125 c896fe29 bellard
        /* sort the constraints (XXX: this is just an heuristic) */
1126 c896fe29 bellard
        sort_constraints(def, 0, def->nb_oargs);
1127 c896fe29 bellard
        sort_constraints(def, def->nb_oargs, def->nb_iargs);
1128 c896fe29 bellard
1129 c896fe29 bellard
#if 0
1130 c896fe29 bellard
        {
1131 c896fe29 bellard
            int i;
1132 c896fe29 bellard

1133 c896fe29 bellard
            printf("%s: sorted=", def->name);
1134 c896fe29 bellard
            for(i = 0; i < def->nb_oargs + def->nb_iargs; i++)
1135 c896fe29 bellard
                printf(" %d", def->sorted_args[i]);
1136 c896fe29 bellard
            printf("\n");
1137 c896fe29 bellard
        }
1138 c896fe29 bellard
#endif
1139 c896fe29 bellard
        tdefs++;
1140 c896fe29 bellard
    }
1141 c896fe29 bellard
1142 c68aaa18 Stefan Weil
#if defined(CONFIG_DEBUG_TCG)
1143 a9751609 Richard Henderson
    i = 0;
1144 c68aaa18 Stefan Weil
    for (op = 0; op < ARRAY_SIZE(tcg_op_defs); op++) {
1145 f412c762 Richard Henderson
        const TCGOpDef *def = &tcg_op_defs[op];
1146 f412c762 Richard Henderson
        if (op < INDEX_op_call
1147 f412c762 Richard Henderson
            || op == INDEX_op_debug_insn_start
1148 f412c762 Richard Henderson
            || (def->flags & TCG_OPF_NOT_PRESENT)) {
1149 c68aaa18 Stefan Weil
            /* Wrong entry in op definitions? */
1150 f412c762 Richard Henderson
            if (def->used) {
1151 f412c762 Richard Henderson
                fprintf(stderr, "Invalid op definition for %s\n", def->name);
1152 a9751609 Richard Henderson
                i = 1;
1153 a9751609 Richard Henderson
            }
1154 c68aaa18 Stefan Weil
        } else {
1155 c68aaa18 Stefan Weil
            /* Missing entry in op definitions? */
1156 f412c762 Richard Henderson
            if (!def->used) {
1157 f412c762 Richard Henderson
                fprintf(stderr, "Missing op definition for %s\n", def->name);
1158 a9751609 Richard Henderson
                i = 1;
1159 a9751609 Richard Henderson
            }
1160 c68aaa18 Stefan Weil
        }
1161 c68aaa18 Stefan Weil
    }
1162 a9751609 Richard Henderson
    if (i == 1) {
1163 a9751609 Richard Henderson
        tcg_abort();
1164 a9751609 Richard Henderson
    }
1165 c68aaa18 Stefan Weil
#endif
1166 c896fe29 bellard
}
1167 c896fe29 bellard
1168 c896fe29 bellard
#ifdef USE_LIVENESS_ANALYSIS
1169 c896fe29 bellard
1170 c896fe29 bellard
/* set a nop for an operation using 'nb_args' */
1171 c896fe29 bellard
static inline void tcg_set_nop(TCGContext *s, uint16_t *opc_ptr, 
1172 c896fe29 bellard
                               TCGArg *args, int nb_args)
1173 c896fe29 bellard
{
1174 c896fe29 bellard
    if (nb_args == 0) {
1175 c896fe29 bellard
        *opc_ptr = INDEX_op_nop;
1176 c896fe29 bellard
    } else {
1177 c896fe29 bellard
        *opc_ptr = INDEX_op_nopn;
1178 c896fe29 bellard
        args[0] = nb_args;
1179 c896fe29 bellard
        args[nb_args - 1] = nb_args;
1180 c896fe29 bellard
    }
1181 c896fe29 bellard
}
1182 c896fe29 bellard
1183 641d5fbe bellard
/* liveness analysis: end of function: globals are live, temps are
1184 641d5fbe bellard
   dead. */
1185 641d5fbe bellard
/* XXX: at this stage, not used as there would be little gains because
1186 641d5fbe bellard
   most TBs end with a conditional jump. */
1187 641d5fbe bellard
static inline void tcg_la_func_end(TCGContext *s, uint8_t *dead_temps)
1188 c896fe29 bellard
{
1189 c896fe29 bellard
    memset(dead_temps, 0, s->nb_globals);
1190 c896fe29 bellard
    memset(dead_temps + s->nb_globals, 1, s->nb_temps - s->nb_globals);
1191 c896fe29 bellard
}
1192 c896fe29 bellard
1193 641d5fbe bellard
/* liveness analysis: end of basic block: globals are live, temps are
1194 641d5fbe bellard
   dead, local temps are live. */
1195 641d5fbe bellard
static inline void tcg_la_bb_end(TCGContext *s, uint8_t *dead_temps)
1196 641d5fbe bellard
{
1197 641d5fbe bellard
    int i;
1198 641d5fbe bellard
    TCGTemp *ts;
1199 641d5fbe bellard
1200 641d5fbe bellard
    memset(dead_temps, 0, s->nb_globals);
1201 641d5fbe bellard
    ts = &s->temps[s->nb_globals];
1202 641d5fbe bellard
    for(i = s->nb_globals; i < s->nb_temps; i++) {
1203 641d5fbe bellard
        if (ts->temp_local)
1204 641d5fbe bellard
            dead_temps[i] = 0;
1205 641d5fbe bellard
        else
1206 641d5fbe bellard
            dead_temps[i] = 1;
1207 641d5fbe bellard
        ts++;
1208 641d5fbe bellard
    }
1209 641d5fbe bellard
}
1210 641d5fbe bellard
1211 866cb6cb Aurelien Jarno
/* Liveness analysis : update the opc_dead_args array to tell if a
1212 c896fe29 bellard
   given input arguments is dead. Instructions updating dead
1213 c896fe29 bellard
   temporaries are removed. */
1214 8fcd3692 blueswir1
static void tcg_liveness_analysis(TCGContext *s)
1215 c896fe29 bellard
{
1216 a9751609 Richard Henderson
    int i, op_index, nb_args, nb_iargs, nb_oargs, arg, nb_ops;
1217 a9751609 Richard Henderson
    TCGOpcode op;
1218 c896fe29 bellard
    TCGArg *args;
1219 c896fe29 bellard
    const TCGOpDef *def;
1220 c896fe29 bellard
    uint8_t *dead_temps;
1221 866cb6cb Aurelien Jarno
    unsigned int dead_args;
1222 c896fe29 bellard
    
1223 c896fe29 bellard
    gen_opc_ptr++; /* skip end */
1224 c896fe29 bellard
1225 c896fe29 bellard
    nb_ops = gen_opc_ptr - gen_opc_buf;
1226 c896fe29 bellard
1227 866cb6cb Aurelien Jarno
    s->op_dead_args = tcg_malloc(nb_ops * sizeof(uint16_t));
1228 c896fe29 bellard
    
1229 c896fe29 bellard
    dead_temps = tcg_malloc(s->nb_temps);
1230 c896fe29 bellard
    memset(dead_temps, 1, s->nb_temps);
1231 c896fe29 bellard
1232 c896fe29 bellard
    args = gen_opparam_ptr;
1233 c896fe29 bellard
    op_index = nb_ops - 1;
1234 c896fe29 bellard
    while (op_index >= 0) {
1235 c896fe29 bellard
        op = gen_opc_buf[op_index];
1236 c896fe29 bellard
        def = &tcg_op_defs[op];
1237 c896fe29 bellard
        switch(op) {
1238 c896fe29 bellard
        case INDEX_op_call:
1239 c6e113f5 bellard
            {
1240 c6e113f5 bellard
                int call_flags;
1241 c896fe29 bellard
1242 c6e113f5 bellard
                nb_args = args[-1];
1243 c6e113f5 bellard
                args -= nb_args;
1244 c6e113f5 bellard
                nb_iargs = args[0] & 0xffff;
1245 c6e113f5 bellard
                nb_oargs = args[0] >> 16;
1246 c6e113f5 bellard
                args++;
1247 c6e113f5 bellard
                call_flags = args[nb_oargs + nb_iargs];
1248 c6e113f5 bellard
1249 c6e113f5 bellard
                /* pure functions can be removed if their result is not
1250 c6e113f5 bellard
                   used */
1251 c6e113f5 bellard
                if (call_flags & TCG_CALL_PURE) {
1252 c6e113f5 bellard
                    for(i = 0; i < nb_oargs; i++) {
1253 c6e113f5 bellard
                        arg = args[i];
1254 c6e113f5 bellard
                        if (!dead_temps[arg])
1255 c6e113f5 bellard
                            goto do_not_remove_call;
1256 c6e113f5 bellard
                    }
1257 c6e113f5 bellard
                    tcg_set_nop(s, gen_opc_buf + op_index, 
1258 c6e113f5 bellard
                                args - 1, nb_args);
1259 c6e113f5 bellard
                } else {
1260 c6e113f5 bellard
                do_not_remove_call:
1261 c896fe29 bellard
1262 c6e113f5 bellard
                    /* output args are dead */
1263 6b64b624 Aurelien Jarno
                    dead_args = 0;
1264 c6e113f5 bellard
                    for(i = 0; i < nb_oargs; i++) {
1265 c6e113f5 bellard
                        arg = args[i];
1266 6b64b624 Aurelien Jarno
                        if (dead_temps[arg]) {
1267 6b64b624 Aurelien Jarno
                            dead_args |= (1 << i);
1268 6b64b624 Aurelien Jarno
                        }
1269 c6e113f5 bellard
                        dead_temps[arg] = 1;
1270 c6e113f5 bellard
                    }
1271 c6e113f5 bellard
                    
1272 b9c18f56 aurel32
                    if (!(call_flags & TCG_CALL_CONST)) {
1273 b9c18f56 aurel32
                        /* globals are live (they may be used by the call) */
1274 b9c18f56 aurel32
                        memset(dead_temps, 0, s->nb_globals);
1275 b9c18f56 aurel32
                    }
1276 b9c18f56 aurel32
1277 c6e113f5 bellard
                    /* input args are live */
1278 866cb6cb Aurelien Jarno
                    for(i = nb_oargs; i < nb_iargs + nb_oargs; i++) {
1279 866cb6cb Aurelien Jarno
                        arg = args[i];
1280 39cf05d3 bellard
                        if (arg != TCG_CALL_DUMMY_ARG) {
1281 39cf05d3 bellard
                            if (dead_temps[arg]) {
1282 866cb6cb Aurelien Jarno
                                dead_args |= (1 << i);
1283 39cf05d3 bellard
                            }
1284 39cf05d3 bellard
                            dead_temps[arg] = 0;
1285 c6e113f5 bellard
                        }
1286 c6e113f5 bellard
                    }
1287 866cb6cb Aurelien Jarno
                    s->op_dead_args[op_index] = dead_args;
1288 c896fe29 bellard
                }
1289 c6e113f5 bellard
                args--;
1290 c896fe29 bellard
            }
1291 c896fe29 bellard
            break;
1292 7e4597d7 bellard
        case INDEX_op_debug_insn_start:
1293 7e4597d7 bellard
            args -= def->nb_args;
1294 7e4597d7 bellard
            break;
1295 c896fe29 bellard
        case INDEX_op_nopn:
1296 c896fe29 bellard
            nb_args = args[-1];
1297 c896fe29 bellard
            args -= nb_args;
1298 c896fe29 bellard
            break;
1299 5ff9d6a4 bellard
        case INDEX_op_discard:
1300 5ff9d6a4 bellard
            args--;
1301 5ff9d6a4 bellard
            /* mark the temporary as dead */
1302 5ff9d6a4 bellard
            dead_temps[args[0]] = 1;
1303 5ff9d6a4 bellard
            break;
1304 c896fe29 bellard
        case INDEX_op_end:
1305 c896fe29 bellard
            break;
1306 c896fe29 bellard
            /* XXX: optimize by hardcoding common cases (e.g. triadic ops) */
1307 c896fe29 bellard
        default:
1308 49516bc0 aurel32
            args -= def->nb_args;
1309 49516bc0 aurel32
            nb_iargs = def->nb_iargs;
1310 49516bc0 aurel32
            nb_oargs = def->nb_oargs;
1311 c896fe29 bellard
1312 49516bc0 aurel32
            /* Test if the operation can be removed because all
1313 49516bc0 aurel32
               its outputs are dead. We assume that nb_oargs == 0
1314 49516bc0 aurel32
               implies side effects */
1315 49516bc0 aurel32
            if (!(def->flags & TCG_OPF_SIDE_EFFECTS) && nb_oargs != 0) {
1316 49516bc0 aurel32
                for(i = 0; i < nb_oargs; i++) {
1317 49516bc0 aurel32
                    arg = args[i];
1318 49516bc0 aurel32
                    if (!dead_temps[arg])
1319 49516bc0 aurel32
                        goto do_not_remove;
1320 49516bc0 aurel32
                }
1321 49516bc0 aurel32
                tcg_set_nop(s, gen_opc_buf + op_index, args, def->nb_args);
1322 c896fe29 bellard
#ifdef CONFIG_PROFILER
1323 49516bc0 aurel32
                s->del_op_count++;
1324 c896fe29 bellard
#endif
1325 49516bc0 aurel32
            } else {
1326 49516bc0 aurel32
            do_not_remove:
1327 c896fe29 bellard
1328 49516bc0 aurel32
                /* output args are dead */
1329 6b64b624 Aurelien Jarno
                dead_args = 0;
1330 49516bc0 aurel32
                for(i = 0; i < nb_oargs; i++) {
1331 49516bc0 aurel32
                    arg = args[i];
1332 6b64b624 Aurelien Jarno
                    if (dead_temps[arg]) {
1333 6b64b624 Aurelien Jarno
                        dead_args |= (1 << i);
1334 6b64b624 Aurelien Jarno
                    }
1335 49516bc0 aurel32
                    dead_temps[arg] = 1;
1336 49516bc0 aurel32
                }
1337 49516bc0 aurel32
1338 49516bc0 aurel32
                /* if end of basic block, update */
1339 49516bc0 aurel32
                if (def->flags & TCG_OPF_BB_END) {
1340 49516bc0 aurel32
                    tcg_la_bb_end(s, dead_temps);
1341 49516bc0 aurel32
                } else if (def->flags & TCG_OPF_CALL_CLOBBER) {
1342 49516bc0 aurel32
                    /* globals are live */
1343 49516bc0 aurel32
                    memset(dead_temps, 0, s->nb_globals);
1344 49516bc0 aurel32
                }
1345 49516bc0 aurel32
1346 49516bc0 aurel32
                /* input args are live */
1347 866cb6cb Aurelien Jarno
                for(i = nb_oargs; i < nb_oargs + nb_iargs; i++) {
1348 866cb6cb Aurelien Jarno
                    arg = args[i];
1349 49516bc0 aurel32
                    if (dead_temps[arg]) {
1350 866cb6cb Aurelien Jarno
                        dead_args |= (1 << i);
1351 c896fe29 bellard
                    }
1352 49516bc0 aurel32
                    dead_temps[arg] = 0;
1353 c896fe29 bellard
                }
1354 866cb6cb Aurelien Jarno
                s->op_dead_args[op_index] = dead_args;
1355 c896fe29 bellard
            }
1356 c896fe29 bellard
            break;
1357 c896fe29 bellard
        }
1358 c896fe29 bellard
        op_index--;
1359 c896fe29 bellard
    }
1360 c896fe29 bellard
1361 c896fe29 bellard
    if (args != gen_opparam_buf)
1362 c896fe29 bellard
        tcg_abort();
1363 c896fe29 bellard
}
1364 c896fe29 bellard
#else
1365 c896fe29 bellard
/* dummy liveness analysis */
1366 655feed5 malc
static void tcg_liveness_analysis(TCGContext *s)
1367 c896fe29 bellard
{
1368 c896fe29 bellard
    int nb_ops;
1369 c896fe29 bellard
    nb_ops = gen_opc_ptr - gen_opc_buf;
1370 c896fe29 bellard
1371 866cb6cb Aurelien Jarno
    s->op_dead_args = tcg_malloc(nb_ops * sizeof(uint16_t));
1372 866cb6cb Aurelien Jarno
    memset(s->op_dead_args, 0, nb_ops * sizeof(uint16_t));
1373 c896fe29 bellard
}
1374 c896fe29 bellard
#endif
1375 c896fe29 bellard
1376 c896fe29 bellard
#ifndef NDEBUG
1377 c896fe29 bellard
static void dump_regs(TCGContext *s)
1378 c896fe29 bellard
{
1379 c896fe29 bellard
    TCGTemp *ts;
1380 c896fe29 bellard
    int i;
1381 c896fe29 bellard
    char buf[64];
1382 c896fe29 bellard
1383 c896fe29 bellard
    for(i = 0; i < s->nb_temps; i++) {
1384 c896fe29 bellard
        ts = &s->temps[i];
1385 ac56dd48 pbrook
        printf("  %10s: ", tcg_get_arg_str_idx(s, buf, sizeof(buf), i));
1386 c896fe29 bellard
        switch(ts->val_type) {
1387 c896fe29 bellard
        case TEMP_VAL_REG:
1388 c896fe29 bellard
            printf("%s", tcg_target_reg_names[ts->reg]);
1389 c896fe29 bellard
            break;
1390 c896fe29 bellard
        case TEMP_VAL_MEM:
1391 c896fe29 bellard
            printf("%d(%s)", (int)ts->mem_offset, tcg_target_reg_names[ts->mem_reg]);
1392 c896fe29 bellard
            break;
1393 c896fe29 bellard
        case TEMP_VAL_CONST:
1394 c896fe29 bellard
            printf("$0x%" TCG_PRIlx, ts->val);
1395 c896fe29 bellard
            break;
1396 c896fe29 bellard
        case TEMP_VAL_DEAD:
1397 c896fe29 bellard
            printf("D");
1398 c896fe29 bellard
            break;
1399 c896fe29 bellard
        default:
1400 c896fe29 bellard
            printf("???");
1401 c896fe29 bellard
            break;
1402 c896fe29 bellard
        }
1403 c896fe29 bellard
        printf("\n");
1404 c896fe29 bellard
    }
1405 c896fe29 bellard
1406 c896fe29 bellard
    for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
1407 c896fe29 bellard
        if (s->reg_to_temp[i] >= 0) {
1408 c896fe29 bellard
            printf("%s: %s\n", 
1409 c896fe29 bellard
                   tcg_target_reg_names[i], 
1410 ac56dd48 pbrook
                   tcg_get_arg_str_idx(s, buf, sizeof(buf), s->reg_to_temp[i]));
1411 c896fe29 bellard
        }
1412 c896fe29 bellard
    }
1413 c896fe29 bellard
}
1414 c896fe29 bellard
1415 c896fe29 bellard
static void check_regs(TCGContext *s)
1416 c896fe29 bellard
{
1417 c896fe29 bellard
    int reg, k;
1418 c896fe29 bellard
    TCGTemp *ts;
1419 c896fe29 bellard
    char buf[64];
1420 c896fe29 bellard
1421 c896fe29 bellard
    for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1422 c896fe29 bellard
        k = s->reg_to_temp[reg];
1423 c896fe29 bellard
        if (k >= 0) {
1424 c896fe29 bellard
            ts = &s->temps[k];
1425 c896fe29 bellard
            if (ts->val_type != TEMP_VAL_REG ||
1426 c896fe29 bellard
                ts->reg != reg) {
1427 c896fe29 bellard
                printf("Inconsistency for register %s:\n", 
1428 c896fe29 bellard
                       tcg_target_reg_names[reg]);
1429 b03cce8e bellard
                goto fail;
1430 c896fe29 bellard
            }
1431 c896fe29 bellard
        }
1432 c896fe29 bellard
    }
1433 c896fe29 bellard
    for(k = 0; k < s->nb_temps; k++) {
1434 c896fe29 bellard
        ts = &s->temps[k];
1435 c896fe29 bellard
        if (ts->val_type == TEMP_VAL_REG &&
1436 c896fe29 bellard
            !ts->fixed_reg &&
1437 c896fe29 bellard
            s->reg_to_temp[ts->reg] != k) {
1438 c896fe29 bellard
                printf("Inconsistency for temp %s:\n", 
1439 ac56dd48 pbrook
                       tcg_get_arg_str_idx(s, buf, sizeof(buf), k));
1440 b03cce8e bellard
        fail:
1441 c896fe29 bellard
                printf("reg state:\n");
1442 c896fe29 bellard
                dump_regs(s);
1443 c896fe29 bellard
                tcg_abort();
1444 c896fe29 bellard
        }
1445 c896fe29 bellard
    }
1446 c896fe29 bellard
}
1447 c896fe29 bellard
#endif
1448 c896fe29 bellard
1449 c896fe29 bellard
static void temp_allocate_frame(TCGContext *s, int temp)
1450 c896fe29 bellard
{
1451 c896fe29 bellard
    TCGTemp *ts;
1452 c896fe29 bellard
    ts = &s->temps[temp];
1453 f44c9960 Blue Swirl
#ifndef __sparc_v9__ /* Sparc64 stack is accessed with offset of 2047 */
1454 b591dc59 Blue Swirl
    s->current_frame_offset = (s->current_frame_offset +
1455 b591dc59 Blue Swirl
                               (tcg_target_long)sizeof(tcg_target_long) - 1) &
1456 b591dc59 Blue Swirl
        ~(sizeof(tcg_target_long) - 1);
1457 f44c9960 Blue Swirl
#endif
1458 b591dc59 Blue Swirl
    if (s->current_frame_offset + (tcg_target_long)sizeof(tcg_target_long) >
1459 b591dc59 Blue Swirl
        s->frame_end) {
1460 5ff9d6a4 bellard
        tcg_abort();
1461 b591dc59 Blue Swirl
    }
1462 c896fe29 bellard
    ts->mem_offset = s->current_frame_offset;
1463 c896fe29 bellard
    ts->mem_reg = s->frame_reg;
1464 c896fe29 bellard
    ts->mem_allocated = 1;
1465 b591dc59 Blue Swirl
    s->current_frame_offset += (tcg_target_long)sizeof(tcg_target_long);
1466 c896fe29 bellard
}
1467 c896fe29 bellard
1468 c896fe29 bellard
/* free register 'reg' by spilling the corresponding temporary if necessary */
1469 c896fe29 bellard
static void tcg_reg_free(TCGContext *s, int reg)
1470 c896fe29 bellard
{
1471 c896fe29 bellard
    TCGTemp *ts;
1472 c896fe29 bellard
    int temp;
1473 c896fe29 bellard
1474 c896fe29 bellard
    temp = s->reg_to_temp[reg];
1475 c896fe29 bellard
    if (temp != -1) {
1476 c896fe29 bellard
        ts = &s->temps[temp];
1477 c896fe29 bellard
        assert(ts->val_type == TEMP_VAL_REG);
1478 c896fe29 bellard
        if (!ts->mem_coherent) {
1479 c896fe29 bellard
            if (!ts->mem_allocated) 
1480 c896fe29 bellard
                temp_allocate_frame(s, temp);
1481 e4d5434c blueswir1
            tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1482 c896fe29 bellard
        }
1483 c896fe29 bellard
        ts->val_type = TEMP_VAL_MEM;
1484 c896fe29 bellard
        s->reg_to_temp[reg] = -1;
1485 c896fe29 bellard
    }
1486 c896fe29 bellard
}
1487 c896fe29 bellard
1488 c896fe29 bellard
/* Allocate a register belonging to reg1 & ~reg2 */
1489 c896fe29 bellard
static int tcg_reg_alloc(TCGContext *s, TCGRegSet reg1, TCGRegSet reg2)
1490 c896fe29 bellard
{
1491 c896fe29 bellard
    int i, reg;
1492 c896fe29 bellard
    TCGRegSet reg_ct;
1493 c896fe29 bellard
1494 c896fe29 bellard
    tcg_regset_andnot(reg_ct, reg1, reg2);
1495 c896fe29 bellard
1496 c896fe29 bellard
    /* first try free registers */
1497 0954d0d9 blueswir1
    for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1498 c896fe29 bellard
        reg = tcg_target_reg_alloc_order[i];
1499 c896fe29 bellard
        if (tcg_regset_test_reg(reg_ct, reg) && s->reg_to_temp[reg] == -1)
1500 c896fe29 bellard
            return reg;
1501 c896fe29 bellard
    }
1502 c896fe29 bellard
1503 c896fe29 bellard
    /* XXX: do better spill choice */
1504 0954d0d9 blueswir1
    for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1505 c896fe29 bellard
        reg = tcg_target_reg_alloc_order[i];
1506 c896fe29 bellard
        if (tcg_regset_test_reg(reg_ct, reg)) {
1507 c896fe29 bellard
            tcg_reg_free(s, reg);
1508 c896fe29 bellard
            return reg;
1509 c896fe29 bellard
        }
1510 c896fe29 bellard
    }
1511 c896fe29 bellard
1512 c896fe29 bellard
    tcg_abort();
1513 c896fe29 bellard
}
1514 c896fe29 bellard
1515 641d5fbe bellard
/* save a temporary to memory. 'allocated_regs' is used in case a
1516 641d5fbe bellard
   temporary registers needs to be allocated to store a constant. */
1517 641d5fbe bellard
static void temp_save(TCGContext *s, int temp, TCGRegSet allocated_regs)
1518 641d5fbe bellard
{
1519 641d5fbe bellard
    TCGTemp *ts;
1520 641d5fbe bellard
    int reg;
1521 641d5fbe bellard
1522 641d5fbe bellard
    ts = &s->temps[temp];
1523 641d5fbe bellard
    if (!ts->fixed_reg) {
1524 641d5fbe bellard
        switch(ts->val_type) {
1525 641d5fbe bellard
        case TEMP_VAL_REG:
1526 641d5fbe bellard
            tcg_reg_free(s, ts->reg);
1527 641d5fbe bellard
            break;
1528 641d5fbe bellard
        case TEMP_VAL_DEAD:
1529 641d5fbe bellard
            ts->val_type = TEMP_VAL_MEM;
1530 641d5fbe bellard
            break;
1531 641d5fbe bellard
        case TEMP_VAL_CONST:
1532 d6859202 Aurelien Jarno
            reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], 
1533 d6859202 Aurelien Jarno
                                allocated_regs);
1534 641d5fbe bellard
            if (!ts->mem_allocated) 
1535 641d5fbe bellard
                temp_allocate_frame(s, temp);
1536 d6859202 Aurelien Jarno
            tcg_out_movi(s, ts->type, reg, ts->val);
1537 d6859202 Aurelien Jarno
            tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1538 641d5fbe bellard
            ts->val_type = TEMP_VAL_MEM;
1539 641d5fbe bellard
            break;
1540 641d5fbe bellard
        case TEMP_VAL_MEM:
1541 641d5fbe bellard
            break;
1542 641d5fbe bellard
        default:
1543 641d5fbe bellard
            tcg_abort();
1544 641d5fbe bellard
        }
1545 641d5fbe bellard
    }
1546 641d5fbe bellard
}
1547 641d5fbe bellard
1548 9814dd27 Dong Xu Wang
/* save globals to their canonical location and assume they can be
1549 e8996ee0 bellard
   modified be the following code. 'allocated_regs' is used in case a
1550 e8996ee0 bellard
   temporary registers needs to be allocated to store a constant. */
1551 e8996ee0 bellard
static void save_globals(TCGContext *s, TCGRegSet allocated_regs)
1552 c896fe29 bellard
{
1553 641d5fbe bellard
    int i;
1554 c896fe29 bellard
1555 c896fe29 bellard
    for(i = 0; i < s->nb_globals; i++) {
1556 641d5fbe bellard
        temp_save(s, i, allocated_regs);
1557 c896fe29 bellard
    }
1558 e5097dc8 bellard
}
1559 e5097dc8 bellard
1560 e5097dc8 bellard
/* at the end of a basic block, we assume all temporaries are dead and
1561 e8996ee0 bellard
   all globals are stored at their canonical location. */
1562 e8996ee0 bellard
static void tcg_reg_alloc_bb_end(TCGContext *s, TCGRegSet allocated_regs)
1563 e5097dc8 bellard
{
1564 e5097dc8 bellard
    TCGTemp *ts;
1565 e5097dc8 bellard
    int i;
1566 e5097dc8 bellard
1567 c896fe29 bellard
    for(i = s->nb_globals; i < s->nb_temps; i++) {
1568 c896fe29 bellard
        ts = &s->temps[i];
1569 641d5fbe bellard
        if (ts->temp_local) {
1570 641d5fbe bellard
            temp_save(s, i, allocated_regs);
1571 641d5fbe bellard
        } else {
1572 641d5fbe bellard
            if (ts->val_type == TEMP_VAL_REG) {
1573 641d5fbe bellard
                s->reg_to_temp[ts->reg] = -1;
1574 641d5fbe bellard
            }
1575 641d5fbe bellard
            ts->val_type = TEMP_VAL_DEAD;
1576 c896fe29 bellard
        }
1577 c896fe29 bellard
    }
1578 e8996ee0 bellard
1579 e8996ee0 bellard
    save_globals(s, allocated_regs);
1580 c896fe29 bellard
}
1581 c896fe29 bellard
1582 866cb6cb Aurelien Jarno
#define IS_DEAD_ARG(n) ((dead_args >> (n)) & 1)
1583 c896fe29 bellard
1584 e8996ee0 bellard
static void tcg_reg_alloc_movi(TCGContext *s, const TCGArg *args)
1585 e8996ee0 bellard
{
1586 e8996ee0 bellard
    TCGTemp *ots;
1587 e8996ee0 bellard
    tcg_target_ulong val;
1588 e8996ee0 bellard
1589 e8996ee0 bellard
    ots = &s->temps[args[0]];
1590 e8996ee0 bellard
    val = args[1];
1591 e8996ee0 bellard
1592 e8996ee0 bellard
    if (ots->fixed_reg) {
1593 e8996ee0 bellard
        /* for fixed registers, we do not do any constant
1594 e8996ee0 bellard
           propagation */
1595 e8996ee0 bellard
        tcg_out_movi(s, ots->type, ots->reg, val);
1596 e8996ee0 bellard
    } else {
1597 1235fc06 ths
        /* The movi is not explicitly generated here */
1598 e8996ee0 bellard
        if (ots->val_type == TEMP_VAL_REG)
1599 e8996ee0 bellard
            s->reg_to_temp[ots->reg] = -1;
1600 e8996ee0 bellard
        ots->val_type = TEMP_VAL_CONST;
1601 e8996ee0 bellard
        ots->val = val;
1602 e8996ee0 bellard
    }
1603 e8996ee0 bellard
}
1604 e8996ee0 bellard
1605 c896fe29 bellard
static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
1606 c896fe29 bellard
                              const TCGArg *args,
1607 866cb6cb Aurelien Jarno
                              unsigned int dead_args)
1608 c896fe29 bellard
{
1609 c896fe29 bellard
    TCGTemp *ts, *ots;
1610 c896fe29 bellard
    int reg;
1611 c896fe29 bellard
    const TCGArgConstraint *arg_ct;
1612 c896fe29 bellard
1613 c896fe29 bellard
    ots = &s->temps[args[0]];
1614 c896fe29 bellard
    ts = &s->temps[args[1]];
1615 c896fe29 bellard
    arg_ct = &def->args_ct[0];
1616 c896fe29 bellard
1617 866cb6cb Aurelien Jarno
    /* XXX: always mark arg dead if IS_DEAD_ARG(1) */
1618 c896fe29 bellard
    if (ts->val_type == TEMP_VAL_REG) {
1619 866cb6cb Aurelien Jarno
        if (IS_DEAD_ARG(1) && !ts->fixed_reg && !ots->fixed_reg) {
1620 c896fe29 bellard
            /* the mov can be suppressed */
1621 c896fe29 bellard
            if (ots->val_type == TEMP_VAL_REG)
1622 c896fe29 bellard
                s->reg_to_temp[ots->reg] = -1;
1623 c896fe29 bellard
            reg = ts->reg;
1624 c896fe29 bellard
            s->reg_to_temp[reg] = -1;
1625 c896fe29 bellard
            ts->val_type = TEMP_VAL_DEAD;
1626 c896fe29 bellard
        } else {
1627 c896fe29 bellard
            if (ots->val_type == TEMP_VAL_REG) {
1628 c896fe29 bellard
                reg = ots->reg;
1629 c896fe29 bellard
            } else {
1630 c896fe29 bellard
                reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1631 c896fe29 bellard
            }
1632 c896fe29 bellard
            if (ts->reg != reg) {
1633 3b6dac34 Richard Henderson
                tcg_out_mov(s, ots->type, reg, ts->reg);
1634 c896fe29 bellard
            }
1635 c896fe29 bellard
        }
1636 c896fe29 bellard
    } else if (ts->val_type == TEMP_VAL_MEM) {
1637 c896fe29 bellard
        if (ots->val_type == TEMP_VAL_REG) {
1638 c896fe29 bellard
            reg = ots->reg;
1639 c896fe29 bellard
        } else {
1640 c896fe29 bellard
            reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1641 c896fe29 bellard
        }
1642 e4d5434c blueswir1
        tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1643 c896fe29 bellard
    } else if (ts->val_type == TEMP_VAL_CONST) {
1644 e8996ee0 bellard
        if (ots->fixed_reg) {
1645 c896fe29 bellard
            reg = ots->reg;
1646 e8996ee0 bellard
            tcg_out_movi(s, ots->type, reg, ts->val);
1647 c896fe29 bellard
        } else {
1648 e8996ee0 bellard
            /* propagate constant */
1649 e8996ee0 bellard
            if (ots->val_type == TEMP_VAL_REG)
1650 e8996ee0 bellard
                s->reg_to_temp[ots->reg] = -1;
1651 e8996ee0 bellard
            ots->val_type = TEMP_VAL_CONST;
1652 e8996ee0 bellard
            ots->val = ts->val;
1653 e8996ee0 bellard
            return;
1654 c896fe29 bellard
        }
1655 c896fe29 bellard
    } else {
1656 c896fe29 bellard
        tcg_abort();
1657 c896fe29 bellard
    }
1658 c896fe29 bellard
    s->reg_to_temp[reg] = args[0];
1659 c896fe29 bellard
    ots->reg = reg;
1660 c896fe29 bellard
    ots->val_type = TEMP_VAL_REG;
1661 c896fe29 bellard
    ots->mem_coherent = 0;
1662 c896fe29 bellard
}
1663 c896fe29 bellard
1664 c896fe29 bellard
static void tcg_reg_alloc_op(TCGContext *s, 
1665 a9751609 Richard Henderson
                             const TCGOpDef *def, TCGOpcode opc,
1666 c896fe29 bellard
                             const TCGArg *args,
1667 866cb6cb Aurelien Jarno
                             unsigned int dead_args)
1668 c896fe29 bellard
{
1669 c896fe29 bellard
    TCGRegSet allocated_regs;
1670 c896fe29 bellard
    int i, k, nb_iargs, nb_oargs, reg;
1671 c896fe29 bellard
    TCGArg arg;
1672 c896fe29 bellard
    const TCGArgConstraint *arg_ct;
1673 c896fe29 bellard
    TCGTemp *ts;
1674 c896fe29 bellard
    TCGArg new_args[TCG_MAX_OP_ARGS];
1675 c896fe29 bellard
    int const_args[TCG_MAX_OP_ARGS];
1676 c896fe29 bellard
1677 c896fe29 bellard
    nb_oargs = def->nb_oargs;
1678 c896fe29 bellard
    nb_iargs = def->nb_iargs;
1679 c896fe29 bellard
1680 c896fe29 bellard
    /* copy constants */
1681 c896fe29 bellard
    memcpy(new_args + nb_oargs + nb_iargs, 
1682 c896fe29 bellard
           args + nb_oargs + nb_iargs, 
1683 c896fe29 bellard
           sizeof(TCGArg) * def->nb_cargs);
1684 c896fe29 bellard
1685 c896fe29 bellard
    /* satisfy input constraints */ 
1686 c896fe29 bellard
    tcg_regset_set(allocated_regs, s->reserved_regs);
1687 c896fe29 bellard
    for(k = 0; k < nb_iargs; k++) {
1688 c896fe29 bellard
        i = def->sorted_args[nb_oargs + k];
1689 c896fe29 bellard
        arg = args[i];
1690 c896fe29 bellard
        arg_ct = &def->args_ct[i];
1691 c896fe29 bellard
        ts = &s->temps[arg];
1692 c896fe29 bellard
        if (ts->val_type == TEMP_VAL_MEM) {
1693 c896fe29 bellard
            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1694 e4d5434c blueswir1
            tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1695 c896fe29 bellard
            ts->val_type = TEMP_VAL_REG;
1696 c896fe29 bellard
            ts->reg = reg;
1697 c896fe29 bellard
            ts->mem_coherent = 1;
1698 c896fe29 bellard
            s->reg_to_temp[reg] = arg;
1699 c896fe29 bellard
        } else if (ts->val_type == TEMP_VAL_CONST) {
1700 c896fe29 bellard
            if (tcg_target_const_match(ts->val, arg_ct)) {
1701 c896fe29 bellard
                /* constant is OK for instruction */
1702 c896fe29 bellard
                const_args[i] = 1;
1703 c896fe29 bellard
                new_args[i] = ts->val;
1704 c896fe29 bellard
                goto iarg_end;
1705 c896fe29 bellard
            } else {
1706 e8996ee0 bellard
                /* need to move to a register */
1707 c896fe29 bellard
                reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1708 c896fe29 bellard
                tcg_out_movi(s, ts->type, reg, ts->val);
1709 e8996ee0 bellard
                ts->val_type = TEMP_VAL_REG;
1710 e8996ee0 bellard
                ts->reg = reg;
1711 e8996ee0 bellard
                ts->mem_coherent = 0;
1712 e8996ee0 bellard
                s->reg_to_temp[reg] = arg;
1713 c896fe29 bellard
            }
1714 c896fe29 bellard
        }
1715 c896fe29 bellard
        assert(ts->val_type == TEMP_VAL_REG);
1716 5ff9d6a4 bellard
        if (arg_ct->ct & TCG_CT_IALIAS) {
1717 5ff9d6a4 bellard
            if (ts->fixed_reg) {
1718 5ff9d6a4 bellard
                /* if fixed register, we must allocate a new register
1719 5ff9d6a4 bellard
                   if the alias is not the same register */
1720 5ff9d6a4 bellard
                if (arg != args[arg_ct->alias_index])
1721 5ff9d6a4 bellard
                    goto allocate_in_reg;
1722 5ff9d6a4 bellard
            } else {
1723 5ff9d6a4 bellard
                /* if the input is aliased to an output and if it is
1724 5ff9d6a4 bellard
                   not dead after the instruction, we must allocate
1725 5ff9d6a4 bellard
                   a new register and move it */
1726 866cb6cb Aurelien Jarno
                if (!IS_DEAD_ARG(i)) {
1727 5ff9d6a4 bellard
                    goto allocate_in_reg;
1728 866cb6cb Aurelien Jarno
                }
1729 5ff9d6a4 bellard
            }
1730 c896fe29 bellard
        }
1731 c896fe29 bellard
        reg = ts->reg;
1732 c896fe29 bellard
        if (tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1733 c896fe29 bellard
            /* nothing to do : the constraint is satisfied */
1734 c896fe29 bellard
        } else {
1735 c896fe29 bellard
        allocate_in_reg:
1736 c896fe29 bellard
            /* allocate a new register matching the constraint 
1737 c896fe29 bellard
               and move the temporary register into it */
1738 c896fe29 bellard
            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1739 3b6dac34 Richard Henderson
            tcg_out_mov(s, ts->type, reg, ts->reg);
1740 c896fe29 bellard
        }
1741 c896fe29 bellard
        new_args[i] = reg;
1742 c896fe29 bellard
        const_args[i] = 0;
1743 c896fe29 bellard
        tcg_regset_set_reg(allocated_regs, reg);
1744 c896fe29 bellard
    iarg_end: ;
1745 c896fe29 bellard
    }
1746 c896fe29 bellard
    
1747 e8996ee0 bellard
    if (def->flags & TCG_OPF_BB_END) {
1748 e8996ee0 bellard
        tcg_reg_alloc_bb_end(s, allocated_regs);
1749 e8996ee0 bellard
    } else {
1750 e8996ee0 bellard
        /* mark dead temporaries and free the associated registers */
1751 866cb6cb Aurelien Jarno
        for(i = nb_oargs; i < nb_oargs + nb_iargs; i++) {
1752 866cb6cb Aurelien Jarno
            arg = args[i];
1753 866cb6cb Aurelien Jarno
            if (IS_DEAD_ARG(i)) {
1754 e8996ee0 bellard
                ts = &s->temps[arg];
1755 e8996ee0 bellard
                if (!ts->fixed_reg) {
1756 e8996ee0 bellard
                    if (ts->val_type == TEMP_VAL_REG)
1757 e8996ee0 bellard
                        s->reg_to_temp[ts->reg] = -1;
1758 e8996ee0 bellard
                    ts->val_type = TEMP_VAL_DEAD;
1759 e8996ee0 bellard
                }
1760 c896fe29 bellard
            }
1761 c896fe29 bellard
        }
1762 e8996ee0 bellard
        
1763 e8996ee0 bellard
        if (def->flags & TCG_OPF_CALL_CLOBBER) {
1764 e8996ee0 bellard
            /* XXX: permit generic clobber register list ? */ 
1765 e8996ee0 bellard
            for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1766 e8996ee0 bellard
                if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
1767 e8996ee0 bellard
                    tcg_reg_free(s, reg);
1768 e8996ee0 bellard
                }
1769 c896fe29 bellard
            }
1770 e8996ee0 bellard
            /* XXX: for load/store we could do that only for the slow path
1771 e8996ee0 bellard
               (i.e. when a memory callback is called) */
1772 e8996ee0 bellard
            
1773 e8996ee0 bellard
            /* store globals and free associated registers (we assume the insn
1774 e8996ee0 bellard
               can modify any global. */
1775 e8996ee0 bellard
            save_globals(s, allocated_regs);
1776 c896fe29 bellard
        }
1777 e8996ee0 bellard
        
1778 e8996ee0 bellard
        /* satisfy the output constraints */
1779 e8996ee0 bellard
        tcg_regset_set(allocated_regs, s->reserved_regs);
1780 e8996ee0 bellard
        for(k = 0; k < nb_oargs; k++) {
1781 e8996ee0 bellard
            i = def->sorted_args[k];
1782 e8996ee0 bellard
            arg = args[i];
1783 e8996ee0 bellard
            arg_ct = &def->args_ct[i];
1784 e8996ee0 bellard
            ts = &s->temps[arg];
1785 e8996ee0 bellard
            if (arg_ct->ct & TCG_CT_ALIAS) {
1786 e8996ee0 bellard
                reg = new_args[arg_ct->alias_index];
1787 e8996ee0 bellard
            } else {
1788 e8996ee0 bellard
                /* if fixed register, we try to use it */
1789 e8996ee0 bellard
                reg = ts->reg;
1790 e8996ee0 bellard
                if (ts->fixed_reg &&
1791 e8996ee0 bellard
                    tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1792 e8996ee0 bellard
                    goto oarg_end;
1793 e8996ee0 bellard
                }
1794 e8996ee0 bellard
                reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1795 c896fe29 bellard
            }
1796 e8996ee0 bellard
            tcg_regset_set_reg(allocated_regs, reg);
1797 e8996ee0 bellard
            /* if a fixed register is used, then a move will be done afterwards */
1798 e8996ee0 bellard
            if (!ts->fixed_reg) {
1799 e8996ee0 bellard
                if (ts->val_type == TEMP_VAL_REG)
1800 e8996ee0 bellard
                    s->reg_to_temp[ts->reg] = -1;
1801 8c11ad25 Aurelien Jarno
                if (IS_DEAD_ARG(i)) {
1802 8c11ad25 Aurelien Jarno
                    ts->val_type = TEMP_VAL_DEAD;
1803 8c11ad25 Aurelien Jarno
                } else {
1804 8c11ad25 Aurelien Jarno
                    ts->val_type = TEMP_VAL_REG;
1805 8c11ad25 Aurelien Jarno
                    ts->reg = reg;
1806 8c11ad25 Aurelien Jarno
                    /* temp value is modified, so the value kept in memory is
1807 8c11ad25 Aurelien Jarno
                       potentially not the same */
1808 8c11ad25 Aurelien Jarno
                    ts->mem_coherent = 0;
1809 8c11ad25 Aurelien Jarno
                    s->reg_to_temp[reg] = arg;
1810 8c11ad25 Aurelien Jarno
               }
1811 e8996ee0 bellard
            }
1812 e8996ee0 bellard
        oarg_end:
1813 e8996ee0 bellard
            new_args[i] = reg;
1814 c896fe29 bellard
        }
1815 c896fe29 bellard
    }
1816 c896fe29 bellard
1817 c896fe29 bellard
    /* emit instruction */
1818 c896fe29 bellard
    tcg_out_op(s, opc, new_args, const_args);
1819 c896fe29 bellard
    
1820 c896fe29 bellard
    /* move the outputs in the correct register if needed */
1821 c896fe29 bellard
    for(i = 0; i < nb_oargs; i++) {
1822 c896fe29 bellard
        ts = &s->temps[args[i]];
1823 c896fe29 bellard
        reg = new_args[i];
1824 c896fe29 bellard
        if (ts->fixed_reg && ts->reg != reg) {
1825 3b6dac34 Richard Henderson
            tcg_out_mov(s, ts->type, ts->reg, reg);
1826 c896fe29 bellard
        }
1827 c896fe29 bellard
    }
1828 c896fe29 bellard
}
1829 c896fe29 bellard
1830 b03cce8e bellard
#ifdef TCG_TARGET_STACK_GROWSUP
1831 b03cce8e bellard
#define STACK_DIR(x) (-(x))
1832 b03cce8e bellard
#else
1833 b03cce8e bellard
#define STACK_DIR(x) (x)
1834 b03cce8e bellard
#endif
1835 b03cce8e bellard
1836 c896fe29 bellard
static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
1837 a9751609 Richard Henderson
                              TCGOpcode opc, const TCGArg *args,
1838 866cb6cb Aurelien Jarno
                              unsigned int dead_args)
1839 c896fe29 bellard
{
1840 c896fe29 bellard
    int nb_iargs, nb_oargs, flags, nb_regs, i, reg, nb_params;
1841 c896fe29 bellard
    TCGArg arg, func_arg;
1842 c896fe29 bellard
    TCGTemp *ts;
1843 f54b3f92 aurel32
    tcg_target_long stack_offset, call_stack_size, func_addr;
1844 b03cce8e bellard
    int const_func_arg, allocate_args;
1845 c896fe29 bellard
    TCGRegSet allocated_regs;
1846 c896fe29 bellard
    const TCGArgConstraint *arg_ct;
1847 c896fe29 bellard
1848 c896fe29 bellard
    arg = *args++;
1849 c896fe29 bellard
1850 c896fe29 bellard
    nb_oargs = arg >> 16;
1851 c896fe29 bellard
    nb_iargs = arg & 0xffff;
1852 c896fe29 bellard
    nb_params = nb_iargs - 1;
1853 c896fe29 bellard
1854 c896fe29 bellard
    flags = args[nb_oargs + nb_iargs];
1855 c896fe29 bellard
1856 c896fe29 bellard
    nb_regs = tcg_target_get_call_iarg_regs_count(flags);
1857 c896fe29 bellard
    if (nb_regs > nb_params)
1858 c896fe29 bellard
        nb_regs = nb_params;
1859 c896fe29 bellard
1860 c896fe29 bellard
    /* assign stack slots first */
1861 c896fe29 bellard
    call_stack_size = (nb_params - nb_regs) * sizeof(tcg_target_long);
1862 c896fe29 bellard
    call_stack_size = (call_stack_size + TCG_TARGET_STACK_ALIGN - 1) & 
1863 c896fe29 bellard
        ~(TCG_TARGET_STACK_ALIGN - 1);
1864 b03cce8e bellard
    allocate_args = (call_stack_size > TCG_STATIC_CALL_ARGS_SIZE);
1865 b03cce8e bellard
    if (allocate_args) {
1866 345649c0 Blue Swirl
        /* XXX: if more than TCG_STATIC_CALL_ARGS_SIZE is needed,
1867 345649c0 Blue Swirl
           preallocate call stack */
1868 345649c0 Blue Swirl
        tcg_abort();
1869 b03cce8e bellard
    }
1870 39cf05d3 bellard
1871 39cf05d3 bellard
    stack_offset = TCG_TARGET_CALL_STACK_OFFSET;
1872 c896fe29 bellard
    for(i = nb_regs; i < nb_params; i++) {
1873 c896fe29 bellard
        arg = args[nb_oargs + i];
1874 39cf05d3 bellard
#ifdef TCG_TARGET_STACK_GROWSUP
1875 39cf05d3 bellard
        stack_offset -= sizeof(tcg_target_long);
1876 39cf05d3 bellard
#endif
1877 39cf05d3 bellard
        if (arg != TCG_CALL_DUMMY_ARG) {
1878 39cf05d3 bellard
            ts = &s->temps[arg];
1879 39cf05d3 bellard
            if (ts->val_type == TEMP_VAL_REG) {
1880 39cf05d3 bellard
                tcg_out_st(s, ts->type, ts->reg, TCG_REG_CALL_STACK, stack_offset);
1881 39cf05d3 bellard
            } else if (ts->val_type == TEMP_VAL_MEM) {
1882 39cf05d3 bellard
                reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], 
1883 39cf05d3 bellard
                                    s->reserved_regs);
1884 39cf05d3 bellard
                /* XXX: not correct if reading values from the stack */
1885 39cf05d3 bellard
                tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1886 39cf05d3 bellard
                tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
1887 39cf05d3 bellard
            } else if (ts->val_type == TEMP_VAL_CONST) {
1888 39cf05d3 bellard
                reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], 
1889 39cf05d3 bellard
                                    s->reserved_regs);
1890 39cf05d3 bellard
                /* XXX: sign extend may be needed on some targets */
1891 39cf05d3 bellard
                tcg_out_movi(s, ts->type, reg, ts->val);
1892 39cf05d3 bellard
                tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
1893 39cf05d3 bellard
            } else {
1894 39cf05d3 bellard
                tcg_abort();
1895 39cf05d3 bellard
            }
1896 c896fe29 bellard
        }
1897 39cf05d3 bellard
#ifndef TCG_TARGET_STACK_GROWSUP
1898 39cf05d3 bellard
        stack_offset += sizeof(tcg_target_long);
1899 39cf05d3 bellard
#endif
1900 c896fe29 bellard
    }
1901 c896fe29 bellard
    
1902 c896fe29 bellard
    /* assign input registers */
1903 c896fe29 bellard
    tcg_regset_set(allocated_regs, s->reserved_regs);
1904 c896fe29 bellard
    for(i = 0; i < nb_regs; i++) {
1905 c896fe29 bellard
        arg = args[nb_oargs + i];
1906 39cf05d3 bellard
        if (arg != TCG_CALL_DUMMY_ARG) {
1907 39cf05d3 bellard
            ts = &s->temps[arg];
1908 39cf05d3 bellard
            reg = tcg_target_call_iarg_regs[i];
1909 39cf05d3 bellard
            tcg_reg_free(s, reg);
1910 39cf05d3 bellard
            if (ts->val_type == TEMP_VAL_REG) {
1911 39cf05d3 bellard
                if (ts->reg != reg) {
1912 3b6dac34 Richard Henderson
                    tcg_out_mov(s, ts->type, reg, ts->reg);
1913 39cf05d3 bellard
                }
1914 39cf05d3 bellard
            } else if (ts->val_type == TEMP_VAL_MEM) {
1915 39cf05d3 bellard
                tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1916 39cf05d3 bellard
            } else if (ts->val_type == TEMP_VAL_CONST) {
1917 39cf05d3 bellard
                /* XXX: sign extend ? */
1918 39cf05d3 bellard
                tcg_out_movi(s, ts->type, reg, ts->val);
1919 39cf05d3 bellard
            } else {
1920 39cf05d3 bellard
                tcg_abort();
1921 c896fe29 bellard
            }
1922 39cf05d3 bellard
            tcg_regset_set_reg(allocated_regs, reg);
1923 c896fe29 bellard
        }
1924 c896fe29 bellard
    }
1925 c896fe29 bellard
    
1926 c896fe29 bellard
    /* assign function address */
1927 c896fe29 bellard
    func_arg = args[nb_oargs + nb_iargs - 1];
1928 c896fe29 bellard
    arg_ct = &def->args_ct[0];
1929 c896fe29 bellard
    ts = &s->temps[func_arg];
1930 f54b3f92 aurel32
    func_addr = ts->val;
1931 c896fe29 bellard
    const_func_arg = 0;
1932 c896fe29 bellard
    if (ts->val_type == TEMP_VAL_MEM) {
1933 c896fe29 bellard
        reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1934 e4d5434c blueswir1
        tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1935 c896fe29 bellard
        func_arg = reg;
1936 e8996ee0 bellard
        tcg_regset_set_reg(allocated_regs, reg);
1937 c896fe29 bellard
    } else if (ts->val_type == TEMP_VAL_REG) {
1938 c896fe29 bellard
        reg = ts->reg;
1939 c896fe29 bellard
        if (!tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1940 c896fe29 bellard
            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1941 3b6dac34 Richard Henderson
            tcg_out_mov(s, ts->type, reg, ts->reg);
1942 c896fe29 bellard
        }
1943 c896fe29 bellard
        func_arg = reg;
1944 e8996ee0 bellard
        tcg_regset_set_reg(allocated_regs, reg);
1945 c896fe29 bellard
    } else if (ts->val_type == TEMP_VAL_CONST) {
1946 f54b3f92 aurel32
        if (tcg_target_const_match(func_addr, arg_ct)) {
1947 c896fe29 bellard
            const_func_arg = 1;
1948 f54b3f92 aurel32
            func_arg = func_addr;
1949 c896fe29 bellard
        } else {
1950 c896fe29 bellard
            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1951 f54b3f92 aurel32
            tcg_out_movi(s, ts->type, reg, func_addr);
1952 c896fe29 bellard
            func_arg = reg;
1953 e8996ee0 bellard
            tcg_regset_set_reg(allocated_regs, reg);
1954 c896fe29 bellard
        }
1955 c896fe29 bellard
    } else {
1956 c896fe29 bellard
        tcg_abort();
1957 c896fe29 bellard
    }
1958 e8996ee0 bellard
        
1959 c896fe29 bellard
    
1960 c896fe29 bellard
    /* mark dead temporaries and free the associated registers */
1961 866cb6cb Aurelien Jarno
    for(i = nb_oargs; i < nb_iargs + nb_oargs; i++) {
1962 866cb6cb Aurelien Jarno
        arg = args[i];
1963 866cb6cb Aurelien Jarno
        if (IS_DEAD_ARG(i)) {
1964 c896fe29 bellard
            ts = &s->temps[arg];
1965 e8996ee0 bellard
            if (!ts->fixed_reg) {
1966 c896fe29 bellard
                if (ts->val_type == TEMP_VAL_REG)
1967 c896fe29 bellard
                    s->reg_to_temp[ts->reg] = -1;
1968 c896fe29 bellard
                ts->val_type = TEMP_VAL_DEAD;
1969 c896fe29 bellard
            }
1970 c896fe29 bellard
        }
1971 c896fe29 bellard
    }
1972 c896fe29 bellard
    
1973 c896fe29 bellard
    /* clobber call registers */
1974 c896fe29 bellard
    for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1975 c896fe29 bellard
        if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
1976 c896fe29 bellard
            tcg_reg_free(s, reg);
1977 c896fe29 bellard
        }
1978 c896fe29 bellard
    }
1979 c896fe29 bellard
    
1980 c896fe29 bellard
    /* store globals and free associated registers (we assume the call
1981 c896fe29 bellard
       can modify any global. */
1982 b9c18f56 aurel32
    if (!(flags & TCG_CALL_CONST)) {
1983 b9c18f56 aurel32
        save_globals(s, allocated_regs);
1984 b9c18f56 aurel32
    }
1985 c896fe29 bellard
1986 c896fe29 bellard
    tcg_out_op(s, opc, &func_arg, &const_func_arg);
1987 c896fe29 bellard
1988 c896fe29 bellard
    /* assign output registers and emit moves if needed */
1989 c896fe29 bellard
    for(i = 0; i < nb_oargs; i++) {
1990 c896fe29 bellard
        arg = args[i];
1991 c896fe29 bellard
        ts = &s->temps[arg];
1992 c896fe29 bellard
        reg = tcg_target_call_oarg_regs[i];
1993 e8996ee0 bellard
        assert(s->reg_to_temp[reg] == -1);
1994 c896fe29 bellard
        if (ts->fixed_reg) {
1995 c896fe29 bellard
            if (ts->reg != reg) {
1996 3b6dac34 Richard Henderson
                tcg_out_mov(s, ts->type, ts->reg, reg);
1997 c896fe29 bellard
            }
1998 c896fe29 bellard
        } else {
1999 c896fe29 bellard
            if (ts->val_type == TEMP_VAL_REG)
2000 c896fe29 bellard
                s->reg_to_temp[ts->reg] = -1;
2001 8c11ad25 Aurelien Jarno
            if (IS_DEAD_ARG(i)) {
2002 8c11ad25 Aurelien Jarno
                ts->val_type = TEMP_VAL_DEAD;
2003 8c11ad25 Aurelien Jarno
            } else {
2004 8c11ad25 Aurelien Jarno
                ts->val_type = TEMP_VAL_REG;
2005 8c11ad25 Aurelien Jarno
                ts->reg = reg;
2006 8c11ad25 Aurelien Jarno
                ts->mem_coherent = 0;
2007 8c11ad25 Aurelien Jarno
                s->reg_to_temp[reg] = arg;
2008 8c11ad25 Aurelien Jarno
            }
2009 c896fe29 bellard
        }
2010 c896fe29 bellard
    }
2011 c896fe29 bellard
    
2012 c896fe29 bellard
    return nb_iargs + nb_oargs + def->nb_cargs + 1;
2013 c896fe29 bellard
}
2014 c896fe29 bellard
2015 c896fe29 bellard
#ifdef CONFIG_PROFILER
2016 c896fe29 bellard
2017 54604f74 aurel32
static int64_t tcg_table_op_count[NB_OPS];
2018 c896fe29 bellard
2019 871e6c35 Blue Swirl
static void dump_op_count(void)
2020 c896fe29 bellard
{
2021 c896fe29 bellard
    int i;
2022 c896fe29 bellard
    FILE *f;
2023 54604f74 aurel32
    f = fopen("/tmp/op.log", "w");
2024 c896fe29 bellard
    for(i = INDEX_op_end; i < NB_OPS; i++) {
2025 54604f74 aurel32
        fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name, tcg_table_op_count[i]);
2026 c896fe29 bellard
    }
2027 c896fe29 bellard
    fclose(f);
2028 c896fe29 bellard
}
2029 c896fe29 bellard
#endif
2030 c896fe29 bellard
2031 c896fe29 bellard
2032 c896fe29 bellard
static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
2033 2ba1eeb6 pbrook
                                      long search_pc)
2034 c896fe29 bellard
{
2035 a9751609 Richard Henderson
    TCGOpcode opc;
2036 a9751609 Richard Henderson
    int op_index;
2037 c896fe29 bellard
    const TCGOpDef *def;
2038 866cb6cb Aurelien Jarno
    unsigned int dead_args;
2039 c896fe29 bellard
    const TCGArg *args;
2040 c896fe29 bellard
2041 c896fe29 bellard
#ifdef DEBUG_DISAS
2042 8fec2b8c aliguori
    if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
2043 93fcfe39 aliguori
        qemu_log("OP:\n");
2044 eeacee4d Blue Swirl
        tcg_dump_ops(s);
2045 93fcfe39 aliguori
        qemu_log("\n");
2046 c896fe29 bellard
    }
2047 c896fe29 bellard
#endif
2048 c896fe29 bellard
2049 c5cc28ff Aurelien Jarno
#ifdef CONFIG_PROFILER
2050 c5cc28ff Aurelien Jarno
    s->opt_time -= profile_getclock();
2051 c5cc28ff Aurelien Jarno
#endif
2052 c5cc28ff Aurelien Jarno
2053 8f2e8c07 Kirill Batuzov
#ifdef USE_TCG_OPTIMIZATIONS
2054 8f2e8c07 Kirill Batuzov
    gen_opparam_ptr =
2055 8f2e8c07 Kirill Batuzov
        tcg_optimize(s, gen_opc_ptr, gen_opparam_buf, tcg_op_defs);
2056 8f2e8c07 Kirill Batuzov
#endif
2057 8f2e8c07 Kirill Batuzov
2058 a23a9ec6 bellard
#ifdef CONFIG_PROFILER
2059 c5cc28ff Aurelien Jarno
    s->opt_time += profile_getclock();
2060 a23a9ec6 bellard
    s->la_time -= profile_getclock();
2061 a23a9ec6 bellard
#endif
2062 c5cc28ff Aurelien Jarno
2063 c896fe29 bellard
    tcg_liveness_analysis(s);
2064 c5cc28ff Aurelien Jarno
2065 a23a9ec6 bellard
#ifdef CONFIG_PROFILER
2066 a23a9ec6 bellard
    s->la_time += profile_getclock();
2067 a23a9ec6 bellard
#endif
2068 c896fe29 bellard
2069 c896fe29 bellard
#ifdef DEBUG_DISAS
2070 8fec2b8c aliguori
    if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_OPT))) {
2071 c5cc28ff Aurelien Jarno
        qemu_log("OP after optimization and liveness analysis:\n");
2072 eeacee4d Blue Swirl
        tcg_dump_ops(s);
2073 93fcfe39 aliguori
        qemu_log("\n");
2074 c896fe29 bellard
    }
2075 c896fe29 bellard
#endif
2076 c896fe29 bellard
2077 c896fe29 bellard
    tcg_reg_alloc_start(s);
2078 c896fe29 bellard
2079 c896fe29 bellard
    s->code_buf = gen_code_buf;
2080 c896fe29 bellard
    s->code_ptr = gen_code_buf;
2081 c896fe29 bellard
2082 c896fe29 bellard
    args = gen_opparam_buf;
2083 c896fe29 bellard
    op_index = 0;
2084 b3db8758 blueswir1
2085 c896fe29 bellard
    for(;;) {
2086 c896fe29 bellard
        opc = gen_opc_buf[op_index];
2087 c896fe29 bellard
#ifdef CONFIG_PROFILER
2088 54604f74 aurel32
        tcg_table_op_count[opc]++;
2089 c896fe29 bellard
#endif
2090 c896fe29 bellard
        def = &tcg_op_defs[opc];
2091 c896fe29 bellard
#if 0
2092 c896fe29 bellard
        printf("%s: %d %d %d\n", def->name,
2093 c896fe29 bellard
               def->nb_oargs, def->nb_iargs, def->nb_cargs);
2094 c896fe29 bellard
        //        dump_regs(s);
2095 c896fe29 bellard
#endif
2096 c896fe29 bellard
        switch(opc) {
2097 c896fe29 bellard
        case INDEX_op_mov_i32:
2098 c896fe29 bellard
        case INDEX_op_mov_i64:
2099 866cb6cb Aurelien Jarno
            dead_args = s->op_dead_args[op_index];
2100 866cb6cb Aurelien Jarno
            tcg_reg_alloc_mov(s, def, args, dead_args);
2101 c896fe29 bellard
            break;
2102 e8996ee0 bellard
        case INDEX_op_movi_i32:
2103 e8996ee0 bellard
        case INDEX_op_movi_i64:
2104 e8996ee0 bellard
            tcg_reg_alloc_movi(s, args);
2105 e8996ee0 bellard
            break;
2106 7e4597d7 bellard
        case INDEX_op_debug_insn_start:
2107 7e4597d7 bellard
            /* debug instruction */
2108 7e4597d7 bellard
            break;
2109 c896fe29 bellard
        case INDEX_op_nop:
2110 c896fe29 bellard
        case INDEX_op_nop1:
2111 c896fe29 bellard
        case INDEX_op_nop2:
2112 c896fe29 bellard
        case INDEX_op_nop3:
2113 c896fe29 bellard
            break;
2114 c896fe29 bellard
        case INDEX_op_nopn:
2115 c896fe29 bellard
            args += args[0];
2116 c896fe29 bellard
            goto next;
2117 5ff9d6a4 bellard
        case INDEX_op_discard:
2118 5ff9d6a4 bellard
            {
2119 5ff9d6a4 bellard
                TCGTemp *ts;
2120 5ff9d6a4 bellard
                ts = &s->temps[args[0]];
2121 5ff9d6a4 bellard
                /* mark the temporary as dead */
2122 e8996ee0 bellard
                if (!ts->fixed_reg) {
2123 5ff9d6a4 bellard
                    if (ts->val_type == TEMP_VAL_REG)
2124 5ff9d6a4 bellard
                        s->reg_to_temp[ts->reg] = -1;
2125 5ff9d6a4 bellard
                    ts->val_type = TEMP_VAL_DEAD;
2126 5ff9d6a4 bellard
                }
2127 5ff9d6a4 bellard
            }
2128 5ff9d6a4 bellard
            break;
2129 c896fe29 bellard
        case INDEX_op_set_label:
2130 e8996ee0 bellard
            tcg_reg_alloc_bb_end(s, s->reserved_regs);
2131 9d6fca70 Stefan Weil
            tcg_out_label(s, args[0], s->code_ptr);
2132 c896fe29 bellard
            break;
2133 c896fe29 bellard
        case INDEX_op_call:
2134 866cb6cb Aurelien Jarno
            dead_args = s->op_dead_args[op_index];
2135 866cb6cb Aurelien Jarno
            args += tcg_reg_alloc_call(s, def, opc, args, dead_args);
2136 c896fe29 bellard
            goto next;
2137 c896fe29 bellard
        case INDEX_op_end:
2138 c896fe29 bellard
            goto the_end;
2139 c896fe29 bellard
        default:
2140 25c4d9cc Richard Henderson
            /* Sanity check that we've not introduced any unhandled opcodes. */
2141 25c4d9cc Richard Henderson
            if (def->flags & TCG_OPF_NOT_PRESENT) {
2142 25c4d9cc Richard Henderson
                tcg_abort();
2143 25c4d9cc Richard Henderson
            }
2144 c896fe29 bellard
            /* Note: in order to speed up the code, it would be much
2145 c896fe29 bellard
               faster to have specialized register allocator functions for
2146 c896fe29 bellard
               some common argument patterns */
2147 866cb6cb Aurelien Jarno
            dead_args = s->op_dead_args[op_index];
2148 866cb6cb Aurelien Jarno
            tcg_reg_alloc_op(s, def, opc, args, dead_args);
2149 c896fe29 bellard
            break;
2150 c896fe29 bellard
        }
2151 c896fe29 bellard
        args += def->nb_args;
2152 8df1ca4b ths
    next:
2153 2ba1eeb6 pbrook
        if (search_pc >= 0 && search_pc < s->code_ptr - gen_code_buf) {
2154 b314f270 bellard
            return op_index;
2155 c896fe29 bellard
        }
2156 c896fe29 bellard
        op_index++;
2157 c896fe29 bellard
#ifndef NDEBUG
2158 c896fe29 bellard
        check_regs(s);
2159 c896fe29 bellard
#endif
2160 c896fe29 bellard
    }
2161 c896fe29 bellard
 the_end:
2162 c896fe29 bellard
    return -1;
2163 c896fe29 bellard
}
2164 c896fe29 bellard
2165 54604f74 aurel32
int tcg_gen_code(TCGContext *s, uint8_t *gen_code_buf)
2166 c896fe29 bellard
{
2167 c896fe29 bellard
#ifdef CONFIG_PROFILER
2168 c896fe29 bellard
    {
2169 c896fe29 bellard
        int n;
2170 c896fe29 bellard
        n = (gen_opc_ptr - gen_opc_buf);
2171 a23a9ec6 bellard
        s->op_count += n;
2172 a23a9ec6 bellard
        if (n > s->op_count_max)
2173 a23a9ec6 bellard
            s->op_count_max = n;
2174 a23a9ec6 bellard
2175 a23a9ec6 bellard
        s->temp_count += s->nb_temps;
2176 a23a9ec6 bellard
        if (s->nb_temps > s->temp_count_max)
2177 a23a9ec6 bellard
            s->temp_count_max = s->nb_temps;
2178 c896fe29 bellard
    }
2179 c896fe29 bellard
#endif
2180 c896fe29 bellard
2181 2ba1eeb6 pbrook
    tcg_gen_code_common(s, gen_code_buf, -1);
2182 c896fe29 bellard
2183 c896fe29 bellard
    /* flush instruction cache */
2184 2aeabc08 Stefan Weil
    flush_icache_range((tcg_target_ulong)gen_code_buf,
2185 2aeabc08 Stefan Weil
                       (tcg_target_ulong)s->code_ptr);
2186 2aeabc08 Stefan Weil
2187 c896fe29 bellard
    return s->code_ptr -  gen_code_buf;
2188 c896fe29 bellard
}
2189 c896fe29 bellard
2190 2ba1eeb6 pbrook
/* Return the index of the micro operation such as the pc after is <
2191 623e265c pbrook
   offset bytes from the start of the TB.  The contents of gen_code_buf must
2192 623e265c pbrook
   not be changed, though writing the same values is ok.
2193 623e265c pbrook
   Return -1 if not found. */
2194 54604f74 aurel32
int tcg_gen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, long offset)
2195 c896fe29 bellard
{
2196 623e265c pbrook
    return tcg_gen_code_common(s, gen_code_buf, offset);
2197 c896fe29 bellard
}
2198 a23a9ec6 bellard
2199 a23a9ec6 bellard
#ifdef CONFIG_PROFILER
2200 405cf9ff Stefan Weil
void tcg_dump_info(FILE *f, fprintf_function cpu_fprintf)
2201 a23a9ec6 bellard
{
2202 a23a9ec6 bellard
    TCGContext *s = &tcg_ctx;
2203 a23a9ec6 bellard
    int64_t tot;
2204 a23a9ec6 bellard
2205 a23a9ec6 bellard
    tot = s->interm_time + s->code_time;
2206 a23a9ec6 bellard
    cpu_fprintf(f, "JIT cycles          %" PRId64 " (%0.3f s at 2.4 GHz)\n",
2207 a23a9ec6 bellard
                tot, tot / 2.4e9);
2208 a23a9ec6 bellard
    cpu_fprintf(f, "translated TBs      %" PRId64 " (aborted=%" PRId64 " %0.1f%%)\n", 
2209 a23a9ec6 bellard
                s->tb_count, 
2210 a23a9ec6 bellard
                s->tb_count1 - s->tb_count,
2211 a23a9ec6 bellard
                s->tb_count1 ? (double)(s->tb_count1 - s->tb_count) / s->tb_count1 * 100.0 : 0);
2212 a23a9ec6 bellard
    cpu_fprintf(f, "avg ops/TB          %0.1f max=%d\n", 
2213 a23a9ec6 bellard
                s->tb_count ? (double)s->op_count / s->tb_count : 0, s->op_count_max);
2214 a23a9ec6 bellard
    cpu_fprintf(f, "deleted ops/TB      %0.2f\n",
2215 a23a9ec6 bellard
                s->tb_count ? 
2216 a23a9ec6 bellard
                (double)s->del_op_count / s->tb_count : 0);
2217 a23a9ec6 bellard
    cpu_fprintf(f, "avg temps/TB        %0.2f max=%d\n",
2218 a23a9ec6 bellard
                s->tb_count ? 
2219 a23a9ec6 bellard
                (double)s->temp_count / s->tb_count : 0,
2220 a23a9ec6 bellard
                s->temp_count_max);
2221 a23a9ec6 bellard
    
2222 a23a9ec6 bellard
    cpu_fprintf(f, "cycles/op           %0.1f\n", 
2223 a23a9ec6 bellard
                s->op_count ? (double)tot / s->op_count : 0);
2224 a23a9ec6 bellard
    cpu_fprintf(f, "cycles/in byte      %0.1f\n", 
2225 a23a9ec6 bellard
                s->code_in_len ? (double)tot / s->code_in_len : 0);
2226 a23a9ec6 bellard
    cpu_fprintf(f, "cycles/out byte     %0.1f\n", 
2227 a23a9ec6 bellard
                s->code_out_len ? (double)tot / s->code_out_len : 0);
2228 a23a9ec6 bellard
    if (tot == 0)
2229 a23a9ec6 bellard
        tot = 1;
2230 a23a9ec6 bellard
    cpu_fprintf(f, "  gen_interm time   %0.1f%%\n", 
2231 a23a9ec6 bellard
                (double)s->interm_time / tot * 100.0);
2232 a23a9ec6 bellard
    cpu_fprintf(f, "  gen_code time     %0.1f%%\n", 
2233 a23a9ec6 bellard
                (double)s->code_time / tot * 100.0);
2234 c5cc28ff Aurelien Jarno
    cpu_fprintf(f, "optim./code time    %0.1f%%\n",
2235 c5cc28ff Aurelien Jarno
                (double)s->opt_time / (s->code_time ? s->code_time : 1)
2236 c5cc28ff Aurelien Jarno
                * 100.0);
2237 a23a9ec6 bellard
    cpu_fprintf(f, "liveness/code time  %0.1f%%\n", 
2238 a23a9ec6 bellard
                (double)s->la_time / (s->code_time ? s->code_time : 1) * 100.0);
2239 a23a9ec6 bellard
    cpu_fprintf(f, "cpu_restore count   %" PRId64 "\n",
2240 a23a9ec6 bellard
                s->restore_count);
2241 a23a9ec6 bellard
    cpu_fprintf(f, "  avg cycles        %0.1f\n",
2242 a23a9ec6 bellard
                s->restore_count ? (double)s->restore_time / s->restore_count : 0);
2243 871e6c35 Blue Swirl
2244 871e6c35 Blue Swirl
    dump_op_count();
2245 a23a9ec6 bellard
}
2246 a23a9ec6 bellard
#else
2247 405cf9ff Stefan Weil
void tcg_dump_info(FILE *f, fprintf_function cpu_fprintf)
2248 a23a9ec6 bellard
{
2249 24bf7b3a bellard
    cpu_fprintf(f, "[TCG profiler not compiled]\n");
2250 a23a9ec6 bellard
}
2251 a23a9ec6 bellard
#endif
2252 813da627 Richard Henderson
2253 813da627 Richard Henderson
#ifdef ELF_HOST_MACHINE
2254 5872bbf2 Richard Henderson
/* In order to use this feature, the backend needs to do three things:
2255 5872bbf2 Richard Henderson

2256 5872bbf2 Richard Henderson
   (1) Define ELF_HOST_MACHINE to indicate both what value to
2257 5872bbf2 Richard Henderson
       put into the ELF image and to indicate support for the feature.
2258 5872bbf2 Richard Henderson

2259 5872bbf2 Richard Henderson
   (2) Define tcg_register_jit.  This should create a buffer containing
2260 5872bbf2 Richard Henderson
       the contents of a .debug_frame section that describes the post-
2261 5872bbf2 Richard Henderson
       prologue unwind info for the tcg machine.
2262 5872bbf2 Richard Henderson

2263 5872bbf2 Richard Henderson
   (3) Call tcg_register_jit_int, with the constructed .debug_frame.
2264 5872bbf2 Richard Henderson
*/
2265 813da627 Richard Henderson
2266 813da627 Richard Henderson
/* Begin GDB interface.  THE FOLLOWING MUST MATCH GDB DOCS.  */
2267 813da627 Richard Henderson
typedef enum {
2268 813da627 Richard Henderson
    JIT_NOACTION = 0,
2269 813da627 Richard Henderson
    JIT_REGISTER_FN,
2270 813da627 Richard Henderson
    JIT_UNREGISTER_FN
2271 813da627 Richard Henderson
} jit_actions_t;
2272 813da627 Richard Henderson
2273 813da627 Richard Henderson
struct jit_code_entry {
2274 813da627 Richard Henderson
    struct jit_code_entry *next_entry;
2275 813da627 Richard Henderson
    struct jit_code_entry *prev_entry;
2276 813da627 Richard Henderson
    const void *symfile_addr;
2277 813da627 Richard Henderson
    uint64_t symfile_size;
2278 813da627 Richard Henderson
};
2279 813da627 Richard Henderson
2280 813da627 Richard Henderson
struct jit_descriptor {
2281 813da627 Richard Henderson
    uint32_t version;
2282 813da627 Richard Henderson
    uint32_t action_flag;
2283 813da627 Richard Henderson
    struct jit_code_entry *relevant_entry;
2284 813da627 Richard Henderson
    struct jit_code_entry *first_entry;
2285 813da627 Richard Henderson
};
2286 813da627 Richard Henderson
2287 813da627 Richard Henderson
void __jit_debug_register_code(void) __attribute__((noinline));
2288 813da627 Richard Henderson
void __jit_debug_register_code(void)
2289 813da627 Richard Henderson
{
2290 813da627 Richard Henderson
    asm("");
2291 813da627 Richard Henderson
}
2292 813da627 Richard Henderson
2293 813da627 Richard Henderson
/* Must statically initialize the version, because GDB may check
2294 813da627 Richard Henderson
   the version before we can set it.  */
2295 813da627 Richard Henderson
struct jit_descriptor __jit_debug_descriptor = { 1, 0, 0, 0 };
2296 813da627 Richard Henderson
2297 813da627 Richard Henderson
/* End GDB interface.  */
2298 813da627 Richard Henderson
2299 813da627 Richard Henderson
static int find_string(const char *strtab, const char *str)
2300 813da627 Richard Henderson
{
2301 813da627 Richard Henderson
    const char *p = strtab + 1;
2302 813da627 Richard Henderson
2303 813da627 Richard Henderson
    while (1) {
2304 813da627 Richard Henderson
        if (strcmp(p, str) == 0) {
2305 813da627 Richard Henderson
            return p - strtab;
2306 813da627 Richard Henderson
        }
2307 813da627 Richard Henderson
        p += strlen(p) + 1;
2308 813da627 Richard Henderson
    }
2309 813da627 Richard Henderson
}
2310 813da627 Richard Henderson
2311 5872bbf2 Richard Henderson
static void tcg_register_jit_int(void *buf_ptr, size_t buf_size,
2312 813da627 Richard Henderson
                                 void *debug_frame, size_t debug_frame_size)
2313 813da627 Richard Henderson
{
2314 5872bbf2 Richard Henderson
    struct __attribute__((packed)) DebugInfo {
2315 5872bbf2 Richard Henderson
        uint32_t  len;
2316 5872bbf2 Richard Henderson
        uint16_t  version;
2317 5872bbf2 Richard Henderson
        uint32_t  abbrev;
2318 5872bbf2 Richard Henderson
        uint8_t   ptr_size;
2319 5872bbf2 Richard Henderson
        uint8_t   cu_die;
2320 5872bbf2 Richard Henderson
        uint16_t  cu_lang;
2321 5872bbf2 Richard Henderson
        uintptr_t cu_low_pc;
2322 5872bbf2 Richard Henderson
        uintptr_t cu_high_pc;
2323 5872bbf2 Richard Henderson
        uint8_t   fn_die;
2324 5872bbf2 Richard Henderson
        char      fn_name[16];
2325 5872bbf2 Richard Henderson
        uintptr_t fn_low_pc;
2326 5872bbf2 Richard Henderson
        uintptr_t fn_high_pc;
2327 5872bbf2 Richard Henderson
        uint8_t   cu_eoc;
2328 5872bbf2 Richard Henderson
    };
2329 813da627 Richard Henderson
2330 813da627 Richard Henderson
    struct ElfImage {
2331 813da627 Richard Henderson
        ElfW(Ehdr) ehdr;
2332 813da627 Richard Henderson
        ElfW(Phdr) phdr;
2333 5872bbf2 Richard Henderson
        ElfW(Shdr) shdr[7];
2334 5872bbf2 Richard Henderson
        ElfW(Sym)  sym[2];
2335 5872bbf2 Richard Henderson
        struct DebugInfo di;
2336 5872bbf2 Richard Henderson
        uint8_t    da[24];
2337 5872bbf2 Richard Henderson
        char       str[80];
2338 5872bbf2 Richard Henderson
    };
2339 5872bbf2 Richard Henderson
2340 5872bbf2 Richard Henderson
    struct ElfImage *img;
2341 5872bbf2 Richard Henderson
2342 5872bbf2 Richard Henderson
    static const struct ElfImage img_template = {
2343 5872bbf2 Richard Henderson
        .ehdr = {
2344 5872bbf2 Richard Henderson
            .e_ident[EI_MAG0] = ELFMAG0,
2345 5872bbf2 Richard Henderson
            .e_ident[EI_MAG1] = ELFMAG1,
2346 5872bbf2 Richard Henderson
            .e_ident[EI_MAG2] = ELFMAG2,
2347 5872bbf2 Richard Henderson
            .e_ident[EI_MAG3] = ELFMAG3,
2348 5872bbf2 Richard Henderson
            .e_ident[EI_CLASS] = ELF_CLASS,
2349 5872bbf2 Richard Henderson
            .e_ident[EI_DATA] = ELF_DATA,
2350 5872bbf2 Richard Henderson
            .e_ident[EI_VERSION] = EV_CURRENT,
2351 5872bbf2 Richard Henderson
            .e_type = ET_EXEC,
2352 5872bbf2 Richard Henderson
            .e_machine = ELF_HOST_MACHINE,
2353 5872bbf2 Richard Henderson
            .e_version = EV_CURRENT,
2354 5872bbf2 Richard Henderson
            .e_phoff = offsetof(struct ElfImage, phdr),
2355 5872bbf2 Richard Henderson
            .e_shoff = offsetof(struct ElfImage, shdr),
2356 5872bbf2 Richard Henderson
            .e_ehsize = sizeof(ElfW(Shdr)),
2357 5872bbf2 Richard Henderson
            .e_phentsize = sizeof(ElfW(Phdr)),
2358 5872bbf2 Richard Henderson
            .e_phnum = 1,
2359 5872bbf2 Richard Henderson
            .e_shentsize = sizeof(ElfW(Shdr)),
2360 5872bbf2 Richard Henderson
            .e_shnum = ARRAY_SIZE(img->shdr),
2361 5872bbf2 Richard Henderson
            .e_shstrndx = ARRAY_SIZE(img->shdr) - 1,
2362 abbb3eae Richard Henderson
#ifdef ELF_HOST_FLAGS
2363 abbb3eae Richard Henderson
            .e_flags = ELF_HOST_FLAGS,
2364 abbb3eae Richard Henderson
#endif
2365 abbb3eae Richard Henderson
#ifdef ELF_OSABI
2366 abbb3eae Richard Henderson
            .e_ident[EI_OSABI] = ELF_OSABI,
2367 abbb3eae Richard Henderson
#endif
2368 5872bbf2 Richard Henderson
        },
2369 5872bbf2 Richard Henderson
        .phdr = {
2370 5872bbf2 Richard Henderson
            .p_type = PT_LOAD,
2371 5872bbf2 Richard Henderson
            .p_flags = PF_X,
2372 5872bbf2 Richard Henderson
        },
2373 5872bbf2 Richard Henderson
        .shdr = {
2374 5872bbf2 Richard Henderson
            [0] = { .sh_type = SHT_NULL },
2375 5872bbf2 Richard Henderson
            /* Trick: The contents of code_gen_buffer are not present in
2376 5872bbf2 Richard Henderson
               this fake ELF file; that got allocated elsewhere.  Therefore
2377 5872bbf2 Richard Henderson
               we mark .text as SHT_NOBITS (similar to .bss) so that readers
2378 5872bbf2 Richard Henderson
               will not look for contents.  We can record any address.  */
2379 5872bbf2 Richard Henderson
            [1] = { /* .text */
2380 5872bbf2 Richard Henderson
                .sh_type = SHT_NOBITS,
2381 5872bbf2 Richard Henderson
                .sh_flags = SHF_EXECINSTR | SHF_ALLOC,
2382 5872bbf2 Richard Henderson
            },
2383 5872bbf2 Richard Henderson
            [2] = { /* .debug_info */
2384 5872bbf2 Richard Henderson
                .sh_type = SHT_PROGBITS,
2385 5872bbf2 Richard Henderson
                .sh_offset = offsetof(struct ElfImage, di),
2386 5872bbf2 Richard Henderson
                .sh_size = sizeof(struct DebugInfo),
2387 5872bbf2 Richard Henderson
            },
2388 5872bbf2 Richard Henderson
            [3] = { /* .debug_abbrev */
2389 5872bbf2 Richard Henderson
                .sh_type = SHT_PROGBITS,
2390 5872bbf2 Richard Henderson
                .sh_offset = offsetof(struct ElfImage, da),
2391 5872bbf2 Richard Henderson
                .sh_size = sizeof(img->da),
2392 5872bbf2 Richard Henderson
            },
2393 5872bbf2 Richard Henderson
            [4] = { /* .debug_frame */
2394 5872bbf2 Richard Henderson
                .sh_type = SHT_PROGBITS,
2395 5872bbf2 Richard Henderson
                .sh_offset = sizeof(struct ElfImage),
2396 5872bbf2 Richard Henderson
            },
2397 5872bbf2 Richard Henderson
            [5] = { /* .symtab */
2398 5872bbf2 Richard Henderson
                .sh_type = SHT_SYMTAB,
2399 5872bbf2 Richard Henderson
                .sh_offset = offsetof(struct ElfImage, sym),
2400 5872bbf2 Richard Henderson
                .sh_size = sizeof(img->sym),
2401 5872bbf2 Richard Henderson
                .sh_info = 1,
2402 5872bbf2 Richard Henderson
                .sh_link = ARRAY_SIZE(img->shdr) - 1,
2403 5872bbf2 Richard Henderson
                .sh_entsize = sizeof(ElfW(Sym)),
2404 5872bbf2 Richard Henderson
            },
2405 5872bbf2 Richard Henderson
            [6] = { /* .strtab */
2406 5872bbf2 Richard Henderson
                .sh_type = SHT_STRTAB,
2407 5872bbf2 Richard Henderson
                .sh_offset = offsetof(struct ElfImage, str),
2408 5872bbf2 Richard Henderson
                .sh_size = sizeof(img->str),
2409 5872bbf2 Richard Henderson
            }
2410 5872bbf2 Richard Henderson
        },
2411 5872bbf2 Richard Henderson
        .sym = {
2412 5872bbf2 Richard Henderson
            [1] = { /* code_gen_buffer */
2413 5872bbf2 Richard Henderson
                .st_info = ELF_ST_INFO(STB_GLOBAL, STT_FUNC),
2414 5872bbf2 Richard Henderson
                .st_shndx = 1,
2415 5872bbf2 Richard Henderson
            }
2416 5872bbf2 Richard Henderson
        },
2417 5872bbf2 Richard Henderson
        .di = {
2418 5872bbf2 Richard Henderson
            .len = sizeof(struct DebugInfo) - 4,
2419 5872bbf2 Richard Henderson
            .version = 2,
2420 5872bbf2 Richard Henderson
            .ptr_size = sizeof(void *),
2421 5872bbf2 Richard Henderson
            .cu_die = 1,
2422 5872bbf2 Richard Henderson
            .cu_lang = 0x8001,  /* DW_LANG_Mips_Assembler */
2423 5872bbf2 Richard Henderson
            .fn_die = 2,
2424 5872bbf2 Richard Henderson
            .fn_name = "code_gen_buffer"
2425 5872bbf2 Richard Henderson
        },
2426 5872bbf2 Richard Henderson
        .da = {
2427 5872bbf2 Richard Henderson
            1,          /* abbrev number (the cu) */
2428 5872bbf2 Richard Henderson
            0x11, 1,    /* DW_TAG_compile_unit, has children */
2429 5872bbf2 Richard Henderson
            0x13, 0x5,  /* DW_AT_language, DW_FORM_data2 */
2430 5872bbf2 Richard Henderson
            0x11, 0x1,  /* DW_AT_low_pc, DW_FORM_addr */
2431 5872bbf2 Richard Henderson
            0x12, 0x1,  /* DW_AT_high_pc, DW_FORM_addr */
2432 5872bbf2 Richard Henderson
            0, 0,       /* end of abbrev */
2433 5872bbf2 Richard Henderson
            2,          /* abbrev number (the fn) */
2434 5872bbf2 Richard Henderson
            0x2e, 0,    /* DW_TAG_subprogram, no children */
2435 5872bbf2 Richard Henderson
            0x3, 0x8,   /* DW_AT_name, DW_FORM_string */
2436 5872bbf2 Richard Henderson
            0x11, 0x1,  /* DW_AT_low_pc, DW_FORM_addr */
2437 5872bbf2 Richard Henderson
            0x12, 0x1,  /* DW_AT_high_pc, DW_FORM_addr */
2438 5872bbf2 Richard Henderson
            0, 0,       /* end of abbrev */
2439 5872bbf2 Richard Henderson
            0           /* no more abbrev */
2440 5872bbf2 Richard Henderson
        },
2441 5872bbf2 Richard Henderson
        .str = "\0" ".text\0" ".debug_info\0" ".debug_abbrev\0"
2442 5872bbf2 Richard Henderson
               ".debug_frame\0" ".symtab\0" ".strtab\0" "code_gen_buffer",
2443 813da627 Richard Henderson
    };
2444 813da627 Richard Henderson
2445 813da627 Richard Henderson
    /* We only need a single jit entry; statically allocate it.  */
2446 813da627 Richard Henderson
    static struct jit_code_entry one_entry;
2447 813da627 Richard Henderson
2448 5872bbf2 Richard Henderson
    uintptr_t buf = (uintptr_t)buf_ptr;
2449 813da627 Richard Henderson
    size_t img_size = sizeof(struct ElfImage) + debug_frame_size;
2450 813da627 Richard Henderson
2451 5872bbf2 Richard Henderson
    img = g_malloc(img_size);
2452 5872bbf2 Richard Henderson
    *img = img_template;
2453 5872bbf2 Richard Henderson
    memcpy(img + 1, debug_frame, debug_frame_size);
2454 813da627 Richard Henderson
2455 5872bbf2 Richard Henderson
    img->phdr.p_vaddr = buf;
2456 5872bbf2 Richard Henderson
    img->phdr.p_paddr = buf;
2457 5872bbf2 Richard Henderson
    img->phdr.p_memsz = buf_size;
2458 813da627 Richard Henderson
2459 813da627 Richard Henderson
    img->shdr[1].sh_name = find_string(img->str, ".text");
2460 5872bbf2 Richard Henderson
    img->shdr[1].sh_addr = buf;
2461 813da627 Richard Henderson
    img->shdr[1].sh_size = buf_size;
2462 813da627 Richard Henderson
2463 5872bbf2 Richard Henderson
    img->shdr[2].sh_name = find_string(img->str, ".debug_info");
2464 5872bbf2 Richard Henderson
    img->shdr[3].sh_name = find_string(img->str, ".debug_abbrev");
2465 5872bbf2 Richard Henderson
2466 5872bbf2 Richard Henderson
    img->shdr[4].sh_name = find_string(img->str, ".debug_frame");
2467 5872bbf2 Richard Henderson
    img->shdr[4].sh_size = debug_frame_size;
2468 5872bbf2 Richard Henderson
2469 5872bbf2 Richard Henderson
    img->shdr[5].sh_name = find_string(img->str, ".symtab");
2470 5872bbf2 Richard Henderson
    img->shdr[6].sh_name = find_string(img->str, ".strtab");
2471 5872bbf2 Richard Henderson
2472 5872bbf2 Richard Henderson
    img->sym[1].st_name = find_string(img->str, "code_gen_buffer");
2473 5872bbf2 Richard Henderson
    img->sym[1].st_value = buf;
2474 5872bbf2 Richard Henderson
    img->sym[1].st_size = buf_size;
2475 813da627 Richard Henderson
2476 5872bbf2 Richard Henderson
    img->di.cu_low_pc = buf;
2477 5872bbf2 Richard Henderson
    img->di.cu_high_pc = buf_size;
2478 5872bbf2 Richard Henderson
    img->di.fn_low_pc = buf;
2479 5872bbf2 Richard Henderson
    img->di.fn_high_pc = buf_size;
2480 813da627 Richard Henderson
2481 813da627 Richard Henderson
#ifdef DEBUG_JIT
2482 813da627 Richard Henderson
    /* Enable this block to be able to debug the ELF image file creation.
2483 813da627 Richard Henderson
       One can use readelf, objdump, or other inspection utilities.  */
2484 813da627 Richard Henderson
    {
2485 813da627 Richard Henderson
        FILE *f = fopen("/tmp/qemu.jit", "w+b");
2486 813da627 Richard Henderson
        if (f) {
2487 5872bbf2 Richard Henderson
            if (fwrite(img, img_size, 1, f) != img_size) {
2488 813da627 Richard Henderson
                /* Avoid stupid unused return value warning for fwrite.  */
2489 813da627 Richard Henderson
            }
2490 813da627 Richard Henderson
            fclose(f);
2491 813da627 Richard Henderson
        }
2492 813da627 Richard Henderson
    }
2493 813da627 Richard Henderson
#endif
2494 813da627 Richard Henderson
2495 813da627 Richard Henderson
    one_entry.symfile_addr = img;
2496 813da627 Richard Henderson
    one_entry.symfile_size = img_size;
2497 813da627 Richard Henderson
2498 813da627 Richard Henderson
    __jit_debug_descriptor.action_flag = JIT_REGISTER_FN;
2499 813da627 Richard Henderson
    __jit_debug_descriptor.relevant_entry = &one_entry;
2500 813da627 Richard Henderson
    __jit_debug_descriptor.first_entry = &one_entry;
2501 813da627 Richard Henderson
    __jit_debug_register_code();
2502 813da627 Richard Henderson
}
2503 813da627 Richard Henderson
#else
2504 5872bbf2 Richard Henderson
/* No support for the feature.  Provide the entry point expected by exec.c,
2505 5872bbf2 Richard Henderson
   and implement the internal function we declared earlier.  */
2506 813da627 Richard Henderson
2507 813da627 Richard Henderson
static void tcg_register_jit_int(void *buf, size_t size,
2508 813da627 Richard Henderson
                                 void *debug_frame, size_t debug_frame_size)
2509 813da627 Richard Henderson
{
2510 813da627 Richard Henderson
}
2511 813da627 Richard Henderson
2512 813da627 Richard Henderson
void tcg_register_jit(void *buf, size_t buf_size)
2513 813da627 Richard Henderson
{
2514 813da627 Richard Henderson
}
2515 813da627 Richard Henderson
#endif /* ELF_HOST_MACHINE */