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