Statistics
| Branch: | Revision:

root / tcg / tcg.c @ d1bdd3af

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

1150 c896fe29 bellard
            printf("%s: sorted=", def->name);
1151 c896fe29 bellard
            for(i = 0; i < def->nb_oargs + def->nb_iargs; i++)
1152 c896fe29 bellard
                printf(" %d", def->sorted_args[i]);
1153 c896fe29 bellard
            printf("\n");
1154 c896fe29 bellard
        }
1155 c896fe29 bellard
#endif
1156 c896fe29 bellard
        tdefs++;
1157 c896fe29 bellard
    }
1158 c896fe29 bellard
1159 c68aaa18 Stefan Weil
#if defined(CONFIG_DEBUG_TCG)
1160 a9751609 Richard Henderson
    i = 0;
1161 c68aaa18 Stefan Weil
    for (op = 0; op < ARRAY_SIZE(tcg_op_defs); op++) {
1162 f412c762 Richard Henderson
        const TCGOpDef *def = &tcg_op_defs[op];
1163 f412c762 Richard Henderson
        if (op < INDEX_op_call
1164 f412c762 Richard Henderson
            || op == INDEX_op_debug_insn_start
1165 f412c762 Richard Henderson
            || (def->flags & TCG_OPF_NOT_PRESENT)) {
1166 c68aaa18 Stefan Weil
            /* Wrong entry in op definitions? */
1167 f412c762 Richard Henderson
            if (def->used) {
1168 f412c762 Richard Henderson
                fprintf(stderr, "Invalid op definition for %s\n", def->name);
1169 a9751609 Richard Henderson
                i = 1;
1170 a9751609 Richard Henderson
            }
1171 c68aaa18 Stefan Weil
        } else {
1172 c68aaa18 Stefan Weil
            /* Missing entry in op definitions? */
1173 f412c762 Richard Henderson
            if (!def->used) {
1174 f412c762 Richard Henderson
                fprintf(stderr, "Missing op definition for %s\n", def->name);
1175 a9751609 Richard Henderson
                i = 1;
1176 a9751609 Richard Henderson
            }
1177 c68aaa18 Stefan Weil
        }
1178 c68aaa18 Stefan Weil
    }
1179 a9751609 Richard Henderson
    if (i == 1) {
1180 a9751609 Richard Henderson
        tcg_abort();
1181 a9751609 Richard Henderson
    }
1182 c68aaa18 Stefan Weil
#endif
1183 c896fe29 bellard
}
1184 c896fe29 bellard
1185 c896fe29 bellard
#ifdef USE_LIVENESS_ANALYSIS
1186 c896fe29 bellard
1187 c896fe29 bellard
/* set a nop for an operation using 'nb_args' */
1188 c896fe29 bellard
static inline void tcg_set_nop(TCGContext *s, uint16_t *opc_ptr, 
1189 c896fe29 bellard
                               TCGArg *args, int nb_args)
1190 c896fe29 bellard
{
1191 c896fe29 bellard
    if (nb_args == 0) {
1192 c896fe29 bellard
        *opc_ptr = INDEX_op_nop;
1193 c896fe29 bellard
    } else {
1194 c896fe29 bellard
        *opc_ptr = INDEX_op_nopn;
1195 c896fe29 bellard
        args[0] = nb_args;
1196 c896fe29 bellard
        args[nb_args - 1] = nb_args;
1197 c896fe29 bellard
    }
1198 c896fe29 bellard
}
1199 c896fe29 bellard
1200 9c43b68d Aurelien Jarno
/* liveness analysis: end of function: all temps are dead, and globals
1201 9c43b68d Aurelien Jarno
   should be in memory. */
1202 9c43b68d Aurelien Jarno
static inline void tcg_la_func_end(TCGContext *s, uint8_t *dead_temps,
1203 9c43b68d Aurelien Jarno
                                   uint8_t *mem_temps)
1204 c896fe29 bellard
{
1205 9c43b68d Aurelien Jarno
    memset(dead_temps, 1, s->nb_temps);
1206 9c43b68d Aurelien Jarno
    memset(mem_temps, 1, s->nb_globals);
1207 9c43b68d Aurelien Jarno
    memset(mem_temps + s->nb_globals, 0, s->nb_temps - s->nb_globals);
1208 c896fe29 bellard
}
1209 c896fe29 bellard
1210 9c43b68d Aurelien Jarno
/* liveness analysis: end of basic block: all temps are dead, globals
1211 9c43b68d Aurelien Jarno
   and local temps should be in memory. */
1212 9c43b68d Aurelien Jarno
static inline void tcg_la_bb_end(TCGContext *s, uint8_t *dead_temps,
1213 9c43b68d Aurelien Jarno
                                 uint8_t *mem_temps)
1214 641d5fbe bellard
{
1215 641d5fbe bellard
    int i;
1216 641d5fbe bellard
1217 9c43b68d Aurelien Jarno
    memset(dead_temps, 1, s->nb_temps);
1218 9c43b68d Aurelien Jarno
    memset(mem_temps, 1, s->nb_globals);
1219 641d5fbe bellard
    for(i = s->nb_globals; i < s->nb_temps; i++) {
1220 9c43b68d Aurelien Jarno
        mem_temps[i] = s->temps[i].temp_local;
1221 641d5fbe bellard
    }
1222 641d5fbe bellard
}
1223 641d5fbe bellard
1224 866cb6cb Aurelien Jarno
/* Liveness analysis : update the opc_dead_args array to tell if a
1225 c896fe29 bellard
   given input arguments is dead. Instructions updating dead
1226 c896fe29 bellard
   temporaries are removed. */
