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