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