1227 8fcd3692 blueswir1
static void tcg_liveness_analysis(TCGContext *s)
1228 c896fe29 bellard
{
1229 a9751609 Richard Henderson
    int i, op_index, nb_args, nb_iargs, nb_oargs, arg, nb_ops;
1230 f1fae40c Richard Henderson
    TCGOpcode op, op_new;
1231 c896fe29 bellard
    TCGArg *args;
1232 c896fe29 bellard
    const TCGOpDef *def;
1233 9c43b68d Aurelien Jarno
    uint8_t *dead_temps, *mem_temps;
1234 ec7a869d Aurelien Jarno
    uint16_t dead_args;
1235 ec7a869d Aurelien Jarno
    uint8_t sync_args;
1236 c896fe29 bellard
    
1237 efd7f486 Evgeny Voevodin
    s->gen_opc_ptr++; /* skip end */
1238 c896fe29 bellard
1239 92414b31 Evgeny Voevodin
    nb_ops = s->gen_opc_ptr - s->gen_opc_buf;
1240 c896fe29 bellard
1241 866cb6cb Aurelien Jarno
    s->op_dead_args = tcg_malloc(nb_ops * sizeof(uint16_t));
1242 ec7a869d Aurelien Jarno
    s->op_sync_args = tcg_malloc(nb_ops * sizeof(uint8_t));
1243 c896fe29 bellard
    
1244 c896fe29 bellard
    dead_temps = tcg_malloc(s->nb_temps);
1245 9c43b68d Aurelien Jarno
    mem_temps = tcg_malloc(s->nb_temps);
1246 9c43b68d Aurelien Jarno
    tcg_la_func_end(s, dead_temps, mem_temps);
1247 c896fe29 bellard
1248 c4afe5c4 Evgeny Voevodin
    args = s->gen_opparam_ptr;
1249 c896fe29 bellard
    op_index = nb_ops - 1;
1250 c896fe29 bellard
    while (op_index >= 0) {
1251 92414b31 Evgeny Voevodin
        op = s->gen_opc_buf[op_index];
1252 c896fe29 bellard
        def = &tcg_op_defs[op];
1253 c896fe29 bellard
        switch(op) {
1254 c896fe29 bellard
        case INDEX_op_call:
1255 c6e113f5 bellard
            {
1256 c6e113f5 bellard
                int call_flags;
1257 c896fe29 bellard
1258 c6e113f5 bellard
                nb_args = args[-1];
1259 c6e113f5 bellard
                args -= nb_args;
1260 c6e113f5 bellard
                nb_iargs = args[0] & 0xffff;
1261 c6e113f5 bellard
                nb_oargs = args[0] >> 16;
1262 c6e113f5 bellard
                args++;
1263 c6e113f5 bellard
                call_flags = args[nb_oargs + nb_iargs];
1264 c6e113f5 bellard
1265 c6e113f5 bellard
                /* pure functions can be removed if their result is not
1266 c6e113f5 bellard
                   used */
1267 78505279 Aurelien Jarno
                if (call_flags & TCG_CALL_NO_SIDE_EFFECTS) {
1268 c6e113f5 bellard
                    for(i = 0; i < nb_oargs; i++) {
1269 c6e113f5 bellard
                        arg = args[i];
1270 9c43b68d Aurelien Jarno
                        if (!dead_temps[arg] || mem_temps[arg]) {
1271 c6e113f5 bellard
                            goto do_not_remove_call;
1272 9c43b68d Aurelien Jarno
                        }
1273 c6e113f5 bellard
                    }
1274 92414b31 Evgeny Voevodin
                    tcg_set_nop(s, s->gen_opc_buf + op_index,
1275 c6e113f5 bellard
                                args - 1, nb_args);
1276 c6e113f5 bellard
                } else {
1277 c6e113f5 bellard
                do_not_remove_call:
1278 c896fe29 bellard
1279 c6e113f5 bellard
                    /* output args are dead */
1280 6b64b624 Aurelien Jarno
                    dead_args = 0;
1281 ec7a869d Aurelien Jarno
                    sync_args = 0;
1282 c6e113f5 bellard
                    for(i = 0; i < nb_oargs; i++) {
1283 c6e113f5 bellard
                        arg = args[i];
1284 6b64b624 Aurelien Jarno
                        if (dead_temps[arg]) {
1285 6b64b624 Aurelien Jarno
                            dead_args |= (1 << i);
1286 6b64b624 Aurelien Jarno
                        }
1287 9c43b68d Aurelien Jarno
                        if (mem_temps[arg]) {
1288 9c43b68d Aurelien Jarno
                            sync_args |= (1 << i);
1289 9c43b68d Aurelien Jarno
                        }
1290 c6e113f5 bellard
                        dead_temps[arg] = 1;
1291 9c43b68d Aurelien Jarno
                        mem_temps[arg] = 0;
1292 c6e113f5 bellard
                    }
1293 78505279 Aurelien Jarno
1294 78505279 Aurelien Jarno
                    if (!(call_flags & TCG_CALL_NO_READ_GLOBALS)) {
1295 78505279 Aurelien Jarno
                        /* globals should be synced to memory */
1296 78505279 Aurelien Jarno
                        memset(mem_temps, 1, s->nb_globals);
1297 78505279 Aurelien Jarno
                    }
1298 78505279 Aurelien Jarno
                    if (!(call_flags & (TCG_CALL_NO_WRITE_GLOBALS |
1299 78505279 Aurelien Jarno
                                        TCG_CALL_NO_READ_GLOBALS))) {
1300 9c43b68d Aurelien Jarno
                        /* globals should go back to memory */
1301 9c43b68d Aurelien Jarno
                        memset(dead_temps, 1, s->nb_globals);
1302 b9c18f56 aurel32
                    }
1303 b9c18f56 aurel32
1304 c6e113f5 bellard
                    /* input args are live */
1305 866cb6cb Aurelien Jarno
                    for(i = nb_oargs; i < nb_iargs + nb_oargs; i++) {
1306 866cb6cb Aurelien Jarno
                        arg = args[i];
1307 39cf05d3 bellard
                        if (arg != TCG_CALL_DUMMY_ARG) {
1308 39cf05d3 bellard
                            if (dead_temps[arg]) {
1309 866cb6cb Aurelien Jarno
                                dead_args |= (1 << i);
1310 39cf05d3 bellard
                            }
1311 39cf05d3 bellard
                            dead_temps[arg] = 0;
1312 c6e113f5 bellard
                        }
1313 c6e113f5 bellard
                    }
1314 866cb6cb Aurelien Jarno
                    s->op_dead_args[op_index] = dead_args;
1315 ec7a869d Aurelien Jarno
                    s->op_sync_args[op_index] = sync_args;
1316 c896fe29 bellard
                }
1317 c6e113f5 bellard
                args--;
1318 c896fe29 bellard
            }
1319 c896fe29 bellard
            break;
1320 7e4597d7 bellard
        case INDEX_op_debug_insn_start:
1321 7e4597d7 bellard
            args -= def->nb_args;
1322 7e4597d7 bellard
            break;
1323 c896fe29 bellard
        case INDEX_op_nopn:
1324 c896fe29 bellard
            nb_args = args[-1];
1325 c896fe29 bellard
            args -= nb_args;
1326 c896fe29 bellard
            break;
1327 5ff9d6a4 bellard
        case INDEX_op_discard:
1328 5ff9d6a4 bellard
            args--;
1329 5ff9d6a4 bellard
            /* mark the temporary as dead */
1330 5ff9d6a4 bellard
            dead_temps[args[0]] = 1;
1331 9c43b68d Aurelien Jarno
            mem_temps[args[0]] = 0;
1332 5ff9d6a4 bellard
            break;
1333 c896fe29 bellard
        case INDEX_op_end:
1334 c896fe29 bellard
            break;
1335 1305c451 Richard Henderson
1336 1305c451 Richard Henderson
        case INDEX_op_add2_i32:
1337 f1fae40c Richard Henderson
            op_new = INDEX_op_add_i32;
1338 f1fae40c Richard Henderson
            goto do_addsub2;
1339 1305c451 Richard Henderson
        case INDEX_op_sub2_i32:
1340 f1fae40c Richard Henderson
            op_new = INDEX_op_sub_i32;
1341 f1fae40c Richard Henderson
            goto do_addsub2;
1342 f1fae40c Richard Henderson
        case INDEX_op_add2_i64:
1343 f1fae40c Richard Henderson
            op_new = INDEX_op_add_i64;
1344 f1fae40c Richard Henderson
            goto do_addsub2;
1345 f1fae40c Richard Henderson
        case INDEX_op_sub2_i64:
1346 f1fae40c Richard Henderson
            op_new = INDEX_op_sub_i64;
1347 f1fae40c Richard Henderson
        do_addsub2:
1348 1305c451 Richard Henderson
            args -= 6;
1349 1305c451 Richard Henderson
            nb_iargs = 4;
1350 1305c451 Richard Henderson
            nb_oargs = 2;
1351 1305c451 Richard Henderson
            /* Test if the high part of the operation is dead, but not
1352 1305c451 Richard Henderson
               the low part.  The result can be optimized to a simple
1353 1305c451 Richard Henderson
               add or sub.  This happens often for x86_64 guest when the
1354 1305c451 Richard Henderson
               cpu mode is set to 32 bit.  */
1355 3c5645fa Kirill Batuzov
            if (dead_temps[args[1]] && !mem_temps[args[1]]) {
1356 3c5645fa Kirill Batuzov
                if (dead_temps[args[0]] && !mem_temps[args[0]]) {
1357 1305c451 Richard Henderson
                    goto do_remove;
1358 1305c451 Richard Henderson
                }
1359 1305c451 Richard Henderson
                /* Create the single operation plus nop.  */
1360 f1fae40c Richard Henderson
                s->gen_opc_buf[op_index] = op = op_new;
1361 1305c451 Richard Henderson
                args[1] = args[2];
1362 1305c451 Richard Henderson
                args[2] = args[4];
1363 92414b31 Evgeny Voevodin
                assert(s->gen_opc_buf[op_index + 1] == INDEX_op_nop);
1364 92414b31 Evgeny Voevodin
                tcg_set_nop(s, s->gen_opc_buf + op_index + 1, args + 3, 3);
1365 1305c451 Richard Henderson
                /* Fall through and mark the single-word operation live.  */
1366 1305c451 Richard Henderson
                nb_iargs = 2;
1367 1305c451 Richard Henderson
                nb_oargs = 1;
1368 1305c451 Richard Henderson
            }
1369 1305c451 Richard Henderson
            goto do_not_remove;
1370 1305c451 Richard Henderson
1371 1414968a Richard Henderson
        case INDEX_op_mulu2_i32:
1372 f1fae40c Richard Henderson
        case INDEX_op_muls2_i32:
1373 f1fae40c Richard Henderson
            op_new = INDEX_op_mul_i32;
1374 f1fae40c Richard Henderson
            goto do_mul2;
1375 f1fae40c Richard Henderson
        case INDEX_op_mulu2_i64:
1376 f1fae40c Richard Henderson
        case INDEX_op_muls2_i64:
1377 f1fae40c Richard Henderson
            op_new = INDEX_op_mul_i64;
1378 f1fae40c Richard Henderson
        do_mul2:
1379 1414968a Richard Henderson
            args -= 4;
1380 1414968a Richard Henderson
            nb_iargs = 2;
1381 1414968a Richard Henderson
            nb_oargs = 2;
1382 1414968a Richard Henderson
            /* Likewise, test for the high part of the operation dead.  */
1383 3c5645fa Kirill Batuzov
            if (dead_temps[args[1]] && !mem_temps[args[1]]) {
1384 3c5645fa Kirill Batuzov
                if (dead_temps[args[0]] && !mem_temps[args[0]]) {
1385 1414968a Richard Henderson
                    goto do_remove;
1386 1414968a Richard Henderson
                }
1387 f1fae40c Richard Henderson
                s->gen_opc_buf[op_index] = op = op_new;
1388 1414968a Richard Henderson
                args[1] = args[2];
1389 1414968a Richard Henderson
                args[2] = args[3];
1390 92414b31 Evgeny Voevodin
                assert(s->gen_opc_buf[op_index + 1] == INDEX_op_nop);
1391 92414b31 Evgeny Voevodin
                tcg_set_nop(s, s->gen_opc_buf + op_index + 1, args + 3, 1);
1392 1414968a Richard Henderson
                /* Fall through and mark the single-word operation live.  */
1393 1414968a Richard Henderson
                nb_oargs = 1;
1394 1414968a Richard Henderson
            }
1395 1414968a Richard Henderson
            goto do_not_remove;
1396 1414968a Richard Henderson
1397 c896fe29 bellard
        default:
1398 1305c451 Richard Henderson
            /* XXX: optimize by hardcoding common cases (e.g. triadic ops) */
1399 49516bc0 aurel32
            args -= def->nb_args;
1400 49516bc0 aurel32
            nb_iargs = def->nb_iargs;
1401 49516bc0 aurel32
            nb_oargs = def->nb_oargs;
1402 c896fe29 bellard
1403 49516bc0 aurel32
            /* Test if the operation can be removed because all
1404 49516bc0 aurel32
               its outputs are dead. We assume that nb_oargs == 0
1405 49516bc0 aurel32
               implies side effects */
1406 49516bc0 aurel32
            if (!(def->flags & TCG_OPF_SIDE_EFFECTS) && nb_oargs != 0) {
1407 49516bc0 aurel32
                for(i = 0; i < nb_oargs; i++) {
1408 49516bc0 aurel32
                    arg = args[i];
1409 9c43b68d Aurelien Jarno
                    if (!dead_temps[arg] || mem_temps[arg]) {
1410 49516bc0 aurel32
                        goto do_not_remove;
1411 9c43b68d Aurelien Jarno
                    }
1412 49516bc0 aurel32
                }
1413 1305c451 Richard Henderson
            do_remove:
1414 92414b31 Evgeny Voevodin
                tcg_set_nop(s, s->gen_opc_buf + op_index, args, def->nb_args);
1415 c896fe29 bellard
#ifdef CONFIG_PROFILER
1416 49516bc0 aurel32
                s->del_op_count++;
1417 c896fe29 bellard
#endif
1418 49516bc0 aurel32
            } else {
1419 49516bc0 aurel32
            do_not_remove:
1420 c896fe29 bellard
1421 49516bc0 aurel32
                /* output args are dead */
1422 6b64b624 Aurelien Jarno
                dead_args = 0;
1423 ec7a869d Aurelien Jarno
                sync_args = 0;
1424 49516bc0 aurel32
                for(i = 0; i < nb_oargs; i++) {
1425 49516bc0 aurel32
                    arg = args[i];
1426 6b64b624 Aurelien Jarno
                    if (dead_temps[arg]) {
1427 6b64b624 Aurelien Jarno
                        dead_args |= (1 << i);
1428 6b64b624 Aurelien Jarno
                    }
1429 9c43b68d Aurelien Jarno
                    if (mem_temps[arg]) {
1430 9c43b68d Aurelien Jarno
                        sync_args |= (1 << i);
1431 9c43b68d Aurelien Jarno
                    }
1432 49516bc0 aurel32
                    dead_temps[arg] = 1;
1433 9c43b68d Aurelien Jarno
                    mem_temps[arg] = 0;
1434 49516bc0 aurel32
                }
1435 49516bc0 aurel32
1436 49516bc0 aurel32
                /* if end of basic block, update */
1437 49516bc0 aurel32
                if (def->flags & TCG_OPF_BB_END) {
1438 9c43b68d Aurelien Jarno
                    tcg_la_bb_end(s, dead_temps, mem_temps);
1439 3d5c5f87 Aurelien Jarno
                } else if (def->flags & TCG_OPF_SIDE_EFFECTS) {
1440 3d5c5f87 Aurelien Jarno
                    /* globals should be synced to memory */
1441 9c43b68d Aurelien Jarno
                    memset(mem_temps, 1, s->nb_globals);
1442 49516bc0 aurel32
                }
1443 49516bc0 aurel32
1444 49516bc0 aurel32
                /* input args are live */
1445 866cb6cb Aurelien Jarno
                for(i = nb_oargs; i < nb_oargs + nb_iargs; i++) {
1446 866cb6cb Aurelien Jarno
                    arg = args[i];
1447 49516bc0 aurel32
                    if (dead_temps[arg]) {
1448 866cb6cb Aurelien Jarno
                        dead_args |= (1 << i);
1449 c896fe29 bellard
                    }
1450 49516bc0 aurel32
                    dead_temps[arg] = 0;
1451 c896fe29 bellard
                }
1452 866cb6cb Aurelien Jarno
                s->op_dead_args[op_index] = dead_args;
1453 ec7a869d Aurelien Jarno
                s->op_sync_args[op_index] = sync_args;
1454 c896fe29 bellard
            }
1455 c896fe29 bellard
            break;
1456 c896fe29 bellard
        }
1457 c896fe29 bellard
        op_index--;
1458 c896fe29 bellard
    }
1459 c896fe29 bellard
1460 1ff0a2c5 Evgeny Voevodin
    if (args != s->gen_opparam_buf) {
1461 c896fe29 bellard
        tcg_abort();
1462 1ff0a2c5 Evgeny Voevodin
    }
1463 c896fe29 bellard
}
1464 c896fe29 bellard
#else
1465 c896fe29 bellard
/* dummy liveness analysis */
1466 655feed5 malc
static void tcg_liveness_analysis(TCGContext *s)
1467 c896fe29 bellard
{
1468 c896fe29 bellard
    int nb_ops;
1469 92414b31 Evgeny Voevodin
    nb_ops = s->gen_opc_ptr - s->gen_opc_buf;
1470 c896fe29 bellard
1471 866cb6cb Aurelien Jarno
    s->op_dead_args = tcg_malloc(nb_ops * sizeof(uint16_t));
1472 866cb6cb Aurelien Jarno
    memset(s->op_dead_args, 0, nb_ops * sizeof(uint16_t));
1473 ec7a869d Aurelien Jarno
    s->op_sync_args = tcg_malloc(nb_ops * sizeof(uint8_t));
1474 ec7a869d Aurelien Jarno
    memset(s->op_sync_args, 0, nb_ops * sizeof(uint8_t));
1475 c896fe29 bellard
}
1476 c896fe29 bellard
#endif
1477 c896fe29 bellard
1478 c896fe29 bellard
#ifndef NDEBUG
1479 c896fe29 bellard
static void dump_regs(TCGContext *s)
1480 c896fe29 bellard
{
1481 c896fe29 bellard
    TCGTemp *ts;
1482 c896fe29 bellard
    int i;
1483 c896fe29 bellard
    char buf[64];
1484 c896fe29 bellard
1485 c896fe29 bellard
    for(i = 0; i < s->nb_temps; i++) {
1486 c896fe29 bellard
        ts = &s->temps[i];
1487 ac56dd48 pbrook
        printf("  %10s: ", tcg_get_arg_str_idx(s, buf, sizeof(buf), i));
1488 c896fe29 bellard
        switch(ts->val_type) {
1489 c896fe29 bellard
        case TEMP_VAL_REG:
1490 c896fe29 bellard
            printf("%s", tcg_target_reg_names[ts->reg]);
1491 c896fe29 bellard
            break;
1492 c896fe29 bellard
        case TEMP_VAL_MEM:
1493 c896fe29 bellard
            printf("%d(%s)", (int)ts->mem_offset, tcg_target_reg_names[ts->mem_reg]);
1494 c896fe29 bellard
            break;
1495 c896fe29 bellard
        case TEMP_VAL_CONST:
1496 c896fe29 bellard
            printf("$0x%" TCG_PRIlx, ts->val);
1497 c896fe29 bellard
            break;
1498 c896fe29 bellard
        case TEMP_VAL_DEAD:
1499 c896fe29 bellard
            printf("D");
1500 c896fe29 bellard
            break;
1501 c896fe29 bellard
        default:
1502 c896fe29 bellard
            printf("???");
1503 c896fe29 bellard
            break;
1504 c896fe29 bellard
        }
1505 c896fe29 bellard
        printf("\n");
1506 c896fe29 bellard
    }
1507 c896fe29 bellard
1508 c896fe29 bellard
    for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
1509 c896fe29 bellard
        if (s->reg_to_temp[i] >= 0) {
1510 c896fe29 bellard
            printf("%s: %s\n", 
1511 c896fe29 bellard
                   tcg_target_reg_names[i], 
1512 ac56dd48 pbrook
                   tcg_get_arg_str_idx(s, buf, sizeof(buf), s->reg_to_temp[i]));
1513 c896fe29 bellard
        }
1514 c896fe29 bellard
    }
1515 c896fe29 bellard
}
1516 c896fe29 bellard
1517 c896fe29 bellard
static void check_regs(TCGContext *s)
1518 c896fe29 bellard
{
1519 c896fe29 bellard
    int reg, k;
1520 c896fe29 bellard
    TCGTemp *ts;
1521 c896fe29 bellard
    char buf[64];
1522 c896fe29 bellard
1523 c896fe29 bellard
    for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1524 c896fe29 bellard
        k = s->reg_to_temp[reg];
1525 c896fe29 bellard
        if (k >= 0) {
1526 c896fe29 bellard
            ts = &s->temps[k];
1527 c896fe29 bellard
            if (ts->val_type != TEMP_VAL_REG ||
1528 c896fe29 bellard
                ts->reg != reg) {
1529 c896fe29 bellard
                printf("Inconsistency for register %s:\n", 
1530 c896fe29 bellard
                       tcg_target_reg_names[reg]);
1531 b03cce8e bellard
                goto fail;
1532 c896fe29 bellard
            }
1533 c896fe29 bellard
        }
1534 c896fe29 bellard
    }
1535 c896fe29 bellard
    for(k = 0; k < s->nb_temps; k++) {
1536 c896fe29 bellard
        ts = &s->temps[k];
1537 c896fe29 bellard
        if (ts->val_type == TEMP_VAL_REG &&
1538 c896fe29 bellard
            !ts->fixed_reg &&
1539 c896fe29 bellard
            s->reg_to_temp[ts->reg] != k) {
1540 c896fe29 bellard
                printf("Inconsistency for temp %s:\n", 
1541 ac56dd48 pbrook
                       tcg_get_arg_str_idx(s, buf, sizeof(buf), k));
1542 b03cce8e bellard
        fail:
1543 c896fe29 bellard
                printf("reg state:\n");
1544 c896fe29 bellard
                dump_regs(s);
1545 c896fe29 bellard
                tcg_abort();
1546 c896fe29 bellard
        }
1547 c896fe29 bellard
    }
