Statistics
| Branch: | Revision:

root / tcg / tcg.c @ 641d5fbe

History | View | Annotate | Download (65.3 kB)

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
/* free all the pool */
200
void tcg_pool_free(TCGContext *s)
201
{
202
    TCGPool *p, *p1;
203

    
204
    for(p = s->pool_first; p != NULL; p = p1) {
205
        p1 = p->next;
206
        qemu_free(p);
207
    }
208
    s->pool_first = NULL;
209
    s->pool_cur = s->pool_end = NULL;
210
}
211

    
212
void tcg_context_init(TCGContext *s)
213
{
214
    int op, total_args, n;
215
    TCGOpDef *def;
216
    TCGArgConstraint *args_ct;
217
    int *sorted_args;
218

    
219
    memset(s, 0, sizeof(*s));
220
    s->temps = s->static_temps;
221
    s->nb_globals = 0;
222
    
223
    /* Count total number of arguments and allocate the corresponding
224
       space */
225
    total_args = 0;
226
    for(op = 0; op < NB_OPS; op++) {
227
        def = &tcg_op_defs[op];
228
        n = def->nb_iargs + def->nb_oargs;
229
        total_args += n;
230
    }
231

    
232
    args_ct = qemu_malloc(sizeof(TCGArgConstraint) * total_args);
233
    sorted_args = qemu_malloc(sizeof(int) * total_args);
234

    
235
    for(op = 0; op < NB_OPS; op++) {
236
        def = &tcg_op_defs[op];
237
        def->args_ct = args_ct;
238
        def->sorted_args = sorted_args;
239
        n = def->nb_iargs + def->nb_oargs;
240
        sorted_args += n;
241
        args_ct += n;
242
    }
243
    
244
    tcg_target_init(s);
245

    
246
    /* init global prologue and epilogue */
247
    s->code_buf = code_gen_prologue;
248
    s->code_ptr = s->code_buf;
249
    tcg_target_qemu_prologue(s);
250
    flush_icache_range((unsigned long)s->code_buf, 
251
                       (unsigned long)s->code_ptr);
252
}
253

    
254
void tcg_set_frame(TCGContext *s, int reg,
255
                   tcg_target_long start, tcg_target_long size)
256
{
257
    s->frame_start = start;
258
    s->frame_end = start + size;
259
    s->frame_reg = reg;
260
}
261

    
262
void tcg_set_macro_func(TCGContext *s, TCGMacroFunc *func)
263
{
264
    s->macro_func = func;
265
}
266

    
267
void tcg_func_start(TCGContext *s)
268
{
269
    int i;
270
    tcg_pool_reset(s);
271
    s->nb_temps = s->nb_globals;
272
    for(i = 0; i < (TCG_TYPE_COUNT * 2); i++)
273
        s->first_free_temp[i] = -1;
274
    s->labels = tcg_malloc(sizeof(TCGLabel) * TCG_MAX_LABELS);
275
    s->nb_labels = 0;
276
    s->current_frame_offset = s->frame_start;
277

    
278
    gen_opc_ptr = gen_opc_buf;
279
    gen_opparam_ptr = gen_opparam_buf;
280
}
281

    
282
static inline void tcg_temp_alloc(TCGContext *s, int n)
283
{
284
    if (n > TCG_MAX_TEMPS)
285
        tcg_abort();
286
}
287

    
288
TCGv tcg_global_reg_new(TCGType type, int reg, const char *name)
289
{
290
    TCGContext *s = &tcg_ctx;
291
    TCGTemp *ts;
292
    int idx;
293

    
294
#if TCG_TARGET_REG_BITS == 32
295
    if (type != TCG_TYPE_I32)
296
        tcg_abort();
297
#endif
298
    if (tcg_regset_test_reg(s->reserved_regs, reg))
299
        tcg_abort();
300
    idx = s->nb_globals;
301
    tcg_temp_alloc(s, s->nb_globals + 1);
302
    ts = &s->temps[s->nb_globals];
303
    ts->base_type = type;
304
    ts->type = type;
305
    ts->fixed_reg = 1;
306
    ts->reg = reg;
307
    ts->name = name;
308
    s->nb_globals++;
309
    tcg_regset_set_reg(s->reserved_regs, reg);
310
    return MAKE_TCGV(idx);
311
}
312

    
313
#if TCG_TARGET_REG_BITS == 32
314
/* temporary hack to avoid register shortage for tcg_qemu_st64() */
315
TCGv tcg_global_reg2_new_hack(TCGType type, int reg1, int reg2, 
316
                              const char *name)
317
{
318
    TCGContext *s = &tcg_ctx;
319
    TCGTemp *ts;
320
    int idx;
321
    char buf[64];
322

    
323
    if (type != TCG_TYPE_I64)
324
        tcg_abort();
325
    idx = s->nb_globals;
326
    tcg_temp_alloc(s, s->nb_globals + 2);
327
    ts = &s->temps[s->nb_globals];
328
    ts->base_type = type;
329
    ts->type = TCG_TYPE_I32;
330
    ts->fixed_reg = 1;
331
    ts->reg = reg1;
332
    pstrcpy(buf, sizeof(buf), name);
333
    pstrcat(buf, sizeof(buf), "_0");
334
    ts->name = strdup(buf);
335

    
336
    ts++;
337
    ts->base_type = type;
338
    ts->type = TCG_TYPE_I32;
339
    ts->fixed_reg = 1;
340
    ts->reg = reg2;
341
    pstrcpy(buf, sizeof(buf), name);
342
    pstrcat(buf, sizeof(buf), "_1");
343
    ts->name = strdup(buf);
344

    
345
    s->nb_globals += 2;
346
    return MAKE_TCGV(idx);
347
}
348
#endif
349

    
350
TCGv tcg_global_mem_new(TCGType type, int reg, tcg_target_long offset,
351
                        const char *name)
352
{
353
    TCGContext *s = &tcg_ctx;
354
    TCGTemp *ts;
355
    int idx;
356

    
357
    idx = s->nb_globals;
358
#if TCG_TARGET_REG_BITS == 32
359
    if (type == TCG_TYPE_I64) {
360
        char buf[64];
361
        tcg_temp_alloc(s, s->nb_globals + 1);
362
        ts = &s->temps[s->nb_globals];
363
        ts->base_type = type;
364
        ts->type = TCG_TYPE_I32;
365
        ts->fixed_reg = 0;
366
        ts->mem_allocated = 1;
367
        ts->mem_reg = reg;
368
#ifdef TCG_TARGET_WORDS_BIGENDIAN
369
        ts->mem_offset = offset + 4;
370
#else
371
        ts->mem_offset = offset;
372
#endif
373
        pstrcpy(buf, sizeof(buf), name);
374
        pstrcat(buf, sizeof(buf), "_0");
375
        ts->name = strdup(buf);
376
        ts++;
377

    
378
        ts->base_type = type;
379
        ts->type = TCG_TYPE_I32;
380
        ts->fixed_reg = 0;
381
        ts->mem_allocated = 1;
382
        ts->mem_reg = reg;
383
#ifdef TCG_TARGET_WORDS_BIGENDIAN
384
        ts->mem_offset = offset;
385
#else
386
        ts->mem_offset = offset + 4;
387
#endif
388
        pstrcpy(buf, sizeof(buf), name);
389
        pstrcat(buf, sizeof(buf), "_1");
390
        ts->name = strdup(buf);
391

    
392
        s->nb_globals += 2;
393
    } else
394
#endif
395
    {
396
        tcg_temp_alloc(s, s->nb_globals + 1);
397
        ts = &s->temps[s->nb_globals];
398
        ts->base_type = type;
399
        ts->type = type;
400
        ts->fixed_reg = 0;
401
        ts->mem_allocated = 1;
402
        ts->mem_reg = reg;
403
        ts->mem_offset = offset;
404
        ts->name = name;
405
        s->nb_globals++;
406
    }
407
    return MAKE_TCGV(idx);
408
}
409

    
410
TCGv tcg_temp_new_internal(TCGType type, int temp_local)
411
{
412
    TCGContext *s = &tcg_ctx;
413
    TCGTemp *ts;
414
    int idx, k;
415

    
416
    k = type;
417
    if (temp_local)
418
        k += TCG_TYPE_COUNT;
419
    idx = s->first_free_temp[k];
420
    if (idx != -1) {
421
        /* There is already an available temp with the
422
           right type */
423
        ts = &s->temps[idx];
424
        s->first_free_temp[k] = ts->next_free_temp;
425
        ts->temp_allocated = 1;
426
        assert(ts->temp_local == temp_local);
427
    } else {
428
        idx = s->nb_temps;
429
#if TCG_TARGET_REG_BITS == 32
430
        if (type == TCG_TYPE_I64) {
431
            tcg_temp_alloc(s, s->nb_temps + 1);
432
            ts = &s->temps[s->nb_temps];
433
            ts->base_type = type;
434
            ts->type = TCG_TYPE_I32;
435
            ts->temp_allocated = 1;
436
            ts->temp_local = temp_local;
437
            ts->name = NULL;
438
            ts++;
439
            ts->base_type = TCG_TYPE_I32;
440
            ts->type = TCG_TYPE_I32;
441
            ts->temp_allocated = 1;
442
            ts->temp_local = temp_local;
443
            ts->name = NULL;
444
            s->nb_temps += 2;
445
        } else
446
#endif
447
        {
448
            tcg_temp_alloc(s, s->nb_temps + 1);
449
            ts = &s->temps[s->nb_temps];
450
            ts->base_type = type;
451
            ts->type = type;
452
            ts->temp_allocated = 1;
453
            ts->temp_local = temp_local;
454
            ts->name = NULL;
455
            s->nb_temps++;
456
        }
457
    }
458
    return MAKE_TCGV(idx);
459
}
460

    
461
void tcg_temp_free(TCGv arg)
462
{
463
    TCGContext *s = &tcg_ctx;
464
    TCGTemp *ts;
465
    int idx = GET_TCGV(arg);
466
    int k;
467

    
468
    assert(idx >= s->nb_globals && idx < s->nb_temps);
469
    ts = &s->temps[idx];
470
    assert(ts->temp_allocated != 0);
471
    ts->temp_allocated = 0;
472
    k = ts->base_type;
473
    if (ts->temp_local)
474
        k += TCG_TYPE_COUNT;
475
    ts->next_free_temp = s->first_free_temp[k];
476
    s->first_free_temp[k] = idx;
477
}
478

    
479

    
480
TCGv tcg_const_i32(int32_t val)
481
{
482
    TCGv t0;
483
    t0 = tcg_temp_new(TCG_TYPE_I32);
484
    tcg_gen_movi_i32(t0, val);
485
    return t0;
486
}
487

    
488
TCGv tcg_const_i64(int64_t val)
489
{
490
    TCGv t0;
491
    t0 = tcg_temp_new(TCG_TYPE_I64);
492
    tcg_gen_movi_i64(t0, val);
493
    return t0;
494
}
495

    
496
void tcg_register_helper(void *func, const char *name)
497
{
498
    TCGContext *s = &tcg_ctx;
499
    int n;
500
    if ((s->nb_helpers + 1) > s->allocated_helpers) {
501
        n = s->allocated_helpers;
502
        if (n == 0) {
503
            n = 4;
504
        } else {
505
            n *= 2;
506
        }
507
        s->helpers = realloc(s->helpers, n * sizeof(TCGHelperInfo));
508
        s->allocated_helpers = n;
509
    }
510
    s->helpers[s->nb_helpers].func = (tcg_target_ulong)func;
511
    s->helpers[s->nb_helpers].name = name;
512
    s->nb_helpers++;
513
}
514

    
515
static inline TCGType tcg_get_base_type(TCGContext *s, TCGv arg)
516
{
517
    return s->temps[GET_TCGV(arg)].base_type;
518
}
519

    
520
static void tcg_gen_call_internal(TCGContext *s, TCGv func, 
521
                                  unsigned int flags,
522
                                  unsigned int nb_rets, const TCGv *rets,
523
                                  unsigned int nb_params, const TCGv *params)
