Statistics
| Branch: | Revision:

root / tcg / tcg.c @ 8c11ad25

History | View | Annotate | Download (65.9 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 use liveness analysis (better code) */
26
#define USE_LIVENESS_ANALYSIS
27

    
28
#include "config.h"
29

    
30
#if !defined(CONFIG_DEBUG_TCG) && !defined(NDEBUG)
31
/* define it to suppress various consistency checks (faster) */
32
#define NDEBUG
33
#endif
34

    
35
#include <stdarg.h>
36
#include <stdlib.h>
37
#include <stdio.h>
38
#include <string.h>
39
#include <inttypes.h>
40
#ifdef _WIN32
41
#include <malloc.h>
42
#endif
43
#ifdef _AIX
44
#include <alloca.h>
45
#endif
46

    
47
#include "qemu-common.h"
48
#include "cache-utils.h"
49
#include "host-utils.h"
50
#include "qemu-timer.h"
51

    
52
/* Note: the long term plan is to reduce the dependancies on the QEMU
53
   CPU definitions. Currently they are used for qemu_ld/st
54
   instructions */
55
#define NO_CPU_IO_DEFS
56
#include "cpu.h"
57
#include "exec-all.h"
58

    
59
#include "tcg-op.h"
60
#include "elf.h"
61

    
62
#if defined(CONFIG_USE_GUEST_BASE) && !defined(TCG_TARGET_HAS_GUEST_BASE)
63
#error GUEST_BASE not supported on this host.
64
#endif
65

    
66
static void tcg_target_init(TCGContext *s);
67
static void tcg_target_qemu_prologue(TCGContext *s);
68
static void patch_reloc(uint8_t *code_ptr, int type, 
69
                        tcg_target_long value, tcg_target_long addend);
70

    
71
static TCGOpDef tcg_op_defs[] = {
72
#define DEF(s, oargs, iargs, cargs, flags) { #s, oargs, iargs, cargs, iargs + oargs + cargs, flags },
73
#include "tcg-opc.h"
74
#undef DEF
75
};
76

    
77
static TCGRegSet tcg_target_available_regs[2];
78
static TCGRegSet tcg_target_call_clobber_regs;
79

    
80
/* XXX: move that inside the context */
81
uint16_t *gen_opc_ptr;
82
TCGArg *gen_opparam_ptr;
83

    
84
static inline void tcg_out8(TCGContext *s, uint8_t v)
85
{
86
    *s->code_ptr++ = v;
87
}
88

    
89
static inline void tcg_out16(TCGContext *s, uint16_t v)
90
{
91
    *(uint16_t *)s->code_ptr = v;
92
    s->code_ptr += 2;
93
}
94

    
95
static inline void tcg_out32(TCGContext *s, uint32_t v)
96
{
97
    *(uint32_t *)s->code_ptr = v;
98
    s->code_ptr += 4;
99
}
100

    
101
/* label relocation processing */
102

    
103
static void tcg_out_reloc(TCGContext *s, uint8_t *code_ptr, int type,
104
                          int label_index, long addend)
105
{
106
    TCGLabel *l;
107
    TCGRelocation *r;
108

    
109
    l = &s->labels[label_index];
110
    if (l->has_value) {
111
        /* FIXME: This may break relocations on RISC targets that
112
           modify instruction fields in place.  The caller may not have 
113
           written the initial value.  */
114
        patch_reloc(code_ptr, type, l->u.value, addend);
115
    } else {
116
        /* add a new relocation entry */
117
        r = tcg_malloc(sizeof(TCGRelocation));
118
        r->type = type;
119
        r->ptr = code_ptr;
120
        r->addend = addend;
121
        r->next = l->u.first_reloc;
122
        l->u.first_reloc = r;
123
    }
124
}
125

    
126
static void tcg_out_label(TCGContext *s, int label_index, 
127
                          tcg_target_long value)
128
{
129
    TCGLabel *l;
130
    TCGRelocation *r;
131

    
132
    l = &s->labels[label_index];
133
    if (l->has_value)
134
        tcg_abort();
135
    r = l->u.first_reloc;
136
    while (r != NULL) {
137
        patch_reloc(r->ptr, r->type, value, r->addend);
138
        r = r->next;
139
    }
140
    l->has_value = 1;
141
    l->u.value = value;
142
}
143

    
144
int gen_new_label(void)
145
{
146
    TCGContext *s = &tcg_ctx;
147
    int idx;
148
    TCGLabel *l;
149

    
150
    if (s->nb_labels >= TCG_MAX_LABELS)
151
        tcg_abort();
152
    idx = s->nb_labels++;
153
    l = &s->labels[idx];
154
    l->has_value = 0;
155
    l->u.first_reloc = NULL;
156
    return idx;
157
}
158

    
159
#include "tcg-target.c"
160

    
161
/* pool based memory allocation */
162
void *tcg_malloc_internal(TCGContext *s, int size)
163
{
164
    TCGPool *p;
165
    int pool_size;
166
    
167
    if (size > TCG_POOL_CHUNK_SIZE) {
168
        /* big malloc: insert a new pool (XXX: could optimize) */
169
        p = qemu_malloc(sizeof(TCGPool) + size);
170
        p->size = size;
171
        if (s->pool_current)
172
            s->pool_current->next = p;
173
        else
174
            s->pool_first = p;
175
        p->next = s->pool_current;
176
    } else {
177
        p = s->pool_current;
178
        if (!p) {
179
            p = s->pool_first;
180
            if (!p)
181
                goto new_pool;
182
        } else {
183
            if (!p->next) {
184
            new_pool:
185
                pool_size = TCG_POOL_CHUNK_SIZE;
186
                p = qemu_malloc(sizeof(TCGPool) + pool_size);
187
                p->size = pool_size;
188
                p->next = NULL;
189
                if (s->pool_current) 
190
                    s->pool_current->next = p;
191
                else
192
                    s->pool_first = p;
193
            } else {
194
                p = p->next;
195
            }
196
        }
197
    }
198
    s->pool_current = p;
199
    s->pool_cur = p->data + size;
200
    s->pool_end = p->data + p->size;
201
    return p->data;
202
}
203

    
204
void tcg_pool_reset(TCGContext *s)
205
{
206
    s->pool_cur = s->pool_end = NULL;
207
    s->pool_current = NULL;
208
}
209

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

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

    
230
    args_ct = qemu_malloc(sizeof(TCGArgConstraint) * total_args);
231
    sorted_args = qemu_malloc(sizeof(int) * total_args);
232

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

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

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

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

    
274
    gen_opc_ptr = gen_opc_buf;
275
    gen_opparam_ptr = gen_opparam_buf;
276
}
277

    
278
static inline void tcg_temp_alloc(TCGContext *s, int n)
279
{
280
    if (n > TCG_MAX_TEMPS)
281
        tcg_abort();
282
}
283

    
284
static inline int tcg_global_reg_new_internal(TCGType type, int reg,
285
                                              const char *name)