1548 c896fe29 bellard
}
1549 c896fe29 bellard
#endif
1550 c896fe29 bellard
1551 c896fe29 bellard
static void temp_allocate_frame(TCGContext *s, int temp)
1552 c896fe29 bellard
{
1553 c896fe29 bellard
    TCGTemp *ts;
1554 c896fe29 bellard
    ts = &s->temps[temp];
1555 9b9c37c3 Richard Henderson
#if !(defined(__sparc__) && TCG_TARGET_REG_BITS == 64)
1556 9b9c37c3 Richard Henderson
    /* Sparc64 stack is accessed with offset of 2047 */
1557 b591dc59 Blue Swirl
    s->current_frame_offset = (s->current_frame_offset +
1558 b591dc59 Blue Swirl
                               (tcg_target_long)sizeof(tcg_target_long) - 1) &
1559 b591dc59 Blue Swirl
        ~(sizeof(tcg_target_long) - 1);
1560 f44c9960 Blue Swirl
#endif
1561 b591dc59 Blue Swirl
    if (s->current_frame_offset + (tcg_target_long)sizeof(tcg_target_long) >
1562 b591dc59 Blue Swirl
        s->frame_end) {
1563 5ff9d6a4 bellard
        tcg_abort();
1564 b591dc59 Blue Swirl
    }
1565 c896fe29 bellard
    ts->mem_offset = s->current_frame_offset;
1566 c896fe29 bellard
    ts->mem_reg = s->frame_reg;
1567 c896fe29 bellard
    ts->mem_allocated = 1;
1568 b591dc59 Blue Swirl
    s->current_frame_offset += (tcg_target_long)sizeof(tcg_target_long);
1569 c896fe29 bellard
}
1570 c896fe29 bellard
1571 7f6ceedf Aurelien Jarno
/* sync register 'reg' by saving it to the corresponding temporary */
1572 7f6ceedf Aurelien Jarno
static inline void tcg_reg_sync(TCGContext *s, int reg)
1573 7f6ceedf Aurelien Jarno
{
1574 7f6ceedf Aurelien Jarno
    TCGTemp *ts;
1575 7f6ceedf Aurelien Jarno
    int temp;
1576 7f6ceedf Aurelien Jarno
1577 7f6ceedf Aurelien Jarno
    temp = s->reg_to_temp[reg];
1578 7f6ceedf Aurelien Jarno
    ts = &s->temps[temp];
1579 7f6ceedf Aurelien Jarno
    assert(ts->val_type == TEMP_VAL_REG);
1580 7f6ceedf Aurelien Jarno
    if (!ts->mem_coherent && !ts->fixed_reg) {
1581 7f6ceedf Aurelien Jarno
        if (!ts->mem_allocated) {
1582 7f6ceedf Aurelien Jarno
            temp_allocate_frame(s, temp);
1583 7f6ceedf Aurelien Jarno
        }
1584 7f6ceedf Aurelien Jarno
        tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1585 7f6ceedf Aurelien Jarno
    }
1586 7f6ceedf Aurelien Jarno
    ts->mem_coherent = 1;
1587 7f6ceedf Aurelien Jarno
}
1588 7f6ceedf Aurelien Jarno
1589 c896fe29 bellard
/* free register 'reg' by spilling the corresponding temporary if necessary */
1590 c896fe29 bellard
static void tcg_reg_free(TCGContext *s, int reg)
1591 c896fe29 bellard
{
1592 c896fe29 bellard
    int temp;
1593 c896fe29 bellard
1594 c896fe29 bellard
    temp = s->reg_to_temp[reg];
1595 c896fe29 bellard
    if (temp != -1) {
1596 7f6ceedf Aurelien Jarno
        tcg_reg_sync(s, reg);
1597 7f6ceedf Aurelien Jarno
        s->temps[temp].val_type = TEMP_VAL_MEM;
1598 c896fe29 bellard
        s->reg_to_temp[reg] = -1;
1599 c896fe29 bellard
    }
1600 c896fe29 bellard
}
1601 c896fe29 bellard
1602 c896fe29 bellard
/* Allocate a register belonging to reg1 & ~reg2 */
1603 c896fe29 bellard
static int tcg_reg_alloc(TCGContext *s, TCGRegSet reg1, TCGRegSet reg2)
1604 c896fe29 bellard
{
1605 c896fe29 bellard
    int i, reg;
1606 c896fe29 bellard
    TCGRegSet reg_ct;
1607 c896fe29 bellard
1608 c896fe29 bellard
    tcg_regset_andnot(reg_ct, reg1, reg2);
1609 c896fe29 bellard
1610 c896fe29 bellard
    /* first try free registers */
1611 0954d0d9 blueswir1
    for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1612 c896fe29 bellard
        reg = tcg_target_reg_alloc_order[i];
1613 c896fe29 bellard
        if (tcg_regset_test_reg(reg_ct, reg) && s->reg_to_temp[reg] == -1)
1614 c896fe29 bellard
            return reg;
1615 c896fe29 bellard
    }
1616 c896fe29 bellard
1617 c896fe29 bellard
    /* XXX: do better spill choice */
1618 0954d0d9 blueswir1
    for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1619 c896fe29 bellard
        reg = tcg_target_reg_alloc_order[i];
1620 c896fe29 bellard
        if (tcg_regset_test_reg(reg_ct, reg)) {
1621 c896fe29 bellard
            tcg_reg_free(s, reg);
1622 c896fe29 bellard
            return reg;
1623 c896fe29 bellard
        }
1624 c896fe29 bellard
    }
1625 c896fe29 bellard
1626 c896fe29 bellard
    tcg_abort();
1627 c896fe29 bellard
}
1628 c896fe29 bellard
1629 639368dd Aurelien Jarno
/* mark a temporary as dead. */
1630 639368dd Aurelien Jarno
static inline void temp_dead(TCGContext *s, int temp)
1631 639368dd Aurelien Jarno
{
1632 639368dd Aurelien Jarno
    TCGTemp *ts;
1633 639368dd Aurelien Jarno
1634 639368dd Aurelien Jarno
    ts = &s->temps[temp];
1635 639368dd Aurelien Jarno
    if (!ts->fixed_reg) {
1636 639368dd Aurelien Jarno
        if (ts->val_type == TEMP_VAL_REG) {
1637 639368dd Aurelien Jarno
            s->reg_to_temp[ts->reg] = -1;
1638 639368dd Aurelien Jarno
        }
1639 e5138db5 Aurelien Jarno
        if (temp < s->nb_globals || ts->temp_local) {
1640 639368dd Aurelien Jarno
            ts->val_type = TEMP_VAL_MEM;
1641 639368dd Aurelien Jarno
        } else {
1642 639368dd Aurelien Jarno
            ts->val_type = TEMP_VAL_DEAD;
1643 639368dd Aurelien Jarno
        }
1644 639368dd Aurelien Jarno
    }
1645 639368dd Aurelien Jarno
}
1646 639368dd Aurelien Jarno
1647 1ad80729 Aurelien Jarno
/* sync a temporary to memory. 'allocated_regs' is used in case a
1648 641d5fbe bellard
   temporary registers needs to be allocated to store a constant. */
1649 1ad80729 Aurelien Jarno
static inline void temp_sync(TCGContext *s, int temp, TCGRegSet allocated_regs)
1650 641d5fbe bellard
{
1651 641d5fbe bellard
    TCGTemp *ts;
1652 641d5fbe bellard
1653 641d5fbe bellard
    ts = &s->temps[temp];
1654 641d5fbe bellard
    if (!ts->fixed_reg) {
1655 641d5fbe bellard
        switch(ts->val_type) {
1656 1ad80729 Aurelien Jarno
        case TEMP_VAL_CONST:
1657 1ad80729 Aurelien Jarno
            ts->reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type],
1658 1ad80729 Aurelien Jarno
                                    allocated_regs);
1659 1ad80729 Aurelien Jarno
            ts->val_type = TEMP_VAL_REG;
1660 1ad80729 Aurelien Jarno
            s->reg_to_temp[ts->reg] = temp;
1661 1ad80729 Aurelien Jarno
            ts->mem_coherent = 0;
1662 1ad80729 Aurelien Jarno
            tcg_out_movi(s, ts->type, ts->reg, ts->val);
1663 1ad80729 Aurelien Jarno
            /* fallthrough*/
1664 641d5fbe bellard
        case TEMP_VAL_REG:
1665 1ad80729 Aurelien Jarno
            tcg_reg_sync(s, ts->reg);
1666 641d5fbe bellard
            break;
1667 641d5fbe bellard
        case TEMP_VAL_DEAD:
1668 641d5fbe bellard
        case TEMP_VAL_MEM:
1669 641d5fbe bellard
            break;
1670 641d5fbe bellard
        default:
1671 641d5fbe bellard
            tcg_abort();
1672 641d5fbe bellard
        }
1673 641d5fbe bellard
    }
1674 641d5fbe bellard
}
1675 641d5fbe bellard
1676 1ad80729 Aurelien Jarno
/* save a temporary to memory. 'allocated_regs' is used in case a
1677 1ad80729 Aurelien Jarno
   temporary registers needs to be allocated to store a constant. */
1678 1ad80729 Aurelien Jarno
static inline void temp_save(TCGContext *s, int temp, TCGRegSet allocated_regs)
1679 1ad80729 Aurelien Jarno
{
1680 2c0366f0 Aurelien Jarno
#ifdef USE_LIVENESS_ANALYSIS
1681 2c0366f0 Aurelien Jarno
    /* The liveness analysis already ensures that globals are back
1682 2c0366f0 Aurelien Jarno
       in memory. Keep an assert for safety. */
1683 2c0366f0 Aurelien Jarno
    assert(s->temps[temp].val_type == TEMP_VAL_MEM || s->temps[temp].fixed_reg);
1684 2c0366f0 Aurelien Jarno
#else
1685 1ad80729 Aurelien Jarno
    temp_sync(s, temp, allocated_regs);
1686 1ad80729 Aurelien Jarno
    temp_dead(s, temp);
1687 2c0366f0 Aurelien Jarno
#endif
1688 1ad80729 Aurelien Jarno
}
1689 1ad80729 Aurelien Jarno
1690 9814dd27 Dong Xu Wang
/* save globals to their canonical location and assume they can be
1691 e8996ee0 bellard
   modified be the following code. 'allocated_regs' is used in case a
1692 e8996ee0 bellard
   temporary registers needs to be allocated to store a constant. */
1693 e8996ee0 bellard
static void save_globals(TCGContext *s, TCGRegSet allocated_regs)
1694 c896fe29 bellard
{
1695 641d5fbe bellard
    int i;
1696 c896fe29 bellard
1697 c896fe29 bellard
    for(i = 0; i < s->nb_globals; i++) {
1698 641d5fbe bellard
        temp_save(s, i, allocated_regs);
1699 c896fe29 bellard
    }
1700 e5097dc8 bellard
}
1701 e5097dc8 bellard
1702 3d5c5f87 Aurelien Jarno
/* sync globals to their canonical location and assume they can be
1703 3d5c5f87 Aurelien Jarno
   read by the following code. 'allocated_regs' is used in case a
1704 3d5c5f87 Aurelien Jarno
   temporary registers needs to be allocated to store a constant. */
1705 3d5c5f87 Aurelien Jarno
static void sync_globals(TCGContext *s, TCGRegSet allocated_regs)
1706 3d5c5f87 Aurelien Jarno
{
1707 3d5c5f87 Aurelien Jarno
    int i;
1708 3d5c5f87 Aurelien Jarno
1709 3d5c5f87 Aurelien Jarno
    for (i = 0; i < s->nb_globals; i++) {
1710 3d5c5f87 Aurelien Jarno
#ifdef USE_LIVENESS_ANALYSIS
1711 3d5c5f87 Aurelien Jarno
        assert(s->temps[i].val_type != TEMP_VAL_REG || s->temps[i].fixed_reg ||
1712 3d5c5f87 Aurelien Jarno
               s->temps[i].mem_coherent);
1713 3d5c5f87 Aurelien Jarno
#else
1714 3d5c5f87 Aurelien Jarno
        temp_sync(s, i, allocated_regs);
1715 3d5c5f87 Aurelien Jarno
#endif
1716 3d5c5f87 Aurelien Jarno
    }
1717 3d5c5f87 Aurelien Jarno
}
1718 3d5c5f87 Aurelien Jarno
1719 e5097dc8 bellard
/* at the end of a basic block, we assume all temporaries are dead and
1720 e8996ee0 bellard
   all globals are stored at their canonical location. */
1721 e8996ee0 bellard
static void tcg_reg_alloc_bb_end(TCGContext *s, TCGRegSet allocated_regs)
1722 e5097dc8 bellard
{
1723 e5097dc8 bellard
    TCGTemp *ts;
1724 e5097dc8 bellard
    int i;
1725 e5097dc8 bellard
1726 c896fe29 bellard
    for(i = s->nb_globals; i < s->nb_temps; i++) {
1727 c896fe29 bellard
        ts = &s->temps[i];
1728 641d5fbe bellard
        if (ts->temp_local) {
1729 641d5fbe bellard
            temp_save(s, i, allocated_regs);
1730 641d5fbe bellard
        } else {
1731 2c0366f0 Aurelien Jarno
#ifdef USE_LIVENESS_ANALYSIS
1732 2c0366f0 Aurelien Jarno
            /* The liveness analysis already ensures that temps are dead.
1733 2c0366f0 Aurelien Jarno
               Keep an assert for safety. */
1734 2c0366f0 Aurelien Jarno
            assert(ts->val_type == TEMP_VAL_DEAD);
1735 2c0366f0 Aurelien Jarno
#else
1736 639368dd Aurelien Jarno
            temp_dead(s, i);
1737 2c0366f0 Aurelien Jarno
#endif
1738 c896fe29 bellard
        }
1739 c896fe29 bellard
    }
1740 e8996ee0 bellard
1741 e8996ee0 bellard
    save_globals(s, allocated_regs);
1742 c896fe29 bellard
}
1743 c896fe29 bellard
1744 866cb6cb Aurelien Jarno
#define IS_DEAD_ARG(n) ((dead_args >> (n)) & 1)
1745 ec7a869d Aurelien Jarno
#define NEED_SYNC_ARG(n) ((sync_args >> (n)) & 1)
1746 c896fe29 bellard
1747 ec7a869d Aurelien Jarno
static void tcg_reg_alloc_movi(TCGContext *s, const TCGArg *args,
1748 ec7a869d Aurelien Jarno
                               uint16_t dead_args, uint8_t sync_args)
