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