Statistics
| Branch: | Revision:

root / tcg / tcg.c @ 866cb6cb

History | View | Annotate | Download (65.4 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 27bfd83c Peter Maydell
454 27bfd83c Peter Maydell
#if defined(CONFIG_DEBUG_TCG)
455 27bfd83c Peter Maydell
    s->temps_in_use++;
456 27bfd83c Peter Maydell
#endif
457 a7812ae4 pbrook
    return idx;
458 c896fe29 bellard
}
459 c896fe29 bellard
460 a7812ae4 pbrook
TCGv_i32 tcg_temp_new_internal_i32(int temp_local)
461 a7812ae4 pbrook
{
462 a7812ae4 pbrook
    int idx;
463 a7812ae4 pbrook
464 a7812ae4 pbrook
    idx = tcg_temp_new_internal(TCG_TYPE_I32, temp_local);
465 a7812ae4 pbrook
    return MAKE_TCGV_I32(idx);
466 a7812ae4 pbrook
}
467 a7812ae4 pbrook
468 a7812ae4 pbrook
TCGv_i64 tcg_temp_new_internal_i64(int temp_local)
469 a7812ae4 pbrook
{
470 a7812ae4 pbrook
    int idx;
471 a7812ae4 pbrook
472 a7812ae4 pbrook
    idx = tcg_temp_new_internal(TCG_TYPE_I64, temp_local);
473 a7812ae4 pbrook
    return MAKE_TCGV_I64(idx);
474 a7812ae4 pbrook
}
475 a7812ae4 pbrook
476 a7812ae4 pbrook
static inline void tcg_temp_free_internal(int idx)
477 c896fe29 bellard
{
478 c896fe29 bellard
    TCGContext *s = &tcg_ctx;
479 c896fe29 bellard
    TCGTemp *ts;
480 641d5fbe bellard
    int k;
481 c896fe29 bellard
482 27bfd83c Peter Maydell
#if defined(CONFIG_DEBUG_TCG)
483 27bfd83c Peter Maydell
    s->temps_in_use--;
484 27bfd83c Peter Maydell
    if (s->temps_in_use < 0) {
485 27bfd83c Peter Maydell
        fprintf(stderr, "More temporaries freed than allocated!\n");
486 27bfd83c Peter Maydell
    }
487 27bfd83c Peter Maydell
#endif
488 27bfd83c Peter Maydell
489 e8996ee0 bellard
    assert(idx >= s->nb_globals && idx < s->nb_temps);
490 c896fe29 bellard
    ts = &s->temps[idx];
491 e8996ee0 bellard
    assert(ts->temp_allocated != 0);
492 e8996ee0 bellard
    ts->temp_allocated = 0;
493 641d5fbe bellard
    k = ts->base_type;
494 641d5fbe bellard
    if (ts->temp_local)
495 641d5fbe bellard
        k += TCG_TYPE_COUNT;
496 641d5fbe bellard
    ts->next_free_temp = s->first_free_temp[k];
497 641d5fbe bellard
    s->first_free_temp[k] = idx;
498 c896fe29 bellard
}
499 c896fe29 bellard
500 a7812ae4 pbrook
void tcg_temp_free_i32(TCGv_i32 arg)
501 a7812ae4 pbrook
{
502 a7812ae4 pbrook
    tcg_temp_free_internal(GET_TCGV_I32(arg));
503 a7812ae4 pbrook
}
504 a7812ae4 pbrook
505 a7812ae4 pbrook
void tcg_temp_free_i64(TCGv_i64 arg)
506 a7812ae4 pbrook
{
507 a7812ae4 pbrook
    tcg_temp_free_internal(GET_TCGV_I64(arg));
508 a7812ae4 pbrook
}
509 e8996ee0 bellard
510 a7812ae4 pbrook
TCGv_i32 tcg_const_i32(int32_t val)
511 c896fe29 bellard
{
512 a7812ae4 pbrook
    TCGv_i32 t0;
513 a7812ae4 pbrook
    t0 = tcg_temp_new_i32();
514 e8996ee0 bellard
    tcg_gen_movi_i32(t0, val);
515 e8996ee0 bellard
    return t0;
516 e8996ee0 bellard
}
517 c896fe29 bellard
518 a7812ae4 pbrook
TCGv_i64 tcg_const_i64(int64_t val)
519 e8996ee0 bellard
{
520 a7812ae4 pbrook
    TCGv_i64 t0;
521 a7812ae4 pbrook
    t0 = tcg_temp_new_i64();
522 e8996ee0 bellard
    tcg_gen_movi_i64(t0, val);
523 e8996ee0 bellard
    return t0;
524 c896fe29 bellard
}
525 c896fe29 bellard
526 a7812ae4 pbrook
TCGv_i32 tcg_const_local_i32(int32_t val)
527 bdffd4a9 aurel32
{
528 a7812ae4 pbrook
    TCGv_i32 t0;
529 a7812ae4 pbrook
    t0 = tcg_temp_local_new_i32();
530 bdffd4a9 aurel32
    tcg_gen_movi_i32(t0, val);
531 bdffd4a9 aurel32
    return t0;
532 bdffd4a9 aurel32
}
533 bdffd4a9 aurel32
534 a7812ae4 pbrook
TCGv_i64 tcg_const_local_i64(int64_t val)
535 bdffd4a9 aurel32
{
536 a7812ae4 pbrook
    TCGv_i64 t0;
537 a7812ae4 pbrook
    t0 = tcg_temp_local_new_i64();
538 bdffd4a9 aurel32
    tcg_gen_movi_i64(t0, val);
539 bdffd4a9 aurel32
    return t0;
540 bdffd4a9 aurel32
}
541 bdffd4a9 aurel32
542 27bfd83c Peter Maydell
#if defined(CONFIG_DEBUG_TCG)
543 27bfd83c Peter Maydell
void tcg_clear_temp_count(void)
544 27bfd83c Peter Maydell
{
545 27bfd83c Peter Maydell
    TCGContext *s = &tcg_ctx;
546 27bfd83c Peter Maydell
    s->temps_in_use = 0;
547 27bfd83c Peter Maydell
}
548 27bfd83c Peter Maydell
549 27bfd83c Peter Maydell
int tcg_check_temp_count(void)
550 27bfd83c Peter Maydell
{
551 27bfd83c Peter Maydell
    TCGContext *s = &tcg_ctx;
552 27bfd83c Peter Maydell
    if (s->temps_in_use) {
553 27bfd83c Peter Maydell
        /* Clear the count so that we don't give another
554 27bfd83c Peter Maydell
         * warning immediately next time around.
555 27bfd83c Peter Maydell
         */
556 27bfd83c Peter Maydell
        s->temps_in_use = 0;
557 27bfd83c Peter Maydell
        return 1;
558 27bfd83c Peter Maydell
    }
559 27bfd83c Peter Maydell
    return 0;
560 27bfd83c Peter Maydell
}
561 27bfd83c Peter Maydell
#endif
562 27bfd83c Peter Maydell
563 c896fe29 bellard
void tcg_register_helper(void *func, const char *name)
564 c896fe29 bellard
{
565 c896fe29 bellard
    TCGContext *s = &tcg_ctx;
566 c896fe29 bellard
    int n;
567 c896fe29 bellard
    if ((s->nb_helpers + 1) > s->allocated_helpers) {
568 c896fe29 bellard
        n = s->allocated_helpers;
569 c896fe29 bellard
        if (n == 0) {
570 c896fe29 bellard
            n = 4;
571 c896fe29 bellard
        } else {
572 c896fe29 bellard
            n *= 2;
573 c896fe29 bellard
        }
574 c896fe29 bellard
        s->helpers = realloc(s->helpers, n * sizeof(TCGHelperInfo));
575 c896fe29 bellard
        s->allocated_helpers = n;
576 c896fe29 bellard
    }
577 4dc81f28 bellard
    s->helpers[s->nb_helpers].func = (tcg_target_ulong)func;
578 c896fe29 bellard
    s->helpers[s->nb_helpers].name = name;
579 c896fe29 bellard
    s->nb_helpers++;
580 c896fe29 bellard
}
581 c896fe29 bellard
582 39cf05d3 bellard
/* Note: we convert the 64 bit args to 32 bit and do some alignment
583 39cf05d3 bellard
   and endian swap. Maybe it would be better to do the alignment
584 39cf05d3 bellard
   and endian swap in tcg_reg_alloc_call(). */
