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