]> git.proxmox.com Git - mirror_qemu.git/blame - tcg/tcg.c
tcg-sparc: Assume v9 cpu always, i.e. force v8plus in 32-bit mode.
[mirror_qemu.git] / tcg / tcg.c
CommitLineData
c896fe29
FB
1/*
2 * Tiny Code Generator for QEMU
3 *
4 * Copyright (c) 2008 Fabrice Bellard
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24
c896fe29
FB
25/* define it to use liveness analysis (better code) */
26#define USE_LIVENESS_ANALYSIS
8f2e8c07 27#define USE_TCG_OPTIMIZATIONS
c896fe29 28
cca82982
AJ
29#include "config.h"
30
813da627
RH
31/* Define to jump the ELF file used to communicate with GDB. */
32#undef DEBUG_JIT
33
a6c6f76c 34#if !defined(CONFIG_DEBUG_TCG) && !defined(NDEBUG)
cca82982
AJ
35/* define it to suppress various consistency checks (faster) */
36#define NDEBUG
37#endif
38
ca10f867 39#include "qemu-common.h"
902b3d5c 40#include "cache-utils.h"
379f6698 41#include "host-utils.h"
2d8ebcf9 42#include "qemu-timer.h"
c896fe29
FB
43
44/* Note: the long term plan is to reduce the dependancies on the QEMU
45 CPU definitions. Currently they are used for qemu_ld/st
46 instructions */
47#define NO_CPU_IO_DEFS
48#include "cpu.h"
c896fe29
FB
49
50#include "tcg-op.h"
813da627
RH
51
52#if TCG_TARGET_REG_BITS == 64
53# define ELF_CLASS ELFCLASS64
54#else
55# define ELF_CLASS ELFCLASS32
56#endif
57#ifdef HOST_WORDS_BIGENDIAN
58# define ELF_DATA ELFDATA2MSB
59#else
60# define ELF_DATA ELFDATA2LSB
61#endif
62
c896fe29
FB
63#include "elf.h"
64
379f6698
PB
65#if defined(CONFIG_USE_GUEST_BASE) && !defined(TCG_TARGET_HAS_GUEST_BASE)
66#error GUEST_BASE not supported on this host.
67#endif
c896fe29 68
c0ad3001 69/* Forward declarations for functions declared in tcg-target.c and used here. */
e4d58b41
RH
70static void tcg_target_init(TCGContext *s);
71static void tcg_target_qemu_prologue(TCGContext *s);
c896fe29 72static void patch_reloc(uint8_t *code_ptr, int type,
f54b3f92 73 tcg_target_long value, tcg_target_long addend);
c896fe29 74
813da627
RH
75static void tcg_register_jit_int(void *buf, size_t size,
76 void *debug_frame, size_t debug_frame_size)
77 __attribute__((unused));
78
c0ad3001
SW
79/* Forward declarations for functions declared and used in tcg-target.c. */
80static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str);
2a534aff 81static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg1,
c0ad3001 82 tcg_target_long arg2);
2a534aff 83static void tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg);
c0ad3001 84static void tcg_out_movi(TCGContext *s, TCGType type,
2a534aff 85 TCGReg ret, tcg_target_long arg);
c0ad3001
SW
86static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
87 const int *const_args);
2a534aff 88static void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, TCGReg arg1,
c0ad3001
SW
89 tcg_target_long arg2);
90static int tcg_target_const_match(tcg_target_long val,
91 const TCGArgConstraint *arg_ct);
92static int tcg_target_get_call_iarg_regs_count(int flags);
93
8399ad59 94TCGOpDef tcg_op_defs[] = {
0e2029a0 95#define DEF(s, oargs, iargs, cargs, flags) { #s, oargs, iargs, cargs, iargs + oargs + cargs, flags },
c896fe29
FB
96#include "tcg-opc.h"
97#undef DEF
c896fe29 98};
2a24374a 99const size_t tcg_op_defs_max = ARRAY_SIZE(tcg_op_defs);
c896fe29 100
b1d8e52e
BS
101static TCGRegSet tcg_target_available_regs[2];
102static TCGRegSet tcg_target_call_clobber_regs;
c896fe29
FB
103
104/* XXX: move that inside the context */
105uint16_t *gen_opc_ptr;
106TCGArg *gen_opparam_ptr;
107
108static inline void tcg_out8(TCGContext *s, uint8_t v)
109{
110 *s->code_ptr++ = v;
111}
112
113static inline void tcg_out16(TCGContext *s, uint16_t v)
114{
115 *(uint16_t *)s->code_ptr = v;
116 s->code_ptr += 2;
117}
118
119static inline void tcg_out32(TCGContext *s, uint32_t v)
120{
121 *(uint32_t *)s->code_ptr = v;
122 s->code_ptr += 4;
123}
124
125/* label relocation processing */
126
a5ad5916
SW
127static void tcg_out_reloc(TCGContext *s, uint8_t *code_ptr, int type,
128 int label_index, long addend)
c896fe29
FB
129{
130 TCGLabel *l;
131 TCGRelocation *r;
132
133 l = &s->labels[label_index];
134 if (l->has_value) {
623e265c
PB
135 /* FIXME: This may break relocations on RISC targets that
136 modify instruction fields in place. The caller may not have
137 written the initial value. */
f54b3f92 138 patch_reloc(code_ptr, type, l->u.value, addend);
c896fe29
FB
139 } else {
140 /* add a new relocation entry */
141 r = tcg_malloc(sizeof(TCGRelocation));
142 r->type = type;
143 r->ptr = code_ptr;
144 r->addend = addend;
145 r->next = l->u.first_reloc;
146 l->u.first_reloc = r;
147 }
148}
149
9d6fca70 150static void tcg_out_label(TCGContext *s, int label_index, void *ptr)
c896fe29
FB
151{
152 TCGLabel *l;
153 TCGRelocation *r;
9d6fca70 154 tcg_target_long value = (tcg_target_long)ptr;
c896fe29
FB
155
156 l = &s->labels[label_index];
157 if (l->has_value)
158 tcg_abort();
159 r = l->u.first_reloc;
160 while (r != NULL) {
f54b3f92 161 patch_reloc(r->ptr, r->type, value, r->addend);
c896fe29
FB
162 r = r->next;
163 }
164 l->has_value = 1;
165 l->u.value = value;
166}
167
168int gen_new_label(void)
169{
170 TCGContext *s = &tcg_ctx;
171 int idx;
172 TCGLabel *l;
173
174 if (s->nb_labels >= TCG_MAX_LABELS)
175 tcg_abort();
176 idx = s->nb_labels++;
177 l = &s->labels[idx];
178 l->has_value = 0;
179 l->u.first_reloc = NULL;
180 return idx;
181}
182
183#include "tcg-target.c"
184
c896fe29
FB
185/* pool based memory allocation */
186void *tcg_malloc_internal(TCGContext *s, int size)
187{
188 TCGPool *p;
189 int pool_size;
190
191 if (size > TCG_POOL_CHUNK_SIZE) {
192 /* big malloc: insert a new pool (XXX: could optimize) */
7267c094 193 p = g_malloc(sizeof(TCGPool) + size);
c896fe29 194 p->size = size;
4055299e
KB
195 p->next = s->pool_first_large;
196 s->pool_first_large = p;
197 return p->data;
c896fe29
FB
198 } else {
199 p = s->pool_current;
200 if (!p) {
201 p = s->pool_first;
202 if (!p)
203 goto new_pool;
204 } else {
205 if (!p->next) {
206 new_pool:
207 pool_size = TCG_POOL_CHUNK_SIZE;
7267c094 208 p = g_malloc(sizeof(TCGPool) + pool_size);
c896fe29
FB
209 p->size = pool_size;
210 p->next = NULL;
211 if (s->pool_current)
212 s->pool_current->next = p;
213 else
214 s->pool_first = p;
215 } else {
216 p = p->next;
217 }
218 }
219 }
220 s->pool_current = p;
221 s->pool_cur = p->data + size;
222 s->pool_end = p->data + p->size;
223 return p->data;
224}
225
226void tcg_pool_reset(TCGContext *s)
227{
4055299e
KB
228 TCGPool *p, *t;
229 for (p = s->pool_first_large; p; p = t) {
230 t = p->next;
231 g_free(p);
232 }
233 s->pool_first_large = NULL;
c896fe29
FB
234 s->pool_cur = s->pool_end = NULL;
235 s->pool_current = NULL;
236}
237
c896fe29
FB
238void tcg_context_init(TCGContext *s)
239{
240 int op, total_args, n;
241 TCGOpDef *def;
242 TCGArgConstraint *args_ct;
243 int *sorted_args;
244
245 memset(s, 0, sizeof(*s));
246 s->temps = s->static_temps;
247 s->nb_globals = 0;
248
249 /* Count total number of arguments and allocate the corresponding
250 space */
251 total_args = 0;
252 for(op = 0; op < NB_OPS; op++) {
253 def = &tcg_op_defs[op];
254 n = def->nb_iargs + def->nb_oargs;
255 total_args += n;
256 }
257
7267c094
AL
258 args_ct = g_malloc(sizeof(TCGArgConstraint) * total_args);
259 sorted_args = g_malloc(sizeof(int) * total_args);
c896fe29
FB
260
261 for(op = 0; op < NB_OPS; op++) {
262 def = &tcg_op_defs[op];
263 def->args_ct = args_ct;
264 def->sorted_args = sorted_args;
265 n = def->nb_iargs + def->nb_oargs;
266 sorted_args += n;
267 args_ct += n;
268 }
269
270 tcg_target_init(s);
9002ec79 271}
b03cce8e 272
9002ec79
RH
273void tcg_prologue_init(TCGContext *s)
274{
b03cce8e
FB
275 /* init global prologue and epilogue */
276 s->code_buf = code_gen_prologue;
277 s->code_ptr = s->code_buf;
278 tcg_target_qemu_prologue(s);
2aeabc08
SW
279 flush_icache_range((tcg_target_ulong)s->code_buf,
280 (tcg_target_ulong)s->code_ptr);
c896fe29
FB
281}
282
283void tcg_set_frame(TCGContext *s, int reg,
284 tcg_target_long start, tcg_target_long size)
285{
286 s->frame_start = start;
287 s->frame_end = start + size;
288 s->frame_reg = reg;
289}
290
c896fe29
FB
291void tcg_func_start(TCGContext *s)
292{
e8996ee0 293 int i;
c896fe29
FB
294 tcg_pool_reset(s);
295 s->nb_temps = s->nb_globals;
641d5fbe 296 for(i = 0; i < (TCG_TYPE_COUNT * 2); i++)
e8996ee0 297 s->first_free_temp[i] = -1;
c896fe29
FB
298 s->labels = tcg_malloc(sizeof(TCGLabel) * TCG_MAX_LABELS);
299 s->nb_labels = 0;
300 s->current_frame_offset = s->frame_start;
301
302 gen_opc_ptr = gen_opc_buf;
303 gen_opparam_ptr = gen_opparam_buf;
304}
305
306static inline void tcg_temp_alloc(TCGContext *s, int n)
307{
308 if (n > TCG_MAX_TEMPS)
309 tcg_abort();
310}
311
a7812ae4
PB
312static inline int tcg_global_reg_new_internal(TCGType type, int reg,
313 const char *name)
c896fe29
FB
314{
315 TCGContext *s = &tcg_ctx;
316 TCGTemp *ts;
317 int idx;
318
319#if TCG_TARGET_REG_BITS == 32
320 if (type != TCG_TYPE_I32)
321 tcg_abort();
322#endif
323 if (tcg_regset_test_reg(s->reserved_regs, reg))
324 tcg_abort();
325 idx = s->nb_globals;
326 tcg_temp_alloc(s, s->nb_globals + 1);
327 ts = &s->temps[s->nb_globals];
328 ts->base_type = type;
329 ts->type = type;
330 ts->fixed_reg = 1;
331 ts->reg = reg;
c896fe29
FB
332 ts->name = name;
333 s->nb_globals++;
334 tcg_regset_set_reg(s->reserved_regs, reg);
a7812ae4
PB
335 return idx;
336}
337
338TCGv_i32 tcg_global_reg_new_i32(int reg, const char *name)
339{
340 int idx;
341
342 idx = tcg_global_reg_new_internal(TCG_TYPE_I32, reg, name);
343 return MAKE_TCGV_I32(idx);
344}
345
346TCGv_i64 tcg_global_reg_new_i64(int reg, const char *name)
347{
348 int idx;
349
350 idx = tcg_global_reg_new_internal(TCG_TYPE_I64, reg, name);
351 return MAKE_TCGV_I64(idx);
c896fe29
FB
352}
353
a7812ae4
PB
354static inline int tcg_global_mem_new_internal(TCGType type, int reg,
355 tcg_target_long offset,
356 const char *name)
c896fe29
FB
357{
358 TCGContext *s = &tcg_ctx;
359 TCGTemp *ts;
360 int idx;
361
362 idx = s->nb_globals;
363#if TCG_TARGET_REG_BITS == 32
364 if (type == TCG_TYPE_I64) {
365 char buf[64];
c588979b 366 tcg_temp_alloc(s, s->nb_globals + 2);
c896fe29
FB
367 ts = &s->temps[s->nb_globals];
368 ts->base_type = type;
369 ts->type = TCG_TYPE_I32;
370 ts->fixed_reg = 0;
371 ts->mem_allocated = 1;
372 ts->mem_reg = reg;
373#ifdef TCG_TARGET_WORDS_BIGENDIAN
374 ts->mem_offset = offset + 4;
375#else
376 ts->mem_offset = offset;
377#endif
c896fe29
FB
378 pstrcpy(buf, sizeof(buf), name);
379 pstrcat(buf, sizeof(buf), "_0");
380 ts->name = strdup(buf);
381 ts++;
382
383 ts->base_type = type;
384 ts->type = TCG_TYPE_I32;
385 ts->fixed_reg = 0;
386 ts->mem_allocated = 1;
387 ts->mem_reg = reg;
388#ifdef TCG_TARGET_WORDS_BIGENDIAN
389 ts->mem_offset = offset;
390#else
391 ts->mem_offset = offset + 4;
392#endif
c896fe29
FB
393 pstrcpy(buf, sizeof(buf), name);
394 pstrcat(buf, sizeof(buf), "_1");
395 ts->name = strdup(buf);
396
397 s->nb_globals += 2;
398 } else
399#endif
400 {
401 tcg_temp_alloc(s, s->nb_globals + 1);
402 ts = &s->temps[s->nb_globals];
403 ts->base_type = type;
404 ts->type = type;
405 ts->fixed_reg = 0;
406 ts->mem_allocated = 1;
407 ts->mem_reg = reg;
408 ts->mem_offset = offset;
c896fe29
FB
409 ts->name = name;
410 s->nb_globals++;
411 }
a7812ae4
PB
412 return idx;
413}
414
415TCGv_i32 tcg_global_mem_new_i32(int reg, tcg_target_long offset,
416 const char *name)
417{
418 int idx;
419
420 idx = tcg_global_mem_new_internal(TCG_TYPE_I32, reg, offset, name);
421 return MAKE_TCGV_I32(idx);
422}
423
424TCGv_i64 tcg_global_mem_new_i64(int reg, tcg_target_long offset,
425 const char *name)
426{
427 int idx;
428
429 idx = tcg_global_mem_new_internal(TCG_TYPE_I64, reg, offset, name);
430 return MAKE_TCGV_I64(idx);
c896fe29
FB
431}
432
a7812ae4 433static inline int tcg_temp_new_internal(TCGType type, int temp_local)
c896fe29
FB
434{
435 TCGContext *s = &tcg_ctx;
436 TCGTemp *ts;
641d5fbe 437 int idx, k;
c896fe29 438
641d5fbe
FB
439 k = type;
440 if (temp_local)
441 k += TCG_TYPE_COUNT;
442 idx = s->first_free_temp[k];
e8996ee0
FB
443 if (idx != -1) {
444 /* There is already an available temp with the
445 right type */
446 ts = &s->temps[idx];
641d5fbe 447 s->first_free_temp[k] = ts->next_free_temp;
e8996ee0 448 ts->temp_allocated = 1;
641d5fbe 449 assert(ts->temp_local == temp_local);
e8996ee0
FB
450 } else {
451 idx = s->nb_temps;
c896fe29 452#if TCG_TARGET_REG_BITS == 32
e8996ee0 453 if (type == TCG_TYPE_I64) {
8df1ca4b 454 tcg_temp_alloc(s, s->nb_temps + 2);
e8996ee0
FB
455 ts = &s->temps[s->nb_temps];
456 ts->base_type = type;
457 ts->type = TCG_TYPE_I32;
458 ts->temp_allocated = 1;
641d5fbe 459 ts->temp_local = temp_local;
e8996ee0
FB
460 ts->name = NULL;
461 ts++;
462 ts->base_type = TCG_TYPE_I32;
463 ts->type = TCG_TYPE_I32;
464 ts->temp_allocated = 1;
641d5fbe 465 ts->temp_local = temp_local;
e8996ee0
FB
466 ts->name = NULL;
467 s->nb_temps += 2;
468 } else
c896fe29 469#endif
e8996ee0
FB
470 {
471 tcg_temp_alloc(s, s->nb_temps + 1);
472 ts = &s->temps[s->nb_temps];
473 ts->base_type = type;
474 ts->type = type;
475 ts->temp_allocated = 1;
641d5fbe 476 ts->temp_local = temp_local;
e8996ee0
FB
477 ts->name = NULL;
478 s->nb_temps++;
479 }
c896fe29 480 }
27bfd83c
PM
481
482#if defined(CONFIG_DEBUG_TCG)
483 s->temps_in_use++;
484#endif
a7812ae4 485 return idx;
c896fe29
FB
486}
487
a7812ae4
PB
488TCGv_i32 tcg_temp_new_internal_i32(int temp_local)
489{
490 int idx;
491
492 idx = tcg_temp_new_internal(TCG_TYPE_I32, temp_local);
493 return MAKE_TCGV_I32(idx);
494}
495
496TCGv_i64 tcg_temp_new_internal_i64(int temp_local)
497{
498 int idx;
499
500 idx = tcg_temp_new_internal(TCG_TYPE_I64, temp_local);
501 return MAKE_TCGV_I64(idx);
502}
503
504static inline void tcg_temp_free_internal(int idx)
c896fe29
FB
505{
506 TCGContext *s = &tcg_ctx;
507 TCGTemp *ts;
641d5fbe 508 int k;
c896fe29 509
27bfd83c
PM
510#if defined(CONFIG_DEBUG_TCG)
511 s->temps_in_use--;
512 if (s->temps_in_use < 0) {
513 fprintf(stderr, "More temporaries freed than allocated!\n");
514 }
515#endif
516
e8996ee0 517 assert(idx >= s->nb_globals && idx < s->nb_temps);
c896fe29 518 ts = &s->temps[idx];
e8996ee0
FB
519 assert(ts->temp_allocated != 0);
520 ts->temp_allocated = 0;
641d5fbe
FB
521 k = ts->base_type;
522 if (ts->temp_local)
523 k += TCG_TYPE_COUNT;
524 ts->next_free_temp = s->first_free_temp[k];
525 s->first_free_temp[k] = idx;
c896fe29
FB
526}
527
a7812ae4
PB
528void tcg_temp_free_i32(TCGv_i32 arg)
529{
530 tcg_temp_free_internal(GET_TCGV_I32(arg));
531}
532
533void tcg_temp_free_i64(TCGv_i64 arg)
534{
535 tcg_temp_free_internal(GET_TCGV_I64(arg));
536}
e8996ee0 537
a7812ae4 538TCGv_i32 tcg_const_i32(int32_t val)
c896fe29 539{
a7812ae4
PB
540 TCGv_i32 t0;
541 t0 = tcg_temp_new_i32();
e8996ee0
FB
542 tcg_gen_movi_i32(t0, val);
543 return t0;
544}
c896fe29 545
a7812ae4 546TCGv_i64 tcg_const_i64(int64_t val)
e8996ee0 547{
a7812ae4
PB
548 TCGv_i64 t0;
549 t0 = tcg_temp_new_i64();
e8996ee0
FB
550 tcg_gen_movi_i64(t0, val);
551 return t0;
c896fe29
FB
552}
553
a7812ae4 554TCGv_i32 tcg_const_local_i32(int32_t val)
bdffd4a9 555{
a7812ae4
PB
556 TCGv_i32 t0;
557 t0 = tcg_temp_local_new_i32();
bdffd4a9
AJ
558 tcg_gen_movi_i32(t0, val);
559 return t0;
560}
561
a7812ae4 562TCGv_i64 tcg_const_local_i64(int64_t val)
bdffd4a9 563{
a7812ae4
PB
564 TCGv_i64 t0;
565 t0 = tcg_temp_local_new_i64();
bdffd4a9
AJ
566 tcg_gen_movi_i64(t0, val);
567 return t0;
568}
569
27bfd83c
PM
570#if defined(CONFIG_DEBUG_TCG)
571void tcg_clear_temp_count(void)
572{
573 TCGContext *s = &tcg_ctx;
574 s->temps_in_use = 0;
575}
576
577int tcg_check_temp_count(void)
578{
579 TCGContext *s = &tcg_ctx;
580 if (s->temps_in_use) {
581 /* Clear the count so that we don't give another
582 * warning immediately next time around.
583 */
584 s->temps_in_use = 0;
585 return 1;
586 }
587 return 0;
588}
589#endif
590
c896fe29
FB
591void tcg_register_helper(void *func, const char *name)
592{
593 TCGContext *s = &tcg_ctx;
594 int n;
595 if ((s->nb_helpers + 1) > s->allocated_helpers) {
596 n = s->allocated_helpers;
597 if (n == 0) {
598 n = 4;
599 } else {
600 n *= 2;
601 }
602 s->helpers = realloc(s->helpers, n * sizeof(TCGHelperInfo));
603 s->allocated_helpers = n;
604 }
4dc81f28 605 s->helpers[s->nb_helpers].func = (tcg_target_ulong)func;
c896fe29
FB
606 s->helpers[s->nb_helpers].name = name;
607 s->nb_helpers++;
608}
609
39cf05d3
FB
610/* Note: we convert the 64 bit args to 32 bit and do some alignment
611 and endian swap. Maybe it would be better to do the alignment
612 and endian swap in tcg_reg_alloc_call(). */
a7812ae4
PB
613void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags,
614 int sizemask, TCGArg ret, int nargs, TCGArg *args)
c896fe29 615{
a7812ae4
PB
616 int i;
617 int real_args;
618 int nb_rets;
619 TCGArg *nparam;
2bece2c8
RH
620
621#if defined(TCG_TARGET_EXTEND_ARGS) && TCG_TARGET_REG_BITS == 64
622 for (i = 0; i < nargs; ++i) {
623 int is_64bit = sizemask & (1 << (i+1)*2);
624 int is_signed = sizemask & (2 << (i+1)*2);
625 if (!is_64bit) {
626 TCGv_i64 temp = tcg_temp_new_i64();
627 TCGv_i64 orig = MAKE_TCGV_I64(args[i]);
628 if (is_signed) {
629 tcg_gen_ext32s_i64(temp, orig);
630 } else {
631 tcg_gen_ext32u_i64(temp, orig);
632 }
633 args[i] = GET_TCGV_I64(temp);
634 }
635 }
636#endif /* TCG_TARGET_EXTEND_ARGS */
637
a7812ae4
PB
638 *gen_opc_ptr++ = INDEX_op_call;
639 nparam = gen_opparam_ptr++;
a7812ae4
PB
640 if (ret != TCG_CALL_DUMMY_ARG) {
641#if TCG_TARGET_REG_BITS < 64
642 if (sizemask & 1) {
39cf05d3 643#ifdef TCG_TARGET_WORDS_BIGENDIAN
a7812ae4
PB
644 *gen_opparam_ptr++ = ret + 1;
645 *gen_opparam_ptr++ = ret;
39cf05d3 646#else
a7812ae4
PB
647 *gen_opparam_ptr++ = ret;
648 *gen_opparam_ptr++ = ret + 1;
39cf05d3 649#endif
a7812ae4
PB
650 nb_rets = 2;
651 } else
652#endif
653 {
654 *gen_opparam_ptr++ = ret;
655 nb_rets = 1;
c896fe29 656 }
a7812ae4
PB
657 } else {
658 nb_rets = 0;
c896fe29 659 }
a7812ae4
PB
660 real_args = 0;
661 for (i = 0; i < nargs; i++) {
662#if TCG_TARGET_REG_BITS < 64
2bece2c8
RH
663 int is_64bit = sizemask & (1 << (i+1)*2);
664 if (is_64bit) {
39cf05d3
FB
665#ifdef TCG_TARGET_CALL_ALIGN_ARGS
666 /* some targets want aligned 64 bit args */
ebd486d5 667 if (real_args & 1) {
a7812ae4 668 *gen_opparam_ptr++ = TCG_CALL_DUMMY_ARG;
ebd486d5 669 real_args++;
39cf05d3
FB
670 }
671#endif
3f90f252
RH
672 /* If stack grows up, then we will be placing successive
673 arguments at lower addresses, which means we need to
674 reverse the order compared to how we would normally
675 treat either big or little-endian. For those arguments
676 that will wind up in registers, this still works for
677 HPPA (the only current STACK_GROWSUP target) since the
678 argument registers are *also* allocated in decreasing
679 order. If another such target is added, this logic may
680 have to get more complicated to differentiate between
681 stack arguments and register arguments. */
682#if defined(TCG_TARGET_WORDS_BIGENDIAN) != defined(TCG_TARGET_STACK_GROWSUP)
a7812ae4
PB
683 *gen_opparam_ptr++ = args[i] + 1;
684 *gen_opparam_ptr++ = args[i];
c896fe29 685#else
a7812ae4
PB
686 *gen_opparam_ptr++ = args[i];
687 *gen_opparam_ptr++ = args[i] + 1;
c896fe29 688#endif
a7812ae4 689 real_args += 2;
2bece2c8 690 continue;
c896fe29 691 }
2bece2c8
RH
692#endif /* TCG_TARGET_REG_BITS < 64 */
693
694 *gen_opparam_ptr++ = args[i];
695 real_args++;
c896fe29 696 }
a7812ae4
PB
697 *gen_opparam_ptr++ = GET_TCGV_PTR(func);
698
699 *gen_opparam_ptr++ = flags;
700
701 *nparam = (nb_rets << 16) | (real_args + 1);
702
703 /* total parameters, needed to go backward in the instruction stream */
704 *gen_opparam_ptr++ = 1 + nb_rets + real_args + 3;
2bece2c8
RH
705
706#if defined(TCG_TARGET_EXTEND_ARGS) && TCG_TARGET_REG_BITS == 64
707 for (i = 0; i < nargs; ++i) {
708 int is_64bit = sizemask & (1 << (i+1)*2);
709 if (!is_64bit) {
710 TCGv_i64 temp = MAKE_TCGV_I64(args[i]);
711 tcg_temp_free_i64(temp);
712 }
713 }
714#endif /* TCG_TARGET_EXTEND_ARGS */
c896fe29 715}
c896fe29 716
ac56dd48 717#if TCG_TARGET_REG_BITS == 32
a7812ae4 718void tcg_gen_shifti_i64(TCGv_i64 ret, TCGv_i64 arg1,
c896fe29
FB
719 int c, int right, int arith)
720{
cf60bce4 721 if (c == 0) {
a7812ae4 722 tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg1));
cf60bce4
FB
723 tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
724 } else if (c >= 32) {
c896fe29
FB
725 c -= 32;
726 if (right) {
727 if (arith) {
a7812ae4 728 tcg_gen_sari_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
ac56dd48 729 tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 31);
c896fe29 730 } else {
a7812ae4 731 tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
ac56dd48 732 tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
c896fe29
FB
733 }
734 } else {
a7812ae4
PB
735 tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_LOW(arg1), c);
736 tcg_gen_movi_i32(TCGV_LOW(ret), 0);
c896fe29
FB
737 }
738 } else {
a7812ae4 739 TCGv_i32 t0, t1;
c896fe29 740
a7812ae4
PB
741 t0 = tcg_temp_new_i32();
742 t1 = tcg_temp_new_i32();
c896fe29 743 if (right) {
ac56dd48 744 tcg_gen_shli_i32(t0, TCGV_HIGH(arg1), 32 - c);
c896fe29 745 if (arith)
ac56dd48 746 tcg_gen_sari_i32(t1, TCGV_HIGH(arg1), c);
a7812ae4 747 else
ac56dd48 748 tcg_gen_shri_i32(t1, TCGV_HIGH(arg1), c);
a7812ae4
PB
749 tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_LOW(arg1), c);
750 tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(ret), t0);
ac56dd48 751 tcg_gen_mov_i32(TCGV_HIGH(ret), t1);
c896fe29 752 } else {
a7812ae4 753 tcg_gen_shri_i32(t0, TCGV_LOW(arg1), 32 - c);
c896fe29 754 /* Note: ret can be the same as arg1, so we use t1 */
a7812ae4 755 tcg_gen_shli_i32(t1, TCGV_LOW(arg1), c);
ac56dd48
PB
756 tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c);
757 tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t0);
a7812ae4 758 tcg_gen_mov_i32(TCGV_LOW(ret), t1);
c896fe29 759 }
a7812ae4
PB
760 tcg_temp_free_i32(t0);
761 tcg_temp_free_i32(t1);
c896fe29
FB
762 }
763}
ac56dd48 764#endif
c896fe29 765
be210acb 766
8fcd3692 767static void tcg_reg_alloc_start(TCGContext *s)
c896fe29
FB
768{
769 int i;
770 TCGTemp *ts;
771 for(i = 0; i < s->nb_globals; i++) {
772 ts = &s->temps[i];
773 if (ts->fixed_reg) {
774 ts->val_type = TEMP_VAL_REG;
775 } else {
776 ts->val_type = TEMP_VAL_MEM;
777 }
778 }
e8996ee0
FB
779 for(i = s->nb_globals; i < s->nb_temps; i++) {
780 ts = &s->temps[i];
781 ts->val_type = TEMP_VAL_DEAD;
782 ts->mem_allocated = 0;
783 ts->fixed_reg = 0;
784 }
c896fe29
FB
785 for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
786 s->reg_to_temp[i] = -1;
787 }
788}
789
ac56dd48
PB
790static char *tcg_get_arg_str_idx(TCGContext *s, char *buf, int buf_size,
791 int idx)
c896fe29
FB
792{
793 TCGTemp *ts;
ac56dd48 794
7f6f0ae5 795 assert(idx >= 0 && idx < s->nb_temps);
ac56dd48 796 ts = &s->temps[idx];
7f6f0ae5 797 assert(ts);
ac56dd48
PB
798 if (idx < s->nb_globals) {
799 pstrcpy(buf, buf_size, ts->name);
c896fe29 800 } else {
641d5fbe
FB
801 if (ts->temp_local)
802 snprintf(buf, buf_size, "loc%d", idx - s->nb_globals);
803 else
804 snprintf(buf, buf_size, "tmp%d", idx - s->nb_globals);
c896fe29
FB
805 }
806 return buf;
807}
808
a7812ae4
PB
809char *tcg_get_arg_str_i32(TCGContext *s, char *buf, int buf_size, TCGv_i32 arg)
810{
811 return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I32(arg));
812}
813
814char *tcg_get_arg_str_i64(TCGContext *s, char *buf, int buf_size, TCGv_i64 arg)
ac56dd48 815{
a810a2de 816 return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I64(arg));
ac56dd48
PB
817}
818
e8996ee0 819static int helper_cmp(const void *p1, const void *p2)
4dc81f28 820{
e8996ee0
FB
821 const TCGHelperInfo *th1 = p1;
822 const TCGHelperInfo *th2 = p2;
823 if (th1->func < th2->func)
824 return -1;
825 else if (th1->func == th2->func)
826 return 0;
827 else
828 return 1;
4dc81f28
FB
829}
830
e8996ee0
FB
831/* find helper definition (Note: A hash table would be better) */
832static TCGHelperInfo *tcg_find_helper(TCGContext *s, tcg_target_ulong val)
4dc81f28 833{
e8996ee0 834 int m, m_min, m_max;
4dc81f28 835 TCGHelperInfo *th;
e8996ee0 836 tcg_target_ulong v;
4dc81f28 837
e8996ee0
FB
838 if (unlikely(!s->helpers_sorted)) {
839 qsort(s->helpers, s->nb_helpers, sizeof(TCGHelperInfo),
840 helper_cmp);
841 s->helpers_sorted = 1;
842 }
843
844 /* binary search */
845 m_min = 0;
846 m_max = s->nb_helpers - 1;
847 while (m_min <= m_max) {
848 m = (m_min + m_max) >> 1;
849 th = &s->helpers[m];
850 v = th->func;
851 if (v == val)
852 return th;
853 else if (val < v) {
854 m_max = m - 1;
855 } else {
856 m_min = m + 1;
4dc81f28
FB
857 }
858 }
e8996ee0 859 return NULL;
4dc81f28
FB
860}
861
f48f3ede
BS
862static const char * const cond_name[] =
863{
864 [TCG_COND_EQ] = "eq",
865 [TCG_COND_NE] = "ne",
866 [TCG_COND_LT] = "lt",
867 [TCG_COND_GE] = "ge",
868 [TCG_COND_LE] = "le",
869 [TCG_COND_GT] = "gt",
870 [TCG_COND_LTU] = "ltu",
871 [TCG_COND_GEU] = "geu",
872 [TCG_COND_LEU] = "leu",
873 [TCG_COND_GTU] = "gtu"
874};
875
eeacee4d 876void tcg_dump_ops(TCGContext *s)
c896fe29
FB
877{
878 const uint16_t *opc_ptr;
879 const TCGArg *args;
880 TCGArg arg;
a9751609
RH
881 TCGOpcode c;
882 int i, k, nb_oargs, nb_iargs, nb_cargs, first_insn;
c896fe29
FB
883 const TCGOpDef *def;
884 char buf[128];
885
7e4597d7 886 first_insn = 1;
c896fe29
FB
887 opc_ptr = gen_opc_buf;
888 args = gen_opparam_buf;
889 while (opc_ptr < gen_opc_ptr) {
890 c = *opc_ptr++;
891 def = &tcg_op_defs[c];
7e4597d7
FB
892 if (c == INDEX_op_debug_insn_start) {
893 uint64_t pc;
894#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
895 pc = ((uint64_t)args[1] << 32) | args[0];
896#else
897 pc = args[0];
898#endif
eeacee4d
BS
899 if (!first_insn) {
900 qemu_log("\n");
901 }
902 qemu_log(" ---- 0x%" PRIx64, pc);
7e4597d7
FB
903 first_insn = 0;
904 nb_oargs = def->nb_oargs;
905 nb_iargs = def->nb_iargs;
906 nb_cargs = def->nb_cargs;
907 } else if (c == INDEX_op_call) {
c896fe29 908 TCGArg arg;
4dc81f28 909
c896fe29
FB
910 /* variable number of arguments */
911 arg = *args++;
912 nb_oargs = arg >> 16;
913 nb_iargs = arg & 0xffff;
914 nb_cargs = def->nb_cargs;
c896fe29 915
eeacee4d 916 qemu_log(" %s ", def->name);
7e4597d7 917
b03cce8e 918 /* function name */
eeacee4d
BS
919 qemu_log("%s",
920 tcg_get_arg_str_idx(s, buf, sizeof(buf),
921 args[nb_oargs + nb_iargs - 1]));
b03cce8e 922 /* flags */
eeacee4d 923 qemu_log(",$0x%" TCG_PRIlx, args[nb_oargs + nb_iargs]);
b03cce8e 924 /* nb out args */
eeacee4d 925 qemu_log(",$%d", nb_oargs);
b03cce8e 926 for(i = 0; i < nb_oargs; i++) {
eeacee4d
BS
927 qemu_log(",");
928 qemu_log("%s", tcg_get_arg_str_idx(s, buf, sizeof(buf),
929 args[i]));
b03cce8e
FB
930 }
931 for(i = 0; i < (nb_iargs - 1); i++) {
eeacee4d 932 qemu_log(",");
39cf05d3 933 if (args[nb_oargs + i] == TCG_CALL_DUMMY_ARG) {
eeacee4d 934 qemu_log("<dummy>");
39cf05d3 935 } else {
eeacee4d
BS
936 qemu_log("%s", tcg_get_arg_str_idx(s, buf, sizeof(buf),
937 args[nb_oargs + i]));
39cf05d3 938 }
b03cce8e 939 }
e8996ee0
FB
940 } else if (c == INDEX_op_movi_i32
941#if TCG_TARGET_REG_BITS == 64
942 || c == INDEX_op_movi_i64
943#endif
944 ) {
945 tcg_target_ulong val;
946 TCGHelperInfo *th;
947
948 nb_oargs = def->nb_oargs;
949 nb_iargs = def->nb_iargs;
950 nb_cargs = def->nb_cargs;
eeacee4d
BS
951 qemu_log(" %s %s,$", def->name,
952 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[0]));
e8996ee0
FB
953 val = args[1];
954 th = tcg_find_helper(s, val);
955 if (th) {
eeacee4d 956 qemu_log("%s", th->name);
e8996ee0 957 } else {
eeacee4d
BS
958 if (c == INDEX_op_movi_i32) {
959 qemu_log("0x%x", (uint32_t)val);
960 } else {
961 qemu_log("0x%" PRIx64 , (uint64_t)val);
962 }
e8996ee0 963 }
b03cce8e 964 } else {
eeacee4d 965 qemu_log(" %s ", def->name);
b03cce8e
FB
966 if (c == INDEX_op_nopn) {
967 /* variable number of arguments */
968 nb_cargs = *args;
969 nb_oargs = 0;
970 nb_iargs = 0;
971 } else {
972 nb_oargs = def->nb_oargs;
973 nb_iargs = def->nb_iargs;
974 nb_cargs = def->nb_cargs;
975 }
976
977 k = 0;
978 for(i = 0; i < nb_oargs; i++) {
eeacee4d
BS
979 if (k != 0) {
980 qemu_log(",");
981 }
982 qemu_log("%s", tcg_get_arg_str_idx(s, buf, sizeof(buf),
983 args[k++]));
b03cce8e
FB
984 }
985 for(i = 0; i < nb_iargs; i++) {
eeacee4d
BS
986 if (k != 0) {
987 qemu_log(",");
988 }
989 qemu_log("%s", tcg_get_arg_str_idx(s, buf, sizeof(buf),
990 args[k++]));
b03cce8e 991 }
be210acb
RH
992 switch (c) {
993 case INDEX_op_brcond_i32:
be210acb 994 case INDEX_op_setcond_i32:
ffc5ea09 995 case INDEX_op_movcond_i32:
f48f3ede 996#if TCG_TARGET_REG_BITS == 32
ffc5ea09 997 case INDEX_op_brcond2_i32:
be210acb 998 case INDEX_op_setcond2_i32:
ffc5ea09
RH
999#else
1000 case INDEX_op_brcond_i64:
be210acb 1001 case INDEX_op_setcond_i64:
ffc5ea09 1002 case INDEX_op_movcond_i64:
f48f3ede 1003#endif
eeacee4d
BS
1004 if (args[k] < ARRAY_SIZE(cond_name) && cond_name[args[k]]) {
1005 qemu_log(",%s", cond_name[args[k++]]);
1006 } else {
1007 qemu_log(",$0x%" TCG_PRIlx, args[k++]);
1008 }
f48f3ede 1009 i = 1;
be210acb
RH
1010 break;
1011 default:
f48f3ede 1012 i = 0;
be210acb
RH
1013 break;
1014 }
f48f3ede 1015 for(; i < nb_cargs; i++) {
eeacee4d
BS
1016 if (k != 0) {
1017 qemu_log(",");
1018 }
b03cce8e 1019 arg = args[k++];
eeacee4d 1020 qemu_log("$0x%" TCG_PRIlx, arg);
b03cce8e 1021 }
c896fe29 1022 }
eeacee4d 1023 qemu_log("\n");
c896fe29
FB
1024 args += nb_iargs + nb_oargs + nb_cargs;
1025 }
1026}
1027
1028/* we give more priority to constraints with less registers */
1029static int get_constraint_priority(const TCGOpDef *def, int k)
1030{
1031 const TCGArgConstraint *arg_ct;
1032
1033 int i, n;
1034 arg_ct = &def->args_ct[k];
1035 if (arg_ct->ct & TCG_CT_ALIAS) {
1036 /* an alias is equivalent to a single register */
1037 n = 1;
1038 } else {
1039 if (!(arg_ct->ct & TCG_CT_REG))
1040 return 0;
1041 n = 0;
1042 for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
1043 if (tcg_regset_test_reg(arg_ct->u.regs, i))
1044 n++;
1045 }
1046 }
1047 return TCG_TARGET_NB_REGS - n + 1;
1048}
1049
1050/* sort from highest priority to lowest */
1051static void sort_constraints(TCGOpDef *def, int start, int n)
1052{
1053 int i, j, p1, p2, tmp;
1054
1055 for(i = 0; i < n; i++)
1056 def->sorted_args[start + i] = start + i;
1057 if (n <= 1)
1058 return;
1059 for(i = 0; i < n - 1; i++) {
1060 for(j = i + 1; j < n; j++) {
1061 p1 = get_constraint_priority(def, def->sorted_args[start + i]);
1062 p2 = get_constraint_priority(def, def->sorted_args[start + j]);
1063 if (p1 < p2) {
1064 tmp = def->sorted_args[start + i];
1065 def->sorted_args[start + i] = def->sorted_args[start + j];
1066 def->sorted_args[start + j] = tmp;
1067 }
1068 }
1069 }
1070}
1071
1072void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs)
1073{
a9751609 1074 TCGOpcode op;
c896fe29
FB
1075 TCGOpDef *def;
1076 const char *ct_str;
1077 int i, nb_args;
1078
1079 for(;;) {
a9751609 1080 if (tdefs->op == (TCGOpcode)-1)
c896fe29
FB
1081 break;
1082 op = tdefs->op;
c3b08d0e 1083 assert((unsigned)op < NB_OPS);
c896fe29 1084 def = &tcg_op_defs[op];
c68aaa18
SW
1085#if defined(CONFIG_DEBUG_TCG)
1086 /* Duplicate entry in op definitions? */
1087 assert(!def->used);
1088 def->used = 1;
1089#endif
c896fe29
FB
1090 nb_args = def->nb_iargs + def->nb_oargs;
1091 for(i = 0; i < nb_args; i++) {
1092 ct_str = tdefs->args_ct_str[i];
c68aaa18
SW
1093 /* Incomplete TCGTargetOpDef entry? */
1094 assert(ct_str != NULL);
c896fe29
FB
1095 tcg_regset_clear(def->args_ct[i].u.regs);
1096 def->args_ct[i].ct = 0;
1097 if (ct_str[0] >= '0' && ct_str[0] <= '9') {
1098 int oarg;
1099 oarg = ct_str[0] - '0';
1100 assert(oarg < def->nb_oargs);
1101 assert(def->args_ct[oarg].ct & TCG_CT_REG);
1102 /* TCG_CT_ALIAS is for the output arguments. The input
5ff9d6a4 1103 argument is tagged with TCG_CT_IALIAS. */
c896fe29 1104 def->args_ct[i] = def->args_ct[oarg];
5ff9d6a4
FB
1105 def->args_ct[oarg].ct = TCG_CT_ALIAS;
1106 def->args_ct[oarg].alias_index = i;
c896fe29 1107 def->args_ct[i].ct |= TCG_CT_IALIAS;
5ff9d6a4 1108 def->args_ct[i].alias_index = oarg;
c896fe29
FB
1109 } else {
1110 for(;;) {
1111 if (*ct_str == '\0')
1112 break;
1113 switch(*ct_str) {
1114 case 'i':
1115 def->args_ct[i].ct |= TCG_CT_CONST;
1116 ct_str++;
1117 break;
1118 default:
1119 if (target_parse_constraint(&def->args_ct[i], &ct_str) < 0) {
1120 fprintf(stderr, "Invalid constraint '%s' for arg %d of operation '%s'\n",
1121 ct_str, i, def->name);
1122 exit(1);
1123 }
1124 }
1125 }
1126 }
1127 }
1128
c68aaa18
SW
1129 /* TCGTargetOpDef entry with too much information? */
1130 assert(i == TCG_MAX_OP_ARGS || tdefs->args_ct_str[i] == NULL);
1131
c896fe29
FB
1132 /* sort the constraints (XXX: this is just an heuristic) */
1133 sort_constraints(def, 0, def->nb_oargs);
1134 sort_constraints(def, def->nb_oargs, def->nb_iargs);
1135
1136#if 0
1137 {
1138 int i;
1139
1140 printf("%s: sorted=", def->name);
1141 for(i = 0; i < def->nb_oargs + def->nb_iargs; i++)
1142 printf(" %d", def->sorted_args[i]);
1143 printf("\n");
1144 }
1145#endif
1146 tdefs++;
1147 }
1148
c68aaa18 1149#if defined(CONFIG_DEBUG_TCG)
a9751609 1150 i = 0;
c68aaa18 1151 for (op = 0; op < ARRAY_SIZE(tcg_op_defs); op++) {
f412c762
RH
1152 const TCGOpDef *def = &tcg_op_defs[op];
1153 if (op < INDEX_op_call
1154 || op == INDEX_op_debug_insn_start
1155 || (def->flags & TCG_OPF_NOT_PRESENT)) {
c68aaa18 1156 /* Wrong entry in op definitions? */
f412c762
RH
1157 if (def->used) {
1158 fprintf(stderr, "Invalid op definition for %s\n", def->name);
a9751609
RH
1159 i = 1;
1160 }
c68aaa18
SW
1161 } else {
1162 /* Missing entry in op definitions? */
f412c762
RH
1163 if (!def->used) {
1164 fprintf(stderr, "Missing op definition for %s\n", def->name);
a9751609
RH
1165 i = 1;
1166 }
c68aaa18
SW
1167 }
1168 }
a9751609
RH
1169 if (i == 1) {
1170 tcg_abort();
1171 }
c68aaa18 1172#endif
c896fe29
FB
1173}
1174
1175#ifdef USE_LIVENESS_ANALYSIS
1176
1177/* set a nop for an operation using 'nb_args' */
1178static inline void tcg_set_nop(TCGContext *s, uint16_t *opc_ptr,
1179 TCGArg *args, int nb_args)
1180{
1181 if (nb_args == 0) {
1182 *opc_ptr = INDEX_op_nop;
1183 } else {
1184 *opc_ptr = INDEX_op_nopn;
1185 args[0] = nb_args;
1186 args[nb_args - 1] = nb_args;
1187 }
1188}
1189
641d5fbe
FB
1190/* liveness analysis: end of function: globals are live, temps are
1191 dead. */
1192/* XXX: at this stage, not used as there would be little gains because
1193 most TBs end with a conditional jump. */
1194static inline void tcg_la_func_end(TCGContext *s, uint8_t *dead_temps)
c896fe29
FB
1195{
1196 memset(dead_temps, 0, s->nb_globals);
1197 memset(dead_temps + s->nb_globals, 1, s->nb_temps - s->nb_globals);
1198}
1199
641d5fbe
FB
1200/* liveness analysis: end of basic block: globals are live, temps are
1201 dead, local temps are live. */
1202static inline void tcg_la_bb_end(TCGContext *s, uint8_t *dead_temps)
1203{
1204 int i;
1205 TCGTemp *ts;
1206
1207 memset(dead_temps, 0, s->nb_globals);
1208 ts = &s->temps[s->nb_globals];
1209 for(i = s->nb_globals; i < s->nb_temps; i++) {
1210 if (ts->temp_local)
1211 dead_temps[i] = 0;
1212 else
1213 dead_temps[i] = 1;
1214 ts++;
1215 }
1216}
1217
866cb6cb 1218/* Liveness analysis : update the opc_dead_args array to tell if a
c896fe29
FB
1219 given input arguments is dead. Instructions updating dead
1220 temporaries are removed. */
8fcd3692 1221static void tcg_liveness_analysis(TCGContext *s)
c896fe29 1222{
a9751609
RH
1223 int i, op_index, nb_args, nb_iargs, nb_oargs, arg, nb_ops;
1224 TCGOpcode op;
c896fe29
FB
1225 TCGArg *args;
1226 const TCGOpDef *def;
1227 uint8_t *dead_temps;
866cb6cb 1228 unsigned int dead_args;
c896fe29
FB
1229
1230 gen_opc_ptr++; /* skip end */
1231
1232 nb_ops = gen_opc_ptr - gen_opc_buf;
1233
866cb6cb 1234 s->op_dead_args = tcg_malloc(nb_ops * sizeof(uint16_t));
c896fe29
FB
1235
1236 dead_temps = tcg_malloc(s->nb_temps);
1237 memset(dead_temps, 1, s->nb_temps);
1238
1239 args = gen_opparam_ptr;
1240 op_index = nb_ops - 1;
1241 while (op_index >= 0) {
1242 op = gen_opc_buf[op_index];
1243 def = &tcg_op_defs[op];
1244 switch(op) {
1245 case INDEX_op_call:
c6e113f5
FB
1246 {
1247 int call_flags;
c896fe29 1248
c6e113f5
FB
1249 nb_args = args[-1];
1250 args -= nb_args;
1251 nb_iargs = args[0] & 0xffff;
1252 nb_oargs = args[0] >> 16;
1253 args++;
1254 call_flags = args[nb_oargs + nb_iargs];
1255
1256 /* pure functions can be removed if their result is not
1257 used */
1258 if (call_flags & TCG_CALL_PURE) {
1259 for(i = 0; i < nb_oargs; i++) {
1260 arg = args[i];
1261 if (!dead_temps[arg])
1262 goto do_not_remove_call;
1263 }
1264 tcg_set_nop(s, gen_opc_buf + op_index,
1265 args - 1, nb_args);
1266 } else {
1267 do_not_remove_call:
c896fe29 1268
c6e113f5 1269 /* output args are dead */
6b64b624 1270 dead_args = 0;
c6e113f5
FB
1271 for(i = 0; i < nb_oargs; i++) {
1272 arg = args[i];
6b64b624
AJ
1273 if (dead_temps[arg]) {
1274 dead_args |= (1 << i);
1275 }
c6e113f5
FB
1276 dead_temps[arg] = 1;
1277 }
1278
b9c18f56
AJ
1279 if (!(call_flags & TCG_CALL_CONST)) {
1280 /* globals are live (they may be used by the call) */
1281 memset(dead_temps, 0, s->nb_globals);
1282 }
1283
c6e113f5 1284 /* input args are live */
866cb6cb
AJ
1285 for(i = nb_oargs; i < nb_iargs + nb_oargs; i++) {
1286 arg = args[i];
39cf05d3
FB
1287 if (arg != TCG_CALL_DUMMY_ARG) {
1288 if (dead_temps[arg]) {
866cb6cb 1289 dead_args |= (1 << i);
39cf05d3
FB
1290 }
1291 dead_temps[arg] = 0;
c6e113f5 1292 }
c6e113f5 1293 }
866cb6cb 1294 s->op_dead_args[op_index] = dead_args;
c896fe29 1295 }
c6e113f5 1296 args--;
c896fe29 1297 }
c896fe29 1298 break;
7e4597d7
FB
1299 case INDEX_op_debug_insn_start:
1300 args -= def->nb_args;
1301 break;
c896fe29
FB
1302 case INDEX_op_nopn:
1303 nb_args = args[-1];
1304 args -= nb_args;
1305 break;
5ff9d6a4
FB
1306 case INDEX_op_discard:
1307 args--;
1308 /* mark the temporary as dead */
1309 dead_temps[args[0]] = 1;
1310 break;
c896fe29
FB
1311 case INDEX_op_end:
1312 break;
1313 /* XXX: optimize by hardcoding common cases (e.g. triadic ops) */
1314 default:
49516bc0
AJ
1315 args -= def->nb_args;
1316 nb_iargs = def->nb_iargs;
1317 nb_oargs = def->nb_oargs;
c896fe29 1318
49516bc0
AJ
1319 /* Test if the operation can be removed because all
1320 its outputs are dead. We assume that nb_oargs == 0
1321 implies side effects */
1322 if (!(def->flags & TCG_OPF_SIDE_EFFECTS) && nb_oargs != 0) {
1323 for(i = 0; i < nb_oargs; i++) {
1324 arg = args[i];
1325 if (!dead_temps[arg])
1326 goto do_not_remove;
1327 }
1328 tcg_set_nop(s, gen_opc_buf + op_index, args, def->nb_args);
c896fe29 1329#ifdef CONFIG_PROFILER
49516bc0 1330 s->del_op_count++;
c896fe29 1331#endif
49516bc0
AJ
1332 } else {
1333 do_not_remove:
c896fe29 1334
49516bc0 1335 /* output args are dead */
6b64b624 1336 dead_args = 0;
49516bc0
AJ
1337 for(i = 0; i < nb_oargs; i++) {
1338 arg = args[i];
6b64b624
AJ
1339 if (dead_temps[arg]) {
1340 dead_args |= (1 << i);
1341 }
49516bc0
AJ
1342 dead_temps[arg] = 1;
1343 }
1344
1345 /* if end of basic block, update */
1346 if (def->flags & TCG_OPF_BB_END) {
1347 tcg_la_bb_end(s, dead_temps);
1348 } else if (def->flags & TCG_OPF_CALL_CLOBBER) {
1349 /* globals are live */
1350 memset(dead_temps, 0, s->nb_globals);
1351 }
1352
1353 /* input args are live */
866cb6cb
AJ
1354 for(i = nb_oargs; i < nb_oargs + nb_iargs; i++) {
1355 arg = args[i];
49516bc0 1356 if (dead_temps[arg]) {
866cb6cb 1357 dead_args |= (1 << i);
c896fe29 1358 }
49516bc0 1359 dead_temps[arg] = 0;
c896fe29 1360 }
866cb6cb 1361 s->op_dead_args[op_index] = dead_args;
c896fe29
FB
1362 }
1363 break;
1364 }
1365 op_index--;
1366 }
1367
1368 if (args != gen_opparam_buf)
1369 tcg_abort();
1370}
1371#else
1372/* dummy liveness analysis */
655feed5 1373static void tcg_liveness_analysis(TCGContext *s)
c896fe29
FB
1374{
1375 int nb_ops;
1376 nb_ops = gen_opc_ptr - gen_opc_buf;
1377
866cb6cb
AJ
1378 s->op_dead_args = tcg_malloc(nb_ops * sizeof(uint16_t));
1379 memset(s->op_dead_args, 0, nb_ops * sizeof(uint16_t));
c896fe29
FB
1380}
1381#endif
1382
1383#ifndef NDEBUG
1384static void dump_regs(TCGContext *s)
1385{
1386 TCGTemp *ts;
1387 int i;
1388 char buf[64];
1389
1390 for(i = 0; i < s->nb_temps; i++) {
1391 ts = &s->temps[i];
ac56dd48 1392 printf(" %10s: ", tcg_get_arg_str_idx(s, buf, sizeof(buf), i));
c896fe29
FB
1393 switch(ts->val_type) {
1394 case TEMP_VAL_REG:
1395 printf("%s", tcg_target_reg_names[ts->reg]);
1396 break;
1397 case TEMP_VAL_MEM:
1398 printf("%d(%s)", (int)ts->mem_offset, tcg_target_reg_names[ts->mem_reg]);
1399 break;
1400 case TEMP_VAL_CONST:
1401 printf("$0x%" TCG_PRIlx, ts->val);
1402 break;
1403 case TEMP_VAL_DEAD:
1404 printf("D");
1405 break;
1406 default:
1407 printf("???");
1408 break;
1409 }
1410 printf("\n");
1411 }
1412
1413 for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
1414 if (s->reg_to_temp[i] >= 0) {
1415 printf("%s: %s\n",
1416 tcg_target_reg_names[i],
ac56dd48 1417 tcg_get_arg_str_idx(s, buf, sizeof(buf), s->reg_to_temp[i]));
c896fe29
FB
1418 }
1419 }
1420}
1421
1422static void check_regs(TCGContext *s)
1423{
1424 int reg, k;
1425 TCGTemp *ts;
1426 char buf[64];
1427
1428 for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1429 k = s->reg_to_temp[reg];
1430 if (k >= 0) {
1431 ts = &s->temps[k];
1432 if (ts->val_type != TEMP_VAL_REG ||
1433 ts->reg != reg) {
1434 printf("Inconsistency for register %s:\n",
1435 tcg_target_reg_names[reg]);
b03cce8e 1436 goto fail;
c896fe29
FB
1437 }
1438 }
1439 }
1440 for(k = 0; k < s->nb_temps; k++) {
1441 ts = &s->temps[k];
1442 if (ts->val_type == TEMP_VAL_REG &&
1443 !ts->fixed_reg &&
1444 s->reg_to_temp[ts->reg] != k) {
1445 printf("Inconsistency for temp %s:\n",
ac56dd48 1446 tcg_get_arg_str_idx(s, buf, sizeof(buf), k));
b03cce8e 1447 fail:
c896fe29
FB
1448 printf("reg state:\n");
1449 dump_regs(s);
1450 tcg_abort();
1451 }
1452 }
1453}
1454#endif
1455
1456static void temp_allocate_frame(TCGContext *s, int temp)
1457{
1458 TCGTemp *ts;
1459 ts = &s->temps[temp];
9b9c37c3
RH
1460#if !(defined(__sparc__) && TCG_TARGET_REG_BITS == 64)
1461 /* Sparc64 stack is accessed with offset of 2047 */
b591dc59
BS
1462 s->current_frame_offset = (s->current_frame_offset +
1463 (tcg_target_long)sizeof(tcg_target_long) - 1) &
1464 ~(sizeof(tcg_target_long) - 1);
f44c9960 1465#endif
b591dc59
BS
1466 if (s->current_frame_offset + (tcg_target_long)sizeof(tcg_target_long) >
1467 s->frame_end) {
5ff9d6a4 1468 tcg_abort();
b591dc59 1469 }
c896fe29
FB
1470 ts->mem_offset = s->current_frame_offset;
1471 ts->mem_reg = s->frame_reg;
1472 ts->mem_allocated = 1;
b591dc59 1473 s->current_frame_offset += (tcg_target_long)sizeof(tcg_target_long);
c896fe29
FB
1474}
1475
1476/* free register 'reg' by spilling the corresponding temporary if necessary */
1477static void tcg_reg_free(TCGContext *s, int reg)
1478{
1479 TCGTemp *ts;
1480 int temp;
1481
1482 temp = s->reg_to_temp[reg];
1483 if (temp != -1) {
1484 ts = &s->temps[temp];
1485 assert(ts->val_type == TEMP_VAL_REG);
1486 if (!ts->mem_coherent) {
1487 if (!ts->mem_allocated)
1488 temp_allocate_frame(s, temp);
e4d5434c 1489 tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
c896fe29
FB
1490 }
1491 ts->val_type = TEMP_VAL_MEM;
1492 s->reg_to_temp[reg] = -1;
1493 }
1494}
1495
1496/* Allocate a register belonging to reg1 & ~reg2 */
1497static int tcg_reg_alloc(TCGContext *s, TCGRegSet reg1, TCGRegSet reg2)
1498{
1499 int i, reg;
1500 TCGRegSet reg_ct;
1501
1502 tcg_regset_andnot(reg_ct, reg1, reg2);
1503
1504 /* first try free registers */
0954d0d9 1505 for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
c896fe29
FB
1506 reg = tcg_target_reg_alloc_order[i];
1507 if (tcg_regset_test_reg(reg_ct, reg) && s->reg_to_temp[reg] == -1)
1508 return reg;
1509 }
1510
1511 /* XXX: do better spill choice */
0954d0d9 1512 for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
c896fe29
FB
1513 reg = tcg_target_reg_alloc_order[i];
1514 if (tcg_regset_test_reg(reg_ct, reg)) {
1515 tcg_reg_free(s, reg);
1516 return reg;
1517 }
1518 }
1519
1520 tcg_abort();
1521}
1522
641d5fbe
FB
1523/* save a temporary to memory. 'allocated_regs' is used in case a
1524 temporary registers needs to be allocated to store a constant. */
1525static void temp_save(TCGContext *s, int temp, TCGRegSet allocated_regs)
1526{
1527 TCGTemp *ts;
1528 int reg;
1529
1530 ts = &s->temps[temp];
1531 if (!ts->fixed_reg) {
1532 switch(ts->val_type) {
1533 case TEMP_VAL_REG:
1534 tcg_reg_free(s, ts->reg);
1535 break;
1536 case TEMP_VAL_DEAD:
1537 ts->val_type = TEMP_VAL_MEM;
1538 break;
1539 case TEMP_VAL_CONST:
d6859202
AJ
1540 reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type],
1541 allocated_regs);
641d5fbe
FB
1542 if (!ts->mem_allocated)
1543 temp_allocate_frame(s, temp);
d6859202
AJ
1544 tcg_out_movi(s, ts->type, reg, ts->val);
1545 tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
641d5fbe
FB
1546 ts->val_type = TEMP_VAL_MEM;
1547 break;
1548 case TEMP_VAL_MEM:
1549 break;
1550 default:
1551 tcg_abort();
1552 }
1553 }
1554}
1555
9814dd27 1556/* save globals to their canonical location and assume they can be
e8996ee0
FB
1557 modified be the following code. 'allocated_regs' is used in case a
1558 temporary registers needs to be allocated to store a constant. */
1559static void save_globals(TCGContext *s, TCGRegSet allocated_regs)
c896fe29 1560{
641d5fbe 1561 int i;
c896fe29
FB
1562
1563 for(i = 0; i < s->nb_globals; i++) {
641d5fbe 1564 temp_save(s, i, allocated_regs);
c896fe29 1565 }
e5097dc8
FB
1566}
1567
1568/* at the end of a basic block, we assume all temporaries are dead and
e8996ee0
FB
1569 all globals are stored at their canonical location. */
1570static void tcg_reg_alloc_bb_end(TCGContext *s, TCGRegSet allocated_regs)
e5097dc8
FB
1571{
1572 TCGTemp *ts;
1573 int i;
1574
c896fe29
FB
1575 for(i = s->nb_globals; i < s->nb_temps; i++) {
1576 ts = &s->temps[i];
641d5fbe
FB
1577 if (ts->temp_local) {
1578 temp_save(s, i, allocated_regs);
1579 } else {
1580 if (ts->val_type == TEMP_VAL_REG) {
1581 s->reg_to_temp[ts->reg] = -1;
1582 }
1583 ts->val_type = TEMP_VAL_DEAD;
c896fe29
FB
1584 }
1585 }
e8996ee0
FB
1586
1587 save_globals(s, allocated_regs);
c896fe29
FB
1588}
1589
866cb6cb 1590#define IS_DEAD_ARG(n) ((dead_args >> (n)) & 1)
c896fe29 1591
e8996ee0
FB
1592static void tcg_reg_alloc_movi(TCGContext *s, const TCGArg *args)
1593{
1594 TCGTemp *ots;
1595 tcg_target_ulong val;
1596
1597 ots = &s->temps[args[0]];
1598 val = args[1];
1599
1600 if (ots->fixed_reg) {
1601 /* for fixed registers, we do not do any constant
1602 propagation */
1603 tcg_out_movi(s, ots->type, ots->reg, val);
1604 } else {
1235fc06 1605 /* The movi is not explicitly generated here */
e8996ee0
FB
1606 if (ots->val_type == TEMP_VAL_REG)
1607 s->reg_to_temp[ots->reg] = -1;
1608 ots->val_type = TEMP_VAL_CONST;
1609 ots->val = val;
1610 }
1611}
1612
c896fe29
FB
1613static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
1614 const TCGArg *args,
866cb6cb 1615 unsigned int dead_args)
c896fe29
FB
1616{
1617 TCGTemp *ts, *ots;
1618 int reg;
1619 const TCGArgConstraint *arg_ct;
1620
1621 ots = &s->temps[args[0]];
1622 ts = &s->temps[args[1]];
1623 arg_ct = &def->args_ct[0];
1624
866cb6cb 1625 /* XXX: always mark arg dead if IS_DEAD_ARG(1) */
c896fe29 1626 if (ts->val_type == TEMP_VAL_REG) {
866cb6cb 1627 if (IS_DEAD_ARG(1) && !ts->fixed_reg && !ots->fixed_reg) {
c896fe29
FB
1628 /* the mov can be suppressed */
1629 if (ots->val_type == TEMP_VAL_REG)
1630 s->reg_to_temp[ots->reg] = -1;
1631 reg = ts->reg;
1632 s->reg_to_temp[reg] = -1;
1633 ts->val_type = TEMP_VAL_DEAD;
1634 } else {
1635 if (ots->val_type == TEMP_VAL_REG) {
1636 reg = ots->reg;
1637 } else {
1638 reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1639 }
1640 if (ts->reg != reg) {
3b6dac34 1641 tcg_out_mov(s, ots->type, reg, ts->reg);
c896fe29
FB
1642 }
1643 }
1644 } else if (ts->val_type == TEMP_VAL_MEM) {
1645 if (ots->val_type == TEMP_VAL_REG) {
1646 reg = ots->reg;
1647 } else {
1648 reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1649 }
e4d5434c 1650 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
c896fe29 1651 } else if (ts->val_type == TEMP_VAL_CONST) {
e8996ee0 1652 if (ots->fixed_reg) {
c896fe29 1653 reg = ots->reg;
e8996ee0 1654 tcg_out_movi(s, ots->type, reg, ts->val);
c896fe29 1655 } else {
e8996ee0
FB
1656 /* propagate constant */
1657 if (ots->val_type == TEMP_VAL_REG)
1658 s->reg_to_temp[ots->reg] = -1;
1659 ots->val_type = TEMP_VAL_CONST;
1660 ots->val = ts->val;
1661 return;
c896fe29 1662 }
c896fe29
FB
1663 } else {
1664 tcg_abort();
1665 }
1666 s->reg_to_temp[reg] = args[0];
1667 ots->reg = reg;
1668 ots->val_type = TEMP_VAL_REG;
1669 ots->mem_coherent = 0;
1670}
1671
1672static void tcg_reg_alloc_op(TCGContext *s,
a9751609 1673 const TCGOpDef *def, TCGOpcode opc,
c896fe29 1674 const TCGArg *args,
866cb6cb 1675 unsigned int dead_args)
c896fe29
FB
1676{
1677 TCGRegSet allocated_regs;
1678 int i, k, nb_iargs, nb_oargs, reg;
1679 TCGArg arg;
1680 const TCGArgConstraint *arg_ct;
1681 TCGTemp *ts;
1682 TCGArg new_args[TCG_MAX_OP_ARGS];
1683 int const_args[TCG_MAX_OP_ARGS];
1684
1685 nb_oargs = def->nb_oargs;
1686 nb_iargs = def->nb_iargs;
1687
1688 /* copy constants */
1689 memcpy(new_args + nb_oargs + nb_iargs,
1690 args + nb_oargs + nb_iargs,
1691 sizeof(TCGArg) * def->nb_cargs);
1692
1693 /* satisfy input constraints */
1694 tcg_regset_set(allocated_regs, s->reserved_regs);
1695 for(k = 0; k < nb_iargs; k++) {
1696 i = def->sorted_args[nb_oargs + k];
1697 arg = args[i];
1698 arg_ct = &def->args_ct[i];
1699 ts = &s->temps[arg];
1700 if (ts->val_type == TEMP_VAL_MEM) {
1701 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
e4d5434c 1702 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
c896fe29
FB
1703 ts->val_type = TEMP_VAL_REG;
1704 ts->reg = reg;
1705 ts->mem_coherent = 1;
1706 s->reg_to_temp[reg] = arg;
1707 } else if (ts->val_type == TEMP_VAL_CONST) {
1708 if (tcg_target_const_match(ts->val, arg_ct)) {
1709 /* constant is OK for instruction */
1710 const_args[i] = 1;
1711 new_args[i] = ts->val;
1712 goto iarg_end;
1713 } else {
e8996ee0 1714 /* need to move to a register */
c896fe29
FB
1715 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1716 tcg_out_movi(s, ts->type, reg, ts->val);
e8996ee0
FB
1717 ts->val_type = TEMP_VAL_REG;
1718 ts->reg = reg;
1719 ts->mem_coherent = 0;
1720 s->reg_to_temp[reg] = arg;
c896fe29
FB
1721 }
1722 }
1723 assert(ts->val_type == TEMP_VAL_REG);
5ff9d6a4
FB
1724 if (arg_ct->ct & TCG_CT_IALIAS) {
1725 if (ts->fixed_reg) {
1726 /* if fixed register, we must allocate a new register
1727 if the alias is not the same register */
1728 if (arg != args[arg_ct->alias_index])
1729 goto allocate_in_reg;
1730 } else {
1731 /* if the input is aliased to an output and if it is
1732 not dead after the instruction, we must allocate
1733 a new register and move it */
866cb6cb 1734 if (!IS_DEAD_ARG(i)) {
5ff9d6a4 1735 goto allocate_in_reg;
866cb6cb 1736 }
5ff9d6a4 1737 }
c896fe29
FB
1738 }
1739 reg = ts->reg;
1740 if (tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1741 /* nothing to do : the constraint is satisfied */
1742 } else {
1743 allocate_in_reg:
1744 /* allocate a new register matching the constraint
1745 and move the temporary register into it */
1746 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
3b6dac34 1747 tcg_out_mov(s, ts->type, reg, ts->reg);
c896fe29 1748 }
c896fe29
FB
1749 new_args[i] = reg;
1750 const_args[i] = 0;
1751 tcg_regset_set_reg(allocated_regs, reg);
1752 iarg_end: ;
1753 }
1754
e8996ee0
FB
1755 if (def->flags & TCG_OPF_BB_END) {
1756 tcg_reg_alloc_bb_end(s, allocated_regs);
1757 } else {
1758 /* mark dead temporaries and free the associated registers */
866cb6cb
AJ
1759 for(i = nb_oargs; i < nb_oargs + nb_iargs; i++) {
1760 arg = args[i];
1761 if (IS_DEAD_ARG(i)) {
e8996ee0
FB
1762 ts = &s->temps[arg];
1763 if (!ts->fixed_reg) {
1764 if (ts->val_type == TEMP_VAL_REG)
1765 s->reg_to_temp[ts->reg] = -1;
1766 ts->val_type = TEMP_VAL_DEAD;
1767 }
c896fe29
FB
1768 }
1769 }
e8996ee0
FB
1770
1771 if (def->flags & TCG_OPF_CALL_CLOBBER) {
1772 /* XXX: permit generic clobber register list ? */
1773 for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1774 if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
1775 tcg_reg_free(s, reg);
1776 }
c896fe29 1777 }
e8996ee0
FB
1778 /* XXX: for load/store we could do that only for the slow path
1779 (i.e. when a memory callback is called) */
1780
1781 /* store globals and free associated registers (we assume the insn
1782 can modify any global. */
1783 save_globals(s, allocated_regs);
c896fe29 1784 }
e8996ee0
FB
1785
1786 /* satisfy the output constraints */
1787 tcg_regset_set(allocated_regs, s->reserved_regs);
1788 for(k = 0; k < nb_oargs; k++) {
1789 i = def->sorted_args[k];
1790 arg = args[i];
1791 arg_ct = &def->args_ct[i];
1792 ts = &s->temps[arg];
1793 if (arg_ct->ct & TCG_CT_ALIAS) {
1794 reg = new_args[arg_ct->alias_index];
1795 } else {
1796 /* if fixed register, we try to use it */
1797 reg = ts->reg;
1798 if (ts->fixed_reg &&
1799 tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1800 goto oarg_end;
1801 }
1802 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
c896fe29 1803 }
e8996ee0
FB
1804 tcg_regset_set_reg(allocated_regs, reg);
1805 /* if a fixed register is used, then a move will be done afterwards */
1806 if (!ts->fixed_reg) {
1807 if (ts->val_type == TEMP_VAL_REG)
1808 s->reg_to_temp[ts->reg] = -1;
8c11ad25
AJ
1809 if (IS_DEAD_ARG(i)) {
1810 ts->val_type = TEMP_VAL_DEAD;
1811 } else {
1812 ts->val_type = TEMP_VAL_REG;
1813 ts->reg = reg;
1814 /* temp value is modified, so the value kept in memory is
1815 potentially not the same */
1816 ts->mem_coherent = 0;
1817 s->reg_to_temp[reg] = arg;
1818 }
e8996ee0
FB
1819 }
1820 oarg_end:
1821 new_args[i] = reg;
c896fe29 1822 }
c896fe29
FB
1823 }
1824
c896fe29
FB
1825 /* emit instruction */
1826 tcg_out_op(s, opc, new_args, const_args);
1827
1828 /* move the outputs in the correct register if needed */
1829 for(i = 0; i < nb_oargs; i++) {
1830 ts = &s->temps[args[i]];
1831 reg = new_args[i];
1832 if (ts->fixed_reg && ts->reg != reg) {
3b6dac34 1833 tcg_out_mov(s, ts->type, ts->reg, reg);
c896fe29
FB
1834 }
1835 }
1836}
1837
b03cce8e
FB
1838#ifdef TCG_TARGET_STACK_GROWSUP
1839#define STACK_DIR(x) (-(x))
1840#else
1841#define STACK_DIR(x) (x)
1842#endif
1843
c896fe29 1844static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
a9751609 1845 TCGOpcode opc, const TCGArg *args,
866cb6cb 1846 unsigned int dead_args)
c896fe29
FB
1847{
1848 int nb_iargs, nb_oargs, flags, nb_regs, i, reg, nb_params;
1849 TCGArg arg, func_arg;
1850 TCGTemp *ts;
f54b3f92 1851 tcg_target_long stack_offset, call_stack_size, func_addr;
b03cce8e 1852 int const_func_arg, allocate_args;
c896fe29
FB
1853 TCGRegSet allocated_regs;
1854 const TCGArgConstraint *arg_ct;
1855
1856 arg = *args++;
1857
1858 nb_oargs = arg >> 16;
1859 nb_iargs = arg & 0xffff;
1860 nb_params = nb_iargs - 1;
1861
1862 flags = args[nb_oargs + nb_iargs];
1863
1864 nb_regs = tcg_target_get_call_iarg_regs_count(flags);
1865 if (nb_regs > nb_params)
1866 nb_regs = nb_params;
1867
1868 /* assign stack slots first */
c896fe29
FB
1869 call_stack_size = (nb_params - nb_regs) * sizeof(tcg_target_long);
1870 call_stack_size = (call_stack_size + TCG_TARGET_STACK_ALIGN - 1) &
1871 ~(TCG_TARGET_STACK_ALIGN - 1);
b03cce8e
FB
1872 allocate_args = (call_stack_size > TCG_STATIC_CALL_ARGS_SIZE);
1873 if (allocate_args) {
345649c0
BS
1874 /* XXX: if more than TCG_STATIC_CALL_ARGS_SIZE is needed,
1875 preallocate call stack */
1876 tcg_abort();
b03cce8e 1877 }
39cf05d3
FB
1878
1879 stack_offset = TCG_TARGET_CALL_STACK_OFFSET;
c896fe29
FB
1880 for(i = nb_regs; i < nb_params; i++) {
1881 arg = args[nb_oargs + i];
39cf05d3
FB
1882#ifdef TCG_TARGET_STACK_GROWSUP
1883 stack_offset -= sizeof(tcg_target_long);
1884#endif
1885 if (arg != TCG_CALL_DUMMY_ARG) {
1886 ts = &s->temps[arg];
1887 if (ts->val_type == TEMP_VAL_REG) {
1888 tcg_out_st(s, ts->type, ts->reg, TCG_REG_CALL_STACK, stack_offset);
1889 } else if (ts->val_type == TEMP_VAL_MEM) {
1890 reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type],
1891 s->reserved_regs);
1892 /* XXX: not correct if reading values from the stack */
1893 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1894 tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
1895 } else if (ts->val_type == TEMP_VAL_CONST) {
1896 reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type],
1897 s->reserved_regs);
1898 /* XXX: sign extend may be needed on some targets */
1899 tcg_out_movi(s, ts->type, reg, ts->val);
1900 tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
1901 } else {
1902 tcg_abort();
1903 }
c896fe29 1904 }
39cf05d3
FB
1905#ifndef TCG_TARGET_STACK_GROWSUP
1906 stack_offset += sizeof(tcg_target_long);
1907#endif
c896fe29
FB
1908 }
1909
1910 /* assign input registers */
1911 tcg_regset_set(allocated_regs, s->reserved_regs);
1912 for(i = 0; i < nb_regs; i++) {
1913 arg = args[nb_oargs + i];
39cf05d3
FB
1914 if (arg != TCG_CALL_DUMMY_ARG) {
1915 ts = &s->temps[arg];
1916 reg = tcg_target_call_iarg_regs[i];
1917 tcg_reg_free(s, reg);
1918 if (ts->val_type == TEMP_VAL_REG) {
1919 if (ts->reg != reg) {
3b6dac34 1920 tcg_out_mov(s, ts->type, reg, ts->reg);
39cf05d3
FB
1921 }
1922 } else if (ts->val_type == TEMP_VAL_MEM) {
1923 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1924 } else if (ts->val_type == TEMP_VAL_CONST) {
1925 /* XXX: sign extend ? */
1926 tcg_out_movi(s, ts->type, reg, ts->val);
1927 } else {
1928 tcg_abort();
c896fe29 1929 }
39cf05d3 1930 tcg_regset_set_reg(allocated_regs, reg);
c896fe29 1931 }
c896fe29
FB
1932 }
1933
1934 /* assign function address */
1935 func_arg = args[nb_oargs + nb_iargs - 1];
1936 arg_ct = &def->args_ct[0];
1937 ts = &s->temps[func_arg];
f54b3f92 1938 func_addr = ts->val;
c896fe29
FB
1939 const_func_arg = 0;
1940 if (ts->val_type == TEMP_VAL_MEM) {
1941 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
e4d5434c 1942 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
c896fe29 1943 func_arg = reg;
e8996ee0 1944 tcg_regset_set_reg(allocated_regs, reg);
c896fe29
FB
1945 } else if (ts->val_type == TEMP_VAL_REG) {
1946 reg = ts->reg;
1947 if (!tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1948 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
3b6dac34 1949 tcg_out_mov(s, ts->type, reg, ts->reg);
c896fe29
FB
1950 }
1951 func_arg = reg;
e8996ee0 1952 tcg_regset_set_reg(allocated_regs, reg);
c896fe29 1953 } else if (ts->val_type == TEMP_VAL_CONST) {
f54b3f92 1954 if (tcg_target_const_match(func_addr, arg_ct)) {
c896fe29 1955 const_func_arg = 1;
f54b3f92 1956 func_arg = func_addr;
c896fe29
FB
1957 } else {
1958 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
f54b3f92 1959 tcg_out_movi(s, ts->type, reg, func_addr);
c896fe29 1960 func_arg = reg;
e8996ee0 1961 tcg_regset_set_reg(allocated_regs, reg);
c896fe29
FB
1962 }
1963 } else {
1964 tcg_abort();
1965 }
e8996ee0 1966
c896fe29
FB
1967
1968 /* mark dead temporaries and free the associated registers */
866cb6cb
AJ
1969 for(i = nb_oargs; i < nb_iargs + nb_oargs; i++) {
1970 arg = args[i];
1971 if (IS_DEAD_ARG(i)) {
c896fe29 1972 ts = &s->temps[arg];
e8996ee0 1973 if (!ts->fixed_reg) {
c896fe29
FB
1974 if (ts->val_type == TEMP_VAL_REG)
1975 s->reg_to_temp[ts->reg] = -1;
1976 ts->val_type = TEMP_VAL_DEAD;
1977 }
1978 }
1979 }
1980
1981 /* clobber call registers */
1982 for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1983 if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
1984 tcg_reg_free(s, reg);
1985 }
1986 }
1987
1988 /* store globals and free associated registers (we assume the call
1989 can modify any global. */
b9c18f56
AJ
1990 if (!(flags & TCG_CALL_CONST)) {
1991 save_globals(s, allocated_regs);
1992 }
c896fe29
FB
1993
1994 tcg_out_op(s, opc, &func_arg, &const_func_arg);
c896fe29
FB
1995
1996 /* assign output registers and emit moves if needed */
1997 for(i = 0; i < nb_oargs; i++) {
1998 arg = args[i];
1999 ts = &s->temps[arg];
2000 reg = tcg_target_call_oarg_regs[i];
e8996ee0 2001 assert(s->reg_to_temp[reg] == -1);
c896fe29
FB
2002 if (ts->fixed_reg) {
2003 if (ts->reg != reg) {
3b6dac34 2004 tcg_out_mov(s, ts->type, ts->reg, reg);
c896fe29
FB
2005 }
2006 } else {
2007 if (ts->val_type == TEMP_VAL_REG)
2008 s->reg_to_temp[ts->reg] = -1;
8c11ad25
AJ
2009 if (IS_DEAD_ARG(i)) {
2010 ts->val_type = TEMP_VAL_DEAD;
2011 } else {
2012 ts->val_type = TEMP_VAL_REG;
2013 ts->reg = reg;
2014 ts->mem_coherent = 0;
2015 s->reg_to_temp[reg] = arg;
2016 }
c896fe29
FB
2017 }
2018 }
2019
2020 return nb_iargs + nb_oargs + def->nb_cargs + 1;
2021}
2022
2023#ifdef CONFIG_PROFILER
2024
54604f74 2025static int64_t tcg_table_op_count[NB_OPS];
c896fe29 2026
871e6c35 2027static void dump_op_count(void)
c896fe29
FB
2028{
2029 int i;
2030 FILE *f;
54604f74 2031 f = fopen("/tmp/op.log", "w");
c896fe29 2032 for(i = INDEX_op_end; i < NB_OPS; i++) {
54604f74 2033 fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name, tcg_table_op_count[i]);
c896fe29
FB
2034 }
2035 fclose(f);
2036}
2037#endif
2038
2039
2040static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
2ba1eeb6 2041 long search_pc)
c896fe29 2042{
a9751609
RH
2043 TCGOpcode opc;
2044 int op_index;
c896fe29 2045 const TCGOpDef *def;
866cb6cb 2046 unsigned int dead_args;
c896fe29
FB
2047 const TCGArg *args;
2048
2049#ifdef DEBUG_DISAS
8fec2b8c 2050 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
93fcfe39 2051 qemu_log("OP:\n");
eeacee4d 2052 tcg_dump_ops(s);
93fcfe39 2053 qemu_log("\n");
c896fe29
FB
2054 }
2055#endif
2056
c5cc28ff
AJ
2057#ifdef CONFIG_PROFILER
2058 s->opt_time -= profile_getclock();
2059#endif
2060
8f2e8c07
KB
2061#ifdef USE_TCG_OPTIMIZATIONS
2062 gen_opparam_ptr =
2063 tcg_optimize(s, gen_opc_ptr, gen_opparam_buf, tcg_op_defs);
2064#endif
2065
a23a9ec6 2066#ifdef CONFIG_PROFILER
c5cc28ff 2067 s->opt_time += profile_getclock();
a23a9ec6
FB
2068 s->la_time -= profile_getclock();
2069#endif
c5cc28ff 2070
c896fe29 2071 tcg_liveness_analysis(s);
c5cc28ff 2072
a23a9ec6
FB
2073#ifdef CONFIG_PROFILER
2074 s->la_time += profile_getclock();
2075#endif
c896fe29
FB
2076
2077#ifdef DEBUG_DISAS
8fec2b8c 2078 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_OPT))) {
c5cc28ff 2079 qemu_log("OP after optimization and liveness analysis:\n");
eeacee4d 2080 tcg_dump_ops(s);
93fcfe39 2081 qemu_log("\n");
c896fe29
FB
2082 }
2083#endif
2084
2085 tcg_reg_alloc_start(s);
2086
2087 s->code_buf = gen_code_buf;
2088 s->code_ptr = gen_code_buf;
2089
c896fe29
FB
2090 args = gen_opparam_buf;
2091 op_index = 0;
b3db8758 2092
c896fe29
FB
2093 for(;;) {
2094 opc = gen_opc_buf[op_index];
2095#ifdef CONFIG_PROFILER
54604f74 2096 tcg_table_op_count[opc]++;
c896fe29
FB
2097#endif
2098 def = &tcg_op_defs[opc];
2099#if 0
2100 printf("%s: %d %d %d\n", def->name,
2101 def->nb_oargs, def->nb_iargs, def->nb_cargs);
2102 // dump_regs(s);
2103#endif
2104 switch(opc) {
2105 case INDEX_op_mov_i32:
2106#if TCG_TARGET_REG_BITS == 64
2107 case INDEX_op_mov_i64:
2108#endif
866cb6cb
AJ
2109 dead_args = s->op_dead_args[op_index];
2110 tcg_reg_alloc_mov(s, def, args, dead_args);
c896fe29 2111 break;
e8996ee0
FB
2112 case INDEX_op_movi_i32:
2113#if TCG_TARGET_REG_BITS == 64
2114 case INDEX_op_movi_i64:
2115#endif
2116 tcg_reg_alloc_movi(s, args);
2117 break;
7e4597d7
FB
2118 case INDEX_op_debug_insn_start:
2119 /* debug instruction */
2120 break;
c896fe29
FB
2121 case INDEX_op_nop:
2122 case INDEX_op_nop1:
2123 case INDEX_op_nop2:
2124 case INDEX_op_nop3:
2125 break;
2126 case INDEX_op_nopn:
2127 args += args[0];
2128 goto next;
5ff9d6a4
FB
2129 case INDEX_op_discard:
2130 {
2131 TCGTemp *ts;
2132 ts = &s->temps[args[0]];
2133 /* mark the temporary as dead */
e8996ee0 2134 if (!ts->fixed_reg) {
5ff9d6a4
FB
2135 if (ts->val_type == TEMP_VAL_REG)
2136 s->reg_to_temp[ts->reg] = -1;
2137 ts->val_type = TEMP_VAL_DEAD;
2138 }
2139 }
2140 break;
c896fe29 2141 case INDEX_op_set_label:
e8996ee0 2142 tcg_reg_alloc_bb_end(s, s->reserved_regs);
9d6fca70 2143 tcg_out_label(s, args[0], s->code_ptr);
c896fe29
FB
2144 break;
2145 case INDEX_op_call:
866cb6cb
AJ
2146 dead_args = s->op_dead_args[op_index];
2147 args += tcg_reg_alloc_call(s, def, opc, args, dead_args);
c896fe29
FB
2148 goto next;
2149 case INDEX_op_end:
2150 goto the_end;
c896fe29 2151 default:
25c4d9cc
RH
2152 /* Sanity check that we've not introduced any unhandled opcodes. */
2153 if (def->flags & TCG_OPF_NOT_PRESENT) {
2154 tcg_abort();
2155 }
c896fe29
FB
2156 /* Note: in order to speed up the code, it would be much
2157 faster to have specialized register allocator functions for
2158 some common argument patterns */
866cb6cb
AJ
2159 dead_args = s->op_dead_args[op_index];
2160 tcg_reg_alloc_op(s, def, opc, args, dead_args);
c896fe29
FB
2161 break;
2162 }
2163 args += def->nb_args;
8df1ca4b 2164 next:
2ba1eeb6 2165 if (search_pc >= 0 && search_pc < s->code_ptr - gen_code_buf) {
b314f270 2166 return op_index;
c896fe29
FB
2167 }
2168 op_index++;
2169#ifndef NDEBUG
2170 check_regs(s);
2171#endif
2172 }
2173 the_end:
2174 return -1;
2175}
2176
54604f74 2177int tcg_gen_code(TCGContext *s, uint8_t *gen_code_buf)
c896fe29
FB
2178{
2179#ifdef CONFIG_PROFILER
2180 {
c896fe29
FB
2181 int n;
2182 n = (gen_opc_ptr - gen_opc_buf);
a23a9ec6
FB
2183 s->op_count += n;
2184 if (n > s->op_count_max)
2185 s->op_count_max = n;
2186
2187 s->temp_count += s->nb_temps;
2188 if (s->nb_temps > s->temp_count_max)
2189 s->temp_count_max = s->nb_temps;
c896fe29
FB
2190 }
2191#endif
2192
2ba1eeb6 2193 tcg_gen_code_common(s, gen_code_buf, -1);
c896fe29
FB
2194
2195 /* flush instruction cache */
2aeabc08
SW
2196 flush_icache_range((tcg_target_ulong)gen_code_buf,
2197 (tcg_target_ulong)s->code_ptr);
2198
c896fe29
FB
2199 return s->code_ptr - gen_code_buf;
2200}
2201
2ba1eeb6 2202/* Return the index of the micro operation such as the pc after is <
623e265c
PB
2203 offset bytes from the start of the TB. The contents of gen_code_buf must
2204 not be changed, though writing the same values is ok.
2205 Return -1 if not found. */
54604f74 2206int tcg_gen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, long offset)
c896fe29 2207{
623e265c 2208 return tcg_gen_code_common(s, gen_code_buf, offset);
c896fe29 2209}
a23a9ec6
FB
2210
2211#ifdef CONFIG_PROFILER
405cf9ff 2212void tcg_dump_info(FILE *f, fprintf_function cpu_fprintf)
a23a9ec6
FB
2213{
2214 TCGContext *s = &tcg_ctx;
2215 int64_t tot;
2216
2217 tot = s->interm_time + s->code_time;
2218 cpu_fprintf(f, "JIT cycles %" PRId64 " (%0.3f s at 2.4 GHz)\n",
2219 tot, tot / 2.4e9);
2220 cpu_fprintf(f, "translated TBs %" PRId64 " (aborted=%" PRId64 " %0.1f%%)\n",
2221 s->tb_count,
2222 s->tb_count1 - s->tb_count,
2223 s->tb_count1 ? (double)(s->tb_count1 - s->tb_count) / s->tb_count1 * 100.0 : 0);
2224 cpu_fprintf(f, "avg ops/TB %0.1f max=%d\n",
2225 s->tb_count ? (double)s->op_count / s->tb_count : 0, s->op_count_max);
a23a9ec6
FB
2226 cpu_fprintf(f, "deleted ops/TB %0.2f\n",
2227 s->tb_count ?
2228 (double)s->del_op_count / s->tb_count : 0);
2229 cpu_fprintf(f, "avg temps/TB %0.2f max=%d\n",
2230 s->tb_count ?
2231 (double)s->temp_count / s->tb_count : 0,
2232 s->temp_count_max);
2233
2234 cpu_fprintf(f, "cycles/op %0.1f\n",
2235 s->op_count ? (double)tot / s->op_count : 0);
2236 cpu_fprintf(f, "cycles/in byte %0.1f\n",
2237 s->code_in_len ? (double)tot / s->code_in_len : 0);
2238 cpu_fprintf(f, "cycles/out byte %0.1f\n",
2239 s->code_out_len ? (double)tot / s->code_out_len : 0);
2240 if (tot == 0)
2241 tot = 1;
2242 cpu_fprintf(f, " gen_interm time %0.1f%%\n",
2243 (double)s->interm_time / tot * 100.0);
2244 cpu_fprintf(f, " gen_code time %0.1f%%\n",
2245 (double)s->code_time / tot * 100.0);
c5cc28ff
AJ
2246 cpu_fprintf(f, "optim./code time %0.1f%%\n",
2247 (double)s->opt_time / (s->code_time ? s->code_time : 1)
2248 * 100.0);
a23a9ec6
FB
2249 cpu_fprintf(f, "liveness/code time %0.1f%%\n",
2250 (double)s->la_time / (s->code_time ? s->code_time : 1) * 100.0);
2251 cpu_fprintf(f, "cpu_restore count %" PRId64 "\n",
2252 s->restore_count);
2253 cpu_fprintf(f, " avg cycles %0.1f\n",
2254 s->restore_count ? (double)s->restore_time / s->restore_count : 0);
871e6c35
BS
2255
2256 dump_op_count();
a23a9ec6
FB
2257}
2258#else
405cf9ff 2259void tcg_dump_info(FILE *f, fprintf_function cpu_fprintf)
a23a9ec6 2260{
24bf7b3a 2261 cpu_fprintf(f, "[TCG profiler not compiled]\n");
a23a9ec6
FB
2262}
2263#endif
813da627
RH
2264
2265#ifdef ELF_HOST_MACHINE
5872bbf2
RH
2266/* In order to use this feature, the backend needs to do three things:
2267
2268 (1) Define ELF_HOST_MACHINE to indicate both what value to
2269 put into the ELF image and to indicate support for the feature.
2270
2271 (2) Define tcg_register_jit. This should create a buffer containing
2272 the contents of a .debug_frame section that describes the post-
2273 prologue unwind info for the tcg machine.
2274
2275 (3) Call tcg_register_jit_int, with the constructed .debug_frame.
2276*/
813da627
RH
2277
2278/* Begin GDB interface. THE FOLLOWING MUST MATCH GDB DOCS. */
2279typedef enum {
2280 JIT_NOACTION = 0,
2281 JIT_REGISTER_FN,
2282 JIT_UNREGISTER_FN
2283} jit_actions_t;
2284
2285struct jit_code_entry {
2286 struct jit_code_entry *next_entry;
2287 struct jit_code_entry *prev_entry;
2288 const void *symfile_addr;
2289 uint64_t symfile_size;
2290};
2291
2292struct jit_descriptor {
2293 uint32_t version;
2294 uint32_t action_flag;
2295 struct jit_code_entry *relevant_entry;
2296 struct jit_code_entry *first_entry;
2297};
2298
2299void __jit_debug_register_code(void) __attribute__((noinline));
2300void __jit_debug_register_code(void)
2301{
2302 asm("");
2303}
2304
2305/* Must statically initialize the version, because GDB may check
2306 the version before we can set it. */
2307struct jit_descriptor __jit_debug_descriptor = { 1, 0, 0, 0 };
2308
2309/* End GDB interface. */
2310
2311static int find_string(const char *strtab, const char *str)
2312{
2313 const char *p = strtab + 1;
2314
2315 while (1) {
2316 if (strcmp(p, str) == 0) {
2317 return p - strtab;
2318 }
2319 p += strlen(p) + 1;
2320 }
2321}
2322
5872bbf2 2323static void tcg_register_jit_int(void *buf_ptr, size_t buf_size,
813da627
RH
2324 void *debug_frame, size_t debug_frame_size)
2325{
5872bbf2
RH
2326 struct __attribute__((packed)) DebugInfo {
2327 uint32_t len;
2328 uint16_t version;
2329 uint32_t abbrev;
2330 uint8_t ptr_size;
2331 uint8_t cu_die;
2332 uint16_t cu_lang;
2333 uintptr_t cu_low_pc;
2334 uintptr_t cu_high_pc;
2335 uint8_t fn_die;
2336 char fn_name[16];
2337 uintptr_t fn_low_pc;
2338 uintptr_t fn_high_pc;
2339 uint8_t cu_eoc;
2340 };
813da627
RH
2341
2342 struct ElfImage {
2343 ElfW(Ehdr) ehdr;
2344 ElfW(Phdr) phdr;
5872bbf2
RH
2345 ElfW(Shdr) shdr[7];
2346 ElfW(Sym) sym[2];
2347 struct DebugInfo di;
2348 uint8_t da[24];
2349 char str[80];
2350 };
2351
2352 struct ElfImage *img;
2353
2354 static const struct ElfImage img_template = {
2355 .ehdr = {
2356 .e_ident[EI_MAG0] = ELFMAG0,
2357 .e_ident[EI_MAG1] = ELFMAG1,
2358 .e_ident[EI_MAG2] = ELFMAG2,
2359 .e_ident[EI_MAG3] = ELFMAG3,
2360 .e_ident[EI_CLASS] = ELF_CLASS,
2361 .e_ident[EI_DATA] = ELF_DATA,
2362 .e_ident[EI_VERSION] = EV_CURRENT,
2363 .e_type = ET_EXEC,
2364 .e_machine = ELF_HOST_MACHINE,
2365 .e_version = EV_CURRENT,
2366 .e_phoff = offsetof(struct ElfImage, phdr),
2367 .e_shoff = offsetof(struct ElfImage, shdr),
2368 .e_ehsize = sizeof(ElfW(Shdr)),
2369 .e_phentsize = sizeof(ElfW(Phdr)),
2370 .e_phnum = 1,
2371 .e_shentsize = sizeof(ElfW(Shdr)),
2372 .e_shnum = ARRAY_SIZE(img->shdr),
2373 .e_shstrndx = ARRAY_SIZE(img->shdr) - 1,
abbb3eae
RH
2374#ifdef ELF_HOST_FLAGS
2375 .e_flags = ELF_HOST_FLAGS,
2376#endif
2377#ifdef ELF_OSABI
2378 .e_ident[EI_OSABI] = ELF_OSABI,
2379#endif
5872bbf2
RH
2380 },
2381 .phdr = {
2382 .p_type = PT_LOAD,
2383 .p_flags = PF_X,
2384 },
2385 .shdr = {
2386 [0] = { .sh_type = SHT_NULL },
2387 /* Trick: The contents of code_gen_buffer are not present in
2388 this fake ELF file; that got allocated elsewhere. Therefore
2389 we mark .text as SHT_NOBITS (similar to .bss) so that readers
2390 will not look for contents. We can record any address. */
2391 [1] = { /* .text */
2392 .sh_type = SHT_NOBITS,
2393 .sh_flags = SHF_EXECINSTR | SHF_ALLOC,
2394 },
2395 [2] = { /* .debug_info */
2396 .sh_type = SHT_PROGBITS,
2397 .sh_offset = offsetof(struct ElfImage, di),
2398 .sh_size = sizeof(struct DebugInfo),
2399 },
2400 [3] = { /* .debug_abbrev */
2401 .sh_type = SHT_PROGBITS,
2402 .sh_offset = offsetof(struct ElfImage, da),
2403 .sh_size = sizeof(img->da),
2404 },
2405 [4] = { /* .debug_frame */
2406 .sh_type = SHT_PROGBITS,
2407 .sh_offset = sizeof(struct ElfImage),
2408 },
2409 [5] = { /* .symtab */
2410 .sh_type = SHT_SYMTAB,
2411 .sh_offset = offsetof(struct ElfImage, sym),
2412 .sh_size = sizeof(img->sym),
2413 .sh_info = 1,
2414 .sh_link = ARRAY_SIZE(img->shdr) - 1,
2415 .sh_entsize = sizeof(ElfW(Sym)),
2416 },
2417 [6] = { /* .strtab */
2418 .sh_type = SHT_STRTAB,
2419 .sh_offset = offsetof(struct ElfImage, str),
2420 .sh_size = sizeof(img->str),
2421 }
2422 },
2423 .sym = {
2424 [1] = { /* code_gen_buffer */
2425 .st_info = ELF_ST_INFO(STB_GLOBAL, STT_FUNC),
2426 .st_shndx = 1,
2427 }
2428 },
2429 .di = {
2430 .len = sizeof(struct DebugInfo) - 4,
2431 .version = 2,
2432 .ptr_size = sizeof(void *),
2433 .cu_die = 1,
2434 .cu_lang = 0x8001, /* DW_LANG_Mips_Assembler */
2435 .fn_die = 2,
2436 .fn_name = "code_gen_buffer"
2437 },
2438 .da = {
2439 1, /* abbrev number (the cu) */
2440 0x11, 1, /* DW_TAG_compile_unit, has children */
2441 0x13, 0x5, /* DW_AT_language, DW_FORM_data2 */
2442 0x11, 0x1, /* DW_AT_low_pc, DW_FORM_addr */
2443 0x12, 0x1, /* DW_AT_high_pc, DW_FORM_addr */
2444 0, 0, /* end of abbrev */
2445 2, /* abbrev number (the fn) */
2446 0x2e, 0, /* DW_TAG_subprogram, no children */
2447 0x3, 0x8, /* DW_AT_name, DW_FORM_string */
2448 0x11, 0x1, /* DW_AT_low_pc, DW_FORM_addr */
2449 0x12, 0x1, /* DW_AT_high_pc, DW_FORM_addr */
2450 0, 0, /* end of abbrev */
2451 0 /* no more abbrev */
2452 },
2453 .str = "\0" ".text\0" ".debug_info\0" ".debug_abbrev\0"
2454 ".debug_frame\0" ".symtab\0" ".strtab\0" "code_gen_buffer",
813da627
RH
2455 };
2456
2457 /* We only need a single jit entry; statically allocate it. */
2458 static struct jit_code_entry one_entry;
2459
5872bbf2 2460 uintptr_t buf = (uintptr_t)buf_ptr;
813da627 2461 size_t img_size = sizeof(struct ElfImage) + debug_frame_size;
813da627 2462
5872bbf2
RH
2463 img = g_malloc(img_size);
2464 *img = img_template;
2465 memcpy(img + 1, debug_frame, debug_frame_size);
813da627 2466
5872bbf2
RH
2467 img->phdr.p_vaddr = buf;
2468 img->phdr.p_paddr = buf;
2469 img->phdr.p_memsz = buf_size;
813da627 2470
813da627 2471 img->shdr[1].sh_name = find_string(img->str, ".text");
5872bbf2 2472 img->shdr[1].sh_addr = buf;
813da627
RH
2473 img->shdr[1].sh_size = buf_size;
2474
5872bbf2
RH
2475 img->shdr[2].sh_name = find_string(img->str, ".debug_info");
2476 img->shdr[3].sh_name = find_string(img->str, ".debug_abbrev");
2477
2478 img->shdr[4].sh_name = find_string(img->str, ".debug_frame");
2479 img->shdr[4].sh_size = debug_frame_size;
2480
2481 img->shdr[5].sh_name = find_string(img->str, ".symtab");
2482 img->shdr[6].sh_name = find_string(img->str, ".strtab");
2483
2484 img->sym[1].st_name = find_string(img->str, "code_gen_buffer");
2485 img->sym[1].st_value = buf;
2486 img->sym[1].st_size = buf_size;
813da627 2487
5872bbf2
RH
2488 img->di.cu_low_pc = buf;
2489 img->di.cu_high_pc = buf_size;
2490 img->di.fn_low_pc = buf;
2491 img->di.fn_high_pc = buf_size;
813da627
RH
2492
2493#ifdef DEBUG_JIT
2494 /* Enable this block to be able to debug the ELF image file creation.
2495 One can use readelf, objdump, or other inspection utilities. */
2496 {
2497 FILE *f = fopen("/tmp/qemu.jit", "w+b");
2498 if (f) {
5872bbf2 2499 if (fwrite(img, img_size, 1, f) != img_size) {
813da627
RH
2500 /* Avoid stupid unused return value warning for fwrite. */
2501 }
2502 fclose(f);
2503 }
2504 }
2505#endif
2506
2507 one_entry.symfile_addr = img;
2508 one_entry.symfile_size = img_size;
2509
2510 __jit_debug_descriptor.action_flag = JIT_REGISTER_FN;
2511 __jit_debug_descriptor.relevant_entry = &one_entry;
2512 __jit_debug_descriptor.first_entry = &one_entry;
2513 __jit_debug_register_code();
2514}
2515#else
5872bbf2
RH
2516/* No support for the feature. Provide the entry point expected by exec.c,
2517 and implement the internal function we declared earlier. */
813da627
RH
2518
2519static void tcg_register_jit_int(void *buf, size_t size,
2520 void *debug_frame, size_t debug_frame_size)
2521{
2522}
2523
2524void tcg_register_jit(void *buf, size_t buf_size)
2525{
2526}
2527#endif /* ELF_HOST_MACHINE */