tcg: improve comment about pure functions
[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                     /* globals are live (they may be used by the call) */
1126                     memset(dead_temps, 0, s->nb_globals);
1127                     
1128                     /* input args are live */
1129                     dead_iargs = 0;
1130                     for(i = 0; i < nb_iargs; i++) {
1131                         arg = args[i + nb_oargs];
1132                         if (arg != TCG_CALL_DUMMY_ARG) {
1133                             if (dead_temps[arg]) {
1134                                 dead_iargs |= (1 << i);
1135                             }
1136                             dead_temps[arg] = 0;
1137                         }
1138                     }
1139                     s->op_dead_iargs[op_index] = dead_iargs;
1140                 }
1141                 args--;
1142             }
1143             break;
1144         case INDEX_op_set_label:
1145             args--;
1146             /* mark end of basic block */
1147             tcg_la_bb_end(s, dead_temps);
1148             break;
1149         case INDEX_op_debug_insn_start:
1150             args -= def->nb_args;
1151             break;
1152         case INDEX_op_nopn:
1153             nb_args = args[-1];
1154             args -= nb_args;
1155             break;
1156         case INDEX_op_discard:
1157             args--;
1158             /* mark the temporary as dead */
1159             dead_temps[args[0]] = 1;
1160             break;
1161         case INDEX_op_end:
1162             break;
1163             /* XXX: optimize by hardcoding common cases (e.g. triadic ops) */
1164         default:
1165             args -= def->nb_args;
1166             nb_iargs = def->nb_iargs;
1167             nb_oargs = def->nb_oargs;
1168
1169             /* Test if the operation can be removed because all
1170                its outputs are dead. We assume that nb_oargs == 0
1171                implies side effects */
1172             if (!(def->flags & TCG_OPF_SIDE_EFFECTS) && nb_oargs != 0) {
1173                 for(i = 0; i < nb_oargs; i++) {
1174                     arg = args[i];
1175                     if (!dead_temps[arg])
1176                         goto do_not_remove;
1177                 }
1178                 tcg_set_nop(s, gen_opc_buf + op_index, args, def->nb_args);
1179 #ifdef CONFIG_PROFILER
1180                 s->del_op_count++;
1181 #endif
1182             } else {
1183             do_not_remove:
1184
1185                 /* output args are dead */
1186                 for(i = 0; i < nb_oargs; i++) {
1187                     arg = args[i];
1188                     dead_temps[arg] = 1;
1189                 }
1190
1191                 /* if end of basic block, update */
1192                 if (def->flags & TCG_OPF_BB_END) {
1193                     tcg_la_bb_end(s, dead_temps);
1194                 } else if (def->flags & TCG_OPF_CALL_CLOBBER) {
1195                     /* globals are live */
1196                     memset(dead_temps, 0, s->nb_globals);
1197                 }
1198
1199                 /* input args are live */
1200                 dead_iargs = 0;
1201                 for(i = 0; i < nb_iargs; i++) {
1202                     arg = args[i + nb_oargs];
1203                     if (dead_temps[arg]) {
1204                         dead_iargs |= (1 << i);
1205                     }
1206                     dead_temps[arg] = 0;
1207                 }
1208                 s->op_dead_iargs[op_index] = dead_iargs;
1209             }
1210             break;
1211         }
1212         op_index--;
1213     }
1214
1215     if (args != gen_opparam_buf)
1216         tcg_abort();
1217 }
1218 #else
1219 /* dummy liveness analysis */
1220 void tcg_liveness_analysis(TCGContext *s)
1221 {
1222     int nb_ops;
1223     nb_ops = gen_opc_ptr - gen_opc_buf;
1224
1225     s->op_dead_iargs = tcg_malloc(nb_ops * sizeof(uint16_t));
1226     memset(s->op_dead_iargs, 0, nb_ops * sizeof(uint16_t));
1227 }
1228 #endif
1229
1230 #ifndef NDEBUG
1231 static void dump_regs(TCGContext *s)
1232 {
1233     TCGTemp *ts;
1234     int i;
1235     char buf[64];
1236
1237     for(i = 0; i < s->nb_temps; i++) {
1238         ts = &s->temps[i];
1239         printf("  %10s: ", tcg_get_arg_str_idx(s, buf, sizeof(buf), i));
1240         switch(ts->val_type) {
1241         case TEMP_VAL_REG:
1242             printf("%s", tcg_target_reg_names[ts->reg]);
1243             break;
1244         case TEMP_VAL_MEM:
1245             printf("%d(%s)", (int)ts->mem_offset, tcg_target_reg_names[ts->mem_reg]);
1246             break;
1247         case TEMP_VAL_CONST:
1248             printf("$0x%" TCG_PRIlx, ts->val);
1249             break;
1250         case TEMP_VAL_DEAD:
1251             printf("D");
1252             break;
1253         default:
1254             printf("???");
1255             break;
1256         }
1257         printf("\n");
1258     }
1259
1260     for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
1261         if (s->reg_to_temp[i] >= 0) {
1262             printf("%s: %s\n", 
1263                    tcg_target_reg_names[i], 
1264                    tcg_get_arg_str_idx(s, buf, sizeof(buf), s->reg_to_temp[i]));
1265         }
1266     }
1267 }
1268
1269 static void check_regs(TCGContext *s)
1270 {
1271     int reg, k;
1272     TCGTemp *ts;
1273     char buf[64];
1274
1275     for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1276         k = s->reg_to_temp[reg];
1277         if (k >= 0) {
1278             ts = &s->temps[k];
1279             if (ts->val_type != TEMP_VAL_REG ||
1280                 ts->reg != reg) {
1281                 printf("Inconsistency for register %s:\n", 
1282                        tcg_target_reg_names[reg]);
1283                 goto fail;
1284             }
1285         }
1286     }
1287     for(k = 0; k < s->nb_temps; k++) {
1288         ts = &s->temps[k];
1289         if (ts->val_type == TEMP_VAL_REG &&
1290             !ts->fixed_reg &&
1291             s->reg_to_temp[ts->reg] != k) {
1292                 printf("Inconsistency for temp %s:\n", 
1293                        tcg_get_arg_str_idx(s, buf, sizeof(buf), k));
1294         fail:
1295                 printf("reg state:\n");
1296                 dump_regs(s);
1297                 tcg_abort();
1298         }
1299     }
1300 }
1301 #endif
1302
1303 static void temp_allocate_frame(TCGContext *s, int temp)
1304 {
1305     TCGTemp *ts;
1306     ts = &s->temps[temp];
1307     s->current_frame_offset = (s->current_frame_offset + sizeof(tcg_target_long) - 1) & ~(sizeof(tcg_target_long) - 1);
1308     if (s->current_frame_offset + sizeof(tcg_target_long) > s->frame_end)
1309         tcg_abort();
1310     ts->mem_offset = s->current_frame_offset;
1311     ts->mem_reg = s->frame_reg;
1312     ts->mem_allocated = 1;
1313     s->current_frame_offset += sizeof(tcg_target_long);
1314 }
1315
1316 /* free register 'reg' by spilling the corresponding temporary if necessary */
1317 static void tcg_reg_free(TCGContext *s, int reg)
1318 {
1319     TCGTemp *ts;
1320     int temp;
1321
1322     temp = s->reg_to_temp[reg];
1323     if (temp != -1) {
1324         ts = &s->temps[temp];
1325         assert(ts->val_type == TEMP_VAL_REG);
1326         if (!ts->mem_coherent) {
1327             if (!ts->mem_allocated) 
1328                 temp_allocate_frame(s, temp);
1329             tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1330         }
1331         ts->val_type = TEMP_VAL_MEM;
1332         s->reg_to_temp[reg] = -1;
1333     }
1334 }
1335
1336 /* Allocate a register belonging to reg1 & ~reg2 */
1337 static int tcg_reg_alloc(TCGContext *s, TCGRegSet reg1, TCGRegSet reg2)
1338 {
1339     int i, reg;
1340     TCGRegSet reg_ct;
1341
1342     tcg_regset_andnot(reg_ct, reg1, reg2);
1343
1344     /* first try free registers */
1345     for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1346         reg = tcg_target_reg_alloc_order[i];
1347         if (tcg_regset_test_reg(reg_ct, reg) && s->reg_to_temp[reg] == -1)
1348             return reg;
1349     }
1350
1351     /* XXX: do better spill choice */
1352     for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1353         reg = tcg_target_reg_alloc_order[i];
1354         if (tcg_regset_test_reg(reg_ct, reg)) {
1355             tcg_reg_free(s, reg);
1356             return reg;
1357         }
1358     }
1359
1360     tcg_abort();
1361 }
1362
1363 /* save a temporary to memory. 'allocated_regs' is used in case a
1364    temporary registers needs to be allocated to store a constant. */
1365 static void temp_save(TCGContext *s, int temp, TCGRegSet allocated_regs)
1366 {
1367     TCGTemp *ts;
1368     int reg;
1369
1370     ts = &s->temps[temp];
1371     if (!ts->fixed_reg) {
1372         switch(ts->val_type) {
1373         case TEMP_VAL_REG:
1374             tcg_reg_free(s, ts->reg);
1375             break;
1376         case TEMP_VAL_DEAD:
1377             ts->val_type = TEMP_VAL_MEM;
1378             break;
1379         case TEMP_VAL_CONST:
1380             reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], 
1381                                 allocated_regs);
1382             if (!ts->mem_allocated) 
1383                 temp_allocate_frame(s, temp);
1384             tcg_out_movi(s, ts->type, reg, ts->val);
1385             tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1386             ts->val_type = TEMP_VAL_MEM;
1387             break;
1388         case TEMP_VAL_MEM:
1389             break;
1390         default:
1391             tcg_abort();
1392         }
1393     }
1394 }
1395
1396 /* save globals to their cannonical location and assume they can be
1397    modified be the following code. 'allocated_regs' is used in case a
1398    temporary registers needs to be allocated to store a constant. */
1399 static void save_globals(TCGContext *s, TCGRegSet allocated_regs)
1400 {
1401     int i;
1402
1403     for(i = 0; i < s->nb_globals; i++) {
1404         temp_save(s, i, allocated_regs);
1405     }
1406 }
1407
1408 /* at the end of a basic block, we assume all temporaries are dead and
1409    all globals are stored at their canonical location. */
1410 static void tcg_reg_alloc_bb_end(TCGContext *s, TCGRegSet allocated_regs)
1411 {
1412     TCGTemp *ts;
1413     int i;
1414
1415     for(i = s->nb_globals; i < s->nb_temps; i++) {
1416         ts = &s->temps[i];
1417         if (ts->temp_local) {
1418             temp_save(s, i, allocated_regs);
1419         } else {
1420             if (ts->val_type == TEMP_VAL_REG) {
1421                 s->reg_to_temp[ts->reg] = -1;
1422             }
1423             ts->val_type = TEMP_VAL_DEAD;
1424         }
1425     }
1426
1427     save_globals(s, allocated_regs);
1428 }
1429
1430 #define IS_DEAD_IARG(n) ((dead_iargs >> (n)) & 1)
1431
1432 static void tcg_reg_alloc_movi(TCGContext *s, const TCGArg *args)
1433 {
1434     TCGTemp *ots;
1435     tcg_target_ulong val;
1436
1437     ots = &s->temps[args[0]];
1438     val = args[1];
1439
1440     if (ots->fixed_reg) {
1441         /* for fixed registers, we do not do any constant
1442            propagation */
1443         tcg_out_movi(s, ots->type, ots->reg, val);
1444     } else {
1445         /* The movi is not explicitly generated here */
1446         if (ots->val_type == TEMP_VAL_REG)
1447             s->reg_to_temp[ots->reg] = -1;
1448         ots->val_type = TEMP_VAL_CONST;
1449         ots->val = val;
1450     }
1451 }
1452
1453 static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
1454                               const TCGArg *args,
1455                               unsigned int dead_iargs)
1456 {
1457     TCGTemp *ts, *ots;
1458     int reg;
1459     const TCGArgConstraint *arg_ct;
1460
1461     ots = &s->temps[args[0]];
1462     ts = &s->temps[args[1]];
1463     arg_ct = &def->args_ct[0];
1464
1465     /* XXX: always mark arg dead if IS_DEAD_IARG(0) */
1466     if (ts->val_type == TEMP_VAL_REG) {
1467         if (IS_DEAD_IARG(0) && !ts->fixed_reg && !ots->fixed_reg) {
1468             /* the mov can be suppressed */
1469             if (ots->val_type == TEMP_VAL_REG)
1470                 s->reg_to_temp[ots->reg] = -1;
1471             reg = ts->reg;
1472             s->reg_to_temp[reg] = -1;
1473             ts->val_type = TEMP_VAL_DEAD;
1474         } else {
1475             if (ots->val_type == TEMP_VAL_REG) {
1476                 reg = ots->reg;
1477             } else {
1478                 reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1479             }
1480             if (ts->reg != reg) {
1481                 tcg_out_mov(s, reg, ts->reg);
1482             }
1483         }
1484     } else if (ts->val_type == TEMP_VAL_MEM) {
1485         if (ots->val_type == TEMP_VAL_REG) {
1486             reg = ots->reg;
1487         } else {
1488             reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1489         }
1490         tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1491     } else if (ts->val_type == TEMP_VAL_CONST) {
1492         if (ots->fixed_reg) {
1493             reg = ots->reg;
1494             tcg_out_movi(s, ots->type, reg, ts->val);
1495         } else {
1496             /* propagate constant */
1497             if (ots->val_type == TEMP_VAL_REG)
1498                 s->reg_to_temp[ots->reg] = -1;
1499             ots->val_type = TEMP_VAL_CONST;
1500             ots->val = ts->val;
1501             return;
1502         }
1503     } else {
1504         tcg_abort();
1505     }
1506     s->reg_to_temp[reg] = args[0];
1507     ots->reg = reg;
1508     ots->val_type = TEMP_VAL_REG;
1509     ots->mem_coherent = 0;
1510 }
1511
1512 static void tcg_reg_alloc_op(TCGContext *s, 
1513                              const TCGOpDef *def, int opc,
1514                              const TCGArg *args,
1515                              unsigned int dead_iargs)
1516 {
1517     TCGRegSet allocated_regs;
1518     int i, k, nb_iargs, nb_oargs, reg;
1519     TCGArg arg;
1520     const TCGArgConstraint *arg_ct;
1521     TCGTemp *ts;
1522     TCGArg new_args[TCG_MAX_OP_ARGS];
1523     int const_args[TCG_MAX_OP_ARGS];
1524
1525     nb_oargs = def->nb_oargs;
1526     nb_iargs = def->nb_iargs;
1527
1528     /* copy constants */
1529     memcpy(new_args + nb_oargs + nb_iargs, 
1530            args + nb_oargs + nb_iargs, 
1531            sizeof(TCGArg) * def->nb_cargs);
1532
1533     /* satisfy input constraints */ 
1534     tcg_regset_set(allocated_regs, s->reserved_regs);
1535     for(k = 0; k < nb_iargs; k++) {
1536         i = def->sorted_args[nb_oargs + k];
1537         arg = args[i];
1538         arg_ct = &def->args_ct[i];
1539         ts = &s->temps[arg];
1540         if (ts->val_type == TEMP_VAL_MEM) {
1541             reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1542             tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1543             ts->val_type = TEMP_VAL_REG;
1544             ts->reg = reg;
1545             ts->mem_coherent = 1;
1546             s->reg_to_temp[reg] = arg;
1547         } else if (ts->val_type == TEMP_VAL_CONST) {
1548             if (tcg_target_const_match(ts->val, arg_ct)) {
1549                 /* constant is OK for instruction */
1550                 const_args[i] = 1;
1551                 new_args[i] = ts->val;
1552                 goto iarg_end;
1553             } else {
1554                 /* need to move to a register */
1555                 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1556                 tcg_out_movi(s, ts->type, reg, ts->val);
1557                 ts->val_type = TEMP_VAL_REG;
1558                 ts->reg = reg;
1559                 ts->mem_coherent = 0;
1560                 s->reg_to_temp[reg] = arg;
1561             }
1562         }
1563         assert(ts->val_type == TEMP_VAL_REG);
1564         if (arg_ct->ct & TCG_CT_IALIAS) {
1565             if (ts->fixed_reg) {
1566                 /* if fixed register, we must allocate a new register
1567                    if the alias is not the same register */
1568                 if (arg != args[arg_ct->alias_index])
1569                     goto allocate_in_reg;
1570             } else {
1571                 /* if the input is aliased to an output and if it is
1572                    not dead after the instruction, we must allocate
1573                    a new register and move it */
1574                 if (!IS_DEAD_IARG(i - nb_oargs)) 
1575                     goto allocate_in_reg;
1576             }
1577         }
1578         reg = ts->reg;
1579         if (tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1580             /* nothing to do : the constraint is satisfied */
1581         } else {
1582         allocate_in_reg:
1583             /* allocate a new register matching the constraint 
1584                and move the temporary register into it */
1585             reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1586             tcg_out_mov(s, reg, ts->reg);
1587         }
1588         new_args[i] = reg;
1589         const_args[i] = 0;
1590         tcg_regset_set_reg(allocated_regs, reg);
1591     iarg_end: ;
1592     }
1593     
1594     if (def->flags & TCG_OPF_BB_END) {
1595         tcg_reg_alloc_bb_end(s, allocated_regs);
1596     } else {
1597         /* mark dead temporaries and free the associated registers */
1598         for(i = 0; i < nb_iargs; i++) {
1599             arg = args[nb_oargs + i];
1600             if (IS_DEAD_IARG(i)) {
1601                 ts = &s->temps[arg];
1602                 if (!ts->fixed_reg) {
1603                     if (ts->val_type == TEMP_VAL_REG)
1604                         s->reg_to_temp[ts->reg] = -1;
1605                     ts->val_type = TEMP_VAL_DEAD;
1606                 }
1607             }
1608         }
1609         
1610         if (def->flags & TCG_OPF_CALL_CLOBBER) {
1611             /* XXX: permit generic clobber register list ? */ 
1612             for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1613                 if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
1614                     tcg_reg_free(s, reg);
1615                 }
1616             }
1617             /* XXX: for load/store we could do that only for the slow path
1618                (i.e. when a memory callback is called) */
1619             
1620             /* store globals and free associated registers (we assume the insn
1621                can modify any global. */
1622             save_globals(s, allocated_regs);
1623         }
1624         
1625         /* satisfy the output constraints */
1626         tcg_regset_set(allocated_regs, s->reserved_regs);
1627         for(k = 0; k < nb_oargs; k++) {
1628             i = def->sorted_args[k];
1629             arg = args[i];
1630             arg_ct = &def->args_ct[i];
1631             ts = &s->temps[arg];
1632             if (arg_ct->ct & TCG_CT_ALIAS) {
1633                 reg = new_args[arg_ct->alias_index];
1634             } else {
1635                 /* if fixed register, we try to use it */
1636                 reg = ts->reg;
1637                 if (ts->fixed_reg &&
1638                     tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1639                     goto oarg_end;
1640                 }
1641                 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1642             }
1643             tcg_regset_set_reg(allocated_regs, reg);
1644             /* if a fixed register is used, then a move will be done afterwards */
1645             if (!ts->fixed_reg) {
1646                 if (ts->val_type == TEMP_VAL_REG)
1647                     s->reg_to_temp[ts->reg] = -1;
1648                 ts->val_type = TEMP_VAL_REG;
1649                 ts->reg = reg;
1650                 /* temp value is modified, so the value kept in memory is
1651                    potentially not the same */
1652                 ts->mem_coherent = 0; 
1653                 s->reg_to_temp[reg] = arg;
1654             }
1655         oarg_end:
1656             new_args[i] = reg;
1657         }
1658     }
1659
1660     /* emit instruction */
1661     tcg_out_op(s, opc, new_args, const_args);
1662     
1663     /* move the outputs in the correct register if needed */
1664     for(i = 0; i < nb_oargs; i++) {
1665         ts = &s->temps[args[i]];
1666         reg = new_args[i];
1667         if (ts->fixed_reg && ts->reg != reg) {
1668             tcg_out_mov(s, ts->reg, reg);
1669         }
1670     }
1671 }
1672
1673 #ifdef TCG_TARGET_STACK_GROWSUP
1674 #define STACK_DIR(x) (-(x))
1675 #else
1676 #define STACK_DIR(x) (x)
1677 #endif
1678
1679 static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
1680                               int opc, const TCGArg *args,
1681                               unsigned int dead_iargs)
1682 {
1683     int nb_iargs, nb_oargs, flags, nb_regs, i, reg, nb_params;
1684     TCGArg arg, func_arg;
1685     TCGTemp *ts;
1686     tcg_target_long stack_offset, call_stack_size, func_addr;
1687     int const_func_arg, allocate_args;
1688     TCGRegSet allocated_regs;
1689     const TCGArgConstraint *arg_ct;
1690
1691     arg = *args++;
1692
1693     nb_oargs = arg >> 16;
1694     nb_iargs = arg & 0xffff;
1695     nb_params = nb_iargs - 1;
1696
1697     flags = args[nb_oargs + nb_iargs];
1698
1699     nb_regs = tcg_target_get_call_iarg_regs_count(flags);
1700     if (nb_regs > nb_params)
1701         nb_regs = nb_params;
1702
1703     /* assign stack slots first */
1704     /* XXX: preallocate call stack */
1705     call_stack_size = (nb_params - nb_regs) * sizeof(tcg_target_long);
1706     call_stack_size = (call_stack_size + TCG_TARGET_STACK_ALIGN - 1) & 
1707         ~(TCG_TARGET_STACK_ALIGN - 1);
1708     allocate_args = (call_stack_size > TCG_STATIC_CALL_ARGS_SIZE);
1709     if (allocate_args) {
1710         tcg_out_addi(s, TCG_REG_CALL_STACK, -STACK_DIR(call_stack_size));
1711     }
1712
1713     stack_offset = TCG_TARGET_CALL_STACK_OFFSET;
1714     for(i = nb_regs; i < nb_params; i++) {
1715         arg = args[nb_oargs + i];
1716 #ifdef TCG_TARGET_STACK_GROWSUP
1717         stack_offset -= sizeof(tcg_target_long);
1718 #endif
1719         if (arg != TCG_CALL_DUMMY_ARG) {
1720             ts = &s->temps[arg];
1721             if (ts->val_type == TEMP_VAL_REG) {
1722                 tcg_out_st(s, ts->type, ts->reg, TCG_REG_CALL_STACK, stack_offset);
1723             } else if (ts->val_type == TEMP_VAL_MEM) {
1724                 reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], 
1725                                     s->reserved_regs);
1726                 /* XXX: not correct if reading values from the stack */
1727                 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1728                 tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
1729             } else if (ts->val_type == TEMP_VAL_CONST) {
1730                 reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], 
1731                                     s->reserved_regs);
1732                 /* XXX: sign extend may be needed on some targets */
1733                 tcg_out_movi(s, ts->type, reg, ts->val);
1734                 tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
1735             } else {
1736                 tcg_abort();
1737             }
1738         }
1739 #ifndef TCG_TARGET_STACK_GROWSUP
1740         stack_offset += sizeof(tcg_target_long);
1741 #endif
1742     }
1743     
1744     /* assign input registers */
1745     tcg_regset_set(allocated_regs, s->reserved_regs);
1746     for(i = 0; i < nb_regs; i++) {
1747         arg = args[nb_oargs + i];
1748         if (arg != TCG_CALL_DUMMY_ARG) {
1749             ts = &s->temps[arg];
1750             reg = tcg_target_call_iarg_regs[i];
1751             tcg_reg_free(s, reg);
1752             if (ts->val_type == TEMP_VAL_REG) {
1753                 if (ts->reg != reg) {
1754                     tcg_out_mov(s, reg, ts->reg);
1755                 }
1756             } else if (ts->val_type == TEMP_VAL_MEM) {
1757                 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1758             } else if (ts->val_type == TEMP_VAL_CONST) {
1759                 /* XXX: sign extend ? */
1760                 tcg_out_movi(s, ts->type, reg, ts->val);
1761             } else {
1762                 tcg_abort();
1763             }
1764             tcg_regset_set_reg(allocated_regs, reg);
1765         }
1766     }
1767     
1768     /* assign function address */
1769     func_arg = args[nb_oargs + nb_iargs - 1];
1770     arg_ct = &def->args_ct[0];
1771     ts = &s->temps[func_arg];
1772     func_addr = ts->val;
1773     const_func_arg = 0;
1774     if (ts->val_type == TEMP_VAL_MEM) {
1775         reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1776         tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1777         func_arg = reg;
1778         tcg_regset_set_reg(allocated_regs, reg);
1779     } else if (ts->val_type == TEMP_VAL_REG) {
1780         reg = ts->reg;
1781         if (!tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1782             reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1783             tcg_out_mov(s, reg, ts->reg);
1784         }
1785         func_arg = reg;
1786         tcg_regset_set_reg(allocated_regs, reg);
1787     } else if (ts->val_type == TEMP_VAL_CONST) {
1788         if (tcg_target_const_match(func_addr, arg_ct)) {
1789             const_func_arg = 1;
1790             func_arg = func_addr;
1791         } else {
1792             reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1793             tcg_out_movi(s, ts->type, reg, func_addr);
1794             func_arg = reg;
1795             tcg_regset_set_reg(allocated_regs, reg);
1796         }
1797     } else {
1798         tcg_abort();
1799     }
1800         
1801     
1802     /* mark dead temporaries and free the associated registers */
1803     for(i = 0; i < nb_iargs; i++) {
1804         arg = args[nb_oargs + i];
1805         if (IS_DEAD_IARG(i)) {
1806             ts = &s->temps[arg];
1807             if (!ts->fixed_reg) {
1808                 if (ts->val_type == TEMP_VAL_REG)
1809                     s->reg_to_temp[ts->reg] = -1;
1810                 ts->val_type = TEMP_VAL_DEAD;
1811             }
1812         }
1813     }
1814     
1815     /* clobber call registers */
1816     for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1817         if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
1818             tcg_reg_free(s, reg);
1819         }
1820     }
1821     
1822     /* store globals and free associated registers (we assume the call
1823        can modify any global. */
1824     save_globals(s, allocated_regs);
1825
1826     tcg_out_op(s, opc, &func_arg, &const_func_arg);
1827     
1828     if (allocate_args) {
1829         tcg_out_addi(s, TCG_REG_CALL_STACK, STACK_DIR(call_stack_size));
1830     }
1831
1832     /* assign output registers and emit moves if needed */
1833     for(i = 0; i < nb_oargs; i++) {
1834         arg = args[i];
1835         ts = &s->temps[arg];
1836         reg = tcg_target_call_oarg_regs[i];
1837         assert(s->reg_to_temp[reg] == -1);
1838         if (ts->fixed_reg) {
1839             if (ts->reg != reg) {
1840                 tcg_out_mov(s, ts->reg, reg);
1841             }
1842         } else {
1843             if (ts->val_type == TEMP_VAL_REG)
1844                 s->reg_to_temp[ts->reg] = -1;
1845             ts->val_type = TEMP_VAL_REG;
1846             ts->reg = reg;
1847             ts->mem_coherent = 0; 
1848             s->reg_to_temp[reg] = arg;
1849         }
1850     }
1851     
1852     return nb_iargs + nb_oargs + def->nb_cargs + 1;
1853 }
1854
1855 #ifdef CONFIG_PROFILER
1856
1857 static int64_t tcg_table_op_count[NB_OPS];
1858
1859 void dump_op_count(void)
1860 {
1861     int i;
1862     FILE *f;
1863     f = fopen("/tmp/op.log", "w");
1864     for(i = INDEX_op_end; i < NB_OPS; i++) {
1865         fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name, tcg_table_op_count[i]);
1866     }
1867     fclose(f);
1868 }
1869 #endif
1870
1871
1872 static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
1873                                       long search_pc)
1874 {
1875     int opc, op_index;
1876     const TCGOpDef *def;
1877     unsigned int dead_iargs;
1878     const TCGArg *args;
1879
1880 #ifdef DEBUG_DISAS
1881     if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
1882         qemu_log("OP:\n");
1883         tcg_dump_ops(s, logfile);
1884         qemu_log("\n");
1885     }
1886 #endif
1887
1888 #ifdef CONFIG_PROFILER
1889     s->la_time -= profile_getclock();
1890 #endif
1891     tcg_liveness_analysis(s);
1892 #ifdef CONFIG_PROFILER
1893     s->la_time += profile_getclock();
1894 #endif
1895
1896 #ifdef DEBUG_DISAS
1897     if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_OPT))) {
1898         qemu_log("OP after la:\n");
1899         tcg_dump_ops(s, logfile);
1900         qemu_log("\n");
1901     }
1902 #endif
1903
1904     tcg_reg_alloc_start(s);
1905
1906     s->code_buf = gen_code_buf;
1907     s->code_ptr = gen_code_buf;
1908
1909     args = gen_opparam_buf;
1910     op_index = 0;
1911
1912     for(;;) {
1913         opc = gen_opc_buf[op_index];
1914 #ifdef CONFIG_PROFILER
1915         tcg_table_op_count[opc]++;
1916 #endif
1917         def = &tcg_op_defs[opc];
1918 #if 0
1919         printf("%s: %d %d %d\n", def->name,
1920                def->nb_oargs, def->nb_iargs, def->nb_cargs);
1921         //        dump_regs(s);
1922 #endif
1923         switch(opc) {
1924         case INDEX_op_mov_i32:
1925 #if TCG_TARGET_REG_BITS == 64
1926         case INDEX_op_mov_i64:
1927 #endif
1928             dead_iargs = s->op_dead_iargs[op_index];
1929             tcg_reg_alloc_mov(s, def, args, dead_iargs);
1930             break;
1931         case INDEX_op_movi_i32:
1932 #if TCG_TARGET_REG_BITS == 64
1933         case INDEX_op_movi_i64:
1934 #endif
1935             tcg_reg_alloc_movi(s, args);
1936             break;
1937         case INDEX_op_debug_insn_start:
1938             /* debug instruction */
1939             break;
1940         case INDEX_op_nop:
1941         case INDEX_op_nop1:
1942         case INDEX_op_nop2:
1943         case INDEX_op_nop3:
1944             break;
1945         case INDEX_op_nopn:
1946             args += args[0];
1947             goto next;
1948         case INDEX_op_discard:
1949             {
1950                 TCGTemp *ts;
1951                 ts = &s->temps[args[0]];
1952                 /* mark the temporary as dead */
1953                 if (!ts->fixed_reg) {
1954                     if (ts->val_type == TEMP_VAL_REG)
1955                         s->reg_to_temp[ts->reg] = -1;
1956                     ts->val_type = TEMP_VAL_DEAD;
1957                 }
1958             }
1959             break;
1960         case INDEX_op_set_label:
1961             tcg_reg_alloc_bb_end(s, s->reserved_regs);
1962             tcg_out_label(s, args[0], (long)s->code_ptr);
1963             break;
1964         case INDEX_op_call:
1965             dead_iargs = s->op_dead_iargs[op_index];
1966             args += tcg_reg_alloc_call(s, def, opc, args, dead_iargs);
1967             goto next;
1968         case INDEX_op_end:
1969             goto the_end;
1970         default:
1971             /* Note: in order to speed up the code, it would be much
1972                faster to have specialized register allocator functions for
1973                some common argument patterns */
1974             dead_iargs = s->op_dead_iargs[op_index];
1975             tcg_reg_alloc_op(s, def, opc, args, dead_iargs);
1976             break;
1977         }
1978         args += def->nb_args;
1979     next:
1980         if (search_pc >= 0 && search_pc < s->code_ptr - gen_code_buf) {
1981             return op_index;
1982         }
1983         op_index++;
1984 #ifndef NDEBUG
1985         check_regs(s);
1986 #endif
1987     }
1988  the_end:
1989     return -1;
1990 }
1991
1992 int tcg_gen_code(TCGContext *s, uint8_t *gen_code_buf)
1993 {
1994 #ifdef CONFIG_PROFILER
1995     {
1996         int n;
1997         n = (gen_opc_ptr - gen_opc_buf);
1998         s->op_count += n;
1999         if (n > s->op_count_max)
2000             s->op_count_max = n;
2001
2002         s->temp_count += s->nb_temps;
2003         if (s->nb_temps > s->temp_count_max)
2004             s->temp_count_max = s->nb_temps;
2005     }
2006 #endif
2007
2008     tcg_gen_code_common(s, gen_code_buf, -1);
2009
2010     /* flush instruction cache */
2011     flush_icache_range((unsigned long)gen_code_buf, 
2012                        (unsigned long)s->code_ptr);
2013     return s->code_ptr -  gen_code_buf;
2014 }
2015
2016 /* Return the index of the micro operation such as the pc after is <
2017    offset bytes from the start of the TB.  The contents of gen_code_buf must
2018    not be changed, though writing the same values is ok.
2019    Return -1 if not found. */
2020 int tcg_gen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, long offset)
2021 {
2022     return tcg_gen_code_common(s, gen_code_buf, offset);
2023 }
2024
2025 #ifdef CONFIG_PROFILER
2026 void tcg_dump_info(FILE *f,
2027                    int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
2028 {
2029     TCGContext *s = &tcg_ctx;
2030     int64_t tot;
2031
2032     tot = s->interm_time + s->code_time;
2033     cpu_fprintf(f, "JIT cycles          %" PRId64 " (%0.3f s at 2.4 GHz)\n",
2034                 tot, tot / 2.4e9);
2035     cpu_fprintf(f, "translated TBs      %" PRId64 " (aborted=%" PRId64 " %0.1f%%)\n", 
2036                 s->tb_count, 
2037                 s->tb_count1 - s->tb_count,
2038                 s->tb_count1 ? (double)(s->tb_count1 - s->tb_count) / s->tb_count1 * 100.0 : 0);
2039     cpu_fprintf(f, "avg ops/TB          %0.1f max=%d\n", 
2040                 s->tb_count ? (double)s->op_count / s->tb_count : 0, s->op_count_max);
2041     cpu_fprintf(f, "deleted ops/TB      %0.2f\n",
2042                 s->tb_count ? 
2043                 (double)s->del_op_count / s->tb_count : 0);
2044     cpu_fprintf(f, "avg temps/TB        %0.2f max=%d\n",
2045                 s->tb_count ? 
2046                 (double)s->temp_count / s->tb_count : 0,
2047                 s->temp_count_max);
2048     
2049     cpu_fprintf(f, "cycles/op           %0.1f\n", 
2050                 s->op_count ? (double)tot / s->op_count : 0);
2051     cpu_fprintf(f, "cycles/in byte      %0.1f\n", 
2052                 s->code_in_len ? (double)tot / s->code_in_len : 0);
2053     cpu_fprintf(f, "cycles/out byte     %0.1f\n", 
2054                 s->code_out_len ? (double)tot / s->code_out_len : 0);
2055     if (tot == 0)
2056         tot = 1;
2057     cpu_fprintf(f, "  gen_interm time   %0.1f%%\n", 
2058                 (double)s->interm_time / tot * 100.0);
2059     cpu_fprintf(f, "  gen_code time     %0.1f%%\n", 
2060                 (double)s->code_time / tot * 100.0);
2061     cpu_fprintf(f, "liveness/code time  %0.1f%%\n", 
2062                 (double)s->la_time / (s->code_time ? s->code_time : 1) * 100.0);
2063     cpu_fprintf(f, "cpu_restore count   %" PRId64 "\n",
2064                 s->restore_count);
2065     cpu_fprintf(f, "  avg cycles        %0.1f\n",
2066                 s->restore_count ? (double)s->restore_time / s->restore_count : 0);
2067     {
2068         extern void dump_op_count(void);
2069         dump_op_count();
2070     }
2071 }
2072 #else
2073 void tcg_dump_info(FILE *f,
2074                    int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
2075 {
2076     cpu_fprintf(f, "[TCG profiler not compiled]\n");
2077 }
2078 #endif