VirtualBox

source: vbox/trunk/src/recompiler_new/tcg/tcg.c@ 15248

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

new REM: disable liveness analysis for 32-bit hosts and 64-bit targets, it's buggy

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

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