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