VirtualBox

source: vbox/trunk/src/recompiler/tcg/tcg.c@ 37676

最後變更 在這個檔案從37676是 37676,由 vboxsync 提交於 14 年 前

clean up...

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette