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