Statistics
| Branch: | Revision:

root / tcg / tcg.c @ 866cb6cb

History | View | Annotate | Download (65.4 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
                    for(i = 0; i < nb_oargs; i++) {
1249
                        arg = args[i];
1250
                        dead_temps[arg] = 1;
1251
                    }
1252
                    
1253
                    if (!(call_flags & TCG_CALL_CONST)) {
1254
                        /* globals are live (they may be used by the call) */
1255
                        memset(dead_temps, 0, s->nb_globals);
1256
                    }
1257

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

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

    
1315
                /* output args are dead */
1316
                for(i = 0; i < nb_oargs; i++) {
1317
                    arg = args[i];
1318
                    dead_temps[arg] = 1;
1319
                }
1320

    
1321
                /* if end of basic block, update */
1322
                if (def->flags & TCG_OPF_BB_END) {
1323
                    tcg_la_bb_end(s, dead_temps);
1324
                } else if (def->flags & TCG_OPF_CALL_CLOBBER) {
1325
                    /* globals are live */
1326
                    memset(dead_temps, 0, s->nb_globals);
1327
                }
1328

    
1329
                /* input args are live */
1330
                dead_args = 0;
1331
                for(i = nb_oargs; i < nb_oargs + nb_iargs; i++) {
1332
                    arg = args[i];
1333
                    if (dead_temps[arg]) {
1334
                        dead_args |= (1 << i);
1335
                    }
1336
                    dead_temps[arg] = 0;
1337
                }
1338
                s->op_dead_args[op_index] = dead_args;
1339
            }
1340
            break;
1341
        }
1342
        op_index--;
1343
    }
1344

    
1345
    if (args != gen_opparam_buf)
1346
        tcg_abort();
1347
}
1348
#else
1349
/* dummy liveness analysis */
1350
static void tcg_liveness_analysis(TCGContext *s)
1351
{
1352
    int nb_ops;
1353
    nb_ops = gen_opc_ptr - gen_opc_buf;
1354

    
1355
    s->op_dead_args = tcg_malloc(nb_ops * sizeof(uint16_t));
1356
    memset(s->op_dead_args, 0, nb_ops * sizeof(uint16_t));
1357
}
1358
#endif
1359

    
1360
#ifndef NDEBUG
1361
static void dump_regs(TCGContext *s)
1362
{
1363
    TCGTemp *ts;
1364
    int i;
1365
    char buf[64];
1366

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

    
1390
    for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
1391
        if (s->reg_to_temp[i] >= 0) {
1392
            printf("%s: %s\n", 
1393
                   tcg_target_reg_names[i], 
1394
                   tcg_get_arg_str_idx(s, buf, sizeof(buf), s->reg_to_temp[i]));
1395
        }
1396
    }
1397
}
1398

    
1399
static void check_regs(TCGContext *s)
1400
{
1401
    int reg, k;
1402
    TCGTemp *ts;
1403
    char buf[64];
1404

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

    
1433
static void temp_allocate_frame(TCGContext *s, int temp)
1434
{
1435
    TCGTemp *ts;
1436
    ts = &s->temps[temp];
1437
    s->current_frame_offset = (s->current_frame_offset + sizeof(tcg_target_long) - 1) & ~(sizeof(tcg_target_long) - 1);
1438
    if (s->current_frame_offset + sizeof(tcg_target_long) > s->frame_end)
1439
        tcg_abort();
1440
    ts->mem_offset = s->current_frame_offset;
1441
    ts->mem_reg = s->frame_reg;
1442
    ts->mem_allocated = 1;
1443
    s->current_frame_offset += sizeof(tcg_target_long);
1444
}
1445

    
1446
/* free register 'reg' by spilling the corresponding temporary if necessary */
1447
static void tcg_reg_free(TCGContext *s, int reg)
1448
{
1449
    TCGTemp *ts;
1450
    int temp;
1451

    
1452
    temp = s->reg_to_temp[reg];
1453
    if (temp != -1) {
1454
        ts = &s->temps[temp];
1455
        assert(ts->val_type == TEMP_VAL_REG);
1456
        if (!ts->mem_coherent) {
1457
            if (!ts->mem_allocated) 
1458
                temp_allocate_frame(s, temp);
1459
            tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1460
        }
1461
        ts->val_type = TEMP_VAL_MEM;
1462
        s->reg_to_temp[reg] = -1;
1463
    }
1464
}
1465

    
1466
/* Allocate a register belonging to reg1 & ~reg2 */
1467
static int tcg_reg_alloc(TCGContext *s, TCGRegSet reg1, TCGRegSet reg2)
1468
{
1469
    int i, reg;
1470
    TCGRegSet reg_ct;
1471

    
1472
    tcg_regset_andnot(reg_ct, reg1, reg2);
1473

    
1474
    /* first try free registers */
1475
    for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1476
        reg = tcg_target_reg_alloc_order[i];
1477
        if (tcg_regset_test_reg(reg_ct, reg) && s->reg_to_temp[reg] == -1)
1478
            return reg;
1479
    }
1480

    
1481
    /* XXX: do better spill choice */
1482
    for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1483
        reg = tcg_target_reg_alloc_order[i];
1484
        if (tcg_regset_test_reg(reg_ct, reg)) {
1485
            tcg_reg_free(s, reg);
1486
            return reg;
1487
        }
1488
    }