286
{
287
    TCGContext *s = &tcg_ctx;
288
    TCGTemp *ts;
289
    int idx;
290

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

    
310
TCGv_i32 tcg_global_reg_new_i32(int reg, const char *name)
311
{
312
    int idx;
313

    
314
    idx = tcg_global_reg_new_internal(TCG_TYPE_I32, reg, name);
315
    return MAKE_TCGV_I32(idx);
316
}
317

    
318
TCGv_i64 tcg_global_reg_new_i64(int reg, const char *name)
319
{
320
    int idx;
321

    
322
    idx = tcg_global_reg_new_internal(TCG_TYPE_I64, reg, name);
323
    return MAKE_TCGV_I64(idx);
324
}
325

    
326
static inline int tcg_global_mem_new_internal(TCGType type, int reg,
327
                                              tcg_target_long offset,
328
                                              const char *name)
329
{
330
    TCGContext *s = &tcg_ctx;
331
    TCGTemp *ts;
332
    int idx;
333

    
334
    idx = s->nb_globals;
335
#if TCG_TARGET_REG_BITS == 32
336
    if (type == TCG_TYPE_I64) {
337
        char buf[64];
338
        tcg_temp_alloc(s, s->nb_globals + 2);
339
        ts = &s->temps[s->nb_globals];
340
        ts->base_type = type;
341
        ts->type = TCG_TYPE_I32;
342
        ts->fixed_reg = 0;
343
        ts->mem_allocated = 1;
344
        ts->mem_reg = reg;
345
#ifdef TCG_TARGET_WORDS_BIGENDIAN
346
        ts->mem_offset = offset + 4;
347
#else
348
        ts->mem_offset = offset;
349
#endif
350
        pstrcpy(buf, sizeof(buf), name);
351
        pstrcat(buf, sizeof(buf), "_0");
352
        ts->name = strdup(buf);
353
        ts++;
354

    
355
        ts->base_type = type;
356
        ts->type = TCG_TYPE_I32;
357
        ts->fixed_reg = 0;
358
        ts->mem_allocated = 1;
359
        ts->mem_reg = reg;
360
#ifdef TCG_TARGET_WORDS_BIGENDIAN
361
        ts->mem_offset = offset;
362
#else
363
        ts->mem_offset = offset + 4;
364
#endif
365
        pstrcpy(buf, sizeof(buf), name);
366
        pstrcat(buf, sizeof(buf), "_1");
367
        ts->name = strdup(buf);
368

    
369
        s->nb_globals += 2;
370
    } else
371
#endif
372
    {
373
        tcg_temp_alloc(s, s->nb_globals + 1);
374
        ts = &s->temps[s->nb_globals];
375
        ts->base_type = type;
376
        ts->type = type;
377
        ts->fixed_reg = 0;
378
        ts->mem_allocated = 1;
379
        ts->mem_reg = reg;
380
        ts->mem_offset = offset;
381
        ts->name = name;
382
        s->nb_globals++;
383
    }
384
    return idx;
385
}
386

    
387
TCGv_i32 tcg_global_mem_new_i32(int reg, tcg_target_long offset,
388
                                const char *name)
389
{
390
    int idx;
391

    
392
    idx = tcg_global_mem_new_internal(TCG_TYPE_I32, reg, offset, name);
393
    return MAKE_TCGV_I32(idx);
394
}
395

    
396
TCGv_i64 tcg_global_mem_new_i64(int reg, tcg_target_long offset,
397
                                const char *name)
398
{
399
    int idx;
400

    
401
    idx = tcg_global_mem_new_internal(TCG_TYPE_I64, reg, offset, name);
402
    return MAKE_TCGV_I64(idx);
403
}
404

    
405
static inline int tcg_temp_new_internal(TCGType type, int temp_local)
406
{
407
    TCGContext *s = &tcg_ctx;
408
    TCGTemp *ts;
409
    int idx, k;
410

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

    
454
#if defined(CONFIG_DEBUG_TCG)
455
    s->temps_in_use++;
456
#endif
457
    return idx;
458
}
459

    
460
TCGv_i32 tcg_temp_new_internal_i32(int temp_local)
461
{
462
    int idx;
463

    
464
    idx = tcg_temp_new_internal(TCG_TYPE_I32, temp_local);
465
    return MAKE_TCGV_I32(idx);
466
}
467

    
468
TCGv_i64 tcg_temp_new_internal_i64(int temp_local)
469
{
470
    int idx;
471

    
472
    idx = tcg_temp_new_internal(TCG_TYPE_I64, temp_local);
473
    return MAKE_TCGV_I64(idx);
474
}
475

    
476
static inline void tcg_temp_free_internal(int idx)
477
{
478
    TCGContext *s = &tcg_ctx;
479
    TCGTemp *ts;
480
    int k;
481

    
482
#if defined(CONFIG_DEBUG_TCG)
483
    s->temps_in_use--;
484
    if (s->temps_in_use < 0) {
485
        fprintf(stderr, "More temporaries freed than allocated!\n");
486
    }
487
#endif
488

    
489
    assert(idx >= s->nb_globals && idx < s->nb_temps);
490
    ts = &s->temps[idx];
491
    assert(ts->temp_allocated != 0);
492
    ts->temp_allocated = 0;
493
    k = ts->base_type;
494
    if (ts->temp_local)
495
        k += TCG_TYPE_COUNT;
496
    ts->next_free_temp = s->first_free_temp[k];
497
    s->first_free_temp[k] = idx;
498
}
499

    
500
void tcg_temp_free_i32(TCGv_i32 arg)
501
{
502
    tcg_temp_free_internal(GET_TCGV_I32(arg));
503
}
504

    
505
void tcg_temp_free_i64(TCGv_i64 arg)
506
{
507
    tcg_temp_free_internal(GET_TCGV_I64(arg));
508
}
509

    
510
TCGv_i32 tcg_const_i32(int32_t val)
511
{
512
    TCGv_i32 t0;
513
    t0 = tcg_temp_new_i32();
514
    tcg_gen_movi_i32(t0, val);
515
    return t0;
516
}
517

    
518
TCGv_i64 tcg_const_i64(int64_t val)
519
{
520
    TCGv_i64 t0;
521
    t0 = tcg_temp_new_i64();
522
    tcg_gen_movi_i64(t0, val);
523
    return t0;
524
}
525

    
526
TCGv_i32 tcg_const_local_i32(int32_t val)
527
{
528
    TCGv_i32 t0;
529
    t0 = tcg_temp_local_new_i32();
530
    tcg_gen_movi_i32(t0, val);
531
    return t0;
532
}
533

    
534
TCGv_i64 tcg_const_local_i64(int64_t val)
535
{
536
    TCGv_i64 t0;
537
    t0 = tcg_temp_local_new_i64();
538
    tcg_gen_movi_i64(t0, val);
539
    return t0;
540
}
541

    
542
#if defined(CONFIG_DEBUG_TCG)
543
void tcg_clear_temp_count(void)
544
{
545
    TCGContext *s = &tcg_ctx;
546
    s->temps_in_use = 0;
547
}
548

    
549
int tcg_check_temp_count(void)
550
{
551
    TCGContext *s = &tcg_ctx;
552
    if (s->temps_in_use) {
553
        /* Clear the count so that we don't give another
554
         * warning immediately next time around.
555
         */
556
        s->temps_in_use = 0;
557
        return 1;
558
    }
559
    return 0;
560
}
561
#endif
562

    
563
void tcg_register_helper(void *func, const char *name)
564
{
565
    TCGContext *s = &tcg_ctx;
566
    int n;
567
    if ((s->nb_helpers + 1) > s->allocated_helpers) {
568
        n = s->allocated_helpers;
569
        if (n == 0) {
570
            n = 4;
571
        } else {
572
            n *= 2;
573
        }
574
        s->helpers = realloc(s->helpers, n * sizeof(TCGHelperInfo));
575
        s->allocated_helpers = n;
576
    }
577
    s->helpers[s->nb_helpers].func = (tcg_target_ulong)func;
578
    s->helpers[s->nb_helpers].name = name;
579
    s->nb_helpers++;
580
}
581

    
582
/* Note: we convert the 64 bit args to 32 bit and do some alignment
583
   and endian swap. Maybe it would be better to do the alignment
584
   and endian swap in tcg_reg_alloc_call(). */
585
void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags,
586
                   int sizemask, TCGArg ret, int nargs, TCGArg *args)
587
{
588
#ifdef TCG_TARGET_I386
589
    int call_type;
590
#endif
591
    int i;
592
    int real_args;
593
    int nb_rets;
594
    TCGArg *nparam;
595

    
596
#if defined(TCG_TARGET_EXTEND_ARGS) && TCG_TARGET_REG_BITS == 64
597
    for (i = 0; i < nargs; ++i) {
598
        int is_64bit = sizemask & (1 << (i+1)*2);
599
        int is_signed = sizemask & (2 << (i+1)*2);
600
        if (!is_64bit) {
601
            TCGv_i64 temp = tcg_temp_new_i64();
602
            TCGv_i64 orig = MAKE_TCGV_I64(args[i]);
603
            if (is_signed) {
604
                tcg_gen_ext32s_i64(temp, orig);
605
            } else {
606
                tcg_gen_ext32u_i64(temp, orig);
607
            }
608
            args[i] = GET_TCGV_I64(temp);
609
        }
610
    }
611
#endif /* TCG_TARGET_EXTEND_ARGS */
612

    
613
    *gen_opc_ptr++ = INDEX_op_call;
614
    nparam = gen_opparam_ptr++;
615
#ifdef TCG_TARGET_I386
616
    call_type = (flags & TCG_CALL_TYPE_MASK);
617
#endif
618
    if (ret != TCG_CALL_DUMMY_ARG) {
619
#if TCG_TARGET_REG_BITS < 64
620
        if (sizemask & 1) {
621
#ifdef TCG_TARGET_WORDS_BIGENDIAN
622
            *gen_opparam_ptr++ = ret + 1;
623
            *gen_opparam_ptr++ = ret;
624
#else
625
            *gen_opparam_ptr++ = ret;
626
            *gen_opparam_ptr++ = ret + 1;
627
#endif
628
            nb_rets = 2;
629
        } else
630
#endif
631
        {
632
            *gen_opparam_ptr++ = ret;
633
            nb_rets = 1;
634
        }
635
    } else {
636
        nb_rets = 0;
637
    }
638
    real_args = 0;
639
    for (i = 0; i < nargs; i++) {
640
#if TCG_TARGET_REG_BITS < 64
641
        int is_64bit = sizemask & (1 << (i+1)*2);
642
        if (is_64bit) {
643
#ifdef TCG_TARGET_I386
644
            /* REGPARM case: if the third parameter is 64 bit, it is
645
               allocated on the stack */
646
            if (i == 2 && call_type == TCG_CALL_TYPE_REGPARM) {
647
                call_type = TCG_CALL_TYPE_REGPARM_2;
648
                flags = (flags & ~TCG_CALL_TYPE_MASK) | call_type;
649
            }
650
#endif
651
#ifdef TCG_TARGET_CALL_ALIGN_ARGS
652
            /* some targets want aligned 64 bit args */
653
            if (real_args & 1) {
654
                *gen_opparam_ptr++ = TCG_CALL_DUMMY_ARG;
655
                real_args++;
656
            }
657
#endif
658
            /* If stack grows up, then we will be placing successive
659
               arguments at lower addresses, which means we need to
660
               reverse the order compared to how we would normally
661
               treat either big or little-endian.  For those arguments
662
               that will wind up in registers, this still works for
663
               HPPA (the only current STACK_GROWSUP target) since the
664
               argument registers are *also* allocated in decreasing
665
               order.  If another such target is added, this logic may
666
               have to get more complicated to differentiate between
667
               stack arguments and register arguments.  */
668
#if defined(TCG_TARGET_WORDS_BIGENDIAN) != defined(TCG_TARGET_STACK_GROWSUP)
669
            *gen_opparam_ptr++ = args[i] + 1;
670
            *gen_opparam_ptr++ = args[i];
671
#else
672
            *gen_opparam_ptr++ = args[i];
673
            *gen_opparam_ptr++ = args[i] + 1;
674
#endif
675
            real_args += 2;
676
            continue;
677
        }
678
#endif /* TCG_TARGET_REG_BITS < 64 */
679

    
680
        *gen_opparam_ptr++ = args[i];
681
        real_args++;
682
    }
683
    *gen_opparam_ptr++ = GET_TCGV_PTR(func);
684

    
685
    *gen_opparam_ptr++ = flags;
686

    
687
    *nparam = (nb_rets << 16) | (real_args + 1);
688

    
689
    /* total parameters, needed to go backward in the instruction stream */
690
    *gen_opparam_ptr++ = 1 + nb_rets + real_args + 3;
691

    
692
#if defined(TCG_TARGET_EXTEND_ARGS) && TCG_TARGET_REG_BITS == 64
693
    for (i = 0; i < nargs; ++i) {
694
        int is_64bit = sizemask & (1 << (i+1)*2);
695
        if (!is_64bit) {
696
            TCGv_i64 temp = MAKE_TCGV_I64(args[i]);
697
            tcg_temp_free_i64(temp);
698
        }
699
    }
700
#endif /* TCG_TARGET_EXTEND_ARGS */
701
}
702

    
703
#if TCG_TARGET_REG_BITS == 32
704
void tcg_gen_shifti_i64(TCGv_i64 ret, TCGv_i64 arg1,
705
                        int c, int right, int arith)