585 a7812ae4 pbrook
void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags,
586 a7812ae4 pbrook
                   int sizemask, TCGArg ret, int nargs, TCGArg *args)
587 c896fe29 bellard
{
588 9678d950 Blue Swirl
#ifdef TCG_TARGET_I386
589 a7812ae4 pbrook
    int call_type;
590 9678d950 Blue Swirl
#endif
591 a7812ae4 pbrook
    int i;
592 a7812ae4 pbrook
    int real_args;
593 a7812ae4 pbrook
    int nb_rets;
594 a7812ae4 pbrook
    TCGArg *nparam;
595 2bece2c8 Richard Henderson
596 2bece2c8 Richard Henderson
#if defined(TCG_TARGET_EXTEND_ARGS) && TCG_TARGET_REG_BITS == 64
597 2bece2c8 Richard Henderson
    for (i = 0; i < nargs; ++i) {
598 2bece2c8 Richard Henderson
        int is_64bit = sizemask & (1 << (i+1)*2);
599 2bece2c8 Richard Henderson
        int is_signed = sizemask & (2 << (i+1)*2);
600 2bece2c8 Richard Henderson
        if (!is_64bit) {
601 2bece2c8 Richard Henderson
            TCGv_i64 temp = tcg_temp_new_i64();
602 2bece2c8 Richard Henderson
            TCGv_i64 orig = MAKE_TCGV_I64(args[i]);
603 2bece2c8 Richard Henderson
            if (is_signed) {
604 2bece2c8 Richard Henderson
                tcg_gen_ext32s_i64(temp, orig);
605 2bece2c8 Richard Henderson
            } else {
606 2bece2c8 Richard Henderson
                tcg_gen_ext32u_i64(temp, orig);
607 2bece2c8 Richard Henderson
            }
608 2bece2c8 Richard Henderson
            args[i] = GET_TCGV_I64(temp);
609 2bece2c8 Richard Henderson
        }
610 2bece2c8 Richard Henderson
    }
611 2bece2c8 Richard Henderson
#endif /* TCG_TARGET_EXTEND_ARGS */
612 2bece2c8 Richard Henderson
613 a7812ae4 pbrook
    *gen_opc_ptr++ = INDEX_op_call;
614 a7812ae4 pbrook
    nparam = gen_opparam_ptr++;
615 9678d950 Blue Swirl
#ifdef TCG_TARGET_I386
616 a7812ae4 pbrook
    call_type = (flags & TCG_CALL_TYPE_MASK);
617 9678d950 Blue Swirl
#endif
618 a7812ae4 pbrook
    if (ret != TCG_CALL_DUMMY_ARG) {
619 a7812ae4 pbrook
#if TCG_TARGET_REG_BITS < 64
620 a7812ae4 pbrook
        if (sizemask & 1) {
621 39cf05d3 bellard
#ifdef TCG_TARGET_WORDS_BIGENDIAN
622 a7812ae4 pbrook
            *gen_opparam_ptr++ = ret + 1;
623 a7812ae4 pbrook
            *gen_opparam_ptr++ = ret;
624 39cf05d3 bellard
#else
625 a7812ae4 pbrook
            *gen_opparam_ptr++ = ret;
626 a7812ae4 pbrook
            *gen_opparam_ptr++ = ret + 1;
627 39cf05d3 bellard
#endif
628 a7812ae4 pbrook
            nb_rets = 2;
629 a7812ae4 pbrook
        } else
630 a7812ae4 pbrook
#endif
631 a7812ae4 pbrook
        {
632 a7812ae4 pbrook
            *gen_opparam_ptr++ = ret;
633 a7812ae4 pbrook
            nb_rets = 1;
634 c896fe29 bellard
        }
635 a7812ae4 pbrook
    } else {
636 a7812ae4 pbrook
        nb_rets = 0;
637 c896fe29 bellard
    }
638 a7812ae4 pbrook
    real_args = 0;
639 a7812ae4 pbrook
    for (i = 0; i < nargs; i++) {
640 a7812ae4 pbrook
#if TCG_TARGET_REG_BITS < 64
641 2bece2c8 Richard Henderson
        int is_64bit = sizemask & (1 << (i+1)*2);
642 2bece2c8 Richard Henderson
        if (is_64bit) {
643 c896fe29 bellard
#ifdef TCG_TARGET_I386
644 c896fe29 bellard
            /* REGPARM case: if the third parameter is 64 bit, it is
645 c896fe29 bellard
               allocated on the stack */
646 a7812ae4 pbrook
            if (i == 2 && call_type == TCG_CALL_TYPE_REGPARM) {
647 c896fe29 bellard
                call_type = TCG_CALL_TYPE_REGPARM_2;
648 c896fe29 bellard
                flags = (flags & ~TCG_CALL_TYPE_MASK) | call_type;
649 c896fe29 bellard
            }
650 a7812ae4 pbrook
#endif
651 39cf05d3 bellard
#ifdef TCG_TARGET_CALL_ALIGN_ARGS
652 39cf05d3 bellard
            /* some targets want aligned 64 bit args */
653 ebd486d5 malc
            if (real_args & 1) {
654 a7812ae4 pbrook
                *gen_opparam_ptr++ = TCG_CALL_DUMMY_ARG;
655 ebd486d5 malc
                real_args++;
656 39cf05d3 bellard
            }
657 39cf05d3 bellard
#endif
658 3f90f252 Richard Henderson
            /* If stack grows up, then we will be placing successive
659 3f90f252 Richard Henderson
               arguments at lower addresses, which means we need to
660 3f90f252 Richard Henderson
               reverse the order compared to how we would normally
661 3f90f252 Richard Henderson
               treat either big or little-endian.  For those arguments
662 3f90f252 Richard Henderson
               that will wind up in registers, this still works for
663 3f90f252 Richard Henderson
               HPPA (the only current STACK_GROWSUP target) since the
664 3f90f252 Richard Henderson
               argument registers are *also* allocated in decreasing
665 3f90f252 Richard Henderson
               order.  If another such target is added, this logic may
666 3f90f252 Richard Henderson
               have to get more complicated to differentiate between
667 3f90f252 Richard Henderson
               stack arguments and register arguments.  */
668 3f90f252 Richard Henderson
#if defined(TCG_TARGET_WORDS_BIGENDIAN) != defined(TCG_TARGET_STACK_GROWSUP)
669 a7812ae4 pbrook
            *gen_opparam_ptr++ = args[i] + 1;
670 a7812ae4 pbrook
            *gen_opparam_ptr++ = args[i];
671 c896fe29 bellard
#else
672 a7812ae4 pbrook
            *gen_opparam_ptr++ = args[i];
673 a7812ae4 pbrook
            *gen_opparam_ptr++ = args[i] + 1;
674 c896fe29 bellard
#endif
675 a7812ae4 pbrook
            real_args += 2;
676 2bece2c8 Richard Henderson
            continue;
677 c896fe29 bellard
        }
678 2bece2c8 Richard Henderson
#endif /* TCG_TARGET_REG_BITS < 64 */
679 2bece2c8 Richard Henderson
680 2bece2c8 Richard Henderson
        *gen_opparam_ptr++ = args[i];
681 2bece2c8 Richard Henderson
        real_args++;
682 c896fe29 bellard
    }
683 a7812ae4 pbrook
    *gen_opparam_ptr++ = GET_TCGV_PTR(func);
684 a7812ae4 pbrook
685 a7812ae4 pbrook
    *gen_opparam_ptr++ = flags;
686 a7812ae4 pbrook
687 a7812ae4 pbrook
    *nparam = (nb_rets << 16) | (real_args + 1);
688 a7812ae4 pbrook
689 a7812ae4 pbrook
    /* total parameters, needed to go backward in the instruction stream */
690 a7812ae4 pbrook
    *gen_opparam_ptr++ = 1 + nb_rets + real_args + 3;
691 2bece2c8 Richard Henderson
692 2bece2c8 Richard Henderson
#if defined(TCG_TARGET_EXTEND_ARGS) && TCG_TARGET_REG_BITS == 64
693 2bece2c8 Richard Henderson
    for (i = 0; i < nargs; ++i) {
694 2bece2c8 Richard Henderson
        int is_64bit = sizemask & (1 << (i+1)*2);
695 2bece2c8 Richard Henderson
        if (!is_64bit) {
696 2bece2c8 Richard Henderson
            TCGv_i64 temp = MAKE_TCGV_I64(args[i]);
697 2bece2c8 Richard Henderson
            tcg_temp_free_i64(temp);
698 2bece2c8 Richard Henderson
        }
699 2bece2c8 Richard Henderson
    }
700 2bece2c8 Richard Henderson
#endif /* TCG_TARGET_EXTEND_ARGS */
701 c896fe29 bellard
}
702 c896fe29 bellard
703 ac56dd48 pbrook
#if TCG_TARGET_REG_BITS == 32
704 a7812ae4 pbrook
void tcg_gen_shifti_i64(TCGv_i64 ret, TCGv_i64 arg1,
705 c896fe29 bellard
                        int c, int right, int arith)
