Statistics
| Branch: | Revision:

root / tcg / tcg.c @ ed23fbd9

History | View | Annotate | Download (61.6 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
void tcg_context_init(TCGContext *s)
200 c896fe29 bellard
{
201 c896fe29 bellard
    int op, total_args, n;
202 c896fe29 bellard
    TCGOpDef *def;
203 c896fe29 bellard
    TCGArgConstraint *args_ct;
204 c896fe29 bellard
    int *sorted_args;
205 c896fe29 bellard
206 c896fe29 bellard
    memset(s, 0, sizeof(*s));
207 c896fe29 bellard
    s->temps = s->static_temps;
208 c896fe29 bellard
    s->nb_globals = 0;
209 c896fe29 bellard
    
210 c896fe29 bellard
    /* Count total number of arguments and allocate the corresponding
211 c896fe29 bellard
       space */
212 c896fe29 bellard
    total_args = 0;
213 c896fe29 bellard
    for(op = 0; op < NB_OPS; op++) {
214 c896fe29 bellard
        def = &tcg_op_defs[op];
215 c896fe29 bellard
        n = def->nb_iargs + def->nb_oargs;
216 c896fe29 bellard
        total_args += n;
217 c896fe29 bellard
    }
218 c896fe29 bellard
219 c896fe29 bellard
    args_ct = qemu_malloc(sizeof(TCGArgConstraint) * total_args);
220 c896fe29 bellard
    sorted_args = qemu_malloc(sizeof(int) * total_args);
221 c896fe29 bellard
222 c896fe29 bellard
    for(op = 0; op < NB_OPS; op++) {
223 c896fe29 bellard
        def = &tcg_op_defs[op];
224 c896fe29 bellard
        def->args_ct = args_ct;
225 c896fe29 bellard
        def->sorted_args = sorted_args;
226 c896fe29 bellard
        n = def->nb_iargs + def->nb_oargs;
227 c896fe29 bellard
        sorted_args += n;
228 c896fe29 bellard
        args_ct += n;
229 c896fe29 bellard
    }
230 c896fe29 bellard
    
231 c896fe29 bellard
    tcg_target_init(s);
232 b03cce8e bellard
233 b03cce8e bellard
    /* init global prologue and epilogue */
234 b03cce8e bellard
    s->code_buf = code_gen_prologue;
235 b03cce8e bellard
    s->code_ptr = s->code_buf;
236 b03cce8e bellard
    tcg_target_qemu_prologue(s);
237 b03cce8e bellard
    flush_icache_range((unsigned long)s->code_buf, 
238 b03cce8e bellard
                       (unsigned long)s->code_ptr);
239 c896fe29 bellard
}
240 c896fe29 bellard
241 c896fe29 bellard
void tcg_set_frame(TCGContext *s, int reg,
242 c896fe29 bellard
                   tcg_target_long start, tcg_target_long size)
243 c896fe29 bellard
{
244 c896fe29 bellard
    s->frame_start = start;
245 c896fe29 bellard
    s->frame_end = start + size;
246 c896fe29 bellard
    s->frame_reg = reg;
247 c896fe29 bellard
}
248 c896fe29 bellard
249 c896fe29 bellard
void tcg_func_start(TCGContext *s)
250 c896fe29 bellard
{
251 e8996ee0 bellard
    int i;
252 c896fe29 bellard
    tcg_pool_reset(s);
253 c896fe29 bellard
    s->nb_temps = s->nb_globals;
254 641d5fbe bellard
    for(i = 0; i < (TCG_TYPE_COUNT * 2); i++)
255 e8996ee0 bellard
        s->first_free_temp[i] = -1;
256 c896fe29 bellard
    s->labels = tcg_malloc(sizeof(TCGLabel) * TCG_MAX_LABELS);
257 c896fe29 bellard
    s->nb_labels = 0;
258 c896fe29 bellard
    s->current_frame_offset = s->frame_start;
259 c896fe29 bellard
260 c896fe29 bellard
    gen_opc_ptr = gen_opc_buf;
261 c896fe29 bellard
    gen_opparam_ptr = gen_opparam_buf;
262 c896fe29 bellard
}
263 c896fe29 bellard
264 c896fe29 bellard
static inline void tcg_temp_alloc(TCGContext *s, int n)
265 c896fe29 bellard
{
266 c896fe29 bellard
    if (n > TCG_MAX_TEMPS)
267 c896fe29 bellard
        tcg_abort();
268 c896fe29 bellard
}
269 c896fe29 bellard
270 ac56dd48 pbrook
TCGv tcg_global_reg_new(TCGType type, int reg, const char *name)
271 c896fe29 bellard
{
272 c896fe29 bellard
    TCGContext *s = &tcg_ctx;
273 c896fe29 bellard
    TCGTemp *ts;
274 c896fe29 bellard
    int idx;
275 c896fe29 bellard
276 c896fe29 bellard
#if TCG_TARGET_REG_BITS == 32
277 c896fe29 bellard
    if (type != TCG_TYPE_I32)
278 c896fe29 bellard
        tcg_abort();
279 c896fe29 bellard
#endif
280 c896fe29 bellard
    if (tcg_regset_test_reg(s->reserved_regs, reg))
281 c896fe29 bellard
        tcg_abort();
282 c896fe29 bellard
    idx = s->nb_globals;
283 c896fe29 bellard
    tcg_temp_alloc(s, s->nb_globals + 1);
284 c896fe29 bellard
    ts = &s->temps[s->nb_globals];
285 c896fe29 bellard
    ts->base_type = type;
286 c896fe29 bellard
    ts->type = type;
287 c896fe29 bellard
    ts->fixed_reg = 1;
288 c896fe29 bellard
    ts->reg = reg;
289 c896fe29 bellard
    ts->name = name;
290 c896fe29 bellard
    s->nb_globals++;
291 c896fe29 bellard
    tcg_regset_set_reg(s->reserved_regs, reg);
292 ac56dd48 pbrook
    return MAKE_TCGV(idx);
293 c896fe29 bellard
}
294 c896fe29 bellard
295 6a8d7b76 bellard
#if TCG_TARGET_REG_BITS == 32
296 6a8d7b76 bellard
/* temporary hack to avoid register shortage for tcg_qemu_st64() */
297 6a8d7b76 bellard
TCGv tcg_global_reg2_new_hack(TCGType type, int reg1, int reg2, 
298 6a8d7b76 bellard
                              const char *name)
299 6a8d7b76 bellard
{
300 6a8d7b76 bellard
    TCGContext *s = &tcg_ctx;
301 6a8d7b76 bellard
    TCGTemp *ts;
302 6a8d7b76 bellard
    int idx;
303 6a8d7b76 bellard
    char buf[64];
304 6a8d7b76 bellard
305 6a8d7b76 bellard
    if (type != TCG_TYPE_I64)
306 6a8d7b76 bellard
        tcg_abort();
307 6a8d7b76 bellard
    idx = s->nb_globals;
308 6a8d7b76 bellard
    tcg_temp_alloc(s, s->nb_globals + 2);
309 6a8d7b76 bellard
    ts = &s->temps[s->nb_globals];
310 6a8d7b76 bellard
    ts->base_type = type;
311 6a8d7b76 bellard
    ts->type = TCG_TYPE_I32;
312 6a8d7b76 bellard
    ts->fixed_reg = 1;
313 6a8d7b76 bellard
    ts->reg = reg1;
314 6a8d7b76 bellard
    pstrcpy(buf, sizeof(buf), name);
315 6a8d7b76 bellard
    pstrcat(buf, sizeof(buf), "_0");
316 6a8d7b76 bellard
    ts->name = strdup(buf);
317 6a8d7b76 bellard
318 6a8d7b76 bellard
    ts++;
319 6a8d7b76 bellard
    ts->base_type = type;
320 6a8d7b76 bellard
    ts->type = TCG_TYPE_I32;
321 6a8d7b76 bellard
    ts->fixed_reg = 1;
322 6a8d7b76 bellard
    ts->reg = reg2;
323 6a8d7b76 bellard
    pstrcpy(buf, sizeof(buf), name);
324 6a8d7b76 bellard
    pstrcat(buf, sizeof(buf), "_1");
325 6a8d7b76 bellard
    ts->name = strdup(buf);
326 6a8d7b76 bellard
327 6a8d7b76 bellard
    s->nb_globals += 2;
328 6a8d7b76 bellard
    return MAKE_TCGV(idx);
329 6a8d7b76 bellard
}
330 6a8d7b76 bellard
#endif
331 6a8d7b76 bellard
332 ac56dd48 pbrook
TCGv tcg_global_mem_new(TCGType type, int reg, tcg_target_long offset,
333 ac56dd48 pbrook
                        const char *name)
334 c896fe29 bellard
{
335 c896fe29 bellard
    TCGContext *s = &tcg_ctx;
336 c896fe29 bellard
    TCGTemp *ts;
337 c896fe29 bellard
    int idx;
338 c896fe29 bellard
339 c896fe29 bellard
    idx = s->nb_globals;
340 c896fe29 bellard
#if TCG_TARGET_REG_BITS == 32
341 c896fe29 bellard
    if (type == TCG_TYPE_I64) {
342 c896fe29 bellard
        char buf[64];
343 c588979b ths
        tcg_temp_alloc(s, s->nb_globals + 2);
344 c896fe29 bellard
        ts = &s->temps[s->nb_globals];
345 c896fe29 bellard
        ts->base_type = type;
346 c896fe29 bellard
        ts->type = TCG_TYPE_I32;
347 c896fe29 bellard
        ts->fixed_reg = 0;
348 c896fe29 bellard
        ts->mem_allocated = 1;
349 c896fe29 bellard
        ts->mem_reg = reg;
350 c896fe29 bellard
#ifdef TCG_TARGET_WORDS_BIGENDIAN
351 c896fe29 bellard
        ts->mem_offset = offset + 4;
352 c896fe29 bellard
#else
353 c896fe29 bellard
        ts->mem_offset = offset;
354 c896fe29 bellard
#endif
355 c896fe29 bellard
        pstrcpy(buf, sizeof(buf), name);
356 c896fe29 bellard
        pstrcat(buf, sizeof(buf), "_0");
357 c896fe29 bellard
        ts->name = strdup(buf);
358 c896fe29 bellard
        ts++;
359 c896fe29 bellard
360 c896fe29 bellard
        ts->base_type = type;
361 c896fe29 bellard
        ts->type = TCG_TYPE_I32;
362 c896fe29 bellard
        ts->fixed_reg = 0;
363 c896fe29 bellard
        ts->mem_allocated = 1;
364 c896fe29 bellard
        ts->mem_reg = reg;
365 c896fe29 bellard
#ifdef TCG_TARGET_WORDS_BIGENDIAN
366 c896fe29 bellard
        ts->mem_offset = offset;
367 c896fe29 bellard
#else
368 c896fe29 bellard
        ts->mem_offset = offset + 4;
369 c896fe29 bellard
#endif
370 c896fe29 bellard
        pstrcpy(buf, sizeof(buf), name);
371 c896fe29 bellard
        pstrcat(buf, sizeof(buf), "_1");
372 c896fe29 bellard
        ts->name = strdup(buf);
373 c896fe29 bellard
374 c896fe29 bellard
        s->nb_globals += 2;
375 c896fe29 bellard
    } else
376 c896fe29 bellard
#endif
377 c896fe29 bellard
    {
378 c896fe29 bellard
        tcg_temp_alloc(s, s->nb_globals + 1);
379 c896fe29 bellard
        ts = &s->temps[s->nb_globals];
380 c896fe29 bellard
        ts->base_type = type;
381 c896fe29 bellard
        ts->type = type;
382 c896fe29 bellard
        ts->fixed_reg = 0;
383 c896fe29 bellard
        ts->mem_allocated = 1;
384 c896fe29 bellard
        ts->mem_reg = reg;
385 c896fe29 bellard
        ts->mem_offset = offset;
386 c896fe29 bellard
        ts->name = name;
387 c896fe29 bellard
        s->nb_globals++;
388 c896fe29 bellard
    }
389 ac56dd48 pbrook
    return MAKE_TCGV(idx);
390 c896fe29 bellard
}
391 c896fe29 bellard
392 641d5fbe bellard
TCGv tcg_temp_new_internal(TCGType type, int temp_local)
393 c896fe29 bellard
{
394 c896fe29 bellard
    TCGContext *s = &tcg_ctx;
395 c896fe29 bellard
    TCGTemp *ts;
396 641d5fbe bellard
    int idx, k;
397 c896fe29 bellard
398 641d5fbe bellard
    k = type;
399 641d5fbe bellard
    if (temp_local)
400 641d5fbe bellard
        k += TCG_TYPE_COUNT;
401 641d5fbe bellard
    idx = s->first_free_temp[k];
402 e8996ee0 bellard
    if (idx != -1) {
403 e8996ee0 bellard
        /* There is already an available temp with the
404 e8996ee0 bellard
           right type */
405 e8996ee0 bellard
        ts = &s->temps[idx];
406 641d5fbe bellard
        s->first_free_temp[k] = ts->next_free_temp;
407 e8996ee0 bellard
        ts->temp_allocated = 1;
408 641d5fbe bellard
        assert(ts->temp_local == temp_local);
409 e8996ee0 bellard
    } else {
410 e8996ee0 bellard
        idx = s->nb_temps;
411 c896fe29 bellard
#if TCG_TARGET_REG_BITS == 32
412 e8996ee0 bellard
        if (type == TCG_TYPE_I64) {
413 8df1ca4b ths
            tcg_temp_alloc(s, s->nb_temps + 2);
414 e8996ee0 bellard
            ts = &s->temps[s->nb_temps];
415 e8996ee0 bellard
            ts->base_type = type;
416 e8996ee0 bellard
            ts->type = TCG_TYPE_I32;
417 e8996ee0 bellard
            ts->temp_allocated = 1;
418 641d5fbe bellard
            ts->temp_local = temp_local;
419 e8996ee0 bellard
            ts->name = NULL;
420 e8996ee0 bellard
            ts++;
421 e8996ee0 bellard
            ts->base_type = TCG_TYPE_I32;
422 e8996ee0 bellard
            ts->type = TCG_TYPE_I32;
423 e8996ee0 bellard
            ts->temp_allocated = 1;
424 641d5fbe bellard
            ts->temp_local = temp_local;
425 e8996ee0 bellard
            ts->name = NULL;
426 e8996ee0 bellard
            s->nb_temps += 2;
427 e8996ee0 bellard
        } else
428 c896fe29 bellard
#endif
429 e8996ee0 bellard
        {
430 e8996ee0 bellard
            tcg_temp_alloc(s, s->nb_temps + 1);
431 e8996ee0 bellard
            ts = &s->temps[s->nb_temps];
432 e8996ee0 bellard
            ts->base_type = type;
433 e8996ee0 bellard
            ts->type = type;
434 e8996ee0 bellard
            ts->temp_allocated = 1;
435 641d5fbe bellard
            ts->temp_local = temp_local;
436 e8996ee0 bellard
            ts->name = NULL;
437 e8996ee0 bellard
            s->nb_temps++;
438 e8996ee0 bellard
        }
439 c896fe29 bellard
    }
440 ac56dd48 pbrook
    return MAKE_TCGV(idx);
441 c896fe29 bellard
}
442 c896fe29 bellard
443 e8996ee0 bellard
void tcg_temp_free(TCGv arg)
444 c896fe29 bellard
{
445 c896fe29 bellard
    TCGContext *s = &tcg_ctx;
446 c896fe29 bellard
    TCGTemp *ts;
447 e8996ee0 bellard
    int idx = GET_TCGV(arg);
448 641d5fbe bellard
    int k;
449 c896fe29 bellard
450 e8996ee0 bellard
    assert(idx >= s->nb_globals && idx < s->nb_temps);
451 c896fe29 bellard
    ts = &s->temps[idx];
452 e8996ee0 bellard
    assert(ts->temp_allocated != 0);
453 e8996ee0 bellard
    ts->temp_allocated = 0;
454 641d5fbe bellard
    k = ts->base_type;
455 641d5fbe bellard
    if (ts->temp_local)
456 641d5fbe bellard
        k += TCG_TYPE_COUNT;
457 641d5fbe bellard
    ts->next_free_temp = s->first_free_temp[k];
458 641d5fbe bellard
    s->first_free_temp[k] = idx;
459 c896fe29 bellard
}
460 c896fe29 bellard
461 e8996ee0 bellard
462 e8996ee0 bellard
TCGv tcg_const_i32(int32_t val)
463 c896fe29 bellard
{
464 e8996ee0 bellard
    TCGv t0;
465 e8996ee0 bellard
    t0 = tcg_temp_new(TCG_TYPE_I32);
466 e8996ee0 bellard
    tcg_gen_movi_i32(t0, val);
467 e8996ee0 bellard
    return t0;
468 e8996ee0 bellard
}
469 c896fe29 bellard
470 e8996ee0 bellard
TCGv tcg_const_i64(int64_t val)
471 e8996ee0 bellard
{
472 e8996ee0 bellard
    TCGv t0;
473 e8996ee0 bellard
    t0 = tcg_temp_new(TCG_TYPE_I64);
474 e8996ee0 bellard
    tcg_gen_movi_i64(t0, val);
475 e8996ee0 bellard
    return t0;
476 c896fe29 bellard
}
477 c896fe29 bellard
478 c896fe29 bellard
void tcg_register_helper(void *func, const char *name)
479 c896fe29 bellard
{
480 c896fe29 bellard
    TCGContext *s = &tcg_ctx;
481 c896fe29 bellard
    int n;
482 c896fe29 bellard
    if ((s->nb_helpers + 1) > s->allocated_helpers) {
483 c896fe29 bellard
        n = s->allocated_helpers;
484 c896fe29 bellard
        if (n == 0) {
485 c896fe29 bellard
            n = 4;
486 c896fe29 bellard
        } else {
487 c896fe29 bellard
            n *= 2;
488 c896fe29 bellard
        }
489 c896fe29 bellard
        s->helpers = realloc(s->helpers, n * sizeof(TCGHelperInfo));
490 c896fe29 bellard
        s->allocated_helpers = n;
491 c896fe29 bellard
    }
492 4dc81f28 bellard
    s->helpers[s->nb_helpers].func = (tcg_target_ulong)func;
493 c896fe29 bellard
    s->helpers[s->nb_helpers].name = name;
494 c896fe29 bellard
    s->nb_helpers++;
495 c896fe29 bellard
}
496 c896fe29 bellard
497 ac56dd48 pbrook
static inline TCGType tcg_get_base_type(TCGContext *s, TCGv arg)
498 c896fe29 bellard
{
499 ac56dd48 pbrook
    return s->temps[GET_TCGV(arg)].base_type;
500 c896fe29 bellard
}
501 c896fe29 bellard
502 ac56dd48 pbrook
static void tcg_gen_call_internal(TCGContext *s, TCGv func, 
503 c896fe29 bellard
                                  unsigned int flags,
504 ac56dd48 pbrook
                                  unsigned int nb_rets, const TCGv *rets,
505 ac56dd48 pbrook
                                  unsigned int nb_params, const TCGv *params)
506 c896fe29 bellard
{
507 c896fe29 bellard
    int i;
508 c896fe29 bellard
    *gen_opc_ptr++ = INDEX_op_call;
509 c896fe29 bellard
    *gen_opparam_ptr++ = (nb_rets << 16) | (nb_params + 1);
510 c896fe29 bellard
    for(i = 0; i < nb_rets; i++) {
511 ac56dd48 pbrook
        *gen_opparam_ptr++ = GET_TCGV(rets[i]);
512 c896fe29 bellard
    }
513 c896fe29 bellard
    for(i = 0; i < nb_params; i++) {
514 ac56dd48 pbrook
        *gen_opparam_ptr++ = GET_TCGV(params[i]);
515 c896fe29 bellard
    }
516 ac56dd48 pbrook
    *gen_opparam_ptr++ = GET_TCGV(func);
517 c896fe29 bellard
518 c896fe29 bellard
    *gen_opparam_ptr++ = flags;
519 c896fe29 bellard
    /* total parameters, needed to go backward in the instruction stream */
520 c896fe29 bellard
    *gen_opparam_ptr++ = 1 + nb_rets + nb_params + 3;
521 c896fe29 bellard
}
522 c896fe29 bellard
523 c896fe29 bellard
524 c896fe29 bellard
#if TCG_TARGET_REG_BITS < 64
525 39cf05d3 bellard
/* Note: we convert the 64 bit args to 32 bit and do some alignment
526 39cf05d3 bellard
   and endian swap. Maybe it would be better to do the alignment
527 39cf05d3 bellard
   and endian swap in tcg_reg_alloc_call(). */
528 ac56dd48 pbrook
void tcg_gen_call(TCGContext *s, TCGv func, unsigned int flags,
529 ac56dd48 pbrook
                  unsigned int nb_rets, const TCGv *rets,
530 ac56dd48 pbrook
                  unsigned int nb_params, const TCGv *args1)
531 c896fe29 bellard
{
532 ac56dd48 pbrook
    TCGv ret, *args2, rets_2[2], arg;
533 c896fe29 bellard
    int j, i, call_type;
534 c896fe29 bellard
535 c896fe29 bellard
    if (nb_rets == 1) {
536 c896fe29 bellard
        ret = rets[0];
537 c896fe29 bellard
        if (tcg_get_base_type(s, ret) == TCG_TYPE_I64) {
538 c896fe29 bellard
            nb_rets = 2;
539 39cf05d3 bellard
#ifdef TCG_TARGET_WORDS_BIGENDIAN
540 39cf05d3 bellard
            rets_2[0] = TCGV_HIGH(ret);
541 39cf05d3 bellard
            rets_2[1] = ret;
542 39cf05d3 bellard
#else
543 c896fe29 bellard
            rets_2[0] = ret;
544 ac56dd48 pbrook
            rets_2[1] = TCGV_HIGH(ret);
545 39cf05d3 bellard
#endif
546 c896fe29 bellard
            rets = rets_2;
547 c896fe29 bellard
        }
548 c896fe29 bellard
    }
549 39cf05d3 bellard
    args2 = alloca((nb_params * 3) * sizeof(TCGv));
550 c896fe29 bellard
    j = 0;
551 c896fe29 bellard
    call_type = (flags & TCG_CALL_TYPE_MASK);
552 c896fe29 bellard
    for(i = 0; i < nb_params; i++) {
553 c896fe29 bellard
        arg = args1[i];
554 c896fe29 bellard
        if (tcg_get_base_type(s, arg) == TCG_TYPE_I64) {
555 c896fe29 bellard
#ifdef TCG_TARGET_I386
556 c896fe29 bellard
            /* REGPARM case: if the third parameter is 64 bit, it is
557 c896fe29 bellard
               allocated on the stack */
558 c896fe29 bellard
            if (j == 2 && call_type == TCG_CALL_TYPE_REGPARM) {
559 c896fe29 bellard
                call_type = TCG_CALL_TYPE_REGPARM_2;
560 c896fe29 bellard
                flags = (flags & ~TCG_CALL_TYPE_MASK) | call_type;
561 c896fe29 bellard
            }
562 c896fe29 bellard
            args2[j++] = arg;
563 ac56dd48 pbrook
            args2[j++] = TCGV_HIGH(arg);
564 c896fe29 bellard
#else
565 39cf05d3 bellard
#ifdef TCG_TARGET_CALL_ALIGN_ARGS
566 39cf05d3 bellard
            /* some targets want aligned 64 bit args */
567 39cf05d3 bellard
            if (j & 1) {
568 39cf05d3 bellard
                args2[j++] = TCG_CALL_DUMMY_ARG;
569 39cf05d3 bellard
            }
570 39cf05d3 bellard
#endif
571 c896fe29 bellard
#ifdef TCG_TARGET_WORDS_BIGENDIAN
572 a0d69e00 blueswir1
            args2[j++] = TCGV_HIGH(arg);
573 c896fe29 bellard
            args2[j++] = arg;
574 c896fe29 bellard
#else
575 c896fe29 bellard
            args2[j++] = arg;
576 ac56dd48 pbrook
            args2[j++] = TCGV_HIGH(arg);
577 c896fe29 bellard
#endif
578 c896fe29 bellard
#endif
579 c896fe29 bellard
        } else {
580 c896fe29 bellard
            args2[j++] = arg;
581 c896fe29 bellard
        }
582 c896fe29 bellard
    }
583 c896fe29 bellard
    tcg_gen_call_internal(s, func, flags, 
584 c896fe29 bellard
                          nb_rets, rets, j, args2);
585 c896fe29 bellard
}
586 c896fe29 bellard
#else
587 ac56dd48 pbrook
void tcg_gen_call(TCGContext *s, TCGv func, unsigned int flags,
588 ac56dd48 pbrook
                  unsigned int nb_rets, const TCGv *rets,
589 ac56dd48 pbrook
                  unsigned int nb_params, const TCGv *args1)
590 c896fe29 bellard
{
591 c896fe29 bellard
    tcg_gen_call_internal(s, func, flags, 
592 c896fe29 bellard
                          nb_rets, rets, nb_params, args1);
593 c896fe29 bellard
}
594 c896fe29 bellard
#endif
595 c896fe29 bellard
596 ac56dd48 pbrook
#if TCG_TARGET_REG_BITS == 32
597 ac56dd48 pbrook
void tcg_gen_shifti_i64(TCGv ret, TCGv arg1, 
598 c896fe29 bellard
                        int c, int right, int arith)
599 c896fe29 bellard
{
600 cf60bce4 bellard
    if (c == 0) {
601 cf60bce4 bellard
        tcg_gen_mov_i32(ret, arg1);
602 cf60bce4 bellard
        tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
603 cf60bce4 bellard
    } else if (c >= 32) {
604 c896fe29 bellard
        c -= 32;
605 c896fe29 bellard
        if (right) {
606 c896fe29 bellard
            if (arith) {
607 ac56dd48 pbrook
                tcg_gen_sari_i32(ret, TCGV_HIGH(arg1), c);
608 ac56dd48 pbrook
                tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 31);
609 c896fe29 bellard
            } else {
610 ac56dd48 pbrook
                tcg_gen_shri_i32(ret, TCGV_HIGH(arg1), c);
611 ac56dd48 pbrook
                tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
612 c896fe29 bellard
            }
613 c896fe29 bellard
        } else {
614 ac56dd48 pbrook
            tcg_gen_shli_i32(TCGV_HIGH(ret), arg1, c);
615 c896fe29 bellard
            tcg_gen_movi_i32(ret, 0);
616 c896fe29 bellard
        }
617 c896fe29 bellard
    } else {
618 ac56dd48 pbrook
        TCGv t0, t1;
619 c896fe29 bellard
620 c896fe29 bellard
        t0 = tcg_temp_new(TCG_TYPE_I32);
621 c896fe29 bellard
        t1 = tcg_temp_new(TCG_TYPE_I32);
622 c896fe29 bellard
        if (right) {
623 ac56dd48 pbrook
            tcg_gen_shli_i32(t0, TCGV_HIGH(arg1), 32 - c);
624 c896fe29 bellard
            if (arith)
625 ac56dd48 pbrook
                tcg_gen_sari_i32(t1, TCGV_HIGH(arg1), c);
626 c896fe29 bellard
            else 
627 ac56dd48 pbrook
                tcg_gen_shri_i32(t1, TCGV_HIGH(arg1), c);
628 c896fe29 bellard
            tcg_gen_shri_i32(ret, arg1, c); 
629 c896fe29 bellard
            tcg_gen_or_i32(ret, ret, t0);
630 ac56dd48 pbrook
            tcg_gen_mov_i32(TCGV_HIGH(ret), t1);
631 c896fe29 bellard
        } else {
632 c896fe29 bellard
            tcg_gen_shri_i32(t0, arg1, 32 - c);
633 c896fe29 bellard
            /* Note: ret can be the same as arg1, so we use t1 */
634 c896fe29 bellard
            tcg_gen_shli_i32(t1, arg1, c); 
635 ac56dd48 pbrook
            tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c);
636 ac56dd48 pbrook
            tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t0);
637 c896fe29 bellard
            tcg_gen_mov_i32(ret, t1);
638 c896fe29 bellard
        }
