Statistics
| Branch: | Revision:

root / tcg / tcg.c @ a10f9f4f

History | View | Annotate | Download (63.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 a6c6f76c Blue Swirl
#if !defined(CONFIG_DEBUG_TCG) && !defined(NDEBUG)
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 6692b043 Aurelien Jarno
#define DEF2(s, oargs, iargs, cargs, flags) { #s, oargs, iargs, 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 3f90f252 Richard Henderson
            /* If stack grows up, then we will be placing successive
600 3f90f252 Richard Henderson
               arguments at lower addresses, which means we need to
601 3f90f252 Richard Henderson
               reverse the order compared to how we would normally
602 3f90f252 Richard Henderson
               treat either big or little-endian.  For those arguments
603 3f90f252 Richard Henderson
               that will wind up in registers, this still works for
604 3f90f252 Richard Henderson
               HPPA (the only current STACK_GROWSUP target) since the
605 3f90f252 Richard Henderson
               argument registers are *also* allocated in decreasing
606 3f90f252 Richard Henderson
               order.  If another such target is added, this logic may
607 3f90f252 Richard Henderson
               have to get more complicated to differentiate between
608 3f90f252 Richard Henderson
               stack arguments and register arguments.  */
609 3f90f252 Richard Henderson
#if defined(TCG_TARGET_WORDS_BIGENDIAN) != defined(TCG_TARGET_STACK_GROWSUP)
610 a7812ae4 pbrook
            *gen_opparam_ptr++ = args[i] + 1;
611 a7812ae4 pbrook
            *gen_opparam_ptr++ = args[i];
612 c896fe29 bellard
#else
613 a7812ae4 pbrook
            *gen_opparam_ptr++ = args[i];
614 a7812ae4 pbrook
            *gen_opparam_ptr++ = args[i] + 1;
615 c896fe29 bellard
#endif
616 a7812ae4 pbrook
            real_args += 2;
617 a7812ae4 pbrook
        } else
618 c896fe29 bellard
#endif
619 a7812ae4 pbrook
        {
620 a7812ae4 pbrook
            *gen_opparam_ptr++ = args[i];
621 a7812ae4 pbrook
            real_args++;
622 c896fe29 bellard
        }
623 c896fe29 bellard
    }
624 a7812ae4 pbrook
    *gen_opparam_ptr++ = GET_TCGV_PTR(func);
625 a7812ae4 pbrook
626 a7812ae4 pbrook
    *gen_opparam_ptr++ = flags;
627 a7812ae4 pbrook
628 a7812ae4 pbrook
    *nparam = (nb_rets << 16) | (real_args + 1);
629 a7812ae4 pbrook
630 a7812ae4 pbrook
    /* total parameters, needed to go backward in the instruction stream */
631 a7812ae4 pbrook
    *gen_opparam_ptr++ = 1 + nb_rets + real_args + 3;
632 c896fe29 bellard
}
633 c896fe29 bellard
634 ac56dd48 pbrook
#if TCG_TARGET_REG_BITS == 32
635 a7812ae4 pbrook
void tcg_gen_shifti_i64(TCGv_i64 ret, TCGv_i64 arg1,
636 c896fe29 bellard
                        int c, int right, int arith)
637 c896fe29 bellard
{
638 cf60bce4 bellard
    if (c == 0) {
639 a7812ae4 pbrook
        tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg1));
640 cf60bce4 bellard
        tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
641 cf60bce4 bellard
    } else if (c >= 32) {
642 c896fe29 bellard
        c -= 32;
643 c896fe29 bellard
        if (right) {
644 c896fe29 bellard
            if (arith) {
645 a7812ae4 pbrook
                tcg_gen_sari_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
646 ac56dd48 pbrook
                tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 31);
647 c896fe29 bellard
            } else {
648 a7812ae4 pbrook
                tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
649 ac56dd48 pbrook
                tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
650 c896fe29 bellard
            }
651 c896fe29 bellard
        } else {
652 a7812ae4 pbrook
            tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_LOW(arg1), c);
653 a7812ae4 pbrook
            tcg_gen_movi_i32(TCGV_LOW(ret), 0);
654 c896fe29 bellard
        }
