Statistics
| Branch: | Revision:

root / tcg / tcg.c @ ae60fea9

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

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