706 c896fe29 bellard
{
707 cf60bce4 bellard
    if (c == 0) {
708 a7812ae4 pbrook
        tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg1));
709 cf60bce4 bellard
        tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
710 cf60bce4 bellard
    } else if (c >= 32) {
711 c896fe29 bellard
        c -= 32;
712 c896fe29 bellard
        if (right) {
713 c896fe29 bellard
            if (arith) {
714 a7812ae4 pbrook
                tcg_gen_sari_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
715 ac56dd48 pbrook
                tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 31);
716 c896fe29 bellard
            } else {
717 a7812ae4 pbrook
                tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
718 ac56dd48 pbrook
                tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
719 c896fe29 bellard
            }
720 c896fe29 bellard
        } else {
721 a7812ae4 pbrook
            tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_LOW(arg1), c);
722 a7812ae4 pbrook
            tcg_gen_movi_i32(TCGV_LOW(ret), 0);
723 c896fe29 bellard
        }
724 c896fe29 bellard
    } else {
725 a7812ae4 pbrook
        TCGv_i32 t0, t1;
726 c896fe29 bellard
727 a7812ae4 pbrook
        t0 = tcg_temp_new_i32();
728 a7812ae4 pbrook
        t1 = tcg_temp_new_i32();
729 c896fe29 bellard
        if (right) {
730 ac56dd48 pbrook
            tcg_gen_shli_i32(t0, TCGV_HIGH(arg1), 32 - c);
731 c896fe29 bellard
            if (arith)
732 ac56dd48 pbrook
                tcg_gen_sari_i32(t1, TCGV_HIGH(arg1), c);
733 a7812ae4 pbrook
            else
734 ac56dd48 pbrook
                tcg_gen_shri_i32(t1, TCGV_HIGH(arg1), c);
735 a7812ae4 pbrook
            tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_LOW(arg1), c);
736 a7812ae4 pbrook
            tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(ret), t0);