655 c896fe29 bellard
    } else {
656 a7812ae4 pbrook
        TCGv_i32 t0, t1;
657 c896fe29 bellard
658 a7812ae4 pbrook
        t0 = tcg_temp_new_i32();
659 a7812ae4 pbrook
        t1 = tcg_temp_new_i32();
660 c896fe29 bellard
        if (right) {
661 ac56dd48 pbrook
            tcg_gen_shli_i32(t0, TCGV_HIGH(arg1), 32 - c);
662 c896fe29 bellard
            if (arith)
663 ac56dd48 pbrook
                tcg_gen_sari_i32(t1, TCGV_HIGH(arg1), c);
664 a7812ae4 pbrook
            else
665 ac56dd48 pbrook
                tcg_gen_shri_i32(t1, TCGV_HIGH(arg1), c);
666 a7812ae4 pbrook
            tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_LOW(arg1), c);
667 a7812ae4 pbrook
            tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(ret), t0);
668 ac56dd48 pbrook
            tcg_gen_mov_i32(TCGV_HIGH(ret), t1);
669 c896fe29 bellard
        } else {
670 a7812ae4 pbrook
            tcg_gen_shri_i32(t0, TCGV_LOW(arg1), 32 - c);
671 c896fe29 bellard
            /* Note: ret can be the same as arg1, so we use t1 */
672 a7812ae4 pbrook
            tcg_gen_shli_i32(t1, TCGV_LOW(arg1), c);
673 ac56dd48 pbrook
            tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c);
674 ac56dd48 pbrook
            tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t0);
675 a7812ae4 pbrook
            tcg_gen_mov_i32(TCGV_LOW(ret), t1);
676 c896fe29 bellard
        }
677 a7812ae4 pbrook
        tcg_temp_free_i32(t0);
678 a7812ae4 pbrook
        tcg_temp_free_i32(t1);
679 c896fe29 bellard
    }
680 c896fe29 bellard
}
681 ac56dd48 pbrook
#endif
682 c896fe29 bellard
683 be210acb Richard Henderson
684 8fcd3692 blueswir1
static void tcg_reg_alloc_start(TCGContext *s)
685 c896fe29 bellard
{
686 c896fe29 bellard
    int i;
687 c896fe29 bellard
    TCGTemp *ts;
688 c896fe29 bellard
    for(i = 0; i < s->nb_globals; i++) {
689 c896fe29 bellard
        ts = &s->temps[i];
690 c896fe29 bellard
        if (ts->fixed_reg) {
691 c896fe29 bellard
            ts->val_type = TEMP_VAL_REG;
692 c896fe29 bellard
        } else {
693 c896fe29 bellard
            ts->val_type = TEMP_VAL_MEM;
694 c896fe29 bellard
        }
695 c896fe29 bellard
    }
696 e8996ee0 bellard
    for(i = s->nb_globals; i < s->nb_temps; i++) {
697 e8996ee0 bellard
        ts = &s->temps[i];
698 e8996ee0 bellard
        ts->val_type = TEMP_VAL_DEAD;
699 e8996ee0 bellard
        ts->mem_allocated = 0;
700 e8996ee0 bellard
        ts->fixed_reg = 0;
701 e8996ee0 bellard
    }
702 c896fe29 bellard
    for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
703 c896fe29 bellard
        s->reg_to_temp[i] = -1;
704 c896fe29 bellard
    }
705 c896fe29 bellard
}
706 c896fe29 bellard
707 ac56dd48 pbrook
static char *tcg_get_arg_str_idx(TCGContext *s, char *buf, int buf_size,
708 ac56dd48 pbrook
                                 int idx)
709 c896fe29 bellard
{
710 c896fe29 bellard
    TCGTemp *ts;
711 ac56dd48 pbrook
712 ac56dd48 pbrook
    ts = &s->temps[idx];
713 ac56dd48 pbrook
    if (idx < s->nb_globals) {
714 ac56dd48 pbrook
        pstrcpy(buf, buf_size, ts->name);
715 c896fe29 bellard
    } else {
716 641d5fbe bellard
        if (ts->temp_local) 
717 641d5fbe bellard
            snprintf(buf, buf_size, "loc%d", idx - s->nb_globals);
718 641d5fbe bellard
        else
719 641d5fbe bellard
            snprintf(buf, buf_size, "tmp%d", idx - s->nb_globals);
720 c896fe29 bellard
    }
721 c896fe29 bellard
    return buf;
722 c896fe29 bellard
}
723 c896fe29 bellard
724 a7812ae4 pbrook
char *tcg_get_arg_str_i32(TCGContext *s, char *buf, int buf_size, TCGv_i32 arg)
725 a7812ae4 pbrook
{
726 a7812ae4 pbrook
    return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I32(arg));
