Statistics
| Branch: | Revision:

root / tcg / tcg.c @ 6b64b624

History | View | Annotate | Download (65.6 kB)

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

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