706
{
707
    if (c == 0) {
708
        tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg1));
709
        tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
710
    } else if (c >= 32) {
711
        c -= 32;
712
        if (right) {
713
            if (arith) {
714
                tcg_gen_sari_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
715
                tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 31);
716
            } else {
717
                tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
718
                tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
719
            }
720
        } else {
721
            tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_LOW(arg1), c);
722
            tcg_gen_movi_i32(TCGV_LOW(ret), 0);
723
        }
724
    } else {
725
        TCGv_i32 t0, t1;
726

    
727
        t0 = tcg_temp_new_i32();
728
        t1 = tcg_temp_new_i32();
729
        if (right) {
730
            tcg_gen_shli_i32(t0, TCGV_HIGH(arg1), 32 - c);
731
            if (arith)
732
                tcg_gen_sari_i32(t1, TCGV_HIGH(arg1), c);
733
            else
734
                tcg_gen_shri_i32(t1, TCGV_HIGH(arg1), c);
735
            tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_LOW(arg1), c);
736
            tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(ret), t0);
737
            tcg_gen_mov_i32(TCGV_HIGH(ret), t1);
738
        } else {
739
            tcg_gen_shri_i32(t0, TCGV_LOW(arg1), 32 - c);
740
            /* Note: ret can be the same as arg1, so we use t1 */
741
            tcg_gen_shli_i32(t1, TCGV_LOW(arg1), c);
742
            tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c);
743
            tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t0);
744
            tcg_gen_mov_i32(TCGV_LOW(ret), t1);
745
        }
746
        tcg_temp_free_i32(t0);
747
        tcg_temp_free_i32(t1);
748
    }
749
}
750
#endif
751

    
752

    
753
static void tcg_reg_alloc_start(TCGContext *s)
754
{
755
    int i;
756
    TCGTemp *ts;
757
    for(i = 0; i < s->nb_globals; i++) {
758
        ts = &s->temps[i];
759
        if (ts->fixed_reg) {
760
            ts->val_type = TEMP_VAL_REG;
761
        } else {
762
            ts->val_type = TEMP_VAL_MEM;
763
        }
764
    }
765
    for(i = s->nb_globals; i < s->nb_temps; i++) {
766
        ts = &s->temps[i];
767
        ts->val_type = TEMP_VAL_DEAD;
768
        ts->mem_allocated = 0;
769
        ts->fixed_reg = 0;
770
    }
771
    for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
772
        s->reg_to_temp[i] = -1;
773
    }
774
}
775

    
776
static char *tcg_get_arg_str_idx(TCGContext *s, char *buf, int buf_size,
777
                                 int idx)
778
{
779
    TCGTemp *ts;
780

    
781
    ts = &s->temps[idx];
782
    if (idx < s->nb_globals) {
783
        pstrcpy(buf, buf_size, ts->name);
784
    } else {
785
        if (ts->temp_local) 
786
            snprintf(buf, buf_size, "loc%d", idx - s->nb_globals);
787
        else
788
            snprintf(buf, buf_size, "tmp%d", idx - s->nb_globals);
789
    }
790
    return buf;
791
}
792

    
793
char *tcg_get_arg_str_i32(TCGContext *s, char *buf, int buf_size, TCGv_i32 arg)
794
{
795
    return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I32(arg));
796
}
797

    
798
char *tcg_get_arg_str_i64(TCGContext *s, char *buf, int buf_size, TCGv_i64 arg)
799
{
800
    return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I64(arg));
801
}
802

    
803
static int helper_cmp(const void *p1, const void *p2)
804
{
805
    const TCGHelperInfo *th1 = p1;
806
    const TCGHelperInfo *th2 = p2;
807
    if (th1->func < th2->func)
808
        return -1;
809
    else if (th1->func == th2->func)
810
        return 0;
811
    else
812
        return 1;
813
}
814

    
815
/* find helper definition (Note: A hash table would be better) */
816
static TCGHelperInfo *tcg_find_helper(TCGContext *s, tcg_target_ulong val)
817
{
818
    int m, m_min, m_max;
819
    TCGHelperInfo *th;
820
    tcg_target_ulong v;
821

    
822
    if (unlikely(!s->helpers_sorted)) {
823
        qsort(s->helpers, s->nb_helpers, sizeof(TCGHelperInfo), 
824
              helper_cmp);
825
        s->helpers_sorted = 1;
826
    }
827

    
828
    /* binary search */
829
    m_min = 0;
830
    m_max = s->nb_helpers - 1;
831
    while (m_min <= m_max) {
832
        m = (m_min + m_max) >> 1;
833
        th = &s->helpers[m];
834
        v = th->func;
835
        if (v == val)
836
            return th;
837
        else if (val < v) {
838
            m_max = m - 1;
839
        } else {
840
            m_min = m + 1;
841
        }
842
    }
843
    return NULL;
844
}
845

    
846
static const char * const cond_name[] =
847
{
848
    [TCG_COND_EQ] = "eq",
849
    [TCG_COND_NE] = "ne",
850
    [TCG_COND_LT] = "lt",
851
    [TCG_COND_GE] = "ge",
852
    [TCG_COND_LE] = "le",
853
    [TCG_COND_GT] = "gt",
854
    [TCG_COND_LTU] = "ltu",
855
    [TCG_COND_GEU] = "geu",
856
    [TCG_COND_LEU] = "leu",
857
    [TCG_COND_GTU] = "gtu"
858
};
859

    
860
void tcg_dump_ops(TCGContext *s, FILE *outfile)
861
{
862
    const uint16_t *opc_ptr;
863
    const TCGArg *args;
864
    TCGArg arg;
865
    TCGOpcode c;
866
    int i, k, nb_oargs, nb_iargs, nb_cargs, first_insn;
867
    const TCGOpDef *def;
868
    char buf[128];
869

    
870
    first_insn = 1;
871
    opc_ptr = gen_opc_buf;
872
    args = gen_opparam_buf;
873
    while (opc_ptr < gen_opc_ptr) {
874
        c = *opc_ptr++;
875
        def = &tcg_op_defs[c];
876
        if (c == INDEX_op_debug_insn_start) {
877
            uint64_t pc;
878
#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
879
            pc = ((uint64_t)args[1] << 32) | args[0];
880
#else
881
            pc = args[0];
882
#endif
883
            if (!first_insn) 
884
                fprintf(outfile, "\n");
885
            fprintf(outfile, " ---- 0x%" PRIx64, pc);
886
            first_insn = 0;
887
            nb_oargs = def->nb_oargs;
888
            nb_iargs = def->nb_iargs;
889
            nb_cargs = def->nb_cargs;
890
        } else if (c == INDEX_op_call) {
891
            TCGArg arg;
892

    
893
            /* variable number of arguments */
894
            arg = *args++;
895
            nb_oargs = arg >> 16;
896
            nb_iargs = arg & 0xffff;
897
            nb_cargs = def->nb_cargs;
898

    
899
            fprintf(outfile, " %s ", def->name);
900

    
901
            /* function name */
902
            fprintf(outfile, "%s",
903
                    tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + nb_iargs - 1]));
904
            /* flags */
905
            fprintf(outfile, ",$0x%" TCG_PRIlx,
906
                    args[nb_oargs + nb_iargs]);
907
            /* nb out args */
908
            fprintf(outfile, ",$%d", nb_oargs);
909
            for(i = 0; i < nb_oargs; i++) {
910
                fprintf(outfile, ",");
911
                fprintf(outfile, "%s",
912
                        tcg_get_arg_str_idx(s, buf, sizeof(buf), args[i]));
913
            }
914
            for(i = 0; i < (nb_iargs - 1); i++) {
915
                fprintf(outfile, ",");
916
                if (args[nb_oargs + i] == TCG_CALL_DUMMY_ARG) {
917
                    fprintf(outfile, "<dummy>");
918
                } else {
919
                    fprintf(outfile, "%s",
920
                            tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + i]));
921
                }
922
            }