524
{
525
    int i;
526
    *gen_opc_ptr++ = INDEX_op_call;
527
    *gen_opparam_ptr++ = (nb_rets << 16) | (nb_params + 1);
528
    for(i = 0; i < nb_rets; i++) {
529
        *gen_opparam_ptr++ = GET_TCGV(rets[i]);
530
    }
531
    for(i = 0; i < nb_params; i++) {
532
        *gen_opparam_ptr++ = GET_TCGV(params[i]);
533
    }
534
    *gen_opparam_ptr++ = GET_TCGV(func);
535

    
536
    *gen_opparam_ptr++ = flags;
537
    /* total parameters, needed to go backward in the instruction stream */
538
    *gen_opparam_ptr++ = 1 + nb_rets + nb_params + 3;
539
}
540

    
541

    
542
#if TCG_TARGET_REG_BITS < 64
543
/* Note: we convert the 64 bit args to 32 bit and do some alignment
544
   and endian swap. Maybe it would be better to do the alignment
545
   and endian swap in tcg_reg_alloc_call(). */
546
void tcg_gen_call(TCGContext *s, TCGv func, unsigned int flags,
547
                  unsigned int nb_rets, const TCGv *rets,
548
                  unsigned int nb_params, const TCGv *args1)
549
{
550
    TCGv ret, *args2, rets_2[2], arg;
551
    int j, i, call_type;
552

    
553
    if (nb_rets == 1) {
554
        ret = rets[0];
555
        if (tcg_get_base_type(s, ret) == TCG_TYPE_I64) {
556
            nb_rets = 2;
557
#ifdef TCG_TARGET_WORDS_BIGENDIAN
558
            rets_2[0] = TCGV_HIGH(ret);
559
            rets_2[1] = ret;
560
#else
561
            rets_2[0] = ret;
562
            rets_2[1] = TCGV_HIGH(ret);
563
#endif
564
            rets = rets_2;
565
        }
566
    }
567
    args2 = alloca((nb_params * 3) * sizeof(TCGv));
568
    j = 0;
569
    call_type = (flags & TCG_CALL_TYPE_MASK);
570
    for(i = 0; i < nb_params; i++) {
571
        arg = args1[i];
572
        if (tcg_get_base_type(s, arg) == TCG_TYPE_I64) {
573
#ifdef TCG_TARGET_I386
574
            /* REGPARM case: if the third parameter is 64 bit, it is
575
               allocated on the stack */
576
            if (j == 2 && call_type == TCG_CALL_TYPE_REGPARM) {
577
                call_type = TCG_CALL_TYPE_REGPARM_2;
578
                flags = (flags & ~TCG_CALL_TYPE_MASK) | call_type;
579
            }
580
            args2[j++] = arg;
581
            args2[j++] = TCGV_HIGH(arg);
582
#else
583
#ifdef TCG_TARGET_CALL_ALIGN_ARGS
584
            /* some targets want aligned 64 bit args */
585
            if (j & 1) {
586
                args2[j++] = TCG_CALL_DUMMY_ARG;
587
            }
588
#endif
589
#ifdef TCG_TARGET_WORDS_BIGENDIAN
590
            args2[j++] = TCGV_HIGH(arg);
591
            args2[j++] = arg;
592
#else
593
            args2[j++] = arg;
594
            args2[j++] = TCGV_HIGH(arg);
595
#endif
596
#endif
597
        } else {
598
            args2[j++] = arg;
599
        }
600
    }
601
    tcg_gen_call_internal(s, func, flags, 
602
                          nb_rets, rets, j, args2);
603
}
604
#else
605
void tcg_gen_call(TCGContext *s, TCGv func, unsigned int flags,
606
                  unsigned int nb_rets, const TCGv *rets,
607
                  unsigned int nb_params, const TCGv *args1)
608
{
609
    tcg_gen_call_internal(s, func, flags, 
610
                          nb_rets, rets, nb_params, args1);
611
}
612
#endif
613

    
614
#if TCG_TARGET_REG_BITS == 32
615
void tcg_gen_shifti_i64(TCGv ret, TCGv arg1, 
616
                        int c, int right, int arith)
617
{
618
    if (c == 0) {
619
        tcg_gen_mov_i32(ret, arg1);
620
        tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
621
    } else if (c >= 32) {
622
        c -= 32;
623
        if (right) {
624
            if (arith) {
625
                tcg_gen_sari_i32(ret, TCGV_HIGH(arg1), c);
626
                tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 31);
627
            } else {
628
                tcg_gen_shri_i32(ret, TCGV_HIGH(arg1), c);
629
                tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
630
            }
631
        } else {
632
            tcg_gen_shli_i32(TCGV_HIGH(ret), arg1, c);
633
            tcg_gen_movi_i32(ret, 0);
634
        }
635
    } else {
636
        TCGv t0, t1;
637

    
638
        t0 = tcg_temp_new(TCG_TYPE_I32);
639
        t1 = tcg_temp_new(TCG_TYPE_I32);
640
        if (right) {
641
            tcg_gen_shli_i32(t0, TCGV_HIGH(arg1), 32 - c);
642
            if (arith)
643
                tcg_gen_sari_i32(t1, TCGV_HIGH(arg1), c);
644
            else 
645
                tcg_gen_shri_i32(t1, TCGV_HIGH(arg1), c);
646
            tcg_gen_shri_i32(ret, arg1, c); 
647
            tcg_gen_or_i32(ret, ret, t0);
648
            tcg_gen_mov_i32(TCGV_HIGH(ret), t1);
649
        } else {
650
            tcg_gen_shri_i32(t0, arg1, 32 - c);
651
            /* Note: ret can be the same as arg1, so we use t1 */
652
            tcg_gen_shli_i32(t1, arg1, c); 
653
            tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c);
654
            tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t0);
655
            tcg_gen_mov_i32(ret, t1);
656
        }
657
        tcg_temp_free(t0);
658
        tcg_temp_free(t1);
659
    }
660
}
661
#endif
662

    
663
void tcg_reg_alloc_start(TCGContext *s)
664
{
665
    int i;
666
    TCGTemp *ts;
667
    for(i = 0; i < s->nb_globals; i++) {
668
        ts = &s->temps[i];
669
        if (ts->fixed_reg) {
670
            ts->val_type = TEMP_VAL_REG;
671
        } else {
672
            ts->val_type = TEMP_VAL_MEM;
673
        }
674
    }
675
    for(i = s->nb_globals; i < s->nb_temps; i++) {
676
        ts = &s->temps[i];
677
        ts->val_type = TEMP_VAL_DEAD;
678
        ts->mem_allocated = 0;
679
        ts->fixed_reg = 0;
680
    }
681
    for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
682
        s->reg_to_temp[i] = -1;
683
    }
684
}
685

    
686
static char *tcg_get_arg_str_idx(TCGContext *s, char *buf, int buf_size,
687
                                 int idx)
688
{
689
    TCGTemp *ts;
690

    
691
    ts = &s->temps[idx];
692
    if (idx < s->nb_globals) {
693
        pstrcpy(buf, buf_size, ts->name);
694
    } else {
695
        if (ts->temp_local) 
696
            snprintf(buf, buf_size, "loc%d", idx - s->nb_globals);
697
        else
698
            snprintf(buf, buf_size, "tmp%d", idx - s->nb_globals);
699
    }
700
    return buf;
701
}
702

    
703
char *tcg_get_arg_str(TCGContext *s, char *buf, int buf_size, TCGv arg)
704
{
705
    return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV(arg));
