Statistics
| Branch: | Revision:

root / tcg / tcg.c @ f878d2d2

History | View | Annotate | Download (61.7 kB)

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

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