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