Statistics
| Branch: | Revision:

root / tcg / tcg.c @ c9c3c80a

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

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