Statistics
| Branch: | Revision:

root / tcg / tcg.c @ caa88be0

History | View | Annotate | Download (61.8 kB)

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

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