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