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