Statistics
| Branch: | Revision:

root / tcg / tcg.c @ 7267c094

History | View | Annotate | Download (66.2 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
#define USE_TCG_OPTIMIZATIONS
28

    
29
#include "config.h"
30

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

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

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

    
53
/* Note: the long term plan is to reduce the dependancies on the QEMU
54
   CPU definitions. Currently they are used for qemu_ld/st
55
   instructions */
56
#define NO_CPU_IO_DEFS
57
#include "cpu.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 = g_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 = g_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 = g_malloc(sizeof(TCGArgConstraint) * total_args);
231
    sorted_args = g_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
#if defined(TCG_TARGET_I386) && TCG_TARGET_REG_BITS < 64
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
#if defined(TCG_TARGET_I386) && TCG_TARGET_REG_BITS < 64
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
#ifndef __sparc_v9__ /* Sparc64 stack is accessed with offset of 2047 */
1444
    s->current_frame_offset = (s->current_frame_offset +
1445
                               (tcg_target_long)sizeof(tcg_target_long) - 1) &
1446
        ~(sizeof(tcg_target_long) - 1);
1447
#endif
1448
    if (s->current_frame_offset + (tcg_target_long)sizeof(tcg_target_long) >
1449
        s->frame_end) {
1450
        tcg_abort();
1451
    }
1452
    ts->mem_offset = s->current_frame_offset;
1453
    ts->mem_reg = s->frame_reg;
1454
    ts->mem_allocated = 1;
1455
    s->current_frame_offset += (tcg_target_long)sizeof(tcg_target_long);
1456
}
1457

    
1458
/* free register 'reg' by spilling the corresponding temporary if necessary */
1459
static void tcg_reg_free(TCGContext *s, int reg)
1460
{
1461
    TCGTemp *ts;
1462
    int temp;
1463

    
1464
    temp = s->reg_to_temp[reg];
1465
    if (temp != -1) {
1466
        ts = &s->temps[temp];
1467
        assert(ts->val_type == TEMP_VAL_REG);
1468
        if (!ts->mem_coherent) {
1469
            if (!ts->mem_allocated) 
1470
                temp_allocate_frame(s, temp);
1471
            tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1472
        }
1473
        ts->val_type = TEMP_VAL_MEM;
1474
        s->reg_to_temp[reg] = -1;
1475
    }
1476
}
1477

    
1478
/* Allocate a register belonging to reg1 & ~reg2 */
1479
static int tcg_reg_alloc(TCGContext *s, TCGRegSet reg1, TCGRegSet reg2)
1480
{
1481
    int i, reg;
1482
    TCGRegSet reg_ct;
1483

    
1484
    tcg_regset_andnot(reg_ct, reg1, reg2);
1485

    
1486
    /* first try free registers */
1487
    for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1488
        reg = tcg_target_reg_alloc_order[i];
1489
        if (tcg_regset_test_reg(reg_ct, reg) && s->reg_to_temp[reg] == -1)
1490
            return reg;
1491
    }
1492

    
1493
    /* XXX: do better spill choice */
1494
    for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1495
        reg = tcg_target_reg_alloc_order[i];
1496
        if (tcg_regset_test_reg(reg_ct, reg)) {
1497
            tcg_reg_free(s, reg);
1498
            return reg;
1499
        }
1500
    }
1501

    
1502
    tcg_abort();
1503
}
1504

    
1505
/* save a temporary to memory. 'allocated_regs' is used in case a
1506
   temporary registers needs to be allocated to store a constant. */