1489

    
1490
    tcg_abort();
1491
}
1492

    
1493
/* save a temporary to memory. 'allocated_regs' is used in case a
1494
   temporary registers needs to be allocated to store a constant. */
1495
static void temp_save(TCGContext *s, int temp, TCGRegSet allocated_regs)
1496
{
1497
    TCGTemp *ts;
1498
    int reg;
1499

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

    
1526
/* save globals to their cannonical location and assume they can be
1527
   modified be the following code. 'allocated_regs' is used in case a
1528
   temporary registers needs to be allocated to store a constant. */
1529
static void save_globals(TCGContext *s, TCGRegSet allocated_regs)
1530
{
1531
    int i;
1532

    
1533
    for(i = 0; i < s->nb_globals; i++) {
1534
        temp_save(s, i, allocated_regs);
1535
    }
1536
}
1537

    
1538
/* at the end of a basic block, we assume all temporaries are dead and
1539
   all globals are stored at their canonical location. */
1540
static void tcg_reg_alloc_bb_end(TCGContext *s, TCGRegSet allocated_regs)
1541
{
1542
    TCGTemp *ts;
1543
    int i;
1544

    
1545
    for(i = s->nb_globals; i < s->nb_temps; i++) {
1546
        ts = &s->temps[i];
1547
        if (ts->temp_local) {
1548
            temp_save(s, i, allocated_regs);
1549
        } else {
1550
            if (ts->val_type == TEMP_VAL_REG) {
1551
                s->reg_to_temp[ts->reg] = -1;
1552
            }
1553
            ts->val_type = TEMP_VAL_DEAD;
1554
        }
1555
    }
1556

    
1557
    save_globals(s, allocated_regs);
1558
}
1559

    
1560
#define IS_DEAD_ARG(n) ((dead_args >> (n)) & 1)
1561

    
1562
static void tcg_reg_alloc_movi(TCGContext *s, const TCGArg *args)
1563
{
1564
    TCGTemp *ots;
1565
    tcg_target_ulong val;
1566

    
1567
    ots = &s->temps[args[0]];
1568
    val = args[1];
1569

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

    
1583
static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
1584
                              const TCGArg *args,
1585
                              unsigned int dead_args)
1586
{
1587
    TCGTemp *ts, *ots;
1588
    int reg;
1589
    const TCGArgConstraint *arg_ct;
1590

    
1591
    ots = &s->temps[args[0]];
1592
    ts = &s->temps[args[1]];
1593
    arg_ct = &def->args_ct[0];
1594

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

    
1642
static void tcg_reg_alloc_op(TCGContext *s, 
1643
                             const TCGOpDef *def, TCGOpcode opc,
1644
                             const TCGArg *args,
1645
                             unsigned int dead_args)
1646
{
1647
    TCGRegSet allocated_regs;
1648
    int i, k, nb_iargs, nb_oargs, reg;
1649
    TCGArg arg;
1650
    const TCGArgConstraint *arg_ct;
1651
    TCGTemp *ts;
1652
    TCGArg new_args[TCG_MAX_OP_ARGS];
1653
    int const_args[TCG_MAX_OP_ARGS];
1654

    
1655
    nb_oargs = def->nb_oargs;
1656
    nb_iargs = def->nb_iargs;
1657

    
1658
    /* copy constants */
1659
    memcpy(new_args + nb_oargs + nb_iargs, 
1660
           args + nb_oargs + nb_iargs, 
1661
           sizeof(TCGArg) * def->nb_cargs);
1662

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

    
1791
    /* emit instruction */
1792
    tcg_out_op(s, opc, new_args, const_args);
1793
    
1794
    /* move the outputs in the correct register if needed */
1795
    for(i = 0; i < nb_oargs; i++) {
1796
        ts = &s->temps[args[i]];
1797
        reg = new_args[i];
1798
        if (ts->fixed_reg && ts->reg != reg) {
1799
            tcg_out_mov(s, ts->type, ts->reg, reg);
1800
        }
1801
    }
1802
}
1803

    
1804
#ifdef TCG_TARGET_STACK_GROWSUP
1805
#define STACK_DIR(x) (-(x))
1806
#else
1807
#define STACK_DIR(x) (x)
1808
#endif
1809

    
1810
static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
1811
                              TCGOpcode opc, const TCGArg *args,
1812
                              unsigned int dead_args)
1813
{
1814
    int nb_iargs, nb_oargs, flags, nb_regs, i, reg, nb_params;
1815
    TCGArg arg, func_arg;
1816
    TCGTemp *ts;
1817
    tcg_target_long stack_offset, call_stack_size, func_addr;
1818
    int const_func_arg, allocate_args;
1819
    TCGRegSet allocated_regs;
1820
    const TCGArgConstraint *arg_ct;
1821

    
1822
    arg = *args++;
1823

    
1824
    nb_oargs = arg >> 16;
1825
    nb_iargs = arg & 0xffff;
1826
    nb_params = nb_iargs - 1;
1827

    
1828
    flags = args[nb_oargs + nb_iargs];
1829

    
1830
    nb_regs = tcg_target_get_call_iarg_regs_count(flags);
1831
    if (nb_regs > nb_params)
1832
        nb_regs = nb_params;
1833

    
1834
    /* assign stack slots first */
1835
    /* XXX: preallocate call stack */
1836
    call_stack_size = (nb_params - nb_regs) * sizeof(tcg_target_long);
1837
    call_stack_size = (call_stack_size + TCG_TARGET_STACK_ALIGN - 1) & 
1838
        ~(TCG_TARGET_STACK_ALIGN - 1);
1839
    allocate_args = (call_stack_size > TCG_STATIC_CALL_ARGS_SIZE);
1840
    if (allocate_args) {
1841
        tcg_out_addi(s, TCG_REG_CALL_STACK, -STACK_DIR(call_stack_size));
1842
    }
1843

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

    
1959
    tcg_out_op(s, opc, &func_arg, &const_func_arg);
1960
    
1961
    if (allocate_args) {
1962
        tcg_out_addi(s, TCG_REG_CALL_STACK, STACK_DIR(call_stack_size));
1963
    }
1964

    
1965
    /* assign output registers and emit moves if needed */
1966
    for(i = 0; i < nb_oargs; i++) {
1967
        arg = args[i];
1968
        ts = &s->temps[arg];
1969
        reg = tcg_target_call_oarg_regs[i];
1970
        assert(s->reg_to_temp[reg] == -1);
1971
        if (ts->fixed_reg) {
1972
            if (ts->reg != reg) {
1973
                tcg_out_mov(s, ts->type, ts->reg, reg);
1974
            }
1975
        } else {
1976
            if (ts->val_type == TEMP_VAL_REG)
1977
                s->reg_to_temp[ts->reg] = -1;
1978
            ts->val_type = TEMP_VAL_REG;
1979
            ts->reg = reg;
1980
            ts->mem_coherent = 0; 
1981
            s->reg_to_temp[reg] = arg;
1982
        }
1983
    }
1984
    
1985
    return nb_iargs + nb_oargs + def->nb_cargs + 1;
1986
}
1987

    
1988
#ifdef CONFIG_PROFILER
1989

    
1990
static int64_t tcg_table_op_count[NB_OPS];
1991

    
1992
static void dump_op_count(void)
1993
{
1994
    int i;
1995
    FILE *f;
1996
    f = fopen("/tmp/op.log", "w");
1997
    for(i = INDEX_op_end; i < NB_OPS; i++) {
1998
        fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name, tcg_table_op_count[i]);
1999
    }
2000
    fclose(f);
2001
}
2002
#endif
2003

    
2004

    
2005
static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
2006
                                      long search_pc)