1749 e8996ee0 bellard
{
1750 e8996ee0 bellard
    TCGTemp *ots;
1751 e8996ee0 bellard
    tcg_target_ulong val;
1752 e8996ee0 bellard
1753 e8996ee0 bellard
    ots = &s->temps[args[0]];
1754 e8996ee0 bellard
    val = args[1];
1755 e8996ee0 bellard
1756 e8996ee0 bellard
    if (ots->fixed_reg) {
1757 e8996ee0 bellard
        /* for fixed registers, we do not do any constant
1758 e8996ee0 bellard
           propagation */
1759 e8996ee0 bellard
        tcg_out_movi(s, ots->type, ots->reg, val);
1760 e8996ee0 bellard
    } else {
1761 1235fc06 ths
        /* The movi is not explicitly generated here */
1762 e8996ee0 bellard
        if (ots->val_type == TEMP_VAL_REG)
1763 e8996ee0 bellard
            s->reg_to_temp[ots->reg] = -1;
1764 e8996ee0 bellard
        ots->val_type = TEMP_VAL_CONST;
1765 e8996ee0 bellard
        ots->val = val;
1766 e8996ee0 bellard
    }
1767 ec7a869d Aurelien Jarno
    if (NEED_SYNC_ARG(0)) {
1768 ec7a869d Aurelien Jarno
        temp_sync(s, args[0], s->reserved_regs);
1769 ec7a869d Aurelien Jarno
    }
1770 4c4e1ab2 Aurelien Jarno
    if (IS_DEAD_ARG(0)) {
1771 4c4e1ab2 Aurelien Jarno
        temp_dead(s, args[0]);
1772 4c4e1ab2 Aurelien Jarno
    }
1773 e8996ee0 bellard
}
1774 e8996ee0 bellard
1775 c896fe29 bellard
static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
1776 ec7a869d Aurelien Jarno
                              const TCGArg *args, uint16_t dead_args,
1777 ec7a869d Aurelien Jarno
                              uint8_t sync_args)
1778 c896fe29 bellard
{
1779 c29c1d7e Aurelien Jarno
    TCGRegSet allocated_regs;
1780 c896fe29 bellard
    TCGTemp *ts, *ots;
1781 c29c1d7e Aurelien Jarno
    const TCGArgConstraint *arg_ct, *oarg_ct;
1782 c896fe29 bellard
1783 c29c1d7e Aurelien Jarno
    tcg_regset_set(allocated_regs, s->reserved_regs);
1784 c896fe29 bellard
    ots = &s->temps[args[0]];
1785 c896fe29 bellard
    ts = &s->temps[args[1]];
1786 c29c1d7e Aurelien Jarno
    oarg_ct = &def->args_ct[0];
1787 c29c1d7e Aurelien Jarno
    arg_ct = &def->args_ct[1];
1788 c29c1d7e Aurelien Jarno
1789 c29c1d7e Aurelien Jarno
    /* If the source value is not in a register, and we're going to be
1790 c29c1d7e Aurelien Jarno
       forced to have it in a register in order to perform the copy,
1791 c29c1d7e Aurelien Jarno
       then copy the SOURCE value into its own register first.  That way
1792 c29c1d7e Aurelien Jarno
       we don't have to reload SOURCE the next time it is used. */
1793 c29c1d7e Aurelien Jarno
    if (((NEED_SYNC_ARG(0) || ots->fixed_reg) && ts->val_type != TEMP_VAL_REG)
1794 c29c1d7e Aurelien Jarno
        || ts->val_type == TEMP_VAL_MEM) {
1795 c29c1d7e Aurelien Jarno
        ts->reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1796 c29c1d7e Aurelien Jarno
        if (ts->val_type == TEMP_VAL_MEM) {
1797 c29c1d7e Aurelien Jarno
            tcg_out_ld(s, ts->type, ts->reg, ts->mem_reg, ts->mem_offset);
1798 c29c1d7e Aurelien Jarno
            ts->mem_coherent = 1;
1799 c29c1d7e Aurelien Jarno
        } else if (ts->val_type == TEMP_VAL_CONST) {
1800 c29c1d7e Aurelien Jarno
            tcg_out_movi(s, ts->type, ts->reg, ts->val);
1801 c29c1d7e Aurelien Jarno
        }
1802 c29c1d7e Aurelien Jarno
        s->reg_to_temp[ts->reg] = args[1];
1803 c29c1d7e Aurelien Jarno
        ts->val_type = TEMP_VAL_REG;
1804 c29c1d7e Aurelien Jarno
    }
1805 c896fe29 bellard
1806 c29c1d7e Aurelien Jarno
    if (IS_DEAD_ARG(0) && !ots->fixed_reg) {
1807 c29c1d7e Aurelien Jarno
        /* mov to a non-saved dead register makes no sense (even with
1808 c29c1d7e Aurelien Jarno
           liveness analysis disabled). */
1809 c29c1d7e Aurelien Jarno
        assert(NEED_SYNC_ARG(0));
1810 c29c1d7e Aurelien Jarno
        /* The code above should have moved the temp to a register. */
1811 c29c1d7e Aurelien Jarno
        assert(ts->val_type == TEMP_VAL_REG);
1812 c29c1d7e Aurelien Jarno
        if (!ots->mem_allocated) {
1813 c29c1d7e Aurelien Jarno
            temp_allocate_frame(s, args[0]);
1814 c29c1d7e Aurelien Jarno
        }
1815 c29c1d7e Aurelien Jarno
        tcg_out_st(s, ots->type, ts->reg, ots->mem_reg, ots->mem_offset);
1816 c29c1d7e Aurelien Jarno
        if (IS_DEAD_ARG(1)) {
1817 c29c1d7e Aurelien Jarno
            temp_dead(s, args[1]);
1818 c29c1d7e Aurelien Jarno
        }
1819 c29c1d7e Aurelien Jarno
        temp_dead(s, args[0]);
1820 c29c1d7e Aurelien Jarno
    } else if (ts->val_type == TEMP_VAL_CONST) {
1821 c29c1d7e Aurelien Jarno
        /* propagate constant */
1822 c29c1d7e Aurelien Jarno
        if (ots->val_type == TEMP_VAL_REG) {
1823 c29c1d7e Aurelien Jarno
            s->reg_to_temp[ots->reg] = -1;
1824 c29c1d7e Aurelien Jarno
        }
1825 c29c1d7e Aurelien Jarno
        ots->val_type = TEMP_VAL_CONST;
1826 c29c1d7e Aurelien Jarno
        ots->val = ts->val;
1827 c29c1d7e Aurelien Jarno
    } else {
1828 c29c1d7e Aurelien Jarno
        /* The code in the first if block should have moved the
1829 c29c1d7e Aurelien Jarno
           temp to a register. */
1830 c29c1d7e Aurelien Jarno
        assert(ts->val_type == TEMP_VAL_REG);
1831 866cb6cb Aurelien Jarno
        if (IS_DEAD_ARG(1) && !ts->fixed_reg && !ots->fixed_reg) {
1832 c896fe29 bellard
            /* the mov can be suppressed */
1833 c29c1d7e Aurelien Jarno
            if (ots->val_type == TEMP_VAL_REG) {
1834 c896fe29 bellard
                s->reg_to_temp[ots->reg] = -1;
1835 c29c1d7e Aurelien Jarno
            }
1836 c29c1d7e Aurelien Jarno
            ots->reg = ts->reg;
1837 639368dd Aurelien Jarno
            temp_dead(s, args[1]);
1838 c896fe29 bellard
        } else {
1839 c29c1d7e Aurelien Jarno
            if (ots->val_type != TEMP_VAL_REG) {
1840 c29c1d7e Aurelien Jarno
                /* When allocating a new register, make sure to not spill the
1841 c29c1d7e Aurelien Jarno
                   input one. */
1842 c29c1d7e Aurelien Jarno
                tcg_regset_set_reg(allocated_regs, ts->reg);
1843 c29c1d7e Aurelien Jarno
                ots->reg = tcg_reg_alloc(s, oarg_ct->u.regs, allocated_regs);
1844 c896fe29 bellard
            }
1845 c29c1d7e Aurelien Jarno
            tcg_out_mov(s, ots->type, ots->reg, ts->reg);
1846 c896fe29 bellard
        }
1847 c29c1d7e Aurelien Jarno
        ots->val_type = TEMP_VAL_REG;
1848 c29c1d7e Aurelien Jarno
        ots->mem_coherent = 0;
1849 c29c1d7e Aurelien Jarno
        s->reg_to_temp[ots->reg] = args[0];
1850 c29c1d7e Aurelien Jarno
        if (NEED_SYNC_ARG(0)) {
1851 c29c1d7e Aurelien Jarno
            tcg_reg_sync(s, ots->reg);
1852 c896fe29 bellard
        }
1853 ec7a869d Aurelien Jarno
    }
1854 c896fe29 bellard
}
1855 c896fe29 bellard
1856 c896fe29 bellard
static void tcg_reg_alloc_op(TCGContext *s, 
1857 a9751609 Richard Henderson
                             const TCGOpDef *def, TCGOpcode opc,
1858 ec7a869d Aurelien Jarno
                             const TCGArg *args, uint16_t dead_args,
1859 ec7a869d Aurelien Jarno
                             uint8_t sync_args)
1860 c896fe29 bellard
{
1861 c896fe29 bellard
    TCGRegSet allocated_regs;
1862 c896fe29 bellard
    int i, k, nb_iargs, nb_oargs, reg;
1863 c896fe29 bellard
    TCGArg arg;
1864 c896fe29 bellard
    const TCGArgConstraint *arg_ct;
1865 c896fe29 bellard
    TCGTemp *ts;
1866 c896fe29 bellard
    TCGArg new_args[TCG_MAX_OP_ARGS];
1867 c896fe29 bellard
    int const_args[TCG_MAX_OP_ARGS];
1868 c896fe29 bellard
1869 c896fe29 bellard
    nb_oargs = def->nb_oargs;
1870 c896fe29 bellard
    nb_iargs = def->nb_iargs;
1871 c896fe29 bellard
1872 c896fe29 bellard
    /* copy constants */
1873 c896fe29 bellard
    memcpy(new_args + nb_oargs + nb_iargs, 
1874 c896fe29 bellard
           args + nb_oargs + nb_iargs, 
1875 c896fe29 bellard
           sizeof(TCGArg) * def->nb_cargs);
1876 c896fe29 bellard
1877 c896fe29 bellard
    /* satisfy input constraints */ 
1878 c896fe29 bellard
    tcg_regset_set(allocated_regs, s->reserved_regs);
1879 c896fe29 bellard
    for(k = 0; k < nb_iargs; k++) {
1880 c896fe29 bellard
        i = def->sorted_args[nb_oargs + k];
1881 c896fe29 bellard
        arg = args[i];
1882 c896fe29 bellard
        arg_ct = &def->args_ct[i];
1883 c896fe29 bellard
        ts = &s->temps[arg];
1884 c896fe29 bellard
        if (ts->val_type == TEMP_VAL_MEM) {
1885 c896fe29 bellard
            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1886 e4d5434c blueswir1
            tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1887 c896fe29 bellard
            ts->val_type = TEMP_VAL_REG;
1888 c896fe29 bellard
            ts->reg = reg;
1889 c896fe29 bellard
            ts->mem_coherent = 1;
1890 c896fe29 bellard
            s->reg_to_temp[reg] = arg;
1891 c896fe29 bellard
        } else if (ts->val_type == TEMP_VAL_CONST) {
1892 c896fe29 bellard
            if (tcg_target_const_match(ts->val, arg_ct)) {
1893 c896fe29 bellard
                /* constant is OK for instruction */
1894 c896fe29 bellard
                const_args[i] = 1;
1895 c896fe29 bellard
                new_args[i] = ts->val;
1896 c896fe29 bellard
                goto iarg_end;
1897 c896fe29 bellard
            } else {
1898 e8996ee0 bellard
                /* need to move to a register */
1899 c896fe29 bellard
                reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1900 c896fe29 bellard
                tcg_out_movi(s, ts->type, reg, ts->val);
1901 e8996ee0 bellard
                ts->val_type = TEMP_VAL_REG;
1902 e8996ee0 bellard
                ts->reg = reg;
1903 e8996ee0 bellard
                ts->mem_coherent = 0;
1904 e8996ee0 bellard
                s->reg_to_temp[reg] = arg;
1905 c896fe29 bellard
            }
1906 c896fe29 bellard
        }
1907 c896fe29 bellard
        assert(ts->val_type == TEMP_VAL_REG);
1908 5ff9d6a4 bellard
        if (arg_ct->ct & TCG_CT_IALIAS) {
1909 5ff9d6a4 bellard
            if (ts->fixed_reg) {
1910 5ff9d6a4 bellard
                /* if fixed register, we must allocate a new register
1911 5ff9d6a4 bellard
                   if the alias is not the same register */
1912 5ff9d6a4 bellard
                if (arg != args[arg_ct->alias_index])
1913 5ff9d6a4 bellard
                    goto allocate_in_reg;
1914 5ff9d6a4 bellard
            } else {
1915 5ff9d6a4 bellard
                /* if the input is aliased to an output and if it is
1916 5ff9d6a4 bellard
                   not dead after the instruction, we must allocate
1917 5ff9d6a4 bellard
                   a new register and move it */
1918 866cb6cb Aurelien Jarno
                if (!IS_DEAD_ARG(i)) {
1919 5ff9d6a4 bellard
                    goto allocate_in_reg;
1920 866cb6cb Aurelien Jarno
                }
1921 5ff9d6a4 bellard
            }
1922 c896fe29 bellard
        }
1923 c896fe29 bellard
        reg = ts->reg;
1924 c896fe29 bellard
        if (tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1925 c896fe29 bellard
            /* nothing to do : the constraint is satisfied */
1926 c896fe29 bellard
        } else {
1927 c896fe29 bellard
        allocate_in_reg:
1928 c896fe29 bellard
            /* allocate a new register matching the constraint 
1929 c896fe29 bellard
               and move the temporary register into it */
1930 c896fe29 bellard
            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1931 3b6dac34 Richard Henderson
            tcg_out_mov(s, ts->type, reg, ts->reg);
1932 c896fe29 bellard
        }
1933 c896fe29 bellard
        new_args[i] = reg;
1934 c896fe29 bellard
        const_args[i] = 0;
1935 c896fe29 bellard
        tcg_regset_set_reg(allocated_regs, reg);
1936 c896fe29 bellard
    iarg_end: ;
1937 c896fe29 bellard
    }
1938 c896fe29 bellard
    
1939 a52ad07e Aurelien Jarno
    /* mark dead temporaries and free the associated registers */
1940 a52ad07e Aurelien Jarno
    for (i = nb_oargs; i < nb_oargs + nb_iargs; i++) {
1941 a52ad07e Aurelien Jarno
        if (IS_DEAD_ARG(i)) {
1942 a52ad07e Aurelien Jarno
            temp_dead(s, args[i]);
1943 a52ad07e Aurelien Jarno
        }
1944 a52ad07e Aurelien Jarno
    }
1945 a52ad07e Aurelien Jarno
1946 e8996ee0 bellard
    if (def->flags & TCG_OPF_BB_END) {
1947 e8996ee0 bellard
        tcg_reg_alloc_bb_end(s, allocated_regs);
1948 e8996ee0 bellard
    } else {
1949 e8996ee0 bellard
        if (def->flags & TCG_OPF_CALL_CLOBBER) {
1950 e8996ee0 bellard
            /* XXX: permit generic clobber register list ? */ 
1951 e8996ee0 bellard
            for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1952 e8996ee0 bellard
                if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
1953 e8996ee0 bellard
                    tcg_reg_free(s, reg);
1954 e8996ee0 bellard
                }
1955 c896fe29 bellard
            }
1956 3d5c5f87 Aurelien Jarno
        }
