]> git.proxmox.com Git - qemu.git/blame - tcg/tcg.c
Separate inet_connect into inet_connect (blocking) and inet_nonblocking_connect
[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 }
ffc1c568 940 } else if (c == INDEX_op_movi_i32 || c == INDEX_op_movi_i64) {
e8996ee0
FB
941 tcg_target_ulong val;
942 TCGHelperInfo *th;
943
944 nb_oargs = def->nb_oargs;
945 nb_iargs = def->nb_iargs;
946 nb_cargs = def->nb_cargs;
eeacee4d
BS
947 qemu_log(" %s %s,$", def->name,
948 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[0]));
e8996ee0
FB
949 val = args[1];
950 th = tcg_find_helper(s, val);
951 if (th) {
eeacee4d 952 qemu_log("%s", th->name);
e8996ee0 953 } else {
eeacee4d
BS
954 if (c == INDEX_op_movi_i32) {
955 qemu_log("0x%x", (uint32_t)val);
956 } else {
957 qemu_log("0x%" PRIx64 , (uint64_t)val);
958 }
e8996ee0 959 }
b03cce8e 960 } else {
eeacee4d 961 qemu_log(" %s ", def->name);
b03cce8e
FB
962 if (c == INDEX_op_nopn) {
963 /* variable number of arguments */
964 nb_cargs = *args;
965 nb_oargs = 0;
966 nb_iargs = 0;
967 } else {
968 nb_oargs = def->nb_oargs;
969 nb_iargs = def->nb_iargs;
970 nb_cargs = def->nb_cargs;
971 }
972
973 k = 0;
974 for(i = 0; i < nb_oargs; i++) {
eeacee4d
BS
975 if (k != 0) {
976 qemu_log(",");
977 }
978 qemu_log("%s", tcg_get_arg_str_idx(s, buf, sizeof(buf),
979 args[k++]));
b03cce8e
FB
980 }
981 for(i = 0; i < nb_iargs; i++) {
eeacee4d
BS
982 if (k != 0) {
983 qemu_log(",");
984 }
985 qemu_log("%s", tcg_get_arg_str_idx(s, buf, sizeof(buf),
986 args[k++]));
b03cce8e 987 }
be210acb
RH
988 switch (c) {
989 case INDEX_op_brcond_i32:
be210acb 990 case INDEX_op_setcond_i32:
6314cc0c 991 case INDEX_op_movcond_i32:
6314cc0c 992 case INDEX_op_brcond2_i32:
be210acb 993 case INDEX_op_setcond2_i32:
6314cc0c 994 case INDEX_op_brcond_i64:
be210acb 995 case INDEX_op_setcond_i64:
6314cc0c 996 case INDEX_op_movcond_i64:
eeacee4d
BS
997 if (args[k] < ARRAY_SIZE(cond_name) && cond_name[args[k]]) {
998 qemu_log(",%s", cond_name[args[k++]]);
999 } else {
1000 qemu_log(",$0x%" TCG_PRIlx, args[k++]);
1001 }
f48f3ede 1002 i = 1;
be210acb
RH
1003 break;
1004 default:
f48f3ede 1005 i = 0;
be210acb
RH
1006 break;
1007 }
f48f3ede 1008 for(; i < nb_cargs; i++) {
eeacee4d
BS
1009 if (k != 0) {
1010 qemu_log(",");
1011 }
b03cce8e 1012 arg = args[k++];
eeacee4d 1013 qemu_log("$0x%" TCG_PRIlx, arg);
b03cce8e 1014 }
c896fe29 1015 }
eeacee4d 1016 qemu_log("\n");
c896fe29
FB
1017 args += nb_iargs + nb_oargs + nb_cargs;
1018 }
1019}
1020
1021/* we give more priority to constraints with less registers */
1022static int get_constraint_priority(const TCGOpDef *def, int k)
1023{
1024 const TCGArgConstraint *arg_ct;
1025
1026 int i, n;
1027 arg_ct = &def->args_ct[k];
1028 if (arg_ct->ct & TCG_CT_ALIAS) {
1029 /* an alias is equivalent to a single register */
1030 n = 1;
1031 } else {
1032 if (!(arg_ct->ct & TCG_CT_REG))
1033 return 0;
1034 n = 0;
1035 for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
1036 if (tcg_regset_test_reg(arg_ct->u.regs, i))
1037 n++;
1038 }
1039 }
1040 return TCG_TARGET_NB_REGS - n + 1;
1041}
1042
1043/* sort from highest priority to lowest */
1044static void sort_constraints(TCGOpDef *def, int start, int n)
1045{
1046 int i, j, p1, p2, tmp;
1047
1048 for(i = 0; i < n; i++)
1049 def->sorted_args[start + i] = start + i;
1050 if (n <= 1)
1051 return;
1052 for(i = 0; i < n - 1; i++) {
1053 for(j = i + 1; j < n; j++) {
1054 p1 = get_constraint_priority(def, def->sorted_args[start + i]);
1055 p2 = get_constraint_priority(def, def->sorted_args[start + j]);
1056 if (p1 < p2) {
1057 tmp = def->sorted_args[start + i];
1058 def->sorted_args[start + i] = def->sorted_args[start + j];
1059 def->sorted_args[start + j] = tmp;
1060 }
1061 }
1062 }
1063}
1064
1065void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs)
1066{
a9751609 1067 TCGOpcode op;
c896fe29
FB
1068 TCGOpDef *def;
1069 const char *ct_str;
1070 int i, nb_args;
1071
1072 for(;;) {
a9751609 1073 if (tdefs->op == (TCGOpcode)-1)
c896fe29
FB
1074 break;
1075 op = tdefs->op;
c3b08d0e 1076 assert((unsigned)op < NB_OPS);
c896fe29 1077 def = &tcg_op_defs[op];
c68aaa18
SW
1078#if defined(CONFIG_DEBUG_TCG)
1079 /* Duplicate entry in op definitions? */
1080 assert(!def->used);
1081 def->used = 1;
1082#endif
c896fe29
FB
1083 nb_args = def->nb_iargs + def->nb_oargs;
1084 for(i = 0; i < nb_args; i++) {
1085 ct_str = tdefs->args_ct_str[i];
c68aaa18
SW
1086 /* Incomplete TCGTargetOpDef entry? */
1087 assert(ct_str != NULL);
c896fe29
FB
1088 tcg_regset_clear(def->args_ct[i].u.regs);
1089 def->args_ct[i].ct = 0;
1090 if (ct_str[0] >= '0' && ct_str[0] <= '9') {
1091 int oarg;
1092 oarg = ct_str[0] - '0';
1093 assert(oarg < def->nb_oargs);
1094 assert(def->args_ct[oarg].ct & TCG_CT_REG);
1095 /* TCG_CT_ALIAS is for the output arguments. The input
5ff9d6a4 1096 argument is tagged with TCG_CT_IALIAS. */
c896fe29 1097 def->args_ct[i] = def->args_ct[oarg];
5ff9d6a4
FB
1098 def->args_ct[oarg].ct = TCG_CT_ALIAS;
1099 def->args_ct[oarg].alias_index = i;
c896fe29 1100 def->args_ct[i].ct |= TCG_CT_IALIAS;
5ff9d6a4 1101 def->args_ct[i].alias_index = oarg;
c896fe29
FB
1102 } else {
1103 for(;;) {
1104 if (*ct_str == '\0')
1105 break;
1106 switch(*ct_str) {
1107 case 'i':
1108 def->args_ct[i].ct |= TCG_CT_CONST;
1109 ct_str++;
1110 break;
1111 default:
1112 if (target_parse_constraint(&def->args_ct[i], &ct_str) < 0) {
1113 fprintf(stderr, "Invalid constraint '%s' for arg %d of operation '%s'\n",
1114 ct_str, i, def->name);
1115 exit(1);
1116 }
1117 }
1118 }
1119 }
1120 }
1121
c68aaa18
SW
1122 /* TCGTargetOpDef entry with too much information? */
1123 assert(i == TCG_MAX_OP_ARGS || tdefs->args_ct_str[i] == NULL);
1124
c896fe29
FB
1125 /* sort the constraints (XXX: this is just an heuristic) */
1126 sort_constraints(def, 0, def->nb_oargs);
1127 sort_constraints(def, def->nb_oargs, def->nb_iargs);
1128
1129#if 0
1130 {
1131 int i;
1132
1133 printf("%s: sorted=", def->name);
1134 for(i = 0; i < def->nb_oargs + def->nb_iargs; i++)
1135 printf(" %d", def->sorted_args[i]);
1136 printf("\n");
1137 }
1138#endif
1139 tdefs++;
1140 }
1141
c68aaa18 1142#if defined(CONFIG_DEBUG_TCG)
a9751609 1143 i = 0;
c68aaa18 1144 for (op = 0; op < ARRAY_SIZE(tcg_op_defs); op++) {
f412c762
RH
1145 const TCGOpDef *def = &tcg_op_defs[op];
1146 if (op < INDEX_op_call
1147 || op == INDEX_op_debug_insn_start
1148 || (def->flags & TCG_OPF_NOT_PRESENT)) {
c68aaa18 1149 /* Wrong entry in op definitions? */
f412c762
RH
1150 if (def->used) {
1151 fprintf(stderr, "Invalid op definition for %s\n", def->name);
a9751609
RH
1152 i = 1;
1153 }
c68aaa18
SW
1154 } else {
1155 /* Missing entry in op definitions? */
f412c762
RH
1156 if (!def->used) {
1157 fprintf(stderr, "Missing op definition for %s\n", def->name);
a9751609
RH
1158 i = 1;
1159 }
c68aaa18
SW
1160 }
1161 }
a9751609
RH
1162 if (i == 1) {
1163 tcg_abort();
1164 }
c68aaa18 1165#endif
c896fe29
FB
1166}
1167
1168#ifdef USE_LIVENESS_ANALYSIS
1169
1170/* set a nop for an operation using 'nb_args' */
1171static inline void tcg_set_nop(TCGContext *s, uint16_t *opc_ptr,
1172 TCGArg *args, int nb_args)
1173{
1174 if (nb_args == 0) {
1175 *opc_ptr = INDEX_op_nop;
1176 } else {
1177 *opc_ptr = INDEX_op_nopn;
1178 args[0] = nb_args;
1179 args[nb_args - 1] = nb_args;
1180 }
1181}
1182
641d5fbe
FB
1183/* liveness analysis: end of function: globals are live, temps are
1184 dead. */
1185/* XXX: at this stage, not used as there would be little gains because
1186 most TBs end with a conditional jump. */
1187static inline void tcg_la_func_end(TCGContext *s, uint8_t *dead_temps)
c896fe29
FB
1188{
1189 memset(dead_temps, 0, s->nb_globals);
1190 memset(dead_temps + s->nb_globals, 1, s->nb_temps - s->nb_globals);
1191}
1192
641d5fbe
FB
1193/* liveness analysis: end of basic block: globals are live, temps are
1194 dead, local temps are live. */
1195static inline void tcg_la_bb_end(TCGContext *s, uint8_t *dead_temps)
1196{
1197 int i;
1198 TCGTemp *ts;
1199
1200 memset(dead_temps, 0, s->nb_globals);
1201 ts = &s->temps[s->nb_globals];
1202 for(i = s->nb_globals; i < s->nb_temps; i++) {
1203 if (ts->temp_local)
1204 dead_temps[i] = 0;
1205 else
1206 dead_temps[i] = 1;
1207 ts++;
1208 }
1209}
1210
866cb6cb 1211/* Liveness analysis : update the opc_dead_args array to tell if a
c896fe29
FB
1212 given input arguments is dead. Instructions updating dead
1213 temporaries are removed. */
8fcd3692 1214static void tcg_liveness_analysis(TCGContext *s)
c896fe29 1215{
a9751609
RH
1216 int i, op_index, nb_args, nb_iargs, nb_oargs, arg, nb_ops;
1217 TCGOpcode op;
c896fe29
FB
1218 TCGArg *args;
1219 const TCGOpDef *def;
1220 uint8_t *dead_temps;
866cb6cb 1221 unsigned int dead_args;
c896fe29
FB
1222
1223 gen_opc_ptr++; /* skip end */
1224
1225 nb_ops = gen_opc_ptr - gen_opc_buf;
1226
866cb6cb 1227 s->op_dead_args = tcg_malloc(nb_ops * sizeof(uint16_t));
c896fe29
FB
1228
1229 dead_temps = tcg_malloc(s->nb_temps);
1230 memset(dead_temps, 1, s->nb_temps);
1231
1232 args = gen_opparam_ptr;
1233 op_index = nb_ops - 1;
1234 while (op_index >= 0) {
1235 op = gen_opc_buf[op_index];
1236 def = &tcg_op_defs[op];
1237 switch(op) {
1238 case INDEX_op_call:
c6e113f5
FB
1239 {
1240 int call_flags;
c896fe29 1241
c6e113f5
FB
1242 nb_args = args[-1];
1243 args -= nb_args;
1244 nb_iargs = args[0] & 0xffff;
1245 nb_oargs = args[0] >> 16;
1246 args++;
1247 call_flags = args[nb_oargs + nb_iargs];
1248
1249 /* pure functions can be removed if their result is not
1250 used */
1251 if (call_flags & TCG_CALL_PURE) {
1252 for(i = 0; i < nb_oargs; i++) {
1253 arg = args[i];
1254 if (!dead_temps[arg])
1255 goto do_not_remove_call;
1256 }
1257 tcg_set_nop(s, gen_opc_buf + op_index,
1258 args - 1, nb_args);
1259 } else {
1260 do_not_remove_call:
c896fe29 1261
c6e113f5 1262 /* output args are dead */
6b64b624 1263 dead_args = 0;
c6e113f5
FB
1264 for(i = 0; i < nb_oargs; i++) {
1265 arg = args[i];
6b64b624
AJ
1266 if (dead_temps[arg]) {
1267 dead_args |= (1 << i);
1268 }
c6e113f5
FB
1269 dead_temps[arg] = 1;
1270 }
1271
b9c18f56
AJ
1272 if (!(call_flags & TCG_CALL_CONST)) {
1273 /* globals are live (they may be used by the call) */
1274 memset(dead_temps, 0, s->nb_globals);
1275 }
1276
c6e113f5 1277 /* input args are live */
866cb6cb
AJ
1278 for(i = nb_oargs; i < nb_iargs + nb_oargs; i++) {
1279 arg = args[i];
39cf05d3
FB
1280 if (arg != TCG_CALL_DUMMY_ARG) {
1281 if (dead_temps[arg]) {
866cb6cb 1282 dead_args |= (1 << i);
39cf05d3
FB
1283 }
1284 dead_temps[arg] = 0;
c6e113f5 1285 }
c6e113f5 1286 }
866cb6cb 1287 s->op_dead_args[op_index] = dead_args;
c896fe29 1288 }
c6e113f5 1289 args--;
c896fe29 1290 }
c896fe29 1291 break;
7e4597d7
FB
1292 case INDEX_op_debug_insn_start:
1293 args -= def->nb_args;
1294 break;
c896fe29
FB
1295 case INDEX_op_nopn:
1296 nb_args = args[-1];
1297 args -= nb_args;
1298 break;
5ff9d6a4
FB
1299 case INDEX_op_discard:
1300 args--;
1301 /* mark the temporary as dead */
1302 dead_temps[args[0]] = 1;
1303 break;
c896fe29
FB
1304 case INDEX_op_end:
1305 break;
1306 /* XXX: optimize by hardcoding common cases (e.g. triadic ops) */
1307 default:
49516bc0
AJ
1308 args -= def->nb_args;
1309 nb_iargs = def->nb_iargs;
1310 nb_oargs = def->nb_oargs;
c896fe29 1311
49516bc0
AJ
1312 /* Test if the operation can be removed because all
1313 its outputs are dead. We assume that nb_oargs == 0
1314 implies side effects */
1315 if (!(def->flags & TCG_OPF_SIDE_EFFECTS) && nb_oargs != 0) {
1316 for(i = 0; i < nb_oargs; i++) {
1317 arg = args[i];
1318 if (!dead_temps[arg])
1319 goto do_not_remove;
1320 }
1321 tcg_set_nop(s, gen_opc_buf + op_index, args, def->nb_args);
c896fe29 1322#ifdef CONFIG_PROFILER
49516bc0 1323 s->del_op_count++;
c896fe29 1324#endif
49516bc0
AJ
1325 } else {
1326 do_not_remove:
c896fe29 1327
49516bc0 1328 /* output args are dead */
6b64b624 1329 dead_args = 0;
49516bc0
AJ
1330 for(i = 0; i < nb_oargs; i++) {
1331 arg = args[i];
6b64b624
AJ
1332 if (dead_temps[arg]) {
1333 dead_args |= (1 << i);
1334 }
49516bc0
AJ
1335 dead_temps[arg] = 1;
1336 }
1337
1338 /* if end of basic block, update */
1339 if (def->flags & TCG_OPF_BB_END) {
1340 tcg_la_bb_end(s, dead_temps);
1341 } else if (def->flags & TCG_OPF_CALL_CLOBBER) {
1342 /* globals are live */
1343 memset(dead_temps, 0, s->nb_globals);
1344 }
1345
1346 /* input args are live */
866cb6cb
AJ
1347 for(i = nb_oargs; i < nb_oargs + nb_iargs; i++) {
1348 arg = args[i];
49516bc0 1349 if (dead_temps[arg]) {
866cb6cb 1350 dead_args |= (1 << i);
c896fe29 1351 }
49516bc0 1352 dead_temps[arg] = 0;
c896fe29 1353 }
866cb6cb 1354 s->op_dead_args[op_index] = dead_args;
c896fe29
FB
1355 }
1356 break;
1357 }
1358 op_index--;
1359 }
1360
1361 if (args != gen_opparam_buf)
1362 tcg_abort();
1363}
1364#else
1365/* dummy liveness analysis */
655feed5 1366static void tcg_liveness_analysis(TCGContext *s)
c896fe29
FB
1367{
1368 int nb_ops;
1369 nb_ops = gen_opc_ptr - gen_opc_buf;
1370
866cb6cb
AJ
1371 s->op_dead_args = tcg_malloc(nb_ops * sizeof(uint16_t));
1372 memset(s->op_dead_args, 0, nb_ops * sizeof(uint16_t));
c896fe29
FB
1373}
1374#endif
1375
1376#ifndef NDEBUG
1377static void dump_regs(TCGContext *s)
1378{
1379 TCGTemp *ts;
1380 int i;
1381 char buf[64];
1382
1383 for(i = 0; i < s->nb_temps; i++) {
1384 ts = &s->temps[i];
ac56dd48 1385 printf(" %10s: ", tcg_get_arg_str_idx(s, buf, sizeof(buf), i));
c896fe29
FB
1386 switch(ts->val_type) {
1387 case TEMP_VAL_REG:
1388 printf("%s", tcg_target_reg_names[ts->reg]);
1389 break;
1390 case TEMP_VAL_MEM:
1391 printf("%d(%s)", (int)ts->mem_offset, tcg_target_reg_names[ts->mem_reg]);
1392 break;
1393 case TEMP_VAL_CONST:
1394 printf("$0x%" TCG_PRIlx, ts->val);
1395 break;
1396 case TEMP_VAL_DEAD:
1397 printf("D");
1398 break;
1399 default:
1400 printf("???");
1401 break;
1402 }
1403 printf("\n");
1404 }
1405
1406 for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
1407 if (s->reg_to_temp[i] >= 0) {
1408 printf("%s: %s\n",
1409 tcg_target_reg_names[i],
ac56dd48 1410 tcg_get_arg_str_idx(s, buf, sizeof(buf), s->reg_to_temp[i]));
c896fe29
FB
1411 }
1412 }
1413}
1414
1415static void check_regs(TCGContext *s)
1416{
1417 int reg, k;
1418 TCGTemp *ts;
1419 char buf[64];
1420
1421 for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1422 k = s->reg_to_temp[reg];
1423 if (k >= 0) {
1424 ts = &s->temps[k];
1425 if (ts->val_type != TEMP_VAL_REG ||
1426 ts->reg != reg) {
1427 printf("Inconsistency for register %s:\n",
1428 tcg_target_reg_names[reg]);
b03cce8e 1429 goto fail;
c896fe29
FB
1430 }
1431 }
1432 }
1433 for(k = 0; k < s->nb_temps; k++) {
1434 ts = &s->temps[k];
1435 if (ts->val_type == TEMP_VAL_REG &&
1436 !ts->fixed_reg &&
1437 s->reg_to_temp[ts->reg] != k) {
1438 printf("Inconsistency for temp %s:\n",
ac56dd48 1439 tcg_get_arg_str_idx(s, buf, sizeof(buf), k));
b03cce8e 1440 fail:
c896fe29
FB
1441 printf("reg state:\n");
1442 dump_regs(s);
1443 tcg_abort();
1444 }
1445 }
1446}
1447#endif
1448
1449static void temp_allocate_frame(TCGContext *s, int temp)
1450{
1451 TCGTemp *ts;
1452 ts = &s->temps[temp];
181dd0b2
RH
1453#if !(defined(__sparc__) && TCG_TARGET_REG_BITS == 64)
1454 /* Sparc64 stack is accessed with offset of 2047 */
b591dc59
BS
1455 s->current_frame_offset = (s->current_frame_offset +
1456 (tcg_target_long)sizeof(tcg_target_long) - 1) &
1457 ~(sizeof(tcg_target_long) - 1);
f44c9960 1458#endif
b591dc59
BS
1459 if (s->current_frame_offset + (tcg_target_long)sizeof(tcg_target_long) >
1460 s->frame_end) {
5ff9d6a4 1461 tcg_abort();
b591dc59 1462 }
c896fe29
FB
1463 ts->mem_offset = s->current_frame_offset;
1464 ts->mem_reg = s->frame_reg;
1465 ts->mem_allocated = 1;
b591dc59 1466 s->current_frame_offset += (tcg_target_long)sizeof(tcg_target_long);
c896fe29
FB
1467}
1468
1469/* free register 'reg' by spilling the corresponding temporary if necessary */
1470static void tcg_reg_free(TCGContext *s, int reg)
1471{
1472 TCGTemp *ts;
1473 int temp;
1474
1475 temp = s->reg_to_temp[reg];
1476 if (temp != -1) {
1477 ts = &s->temps[temp];
1478 assert(ts->val_type == TEMP_VAL_REG);
1479 if (!ts->mem_coherent) {
1480 if (!ts->mem_allocated)
1481 temp_allocate_frame(s, temp);
e4d5434c 1482 tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
c896fe29
FB
1483 }
1484 ts->val_type = TEMP_VAL_MEM;
1485 s->reg_to_temp[reg] = -1;
1486 }
1487}
1488
1489/* Allocate a register belonging to reg1 & ~reg2 */
1490static int tcg_reg_alloc(TCGContext *s, TCGRegSet reg1, TCGRegSet reg2)
1491{
1492 int i, reg;
1493 TCGRegSet reg_ct;
1494
1495 tcg_regset_andnot(reg_ct, reg1, reg2);
1496
1497 /* first try free registers */
0954d0d9 1498 for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
c896fe29
FB
1499 reg = tcg_target_reg_alloc_order[i];
1500 if (tcg_regset_test_reg(reg_ct, reg) && s->reg_to_temp[reg] == -1)
1501 return reg;
1502 }
1503
1504 /* XXX: do better spill choice */
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)) {
1508 tcg_reg_free(s, reg);
1509 return reg;
1510 }
1511 }
1512
1513 tcg_abort();
1514}
1515
641d5fbe
FB
1516/* save a temporary to memory. 'allocated_regs' is used in case a
1517 temporary registers needs to be allocated to store a constant. */
1518static void temp_save(TCGContext *s, int temp, TCGRegSet allocated_regs)
1519{
1520 TCGTemp *ts;
1521 int reg;
1522
1523 ts = &s->temps[temp];
1524 if (!ts->fixed_reg) {
1525 switch(ts->val_type) {
1526 case TEMP_VAL_REG:
1527 tcg_reg_free(s, ts->reg);
1528 break;
1529 case TEMP_VAL_DEAD:
1530 ts->val_type = TEMP_VAL_MEM;
1531 break;
1532 case TEMP_VAL_CONST:
d6859202
AJ
1533 reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type],
1534 allocated_regs);
641d5fbe
FB
1535 if (!ts->mem_allocated)
1536 temp_allocate_frame(s, temp);
d6859202
AJ
1537 tcg_out_movi(s, ts->type, reg, ts->val);
1538 tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
641d5fbe
FB
1539 ts->val_type = TEMP_VAL_MEM;
1540 break;
1541 case TEMP_VAL_MEM:
1542 break;
1543 default:
1544 tcg_abort();
1545 }
1546 }
1547}
1548
9814dd27 1549/* save globals to their canonical location and assume they can be
e8996ee0
FB
1550 modified be the following code. 'allocated_regs' is used in case a
1551 temporary registers needs to be allocated to store a constant. */
1552static void save_globals(TCGContext *s, TCGRegSet allocated_regs)
c896fe29 1553{
641d5fbe 1554 int i;
c896fe29
FB
1555
1556 for(i = 0; i < s->nb_globals; i++) {
641d5fbe 1557 temp_save(s, i, allocated_regs);
c896fe29 1558 }
e5097dc8
FB
1559}
1560
1561/* at the end of a basic block, we assume all temporaries are dead and
e8996ee0
FB
1562 all globals are stored at their canonical location. */
1563static void tcg_reg_alloc_bb_end(TCGContext *s, TCGRegSet allocated_regs)
e5097dc8
FB
1564{
1565 TCGTemp *ts;
1566 int i;
1567
c896fe29
FB
1568 for(i = s->nb_globals; i < s->nb_temps; i++) {
1569 ts = &s->temps[i];
641d5fbe
FB
1570 if (ts->temp_local) {
1571 temp_save(s, i, allocated_regs);
1572 } else {
1573 if (ts->val_type == TEMP_VAL_REG) {
1574 s->reg_to_temp[ts->reg] = -1;
1575 }
1576 ts->val_type = TEMP_VAL_DEAD;
c896fe29
FB
1577 }
1578 }
e8996ee0
FB
1579
1580 save_globals(s, allocated_regs);
c896fe29
FB
1581}
1582
866cb6cb 1583#define IS_DEAD_ARG(n) ((dead_args >> (n)) & 1)
c896fe29 1584
e8996ee0
FB
1585static void tcg_reg_alloc_movi(TCGContext *s, const TCGArg *args)
1586{
1587 TCGTemp *ots;
1588 tcg_target_ulong val;
1589
1590 ots = &s->temps[args[0]];
1591 val = args[1];
1592
1593 if (ots->fixed_reg) {
1594 /* for fixed registers, we do not do any constant
1595 propagation */
1596 tcg_out_movi(s, ots->type, ots->reg, val);
1597 } else {
1235fc06 1598 /* The movi is not explicitly generated here */
e8996ee0
FB
1599 if (ots->val_type == TEMP_VAL_REG)
1600 s->reg_to_temp[ots->reg] = -1;
1601 ots->val_type = TEMP_VAL_CONST;
1602 ots->val = val;
1603 }
1604}
1605
c896fe29
FB
1606static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
1607 const TCGArg *args,
866cb6cb 1608 unsigned int dead_args)
c896fe29
FB
1609{
1610 TCGTemp *ts, *ots;
1611 int reg;
1612 const TCGArgConstraint *arg_ct;
1613
1614 ots = &s->temps[args[0]];
1615 ts = &s->temps[args[1]];
1616 arg_ct = &def->args_ct[0];
1617
866cb6cb 1618 /* XXX: always mark arg dead if IS_DEAD_ARG(1) */
c896fe29 1619 if (ts->val_type == TEMP_VAL_REG) {
866cb6cb 1620 if (IS_DEAD_ARG(1) && !ts->fixed_reg && !ots->fixed_reg) {
c896fe29
FB
1621 /* the mov can be suppressed */
1622 if (ots->val_type == TEMP_VAL_REG)
1623 s->reg_to_temp[ots->reg] = -1;
1624 reg = ts->reg;
1625 s->reg_to_temp[reg] = -1;
1626 ts->val_type = TEMP_VAL_DEAD;
1627 } else {
1628 if (ots->val_type == TEMP_VAL_REG) {
1629 reg = ots->reg;
1630 } else {
1631 reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1632 }
1633 if (ts->reg != reg) {
3b6dac34 1634 tcg_out_mov(s, ots->type, reg, ts->reg);
c896fe29
FB
1635 }
1636 }
1637 } else if (ts->val_type == TEMP_VAL_MEM) {
1638 if (ots->val_type == TEMP_VAL_REG) {
1639 reg = ots->reg;
1640 } else {
1641 reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1642 }
e4d5434c 1643 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
c896fe29 1644 } else if (ts->val_type == TEMP_VAL_CONST) {
e8996ee0 1645 if (ots->fixed_reg) {
c896fe29 1646 reg = ots->reg;
e8996ee0 1647 tcg_out_movi(s, ots->type, reg, ts->val);
c896fe29 1648 } else {
e8996ee0
FB
1649 /* propagate constant */
1650 if (ots->val_type == TEMP_VAL_REG)
1651 s->reg_to_temp[ots->reg] = -1;
1652 ots->val_type = TEMP_VAL_CONST;
1653 ots->val = ts->val;
1654 return;
c896fe29 1655 }
c896fe29
FB
1656 } else {
1657 tcg_abort();
1658 }
1659 s->reg_to_temp[reg] = args[0];
1660 ots->reg = reg;
1661 ots->val_type = TEMP_VAL_REG;
1662 ots->mem_coherent = 0;
1663}
1664
1665static void tcg_reg_alloc_op(TCGContext *s,
a9751609 1666 const TCGOpDef *def, TCGOpcode opc,
c896fe29 1667 const TCGArg *args,
866cb6cb 1668 unsigned int dead_args)
c896fe29
FB
1669{
1670 TCGRegSet allocated_regs;
1671 int i, k, nb_iargs, nb_oargs, reg;
1672 TCGArg arg;
1673 const TCGArgConstraint *arg_ct;
1674 TCGTemp *ts;
1675 TCGArg new_args[TCG_MAX_OP_ARGS];
1676 int const_args[TCG_MAX_OP_ARGS];
1677
1678 nb_oargs = def->nb_oargs;
1679 nb_iargs = def->nb_iargs;
1680
1681 /* copy constants */
1682 memcpy(new_args + nb_oargs + nb_iargs,
1683 args + nb_oargs + nb_iargs,
1684 sizeof(TCGArg) * def->nb_cargs);
1685
1686 /* satisfy input constraints */
1687 tcg_regset_set(allocated_regs, s->reserved_regs);
1688 for(k = 0; k < nb_iargs; k++) {
1689 i = def->sorted_args[nb_oargs + k];
1690 arg = args[i];
1691 arg_ct = &def->args_ct[i];
1692 ts = &s->temps[arg];
1693 if (ts->val_type == TEMP_VAL_MEM) {
1694 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
e4d5434c 1695 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
c896fe29
FB
1696 ts->val_type = TEMP_VAL_REG;
1697 ts->reg = reg;
1698 ts->mem_coherent = 1;
1699 s->reg_to_temp[reg] = arg;
1700 } else if (ts->val_type == TEMP_VAL_CONST) {
1701 if (tcg_target_const_match(ts->val, arg_ct)) {
1702 /* constant is OK for instruction */
1703 const_args[i] = 1;
1704 new_args[i] = ts->val;
1705 goto iarg_end;
1706 } else {
e8996ee0 1707 /* need to move to a register */
c896fe29
FB
1708 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1709 tcg_out_movi(s, ts->type, reg, ts->val);
e8996ee0
FB
1710 ts->val_type = TEMP_VAL_REG;
1711 ts->reg = reg;
1712 ts->mem_coherent = 0;
1713 s->reg_to_temp[reg] = arg;
c896fe29
FB
1714 }
1715 }
1716 assert(ts->val_type == TEMP_VAL_REG);
5ff9d6a4
FB
1717 if (arg_ct->ct & TCG_CT_IALIAS) {
1718 if (ts->fixed_reg) {
1719 /* if fixed register, we must allocate a new register
1720 if the alias is not the same register */
1721 if (arg != args[arg_ct->alias_index])
1722 goto allocate_in_reg;
1723 } else {
1724 /* if the input is aliased to an output and if it is
1725 not dead after the instruction, we must allocate
1726 a new register and move it */
866cb6cb 1727 if (!IS_DEAD_ARG(i)) {
5ff9d6a4 1728 goto allocate_in_reg;
866cb6cb 1729 }
5ff9d6a4 1730 }
c896fe29
FB
1731 }
1732 reg = ts->reg;
1733 if (tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1734 /* nothing to do : the constraint is satisfied */
1735 } else {
1736 allocate_in_reg:
1737 /* allocate a new register matching the constraint
1738 and move the temporary register into it */
1739 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
3b6dac34 1740 tcg_out_mov(s, ts->type, reg, ts->reg);
c896fe29 1741 }
c896fe29
FB
1742 new_args[i] = reg;
1743 const_args[i] = 0;
1744 tcg_regset_set_reg(allocated_regs, reg);
1745 iarg_end: ;
1746 }
1747
e8996ee0
FB
1748 if (def->flags & TCG_OPF_BB_END) {
1749 tcg_reg_alloc_bb_end(s, allocated_regs);
1750 } else {
1751 /* mark dead temporaries and free the associated registers */
866cb6cb
AJ
1752 for(i = nb_oargs; i < nb_oargs + nb_iargs; i++) {
1753 arg = args[i];
1754 if (IS_DEAD_ARG(i)) {
e8996ee0
FB
1755 ts = &s->temps[arg];
1756 if (!ts->fixed_reg) {
1757 if (ts->val_type == TEMP_VAL_REG)
1758 s->reg_to_temp[ts->reg] = -1;
1759 ts->val_type = TEMP_VAL_DEAD;
1760 }
c896fe29
FB
1761 }
1762 }
e8996ee0
FB
1763
1764 if (def->flags & TCG_OPF_CALL_CLOBBER) {
1765 /* XXX: permit generic clobber register list ? */
1766 for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1767 if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
1768 tcg_reg_free(s, reg);
1769 }
c896fe29 1770 }
e8996ee0
FB
1771 /* XXX: for load/store we could do that only for the slow path
1772 (i.e. when a memory callback is called) */
1773
1774 /* store globals and free associated registers (we assume the insn
1775 can modify any global. */
1776 save_globals(s, allocated_regs);
c896fe29 1777 }
e8996ee0
FB
1778
1779 /* satisfy the output constraints */
1780 tcg_regset_set(allocated_regs, s->reserved_regs);
1781 for(k = 0; k < nb_oargs; k++) {
1782 i = def->sorted_args[k];
1783 arg = args[i];
1784 arg_ct = &def->args_ct[i];
1785 ts = &s->temps[arg];
1786 if (arg_ct->ct & TCG_CT_ALIAS) {
1787 reg = new_args[arg_ct->alias_index];
1788 } else {
1789 /* if fixed register, we try to use it */
1790 reg = ts->reg;
1791 if (ts->fixed_reg &&
1792 tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1793 goto oarg_end;
1794 }
1795 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
c896fe29 1796 }
e8996ee0
FB
1797 tcg_regset_set_reg(allocated_regs, reg);
1798 /* if a fixed register is used, then a move will be done afterwards */
1799 if (!ts->fixed_reg) {
1800 if (ts->val_type == TEMP_VAL_REG)
1801 s->reg_to_temp[ts->reg] = -1;
8c11ad25
AJ
1802 if (IS_DEAD_ARG(i)) {
1803 ts->val_type = TEMP_VAL_DEAD;
1804 } else {
1805 ts->val_type = TEMP_VAL_REG;
1806 ts->reg = reg;
1807 /* temp value is modified, so the value kept in memory is
1808 potentially not the same */
1809 ts->mem_coherent = 0;
1810 s->reg_to_temp[reg] = arg;
1811 }
e8996ee0
FB
1812 }
1813 oarg_end:
1814 new_args[i] = reg;
c896fe29 1815 }
c896fe29
FB
1816 }
1817
c896fe29
FB
1818 /* emit instruction */
1819 tcg_out_op(s, opc, new_args, const_args);
1820
1821 /* move the outputs in the correct register if needed */
1822 for(i = 0; i < nb_oargs; i++) {
1823 ts = &s->temps[args[i]];
1824 reg = new_args[i];
1825 if (ts->fixed_reg && ts->reg != reg) {
3b6dac34 1826 tcg_out_mov(s, ts->type, ts->reg, reg);
c896fe29
FB
1827 }
1828 }
1829}
1830
b03cce8e
FB
1831#ifdef TCG_TARGET_STACK_GROWSUP
1832#define STACK_DIR(x) (-(x))
1833#else
1834#define STACK_DIR(x) (x)
1835#endif
1836
c896fe29 1837static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
a9751609 1838 TCGOpcode opc, const TCGArg *args,
866cb6cb 1839 unsigned int dead_args)
c896fe29
FB
1840{
1841 int nb_iargs, nb_oargs, flags, nb_regs, i, reg, nb_params;
1842 TCGArg arg, func_arg;
1843 TCGTemp *ts;
f54b3f92 1844 tcg_target_long stack_offset, call_stack_size, func_addr;
b03cce8e 1845 int const_func_arg, allocate_args;
c896fe29
FB
1846 TCGRegSet allocated_regs;
1847 const TCGArgConstraint *arg_ct;
1848
1849 arg = *args++;
1850
1851 nb_oargs = arg >> 16;
1852 nb_iargs = arg & 0xffff;
1853 nb_params = nb_iargs - 1;
1854
1855 flags = args[nb_oargs + nb_iargs];
1856
1857 nb_regs = tcg_target_get_call_iarg_regs_count(flags);
1858 if (nb_regs > nb_params)
1859 nb_regs = nb_params;
1860
1861 /* assign stack slots first */
c896fe29
FB
1862 call_stack_size = (nb_params - nb_regs) * sizeof(tcg_target_long);
1863 call_stack_size = (call_stack_size + TCG_TARGET_STACK_ALIGN - 1) &
1864 ~(TCG_TARGET_STACK_ALIGN - 1);
b03cce8e
FB
1865 allocate_args = (call_stack_size > TCG_STATIC_CALL_ARGS_SIZE);
1866 if (allocate_args) {
345649c0
BS
1867 /* XXX: if more than TCG_STATIC_CALL_ARGS_SIZE is needed,
1868 preallocate call stack */
1869 tcg_abort();
b03cce8e 1870 }
39cf05d3
FB
1871
1872 stack_offset = TCG_TARGET_CALL_STACK_OFFSET;
c896fe29
FB
1873 for(i = nb_regs; i < nb_params; i++) {
1874 arg = args[nb_oargs + i];
39cf05d3
FB
1875#ifdef TCG_TARGET_STACK_GROWSUP
1876 stack_offset -= sizeof(tcg_target_long);
1877#endif
1878 if (arg != TCG_CALL_DUMMY_ARG) {
1879 ts = &s->temps[arg];
1880 if (ts->val_type == TEMP_VAL_REG) {
1881 tcg_out_st(s, ts->type, ts->reg, TCG_REG_CALL_STACK, stack_offset);
1882 } else if (ts->val_type == TEMP_VAL_MEM) {
1883 reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type],
1884 s->reserved_regs);
1885 /* XXX: not correct if reading values from the stack */
1886 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1887 tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
1888 } else if (ts->val_type == TEMP_VAL_CONST) {
1889 reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type],
1890 s->reserved_regs);
1891 /* XXX: sign extend may be needed on some targets */
1892 tcg_out_movi(s, ts->type, reg, ts->val);
1893 tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
1894 } else {
1895 tcg_abort();
1896 }
c896fe29 1897 }
39cf05d3
FB
1898#ifndef TCG_TARGET_STACK_GROWSUP
1899 stack_offset += sizeof(tcg_target_long);
1900#endif
c896fe29
FB
1901 }
1902
1903 /* assign input registers */
1904 tcg_regset_set(allocated_regs, s->reserved_regs);
1905 for(i = 0; i < nb_regs; i++) {
1906 arg = args[nb_oargs + i];
39cf05d3
FB
1907 if (arg != TCG_CALL_DUMMY_ARG) {
1908 ts = &s->temps[arg];
1909 reg = tcg_target_call_iarg_regs[i];
1910 tcg_reg_free(s, reg);
1911 if (ts->val_type == TEMP_VAL_REG) {
1912 if (ts->reg != reg) {
3b6dac34 1913 tcg_out_mov(s, ts->type, reg, ts->reg);
39cf05d3
FB
1914 }
1915 } else if (ts->val_type == TEMP_VAL_MEM) {
1916 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1917 } else if (ts->val_type == TEMP_VAL_CONST) {
1918 /* XXX: sign extend ? */
1919 tcg_out_movi(s, ts->type, reg, ts->val);
1920 } else {
1921 tcg_abort();
c896fe29 1922 }
39cf05d3 1923 tcg_regset_set_reg(allocated_regs, reg);
c896fe29 1924 }
c896fe29
FB
1925 }
1926
1927 /* assign function address */
1928 func_arg = args[nb_oargs + nb_iargs - 1];
1929 arg_ct = &def->args_ct[0];
1930 ts = &s->temps[func_arg];
f54b3f92 1931 func_addr = ts->val;
c896fe29
FB
1932 const_func_arg = 0;
1933 if (ts->val_type == TEMP_VAL_MEM) {
1934 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
e4d5434c 1935 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
c896fe29 1936 func_arg = reg;
e8996ee0 1937 tcg_regset_set_reg(allocated_regs, reg);
c896fe29
FB
1938 } else if (ts->val_type == TEMP_VAL_REG) {
1939 reg = ts->reg;
1940 if (!tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1941 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
3b6dac34 1942 tcg_out_mov(s, ts->type, reg, ts->reg);
c896fe29
FB
1943 }
1944 func_arg = reg;
e8996ee0 1945 tcg_regset_set_reg(allocated_regs, reg);
c896fe29 1946 } else if (ts->val_type == TEMP_VAL_CONST) {
f54b3f92 1947 if (tcg_target_const_match(func_addr, arg_ct)) {
c896fe29 1948 const_func_arg = 1;
f54b3f92 1949 func_arg = func_addr;
c896fe29
FB
1950 } else {
1951 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
f54b3f92 1952 tcg_out_movi(s, ts->type, reg, func_addr);
c896fe29 1953 func_arg = reg;
e8996ee0 1954 tcg_regset_set_reg(allocated_regs, reg);
c896fe29
FB
1955 }
1956 } else {
1957 tcg_abort();
1958 }
e8996ee0 1959
c896fe29
FB
1960
1961 /* mark dead temporaries and free the associated registers */
866cb6cb
AJ
1962 for(i = nb_oargs; i < nb_iargs + nb_oargs; i++) {
1963 arg = args[i];
1964 if (IS_DEAD_ARG(i)) {
c896fe29 1965 ts = &s->temps[arg];
e8996ee0 1966 if (!ts->fixed_reg) {
c896fe29
FB
1967 if (ts->val_type == TEMP_VAL_REG)
1968 s->reg_to_temp[ts->reg] = -1;
1969 ts->val_type = TEMP_VAL_DEAD;
1970 }
1971 }
1972 }
1973
1974 /* clobber call registers */
1975 for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1976 if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
1977 tcg_reg_free(s, reg);
1978 }
1979 }
1980
1981 /* store globals and free associated registers (we assume the call
1982 can modify any global. */
b9c18f56
AJ
1983 if (!(flags & TCG_CALL_CONST)) {
1984 save_globals(s, allocated_regs);
1985 }
c896fe29
FB
1986
1987 tcg_out_op(s, opc, &func_arg, &const_func_arg);
c896fe29
FB
1988
1989 /* assign output registers and emit moves if needed */
1990 for(i = 0; i < nb_oargs; i++) {
1991 arg = args[i];
1992 ts = &s->temps[arg];
1993 reg = tcg_target_call_oarg_regs[i];
e8996ee0 1994 assert(s->reg_to_temp[reg] == -1);
c896fe29
FB
1995 if (ts->fixed_reg) {
1996 if (ts->reg != reg) {
3b6dac34 1997 tcg_out_mov(s, ts->type, ts->reg, reg);
c896fe29
FB
1998 }
1999 } else {
2000 if (ts->val_type == TEMP_VAL_REG)
2001 s->reg_to_temp[ts->reg] = -1;
8c11ad25
AJ
2002 if (IS_DEAD_ARG(i)) {
2003 ts->val_type = TEMP_VAL_DEAD;
2004 } else {
2005 ts->val_type = TEMP_VAL_REG;
2006 ts->reg = reg;
2007 ts->mem_coherent = 0;
2008 s->reg_to_temp[reg] = arg;
2009 }
c896fe29
FB
2010 }
2011 }
2012
2013 return nb_iargs + nb_oargs + def->nb_cargs + 1;
2014}
2015
2016#ifdef CONFIG_PROFILER
2017
54604f74 2018static int64_t tcg_table_op_count[NB_OPS];
c896fe29 2019
871e6c35 2020static void dump_op_count(void)
c896fe29
FB
2021{
2022 int i;
2023 FILE *f;
54604f74 2024 f = fopen("/tmp/op.log", "w");
c896fe29 2025 for(i = INDEX_op_end; i < NB_OPS; i++) {
54604f74 2026 fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name, tcg_table_op_count[i]);
c896fe29
FB
2027 }
2028 fclose(f);
2029}
2030#endif
2031
2032
2033static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
2ba1eeb6 2034 long search_pc)
c896fe29 2035{
a9751609
RH
2036 TCGOpcode opc;
2037 int op_index;
c896fe29 2038 const TCGOpDef *def;
866cb6cb 2039 unsigned int dead_args;
c896fe29
FB
2040 const TCGArg *args;
2041
2042#ifdef DEBUG_DISAS
8fec2b8c 2043 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
93fcfe39 2044 qemu_log("OP:\n");
eeacee4d 2045 tcg_dump_ops(s);
93fcfe39 2046 qemu_log("\n");
c896fe29
FB
2047 }
2048#endif
2049
8f2e8c07
KB
2050#ifdef USE_TCG_OPTIMIZATIONS
2051 gen_opparam_ptr =
2052 tcg_optimize(s, gen_opc_ptr, gen_opparam_buf, tcg_op_defs);
2053#endif
2054
a23a9ec6
FB
2055#ifdef CONFIG_PROFILER
2056 s->la_time -= profile_getclock();
2057#endif
c896fe29 2058 tcg_liveness_analysis(s);
a23a9ec6
FB
2059#ifdef CONFIG_PROFILER
2060 s->la_time += profile_getclock();
2061#endif
c896fe29
FB
2062
2063#ifdef DEBUG_DISAS
8fec2b8c 2064 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_OPT))) {
6a957025 2065 qemu_log("OP after liveness analysis:\n");
eeacee4d 2066 tcg_dump_ops(s);
93fcfe39 2067 qemu_log("\n");
c896fe29
FB
2068 }
2069#endif
2070
2071 tcg_reg_alloc_start(s);
2072
2073 s->code_buf = gen_code_buf;
2074 s->code_ptr = gen_code_buf;
2075
c896fe29
FB
2076 args = gen_opparam_buf;
2077 op_index = 0;
b3db8758 2078
c896fe29
FB
2079 for(;;) {
2080 opc = gen_opc_buf[op_index];
2081#ifdef CONFIG_PROFILER
54604f74 2082 tcg_table_op_count[opc]++;
c896fe29
FB
2083#endif
2084 def = &tcg_op_defs[opc];
2085#if 0
2086 printf("%s: %d %d %d\n", def->name,
2087 def->nb_oargs, def->nb_iargs, def->nb_cargs);
2088 // dump_regs(s);
2089#endif
2090 switch(opc) {
2091 case INDEX_op_mov_i32:
c896fe29 2092 case INDEX_op_mov_i64:
866cb6cb
AJ
2093 dead_args = s->op_dead_args[op_index];
2094 tcg_reg_alloc_mov(s, def, args, dead_args);
c896fe29 2095 break;
e8996ee0 2096 case INDEX_op_movi_i32:
e8996ee0 2097 case INDEX_op_movi_i64:
e8996ee0
FB
2098 tcg_reg_alloc_movi(s, args);
2099 break;
7e4597d7
FB
2100 case INDEX_op_debug_insn_start:
2101 /* debug instruction */
2102 break;
c896fe29
FB
2103 case INDEX_op_nop:
2104 case INDEX_op_nop1:
2105 case INDEX_op_nop2:
2106 case INDEX_op_nop3:
2107 break;
2108 case INDEX_op_nopn:
2109 args += args[0];
2110 goto next;
5ff9d6a4
FB
2111 case INDEX_op_discard:
2112 {
2113 TCGTemp *ts;
2114 ts = &s->temps[args[0]];
2115 /* mark the temporary as dead */
e8996ee0 2116 if (!ts->fixed_reg) {
5ff9d6a4
FB
2117 if (ts->val_type == TEMP_VAL_REG)
2118 s->reg_to_temp[ts->reg] = -1;
2119 ts->val_type = TEMP_VAL_DEAD;
2120 }
2121 }
2122 break;
c896fe29 2123 case INDEX_op_set_label:
e8996ee0 2124 tcg_reg_alloc_bb_end(s, s->reserved_regs);
9d6fca70 2125 tcg_out_label(s, args[0], s->code_ptr);
c896fe29
FB
2126 break;
2127 case INDEX_op_call:
866cb6cb
AJ
2128 dead_args = s->op_dead_args[op_index];
2129 args += tcg_reg_alloc_call(s, def, opc, args, dead_args);
c896fe29
FB
2130 goto next;
2131 case INDEX_op_end:
2132 goto the_end;
c896fe29 2133 default:
25c4d9cc
RH
2134 /* Sanity check that we've not introduced any unhandled opcodes. */
2135 if (def->flags & TCG_OPF_NOT_PRESENT) {
2136 tcg_abort();
2137 }
c896fe29
FB
2138 /* Note: in order to speed up the code, it would be much
2139 faster to have specialized register allocator functions for
2140 some common argument patterns */
866cb6cb
AJ
2141 dead_args = s->op_dead_args[op_index];
2142 tcg_reg_alloc_op(s, def, opc, args, dead_args);
c896fe29
FB
2143 break;
2144 }
2145 args += def->nb_args;
8df1ca4b 2146 next:
2ba1eeb6 2147 if (search_pc >= 0 && search_pc < s->code_ptr - gen_code_buf) {
b314f270 2148 return op_index;
c896fe29
FB
2149 }
2150 op_index++;
2151#ifndef NDEBUG
2152 check_regs(s);
2153#endif
2154 }
2155 the_end:
2156 return -1;
2157}
2158
54604f74 2159int tcg_gen_code(TCGContext *s, uint8_t *gen_code_buf)
c896fe29
FB
2160{
2161#ifdef CONFIG_PROFILER
2162 {
c896fe29
FB
2163 int n;
2164 n = (gen_opc_ptr - gen_opc_buf);
a23a9ec6
FB
2165 s->op_count += n;
2166 if (n > s->op_count_max)
2167 s->op_count_max = n;
2168
2169 s->temp_count += s->nb_temps;
2170 if (s->nb_temps > s->temp_count_max)
2171 s->temp_count_max = s->nb_temps;
c896fe29
FB
2172 }
2173#endif
2174
2ba1eeb6 2175 tcg_gen_code_common(s, gen_code_buf, -1);
c896fe29
FB
2176
2177 /* flush instruction cache */
2aeabc08
SW
2178 flush_icache_range((tcg_target_ulong)gen_code_buf,
2179 (tcg_target_ulong)s->code_ptr);
2180
c896fe29
FB
2181 return s->code_ptr - gen_code_buf;
2182}
2183
2ba1eeb6 2184/* Return the index of the micro operation such as the pc after is <
623e265c
PB
2185 offset bytes from the start of the TB. The contents of gen_code_buf must
2186 not be changed, though writing the same values is ok.
2187 Return -1 if not found. */
54604f74 2188int tcg_gen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, long offset)
c896fe29 2189{
623e265c 2190 return tcg_gen_code_common(s, gen_code_buf, offset);
c896fe29 2191}
a23a9ec6
FB
2192
2193#ifdef CONFIG_PROFILER
405cf9ff 2194void tcg_dump_info(FILE *f, fprintf_function cpu_fprintf)
a23a9ec6
FB
2195{
2196 TCGContext *s = &tcg_ctx;
2197 int64_t tot;
2198
2199 tot = s->interm_time + s->code_time;
2200 cpu_fprintf(f, "JIT cycles %" PRId64 " (%0.3f s at 2.4 GHz)\n",
2201 tot, tot / 2.4e9);
2202 cpu_fprintf(f, "translated TBs %" PRId64 " (aborted=%" PRId64 " %0.1f%%)\n",
2203 s->tb_count,
2204 s->tb_count1 - s->tb_count,
2205 s->tb_count1 ? (double)(s->tb_count1 - s->tb_count) / s->tb_count1 * 100.0 : 0);
2206 cpu_fprintf(f, "avg ops/TB %0.1f max=%d\n",
2207 s->tb_count ? (double)s->op_count / s->tb_count : 0, s->op_count_max);
a23a9ec6
FB
2208 cpu_fprintf(f, "deleted ops/TB %0.2f\n",
2209 s->tb_count ?
2210 (double)s->del_op_count / s->tb_count : 0);
2211 cpu_fprintf(f, "avg temps/TB %0.2f max=%d\n",
2212 s->tb_count ?
2213 (double)s->temp_count / s->tb_count : 0,
2214 s->temp_count_max);
2215
2216 cpu_fprintf(f, "cycles/op %0.1f\n",
2217 s->op_count ? (double)tot / s->op_count : 0);
2218 cpu_fprintf(f, "cycles/in byte %0.1f\n",
2219 s->code_in_len ? (double)tot / s->code_in_len : 0);
2220 cpu_fprintf(f, "cycles/out byte %0.1f\n",
2221 s->code_out_len ? (double)tot / s->code_out_len : 0);
2222 if (tot == 0)
2223 tot = 1;
2224 cpu_fprintf(f, " gen_interm time %0.1f%%\n",
2225 (double)s->interm_time / tot * 100.0);
2226 cpu_fprintf(f, " gen_code time %0.1f%%\n",
2227 (double)s->code_time / tot * 100.0);
2228 cpu_fprintf(f, "liveness/code time %0.1f%%\n",
2229 (double)s->la_time / (s->code_time ? s->code_time : 1) * 100.0);
2230 cpu_fprintf(f, "cpu_restore count %" PRId64 "\n",
2231 s->restore_count);
2232 cpu_fprintf(f, " avg cycles %0.1f\n",
2233 s->restore_count ? (double)s->restore_time / s->restore_count : 0);
871e6c35
BS
2234
2235 dump_op_count();
a23a9ec6
FB
2236}
2237#else
405cf9ff 2238void tcg_dump_info(FILE *f, fprintf_function cpu_fprintf)
a23a9ec6 2239{
24bf7b3a 2240 cpu_fprintf(f, "[TCG profiler not compiled]\n");
a23a9ec6
FB
2241}
2242#endif
813da627
RH
2243
2244#ifdef ELF_HOST_MACHINE
5872bbf2
RH
2245/* In order to use this feature, the backend needs to do three things:
2246
2247 (1) Define ELF_HOST_MACHINE to indicate both what value to
2248 put into the ELF image and to indicate support for the feature.
2249
2250 (2) Define tcg_register_jit. This should create a buffer containing
2251 the contents of a .debug_frame section that describes the post-
2252 prologue unwind info for the tcg machine.
2253
2254 (3) Call tcg_register_jit_int, with the constructed .debug_frame.
2255*/
813da627
RH
2256
2257/* Begin GDB interface. THE FOLLOWING MUST MATCH GDB DOCS. */
2258typedef enum {
2259 JIT_NOACTION = 0,
2260 JIT_REGISTER_FN,
2261 JIT_UNREGISTER_FN
2262} jit_actions_t;
2263
2264struct jit_code_entry {
2265 struct jit_code_entry *next_entry;
2266 struct jit_code_entry *prev_entry;
2267 const void *symfile_addr;
2268 uint64_t symfile_size;
2269};
2270
2271struct jit_descriptor {
2272 uint32_t version;
2273 uint32_t action_flag;
2274 struct jit_code_entry *relevant_entry;
2275 struct jit_code_entry *first_entry;
2276};
2277
2278void __jit_debug_register_code(void) __attribute__((noinline));
2279void __jit_debug_register_code(void)
2280{
2281 asm("");
2282}
2283
2284/* Must statically initialize the version, because GDB may check
2285 the version before we can set it. */
2286struct jit_descriptor __jit_debug_descriptor = { 1, 0, 0, 0 };
2287
2288/* End GDB interface. */
2289
2290static int find_string(const char *strtab, const char *str)
2291{
2292 const char *p = strtab + 1;
2293
2294 while (1) {
2295 if (strcmp(p, str) == 0) {
2296 return p - strtab;
2297 }
2298 p += strlen(p) + 1;
2299 }
2300}
2301
5872bbf2 2302static void tcg_register_jit_int(void *buf_ptr, size_t buf_size,
813da627
RH
2303 void *debug_frame, size_t debug_frame_size)
2304{
5872bbf2
RH
2305 struct __attribute__((packed)) DebugInfo {
2306 uint32_t len;
2307 uint16_t version;
2308 uint32_t abbrev;
2309 uint8_t ptr_size;
2310 uint8_t cu_die;
2311 uint16_t cu_lang;
2312 uintptr_t cu_low_pc;
2313 uintptr_t cu_high_pc;
2314 uint8_t fn_die;
2315 char fn_name[16];
2316 uintptr_t fn_low_pc;
2317 uintptr_t fn_high_pc;
2318 uint8_t cu_eoc;
2319 };
813da627
RH
2320
2321 struct ElfImage {
2322 ElfW(Ehdr) ehdr;
2323 ElfW(Phdr) phdr;
5872bbf2
RH
2324 ElfW(Shdr) shdr[7];
2325 ElfW(Sym) sym[2];
2326 struct DebugInfo di;
2327 uint8_t da[24];
2328 char str[80];
2329 };
2330
2331 struct ElfImage *img;
2332
2333 static const struct ElfImage img_template = {
2334 .ehdr = {
2335 .e_ident[EI_MAG0] = ELFMAG0,
2336 .e_ident[EI_MAG1] = ELFMAG1,
2337 .e_ident[EI_MAG2] = ELFMAG2,
2338 .e_ident[EI_MAG3] = ELFMAG3,
2339 .e_ident[EI_CLASS] = ELF_CLASS,
2340 .e_ident[EI_DATA] = ELF_DATA,
2341 .e_ident[EI_VERSION] = EV_CURRENT,
2342 .e_type = ET_EXEC,
2343 .e_machine = ELF_HOST_MACHINE,
2344 .e_version = EV_CURRENT,
2345 .e_phoff = offsetof(struct ElfImage, phdr),
2346 .e_shoff = offsetof(struct ElfImage, shdr),
2347 .e_ehsize = sizeof(ElfW(Shdr)),
2348 .e_phentsize = sizeof(ElfW(Phdr)),
2349 .e_phnum = 1,
2350 .e_shentsize = sizeof(ElfW(Shdr)),
2351 .e_shnum = ARRAY_SIZE(img->shdr),
2352 .e_shstrndx = ARRAY_SIZE(img->shdr) - 1,
abbb3eae
RH
2353#ifdef ELF_HOST_FLAGS
2354 .e_flags = ELF_HOST_FLAGS,
2355#endif
2356#ifdef ELF_OSABI
2357 .e_ident[EI_OSABI] = ELF_OSABI,
2358#endif
5872bbf2
RH
2359 },
2360 .phdr = {
2361 .p_type = PT_LOAD,
2362 .p_flags = PF_X,
2363 },
2364 .shdr = {
2365 [0] = { .sh_type = SHT_NULL },
2366 /* Trick: The contents of code_gen_buffer are not present in
2367 this fake ELF file; that got allocated elsewhere. Therefore
2368 we mark .text as SHT_NOBITS (similar to .bss) so that readers
2369 will not look for contents. We can record any address. */
2370 [1] = { /* .text */
2371 .sh_type = SHT_NOBITS,
2372 .sh_flags = SHF_EXECINSTR | SHF_ALLOC,
2373 },
2374 [2] = { /* .debug_info */
2375 .sh_type = SHT_PROGBITS,
2376 .sh_offset = offsetof(struct ElfImage, di),
2377 .sh_size = sizeof(struct DebugInfo),
2378 },
2379 [3] = { /* .debug_abbrev */
2380 .sh_type = SHT_PROGBITS,
2381 .sh_offset = offsetof(struct ElfImage, da),
2382 .sh_size = sizeof(img->da),
2383 },
2384 [4] = { /* .debug_frame */
2385 .sh_type = SHT_PROGBITS,
2386 .sh_offset = sizeof(struct ElfImage),
2387 },
2388 [5] = { /* .symtab */
2389 .sh_type = SHT_SYMTAB,
2390 .sh_offset = offsetof(struct ElfImage, sym),
2391 .sh_size = sizeof(img->sym),
2392 .sh_info = 1,
2393 .sh_link = ARRAY_SIZE(img->shdr) - 1,
2394 .sh_entsize = sizeof(ElfW(Sym)),
2395 },
2396 [6] = { /* .strtab */
2397 .sh_type = SHT_STRTAB,
2398 .sh_offset = offsetof(struct ElfImage, str),
2399 .sh_size = sizeof(img->str),
2400 }
2401 },
2402 .sym = {
2403 [1] = { /* code_gen_buffer */
2404 .st_info = ELF_ST_INFO(STB_GLOBAL, STT_FUNC),
2405 .st_shndx = 1,
2406 }
2407 },
2408 .di = {
2409 .len = sizeof(struct DebugInfo) - 4,
2410 .version = 2,
2411 .ptr_size = sizeof(void *),
2412 .cu_die = 1,
2413 .cu_lang = 0x8001, /* DW_LANG_Mips_Assembler */
2414 .fn_die = 2,
2415 .fn_name = "code_gen_buffer"
2416 },
2417 .da = {
2418 1, /* abbrev number (the cu) */
2419 0x11, 1, /* DW_TAG_compile_unit, has children */
2420 0x13, 0x5, /* DW_AT_language, DW_FORM_data2 */
2421 0x11, 0x1, /* DW_AT_low_pc, DW_FORM_addr */
2422 0x12, 0x1, /* DW_AT_high_pc, DW_FORM_addr */
2423 0, 0, /* end of abbrev */
2424 2, /* abbrev number (the fn) */
2425 0x2e, 0, /* DW_TAG_subprogram, no children */
2426 0x3, 0x8, /* DW_AT_name, DW_FORM_string */
2427 0x11, 0x1, /* DW_AT_low_pc, DW_FORM_addr */
2428 0x12, 0x1, /* DW_AT_high_pc, DW_FORM_addr */
2429 0, 0, /* end of abbrev */
2430 0 /* no more abbrev */
2431 },
2432 .str = "\0" ".text\0" ".debug_info\0" ".debug_abbrev\0"
2433 ".debug_frame\0" ".symtab\0" ".strtab\0" "code_gen_buffer",
813da627
RH
2434 };
2435
2436 /* We only need a single jit entry; statically allocate it. */
2437 static struct jit_code_entry one_entry;
2438
5872bbf2 2439 uintptr_t buf = (uintptr_t)buf_ptr;
813da627 2440 size_t img_size = sizeof(struct ElfImage) + debug_frame_size;
813da627 2441
5872bbf2
RH
2442 img = g_malloc(img_size);
2443 *img = img_template;
2444 memcpy(img + 1, debug_frame, debug_frame_size);
813da627 2445
5872bbf2
RH
2446 img->phdr.p_vaddr = buf;
2447 img->phdr.p_paddr = buf;
2448 img->phdr.p_memsz = buf_size;
813da627 2449
813da627 2450 img->shdr[1].sh_name = find_string(img->str, ".text");
5872bbf2 2451 img->shdr[1].sh_addr = buf;
813da627
RH
2452 img->shdr[1].sh_size = buf_size;
2453
5872bbf2
RH
2454 img->shdr[2].sh_name = find_string(img->str, ".debug_info");
2455 img->shdr[3].sh_name = find_string(img->str, ".debug_abbrev");
2456
2457 img->shdr[4].sh_name = find_string(img->str, ".debug_frame");
2458 img->shdr[4].sh_size = debug_frame_size;
2459
2460 img->shdr[5].sh_name = find_string(img->str, ".symtab");
2461 img->shdr[6].sh_name = find_string(img->str, ".strtab");
2462
2463 img->sym[1].st_name = find_string(img->str, "code_gen_buffer");
2464 img->sym[1].st_value = buf;
2465 img->sym[1].st_size = buf_size;
813da627 2466
5872bbf2
RH
2467 img->di.cu_low_pc = buf;
2468 img->di.cu_high_pc = buf_size;
2469 img->di.fn_low_pc = buf;
2470 img->di.fn_high_pc = buf_size;
813da627
RH
2471
2472#ifdef DEBUG_JIT
2473 /* Enable this block to be able to debug the ELF image file creation.
2474 One can use readelf, objdump, or other inspection utilities. */
2475 {
2476 FILE *f = fopen("/tmp/qemu.jit", "w+b");
2477 if (f) {
5872bbf2 2478 if (fwrite(img, img_size, 1, f) != img_size) {
813da627
RH
2479 /* Avoid stupid unused return value warning for fwrite. */
2480 }
2481 fclose(f);
2482 }
2483 }
2484#endif
2485
2486 one_entry.symfile_addr = img;
2487 one_entry.symfile_size = img_size;
2488
2489 __jit_debug_descriptor.action_flag = JIT_REGISTER_FN;
2490 __jit_debug_descriptor.relevant_entry = &one_entry;
2491 __jit_debug_descriptor.first_entry = &one_entry;
2492 __jit_debug_register_code();
2493}
2494#else
5872bbf2
RH
2495/* No support for the feature. Provide the entry point expected by exec.c,
2496 and implement the internal function we declared earlier. */
813da627
RH
2497
2498static void tcg_register_jit_int(void *buf, size_t size,
2499 void *debug_frame, size_t debug_frame_size)
2500{
2501}
2502
2503void tcg_register_jit(void *buf, size_t buf_size)
2504{
2505}
2506#endif /* ELF_HOST_MACHINE */