639 e8996ee0 bellard
        tcg_temp_free(t0);
640 e8996ee0 bellard
        tcg_temp_free(t1);
641 c896fe29 bellard
    }
642 c896fe29 bellard
}
643 ac56dd48 pbrook
#endif
644 c896fe29 bellard
645 8fcd3692 blueswir1
static void tcg_reg_alloc_start(TCGContext *s)
646 c896fe29 bellard
{
647 c896fe29 bellard
    int i;
648 c896fe29 bellard
    TCGTemp *ts;
649 c896fe29 bellard
    for(i = 0; i < s->nb_globals; i++) {
650 c896fe29 bellard
        ts = &s->temps[i];
651 c896fe29 bellard
        if (ts->fixed_reg) {
652 c896fe29 bellard
            ts->val_type = TEMP_VAL_REG;
653 c896fe29 bellard
        } else {
654 c896fe29 bellard
            ts->val_type = TEMP_VAL_MEM;
655 c896fe29 bellard
        }
656 c896fe29 bellard
    }
657 e8996ee0 bellard
    for(i = s->nb_globals; i < s->nb_temps; i++) {
658 e8996ee0 bellard
        ts = &s->temps[i];
659 e8996ee0 bellard
        ts->val_type = TEMP_VAL_DEAD;
660 e8996ee0 bellard
        ts->mem_allocated = 0;
661 e8996ee0 bellard
        ts->fixed_reg = 0;
662 e8996ee0 bellard
    }
663 c896fe29 bellard
    for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
664 c896fe29 bellard
        s->reg_to_temp[i] = -1;
665 c896fe29 bellard
    }
