Statistics
| Branch: | Revision:

root / tcg / tcg.c @ 5d8a4f8f

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

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