1507
static void temp_save(TCGContext *s, int temp, TCGRegSet allocated_regs)
1508
{
1509
    TCGTemp *ts;
1510
    int reg;
1511

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

    
1538
/* save globals to their cannonical location and assume they can be
1539
   modified be the following code. 'allocated_regs' is used in case a
1540
   temporary registers needs to be allocated to store a constant. */
1541
static void save_globals(TCGContext *s, TCGRegSet allocated_regs)
1542
{
1543
    int i;
1544

    
1545
    for(i = 0; i < s->nb_globals; i++) {
1546
        temp_save(s, i, allocated_regs);
1547
    }
1548
}
1549

    
1550
/* at the end of a basic block, we assume all temporaries are dead and
1551
   all globals are stored at their canonical location. */
1552
static void tcg_reg_alloc_bb_end(TCGContext *s, TCGRegSet allocated_regs)
1553
{
1554
    TCGTemp *ts;
1555
    int i;
1556

    
1557
    for(i = s->nb_globals; i < s->nb_temps; i++) {
1558
        ts = &s->temps[i];
1559
        if (ts->temp_local) {
1560
            temp_save(s, i, allocated_regs);
1561
        } else {
1562
            if (ts->val_type == TEMP_VAL_REG) {
1563
                s->reg_to_temp[ts->reg] = -1;
1564
            }
1565
            ts->val_type = TEMP_VAL_DEAD;
1566
        }
1567
    }
1568

    
1569
    save_globals(s, allocated_regs);
1570
}
1571

    
1572
#define IS_DEAD_ARG(n) ((dead_args >> (n)) & 1)
1573

    
1574
static void tcg_reg_alloc_movi(TCGContext *s, const TCGArg *args)
1575
{
1576
    TCGTemp *ots;
1577
    tcg_target_ulong val;
1578

    
1579
    ots = &s->temps[args[0]];
1580
    val = args[1];
1581

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

    
1595
static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
1596
                              const TCGArg *args,
1597
                              unsigned int dead_args)
1598
{
1599
    TCGTemp *ts, *ots;
1600
    int reg;
1601
    const TCGArgConstraint *arg_ct;
1602

    
1603
    ots = &s->temps[args[0]];
1604
    ts = &s->temps[args[1]];
1605
    arg_ct = &def->args_ct[0];
1606

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

    
1654
static void tcg_reg_alloc_op(TCGContext *s, 
1655
                             const TCGOpDef *def, TCGOpcode opc,
1656
                             const TCGArg *args,
1657
                             unsigned int dead_args)
1658
{
1659
    TCGRegSet allocated_regs;
1660
    int i, k, nb_iargs, nb_oargs, reg;
1661
    TCGArg arg;
1662
    const TCGArgConstraint *arg_ct;
1663
    TCGTemp *ts;
1664
    TCGArg new_args[TCG_MAX_OP_ARGS];
1665
    int const_args[TCG_MAX_OP_ARGS];
1666

    
1667
    nb_oargs = def->nb_oargs;
1668
    nb_iargs = def->nb_iargs;
1669

    
1670
    /* copy constants */
1671
    memcpy(new_args + nb_oargs + nb_iargs, 
1672
           args + nb_oargs + nb_iargs, 
1673
           sizeof(TCGArg) * def->nb_cargs);
1674

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

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

    
1820
#ifdef TCG_TARGET_STACK_GROWSUP
1821
#define STACK_DIR(x) (-(x))
1822
#else
1823
#define STACK_DIR(x) (x)
1824
#endif
1825

    
1826
static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
1827
                              TCGOpcode opc, const TCGArg *args,
1828
                              unsigned int dead_args)
1829
{
1830
    int nb_iargs, nb_oargs, flags, nb_regs, i, reg, nb_params;
1831
    TCGArg arg, func_arg;
1832
    TCGTemp *ts;
1833
    tcg_target_long stack_offset, call_stack_size, func_addr;
1834
    int const_func_arg, allocate_args;
1835
    TCGRegSet allocated_regs;
1836
    const TCGArgConstraint *arg_ct;
1837

    
1838
    arg = *args++;
1839

    
1840
    nb_oargs = arg >> 16;
1841
    nb_iargs = arg & 0xffff;
1842
    nb_params = nb_iargs - 1;
1843

    
1844
    flags = args[nb_oargs + nb_iargs];
1845

    
1846
    nb_regs = tcg_target_get_call_iarg_regs_count(flags);
1847
    if (nb_regs > nb_params)
1848
        nb_regs = nb_params;
1849

    
1850
    /* assign stack slots first */
1851
    call_stack_size = (nb_params - nb_regs) * sizeof(tcg_target_long);
1852
    call_stack_size = (call_stack_size + TCG_TARGET_STACK_ALIGN - 1) & 
1853
        ~(TCG_TARGET_STACK_ALIGN - 1);
1854
    allocate_args = (call_stack_size > TCG_STATIC_CALL_ARGS_SIZE);
1855
    if (allocate_args) {
1856
        /* XXX: if more than TCG_STATIC_CALL_ARGS_SIZE is needed,
1857
           preallocate call stack */
1858
        tcg_abort();
1859
    }
1860

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

    
1976
    tcg_out_op(s, opc, &func_arg, &const_func_arg);
1977

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

    
2005
#ifdef CONFIG_PROFILER
2006

    
2007
static int64_t tcg_table_op_count[NB_OPS];
2008

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

    
2021

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

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

    
2039
#ifdef USE_TCG_OPTIMIZATIONS
2040
    gen_opparam_ptr =
2041
        tcg_optimize(s, gen_opc_ptr, gen_opparam_buf, tcg_op_defs);
2042
#endif
2043

    
2044
#ifdef CONFIG_PROFILER
2045
    s->la_time -= profile_getclock();
2046
#endif
2047
    tcg_liveness_analysis(s);
2048
#ifdef CONFIG_PROFILER
2049
    s->la_time += profile_getclock();
2050
#endif
2051

    
2052
#ifdef DEBUG_DISAS
2053
    if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_OPT))) {
2054
        qemu_log("OP after liveness analysis:\n");
2055
        tcg_dump_ops(s, logfile);
2056
        qemu_log("\n");
2057
    }
