Statistics
| Branch: | Revision:

root / tcg / tcg.c @ 1b902f7d

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

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

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

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

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