1957 3d5c5f87 Aurelien Jarno
        if (def->flags & TCG_OPF_SIDE_EFFECTS) {
1958 3d5c5f87 Aurelien Jarno
            /* sync globals if the op has side effects and might trigger
1959 3d5c5f87 Aurelien Jarno
               an exception. */
1960 3d5c5f87 Aurelien Jarno
            sync_globals(s, allocated_regs);
1961 c896fe29 bellard
        }
1962 e8996ee0 bellard
        
1963 e8996ee0 bellard
        /* satisfy the output constraints */
1964 e8996ee0 bellard
        tcg_regset_set(allocated_regs, s->reserved_regs);
1965 e8996ee0 bellard
        for(k = 0; k < nb_oargs; k++) {
1966 e8996ee0 bellard
            i = def->sorted_args[k];
1967 e8996ee0 bellard
            arg = args[i];
1968 e8996ee0 bellard
            arg_ct = &def->args_ct[i];
1969 e8996ee0 bellard
            ts = &s->temps[arg];
1970 e8996ee0 bellard
            if (arg_ct->ct & TCG_CT_ALIAS) {
1971 e8996ee0 bellard
                reg = new_args[arg_ct->alias_index];
1972 e8996ee0 bellard
            } else {
1973 e8996ee0 bellard
                /* if fixed register, we try to use it */
1974 e8996ee0 bellard
                reg = ts->reg;
1975 e8996ee0 bellard
                if (ts->fixed_reg &&
1976 e8996ee0 bellard
                    tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1977 e8996ee0 bellard
                    goto oarg_end;
1978 e8996ee0 bellard
                }
1979 e8996ee0 bellard
                reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1980 c896fe29 bellard
            }
1981 e8996ee0 bellard
            tcg_regset_set_reg(allocated_regs, reg);
1982 e8996ee0 bellard
            /* if a fixed register is used, then a move will be done afterwards */
1983 e8996ee0 bellard
            if (!ts->fixed_reg) {
1984 ec7a869d Aurelien Jarno
                if (ts->val_type == TEMP_VAL_REG) {
1985 ec7a869d Aurelien Jarno
                    s->reg_to_temp[ts->reg] = -1;
1986 ec7a869d Aurelien Jarno
                }
1987 ec7a869d Aurelien Jarno
                ts->val_type = TEMP_VAL_REG;
1988 ec7a869d Aurelien Jarno
                ts->reg = reg;
1989 ec7a869d Aurelien Jarno
                /* temp value is modified, so the value kept in memory is
1990 ec7a869d Aurelien Jarno
                   potentially not the same */
1991 ec7a869d Aurelien Jarno
                ts->mem_coherent = 0;
1992 ec7a869d Aurelien Jarno
                s->reg_to_temp[reg] = arg;
1993 e8996ee0 bellard
            }
1994 e8996ee0 bellard
        oarg_end:
1995 e8996ee0 bellard
            new_args[i] = reg;
1996 c896fe29 bellard
        }
1997 c896fe29 bellard
    }
1998 c896fe29 bellard
1999 c896fe29 bellard
    /* emit instruction */
2000 c896fe29 bellard
    tcg_out_op(s, opc, new_args, const_args);
2001 c896fe29 bellard
    
2002 c896fe29 bellard
    /* move the outputs in the correct register if needed */
2003 c896fe29 bellard
    for(i = 0; i < nb_oargs; i++) {
2004 c896fe29 bellard
        ts = &s->temps[args[i]];
2005 c896fe29 bellard
        reg = new_args[i];
2006 c896fe29 bellard
        if (ts->fixed_reg && ts->reg != reg) {
2007 3b6dac34 Richard Henderson
            tcg_out_mov(s, ts->type, ts->reg, reg);
2008 c896fe29 bellard
        }
2009 ec7a869d Aurelien Jarno
        if (NEED_SYNC_ARG(i)) {
2010 ec7a869d Aurelien Jarno
            tcg_reg_sync(s, reg);
2011 ec7a869d Aurelien Jarno
        }
2012 ec7a869d Aurelien Jarno
        if (IS_DEAD_ARG(i)) {
2013 ec7a869d Aurelien Jarno
            temp_dead(s, args[i]);
2014 ec7a869d Aurelien Jarno
        }
2015 c896fe29 bellard
    }
2016 c896fe29 bellard
}
2017 c896fe29 bellard
2018 b03cce8e bellard
#ifdef TCG_TARGET_STACK_GROWSUP
2019 b03cce8e bellard
#define STACK_DIR(x) (-(x))
2020 b03cce8e bellard
#else
2021 b03cce8e bellard
#define STACK_DIR(x) (x)
2022 b03cce8e bellard
#endif
2023 b03cce8e bellard
2024 c896fe29 bellard
static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
2025 a9751609 Richard Henderson
                              TCGOpcode opc, const TCGArg *args,
2026 ec7a869d Aurelien Jarno
                              uint16_t dead_args, uint8_t sync_args)
2027 c896fe29 bellard
{
2028 c896fe29 bellard
    int nb_iargs, nb_oargs, flags, nb_regs, i, reg, nb_params;
2029 c896fe29 bellard
    TCGArg arg, func_arg;
2030 c896fe29 bellard
    TCGTemp *ts;
2031 f54b3f92 aurel32
    tcg_target_long stack_offset, call_stack_size, func_addr;
2032 b03cce8e bellard
    int const_func_arg, allocate_args;
2033 c896fe29 bellard
    TCGRegSet allocated_regs;
2034 c896fe29 bellard
    const TCGArgConstraint *arg_ct;
2035 c896fe29 bellard
2036 c896fe29 bellard
    arg = *args++;
2037 c896fe29 bellard
2038 c896fe29 bellard
    nb_oargs = arg >> 16;
2039 c896fe29 bellard
    nb_iargs = arg & 0xffff;
2040 c896fe29 bellard
    nb_params = nb_iargs - 1;
2041 c896fe29 bellard
2042 c896fe29 bellard
    flags = args[nb_oargs + nb_iargs];
2043 c896fe29 bellard
2044 6e17d0c5 Stefan Weil
    nb_regs = ARRAY_SIZE(tcg_target_call_iarg_regs);
2045 c896fe29 bellard
    if (nb_regs > nb_params)
2046 c896fe29 bellard
        nb_regs = nb_params;
2047 c896fe29 bellard
2048 c896fe29 bellard
    /* assign stack slots first */
2049 c896fe29 bellard
    call_stack_size = (nb_params - nb_regs) * sizeof(tcg_target_long);
2050 c896fe29 bellard
    call_stack_size = (call_stack_size + TCG_TARGET_STACK_ALIGN - 1) & 
2051 c896fe29 bellard
        ~(TCG_TARGET_STACK_ALIGN - 1);
2052 b03cce8e bellard
    allocate_args = (call_stack_size > TCG_STATIC_CALL_ARGS_SIZE);
2053 b03cce8e bellard
    if (allocate_args) {
2054 345649c0 Blue Swirl
        /* XXX: if more than TCG_STATIC_CALL_ARGS_SIZE is needed,
2055 345649c0 Blue Swirl
           preallocate call stack */
2056 345649c0 Blue Swirl
        tcg_abort();
2057 b03cce8e bellard
    }
2058 39cf05d3 bellard
2059 39cf05d3 bellard
    stack_offset = TCG_TARGET_CALL_STACK_OFFSET;
2060 c896fe29 bellard
    for(i = nb_regs; i < nb_params; i++) {
2061 c896fe29 bellard
        arg = args[nb_oargs + i];
2062 39cf05d3 bellard
#ifdef TCG_TARGET_STACK_GROWSUP
2063 39cf05d3 bellard
        stack_offset -= sizeof(tcg_target_long);
2064 39cf05d3 bellard
#endif
2065 39cf05d3 bellard
        if (arg != TCG_CALL_DUMMY_ARG) {
2066 39cf05d3 bellard
            ts = &s->temps[arg];
2067 39cf05d3 bellard
            if (ts->val_type == TEMP_VAL_REG) {
2068 39cf05d3 bellard
                tcg_out_st(s, ts->type, ts->reg, TCG_REG_CALL_STACK, stack_offset);
2069 39cf05d3 bellard
            } else if (ts->val_type == TEMP_VAL_MEM) {
2070 39cf05d3 bellard
                reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], 
2071 39cf05d3 bellard
                                    s->reserved_regs);
2072 39cf05d3 bellard
                /* XXX: not correct if reading values from the stack */
2073 39cf05d3 bellard
                tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
2074 39cf05d3 bellard
                tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
2075 39cf05d3 bellard
            } else if (ts->val_type == TEMP_VAL_CONST) {
2076 39cf05d3 bellard
                reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], 
2077 39cf05d3 bellard
                                    s->reserved_regs);
2078 39cf05d3 bellard
                /* XXX: sign extend may be needed on some targets */
2079 39cf05d3 bellard
                tcg_out_movi(s, ts->type, reg, ts->val);
2080 39cf05d3 bellard
                tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
2081 39cf05d3 bellard
            } else {
2082 39cf05d3 bellard
                tcg_abort();
2083 39cf05d3 bellard
            }
2084 c896fe29 bellard
        }
2085 39cf05d3 bellard
#ifndef TCG_TARGET_STACK_GROWSUP
2086 39cf05d3 bellard
        stack_offset += sizeof(tcg_target_long);
2087 39cf05d3 bellard
#endif
2088 c896fe29 bellard
    }
2089 c896fe29 bellard
    
2090 c896fe29 bellard
    /* assign input registers */
2091 c896fe29 bellard
    tcg_regset_set(allocated_regs, s->reserved_regs);
2092 c896fe29 bellard
    for(i = 0; i < nb_regs; i++) {
2093 c896fe29 bellard
        arg = args[nb_oargs + i];
2094 39cf05d3 bellard
        if (arg != TCG_CALL_DUMMY_ARG) {
2095 39cf05d3 bellard
            ts = &s->temps[arg];
2096 39cf05d3 bellard
            reg = tcg_target_call_iarg_regs[i];
2097 39cf05d3 bellard
            tcg_reg_free(s, reg);
2098 39cf05d3 bellard
            if (ts->val_type == TEMP_VAL_REG) {
2099 39cf05d3 bellard
                if (ts->reg != reg) {
2100 3b6dac34 Richard Henderson
                    tcg_out_mov(s, ts->type, reg, ts->reg);
2101 39cf05d3 bellard
                }
2102 39cf05d3 bellard
            } else if (ts->val_type == TEMP_VAL_MEM) {
2103 39cf05d3 bellard
                tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
2104 39cf05d3 bellard
            } else if (ts->val_type == TEMP_VAL_CONST) {
2105 39cf05d3 bellard
                /* XXX: sign extend ? */
2106 39cf05d3 bellard
                tcg_out_movi(s, ts->type, reg, ts->val);
2107 39cf05d3 bellard
            } else {
2108 39cf05d3 bellard
                tcg_abort();
2109 c896fe29 bellard
            }
2110 39cf05d3 bellard
            tcg_regset_set_reg(allocated_regs, reg);
2111 c896fe29 bellard
        }
2112 c896fe29 bellard
    }
2113 c896fe29 bellard
    
2114 c896fe29 bellard
    /* assign function address */
2115 c896fe29 bellard
    func_arg = args[nb_oargs + nb_iargs - 1];
2116 c896fe29 bellard
    arg_ct = &def->args_ct[0];
2117 c896fe29 bellard
    ts = &s->temps[func_arg];
2118 f54b3f92 aurel32
    func_addr = ts->val;
2119 c896fe29 bellard
    const_func_arg = 0;
