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