923
        } else if (c == INDEX_op_movi_i32 
924
#if TCG_TARGET_REG_BITS == 64
925
                   || c == INDEX_op_movi_i64
926
#endif
927
                   ) {
928
            tcg_target_ulong val;
929
            TCGHelperInfo *th;
930

    
931
            nb_oargs = def->nb_oargs;
932
            nb_iargs = def->nb_iargs;
933
            nb_cargs = def->nb_cargs;
934
            fprintf(outfile, " %s %s,$", def->name, 
935
                    tcg_get_arg_str_idx(s, buf, sizeof(buf), args[0]));
936
            val = args[1];
937
            th = tcg_find_helper(s, val);
938
            if (th) {
939
                fprintf(outfile, "%s", th->name);
940
            } else {
941
                if (c == INDEX_op_movi_i32)
942
                    fprintf(outfile, "0x%x", (uint32_t)val);
943
                else
944
                    fprintf(outfile, "0x%" PRIx64 , (uint64_t)val);
945
            }
946
        } else {
947
            fprintf(outfile, " %s ", def->name);
948
            if (c == INDEX_op_nopn) {
949
                /* variable number of arguments */
950
                nb_cargs = *args;
951
                nb_oargs = 0;
952
                nb_iargs = 0;
953
            } else {
954
                nb_oargs = def->nb_oargs;
955
                nb_iargs = def->nb_iargs;
956
                nb_cargs = def->nb_cargs;
957
            }
958
            
959
            k = 0;
960
            for(i = 0; i < nb_oargs; i++) {
961
                if (k != 0)
962
                    fprintf(outfile, ",");
963
                fprintf(outfile, "%s",
964
                        tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
965
            }
966
            for(i = 0; i < nb_iargs; i++) {
967
                if (k != 0)
968
                    fprintf(outfile, ",");
969
                fprintf(outfile, "%s",
970
                        tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
971
            }
972
            switch (c) {
973
            case INDEX_op_brcond_i32:
974
#if TCG_TARGET_REG_BITS == 32
975
            case INDEX_op_brcond2_i32:
976
#elif TCG_TARGET_REG_BITS == 64
977
            case INDEX_op_brcond_i64:
978
#endif
979
            case INDEX_op_setcond_i32:
980
#if TCG_TARGET_REG_BITS == 32
981
            case INDEX_op_setcond2_i32:
982
#elif TCG_TARGET_REG_BITS == 64
983
            case INDEX_op_setcond_i64:
984
#endif
985
                if (args[k] < ARRAY_SIZE(cond_name) && cond_name[args[k]])
986
                    fprintf(outfile, ",%s", cond_name[args[k++]]);
987
                else
988
                    fprintf(outfile, ",$0x%" TCG_PRIlx, args[k++]);
989
                i = 1;
990
                break;
991
            default:
992
                i = 0;
993
                break;
994
            }
995
            for(; i < nb_cargs; i++) {
996
                if (k != 0)
997
                    fprintf(outfile, ",");
998
                arg = args[k++];
999
                fprintf(outfile, "$0x%" TCG_PRIlx, arg);
1000
            }
1001
        }
1002
        fprintf(outfile, "\n");
1003
        args += nb_iargs + nb_oargs + nb_cargs;
1004
    }
1005
}
1006

    
1007
/* we give more priority to constraints with less registers */
1008
static int get_constraint_priority(const TCGOpDef *def, int k)
1009
{
1010
    const TCGArgConstraint *arg_ct;
1011

    
1012
    int i, n;
1013
    arg_ct = &def->args_ct[k];
1014
    if (arg_ct->ct & TCG_CT_ALIAS) {
1015
        /* an alias is equivalent to a single register */
1016
        n = 1;
1017
    } else {
1018
        if (!(arg_ct->ct & TCG_CT_REG))
1019
            return 0;
1020
        n = 0;
1021
        for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
1022
            if (tcg_regset_test_reg(arg_ct->u.regs, i))
1023
                n++;
1024
        }
1025
    }
1026
    return TCG_TARGET_NB_REGS - n + 1;
1027
}
1028

    
1029
/* sort from highest priority to lowest */
1030
static void sort_constraints(TCGOpDef *def, int start, int n)
1031
{
1032
    int i, j, p1, p2, tmp;
1033

    
1034
    for(i = 0; i < n; i++)
1035
        def->sorted_args[start + i] = start + i;
1036
    if (n <= 1)
1037
        return;
1038
    for(i = 0; i < n - 1; i++) {
1039
        for(j = i + 1; j < n; j++) {
1040
            p1 = get_constraint_priority(def, def->sorted_args[start + i]);
1041
            p2 = get_constraint_priority(def, def->sorted_args[start + j]);
1042
            if (p1 < p2) {
1043
                tmp = def->sorted_args[start + i];
1044
                def->sorted_args[start + i] = def->sorted_args[start + j];
1045
                def->sorted_args[start + j] = tmp;
1046
            }
1047
        }
1048
    }
1049
}
1050

    
1051
void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs)
1052
{
1053
    TCGOpcode op;
1054
    TCGOpDef *def;
1055
    const char *ct_str;
1056
    int i, nb_args;
1057

    
1058
    for(;;) {
1059
        if (tdefs->op == (TCGOpcode)-1)
1060
            break;
1061
        op = tdefs->op;
1062
        assert((unsigned)op < NB_OPS);
1063
        def = &tcg_op_defs[op];
1064
#if defined(CONFIG_DEBUG_TCG)
1065
        /* Duplicate entry in op definitions? */
1066
        assert(!def->used);
1067
        def->used = 1;
1068
#endif
1069
        nb_args = def->nb_iargs + def->nb_oargs;
1070
        for(i = 0; i < nb_args; i++) {
1071
            ct_str = tdefs->args_ct_str[i];
1072
            /* Incomplete TCGTargetOpDef entry? */
1073
            assert(ct_str != NULL);
1074
            tcg_regset_clear(def->args_ct[i].u.regs);
1075
            def->args_ct[i].ct = 0;
1076
            if (ct_str[0] >= '0' && ct_str[0] <= '9') {
1077
                int oarg;
1078
                oarg = ct_str[0] - '0';
1079
                assert(oarg < def->nb_oargs);
1080
                assert(def->args_ct[oarg].ct & TCG_CT_REG);
1081
                /* TCG_CT_ALIAS is for the output arguments. The input
1082
                   argument is tagged with TCG_CT_IALIAS. */
1083
                def->args_ct[i] = def->args_ct[oarg];
1084
                def->args_ct[oarg].ct = TCG_CT_ALIAS;
1085
                def->args_ct[oarg].alias_index = i;
1086
                def->args_ct[i].ct |= TCG_CT_IALIAS;
1087
                def->args_ct[i].alias_index = oarg;
1088
            } else {
1089
                for(;;) {
1090
                    if (*ct_str == '\0')
1091
                        break;
1092
                    switch(*ct_str) {
1093
                    case 'i':
1094
                        def->args_ct[i].ct |= TCG_CT_CONST;
1095
                        ct_str++;
1096
                        break;
1097
                    default:
1098
                        if (target_parse_constraint(&def->args_ct[i], &ct_str) < 0) {
1099
                            fprintf(stderr, "Invalid constraint '%s' for arg %d of operation '%s'\n",
1100
                                    ct_str, i, def->name);
1101
                            exit(1);
1102
                        }
1103
                    }
1104
                }
1105
            }
1106
        }
1107

    
1108
        /* TCGTargetOpDef entry with too much information? */
1109
        assert(i == TCG_MAX_OP_ARGS || tdefs->args_ct_str[i] == NULL);
1110

    
1111
        /* sort the constraints (XXX: this is just an heuristic) */
1112
        sort_constraints(def, 0, def->nb_oargs);
1113
        sort_constraints(def, def->nb_oargs, def->nb_iargs);
1114

    
1115
#if 0
1116
        {
1117
            int i;
1118

1119
            printf("%s: sorted=", def->name);
1120
            for(i = 0; i < def->nb_oargs + def->nb_iargs; i++)
1121
                printf(" %d", def->sorted_args[i]);
1122
            printf("\n");
1123
        }
1124
#endif
1125
        tdefs++;
1126
    }
1127

    
1128
#if defined(CONFIG_DEBUG_TCG)
1129
    i = 0;
1130
    for (op = 0; op < ARRAY_SIZE(tcg_op_defs); op++) {
1131
        if (op < INDEX_op_call || op == INDEX_op_debug_insn_start) {
1132
            /* Wrong entry in op definitions? */
1133
            if (tcg_op_defs[op].used) {
1134
                fprintf(stderr, "Invalid op definition for %s\n",
1135
                        tcg_op_defs[op].name);
1136
                i = 1;
1137
            }
1138
        } else {
1139
            /* Missing entry in op definitions? */
1140
            if (!tcg_op_defs[op].used) {
1141
                fprintf(stderr, "Missing op definition for %s\n",
1142
                        tcg_op_defs[op].name);
1143
                i = 1;
1144
            }
1145
        }
1146
    }
1147
    if (i == 1) {
1148
        tcg_abort();
1149
    }
1150
#endif
1151
}
1152

    
1153
#ifdef USE_LIVENESS_ANALYSIS
1154

    
1155
/* set a nop for an operation using 'nb_args' */
1156
static inline void tcg_set_nop(TCGContext *s, uint16_t *opc_ptr, 
1157
                               TCGArg *args, int nb_args)
1158
{
1159
    if (nb_args == 0) {
1160
        *opc_ptr = INDEX_op_nop;
1161
    } else {
1162
        *opc_ptr = INDEX_op_nopn;
1163
        args[0] = nb_args;
1164
        args[nb_args - 1] = nb_args;
1165
    }
1166
}
1167

    
1168
/* liveness analysis: end of function: globals are live, temps are
1169
   dead. */
1170
/* XXX: at this stage, not used as there would be little gains because
1171
   most TBs end with a conditional jump. */
1172
static inline void tcg_la_func_end(TCGContext *s, uint8_t *dead_temps)
1173
{
1174
    memset(dead_temps, 0, s->nb_globals);
1175
    memset(dead_temps + s->nb_globals, 1, s->nb_temps - s->nb_globals);
1176
}
1177

    
1178
/* liveness analysis: end of basic block: globals are live, temps are
1179
   dead, local temps are live. */
1180
static inline void tcg_la_bb_end(TCGContext *s, uint8_t *dead_temps)
1181
{
1182
    int i;
1183
    TCGTemp *ts;
1184

    
1185
    memset(dead_temps, 0, s->nb_globals);
1186
    ts = &s->temps[s->nb_globals];
1187
    for(i = s->nb_globals; i < s->nb_temps; i++) {
1188
        if (ts->temp_local)
1189
            dead_temps[i] = 0;
1190
        else
1191
            dead_temps[i] = 1;
1192
        ts++;
1193
    }
1194
}
1195

    
1196
/* Liveness analysis : update the opc_dead_args array to tell if a
1197
   given input arguments is dead. Instructions updating dead
1198
   temporaries are removed. */
