Add TCG variable opaque type.
[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
38 #include "config.h"
39 #include "osdep.h"
40
41 /* Note: the long term plan is to reduce the dependancies on the QEMU
42    CPU definitions. Currently they are used for qemu_ld/st
43    instructions */
44 #define NO_CPU_IO_DEFS
45 #include "cpu.h"
46 #include "exec-all.h"
47
48 #include "tcg-op.h"
49 #include "elf.h"
50
51
52 static void patch_reloc(uint8_t *code_ptr, int type, 
53                         tcg_target_long value);
54
55 TCGOpDef tcg_op_defs[] = {
56 #define DEF(s, n, copy_size) { #s, 0, 0, n, n, 0, copy_size },
57 #define DEF2(s, iargs, oargs, cargs, flags) { #s, iargs, oargs, cargs, iargs + oargs + cargs, flags, 0 },
58 #include "tcg-opc.h"
59 #undef DEF
60 #undef DEF2
61 };
62
63 TCGRegSet tcg_target_available_regs[2];
64 TCGRegSet tcg_target_call_clobber_regs;
65
66 /* XXX: move that inside the context */
67 uint16_t *gen_opc_ptr;
68 TCGArg *gen_opparam_ptr;
69
70 static inline void tcg_out8(TCGContext *s, uint8_t v)
71 {
72     *s->code_ptr++ = v;
73 }
74
75 static inline void tcg_out16(TCGContext *s, uint16_t v)
76 {
77     *(uint16_t *)s->code_ptr = v;
78     s->code_ptr += 2;
79 }
80
81 static inline void tcg_out32(TCGContext *s, uint32_t v)
82 {
83     *(uint32_t *)s->code_ptr = v;
84     s->code_ptr += 4;
85 }
86
87 /* label relocation processing */
88
89 void tcg_out_reloc(TCGContext *s, uint8_t *code_ptr, int type, 
90                    int label_index, long addend)
91 {
92     TCGLabel *l;
93     TCGRelocation *r;
94
95     l = &s->labels[label_index];
96     if (l->has_value) {
97         patch_reloc(code_ptr, type, l->u.value + addend);
98     } else {
99         /* add a new relocation entry */
100         r = tcg_malloc(sizeof(TCGRelocation));
101         r->type = type;
102         r->ptr = code_ptr;
103         r->addend = addend;
104         r->next = l->u.first_reloc;
105         l->u.first_reloc = r;
106     }
107 }
108
109 static void tcg_out_label(TCGContext *s, int label_index, 
110                           tcg_target_long value)
111 {
112     TCGLabel *l;
113     TCGRelocation *r;
114
115     l = &s->labels[label_index];
116     if (l->has_value)
117         tcg_abort();
118     r = l->u.first_reloc;
119     while (r != NULL) {
120         patch_reloc(r->ptr, r->type, value + r->addend);
121         r = r->next;
122     }
123     l->has_value = 1;
124     l->u.value = value;
125 }
126
127 int gen_new_label(void)
128 {
129     TCGContext *s = &tcg_ctx;
130     int idx;
131     TCGLabel *l;
132
133     if (s->nb_labels >= TCG_MAX_LABELS)
134         tcg_abort();
135     idx = s->nb_labels++;
136     l = &s->labels[idx];
137     l->has_value = 0;
138     l->u.first_reloc = NULL;
139     return idx;
140 }
141
142 #include "tcg-target.c"
143
144 /* XXX: factorize */
145 static void pstrcpy(char *buf, int buf_size, const char *str)
146 {
147     int c;
148     char *q = buf;
149
150     if (buf_size <= 0)
151         return;
152
153     for(;;) {
154         c = *str++;
155         if (c == 0 || q >= buf + buf_size - 1)
156             break;
157         *q++ = c;
158     }
159     *q = '\0';
160 }
161
162 #if TCG_TARGET_REG_BITS == 32
163 /* strcat and truncate. */
164 static char *pstrcat(char *buf, int buf_size, const char *s)
165 {
166     int len;
167     len = strlen(buf);
168     if (len < buf_size)
169         pstrcpy(buf + len, buf_size - len, s);
170     return buf;
171 }
172 #endif
173
174 /* pool based memory allocation */
175 void *tcg_malloc_internal(TCGContext *s, int size)
176 {
177     TCGPool *p;
178     int pool_size;
179     
180     if (size > TCG_POOL_CHUNK_SIZE) {
181         /* big malloc: insert a new pool (XXX: could optimize) */
182         p = qemu_malloc(sizeof(TCGPool) + size);
183         p->size = size;
184         if (s->pool_current)
185             s->pool_current->next = p;
186         else
187             s->pool_first = p;
188         p->next = s->pool_current;
189     } else {
190         p = s->pool_current;
191         if (!p) {
192             p = s->pool_first;
193             if (!p)
194                 goto new_pool;
195         } else {
196             if (!p->next) {
197             new_pool:
198                 pool_size = TCG_POOL_CHUNK_SIZE;
199                 p = qemu_malloc(sizeof(TCGPool) + pool_size);
200                 p->size = pool_size;
201                 p->next = NULL;
202                 if (s->pool_current) 
203                     s->pool_current->next = p;
204                 else
205                     s->pool_first = p;
206             } else {
207                 p = p->next;
208             }
209         }
210     }
211     s->pool_current = p;
212     s->pool_cur = p->data + size;
213     s->pool_end = p->data + p->size;
214     return p->data;
215 }
216
217 void tcg_pool_reset(TCGContext *s)
218 {
219     s->pool_cur = s->pool_end = NULL;
220     s->pool_current = NULL;
221 }
222
223 /* free all the pool */
224 void tcg_pool_free(TCGContext *s)
225 {
226     TCGPool *p, *p1;
227
228     for(p = s->pool_first; p != NULL; p = p1) {
229         p1 = p->next;
230         qemu_free(p);
231     }
232     s->pool_first = NULL;
233     s->pool_cur = s->pool_end = NULL;
234 }
235
236 void tcg_context_init(TCGContext *s)
237 {
238     int op, total_args, n;
239     TCGOpDef *def;
240     TCGArgConstraint *args_ct;
241     int *sorted_args;
242
243     memset(s, 0, sizeof(*s));
244     s->temps = s->static_temps;
245     s->nb_globals = 0;
246     
247     /* Count total number of arguments and allocate the corresponding
248        space */
249     total_args = 0;
250     for(op = 0; op < NB_OPS; op++) {
251         def = &tcg_op_defs[op];
252         n = def->nb_iargs + def->nb_oargs;
253         total_args += n;
254     }
255
256     args_ct = qemu_malloc(sizeof(TCGArgConstraint) * total_args);
257     sorted_args = qemu_malloc(sizeof(int) * total_args);
258
259     for(op = 0; op < NB_OPS; op++) {
260         def = &tcg_op_defs[op];
261         def->args_ct = args_ct;
262         def->sorted_args = sorted_args;
263         n = def->nb_iargs + def->nb_oargs;
264         sorted_args += n;
265         args_ct += n;
266     }
267     
268     tcg_target_init(s);
269 }
270
271 void tcg_set_frame(TCGContext *s, int reg,
272                    tcg_target_long start, tcg_target_long size)
273 {
274     s->frame_start = start;
275     s->frame_end = start + size;
276     s->frame_reg = reg;
277 }
278
279 void tcg_set_macro_func(TCGContext *s, TCGMacroFunc *func)
280 {
281     s->macro_func = func;
282 }
283
284 void tcg_func_start(TCGContext *s)
285 {
286     tcg_pool_reset(s);
287     s->nb_temps = s->nb_globals;
288     s->labels = tcg_malloc(sizeof(TCGLabel) * TCG_MAX_LABELS);
289     s->nb_labels = 0;
290     s->current_frame_offset = s->frame_start;
291
292     gen_opc_ptr = gen_opc_buf;
293     gen_opparam_ptr = gen_opparam_buf;
294 }
295
296 static inline void tcg_temp_alloc(TCGContext *s, int n)
297 {
298     if (n > TCG_MAX_TEMPS)
299         tcg_abort();
300 }
301
302 TCGv tcg_global_reg_new(TCGType type, int reg, const char *name)
303 {
304     TCGContext *s = &tcg_ctx;
305     TCGTemp *ts;
306     int idx;
307
308 #if TCG_TARGET_REG_BITS == 32
309     if (type != TCG_TYPE_I32)
310         tcg_abort();
311 #endif
312     if (tcg_regset_test_reg(s->reserved_regs, reg))
313         tcg_abort();
314     idx = s->nb_globals;
315     tcg_temp_alloc(s, s->nb_globals + 1);
316     ts = &s->temps[s->nb_globals];
317     ts->base_type = type;
318     ts->type = type;
319     ts->fixed_reg = 1;
320     ts->reg = reg;
321     ts->val_type = TEMP_VAL_REG;
322     ts->name = name;
323     s->nb_globals++;
324     tcg_regset_set_reg(s->reserved_regs, reg);
325     return MAKE_TCGV(idx);
326 }
327
328 TCGv tcg_global_mem_new(TCGType type, int reg, tcg_target_long offset,
329                         const char *name)
330 {
331     TCGContext *s = &tcg_ctx;
332     TCGTemp *ts;
333     int idx;
334
335     idx = s->nb_globals;
336 #if TCG_TARGET_REG_BITS == 32
337     if (type == TCG_TYPE_I64) {
338         char buf[64];
339         tcg_temp_alloc(s, s->nb_globals + 1);
340         ts = &s->temps[s->nb_globals];
341         ts->base_type = type;
342         ts->type = TCG_TYPE_I32;
343         ts->fixed_reg = 0;
344         ts->mem_allocated = 1;
345         ts->mem_reg = reg;
346 #ifdef TCG_TARGET_WORDS_BIGENDIAN
347         ts->mem_offset = offset + 4;
348 #else
349         ts->mem_offset = offset;
350 #endif
351         ts->val_type = TEMP_VAL_MEM;
352         pstrcpy(buf, sizeof(buf), name);
353         pstrcat(buf, sizeof(buf), "_0");
354         ts->name = strdup(buf);
355         ts++;
356
357         ts->base_type = type;
358         ts->type = TCG_TYPE_I32;
359         ts->fixed_reg = 0;
360         ts->mem_allocated = 1;
361         ts->mem_reg = reg;
362 #ifdef TCG_TARGET_WORDS_BIGENDIAN
363         ts->mem_offset = offset;
364 #else
365         ts->mem_offset = offset + 4;
366 #endif
367         ts->val_type = TEMP_VAL_MEM;
368         pstrcpy(buf, sizeof(buf), name);
369         pstrcat(buf, sizeof(buf), "_1");
370         ts->name = strdup(buf);
371
372         s->nb_globals += 2;
373     } else
374 #endif
375     {
376         tcg_temp_alloc(s, s->nb_globals + 1);
377         ts = &s->temps[s->nb_globals];
378         ts->base_type = type;
379         ts->type = type;
380         ts->fixed_reg = 0;
381         ts->mem_allocated = 1;
382         ts->mem_reg = reg;
383         ts->mem_offset = offset;
384         ts->val_type = TEMP_VAL_MEM;
385         ts->name = name;
386         s->nb_globals++;
387     }
388     return MAKE_TCGV(idx);
389 }
390
391 TCGv tcg_temp_new(TCGType type)
392 {
393     TCGContext *s = &tcg_ctx;
394     TCGTemp *ts;
395     int idx;
396
397     idx = s->nb_temps;
398 #if TCG_TARGET_REG_BITS == 32
399     if (type == TCG_TYPE_I64) {
400         tcg_temp_alloc(s, s->nb_temps + 1);
401         ts = &s->temps[s->nb_temps];
402         ts->base_type = type;
403         ts->type = TCG_TYPE_I32;
404         ts->val_type = TEMP_VAL_DEAD;
405         ts->mem_allocated = 0;
406         ts->name = NULL;
407         ts++;
408         ts->base_type = TCG_TYPE_I32;
409         ts->type = TCG_TYPE_I32;
410         ts->val_type = TEMP_VAL_DEAD;
411         ts->mem_allocated = 0;
412         ts->name = NULL;
413         s->nb_temps += 2;
414     } else
415 #endif
416     {
417         tcg_temp_alloc(s, s->nb_temps + 1);
418         ts = &s->temps[s->nb_temps];
419         ts->base_type = type;
420         ts->type = type;
421         ts->val_type = TEMP_VAL_DEAD;
422         ts->mem_allocated = 0;
423         ts->name = NULL;
424         s->nb_temps++;
425     }
426     return MAKE_TCGV(idx);
427 }
428
429 TCGv tcg_const_i32(int32_t val)
430 {
431     TCGContext *s = &tcg_ctx;
432     TCGTemp *ts;
433     int idx;
434
435     idx = s->nb_temps;
436     tcg_temp_alloc(s, idx + 1);
437     ts = &s->temps[idx];
438     ts->base_type = ts->type = TCG_TYPE_I32;
439     ts->val_type = TEMP_VAL_CONST;
440     ts->name = NULL;
441     ts->val = val;
442     s->nb_temps++;
443     return MAKE_TCGV(idx);
444 }
445
446 TCGv tcg_const_i64(int64_t val)
447 {
448     TCGContext *s = &tcg_ctx;
449     TCGTemp *ts;
450     int idx;
451
452     idx = s->nb_temps;
453 #if TCG_TARGET_REG_BITS == 32
454     tcg_temp_alloc(s, idx + 2);
455     ts = &s->temps[idx];
456     ts->base_type = TCG_TYPE_I64;
457     ts->type = TCG_TYPE_I32;
458     ts->val_type = TEMP_VAL_CONST;
459     ts->name = NULL;
460     ts->val = val;
461     ts++;
462     ts->base_type = TCG_TYPE_I32;
463     ts->type = TCG_TYPE_I32;
464     ts->val_type = TEMP_VAL_CONST;
465     ts->name = NULL;
466     ts->val = val >> 32;
467     s->nb_temps += 2;
468 #else
469     tcg_temp_alloc(s, idx + 1);
470     ts = &s->temps[idx];
471     ts->base_type = ts->type = TCG_TYPE_I64;
472     ts->val_type = TEMP_VAL_CONST;
473     ts->name = NULL;
474     ts->val = val;
475     s->nb_temps++;
476 #endif    
477     return MAKE_TCGV(idx);
478 }
479
480 void tcg_register_helper(void *func, const char *name)
481 {
482     TCGContext *s = &tcg_ctx;
483     int n;
484     if ((s->nb_helpers + 1) > s->allocated_helpers) {
485         n = s->allocated_helpers;
486         if (n == 0) {
487             n = 4;
488         } else {
489             n *= 2;
490         }
491         s->helpers = realloc(s->helpers, n * sizeof(TCGHelperInfo));
492         s->allocated_helpers = n;
493     }
494     s->helpers[s->nb_helpers].func = func;
495     s->helpers[s->nb_helpers].name = name;
496     s->nb_helpers++;
497 }
498
499 const char *tcg_helper_get_name(TCGContext *s, void *func)
500 {
501     int i;
502
503     for(i = 0; i < s->nb_helpers; i++) {
504         if (s->helpers[i].func == func)
505             return s->helpers[i].name;
506     }
507     return NULL;
508 }
509
510 static inline TCGType tcg_get_base_type(TCGContext *s, TCGv arg)
511 {
512     return s->temps[GET_TCGV(arg)].base_type;
513 }
514
515 static void tcg_gen_call_internal(TCGContext *s, TCGv func, 
516                                   unsigned int flags,
517                                   unsigned int nb_rets, const TCGv *rets,
518                                   unsigned int nb_params, const TCGv *params)
519 {
520     int i;
521     *gen_opc_ptr++ = INDEX_op_call;
522     *gen_opparam_ptr++ = (nb_rets << 16) | (nb_params + 1);
523     for(i = 0; i < nb_rets; i++) {
524         *gen_opparam_ptr++ = GET_TCGV(rets[i]);
525     }
526     for(i = 0; i < nb_params; i++) {
527         *gen_opparam_ptr++ = GET_TCGV(params[i]);
528     }
529     *gen_opparam_ptr++ = GET_TCGV(func);
530
531     *gen_opparam_ptr++ = flags;
532     /* total parameters, needed to go backward in the instruction stream */
533     *gen_opparam_ptr++ = 1 + nb_rets + nb_params + 3;
534 }
535
536
537 #if TCG_TARGET_REG_BITS < 64
538 /* Note: we convert the 64 bit args to 32 bit */
539 void tcg_gen_call(TCGContext *s, TCGv func, unsigned int flags,
540                   unsigned int nb_rets, const TCGv *rets,
541                   unsigned int nb_params, const TCGv *args1)
542 {
543     TCGv ret, *args2, rets_2[2], arg;
544     int j, i, call_type;
545
546     if (nb_rets == 1) {
547         ret = rets[0];
548         if (tcg_get_base_type(s, ret) == TCG_TYPE_I64) {
549             nb_rets = 2;
550             rets_2[0] = ret;
551             rets_2[1] = TCGV_HIGH(ret);
552             rets = rets_2;
553         }
554     }
555     args2 = alloca((nb_params * 2) * sizeof(TCGv));
556     j = 0;
557     call_type = (flags & TCG_CALL_TYPE_MASK);
558     for(i = 0; i < nb_params; i++) {
559         arg = args1[i];
560         if (tcg_get_base_type(s, arg) == TCG_TYPE_I64) {
561 #ifdef TCG_TARGET_I386
562             /* REGPARM case: if the third parameter is 64 bit, it is
563                allocated on the stack */
564             if (j == 2 && call_type == TCG_CALL_TYPE_REGPARM) {
565                 call_type = TCG_CALL_TYPE_REGPARM_2;
566                 flags = (flags & ~TCG_CALL_TYPE_MASK) | call_type;
567             }
568             args2[j++] = arg;
569             args2[j++] = TCGV_HIGH(arg);
570 #else
571 #ifdef TCG_TARGET_WORDS_BIGENDIAN
572             args2[j++] = TCGV_HOGH(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         return;
602     if (c >= 32) {
603         c -= 32;
604         if (right) {
605             if (arith) {
606                 tcg_gen_sari_i32(ret, TCGV_HIGH(arg1), c);
607                 tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 31);
608             } else {
609                 tcg_gen_shri_i32(ret, TCGV_HIGH(arg1), c);
610                 tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
611             }
612         } else {
613             tcg_gen_shli_i32(TCGV_HIGH(ret), arg1, c);
614             tcg_gen_movi_i32(ret, 0);
615         }
616     } else {
617         TCGv t0, t1;
618
619         t0 = tcg_temp_new(TCG_TYPE_I32);
620         t1 = tcg_temp_new(TCG_TYPE_I32);
621         if (right) {
622             tcg_gen_shli_i32(t0, TCGV_HIGH(arg1), 32 - c);
623             if (arith)
624                 tcg_gen_sari_i32(t1, TCGV_HIGH(arg1), c);
625             else 
626                 tcg_gen_shri_i32(t1, TCGV_HIGH(arg1), c);
627             tcg_gen_shri_i32(ret, arg1, c); 
628             tcg_gen_or_i32(ret, ret, t0);
629             tcg_gen_mov_i32(TCGV_HIGH(ret), t1);
630         } else {
631             tcg_gen_shri_i32(t0, arg1, 32 - c);
632             /* Note: ret can be the same as arg1, so we use t1 */
633             tcg_gen_shli_i32(t1, arg1, c); 
634             tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c);
635             tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t0);
636             tcg_gen_mov_i32(ret, t1);
637         }
638     }
639 }
640 #endif
641
642 void tcg_reg_alloc_start(TCGContext *s)
643 {
644     int i;
645     TCGTemp *ts;
646     for(i = 0; i < s->nb_globals; i++) {
647         ts = &s->temps[i];
648         if (ts->fixed_reg) {
649             ts->val_type = TEMP_VAL_REG;
650         } else {
651             ts->val_type = TEMP_VAL_MEM;
652         }
653     }
654     for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
655         s->reg_to_temp[i] = -1;
656     }
657 }
658
659 static char *tcg_get_arg_str_idx(TCGContext *s, char *buf, int buf_size,
660                                  int idx)
661 {
662     TCGTemp *ts;
663
664     ts = &s->temps[idx];
665     if (idx < s->nb_globals) {
666         pstrcpy(buf, buf_size, ts->name);
667     } else {
668         if (ts->val_type == TEMP_VAL_CONST) {
669             snprintf(buf, buf_size, "$0x%" TCG_PRIlx , ts->val);
670         } else {
671             snprintf(buf, buf_size, "tmp%d", idx - s->nb_globals);
672         }
673     }
674     return buf;
675 }
676
677 char *tcg_get_arg_str(TCGContext *s, char *buf, int buf_size, TCGv arg)
678 {
679     return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV(arg));
680 }
681
682 void tcg_dump_ops(TCGContext *s, FILE *outfile)
683 {
684     const uint16_t *opc_ptr;
685     const TCGArg *args;
686     TCGArg arg;
687     int c, i, k, nb_oargs, nb_iargs, nb_cargs;
688     const TCGOpDef *def;
689     char buf[128];
690
691     opc_ptr = gen_opc_buf;
692     args = gen_opparam_buf;
693     while (opc_ptr < gen_opc_ptr) {
694         c = *opc_ptr++;
695         def = &tcg_op_defs[c];
696         fprintf(outfile, " %s ", def->name);
697         if (c == INDEX_op_call) {
698             TCGArg arg;
699             /* variable number of arguments */
700             arg = *args++;
701             nb_oargs = arg >> 16;
702             nb_iargs = arg & 0xffff;
703             nb_cargs = def->nb_cargs;
704         } else if (c == INDEX_op_nopn) {
705             /* variable number of arguments */
706             nb_cargs = *args;
707             nb_oargs = 0;
708             nb_iargs = 0;
709         } else {
710             nb_oargs = def->nb_oargs;
711             nb_iargs = def->nb_iargs;
712             nb_cargs = def->nb_cargs;
713         }
714
715         k = 0;
716         for(i = 0; i < nb_oargs; i++) {
717             if (k != 0)
718                 fprintf(outfile, ",");
719             fprintf(outfile, "%s",
720                     tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
721         }
722         for(i = 0; i < nb_iargs; i++) {
723             if (k != 0)
724                 fprintf(outfile, ",");
725             /* XXX: dump helper name for call */
726             fprintf(outfile, "%s",
727                     tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
728         }
729         for(i = 0; i < nb_cargs; i++) {
730             if (k != 0)
731                 fprintf(outfile, ",");
732             arg = args[k++];
733             fprintf(outfile, "$0x%" TCG_PRIlx, arg);
734         }
735         fprintf(outfile, "\n");
736         args += nb_iargs + nb_oargs + nb_cargs;
737     }
738 }
739
740 /* we give more priority to constraints with less registers */
741 static int get_constraint_priority(const TCGOpDef *def, int k)
742 {
743     const TCGArgConstraint *arg_ct;
744
745     int i, n;
746     arg_ct = &def->args_ct[k];
747     if (arg_ct->ct & TCG_CT_ALIAS) {
748         /* an alias is equivalent to a single register */
749         n = 1;
750     } else {
751         if (!(arg_ct->ct & TCG_CT_REG))
752             return 0;
753         n = 0;
754         for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
755             if (tcg_regset_test_reg(arg_ct->u.regs, i))
756                 n++;
757         }
758     }
759     return TCG_TARGET_NB_REGS - n + 1;
760 }
761
762 /* sort from highest priority to lowest */
763 static void sort_constraints(TCGOpDef *def, int start, int n)
764 {
765     int i, j, p1, p2, tmp;
766
767     for(i = 0; i < n; i++)
768         def->sorted_args[start + i] = start + i;
769     if (n <= 1)
770         return;
771     for(i = 0; i < n - 1; i++) {
772         for(j = i + 1; j < n; j++) {
773             p1 = get_constraint_priority(def, def->sorted_args[start + i]);
774             p2 = get_constraint_priority(def, def->sorted_args[start + j]);
775             if (p1 < p2) {
776                 tmp = def->sorted_args[start + i];
777                 def->sorted_args[start + i] = def->sorted_args[start + j];
778                 def->sorted_args[start + j] = tmp;
779             }
780         }
781     }
782 }
783
784 void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs)
785 {
786     int op;
787     TCGOpDef *def;
788     const char *ct_str;
789     int i, nb_args;
790
791     for(;;) {
792         if (tdefs->op < 0)
793             break;
794         op = tdefs->op;
795         assert(op >= 0 && op < NB_OPS);
796         def = &tcg_op_defs[op];
797         nb_args = def->nb_iargs + def->nb_oargs;
798         for(i = 0; i < nb_args; i++) {
799             ct_str = tdefs->args_ct_str[i];
800             tcg_regset_clear(def->args_ct[i].u.regs);
801             def->args_ct[i].ct = 0;
802             if (ct_str[0] >= '0' && ct_str[0] <= '9') {
803                 int oarg;
804                 oarg = ct_str[0] - '0';
805                 assert(oarg < def->nb_oargs);
806                 assert(def->args_ct[oarg].ct & TCG_CT_REG);
807                 /* TCG_CT_ALIAS is for the output arguments. The input
808                    argument is tagged with TCG_CT_IALIAS for
809                    informative purposes. */
810                 def->args_ct[i] = def->args_ct[oarg];
811                 def->args_ct[oarg].ct = i | TCG_CT_ALIAS;
812                 def->args_ct[i].ct |= TCG_CT_IALIAS;
813             } else {
814                 for(;;) {
815                     if (*ct_str == '\0')
816                         break;
817                     switch(*ct_str) {
818                     case 'i':
819                         def->args_ct[i].ct |= TCG_CT_CONST;
820                         ct_str++;
821                         break;
822                     default:
823                         if (target_parse_constraint(&def->args_ct[i], &ct_str) < 0) {
824                             fprintf(stderr, "Invalid constraint '%s' for arg %d of operation '%s'\n",
825                                     ct_str, i, def->name);
826                             exit(1);
827                         }
828                     }
829                 }
830             }
831         }
832
833         /* sort the constraints (XXX: this is just an heuristic) */
834         sort_constraints(def, 0, def->nb_oargs);
835         sort_constraints(def, def->nb_oargs, def->nb_iargs);
836
837 #if 0
838         {
839             int i;
840
841             printf("%s: sorted=", def->name);
842             for(i = 0; i < def->nb_oargs + def->nb_iargs; i++)
843                 printf(" %d", def->sorted_args[i]);
844             printf("\n");
845         }
846 #endif
847         tdefs++;
848     }
849
850 }
851
852 #ifdef USE_LIVENESS_ANALYSIS
853
854 /* set a nop for an operation using 'nb_args' */
855 static inline void tcg_set_nop(TCGContext *s, uint16_t *opc_ptr, 
856                                TCGArg *args, int nb_args)
857 {
858     if (nb_args == 0) {
859         *opc_ptr = INDEX_op_nop;
860     } else {
861         *opc_ptr = INDEX_op_nopn;
862         args[0] = nb_args;
863         args[nb_args - 1] = nb_args;
864     }
865 }
866
867 /* liveness analysis: end of basic block: globals are live, temps are dead */
868 static inline void tcg_la_bb_end(TCGContext *s, uint8_t *dead_temps)
869 {
870     memset(dead_temps, 0, s->nb_globals);
871     memset(dead_temps + s->nb_globals, 1, s->nb_temps - s->nb_globals);
872 }
873
874 /* Liveness analysis : update the opc_dead_iargs array to tell if a
875    given input arguments is dead. Instructions updating dead
876    temporaries are removed. */
877 void tcg_liveness_analysis(TCGContext *s)
878 {
879     int i, op_index, op, nb_args, nb_iargs, nb_oargs, arg, nb_ops;
880     TCGArg *args;
881     const TCGOpDef *def;
882     uint8_t *dead_temps;
883     unsigned int dead_iargs;
884     
885     gen_opc_ptr++; /* skip end */
886
887     nb_ops = gen_opc_ptr - gen_opc_buf;
888
889     /* XXX: make it really dynamic */
890     s->op_dead_iargs = tcg_malloc(OPC_BUF_SIZE * sizeof(uint16_t));
891     
892     dead_temps = tcg_malloc(s->nb_temps);
893     memset(dead_temps, 1, s->nb_temps);
894
895     args = gen_opparam_ptr;
896     op_index = nb_ops - 1;
897     while (op_index >= 0) {
898         op = gen_opc_buf[op_index];
899         def = &tcg_op_defs[op];
900         switch(op) {
901         case INDEX_op_call:
902             nb_args = args[-1];
903             args -= nb_args;
904             nb_iargs = args[0] & 0xffff;
905             nb_oargs = args[0] >> 16;
906             args++;
907
908             /* output args are dead */
909             for(i = 0; i < nb_oargs; i++) {
910                 arg = args[i];
911                 dead_temps[arg] = 1;
912             }
913             
914             /* globals are live (they may be used by the call) */
915             memset(dead_temps, 0, s->nb_globals);
916
917             /* input args are live */
918             dead_iargs = 0;
919             for(i = 0; i < nb_iargs; i++) {
920                 arg = args[i + nb_oargs];
921                 if (dead_temps[arg]) {
922                     dead_iargs |= (1 << i);
923                 }
924                 dead_temps[arg] = 0;
925             }
926             s->op_dead_iargs[op_index] = dead_iargs;
927             args--;
928             break;
929         case INDEX_op_set_label:
930             args--;
931             /* mark end of basic block */
932             tcg_la_bb_end(s, dead_temps);
933             break;
934         case INDEX_op_nopn:
935             nb_args = args[-1];
936             args -= nb_args;
937             break;
938         case INDEX_op_macro_2:
939             {
940                 int dead_args[2], macro_id;
941                 int saved_op_index, saved_arg_index;
942                 int macro_op_index, macro_arg_index;
943                 int macro_end_op_index, macro_end_arg_index;
944                 int last_nb_temps;
945                 
946                 nb_args = 3;
947                 args -= nb_args;
948                 dead_args[0] = dead_temps[args[0]];
949                 dead_args[1] = dead_temps[args[1]];
950                 macro_id = args[2];
951
952                 /* call the macro function which generate code
953                    depending on the live outputs */
954                 saved_op_index = op_index;
955                 saved_arg_index = args - gen_opparam_buf;
956
957                 /* add a macro start instruction */
958                 *gen_opc_ptr++ = INDEX_op_macro_start;
959                 *gen_opparam_ptr++ = saved_op_index;
960                 *gen_opparam_ptr++ = saved_arg_index;
961
962                 macro_op_index = gen_opc_ptr - gen_opc_buf;
963                 macro_arg_index = gen_opparam_ptr -  gen_opparam_buf;
964
965                 last_nb_temps = s->nb_temps;
966
967                 s->macro_func(s, macro_id, dead_args);
968
969                 /* realloc temp info (XXX: make it faster) */
970                 if (s->nb_temps > last_nb_temps) {
971                     uint8_t *new_dead_temps;
972
973                     new_dead_temps = tcg_malloc(s->nb_temps);
974                     memcpy(new_dead_temps, dead_temps, last_nb_temps);
975                     memset(new_dead_temps + last_nb_temps, 1, 
976                            s->nb_temps - last_nb_temps);
977                     dead_temps = new_dead_temps;
978                 }
979
980                 macro_end_op_index = gen_opc_ptr - gen_opc_buf;
981                 macro_end_arg_index = gen_opparam_ptr - gen_opparam_buf;
982
983                 /* end of macro: add a goto to the next instruction */
984                 *gen_opc_ptr++ = INDEX_op_macro_end;
985                 *gen_opparam_ptr++ = op_index + 1;
986                 *gen_opparam_ptr++ = saved_arg_index + nb_args;
987
988                 /* modify the macro operation to be a macro_goto */
989                 gen_opc_buf[op_index] = INDEX_op_macro_goto;
990                 args[0] = macro_op_index;
991                 args[1] = macro_arg_index;
992                 args[2] = 0; /* dummy third arg to match the 
993                                 macro parameters */
994
995                 /* set the next instruction to the end of the macro */
996                 op_index = macro_end_op_index;
997                 args = macro_end_arg_index + gen_opparam_buf;
998             }
999             break;
1000         case INDEX_op_macro_start:
1001             args -= 2;
1002             op_index = args[0];
1003             args = gen_opparam_buf + args[1];
1004             break;
1005         case INDEX_op_macro_goto:
1006         case INDEX_op_macro_end:
1007             tcg_abort(); /* should never happen in liveness analysis */
1008         case INDEX_op_end:
1009             break;
1010             /* XXX: optimize by hardcoding common cases (e.g. triadic ops) */
1011         default:
1012             if (op > INDEX_op_end) {
1013                 args -= def->nb_args;
1014                 nb_iargs = def->nb_iargs;
1015                 nb_oargs = def->nb_oargs;
1016
1017                 /* Test if the operation can be removed because all
1018                    its outputs are dead. We may add a flag to
1019                    explicitely tell if the op has side
1020                    effects. Currently we assume that if nb_oargs == 0
1021                    or OPF_BB_END is set, the operation has side
1022                    effects and cannot be removed */
1023                 if (nb_oargs != 0 && !(def->flags & TCG_OPF_BB_END)) {
1024                     for(i = 0; i < nb_oargs; i++) {
1025                         arg = args[i];
1026                         if (!dead_temps[arg])
1027                             goto do_not_remove;
1028                     }
1029                     tcg_set_nop(s, gen_opc_buf + op_index, args, def->nb_args);
1030 #ifdef CONFIG_PROFILER
1031                     {
1032                         extern int64_t dyngen_tcg_del_op_count;
1033                         dyngen_tcg_del_op_count++;
1034                     }
1035 #endif
1036                 } else {
1037                 do_not_remove:
1038
1039                     /* output args are dead */
1040                     for(i = 0; i < nb_oargs; i++) {
1041                         arg = args[i];
1042                         dead_temps[arg] = 1;
1043                     }
1044                     
1045                     /* if end of basic block, update */
1046                     if (def->flags & TCG_OPF_BB_END) {
1047                         tcg_la_bb_end(s, dead_temps);
1048                     }
1049                     
1050                     /* input args are live */
1051                     dead_iargs = 0;
1052                     for(i = 0; i < nb_iargs; i++) {
1053                         arg = args[i + nb_oargs];
1054                         if (dead_temps[arg]) {
1055                             dead_iargs |= (1 << i);
1056                         }
1057                         dead_temps[arg] = 0;
1058                     }
1059                     s->op_dead_iargs[op_index] = dead_iargs;
1060                 }
1061             } else {
1062                 /* legacy dyngen operations */
1063                 args -= def->nb_args;
1064                 /* mark end of basic block */
1065                 tcg_la_bb_end(s, dead_temps);
1066             }
1067             break;
1068         }
1069         op_index--;
1070     }
1071
1072     if (args != gen_opparam_buf)
1073         tcg_abort();
1074 }
1075 #else
1076 /* dummy liveness analysis */
1077 void tcg_liveness_analysis(TCGContext *s)
1078 {
1079     int nb_ops;
1080     nb_ops = gen_opc_ptr - gen_opc_buf;
1081
1082     s->op_dead_iargs = tcg_malloc(nb_ops * sizeof(uint16_t));
1083     memset(s->op_dead_iargs, 0, nb_ops * sizeof(uint16_t));
1084 }
1085 #endif
1086
1087 #ifndef NDEBUG
1088 static void dump_regs(TCGContext *s)
1089 {
1090     TCGTemp *ts;
1091     int i;
1092     char buf[64];
1093
1094     for(i = 0; i < s->nb_temps; i++) {
1095         ts = &s->temps[i];
1096         printf("  %10s: ", tcg_get_arg_str_idx(s, buf, sizeof(buf), i));
1097         switch(ts->val_type) {
1098         case TEMP_VAL_REG:
1099             printf("%s", tcg_target_reg_names[ts->reg]);
1100             break;
1101         case TEMP_VAL_MEM:
1102             printf("%d(%s)", (int)ts->mem_offset, tcg_target_reg_names[ts->mem_reg]);
1103             break;
1104         case TEMP_VAL_CONST:
1105             printf("$0x%" TCG_PRIlx, ts->val);
1106             break;
1107         case TEMP_VAL_DEAD:
1108             printf("D");
1109             break;
1110         default:
1111             printf("???");
1112             break;
1113         }
1114         printf("\n");
1115     }
1116
1117     for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
1118         if (s->reg_to_temp[i] >= 0) {
1119             printf("%s: %s\n", 
1120                    tcg_target_reg_names[i], 
1121                    tcg_get_arg_str_idx(s, buf, sizeof(buf), s->reg_to_temp[i]));
1122         }
1123     }
1124 }
1125
1126 static void check_regs(TCGContext *s)
1127 {
1128     int reg, k;
1129     TCGTemp *ts;
1130     char buf[64];
1131
1132     for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1133         k = s->reg_to_temp[reg];
1134         if (k >= 0) {
1135             ts = &s->temps[k];
1136             if (ts->val_type != TEMP_VAL_REG ||
1137                 ts->reg != reg) {
1138                 printf("Inconsistency for register %s:\n", 
1139                        tcg_target_reg_names[reg]);
1140                 printf("reg state:\n");
1141                 dump_regs(s);
1142                 tcg_abort();
1143             }
1144         }
1145     }
1146     for(k = 0; k < s->nb_temps; k++) {
1147         ts = &s->temps[k];
1148         if (ts->val_type == TEMP_VAL_REG &&
1149             !ts->fixed_reg &&
1150             s->reg_to_temp[ts->reg] != k) {
1151                 printf("Inconsistency for temp %s:\n", 
1152                        tcg_get_arg_str_idx(s, buf, sizeof(buf), k));
1153                 printf("reg state:\n");
1154                 dump_regs(s);
1155                 tcg_abort();
1156         }
1157     }
1158 }
1159 #endif
1160
1161 static void temp_allocate_frame(TCGContext *s, int temp)
1162 {
1163     TCGTemp *ts;
1164     ts = &s->temps[temp];
1165     s->current_frame_offset = (s->current_frame_offset + sizeof(tcg_target_long) - 1) & ~(sizeof(tcg_target_long) - 1);
1166     if (s->current_frame_offset + sizeof(tcg_target_long) > s->frame_end)
1167         abort();
1168     ts->mem_offset = s->current_frame_offset;
1169     ts->mem_reg = s->frame_reg;
1170     ts->mem_allocated = 1;
1171     s->current_frame_offset += sizeof(tcg_target_long);
1172 }
1173
1174 /* free register 'reg' by spilling the corresponding temporary if necessary */
1175 static void tcg_reg_free(TCGContext *s, int reg)
1176 {
1177     TCGTemp *ts;
1178     int temp;
1179
1180     temp = s->reg_to_temp[reg];
1181     if (temp != -1) {
1182         ts = &s->temps[temp];
1183         assert(ts->val_type == TEMP_VAL_REG);
1184         if (!ts->mem_coherent) {
1185             if (!ts->mem_allocated) 
1186                 temp_allocate_frame(s, temp);
1187             tcg_out_st(s, reg, ts->mem_reg, ts->mem_offset);
1188         }
1189         ts->val_type = TEMP_VAL_MEM;
1190         s->reg_to_temp[reg] = -1;
1191     }
1192 }
1193
1194 /* Allocate a register belonging to reg1 & ~reg2 */
1195 static int tcg_reg_alloc(TCGContext *s, TCGRegSet reg1, TCGRegSet reg2)
1196 {
1197     int i, reg;
1198     TCGRegSet reg_ct;
1199
1200     tcg_regset_andnot(reg_ct, reg1, reg2);
1201
1202     /* first try free registers */
1203     for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
1204         reg = tcg_target_reg_alloc_order[i];
1205         if (tcg_regset_test_reg(reg_ct, reg) && s->reg_to_temp[reg] == -1)
1206             return reg;
1207     }
1208
1209     /* XXX: do better spill choice */
1210     for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
1211         reg = tcg_target_reg_alloc_order[i];
1212         if (tcg_regset_test_reg(reg_ct, reg)) {
1213             tcg_reg_free(s, reg);
1214             return reg;
1215         }
1216     }
1217
1218     tcg_abort();
1219 }
1220
1221 /* at the end of a basic block, we assume all temporaries are dead and
1222    all globals are stored at their canonical location */
1223 /* XXX: optimize by handling constants in another array ? */
1224 void tcg_reg_alloc_bb_end(TCGContext *s)
1225 {
1226     TCGTemp *ts;
1227     int i;
1228
1229     for(i = 0; i < s->nb_globals; i++) {
1230         ts = &s->temps[i];
1231         if (!ts->fixed_reg) {
1232             if (ts->val_type == TEMP_VAL_REG) {
1233                 tcg_reg_free(s, ts->reg);
1234             }
1235         }
1236     }
1237
1238     for(i = s->nb_globals; i < s->nb_temps; i++) {
1239         ts = &s->temps[i];
1240         if (ts->val_type != TEMP_VAL_CONST) {
1241             if (ts->val_type == TEMP_VAL_REG) {
1242                 s->reg_to_temp[ts->reg] = -1;
1243             }
1244             ts->val_type = TEMP_VAL_DEAD;
1245         }
1246     }
1247 }
1248
1249 #define IS_DEAD_IARG(n) ((dead_iargs >> (n)) & 1)
1250
1251 static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
1252                               const TCGArg *args,
1253                               unsigned int dead_iargs)
1254 {
1255     TCGTemp *ts, *ots;
1256     int reg;
1257     const TCGArgConstraint *arg_ct;
1258
1259     ots = &s->temps[args[0]];
1260     ts = &s->temps[args[1]];
1261     arg_ct = &def->args_ct[0];
1262
1263     if (ts->val_type == TEMP_VAL_REG) {
1264         if (IS_DEAD_IARG(0) && !ts->fixed_reg && !ots->fixed_reg) {
1265             /* the mov can be suppressed */
1266             if (ots->val_type == TEMP_VAL_REG)
1267                 s->reg_to_temp[ots->reg] = -1;
1268             reg = ts->reg;
1269             s->reg_to_temp[reg] = -1;
1270             ts->val_type = TEMP_VAL_DEAD;
1271         } else {
1272             if (ots->val_type == TEMP_VAL_REG) {
1273                 reg = ots->reg;
1274             } else {
1275                 reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1276             }
1277             if (ts->reg != reg) {
1278                 tcg_out_mov(s, reg, ts->reg);
1279             }
1280         }
1281     } else if (ts->val_type == TEMP_VAL_MEM) {
1282         if (ots->val_type == TEMP_VAL_REG) {
1283             reg = ots->reg;
1284         } else {
1285             reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1286         }
1287         tcg_out_ld(s, reg, ts->mem_reg, ts->mem_offset);
1288     } else if (ts->val_type == TEMP_VAL_CONST) {
1289         if (ots->val_type == TEMP_VAL_REG) {
1290             reg = ots->reg;
1291         } else {
1292             reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1293         }
1294         tcg_out_movi(s, ots->type, reg, ts->val);
1295     } else {
1296         tcg_abort();
1297     }
1298     s->reg_to_temp[reg] = args[0];
1299     ots->reg = reg;
1300     ots->val_type = TEMP_VAL_REG;
1301     ots->mem_coherent = 0;
1302 }
1303
1304 static void tcg_reg_alloc_op(TCGContext *s, 
1305                              const TCGOpDef *def, int opc,
1306                              const TCGArg *args,
1307                              unsigned int dead_iargs)
1308 {
1309     TCGRegSet allocated_regs;
1310     int i, k, nb_iargs, nb_oargs, reg;
1311     TCGArg arg;
1312     const TCGArgConstraint *arg_ct;
1313     TCGTemp *ts;
1314     TCGArg new_args[TCG_MAX_OP_ARGS];
1315     int const_args[TCG_MAX_OP_ARGS];
1316
1317     nb_oargs = def->nb_oargs;
1318     nb_iargs = def->nb_iargs;
1319
1320     /* copy constants */
1321     memcpy(new_args + nb_oargs + nb_iargs, 
1322            args + nb_oargs + nb_iargs, 
1323            sizeof(TCGArg) * def->nb_cargs);
1324
1325     /* satisfy input constraints */ 
1326     tcg_regset_set(allocated_regs, s->reserved_regs);
1327     for(k = 0; k < nb_iargs; k++) {
1328         i = def->sorted_args[nb_oargs + k];
1329         arg = args[i];
1330         arg_ct = &def->args_ct[i];
1331         ts = &s->temps[arg];
1332         if (ts->val_type == TEMP_VAL_MEM) {
1333             reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1334             tcg_out_ld(s, reg, ts->mem_reg, ts->mem_offset);
1335             ts->val_type = TEMP_VAL_REG;
1336             ts->reg = reg;
1337             ts->mem_coherent = 1;
1338             s->reg_to_temp[reg] = arg;
1339         } else if (ts->val_type == TEMP_VAL_CONST) {
1340             if (tcg_target_const_match(ts->val, arg_ct)) {
1341                 /* constant is OK for instruction */
1342                 const_args[i] = 1;
1343                 new_args[i] = ts->val;
1344                 goto iarg_end;
1345             } else {
1346                 /* need to move to a register*/
1347                 reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1348                 tcg_out_movi(s, ts->type, reg, ts->val);
1349                 goto iarg_end1;
1350             }
1351         }
1352         assert(ts->val_type == TEMP_VAL_REG);
1353         if ((arg_ct->ct & TCG_CT_IALIAS) &&
1354             !IS_DEAD_IARG(i - nb_oargs)) {
1355             /* if the input is aliased to an output and if it is
1356                not dead after the instruction, we must allocate
1357                a new register and move it */
1358             goto allocate_in_reg;
1359         }
1360         reg = ts->reg;
1361         if (tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1362             /* nothing to do : the constraint is satisfied */
1363         } else {
1364         allocate_in_reg:
1365             /* allocate a new register matching the constraint 
1366                and move the temporary register into it */
1367             reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1368             tcg_out_mov(s, reg, ts->reg);
1369         }
1370     iarg_end1:
1371         new_args[i] = reg;
1372         const_args[i] = 0;
1373         tcg_regset_set_reg(allocated_regs, reg);
1374     iarg_end: ;
1375     }
1376     
1377     /* mark dead temporaries and free the associated registers */
1378     for(i = 0; i < nb_iargs; i++) {
1379         arg = args[nb_oargs + i];
1380         if (IS_DEAD_IARG(i)) {
1381             ts = &s->temps[arg];
1382             if (ts->val_type != TEMP_VAL_CONST && !ts->fixed_reg) {
1383                 if (ts->val_type == TEMP_VAL_REG)
1384                     s->reg_to_temp[ts->reg] = -1;
1385                 ts->val_type = TEMP_VAL_DEAD;
1386             }
1387         }
1388     }
1389
1390     /* XXX: permit generic clobber register list ? */ 
1391     if (def->flags & TCG_OPF_CALL_CLOBBER) {
1392         for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1393             if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
1394                 tcg_reg_free(s, reg);
1395             }
1396         }
1397     }
1398
1399     /* satisfy the output constraints */
1400     tcg_regset_set(allocated_regs, s->reserved_regs);
1401     for(k = 0; k < nb_oargs; k++) {
1402         i = def->sorted_args[k];
1403         arg = args[i];
1404         arg_ct = &def->args_ct[i];
1405         ts = &s->temps[arg];
1406         if (arg_ct->ct & TCG_CT_ALIAS) {
1407             reg = new_args[arg_ct->ct & ~TCG_CT_ALIAS];
1408         } else {
1409             /* if fixed register, we try to use it */
1410             reg = ts->reg;
1411             if (ts->fixed_reg &&
1412                 tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1413                 goto oarg_end;
1414             }
1415             reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1416         }
1417         tcg_regset_set_reg(allocated_regs, reg);
1418         /* if a fixed register is used, then a move will be done afterwards */
1419         if (!ts->fixed_reg) {
1420             if (ts->val_type == TEMP_VAL_REG)
1421                 s->reg_to_temp[ts->reg] = -1;
1422             ts->val_type = TEMP_VAL_REG;
1423             ts->reg = reg;
1424             /* temp value is modified, so the value kept in memory is
1425                potentially not the same */
1426             ts->mem_coherent = 0; 
1427             s->reg_to_temp[reg] = arg;
1428         }
1429     oarg_end:
1430         new_args[i] = reg;
1431     }
1432
1433     if (def->flags & TCG_OPF_BB_END)
1434         tcg_reg_alloc_bb_end(s);
1435
1436     /* emit instruction */
1437     tcg_out_op(s, opc, new_args, const_args);
1438     
1439     /* move the outputs in the correct register if needed */
1440     for(i = 0; i < nb_oargs; i++) {
1441         ts = &s->temps[args[i]];
1442         reg = new_args[i];
1443         if (ts->fixed_reg && ts->reg != reg) {
1444             tcg_out_mov(s, ts->reg, reg);
1445         }
1446     }
1447 }
1448
1449 static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
1450                               int opc, const TCGArg *args,
1451                               unsigned int dead_iargs)
1452 {
1453     int nb_iargs, nb_oargs, flags, nb_regs, i, reg, nb_params;
1454     TCGArg arg, func_arg;
1455     TCGTemp *ts;
1456     tcg_target_long stack_offset, call_stack_size;
1457     int const_func_arg;
1458     TCGRegSet allocated_regs;
1459     const TCGArgConstraint *arg_ct;
1460
1461     arg = *args++;
1462
1463     nb_oargs = arg >> 16;
1464     nb_iargs = arg & 0xffff;
1465     nb_params = nb_iargs - 1;
1466
1467     flags = args[nb_oargs + nb_iargs];
1468
1469     nb_regs = tcg_target_get_call_iarg_regs_count(flags);
1470     if (nb_regs > nb_params)
1471         nb_regs = nb_params;
1472
1473     /* assign stack slots first */
1474     /* XXX: preallocate call stack */
1475     call_stack_size = (nb_params - nb_regs) * sizeof(tcg_target_long);
1476     call_stack_size = (call_stack_size + TCG_TARGET_STACK_ALIGN - 1) & 
1477         ~(TCG_TARGET_STACK_ALIGN - 1);
1478     tcg_out_addi(s, TCG_REG_CALL_STACK, -call_stack_size);
1479
1480     stack_offset = 0;
1481     for(i = nb_regs; i < nb_params; i++) {
1482         arg = args[nb_oargs + i];
1483         ts = &s->temps[arg];
1484         if (ts->val_type == TEMP_VAL_REG) {
1485             tcg_out_st(s, ts->reg, TCG_REG_CALL_STACK, stack_offset);
1486         } else if (ts->val_type == TEMP_VAL_MEM) {
1487             reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], 
1488                                 s->reserved_regs);
1489             /* XXX: not correct if reading values from the stack */
1490             tcg_out_ld(s, reg, ts->mem_reg, ts->mem_offset);
1491             tcg_out_st(s, reg, TCG_REG_CALL_STACK, stack_offset);
1492         } else if (ts->val_type == TEMP_VAL_CONST) {
1493             reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], 
1494                                 s->reserved_regs);
1495             /* XXX: sign extend may be needed on some targets */
1496             tcg_out_movi(s, ts->type, reg, ts->val);
1497             tcg_out_st(s, reg, TCG_REG_CALL_STACK, stack_offset);
1498         } else {
1499             tcg_abort();
1500         }
1501         stack_offset += sizeof(tcg_target_long);
1502     }
1503     
1504     /* assign input registers */
1505     tcg_regset_set(allocated_regs, s->reserved_regs);
1506     for(i = 0; i < nb_regs; i++) {
1507         arg = args[nb_oargs + i];
1508         ts = &s->temps[arg];
1509         reg = tcg_target_call_iarg_regs[i];
1510         tcg_reg_free(s, reg);
1511         if (ts->val_type == TEMP_VAL_REG) {
1512             if (ts->reg != reg) {
1513                 tcg_out_mov(s, reg, ts->reg);
1514             }
1515         } else if (ts->val_type == TEMP_VAL_MEM) {
1516             tcg_out_ld(s, reg, ts->mem_reg, ts->mem_offset);
1517         } else if (ts->val_type == TEMP_VAL_CONST) {
1518             /* XXX: sign extend ? */
1519             tcg_out_movi(s, ts->type, reg, ts->val);
1520         } else {
1521             tcg_abort();
1522         }
1523         tcg_regset_set_reg(allocated_regs, reg);
1524     }
1525     
1526     /* assign function address */
1527     func_arg = args[nb_oargs + nb_iargs - 1];
1528     arg_ct = &def->args_ct[0];
1529     ts = &s->temps[func_arg];
1530     const_func_arg = 0;
1531     if (ts->val_type == TEMP_VAL_MEM) {
1532         reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1533         tcg_out_ld(s, reg, ts->mem_reg, ts->mem_offset);
1534         func_arg = reg;
1535     } else if (ts->val_type == TEMP_VAL_REG) {
1536         reg = ts->reg;
1537         if (!tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1538             reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1539             tcg_out_mov(s, reg, ts->reg);
1540         }
1541         func_arg = reg;
1542     } else if (ts->val_type == TEMP_VAL_CONST) {
1543         if (tcg_target_const_match(ts->val, arg_ct)) {
1544             const_func_arg = 1;
1545             func_arg = ts->val;
1546         } else {
1547             reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1548             tcg_out_movi(s, ts->type, reg, ts->val);
1549             func_arg = reg;
1550         }
1551     } else {
1552         tcg_abort();
1553     }
1554     
1555     /* mark dead temporaries and free the associated registers */
1556     for(i = 0; i < nb_params; i++) {
1557         arg = args[nb_oargs + i];
1558         if (IS_DEAD_IARG(i)) {
1559             ts = &s->temps[arg];
1560             if (ts->val_type != TEMP_VAL_CONST && !ts->fixed_reg) {
1561                 if (ts->val_type == TEMP_VAL_REG)
1562                     s->reg_to_temp[ts->reg] = -1;
1563                 ts->val_type = TEMP_VAL_DEAD;
1564             }
1565         }
1566     }
1567     
1568     /* clobber call registers */
1569     for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1570         if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
1571             tcg_reg_free(s, reg);
1572         }
1573     }
1574     
1575     /* store globals and free associated registers (we assume the call
1576        can modify any global. */
1577     for(i = 0; i < s->nb_globals; i++) {
1578         ts = &s->temps[i];
1579         if (!ts->fixed_reg) {
1580             if (ts->val_type == TEMP_VAL_REG) {
1581                 tcg_reg_free(s, ts->reg);
1582             }
1583         }
1584     }
1585
1586     tcg_out_op(s, opc, &func_arg, &const_func_arg);
1587     
1588     tcg_out_addi(s, TCG_REG_CALL_STACK, call_stack_size);
1589
1590     /* assign output registers and emit moves if needed */
1591     for(i = 0; i < nb_oargs; i++) {
1592         arg = args[i];
1593         ts = &s->temps[arg];
1594         reg = tcg_target_call_oarg_regs[i];
1595         tcg_reg_free(s, reg);
1596         if (ts->fixed_reg) {
1597             if (ts->reg != reg) {
1598                 tcg_out_mov(s, ts->reg, reg);
1599             }
1600         } else {
1601             if (ts->val_type == TEMP_VAL_REG)
1602                 s->reg_to_temp[ts->reg] = -1;
1603             ts->val_type = TEMP_VAL_REG;
1604             ts->reg = reg;
1605             ts->mem_coherent = 0; 
1606             s->reg_to_temp[reg] = arg;
1607         }
1608     }
1609     
1610     return nb_iargs + nb_oargs + def->nb_cargs + 1;
1611 }
1612
1613 #ifdef CONFIG_PROFILER
1614
1615 static int64_t dyngen_table_op_count[NB_OPS];
1616
1617 void dump_op_count(void)
1618 {
1619     int i;
1620     FILE *f;
1621     f = fopen("/tmp/op1.log", "w");
1622     for(i = 0; i < INDEX_op_end; i++) {
1623         fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name, dyngen_table_op_count[i]);
1624     }
1625     fclose(f);
1626     f = fopen("/tmp/op2.log", "w");
1627     for(i = INDEX_op_end; i < NB_OPS; i++) {
1628         fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name, dyngen_table_op_count[i]);
1629     }
1630     fclose(f);
1631 }
1632 #endif
1633
1634
1635 static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
1636                                       int do_search_pc,
1637                                       const uint8_t *searched_pc)
1638 {
1639     int opc, op_index, macro_op_index;
1640     const TCGOpDef *def;
1641     unsigned int dead_iargs;
1642     const TCGArg *args;
1643
1644 #ifdef DEBUG_DISAS
1645     if (unlikely(loglevel & CPU_LOG_TB_OP)) {
1646         fprintf(logfile, "OP:\n");
1647         tcg_dump_ops(s, logfile);
1648         fprintf(logfile, "\n");
1649     }
1650 #endif
1651
1652     tcg_liveness_analysis(s);
1653
1654 #ifdef DEBUG_DISAS
1655     if (unlikely(loglevel & CPU_LOG_TB_OP_OPT)) {
1656         fprintf(logfile, "OP after la:\n");
1657         tcg_dump_ops(s, logfile);
1658         fprintf(logfile, "\n");
1659     }
1660 #endif
1661
1662     tcg_reg_alloc_start(s);
1663
1664     s->code_buf = gen_code_buf;
1665     s->code_ptr = gen_code_buf;
1666
1667     macro_op_index = -1;
1668     args = gen_opparam_buf;
1669     op_index = 0;
1670     for(;;) {
1671         opc = gen_opc_buf[op_index];
1672 #ifdef CONFIG_PROFILER
1673         dyngen_table_op_count[opc]++;
1674 #endif
1675         def = &tcg_op_defs[opc];
1676 #if 0
1677         printf("%s: %d %d %d\n", def->name,
1678                def->nb_oargs, def->nb_iargs, def->nb_cargs);
1679         //        dump_regs(s);
1680 #endif
1681         switch(opc) {
1682         case INDEX_op_mov_i32:
1683 #if TCG_TARGET_REG_BITS == 64
1684         case INDEX_op_mov_i64:
1685 #endif
1686             dead_iargs = s->op_dead_iargs[op_index];
1687             tcg_reg_alloc_mov(s, def, args, dead_iargs);
1688             break;
1689         case INDEX_op_nop:
1690         case INDEX_op_nop1:
1691         case INDEX_op_nop2:
1692         case INDEX_op_nop3:
1693             break;
1694         case INDEX_op_nopn:
1695             args += args[0];
1696             goto next;
1697         case INDEX_op_macro_goto:
1698             macro_op_index = op_index; /* only used for exceptions */
1699             op_index = args[0] - 1;
1700             args = gen_opparam_buf + args[1];
1701             goto next;
1702         case INDEX_op_macro_end:
1703             macro_op_index = -1; /* only used for exceptions */
1704             op_index = args[0] - 1;
1705             args = gen_opparam_buf + args[1];
1706             goto next;
1707         case INDEX_op_macro_start:
1708             /* must never happen here */
1709             tcg_abort();
1710         case INDEX_op_set_label:
1711             tcg_reg_alloc_bb_end(s);
1712             tcg_out_label(s, args[0], (long)s->code_ptr);
1713             break;
1714         case INDEX_op_call:
1715             dead_iargs = s->op_dead_iargs[op_index];
1716             args += tcg_reg_alloc_call(s, def, opc, args, dead_iargs);
1717             goto next;
1718         case INDEX_op_end:
1719             goto the_end;
1720         case 0 ... INDEX_op_end - 1:
1721             /* legacy dyngen ops */
1722 #ifdef CONFIG_PROFILER
1723             {
1724                 extern int64_t dyngen_old_op_count;
1725                 dyngen_old_op_count++;
1726             }
1727 #endif
1728             tcg_reg_alloc_bb_end(s);
1729             if (do_search_pc) {
1730                 s->code_ptr += def->copy_size;
1731                 args += def->nb_args;
1732             } else {
1733                 args = dyngen_op(s, opc, args);
1734             }
1735             goto next;
1736         default:
1737             /* Note: in order to speed up the code, it would be much
1738                faster to have specialized register allocator functions for
1739                some common argument patterns */
1740             dead_iargs = s->op_dead_iargs[op_index];
1741             tcg_reg_alloc_op(s, def, opc, args, dead_iargs);
1742             break;
1743         }
1744         args += def->nb_args;
1745     next: ;
1746         if (do_search_pc) {
1747             if (searched_pc < s->code_ptr) {
1748                 if (macro_op_index >= 0)
1749                     return macro_op_index;
1750                 else
1751                     return op_index;
1752             }
1753         }
1754         op_index++;
1755 #ifndef NDEBUG
1756         check_regs(s);
1757 #endif
1758     }
1759  the_end:
1760     return -1;
1761 }
1762
1763 int dyngen_code(TCGContext *s, uint8_t *gen_code_buf)
1764 {
1765 #ifdef CONFIG_PROFILER
1766     {
1767         extern int64_t dyngen_op_count;
1768         extern int dyngen_op_count_max;
1769         int n;
1770         n = (gen_opc_ptr - gen_opc_buf);
1771         dyngen_op_count += n;
1772         if (n > dyngen_op_count_max)
1773             dyngen_op_count_max = n;
1774     }
1775 #endif
1776
1777     tcg_gen_code_common(s, gen_code_buf, 0, NULL);
1778
1779     /* flush instruction cache */
1780     flush_icache_range((unsigned long)gen_code_buf, 
1781                        (unsigned long)s->code_ptr);
1782     return s->code_ptr -  gen_code_buf;
1783 }
1784
1785 /* return the index of the micro operation such as the pc after is <
1786    search_pc. Note: gen_code_buf is accessed during the operation, but
1787    its content should not be modified. Return -1 if not found. */
1788 int dyngen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf,
1789                           const uint8_t *searched_pc)
1790 {
1791     return tcg_gen_code_common(s, gen_code_buf, 1, searched_pc);
1792 }