706
}
707

    
708
static int helper_cmp(const void *p1, const void *p2)
709
{
710
    const TCGHelperInfo *th1 = p1;
711
    const TCGHelperInfo *th2 = p2;
712
    if (th1->func < th2->func)
713
        return -1;
714
    else if (th1->func == th2->func)
715
        return 0;
716
    else
717
        return 1;
718
}
719

    
720
/* find helper definition (Note: A hash table would be better) */
721
static TCGHelperInfo *tcg_find_helper(TCGContext *s, tcg_target_ulong val)
722
{
723
    int m, m_min, m_max;
724
    TCGHelperInfo *th;
725
    tcg_target_ulong v;
726

    
727
    if (unlikely(!s->helpers_sorted)) {
728
        qsort(s->helpers, s->nb_helpers, sizeof(TCGHelperInfo), 
729
              helper_cmp);
730
        s->helpers_sorted = 1;
731
    }
732

    
733
    /* binary search */
734
    m_min = 0;
735
    m_max = s->nb_helpers - 1;
736
    while (m_min <= m_max) {
737
        m = (m_min + m_max) >> 1;
738
        th = &s->helpers[m];
739
        v = th->func;
740
        if (v == val)
741
            return th;
742
        else if (val < v) {
743
            m_max = m - 1;
744
        } else {
745
            m_min = m + 1;
746
        }
747
    }
748
    return NULL;
749
}
750

    
751
void tcg_dump_ops(TCGContext *s, FILE *outfile)
752
{
753
    const uint16_t *opc_ptr;
754
    const TCGArg *args;
755
    TCGArg arg;
756
    int c, i, k, nb_oargs, nb_iargs, nb_cargs, first_insn;
757
    const TCGOpDef *def;
758
    char buf[128];
759

    
760
    first_insn = 1;
761
    opc_ptr = gen_opc_buf;
762
    args = gen_opparam_buf;
763
    while (opc_ptr < gen_opc_ptr) {
764
        c = *opc_ptr++;
765
        def = &tcg_op_defs[c];
766
        if (c == INDEX_op_debug_insn_start) {
767
            uint64_t pc;
768
#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
769
            pc = ((uint64_t)args[1] << 32) | args[0];
770
#else
771
            pc = args[0];
772
#endif
773
            if (!first_insn) 
774
                fprintf(outfile, "\n");
775
            fprintf(outfile, " ---- 0x%" PRIx64, pc);
776
            first_insn = 0;
777
            nb_oargs = def->nb_oargs;
778
            nb_iargs = def->nb_iargs;
779
            nb_cargs = def->nb_cargs;
780
        } else if (c == INDEX_op_call) {
781
            TCGArg arg;
782

    
783
            /* variable number of arguments */
784
            arg = *args++;
785
            nb_oargs = arg >> 16;
786
            nb_iargs = arg & 0xffff;
787
            nb_cargs = def->nb_cargs;
788

    
789
            fprintf(outfile, " %s ", def->name);
790

    
791
            /* function name */
792
            fprintf(outfile, "%s",
793
                    tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + nb_iargs - 1]));
794
            /* flags */
795
            fprintf(outfile, ",$0x%" TCG_PRIlx,
796
                    args[nb_oargs + nb_iargs]);
797
            /* nb out args */
798
            fprintf(outfile, ",$%d", nb_oargs);
799
            for(i = 0; i < nb_oargs; i++) {
800
                fprintf(outfile, ",");
801
                fprintf(outfile, "%s",
802
                        tcg_get_arg_str_idx(s, buf, sizeof(buf), args[i]));
803
            }
804
            for(i = 0; i < (nb_iargs - 1); i++) {
805
                fprintf(outfile, ",");
806
                if (args[nb_oargs + i] == TCG_CALL_DUMMY_ARG) {
807
                    fprintf(outfile, "<dummy>");
808
                } else {
809
                    fprintf(outfile, "%s",
810
                            tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + i]));
811
                }
812
            }
813
        } else if (c == INDEX_op_movi_i32 
814
#if TCG_TARGET_REG_BITS == 64
815
                   || c == INDEX_op_movi_i64
816
#endif
817
                   ) {
818
            tcg_target_ulong val;
819
            TCGHelperInfo *th;
820

    
821
            nb_oargs = def->nb_oargs;
822
            nb_iargs = def->nb_iargs;
823
            nb_cargs = def->nb_cargs;
824
            fprintf(outfile, " %s %s,$", def->name, 
825
                    tcg_get_arg_str_idx(s, buf, sizeof(buf), args[0]));
826
            val = args[1];
827
            th = tcg_find_helper(s, val);
828
            if (th) {
829
                fprintf(outfile, th->name);
830
            } else {
831
                if (c == INDEX_op_movi_i32)
832
                    fprintf(outfile, "0x%x", (uint32_t)val);
833
                else
834
                    fprintf(outfile, "0x%" PRIx64 , (uint64_t)val);
835
            }
836
        } else {
837
            fprintf(outfile, " %s ", def->name);
838
            if (c == INDEX_op_nopn) {
839
                /* variable number of arguments */
840
                nb_cargs = *args;
841
                nb_oargs = 0;
842
                nb_iargs = 0;
843
            } else {
844
                nb_oargs = def->nb_oargs;
845
                nb_iargs = def->nb_iargs;
846
                nb_cargs = def->nb_cargs;
847
            }
848
            
849
            k = 0;
850
            for(i = 0; i < nb_oargs; i++) {
851
                if (k != 0)
852
                    fprintf(outfile, ",");
853
                fprintf(outfile, "%s",
854
                        tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
855
            }
856
            for(i = 0; i < nb_iargs; i++) {
857
                if (k != 0)
858
                    fprintf(outfile, ",");
859
                fprintf(outfile, "%s",
860
                        tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
861
            }
862
            for(i = 0; i < nb_cargs; i++) {
863
                if (k != 0)
864
                    fprintf(outfile, ",");
865
                arg = args[k++];
866
                fprintf(outfile, "$0x%" TCG_PRIlx, arg);
867
            }
868
        }
869
        fprintf(outfile, "\n");
870
        args += nb_iargs + nb_oargs + nb_cargs;
871
    }
872
}
873

    
874
/* we give more priority to constraints with less registers */
875
static int get_constraint_priority(const TCGOpDef *def, int k)
876
{
877
    const TCGArgConstraint *arg_ct;
878

    
879
    int i, n;
880
    arg_ct = &def->args_ct[k];
881
    if (arg_ct->ct & TCG_CT_ALIAS) {
882
        /* an alias is equivalent to a single register */
883
        n = 1;
884
    } else {
885
        if (!(arg_ct->ct & TCG_CT_REG))
886
            return 0;
887
        n = 0;
888
        for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
889
            if (tcg_regset_test_reg(arg_ct->u.regs, i))
890
                n++;
891
        }
892
    }
893
    return TCG_TARGET_NB_REGS - n + 1;
894
}
895

    
896
/* sort from highest priority to lowest */
897
static void sort_constraints(TCGOpDef *def, int start, int n)
898
{
899
    int i, j, p1, p2, tmp;
900

    
901
    for(i = 0; i < n; i++)
902
        def->sorted_args[start + i] = start + i;
903
    if (n <= 1)
904
        return;
905
    for(i = 0; i < n - 1; i++) {
906
        for(j = i + 1; j < n; j++) {
907
            p1 = get_constraint_priority(def, def->sorted_args[start + i]);
908
            p2 = get_constraint_priority(def, def->sorted_args[start + j]);
909
            if (p1 < p2) {
910
                tmp = def->sorted_args[start + i];
911
                def->sorted_args[start + i] = def->sorted_args[start + j];
912
                def->sorted_args[start + j] = tmp;
913
            }
914
        }
915
    }
916
}
917

    
918
void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs)
919
{
920
    int op;
921
    TCGOpDef *def;
922
    const char *ct_str;
923
    int i, nb_args;
924

    
925
    for(;;) {
926
        if (tdefs->op < 0)
927
            break;
928
        op = tdefs->op;
929
        assert(op >= 0 && op < NB_OPS);
930
        def = &tcg_op_defs[op];
931
        nb_args = def->nb_iargs + def->nb_oargs;
932
        for(i = 0; i < nb_args; i++) {
933
            ct_str = tdefs->args_ct_str[i];
934
            tcg_regset_clear(def->args_ct[i].u.regs);
935
            def->args_ct[i].ct = 0;
936
            if (ct_str[0] >= '0' && ct_str[0] <= '9') {
937
                int oarg;
938
                oarg = ct_str[0] - '0';
939
                assert(oarg < def->nb_oargs);
940
                assert(def->args_ct[oarg].ct & TCG_CT_REG);
941
                /* TCG_CT_ALIAS is for the output arguments. The input
942
                   argument is tagged with TCG_CT_IALIAS. */
943
                def->args_ct[i] = def->args_ct[oarg];
944
                def->args_ct[oarg].ct = TCG_CT_ALIAS;
945
                def->args_ct[oarg].alias_index = i;
946
                def->args_ct[i].ct |= TCG_CT_IALIAS;
947
                def->args_ct[i].alias_index = oarg;
948
            } else {
949
                for(;;) {
950
                    if (*ct_str == '\0')
951
                        break;
952
                    switch(*ct_str) {
953
                    case 'i':
954
                        def->args_ct[i].ct |= TCG_CT_CONST;
955
                        ct_str++;
956
                        break;
957
                    default:
958
                        if (target_parse_constraint(&def->args_ct[i], &ct_str) < 0) {
959
                            fprintf(stderr, "Invalid constraint '%s' for arg %d of operation '%s'\n",
960
                                    ct_str, i, def->name);
961
                            exit(1);
962
                        }
963
                    }
964
                }
965
            }
966
        }
967

    
968
        /* sort the constraints (XXX: this is just an heuristic) */
969
        sort_constraints(def, 0, def->nb_oargs);
970
        sort_constraints(def, def->nb_oargs, def->nb_iargs);
971

    
972
#if 0
973
        {
974
            int i;
975

976
            printf("%s: sorted=", def->name);
977
            for(i = 0; i < def->nb_oargs + def->nb_iargs; i++)
978
                printf(" %d", def->sorted_args[i]);
979
            printf("\n");
980
        }
981
#endif
982
        tdefs++;
983
    }
984

    
985
}
986

    
987
#ifdef USE_LIVENESS_ANALYSIS
988

    
989
/* set a nop for an operation using 'nb_args' */
990
static inline void tcg_set_nop(TCGContext *s, uint16_t *opc_ptr, 
991
                               TCGArg *args, int nb_args)