727 a7812ae4 pbrook
}
728 a7812ae4 pbrook
729 a7812ae4 pbrook
char *tcg_get_arg_str_i64(TCGContext *s, char *buf, int buf_size, TCGv_i64 arg)
730 ac56dd48 pbrook
{
731 a810a2de blueswir1
    return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I64(arg));
732 ac56dd48 pbrook
}
733 ac56dd48 pbrook
734 e8996ee0 bellard
static int helper_cmp(const void *p1, const void *p2)
735 4dc81f28 bellard
{
736 e8996ee0 bellard
    const TCGHelperInfo *th1 = p1;
737 e8996ee0 bellard
    const TCGHelperInfo *th2 = p2;
738 e8996ee0 bellard
    if (th1->func < th2->func)
739 e8996ee0 bellard
        return -1;
740 e8996ee0 bellard
    else if (th1->func == th2->func)
741 e8996ee0 bellard
        return 0;
742 e8996ee0 bellard
    else
743 e8996ee0 bellard
        return 1;
744 4dc81f28 bellard
}
745 4dc81f28 bellard
746 e8996ee0 bellard
/* find helper definition (Note: A hash table would be better) */
747 e8996ee0 bellard
static TCGHelperInfo *tcg_find_helper(TCGContext *s, tcg_target_ulong val)
748 4dc81f28 bellard
{
749 e8996ee0 bellard
    int m, m_min, m_max;
750 4dc81f28 bellard
    TCGHelperInfo *th;
751 e8996ee0 bellard
    tcg_target_ulong v;
752 4dc81f28 bellard
753 e8996ee0 bellard
    if (unlikely(!s->helpers_sorted)) {
754 e8996ee0 bellard
        qsort(s->helpers, s->nb_helpers, sizeof(TCGHelperInfo), 
755 e8996ee0 bellard
              helper_cmp);
756 e8996ee0 bellard
        s->helpers_sorted = 1;
757 e8996ee0 bellard
    }
758 e8996ee0 bellard
759 e8996ee0 bellard
    /* binary search */
760 e8996ee0 bellard
    m_min = 0;
761 e8996ee0 bellard
    m_max = s->nb_helpers - 1;
762 e8996ee0 bellard
    while (m_min <= m_max) {
763 e8996ee0 bellard
        m = (m_min + m_max) >> 1;
764 e8996ee0 bellard
        th = &s->helpers[m];
765 e8996ee0 bellard
        v = th->func;
766 e8996ee0 bellard
        if (v == val)
767 e8996ee0 bellard
            return th;
768 e8996ee0 bellard
        else if (val < v) {
769 e8996ee0 bellard
            m_max = m - 1;
770 e8996ee0 bellard
        } else {
771 e8996ee0 bellard
            m_min = m + 1;
772 4dc81f28 bellard
        }
773 4dc81f28 bellard
    }
774 e8996ee0 bellard
    return NULL;
775 4dc81f28 bellard
}
776 4dc81f28 bellard
777 f48f3ede blueswir1
static const char * const cond_name[] =
778 f48f3ede blueswir1
{
779 f48f3ede blueswir1
    [TCG_COND_EQ] = "eq",
780 f48f3ede blueswir1
    [TCG_COND_NE] = "ne",
781 f48f3ede blueswir1
    [TCG_COND_LT] = "lt",
782 f48f3ede blueswir1
    [TCG_COND_GE] = "ge",
783 f48f3ede blueswir1
    [TCG_COND_LE] = "le",
784 f48f3ede blueswir1
    [TCG_COND_GT] = "gt",
785 f48f3ede blueswir1
    [TCG_COND_LTU] = "ltu",
786 f48f3ede blueswir1
    [TCG_COND_GEU] = "geu",
787 f48f3ede blueswir1
    [TCG_COND_LEU] = "leu",
788 f48f3ede blueswir1
    [TCG_COND_GTU] = "gtu"
789 f48f3ede blueswir1
};
790 f48f3ede blueswir1
791 c896fe29 bellard
void tcg_dump_ops(TCGContext *s, FILE *outfile)
792 c896fe29 bellard
{
793 c896fe29 bellard
    const uint16_t *opc_ptr;
794 c896fe29 bellard
    const TCGArg *args;
795 c896fe29 bellard
    TCGArg arg;
796 a9751609 Richard Henderson
    TCGOpcode c;
797 a9751609 Richard Henderson
    int i, k, nb_oargs, nb_iargs, nb_cargs, first_insn;
798 c896fe29 bellard
    const TCGOpDef *def;
799 c896fe29 bellard
    char buf[128];
800 c896fe29 bellard
801 7e4597d7 bellard
    first_insn = 1;
802 c896fe29 bellard
    opc_ptr = gen_opc_buf;
803 c896fe29 bellard
    args = gen_opparam_buf;
804 c896fe29 bellard
    while (opc_ptr < gen_opc_ptr) {
805 c896fe29 bellard
        c = *opc_ptr++;
806 c896fe29 bellard
        def = &tcg_op_defs[c];
807 7e4597d7 bellard
        if (c == INDEX_op_debug_insn_start) {
808 7e4597d7 bellard
            uint64_t pc;
809 7e4597d7 bellard
#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
810 7e4597d7 bellard
            pc = ((uint64_t)args[1] << 32) | args[0];
811 7e4597d7 bellard
#else
812 7e4597d7 bellard
            pc = args[0];
813 7e4597d7 bellard
#endif
814 7e4597d7 bellard
            if (!first_insn) 
815 7e4597d7 bellard
                fprintf(outfile, "\n");
816 7e4597d7 bellard
            fprintf(outfile, " ---- 0x%" PRIx64, pc);
817 7e4597d7 bellard
            first_insn = 0;
818 7e4597d7 bellard
            nb_oargs = def->nb_oargs;
819 7e4597d7 bellard
            nb_iargs = def->nb_iargs;
820 7e4597d7 bellard
            nb_cargs = def->nb_cargs;
821 7e4597d7 bellard
        } else if (c == INDEX_op_call) {
822 c896fe29 bellard
            TCGArg arg;
823 4dc81f28 bellard
824 c896fe29 bellard
            /* variable number of arguments */
825 c896fe29 bellard
            arg = *args++;
826 c896fe29 bellard
            nb_oargs = arg >> 16;
827 c896fe29 bellard
            nb_iargs = arg & 0xffff;
828 c896fe29 bellard
            nb_cargs = def->nb_cargs;
829 c896fe29 bellard
830 7e4597d7 bellard
            fprintf(outfile, " %s ", def->name);
831 7e4597d7 bellard
832 b03cce8e bellard
            /* function name */
833 ac56dd48 pbrook
            fprintf(outfile, "%s",
834 e8996ee0 bellard
                    tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + nb_iargs - 1]));
835 b03cce8e bellard
            /* flags */
836 b03cce8e bellard
            fprintf(outfile, ",$0x%" TCG_PRIlx,
837 b03cce8e bellard
                    args[nb_oargs + nb_iargs]);
838 b03cce8e bellard
            /* nb out args */
839 b03cce8e bellard
            fprintf(outfile, ",$%d", nb_oargs);
840 b03cce8e bellard
            for(i = 0; i < nb_oargs; i++) {
841 b03cce8e bellard
                fprintf(outfile, ",");
842 b03cce8e bellard
                fprintf(outfile, "%s",
843 b03cce8e bellard
                        tcg_get_arg_str_idx(s, buf, sizeof(buf), args[i]));
844 b03cce8e bellard
            }
845 b03cce8e bellard
            for(i = 0; i < (nb_iargs - 1); i++) {
846 c896fe29 bellard
                fprintf(outfile, ",");
847 39cf05d3 bellard
                if (args[nb_oargs + i] == TCG_CALL_DUMMY_ARG) {
848 39cf05d3 bellard
                    fprintf(outfile, "<dummy>");
849 39cf05d3 bellard
                } else {
850 39cf05d3 bellard
                    fprintf(outfile, "%s",
851 39cf05d3 bellard
                            tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + i]));
852 39cf05d3 bellard
                }
