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