2007
{
2008
    TCGOpcode opc;
2009
    int op_index;
2010
    const TCGOpDef *def;
2011
    unsigned int dead_args;
2012
    const TCGArg *args;
2013

    
2014
#ifdef DEBUG_DISAS
2015
    if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
2016
        qemu_log("OP:\n");
2017
        tcg_dump_ops(s, logfile);
2018
        qemu_log("\n");
2019
    }
2020
#endif
2021

    
2022
#ifdef CONFIG_PROFILER
2023
    s->la_time -= profile_getclock();
2024
#endif
2025
    tcg_liveness_analysis(s);
2026
#ifdef CONFIG_PROFILER
2027
    s->la_time += profile_getclock();
2028
#endif
2029

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

    
2038
    tcg_reg_alloc_start(s);
2039

    
2040
    s->code_buf = gen_code_buf;
2041
    s->code_ptr = gen_code_buf;
2042

    
2043
    args = gen_opparam_buf;
2044
    op_index = 0;
2045

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

    
2126
int tcg_gen_code(TCGContext *s, uint8_t *gen_code_buf)
2127
{
2128
#ifdef CONFIG_PROFILER
2129
    {
2130
        int n;
2131
        n = (gen_opc_ptr - gen_opc_buf);
2132
        s->op_count += n;
2133
        if (n > s->op_count_max)
2134
            s->op_count_max = n;
2135

    
2136
        s->temp_count += s->nb_temps;
2137
        if (s->nb_temps > s->temp_count_max)
2138
            s->temp_count_max = s->nb_temps;
2139
    }
2140
#endif
2141

    
2142
    tcg_gen_code_common(s, gen_code_buf, -1);
2143

    
2144
    /* flush instruction cache */
2145
    flush_icache_range((unsigned long)gen_code_buf, 
2146
                       (unsigned long)s->code_ptr);
2147
    return s->code_ptr -  gen_code_buf;
2148
}
2149

    
2150
/* Return the index of the micro operation such as the pc after is <
2151
   offset bytes from the start of the TB.  The contents of gen_code_buf must
2152
   not be changed, though writing the same values is ok.
2153
   Return -1 if not found. */
