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