Statistics
| Branch: | Revision:

root / tcg / tcg.c @ a23a9ec6

History | View | Annotate | Download (61.5 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 suppress various consistency checks (faster) */
26 c896fe29 bellard
#define NDEBUG
27 c896fe29 bellard
28 c896fe29 bellard
/* define it to use liveness analysis (better code) */
29 c896fe29 bellard
#define USE_LIVENESS_ANALYSIS
30 c896fe29 bellard
31 c896fe29 bellard
#include <assert.h>
32 c896fe29 bellard
#include <stdarg.h>
33 c896fe29 bellard
#include <stdlib.h>
34 c896fe29 bellard
#include <stdio.h>
35 c896fe29 bellard
#include <string.h>
36 c896fe29 bellard
#include <inttypes.h>
37 3fe43da7 bellard
#ifdef _WIN32
38 3fe43da7 bellard
#include <malloc.h>
39 3fe43da7 bellard
#endif
40 c896fe29 bellard
41 c896fe29 bellard
#include "config.h"
42 ca10f867 aurel32
#include "qemu-common.h"
43 c896fe29 bellard
44 c896fe29 bellard
/* Note: the long term plan is to reduce the dependancies on the QEMU
45 c896fe29 bellard
   CPU definitions. Currently they are used for qemu_ld/st
46 c896fe29 bellard
   instructions */
47 c896fe29 bellard
#define NO_CPU_IO_DEFS
48 c896fe29 bellard
#include "cpu.h"
49 c896fe29 bellard
#include "exec-all.h"
50 c896fe29 bellard
51 c896fe29 bellard
#include "tcg-op.h"
52 c896fe29 bellard
#include "elf.h"
53 c896fe29 bellard
54 c896fe29 bellard
55 c896fe29 bellard
static void patch_reloc(uint8_t *code_ptr, int type, 
56 f54b3f92 aurel32
                        tcg_target_long value, tcg_target_long addend);
57 c896fe29 bellard
58 c896fe29 bellard
TCGOpDef tcg_op_defs[] = {
59 c896fe29 bellard
#define DEF(s, n, copy_size) { #s, 0, 0, n, n, 0, copy_size },
60 c896fe29 bellard
#define DEF2(s, iargs, oargs, cargs, flags) { #s, iargs, oargs, cargs, iargs + oargs + cargs, flags, 0 },
61 c896fe29 bellard
#include "tcg-opc.h"
62 c896fe29 bellard
#undef DEF
63 c896fe29 bellard
#undef DEF2
64 c896fe29 bellard
};
65 c896fe29 bellard
66 c896fe29 bellard
TCGRegSet tcg_target_available_regs[2];
67 c896fe29 bellard
TCGRegSet tcg_target_call_clobber_regs;
68 c896fe29 bellard
69 c896fe29 bellard
/* XXX: move that inside the context */
70 c896fe29 bellard
uint16_t *gen_opc_ptr;
71 c896fe29 bellard
TCGArg *gen_opparam_ptr;
72 c896fe29 bellard
73 c896fe29 bellard
static inline void tcg_out8(TCGContext *s, uint8_t v)
74 c896fe29 bellard
{
75 c896fe29 bellard
    *s->code_ptr++ = v;
76 c896fe29 bellard
}
77 c896fe29 bellard
78 c896fe29 bellard
static inline void tcg_out16(TCGContext *s, uint16_t v)
79 c896fe29 bellard
{
80 c896fe29 bellard
    *(uint16_t *)s->code_ptr = v;
81 c896fe29 bellard
    s->code_ptr += 2;
82 c896fe29 bellard
}
83 c896fe29 bellard
84 c896fe29 bellard
static inline void tcg_out32(TCGContext *s, uint32_t v)
85 c896fe29 bellard
{
86 c896fe29 bellard
    *(uint32_t *)s->code_ptr = v;
87 c896fe29 bellard
    s->code_ptr += 4;
88 c896fe29 bellard
}
89 c896fe29 bellard
90 c896fe29 bellard
/* label relocation processing */
91 c896fe29 bellard
92 c896fe29 bellard
void tcg_out_reloc(TCGContext *s, uint8_t *code_ptr, int type, 
93 c896fe29 bellard
                   int label_index, long addend)
94 c896fe29 bellard
{
95 c896fe29 bellard
    TCGLabel *l;
96 c896fe29 bellard
    TCGRelocation *r;
97 c896fe29 bellard
98 c896fe29 bellard
    l = &s->labels[label_index];
99 c896fe29 bellard
    if (l->has_value) {
100 623e265c pbrook
        /* FIXME: This may break relocations on RISC targets that
101 623e265c pbrook
           modify instruction fields in place.  The caller may not have 
102 623e265c pbrook
           written the initial value.  */
103 f54b3f92 aurel32
        patch_reloc(code_ptr, type, l->u.value, addend);
104 c896fe29 bellard
    } else {
105 c896fe29 bellard
        /* add a new relocation entry */
106 c896fe29 bellard
        r = tcg_malloc(sizeof(TCGRelocation));
107 c896fe29 bellard
        r->type = type;
108 c896fe29 bellard
        r->ptr = code_ptr;
109 c896fe29 bellard
        r->addend = addend;
110 c896fe29 bellard
        r->next = l->u.first_reloc;
111 c896fe29 bellard
        l->u.first_reloc = r;
112 c896fe29 bellard
    }
113 c896fe29 bellard
}
114 c896fe29 bellard
115 c896fe29 bellard
static void tcg_out_label(TCGContext *s, int label_index, 
116 c896fe29 bellard
                          tcg_target_long value)
117 c896fe29 bellard
{
118 c896fe29 bellard
    TCGLabel *l;
119 c896fe29 bellard
    TCGRelocation *r;
120 c896fe29 bellard
121 c896fe29 bellard
    l = &s->labels[label_index];
122 c896fe29 bellard
    if (l->has_value)
123 c896fe29 bellard
        tcg_abort();
124 c896fe29 bellard
    r = l->u.first_reloc;
125 c896fe29 bellard
    while (r != NULL) {
126 f54b3f92 aurel32
        patch_reloc(r->ptr, r->type, value, r->addend);
127 c896fe29 bellard
        r = r->next;
128 c896fe29 bellard
    }
129 c896fe29 bellard
    l->has_value = 1;
130 c896fe29 bellard
    l->u.value = value;
131 c896fe29 bellard
}
132 c896fe29 bellard
133 c896fe29 bellard
int gen_new_label(void)
134 c896fe29 bellard
{
135 c896fe29 bellard
    TCGContext *s = &tcg_ctx;
136 c896fe29 bellard
    int idx;
137 c896fe29 bellard
    TCGLabel *l;
138 c896fe29 bellard
139 c896fe29 bellard
    if (s->nb_labels >= TCG_MAX_LABELS)
140 c896fe29 bellard
        tcg_abort();
141 c896fe29 bellard
    idx = s->nb_labels++;
142 c896fe29 bellard
    l = &s->labels[idx];
143 c896fe29 bellard
    l->has_value = 0;
144 c896fe29 bellard
    l->u.first_reloc = NULL;
145 c896fe29 bellard
    return idx;
146 c896fe29 bellard
}
147 c896fe29 bellard
148 c896fe29 bellard
#include "tcg-target.c"
149 c896fe29 bellard
150 c896fe29 bellard
/* pool based memory allocation */
151 c896fe29 bellard
void *tcg_malloc_internal(TCGContext *s, int size)
152 c896fe29 bellard
{
153 c896fe29 bellard
    TCGPool *p;
154 c896fe29 bellard
    int pool_size;
155 c896fe29 bellard
    
156 c896fe29 bellard
    if (size > TCG_POOL_CHUNK_SIZE) {
157 c896fe29 bellard
        /* big malloc: insert a new pool (XXX: could optimize) */
158 c896fe29 bellard
        p = qemu_malloc(sizeof(TCGPool) + size);
159 c896fe29 bellard
        p->size = size;
160 c896fe29 bellard
        if (s->pool_current)
161 c896fe29 bellard
            s->pool_current->next = p;
162 c896fe29 bellard
        else
163 c896fe29 bellard
            s->pool_first = p;
164 c896fe29 bellard
        p->next = s->pool_current;
165 c896fe29 bellard
    } else {
166 c896fe29 bellard
        p = s->pool_current;
167 c896fe29 bellard
        if (!p) {
168 c896fe29 bellard
            p = s->pool_first;
169 c896fe29 bellard
            if (!p)
170 c896fe29 bellard
                goto new_pool;
171 c896fe29 bellard
        } else {
172 c896fe29 bellard
            if (!p->next) {
173 c896fe29 bellard
            new_pool:
174 c896fe29 bellard
                pool_size = TCG_POOL_CHUNK_SIZE;
175 c896fe29 bellard
                p = qemu_malloc(sizeof(TCGPool) + pool_size);
176 c896fe29 bellard
                p->size = pool_size;
177 c896fe29 bellard
                p->next = NULL;
178 c896fe29 bellard
                if (s->pool_current) 
179 c896fe29 bellard
                    s->pool_current->next = p;
180 c896fe29 bellard
                else
181 c896fe29 bellard
                    s->pool_first = p;
182 c896fe29 bellard
            } else {
183 c896fe29 bellard
                p = p->next;
184 c896fe29 bellard
            }
185 c896fe29 bellard
        }
186 c896fe29 bellard
    }
187 c896fe29 bellard
    s->pool_current = p;
188 c896fe29 bellard
    s->pool_cur = p->data + size;
189 c896fe29 bellard
    s->pool_end = p->data + p->size;
190 c896fe29 bellard
    return p->data;
191 c896fe29 bellard
}
192 c896fe29 bellard
193 c896fe29 bellard
void tcg_pool_reset(TCGContext *s)
194 c896fe29 bellard
{
195 c896fe29 bellard
    s->pool_cur = s->pool_end = NULL;
196 c896fe29 bellard
    s->pool_current = NULL;
197 c896fe29 bellard
}
198 c896fe29 bellard
199 c896fe29 bellard
/* free all the pool */
200 c896fe29 bellard
void tcg_pool_free(TCGContext *s)
201 c896fe29 bellard
{
202 c896fe29 bellard
    TCGPool *p, *p1;
203 c896fe29 bellard
204 c896fe29 bellard
    for(p = s->pool_first; p != NULL; p = p1) {
205 c896fe29 bellard
        p1 = p->next;
206 c896fe29 bellard
        qemu_free(p);
207 c896fe29 bellard
    }
208 c896fe29 bellard
    s->pool_first = NULL;
209 c896fe29 bellard
    s->pool_cur = s->pool_end = NULL;
210 c896fe29 bellard
}
211 c896fe29 bellard
212 c896fe29 bellard
void tcg_context_init(TCGContext *s)
213 c896fe29 bellard
{
214 c896fe29 bellard
    int op, total_args, n;
215 c896fe29 bellard
    TCGOpDef *def;
216 c896fe29 bellard
    TCGArgConstraint *args_ct;
217 c896fe29 bellard
    int *sorted_args;
218 c896fe29 bellard
219 c896fe29 bellard
    memset(s, 0, sizeof(*s));
220 c896fe29 bellard
    s->temps = s->static_temps;
221 c896fe29 bellard
    s->nb_globals = 0;
222 c896fe29 bellard
    
223 c896fe29 bellard
    /* Count total number of arguments and allocate the corresponding
224 c896fe29 bellard
       space */
225 c896fe29 bellard
    total_args = 0;
226 c896fe29 bellard
    for(op = 0; op < NB_OPS; op++) {
227 c896fe29 bellard
        def = &tcg_op_defs[op];
228 c896fe29 bellard
        n = def->nb_iargs + def->nb_oargs;
229 c896fe29 bellard
        total_args += n;
230 c896fe29 bellard
    }
231 c896fe29 bellard
232 c896fe29 bellard
    args_ct = qemu_malloc(sizeof(TCGArgConstraint) * total_args);
233 c896fe29 bellard
    sorted_args = qemu_malloc(sizeof(int) * total_args);
234 c896fe29 bellard
235 c896fe29 bellard
    for(op = 0; op < NB_OPS; op++) {
236 c896fe29 bellard
        def = &tcg_op_defs[op];
237 c896fe29 bellard
        def->args_ct = args_ct;
238 c896fe29 bellard
        def->sorted_args = sorted_args;
239 c896fe29 bellard
        n = def->nb_iargs + def->nb_oargs;
240 c896fe29 bellard
        sorted_args += n;
241 c896fe29 bellard
        args_ct += n;
242 c896fe29 bellard
    }
243 c896fe29 bellard
    
244 c896fe29 bellard
    tcg_target_init(s);
245 b03cce8e bellard
246 b03cce8e bellard
    /* init global prologue and epilogue */
247 b03cce8e bellard
    s->code_buf = code_gen_prologue;
248 b03cce8e bellard
    s->code_ptr = s->code_buf;
249 b03cce8e bellard
    tcg_target_qemu_prologue(s);
250 b03cce8e bellard
    flush_icache_range((unsigned long)s->code_buf, 
251 b03cce8e bellard
                       (unsigned long)s->code_ptr);
252 c896fe29 bellard
}
253 c896fe29 bellard
254 c896fe29 bellard
void tcg_set_frame(TCGContext *s, int reg,
255 c896fe29 bellard
                   tcg_target_long start, tcg_target_long size)
256 c896fe29 bellard
{
257 c896fe29 bellard
    s->frame_start = start;
258 c896fe29 bellard
    s->frame_end = start + size;
259 c896fe29 bellard
    s->frame_reg = reg;
260 c896fe29 bellard
}
261 c896fe29 bellard
262 c896fe29 bellard
void tcg_set_macro_func(TCGContext *s, TCGMacroFunc *func)
263 c896fe29 bellard
{
264 c896fe29 bellard
    s->macro_func = func;
265 c896fe29 bellard
}
266 c896fe29 bellard
267 c896fe29 bellard
void tcg_func_start(TCGContext *s)
268 c896fe29 bellard
{
269 c896fe29 bellard
    tcg_pool_reset(s);
270 c896fe29 bellard
    s->nb_temps = s->nb_globals;
271 c896fe29 bellard
    s->labels = tcg_malloc(sizeof(TCGLabel) * TCG_MAX_LABELS);
272 c896fe29 bellard
    s->nb_labels = 0;
273 c896fe29 bellard
    s->current_frame_offset = s->frame_start;
274 c896fe29 bellard
275 c896fe29 bellard
    gen_opc_ptr = gen_opc_buf;
276 c896fe29 bellard
    gen_opparam_ptr = gen_opparam_buf;
277 c896fe29 bellard
}
278 c896fe29 bellard
279 c896fe29 bellard
static inline void tcg_temp_alloc(TCGContext *s, int n)
280 c896fe29 bellard
{
281 c896fe29 bellard
    if (n > TCG_MAX_TEMPS)
282 c896fe29 bellard
        tcg_abort();
283 c896fe29 bellard
}
284 c896fe29 bellard
285 ac56dd48 pbrook
TCGv tcg_global_reg_new(TCGType type, int reg, 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->val_type = TEMP_VAL_REG;
305 c896fe29 bellard
    ts->name = name;
306 c896fe29 bellard
    s->nb_globals++;
307 c896fe29 bellard
    tcg_regset_set_reg(s->reserved_regs, reg);
308 ac56dd48 pbrook
    return MAKE_TCGV(idx);
309 c896fe29 bellard
}
310 c896fe29 bellard
311 6a8d7b76 bellard
#if TCG_TARGET_REG_BITS == 32
312 6a8d7b76 bellard
/* temporary hack to avoid register shortage for tcg_qemu_st64() */
313 6a8d7b76 bellard
TCGv tcg_global_reg2_new_hack(TCGType type, int reg1, int reg2, 
314 6a8d7b76 bellard
                              const char *name)
315 6a8d7b76 bellard
{
316 6a8d7b76 bellard
    TCGContext *s = &tcg_ctx;
317 6a8d7b76 bellard
    TCGTemp *ts;
318 6a8d7b76 bellard
    int idx;
319 6a8d7b76 bellard
    char buf[64];
320 6a8d7b76 bellard
321 6a8d7b76 bellard
    if (type != TCG_TYPE_I64)
322 6a8d7b76 bellard
        tcg_abort();
323 6a8d7b76 bellard
    idx = s->nb_globals;
324 6a8d7b76 bellard
    tcg_temp_alloc(s, s->nb_globals + 2);
325 6a8d7b76 bellard
    ts = &s->temps[s->nb_globals];
326 6a8d7b76 bellard
    ts->base_type = type;
327 6a8d7b76 bellard
    ts->type = TCG_TYPE_I32;
328 6a8d7b76 bellard
    ts->fixed_reg = 1;
329 6a8d7b76 bellard
    ts->reg = reg1;
330 6a8d7b76 bellard
    ts->val_type = TEMP_VAL_REG;
331 6a8d7b76 bellard
    pstrcpy(buf, sizeof(buf), name);
332 6a8d7b76 bellard
    pstrcat(buf, sizeof(buf), "_0");
333 6a8d7b76 bellard
    ts->name = strdup(buf);
334 6a8d7b76 bellard
335 6a8d7b76 bellard
    ts++;
336 6a8d7b76 bellard
    ts->base_type = type;
337 6a8d7b76 bellard
    ts->type = TCG_TYPE_I32;
338 6a8d7b76 bellard
    ts->fixed_reg = 1;
339 6a8d7b76 bellard
    ts->reg = reg2;
340 6a8d7b76 bellard
    ts->val_type = TEMP_VAL_REG;
341 6a8d7b76 bellard
    pstrcpy(buf, sizeof(buf), name);
342 6a8d7b76 bellard
    pstrcat(buf, sizeof(buf), "_1");
343 6a8d7b76 bellard
    ts->name = strdup(buf);
344 6a8d7b76 bellard
345 6a8d7b76 bellard
    s->nb_globals += 2;
346 6a8d7b76 bellard
    return MAKE_TCGV(idx);
347 6a8d7b76 bellard
}
348 6a8d7b76 bellard
#endif
349 6a8d7b76 bellard
350 ac56dd48 pbrook
TCGv tcg_global_mem_new(TCGType type, int reg, tcg_target_long offset,
351 ac56dd48 pbrook
                        const char *name)
352 c896fe29 bellard
{
353 c896fe29 bellard
    TCGContext *s = &tcg_ctx;
354 c896fe29 bellard
    TCGTemp *ts;
355 c896fe29 bellard
    int idx;
356 c896fe29 bellard
357 c896fe29 bellard
    idx = s->nb_globals;
358 c896fe29 bellard
#if TCG_TARGET_REG_BITS == 32
359 c896fe29 bellard
    if (type == TCG_TYPE_I64) {
360 c896fe29 bellard
        char buf[64];
361 c896fe29 bellard
        tcg_temp_alloc(s, s->nb_globals + 1);
362 c896fe29 bellard
        ts = &s->temps[s->nb_globals];
363 c896fe29 bellard
        ts->base_type = type;
364 c896fe29 bellard
        ts->type = TCG_TYPE_I32;
365 c896fe29 bellard
        ts->fixed_reg = 0;
366 c896fe29 bellard
        ts->mem_allocated = 1;
367 c896fe29 bellard
        ts->mem_reg = reg;
368 c896fe29 bellard
#ifdef TCG_TARGET_WORDS_BIGENDIAN
369 c896fe29 bellard
        ts->mem_offset = offset + 4;
370 c896fe29 bellard
#else
371 c896fe29 bellard
        ts->mem_offset = offset;
372 c896fe29 bellard
#endif
373 c896fe29 bellard
        ts->val_type = TEMP_VAL_MEM;
374 c896fe29 bellard
        pstrcpy(buf, sizeof(buf), name);
375 c896fe29 bellard
        pstrcat(buf, sizeof(buf), "_0");
376 c896fe29 bellard
        ts->name = strdup(buf);
377 c896fe29 bellard
        ts++;
378 c896fe29 bellard
379 c896fe29 bellard
        ts->base_type = type;
380 c896fe29 bellard
        ts->type = TCG_TYPE_I32;
381 c896fe29 bellard
        ts->fixed_reg = 0;
382 c896fe29 bellard
        ts->mem_allocated = 1;
383 c896fe29 bellard
        ts->mem_reg = reg;
384 c896fe29 bellard
#ifdef TCG_TARGET_WORDS_BIGENDIAN
385 c896fe29 bellard
        ts->mem_offset = offset;
386 c896fe29 bellard
#else
387 c896fe29 bellard
        ts->mem_offset = offset + 4;
388 c896fe29 bellard
#endif
389 c896fe29 bellard
        ts->val_type = TEMP_VAL_MEM;
390 c896fe29 bellard
        pstrcpy(buf, sizeof(buf), name);
391 c896fe29 bellard
        pstrcat(buf, sizeof(buf), "_1");
392 c896fe29 bellard
        ts->name = strdup(buf);
393 c896fe29 bellard
394 c896fe29 bellard
        s->nb_globals += 2;
395 c896fe29 bellard
    } else
396 c896fe29 bellard
#endif
397 c896fe29 bellard
    {
398 c896fe29 bellard
        tcg_temp_alloc(s, s->nb_globals + 1);
399 c896fe29 bellard
        ts = &s->temps[s->nb_globals];
400 c896fe29 bellard
        ts->base_type = type;
401 c896fe29 bellard
        ts->type = type;
402 c896fe29 bellard
        ts->fixed_reg = 0;
403 c896fe29 bellard
        ts->mem_allocated = 1;
404 c896fe29 bellard
        ts->mem_reg = reg;
405 c896fe29 bellard
        ts->mem_offset = offset;
406 c896fe29 bellard
        ts->val_type = TEMP_VAL_MEM;
407 c896fe29 bellard
        ts->name = name;
408 c896fe29 bellard
        s->nb_globals++;
409 c896fe29 bellard
    }
410 ac56dd48 pbrook
    return MAKE_TCGV(idx);
411 c896fe29 bellard
}
412 c896fe29 bellard
413 ac56dd48 pbrook
TCGv tcg_temp_new(TCGType type)
414 c896fe29 bellard
{
415 c896fe29 bellard
    TCGContext *s = &tcg_ctx;
416 c896fe29 bellard
    TCGTemp *ts;
417 c896fe29 bellard
    int idx;
418 c896fe29 bellard
419 c896fe29 bellard
    idx = s->nb_temps;
420 c896fe29 bellard
#if TCG_TARGET_REG_BITS == 32
421 c896fe29 bellard
    if (type == TCG_TYPE_I64) {
422 c896fe29 bellard
        tcg_temp_alloc(s, s->nb_temps + 1);
423 c896fe29 bellard
        ts = &s->temps[s->nb_temps];
424 c896fe29 bellard
        ts->base_type = type;
425 c896fe29 bellard
        ts->type = TCG_TYPE_I32;
426 5ff9d6a4 bellard
        ts->fixed_reg = 0;
427 c896fe29 bellard
        ts->val_type = TEMP_VAL_DEAD;
428 c896fe29 bellard
        ts->mem_allocated = 0;
429 c896fe29 bellard
        ts->name = NULL;
430 c896fe29 bellard
        ts++;
431 c896fe29 bellard
        ts->base_type = TCG_TYPE_I32;
432 c896fe29 bellard
        ts->type = TCG_TYPE_I32;
433 c896fe29 bellard
        ts->val_type = TEMP_VAL_DEAD;
434 5ff9d6a4 bellard
        ts->fixed_reg = 0;
435 c896fe29 bellard
        ts->mem_allocated = 0;
436 c896fe29 bellard
        ts->name = NULL;
437 c896fe29 bellard
        s->nb_temps += 2;
438 c896fe29 bellard
    } else
439 c896fe29 bellard
#endif
440 c896fe29 bellard
    {
441 c896fe29 bellard
        tcg_temp_alloc(s, s->nb_temps + 1);
442 c896fe29 bellard
        ts = &s->temps[s->nb_temps];
443 c896fe29 bellard
        ts->base_type = type;
444 c896fe29 bellard
        ts->type = type;
445 5ff9d6a4 bellard
        ts->fixed_reg = 0;
446 c896fe29 bellard
        ts->val_type = TEMP_VAL_DEAD;
447 c896fe29 bellard
        ts->mem_allocated = 0;
448 c896fe29 bellard
        ts->name = NULL;
449 c896fe29 bellard
        s->nb_temps++;
450 c896fe29 bellard
    }
451 ac56dd48 pbrook
    return MAKE_TCGV(idx);
452 c896fe29 bellard
}
453 c896fe29 bellard
454 ac56dd48 pbrook
TCGv tcg_const_i32(int32_t val)
455 c896fe29 bellard
{
456 c896fe29 bellard
    TCGContext *s = &tcg_ctx;
457 c896fe29 bellard
    TCGTemp *ts;
458 c896fe29 bellard
    int idx;
459 c896fe29 bellard
460 c896fe29 bellard
    idx = s->nb_temps;
461 c896fe29 bellard
    tcg_temp_alloc(s, idx + 1);
462 c896fe29 bellard
    ts = &s->temps[idx];
463 c896fe29 bellard
    ts->base_type = ts->type = TCG_TYPE_I32;
464 c896fe29 bellard
    ts->val_type = TEMP_VAL_CONST;
465 c896fe29 bellard
    ts->name = NULL;
466 c896fe29 bellard
    ts->val = val;
467 c896fe29 bellard
    s->nb_temps++;
468 ac56dd48 pbrook
    return MAKE_TCGV(idx);
469 c896fe29 bellard
}
470 c896fe29 bellard
471 ac56dd48 pbrook
TCGv tcg_const_i64(int64_t val)
472 c896fe29 bellard
{
473 c896fe29 bellard
    TCGContext *s = &tcg_ctx;
474 c896fe29 bellard
    TCGTemp *ts;
475 c896fe29 bellard
    int idx;
476 c896fe29 bellard
477 c896fe29 bellard
    idx = s->nb_temps;
478 c896fe29 bellard
#if TCG_TARGET_REG_BITS == 32
479 c896fe29 bellard
    tcg_temp_alloc(s, idx + 2);
480 c896fe29 bellard
    ts = &s->temps[idx];
481 c896fe29 bellard
    ts->base_type = TCG_TYPE_I64;
482 c896fe29 bellard
    ts->type = TCG_TYPE_I32;
483 c896fe29 bellard
    ts->val_type = TEMP_VAL_CONST;
484 c896fe29 bellard
    ts->name = NULL;
485 c896fe29 bellard
    ts->val = val;
486 c896fe29 bellard
    ts++;
487 c896fe29 bellard
    ts->base_type = TCG_TYPE_I32;
488 c896fe29 bellard
    ts->type = TCG_TYPE_I32;
489 c896fe29 bellard
    ts->val_type = TEMP_VAL_CONST;
490 c896fe29 bellard
    ts->name = NULL;
491 c896fe29 bellard
    ts->val = val >> 32;
492 c896fe29 bellard
    s->nb_temps += 2;
493 c896fe29 bellard
#else
494 c896fe29 bellard
    tcg_temp_alloc(s, idx + 1);
495 c896fe29 bellard
    ts = &s->temps[idx];
496 c896fe29 bellard
    ts->base_type = ts->type = TCG_TYPE_I64;
497 c896fe29 bellard
    ts->val_type = TEMP_VAL_CONST;
498 c896fe29 bellard
    ts->name = NULL;
499 c896fe29 bellard
    ts->val = val;
500 c896fe29 bellard
    s->nb_temps++;
501 c896fe29 bellard
#endif    
502 ac56dd48 pbrook
    return MAKE_TCGV(idx);
503 c896fe29 bellard
}
504 c896fe29 bellard
505 c896fe29 bellard
void tcg_register_helper(void *func, const char *name)
506 c896fe29 bellard
{
507 c896fe29 bellard
    TCGContext *s = &tcg_ctx;
508 c896fe29 bellard
    int n;
509 c896fe29 bellard
    if ((s->nb_helpers + 1) > s->allocated_helpers) {
510 c896fe29 bellard
        n = s->allocated_helpers;
511 c896fe29 bellard
        if (n == 0) {
512 c896fe29 bellard
            n = 4;
513 c896fe29 bellard
        } else {
514 c896fe29 bellard
            n *= 2;
515 c896fe29 bellard
        }
516 c896fe29 bellard
        s->helpers = realloc(s->helpers, n * sizeof(TCGHelperInfo));
517 c896fe29 bellard
        s->allocated_helpers = n;
518 c896fe29 bellard
    }
519 4dc81f28 bellard
    s->helpers[s->nb_helpers].func = (tcg_target_ulong)func;
520 c896fe29 bellard
    s->helpers[s->nb_helpers].name = name;
521 c896fe29 bellard
    s->nb_helpers++;
522 c896fe29 bellard
}
523 c896fe29 bellard
524 ac56dd48 pbrook
static inline TCGType tcg_get_base_type(TCGContext *s, TCGv arg)
525 c896fe29 bellard
{
526 ac56dd48 pbrook
    return s->temps[GET_TCGV(arg)].base_type;
527 c896fe29 bellard
}
528 c896fe29 bellard
529 ac56dd48 pbrook
static void tcg_gen_call_internal(TCGContext *s, TCGv func, 
530 c896fe29 bellard
                                  unsigned int flags,
531 ac56dd48 pbrook
                                  unsigned int nb_rets, const TCGv *rets,
532 ac56dd48 pbrook
                                  unsigned int nb_params, const TCGv *params)
533 c896fe29 bellard
{
534 c896fe29 bellard
    int i;
535 c896fe29 bellard
    *gen_opc_ptr++ = INDEX_op_call;
536 c896fe29 bellard
    *gen_opparam_ptr++ = (nb_rets << 16) | (nb_params + 1);
537 c896fe29 bellard
    for(i = 0; i < nb_rets; i++) {
538 ac56dd48 pbrook
        *gen_opparam_ptr++ = GET_TCGV(rets[i]);
539 c896fe29 bellard
    }
540 c896fe29 bellard
    for(i = 0; i < nb_params; i++) {
541 ac56dd48 pbrook
        *gen_opparam_ptr++ = GET_TCGV(params[i]);
542 c896fe29 bellard
    }
543 ac56dd48 pbrook
    *gen_opparam_ptr++ = GET_TCGV(func);
544 c896fe29 bellard
545 c896fe29 bellard
    *gen_opparam_ptr++ = flags;
546 c896fe29 bellard
    /* total parameters, needed to go backward in the instruction stream */
547 c896fe29 bellard
    *gen_opparam_ptr++ = 1 + nb_rets + nb_params + 3;
548 c896fe29 bellard
}
549 c896fe29 bellard
550 c896fe29 bellard
551 c896fe29 bellard
#if TCG_TARGET_REG_BITS < 64
552 39cf05d3 bellard
/* Note: we convert the 64 bit args to 32 bit and do some alignment
553 39cf05d3 bellard
   and endian swap. Maybe it would be better to do the alignment
554 39cf05d3 bellard
   and endian swap in tcg_reg_alloc_call(). */
555 ac56dd48 pbrook
void tcg_gen_call(TCGContext *s, TCGv func, unsigned int flags,
556 ac56dd48 pbrook
                  unsigned int nb_rets, const TCGv *rets,
557 ac56dd48 pbrook
                  unsigned int nb_params, const TCGv *args1)
558 c896fe29 bellard
{
559 ac56dd48 pbrook
    TCGv ret, *args2, rets_2[2], arg;
560 c896fe29 bellard
    int j, i, call_type;
561 c896fe29 bellard
562 c896fe29 bellard
    if (nb_rets == 1) {
563 c896fe29 bellard
        ret = rets[0];
564 c896fe29 bellard
        if (tcg_get_base_type(s, ret) == TCG_TYPE_I64) {
565 c896fe29 bellard
            nb_rets = 2;
566 39cf05d3 bellard
#ifdef TCG_TARGET_WORDS_BIGENDIAN
567 39cf05d3 bellard
            rets_2[0] = TCGV_HIGH(ret);
568 39cf05d3 bellard
            rets_2[1] = ret;
569 39cf05d3 bellard
#else
570 c896fe29 bellard
            rets_2[0] = ret;
571 ac56dd48 pbrook
            rets_2[1] = TCGV_HIGH(ret);
572 39cf05d3 bellard
#endif
573 c896fe29 bellard
            rets = rets_2;
574 c896fe29 bellard
        }
575 c896fe29 bellard
    }
576 39cf05d3 bellard
    args2 = alloca((nb_params * 3) * sizeof(TCGv));
577 c896fe29 bellard
    j = 0;
578 c896fe29 bellard
    call_type = (flags & TCG_CALL_TYPE_MASK);
579 c896fe29 bellard
    for(i = 0; i < nb_params; i++) {
580 c896fe29 bellard
        arg = args1[i];
581 c896fe29 bellard
        if (tcg_get_base_type(s, arg) == TCG_TYPE_I64) {
582 c896fe29 bellard
#ifdef TCG_TARGET_I386
583 c896fe29 bellard
            /* REGPARM case: if the third parameter is 64 bit, it is
584 c896fe29 bellard
               allocated on the stack */
585 c896fe29 bellard
            if (j == 2 && call_type == TCG_CALL_TYPE_REGPARM) {
586 c896fe29 bellard
                call_type = TCG_CALL_TYPE_REGPARM_2;
587 c896fe29 bellard
                flags = (flags & ~TCG_CALL_TYPE_MASK) | call_type;
588 c896fe29 bellard
            }
589 c896fe29 bellard
            args2[j++] = arg;
590 ac56dd48 pbrook
            args2[j++] = TCGV_HIGH(arg);
591 c896fe29 bellard
#else
592 39cf05d3 bellard
#ifdef TCG_TARGET_CALL_ALIGN_ARGS
593 39cf05d3 bellard
            /* some targets want aligned 64 bit args */
594 39cf05d3 bellard
            if (j & 1) {
595 39cf05d3 bellard
                args2[j++] = TCG_CALL_DUMMY_ARG;
596 39cf05d3 bellard
            }
597 39cf05d3 bellard
#endif
598 c896fe29 bellard
#ifdef TCG_TARGET_WORDS_BIGENDIAN
599 a0d69e00 blueswir1
            args2[j++] = TCGV_HIGH(arg);
600 c896fe29 bellard
            args2[j++] = arg;
601 c896fe29 bellard
#else
602 c896fe29 bellard
            args2[j++] = arg;
603 ac56dd48 pbrook
            args2[j++] = TCGV_HIGH(arg);
604 c896fe29 bellard
#endif
605 c896fe29 bellard
#endif
606 c896fe29 bellard
        } else {
607 c896fe29 bellard
            args2[j++] = arg;
608 c896fe29 bellard
        }
609 c896fe29 bellard
    }
610 c896fe29 bellard
    tcg_gen_call_internal(s, func, flags, 
611 c896fe29 bellard
                          nb_rets, rets, j, args2);
612 c896fe29 bellard
}
613 c896fe29 bellard
#else
614 ac56dd48 pbrook
void tcg_gen_call(TCGContext *s, TCGv func, unsigned int flags,
615 ac56dd48 pbrook
                  unsigned int nb_rets, const TCGv *rets,
616 ac56dd48 pbrook
                  unsigned int nb_params, const TCGv *args1)
617 c896fe29 bellard
{
618 c896fe29 bellard
    tcg_gen_call_internal(s, func, flags, 
619 c896fe29 bellard
                          nb_rets, rets, nb_params, args1);
620 c896fe29 bellard
}
621 c896fe29 bellard
#endif
622 c896fe29 bellard
623 ac56dd48 pbrook
#if TCG_TARGET_REG_BITS == 32
624 ac56dd48 pbrook
void tcg_gen_shifti_i64(TCGv ret, TCGv arg1, 
625 c896fe29 bellard
                        int c, int right, int arith)
626 c896fe29 bellard
{
627 cf60bce4 bellard
    if (c == 0) {
628 cf60bce4 bellard
        tcg_gen_mov_i32(ret, arg1);
629 cf60bce4 bellard
        tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
630 cf60bce4 bellard
    } else if (c >= 32) {
631 c896fe29 bellard
        c -= 32;
632 c896fe29 bellard
        if (right) {
633 c896fe29 bellard
            if (arith) {
634 ac56dd48 pbrook
                tcg_gen_sari_i32(ret, TCGV_HIGH(arg1), c);
635 ac56dd48 pbrook
                tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 31);
636 c896fe29 bellard
            } else {
637 ac56dd48 pbrook
                tcg_gen_shri_i32(ret, TCGV_HIGH(arg1), c);
638 ac56dd48 pbrook
                tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
639 c896fe29 bellard
            }
640 c896fe29 bellard
        } else {
641 ac56dd48 pbrook
            tcg_gen_shli_i32(TCGV_HIGH(ret), arg1, c);
642 c896fe29 bellard
            tcg_gen_movi_i32(ret, 0);
643 c896fe29 bellard
        }
644 c896fe29 bellard
    } else {
645 ac56dd48 pbrook
        TCGv t0, t1;
646 c896fe29 bellard
647 c896fe29 bellard
        t0 = tcg_temp_new(TCG_TYPE_I32);
648 c896fe29 bellard
        t1 = tcg_temp_new(TCG_TYPE_I32);
649 c896fe29 bellard
        if (right) {
650 ac56dd48 pbrook
            tcg_gen_shli_i32(t0, TCGV_HIGH(arg1), 32 - c);
651 c896fe29 bellard
            if (arith)
652 ac56dd48 pbrook
                tcg_gen_sari_i32(t1, TCGV_HIGH(arg1), c);
653 c896fe29 bellard
            else 
654 ac56dd48 pbrook
                tcg_gen_shri_i32(t1, TCGV_HIGH(arg1), c);
655 c896fe29 bellard
            tcg_gen_shri_i32(ret, arg1, c); 
656 c896fe29 bellard
            tcg_gen_or_i32(ret, ret, t0);
657 ac56dd48 pbrook
            tcg_gen_mov_i32(TCGV_HIGH(ret), t1);
658 c896fe29 bellard
        } else {
659 c896fe29 bellard
            tcg_gen_shri_i32(t0, arg1, 32 - c);
660 c896fe29 bellard
            /* Note: ret can be the same as arg1, so we use t1 */
661 c896fe29 bellard
            tcg_gen_shli_i32(t1, arg1, c); 
662 ac56dd48 pbrook
            tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c);
663 ac56dd48 pbrook
            tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t0);
664 c896fe29 bellard
            tcg_gen_mov_i32(ret, t1);
665 c896fe29 bellard
        }
