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