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