666 c896fe29 bellard
}
667 c896fe29 bellard
668 ac56dd48 pbrook
static char *tcg_get_arg_str_idx(TCGContext *s, char *buf, int buf_size,
669 ac56dd48 pbrook
                                 int idx)
670 c896fe29 bellard
{
671 c896fe29 bellard
    TCGTemp *ts;
672 ac56dd48 pbrook
673 ac56dd48 pbrook
    ts = &s->temps[idx];
674 ac56dd48 pbrook
    if (idx < s->nb_globals) {
675 ac56dd48 pbrook
        pstrcpy(buf, buf_size, ts->name);
676 c896fe29 bellard
    } else {
677 641d5fbe bellard
        if (ts->temp_local) 
678 641d5fbe bellard
            snprintf(buf, buf_size, "loc%d", idx - s->nb_globals);
679 641d5fbe bellard
        else
680 641d5fbe bellard
            snprintf(buf, buf_size, "tmp%d", idx - s->nb_globals);
681 c896fe29 bellard
    }
682 c896fe29 bellard
    return buf;
683 c896fe29 bellard
}
684 c896fe29 bellard
685 ac56dd48 pbrook
char *tcg_get_arg_str(TCGContext *s, char *buf, int buf_size, TCGv arg)
686 ac56dd48 pbrook
{
687 ac56dd48 pbrook
    return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV(arg));
