]> Git Repo - qemu.git/blob - tcg/tcg.c
Merge remote branch 'mst/for_anthony' into staging
[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 CONFIG_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, oargs, iargs, cargs, flags) { #s, oargs, iargs, 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
674 static void tcg_reg_alloc_start(TCGContext *s)
675 {
676     int i;
677     TCGTemp *ts;
678     for(i = 0; i < s->nb_globals; i++) {
679         ts = &s->temps[i];
680         if (ts->fixed_reg) {
681             ts->val_type = TEMP_VAL_REG;
682         } else {
683             ts->val_type = TEMP_VAL_MEM;
684         }
685     }
686     for(i = s->nb_globals; i < s->nb_temps; i++) {
687         ts = &s->temps[i];
688         ts->val_type = TEMP_VAL_DEAD;
689         ts->mem_allocated = 0;
690         ts->fixed_reg = 0;
691     }
692     for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
693         s->reg_to_temp[i] = -1;
694     }
695 }
696
697 static char *tcg_get_arg_str_idx(TCGContext *s, char *buf, int buf_size,
698                                  int idx)
699 {
700     TCGTemp *ts;
701
702     ts = &s->temps[idx];
703     if (idx < s->nb_globals) {
704         pstrcpy(buf, buf_size, ts->name);
705     } else {
706         if (ts->temp_local) 
707             snprintf(buf, buf_size, "loc%d", idx - s->nb_globals);
708         else
709             snprintf(buf, buf_size, "tmp%d", idx - s->nb_globals);
710     }
711     return buf;
712 }
713
714 char *tcg_get_arg_str_i32(TCGContext *s, char *buf, int buf_size, TCGv_i32 arg)
715 {
716     return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I32(arg));
717 }
718
719 char *tcg_get_arg_str_i64(TCGContext *s, char *buf, int buf_size, TCGv_i64 arg)
720 {
721     return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I64(arg));
722 }
723
724 static int helper_cmp(const void *p1, const void *p2)
725 {
726     const TCGHelperInfo *th1 = p1;
727     const TCGHelperInfo *th2 = p2;
728     if (th1->func < th2->func)
729         return -1;
730     else if (th1->func == th2->func)
731         return 0;
732     else
733         return 1;
734 }
735
736 /* find helper definition (Note: A hash table would be better) */
737 static TCGHelperInfo *tcg_find_helper(TCGContext *s, tcg_target_ulong val)
738 {
739     int m, m_min, m_max;
740     TCGHelperInfo *th;
741     tcg_target_ulong v;
742
743     if (unlikely(!s->helpers_sorted)) {
744         qsort(s->helpers, s->nb_helpers, sizeof(TCGHelperInfo), 
745               helper_cmp);
746         s->helpers_sorted = 1;
747     }
748
749     /* binary search */
750     m_min = 0;
751     m_max = s->nb_helpers - 1;
752     while (m_min <= m_max) {
753         m = (m_min + m_max) >> 1;
754         th = &s->helpers[m];
755         v = th->func;
756         if (v == val)
757             return th;
758         else if (val < v) {
759             m_max = m - 1;
760         } else {
761             m_min = m + 1;
762         }
763     }
764     return NULL;
765 }
766
767 static const char * const cond_name[] =
768 {
769     [TCG_COND_EQ] = "eq",
770     [TCG_COND_NE] = "ne",
771     [TCG_COND_LT] = "lt",
772     [TCG_COND_GE] = "ge",
773     [TCG_COND_LE] = "le",
774     [TCG_COND_GT] = "gt",
775     [TCG_COND_LTU] = "ltu",
776     [TCG_COND_GEU] = "geu",
777     [TCG_COND_LEU] = "leu",
778     [TCG_COND_GTU] = "gtu"
779 };
780
781 void tcg_dump_ops(TCGContext *s, FILE *outfile)
782 {
783     const uint16_t *opc_ptr;
784     const TCGArg *args;
785     TCGArg arg;
786     int c, i, k, nb_oargs, nb_iargs, nb_cargs, first_insn;
787     const TCGOpDef *def;
788     char buf[128];
789
790     first_insn = 1;
791     opc_ptr = gen_opc_buf;
792     args = gen_opparam_buf;
793     while (opc_ptr < gen_opc_ptr) {
794         c = *opc_ptr++;
795         def = &tcg_op_defs[c];
796         if (c == INDEX_op_debug_insn_start) {
797             uint64_t pc;
798 #if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
799             pc = ((uint64_t)args[1] << 32) | args[0];
800 #else
801             pc = args[0];
802 #endif
803             if (!first_insn) 
804                 fprintf(outfile, "\n");
805             fprintf(outfile, " ---- 0x%" PRIx64, pc);
806             first_insn = 0;
807             nb_oargs = def->nb_oargs;
808             nb_iargs = def->nb_iargs;
809             nb_cargs = def->nb_cargs;
810         } else if (c == INDEX_op_call) {
811             TCGArg arg;
812
813             /* variable number of arguments */
814             arg = *args++;
815             nb_oargs = arg >> 16;
816             nb_iargs = arg & 0xffff;
817             nb_cargs = def->nb_cargs;
818
819             fprintf(outfile, " %s ", def->name);
820
821             /* function name */
822             fprintf(outfile, "%s",
823                     tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + nb_iargs - 1]));
824             /* flags */
825             fprintf(outfile, ",$0x%" TCG_PRIlx,
826                     args[nb_oargs + nb_iargs]);
827             /* nb out args */
828             fprintf(outfile, ",$%d", nb_oargs);
829             for(i = 0; i < nb_oargs; i++) {
830                 fprintf(outfile, ",");
831                 fprintf(outfile, "%s",
832                         tcg_get_arg_str_idx(s, buf, sizeof(buf), args[i]));
833             }
834             for(i = 0; i < (nb_iargs - 1); i++) {
835                 fprintf(outfile, ",");
836                 if (args[nb_oargs + i] == TCG_CALL_DUMMY_ARG) {
837                     fprintf(outfile, "<dummy>");
838                 } else {
839                     fprintf(outfile, "%s",
840                             tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + i]));
841                 }
842             }
843         } else if (c == INDEX_op_movi_i32 
844 #if TCG_TARGET_REG_BITS == 64
845                    || c == INDEX_op_movi_i64
846 #endif
847                    ) {
848             tcg_target_ulong val;
849             TCGHelperInfo *th;
850
851             nb_oargs = def->nb_oargs;
852             nb_iargs = def->nb_iargs;
853             nb_cargs = def->nb_cargs;
854             fprintf(outfile, " %s %s,$", def->name, 
855                     tcg_get_arg_str_idx(s, buf, sizeof(buf), args[0]));
856             val = args[1];
857             th = tcg_find_helper(s, val);
858             if (th) {
859                 fprintf(outfile, "%s", th->name);
860             } else {
861                 if (c == INDEX_op_movi_i32)
862                     fprintf(outfile, "0x%x", (uint32_t)val);
863                 else
864                     fprintf(outfile, "0x%" PRIx64 , (uint64_t)val);
865             }
866         } else {
867             fprintf(outfile, " %s ", def->name);
868             if (c == INDEX_op_nopn) {
869                 /* variable number of arguments */
870                 nb_cargs = *args;
871                 nb_oargs = 0;
872                 nb_iargs = 0;
873             } else {
874                 nb_oargs = def->nb_oargs;
875                 nb_iargs = def->nb_iargs;
876                 nb_cargs = def->nb_cargs;
877             }
878             
879             k = 0;
880             for(i = 0; i < nb_oargs; i++) {
881                 if (k != 0)
882                     fprintf(outfile, ",");
883                 fprintf(outfile, "%s",
884                         tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
885             }
886             for(i = 0; i < nb_iargs; i++) {
887                 if (k != 0)
888                     fprintf(outfile, ",");
889                 fprintf(outfile, "%s",
890                         tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
891             }
892             switch (c) {
893             case INDEX_op_brcond_i32:
894 #if TCG_TARGET_REG_BITS == 32
895             case INDEX_op_brcond2_i32:
896 #elif TCG_TARGET_REG_BITS == 64
897             case INDEX_op_brcond_i64:
898 #endif
899             case INDEX_op_setcond_i32:
900 #if TCG_TARGET_REG_BITS == 32
901             case INDEX_op_setcond2_i32:
902 #elif TCG_TARGET_REG_BITS == 64
903             case INDEX_op_setcond_i64:
904 #endif
905                 if (args[k] < ARRAY_SIZE(cond_name) && cond_name[args[k]])
906                     fprintf(outfile, ",%s", cond_name[args[k++]]);
907                 else
908                     fprintf(outfile, ",$0x%" TCG_PRIlx, args[k++]);
909                 i = 1;
910                 break;
911             default:
912                 i = 0;
913                 break;
914             }
915             for(; i < nb_cargs; i++) {
916                 if (k != 0)
917                     fprintf(outfile, ",");
918                 arg = args[k++];
919                 fprintf(outfile, "$0x%" TCG_PRIlx, arg);
920             }
921         }
922         fprintf(outfile, "\n");
923         args += nb_iargs + nb_oargs + nb_cargs;
924     }
925 }
926
927 /* we give more priority to constraints with less registers */
928 static int get_constraint_priority(const TCGOpDef *def, int k)
929 {
930     const TCGArgConstraint *arg_ct;
931
932     int i, n;
933     arg_ct = &def->args_ct[k];
934     if (arg_ct->ct & TCG_CT_ALIAS) {
935         /* an alias is equivalent to a single register */
936         n = 1;
937     } else {
938         if (!(arg_ct->ct & TCG_CT_REG))
939             return 0;
940         n = 0;
941         for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
942             if (tcg_regset_test_reg(arg_ct->u.regs, i))
943                 n++;
944         }
945     }
946     return TCG_TARGET_NB_REGS - n + 1;
947 }
948
949 /* sort from highest priority to lowest */
950 static void sort_constraints(TCGOpDef *def, int start, int n)
951 {
952     int i, j, p1, p2, tmp;
953
954     for(i = 0; i < n; i++)
955         def->sorted_args[start + i] = start + i;
956     if (n <= 1)
957         return;
958     for(i = 0; i < n - 1; i++) {
959         for(j = i + 1; j < n; j++) {
960             p1 = get_constraint_priority(def, def->sorted_args[start + i]);
961             p2 = get_constraint_priority(def, def->sorted_args[start + j]);
962             if (p1 < p2) {
963                 tmp = def->sorted_args[start + i];
964                 def->sorted_args[start + i] = def->sorted_args[start + j];
965                 def->sorted_args[start + j] = tmp;
966             }
967         }
968     }
969 }
970
971 void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs)
972 {
973     int op;
974     TCGOpDef *def;
975     const char *ct_str;
976     int i, nb_args;
977
978     for(;;) {
979         if (tdefs->op < 0)
980             break;
981         op = tdefs->op;
982         assert(op >= 0 && op < NB_OPS);
983         def = &tcg_op_defs[op];
984 #if defined(CONFIG_DEBUG_TCG)
985         /* Duplicate entry in op definitions? */
986         assert(!def->used);
987         def->used = 1;
988 #endif
989         nb_args = def->nb_iargs + def->nb_oargs;
990         for(i = 0; i < nb_args; i++) {
991             ct_str = tdefs->args_ct_str[i];
992             /* Incomplete TCGTargetOpDef entry? */
993             assert(ct_str != NULL);
994             tcg_regset_clear(def->args_ct[i].u.regs);
995             def->args_ct[i].ct = 0;
996             if (ct_str[0] >= '0' && ct_str[0] <= '9') {
997                 int oarg;
998                 oarg = ct_str[0] - '0';
999                 assert(oarg < def->nb_oargs);
1000                 assert(def->args_ct[oarg].ct & TCG_CT_REG);
1001                 /* TCG_CT_ALIAS is for the output arguments. The input
1002                    argument is tagged with TCG_CT_IALIAS. */
1003                 def->args_ct[i] = def->args_ct[oarg];
1004                 def->args_ct[oarg].ct = TCG_CT_ALIAS;
1005                 def->args_ct[oarg].alias_index = i;
1006                 def->args_ct[i].ct |= TCG_CT_IALIAS;
1007                 def->args_ct[i].alias_index = oarg;
1008             } else {
1009                 for(;;) {
1010                     if (*ct_str == '\0')
1011                         break;
1012                     switch(*ct_str) {
1013                     case 'i':
1014                         def->args_ct[i].ct |= TCG_CT_CONST;
1015                         ct_str++;
1016                         break;
1017                     default:
1018                         if (target_parse_constraint(&def->args_ct[i], &ct_str) < 0) {
1019                             fprintf(stderr, "Invalid constraint '%s' for arg %d of operation '%s'\n",
1020                                     ct_str, i, def->name);
1021                             exit(1);
1022                         }
1023                     }
1024                 }
1025             }
1026         }
1027
1028         /* TCGTargetOpDef entry with too much information? */
1029         assert(i == TCG_MAX_OP_ARGS || tdefs->args_ct_str[i] == NULL);
1030
1031         /* sort the constraints (XXX: this is just an heuristic) */
1032         sort_constraints(def, 0, def->nb_oargs);
1033         sort_constraints(def, def->nb_oargs, def->nb_iargs);
1034
1035 #if 0
1036         {
1037             int i;
1038
1039             printf("%s: sorted=", def->name);
1040             for(i = 0; i < def->nb_oargs + def->nb_iargs; i++)
1041                 printf(" %d", def->sorted_args[i]);
1042             printf("\n");
1043         }
1044 #endif
1045         tdefs++;
1046     }
1047
1048 #if defined(CONFIG_DEBUG_TCG)
1049     for (op = 0; op < ARRAY_SIZE(tcg_op_defs); op++) {
1050         if (op < INDEX_op_call || op == INDEX_op_debug_insn_start) {
1051             /* Wrong entry in op definitions? */
1052             assert(!tcg_op_defs[op].used);
1053         } else {
1054             /* Missing entry in op definitions? */
1055             assert(tcg_op_defs[op].used);
1056         }
1057     }
1058 #endif
1059 }
1060
1061 #ifdef USE_LIVENESS_ANALYSIS
1062
1063 /* set a nop for an operation using 'nb_args' */
1064 static inline void tcg_set_nop(TCGContext *s, uint16_t *opc_ptr, 
1065                                TCGArg *args, int nb_args)
1066 {
1067     if (nb_args == 0) {
1068         *opc_ptr = INDEX_op_nop;
1069     } else {
1070         *opc_ptr = INDEX_op_nopn;
1071         args[0] = nb_args;
1072         args[nb_args - 1] = nb_args;
1073     }
1074 }
1075
1076 /* liveness analysis: end of function: globals are live, temps are
1077    dead. */
1078 /* XXX: at this stage, not used as there would be little gains because
1079    most TBs end with a conditional jump. */
1080 static inline void tcg_la_func_end(TCGContext *s, uint8_t *dead_temps)
1081 {
1082     memset(dead_temps, 0, s->nb_globals);
1083     memset(dead_temps + s->nb_globals, 1, s->nb_temps - s->nb_globals);
1084 }
1085
1086 /* liveness analysis: end of basic block: globals are live, temps are
1087    dead, local temps are live. */
1088 static inline void tcg_la_bb_end(TCGContext *s, uint8_t *dead_temps)
1089 {
1090     int i;
1091     TCGTemp *ts;
1092
1093     memset(dead_temps, 0, s->nb_globals);
1094     ts = &s->temps[s->nb_globals];
1095     for(i = s->nb_globals; i < s->nb_temps; i++) {
1096         if (ts->temp_local)
1097             dead_temps[i] = 0;
1098         else
1099             dead_temps[i] = 1;
1100         ts++;
1101     }
1102 }
1103
1104 /* Liveness analysis : update the opc_dead_iargs array to tell if a
1105    given input arguments is dead. Instructions updating dead
1106    temporaries are removed. */
1107 static void tcg_liveness_analysis(TCGContext *s)
1108 {
1109     int i, op_index, op, nb_args, nb_iargs, nb_oargs, arg, nb_ops;
1110     TCGArg *args;
1111     const TCGOpDef *def;
1112     uint8_t *dead_temps;
1113     unsigned int dead_iargs;
1114     
1115     gen_opc_ptr++; /* skip end */
1116
1117     nb_ops = gen_opc_ptr - gen_opc_buf;
1118
1119     s->op_dead_iargs = tcg_malloc(nb_ops * sizeof(uint16_t));
1120     
1121     dead_temps = tcg_malloc(s->nb_temps);
1122     memset(dead_temps, 1, s->nb_temps);
1123
1124     args = gen_opparam_ptr;
1125     op_index = nb_ops - 1;
1126     while (op_index >= 0) {
1127         op = gen_opc_buf[op_index];
1128         def = &tcg_op_defs[op];
1129         switch(op) {
1130         case INDEX_op_call:
1131             {
1132                 int call_flags;
1133
1134                 nb_args = args[-1];
1135                 args -= nb_args;
1136                 nb_iargs = args[0] & 0xffff;
1137                 nb_oargs = args[0] >> 16;
1138                 args++;
1139                 call_flags = args[nb_oargs + nb_iargs];
1140
1141                 /* pure functions can be removed if their result is not
1142                    used */
1143                 if (call_flags & TCG_CALL_PURE) {
1144                     for(i = 0; i < nb_oargs; i++) {
1145                         arg = args[i];
1146                         if (!dead_temps[arg])
1147                             goto do_not_remove_call;
1148                     }
1149                     tcg_set_nop(s, gen_opc_buf + op_index, 
1150                                 args - 1, nb_args);
1151                 } else {
1152                 do_not_remove_call:
1153
1154                     /* output args are dead */
1155                     for(i = 0; i < nb_oargs; i++) {
1156                         arg = args[i];
1157                         dead_temps[arg] = 1;
1158                     }
1159                     
1160                     if (!(call_flags & TCG_CALL_CONST)) {
1161                         /* globals are live (they may be used by the call) */
1162                         memset(dead_temps, 0, s->nb_globals);
1163                     }
1164
1165                     /* input args are live */
1166                     dead_iargs = 0;
1167                     for(i = 0; i < nb_iargs; i++) {
1168                         arg = args[i + nb_oargs];
1169                         if (arg != TCG_CALL_DUMMY_ARG) {
1170                             if (dead_temps[arg]) {
1171                                 dead_iargs |= (1 << i);
1172                             }
1173                             dead_temps[arg] = 0;
1174                         }
1175                     }
1176                     s->op_dead_iargs[op_index] = dead_iargs;
1177                 }
1178                 args--;
1179             }
1180             break;
1181         case INDEX_op_set_label:
1182             args--;
1183             /* mark end of basic block */
1184             tcg_la_bb_end(s, dead_temps);
1185             break;
1186         case INDEX_op_debug_insn_start:
1187             args -= def->nb_args;
1188             break;
1189         case INDEX_op_nopn:
1190             nb_args = args[-1];
1191             args -= nb_args;
1192             break;
1193         case INDEX_op_discard:
1194             args--;
1195             /* mark the temporary as dead */
1196             dead_temps[args[0]] = 1;
1197             break;
1198         case INDEX_op_end:
1199             break;
1200             /* XXX: optimize by hardcoding common cases (e.g. triadic ops) */
1201         default:
1202             args -= def->nb_args;
1203             nb_iargs = def->nb_iargs;
1204             nb_oargs = def->nb_oargs;
1205
1206             /* Test if the operation can be removed because all
1207                its outputs are dead. We assume that nb_oargs == 0
1208                implies side effects */
1209             if (!(def->flags & TCG_OPF_SIDE_EFFECTS) && nb_oargs != 0) {
1210                 for(i = 0; i < nb_oargs; i++) {
1211                     arg = args[i];
1212                     if (!dead_temps[arg])
1213                         goto do_not_remove;
1214                 }
1215                 tcg_set_nop(s, gen_opc_buf + op_index, args, def->nb_args);
1216 #ifdef CONFIG_PROFILER
1217                 s->del_op_count++;
1218 #endif
1219             } else {
1220             do_not_remove:
1221
1222                 /* output args are dead */
1223                 for(i = 0; i < nb_oargs; i++) {
1224                     arg = args[i];
1225                     dead_temps[arg] = 1;
1226                 }
1227
1228                 /* if end of basic block, update */
1229                 if (def->flags & TCG_OPF_BB_END) {
1230                     tcg_la_bb_end(s, dead_temps);
1231                 } else if (def->flags & TCG_OPF_CALL_CLOBBER) {
1232                     /* globals are live */
1233                     memset(dead_temps, 0, s->nb_globals);
1234                 }
1235
1236                 /* input args are live */
1237                 dead_iargs = 0;
1238                 for(i = 0; i < nb_iargs; i++) {
1239                     arg = args[i + nb_oargs];
1240                     if (dead_temps[arg]) {
1241                         dead_iargs |= (1 << i);
1242                     }
1243                     dead_temps[arg] = 0;
1244                 }
1245                 s->op_dead_iargs[op_index] = dead_iargs;
1246             }
1247             break;
1248         }
1249         op_index--;
1250     }
1251
1252     if (args != gen_opparam_buf)
1253         tcg_abort();
1254 }
1255 #else
1256 /* dummy liveness analysis */
1257 void tcg_liveness_analysis(TCGContext *s)
1258 {
1259     int nb_ops;
1260     nb_ops = gen_opc_ptr - gen_opc_buf;
1261
1262     s->op_dead_iargs = tcg_malloc(nb_ops * sizeof(uint16_t));
1263     memset(s->op_dead_iargs, 0, nb_ops * sizeof(uint16_t));
1264 }
1265 #endif
1266
1267 #ifndef NDEBUG
1268 static void dump_regs(TCGContext *s)
1269 {
1270     TCGTemp *ts;
1271     int i;
1272     char buf[64];
1273
1274     for(i = 0; i < s->nb_temps; i++) {
1275         ts = &s->temps[i];
1276         printf("  %10s: ", tcg_get_arg_str_idx(s, buf, sizeof(buf), i));
1277         switch(ts->val_type) {
1278         case TEMP_VAL_REG:
1279             printf("%s", tcg_target_reg_names[ts->reg]);
1280             break;
1281         case TEMP_VAL_MEM:
1282             printf("%d(%s)", (int)ts->mem_offset, tcg_target_reg_names[ts->mem_reg]);
1283             break;
1284         case TEMP_VAL_CONST:
1285             printf("$0x%" TCG_PRIlx, ts->val);
1286             break;
1287         case TEMP_VAL_DEAD:
1288             printf("D");
1289             break;
1290         default:
1291             printf("???");
1292             break;
1293         }
1294         printf("\n");
1295     }
1296
1297     for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
1298         if (s->reg_to_temp[i] >= 0) {
1299             printf("%s: %s\n", 
1300                    tcg_target_reg_names[i], 
1301                    tcg_get_arg_str_idx(s, buf, sizeof(buf), s->reg_to_temp[i]));
1302         }
1303     }
1304 }
1305
1306 static void check_regs(TCGContext *s)
1307 {
1308     int reg, k;
1309     TCGTemp *ts;
1310     char buf[64];
1311
1312     for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1313         k = s->reg_to_temp[reg];
1314         if (k >= 0) {
1315             ts = &s->temps[k];
1316             if (ts->val_type != TEMP_VAL_REG ||
1317                 ts->reg != reg) {
1318                 printf("Inconsistency for register %s:\n", 
1319                        tcg_target_reg_names[reg]);
1320                 goto fail;
1321             }
1322         }
1323     }
1324     for(k = 0; k < s->nb_temps; k++) {
1325         ts = &s->temps[k];
1326         if (ts->val_type == TEMP_VAL_REG &&
1327             !ts->fixed_reg &&
1328             s->reg_to_temp[ts->reg] != k) {
1329                 printf("Inconsistency for temp %s:\n", 
1330                        tcg_get_arg_str_idx(s, buf, sizeof(buf), k));
1331         fail:
1332                 printf("reg state:\n");
1333                 dump_regs(s);
1334                 tcg_abort();
1335         }
1336     }
1337 }
1338 #endif
1339
1340 static void temp_allocate_frame(TCGContext *s, int temp)
1341 {
1342     TCGTemp *ts;
1343     ts = &s->temps[temp];
1344     s->current_frame_offset = (s->current_frame_offset + sizeof(tcg_target_long) - 1) & ~(sizeof(tcg_target_long) - 1);
1345     if (s->current_frame_offset + sizeof(tcg_target_long) > s->frame_end)
1346         tcg_abort();
1347     ts->mem_offset = s->current_frame_offset;
1348     ts->mem_reg = s->frame_reg;
1349     ts->mem_allocated = 1;
1350     s->current_frame_offset += sizeof(tcg_target_long);
1351 }
1352
1353 /* free register 'reg' by spilling the corresponding temporary if necessary */
1354 static void tcg_reg_free(TCGContext *s, int reg)
1355 {
1356     TCGTemp *ts;
1357     int temp;
1358
1359     temp = s->reg_to_temp[reg];
1360     if (temp != -1) {
1361         ts = &s->temps[temp];
1362         assert(ts->val_type == TEMP_VAL_REG);
1363         if (!ts->mem_coherent) {
1364             if (!ts->mem_allocated) 
1365                 temp_allocate_frame(s, temp);
1366             tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1367         }
1368         ts->val_type = TEMP_VAL_MEM;
1369         s->reg_to_temp[reg] = -1;
1370     }
1371 }
1372
1373 /* Allocate a register belonging to reg1 & ~reg2 */
1374 static int tcg_reg_alloc(TCGContext *s, TCGRegSet reg1, TCGRegSet reg2)
1375 {
1376     int i, reg;
1377     TCGRegSet reg_ct;
1378
1379     tcg_regset_andnot(reg_ct, reg1, reg2);
1380
1381     /* first try free registers */
1382     for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1383         reg = tcg_target_reg_alloc_order[i];
1384         if (tcg_regset_test_reg(reg_ct, reg) && s->reg_to_temp[reg] == -1)
1385             return reg;
1386     }
1387
1388     /* XXX: do better spill choice */
1389     for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1390         reg = tcg_target_reg_alloc_order[i];
1391         if (tcg_regset_test_reg(reg_ct, reg)) {
1392             tcg_reg_free(s, reg);
1393             return reg;
1394         }
1395     }
1396
1397     tcg_abort();
1398 }
1399
1400 /* save a temporary to memory. 'allocated_regs' is used in case a
1401    temporary registers needs to be allocated to store a constant. */
1402 static void temp_save(TCGContext *s, int temp, TCGRegSet allocated_regs)
1403 {
1404     TCGTemp *ts;
1405     int reg;
1406
1407     ts = &s->temps[temp];
1408     if (!ts->fixed_reg) {
1409         switch(ts->val_type) {
1410         case TEMP_VAL_REG:
1411             tcg_reg_free(s, ts->reg);
1412             break;
1413         case TEMP_VAL_DEAD:
1414             ts->val_type = TEMP_VAL_MEM;
1415             break;
1416         case TEMP_VAL_CONST:
1417             reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], 
1418                                 allocated_regs);
1419             if (!ts->mem_allocated) 
1420                 temp_allocate_frame(s, temp);
1421             tcg_out_movi(s, ts->type, reg, ts->val);
1422             tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1423             ts->val_type = TEMP_VAL_MEM;
1424             break;
1425         case TEMP_VAL_MEM:
1426             break;
1427         default:
1428             tcg_abort();
1429         }
1430     }
1431 }
1432
1433 /* save globals to their cannonical location and assume they can be
1434    modified be the following code. 'allocated_regs' is used in case a
1435    temporary registers needs to be allocated to store a constant. */
1436 static void save_globals(TCGContext *s, TCGRegSet allocated_regs)
1437 {
1438     int i;
1439
1440     for(i = 0; i < s->nb_globals; i++) {
1441         temp_save(s, i, allocated_regs);
1442     }
1443 }
1444
1445 /* at the end of a basic block, we assume all temporaries are dead and
1446    all globals are stored at their canonical location. */
1447 static void tcg_reg_alloc_bb_end(TCGContext *s, TCGRegSet allocated_regs)
1448 {
1449     TCGTemp *ts;
1450     int i;
1451
1452     for(i = s->nb_globals; i < s->nb_temps; i++) {
1453         ts = &s->temps[i];
1454         if (ts->temp_local) {
1455             temp_save(s, i, allocated_regs);
1456         } else {
1457             if (ts->val_type == TEMP_VAL_REG) {
1458                 s->reg_to_temp[ts->reg] = -1;
1459             }
1460             ts->val_type = TEMP_VAL_DEAD;
1461         }
1462     }
1463
1464     save_globals(s, allocated_regs);
1465 }
1466
1467 #define IS_DEAD_IARG(n) ((dead_iargs >> (n)) & 1)
1468
1469 static void tcg_reg_alloc_movi(TCGContext *s, const TCGArg *args)
1470 {
1471     TCGTemp *ots;
1472     tcg_target_ulong val;
1473
1474     ots = &s->temps[args[0]];
1475     val = args[1];
1476
1477     if (ots->fixed_reg) {
1478         /* for fixed registers, we do not do any constant
1479            propagation */
1480         tcg_out_movi(s, ots->type, ots->reg, val);
1481     } else {
1482         /* The movi is not explicitly generated here */
1483         if (ots->val_type == TEMP_VAL_REG)
1484             s->reg_to_temp[ots->reg] = -1;
1485         ots->val_type = TEMP_VAL_CONST;
1486         ots->val = val;
1487     }
1488 }
1489
1490 static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
1491                               const TCGArg *args,
1492                               unsigned int dead_iargs)
1493 {
1494     TCGTemp *ts, *ots;
1495     int reg;
1496     const TCGArgConstraint *arg_ct;
1497
1498     ots = &s->temps[args[0]];
1499     ts = &s->temps[args[1]];
1500     arg_ct = &def->args_ct[0];
1501
1502     /* XXX: always mark arg dead if IS_DEAD_IARG(0) */
1503     if (ts->val_type == TEMP_VAL_REG) {
1504         if (IS_DEAD_IARG(0) && !ts->fixed_reg && !ots->fixed_reg) {
1505             /* the mov can be suppressed */
1506             if (ots->val_type == TEMP_VAL_REG)
1507                 s->reg_to_temp[ots->reg] = -1;
1508             reg = ts->reg;
1509             s->reg_to_temp[reg] = -1;
1510             ts->val_type = TEMP_VAL_DEAD;
1511         } else {
1512             if (ots->val_type == TEMP_VAL_REG) {
1513                 reg = ots->reg;
1514             } else {
1515                 reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1516             }
1517             if (ts->reg != reg) {
1518                 tcg_out_mov(s, reg, ts->reg);
1519             }
1520         }
1521     } else if (ts->val_type == TEMP_VAL_MEM) {
1522         if (ots->val_type == TEMP_VAL_REG) {
1523             reg = ots->reg;
1524         } else {
1525             reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1526         }
1527         tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1528     } else if (ts->val_type == TEMP_VAL_CONST) {
1529         if (ots->fixed_reg) {
1530             reg = ots->reg;
1531             tcg_out_movi(s, ots->type, reg, ts->val);
1532         } else {
1533             /* propagate constant */
1534             if (ots->val_type == TEMP_VAL_REG)
1535                 s->reg_to_temp[ots->reg] = -1;
1536             ots->val_type = TEMP_VAL_CONST;
1537             ots->val = ts->val;
1538             return;
1539         }
1540     } else {
1541         tcg_abort();
1542     }
1543     s->reg_to_temp[reg] = args[0];
1544     ots->reg = reg;
1545     ots->val_type = TEMP_VAL_REG;
1546     ots->mem_coherent = 0;
1547 }
1548
1549 static void tcg_reg_alloc_op(TCGContext *s, 
1550                              const TCGOpDef *def, int opc,
1551                              const TCGArg *args,
1552                              unsigned int dead_iargs)
1553 {
1554     TCGRegSet allocated_regs;
1555     int i, k, nb_iargs, nb_oargs, reg;
1556     TCGArg arg;
1557     const TCGArgConstraint *arg_ct;
1558     TCGTemp *ts;
1559     TCGArg new_args[TCG_MAX_OP_ARGS];
1560     int const_args[TCG_MAX_OP_ARGS];
1561
1562     nb_oargs = def->nb_oargs;
1563     nb_iargs = def->nb_iargs;
1564
1565     /* copy constants */
1566     memcpy(new_args + nb_oargs + nb_iargs, 
1567            args + nb_oargs + nb_iargs, 
1568            sizeof(TCGArg) * def->nb_cargs);
1569
1570     /* satisfy input constraints */ 
1571     tcg_regset_set(allocated_regs, s->reserved_regs);
1572     for(k = 0; k < nb_iargs; k++) {
1573         i = def->sorted_args[nb_oargs + k];
1574         arg = args[i];
1575         arg_ct = &def->args_ct[i];
1576         ts = &s->temps[arg];
1577         if (ts->val_type == TEMP_VAL_MEM) {
1578             reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1579             tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1580             ts->val_type = TEMP_VAL_REG;
1581             ts->reg = reg;
1582             ts->mem_coherent = 1;
1583             s->reg_to_temp[reg] = arg;
1584         } else if (ts->val_type == TEMP_VAL_CONST) {
1585             if (tcg_target_const_match(ts->val, arg_ct)) {
1586                 /* constant is OK for instruction */
1587                 const_args[i] = 1;
1588                 new_args[i] = ts->val;
1589                 goto iarg_end;
1590             } else {
1591                 /* need to move to a register */
1592                 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1593                 tcg_out_movi(s, ts->type, reg, ts->val);
1594                 ts->val_type = TEMP_VAL_REG;
1595                 ts->reg = reg;
1596                 ts->mem_coherent = 0;
1597                 s->reg_to_temp[reg] = arg;
1598             }
1599         }
1600         assert(ts->val_type == TEMP_VAL_REG);
1601         if (arg_ct->ct & TCG_CT_IALIAS) {
1602             if (ts->fixed_reg) {
1603                 /* if fixed register, we must allocate a new register
1604                    if the alias is not the same register */
1605                 if (arg != args[arg_ct->alias_index])
1606                     goto allocate_in_reg;
1607             } else {
1608                 /* if the input is aliased to an output and if it is
1609                    not dead after the instruction, we must allocate
1610                    a new register and move it */
1611                 if (!IS_DEAD_IARG(i - nb_oargs)) 
1612                     goto allocate_in_reg;
1613             }
1614         }
1615         reg = ts->reg;
1616         if (tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1617             /* nothing to do : the constraint is satisfied */
1618         } else {
1619         allocate_in_reg:
1620             /* allocate a new register matching the constraint 
1621                and move the temporary register into it */
1622             reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1623             tcg_out_mov(s, reg, ts->reg);
1624         }
1625         new_args[i] = reg;
1626         const_args[i] = 0;
1627         tcg_regset_set_reg(allocated_regs, reg);
1628     iarg_end: ;
1629     }
1630     
1631     if (def->flags & TCG_OPF_BB_END) {
1632         tcg_reg_alloc_bb_end(s, allocated_regs);
1633     } else {
1634         /* mark dead temporaries and free the associated registers */
1635         for(i = 0; i < nb_iargs; i++) {
1636             arg = args[nb_oargs + i];
1637             if (IS_DEAD_IARG(i)) {
1638                 ts = &s->temps[arg];
1639                 if (!ts->fixed_reg) {
1640                     if (ts->val_type == TEMP_VAL_REG)
1641                         s->reg_to_temp[ts->reg] = -1;
1642                     ts->val_type = TEMP_VAL_DEAD;
1643                 }
1644             }
1645         }
1646         
1647         if (def->flags & TCG_OPF_CALL_CLOBBER) {
1648             /* XXX: permit generic clobber register list ? */ 
1649             for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1650                 if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
1651                     tcg_reg_free(s, reg);
1652                 }
1653             }
1654             /* XXX: for load/store we could do that only for the slow path
1655                (i.e. when a memory callback is called) */
1656             
1657             /* store globals and free associated registers (we assume the insn
1658                can modify any global. */
1659             save_globals(s, allocated_regs);
1660         }
1661         
1662         /* satisfy the output constraints */
1663         tcg_regset_set(allocated_regs, s->reserved_regs);
1664         for(k = 0; k < nb_oargs; k++) {
1665             i = def->sorted_args[k];
1666             arg = args[i];
1667             arg_ct = &def->args_ct[i];
1668             ts = &s->temps[arg];
1669             if (arg_ct->ct & TCG_CT_ALIAS) {
1670                 reg = new_args[arg_ct->alias_index];
1671             } else {
1672                 /* if fixed register, we try to use it */
1673                 reg = ts->reg;
1674                 if (ts->fixed_reg &&
1675                     tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1676                     goto oarg_end;
1677                 }
1678                 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1679             }
1680             tcg_regset_set_reg(allocated_regs, reg);
1681             /* if a fixed register is used, then a move will be done afterwards */
1682             if (!ts->fixed_reg) {
1683                 if (ts->val_type == TEMP_VAL_REG)
1684                     s->reg_to_temp[ts->reg] = -1;
1685                 ts->val_type = TEMP_VAL_REG;
1686                 ts->reg = reg;
1687                 /* temp value is modified, so the value kept in memory is
1688                    potentially not the same */
1689                 ts->mem_coherent = 0; 
1690                 s->reg_to_temp[reg] = arg;
1691             }
1692         oarg_end:
1693             new_args[i] = reg;
1694         }
1695     }
1696
1697     /* emit instruction */
1698     tcg_out_op(s, opc, new_args, const_args);
1699     
1700     /* move the outputs in the correct register if needed */
1701     for(i = 0; i < nb_oargs; i++) {
1702         ts = &s->temps[args[i]];
1703         reg = new_args[i];
1704         if (ts->fixed_reg && ts->reg != reg) {
1705             tcg_out_mov(s, ts->reg, reg);
1706         }
1707     }
1708 }
1709
1710 #ifdef TCG_TARGET_STACK_GROWSUP
1711 #define STACK_DIR(x) (-(x))
1712 #else
1713 #define STACK_DIR(x) (x)
1714 #endif
1715
1716 static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
1717                               int opc, const TCGArg *args,
1718                               unsigned int dead_iargs)
1719 {
1720     int nb_iargs, nb_oargs, flags, nb_regs, i, reg, nb_params;
1721     TCGArg arg, func_arg;
1722     TCGTemp *ts;
1723     tcg_target_long stack_offset, call_stack_size, func_addr;
1724     int const_func_arg, allocate_args;
1725     TCGRegSet allocated_regs;
1726     const TCGArgConstraint *arg_ct;
1727
1728     arg = *args++;
1729
1730     nb_oargs = arg >> 16;
1731     nb_iargs = arg & 0xffff;
1732     nb_params = nb_iargs - 1;
1733
1734     flags = args[nb_oargs + nb_iargs];
1735
1736     nb_regs = tcg_target_get_call_iarg_regs_count(flags);
1737     if (nb_regs > nb_params)
1738         nb_regs = nb_params;
1739
1740     /* assign stack slots first */
1741     /* XXX: preallocate call stack */
1742     call_stack_size = (nb_params - nb_regs) * sizeof(tcg_target_long);
1743     call_stack_size = (call_stack_size + TCG_TARGET_STACK_ALIGN - 1) & 
1744         ~(TCG_TARGET_STACK_ALIGN - 1);
1745     allocate_args = (call_stack_size > TCG_STATIC_CALL_ARGS_SIZE);
1746     if (allocate_args) {
1747         tcg_out_addi(s, TCG_REG_CALL_STACK, -STACK_DIR(call_stack_size));
1748     }
1749
1750     stack_offset = TCG_TARGET_CALL_STACK_OFFSET;
1751     for(i = nb_regs; i < nb_params; i++) {
1752         arg = args[nb_oargs + i];
1753 #ifdef TCG_TARGET_STACK_GROWSUP
1754         stack_offset -= sizeof(tcg_target_long);
1755 #endif
1756         if (arg != TCG_CALL_DUMMY_ARG) {
1757             ts = &s->temps[arg];
1758             if (ts->val_type == TEMP_VAL_REG) {
1759                 tcg_out_st(s, ts->type, ts->reg, TCG_REG_CALL_STACK, stack_offset);
1760             } else if (ts->val_type == TEMP_VAL_MEM) {
1761                 reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], 
1762                                     s->reserved_regs);
1763                 /* XXX: not correct if reading values from the stack */
1764                 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1765                 tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
1766             } else if (ts->val_type == TEMP_VAL_CONST) {
1767                 reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], 
1768                                     s->reserved_regs);
1769                 /* XXX: sign extend may be needed on some targets */
1770                 tcg_out_movi(s, ts->type, reg, ts->val);
1771                 tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
1772             } else {
1773                 tcg_abort();
1774             }
1775         }
1776 #ifndef TCG_TARGET_STACK_GROWSUP
1777         stack_offset += sizeof(tcg_target_long);
1778 #endif
1779     }
1780     
1781     /* assign input registers */
1782     tcg_regset_set(allocated_regs, s->reserved_regs);
1783     for(i = 0; i < nb_regs; i++) {
1784         arg = args[nb_oargs + i];
1785         if (arg != TCG_CALL_DUMMY_ARG) {
1786             ts = &s->temps[arg];
1787             reg = tcg_target_call_iarg_regs[i];
1788             tcg_reg_free(s, reg);
1789             if (ts->val_type == TEMP_VAL_REG) {
1790                 if (ts->reg != reg) {
1791                     tcg_out_mov(s, reg, ts->reg);
1792                 }
1793             } else if (ts->val_type == TEMP_VAL_MEM) {
1794                 tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1795             } else if (ts->val_type == TEMP_VAL_CONST) {
1796                 /* XXX: sign extend ? */
1797                 tcg_out_movi(s, ts->type, reg, ts->val);
1798             } else {
1799                 tcg_abort();
1800             }
1801             tcg_regset_set_reg(allocated_regs, reg);
1802         }
1803     }
1804     
1805     /* assign function address */
1806     func_arg = args[nb_oargs + nb_iargs - 1];
1807     arg_ct = &def->args_ct[0];
1808     ts = &s->temps[func_arg];
1809     func_addr = ts->val;
1810     const_func_arg = 0;
1811     if (ts->val_type == TEMP_VAL_MEM) {
1812         reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1813         tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1814         func_arg = reg;
1815         tcg_regset_set_reg(allocated_regs, reg);
1816     } else if (ts->val_type == TEMP_VAL_REG) {
1817         reg = ts->reg;
1818         if (!tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1819             reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1820             tcg_out_mov(s, reg, ts->reg);
1821         }
1822         func_arg = reg;
1823         tcg_regset_set_reg(allocated_regs, reg);
1824     } else if (ts->val_type == TEMP_VAL_CONST) {
1825         if (tcg_target_const_match(func_addr, arg_ct)) {
1826             const_func_arg = 1;
1827             func_arg = func_addr;
1828         } else {
1829             reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1830             tcg_out_movi(s, ts->type, reg, func_addr);
1831             func_arg = reg;
1832             tcg_regset_set_reg(allocated_regs, reg);
1833         }
1834     } else {
1835         tcg_abort();
1836     }
1837         
1838     
1839     /* mark dead temporaries and free the associated registers */
1840     for(i = 0; i < nb_iargs; i++) {
1841         arg = args[nb_oargs + i];
1842         if (IS_DEAD_IARG(i)) {
1843             ts = &s->temps[arg];
1844             if (!ts->fixed_reg) {
1845                 if (ts->val_type == TEMP_VAL_REG)
1846                     s->reg_to_temp[ts->reg] = -1;
1847                 ts->val_type = TEMP_VAL_DEAD;
1848             }
1849         }
1850     }
1851     
1852     /* clobber call registers */
1853     for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1854         if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
1855             tcg_reg_free(s, reg);
1856         }
1857     }
1858     
1859     /* store globals and free associated registers (we assume the call
1860        can modify any global. */
1861     if (!(flags & TCG_CALL_CONST)) {
1862         save_globals(s, allocated_regs);
1863     }
1864
1865     tcg_out_op(s, opc, &func_arg, &const_func_arg);
1866     
1867     if (allocate_args) {
1868         tcg_out_addi(s, TCG_REG_CALL_STACK, STACK_DIR(call_stack_size));
1869     }
1870
1871     /* assign output registers and emit moves if needed */
1872     for(i = 0; i < nb_oargs; i++) {
1873         arg = args[i];
1874         ts = &s->temps[arg];
1875         reg = tcg_target_call_oarg_regs[i];
1876         assert(s->reg_to_temp[reg] == -1);
1877         if (ts->fixed_reg) {
1878             if (ts->reg != reg) {
1879                 tcg_out_mov(s, ts->reg, reg);
1880             }
1881         } else {
1882             if (ts->val_type == TEMP_VAL_REG)
1883                 s->reg_to_temp[ts->reg] = -1;
1884             ts->val_type = TEMP_VAL_REG;
1885             ts->reg = reg;
1886             ts->mem_coherent = 0; 
1887             s->reg_to_temp[reg] = arg;
1888         }
1889     }
1890     
1891     return nb_iargs + nb_oargs + def->nb_cargs + 1;
1892 }
1893
1894 #ifdef CONFIG_PROFILER
1895
1896 static int64_t tcg_table_op_count[NB_OPS];
1897
1898 static void dump_op_count(void)
1899 {
1900     int i;
1901     FILE *f;
1902     f = fopen("/tmp/op.log", "w");
1903     for(i = INDEX_op_end; i < NB_OPS; i++) {
1904         fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name, tcg_table_op_count[i]);
1905     }
1906     fclose(f);
1907 }
1908 #endif
1909
1910
1911 static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
1912                                       long search_pc)
1913 {
1914     int opc, op_index;
1915     const TCGOpDef *def;
1916     unsigned int dead_iargs;
1917     const TCGArg *args;
1918
1919 #ifdef DEBUG_DISAS
1920     if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
1921         qemu_log("OP:\n");
1922         tcg_dump_ops(s, logfile);
1923         qemu_log("\n");
1924     }
1925 #endif
1926
1927 #ifdef CONFIG_PROFILER
1928     s->la_time -= profile_getclock();
1929 #endif
1930     tcg_liveness_analysis(s);
1931 #ifdef CONFIG_PROFILER
1932     s->la_time += profile_getclock();
1933 #endif
1934
1935 #ifdef DEBUG_DISAS
1936     if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_OPT))) {
1937         qemu_log("OP after liveness analysis:\n");
1938         tcg_dump_ops(s, logfile);
1939         qemu_log("\n");
1940     }
1941 #endif
1942
1943     tcg_reg_alloc_start(s);
1944
1945     s->code_buf = gen_code_buf;
1946     s->code_ptr = gen_code_buf;
1947
1948     args = gen_opparam_buf;
1949     op_index = 0;
1950
1951     for(;;) {
1952         opc = gen_opc_buf[op_index];
1953 #ifdef CONFIG_PROFILER
1954         tcg_table_op_count[opc]++;
1955 #endif
1956         def = &tcg_op_defs[opc];
1957 #if 0
1958         printf("%s: %d %d %d\n", def->name,
1959                def->nb_oargs, def->nb_iargs, def->nb_cargs);
1960         //        dump_regs(s);
1961 #endif
1962         switch(opc) {
1963         case INDEX_op_mov_i32:
1964 #if TCG_TARGET_REG_BITS == 64
1965         case INDEX_op_mov_i64:
1966 #endif
1967             dead_iargs = s->op_dead_iargs[op_index];
1968             tcg_reg_alloc_mov(s, def, args, dead_iargs);
1969             break;
1970         case INDEX_op_movi_i32:
1971 #if TCG_TARGET_REG_BITS == 64
1972         case INDEX_op_movi_i64:
1973 #endif
1974             tcg_reg_alloc_movi(s, args);
1975             break;
1976         case INDEX_op_debug_insn_start:
1977             /* debug instruction */
1978             break;
1979         case INDEX_op_nop:
1980         case INDEX_op_nop1:
1981         case INDEX_op_nop2:
1982         case INDEX_op_nop3:
1983             break;
1984         case INDEX_op_nopn:
1985             args += args[0];
1986             goto next;
1987         case INDEX_op_discard:
1988             {
1989                 TCGTemp *ts;
1990                 ts = &s->temps[args[0]];
1991                 /* mark the temporary as dead */
1992                 if (!ts->fixed_reg) {
1993                     if (ts->val_type == TEMP_VAL_REG)
1994                         s->reg_to_temp[ts->reg] = -1;
1995                     ts->val_type = TEMP_VAL_DEAD;
1996                 }
1997             }
1998             break;
1999         case INDEX_op_set_label:
2000             tcg_reg_alloc_bb_end(s, s->reserved_regs);
2001             tcg_out_label(s, args[0], (long)s->code_ptr);
2002             break;
2003         case INDEX_op_call:
2004             dead_iargs = s->op_dead_iargs[op_index];
2005             args += tcg_reg_alloc_call(s, def, opc, args, dead_iargs);
2006             goto next;
2007         case INDEX_op_end:
2008             goto the_end;
2009         default:
2010             /* Note: in order to speed up the code, it would be much
2011                faster to have specialized register allocator functions for
2012                some common argument patterns */
2013             dead_iargs = s->op_dead_iargs[op_index];
2014             tcg_reg_alloc_op(s, def, opc, args, dead_iargs);
2015             break;
2016         }
2017         args += def->nb_args;
2018     next:
2019         if (search_pc >= 0 && search_pc < s->code_ptr - gen_code_buf) {
2020             return op_index;
2021         }
2022         op_index++;
2023 #ifndef NDEBUG
2024         check_regs(s);
2025 #endif
2026     }
2027  the_end:
2028     return -1;
2029 }
2030
2031 int tcg_gen_code(TCGContext *s, uint8_t *gen_code_buf)
2032 {
2033 #ifdef CONFIG_PROFILER
2034     {
2035         int n;
2036         n = (gen_opc_ptr - gen_opc_buf);
2037         s->op_count += n;
2038         if (n > s->op_count_max)
2039             s->op_count_max = n;
2040
2041         s->temp_count += s->nb_temps;
2042         if (s->nb_temps > s->temp_count_max)
2043             s->temp_count_max = s->nb_temps;
2044     }
2045 #endif
2046
2047     tcg_gen_code_common(s, gen_code_buf, -1);
2048
2049     /* flush instruction cache */
2050     flush_icache_range((unsigned long)gen_code_buf, 
2051                        (unsigned long)s->code_ptr);
2052     return s->code_ptr -  gen_code_buf;
2053 }
2054
2055 /* Return the index of the micro operation such as the pc after is <
2056    offset bytes from the start of the TB.  The contents of gen_code_buf must
2057    not be changed, though writing the same values is ok.
2058    Return -1 if not found. */
2059 int tcg_gen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, long offset)
2060 {
2061     return tcg_gen_code_common(s, gen_code_buf, offset);
2062 }
2063
2064 #ifdef CONFIG_PROFILER
2065 void tcg_dump_info(FILE *f,
2066                    int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
2067 {
2068     TCGContext *s = &tcg_ctx;
2069     int64_t tot;
2070
2071     tot = s->interm_time + s->code_time;
2072     cpu_fprintf(f, "JIT cycles          %" PRId64 " (%0.3f s at 2.4 GHz)\n",
2073                 tot, tot / 2.4e9);
2074     cpu_fprintf(f, "translated TBs      %" PRId64 " (aborted=%" PRId64 " %0.1f%%)\n", 
2075                 s->tb_count, 
2076                 s->tb_count1 - s->tb_count,
2077                 s->tb_count1 ? (double)(s->tb_count1 - s->tb_count) / s->tb_count1 * 100.0 : 0);
2078     cpu_fprintf(f, "avg ops/TB          %0.1f max=%d\n", 
2079                 s->tb_count ? (double)s->op_count / s->tb_count : 0, s->op_count_max);
2080     cpu_fprintf(f, "deleted ops/TB      %0.2f\n",
2081                 s->tb_count ? 
2082                 (double)s->del_op_count / s->tb_count : 0);
2083     cpu_fprintf(f, "avg temps/TB        %0.2f max=%d\n",
2084                 s->tb_count ? 
2085                 (double)s->temp_count / s->tb_count : 0,
2086                 s->temp_count_max);
2087     
2088     cpu_fprintf(f, "cycles/op           %0.1f\n", 
2089                 s->op_count ? (double)tot / s->op_count : 0);
2090     cpu_fprintf(f, "cycles/in byte      %0.1f\n", 
2091                 s->code_in_len ? (double)tot / s->code_in_len : 0);
2092     cpu_fprintf(f, "cycles/out byte     %0.1f\n", 
2093                 s->code_out_len ? (double)tot / s->code_out_len : 0);
2094     if (tot == 0)
2095         tot = 1;
2096     cpu_fprintf(f, "  gen_interm time   %0.1f%%\n", 
2097                 (double)s->interm_time / tot * 100.0);
2098     cpu_fprintf(f, "  gen_code time     %0.1f%%\n", 
2099                 (double)s->code_time / tot * 100.0);
2100     cpu_fprintf(f, "liveness/code time  %0.1f%%\n", 
2101                 (double)s->la_time / (s->code_time ? s->code_time : 1) * 100.0);
2102     cpu_fprintf(f, "cpu_restore count   %" PRId64 "\n",
2103                 s->restore_count);
2104     cpu_fprintf(f, "  avg cycles        %0.1f\n",
2105                 s->restore_count ? (double)s->restore_time / s->restore_count : 0);
2106
2107     dump_op_count();
2108 }
2109 #else
2110 void tcg_dump_info(FILE *f,
2111                    int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
2112 {
2113     cpu_fprintf(f, "[TCG profiler not compiled]\n");
2114 }
2115 #endif
This page took 0.144268 seconds and 4 git commands to generate.