1199
static void tcg_liveness_analysis(TCGContext *s)
1200
{
1201
    int i, op_index, nb_args, nb_iargs, nb_oargs, arg, nb_ops;
1202
    TCGOpcode op;
1203
    TCGArg *args;
1204
    const TCGOpDef *def;
1205
    uint8_t *dead_temps;
1206
    unsigned int dead_args;
1207
    
1208
    gen_opc_ptr++; /* skip end */
1209

    
1210
    nb_ops = gen_opc_ptr - gen_opc_buf;
1211

    
1212
    s->op_dead_args = tcg_malloc(nb_ops * sizeof(uint16_t));
1213
    
1214
    dead_temps = tcg_malloc(s->nb_temps);
1215
    memset(dead_temps, 1, s->nb_temps);
1216

    
1217
    args = gen_opparam_ptr;
1218
    op_index = nb_ops - 1;
1219
    while (op_index >= 0) {
1220
        op = gen_opc_buf[op_index];
1221
        def = &tcg_op_defs[op];
1222
        switch(op) {
1223
        case INDEX_op_call:
1224
            {
1225
                int call_flags;
1226

    
1227
                nb_args = args[-1];
1228
                args -= nb_args;
1229
                nb_iargs = args[0] & 0xffff;
1230
                nb_oargs = args[0] >> 16;
1231
                args++;
1232
                call_flags = args[nb_oargs + nb_iargs];
1233

    
1234
                /* pure functions can be removed if their result is not
1235
                   used */
1236
                if (call_flags & TCG_CALL_PURE) {
1237
                    for(i = 0; i < nb_oargs; i++) {
1238
                        arg = args[i];
1239
                        if (!dead_temps[arg])
1240
                            goto do_not_remove_call;
1241
                    }
1242
                    tcg_set_nop(s, gen_opc_buf + op_index, 
1243
                                args - 1, nb_args);
1244
                } else {
1245
                do_not_remove_call:
1246

    
1247
                    /* output args are dead */
1248
                    dead_args = 0;
1249
                    for(i = 0; i < nb_oargs; i++) {
1250
                        arg = args[i];
1251
                        if (dead_temps[arg]) {
1252
                            dead_args |= (1 << i);
1253
                        }
1254
                        dead_temps[arg] = 1;
1255
                    }
1256
                    
1257
                    if (!(call_flags & TCG_CALL_CONST)) {
1258
                        /* globals are live (they may be used by the call) */
1259
                        memset(dead_temps, 0, s->nb_globals);
1260
                    }
1261

    
1262
                    /* input args are live */
1263
                    for(i = nb_oargs; i < nb_iargs + nb_oargs; i++) {
1264
                        arg = args[i];
1265
                        if (arg != TCG_CALL_DUMMY_ARG) {
1266
                            if (dead_temps[arg]) {
1267
                                dead_args |= (1 << i);
1268
                            }
1269
                            dead_temps[arg] = 0;
1270
                        }
1271
                    }
1272
                    s->op_dead_args[op_index] = dead_args;
1273
                }
1274
                args--;
1275
            }
1276
            break;
1277
        case INDEX_op_set_label:
1278
            args--;
1279
            /* mark end of basic block */
1280
            tcg_la_bb_end(s, dead_temps);
1281
            break;
1282
        case INDEX_op_debug_insn_start:
1283
            args -= def->nb_args;
1284
            break;
1285
        case INDEX_op_nopn:
1286
            nb_args = args[-1];
1287
            args -= nb_args;
1288
            break;
1289
        case INDEX_op_discard:
1290
            args--;
1291
            /* mark the temporary as dead */
1292
            dead_temps[args[0]] = 1;
1293
            break;
1294
        case INDEX_op_end:
1295
            break;
1296
            /* XXX: optimize by hardcoding common cases (e.g. triadic ops) */
1297
        default:
1298
            args -= def->nb_args;
1299
            nb_iargs = def->nb_iargs;
1300
            nb_oargs = def->nb_oargs;
1301

    
1302
            /* Test if the operation can be removed because all
1303
               its outputs are dead. We assume that nb_oargs == 0
1304
               implies side effects */
1305
            if (!(def->flags & TCG_OPF_SIDE_EFFECTS) && nb_oargs != 0) {
1306
                for(i = 0; i < nb_oargs; i++) {
1307
                    arg = args[i];
1308
                    if (!dead_temps[arg])
1309
                        goto do_not_remove;
1310
                }
1311
                tcg_set_nop(s, gen_opc_buf + op_index, args, def->nb_args);
1312
#ifdef CONFIG_PROFILER
1313
                s->del_op_count++;
1314
#endif
1315
            } else {
1316
            do_not_remove:
1317

    
1318
                /* output args are dead */
1319
                dead_args = 0;
1320
                for(i = 0; i < nb_oargs; i++) {
1321
                    arg = args[i];
1322
                    if (dead_temps[arg]) {
1323
                        dead_args |= (1 << i);
1324
                    }
1325
                    dead_temps[arg] = 1;
1326
                }
1327

    
1328
                /* if end of basic block, update */
1329
                if (def->flags & TCG_OPF_BB_END) {
1330
                    tcg_la_bb_end(s, dead_temps);
1331
                } else if (def->flags & TCG_OPF_CALL_CLOBBER) {
1332
                    /* globals are live */
1333
                    memset(dead_temps, 0, s->nb_globals);
1334
                }
1335

    
1336
                /* input args are live */
1337
                for(i = nb_oargs; i < nb_oargs + nb_iargs; i++) {
1338
                    arg = args[i];
1339
                    if (dead_temps[arg]) {
1340
                        dead_args |= (1 << i);
1341
                    }
1342
                    dead_temps[arg] = 0;
1343
                }
1344
                s->op_dead_args[op_index] = dead_args;
1345
            }
1346
            break;
1347
        }
1348
        op_index--;
1349
    }
1350

    
1351
    if (args != gen_opparam_buf)
1352
        tcg_abort();
1353
}
1354
#else
1355
/* dummy liveness analysis */
1356
static void tcg_liveness_analysis(TCGContext *s)
1357
{
1358
    int nb_ops;
1359
    nb_ops = gen_opc_ptr - gen_opc_buf;
1360

    
1361
    s->op_dead_args = tcg_malloc(nb_ops * sizeof(uint16_t));
1362
    memset(s->op_dead_args, 0, nb_ops * sizeof(uint16_t));
1363
}
1364
#endif
1365

    
1366
#ifndef NDEBUG
1367
static void dump_regs(TCGContext *s)
1368
{
1369
    TCGTemp *ts;
1370
    int i;
1371
    char buf[64];
1372

    
1373
    for(i = 0; i < s->nb_temps; i++) {
1374
        ts = &s->temps[i];
1375
        printf("  %10s: ", tcg_get_arg_str_idx(s, buf, sizeof(buf), i));
1376
        switch(ts->val_type) {
1377
        case TEMP_VAL_REG:
1378
            printf("%s", tcg_target_reg_names[ts->reg]);
1379
            break;
1380
        case TEMP_VAL_MEM:
1381
            printf("%d(%s)", (int)ts->mem_offset, tcg_target_reg_names[ts->mem_reg]);
1382
            break;
1383
        case TEMP_VAL_CONST:
1384
            printf("$0x%" TCG_PRIlx, ts->val);
1385
            break;
1386
        case TEMP_VAL_DEAD:
1387
            printf("D");
1388
            break;
1389
        default:
1390
            printf("???");
1391
            break;
1392
        }
1393
        printf("\n");
1394
    }
1395

    
1396
    for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
1397
        if (s->reg_to_temp[i] >= 0) {
1398
            printf("%s: %s\n", 
1399
                   tcg_target_reg_names[i], 
1400
                   tcg_get_arg_str_idx(s, buf, sizeof(buf), s->reg_to_temp[i]));
1401
        }
1402
    }
1403
}
1404

    
1405
static void check_regs(TCGContext *s)
1406
{
1407
    int reg, k;
1408
    TCGTemp *ts;
1409
    char buf[64];
1410

    
1411
    for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1412
        k = s->reg_to_temp[reg];
1413
        if (k >= 0) {
1414
            ts = &s->temps[k];
1415
            if (ts->val_type != TEMP_VAL_REG ||
1416
                ts->reg != reg) {
1417
                printf("Inconsistency for register %s:\n", 
1418
                       tcg_target_reg_names[reg]);
1419
                goto fail;
1420
            }
1421
        }
1422
    }
1423
    for(k = 0; k < s->nb_temps; k++) {
1424
        ts = &s->temps[k];
1425
        if (ts->val_type == TEMP_VAL_REG &&
1426
            !ts->fixed_reg &&
1427
            s->reg_to_temp[ts->reg] != k) {
1428
                printf("Inconsistency for temp %s:\n", 
1429
                       tcg_get_arg_str_idx(s, buf, sizeof(buf), k));
1430
        fail:
1431
                printf("reg state:\n");
1432
                dump_regs(s);
1433
                tcg_abort();
1434
        }
1435
    }
1436
}
1437
#endif
1438

    
1439
static void temp_allocate_frame(TCGContext *s, int temp)
1440
{
1441
    TCGTemp *ts;
1442
    ts = &s->temps[temp];
1443
    s->current_frame_offset = (s->current_frame_offset + sizeof(tcg_target_long) - 1) & ~(sizeof(tcg_target_long) - 1);
1444
    if (s->current_frame_offset + sizeof(tcg_target_long) > s->frame_end)
1445
        tcg_abort();
1446
    ts->mem_offset = s->current_frame_offset;
1447
    ts->mem_reg = s->frame_reg;
1448
    ts->mem_allocated = 1;
1449
    s->current_frame_offset += sizeof(tcg_target_long);
1450
}
1451

    
1452
/* free register 'reg' by spilling the corresponding temporary if necessary */
1453
static void tcg_reg_free(TCGContext *s, int reg)
1454
{
1455
    TCGTemp *ts;
1456
    int temp;
1457

    
1458
    temp = s->reg_to_temp[reg];
1459
    if (temp != -1) {
1460
        ts = &s->temps[temp];
1461
        assert(ts->val_type == TEMP_VAL_REG);
1462
        if (!ts->mem_coherent) {
1463
            if (!ts->mem_allocated) 
1464
                temp_allocate_frame(s, temp);
1465
            tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1466
        }
1467
        ts->val_type = TEMP_VAL_MEM;
1468
        s->reg_to_temp[reg] = -1;
1469
    }
1470
}
1471

    
1472
/* Allocate a register belonging to reg1 & ~reg2 */
1473
static int tcg_reg_alloc(TCGContext *s, TCGRegSet reg1, TCGRegSet reg2)
1474
{
1475
    int i, reg;
1476
    TCGRegSet reg_ct;
1477

    
1478
    tcg_regset_andnot(reg_ct, reg1, reg2);
1479

    
1480
    /* first try free registers */
1481
    for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1482
        reg = tcg_target_reg_alloc_order[i];
1483
        if (tcg_regset_test_reg(reg_ct, reg) && s->reg_to_temp[reg] == -1)
1484
            return reg;
1485
    }
