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