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