737 ac56dd48 pbrook
            tcg_gen_mov_i32(TCGV_HIGH(ret), t1);
738 c896fe29 bellard
        } else {
739 a7812ae4 pbrook
            tcg_gen_shri_i32(t0, TCGV_LOW(arg1), 32 - c);
740 c896fe29 bellard
            /* Note: ret can be the same as arg1, so we use t1 */
741 a7812ae4 pbrook
            tcg_gen_shli_i32(t1, TCGV_LOW(arg1), c);
742 ac56dd48 pbrook
            tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c);
743 ac56dd48 pbrook
            tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t0);
744 a7812ae4 pbrook
            tcg_gen_mov_i32(TCGV_LOW(ret), t1);
745 c896fe29 bellard
        }
746 a7812ae4 pbrook
        tcg_temp_free_i32(t0);
747 a7812ae4 pbrook
        tcg_temp_free_i32(t1);
748 c896fe29 bellard
    }
749 c896fe29 bellard
}
750 ac56dd48 pbrook
#endif
751 c896fe29 bellard
752 be210acb Richard Henderson
753 8fcd3692 blueswir1
static void tcg_reg_alloc_start(TCGContext *s)
754 c896fe29 bellard
{
755 c896fe29 bellard
    int i;
756 c896fe29 bellard
    TCGTemp *ts;
757 c896fe29 bellard
    for(i = 0; i < s->nb_globals; i++) {
758 c896fe29 bellard
        ts = &s->temps[i];
759 c896fe29 bellard
        if (ts->fixed_reg) {
760 c896fe29 bellard
            ts->val_type = TEMP_VAL_REG;
761 c896fe29 bellard
        } else {
762 c896fe29 bellard
            ts->val_type = TEMP_VAL_MEM;
763 c896fe29 bellard
        }
764 c896fe29 bellard
    }
765 e8996ee0 bellard
    for(i = s->nb_globals; i < s->nb_temps; i++) {
766 e8996ee0 bellard
        ts = &s->temps[i];
767 e8996ee0 bellard
        ts->val_type = TEMP_VAL_DEAD;
768 e8996ee0 bellard
        ts->mem_allocated = 0;
769 e8996ee0 bellard
        ts->fixed_reg = 0;
770 e8996ee0 bellard
    }
771 c896fe29 bellard
    for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
772 c896fe29 bellard
        s->reg_to_temp[i] = -1;
773 c896fe29 bellard
    }
774 c896fe29 bellard
}
775 c896fe29 bellard
776 ac56dd48 pbrook
static char *tcg_get_arg_str_idx(TCGContext *s, char *buf, int buf_size,
777 ac56dd48 pbrook
                                 int idx)
