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