992
{
993
    if (nb_args == 0) {
994
        *opc_ptr = INDEX_op_nop;
995
    } else {
996
        *opc_ptr = INDEX_op_nopn;
997
        args[0] = nb_args;
998
        args[nb_args - 1] = nb_args;
999
    }
1000
}
1001

    
1002
/* liveness analysis: end of function: globals are live, temps are
1003
   dead. */
1004
/* XXX: at this stage, not used as there would be little gains because
1005
   most TBs end with a conditional jump. */
1006
static inline void tcg_la_func_end(TCGContext *s, uint8_t *dead_temps)
1007
{
1008
    memset(dead_temps, 0, s->nb_globals);
1009
    memset(dead_temps + s->nb_globals, 1, s->nb_temps - s->nb_globals);
1010
}
1011

    
1012
/* liveness analysis: end of basic block: globals are live, temps are
1013
   dead, local temps are live. */
1014
static inline void tcg_la_bb_end(TCGContext *s, uint8_t *dead_temps)
1015
{
1016
    int i;
1017
    TCGTemp *ts;
1018

    
1019
    memset(dead_temps, 0, s->nb_globals);
1020
    ts = &s->temps[s->nb_globals];
1021
    for(i = s->nb_globals; i < s->nb_temps; i++) {
1022
        if (ts->temp_local)
1023
            dead_temps[i] = 0;
1024
        else
1025
            dead_temps[i] = 1;
1026
        ts++;
1027
    }
1028
}
1029

    
1030
/* Liveness analysis : update the opc_dead_iargs array to tell if a
1031
   given input arguments is dead. Instructions updating dead
1032
   temporaries are removed. */
1033
void tcg_liveness_analysis(TCGContext *s)
1034
{
1035
    int i, op_index, op, nb_args, nb_iargs, nb_oargs, arg, nb_ops;
1036
    TCGArg *args;
1037
    const TCGOpDef *def;
1038
    uint8_t *dead_temps;
1039
    unsigned int dead_iargs;
1040
    
1041
    gen_opc_ptr++; /* skip end */
1042

    
1043
    nb_ops = gen_opc_ptr - gen_opc_buf;
1044

    
1045
    /* XXX: make it really dynamic */
1046
    s->op_dead_iargs = tcg_malloc(OPC_BUF_SIZE * sizeof(uint16_t));
1047
    
1048
    dead_temps = tcg_malloc(s->nb_temps);
1049
    memset(dead_temps, 1, s->nb_temps);
1050

    
1051
    args = gen_opparam_ptr;
1052
    op_index = nb_ops - 1;
1053
    while (op_index >= 0) {
1054
        op = gen_opc_buf[op_index];
1055
        def = &tcg_op_defs[op];
1056
        switch(op) {
1057
        case INDEX_op_call:
1058
            {
1059
                int call_flags;
1060

    
1061
                nb_args = args[-1];
1062
                args -= nb_args;
1063
                nb_iargs = args[0] & 0xffff;
1064
                nb_oargs = args[0] >> 16;
1065
                args++;
1066
                call_flags = args[nb_oargs + nb_iargs];
1067

    
1068
                /* pure functions can be removed if their result is not
1069
                   used */
1070
                if (call_flags & TCG_CALL_PURE) {
1071
                    for(i = 0; i < nb_oargs; i++) {
1072
                        arg = args[i];
1073
                        if (!dead_temps[arg])
1074
                            goto do_not_remove_call;
1075
                    }
1076
                    tcg_set_nop(s, gen_opc_buf + op_index, 
1077
                                args - 1, nb_args);
1078
                } else {
1079
                do_not_remove_call:
1080

    
1081
                    /* output args are dead */
1082
                    for(i = 0; i < nb_oargs; i++) {
1083
                        arg = args[i];
1084
                        dead_temps[arg] = 1;
1085
                    }
1086
                    
1087
                    /* globals are live (they may be used by the call) */
1088
                    memset(dead_temps, 0, s->nb_globals);
1089
                    
1090
                    /* input args are live */
1091
                    dead_iargs = 0;
1092
                    for(i = 0; i < nb_iargs; i++) {
1093
                        arg = args[i + nb_oargs];
1094
                        if (arg != TCG_CALL_DUMMY_ARG) {
1095
                            if (dead_temps[arg]) {
1096
                                dead_iargs |= (1 << i);
1097
                            }
1098
                            dead_temps[arg] = 0;
1099
                        }
1100
                    }
1101
                    s->op_dead_iargs[op_index] = dead_iargs;
1102
                }
1103
                args--;
1104
            }
1105
            break;
1106
        case INDEX_op_set_label:
1107
            args--;
1108
            /* mark end of basic block */
1109
            tcg_la_bb_end(s, dead_temps);
1110
            break;
1111
        case INDEX_op_debug_insn_start:
1112
            args -= def->nb_args;
1113
            break;
1114
        case INDEX_op_nopn:
1115
            nb_args = args[-1];
1116
            args -= nb_args;
1117
            break;
1118
        case INDEX_op_discard:
1119
            args--;
1120
            /* mark the temporary as dead */
1121
            dead_temps[args[0]] = 1;
1122
            break;
1123
        case INDEX_op_macro_2:
1124
            {
1125
                int dead_args[2], macro_id;
1126
                int saved_op_index, saved_arg_index;
1127
                int macro_op_index, macro_arg_index;
1128
                int macro_end_op_index, macro_end_arg_index;
1129
                int last_nb_temps;
1130
                
1131
                nb_args = 3;
1132
                args -= nb_args;
1133
                dead_args[0] = dead_temps[args[0]];
1134
                dead_args[1] = dead_temps[args[1]];
1135
                macro_id = args[2];
1136

    
1137
                /* call the macro function which generate code
1138
                   depending on the live outputs */
1139
                saved_op_index = op_index;
1140
                saved_arg_index = args - gen_opparam_buf;
1141

    
1142
                /* add a macro start instruction */
1143
                *gen_opc_ptr++ = INDEX_op_macro_start;
1144
                *gen_opparam_ptr++ = saved_op_index;
1145
                *gen_opparam_ptr++ = saved_arg_index;
1146

    
1147
                macro_op_index = gen_opc_ptr - gen_opc_buf;
1148
                macro_arg_index = gen_opparam_ptr -  gen_opparam_buf;
1149

    
1150
                last_nb_temps = s->nb_temps;
1151

    
1152
                s->macro_func(s, macro_id, dead_args);
1153

    
1154
                /* realloc temp info (XXX: make it faster) */
1155
                if (s->nb_temps > last_nb_temps) {
1156
                    uint8_t *new_dead_temps;
1157

    
1158
                    new_dead_temps = tcg_malloc(s->nb_temps);
1159
                    memcpy(new_dead_temps, dead_temps, last_nb_temps);
1160
                    memset(new_dead_temps + last_nb_temps, 1, 
1161
                           s->nb_temps - last_nb_temps);
1162
                    dead_temps = new_dead_temps;
1163
                }
1164

    
1165
                macro_end_op_index = gen_opc_ptr - gen_opc_buf;
1166
                macro_end_arg_index = gen_opparam_ptr - gen_opparam_buf;
1167

    
1168
                /* end of macro: add a goto to the next instruction */
1169
                *gen_opc_ptr++ = INDEX_op_macro_end;
1170
                *gen_opparam_ptr++ = op_index + 1;
1171
                *gen_opparam_ptr++ = saved_arg_index + nb_args;
1172

    
1173
                /* modify the macro operation to be a macro_goto */
1174
                gen_opc_buf[op_index] = INDEX_op_macro_goto;
1175
                args[0] = macro_op_index;
1176
                args[1] = macro_arg_index;
1177
                args[2] = 0; /* dummy third arg to match the 
1178
                                macro parameters */
1179

    
1180
                /* set the next instruction to the end of the macro */
1181
                op_index = macro_end_op_index;
1182
                args = macro_end_arg_index + gen_opparam_buf;
1183
            }
1184
            break;
1185
        case INDEX_op_macro_start:
1186
            args -= 2;
1187
            op_index = args[0];
1188
            args = gen_opparam_buf + args[1];
1189
            break;
1190
        case INDEX_op_macro_goto:
1191
        case INDEX_op_macro_end:
1192
            tcg_abort(); /* should never happen in liveness analysis */
1193
        case INDEX_op_end:
1194
            break;
1195
            /* XXX: optimize by hardcoding common cases (e.g. triadic ops) */
1196
        default:
1197
            if (op > INDEX_op_end) {
1198
                args -= def->nb_args;
1199
                nb_iargs = def->nb_iargs;
1200
                nb_oargs = def->nb_oargs;
1201

    
1202
                /* Test if the operation can be removed because all
1203
                   its outputs are dead. We assume that nb_oargs == 0
1204
                   implies side effects */
1205
                if (!(def->flags & TCG_OPF_SIDE_EFFECTS) && nb_oargs != 0) {
1206
                    for(i = 0; i < nb_oargs; i++) {
1207
                        arg = args[i];
1208
                        if (!dead_temps[arg])
1209
                            goto do_not_remove;
1210
                    }
1211
                    tcg_set_nop(s, gen_opc_buf + op_index, args, def->nb_args);
1212
#ifdef CONFIG_PROFILER
1213
                    s->del_op_count++;
1214
#endif
1215
                } else {
1216
                do_not_remove:
1217

    
1218
                    /* output args are dead */
1219
                    for(i = 0; i < nb_oargs; i++) {
1220
                        arg = args[i];
1221
                        dead_temps[arg] = 1;
1222
                    }
1223
                    
1224
                    /* if end of basic block, update */
1225
                    if (def->flags & TCG_OPF_BB_END) {
1226
                        tcg_la_bb_end(s, dead_temps);
1227
                    } else if (def->flags & TCG_OPF_CALL_CLOBBER) {
1228
                        /* globals are live */
1229
                        memset(dead_temps, 0, s->nb_globals);
1230
                    }
1231
                    
1232
                    /* input args are live */
1233
                    dead_iargs = 0;
1234
                    for(i = 0; i < nb_iargs; i++) {
1235
                        arg = args[i + nb_oargs];
1236
                        if (dead_temps[arg]) {
1237
                            dead_iargs |= (1 << i);
1238
                        }
1239
                        dead_temps[arg] = 0;
1240
                    }
1241
                    s->op_dead_iargs[op_index] = dead_iargs;
1242
                }
1243
            } else {
1244
                /* legacy dyngen operations */
1245
                args -= def->nb_args;
1246
                /* mark end of basic block */
1247
                tcg_la_bb_end(s, dead_temps);
1248
            }
1249
            break;
1250
        }
1251
        op_index--;
1252
    }
1253

    
1254
    if (args != gen_opparam_buf)
1255
        tcg_abort();
1256
}
1257
#else
1258
/* dummy liveness analysis */
1259
void tcg_liveness_analysis(TCGContext *s)
1260
{
1261
    int nb_ops;
1262
    nb_ops = gen_opc_ptr - gen_opc_buf;
1263

    
1264
    s->op_dead_iargs = tcg_malloc(nb_ops * sizeof(uint16_t));
1265
    memset(s->op_dead_iargs, 0, nb_ops * sizeof(uint16_t));
1266
}
1267
#endif
1268

    
1269
#ifndef NDEBUG
1270
static void dump_regs(TCGContext *s)
1271
{
1272
    TCGTemp *ts;
1273
    int i;
1274
    char buf[64];
1275

    
1276
    for(i = 0; i < s->nb_temps; i++) {
1277
        ts = &s->temps[i];
1278
        printf("  %10s: ", tcg_get_arg_str_idx(s, buf, sizeof(buf), i));
1279
        switch(ts->val_type) {
1280
        case TEMP_VAL_REG:
1281
            printf("%s", tcg_target_reg_names[ts->reg]);
1282
            break;
1283
        case TEMP_VAL_MEM:
1284
            printf("%d(%s)", (int)ts->mem_offset, tcg_target_reg_names[ts->mem_reg]);
1285
            break;
1286
        case TEMP_VAL_CONST:
1287
            printf("$0x%" TCG_PRIlx, ts->val);
1288
            break;
1289
        case TEMP_VAL_DEAD:
1290
            printf("D");
1291
            break;
1292
        default:
1293
            printf("???");
1294
            break;
1295
        }
1296
        printf("\n");
1297
    }
1298

    
1299
    for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
1300
        if (s->reg_to_temp[i] >= 0) {
1301
            printf("%s: %s\n", 
1302
                   tcg_target_reg_names[i], 
1303
                   tcg_get_arg_str_idx(s, buf, sizeof(buf), s->reg_to_temp[i]));
1304
        }
1305
    }
