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