Statistics
| Branch: | Revision:

root / tcg / tcg.c @ 814589c4

History | View | Annotate | Download (75.7 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 e8996ee0 bellard
        } else if (c == INDEX_op_movi_i32 
941 e8996ee0 bellard
#if TCG_TARGET_REG_BITS == 64
942 e8996ee0 bellard
                   || c == INDEX_op_movi_i64
943 e8996ee0 bellard
#endif
944 e8996ee0 bellard
                   ) {
945 e8996ee0 bellard
            tcg_target_ulong val;
946 e8996ee0 bellard
            TCGHelperInfo *th;
947 e8996ee0 bellard
948 e8996ee0 bellard
            nb_oargs = def->nb_oargs;
949 e8996ee0 bellard
            nb_iargs = def->nb_iargs;
950 e8996ee0 bellard
            nb_cargs = def->nb_cargs;
951 eeacee4d Blue Swirl
            qemu_log(" %s %s,$", def->name,
952 eeacee4d Blue Swirl
                     tcg_get_arg_str_idx(s, buf, sizeof(buf), args[0]));
953 e8996ee0 bellard
            val = args[1];
954 e8996ee0 bellard
            th = tcg_find_helper(s, val);
955 e8996ee0 bellard
            if (th) {
956 eeacee4d Blue Swirl
                qemu_log("%s", th->name);
957 e8996ee0 bellard
            } else {
958 eeacee4d Blue Swirl
                if (c == INDEX_op_movi_i32) {
959 eeacee4d Blue Swirl
                    qemu_log("0x%x", (uint32_t)val);
960 eeacee4d Blue Swirl
                } else {
961 eeacee4d Blue Swirl
                    qemu_log("0x%" PRIx64 , (uint64_t)val);
962 eeacee4d Blue Swirl
                }
963 e8996ee0 bellard
            }
964 b03cce8e bellard
        } else {
965 eeacee4d Blue Swirl
            qemu_log(" %s ", def->name);
966 b03cce8e bellard
            if (c == INDEX_op_nopn) {
967 b03cce8e bellard
                /* variable number of arguments */
968 b03cce8e bellard
                nb_cargs = *args;
969 b03cce8e bellard
                nb_oargs = 0;
970 b03cce8e bellard
                nb_iargs = 0;
971 b03cce8e bellard
            } else {
972 b03cce8e bellard
                nb_oargs = def->nb_oargs;
973 b03cce8e bellard
                nb_iargs = def->nb_iargs;
974 b03cce8e bellard
                nb_cargs = def->nb_cargs;
975 b03cce8e bellard
            }
976 b03cce8e bellard
            
977 b03cce8e bellard
            k = 0;
978 b03cce8e bellard
            for(i = 0; i < nb_oargs; i++) {
979 eeacee4d Blue Swirl
                if (k != 0) {
980 eeacee4d Blue Swirl
                    qemu_log(",");
981 eeacee4d Blue Swirl
                }
982 eeacee4d Blue Swirl
                qemu_log("%s", tcg_get_arg_str_idx(s, buf, sizeof(buf),
983 eeacee4d Blue Swirl
                                                   args[k++]));
984 b03cce8e bellard
            }
985 b03cce8e bellard
            for(i = 0; i < nb_iargs; i++) {
986 eeacee4d Blue Swirl
                if (k != 0) {
987 eeacee4d Blue Swirl
                    qemu_log(",");
988 eeacee4d Blue Swirl
                }
989 eeacee4d Blue Swirl
                qemu_log("%s", tcg_get_arg_str_idx(s, buf, sizeof(buf),
990 eeacee4d Blue Swirl
                                                   args[k++]));
991 b03cce8e bellard
            }
992 be210acb Richard Henderson
            switch (c) {
993 be210acb Richard Henderson
            case INDEX_op_brcond_i32:
994 be210acb Richard Henderson
#if TCG_TARGET_REG_BITS == 32
995 be210acb Richard Henderson
            case INDEX_op_brcond2_i32:
996 be210acb Richard Henderson
#elif TCG_TARGET_REG_BITS == 64
997 be210acb Richard Henderson
            case INDEX_op_brcond_i64:
998 be210acb Richard Henderson
#endif
999 be210acb Richard Henderson
            case INDEX_op_setcond_i32:
1000 f48f3ede blueswir1
#if TCG_TARGET_REG_BITS == 32
1001 be210acb Richard Henderson
            case INDEX_op_setcond2_i32:
1002 f48f3ede blueswir1
#elif TCG_TARGET_REG_BITS == 64
1003 be210acb Richard Henderson
            case INDEX_op_setcond_i64:
1004 f48f3ede blueswir1
#endif
1005 eeacee4d Blue Swirl
                if (args[k] < ARRAY_SIZE(cond_name) && cond_name[args[k]]) {
1006 eeacee4d Blue Swirl
                    qemu_log(",%s", cond_name[args[k++]]);
1007 eeacee4d Blue Swirl
                } else {
1008 eeacee4d Blue Swirl
                    qemu_log(",$0x%" TCG_PRIlx, args[k++]);
1009 eeacee4d Blue Swirl
                }
1010 f48f3ede blueswir1
                i = 1;
1011 be210acb Richard Henderson
                break;
1012 be210acb Richard Henderson
            default:
1013 f48f3ede blueswir1
                i = 0;
1014 be210acb Richard Henderson
                break;
1015 be210acb Richard Henderson
            }
1016 f48f3ede blueswir1
            for(; i < nb_cargs; i++) {
1017 eeacee4d Blue Swirl
                if (k != 0) {
1018 eeacee4d Blue Swirl
                    qemu_log(",");
1019 eeacee4d Blue Swirl
                }
1020 b03cce8e bellard
                arg = args[k++];
1021 eeacee4d Blue Swirl
                qemu_log("$0x%" TCG_PRIlx, arg);
1022 b03cce8e bellard
            }
1023 c896fe29 bellard
        }