1486

    
1487
    /* XXX: do better spill choice */
1488
    for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1489
        reg = tcg_target_reg_alloc_order[i];
1490
        if (tcg_regset_test_reg(reg_ct, reg)) {
1491
            tcg_reg_free(s, reg);
1492
            return reg;
1493
        }
1494
    }
1495

    
1496
    tcg_abort();
1497
}
1498

    
1499
/* save a temporary to memory. 'allocated_regs' is used in case a
1500
   temporary registers needs to be allocated to store a constant. */
1501
static void temp_save(TCGContext *s, int temp, TCGRegSet allocated_regs)
1502
{
1503
    TCGTemp *ts;
1504
    int reg;
1505

    
1506
    ts = &s->temps[temp];
1507
    if (!ts->fixed_reg) {
1508
        switch(ts->val_type) {
1509
        case TEMP_VAL_REG:
1510
            tcg_reg_free(s, ts->reg);
1511
            break;
1512
        case TEMP_VAL_DEAD:
1513
            ts->val_type = TEMP_VAL_MEM;
1514
            break;
1515
        case TEMP_VAL_CONST:
1516
            reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], 
1517
                                allocated_regs);
1518
            if (!ts->mem_allocated) 
1519
                temp_allocate_frame(s, temp);
1520
            tcg_out_movi(s, ts->type, reg, ts->val);
1521
            tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1522
            ts->val_type = TEMP_VAL_MEM;
1523
            break;
1524
        case TEMP_VAL_MEM:
1525
            break;
1526
        default:
1527
            tcg_abort();
1528
        }
1529
    }
1530
}
1531

    
1532
/* save globals to their cannonical location and assume they can be
1533
   modified be the following code. 'allocated_regs' is used in case a
1534
   temporary registers needs to be allocated to store a constant. */
1535
static void save_globals(TCGContext *s, TCGRegSet allocated_regs)
1536
{
1537
    int i;
1538

    
1539
    for(i = 0; i < s->nb_globals; i++) {
1540
        temp_save(s, i, allocated_regs);
1541
    }
1542
}
1543

    
1544
/* at the end of a basic block, we assume all temporaries are dead and
1545
   all globals are stored at their canonical location. */
1546
static void tcg_reg_alloc_bb_end(TCGContext *s, TCGRegSet allocated_regs)
1547
{
1548
    TCGTemp *ts;
1549
    int i;
1550

    
1551
    for(i = s->nb_globals; i < s->nb_temps; i++) {
1552
        ts = &s->temps[i];
1553
        if (ts->temp_local) {
1554
            temp_save(s, i, allocated_regs);
1555
        } else {
1556
            if (ts->val_type == TEMP_VAL_REG) {
1557
                s->reg_to_temp[ts->reg] = -1;
1558
            }
1559
            ts->val_type = TEMP_VAL_DEAD;
1560
        }
1561
    }
1562

    
1563
    save_globals(s, allocated_regs);
1564
}
1565

    
1566
#define IS_DEAD_ARG(n) ((dead_args >> (n)) & 1)
1567

    
1568
static void tcg_reg_alloc_movi(TCGContext *s, const TCGArg *args)
1569
{
1570
    TCGTemp *ots;
1571
    tcg_target_ulong val;
1572

    
1573
    ots = &s->temps[args[0]];
1574
    val = args[1];
1575

    
1576
    if (ots->fixed_reg) {
1577
        /* for fixed registers, we do not do any constant
1578
           propagation */
1579
        tcg_out_movi(s, ots->type, ots->reg, val);
1580
    } else {
1581
        /* The movi is not explicitly generated here */
1582
        if (ots->val_type == TEMP_VAL_REG)
1583
            s->reg_to_temp[ots->reg] = -1;
1584
        ots->val_type = TEMP_VAL_CONST;
1585
        ots->val = val;
1586
    }
1587
}
1588

    
1589
static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
1590
                              const TCGArg *args,
1591
                              unsigned int dead_args)
1592
{
1593
    TCGTemp *ts, *ots;
1594
    int reg;
1595
    const TCGArgConstraint *arg_ct;
1596

    
1597
    ots = &s->temps[args[0]];
1598
    ts = &s->temps[args[1]];
1599
    arg_ct = &def->args_ct[0];
1600

    
1601
    /* XXX: always mark arg dead if IS_DEAD_ARG(1) */
1602
    if (ts->val_type == TEMP_VAL_REG) {
1603
        if (IS_DEAD_ARG(1) && !ts->fixed_reg && !ots->fixed_reg) {
1604
            /* the mov can be suppressed */
1605
            if (ots->val_type == TEMP_VAL_REG)
1606
                s->reg_to_temp[ots->reg] = -1;
1607
            reg = ts->reg;
1608
            s->reg_to_temp[reg] = -1;
1609
            ts->val_type = TEMP_VAL_DEAD;
1610
        } else {
1611
            if (ots->val_type == TEMP_VAL_REG) {
1612
                reg = ots->reg;
1613
            } else {
1614
                reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1615
            }
1616
            if (ts->reg != reg) {
1617
                tcg_out_mov(s, ots->type, reg, ts->reg);
1618
            }
1619
        }
1620
    } else if (ts->val_type == TEMP_VAL_MEM) {
1621
        if (ots->val_type == TEMP_VAL_REG) {
1622
            reg = ots->reg;
1623
        } else {
1624
            reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1625
        }
1626
        tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1627
    } else if (ts->val_type == TEMP_VAL_CONST) {
1628
        if (ots->fixed_reg) {
1629
            reg = ots->reg;
1630
            tcg_out_movi(s, ots->type, reg, ts->val);
1631
        } else {
1632
            /* propagate constant */
1633
            if (ots->val_type == TEMP_VAL_REG)
1634
                s->reg_to_temp[ots->reg] = -1;
1635
            ots->val_type = TEMP_VAL_CONST;
1636
            ots->val = ts->val;
1637
            return;
1638
        }
1639
    } else {
1640
        tcg_abort();
1641
    }
1642
    s->reg_to_temp[reg] = args[0];
1643
    ots->reg = reg;
1644
    ots->val_type = TEMP_VAL_REG;
1645
    ots->mem_coherent = 0;
1646
}
1647

    
1648
static void tcg_reg_alloc_op(TCGContext *s, 
1649
                             const TCGOpDef *def, TCGOpcode opc,
1650
                             const TCGArg *args,
1651
                             unsigned int dead_args)
1652
{
1653
    TCGRegSet allocated_regs;
1654
    int i, k, nb_iargs, nb_oargs, reg;
1655
    TCGArg arg;
1656
    const TCGArgConstraint *arg_ct;
1657
    TCGTemp *ts;
1658
    TCGArg new_args[TCG_MAX_OP_ARGS];
1659
    int const_args[TCG_MAX_OP_ARGS];
1660

    
1661
    nb_oargs = def->nb_oargs;
1662
    nb_iargs = def->nb_iargs;
1663

    
1664
    /* copy constants */
1665
    memcpy(new_args + nb_oargs + nb_iargs, 
1666
           args + nb_oargs + nb_iargs, 
1667
           sizeof(TCGArg) * def->nb_cargs);
1668

    
1669
    /* satisfy input constraints */ 
1670
    tcg_regset_set(allocated_regs, s->reserved_regs);
1671
    for(k = 0; k < nb_iargs; k++) {
1672
        i = def->sorted_args[nb_oargs + k];
1673
        arg = args[i];
1674
        arg_ct = &def->args_ct[i];
1675
        ts = &s->temps[arg];
1676
        if (ts->val_type == TEMP_VAL_MEM) {
1677
            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1678
            tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1679
            ts->val_type = TEMP_VAL_REG;
1680
            ts->reg = reg;
1681
            ts->mem_coherent = 1;
1682
            s->reg_to_temp[reg] = arg;
1683
        } else if (ts->val_type == TEMP_VAL_CONST) {
1684
            if (tcg_target_const_match(ts->val, arg_ct)) {
1685
                /* constant is OK for instruction */
1686
                const_args[i] = 1;
1687
                new_args[i] = ts->val;
1688
                goto iarg_end;
1689
            } else {
1690
                /* need to move to a register */
1691
                reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1692
                tcg_out_movi(s, ts->type, reg, ts->val);
1693
                ts->val_type = TEMP_VAL_REG;
1694
                ts->reg = reg;
1695
                ts->mem_coherent = 0;
1696
                s->reg_to_temp[reg] = arg;
1697
            }
1698
        }
1699
        assert(ts->val_type == TEMP_VAL_REG);
1700
        if (arg_ct->ct & TCG_CT_IALIAS) {
1701
            if (ts->fixed_reg) {
1702
                /* if fixed register, we must allocate a new register
1703
                   if the alias is not the same register */
1704
                if (arg != args[arg_ct->alias_index])
1705
                    goto allocate_in_reg;
1706
            } else {
1707
                /* if the input is aliased to an output and if it is
1708
                   not dead after the instruction, we must allocate
1709
                   a new register and move it */
1710
                if (!IS_DEAD_ARG(i)) {
1711
                    goto allocate_in_reg;
1712
                }
1713
            }
1714
        }
1715
        reg = ts->reg;
1716
        if (tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1717
            /* nothing to do : the constraint is satisfied */
1718
        } else {
1719
        allocate_in_reg:
1720
            /* allocate a new register matching the constraint 
1721
               and move the temporary register into it */
1722
            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1723
            tcg_out_mov(s, ts->type, reg, ts->reg);
1724
        }
1725
        new_args[i] = reg;
1726
        const_args[i] = 0;
1727
        tcg_regset_set_reg(allocated_regs, reg);
1728
    iarg_end: ;
1729
    }
1730
    
1731
    if (def->flags & TCG_OPF_BB_END) {
1732
        tcg_reg_alloc_bb_end(s, allocated_regs);
1733
    } else {
1734
        /* mark dead temporaries and free the associated registers */
1735
        for(i = nb_oargs; i < nb_oargs + nb_iargs; i++) {
1736
            arg = args[i];
1737
            if (IS_DEAD_ARG(i)) {
1738
                ts = &s->temps[arg];
1739
                if (!ts->fixed_reg) {
1740
                    if (ts->val_type == TEMP_VAL_REG)
1741
                        s->reg_to_temp[ts->reg] = -1;
1742
                    ts->val_type = TEMP_VAL_DEAD;
1743
                }
1744
            }
1745
        }
1746
        
1747
        if (def->flags & TCG_OPF_CALL_CLOBBER) {
1748
            /* XXX: permit generic clobber register list ? */ 
1749
            for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1750
                if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
1751
                    tcg_reg_free(s, reg);
1752
                }
1753
            }
1754
            /* XXX: for load/store we could do that only for the slow path
1755
               (i.e. when a memory callback is called) */
1756
            
1757
            /* store globals and free associated registers (we assume the insn
1758
               can modify any global. */
1759
            save_globals(s, allocated_regs);
1760
        }