2154
int tcg_gen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, long offset)
2155
{
2156
    return tcg_gen_code_common(s, gen_code_buf, offset);
2157
}
2158

    
2159
#ifdef CONFIG_PROFILER
2160
void tcg_dump_info(FILE *f, fprintf_function cpu_fprintf)
2161
{
2162
    TCGContext *s = &tcg_ctx;
2163
    int64_t tot;
2164

    
2165
    tot = s->interm_time + s->code_time;
2166
    cpu_fprintf(f, "JIT cycles          %" PRId64 " (%0.3f s at 2.4 GHz)\n",
2167
                tot, tot / 2.4e9);
2168
    cpu_fprintf(f, "translated TBs      %" PRId64 " (aborted=%" PRId64 " %0.1f%%)\n", 
2169
                s->tb_count, 
2170
                s->tb_count1 - s->tb_count,
2171
                s->tb_count1 ? (double)(s->tb_count1 - s->tb_count) / s->tb_count1 * 100.0 : 0);
2172
    cpu_fprintf(f, "avg ops/TB          %0.1f max=%d\n", 
2173
                s->tb_count ? (double)s->op_count / s->tb_count : 0, s->op_count_max);
2174
    cpu_fprintf(f, "deleted ops/TB      %0.2f\n",
2175
                s->tb_count ? 
2176
                (double)s->del_op_count / s->tb_count : 0);
2177
    cpu_fprintf(f, "avg temps/TB        %0.2f max=%d\n",
2178
                s->tb_count ? 
2179
                (double)s->temp_count / s->tb_count : 0,
2180
                s->temp_count_max);
2181
    
2182
    cpu_fprintf(f, "cycles/op           %0.1f\n", 
2183
                s->op_count ? (double)tot / s->op_count : 0);
2184
    cpu_fprintf(f, "cycles/in byte      %0.1f\n", 
2185
                s->code_in_len ? (double)tot / s->code_in_len : 0);
2186
    cpu_fprintf(f, "cycles/out byte     %0.1f\n", 
2187
                s->code_out_len ? (double)tot / s->code_out_len : 0);
2188
    if (tot == 0)
2189
        tot = 1;
2190
    cpu_fprintf(f, "  gen_interm time   %0.1f%%\n", 
2191
                (double)s->interm_time / tot * 100.0);
2192
    cpu_fprintf(f, "  gen_code time     %0.1f%%\n", 
2193
                (double)s->code_time / tot * 100.0);
2194
    cpu_fprintf(f, "liveness/code time  %0.1f%%\n", 
2195
                (double)s->la_time / (s->code_time ? s->code_time : 1) * 100.0);
2196
    cpu_fprintf(f, "cpu_restore count   %" PRId64 "\n",
2197
                s->restore_count);
2198
    cpu_fprintf(f, "  avg cycles        %0.1f\n",
2199
                s->restore_count ? (double)s->restore_time / s->restore_count : 0);
2200

    
2201
    dump_op_count();
2202
}
2203
#else
2204
void tcg_dump_info(FILE *f, fprintf_function cpu_fprintf)
2205
{
2206
    cpu_fprintf(f, "[TCG profiler not compiled]\n");
2207
}
2208
#endif