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