Statistics
| Branch: | Revision:

root / tcg / tcg.c @ 6b64b624

History | View | Annotate | Download (65.6 kB)

1
/*
2
 * Tiny Code Generator for QEMU
3
 *
4
 * Copyright (c) 2008 Fabrice Bellard
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7
 * of this software and associated documentation files (the "Software"), to deal
8
 * in the Software without restriction, including without limitation the rights
9
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
 * copies of the Software, and to permit persons to whom the Software is
11
 * furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
 * THE SOFTWARE.
23
 */
24

    
25
/* define it to use liveness analysis (better code) */
26
#define USE_LIVENESS_ANALYSIS
27

    
28
#include "config.h"
29

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

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

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

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

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

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

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

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

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

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

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

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

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

    
101
/* label relocation processing */
102

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

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

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

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

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

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

    
159
#include "tcg-target.c"
160

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
685
    *gen_opparam_ptr++ = flags;
686

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

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

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

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

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

    
752

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1115
#if 0
1116
        {
1117
            int i;
1118

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

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

    
1153
#ifdef USE_LIVENESS_ANALYSIS
1154

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

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

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

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

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

    
1210
    nb_ops = gen_opc_ptr - gen_opc_buf;
1211

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1478
    tcg_regset_andnot(reg_ct, reg1, reg2);
1479

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

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

    
1496
    tcg_abort();
1497
}
1498

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

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

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

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

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

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

    
1563
    save_globals(s, allocated_regs);
1564
}
1565

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

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

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

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

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

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

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

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

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

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

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

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

    
1810
#ifdef TCG_TARGET_STACK_GROWSUP
1811
#define STACK_DIR(x) (-(x))
1812
#else
1813
#define STACK_DIR(x) (x)
1814
#endif
1815

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

    
1828
    arg = *args++;
1829

    
1830
    nb_oargs = arg >> 16;
1831
    nb_iargs = arg & 0xffff;
1832
    nb_params = nb_iargs - 1;
1833

    
1834
    flags = args[nb_oargs + nb_iargs];
1835

    
1836
    nb_regs = tcg_target_get_call_iarg_regs_count(flags);
1837
    if (nb_regs > nb_params)
1838
        nb_regs = nb_params;
1839

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

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

    
1965
    tcg_out_op(s, opc, &func_arg, &const_func_arg);
1966
    
1967
    if (allocate_args) {
1968
        tcg_out_addi(s, TCG_REG_CALL_STACK, STACK_DIR(call_stack_size));
1969
    }
1970

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

    
1994
#ifdef CONFIG_PROFILER
1995

    
1996
static int64_t tcg_table_op_count[NB_OPS];
1997

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

    
2010

    
2011
static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
2012
                                      long search_pc)
2013
{
2014
    TCGOpcode opc;
2015
    int op_index;
2016
    const TCGOpDef *def;
2017
    unsigned int dead_args;
2018
    const TCGArg *args;
2019

    
2020
#ifdef DEBUG_DISAS
2021
    if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
2022
        qemu_log("OP:\n");
2023
        tcg_dump_ops(s, logfile);
2024
        qemu_log("\n");
2025
    }
2026
#endif
2027

    
2028
#ifdef CONFIG_PROFILER
2029
    s->la_time -= profile_getclock();
2030
#endif
2031
    tcg_liveness_analysis(s);
2032
#ifdef CONFIG_PROFILER
2033
    s->la_time += profile_getclock();
2034
#endif
2035

    
2036
#ifdef DEBUG_DISAS
2037
    if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_OPT))) {
2038
        qemu_log("OP after liveness analysis:\n");
2039
        tcg_dump_ops(s, logfile);
2040
        qemu_log("\n");
2041
    }
2042
#endif
2043

    
2044
    tcg_reg_alloc_start(s);
2045

    
2046
    s->code_buf = gen_code_buf;
2047
    s->code_ptr = gen_code_buf;
2048

    
2049
    args = gen_opparam_buf;
2050
    op_index = 0;
2051

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

    
2132
int tcg_gen_code(TCGContext *s, uint8_t *gen_code_buf)
2133
{
2134
#ifdef CONFIG_PROFILER
2135
    {
2136
        int n;
2137
        n = (gen_opc_ptr - gen_opc_buf);
2138
        s->op_count += n;
2139
        if (n > s->op_count_max)
2140
            s->op_count_max = n;
2141

    
2142
        s->temp_count += s->nb_temps;
2143
        if (s->nb_temps > s->temp_count_max)
2144
            s->temp_count_max = s->nb_temps;
2145
    }
2146
#endif
2147

    
2148
    tcg_gen_code_common(s, gen_code_buf, -1);
2149

    
2150
    /* flush instruction cache */
2151
    flush_icache_range((unsigned long)gen_code_buf, 
2152
                       (unsigned long)s->code_ptr);
2153
    return s->code_ptr -  gen_code_buf;
2154
}
2155

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

    
2165
#ifdef CONFIG_PROFILER
2166
void tcg_dump_info(FILE *f, fprintf_function cpu_fprintf)
2167
{
2168
    TCGContext *s = &tcg_ctx;
2169
    int64_t tot;
2170

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

    
2207
    dump_op_count();
2208
}
2209
#else
2210
void tcg_dump_info(FILE *f, fprintf_function cpu_fprintf)
2211
{
2212
    cpu_fprintf(f, "[TCG profiler not compiled]\n");
2213
}
2214
#endif