688 ac56dd48 pbrook
}
689 ac56dd48 pbrook
690 e8996ee0 bellard
static int helper_cmp(const void *p1, const void *p2)
691 4dc81f28 bellard
{
692 e8996ee0 bellard
    const TCGHelperInfo *th1 = p1;
693 e8996ee0 bellard
    const TCGHelperInfo *th2 = p2;
694 e8996ee0 bellard
    if (th1->func < th2->func)
695 e8996ee0 bellard
        return -1;
696 e8996ee0 bellard
    else if (th1->func == th2->func)
697 e8996ee0 bellard
        return 0;
698 e8996ee0 bellard
    else
699 e8996ee0 bellard
        return 1;
700 4dc81f28 bellard
}
701 4dc81f28 bellard
702 e8996ee0 bellard
/* find helper definition (Note: A hash table would be better) */
703 e8996ee0 bellard
static TCGHelperInfo *tcg_find_helper(TCGContext *s, tcg_target_ulong val)
704 4dc81f28 bellard
{
705 e8996ee0 bellard
    int m, m_min, m_max;
706 4dc81f28 bellard
    TCGHelperInfo *th;
707 e8996ee0 bellard
    tcg_target_ulong v;
708 4dc81f28 bellard
709 e8996ee0 bellard
    if (unlikely(!s->helpers_sorted)) {
710 e8996ee0 bellard
        qsort(s->helpers, s->nb_helpers, sizeof(TCGHelperInfo), 
711 e8996ee0 bellard
              helper_cmp);
712 e8996ee0 bellard
        s->helpers_sorted = 1;
713 e8996ee0 bellard
    }
714 e8996ee0 bellard
715 e8996ee0 bellard
    /* binary search */
716 e8996ee0 bellard
    m_min = 0;
717 e8996ee0 bellard
    m_max = s->nb_helpers - 1;
718 e8996ee0 bellard
    while (m_min <= m_max) {
719 e8996ee0 bellard
        m = (m_min + m_max) >> 1;
720 e8996ee0 bellard
        th = &s->helpers[m];
721 e8996ee0 bellard
        v = th->func;
722 e8996ee0 bellard
        if (v == val)
723 e8996ee0 bellard
            return th;
724 e8996ee0 bellard
        else if (val < v) {
725 e8996ee0 bellard
            m_max = m - 1;
726 e8996ee0 bellard
        } else {
727 e8996ee0 bellard
            m_min = m + 1;
728 4dc81f28 bellard
        }
729 4dc81f28 bellard
    }
730 e8996ee0 bellard
    return NULL;
731 4dc81f28 bellard
}
732 4dc81f28 bellard
733 c896fe29 bellard
void tcg_dump_ops(TCGContext *s, FILE *outfile)
734 c896fe29 bellard
{
735 c896fe29 bellard
    const uint16_t *opc_ptr;
736 c896fe29 bellard
    const TCGArg *args;
737 c896fe29 bellard
    TCGArg arg;
738 7e4597d7 bellard
    int c, i, k, nb_oargs, nb_iargs, nb_cargs, first_insn;
739 c896fe29 bellard
    const TCGOpDef *def;
740 c896fe29 bellard
    char buf[128];
741 c896fe29 bellard
742 7e4597d7 bellard
    first_insn = 1;
743 c896fe29 bellard
    opc_ptr = gen_opc_buf;
744 c896fe29 bellard
    args = gen_opparam_buf;
745 c896fe29 bellard
    while (opc_ptr < gen_opc_ptr) {
746 c896fe29 bellard
        c = *opc_ptr++;
747 c896fe29 bellard
        def = &tcg_op_defs[c];
748 7e4597d7 bellard
        if (c == INDEX_op_debug_insn_start) {
749 7e4597d7 bellard
            uint64_t pc;
750 7e4597d7 bellard
#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
751 7e4597d7 bellard
            pc = ((uint64_t)args[1] << 32) | args[0];
752 7e4597d7 bellard
#else
753 7e4597d7 bellard
            pc = args[0];
754 7e4597d7 bellard
#endif
755 7e4597d7 bellard
            if (!first_insn) 
756 7e4597d7 bellard
                fprintf(outfile, "\n");
757 7e4597d7 bellard
            fprintf(outfile, " ---- 0x%" PRIx64, pc);
758 7e4597d7 bellard
            first_insn = 0;
759 7e4597d7 bellard
            nb_oargs = def->nb_oargs;
760 7e4597d7 bellard
            nb_iargs = def->nb_iargs;
761 7e4597d7 bellard
            nb_cargs = def->nb_cargs;
762 7e4597d7 bellard
        } else if (c == INDEX_op_call) {
763 c896fe29 bellard
            TCGArg arg;
764 4dc81f28 bellard
765 c896fe29 bellard
            /* variable number of arguments */
766 c896fe29 bellard
            arg = *args++;
767 c896fe29 bellard
            nb_oargs = arg >> 16;
768 c896fe29 bellard
            nb_iargs = arg & 0xffff;
769 c896fe29 bellard
            nb_cargs = def->nb_cargs;
770 c896fe29 bellard
771 7e4597d7 bellard
            fprintf(outfile, " %s ", def->name);
772 7e4597d7 bellard
773 b03cce8e bellard
            /* function name */
774 ac56dd48 pbrook
            fprintf(outfile, "%s",
775 e8996ee0 bellard
                    tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + nb_iargs - 1]));
776 b03cce8e bellard
            /* flags */
777 b03cce8e bellard
            fprintf(outfile, ",$0x%" TCG_PRIlx,
778 b03cce8e bellard
                    args[nb_oargs + nb_iargs]);
779 b03cce8e bellard
            /* nb out args */
780 b03cce8e bellard
            fprintf(outfile, ",$%d", nb_oargs);
781 b03cce8e bellard
            for(i = 0; i < nb_oargs; i++) {
782 b03cce8e bellard
                fprintf(outfile, ",");
783 b03cce8e bellard
                fprintf(outfile, "%s",
784 b03cce8e bellard
                        tcg_get_arg_str_idx(s, buf, sizeof(buf), args[i]));
785 b03cce8e bellard
            }
786 b03cce8e bellard
            for(i = 0; i < (nb_iargs - 1); i++) {
787 c896fe29 bellard
                fprintf(outfile, ",");
788 39cf05d3 bellard
                if (args[nb_oargs + i] == TCG_CALL_DUMMY_ARG) {
789 39cf05d3 bellard
                    fprintf(outfile, "<dummy>");
790 39cf05d3 bellard
                } else {
791 39cf05d3 bellard
                    fprintf(outfile, "%s",
792 39cf05d3 bellard
                            tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + i]));
793 39cf05d3 bellard
                }
