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