778 c896fe29 bellard
{
779 c896fe29 bellard
    TCGTemp *ts;
780 ac56dd48 pbrook
781 ac56dd48 pbrook
    ts = &s->temps[idx];
782 ac56dd48 pbrook
    if (idx < s->nb_globals) {
783 ac56dd48 pbrook
        pstrcpy(buf, buf_size, ts->name);
784 c896fe29 bellard
    } else {
785 641d5fbe bellard
        if (ts->temp_local) 
786 641d5fbe bellard
            snprintf(buf, buf_size, "loc%d", idx - s->nb_globals);
787 641d5fbe bellard
        else
788 641d5fbe bellard
            snprintf(buf, buf_size, "tmp%d", idx - s->nb_globals);
789 c896fe29 bellard
    }
790 c896fe29 bellard
    return buf;
791 c896fe29 bellard
}
792 c896fe29 bellard
793 a7812ae4 pbrook
char *tcg_get_arg_str_i32(TCGContext *s, char *buf, int buf_size, TCGv_i32 arg)
794 a7812ae4 pbrook
{
795 a7812ae4 pbrook
    return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I32(arg));
796 a7812ae4 pbrook
}
797 a7812ae4 pbrook
798 a7812ae4 pbrook
char *tcg_get_arg_str_i64(TCGContext *s, char *buf, int buf_size, TCGv_i64 arg)
799 ac56dd48 pbrook
{
800 a810a2de blueswir1
    return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I64(arg));
801 ac56dd48 pbrook
}
802 ac56dd48 pbrook
803 e8996ee0 bellard
static int helper_cmp(const void *p1, const void *p2)
804 4dc81f28 bellard
{
805 e8996ee0 bellard
    const TCGHelperInfo *th1 = p1;
806 e8996ee0 bellard
    const TCGHelperInfo *th2 = p2;
807 e8996ee0 bellard
    if (th1->func < th2->func)
808 e8996ee0 bellard
        return -1;
809 e8996ee0 bellard
    else if (th1->func == th2->func)
810 e8996ee0 bellard
        return 0;
811 e8996ee0 bellard
    else
812 e8996ee0 bellard
        return 1;
813 4dc81f28 bellard
}
814 4dc81f28 bellard
815 e8996ee0 bellard
/* find helper definition (Note: A hash table would be better) */
816 e8996ee0 bellard
static TCGHelperInfo *tcg_find_helper(TCGContext *s, tcg_target_ulong val)
817 4dc81f28 bellard
{
818 e8996ee0 bellard
    int m, m_min, m_max;
819 4dc81f28 bellard
    TCGHelperInfo *th;
820 e8996ee0 bellard
    tcg_target_ulong v;
821 4dc81f28 bellard
822 e8996ee0 bellard
    if (unlikely(!s->helpers_sorted)) {
823 e8996ee0 bellard
        qsort(s->helpers, s->nb_helpers, sizeof(TCGHelperInfo), 
824 e8996ee0 bellard
              helper_cmp);
825 e8996ee0 bellard
        s->helpers_sorted = 1;
826 e8996ee0 bellard
    }
827 e8996ee0 bellard
828 e8996ee0 bellard
    /* binary search */
829 e8996ee0 bellard
    m_min = 0;
830 e8996ee0 bellard
    m_max = s->nb_helpers - 1;
831 e8996ee0 bellard
    while (m_min <= m_max) {
832 e8996ee0 bellard
        m = (m_min + m_max) >> 1;
833 e8996ee0 bellard
        th = &s->helpers[m];
834 e8996ee0 bellard
        v = th->func;
835 e8996ee0 bellard
        if (v == val)
836 e8996ee0 bellard
            return th;
837 e8996ee0 bellard
        else if (val < v) {
838 e8996ee0 bellard
            m_max = m - 1;
839 e8996ee0 bellard
        } else {
840 e8996ee0 bellard
            m_min = m + 1;
841 4dc81f28 bellard
        }
842 4dc81f28 bellard
    }
843 e8996ee0 bellard
    return NULL;
844 4dc81f28 bellard
}
845 4dc81f28 bellard
846 f48f3ede blueswir1
static const char * const cond_name[] =
847 f48f3ede blueswir1
{
848 f48f3ede blueswir1
    [TCG_COND_EQ] = "eq",
849 f48f3ede blueswir1
    [TCG_COND_NE] = "ne",
850 f48f3ede blueswir1
    [TCG_COND_LT] = "lt",
851 f48f3ede blueswir1
    [TCG_COND_GE] = "ge",
852 f48f3ede blueswir1
    [TCG_COND_LE] = "le",
853 f48f3ede blueswir1
    [TCG_COND_GT] = "gt",
854 f48f3ede blueswir1
    [TCG_COND_LTU] = "ltu",
855 f48f3ede blueswir1
    [TCG_COND_GEU] = "geu",
856 f48f3ede blueswir1
    [TCG_COND_LEU] = "leu",
857 f48f3ede blueswir1
    [TCG_COND_GTU] = "gtu"
858 f48f3ede blueswir1
};
859 f48f3ede blueswir1
860 c896fe29 bellard
void tcg_dump_ops(TCGContext *s, FILE *outfile)
861 c896fe29 bellard
{
862 c896fe29 bellard
    const uint16_t *opc_ptr;
863 c896fe29 bellard
    const TCGArg *args;
864 c896fe29 bellard
    TCGArg arg;
865 a9751609 Richard Henderson
    TCGOpcode c;
866 a9751609 Richard Henderson
    int i, k, nb_oargs, nb_iargs, nb_cargs, first_insn;
867 c896fe29 bellard
    const TCGOpDef *def;
868 c896fe29 bellard
    char buf[128];
869 c896fe29 bellard
870 7e4597d7 bellard
    first_insn = 1;
871 c896fe29 bellard
    opc_ptr = gen_opc_buf;
872 c896fe29 bellard
    args = gen_opparam_buf;
873 c896fe29 bellard
    while (opc_ptr < gen_opc_ptr) {
874 c896fe29 bellard
        c = *opc_ptr++;
875 c896fe29 bellard
        def = &tcg_op_defs[c];
876 7e4597d7 bellard
        if (c == INDEX_op_debug_insn_start) {
877 7e4597d7 bellard
            uint64_t pc;
878 7e4597d7 bellard
#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
879 7e4597d7 bellard
            pc = ((uint64_t)args[1] << 32) | args[0];
880 7e4597d7 bellard
#else
881 7e4597d7 bellard
            pc = args[0];
882 7e4597d7 bellard
#endif
883 7e4597d7 bellard
            if (!first_insn) 
884 7e4597d7 bellard
                fprintf(outfile, "\n");
885 7e4597d7 bellard
            fprintf(outfile, " ---- 0x%" PRIx64, pc);
886 7e4597d7 bellard
            first_insn = 0;
887 7e4597d7 bellard
            nb_oargs = def->nb_oargs;
888 7e4597d7 bellard
            nb_iargs = def->nb_iargs;
889 7e4597d7 bellard
            nb_cargs = def->nb_cargs;
890 7e4597d7 bellard
        } else if (c == INDEX_op_call) {
891 c896fe29 bellard
            TCGArg arg;
892 4dc81f28 bellard
893 c896fe29 bellard
            /* variable number of arguments */
894 c896fe29 bellard
            arg = *args++;
895 c896fe29 bellard
            nb_oargs = arg >> 16;
896 c896fe29 bellard
            nb_iargs = arg & 0xffff;
897 c896fe29 bellard
            nb_cargs = def->nb_cargs;
898 c896fe29 bellard
899 7e4597d7 bellard
            fprintf(outfile, " %s ", def->name);
900 7e4597d7 bellard
901 b03cce8e bellard
            /* function name */
902 ac56dd48 pbrook
            fprintf(outfile, "%s",
903 e8996ee0 bellard
                    tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + nb_iargs - 1]));
904 b03cce8e bellard
            /* flags */
905 b03cce8e bellard
            fprintf(outfile, ",$0x%" TCG_PRIlx,
906 b03cce8e bellard
                    args[nb_oargs + nb_iargs]);
907 b03cce8e bellard
            /* nb out args */
908 b03cce8e bellard
            fprintf(outfile, ",$%d", nb_oargs);
909 b03cce8e bellard
            for(i = 0; i < nb_oargs; i++) {
910 b03cce8e bellard
                fprintf(outfile, ",");
911 b03cce8e bellard
                fprintf(outfile, "%s",
912 b03cce8e bellard
                        tcg_get_arg_str_idx(s, buf, sizeof(buf), args[i]));
913 b03cce8e bellard
            }
914 b03cce8e bellard
            for(i = 0; i < (nb_iargs - 1); i++) {
915 c896fe29 bellard
                fprintf(outfile, ",");
916 39cf05d3 bellard
                if (args[nb_oargs + i] == TCG_CALL_DUMMY_ARG) {
917 39cf05d3 bellard
                    fprintf(outfile, "<dummy>");
918 39cf05d3 bellard
                } else {
919 39cf05d3 bellard
                    fprintf(outfile, "%s",
920 39cf05d3 bellard
                            tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + i]));
921 39cf05d3 bellard
                }
