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