1024 eeacee4d Blue Swirl
        qemu_log("\n");
1025 c896fe29 bellard
        args += nb_iargs + nb_oargs + nb_cargs;
1026 c896fe29 bellard
    }
1027 c896fe29 bellard
}
1028 c896fe29 bellard
1029 c896fe29 bellard
/* we give more priority to constraints with less registers */
1030 c896fe29 bellard
static int get_constraint_priority(const TCGOpDef *def, int k)
1031 c896fe29 bellard
{
1032 c896fe29 bellard
    const TCGArgConstraint *arg_ct;
1033 c896fe29 bellard
1034 c896fe29 bellard
    int i, n;
1035 c896fe29 bellard
    arg_ct = &def->args_ct[k];
1036 c896fe29 bellard
    if (arg_ct->ct & TCG_CT_ALIAS) {
1037 c896fe29 bellard
        /* an alias is equivalent to a single register */
1038 c896fe29 bellard
        n = 1;
1039 c896fe29 bellard
    } else {
1040 c896fe29 bellard
        if (!(arg_ct->ct & TCG_CT_REG))
1041 c896fe29 bellard
            return 0;
1042 c896fe29 bellard
        n = 0;
1043 c896fe29 bellard
        for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
1044 c896fe29 bellard
            if (tcg_regset_test_reg(arg_ct->u.regs, i))
1045 c896fe29 bellard
                n++;
1046 c896fe29 bellard
        }
1047 c896fe29 bellard
    }
1048 c896fe29 bellard
    return TCG_TARGET_NB_REGS - n + 1;
