Statistics
| Branch: | Revision:

root / tcg / tcg.c @ 2bece2c8

History | View | Annotate | Download (64.9 kB)

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

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