853 b03cce8e bellard
            }
854 e8996ee0 bellard
        } else if (c == INDEX_op_movi_i32 
855 e8996ee0 bellard
#if TCG_TARGET_REG_BITS == 64
856 e8996ee0 bellard
                   || c == INDEX_op_movi_i64
857 e8996ee0 bellard
#endif
858 e8996ee0 bellard
                   ) {
859 e8996ee0 bellard
            tcg_target_ulong val;
860 e8996ee0 bellard
            TCGHelperInfo *th;
861 e8996ee0 bellard
862 e8996ee0 bellard
            nb_oargs = def->nb_oargs;
863 e8996ee0 bellard
            nb_iargs = def->nb_iargs;
864 e8996ee0 bellard
            nb_cargs = def->nb_cargs;
865 e8996ee0 bellard
            fprintf(outfile, " %s %s,$", def->name, 
866 e8996ee0 bellard
                    tcg_get_arg_str_idx(s, buf, sizeof(buf), args[0]));
867 e8996ee0 bellard
            val = args[1];
868 e8996ee0 bellard
            th = tcg_find_helper(s, val);
869 e8996ee0 bellard
            if (th) {
870 3e9a474e aurel32
                fprintf(outfile, "%s", th->name);
871 e8996ee0 bellard
            } else {
872 e8996ee0 bellard
                if (c == INDEX_op_movi_i32)
873 e8996ee0 bellard
                    fprintf(outfile, "0x%x", (uint32_t)val);
874 e8996ee0 bellard
                else
875 e8996ee0 bellard
                    fprintf(outfile, "0x%" PRIx64 , (uint64_t)val);
876 e8996ee0 bellard
            }
877 b03cce8e bellard
        } else {
878 7e4597d7 bellard
            fprintf(outfile, " %s ", def->name);
879 b03cce8e bellard
            if (c == INDEX_op_nopn) {
880 b03cce8e bellard
                /* variable number of arguments */
881 b03cce8e bellard
                nb_cargs = *args;
882 b03cce8e bellard
                nb_oargs = 0;
883 b03cce8e bellard
                nb_iargs = 0;
884 b03cce8e bellard
            } else {
885 b03cce8e bellard
                nb_oargs = def->nb_oargs;
886 b03cce8e bellard
                nb_iargs = def->nb_iargs;
887 b03cce8e bellard
                nb_cargs = def->nb_cargs;
888 b03cce8e bellard
            }
889 b03cce8e bellard
            
890 b03cce8e bellard
            k = 0;
891 b03cce8e bellard
            for(i = 0; i < nb_oargs; i++) {
892 b03cce8e bellard
                if (k != 0)
893 b03cce8e bellard
                    fprintf(outfile, ",");
894 b03cce8e bellard
                fprintf(outfile, "%s",
895 b03cce8e bellard
                        tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
896 b03cce8e bellard
            }
897 b03cce8e bellard
            for(i = 0; i < nb_iargs; i++) {
898 b03cce8e bellard
                if (k != 0)
899 b03cce8e bellard
                    fprintf(outfile, ",");
900 b03cce8e bellard
                fprintf(outfile, "%s",
901 b03cce8e bellard
                        tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
902 b03cce8e bellard
            }
903 be210acb Richard Henderson
            switch (c) {
904 be210acb Richard Henderson
            case INDEX_op_brcond_i32:
905 be210acb Richard Henderson
#if TCG_TARGET_REG_BITS == 32
906 be210acb Richard Henderson
            case INDEX_op_brcond2_i32:
907 be210acb Richard Henderson
#elif TCG_TARGET_REG_BITS == 64
908 be210acb Richard Henderson
            case INDEX_op_brcond_i64:
909 be210acb Richard Henderson
#endif
910 be210acb Richard Henderson
            case INDEX_op_setcond_i32:
911 f48f3ede blueswir1
#if TCG_TARGET_REG_BITS == 32
912 be210acb Richard Henderson
            case INDEX_op_setcond2_i32:
913 f48f3ede blueswir1
#elif TCG_TARGET_REG_BITS == 64
914 be210acb Richard Henderson
            case INDEX_op_setcond_i64:
915 f48f3ede blueswir1
#endif
916 f48f3ede blueswir1
                if (args[k] < ARRAY_SIZE(cond_name) && cond_name[args[k]])
917 f48f3ede blueswir1
                    fprintf(outfile, ",%s", cond_name[args[k++]]);
918 f48f3ede blueswir1
                else
919 f48f3ede blueswir1
                    fprintf(outfile, ",$0x%" TCG_PRIlx, args[k++]);
920 f48f3ede blueswir1
                i = 1;
921 be210acb Richard Henderson
                break;
922 be210acb Richard Henderson
            default:
923 f48f3ede blueswir1
                i = 0;
924 be210acb Richard Henderson
                break;
925 be210acb Richard Henderson
            }
926 f48f3ede blueswir1
            for(; i < nb_cargs; i++) {
927 b03cce8e bellard
                if (k != 0)
928 b03cce8e bellard
                    fprintf(outfile, ",");
929 b03cce8e bellard
                arg = args[k++];
930 b03cce8e bellard
                fprintf(outfile, "$0x%" TCG_PRIlx, arg);
931 b03cce8e bellard
            }
932 c896fe29 bellard
        }
933 c896fe29 bellard
        fprintf(outfile, "\n");
934 c896fe29 bellard
        args += nb_iargs + nb_oargs + nb_cargs;
935 c896fe29 bellard
    }
936 c896fe29 bellard
}
937 c896fe29 bellard
938 c896fe29 bellard
/* we give more priority to constraints with less registers */
939 c896fe29 bellard
static int get_constraint_priority(const TCGOpDef *def, int k)
940 c896fe29 bellard
{
941 c896fe29 bellard
    const TCGArgConstraint *arg_ct;
942 c896fe29 bellard
943 c896fe29 bellard
    int i, n;
944 c896fe29 bellard
    arg_ct = &def->args_ct[k];
945 c896fe29 bellard
    if (arg_ct->ct & TCG_CT_ALIAS) {
946 c896fe29 bellard
        /* an alias is equivalent to a single register */
947 c896fe29 bellard
        n = 1;
948 c896fe29 bellard
    } else {
949 c896fe29 bellard
        if (!(arg_ct->ct & TCG_CT_REG))
950 c896fe29 bellard
            return 0;
951 c896fe29 bellard
        n = 0;
952 c896fe29 bellard
        for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
953 c896fe29 bellard
            if (tcg_regset_test_reg(arg_ct->u.regs, i))
954 c896fe29 bellard
                n++;
955 c896fe29 bellard
        }
956 c896fe29 bellard
    }