2058
#endif
2059

    
2060
    tcg_reg_alloc_start(s);
2061

    
2062
    s->code_buf = gen_code_buf;
2063
    s->code_ptr = gen_code_buf;
2064

    
2065
    args = gen_opparam_buf;
2066
    op_index = 0;
2067

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

    
2148
int tcg_gen_code(TCGContext *s, uint8_t *gen_code_buf)
2149
{
2150
#ifdef CONFIG_PROFILER
2151
    {
2152
        int n;
2153
        n = (gen_opc_ptr - gen_opc_buf);
2154
        s->op_count += n;
2155
        if (n > s->op_count_max)
2156
            s->op_count_max = n;
2157

    
2158
        s->temp_count += s->nb_temps;
2159
        if (s->nb_temps > s->temp_count_max)
2160
            s->temp_count_max = s->nb_temps;
2161
    }
2162
#endif
2163

    
2164
    tcg_gen_code_common(s, gen_code_buf, -1);
2165

    
2166
    /* flush instruction cache */
2167
    flush_icache_range((unsigned long)gen_code_buf, 
2168
                       (unsigned long)s->code_ptr);
2169
    return s->code_ptr -  gen_code_buf;
2170
}
2171

    
2172
/* Return the index of the micro operation such as the pc after is <
2173
   offset bytes from the start of the TB.  The contents of gen_code_buf must
2174
   not be changed, though writing the same values is ok.
2175
   Return -1 if not found. */
2176
int tcg_gen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, long offset)
2177
{
2178
    return tcg_gen_code_common(s, gen_code_buf, offset);
2179
}
2180

    
2181
#ifdef CONFIG_PROFILER
2182
void tcg_dump_info(FILE *f, fprintf_function cpu_fprintf)
2183
{
2184
    TCGContext *s = &tcg_ctx;
2185
    int64_t tot;
2186

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

    
2223
    dump_op_count();
2224
}
2225
#else
2226
void tcg_dump_info(FILE *f, fprintf_function cpu_fprintf)
2227
{
2228
    cpu_fprintf(f, "[TCG profiler not compiled]\n");
2229
}
2230
#endif