Statistics
| Branch: | Revision:

root / tcg / tcg.c @ 79d342dc

History | View | Annotate | Download (61.5 kB)

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

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