1049 c896fe29 bellard
}
1050 c896fe29 bellard
1051 c896fe29 bellard
/* sort from highest priority to lowest */
1052 c896fe29 bellard
static void sort_constraints(TCGOpDef *def, int start, int n)
1053 c896fe29 bellard
{
1054 c896fe29 bellard
    int i, j, p1, p2, tmp;
1055 c896fe29 bellard
1056 c896fe29 bellard
    for(i = 0; i < n; i++)
1057 c896fe29 bellard
        def->sorted_args[start + i] = start + i;
1058 c896fe29 bellard
    if (n <= 1)
1059 c896fe29 bellard
        return;
1060 c896fe29 bellard
    for(i = 0; i < n - 1; i++) {
1061 c896fe29 bellard
        for(j = i + 1; j < n; j++) {
1062 c896fe29 bellard
            p1 = get_constraint_priority(def, def->sorted_args[start + i]);
1063 c896fe29 bellard
            p2 = get_constraint_priority(def, def->sorted_args[start + j]);
1064 c896fe29 bellard
            if (p1 < p2) {
1065 c896fe29 bellard
                tmp = def->sorted_args[start + i];
1066 c896fe29 bellard
                def->sorted_args[start + i] = def->sorted_args[start + j];
1067 c896fe29 bellard
                def->sorted_args[start + j] = tmp;
1068 c896fe29 bellard
            }
1069 c896fe29 bellard
        }
1070 c896fe29 bellard
    }
1071 c896fe29 bellard
}
1072 c896fe29 bellard
1073 c896fe29 bellard
void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs)
1074 c896fe29 bellard
{
1075 a9751609 Richard Henderson
    TCGOpcode op;
1076 c896fe29 bellard
    TCGOpDef *def;
1077 c896fe29 bellard
    const char *ct_str;
1078 c896fe29 bellard
    int i, nb_args;
1079 c896fe29 bellard
1080 c896fe29 bellard
    for(;;) {
1081 a9751609 Richard Henderson
        if (tdefs->op == (TCGOpcode)-1)
1082 c896fe29 bellard
            break;
1083 c896fe29 bellard
        op = tdefs->op;
1084 c3b08d0e Stefan Weil
        assert((unsigned)op < NB_OPS);
1085 c896fe29 bellard
        def = &tcg_op_defs[op];
1086 c68aaa18 Stefan Weil
#if defined(CONFIG_DEBUG_TCG)
1087 c68aaa18 Stefan Weil
        /* Duplicate entry in op definitions? */
1088 c68aaa18 Stefan Weil
        assert(!def->used);
1089 c68aaa18 Stefan Weil
        def->used = 1;
1090 c68aaa18 Stefan Weil
#endif
1091 c896fe29 bellard
        nb_args = def->nb_iargs + def->nb_oargs;
1092 c896fe29 bellard
        for(i = 0; i < nb_args; i++) {
1093 c896fe29 bellard
            ct_str = tdefs->args_ct_str[i];
1094 c68aaa18 Stefan Weil
            /* Incomplete TCGTargetOpDef entry? */
1095 c68aaa18 Stefan Weil
            assert(ct_str != NULL);
1096 c896fe29 bellard
            tcg_regset_clear(def->args_ct[i].u.regs);
1097 c896fe29 bellard
            def->args_ct[i].ct = 0;
1098 c896fe29 bellard
            if (ct_str[0] >= '0' && ct_str[0] <= '9') {
1099 c896fe29 bellard
                int oarg;
1100 c896fe29 bellard
                oarg = ct_str[0] - '0';
1101 c896fe29 bellard
                assert(oarg < def->nb_oargs);
1102 c896fe29 bellard
                assert(def->args_ct[oarg].ct & TCG_CT_REG);
1103 c896fe29 bellard
                /* TCG_CT_ALIAS is for the output arguments. The input
1104 5ff9d6a4 bellard
                   argument is tagged with TCG_CT_IALIAS. */
1105 c896fe29 bellard
                def->args_ct[i] = def->args_ct[oarg];
1106 5ff9d6a4 bellard
                def->args_ct[oarg].ct = TCG_CT_ALIAS;
1107 5ff9d6a4 bellard
                def->args_ct[oarg].alias_index = i;
1108 c896fe29 bellard
                def->args_ct[i].ct |= TCG_CT_IALIAS;
1109 5ff9d6a4 bellard
                def->args_ct[i].alias_index = oarg;
1110 c896fe29 bellard
            } else {
1111 c896fe29 bellard
                for(;;) {
1112 c896fe29 bellard
                    if (*ct_str == '\0')
1113 c896fe29 bellard
                        break;
1114 c896fe29 bellard
                    switch(*ct_str) {
1115 c896fe29 bellard
                    case 'i':
1116 c896fe29 bellard
                        def->args_ct[i].ct |= TCG_CT_CONST;
1117 c896fe29 bellard
                        ct_str++;
1118 c896fe29 bellard
                        break;
1119 c896fe29 bellard
                    default:
1120 c896fe29 bellard
                        if (target_parse_constraint(&def->args_ct[i], &ct_str) < 0) {
1121 c896fe29 bellard
                            fprintf(stderr, "Invalid constraint '%s' for arg %d of operation '%s'\n",
1122 c896fe29 bellard
                                    ct_str, i, def->name);
1123 c896fe29 bellard
                            exit(1);
1124 c896fe29 bellard
                        }
1125 c896fe29 bellard
                    }
1126 c896fe29 bellard
                }
1127 c896fe29 bellard
            }
1128 c896fe29 bellard
        }
1129 c896fe29 bellard
1130 c68aaa18 Stefan Weil
        /* TCGTargetOpDef entry with too much information? */
1131 c68aaa18 Stefan Weil
        assert(i == TCG_MAX_OP_ARGS || tdefs->args_ct_str[i] == NULL);
1132 c68aaa18 Stefan Weil
1133 c896fe29 bellard
        /* sort the constraints (XXX: this is just an heuristic) */
1134 c896fe29 bellard
        sort_constraints(def, 0, def->nb_oargs);
1135 c896fe29 bellard
        sort_constraints(def, def->nb_oargs, def->nb_iargs);
1136 c896fe29 bellard
1137 c896fe29 bellard
#if 0
1138 c896fe29 bellard
        {
1139 c896fe29 bellard
            int i;
1140 c896fe29 bellard

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

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

2266 5872bbf2 Richard Henderson
   (2) Define tcg_register_jit.  This should create a buffer containing
2267 5872bbf2 Richard Henderson
       the contents of a .debug_frame section that describes the post-
2268 5872bbf2 Richard Henderson
       prologue unwind info for the tcg machine.
2269 5872bbf2 Richard Henderson

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