1306
}
1307

    
1308
static void check_regs(TCGContext *s)
1309
{
1310
    int reg, k;
1311
    TCGTemp *ts;
1312
    char buf[64];
1313

    
1314
    for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1315
        k = s->reg_to_temp[reg];
1316
        if (k >= 0) {
1317
            ts = &s->temps[k];
1318
            if (ts->val_type != TEMP_VAL_REG ||
1319
                ts->reg != reg) {
1320
                printf("Inconsistency for register %s:\n", 
1321
                       tcg_target_reg_names[reg]);
1322
                goto fail;
1323
            }
1324
        }
1325
    }
1326
    for(k = 0; k < s->nb_temps; k++) {
1327
        ts = &s->temps[k];
1328
        if (ts->val_type == TEMP_VAL_REG &&
1329
            !ts->fixed_reg &&
1330
            s->reg_to_temp[ts->reg] != k) {
1331
                printf("Inconsistency for temp %s:\n", 
1332
                       tcg_get_arg_str_idx(s, buf, sizeof(buf), k));
1333
        fail:
1334
                printf("reg state:\n");
1335
                dump_regs(s);
1336
                tcg_abort();
1337
        }
1338
    }
1339
}
1340
#endif
1341

    
1342
static void temp_allocate_frame(TCGContext *s, int temp)
1343
{
1344
    TCGTemp *ts;
1345
    ts = &s->temps[temp];
1346
    s->current_frame_offset = (s->current_frame_offset + sizeof(tcg_target_long) - 1) & ~(sizeof(tcg_target_long) - 1);
1347
    if (s->current_frame_offset + sizeof(tcg_target_long) > s->frame_end)
1348
        tcg_abort();
1349
    ts->mem_offset = s->current_frame_offset;
1350
    ts->mem_reg = s->frame_reg;
1351
    ts->mem_allocated = 1;
1352
    s->current_frame_offset += sizeof(tcg_target_long);
1353
}
1354

    
1355
/* free register 'reg' by spilling the corresponding temporary if necessary */
1356
static void tcg_reg_free(TCGContext *s, int reg)
1357
{
1358
    TCGTemp *ts;
1359
    int temp;
1360

    
1361
    temp = s->reg_to_temp[reg];
1362
    if (temp != -1) {
1363
        ts = &s->temps[temp];
1364
        assert(ts->val_type == TEMP_VAL_REG);
1365
        if (!ts->mem_coherent) {
1366
            if (!ts->mem_allocated) 
1367
                temp_allocate_frame(s, temp);
1368
            tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1369
        }
1370
        ts->val_type = TEMP_VAL_MEM;
1371
        s->reg_to_temp[reg] = -1;
1372
    }
1373
}
1374

    
1375
/* Allocate a register belonging to reg1 & ~reg2 */
1376
static int tcg_reg_alloc(TCGContext *s, TCGRegSet reg1, TCGRegSet reg2)
1377
{
1378
    int i, reg;
1379
    TCGRegSet reg_ct;
1380

    
1381
    tcg_regset_andnot(reg_ct, reg1, reg2);
1382

    
1383
    /* first try free registers */
1384
    for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1385
        reg = tcg_target_reg_alloc_order[i];
1386
        if (tcg_regset_test_reg(reg_ct, reg) && s->reg_to_temp[reg] == -1)
1387
            return reg;
1388
    }
1389

    
1390
    /* XXX: do better spill choice */
1391
    for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1392
        reg = tcg_target_reg_alloc_order[i];
1393
        if (tcg_regset_test_reg(reg_ct, reg)) {
1394
            tcg_reg_free(s, reg);
1395
            return reg;
1396
        }
1397
    }
1398

    
1399
    tcg_abort();
1400
}
1401

    
1402
/* save a temporary to memory. 'allocated_regs' is used in case a
1403
   temporary registers needs to be allocated to store a constant. */
1404
static void temp_save(TCGContext *s, int temp, TCGRegSet allocated_regs)
1405
{
1406
    TCGTemp *ts;
1407
    int reg;
1408

    
1409
    ts = &s->temps[temp];
1410
    if (!ts->fixed_reg) {
1411
        switch(ts->val_type) {
1412
        case TEMP_VAL_REG:
1413
            tcg_reg_free(s, ts->reg);
1414
            break;
1415
        case TEMP_VAL_DEAD:
1416
            ts->val_type = TEMP_VAL_MEM;
1417
            break;
1418
        case TEMP_VAL_CONST:
1419
            reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], 
1420
                                allocated_regs);
1421
            if (!ts->mem_allocated) 
1422
                temp_allocate_frame(s, temp);
1423
            tcg_out_movi(s, ts->type, reg, ts->val);
1424
            tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1425
            ts->val_type = TEMP_VAL_MEM;
1426
            break;
1427
        case TEMP_VAL_MEM:
1428
            break;
1429
        default:
1430
            tcg_abort();
1431
        }
1432
    }
1433
}
1434

    
1435
/* save globals to their cannonical location and assume they can be
1436
   modified be the following code. 'allocated_regs' is used in case a
1437
   temporary registers needs to be allocated to store a constant. */
1438
static void save_globals(TCGContext *s, TCGRegSet allocated_regs)
1439
{
1440
    int i;
1441

    
1442
    for(i = 0; i < s->nb_globals; i++) {
1443
        temp_save(s, i, allocated_regs);
1444
    }
1445
}
1446

    
1447
/* at the end of a basic block, we assume all temporaries are dead and
1448
   all globals are stored at their canonical location. */
