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