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