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