1449
static void tcg_reg_alloc_bb_end(TCGContext *s, TCGRegSet allocated_regs)
1450
{
1451
    TCGTemp *ts;
1452
    int i;
1453

    
1454
    for(i = s->nb_globals; i < s->nb_temps; i++) {
1455
        ts = &s->temps[i];
1456
        if (ts->temp_local) {
1457
            temp_save(s, i, allocated_regs);
1458
        } else {
1459
            if (ts->val_type == TEMP_VAL_REG) {
1460
                s->reg_to_temp[ts->reg] = -1;
1461
            }
1462
            ts->val_type = TEMP_VAL_DEAD;
1463
        }
1464
    }
1465

    
1466
    save_globals(s, allocated_regs);
1467
}
1468

    
1469
#define IS_DEAD_IARG(n) ((dead_iargs >> (n)) & 1)
1470

    
1471
static void tcg_reg_alloc_movi(TCGContext *s, const TCGArg *args)
1472
{
1473
    TCGTemp *ots;
1474
    tcg_target_ulong val;
1475

    
1476
    ots = &s->temps[args[0]];
1477
    val = args[1];
1478

    
1479
    if (ots->fixed_reg) {
1480
        /* for fixed registers, we do not do any constant
1481
           propagation */
1482
        tcg_out_movi(s, ots->type, ots->reg, val);
1483
    } else {
1484
        /* The movi is not explicitely generated here */
1485
        if (ots->val_type == TEMP_VAL_REG)
1486
            s->reg_to_temp[ots->reg] = -1;
1487
        ots->val_type = TEMP_VAL_CONST;
1488
        ots->val = val;
1489
    }
1490
}
1491

    
1492
static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
1493
                              const TCGArg *args,
1494
                              unsigned int dead_iargs)
1495
{
1496
    TCGTemp *ts, *ots;
1497
    int reg;
1498
    const TCGArgConstraint *arg_ct;
1499

    
1500
    ots = &s->temps[args[0]];
1501
    ts = &s->temps[args[1]];
1502
    arg_ct = &def->args_ct[0];
1503

    
1504
    /* XXX: always mark arg dead if IS_DEAD_IARG(0) */
1505
    if (ts->val_type == TEMP_VAL_REG) {
1506
        if (IS_DEAD_IARG(0) && !ts->fixed_reg && !ots->fixed_reg) {
1507
            /* the mov can be suppressed */
1508
            if (ots->val_type == TEMP_VAL_REG)
1509
                s->reg_to_temp[ots->reg] = -1;
1510
            reg = ts->reg;
1511
            s->reg_to_temp[reg] = -1;
1512
            ts->val_type = TEMP_VAL_DEAD;
1513
        } else {
1514
            if (ots->val_type == TEMP_VAL_REG) {
1515
                reg = ots->reg;
1516
            } else {
1517
                reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1518
            }
1519
            if (ts->reg != reg) {
1520
                tcg_out_mov(s, reg, ts->reg);
1521
            }
1522
        }
1523
    } else if (ts->val_type == TEMP_VAL_MEM) {
1524
        if (ots->val_type == TEMP_VAL_REG) {
1525
            reg = ots->reg;
1526
        } else {
1527
            reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1528
        }
1529
        tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1530
    } else if (ts->val_type == TEMP_VAL_CONST) {
1531
        if (ots->fixed_reg) {
1532
            reg = ots->reg;
1533
            tcg_out_movi(s, ots->type, reg, ts->val);
1534
        } else {
1535
            /* propagate constant */
1536
            if (ots->val_type == TEMP_VAL_REG)
1537
                s->reg_to_temp[ots->reg] = -1;
1538
            ots->val_type = TEMP_VAL_CONST;
1539
            ots->val = ts->val;
1540
            return;
1541
        }
1542
    } else {
1543
        tcg_abort();
1544
    }
1545
    s->reg_to_temp[reg] = args[0];
1546
    ots->reg = reg;
1547
    ots->val_type = TEMP_VAL_REG;
1548
    ots->mem_coherent = 0;
1549
}
1550

    
1551
static void tcg_reg_alloc_op(TCGContext *s, 
1552
                             const TCGOpDef *def, int opc,
1553
                             const TCGArg *args,
1554
                             unsigned int dead_iargs)
1555
{
1556
    TCGRegSet allocated_regs;
1557
    int i, k, nb_iargs, nb_oargs, reg;
1558
    TCGArg arg;
1559
    const TCGArgConstraint *arg_ct;
1560
    TCGTemp *ts;
1561
    TCGArg new_args[TCG_MAX_OP_ARGS];
1562
    int const_args[TCG_MAX_OP_ARGS];
1563

    
1564
    nb_oargs = def->nb_oargs;
1565
    nb_iargs = def->nb_iargs;
1566

    
1567
    /* copy constants */
1568
    memcpy(new_args + nb_oargs + nb_iargs, 
1569
           args + nb_oargs + nb_iargs, 
1570
           sizeof(TCGArg) * def->nb_cargs);
1571

    
1572
    /* satisfy input constraints */ 
1573
    tcg_regset_set(allocated_regs, s->reserved_regs);
1574
    for(k = 0; k < nb_iargs; k++) {
1575
        i = def->sorted_args[nb_oargs + k];
1576
        arg = args[i];
1577
        arg_ct = &def->args_ct[i];
1578
        ts = &s->temps[arg];
1579
        if (ts->val_type == TEMP_VAL_MEM) {
1580
            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1581
            tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1582
            ts->val_type = TEMP_VAL_REG;
1583
            ts->reg = reg;
1584
            ts->mem_coherent = 1;
1585
            s->reg_to_temp[reg] = arg;
1586
        } else if (ts->val_type == TEMP_VAL_CONST) {
1587
            if (tcg_target_const_match(ts->val, arg_ct)) {
1588
                /* constant is OK for instruction */
1589
                const_args[i] = 1;
1590
                new_args[i] = ts->val;
1591
                goto iarg_end;
1592
            } else {
1593
                /* need to move to a register */
1594
                reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1595
                tcg_out_movi(s, ts->type, reg, ts->val);
1596
                ts->val_type = TEMP_VAL_REG;
1597
                ts->reg = reg;
1598
                ts->mem_coherent = 0;
1599
                s->reg_to_temp[reg] = arg;
1600
            }
1601
        }
1602
        assert(ts->val_type == TEMP_VAL_REG);
1603
        if (arg_ct->ct & TCG_CT_IALIAS) {
1604
            if (ts->fixed_reg) {
1605
                /* if fixed register, we must allocate a new register
1606
                   if the alias is not the same register */
1607
                if (arg != args[arg_ct->alias_index])
1608
                    goto allocate_in_reg;
1609
            } else {
1610
                /* if the input is aliased to an output and if it is
1611
                   not dead after the instruction, we must allocate
1612
                   a new register and move it */
1613
                if (!IS_DEAD_IARG(i - nb_oargs)) 
1614
                    goto allocate_in_reg;
1615
            }
1616
        }
1617
        reg = ts->reg;
1618
        if (tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1619
            /* nothing to do : the constraint is satisfied */
1620
        } else {
1621
        allocate_in_reg:
1622
            /* allocate a new register matching the constraint 
1623
               and move the temporary register into it */
1624
            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1625
            tcg_out_mov(s, reg, ts->reg);
1626
        }
1627
        new_args[i] = reg;
1628
        const_args[i] = 0;
1629
        tcg_regset_set_reg(allocated_regs, reg);
1630
    iarg_end: ;
1631
    }
1632
    
1633
    if (def->flags & TCG_OPF_BB_END) {
1634
        tcg_reg_alloc_bb_end(s, allocated_regs);
1635
    } else {
1636
        /* mark dead temporaries and free the associated registers */
1637
        for(i = 0; i < nb_iargs; i++) {
1638
            arg = args[nb_oargs + i];
1639
            if (IS_DEAD_IARG(i)) {
1640
                ts = &s->temps[arg];
1641
                if (!ts->fixed_reg) {
1642
                    if (ts->val_type == TEMP_VAL_REG)
1643
                        s->reg_to_temp[ts->reg] = -1;
1644
                    ts->val_type = TEMP_VAL_DEAD;
1645
                }
1646
            }
1647
        }
1648
        
1649
        if (def->flags & TCG_OPF_CALL_CLOBBER) {
1650
            /* XXX: permit generic clobber register list ? */ 
1651
            for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1652
                if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
1653
                    tcg_reg_free(s, reg);
1654
                }
1655
            }
1656
            /* XXX: for load/store we could do that only for the slow path
1657
               (i.e. when a memory callback is called) */
1658
            
1659
            /* store globals and free associated registers (we assume the insn
1660
               can modify any global. */
1661
            save_globals(s, allocated_regs);
1662
        }
1663
        
1664
        /* satisfy the output constraints */
1665
        tcg_regset_set(allocated_regs, s->reserved_regs);
1666
        for(k = 0; k < nb_oargs; k++) {
1667
            i = def->sorted_args[k];
1668
            arg = args[i];
1669
            arg_ct = &def->args_ct[i];
1670
            ts = &s->temps[arg];
1671
            if (arg_ct->ct & TCG_CT_ALIAS) {
1672
                reg = new_args[arg_ct->alias_index];
1673
            } else {
1674
                /* if fixed register, we try to use it */
1675
                reg = ts->reg;
1676
                if (ts->fixed_reg &&
1677
                    tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1678
                    goto oarg_end;
1679
                }
1680
                reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1681
            }
1682
            tcg_regset_set_reg(allocated_regs, reg);
1683
            /* if a fixed register is used, then a move will be done afterwards */
1684
            if (!ts->fixed_reg) {
1685
                if (ts->val_type == TEMP_VAL_REG)
1686
                    s->reg_to_temp[ts->reg] = -1;
1687
                ts->val_type = TEMP_VAL_REG;
1688
                ts->reg = reg;
1689
                /* temp value is modified, so the value kept in memory is
1690
                   potentially not the same */
1691
                ts->mem_coherent = 0; 
1692
                s->reg_to_temp[reg] = arg;
1693
            }
1694
        oarg_end:
1695
            new_args[i] = reg;
1696
        }