922 b03cce8e bellard
            }
923 e8996ee0 bellard
        } else if (c == INDEX_op_movi_i32 
924 e8996ee0 bellard
#if TCG_TARGET_REG_BITS == 64
925 e8996ee0 bellard
                   || c == INDEX_op_movi_i64
926 e8996ee0 bellard
#endif
927 e8996ee0 bellard
                   ) {
928 e8996ee0 bellard
            tcg_target_ulong val;
929 e8996ee0 bellard
            TCGHelperInfo *th;
930 e8996ee0 bellard
931 e8996ee0 bellard
            nb_oargs = def->nb_oargs;
932 e8996ee0 bellard
            nb_iargs = def->nb_iargs;
933 e8996ee0 bellard
            nb_cargs = def->nb_cargs;
934 e8996ee0 bellard
            fprintf(outfile, " %s %s,$", def->name, 
935 e8996ee0 bellard
                    tcg_get_arg_str_idx(s, buf, sizeof(buf), args[0]));
936 e8996ee0 bellard
            val = args[1];
937 e8996ee0 bellard
            th = tcg_find_helper(s, val);
938 e8996ee0 bellard
            if (th) {
939 3e9a474e aurel32
                fprintf(outfile, "%s", th->name);
940 e8996ee0 bellard
            } else {
941 e8996ee0 bellard
                if (c == INDEX_op_movi_i32)
942 e8996ee0 bellard
                    fprintf(outfile, "0x%x", (uint32_t)val);
943 e8996ee0 bellard
                else
944 e8996ee0 bellard
                    fprintf(outfile, "0x%" PRIx64 , (uint64_t)val);
945 e8996ee0 bellard
            }
946 b03cce8e bellard
        } else {
947 7e4597d7 bellard
            fprintf(outfile, " %s ", def->name);
948 b03cce8e bellard
            if (c == INDEX_op_nopn) {
949 b03cce8e bellard
                /* variable number of arguments */
950 b03cce8e bellard
                nb_cargs = *args;
951 b03cce8e bellard
                nb_oargs = 0;
952 b03cce8e bellard
                nb_iargs = 0;
953 b03cce8e bellard
            } else {
954 b03cce8e bellard
                nb_oargs = def->nb_oargs;
955 b03cce8e bellard
                nb_iargs = def->nb_iargs;
956 b03cce8e bellard
                nb_cargs = def->nb_cargs;
957 b03cce8e bellard
            }
958 b03cce8e bellard
            
959 b03cce8e bellard
            k = 0;
960 b03cce8e bellard
            for(i = 0; i < nb_oargs; i++) {
961 b03cce8e bellard
                if (k != 0)
962 b03cce8e bellard
                    fprintf(outfile, ",");
963 b03cce8e bellard
                fprintf(outfile, "%s",
964 b03cce8e bellard
                        tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
965 b03cce8e bellard
            }
966 b03cce8e bellard
            for(i = 0; i < nb_iargs; i++) {
967 b03cce8e bellard
                if (k != 0)
968 b03cce8e bellard
                    fprintf(outfile, ",");
969 b03cce8e bellard
                fprintf(outfile, "%s",
970 b03cce8e bellard
                        tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
971 b03cce8e bellard
            }
972 be210acb Richard Henderson
            switch (c) {
973 be210acb Richard Henderson
            case INDEX_op_brcond_i32:
974 be210acb Richard Henderson
#if TCG_TARGET_REG_BITS == 32
975 be210acb Richard Henderson
            case INDEX_op_brcond2_i32:
976 be210acb Richard Henderson
#elif TCG_TARGET_REG_BITS == 64
977 be210acb Richard Henderson
            case INDEX_op_brcond_i64:
978 be210acb Richard Henderson
#endif
979 be210acb Richard Henderson
            case INDEX_op_setcond_i32:
980 f48f3ede blueswir1
#if TCG_TARGET_REG_BITS == 32
981 be210acb Richard Henderson
            case INDEX_op_setcond2_i32:
982 f48f3ede blueswir1
#elif TCG_TARGET_REG_BITS == 64
983 be210acb Richard Henderson
            case INDEX_op_setcond_i64:
984 f48f3ede blueswir1
#endif
985 f48f3ede blueswir1
                if (args[k] < ARRAY_SIZE(cond_name) && cond_name[args[k]])
986 f48f3ede blueswir1
                    fprintf(outfile, ",%s", cond_name[args[k++]]);
987 f48f3ede blueswir1
                else
988 f48f3ede blueswir1
                    fprintf(outfile, ",$0x%" TCG_PRIlx, args[k++]);
989 f48f3ede blueswir1
                i = 1;
990 be210acb Richard Henderson
                break;
991 be210acb Richard Henderson
            default:
992 f48f3ede blueswir1
                i = 0;
993 be210acb Richard Henderson
                break;
994 be210acb Richard Henderson
            }
995 f48f3ede blueswir1
            for(; i < nb_cargs; i++) {
996 b03cce8e bellard
                if (k != 0)
997 b03cce8e bellard
                    fprintf(outfile, ",");
998 b03cce8e bellard
                arg = args[k++];
999 b03cce8e bellard
                fprintf(outfile, "$0x%" TCG_PRIlx, arg);
1000 b03cce8e bellard
            }
1001 c896fe29 bellard
        }
1002 c896fe29 bellard
        fprintf(outfile, "\n");
1003 c896fe29 bellard
        args += nb_iargs + nb_oargs + nb_cargs;
1004 c896fe29 bellard
    }
1005 c896fe29 bellard
}
1006 c896fe29 bellard
1007 c896fe29 bellard
/* we give more priority to constraints with less registers */
1008 c896fe29 bellard
static int get_constraint_priority(const TCGOpDef *def, int k)
1009 c896fe29 bellard
{
1010 c896fe29 bellard
    const TCGArgConstraint *arg_ct;
1011 c896fe29 bellard
1012 c896fe29 bellard
    int i, n;
1013 c896fe29 bellard
    arg_ct = &def->args_ct[k];
1014 c896fe29 bellard
    if (arg_ct->ct & TCG_CT_ALIAS) {
1015 c896fe29 bellard
        /* an alias is equivalent to a single register */
1016 c896fe29 bellard
        n = 1;
1017 c896fe29 bellard
    } else {
1018 c896fe29 bellard
        if (!(arg_ct->ct & TCG_CT_REG))
1019 c896fe29 bellard
            return 0;
1020 c896fe29 bellard
        n = 0;
1021 c896fe29 bellard
        for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
1022 c896fe29 bellard
            if (tcg_regset_test_reg(arg_ct->u.regs, i))
1023 c896fe29 bellard
                n++;
1024 c896fe29 bellard
        }
1025 c896fe29 bellard
    }
