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