]> git.proxmox.com Git - qemu.git/blob - tcg/tcg.c
profiler clean up
[qemu.git] / tcg / tcg.c
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>
37 #ifdef _WIN32
38 #include <malloc.h>
39 #endif
40
41 #include "config.h"
42 #include "qemu-common.h"
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
55 static void patch_reloc(uint8_t *code_ptr, int type,
56 tcg_target_long value, tcg_target_long addend);
57
58 TCGOpDef 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
66 TCGRegSet tcg_target_available_regs[2];
67 TCGRegSet tcg_target_call_clobber_regs;
68
69 /* XXX: move that inside the context */
70 uint16_t *gen_opc_ptr;
71 TCGArg *gen_opparam_ptr;
72
73 static inline void tcg_out8(TCGContext *s, uint8_t v)
74 {
75 *s->code_ptr++ = v;
76 }
77
78 static inline void tcg_out16(TCGContext *s, uint16_t v)
79 {
80 *(uint16_t *)s->code_ptr = v;
81 s->code_ptr += 2;
82 }
83
84 static 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
92 void 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) {
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. */
103 patch_reloc(code_ptr, type, l->u.value, addend);
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
115 static 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) {
126 patch_reloc(r->ptr, r->type, value, r->addend);
127 r = r->next;
128 }
129 l->has_value = 1;
130 l->u.value = value;
131 }
132
133 int 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
150 /* pool based memory allocation */
151 void *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
193 void 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 */
200 void 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
212 void 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);
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);
252 }
253
254 void 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
262 void tcg_set_macro_func(TCGContext *s, TCGMacroFunc *func)
263 {
264 s->macro_func = func;
265 }
266
267 void 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
279 static inline void tcg_temp_alloc(TCGContext *s, int n)
280 {
281 if (n > TCG_MAX_TEMPS)
282 tcg_abort();
283 }
284
285 TCGv tcg_global_reg_new(TCGType type, int reg, const char *name)
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);
308 return MAKE_TCGV(idx);
309 }
310
311 #if TCG_TARGET_REG_BITS == 32
312 /* temporary hack to avoid register shortage for tcg_qemu_st64() */
313 TCGv 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
350 TCGv tcg_global_mem_new(TCGType type, int reg, tcg_target_long offset,
351 const char *name)
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 }
410 return MAKE_TCGV(idx);
411 }
412
413 TCGv tcg_temp_new(TCGType type)
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;
426 ts->fixed_reg = 0;
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;
434 ts->fixed_reg = 0;
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;
445 ts->fixed_reg = 0;
446 ts->val_type = TEMP_VAL_DEAD;
447 ts->mem_allocated = 0;
448 ts->name = NULL;
449 s->nb_temps++;
450 }
451 return MAKE_TCGV(idx);
452 }
453
454 TCGv tcg_const_i32(int32_t val)
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++;
468 return MAKE_TCGV(idx);
469 }
470
471 TCGv tcg_const_i64(int64_t val)
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
502 return MAKE_TCGV(idx);
503 }
504
505 void 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 }
519 s->helpers[s->nb_helpers].func = (tcg_target_ulong)func;
520 s->helpers[s->nb_helpers].name = name;
521 s->nb_helpers++;
522 }
523
524 static inline TCGType tcg_get_base_type(TCGContext *s, TCGv arg)
525 {
526 return s->temps[GET_TCGV(arg)].base_type;
527 }
528
529 static void tcg_gen_call_internal(TCGContext *s, TCGv func,
530 unsigned int flags,
531 unsigned int nb_rets, const TCGv *rets,
532 unsigned int nb_params, const TCGv *params)
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++) {
538 *gen_opparam_ptr++ = GET_TCGV(rets[i]);
539 }
540 for(i = 0; i < nb_params; i++) {
541 *gen_opparam_ptr++ = GET_TCGV(params[i]);
542 }
543 *gen_opparam_ptr++ = GET_TCGV(func);
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
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(). */
555 void 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)
558 {
559 TCGv ret, *args2, rets_2[2], arg;
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;
566 #ifdef TCG_TARGET_WORDS_BIGENDIAN
567 rets_2[0] = TCGV_HIGH(ret);
568 rets_2[1] = ret;
569 #else
570 rets_2[0] = ret;
571 rets_2[1] = TCGV_HIGH(ret);
572 #endif
573 rets = rets_2;
574 }
575 }
576 args2 = alloca((nb_params * 3) * sizeof(TCGv));
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;
590 args2[j++] = TCGV_HIGH(arg);
591 #else
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
598 #ifdef TCG_TARGET_WORDS_BIGENDIAN
599 args2[j++] = TCGV_HIGH(arg);
600 args2[j++] = arg;
601 #else
602 args2[j++] = arg;
603 args2[j++] = TCGV_HIGH(arg);
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
614 void 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)
617 {
618 tcg_gen_call_internal(s, func, flags,
619 nb_rets, rets, nb_params, args1);
620 }
621 #endif
622
623 #if TCG_TARGET_REG_BITS == 32
624 void tcg_gen_shifti_i64(TCGv ret, TCGv arg1,
625 int c, int right, int arith)
626 {
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) {
631 c -= 32;
632 if (right) {
633 if (arith) {
634 tcg_gen_sari_i32(ret, TCGV_HIGH(arg1), c);
635 tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 31);
636 } else {
637 tcg_gen_shri_i32(ret, TCGV_HIGH(arg1), c);
638 tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
639 }
640 } else {
641 tcg_gen_shli_i32(TCGV_HIGH(ret), arg1, c);
642 tcg_gen_movi_i32(ret, 0);
643 }
644 } else {
645 TCGv t0, t1;
646
647 t0 = tcg_temp_new(TCG_TYPE_I32);
648 t1 = tcg_temp_new(TCG_TYPE_I32);
649 if (right) {
650 tcg_gen_shli_i32(t0, TCGV_HIGH(arg1), 32 - c);
651 if (arith)
652 tcg_gen_sari_i32(t1, TCGV_HIGH(arg1), c);
653 else
654 tcg_gen_shri_i32(t1, TCGV_HIGH(arg1), c);
655 tcg_gen_shri_i32(ret, arg1, c);
656 tcg_gen_or_i32(ret, ret, t0);
657 tcg_gen_mov_i32(TCGV_HIGH(ret), t1);
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);
662 tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c);
663 tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t0);
664 tcg_gen_mov_i32(ret, t1);
665 }
666 }
667 }
668 #endif
669
670 void 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
687 static char *tcg_get_arg_str_idx(TCGContext *s, char *buf, int buf_size,
688 int idx)
689 {
690 TCGTemp *ts;
691
692 ts = &s->temps[idx];
693 if (idx < s->nb_globals) {
694 pstrcpy(buf, buf_size, ts->name);
695 } else {
696 if (ts->val_type == TEMP_VAL_CONST) {
697 snprintf(buf, buf_size, "$0x%" TCG_PRIlx , ts->val);
698 } else {
699 snprintf(buf, buf_size, "tmp%d", idx - s->nb_globals);
700 }
701 }
702 return buf;
703 }
704
705 char *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
710 /* find helper definition (XXX: inefficient) */
711 static 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
721 static 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
741 void tcg_dump_ops(TCGContext *s, FILE *outfile)
742 {
743 const uint16_t *opc_ptr;
744 const TCGArg *args;
745 TCGArg arg;
746 int c, i, k, nb_oargs, nb_iargs, nb_cargs, first_insn;
747 const TCGOpDef *def;
748 char buf[128];
749
750 first_insn = 1;
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];
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) {
771 TCGArg arg;
772
773 /* variable number of arguments */
774 arg = *args++;
775 nb_oargs = arg >> 16;
776 nb_iargs = arg & 0xffff;
777 nb_cargs = def->nb_cargs;
778
779 fprintf(outfile, " %s ", def->name);
780
781 /* function name */
782 fprintf(outfile, "%s",
783 tcg_get_helper_str_idx(s, buf, sizeof(buf), args[nb_oargs + nb_iargs - 1]));
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++) {
795 fprintf(outfile, ",");
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 }
802 }
803 } else {
804 fprintf(outfile, " %s ", def->name);
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 }
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 */
842 static 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 */
864 static 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
885 void 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
909 argument is tagged with TCG_CT_IALIAS. */
910 def->args_ct[i] = def->args_ct[oarg];
911 def->args_ct[oarg].ct = TCG_CT_ALIAS;
912 def->args_ct[oarg].alias_index = i;
913 def->args_ct[i].ct |= TCG_CT_IALIAS;
914 def->args_ct[i].alias_index = oarg;
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' */
957 static 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 */
970 static 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. */
979 void 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:
1004 {
1005 int call_flags;
1006
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:
1026
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];
1040 if (arg != TCG_CALL_DUMMY_ARG) {
1041 if (dead_temps[arg]) {
1042 dead_iargs |= (1 << i);
1043 }
1044 dead_temps[arg] = 0;
1045 }
1046 }
1047 s->op_dead_iargs[op_index] = dead_iargs;
1048 }
1049 args--;
1050 }
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;
1057 case INDEX_op_debug_insn_start:
1058 args -= def->nb_args;
1059 break;
1060 case INDEX_op_nopn:
1061 nb_args = args[-1];
1062 args -= nb_args;
1063 break;
1064 case INDEX_op_discard:
1065 args--;
1066 /* mark the temporary as dead */
1067 dead_temps[args[0]] = 1;
1068 break;
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
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) {
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
1159 s->del_op_count++;
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);
1173 } else if (def->flags & TCG_OPF_CALL_CLOBBER) {
1174 /* globals are live */
1175 memset(dead_temps, 0, s->nb_globals);
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 */
1205 void 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
1216 static 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];
1224 printf(" %10s: ", tcg_get_arg_str_idx(s, buf, sizeof(buf), i));
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],
1249 tcg_get_arg_str_idx(s, buf, sizeof(buf), s->reg_to_temp[i]));
1250 }
1251 }
1252 }
1253
1254 static 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]);
1268 goto fail;
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",
1278 tcg_get_arg_str_idx(s, buf, sizeof(buf), k));
1279 fail:
1280 printf("reg state:\n");
1281 dump_regs(s);
1282 tcg_abort();
1283 }
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 }
1289 }
1290 }
1291 #endif
1292
1293 static 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)
1299 tcg_abort();
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 */
1307 static 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);
1319 tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
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 */
1327 static 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 */
1335 for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
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 */
1342 for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
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
1353 /* save globals to their cannonical location and assume they can be
1354 modified be the following code. */
1355 static void save_globals(TCGContext *s)
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);
1365 } else if (ts->val_type == TEMP_VAL_DEAD) {
1366 ts->val_type = TEMP_VAL_MEM;
1367 }
1368 }
1369 }
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 ? */
1375 void tcg_reg_alloc_bb_end(TCGContext *s)
1376 {
1377 TCGTemp *ts;
1378 int i;
1379
1380 save_globals(s);
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
1395 static 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 }
1431 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
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
1448 static 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);
1478 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
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);
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 }
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
1541 if (def->flags & TCG_OPF_CALL_CLOBBER) {
1542 /* XXX: permit generic clobber register list ? */
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 }
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. */
1553 save_globals(s);
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) {
1564 reg = new_args[arg_ct->alias_index];
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
1606 #ifdef TCG_TARGET_STACK_GROWSUP
1607 #define STACK_DIR(x) (-(x))
1608 #else
1609 #define STACK_DIR(x) (x)
1610 #endif
1611
1612 static 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;
1619 tcg_target_long stack_offset, call_stack_size, func_addr;
1620 int const_func_arg, allocate_args;
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);
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 }
1645
1646 stack_offset = TCG_TARGET_CALL_STACK_OFFSET;
1647 for(i = nb_regs; i < nb_params; i++) {
1648 arg = args[nb_oargs + i];
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 }
1671 }
1672 #ifndef TCG_TARGET_STACK_GROWSUP
1673 stack_offset += sizeof(tcg_target_long);
1674 #endif
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];
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();
1696 }
1697 tcg_regset_set_reg(allocated_regs, reg);
1698 }
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];
1705 func_addr = ts->val;
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);
1709 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
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) {
1719 if (tcg_target_const_match(func_addr, arg_ct)) {
1720 const_func_arg = 1;
1721 func_arg = func_addr;
1722 } else {
1723 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1724 tcg_out_movi(s, ts->type, reg, func_addr);
1725 func_arg = reg;
1726 }
1727 } else {
1728 tcg_abort();
1729 }
1730
1731 /* mark dead temporaries and free the associated registers */
1732 for(i = 0; i < nb_iargs; i++) {
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. */
1753 save_globals(s);
1754
1755 tcg_out_op(s, opc, &func_arg, &const_func_arg);
1756
1757 if (allocate_args) {
1758 tcg_out_addi(s, TCG_REG_CALL_STACK, STACK_DIR(call_stack_size));
1759 }
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
1786 static int64_t dyngen_table_op_count[NB_OPS];
1787
1788 void 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
1806 static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
1807 long search_pc)
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
1822 #ifdef CONFIG_PROFILER
1823 s->la_time -= profile_getclock();
1824 #endif
1825 tcg_liveness_analysis(s);
1826 #ifdef CONFIG_PROFILER
1827 s->la_time += profile_getclock();
1828 #endif
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;
1846
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;
1866 case INDEX_op_debug_insn_start:
1867 /* debug instruction */
1868 break;
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;
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;
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;
1912
1913 #ifdef CONFIG_DYNGEN_OP
1914 case 0 ... INDEX_op_end - 1:
1915 /* legacy dyngen ops */
1916 #ifdef CONFIG_PROFILER
1917 s->old_op_count++;
1918 #endif
1919 tcg_reg_alloc_bb_end(s);
1920 if (search_pc >= 0) {
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;
1927 #endif
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: ;
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;
1943 }
1944 op_index++;
1945 #ifndef NDEBUG
1946 check_regs(s);
1947 #endif
1948 }
1949 the_end:
1950 return -1;
1951 }
1952
1953 int dyngen_code(TCGContext *s, uint8_t *gen_code_buf)
1954 {
1955 #ifdef CONFIG_PROFILER
1956 {
1957 int n;
1958 n = (gen_opc_ptr - gen_opc_buf);
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;
1966 }
1967 #endif
1968
1969 tcg_gen_code_common(s, gen_code_buf, -1);
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
1977 /* Return the index of the micro operation such as the pc after is <
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. */
1981 int dyngen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, long offset)
1982 {
1983 return tcg_gen_code_common(s, gen_code_buf, offset);
1984 }
1985
1986 #ifdef CONFIG_PROFILER
1987 void 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
2036 void dump_tcg_info(FILE *f,
2037 int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
2038 {
2039 cpu_fprintf("[TCG profiler not compiled]\n");
2040 }
2041 #endif