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