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