1761
        
1762
        /* satisfy the output constraints */
1763
        tcg_regset_set(allocated_regs, s->reserved_regs);
1764
        for(k = 0; k < nb_oargs; k++) {
1765
            i = def->sorted_args[k];
1766
            arg = args[i];
1767
            arg_ct = &def->args_ct[i];
1768
            ts = &s->temps[arg];
1769
            if (arg_ct->ct & TCG_CT_ALIAS) {
1770
                reg = new_args[arg_ct->alias_index];
1771
            } else {
1772
                /* if fixed register, we try to use it */
1773
                reg = ts->reg;
1774
                if (ts->fixed_reg &&
1775
                    tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1776
                    goto oarg_end;
1777
                }
1778
                reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1779
            }
1780
            tcg_regset_set_reg(allocated_regs, reg);
1781
            /* if a fixed register is used, then a move will be done afterwards */
1782
            if (!ts->fixed_reg) {
1783
                if (ts->val_type == TEMP_VAL_REG)
1784
                    s->reg_to_temp[ts->reg] = -1;
1785
                if (IS_DEAD_ARG(i)) {
1786
                    ts->val_type = TEMP_VAL_DEAD;
1787
                } else {
1788
                    ts->val_type = TEMP_VAL_REG;
1789
                    ts->reg = reg;
1790
                    /* temp value is modified, so the value kept in memory is
1791
                       potentially not the same */
1792
                    ts->mem_coherent = 0;
1793
                    s->reg_to_temp[reg] = arg;
1794
               }
1795
            }
1796
        oarg_end:
1797
            new_args[i] = reg;
1798
        }
1799
    }
1800

    
1801
    /* emit instruction */
1802
    tcg_out_op(s, opc, new_args, const_args);
1803
    
1804
    /* move the outputs in the correct register if needed */
1805
    for(i = 0; i < nb_oargs; i++) {
1806
        ts = &s->temps[args[i]];
1807
        reg = new_args[i];
1808
        if (ts->fixed_reg && ts->reg != reg) {
1809
            tcg_out_mov(s, ts->type, ts->reg, reg);
1810
        }
1811
    }
1812
}
1813

    
1814
#ifdef TCG_TARGET_STACK_GROWSUP
1815
#define STACK_DIR(x) (-(x))
1816
#else
1817
#define STACK_DIR(x) (x)
1818
#endif
1819

    
1820
static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
1821
                              TCGOpcode opc, const TCGArg *args,
1822
                              unsigned int dead_args)
1823
{
1824
    int nb_iargs, nb_oargs, flags, nb_regs, i, reg, nb_params;
1825
    TCGArg arg, func_arg;
1826
    TCGTemp *ts;
1827
    tcg_target_long stack_offset, call_stack_size, func_addr;
1828
    int const_func_arg, allocate_args;
1829
    TCGRegSet allocated_regs;
1830
    const TCGArgConstraint *arg_ct;
1831

    
1832
    arg = *args++;
1833

    
1834
    nb_oargs = arg >> 16;
1835
    nb_iargs = arg & 0xffff;
1836
    nb_params = nb_iargs - 1;
1837

    
1838
    flags = args[nb_oargs + nb_iargs];
1839

    
1840
    nb_regs = tcg_target_get_call_iarg_regs_count(flags);
1841
    if (nb_regs > nb_params)
1842
        nb_regs = nb_params;
1843

    
1844
    /* assign stack slots first */
1845
    /* XXX: preallocate call stack */
1846
    call_stack_size = (nb_params - nb_regs) * sizeof(tcg_target_long);
1847
    call_stack_size = (call_stack_size + TCG_TARGET_STACK_ALIGN - 1) & 
1848
        ~(TCG_TARGET_STACK_ALIGN - 1);
1849
    allocate_args = (call_stack_size > TCG_STATIC_CALL_ARGS_SIZE);
1850
    if (allocate_args) {
1851
        tcg_out_addi(s, TCG_REG_CALL_STACK, -STACK_DIR(call_stack_size));
1852
    }
1853

    
1854
    stack_offset = TCG_TARGET_CALL_STACK_OFFSET;
1855
    for(i = nb_regs; i < nb_params; i++) {
1856
        arg = args[nb_oargs + i];
1857
#ifdef TCG_TARGET_STACK_GROWSUP
1858
        stack_offset -= sizeof(tcg_target_long);
1859
#endif
1860
        if (arg != TCG_CALL_DUMMY_ARG) {
1861
            ts = &s->temps[arg];
1862
            if (ts->val_type == TEMP_VAL_REG) {
1863
                tcg_out_st(s, ts->type, ts->reg, TCG_REG_CALL_STACK, stack_offset);
1864
            } else if (ts->val_type == TEMP_VAL_MEM) {
1865
                reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], 
1866
                                    s->reserved_regs);
1867
                /* XXX: not correct if reading values from the stack */
1868
                tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1869
                tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
1870
            } else if (ts->val_type == TEMP_VAL_CONST) {
1871
                reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], 
1872
                                    s->reserved_regs);
1873
                /* XXX: sign extend may be needed on some targets */
1874
                tcg_out_movi(s, ts->type, reg, ts->val);
1875
                tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
1876
            } else {
1877
                tcg_abort();
1878
            }
1879
        }
1880
#ifndef TCG_TARGET_STACK_GROWSUP
1881
        stack_offset += sizeof(tcg_target_long);
1882
#endif
1883
    }
1884
    
1885
    /* assign input registers */
1886
    tcg_regset_set(allocated_regs, s->reserved_regs);
1887
    for(i = 0; i < nb_regs; i++) {
1888
        arg = args[nb_oargs + i];
1889
        if (arg != TCG_CALL_DUMMY_ARG) {
1890
            ts = &s->temps[arg];
1891
            reg = tcg_target_call_iarg_regs[i];
1892
            tcg_reg_free(s, reg);
1893
            if (ts->val_type == TEMP_VAL_REG) {
1894
                if (ts->reg != reg) {
1895
                    tcg_out_mov(s, ts->type, reg, ts->reg);
1896
                }
1897
            } else if (ts->val_type == TEMP_VAL_MEM) {
1898
                tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1899
            } else if (ts->val_type == TEMP_VAL_CONST) {
1900
                /* XXX: sign extend ? */
1901
                tcg_out_movi(s, ts->type, reg, ts->val);
1902
            } else {
1903
                tcg_abort();
1904
            }
1905
            tcg_regset_set_reg(allocated_regs, reg);
1906
        }
1907
    }
1908
    
1909
    /* assign function address */
1910
    func_arg = args[nb_oargs + nb_iargs - 1];
1911
    arg_ct = &def->args_ct[0];
1912
    ts = &s->temps[func_arg];
1913
    func_addr = ts->val;
1914
    const_func_arg = 0;
1915
    if (ts->val_type == TEMP_VAL_MEM) {
1916
        reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1917
        tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1918
        func_arg = reg;
1919
        tcg_regset_set_reg(allocated_regs, reg);
1920
    } else if (ts->val_type == TEMP_VAL_REG) {
1921
        reg = ts->reg;
1922
        if (!tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1923
            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1924
            tcg_out_mov(s, ts->type, reg, ts->reg);
1925
        }
1926
        func_arg = reg;
1927
        tcg_regset_set_reg(allocated_regs, reg);
1928
    } else if (ts->val_type == TEMP_VAL_CONST) {
1929
        if (tcg_target_const_match(func_addr, arg_ct)) {
1930
            const_func_arg = 1;
1931
            func_arg = func_addr;
1932
        } else {
1933
            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1934
            tcg_out_movi(s, ts->type, reg, func_addr);
1935
            func_arg = reg;
1936
            tcg_regset_set_reg(allocated_regs, reg);
1937
        }
1938
    } else {
1939
        tcg_abort();
1940
    }
1941
        
1942
    
1943
    /* mark dead temporaries and free the associated registers */
1944
    for(i = nb_oargs; i < nb_iargs + nb_oargs; i++) {
1945
        arg = args[i];
1946
        if (IS_DEAD_ARG(i)) {
1947
            ts = &s->temps[arg];
1948
            if (!ts->fixed_reg) {
1949
                if (ts->val_type == TEMP_VAL_REG)
1950
                    s->reg_to_temp[ts->reg] = -1;
1951
                ts->val_type = TEMP_VAL_DEAD;
1952
            }
1953
        }
1954
    }
1955
    
1956
    /* clobber call registers */
1957
    for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1958
        if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
1959
            tcg_reg_free(s, reg);
1960
        }
1961
    }
1962
    
1963
    /* store globals and free associated registers (we assume the call
1964
       can modify any global. */
1965
    if (!(flags & TCG_CALL_CONST)) {
1966
        save_globals(s, allocated_regs);
1967
    }
1968

    
1969
    tcg_out_op(s, opc, &func_arg, &const_func_arg);
1970
    
1971
    if (allocate_args) {
1972
        tcg_out_addi(s, TCG_REG_CALL_STACK, STACK_DIR(call_stack_size));
1973
    }
1974

    
1975
    /* assign output registers and emit moves if needed */