2120 c896fe29 bellard
    if (ts->val_type == TEMP_VAL_MEM) {
2121 c896fe29 bellard
        reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
2122 e4d5434c blueswir1
        tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
2123 c896fe29 bellard
        func_arg = reg;
2124 e8996ee0 bellard
        tcg_regset_set_reg(allocated_regs, reg);
2125 c896fe29 bellard
    } else if (ts->val_type == TEMP_VAL_REG) {
2126 c896fe29 bellard
        reg = ts->reg;
2127 c896fe29 bellard
        if (!tcg_regset_test_reg(arg_ct->u.regs, reg)) {
2128 c896fe29 bellard
            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
2129 3b6dac34 Richard Henderson
            tcg_out_mov(s, ts->type, reg, ts->reg);
2130 c896fe29 bellard
        }
2131 c896fe29 bellard
        func_arg = reg;
2132 e8996ee0 bellard
        tcg_regset_set_reg(allocated_regs, reg);
2133 c896fe29 bellard
    } else if (ts->val_type == TEMP_VAL_CONST) {
2134 f54b3f92 aurel32
        if (tcg_target_const_match(func_addr, arg_ct)) {
2135 c896fe29 bellard
            const_func_arg = 1;
2136 f54b3f92 aurel32
            func_arg = func_addr;
2137 c896fe29 bellard
        } else {
2138 c896fe29 bellard
            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
2139 f54b3f92 aurel32
            tcg_out_movi(s, ts->type, reg, func_addr);
2140 c896fe29 bellard
            func_arg = reg;
2141 e8996ee0 bellard
            tcg_regset_set_reg(allocated_regs, reg);
2142 c896fe29 bellard
        }
2143 c896fe29 bellard
    } else {
2144 c896fe29 bellard
        tcg_abort();
2145 c896fe29 bellard
    }
2146 e8996ee0 bellard
        
2147 c896fe29 bellard
    
2148 c896fe29 bellard
    /* mark dead temporaries and free the associated registers */
2149 866cb6cb Aurelien Jarno
    for(i = nb_oargs; i < nb_iargs + nb_oargs; i++) {
2150 866cb6cb Aurelien Jarno
        if (IS_DEAD_ARG(i)) {
2151 639368dd Aurelien Jarno
            temp_dead(s, args[i]);
2152 c896fe29 bellard
        }
2153 c896fe29 bellard
    }
2154 c896fe29 bellard
    
2155 c896fe29 bellard
    /* clobber call registers */
2156 c896fe29 bellard
    for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
2157 c896fe29 bellard
        if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
2158 c896fe29 bellard
            tcg_reg_free(s, reg);
2159 c896fe29 bellard
        }
2160 c896fe29 bellard
    }
2161 78505279 Aurelien Jarno
2162 78505279 Aurelien Jarno
    /* Save globals if they might be written by the helper, sync them if
2163 78505279 Aurelien Jarno
       they might be read. */
2164 78505279 Aurelien Jarno
    if (flags & TCG_CALL_NO_READ_GLOBALS) {
2165 78505279 Aurelien Jarno
        /* Nothing to do */
2166 78505279 Aurelien Jarno
    } else if (flags & TCG_CALL_NO_WRITE_GLOBALS) {
2167 78505279 Aurelien Jarno
        sync_globals(s, allocated_regs);
2168 78505279 Aurelien Jarno
    } else {
2169 b9c18f56 aurel32
        save_globals(s, allocated_regs);
2170 b9c18f56 aurel32
    }
2171 c896fe29 bellard
2172 c896fe29 bellard
    tcg_out_op(s, opc, &func_arg, &const_func_arg);
2173 c896fe29 bellard
2174 c896fe29 bellard
    /* assign output registers and emit moves if needed */
2175 c896fe29 bellard
    for(i = 0; i < nb_oargs; i++) {
2176 c896fe29 bellard
        arg = args[i];
2177 c896fe29 bellard
        ts = &s->temps[arg];
2178 c896fe29 bellard
        reg = tcg_target_call_oarg_regs[i];
2179 e8996ee0 bellard
        assert(s->reg_to_temp[reg] == -1);
2180 c896fe29 bellard
        if (ts->fixed_reg) {
2181 c896fe29 bellard
            if (ts->reg != reg) {
2182 3b6dac34 Richard Henderson
                tcg_out_mov(s, ts->type, ts->reg, reg);
2183 c896fe29 bellard
            }
2184 c896fe29 bellard
        } else {
2185 ec7a869d Aurelien Jarno
            if (ts->val_type == TEMP_VAL_REG) {
2186 ec7a869d Aurelien Jarno
                s->reg_to_temp[ts->reg] = -1;
2187 ec7a869d Aurelien Jarno
            }
2188 ec7a869d Aurelien Jarno
            ts->val_type = TEMP_VAL_REG;
2189 ec7a869d Aurelien Jarno
            ts->reg = reg;
2190 ec7a869d Aurelien Jarno
            ts->mem_coherent = 0;
2191 ec7a869d Aurelien Jarno
            s->reg_to_temp[reg] = arg;
2192 ec7a869d Aurelien Jarno
            if (NEED_SYNC_ARG(i)) {
2193 ec7a869d Aurelien Jarno
                tcg_reg_sync(s, reg);
2194 ec7a869d Aurelien Jarno
            }
2195 8c11ad25 Aurelien Jarno
            if (IS_DEAD_ARG(i)) {
2196 639368dd Aurelien Jarno
                temp_dead(s, args[i]);
2197 8c11ad25 Aurelien Jarno
            }
2198 c896fe29 bellard
        }
2199 c896fe29 bellard
    }
2200 c896fe29 bellard
    
2201 c896fe29 bellard
    return nb_iargs + nb_oargs + def->nb_cargs + 1;
2202 c896fe29 bellard
}
2203 c896fe29 bellard
2204 c896fe29 bellard
#ifdef CONFIG_PROFILER
2205 c896fe29 bellard
2206 54604f74 aurel32
static int64_t tcg_table_op_count[NB_OPS];
2207 c896fe29 bellard
2208 871e6c35 Blue Swirl
static void dump_op_count(void)
2209 c896fe29 bellard
{
2210 c896fe29 bellard
    int i;
2211 c896fe29 bellard
    FILE *f;
2212 54604f74 aurel32
    f = fopen("/tmp/op.log", "w");
2213 c896fe29 bellard
    for(i = INDEX_op_end; i < NB_OPS; i++) {
2214 54604f74 aurel32
        fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name, tcg_table_op_count[i]);
2215 c896fe29 bellard
    }
2216 c896fe29 bellard
    fclose(f);
2217 c896fe29 bellard
}
2218 c896fe29 bellard
#endif
2219 c896fe29 bellard
2220 c896fe29 bellard
2221 c896fe29 bellard
static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
2222 2ba1eeb6 pbrook
                                      long search_pc)
2223 c896fe29 bellard
{
2224 a9751609 Richard Henderson
    TCGOpcode opc;
2225 a9751609 Richard Henderson
    int op_index;
2226 c896fe29 bellard
    const TCGOpDef *def;
2227 c896fe29 bellard
    const TCGArg *args;
2228 c896fe29 bellard
2229 c896fe29 bellard
#ifdef DEBUG_DISAS
2230 8fec2b8c aliguori
    if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
2231 93fcfe39 aliguori
        qemu_log("OP:\n");
2232 eeacee4d Blue Swirl
        tcg_dump_ops(s);
2233 93fcfe39 aliguori
        qemu_log("\n");
2234 c896fe29 bellard
    }
2235 c896fe29 bellard
#endif
2236 c896fe29 bellard
2237 c5cc28ff Aurelien Jarno
#ifdef CONFIG_PROFILER
2238 c5cc28ff Aurelien Jarno
    s->opt_time -= profile_getclock();
2239 c5cc28ff Aurelien Jarno
#endif
2240 c5cc28ff Aurelien Jarno
2241 8f2e8c07 Kirill Batuzov
#ifdef USE_TCG_OPTIMIZATIONS
2242 c4afe5c4 Evgeny Voevodin
    s->gen_opparam_ptr =
2243 1ff0a2c5 Evgeny Voevodin
        tcg_optimize(s, s->gen_opc_ptr, s->gen_opparam_buf, tcg_op_defs);
2244 8f2e8c07 Kirill Batuzov
#endif
2245 8f2e8c07 Kirill Batuzov
2246 a23a9ec6 bellard
#ifdef CONFIG_PROFILER
2247 c5cc28ff Aurelien Jarno
    s->opt_time += profile_getclock();
2248 a23a9ec6 bellard
    s->la_time -= profile_getclock();
2249 a23a9ec6 bellard
#endif
2250 c5cc28ff Aurelien Jarno
2251 c896fe29 bellard
    tcg_liveness_analysis(s);
2252 c5cc28ff Aurelien Jarno
2253 a23a9ec6 bellard
#ifdef CONFIG_PROFILER
2254 a23a9ec6 bellard
    s->la_time += profile_getclock();
2255 a23a9ec6 bellard
#endif
2256 c896fe29 bellard
2257 c896fe29 bellard
#ifdef DEBUG_DISAS
2258 8fec2b8c aliguori
    if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_OPT))) {
2259 c5cc28ff Aurelien Jarno
        qemu_log("OP after optimization and liveness analysis:\n");
2260 eeacee4d Blue Swirl
        tcg_dump_ops(s);
2261 93fcfe39 aliguori
        qemu_log("\n");
2262 c896fe29 bellard
    }
2263 c896fe29 bellard
#endif
2264 c896fe29 bellard
2265 c896fe29 bellard
    tcg_reg_alloc_start(s);
2266 c896fe29 bellard
2267 c896fe29 bellard
    s->code_buf = gen_code_buf;
2268 c896fe29 bellard
    s->code_ptr = gen_code_buf;
2269 c896fe29 bellard
2270 1ff0a2c5 Evgeny Voevodin
    args = s->gen_opparam_buf;
2271 c896fe29 bellard
    op_index = 0;
2272 b3db8758 blueswir1
2273 c896fe29 bellard
    for(;;) {
2274 92414b31 Evgeny Voevodin
        opc = s->gen_opc_buf[op_index];
2275 c896fe29 bellard
#ifdef CONFIG_PROFILER
2276 54604f74 aurel32
        tcg_table_op_count[opc]++;
2277 c896fe29 bellard
#endif
2278 c896fe29 bellard
        def = &tcg_op_defs[opc];
2279 c896fe29 bellard
#if 0
2280 c896fe29 bellard
        printf("%s: %d %d %d\n", def->name,
2281 c896fe29 bellard
               def->nb_oargs, def->nb_iargs, def->nb_cargs);
2282 c896fe29 bellard
        //        dump_regs(s);
2283 c896fe29 bellard
#endif
2284 c896fe29 bellard
        switch(opc) {
2285 c896fe29 bellard
        case INDEX_op_mov_i32:
2286 c896fe29 bellard
        case INDEX_op_mov_i64:
2287 ec7a869d Aurelien Jarno
            tcg_reg_alloc_mov(s, def, args, s->op_dead_args[op_index],
2288 ec7a869d Aurelien Jarno
                              s->op_sync_args[op_index]);
2289 c896fe29 bellard
            break;
2290 e8996ee0 bellard
        case INDEX_op_movi_i32:
2291 e8996ee0 bellard
        case INDEX_op_movi_i64:
2292 ec7a869d Aurelien Jarno
            tcg_reg_alloc_movi(s, args, s->op_dead_args[op_index],
2293 ec7a869d Aurelien Jarno
                               s->op_sync_args[op_index]);
2294 e8996ee0 bellard
            break;
2295 7e4597d7 bellard
        case INDEX_op_debug_insn_start:
2296 7e4597d7 bellard
            /* debug instruction */
2297 7e4597d7 bellard
            break;
2298 c896fe29 bellard
        case INDEX_op_nop:
2299 c896fe29 bellard
        case INDEX_op_nop1:
2300 c896fe29 bellard
        case INDEX_op_nop2:
2301 c896fe29 bellard
        case INDEX_op_nop3:
2302 c896fe29 bellard
            break;
2303 c896fe29 bellard
        case INDEX_op_nopn:
2304 c896fe29 bellard
            args += args[0];
2305 c896fe29 bellard
            goto next;
2306 5ff9d6a4 bellard
        case INDEX_op_discard:
2307 639368dd Aurelien Jarno
            temp_dead(s, args[0]);
2308 5ff9d6a4 bellard
            break;
2309 c896fe29 bellard
        case INDEX_op_set_label:
2310 e8996ee0 bellard
            tcg_reg_alloc_bb_end(s, s->reserved_regs);
2311 9d6fca70 Stefan Weil
            tcg_out_label(s, args[0], s->code_ptr);
2312 c896fe29 bellard
            break;
2313 c896fe29 bellard
        case INDEX_op_call:
2314 ec7a869d Aurelien Jarno
            args += tcg_reg_alloc_call(s, def, opc, args,
2315 ec7a869d Aurelien Jarno
                                       s->op_dead_args[op_index],
2316 ec7a869d Aurelien Jarno
                                       s->op_sync_args[op_index]);
2317 c896fe29 bellard
            goto next;
2318 c896fe29 bellard
        case INDEX_op_end:
2319 c896fe29 bellard
            goto the_end;
2320 c896fe29 bellard
        default:
2321 25c4d9cc Richard Henderson
            /* Sanity check that we've not introduced any unhandled opcodes. */
2322 25c4d9cc Richard Henderson
            if (def->flags & TCG_OPF_NOT_PRESENT) {
2323 25c4d9cc Richard Henderson
                tcg_abort();
2324 25c4d9cc Richard Henderson
            }
2325 c896fe29 bellard
            /* Note: in order to speed up the code, it would be much
2326 c896fe29 bellard
               faster to have specialized register allocator functions for
2327 c896fe29 bellard
               some common argument patterns */
2328 ec7a869d Aurelien Jarno
            tcg_reg_alloc_op(s, def, opc, args, s->op_dead_args[op_index],
2329 ec7a869d Aurelien Jarno
                             s->op_sync_args[op_index]);
2330 c896fe29 bellard
            break;
2331 c896fe29 bellard
        }
2332 c896fe29 bellard
        args += def->nb_args;
2333 8df1ca4b ths
    next:
2334 2ba1eeb6 pbrook
        if (search_pc >= 0 && search_pc < s->code_ptr - gen_code_buf) {
2335 b314f270 bellard
            return op_index;
2336 c896fe29 bellard
        }
2337 c896fe29 bellard
        op_index++;
2338 c896fe29 bellard
#ifndef NDEBUG
2339 c896fe29 bellard
        check_regs(s);
2340 c896fe29 bellard
#endif
2341 c896fe29 bellard
    }