666 c896fe29 bellard
    }
667 c896fe29 bellard
}
668 ac56dd48 pbrook
#endif
669 c896fe29 bellard
670 c896fe29 bellard
void tcg_reg_alloc_start(TCGContext *s)
671 c896fe29 bellard
{
672 c896fe29 bellard
    int i;
673 c896fe29 bellard
    TCGTemp *ts;
674 c896fe29 bellard
    for(i = 0; i < s->nb_globals; i++) {
675 c896fe29 bellard
        ts = &s->temps[i];
676 c896fe29 bellard
        if (ts->fixed_reg) {
677 c896fe29 bellard
            ts->val_type = TEMP_VAL_REG;
678 c896fe29 bellard
        } else {
679 c896fe29 bellard
            ts->val_type = TEMP_VAL_MEM;
680 c896fe29 bellard
        }
681 c896fe29 bellard
    }
682 c896fe29 bellard
    for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
683 c896fe29 bellard
        s->reg_to_temp[i] = -1;
684 c896fe29 bellard
    }
685 c896fe29 bellard
}
686 c896fe29 bellard
687 ac56dd48 pbrook
static char *tcg_get_arg_str_idx(TCGContext *s, char *buf, int buf_size,
688 ac56dd48 pbrook
                                 int idx)
689 c896fe29 bellard
{
690 c896fe29 bellard
    TCGTemp *ts;
691 ac56dd48 pbrook
692 ac56dd48 pbrook
    ts = &s->temps[idx];
693 ac56dd48 pbrook
    if (idx < s->nb_globals) {
694 ac56dd48 pbrook
        pstrcpy(buf, buf_size, ts->name);
695 c896fe29 bellard
    } else {
696 c896fe29 bellard
        if (ts->val_type == TEMP_VAL_CONST) {
697 c896fe29 bellard
            snprintf(buf, buf_size, "$0x%" TCG_PRIlx , ts->val);
698 c896fe29 bellard
        } else {
699 ac56dd48 pbrook
            snprintf(buf, buf_size, "tmp%d", idx - s->nb_globals);
700 c896fe29 bellard
        }
701 c896fe29 bellard
    }
702 c896fe29 bellard
    return buf;
703 c896fe29 bellard
}
704 c896fe29 bellard
705 ac56dd48 pbrook
char *tcg_get_arg_str(TCGContext *s, char *buf, int buf_size, TCGv arg)
706 ac56dd48 pbrook
{
707 ac56dd48 pbrook
    return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV(arg));