1697
    }
1698

    
1699
    /* emit instruction */
1700
    tcg_out_op(s, opc, new_args, const_args);
1701
    
1702
    /* move the outputs in the correct register if needed */
1703
    for(i = 0; i < nb_oargs; i++) {
1704
        ts = &s->temps[args[i]];
1705
        reg = new_args[i];
1706
        if (ts->fixed_reg && ts->reg != reg) {
1707
            tcg_out_mov(s, ts->reg, reg);
1708
        }
1709
    }
1710
}
1711

    
1712
#ifdef TCG_TARGET_STACK_GROWSUP
1713
#define STACK_DIR(x) (-(x))
1714
#else
1715
#define STACK_DIR(x) (x)
1716
#endif
1717

    
1718
static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
1719
                              int opc, const TCGArg *args,
1720
                              unsigned int dead_iargs)
1721
{
1722
    int nb_iargs, nb_oargs, flags, nb_regs, i, reg, nb_params;
1723
    TCGArg arg, func_arg;
1724
    TCGTemp *ts;
1725
    tcg_target_long stack_offset, call_stack_size, func_addr;
1726
    int const_func_arg, allocate_args;
1727
    TCGRegSet allocated_regs;
1728
    const TCGArgConstraint *arg_ct;
1729

    
1730
    arg = *args++;
1731

    
1732
    nb_oargs = arg >> 16;
1733
    nb_iargs = arg & 0xffff;
1734
    nb_params = nb_iargs - 1;
1735

    
1736
    flags = args[nb_oargs + nb_iargs];
1737

    
1738
    nb_regs = tcg_target_get_call_iarg_regs_count(flags);
1739
    if (nb_regs > nb_params)
1740
        nb_regs = nb_params;
1741

    
1742
    /* assign stack slots first */
1743
    /* XXX: preallocate call stack */
1744
    call_stack_size = (nb_params - nb_regs) * sizeof(tcg_target_long);
1745
    call_stack_size = (call_stack_size + TCG_TARGET_STACK_ALIGN - 1) & 
1746
        ~(TCG_TARGET_STACK_ALIGN - 1);
1747
    allocate_args = (call_stack_size > TCG_STATIC_CALL_ARGS_SIZE);
1748
    if (allocate_args) {
1749
        tcg_out_addi(s, TCG_REG_CALL_STACK, -STACK_DIR(call_stack_size));
1750
    }
1751

    
1752
    stack_offset = TCG_TARGET_CALL_STACK_OFFSET;
1753
    for(i = nb_regs; i < nb_params; i++) {
1754
        arg = args[nb_oargs + i];
1755
#ifdef TCG_TARGET_STACK_GROWSUP
1756
        stack_offset -= sizeof(tcg_target_long);
1757
#endif
1758
        if (arg != TCG_CALL_DUMMY_ARG) {
1759
            ts = &s->temps[arg];
1760
            if (ts->val_type == TEMP_VAL_REG) {
1761
                tcg_out_st(s, ts->type, ts->reg, TCG_REG_CALL_STACK, stack_offset);
1762
            } else if (ts->val_type == TEMP_VAL_MEM) {
1763
                reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], 
1764
                                    s->reserved_regs);
1765
                /* XXX: not correct if reading values from the stack */
1766
                tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1767
                tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
1768
            } else if (ts->val_type == TEMP_VAL_CONST) {
1769
                reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], 
1770
                                    s->reserved_regs);
1771
                /* XXX: sign extend may be needed on some targets */
1772
                tcg_out_movi(s, ts->type, reg, ts->val);
1773
                tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
1774
            } else {
1775
                tcg_abort();
1776
            }
1777
        }
1778
#ifndef TCG_TARGET_STACK_GROWSUP
1779
        stack_offset += sizeof(tcg_target_long);
1780
#endif
1781
    }
1782
    
1783
    /* assign input registers */
1784
    tcg_regset_set(allocated_regs, s->reserved_regs);
1785
    for(i = 0; i < nb_regs; i++) {
1786
        arg = args[nb_oargs + i];
1787
        if (arg != TCG_CALL_DUMMY_ARG) {
1788
            ts = &s->temps[arg];
1789
            reg = tcg_target_call_iarg_regs[i];
1790
            tcg_reg_free(s, reg);
1791
            if (ts->val_type == TEMP_VAL_REG) {
1792
                if (ts->reg != reg) {
1793
                    tcg_out_mov(s, reg, ts->reg);
1794
                }
1795
            } else if (ts->val_type == TEMP_VAL_MEM) {
1796
                tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1797
            } else if (ts->val_type == TEMP_VAL_CONST) {
1798
                /* XXX: sign extend ? */
1799
                tcg_out_movi(s, ts->type, reg, ts->val);
1800
            } else {
1801
                tcg_abort();
1802
            }
1803
            tcg_regset_set_reg(allocated_regs, reg);
1804
        }
1805
    }
1806
    
1807
    /* assign function address */
1808
    func_arg = args[nb_oargs + nb_iargs - 1];
1809
    arg_ct = &def->args_ct[0];
1810
    ts = &s->temps[func_arg];
1811
    func_addr = ts->val;
1812
    const_func_arg = 0;
1813
    if (ts->val_type == TEMP_VAL_MEM) {
1814
        reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1815
        tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1816
        func_arg = reg;
1817
        tcg_regset_set_reg(allocated_regs, reg);
1818
    } else if (ts->val_type == TEMP_VAL_REG) {
1819
        reg = ts->reg;
1820
        if (!tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1821
            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1822
            tcg_out_mov(s, reg, ts->reg);
1823
        }
1824
        func_arg = reg;
1825
        tcg_regset_set_reg(allocated_regs, reg);
1826
    } else if (ts->val_type == TEMP_VAL_CONST) {
1827
        if (tcg_target_const_match(func_addr, arg_ct)) {
1828
            const_func_arg = 1;
1829
            func_arg = func_addr;
1830
        } else {
1831
            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1832
            tcg_out_movi(s, ts->type, reg, func_addr);
1833
            func_arg = reg;
1834
            tcg_regset_set_reg(allocated_regs, reg);
1835
        }
1836
    } else {
1837
        tcg_abort();
1838
    }
1839
        
1840
    
1841
    /* mark dead temporaries and free the associated registers */
1842
    for(i = 0; i < nb_iargs; i++) {
1843
        arg = args[nb_oargs + i];
1844
        if (IS_DEAD_IARG(i)) {
1845
            ts = &s->temps[arg];
1846
            if (!ts->fixed_reg) {
1847
                if (ts->val_type == TEMP_VAL_REG)
1848
                    s->reg_to_temp[ts->reg] = -1;
1849
                ts->val_type = TEMP_VAL_DEAD;
1850
            }
1851
        }
1852
    }
1853
    
1854
    /* clobber call registers */
1855
    for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1856
        if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
1857
            tcg_reg_free(s, reg);
1858
        }
1859
    }
1860
    
1861
    /* store globals and free associated registers (we assume the call
1862
       can modify any global. */
1863
    save_globals(s, allocated_regs);
1864

    
1865
    tcg_out_op(s, opc, &func_arg, &const_func_arg);
1866
    
1867
    if (allocate_args) {
1868
        tcg_out_addi(s, TCG_REG_CALL_STACK, STACK_DIR(call_stack_size));
1869
    }
1870

    
1871
    /* assign output registers and emit moves if needed */
1872
    for(i = 0; i < nb_oargs; i++) {
1873
        arg = args[i];
1874
        ts = &s->temps[arg];
1875
        reg = tcg_target_call_oarg_regs[i];
1876
        assert(s->reg_to_temp[reg] == -1);
1877
        if (ts->fixed_reg) {
1878
            if (ts->reg != reg) {
1879
                tcg_out_mov(s, ts->reg, reg);
1880
            }
1881
        } else {
1882
            if (ts->val_type == TEMP_VAL_REG)
1883
                s->reg_to_temp[ts->reg] = -1;
1884
            ts->val_type = TEMP_VAL_REG;
1885
            ts->reg = reg;
1886
            ts->mem_coherent = 0; 
1887
            s->reg_to_temp[reg] = arg;
1888
        }
1889
    }
1890
    
1891
    return nb_iargs + nb_oargs + def->nb_cargs + 1;
1892
}
1893

    
1894
#ifdef CONFIG_PROFILER
1895

    
1896
static int64_t dyngen_table_op_count[NB_OPS];
1897

    
1898
void dump_op_count(void)
1899
{
1900
    int i;
1901
    FILE *f;
1902
    f = fopen("/tmp/op1.log", "w");
1903
    for(i = 0; i < INDEX_op_end; i++) {
1904
        fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name, dyngen_table_op_count[i]);
1905
    }
1906
    fclose(f);
1907
    f = fopen("/tmp/op2.log", "w");
1908
    for(i = INDEX_op_end; i < NB_OPS; i++) {
1909
        fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name, dyngen_table_op_count[i]);
1910
    }
1911
    fclose(f);
1912
}
1913
#endif
1914

    
1915

    
1916
static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
1917
                                      long search_pc)