794 b03cce8e bellard
            }
795 e8996ee0 bellard
        } else if (c == INDEX_op_movi_i32 
796 e8996ee0 bellard
#if TCG_TARGET_REG_BITS == 64
797 e8996ee0 bellard
                   || c == INDEX_op_movi_i64
798 e8996ee0 bellard
#endif
799 e8996ee0 bellard
                   ) {
800 e8996ee0 bellard
            tcg_target_ulong val;
801 e8996ee0 bellard
            TCGHelperInfo *th;
802 e8996ee0 bellard
803 e8996ee0 bellard
            nb_oargs = def->nb_oargs;
804 e8996ee0 bellard
            nb_iargs = def->nb_iargs;
805 e8996ee0 bellard
            nb_cargs = def->nb_cargs;
806 e8996ee0 bellard
            fprintf(outfile, " %s %s,$", def->name, 
807 e8996ee0 bellard
                    tcg_get_arg_str_idx(s, buf, sizeof(buf), args[0]));
808 e8996ee0 bellard
            val = args[1];
809 e8996ee0 bellard
            th = tcg_find_helper(s, val);
810 e8996ee0 bellard
            if (th) {
811 e8996ee0 bellard
                fprintf(outfile, th->name);
812 e8996ee0 bellard
            } else {
813 e8996ee0 bellard
                if (c == INDEX_op_movi_i32)
814 e8996ee0 bellard
                    fprintf(outfile, "0x%x", (uint32_t)val);
815 e8996ee0 bellard
                else
816 e8996ee0 bellard
                    fprintf(outfile, "0x%" PRIx64 , (uint64_t)val);
817 e8996ee0 bellard
            }
818 b03cce8e bellard
        } else {
819 7e4597d7 bellard
            fprintf(outfile, " %s ", def->name);
820 b03cce8e bellard
            if (c == INDEX_op_nopn) {
821 b03cce8e bellard
                /* variable number of arguments */
822 b03cce8e bellard
                nb_cargs = *args;
823 b03cce8e bellard
                nb_oargs = 0;
824 b03cce8e bellard
                nb_iargs = 0;
825 b03cce8e bellard
            } else {
826 b03cce8e bellard
                nb_oargs = def->nb_oargs;
827 b03cce8e bellard
                nb_iargs = def->nb_iargs;
828 b03cce8e bellard
                nb_cargs = def->nb_cargs;
829 b03cce8e bellard
            }
830 b03cce8e bellard
            
831 b03cce8e bellard
            k = 0;
832 b03cce8e bellard
            for(i = 0; i < nb_oargs; i++) {
833 b03cce8e bellard
                if (k != 0)
834 b03cce8e bellard
                    fprintf(outfile, ",");
835 b03cce8e bellard
                fprintf(outfile, "%s",
836 b03cce8e bellard
                        tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
837 b03cce8e bellard
            }
838 b03cce8e bellard
            for(i = 0; i < nb_iargs; i++) {
839 b03cce8e bellard
                if (k != 0)
840 b03cce8e bellard
                    fprintf(outfile, ",");
841 b03cce8e bellard
                fprintf(outfile, "%s",
842 b03cce8e bellard
                        tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
843 b03cce8e bellard
            }
844 b03cce8e bellard
            for(i = 0; i < nb_cargs; i++) {
845 b03cce8e bellard
                if (k != 0)
846 b03cce8e bellard
                    fprintf(outfile, ",");
847 b03cce8e bellard
                arg = args[k++];
848 b03cce8e bellard
                fprintf(outfile, "$0x%" TCG_PRIlx, arg);
849 b03cce8e bellard
            }
850 c896fe29 bellard
        }
851 c896fe29 bellard
        fprintf(outfile, "\n");
852 c896fe29 bellard
        args += nb_iargs + nb_oargs + nb_cargs;
853 c896fe29 bellard
    }
854 c896fe29 bellard
}
855 c896fe29 bellard
856 c896fe29 bellard
/* we give more priority to constraints with less registers */
857 c896fe29 bellard
static int get_constraint_priority(const TCGOpDef *def, int k)
858 c896fe29 bellard
{
859 c896fe29 bellard
    const TCGArgConstraint *arg_ct;
860 c896fe29 bellard
861 c896fe29 bellard
    int i, n;
862 c896fe29 bellard
    arg_ct = &def->args_ct[k];
863 c896fe29 bellard
    if (arg_ct->ct & TCG_CT_ALIAS) {
864 c896fe29 bellard
        /* an alias is equivalent to a single register */
865 c896fe29 bellard
        n = 1;
866 c896fe29 bellard
    } else {
867 c896fe29 bellard
        if (!(arg_ct->ct & TCG_CT_REG))
868 c896fe29 bellard
            return 0;
869 c896fe29 bellard
        n = 0;
870 c896fe29 bellard
        for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
871 c896fe29 bellard
            if (tcg_regset_test_reg(arg_ct->u.regs, i))
872 c896fe29 bellard
                n++;
873 c896fe29 bellard
        }
874 c896fe29 bellard
    }
