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