1918
{
1919
    int opc, op_index, macro_op_index;
1920
    const TCGOpDef *def;
1921
    unsigned int dead_iargs;
1922
    const TCGArg *args;
1923

    
1924
#ifdef DEBUG_DISAS
1925
    if (unlikely(loglevel & CPU_LOG_TB_OP)) {
1926
        fprintf(logfile, "OP:\n");
1927
        tcg_dump_ops(s, logfile);
1928
        fprintf(logfile, "\n");
1929
    }
1930
#endif
1931

    
1932
#ifdef CONFIG_PROFILER
1933
    s->la_time -= profile_getclock();
1934
#endif
1935
    tcg_liveness_analysis(s);
1936
#ifdef CONFIG_PROFILER
1937
    s->la_time += profile_getclock();
1938
#endif
1939

    
1940
#ifdef DEBUG_DISAS
1941
    if (unlikely(loglevel & CPU_LOG_TB_OP_OPT)) {
1942
        fprintf(logfile, "OP after la:\n");
1943
        tcg_dump_ops(s, logfile);
1944
        fprintf(logfile, "\n");
1945
    }
1946
#endif
1947

    
1948
    tcg_reg_alloc_start(s);
1949

    
1950
    s->code_buf = gen_code_buf;
1951
    s->code_ptr = gen_code_buf;
1952

    
1953
    macro_op_index = -1;
1954
    args = gen_opparam_buf;
1955
    op_index = 0;
1956

    
1957
    for(;;) {
1958
        opc = gen_opc_buf[op_index];
1959
#ifdef CONFIG_PROFILER
1960
        dyngen_table_op_count[opc]++;
1961
#endif
1962
        def = &tcg_op_defs[opc];
1963
#if 0
1964
        printf("%s: %d %d %d\n", def->name,
1965
               def->nb_oargs, def->nb_iargs, def->nb_cargs);
1966
        //        dump_regs(s);
1967
#endif
1968
        switch(opc) {
1969
        case INDEX_op_mov_i32:
1970
#if TCG_TARGET_REG_BITS == 64
1971
        case INDEX_op_mov_i64:
1972
#endif
1973
            dead_iargs = s->op_dead_iargs[op_index];
1974
            tcg_reg_alloc_mov(s, def, args, dead_iargs);
1975
            break;
1976
        case INDEX_op_movi_i32:
1977
#if TCG_TARGET_REG_BITS == 64
1978
        case INDEX_op_movi_i64:
1979
#endif
1980
            tcg_reg_alloc_movi(s, args);
1981
            break;
1982
        case INDEX_op_debug_insn_start:
1983
            /* debug instruction */
1984
            break;
1985
        case INDEX_op_nop:
1986
        case INDEX_op_nop1:
1987
        case INDEX_op_nop2:
1988
        case INDEX_op_nop3:
1989
            break;
1990
        case INDEX_op_nopn:
1991
            args += args[0];
1992
            goto next;
1993
        case INDEX_op_discard:
1994
            {
1995
                TCGTemp *ts;
1996
                ts = &s->temps[args[0]];
1997
                /* mark the temporary as dead */
1998
                if (!ts->fixed_reg) {
1999
                    if (ts->val_type == TEMP_VAL_REG)
2000
                        s->reg_to_temp[ts->reg] = -1;
2001
                    ts->val_type = TEMP_VAL_DEAD;
2002
                }
2003
            }
2004
            break;
2005
        case INDEX_op_macro_goto:
2006
            macro_op_index = op_index; /* only used for exceptions */
2007
            op_index = args[0] - 1;
2008
            args = gen_opparam_buf + args[1];
2009
            goto next;
2010
        case INDEX_op_macro_end:
2011
            macro_op_index = -1; /* only used for exceptions */
2012
            op_index = args[0] - 1;
2013
            args = gen_opparam_buf + args[1];
2014
            goto next;
2015
        case INDEX_op_macro_start:
2016
            /* must never happen here */
2017
            tcg_abort();
2018
        case INDEX_op_set_label:
2019
            tcg_reg_alloc_bb_end(s, s->reserved_regs);
2020
            tcg_out_label(s, args[0], (long)s->code_ptr);
2021
            break;
2022
        case INDEX_op_call:
2023
            dead_iargs = s->op_dead_iargs[op_index];
2024
            args += tcg_reg_alloc_call(s, def, opc, args, dead_iargs);
2025
            goto next;
2026
        case INDEX_op_end:
2027
            goto the_end;
2028

    
2029
#ifdef CONFIG_DYNGEN_OP
2030
        case 0 ... INDEX_op_end - 1:
2031
            /* legacy dyngen ops */
2032
#ifdef CONFIG_PROFILER
2033
            s->old_op_count++;
2034
#endif
2035
            tcg_reg_alloc_bb_end(s, s->reserved_regs);
2036
            if (search_pc >= 0) {
2037
                s->code_ptr += def->copy_size;
2038
                args += def->nb_args;
2039
            } else {
2040
                args = dyngen_op(s, opc, args);
2041
            }
2042
            goto next;
2043
#endif
2044
        default:
2045
            /* Note: in order to speed up the code, it would be much
2046
               faster to have specialized register allocator functions for
2047
               some common argument patterns */
2048
            dead_iargs = s->op_dead_iargs[op_index];
2049
            tcg_reg_alloc_op(s, def, opc, args, dead_iargs);
2050
            break;
2051
        }
2052
        args += def->nb_args;
2053
    next: ;
2054
        if (search_pc >= 0 && search_pc < s->code_ptr - gen_code_buf) {
2055
            if (macro_op_index >= 0)
2056
                return macro_op_index;
2057
            else
2058
                return op_index;
2059
        }
2060
        op_index++;
2061
#ifndef NDEBUG
2062
        check_regs(s);
2063
#endif
2064
    }
2065
 the_end:
2066
    return -1;
2067
}
2068

    
2069
int dyngen_code(TCGContext *s, uint8_t *gen_code_buf)
2070
{
2071
#ifdef CONFIG_PROFILER
2072
    {
2073
        int n;
2074
        n = (gen_opc_ptr - gen_opc_buf);
2075
        s->op_count += n;
2076
        if (n > s->op_count_max)
2077
            s->op_count_max = n;
2078

    
2079
        s->temp_count += s->nb_temps;
2080
        if (s->nb_temps > s->temp_count_max)
2081
            s->temp_count_max = s->nb_temps;
2082
    }
2083
#endif
2084

    
2085
    tcg_gen_code_common(s, gen_code_buf, -1);
2086

    
2087
    /* flush instruction cache */
2088
    flush_icache_range((unsigned long)gen_code_buf, 
2089
                       (unsigned long)s->code_ptr);
2090
    return s->code_ptr -  gen_code_buf;
2091
}
2092

    
2093
/* Return the index of the micro operation such as the pc after is <
2094
   offset bytes from the start of the TB.  The contents of gen_code_buf must
2095
   not be changed, though writing the same values is ok.
2096
   Return -1 if not found. */
2097
int dyngen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, long offset)
2098
{
2099
    return tcg_gen_code_common(s, gen_code_buf, offset);
2100
}
2101

    
2102
#ifdef CONFIG_PROFILER
2103
void tcg_dump_info(FILE *f,
2104
                   int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
2105
{
2106
    TCGContext *s = &tcg_ctx;
2107
    int64_t tot;
2108

    
2109
    tot = s->interm_time + s->code_time;
2110
    cpu_fprintf(f, "JIT cycles          %" PRId64 " (%0.3f s at 2.4 GHz)\n",
2111
                tot, tot / 2.4e9);
2112
    cpu_fprintf(f, "translated TBs      %" PRId64 " (aborted=%" PRId64 " %0.1f%%)\n", 
2113
                s->tb_count, 
2114
                s->tb_count1 - s->tb_count,
2115
                s->tb_count1 ? (double)(s->tb_count1 - s->tb_count) / s->tb_count1 * 100.0 : 0);
2116
    cpu_fprintf(f, "avg ops/TB          %0.1f max=%d\n", 
2117
                s->tb_count ? (double)s->op_count / s->tb_count : 0, s->op_count_max);
2118
    cpu_fprintf(f, "old ops/total ops   %0.1f%%\n", 
2119
                s->op_count ? (double)s->old_op_count / s->op_count * 100.0 : 0);
2120
    cpu_fprintf(f, "deleted ops/TB      %0.2f\n",
2121
                s->tb_count ? 
2122
                (double)s->del_op_count / s->tb_count : 0);
2123
    cpu_fprintf(f, "avg temps/TB        %0.2f max=%d\n",
2124
                s->tb_count ? 
2125
                (double)s->temp_count / s->tb_count : 0,
2126
                s->temp_count_max);
2127
    
2128
    cpu_fprintf(f, "cycles/op           %0.1f\n", 
2129
                s->op_count ? (double)tot / s->op_count : 0);
2130
    cpu_fprintf(f, "cycles/in byte      %0.1f\n", 
2131
                s->code_in_len ? (double)tot / s->code_in_len : 0);
2132
    cpu_fprintf(f, "cycles/out byte     %0.1f\n", 
2133
                s->code_out_len ? (double)tot / s->code_out_len : 0);
2134
    if (tot == 0)
2135
        tot = 1;
2136
    cpu_fprintf(f, "  gen_interm time   %0.1f%%\n", 
2137
                (double)s->interm_time / tot * 100.0);
2138
    cpu_fprintf(f, "  gen_code time     %0.1f%%\n", 
2139
                (double)s->code_time / tot * 100.0);
2140
    cpu_fprintf(f, "liveness/code time  %0.1f%%\n", 
2141
                (double)s->la_time / (s->code_time ? s->code_time : 1) * 100.0);
2142
    cpu_fprintf(f, "cpu_restore count   %" PRId64 "\n",
2143
                s->restore_count);
2144
    cpu_fprintf(f, "  avg cycles        %0.1f\n",
2145
                s->restore_count ? (double)s->restore_time / s->restore_count : 0);
2146
    {
2147
        extern void dump_op_count(void);
2148
        dump_op_count();
2149
    }
2150
}
2151
#else
2152
void tcg_dump_info(FILE *f,
2153
                   int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
2154
{
2155
    cpu_fprintf(f, "[TCG profiler not compiled]\n");
2156
}
2157
#endif