]> git.proxmox.com Git - qemu.git/blame - tcg/tcg.c
alpha-linux-user: Fix sigprocmask.
[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
a5ad5916
SW
103static void tcg_out_reloc(TCGContext *s, uint8_t *code_ptr, int type,
104 int label_index, long addend)
c896fe29
FB
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{
9678d950 553#ifdef TCG_TARGET_I386
a7812ae4 554 int call_type;
9678d950 555#endif
a7812ae4
PB
556 int i;
557 int real_args;
558 int nb_rets;
559 TCGArg *nparam;
560 *gen_opc_ptr++ = INDEX_op_call;
561 nparam = gen_opparam_ptr++;
9678d950 562#ifdef TCG_TARGET_I386
a7812ae4 563 call_type = (flags & TCG_CALL_TYPE_MASK);
9678d950 564#endif
a7812ae4
PB
565 if (ret != TCG_CALL_DUMMY_ARG) {
566#if TCG_TARGET_REG_BITS < 64
567 if (sizemask & 1) {
39cf05d3 568#ifdef TCG_TARGET_WORDS_BIGENDIAN
a7812ae4
PB
569 *gen_opparam_ptr++ = ret + 1;
570 *gen_opparam_ptr++ = ret;
39cf05d3 571#else
a7812ae4
PB
572 *gen_opparam_ptr++ = ret;
573 *gen_opparam_ptr++ = ret + 1;
39cf05d3 574#endif
a7812ae4
PB
575 nb_rets = 2;
576 } else
577#endif
578 {
579 *gen_opparam_ptr++ = ret;
580 nb_rets = 1;
c896fe29 581 }
a7812ae4
PB
582 } else {
583 nb_rets = 0;
c896fe29 584 }
a7812ae4
PB
585 real_args = 0;
586 for (i = 0; i < nargs; i++) {
587#if TCG_TARGET_REG_BITS < 64
588 if (sizemask & (2 << i)) {
c896fe29
FB
589#ifdef TCG_TARGET_I386
590 /* REGPARM case: if the third parameter is 64 bit, it is
591 allocated on the stack */
a7812ae4 592 if (i == 2 && call_type == TCG_CALL_TYPE_REGPARM) {
c896fe29
FB
593 call_type = TCG_CALL_TYPE_REGPARM_2;
594 flags = (flags & ~TCG_CALL_TYPE_MASK) | call_type;
595 }
a7812ae4 596#endif
39cf05d3
FB
597#ifdef TCG_TARGET_CALL_ALIGN_ARGS
598 /* some targets want aligned 64 bit args */
ebd486d5 599 if (real_args & 1) {
a7812ae4 600 *gen_opparam_ptr++ = TCG_CALL_DUMMY_ARG;
ebd486d5 601 real_args++;
39cf05d3
FB
602 }
603#endif
3f90f252
RH
604 /* If stack grows up, then we will be placing successive
605 arguments at lower addresses, which means we need to
606 reverse the order compared to how we would normally
607 treat either big or little-endian. For those arguments
608 that will wind up in registers, this still works for
609 HPPA (the only current STACK_GROWSUP target) since the
610 argument registers are *also* allocated in decreasing
611 order. If another such target is added, this logic may
612 have to get more complicated to differentiate between
613 stack arguments and register arguments. */
614#if defined(TCG_TARGET_WORDS_BIGENDIAN) != defined(TCG_TARGET_STACK_GROWSUP)
a7812ae4
PB
615 *gen_opparam_ptr++ = args[i] + 1;
616 *gen_opparam_ptr++ = args[i];
c896fe29 617#else
a7812ae4
PB
618 *gen_opparam_ptr++ = args[i];
619 *gen_opparam_ptr++ = args[i] + 1;
c896fe29 620#endif
a7812ae4
PB
621 real_args += 2;
622 } else
c896fe29 623#endif
a7812ae4
PB
624 {
625 *gen_opparam_ptr++ = args[i];
626 real_args++;
c896fe29
FB
627 }
628 }
a7812ae4
PB
629 *gen_opparam_ptr++ = GET_TCGV_PTR(func);
630
631 *gen_opparam_ptr++ = flags;
632
633 *nparam = (nb_rets << 16) | (real_args + 1);
634
635 /* total parameters, needed to go backward in the instruction stream */
636 *gen_opparam_ptr++ = 1 + nb_rets + real_args + 3;
c896fe29 637}
c896fe29 638
ac56dd48 639#if TCG_TARGET_REG_BITS == 32
a7812ae4 640void tcg_gen_shifti_i64(TCGv_i64 ret, TCGv_i64 arg1,
c896fe29
FB
641 int c, int right, int arith)
642{
cf60bce4 643 if (c == 0) {
a7812ae4 644 tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg1));
cf60bce4
FB
645 tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
646 } else if (c >= 32) {
c896fe29
FB
647 c -= 32;
648 if (right) {
649 if (arith) {
a7812ae4 650 tcg_gen_sari_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
ac56dd48 651 tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 31);
c896fe29 652 } else {
a7812ae4 653 tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
ac56dd48 654 tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
c896fe29
FB
655 }
656 } else {
a7812ae4
PB
657 tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_LOW(arg1), c);
658 tcg_gen_movi_i32(TCGV_LOW(ret), 0);
c896fe29
FB
659 }
660 } else {
a7812ae4 661 TCGv_i32 t0, t1;
c896fe29 662
a7812ae4
PB
663 t0 = tcg_temp_new_i32();
664 t1 = tcg_temp_new_i32();
c896fe29 665 if (right) {
ac56dd48 666 tcg_gen_shli_i32(t0, TCGV_HIGH(arg1), 32 - c);
c896fe29 667 if (arith)
ac56dd48 668 tcg_gen_sari_i32(t1, TCGV_HIGH(arg1), c);
a7812ae4 669 else
ac56dd48 670 tcg_gen_shri_i32(t1, TCGV_HIGH(arg1), c);
a7812ae4
PB
671 tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_LOW(arg1), c);
672 tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(ret), t0);
ac56dd48 673 tcg_gen_mov_i32(TCGV_HIGH(ret), t1);
c896fe29 674 } else {
a7812ae4 675 tcg_gen_shri_i32(t0, TCGV_LOW(arg1), 32 - c);
c896fe29 676 /* Note: ret can be the same as arg1, so we use t1 */
a7812ae4 677 tcg_gen_shli_i32(t1, TCGV_LOW(arg1), c);
ac56dd48
PB
678 tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c);
679 tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t0);
a7812ae4 680 tcg_gen_mov_i32(TCGV_LOW(ret), t1);
c896fe29 681 }
a7812ae4
PB
682 tcg_temp_free_i32(t0);
683 tcg_temp_free_i32(t1);
c896fe29
FB
684 }
685}
ac56dd48 686#endif
c896fe29 687
be210acb 688
8fcd3692 689static void tcg_reg_alloc_start(TCGContext *s)
c896fe29
FB
690{
691 int i;
692 TCGTemp *ts;
693 for(i = 0; i < s->nb_globals; i++) {
694 ts = &s->temps[i];
695 if (ts->fixed_reg) {
696 ts->val_type = TEMP_VAL_REG;
697 } else {
698 ts->val_type = TEMP_VAL_MEM;
699 }
700 }
e8996ee0
FB
701 for(i = s->nb_globals; i < s->nb_temps; i++) {
702 ts = &s->temps[i];
703 ts->val_type = TEMP_VAL_DEAD;
704 ts->mem_allocated = 0;
705 ts->fixed_reg = 0;
706 }
c896fe29
FB
707 for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
708 s->reg_to_temp[i] = -1;
709 }
710}
711
ac56dd48
PB
712static char *tcg_get_arg_str_idx(TCGContext *s, char *buf, int buf_size,
713 int idx)
c896fe29
FB
714{
715 TCGTemp *ts;
ac56dd48
PB
716
717 ts = &s->temps[idx];
718 if (idx < s->nb_globals) {
719 pstrcpy(buf, buf_size, ts->name);
c896fe29 720 } else {
641d5fbe
FB
721 if (ts->temp_local)
722 snprintf(buf, buf_size, "loc%d", idx - s->nb_globals);
723 else
724 snprintf(buf, buf_size, "tmp%d", idx - s->nb_globals);
c896fe29
FB
725 }
726 return buf;
727}
728
a7812ae4
PB
729char *tcg_get_arg_str_i32(TCGContext *s, char *buf, int buf_size, TCGv_i32 arg)
730{
731 return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I32(arg));
732}
733
734char *tcg_get_arg_str_i64(TCGContext *s, char *buf, int buf_size, TCGv_i64 arg)
ac56dd48 735{
a810a2de 736 return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I64(arg));
ac56dd48
PB
737}
738
e8996ee0 739static int helper_cmp(const void *p1, const void *p2)
4dc81f28 740{
e8996ee0
FB
741 const TCGHelperInfo *th1 = p1;
742 const TCGHelperInfo *th2 = p2;
743 if (th1->func < th2->func)
744 return -1;
745 else if (th1->func == th2->func)
746 return 0;
747 else
748 return 1;
4dc81f28
FB
749}
750
e8996ee0
FB
751/* find helper definition (Note: A hash table would be better) */
752static TCGHelperInfo *tcg_find_helper(TCGContext *s, tcg_target_ulong val)
4dc81f28 753{
e8996ee0 754 int m, m_min, m_max;
4dc81f28 755 TCGHelperInfo *th;
e8996ee0 756 tcg_target_ulong v;
4dc81f28 757
e8996ee0
FB
758 if (unlikely(!s->helpers_sorted)) {
759 qsort(s->helpers, s->nb_helpers, sizeof(TCGHelperInfo),
760 helper_cmp);
761 s->helpers_sorted = 1;
762 }
763
764 /* binary search */
765 m_min = 0;
766 m_max = s->nb_helpers - 1;
767 while (m_min <= m_max) {
768 m = (m_min + m_max) >> 1;
769 th = &s->helpers[m];
770 v = th->func;
771 if (v == val)
772 return th;
773 else if (val < v) {
774 m_max = m - 1;
775 } else {
776 m_min = m + 1;
4dc81f28
FB
777 }
778 }
e8996ee0 779 return NULL;
4dc81f28
FB
780}
781
f48f3ede
BS
782static const char * const cond_name[] =
783{
784 [TCG_COND_EQ] = "eq",
785 [TCG_COND_NE] = "ne",
786 [TCG_COND_LT] = "lt",
787 [TCG_COND_GE] = "ge",
788 [TCG_COND_LE] = "le",
789 [TCG_COND_GT] = "gt",
790 [TCG_COND_LTU] = "ltu",
791 [TCG_COND_GEU] = "geu",
792 [TCG_COND_LEU] = "leu",
793 [TCG_COND_GTU] = "gtu"
794};
795
c896fe29
FB
796void tcg_dump_ops(TCGContext *s, FILE *outfile)
797{
798 const uint16_t *opc_ptr;
799 const TCGArg *args;
800 TCGArg arg;
a9751609
RH
801 TCGOpcode c;
802 int i, k, nb_oargs, nb_iargs, nb_cargs, first_insn;
c896fe29
FB
803 const TCGOpDef *def;
804 char buf[128];
805
7e4597d7 806 first_insn = 1;
c896fe29
FB
807 opc_ptr = gen_opc_buf;
808 args = gen_opparam_buf;
809 while (opc_ptr < gen_opc_ptr) {
810 c = *opc_ptr++;
811 def = &tcg_op_defs[c];
7e4597d7
FB
812 if (c == INDEX_op_debug_insn_start) {
813 uint64_t pc;
814#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
815 pc = ((uint64_t)args[1] << 32) | args[0];
816#else
817 pc = args[0];
818#endif
819 if (!first_insn)
820 fprintf(outfile, "\n");
821 fprintf(outfile, " ---- 0x%" PRIx64, pc);
822 first_insn = 0;
823 nb_oargs = def->nb_oargs;
824 nb_iargs = def->nb_iargs;
825 nb_cargs = def->nb_cargs;
826 } else if (c == INDEX_op_call) {
c896fe29 827 TCGArg arg;
4dc81f28 828
c896fe29
FB
829 /* variable number of arguments */
830 arg = *args++;
831 nb_oargs = arg >> 16;
832 nb_iargs = arg & 0xffff;
833 nb_cargs = def->nb_cargs;
c896fe29 834
7e4597d7
FB
835 fprintf(outfile, " %s ", def->name);
836
b03cce8e 837 /* function name */
ac56dd48 838 fprintf(outfile, "%s",
e8996ee0 839 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + nb_iargs - 1]));
b03cce8e
FB
840 /* flags */
841 fprintf(outfile, ",$0x%" TCG_PRIlx,
842 args[nb_oargs + nb_iargs]);
843 /* nb out args */
844 fprintf(outfile, ",$%d", nb_oargs);
845 for(i = 0; i < nb_oargs; i++) {
846 fprintf(outfile, ",");
847 fprintf(outfile, "%s",
848 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[i]));
849 }
850 for(i = 0; i < (nb_iargs - 1); i++) {
c896fe29 851 fprintf(outfile, ",");
39cf05d3
FB
852 if (args[nb_oargs + i] == TCG_CALL_DUMMY_ARG) {
853 fprintf(outfile, "<dummy>");
854 } else {
855 fprintf(outfile, "%s",
856 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + i]));
857 }
b03cce8e 858 }
e8996ee0
FB
859 } else if (c == INDEX_op_movi_i32
860#if TCG_TARGET_REG_BITS == 64
861 || c == INDEX_op_movi_i64
862#endif
863 ) {
864 tcg_target_ulong val;
865 TCGHelperInfo *th;
866
867 nb_oargs = def->nb_oargs;
868 nb_iargs = def->nb_iargs;
869 nb_cargs = def->nb_cargs;
870 fprintf(outfile, " %s %s,$", def->name,
871 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[0]));
872 val = args[1];
873 th = tcg_find_helper(s, val);
874 if (th) {
3e9a474e 875 fprintf(outfile, "%s", th->name);
e8996ee0
FB
876 } else {
877 if (c == INDEX_op_movi_i32)
878 fprintf(outfile, "0x%x", (uint32_t)val);
879 else
880 fprintf(outfile, "0x%" PRIx64 , (uint64_t)val);
881 }
b03cce8e 882 } else {
7e4597d7 883 fprintf(outfile, " %s ", def->name);
b03cce8e
FB
884 if (c == INDEX_op_nopn) {
885 /* variable number of arguments */
886 nb_cargs = *args;
887 nb_oargs = 0;
888 nb_iargs = 0;
889 } else {
890 nb_oargs = def->nb_oargs;
891 nb_iargs = def->nb_iargs;
892 nb_cargs = def->nb_cargs;
893 }
894
895 k = 0;
896 for(i = 0; i < nb_oargs; i++) {
897 if (k != 0)
898 fprintf(outfile, ",");
899 fprintf(outfile, "%s",
900 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
901 }
902 for(i = 0; i < nb_iargs; i++) {
903 if (k != 0)
904 fprintf(outfile, ",");
905 fprintf(outfile, "%s",
906 tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
907 }
be210acb
RH
908 switch (c) {
909 case INDEX_op_brcond_i32:
910#if TCG_TARGET_REG_BITS == 32
911 case INDEX_op_brcond2_i32:
912#elif TCG_TARGET_REG_BITS == 64
913 case INDEX_op_brcond_i64:
914#endif
915 case INDEX_op_setcond_i32:
f48f3ede 916#if TCG_TARGET_REG_BITS == 32
be210acb 917 case INDEX_op_setcond2_i32:
f48f3ede 918#elif TCG_TARGET_REG_BITS == 64
be210acb 919 case INDEX_op_setcond_i64:
f48f3ede 920#endif
f48f3ede
BS
921 if (args[k] < ARRAY_SIZE(cond_name) && cond_name[args[k]])
922 fprintf(outfile, ",%s", cond_name[args[k++]]);
923 else
924 fprintf(outfile, ",$0x%" TCG_PRIlx, args[k++]);
925 i = 1;
be210acb
RH
926 break;
927 default:
f48f3ede 928 i = 0;
be210acb
RH
929 break;
930 }
f48f3ede 931 for(; i < nb_cargs; i++) {
b03cce8e
FB
932 if (k != 0)
933 fprintf(outfile, ",");
934 arg = args[k++];
935 fprintf(outfile, "$0x%" TCG_PRIlx, arg);
936 }
c896fe29
FB
937 }
938 fprintf(outfile, "\n");
939 args += nb_iargs + nb_oargs + nb_cargs;
940 }
941}
942
943/* we give more priority to constraints with less registers */
944static int get_constraint_priority(const TCGOpDef *def, int k)
945{
946 const TCGArgConstraint *arg_ct;
947
948 int i, n;
949 arg_ct = &def->args_ct[k];
950 if (arg_ct->ct & TCG_CT_ALIAS) {
951 /* an alias is equivalent to a single register */
952 n = 1;
953 } else {
954 if (!(arg_ct->ct & TCG_CT_REG))
955 return 0;
956 n = 0;
957 for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
958 if (tcg_regset_test_reg(arg_ct->u.regs, i))
959 n++;
960 }
961 }
962 return TCG_TARGET_NB_REGS - n + 1;
963}
964
965/* sort from highest priority to lowest */
966static void sort_constraints(TCGOpDef *def, int start, int n)
967{
968 int i, j, p1, p2, tmp;
969
970 for(i = 0; i < n; i++)
971 def->sorted_args[start + i] = start + i;
972 if (n <= 1)
973 return;
974 for(i = 0; i < n - 1; i++) {
975 for(j = i + 1; j < n; j++) {
976 p1 = get_constraint_priority(def, def->sorted_args[start + i]);
977 p2 = get_constraint_priority(def, def->sorted_args[start + j]);
978 if (p1 < p2) {
979 tmp = def->sorted_args[start + i];
980 def->sorted_args[start + i] = def->sorted_args[start + j];
981 def->sorted_args[start + j] = tmp;
982 }
983 }
984 }
985}
986
987void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs)
988{
a9751609 989 TCGOpcode op;
c896fe29
FB
990 TCGOpDef *def;
991 const char *ct_str;
992 int i, nb_args;
993
994 for(;;) {
a9751609 995 if (tdefs->op == (TCGOpcode)-1)
c896fe29
FB
996 break;
997 op = tdefs->op;
998 assert(op >= 0 && op < NB_OPS);
999 def = &tcg_op_defs[op];
c68aaa18
SW
1000#if defined(CONFIG_DEBUG_TCG)
1001 /* Duplicate entry in op definitions? */
1002 assert(!def->used);
1003 def->used = 1;
1004#endif
c896fe29
FB
1005 nb_args = def->nb_iargs + def->nb_oargs;
1006 for(i = 0; i < nb_args; i++) {
1007 ct_str = tdefs->args_ct_str[i];
c68aaa18
SW
1008 /* Incomplete TCGTargetOpDef entry? */
1009 assert(ct_str != NULL);
c896fe29
FB
1010 tcg_regset_clear(def->args_ct[i].u.regs);
1011 def->args_ct[i].ct = 0;
1012 if (ct_str[0] >= '0' && ct_str[0] <= '9') {
1013 int oarg;
1014 oarg = ct_str[0] - '0';
1015 assert(oarg < def->nb_oargs);
1016 assert(def->args_ct[oarg].ct & TCG_CT_REG);
1017 /* TCG_CT_ALIAS is for the output arguments. The input
5ff9d6a4 1018 argument is tagged with TCG_CT_IALIAS. */
c896fe29 1019 def->args_ct[i] = def->args_ct[oarg];
5ff9d6a4
FB
1020 def->args_ct[oarg].ct = TCG_CT_ALIAS;
1021 def->args_ct[oarg].alias_index = i;
c896fe29 1022 def->args_ct[i].ct |= TCG_CT_IALIAS;
5ff9d6a4 1023 def->args_ct[i].alias_index = oarg;
c896fe29
FB
1024 } else {
1025 for(;;) {
1026 if (*ct_str == '\0')
1027 break;
1028 switch(*ct_str) {
1029 case 'i':
1030 def->args_ct[i].ct |= TCG_CT_CONST;
1031 ct_str++;
1032 break;
1033 default:
1034 if (target_parse_constraint(&def->args_ct[i], &ct_str) < 0) {
1035 fprintf(stderr, "Invalid constraint '%s' for arg %d of operation '%s'\n",
1036 ct_str, i, def->name);
1037 exit(1);
1038 }
1039 }
1040 }
1041 }
1042 }
1043
c68aaa18
SW
1044 /* TCGTargetOpDef entry with too much information? */
1045 assert(i == TCG_MAX_OP_ARGS || tdefs->args_ct_str[i] == NULL);
1046
c896fe29
FB
1047 /* sort the constraints (XXX: this is just an heuristic) */
1048 sort_constraints(def, 0, def->nb_oargs);
1049 sort_constraints(def, def->nb_oargs, def->nb_iargs);
1050
1051#if 0
1052 {
1053 int i;
1054
1055 printf("%s: sorted=", def->name);
1056 for(i = 0; i < def->nb_oargs + def->nb_iargs; i++)
1057 printf(" %d", def->sorted_args[i]);
1058 printf("\n");
1059 }
1060#endif
1061 tdefs++;
1062 }
1063
c68aaa18 1064#if defined(CONFIG_DEBUG_TCG)
a9751609 1065 i = 0;
c68aaa18
SW
1066 for (op = 0; op < ARRAY_SIZE(tcg_op_defs); op++) {
1067 if (op < INDEX_op_call || op == INDEX_op_debug_insn_start) {
1068 /* Wrong entry in op definitions? */
a9751609
RH
1069 if (tcg_op_defs[op].used) {
1070 fprintf(stderr, "Invalid op definition for %s\n",
1071 tcg_op_defs[op].name);
1072 i = 1;
1073 }
c68aaa18
SW
1074 } else {
1075 /* Missing entry in op definitions? */
a9751609
RH
1076 if (!tcg_op_defs[op].used) {
1077 fprintf(stderr, "Missing op definition for %s\n",
1078 tcg_op_defs[op].name);
1079 i = 1;
1080 }
c68aaa18
SW
1081 }
1082 }
a9751609
RH
1083 if (i == 1) {
1084 tcg_abort();
1085 }
c68aaa18 1086#endif
c896fe29
FB
1087}
1088
1089#ifdef USE_LIVENESS_ANALYSIS
1090
1091/* set a nop for an operation using 'nb_args' */
1092static inline void tcg_set_nop(TCGContext *s, uint16_t *opc_ptr,
1093 TCGArg *args, int nb_args)
1094{
1095 if (nb_args == 0) {
1096 *opc_ptr = INDEX_op_nop;
1097 } else {
1098 *opc_ptr = INDEX_op_nopn;
1099 args[0] = nb_args;
1100 args[nb_args - 1] = nb_args;
1101 }
1102}
1103
641d5fbe
FB
1104/* liveness analysis: end of function: globals are live, temps are
1105 dead. */
1106/* XXX: at this stage, not used as there would be little gains because
1107 most TBs end with a conditional jump. */
1108static inline void tcg_la_func_end(TCGContext *s, uint8_t *dead_temps)
c896fe29
FB
1109{
1110 memset(dead_temps, 0, s->nb_globals);
1111 memset(dead_temps + s->nb_globals, 1, s->nb_temps - s->nb_globals);
1112}
1113
641d5fbe
FB
1114/* liveness analysis: end of basic block: globals are live, temps are
1115 dead, local temps are live. */
1116static inline void tcg_la_bb_end(TCGContext *s, uint8_t *dead_temps)
1117{
1118 int i;
1119 TCGTemp *ts;
1120
1121 memset(dead_temps, 0, s->nb_globals);
1122 ts = &s->temps[s->nb_globals];
1123 for(i = s->nb_globals; i < s->nb_temps; i++) {
1124 if (ts->temp_local)
1125 dead_temps[i] = 0;
1126 else
1127 dead_temps[i] = 1;
1128 ts++;
1129 }
1130}
1131
c896fe29
FB
1132/* Liveness analysis : update the opc_dead_iargs array to tell if a
1133 given input arguments is dead. Instructions updating dead
1134 temporaries are removed. */
8fcd3692 1135static void tcg_liveness_analysis(TCGContext *s)
c896fe29 1136{
a9751609
RH
1137 int i, op_index, nb_args, nb_iargs, nb_oargs, arg, nb_ops;
1138 TCGOpcode op;
c896fe29
FB
1139 TCGArg *args;
1140 const TCGOpDef *def;
1141 uint8_t *dead_temps;
1142 unsigned int dead_iargs;
1143
1144 gen_opc_ptr++; /* skip end */
1145
1146 nb_ops = gen_opc_ptr - gen_opc_buf;
1147
94f4af02 1148 s->op_dead_iargs = tcg_malloc(nb_ops * sizeof(uint16_t));
c896fe29
FB
1149
1150 dead_temps = tcg_malloc(s->nb_temps);
1151 memset(dead_temps, 1, s->nb_temps);
1152
1153 args = gen_opparam_ptr;
1154 op_index = nb_ops - 1;
1155 while (op_index >= 0) {
1156 op = gen_opc_buf[op_index];
1157 def = &tcg_op_defs[op];
1158 switch(op) {
1159 case INDEX_op_call:
c6e113f5
FB
1160 {
1161 int call_flags;
c896fe29 1162
c6e113f5
FB
1163 nb_args = args[-1];
1164 args -= nb_args;
1165 nb_iargs = args[0] & 0xffff;
1166 nb_oargs = args[0] >> 16;
1167 args++;
1168 call_flags = args[nb_oargs + nb_iargs];
1169
1170 /* pure functions can be removed if their result is not
1171 used */
1172 if (call_flags & TCG_CALL_PURE) {
1173 for(i = 0; i < nb_oargs; i++) {
1174 arg = args[i];
1175 if (!dead_temps[arg])
1176 goto do_not_remove_call;
1177 }
1178 tcg_set_nop(s, gen_opc_buf + op_index,
1179 args - 1, nb_args);
1180 } else {
1181 do_not_remove_call:
c896fe29 1182
c6e113f5
FB
1183 /* output args are dead */
1184 for(i = 0; i < nb_oargs; i++) {
1185 arg = args[i];
1186 dead_temps[arg] = 1;
1187 }
1188
b9c18f56
AJ
1189 if (!(call_flags & TCG_CALL_CONST)) {
1190 /* globals are live (they may be used by the call) */
1191 memset(dead_temps, 0, s->nb_globals);
1192 }
1193
c6e113f5
FB
1194 /* input args are live */
1195 dead_iargs = 0;
1196 for(i = 0; i < nb_iargs; i++) {
1197 arg = args[i + nb_oargs];
39cf05d3
FB
1198 if (arg != TCG_CALL_DUMMY_ARG) {
1199 if (dead_temps[arg]) {
1200 dead_iargs |= (1 << i);
1201 }
1202 dead_temps[arg] = 0;
c6e113f5 1203 }
c6e113f5
FB
1204 }
1205 s->op_dead_iargs[op_index] = dead_iargs;
c896fe29 1206 }
c6e113f5 1207 args--;
c896fe29 1208 }
c896fe29
FB
1209 break;
1210 case INDEX_op_set_label:
1211 args--;
1212 /* mark end of basic block */
1213 tcg_la_bb_end(s, dead_temps);
1214 break;
7e4597d7
FB
1215 case INDEX_op_debug_insn_start:
1216 args -= def->nb_args;
1217 break;
c896fe29
FB
1218 case INDEX_op_nopn:
1219 nb_args = args[-1];
1220 args -= nb_args;
1221 break;
5ff9d6a4
FB
1222 case INDEX_op_discard:
1223 args--;
1224 /* mark the temporary as dead */
1225 dead_temps[args[0]] = 1;
1226 break;
c896fe29
FB
1227 case INDEX_op_end:
1228 break;
1229 /* XXX: optimize by hardcoding common cases (e.g. triadic ops) */
1230 default:
49516bc0
AJ
1231 args -= def->nb_args;
1232 nb_iargs = def->nb_iargs;
1233 nb_oargs = def->nb_oargs;
c896fe29 1234
49516bc0
AJ
1235 /* Test if the operation can be removed because all
1236 its outputs are dead. We assume that nb_oargs == 0
1237 implies side effects */
1238 if (!(def->flags & TCG_OPF_SIDE_EFFECTS) && nb_oargs != 0) {
1239 for(i = 0; i < nb_oargs; i++) {
1240 arg = args[i];
1241 if (!dead_temps[arg])
1242 goto do_not_remove;
1243 }
1244 tcg_set_nop(s, gen_opc_buf + op_index, args, def->nb_args);
c896fe29 1245#ifdef CONFIG_PROFILER
49516bc0 1246 s->del_op_count++;
c896fe29 1247#endif
49516bc0
AJ
1248 } else {
1249 do_not_remove:
c896fe29 1250
49516bc0
AJ
1251 /* output args are dead */
1252 for(i = 0; i < nb_oargs; i++) {
1253 arg = args[i];
1254 dead_temps[arg] = 1;
1255 }
1256
1257 /* if end of basic block, update */
1258 if (def->flags & TCG_OPF_BB_END) {
1259 tcg_la_bb_end(s, dead_temps);
1260 } else if (def->flags & TCG_OPF_CALL_CLOBBER) {
1261 /* globals are live */
1262 memset(dead_temps, 0, s->nb_globals);
1263 }
1264
1265 /* input args are live */
1266 dead_iargs = 0;
1267 for(i = 0; i < nb_iargs; i++) {
1268 arg = args[i + nb_oargs];
1269 if (dead_temps[arg]) {
1270 dead_iargs |= (1 << i);
c896fe29 1271 }
49516bc0 1272 dead_temps[arg] = 0;
c896fe29 1273 }
49516bc0 1274 s->op_dead_iargs[op_index] = dead_iargs;
c896fe29
FB
1275 }
1276 break;
1277 }
1278 op_index--;
1279 }
1280
1281 if (args != gen_opparam_buf)
1282 tcg_abort();
1283}
1284#else
1285/* dummy liveness analysis */
655feed5 1286static void tcg_liveness_analysis(TCGContext *s)
c896fe29
FB
1287{
1288 int nb_ops;
1289 nb_ops = gen_opc_ptr - gen_opc_buf;
1290
1291 s->op_dead_iargs = tcg_malloc(nb_ops * sizeof(uint16_t));
1292 memset(s->op_dead_iargs, 0, nb_ops * sizeof(uint16_t));
1293}
1294#endif
1295
1296#ifndef NDEBUG
1297static void dump_regs(TCGContext *s)
1298{
1299 TCGTemp *ts;
1300 int i;
1301 char buf[64];
1302
1303 for(i = 0; i < s->nb_temps; i++) {
1304 ts = &s->temps[i];
ac56dd48 1305 printf(" %10s: ", tcg_get_arg_str_idx(s, buf, sizeof(buf), i));
c896fe29
FB
1306 switch(ts->val_type) {
1307 case TEMP_VAL_REG:
1308 printf("%s", tcg_target_reg_names[ts->reg]);
1309 break;
1310 case TEMP_VAL_MEM:
1311 printf("%d(%s)", (int)ts->mem_offset, tcg_target_reg_names[ts->mem_reg]);
1312 break;
1313 case TEMP_VAL_CONST:
1314 printf("$0x%" TCG_PRIlx, ts->val);
1315 break;
1316 case TEMP_VAL_DEAD:
1317 printf("D");
1318 break;
1319 default:
1320 printf("???");
1321 break;
1322 }
1323 printf("\n");
1324 }
1325
1326 for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
1327 if (s->reg_to_temp[i] >= 0) {
1328 printf("%s: %s\n",
1329 tcg_target_reg_names[i],
ac56dd48 1330 tcg_get_arg_str_idx(s, buf, sizeof(buf), s->reg_to_temp[i]));
c896fe29
FB
1331 }
1332 }
1333}
1334
1335static void check_regs(TCGContext *s)
1336{
1337 int reg, k;
1338 TCGTemp *ts;
1339 char buf[64];
1340
1341 for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1342 k = s->reg_to_temp[reg];
1343 if (k >= 0) {
1344 ts = &s->temps[k];
1345 if (ts->val_type != TEMP_VAL_REG ||
1346 ts->reg != reg) {
1347 printf("Inconsistency for register %s:\n",
1348 tcg_target_reg_names[reg]);
b03cce8e 1349 goto fail;
c896fe29
FB
1350 }
1351 }
1352 }
1353 for(k = 0; k < s->nb_temps; k++) {
1354 ts = &s->temps[k];
1355 if (ts->val_type == TEMP_VAL_REG &&
1356 !ts->fixed_reg &&
1357 s->reg_to_temp[ts->reg] != k) {
1358 printf("Inconsistency for temp %s:\n",
ac56dd48 1359 tcg_get_arg_str_idx(s, buf, sizeof(buf), k));
b03cce8e 1360 fail:
c896fe29
FB
1361 printf("reg state:\n");
1362 dump_regs(s);
1363 tcg_abort();
1364 }
1365 }
1366}
1367#endif
1368
1369static void temp_allocate_frame(TCGContext *s, int temp)
1370{
1371 TCGTemp *ts;
1372 ts = &s->temps[temp];
1373 s->current_frame_offset = (s->current_frame_offset + sizeof(tcg_target_long) - 1) & ~(sizeof(tcg_target_long) - 1);
1374 if (s->current_frame_offset + sizeof(tcg_target_long) > s->frame_end)
5ff9d6a4 1375 tcg_abort();
c896fe29
FB
1376 ts->mem_offset = s->current_frame_offset;
1377 ts->mem_reg = s->frame_reg;
1378 ts->mem_allocated = 1;
1379 s->current_frame_offset += sizeof(tcg_target_long);
1380}
1381
1382/* free register 'reg' by spilling the corresponding temporary if necessary */
1383static void tcg_reg_free(TCGContext *s, int reg)
1384{
1385 TCGTemp *ts;
1386 int temp;
1387
1388 temp = s->reg_to_temp[reg];
1389 if (temp != -1) {
1390 ts = &s->temps[temp];
1391 assert(ts->val_type == TEMP_VAL_REG);
1392 if (!ts->mem_coherent) {
1393 if (!ts->mem_allocated)
1394 temp_allocate_frame(s, temp);
e4d5434c 1395 tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
c896fe29
FB
1396 }
1397 ts->val_type = TEMP_VAL_MEM;
1398 s->reg_to_temp[reg] = -1;
1399 }
1400}
1401
1402/* Allocate a register belonging to reg1 & ~reg2 */
1403static int tcg_reg_alloc(TCGContext *s, TCGRegSet reg1, TCGRegSet reg2)
1404{
1405 int i, reg;
1406 TCGRegSet reg_ct;
1407
1408 tcg_regset_andnot(reg_ct, reg1, reg2);
1409
1410 /* first try free registers */
0954d0d9 1411 for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
c896fe29
FB
1412 reg = tcg_target_reg_alloc_order[i];
1413 if (tcg_regset_test_reg(reg_ct, reg) && s->reg_to_temp[reg] == -1)
1414 return reg;
1415 }
1416
1417 /* XXX: do better spill choice */
0954d0d9 1418 for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
c896fe29
FB
1419 reg = tcg_target_reg_alloc_order[i];
1420 if (tcg_regset_test_reg(reg_ct, reg)) {
1421 tcg_reg_free(s, reg);
1422 return reg;
1423 }
1424 }
1425
1426 tcg_abort();
1427}
1428
641d5fbe
FB
1429/* save a temporary to memory. 'allocated_regs' is used in case a
1430 temporary registers needs to be allocated to store a constant. */
1431static void temp_save(TCGContext *s, int temp, TCGRegSet allocated_regs)
1432{
1433 TCGTemp *ts;
1434 int reg;
1435
1436 ts = &s->temps[temp];
1437 if (!ts->fixed_reg) {
1438 switch(ts->val_type) {
1439 case TEMP_VAL_REG:
1440 tcg_reg_free(s, ts->reg);
1441 break;
1442 case TEMP_VAL_DEAD:
1443 ts->val_type = TEMP_VAL_MEM;
1444 break;
1445 case TEMP_VAL_CONST:
d6859202
AJ
1446 reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type],
1447 allocated_regs);
641d5fbe
FB
1448 if (!ts->mem_allocated)
1449 temp_allocate_frame(s, temp);
d6859202
AJ
1450 tcg_out_movi(s, ts->type, reg, ts->val);
1451 tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
641d5fbe
FB
1452 ts->val_type = TEMP_VAL_MEM;
1453 break;
1454 case TEMP_VAL_MEM:
1455 break;
1456 default:
1457 tcg_abort();
1458 }
1459 }
1460}
1461
e5097dc8 1462/* save globals to their cannonical location and assume they can be
e8996ee0
FB
1463 modified be the following code. 'allocated_regs' is used in case a
1464 temporary registers needs to be allocated to store a constant. */
1465static void save_globals(TCGContext *s, TCGRegSet allocated_regs)
c896fe29 1466{
641d5fbe 1467 int i;
c896fe29
FB
1468
1469 for(i = 0; i < s->nb_globals; i++) {
641d5fbe 1470 temp_save(s, i, allocated_regs);
c896fe29 1471 }
e5097dc8
FB
1472}
1473
1474/* at the end of a basic block, we assume all temporaries are dead and
e8996ee0
FB
1475 all globals are stored at their canonical location. */
1476static void tcg_reg_alloc_bb_end(TCGContext *s, TCGRegSet allocated_regs)
e5097dc8
FB
1477{
1478 TCGTemp *ts;
1479 int i;
1480
c896fe29
FB
1481 for(i = s->nb_globals; i < s->nb_temps; i++) {
1482 ts = &s->temps[i];
641d5fbe
FB
1483 if (ts->temp_local) {
1484 temp_save(s, i, allocated_regs);
1485 } else {
1486 if (ts->val_type == TEMP_VAL_REG) {
1487 s->reg_to_temp[ts->reg] = -1;
1488 }
1489 ts->val_type = TEMP_VAL_DEAD;
c896fe29
FB
1490 }
1491 }
e8996ee0
FB
1492
1493 save_globals(s, allocated_regs);
c896fe29
FB
1494}
1495
1496#define IS_DEAD_IARG(n) ((dead_iargs >> (n)) & 1)
1497
e8996ee0
FB
1498static void tcg_reg_alloc_movi(TCGContext *s, const TCGArg *args)
1499{
1500 TCGTemp *ots;
1501 tcg_target_ulong val;
1502
1503 ots = &s->temps[args[0]];
1504 val = args[1];
1505
1506 if (ots->fixed_reg) {
1507 /* for fixed registers, we do not do any constant
1508 propagation */
1509 tcg_out_movi(s, ots->type, ots->reg, val);
1510 } else {
1235fc06 1511 /* The movi is not explicitly generated here */
e8996ee0
FB
1512 if (ots->val_type == TEMP_VAL_REG)
1513 s->reg_to_temp[ots->reg] = -1;
1514 ots->val_type = TEMP_VAL_CONST;
1515 ots->val = val;
1516 }
1517}
1518
c896fe29
FB
1519static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
1520 const TCGArg *args,
1521 unsigned int dead_iargs)
1522{
1523 TCGTemp *ts, *ots;
1524 int reg;
1525 const TCGArgConstraint *arg_ct;
1526
1527 ots = &s->temps[args[0]];
1528 ts = &s->temps[args[1]];
1529 arg_ct = &def->args_ct[0];
1530
e8996ee0 1531 /* XXX: always mark arg dead if IS_DEAD_IARG(0) */
c896fe29
FB
1532 if (ts->val_type == TEMP_VAL_REG) {
1533 if (IS_DEAD_IARG(0) && !ts->fixed_reg && !ots->fixed_reg) {
1534 /* the mov can be suppressed */
1535 if (ots->val_type == TEMP_VAL_REG)
1536 s->reg_to_temp[ots->reg] = -1;
1537 reg = ts->reg;
1538 s->reg_to_temp[reg] = -1;
1539 ts->val_type = TEMP_VAL_DEAD;
1540 } else {
1541 if (ots->val_type == TEMP_VAL_REG) {
1542 reg = ots->reg;
1543 } else {
1544 reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1545 }
1546 if (ts->reg != reg) {
1547 tcg_out_mov(s, reg, ts->reg);
1548 }
1549 }
1550 } else if (ts->val_type == TEMP_VAL_MEM) {
1551 if (ots->val_type == TEMP_VAL_REG) {
1552 reg = ots->reg;
1553 } else {
1554 reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1555 }
e4d5434c 1556 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
c896fe29 1557 } else if (ts->val_type == TEMP_VAL_CONST) {
e8996ee0 1558 if (ots->fixed_reg) {
c896fe29 1559 reg = ots->reg;
e8996ee0 1560 tcg_out_movi(s, ots->type, reg, ts->val);
c896fe29 1561 } else {
e8996ee0
FB
1562 /* propagate constant */
1563 if (ots->val_type == TEMP_VAL_REG)
1564 s->reg_to_temp[ots->reg] = -1;
1565 ots->val_type = TEMP_VAL_CONST;
1566 ots->val = ts->val;
1567 return;
c896fe29 1568 }
c896fe29
FB
1569 } else {
1570 tcg_abort();
1571 }
1572 s->reg_to_temp[reg] = args[0];
1573 ots->reg = reg;
1574 ots->val_type = TEMP_VAL_REG;
1575 ots->mem_coherent = 0;
1576}
1577
1578static void tcg_reg_alloc_op(TCGContext *s,
a9751609 1579 const TCGOpDef *def, TCGOpcode opc,
c896fe29
FB
1580 const TCGArg *args,
1581 unsigned int dead_iargs)
1582{
1583 TCGRegSet allocated_regs;
1584 int i, k, nb_iargs, nb_oargs, reg;
1585 TCGArg arg;
1586 const TCGArgConstraint *arg_ct;
1587 TCGTemp *ts;
1588 TCGArg new_args[TCG_MAX_OP_ARGS];
1589 int const_args[TCG_MAX_OP_ARGS];
1590
1591 nb_oargs = def->nb_oargs;
1592 nb_iargs = def->nb_iargs;
1593
1594 /* copy constants */
1595 memcpy(new_args + nb_oargs + nb_iargs,
1596 args + nb_oargs + nb_iargs,
1597 sizeof(TCGArg) * def->nb_cargs);
1598
1599 /* satisfy input constraints */
1600 tcg_regset_set(allocated_regs, s->reserved_regs);
1601 for(k = 0; k < nb_iargs; k++) {
1602 i = def->sorted_args[nb_oargs + k];
1603 arg = args[i];
1604 arg_ct = &def->args_ct[i];
1605 ts = &s->temps[arg];
1606 if (ts->val_type == TEMP_VAL_MEM) {
1607 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
e4d5434c 1608 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
c896fe29
FB
1609 ts->val_type = TEMP_VAL_REG;
1610 ts->reg = reg;
1611 ts->mem_coherent = 1;
1612 s->reg_to_temp[reg] = arg;
1613 } else if (ts->val_type == TEMP_VAL_CONST) {
1614 if (tcg_target_const_match(ts->val, arg_ct)) {
1615 /* constant is OK for instruction */
1616 const_args[i] = 1;
1617 new_args[i] = ts->val;
1618 goto iarg_end;
1619 } else {
e8996ee0 1620 /* need to move to a register */
c896fe29
FB
1621 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1622 tcg_out_movi(s, ts->type, reg, ts->val);
e8996ee0
FB
1623 ts->val_type = TEMP_VAL_REG;
1624 ts->reg = reg;
1625 ts->mem_coherent = 0;
1626 s->reg_to_temp[reg] = arg;
c896fe29
FB
1627 }
1628 }
1629 assert(ts->val_type == TEMP_VAL_REG);
5ff9d6a4
FB
1630 if (arg_ct->ct & TCG_CT_IALIAS) {
1631 if (ts->fixed_reg) {
1632 /* if fixed register, we must allocate a new register
1633 if the alias is not the same register */
1634 if (arg != args[arg_ct->alias_index])
1635 goto allocate_in_reg;
1636 } else {
1637 /* if the input is aliased to an output and if it is
1638 not dead after the instruction, we must allocate
1639 a new register and move it */
1640 if (!IS_DEAD_IARG(i - nb_oargs))
1641 goto allocate_in_reg;
1642 }
c896fe29
FB
1643 }
1644 reg = ts->reg;
1645 if (tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1646 /* nothing to do : the constraint is satisfied */
1647 } else {
1648 allocate_in_reg:
1649 /* allocate a new register matching the constraint
1650 and move the temporary register into it */
1651 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1652 tcg_out_mov(s, reg, ts->reg);
1653 }
c896fe29
FB
1654 new_args[i] = reg;
1655 const_args[i] = 0;
1656 tcg_regset_set_reg(allocated_regs, reg);
1657 iarg_end: ;
1658 }
1659
e8996ee0
FB
1660 if (def->flags & TCG_OPF_BB_END) {
1661 tcg_reg_alloc_bb_end(s, allocated_regs);
1662 } else {
1663 /* mark dead temporaries and free the associated registers */
1664 for(i = 0; i < nb_iargs; i++) {
1665 arg = args[nb_oargs + i];
1666 if (IS_DEAD_IARG(i)) {
1667 ts = &s->temps[arg];
1668 if (!ts->fixed_reg) {
1669 if (ts->val_type == TEMP_VAL_REG)
1670 s->reg_to_temp[ts->reg] = -1;
1671 ts->val_type = TEMP_VAL_DEAD;
1672 }
c896fe29
FB
1673 }
1674 }
e8996ee0
FB
1675
1676 if (def->flags & TCG_OPF_CALL_CLOBBER) {
1677 /* XXX: permit generic clobber register list ? */
1678 for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1679 if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
1680 tcg_reg_free(s, reg);
1681 }
c896fe29 1682 }
e8996ee0
FB
1683 /* XXX: for load/store we could do that only for the slow path
1684 (i.e. when a memory callback is called) */
1685
1686 /* store globals and free associated registers (we assume the insn
1687 can modify any global. */
1688 save_globals(s, allocated_regs);
c896fe29 1689 }
e8996ee0
FB
1690
1691 /* satisfy the output constraints */
1692 tcg_regset_set(allocated_regs, s->reserved_regs);
1693 for(k = 0; k < nb_oargs; k++) {
1694 i = def->sorted_args[k];
1695 arg = args[i];
1696 arg_ct = &def->args_ct[i];
1697 ts = &s->temps[arg];
1698 if (arg_ct->ct & TCG_CT_ALIAS) {
1699 reg = new_args[arg_ct->alias_index];
1700 } else {
1701 /* if fixed register, we try to use it */
1702 reg = ts->reg;
1703 if (ts->fixed_reg &&
1704 tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1705 goto oarg_end;
1706 }
1707 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
c896fe29 1708 }
e8996ee0
FB
1709 tcg_regset_set_reg(allocated_regs, reg);
1710 /* if a fixed register is used, then a move will be done afterwards */
1711 if (!ts->fixed_reg) {
1712 if (ts->val_type == TEMP_VAL_REG)
1713 s->reg_to_temp[ts->reg] = -1;
1714 ts->val_type = TEMP_VAL_REG;
1715 ts->reg = reg;
1716 /* temp value is modified, so the value kept in memory is
1717 potentially not the same */
1718 ts->mem_coherent = 0;
1719 s->reg_to_temp[reg] = arg;
1720 }
1721 oarg_end:
1722 new_args[i] = reg;
c896fe29 1723 }
c896fe29
FB
1724 }
1725
c896fe29
FB
1726 /* emit instruction */
1727 tcg_out_op(s, opc, new_args, const_args);
1728
1729 /* move the outputs in the correct register if needed */
1730 for(i = 0; i < nb_oargs; i++) {
1731 ts = &s->temps[args[i]];
1732 reg = new_args[i];
1733 if (ts->fixed_reg && ts->reg != reg) {
1734 tcg_out_mov(s, ts->reg, reg);
1735 }
1736 }
1737}
1738
b03cce8e
FB
1739#ifdef TCG_TARGET_STACK_GROWSUP
1740#define STACK_DIR(x) (-(x))
1741#else
1742#define STACK_DIR(x) (x)
1743#endif
1744
c896fe29 1745static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
a9751609 1746 TCGOpcode opc, const TCGArg *args,
c896fe29
FB
1747 unsigned int dead_iargs)
1748{
1749 int nb_iargs, nb_oargs, flags, nb_regs, i, reg, nb_params;
1750 TCGArg arg, func_arg;
1751 TCGTemp *ts;
f54b3f92 1752 tcg_target_long stack_offset, call_stack_size, func_addr;
b03cce8e 1753 int const_func_arg, allocate_args;
c896fe29
FB
1754 TCGRegSet allocated_regs;
1755 const TCGArgConstraint *arg_ct;
1756
1757 arg = *args++;
1758
1759 nb_oargs = arg >> 16;
1760 nb_iargs = arg & 0xffff;
1761 nb_params = nb_iargs - 1;
1762
1763 flags = args[nb_oargs + nb_iargs];
1764
1765 nb_regs = tcg_target_get_call_iarg_regs_count(flags);
1766 if (nb_regs > nb_params)
1767 nb_regs = nb_params;
1768
1769 /* assign stack slots first */
1770 /* XXX: preallocate call stack */
1771 call_stack_size = (nb_params - nb_regs) * sizeof(tcg_target_long);
1772 call_stack_size = (call_stack_size + TCG_TARGET_STACK_ALIGN - 1) &
1773 ~(TCG_TARGET_STACK_ALIGN - 1);
b03cce8e
FB
1774 allocate_args = (call_stack_size > TCG_STATIC_CALL_ARGS_SIZE);
1775 if (allocate_args) {
1776 tcg_out_addi(s, TCG_REG_CALL_STACK, -STACK_DIR(call_stack_size));
1777 }
39cf05d3
FB
1778
1779 stack_offset = TCG_TARGET_CALL_STACK_OFFSET;
c896fe29
FB
1780 for(i = nb_regs; i < nb_params; i++) {
1781 arg = args[nb_oargs + i];
39cf05d3
FB
1782#ifdef TCG_TARGET_STACK_GROWSUP
1783 stack_offset -= sizeof(tcg_target_long);
1784#endif
1785 if (arg != TCG_CALL_DUMMY_ARG) {
1786 ts = &s->temps[arg];
1787 if (ts->val_type == TEMP_VAL_REG) {
1788 tcg_out_st(s, ts->type, ts->reg, TCG_REG_CALL_STACK, stack_offset);
1789 } else if (ts->val_type == TEMP_VAL_MEM) {
1790 reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type],
1791 s->reserved_regs);
1792 /* XXX: not correct if reading values from the stack */
1793 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1794 tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
1795 } else if (ts->val_type == TEMP_VAL_CONST) {
1796 reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type],
1797 s->reserved_regs);
1798 /* XXX: sign extend may be needed on some targets */
1799 tcg_out_movi(s, ts->type, reg, ts->val);
1800 tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
1801 } else {
1802 tcg_abort();
1803 }
c896fe29 1804 }
39cf05d3
FB
1805#ifndef TCG_TARGET_STACK_GROWSUP
1806 stack_offset += sizeof(tcg_target_long);
1807#endif
c896fe29
FB
1808 }
1809
1810 /* assign input registers */
1811 tcg_regset_set(allocated_regs, s->reserved_regs);
1812 for(i = 0; i < nb_regs; i++) {
1813 arg = args[nb_oargs + i];
39cf05d3
FB
1814 if (arg != TCG_CALL_DUMMY_ARG) {
1815 ts = &s->temps[arg];
1816 reg = tcg_target_call_iarg_regs[i];
1817 tcg_reg_free(s, reg);
1818 if (ts->val_type == TEMP_VAL_REG) {
1819 if (ts->reg != reg) {
1820 tcg_out_mov(s, reg, ts->reg);
1821 }
1822 } else if (ts->val_type == TEMP_VAL_MEM) {
1823 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1824 } else if (ts->val_type == TEMP_VAL_CONST) {
1825 /* XXX: sign extend ? */
1826 tcg_out_movi(s, ts->type, reg, ts->val);
1827 } else {
1828 tcg_abort();
c896fe29 1829 }
39cf05d3 1830 tcg_regset_set_reg(allocated_regs, reg);
c896fe29 1831 }
c896fe29
FB
1832 }
1833
1834 /* assign function address */
1835 func_arg = args[nb_oargs + nb_iargs - 1];
1836 arg_ct = &def->args_ct[0];
1837 ts = &s->temps[func_arg];
f54b3f92 1838 func_addr = ts->val;
c896fe29
FB
1839 const_func_arg = 0;
1840 if (ts->val_type == TEMP_VAL_MEM) {
1841 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
e4d5434c 1842 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
c896fe29 1843 func_arg = reg;
e8996ee0 1844 tcg_regset_set_reg(allocated_regs, reg);
c896fe29
FB
1845 } else if (ts->val_type == TEMP_VAL_REG) {
1846 reg = ts->reg;
1847 if (!tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1848 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1849 tcg_out_mov(s, reg, ts->reg);
1850 }
1851 func_arg = reg;
e8996ee0 1852 tcg_regset_set_reg(allocated_regs, reg);
c896fe29 1853 } else if (ts->val_type == TEMP_VAL_CONST) {
f54b3f92 1854 if (tcg_target_const_match(func_addr, arg_ct)) {
c896fe29 1855 const_func_arg = 1;
f54b3f92 1856 func_arg = func_addr;
c896fe29
FB
1857 } else {
1858 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
f54b3f92 1859 tcg_out_movi(s, ts->type, reg, func_addr);
c896fe29 1860 func_arg = reg;
e8996ee0 1861 tcg_regset_set_reg(allocated_regs, reg);
c896fe29
FB
1862 }
1863 } else {
1864 tcg_abort();
1865 }
e8996ee0 1866
c896fe29
FB
1867
1868 /* mark dead temporaries and free the associated registers */
c6e113f5 1869 for(i = 0; i < nb_iargs; i++) {
c896fe29
FB
1870 arg = args[nb_oargs + i];
1871 if (IS_DEAD_IARG(i)) {
1872 ts = &s->temps[arg];
e8996ee0 1873 if (!ts->fixed_reg) {
c896fe29
FB
1874 if (ts->val_type == TEMP_VAL_REG)
1875 s->reg_to_temp[ts->reg] = -1;
1876 ts->val_type = TEMP_VAL_DEAD;
1877 }
1878 }
1879 }
1880
1881 /* clobber call registers */
1882 for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1883 if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
1884 tcg_reg_free(s, reg);
1885 }
1886 }
1887
1888 /* store globals and free associated registers (we assume the call
1889 can modify any global. */
b9c18f56
AJ
1890 if (!(flags & TCG_CALL_CONST)) {
1891 save_globals(s, allocated_regs);
1892 }
c896fe29
FB
1893
1894 tcg_out_op(s, opc, &func_arg, &const_func_arg);
1895
b03cce8e
FB
1896 if (allocate_args) {
1897 tcg_out_addi(s, TCG_REG_CALL_STACK, STACK_DIR(call_stack_size));
1898 }
c896fe29
FB
1899
1900 /* assign output registers and emit moves if needed */
1901 for(i = 0; i < nb_oargs; i++) {
1902 arg = args[i];
1903 ts = &s->temps[arg];
1904 reg = tcg_target_call_oarg_regs[i];
e8996ee0 1905 assert(s->reg_to_temp[reg] == -1);
c896fe29
FB
1906 if (ts->fixed_reg) {
1907 if (ts->reg != reg) {
1908 tcg_out_mov(s, ts->reg, reg);
1909 }
1910 } else {
1911 if (ts->val_type == TEMP_VAL_REG)
1912 s->reg_to_temp[ts->reg] = -1;
1913 ts->val_type = TEMP_VAL_REG;
1914 ts->reg = reg;
1915 ts->mem_coherent = 0;
1916 s->reg_to_temp[reg] = arg;
1917 }
1918 }
1919
1920 return nb_iargs + nb_oargs + def->nb_cargs + 1;
1921}
1922
1923#ifdef CONFIG_PROFILER
1924
54604f74 1925static int64_t tcg_table_op_count[NB_OPS];
c896fe29 1926
871e6c35 1927static void dump_op_count(void)
c896fe29
FB
1928{
1929 int i;
1930 FILE *f;
54604f74 1931 f = fopen("/tmp/op.log", "w");
c896fe29 1932 for(i = INDEX_op_end; i < NB_OPS; i++) {
54604f74 1933 fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name, tcg_table_op_count[i]);
c896fe29
FB
1934 }
1935 fclose(f);
1936}
1937#endif
1938
1939
1940static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
2ba1eeb6 1941 long search_pc)
c896fe29 1942{
a9751609
RH
1943 TCGOpcode opc;
1944 int op_index;
c896fe29
FB
1945 const TCGOpDef *def;
1946 unsigned int dead_iargs;
1947 const TCGArg *args;
1948
1949#ifdef DEBUG_DISAS
8fec2b8c 1950 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
93fcfe39 1951 qemu_log("OP:\n");
c896fe29 1952 tcg_dump_ops(s, logfile);
93fcfe39 1953 qemu_log("\n");
c896fe29
FB
1954 }
1955#endif
1956
a23a9ec6
FB
1957#ifdef CONFIG_PROFILER
1958 s->la_time -= profile_getclock();
1959#endif
c896fe29 1960 tcg_liveness_analysis(s);
a23a9ec6
FB
1961#ifdef CONFIG_PROFILER
1962 s->la_time += profile_getclock();
1963#endif
c896fe29
FB
1964
1965#ifdef DEBUG_DISAS
8fec2b8c 1966 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_OPT))) {
6a957025 1967 qemu_log("OP after liveness analysis:\n");
c896fe29 1968 tcg_dump_ops(s, logfile);
93fcfe39 1969 qemu_log("\n");
c896fe29
FB
1970 }
1971#endif
1972
1973 tcg_reg_alloc_start(s);
1974
1975 s->code_buf = gen_code_buf;
1976 s->code_ptr = gen_code_buf;
1977
c896fe29
FB
1978 args = gen_opparam_buf;
1979 op_index = 0;
b3db8758 1980
c896fe29
FB
1981 for(;;) {
1982 opc = gen_opc_buf[op_index];
1983#ifdef CONFIG_PROFILER
54604f74 1984 tcg_table_op_count[opc]++;
c896fe29
FB
1985#endif
1986 def = &tcg_op_defs[opc];
1987#if 0
1988 printf("%s: %d %d %d\n", def->name,
1989 def->nb_oargs, def->nb_iargs, def->nb_cargs);
1990 // dump_regs(s);
1991#endif
1992 switch(opc) {
1993 case INDEX_op_mov_i32:
1994#if TCG_TARGET_REG_BITS == 64
1995 case INDEX_op_mov_i64:
1996#endif
1997 dead_iargs = s->op_dead_iargs[op_index];
1998 tcg_reg_alloc_mov(s, def, args, dead_iargs);
1999 break;
e8996ee0
FB
2000 case INDEX_op_movi_i32:
2001#if TCG_TARGET_REG_BITS == 64
2002 case INDEX_op_movi_i64:
2003#endif
2004 tcg_reg_alloc_movi(s, args);
2005 break;
7e4597d7
FB
2006 case INDEX_op_debug_insn_start:
2007 /* debug instruction */
2008 break;
c896fe29
FB
2009 case INDEX_op_nop:
2010 case INDEX_op_nop1:
2011 case INDEX_op_nop2:
2012 case INDEX_op_nop3:
2013 break;
2014 case INDEX_op_nopn:
2015 args += args[0];
2016 goto next;
5ff9d6a4
FB
2017 case INDEX_op_discard:
2018 {
2019 TCGTemp *ts;
2020 ts = &s->temps[args[0]];
2021 /* mark the temporary as dead */
e8996ee0 2022 if (!ts->fixed_reg) {
5ff9d6a4
FB
2023 if (ts->val_type == TEMP_VAL_REG)
2024 s->reg_to_temp[ts->reg] = -1;
2025 ts->val_type = TEMP_VAL_DEAD;
2026 }
2027 }
2028 break;
c896fe29 2029 case INDEX_op_set_label:
e8996ee0 2030 tcg_reg_alloc_bb_end(s, s->reserved_regs);
c896fe29
FB
2031 tcg_out_label(s, args[0], (long)s->code_ptr);
2032 break;
2033 case INDEX_op_call:
2034 dead_iargs = s->op_dead_iargs[op_index];
2035 args += tcg_reg_alloc_call(s, def, opc, args, dead_iargs);
2036 goto next;
2037 case INDEX_op_end:
2038 goto the_end;
c896fe29
FB
2039 default:
2040 /* Note: in order to speed up the code, it would be much
2041 faster to have specialized register allocator functions for
2042 some common argument patterns */
2043 dead_iargs = s->op_dead_iargs[op_index];
2044 tcg_reg_alloc_op(s, def, opc, args, dead_iargs);
2045 break;
2046 }
2047 args += def->nb_args;
8df1ca4b 2048 next:
2ba1eeb6 2049 if (search_pc >= 0 && search_pc < s->code_ptr - gen_code_buf) {
b314f270 2050 return op_index;
c896fe29
FB
2051 }
2052 op_index++;
2053#ifndef NDEBUG
2054 check_regs(s);
2055#endif
2056 }
2057 the_end:
2058 return -1;
2059}
2060
54604f74 2061int tcg_gen_code(TCGContext *s, uint8_t *gen_code_buf)
c896fe29
FB
2062{
2063#ifdef CONFIG_PROFILER
2064 {
c896fe29
FB
2065 int n;
2066 n = (gen_opc_ptr - gen_opc_buf);
a23a9ec6
FB
2067 s->op_count += n;
2068 if (n > s->op_count_max)
2069 s->op_count_max = n;
2070
2071 s->temp_count += s->nb_temps;
2072 if (s->nb_temps > s->temp_count_max)
2073 s->temp_count_max = s->nb_temps;
c896fe29
FB
2074 }
2075#endif
2076
2ba1eeb6 2077 tcg_gen_code_common(s, gen_code_buf, -1);
c896fe29
FB
2078
2079 /* flush instruction cache */
2080 flush_icache_range((unsigned long)gen_code_buf,
2081 (unsigned long)s->code_ptr);
2082 return s->code_ptr - gen_code_buf;
2083}
2084
2ba1eeb6 2085/* Return the index of the micro operation such as the pc after is <
623e265c
PB
2086 offset bytes from the start of the TB. The contents of gen_code_buf must
2087 not be changed, though writing the same values is ok.
2088 Return -1 if not found. */
54604f74 2089int tcg_gen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, long offset)
c896fe29 2090{
623e265c 2091 return tcg_gen_code_common(s, gen_code_buf, offset);
c896fe29 2092}
a23a9ec6
FB
2093
2094#ifdef CONFIG_PROFILER
2095void tcg_dump_info(FILE *f,
2096 int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
2097{
2098 TCGContext *s = &tcg_ctx;
2099 int64_t tot;
2100
2101 tot = s->interm_time + s->code_time;
2102 cpu_fprintf(f, "JIT cycles %" PRId64 " (%0.3f s at 2.4 GHz)\n",
2103 tot, tot / 2.4e9);
2104 cpu_fprintf(f, "translated TBs %" PRId64 " (aborted=%" PRId64 " %0.1f%%)\n",
2105 s->tb_count,
2106 s->tb_count1 - s->tb_count,
2107 s->tb_count1 ? (double)(s->tb_count1 - s->tb_count) / s->tb_count1 * 100.0 : 0);
2108 cpu_fprintf(f, "avg ops/TB %0.1f max=%d\n",
2109 s->tb_count ? (double)s->op_count / s->tb_count : 0, s->op_count_max);
a23a9ec6
FB
2110 cpu_fprintf(f, "deleted ops/TB %0.2f\n",
2111 s->tb_count ?
2112 (double)s->del_op_count / s->tb_count : 0);
2113 cpu_fprintf(f, "avg temps/TB %0.2f max=%d\n",
2114 s->tb_count ?
2115 (double)s->temp_count / s->tb_count : 0,
2116 s->temp_count_max);
2117
2118 cpu_fprintf(f, "cycles/op %0.1f\n",
2119 s->op_count ? (double)tot / s->op_count : 0);
2120 cpu_fprintf(f, "cycles/in byte %0.1f\n",
2121 s->code_in_len ? (double)tot / s->code_in_len : 0);
2122 cpu_fprintf(f, "cycles/out byte %0.1f\n",
2123 s->code_out_len ? (double)tot / s->code_out_len : 0);
2124 if (tot == 0)
2125 tot = 1;
2126 cpu_fprintf(f, " gen_interm time %0.1f%%\n",
2127 (double)s->interm_time / tot * 100.0);
2128 cpu_fprintf(f, " gen_code time %0.1f%%\n",
2129 (double)s->code_time / tot * 100.0);
2130 cpu_fprintf(f, "liveness/code time %0.1f%%\n",
2131 (double)s->la_time / (s->code_time ? s->code_time : 1) * 100.0);
2132 cpu_fprintf(f, "cpu_restore count %" PRId64 "\n",
2133 s->restore_count);
2134 cpu_fprintf(f, " avg cycles %0.1f\n",
2135 s->restore_count ? (double)s->restore_time / s->restore_count : 0);
871e6c35
BS
2136
2137 dump_op_count();
a23a9ec6
FB
2138}
2139#else
24bf7b3a 2140void tcg_dump_info(FILE *f,
a23a9ec6
FB
2141 int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
2142{
24bf7b3a 2143 cpu_fprintf(f, "[TCG profiler not compiled]\n");
a23a9ec6
FB
2144}
2145#endif