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