2342 c896fe29 bellard
 the_end:
2343 b76f0d8c Yeongkyoon Lee
#if defined(CONFIG_QEMU_LDST_OPTIMIZATION) && defined(CONFIG_SOFTMMU)
2344 b76f0d8c Yeongkyoon Lee
    /* Generate TB finalization at the end of block */
2345 b76f0d8c Yeongkyoon Lee
    tcg_out_tb_finalize(s);
2346 b76f0d8c Yeongkyoon Lee
#endif
2347 c896fe29 bellard
    return -1;
2348 c896fe29 bellard
}
2349 c896fe29 bellard
2350 54604f74 aurel32
int tcg_gen_code(TCGContext *s, uint8_t *gen_code_buf)
2351 c896fe29 bellard
{
2352 c896fe29 bellard
#ifdef CONFIG_PROFILER
2353 c896fe29 bellard
    {
2354 c896fe29 bellard
        int n;
2355 92414b31 Evgeny Voevodin
        n = (s->gen_opc_ptr - s->gen_opc_buf);
2356 a23a9ec6 bellard
        s->op_count += n;
2357 a23a9ec6 bellard
        if (n > s->op_count_max)
2358 a23a9ec6 bellard
            s->op_count_max = n;
2359 a23a9ec6 bellard
2360 a23a9ec6 bellard
        s->temp_count += s->nb_temps;
2361 a23a9ec6 bellard
        if (s->nb_temps > s->temp_count_max)
2362 a23a9ec6 bellard
            s->temp_count_max = s->nb_temps;
2363 c896fe29 bellard
    }
2364 c896fe29 bellard
#endif
2365 c896fe29 bellard
2366 2ba1eeb6 pbrook
    tcg_gen_code_common(s, gen_code_buf, -1);
2367 c896fe29 bellard
2368 c896fe29 bellard
    /* flush instruction cache */
2369 2aeabc08 Stefan Weil
    flush_icache_range((tcg_target_ulong)gen_code_buf,
2370 2aeabc08 Stefan Weil
                       (tcg_target_ulong)s->code_ptr);
2371 2aeabc08 Stefan Weil
2372 c896fe29 bellard
    return s->code_ptr -  gen_code_buf;
2373 c896fe29 bellard
}
2374 c896fe29 bellard
2375 2ba1eeb6 pbrook
/* Return the index of the micro operation such as the pc after is <
2376 623e265c pbrook
   offset bytes from the start of the TB.  The contents of gen_code_buf must
2377 623e265c pbrook
   not be changed, though writing the same values is ok.
2378 623e265c pbrook
   Return -1 if not found. */
2379 54604f74 aurel32
int tcg_gen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, long offset)
2380 c896fe29 bellard
{
2381 623e265c pbrook
    return tcg_gen_code_common(s, gen_code_buf, offset);
2382 c896fe29 bellard
}
2383 a23a9ec6 bellard
2384 a23a9ec6 bellard
#ifdef CONFIG_PROFILER
2385 405cf9ff Stefan Weil
void tcg_dump_info(FILE *f, fprintf_function cpu_fprintf)
2386 a23a9ec6 bellard
{
2387 a23a9ec6 bellard
    TCGContext *s = &tcg_ctx;
2388 a23a9ec6 bellard
    int64_t tot;
2389 a23a9ec6 bellard
2390 a23a9ec6 bellard
    tot = s->interm_time + s->code_time;
2391 a23a9ec6 bellard
    cpu_fprintf(f, "JIT cycles          %" PRId64 " (%0.3f s at 2.4 GHz)\n",
2392 a23a9ec6 bellard
                tot, tot / 2.4e9);
2393 a23a9ec6 bellard
    cpu_fprintf(f, "translated TBs      %" PRId64 " (aborted=%" PRId64 " %0.1f%%)\n", 
2394 a23a9ec6 bellard
                s->tb_count, 
2395 a23a9ec6 bellard
                s->tb_count1 - s->tb_count,
2396 a23a9ec6 bellard
                s->tb_count1 ? (double)(s->tb_count1 - s->tb_count) / s->tb_count1 * 100.0 : 0);
2397 a23a9ec6 bellard
    cpu_fprintf(f, "avg ops/TB          %0.1f max=%d\n", 
2398 a23a9ec6 bellard
                s->tb_count ? (double)s->op_count / s->tb_count : 0, s->op_count_max);
2399 a23a9ec6 bellard
    cpu_fprintf(f, "deleted ops/TB      %0.2f\n",
2400 a23a9ec6 bellard
                s->tb_count ? 
2401 a23a9ec6 bellard
                (double)s->del_op_count / s->tb_count : 0);
2402 a23a9ec6 bellard
    cpu_fprintf(f, "avg temps/TB        %0.2f max=%d\n",
2403 a23a9ec6 bellard
                s->tb_count ? 
2404 a23a9ec6 bellard
                (double)s->temp_count / s->tb_count : 0,
2405 a23a9ec6 bellard
                s->temp_count_max);
2406 a23a9ec6 bellard
    
2407 a23a9ec6 bellard
    cpu_fprintf(f, "cycles/op           %0.1f\n", 
2408 a23a9ec6 bellard
                s->op_count ? (double)tot / s->op_count : 0);
2409 a23a9ec6 bellard
    cpu_fprintf(f, "cycles/in byte      %0.1f\n", 
2410 a23a9ec6 bellard
                s->code_in_len ? (double)tot / s->code_in_len : 0);
2411 a23a9ec6 bellard
    cpu_fprintf(f, "cycles/out byte     %0.1f\n", 
2412 a23a9ec6 bellard
                s->code_out_len ? (double)tot / s->code_out_len : 0);
2413 a23a9ec6 bellard
    if (tot == 0)
2414 a23a9ec6 bellard
        tot = 1;
2415 a23a9ec6 bellard
    cpu_fprintf(f, "  gen_interm time   %0.1f%%\n", 
2416 a23a9ec6 bellard
                (double)s->interm_time / tot * 100.0);
2417 a23a9ec6 bellard
    cpu_fprintf(f, "  gen_code time     %0.1f%%\n", 
2418 a23a9ec6 bellard
                (double)s->code_time / tot * 100.0);
2419 c5cc28ff Aurelien Jarno
    cpu_fprintf(f, "optim./code time    %0.1f%%\n",
2420 c5cc28ff Aurelien Jarno
                (double)s->opt_time / (s->code_time ? s->code_time : 1)
2421 c5cc28ff Aurelien Jarno
                * 100.0);
2422 a23a9ec6 bellard
    cpu_fprintf(f, "liveness/code time  %0.1f%%\n", 
2423 a23a9ec6 bellard
                (double)s->la_time / (s->code_time ? s->code_time : 1) * 100.0);
2424 a23a9ec6 bellard
    cpu_fprintf(f, "cpu_restore count   %" PRId64 "\n",
2425 a23a9ec6 bellard
                s->restore_count);
2426 a23a9ec6 bellard
    cpu_fprintf(f, "  avg cycles        %0.1f\n",
2427 a23a9ec6 bellard
                s->restore_count ? (double)s->restore_time / s->restore_count : 0);
2428 871e6c35 Blue Swirl
2429 871e6c35 Blue Swirl
    dump_op_count();
2430 a23a9ec6 bellard
}
2431 a23a9ec6 bellard
#else
2432 405cf9ff Stefan Weil
void tcg_dump_info(FILE *f, fprintf_function cpu_fprintf)
2433 a23a9ec6 bellard
{
2434 24bf7b3a bellard
    cpu_fprintf(f, "[TCG profiler not compiled]\n");
2435 a23a9ec6 bellard
}
2436 a23a9ec6 bellard
#endif
2437 813da627 Richard Henderson
2438 813da627 Richard Henderson
#ifdef ELF_HOST_MACHINE
2439 5872bbf2 Richard Henderson
/* In order to use this feature, the backend needs to do three things:
2440 5872bbf2 Richard Henderson

2441 5872bbf2 Richard Henderson
   (1) Define ELF_HOST_MACHINE to indicate both what value to
2442 5872bbf2 Richard Henderson
       put into the ELF image and to indicate support for the feature.
2443 5872bbf2 Richard Henderson

2444 5872bbf2 Richard Henderson
   (2) Define tcg_register_jit.  This should create a buffer containing
2445 5872bbf2 Richard Henderson
       the contents of a .debug_frame section that describes the post-
2446 5872bbf2 Richard Henderson
       prologue unwind info for the tcg machine.
2447 5872bbf2 Richard Henderson

2448 5872bbf2 Richard Henderson
   (3) Call tcg_register_jit_int, with the constructed .debug_frame.
2449 5872bbf2 Richard Henderson
*/
2450 813da627 Richard Henderson
2451 813da627 Richard Henderson
/* Begin GDB interface.  THE FOLLOWING MUST MATCH GDB DOCS.  */
2452 813da627 Richard Henderson
typedef enum {
2453 813da627 Richard Henderson
    JIT_NOACTION = 0,
2454 813da627 Richard Henderson
    JIT_REGISTER_FN,
2455 813da627 Richard Henderson
    JIT_UNREGISTER_FN
2456 813da627 Richard Henderson
} jit_actions_t;
2457 813da627 Richard Henderson
2458 813da627 Richard Henderson
struct jit_code_entry {
2459 813da627 Richard Henderson
    struct jit_code_entry *next_entry;
2460 813da627 Richard Henderson
    struct jit_code_entry *prev_entry;
2461 813da627 Richard Henderson
    const void *symfile_addr;
2462 813da627 Richard Henderson
    uint64_t symfile_size;
2463 813da627 Richard Henderson
};
2464 813da627 Richard Henderson
2465 813da627 Richard Henderson
struct jit_descriptor {
2466 813da627 Richard Henderson
    uint32_t version;
2467 813da627 Richard Henderson
    uint32_t action_flag;
2468 813da627 Richard Henderson
    struct jit_code_entry *relevant_entry;
2469 813da627 Richard Henderson
    struct jit_code_entry *first_entry;
2470 813da627 Richard Henderson
};
2471 813da627 Richard Henderson
2472 813da627 Richard Henderson
void __jit_debug_register_code(void) __attribute__((noinline));
2473 813da627 Richard Henderson
void __jit_debug_register_code(void)
2474 813da627 Richard Henderson
{
2475 813da627 Richard Henderson
    asm("");
2476 813da627 Richard Henderson
}
2477 813da627 Richard Henderson
2478 813da627 Richard Henderson
/* Must statically initialize the version, because GDB may check
2479 813da627 Richard Henderson
   the version before we can set it.  */
2480 813da627 Richard Henderson
struct jit_descriptor __jit_debug_descriptor = { 1, 0, 0, 0 };
2481 813da627 Richard Henderson
2482 813da627 Richard Henderson
/* End GDB interface.  */
2483 813da627 Richard Henderson
2484 813da627 Richard Henderson
static int find_string(const char *strtab, const char *str)
2485 813da627 Richard Henderson
{
2486 813da627 Richard Henderson
    const char *p = strtab + 1;
2487 813da627 Richard Henderson
2488 813da627 Richard Henderson
    while (1) {
2489 813da627 Richard Henderson
        if (strcmp(p, str) == 0) {
2490 813da627 Richard Henderson
            return p - strtab;
2491 813da627 Richard Henderson
        }
2492 813da627 Richard Henderson
        p += strlen(p) + 1;
2493 813da627 Richard Henderson
    }
2494 813da627 Richard Henderson
}
2495 813da627 Richard Henderson
2496 5872bbf2 Richard Henderson
static void tcg_register_jit_int(void *buf_ptr, size_t buf_size,
2497 813da627 Richard Henderson
                                 void *debug_frame, size_t debug_frame_size)