708 ac56dd48 pbrook
}
709 ac56dd48 pbrook
710 4dc81f28 bellard
/* find helper definition (XXX: inefficient) */
711 4dc81f28 bellard
static TCGHelperInfo *tcg_find_helper(TCGContext *s, tcg_target_ulong val)
712 4dc81f28 bellard
{
713 4dc81f28 bellard
    int i;
714 4dc81f28 bellard
    for(i = 0; i < s->nb_helpers; i++) {
715 4dc81f28 bellard
        if (s->helpers[i].func == val) 
716 4dc81f28 bellard
            return &s->helpers[i];
717 4dc81f28 bellard
    }
718 4dc81f28 bellard
    return NULL;
719 4dc81f28 bellard
}
720 4dc81f28 bellard
721 4dc81f28 bellard
static const char *tcg_get_helper_str_idx(TCGContext *s, char *buf, int buf_size,
722 4dc81f28 bellard
                                          int idx)
723 4dc81f28 bellard
{
724 4dc81f28 bellard
    TCGTemp *ts;
725 4dc81f28 bellard
    TCGHelperInfo *th;
726 4dc81f28 bellard
727 4dc81f28 bellard
    ts = &s->temps[idx];
728 4dc81f28 bellard
    if (ts->val_type == TEMP_VAL_CONST) {
729 4dc81f28 bellard
        /* find helper name (XXX: inefficient) */
730 4dc81f28 bellard
        th = tcg_find_helper(s, ts->val);
731 4dc81f28 bellard
        if (th) {
732 4dc81f28 bellard
            pstrcpy(buf, buf_size, "$");
733 4dc81f28 bellard
            pstrcat(buf, buf_size, th->name);
734 4dc81f28 bellard
            return buf;
735 4dc81f28 bellard
        }
736 4dc81f28 bellard
    }
737 4dc81f28 bellard
    return tcg_get_arg_str_idx(s, buf, buf_size, idx);
738 4dc81f28 bellard
}
739 4dc81f28 bellard
740 4dc81f28 bellard
741 c896fe29 bellard
void tcg_dump_ops(TCGContext *s, FILE *outfile)
742 c896fe29 bellard
{
743 c896fe29 bellard
    const uint16_t *opc_ptr;
744 c896fe29 bellard
    const TCGArg *args;
745 c896fe29 bellard
    TCGArg arg;
746 7e4597d7 bellard
    int c, i, k, nb_oargs, nb_iargs, nb_cargs, first_insn;
747 c896fe29 bellard
    const TCGOpDef *def;
748 c896fe29 bellard
    char buf[128];
749 c896fe29 bellard
750 7e4597d7 bellard
    first_insn = 1;
751 c896fe29 bellard
    opc_ptr = gen_opc_buf;
752 c896fe29 bellard
    args = gen_opparam_buf;
753 c896fe29 bellard
    while (opc_ptr < gen_opc_ptr) {
754 c896fe29 bellard
        c = *opc_ptr++;
755 c896fe29 bellard
        def = &tcg_op_defs[c];
756 7e4597d7 bellard
        if (c == INDEX_op_debug_insn_start) {
757 7e4597d7 bellard
            uint64_t pc;
758 7e4597d7 bellard
#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
759 7e4597d7 bellard
            pc = ((uint64_t)args[1] << 32) | args[0];
760 7e4597d7 bellard
#else
761 7e4597d7 bellard
            pc = args[0];
762 7e4597d7 bellard
#endif
763 7e4597d7 bellard
            if (!first_insn) 
764 7e4597d7 bellard
                fprintf(outfile, "\n");
765 7e4597d7 bellard
            fprintf(outfile, " ---- 0x%" PRIx64, pc);
766 7e4597d7 bellard
            first_insn = 0;
767 7e4597d7 bellard
            nb_oargs = def->nb_oargs;
768 7e4597d7 bellard
            nb_iargs = def->nb_iargs;
769 7e4597d7 bellard
            nb_cargs = def->nb_cargs;
770 7e4597d7 bellard
        } else if (c == INDEX_op_call) {
771 c896fe29 bellard
            TCGArg arg;
772 4dc81f28 bellard
773 c896fe29 bellard
            /* variable number of arguments */
774 c896fe29 bellard
            arg = *args++;
775 c896fe29 bellard
            nb_oargs = arg >> 16;
776 c896fe29 bellard
            nb_iargs = arg & 0xffff;
777 c896fe29 bellard
            nb_cargs = def->nb_cargs;
778 c896fe29 bellard
779 7e4597d7 bellard
            fprintf(outfile, " %s ", def->name);
780 7e4597d7 bellard
781 b03cce8e bellard
            /* function name */
782 ac56dd48 pbrook
            fprintf(outfile, "%s",
783 4dc81f28 bellard
                    tcg_get_helper_str_idx(s, buf, sizeof(buf), args[nb_oargs + nb_iargs - 1]));
784 b03cce8e bellard
            /* flags */
785 b03cce8e bellard
            fprintf(outfile, ",$0x%" TCG_PRIlx,
786 b03cce8e bellard
                    args[nb_oargs + nb_iargs]);
787 b03cce8e bellard
            /* nb out args */
788 b03cce8e bellard
            fprintf(outfile, ",$%d", nb_oargs);
789 b03cce8e bellard
            for(i = 0; i < nb_oargs; i++) {
790 b03cce8e bellard
                fprintf(outfile, ",");
791 b03cce8e bellard
                fprintf(outfile, "%s",
792 b03cce8e bellard
                        tcg_get_arg_str_idx(s, buf, sizeof(buf), args[i]));
793 b03cce8e bellard
            }
794 b03cce8e bellard
            for(i = 0; i < (nb_iargs - 1); i++) {
795 c896fe29 bellard
                fprintf(outfile, ",");
796 39cf05d3 bellard
                if (args[nb_oargs + i] == TCG_CALL_DUMMY_ARG) {
797 39cf05d3 bellard
                    fprintf(outfile, "<dummy>");
798 39cf05d3 bellard
                } else {
799 39cf05d3 bellard
                    fprintf(outfile, "%s",
800 39cf05d3 bellard
                            tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + i]));
801 39cf05d3 bellard
                }
802 b03cce8e bellard
            }
803 b03cce8e bellard
        } else {
804 7e4597d7 bellard
            fprintf(outfile, " %s ", def->name);
805 b03cce8e bellard
            if (c == INDEX_op_nopn) {
806 b03cce8e bellard
                /* variable number of arguments */
807 b03cce8e bellard
                nb_cargs = *args;
808 b03cce8e bellard
                nb_oargs = 0;
809 b03cce8e bellard
                nb_iargs = 0;
810 b03cce8e bellard
            } else {
811 b03cce8e bellard
                nb_oargs = def->nb_oargs;
812 b03cce8e bellard
                nb_iargs = def->nb_iargs;
813 b03cce8e bellard
                nb_cargs = def->nb_cargs;
814 b03cce8e bellard
            }
815 b03cce8e bellard
            
816 b03cce8e bellard
            k = 0;
817 b03cce8e bellard
            for(i = 0; i < nb_oargs; i++) {
818 b03cce8e bellard
                if (k != 0)
819 b03cce8e bellard
                    fprintf(outfile, ",");
820 b03cce8e bellard
                fprintf(outfile, "%s",
821 b03cce8e bellard
                        tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
822 b03cce8e bellard
            }
823 b03cce8e bellard
            for(i = 0; i < nb_iargs; i++) {
824 b03cce8e bellard
                if (k != 0)
825 b03cce8e bellard
                    fprintf(outfile, ",");
826 b03cce8e bellard
                fprintf(outfile, "%s",
827 b03cce8e bellard
                        tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
828 b03cce8e bellard
            }
829 b03cce8e bellard
            for(i = 0; i < nb_cargs; i++) {
830 b03cce8e bellard
                if (k != 0)
831 b03cce8e bellard
                    fprintf(outfile, ",");
832 b03cce8e bellard
                arg = args[k++];
833 b03cce8e bellard
                fprintf(outfile, "$0x%" TCG_PRIlx, arg);
834 b03cce8e bellard
            }
835 c896fe29 bellard
        }
836 c896fe29 bellard
        fprintf(outfile, "\n");
837 c896fe29 bellard
        args += nb_iargs + nb_oargs + nb_cargs;
838 c896fe29 bellard
    }
839 c896fe29 bellard
}
840 c896fe29 bellard
841 c896fe29 bellard
/* we give more priority to constraints with less registers */
842 c896fe29 bellard
static int get_constraint_priority(const TCGOpDef *def, int k)
843 c896fe29 bellard
{
844 c896fe29 bellard
    const TCGArgConstraint *arg_ct;
845 c896fe29 bellard
846 c896fe29 bellard
    int i, n;
847 c896fe29 bellard
    arg_ct = &def->args_ct[k];
848 c896fe29 bellard
    if (arg_ct->ct & TCG_CT_ALIAS) {
849 c896fe29 bellard
        /* an alias is equivalent to a single register */
850 c896fe29 bellard
        n = 1;
851 c896fe29 bellard
    } else {
852 c896fe29 bellard
        if (!(arg_ct->ct & TCG_CT_REG))
853 c896fe29 bellard
            return 0;
854 c896fe29 bellard
        n = 0;
855 c896fe29 bellard
        for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
856 c896fe29 bellard
            if (tcg_regset_test_reg(arg_ct->u.regs, i))
857 c896fe29 bellard
                n++;
858 c896fe29 bellard
        }
859 c896fe29 bellard
    }