1976
    for(i = 0; i < nb_oargs; i++) {
1977
        arg = args[i];
1978
        ts = &s->temps[arg];
1979
        reg = tcg_target_call_oarg_regs[i];
1980
        assert(s->reg_to_temp[reg] == -1);
1981
        if (ts->fixed_reg) {
1982
            if (ts->reg != reg) {
1983
                tcg_out_mov(s, ts->type, ts->reg, reg);
1984
            }
1985
        } else {
1986
            if (ts->val_type == TEMP_VAL_REG)
1987
                s->reg_to_temp[ts->reg] = -1;
1988
            if (IS_DEAD_ARG(i)) {
1989
                ts->val_type = TEMP_VAL_DEAD;
1990
            } else {
1991
                ts->val_type = TEMP_VAL_REG;
1992
                ts->reg = reg;
1993
                ts->mem_coherent = 0;
1994
                s->reg_to_temp[reg] = arg;
1995
            }
1996
        }
1997
    }
1998
    
1999
    return nb_iargs + nb_oargs + def->nb_cargs + 1;
2000
}
2001

    
2002
#ifdef CONFIG_PROFILER
2003

    
2004
static int64_t tcg_table_op_count[NB_OPS];
2005

    
2006
static void dump_op_count(void)
2007
{
2008
    int i;
2009
    FILE *f;
2010
    f = fopen("/tmp/op.log", "w");
2011
    for(i = INDEX_op_end; i < NB_OPS; i++) {
2012
        fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name, tcg_table_op_count[i]);
2013
    }
2014
    fclose(f);
2015
}
2016
#endif
2017

    
2018

    
2019
static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
2020
                                      long search_pc)
2021
{
2022
    TCGOpcode opc;
2023
    int op_index;
2024
    const TCGOpDef *def;
2025
    unsigned int dead_args;
2026
    const TCGArg *args;
2027

    
2028
#ifdef DEBUG_DISAS
2029
    if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
2030
        qemu_log("OP:\n");
2031
        tcg_dump_ops(s, logfile);
2032
        qemu_log("\n");
2033
    }
2034
#endif
2035

    
2036
#ifdef CONFIG_PROFILER
2037
    s->la_time -= profile_getclock();
2038
#endif
2039
    tcg_liveness_analysis(s);
2040
#ifdef CONFIG_PROFILER
2041
    s->la_time += profile_getclock();
2042
#endif
2043

    
2044
#ifdef DEBUG_DISAS
2045
    if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_OPT))) {
2046
        qemu_log("OP after liveness analysis:\n");
2047
        tcg_dump_ops(s, logfile);
2048
        qemu_log("\n");
2049
    }
2050
#endif
2051

    
2052
    tcg_reg_alloc_start(s);
2053

    
2054
    s->code_buf = gen_code_buf;
2055
    s->code_ptr = gen_code_buf;
2056

    
2057
    args = gen_opparam_buf;
2058
    op_index = 0;
2059

    
2060
    for(;;) {
2061
        opc = gen_opc_buf[op_index];
2062
#ifdef CONFIG_PROFILER
2063
        tcg_table_op_count[opc]++;
2064
#endif
2065
        def = &tcg_op_defs[opc];
2066
#if 0
2067
        printf("%s: %d %d %d\n", def->name,
2068
               def->nb_oargs, def->nb_iargs, def->nb_cargs);
2069
        //        dump_regs(s);
2070
#endif
2071
        switch(opc) {
2072
        case INDEX_op_mov_i32:
2073
#if TCG_TARGET_REG_BITS == 64
2074
        case INDEX_op_mov_i64:
2075
#endif
2076
            dead_args = s->op_dead_args[op_index];
2077
            tcg_reg_alloc_mov(s, def, args, dead_args);
2078
            break;
2079
        case INDEX_op_movi_i32:
2080
#if TCG_TARGET_REG_BITS == 64
2081
        case INDEX_op_movi_i64:
2082
#endif
2083
            tcg_reg_alloc_movi(s, args);
2084
            break;
2085
        case INDEX_op_debug_insn_start:
2086
            /* debug instruction */
2087
            break;
2088
        case INDEX_op_nop:
2089
        case INDEX_op_nop1:
2090
        case INDEX_op_nop2:
2091
        case INDEX_op_nop3:
2092
            break;
2093
        case INDEX_op_nopn:
2094
            args += args[0];
2095
            goto next;
2096
        case INDEX_op_discard:
2097
            {
2098
                TCGTemp *ts;
2099
                ts = &s->temps[args[0]];
2100
                /* mark the temporary as dead */
2101
                if (!ts->fixed_reg) {
2102
                    if (ts->val_type == TEMP_VAL_REG)
2103
                        s->reg_to_temp[ts->reg] = -1;
2104
                    ts->val_type = TEMP_VAL_DEAD;
2105
                }
2106
            }
2107
            break;
2108
        case INDEX_op_set_label:
2109
            tcg_reg_alloc_bb_end(s, s->reserved_regs);
2110
            tcg_out_label(s, args[0], (long)s->code_ptr);
2111
            break;
2112
        case INDEX_op_call:
2113
            dead_args = s->op_dead_args[op_index];
2114
            args += tcg_reg_alloc_call(s, def, opc, args, dead_args);
2115
            goto next;
2116
        case INDEX_op_end:
2117
            goto the_end;
2118
        default:
2119
            /* Note: in order to speed up the code, it would be much
2120
               faster to have specialized register allocator functions for
2121
               some common argument patterns */
2122
            dead_args = s->op_dead_args[op_index];
2123
            tcg_reg_alloc_op(s, def, opc, args, dead_args);
2124
            break;
2125
        }
2126
        args += def->nb_args;
2127
    next:
2128
        if (search_pc >= 0 && search_pc < s->code_ptr - gen_code_buf) {
2129
            return op_index;
2130
        }
2131
        op_index++;
2132
#ifndef NDEBUG
2133
        check_regs(s);
2134
#endif
2135
    }
2136
 the_end:
2137
    return -1;
2138
}
2139

    
2140
int tcg_gen_code(TCGContext *s, uint8_t *gen_code_buf)
2141
{
2142
#ifdef CONFIG_PROFILER
2143
    {
2144
        int n;
2145
        n = (gen_opc_ptr - gen_opc_buf);
2146
        s->op_count += n;
2147
        if (n > s->op_count_max)
2148
            s->op_count_max = n;
2149

    
2150
        s->temp_count += s->nb_temps;
2151
        if (s->nb_temps > s->temp_count_max)
2152
            s->temp_count_max = s->nb_temps;
2153
    }
2154
#endif
2155

    
2156
    tcg_gen_code_common(s, gen_code_buf, -1);
2157

    
2158
    /* flush instruction cache */
2159
    flush_icache_range((unsigned long)gen_code_buf, 
2160
                       (unsigned long)s->code_ptr);
2161
    return s->code_ptr -  gen_code_buf;
2162
}
2163

    
2164
/* Return the index of the micro operation such as the pc after is <
2165
   offset bytes from the start of the TB.  The contents of gen_code_buf must
2166
   not be changed, though writing the same values is ok.
2167
   Return -1 if not found. */
2168
int tcg_gen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, long offset)
2169
{
2170
    return tcg_gen_code_common(s, gen_code_buf, offset);
2171
}
2172

    
2173
#ifdef CONFIG_PROFILER
2174
void tcg_dump_info(FILE *f, fprintf_function cpu_fprintf)
2175
{
2176
    TCGContext *s = &tcg_ctx;
2177
    int64_t tot;
2178

    
2179
    tot = s->interm_time + s->code_time;
2180
    cpu_fprintf(f, "JIT cycles          %" PRId64 " (%0.3f s at 2.4 GHz)\n",
2181
                tot, tot / 2.4e9);
2182
    cpu_fprintf(f, "translated TBs      %" PRId64 " (aborted=%" PRId64 " %0.1f%%)\n", 
2183
                s->tb_count, 
2184
                s->tb_count1 - s->tb_count,
2185
                s->tb_count1 ? (double)(s->tb_count1 - s->tb_count) / s->tb_count1 * 100.0 : 0);
2186
    cpu_fprintf(f, "avg ops/TB          %0.1f max=%d\n", 
2187
                s->tb_count ? (double)s->op_count / s->tb_count : 0, s->op_count_max);
2188
    cpu_fprintf(f, "deleted ops/TB      %0.2f\n",
2189
                s->tb_count ? 
2190
                (double)s->del_op_count / s->tb_count : 0);
2191
    cpu_fprintf(f, "avg temps/TB        %0.2f max=%d\n",
2192
                s->tb_count ? 
2193
                (double)s->temp_count / s->tb_count : 0,
2194
                s->temp_count_max);
2195
    
2196
    cpu_fprintf(f, "cycles/op           %0.1f\n", 
2197
                s->op_count ? (double)tot / s->op_count : 0);
2198
    cpu_fprintf(f, "cycles/in byte      %0.1f\n", 
2199
                s->code_in_len ? (double)tot / s->code_in_len : 0);
2200
    cpu_fprintf(f, "cycles/out byte     %0.1f\n", 
2201
                s->code_out_len ? (double)tot / s->code_out_len : 0);
2202
    if (tot == 0)
2203
        tot = 1;
2204
    cpu_fprintf(f, "  gen_interm time   %0.1f%%\n", 
2205
                (double)s->interm_time / tot * 100.0);
2206
    cpu_fprintf(f, "  gen_code time     %0.1f%%\n", 
2207
                (double)s->code_time / tot * 100.0);
2208
    cpu_fprintf(f, "liveness/code time  %0.1f%%\n", 
2209
                (double)s->la_time / (s->code_time ? s->code_time : 1) * 100.0);
2210
    cpu_fprintf(f, "cpu_restore count   %" PRId64 "\n",
2211
                s->restore_count);
2212
    cpu_fprintf(f, "  avg cycles        %0.1f\n",
2213
                s->restore_count ? (double)s->restore_time / s->restore_count : 0);
2214

    
2215
    dump_op_count();
2216
}
2217
#else
2218
void tcg_dump_info(FILE *f, fprintf_function cpu_fprintf)
2219
{
2220
    cpu_fprintf(f, "[TCG profiler not compiled]\n");
2221
}
2222
#endif