957 c896fe29 bellard
    return TCG_TARGET_NB_REGS - n + 1;
958 c896fe29 bellard
}
959 c896fe29 bellard
960 c896fe29 bellard
/* sort from highest priority to lowest */
961 c896fe29 bellard
static void sort_constraints(TCGOpDef *def, int start, int n)
962 c896fe29 bellard
{
963 c896fe29 bellard
    int i, j, p1, p2, tmp;
964 c896fe29 bellard
965 c896fe29 bellard
    for(i = 0; i < n; i++)
966 c896fe29 bellard
        def->sorted_args[start + i] = start + i;
967 c896fe29 bellard
    if (n <= 1)
968 c896fe29 bellard
        return;
969 c896fe29 bellard
    for(i = 0; i < n - 1; i++) {
970 c896fe29 bellard
        for(j = i + 1; j < n; j++) {
971 c896fe29 bellard
            p1 = get_constraint_priority(def, def->sorted_args[start + i]);
972 c896fe29 bellard
            p2 = get_constraint_priority(def, def->sorted_args[start + j]);
973 c896fe29 bellard
            if (p1 < p2) {
974 c896fe29 bellard
                tmp = def->sorted_args[start + i];
975 c896fe29 bellard
                def->sorted_args[start + i] = def->sorted_args[start + j];
976 c896fe29 bellard
                def->sorted_args[start + j] = tmp;
977 c896fe29 bellard
            }
978 c896fe29 bellard
        }
979 c896fe29 bellard
    }
980 c896fe29 bellard
}
981 c896fe29 bellard
982 c896fe29 bellard
void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs)
983 c896fe29 bellard
{
984 a9751609 Richard Henderson
    TCGOpcode op;
985 c896fe29 bellard
    TCGOpDef *def;
986 c896fe29 bellard
    const char *ct_str;
987 c896fe29 bellard
    int i, nb_args;
988 c896fe29 bellard
989 c896fe29 bellard
    for(;;) {
990 a9751609 Richard Henderson
        if (tdefs->op == (TCGOpcode)-1)
991 c896fe29 bellard
            break;
992 c896fe29 bellard
        op = tdefs->op;
993 c896fe29 bellard
        assert(op >= 0 && op < NB_OPS);
994 c896fe29 bellard
        def = &tcg_op_defs[op];
995 c68aaa18 Stefan Weil
#if defined(CONFIG_DEBUG_TCG)
996 c68aaa18 Stefan Weil
        /* Duplicate entry in op definitions? */
997 c68aaa18 Stefan Weil
        assert(!def->used);
998 c68aaa18 Stefan Weil
        def->used = 1;
999 c68aaa18 Stefan Weil
#endif
1000 c896fe29 bellard
        nb_args = def->nb_iargs + def->nb_oargs;
1001 c896fe29 bellard
        for(i = 0; i < nb_args; i++) {
1002 c896fe29 bellard
            ct_str = tdefs->args_ct_str[i];
1003 c68aaa18 Stefan Weil
            /* Incomplete TCGTargetOpDef entry? */
1004 c68aaa18 Stefan Weil
            assert(ct_str != NULL);
1005 c896fe29 bellard
            tcg_regset_clear(def->args_ct[i].u.regs);
1006 c896fe29 bellard
            def->args_ct[i].ct = 0;
1007 c896fe29 bellard
            if (ct_str[0] >= '0' && ct_str[0] <= '9') {
1008 c896fe29 bellard
                int oarg;
1009 c896fe29 bellard
                oarg = ct_str[0] - '0';
1010 c896fe29 bellard
                assert(oarg < def->nb_oargs);
1011 c896fe29 bellard
                assert(def->args_ct[oarg].ct & TCG_CT_REG);
1012 c896fe29 bellard
                /* TCG_CT_ALIAS is for the output arguments. The input
1013 5ff9d6a4 bellard
                   argument is tagged with TCG_CT_IALIAS. */
1014 c896fe29 bellard
                def->args_ct[i] = def->args_ct[oarg];
1015 5ff9d6a4 bellard
                def->args_ct[oarg].ct = TCG_CT_ALIAS;
1016 5ff9d6a4 bellard
                def->args_ct[oarg].alias_index = i;
1017 c896fe29 bellard
                def->args_ct[i].ct |= TCG_CT_IALIAS;
1018 5ff9d6a4 bellard
                def->args_ct[i].alias_index = oarg;
1019 c896fe29 bellard
            } else {
1020 c896fe29 bellard
                for(;;) {
1021 c896fe29 bellard
                    if (*ct_str == '\0')
1022 c896fe29 bellard
                        break;
1023 c896fe29 bellard
                    switch(*ct_str) {
1024 c896fe29 bellard
                    case 'i':
1025 c896fe29 bellard
                        def->args_ct[i].ct |= TCG_CT_CONST;
1026 c896fe29 bellard
                        ct_str++;
1027 c896fe29 bellard
                        break;
1028 c896fe29 bellard
                    default:
1029 c896fe29 bellard
                        if (target_parse_constraint(&def->args_ct[i], &ct_str) < 0) {
1030 c896fe29 bellard
                            fprintf(stderr, "Invalid constraint '%s' for arg %d of operation '%s'\n",
1031 c896fe29 bellard
                                    ct_str, i, def->name);
1032 c896fe29 bellard
                            exit(1);
1033 c896fe29 bellard
                        }
1034 c896fe29 bellard
                    }
1035 c896fe29 bellard
                }
1036 c896fe29 bellard
            }
1037 c896fe29 bellard
        }
1038 c896fe29 bellard
1039 c68aaa18 Stefan Weil
        /* TCGTargetOpDef entry with too much information? */
1040 c68aaa18 Stefan Weil
        assert(i == TCG_MAX_OP_ARGS || tdefs->args_ct_str[i] == NULL);
1041 c68aaa18 Stefan Weil
1042 c896fe29 bellard
        /* sort the constraints (XXX: this is just an heuristic) */
1043 c896fe29 bellard
        sort_constraints(def, 0, def->nb_oargs);
1044 c896fe29 bellard
        sort_constraints(def, def->nb_oargs, def->nb_iargs);
1045 c896fe29 bellard
1046 c896fe29 bellard
#if 0
1047 c896fe29 bellard
        {
1048 c896fe29 bellard
            int i;
1049 c896fe29 bellard

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