860 c896fe29 bellard
    return TCG_TARGET_NB_REGS - n + 1;
861 c896fe29 bellard
}
862 c896fe29 bellard
863 c896fe29 bellard
/* sort from highest priority to lowest */
864 c896fe29 bellard
static void sort_constraints(TCGOpDef *def, int start, int n)
865 c896fe29 bellard
{
866 c896fe29 bellard
    int i, j, p1, p2, tmp;
867 c896fe29 bellard
868 c896fe29 bellard
    for(i = 0; i < n; i++)
869 c896fe29 bellard
        def->sorted_args[start + i] = start + i;
870 c896fe29 bellard
    if (n <= 1)
871 c896fe29 bellard
        return;
872 c896fe29 bellard
    for(i = 0; i < n - 1; i++) {
873 c896fe29 bellard
        for(j = i + 1; j < n; j++) {
874 c896fe29 bellard
            p1 = get_constraint_priority(def, def->sorted_args[start + i]);
875 c896fe29 bellard
            p2 = get_constraint_priority(def, def->sorted_args[start + j]);
876 c896fe29 bellard
            if (p1 < p2) {
877 c896fe29 bellard
                tmp = def->sorted_args[start + i];
878 c896fe29 bellard
                def->sorted_args[start + i] = def->sorted_args[start + j];
879 c896fe29 bellard
                def->sorted_args[start + j] = tmp;
880 c896fe29 bellard
            }
881 c896fe29 bellard
        }
882 c896fe29 bellard
    }
883 c896fe29 bellard
}
884 c896fe29 bellard
885 c896fe29 bellard
void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs)
886 c896fe29 bellard
{
887 c896fe29 bellard
    int op;
888 c896fe29 bellard
    TCGOpDef *def;
889 c896fe29 bellard
    const char *ct_str;
890 c896fe29 bellard
    int i, nb_args;
891 c896fe29 bellard
892 c896fe29 bellard
    for(;;) {
893 c896fe29 bellard
        if (tdefs->op < 0)
894 c896fe29 bellard
            break;
895 c896fe29 bellard
        op = tdefs->op;
896 c896fe29 bellard
        assert(op >= 0 && op < NB_OPS);
897 c896fe29 bellard
        def = &tcg_op_defs[op];
898 c896fe29 bellard
        nb_args = def->nb_iargs + def->nb_oargs;
899 c896fe29 bellard
        for(i = 0; i < nb_args; i++) {
900 c896fe29 bellard
            ct_str = tdefs->args_ct_str[i];
901 c896fe29 bellard
            tcg_regset_clear(def->args_ct[i].u.regs);
902 c896fe29 bellard
            def->args_ct[i].ct = 0;
903 c896fe29 bellard
            if (ct_str[0] >= '0' && ct_str[0] <= '9') {
904 c896fe29 bellard
                int oarg;
905 c896fe29 bellard
                oarg = ct_str[0] - '0';
906 c896fe29 bellard
                assert(oarg < def->nb_oargs);
907 c896fe29 bellard
                assert(def->args_ct[oarg].ct & TCG_CT_REG);
908 c896fe29 bellard
                /* TCG_CT_ALIAS is for the output arguments. The input
909 5ff9d6a4 bellard
                   argument is tagged with TCG_CT_IALIAS. */
910 c896fe29 bellard
                def->args_ct[i] = def->args_ct[oarg];
911 5ff9d6a4 bellard
                def->args_ct[oarg].ct = TCG_CT_ALIAS;
912 5ff9d6a4 bellard
                def->args_ct[oarg].alias_index = i;
913 c896fe29 bellard
                def->args_ct[i].ct |= TCG_CT_IALIAS;
914 5ff9d6a4 bellard
                def->args_ct[i].alias_index = oarg;
915 c896fe29 bellard
            } else {
916 c896fe29 bellard
                for(;;) {
917 c896fe29 bellard
                    if (*ct_str == '\0')
918 c896fe29 bellard
                        break;
919 c896fe29 bellard
                    switch(*ct_str) {
920 c896fe29 bellard
                    case 'i':
921 c896fe29 bellard
                        def->args_ct[i].ct |= TCG_CT_CONST;
922 c896fe29 bellard
                        ct_str++;
923 c896fe29 bellard
                        break;
924 c896fe29 bellard
                    default:
925 c896fe29 bellard
                        if (target_parse_constraint(&def->args_ct[i], &ct_str) < 0) {
926 c896fe29 bellard
                            fprintf(stderr, "Invalid constraint '%s' for arg %d of operation '%s'\n",
927 c896fe29 bellard
                                    ct_str, i, def->name);
928 c896fe29 bellard
                            exit(1);
929 c896fe29 bellard
                        }
930 c896fe29 bellard
                    }
931 c896fe29 bellard
                }
932 c896fe29 bellard
            }
933 c896fe29 bellard
        }
934 c896fe29 bellard
935 c896fe29 bellard
        /* sort the constraints (XXX: this is just an heuristic) */
936 c896fe29 bellard
        sort_constraints(def, 0, def->nb_oargs);
937 c896fe29 bellard
        sort_constraints(def, def->nb_oargs, def->nb_iargs);
938 c896fe29 bellard
939 c896fe29 bellard
#if 0
940 c896fe29 bellard
        {
941 c896fe29 bellard
            int i;
942 c896fe29 bellard

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