875 c896fe29 bellard
    return TCG_TARGET_NB_REGS - n + 1;
876 c896fe29 bellard
}
877 c896fe29 bellard
878 c896fe29 bellard
/* sort from highest priority to lowest */
879 c896fe29 bellard
static void sort_constraints(TCGOpDef *def, int start, int n)
880 c896fe29 bellard
{
881 c896fe29 bellard
    int i, j, p1, p2, tmp;
882 c896fe29 bellard
883 c896fe29 bellard
    for(i = 0; i < n; i++)
884 c896fe29 bellard
        def->sorted_args[start + i] = start + i;
885 c896fe29 bellard
    if (n <= 1)
886 c896fe29 bellard
        return;
887 c896fe29 bellard
    for(i = 0; i < n - 1; i++) {
888 c896fe29 bellard
        for(j = i + 1; j < n; j++) {
889 c896fe29 bellard
            p1 = get_constraint_priority(def, def->sorted_args[start + i]);
890 c896fe29 bellard
            p2 = get_constraint_priority(def, def->sorted_args[start + j]);
891 c896fe29 bellard
            if (p1 < p2) {
892 c896fe29 bellard
                tmp = def->sorted_args[start + i];
893 c896fe29 bellard
                def->sorted_args[start + i] = def->sorted_args[start + j];
894 c896fe29 bellard
                def->sorted_args[start + j] = tmp;
895 c896fe29 bellard
            }
896 c896fe29 bellard
        }
897 c896fe29 bellard
    }
898 c896fe29 bellard
}
899 c896fe29 bellard
900 c896fe29 bellard
void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs)
901 c896fe29 bellard
{
902 c896fe29 bellard
    int op;
903 c896fe29 bellard
    TCGOpDef *def;
904 c896fe29 bellard
    const char *ct_str;
905 c896fe29 bellard
    int i, nb_args;
906 c896fe29 bellard
907 c896fe29 bellard
    for(;;) {
908 c896fe29 bellard
        if (tdefs->op < 0)
909 c896fe29 bellard
            break;
910 c896fe29 bellard
        op = tdefs->op;
911 c896fe29 bellard
        assert(op >= 0 && op < NB_OPS);
912 c896fe29 bellard
        def = &tcg_op_defs[op];
913 c896fe29 bellard
        nb_args = def->nb_iargs + def->nb_oargs;
914 c896fe29 bellard
        for(i = 0; i < nb_args; i++) {
915 c896fe29 bellard
            ct_str = tdefs->args_ct_str[i];
916 c896fe29 bellard
            tcg_regset_clear(def->args_ct[i].u.regs);
917 c896fe29 bellard
            def->args_ct[i].ct = 0;
918 c896fe29 bellard
            if (ct_str[0] >= '0' && ct_str[0] <= '9') {
919 c896fe29 bellard
                int oarg;
920 c896fe29 bellard
                oarg = ct_str[0] - '0';
921 c896fe29 bellard
                assert(oarg < def->nb_oargs);
922 c896fe29 bellard
                assert(def->args_ct[oarg].ct & TCG_CT_REG);
923 c896fe29 bellard
                /* TCG_CT_ALIAS is for the output arguments. The input
924 5ff9d6a4 bellard
                   argument is tagged with TCG_CT_IALIAS. */
925 c896fe29 bellard
                def->args_ct[i] = def->args_ct[oarg];
926 5ff9d6a4 bellard
                def->args_ct[oarg].ct = TCG_CT_ALIAS;
927 5ff9d6a4 bellard
                def->args_ct[oarg].alias_index = i;
928 c896fe29 bellard
                def->args_ct[i].ct |= TCG_CT_IALIAS;
929 5ff9d6a4 bellard
                def->args_ct[i].alias_index = oarg;
930 c896fe29 bellard
            } else {
931 c896fe29 bellard
                for(;;) {
932 c896fe29 bellard
                    if (*ct_str == '\0')
933 c896fe29 bellard
                        break;
934 c896fe29 bellard
                    switch(*ct_str) {
935 c896fe29 bellard
                    case 'i':
936 c896fe29 bellard
                        def->args_ct[i].ct |= TCG_CT_CONST;
937 c896fe29 bellard
                        ct_str++;
938 c896fe29 bellard
                        break;
939 c896fe29 bellard
                    default:
940 c896fe29 bellard
                        if (target_parse_constraint(&def->args_ct[i], &ct_str) < 0) {
941 c896fe29 bellard
                            fprintf(stderr, "Invalid constraint '%s' for arg %d of operation '%s'\n",
942 c896fe29 bellard
                                    ct_str, i, def->name);
943 c896fe29 bellard
                            exit(1);
944 c896fe29 bellard
                        }
945 c896fe29 bellard
                    }
946 c896fe29 bellard
                }
947 c896fe29 bellard
            }
948 c896fe29 bellard
        }
949 c896fe29 bellard
950 c896fe29 bellard
        /* sort the constraints (XXX: this is just an heuristic) */
951 c896fe29 bellard
        sort_constraints(def, 0, def->nb_oargs);
952 c896fe29 bellard
        sort_constraints(def, def->nb_oargs, def->nb_iargs);
953 c896fe29 bellard
954 c896fe29 bellard
#if 0
955 c896fe29 bellard
        {
956 c896fe29 bellard
            int i;
957 c896fe29 bellard

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