1026 c896fe29 bellard
    return TCG_TARGET_NB_REGS - n + 1;
1027 c896fe29 bellard
}
1028 c896fe29 bellard
1029 c896fe29 bellard
/* sort from highest priority to lowest */
1030 c896fe29 bellard
static void sort_constraints(TCGOpDef *def, int start, int n)
1031 c896fe29 bellard
{
1032 c896fe29 bellard
    int i, j, p1, p2, tmp;
1033 c896fe29 bellard
1034 c896fe29 bellard
    for(i = 0; i < n; i++)
1035 c896fe29 bellard
        def->sorted_args[start + i] = start + i;
1036 c896fe29 bellard
    if (n <= 1)
1037 c896fe29 bellard
        return;
1038 c896fe29 bellard
    for(i = 0; i < n - 1; i++) {
1039 c896fe29 bellard
        for(j = i + 1; j < n; j++) {
1040 c896fe29 bellard
            p1 = get_constraint_priority(def, def->sorted_args[start + i]);
1041 c896fe29 bellard
            p2 = get_constraint_priority(def, def->sorted_args[start + j]);
1042 c896fe29 bellard
            if (p1 < p2) {
1043 c896fe29 bellard
                tmp = def->sorted_args[start + i];
1044 c896fe29 bellard
                def->sorted_args[start + i] = def->sorted_args[start + j];
1045 c896fe29 bellard
                def->sorted_args[start + j] = tmp;
1046 c896fe29 bellard
            }
1047 c896fe29 bellard
        }
1048 c896fe29 bellard
    }
1049 c896fe29 bellard
}
1050 c896fe29 bellard
1051 c896fe29 bellard
void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs)
1052 c896fe29 bellard
{
1053 a9751609 Richard Henderson
    TCGOpcode op;
1054 c896fe29 bellard
    TCGOpDef *def;
1055 c896fe29 bellard
    const char *ct_str;
1056 c896fe29 bellard
    int i, nb_args;
1057 c896fe29 bellard
1058 c896fe29 bellard
    for(;;) {
1059 a9751609 Richard Henderson
        if (tdefs->op == (TCGOpcode)-1)
1060 c896fe29 bellard
            break;
1061 c896fe29 bellard
        op = tdefs->op;
1062 c3b08d0e Stefan Weil
        assert((unsigned)op < NB_OPS);
1063 c896fe29 bellard
        def = &tcg_op_defs[op];
1064 c68aaa18 Stefan Weil
#if defined(CONFIG_DEBUG_TCG)
1065 c68aaa18 Stefan Weil
        /* Duplicate entry in op definitions? */
1066 c68aaa18 Stefan Weil
        assert(!def->used);
1067 c68aaa18 Stefan Weil
        def->used = 1;
1068 c68aaa18 Stefan Weil
#endif
1069 c896fe29 bellard
        nb_args = def->nb_iargs + def->nb_oargs;
1070 c896fe29 bellard
        for(i = 0; i < nb_args; i++) {
1071 c896fe29 bellard
            ct_str = tdefs->args_ct_str[i];
1072 c68aaa18 Stefan Weil
            /* Incomplete TCGTargetOpDef entry? */
1073 c68aaa18 Stefan Weil
            assert(ct_str != NULL);
1074 c896fe29 bellard
            tcg_regset_clear(def->args_ct[i].u.regs);
1075 c896fe29 bellard
            def->args_ct[i].ct = 0;
1076 c896fe29 bellard
            if (ct_str[0] >= '0' && ct_str[0] <= '9') {
1077 c896fe29 bellard
                int oarg;
1078 c896fe29 bellard
                oarg = ct_str[0] - '0';
1079 c896fe29 bellard
                assert(oarg < def->nb_oargs);
1080 c896fe29 bellard
                assert(def->args_ct[oarg].ct & TCG_CT_REG);
1081 c896fe29 bellard
                /* TCG_CT_ALIAS is for the output arguments. The input
1082 5ff9d6a4 bellard
                   argument is tagged with TCG_CT_IALIAS. */
1083 c896fe29 bellard
                def->args_ct[i] = def->args_ct[oarg];
1084 5ff9d6a4 bellard
                def->args_ct[oarg].ct = TCG_CT_ALIAS;
1085 5ff9d6a4 bellard
                def->args_ct[oarg].alias_index = i;
1086 c896fe29 bellard
                def->args_ct[i].ct |= TCG_CT_IALIAS;
1087 5ff9d6a4 bellard
                def->args_ct[i].alias_index = oarg;
1088 c896fe29 bellard
            } else {
1089 c896fe29 bellard
                for(;;) {
1090 c896fe29 bellard
                    if (*ct_str == '\0')
1091 c896fe29 bellard
                        break;
1092 c896fe29 bellard
                    switch(*ct_str) {
1093 c896fe29 bellard
                    case 'i':
1094 c896fe29 bellard
                        def->args_ct[i].ct |= TCG_CT_CONST;
1095 c896fe29 bellard
                        ct_str++;
1096 c896fe29 bellard
                        break;
1097 c896fe29 bellard
                    default:
1098 c896fe29 bellard
                        if (target_parse_constraint(&def->args_ct[i], &ct_str) < 0) {
1099 c896fe29 bellard
                            fprintf(stderr, "Invalid constraint '%s' for arg %d of operation '%s'\n",
1100 c896fe29 bellard
                                    ct_str, i, def->name);
1101 c896fe29 bellard
                            exit(1);
1102 c896fe29 bellard
                        }
1103 c896fe29 bellard
                    }
1104 c896fe29 bellard
                }
1105 c896fe29 bellard
            }
1106 c896fe29 bellard
        }
1107 c896fe29 bellard
1108 c68aaa18 Stefan Weil
        /* TCGTargetOpDef entry with too much information? */
1109 c68aaa18 Stefan Weil
        assert(i == TCG_MAX_OP_ARGS || tdefs->args_ct_str[i] == NULL);
1110 c68aaa18 Stefan Weil
1111 c896fe29 bellard
        /* sort the constraints (XXX: this is just an heuristic) */
1112 c896fe29 bellard
        sort_constraints(def, 0, def->nb_oargs);
1113 c896fe29 bellard
        sort_constraints(def, def->nb_oargs, def->nb_iargs);
1114 c896fe29 bellard
1115 c896fe29 bellard
#if 0
1116 c896fe29 bellard
        {
1117 c896fe29 bellard
            int i;
1118 c896fe29 bellard

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