2498 813da627 Richard Henderson
{
2499 5872bbf2 Richard Henderson
    struct __attribute__((packed)) DebugInfo {
2500 5872bbf2 Richard Henderson
        uint32_t  len;
2501 5872bbf2 Richard Henderson
        uint16_t  version;
2502 5872bbf2 Richard Henderson
        uint32_t  abbrev;
2503 5872bbf2 Richard Henderson
        uint8_t   ptr_size;
2504 5872bbf2 Richard Henderson
        uint8_t   cu_die;
2505 5872bbf2 Richard Henderson
        uint16_t  cu_lang;
2506 5872bbf2 Richard Henderson
        uintptr_t cu_low_pc;
2507 5872bbf2 Richard Henderson
        uintptr_t cu_high_pc;
2508 5872bbf2 Richard Henderson
        uint8_t   fn_die;
2509 5872bbf2 Richard Henderson
        char      fn_name[16];
2510 5872bbf2 Richard Henderson
        uintptr_t fn_low_pc;
2511 5872bbf2 Richard Henderson
        uintptr_t fn_high_pc;
2512 5872bbf2 Richard Henderson
        uint8_t   cu_eoc;
2513 5872bbf2 Richard Henderson
    };
2514 813da627 Richard Henderson
2515 813da627 Richard Henderson
    struct ElfImage {
2516 813da627 Richard Henderson
        ElfW(Ehdr) ehdr;
2517 813da627 Richard Henderson
        ElfW(Phdr) phdr;
2518 5872bbf2 Richard Henderson
        ElfW(Shdr) shdr[7];
2519 5872bbf2 Richard Henderson
        ElfW(Sym)  sym[2];
2520 5872bbf2 Richard Henderson
        struct DebugInfo di;
2521 5872bbf2 Richard Henderson
        uint8_t    da[24];
2522 5872bbf2 Richard Henderson
        char       str[80];
2523 5872bbf2 Richard Henderson
    };
2524 5872bbf2 Richard Henderson
2525 5872bbf2 Richard Henderson
    struct ElfImage *img;
2526 5872bbf2 Richard Henderson
2527 5872bbf2 Richard Henderson
    static const struct ElfImage img_template = {
2528 5872bbf2 Richard Henderson
        .ehdr = {
2529 5872bbf2 Richard Henderson
            .e_ident[EI_MAG0] = ELFMAG0,
2530 5872bbf2 Richard Henderson
            .e_ident[EI_MAG1] = ELFMAG1,
2531 5872bbf2 Richard Henderson
            .e_ident[EI_MAG2] = ELFMAG2,
2532 5872bbf2 Richard Henderson
            .e_ident[EI_MAG3] = ELFMAG3,
2533 5872bbf2 Richard Henderson
            .e_ident[EI_CLASS] = ELF_CLASS,
2534 5872bbf2 Richard Henderson
            .e_ident[EI_DATA] = ELF_DATA,
2535 5872bbf2 Richard Henderson
            .e_ident[EI_VERSION] = EV_CURRENT,
2536 5872bbf2 Richard Henderson
            .e_type = ET_EXEC,
2537 5872bbf2 Richard Henderson
            .e_machine = ELF_HOST_MACHINE,
2538 5872bbf2 Richard Henderson
            .e_version = EV_CURRENT,
2539 5872bbf2 Richard Henderson
            .e_phoff = offsetof(struct ElfImage, phdr),
2540 5872bbf2 Richard Henderson
            .e_shoff = offsetof(struct ElfImage, shdr),
2541 5872bbf2 Richard Henderson
            .e_ehsize = sizeof(ElfW(Shdr)),
2542 5872bbf2 Richard Henderson
            .e_phentsize = sizeof(ElfW(Phdr)),
2543 5872bbf2 Richard Henderson
            .e_phnum = 1,
2544 5872bbf2 Richard Henderson
            .e_shentsize = sizeof(ElfW(Shdr)),
2545 5872bbf2 Richard Henderson
            .e_shnum = ARRAY_SIZE(img->shdr),
2546 5872bbf2 Richard Henderson
            .e_shstrndx = ARRAY_SIZE(img->shdr) - 1,
2547 abbb3eae Richard Henderson
#ifdef ELF_HOST_FLAGS
2548 abbb3eae Richard Henderson
            .e_flags = ELF_HOST_FLAGS,
2549 abbb3eae Richard Henderson
#endif
2550 abbb3eae Richard Henderson
#ifdef ELF_OSABI
2551 abbb3eae Richard Henderson
            .e_ident[EI_OSABI] = ELF_OSABI,
2552 abbb3eae Richard Henderson
#endif
2553 5872bbf2 Richard Henderson
        },
2554 5872bbf2 Richard Henderson
        .phdr = {
2555 5872bbf2 Richard Henderson
            .p_type = PT_LOAD,
2556 5872bbf2 Richard Henderson
            .p_flags = PF_X,
2557 5872bbf2 Richard Henderson
        },
2558 5872bbf2 Richard Henderson
        .shdr = {
2559 5872bbf2 Richard Henderson
            [0] = { .sh_type = SHT_NULL },
2560 5872bbf2 Richard Henderson
            /* Trick: The contents of code_gen_buffer are not present in
2561 5872bbf2 Richard Henderson
               this fake ELF file; that got allocated elsewhere.  Therefore
2562 5872bbf2 Richard Henderson
               we mark .text as SHT_NOBITS (similar to .bss) so that readers
2563 5872bbf2 Richard Henderson
               will not look for contents.  We can record any address.  */
2564 5872bbf2 Richard Henderson
            [1] = { /* .text */
2565 5872bbf2 Richard Henderson
                .sh_type = SHT_NOBITS,
2566 5872bbf2 Richard Henderson
                .sh_flags = SHF_EXECINSTR | SHF_ALLOC,
2567 5872bbf2 Richard Henderson
            },
2568 5872bbf2 Richard Henderson
            [2] = { /* .debug_info */
2569 5872bbf2 Richard Henderson
                .sh_type = SHT_PROGBITS,
2570 5872bbf2 Richard Henderson
                .sh_offset = offsetof(struct ElfImage, di),
2571 5872bbf2 Richard Henderson
                .sh_size = sizeof(struct DebugInfo),
2572 5872bbf2 Richard Henderson
            },
2573 5872bbf2 Richard Henderson
            [3] = { /* .debug_abbrev */
2574 5872bbf2 Richard Henderson
                .sh_type = SHT_PROGBITS,
2575 5872bbf2 Richard Henderson
                .sh_offset = offsetof(struct ElfImage, da),
2576 5872bbf2 Richard Henderson
                .sh_size = sizeof(img->da),
2577 5872bbf2 Richard Henderson
            },
2578 5872bbf2 Richard Henderson
            [4] = { /* .debug_frame */
2579 5872bbf2 Richard Henderson
                .sh_type = SHT_PROGBITS,
2580 5872bbf2 Richard Henderson
                .sh_offset = sizeof(struct ElfImage),
2581 5872bbf2 Richard Henderson
            },
2582 5872bbf2 Richard Henderson
            [5] = { /* .symtab */
2583 5872bbf2 Richard Henderson
                .sh_type = SHT_SYMTAB,
2584 5872bbf2 Richard Henderson
                .sh_offset = offsetof(struct ElfImage, sym),
2585 5872bbf2 Richard Henderson
                .sh_size = sizeof(img->sym),
2586 5872bbf2 Richard Henderson
                .sh_info = 1,
2587 5872bbf2 Richard Henderson
                .sh_link = ARRAY_SIZE(img->shdr) - 1,
2588 5872bbf2 Richard Henderson
                .sh_entsize = sizeof(ElfW(Sym)),
2589 5872bbf2 Richard Henderson
            },
2590 5872bbf2 Richard Henderson
            [6] = { /* .strtab */
2591 5872bbf2 Richard Henderson
                .sh_type = SHT_STRTAB,
2592 5872bbf2 Richard Henderson
                .sh_offset = offsetof(struct ElfImage, str),
2593 5872bbf2 Richard Henderson
                .sh_size = sizeof(img->str),
2594 5872bbf2 Richard Henderson
            }
2595 5872bbf2 Richard Henderson
        },
2596 5872bbf2 Richard Henderson
        .sym = {
2597 5872bbf2 Richard Henderson
            [1] = { /* code_gen_buffer */
2598 5872bbf2 Richard Henderson
                .st_info = ELF_ST_INFO(STB_GLOBAL, STT_FUNC),
2599 5872bbf2 Richard Henderson
                .st_shndx = 1,
2600 5872bbf2 Richard Henderson
            }
2601 5872bbf2 Richard Henderson
        },
2602 5872bbf2 Richard Henderson
        .di = {
2603 5872bbf2 Richard Henderson
            .len = sizeof(struct DebugInfo) - 4,
2604 5872bbf2 Richard Henderson
            .version = 2,
2605 5872bbf2 Richard Henderson
            .ptr_size = sizeof(void *),
2606 5872bbf2 Richard Henderson
            .cu_die = 1,
2607 5872bbf2 Richard Henderson
            .cu_lang = 0x8001,  /* DW_LANG_Mips_Assembler */
2608 5872bbf2 Richard Henderson
            .fn_die = 2,
2609 5872bbf2 Richard Henderson
            .fn_name = "code_gen_buffer"
2610 5872bbf2 Richard Henderson
        },
2611 5872bbf2 Richard Henderson
        .da = {
2612 5872bbf2 Richard Henderson
            1,          /* abbrev number (the cu) */
2613 5872bbf2 Richard Henderson
            0x11, 1,    /* DW_TAG_compile_unit, has children */
2614 5872bbf2 Richard Henderson
            0x13, 0x5,  /* DW_AT_language, DW_FORM_data2 */
2615 5872bbf2 Richard Henderson
            0x11, 0x1,  /* DW_AT_low_pc, DW_FORM_addr */
2616 5872bbf2 Richard Henderson
            0x12, 0x1,  /* DW_AT_high_pc, DW_FORM_addr */
2617 5872bbf2 Richard Henderson
            0, 0,       /* end of abbrev */
2618 5872bbf2 Richard Henderson
            2,          /* abbrev number (the fn) */
2619 5872bbf2 Richard Henderson
            0x2e, 0,    /* DW_TAG_subprogram, no children */
2620 5872bbf2 Richard Henderson
            0x3, 0x8,   /* DW_AT_name, DW_FORM_string */
2621 5872bbf2 Richard Henderson
            0x11, 0x1,  /* DW_AT_low_pc, DW_FORM_addr */
2622 5872bbf2 Richard Henderson
            0x12, 0x1,  /* DW_AT_high_pc, DW_FORM_addr */
2623 5872bbf2 Richard Henderson
            0, 0,       /* end of abbrev */
2624 5872bbf2 Richard Henderson
            0           /* no more abbrev */
2625 5872bbf2 Richard Henderson
        },
2626 5872bbf2 Richard Henderson
        .str = "\0" ".text\0" ".debug_info\0" ".debug_abbrev\0"
2627 5872bbf2 Richard Henderson
               ".debug_frame\0" ".symtab\0" ".strtab\0" "code_gen_buffer",
2628 813da627 Richard Henderson
    };
2629 813da627 Richard Henderson
2630 813da627 Richard Henderson
    /* We only need a single jit entry; statically allocate it.  */
2631 813da627 Richard Henderson
    static struct jit_code_entry one_entry;
2632 813da627 Richard Henderson
2633 5872bbf2 Richard Henderson
    uintptr_t buf = (uintptr_t)buf_ptr;
2634 813da627 Richard Henderson
    size_t img_size = sizeof(struct ElfImage) + debug_frame_size;
2635 813da627 Richard Henderson
2636 5872bbf2 Richard Henderson
    img = g_malloc(img_size);
2637 5872bbf2 Richard Henderson
    *img = img_template;
2638 5872bbf2 Richard Henderson
    memcpy(img + 1, debug_frame, debug_frame_size);
2639 813da627 Richard Henderson
2640 5872bbf2 Richard Henderson
    img->phdr.p_vaddr = buf;
2641 5872bbf2 Richard Henderson
    img->phdr.p_paddr = buf;
2642 5872bbf2 Richard Henderson
    img->phdr.p_memsz = buf_size;
2643 813da627 Richard Henderson
2644 813da627 Richard Henderson
    img->shdr[1].sh_name = find_string(img->str, ".text");
2645 5872bbf2 Richard Henderson
    img->shdr[1].sh_addr = buf;
2646 813da627 Richard Henderson
    img->shdr[1].sh_size = buf_size;
2647 813da627 Richard Henderson
2648 5872bbf2 Richard Henderson
    img->shdr[2].sh_name = find_string(img->str, ".debug_info");
2649 5872bbf2 Richard Henderson
    img->shdr[3].sh_name = find_string(img->str, ".debug_abbrev");
2650 5872bbf2 Richard Henderson
2651 5872bbf2 Richard Henderson
    img->shdr[4].sh_name = find_string(img->str, ".debug_frame");
2652 5872bbf2 Richard Henderson
    img->shdr[4].sh_size = debug_frame_size;
2653 5872bbf2 Richard Henderson
2654 5872bbf2 Richard Henderson
    img->shdr[5].sh_name = find_string(img->str, ".symtab");
2655 5872bbf2 Richard Henderson
    img->shdr[6].sh_name = find_string(img->str, ".strtab");
2656 5872bbf2 Richard Henderson
2657 5872bbf2 Richard Henderson
    img->sym[1].st_name = find_string(img->str, "code_gen_buffer");
2658 5872bbf2 Richard Henderson
    img->sym[1].st_value = buf;
2659 5872bbf2 Richard Henderson
    img->sym[1].st_size = buf_size;
2660 813da627 Richard Henderson
2661 5872bbf2 Richard Henderson
    img->di.cu_low_pc = buf;
2662 5872bbf2 Richard Henderson
    img->di.cu_high_pc = buf_size;
2663 5872bbf2 Richard Henderson
    img->di.fn_low_pc = buf;
2664 5872bbf2 Richard Henderson
    img->di.fn_high_pc = buf_size;
2665 813da627 Richard Henderson
2666 813da627 Richard Henderson
#ifdef DEBUG_JIT
2667 813da627 Richard Henderson
    /* Enable this block to be able to debug the ELF image file creation.
2668 813da627 Richard Henderson
       One can use readelf, objdump, or other inspection utilities.  */
2669 813da627 Richard Henderson
    {
2670 813da627 Richard Henderson
        FILE *f = fopen("/tmp/qemu.jit", "w+b");
2671 813da627 Richard Henderson
        if (f) {
2672 5872bbf2 Richard Henderson
            if (fwrite(img, img_size, 1, f) != img_size) {
2673 813da627 Richard Henderson
                /* Avoid stupid unused return value warning for fwrite.  */
2674 813da627 Richard Henderson
            }
2675 813da627 Richard Henderson
            fclose(f);
2676 813da627 Richard Henderson
        }
2677 813da627 Richard Henderson
    }
2678 813da627 Richard Henderson
#endif
2679 813da627 Richard Henderson
2680 813da627 Richard Henderson
    one_entry.symfile_addr = img;
2681 813da627 Richard Henderson
    one_entry.symfile_size = img_size;
2682 813da627 Richard Henderson
2683 813da627 Richard Henderson
    __jit_debug_descriptor.action_flag = JIT_REGISTER_FN;
2684 813da627 Richard Henderson
    __jit_debug_descriptor.relevant_entry = &one_entry;
2685 813da627 Richard Henderson
    __jit_debug_descriptor.first_entry = &one_entry;
2686 813da627 Richard Henderson
    __jit_debug_register_code();
2687 813da627 Richard Henderson
}
2688 813da627 Richard Henderson
#else
2689 5872bbf2 Richard Henderson
/* No support for the feature.  Provide the entry point expected by exec.c,
2690 5872bbf2 Richard Henderson
   and implement the internal function we declared earlier.  */
2691 813da627 Richard Henderson
2692 813da627 Richard Henderson
static void tcg_register_jit_int(void *buf, size_t size,
2693 813da627 Richard Henderson
                                 void *debug_frame, size_t debug_frame_size)
2694 813da627 Richard Henderson
{
2695 813da627 Richard Henderson
}
2696 813da627 Richard Henderson
2697 813da627 Richard Henderson
void tcg_register_jit(void *buf, size_t buf_size)
2698 813da627 Richard Henderson
{
2699 813da627 Richard Henderson
}
2700 813da627 Richard Henderson
#endif /* ELF_HOST_MACHINE */