Statistics
| Branch: | Revision:

root / tcg / tcg.c @ 1d2699ae

History | View | Annotate | Download (61.9 kB)

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

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

    
28
#include "config.h"
29

    
30
#ifndef CONFIG_DEBUG_TCG
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

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

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

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

    
65
static void patch_reloc(uint8_t *code_ptr, int type, 
66
                        tcg_target_long value, tcg_target_long addend);
67

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

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

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

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

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

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

    
100
/* label relocation processing */
101

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

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

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

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

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

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

    
158
#include "tcg-target.c"
159

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

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

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

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

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

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

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

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

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

    
270
    gen_opc_ptr = gen_opc_buf;
271
    gen_opparam_ptr = gen_opparam_buf;
272
}
273

    
274
static inline void tcg_temp_alloc(TCGContext *s, int n)
275
{
276
    if (n > TCG_MAX_TEMPS)
277
        tcg_abort();
278
}
279

    
280
static inline int tcg_global_reg_new_internal(TCGType type, int reg,
281
                                              const char *name)
282
{
283
    TCGContext *s = &tcg_ctx;
284
    TCGTemp *ts;
285
    int idx;
286

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

    
306
TCGv_i32 tcg_global_reg_new_i32(int reg, const char *name)
307
{
308
    int idx;
309

    
310
    idx = tcg_global_reg_new_internal(TCG_TYPE_I32, reg, name);
311
    return MAKE_TCGV_I32(idx);
312
}
313

    
314
TCGv_i64 tcg_global_reg_new_i64(int reg, const char *name)
315
{
316
    int idx;
317

    
318
    idx = tcg_global_reg_new_internal(TCG_TYPE_I64, reg, name);
319
    return MAKE_TCGV_I64(idx);
320
}
321

    
322
static inline int tcg_global_mem_new_internal(TCGType type, int reg,
323
                                              tcg_target_long offset,
324
                                              const char *name)
325
{
326
    TCGContext *s = &tcg_ctx;
327
    TCGTemp *ts;
328
    int idx;
329

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

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

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

    
383
TCGv_i32 tcg_global_mem_new_i32(int reg, tcg_target_long offset,
384
                                const char *name)
385
{
386
    int idx;
387

    
388
    idx = tcg_global_mem_new_internal(TCG_TYPE_I32, reg, offset, name);
389
    return MAKE_TCGV_I32(idx);
390
}
391

    
392
TCGv_i64 tcg_global_mem_new_i64(int reg, tcg_target_long offset,
393
                                const char *name)
394
{
395
    int idx;
396

    
397
    idx = tcg_global_mem_new_internal(TCG_TYPE_I64, reg, offset, name);
398
    return MAKE_TCGV_I64(idx);
399
}
400

    
401
static inline int tcg_temp_new_internal(TCGType type, int temp_local)
402
{
403
    TCGContext *s = &tcg_ctx;
404
    TCGTemp *ts;
405
    int idx, k;
406

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

    
452
TCGv_i32 tcg_temp_new_internal_i32(int temp_local)
453
{
454
    int idx;
455

    
456
    idx = tcg_temp_new_internal(TCG_TYPE_I32, temp_local);
457
    return MAKE_TCGV_I32(idx);
458
}
459

    
460
TCGv_i64 tcg_temp_new_internal_i64(int temp_local)
461
{
462
    int idx;
463

    
464
    idx = tcg_temp_new_internal(TCG_TYPE_I64, temp_local);
465
    return MAKE_TCGV_I64(idx);
466
}
467

    
468
static inline void tcg_temp_free_internal(int idx)
469
{
470
    TCGContext *s = &tcg_ctx;
471
    TCGTemp *ts;
472
    int k;
473

    
474
    assert(idx >= s->nb_globals && idx < s->nb_temps);
475
    ts = &s->temps[idx];
476
    assert(ts->temp_allocated != 0);
477
    ts->temp_allocated = 0;
478
    k = ts->base_type;
479
    if (ts->temp_local)
480
        k += TCG_TYPE_COUNT;
481
    ts->next_free_temp = s->first_free_temp[k];
482
    s->first_free_temp[k] = idx;
483
}
484

    
485
void tcg_temp_free_i32(TCGv_i32 arg)
486
{
487
    tcg_temp_free_internal(GET_TCGV_I32(arg));
488
}
489

    
490
void tcg_temp_free_i64(TCGv_i64 arg)
491
{
492
    tcg_temp_free_internal(GET_TCGV_I64(arg));
493
}
494

    
495
TCGv_i32 tcg_const_i32(int32_t val)
496
{
497
    TCGv_i32 t0;
498
    t0 = tcg_temp_new_i32();
499
    tcg_gen_movi_i32(t0, val);
500
    return t0;
501
}
502

    
503
TCGv_i64 tcg_const_i64(int64_t val)
504
{
505
    TCGv_i64 t0;
506
    t0 = tcg_temp_new_i64();
507
    tcg_gen_movi_i64(t0, val);
508
    return t0;
509
}
510

    
511
TCGv_i32 tcg_const_local_i32(int32_t val)
512
{
513
    TCGv_i32 t0;
514
    t0 = tcg_temp_local_new_i32();
515
    tcg_gen_movi_i32(t0, val);
516
    return t0;
517
}
518

    
519
TCGv_i64 tcg_const_local_i64(int64_t val)
520
{
521
    TCGv_i64 t0;
522
    t0 = tcg_temp_local_new_i64();
523
    tcg_gen_movi_i64(t0, val);
524
    return t0;
525
}
526

    
527
void tcg_register_helper(void *func, const char *name)
528
{
529
    TCGContext *s = &tcg_ctx;
530
    int n;
531
    if ((s->nb_helpers + 1) > s->allocated_helpers) {
532
        n = s->allocated_helpers;
533
        if (n == 0) {
534
            n = 4;
535
        } else {
536
            n *= 2;
537
        }
538
        s->helpers = realloc(s->helpers, n * sizeof(TCGHelperInfo));
539
        s->allocated_helpers = n;
540
    }
541
    s->helpers[s->nb_helpers].func = (tcg_target_ulong)func;
542
    s->helpers[s->nb_helpers].name = name;
543
    s->nb_helpers++;
544
}
545

    
546
/* Note: we convert the 64 bit args to 32 bit and do some alignment
547
   and endian swap. Maybe it would be better to do the alignment
548
   and endian swap in tcg_reg_alloc_call(). */
549
void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags,
550
                   int sizemask, TCGArg ret, int nargs, TCGArg *args)
551
{
552
    int call_type;
553
    int i;
554
    int real_args;
555
    int nb_rets;
556
    TCGArg *nparam;
557
    *gen_opc_ptr++ = INDEX_op_call;
558
    nparam = gen_opparam_ptr++;
559
    call_type = (flags & TCG_CALL_TYPE_MASK);
560
    if (ret != TCG_CALL_DUMMY_ARG) {
561
#if TCG_TARGET_REG_BITS < 64
562
        if (sizemask & 1) {
563
#ifdef TCG_TARGET_WORDS_BIGENDIAN
564
            *gen_opparam_ptr++ = ret + 1;
565
            *gen_opparam_ptr++ = ret;
566
#else
567
            *gen_opparam_ptr++ = ret;
568
            *gen_opparam_ptr++ = ret + 1;
569
#endif
570
            nb_rets = 2;
571
        } else
572
#endif
573
        {
574
            *gen_opparam_ptr++ = ret;
575
            nb_rets = 1;
576
        }
577
    } else {
578
        nb_rets = 0;
579
    }
580
    real_args = 0;
581
    for (i = 0; i < nargs; i++) {
582
#if TCG_TARGET_REG_BITS < 64
583
        if (sizemask & (2 << i)) {
584
#ifdef TCG_TARGET_I386
585
            /* REGPARM case: if the third parameter is 64 bit, it is
586
               allocated on the stack */
587
            if (i == 2 && call_type == TCG_CALL_TYPE_REGPARM) {
588
                call_type = TCG_CALL_TYPE_REGPARM_2;
589
                flags = (flags & ~TCG_CALL_TYPE_MASK) | call_type;
590
            }
591
#endif
592
#ifdef TCG_TARGET_CALL_ALIGN_ARGS
593
            /* some targets want aligned 64 bit args */
594
            if (real_args & 1) {
595
                *gen_opparam_ptr++ = TCG_CALL_DUMMY_ARG;
596
                real_args++;
597
            }
598
#endif
599
#ifdef TCG_TARGET_WORDS_BIGENDIAN
600
            *gen_opparam_ptr++ = args[i] + 1;
601
            *gen_opparam_ptr++ = args[i];
602
#else
603
            *gen_opparam_ptr++ = args[i];
604
            *gen_opparam_ptr++ = args[i] + 1;
605
#endif
606
            real_args += 2;
607
        } else
608
#endif
609
        {
610
            *gen_opparam_ptr++ = args[i];
611
            real_args++;
612
        }
613
    }
614
    *gen_opparam_ptr++ = GET_TCGV_PTR(func);
615

    
616
    *gen_opparam_ptr++ = flags;
617

    
618
    *nparam = (nb_rets << 16) | (real_args + 1);
619

    
620
    /* total parameters, needed to go backward in the instruction stream */
621
    *gen_opparam_ptr++ = 1 + nb_rets + real_args + 3;
622
}
623

    
624
#if TCG_TARGET_REG_BITS == 32
625
void tcg_gen_shifti_i64(TCGv_i64 ret, TCGv_i64 arg1,
626
                        int c, int right, int arith)
627
{
628
    if (c == 0) {
629
        tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg1));
630
        tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
631
    } else if (c >= 32) {
632
        c -= 32;
633
        if (right) {
634
            if (arith) {
635
                tcg_gen_sari_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
636
                tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 31);
637
            } else {
638
                tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
639
                tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
640
            }
641
        } else {
642
            tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_LOW(arg1), c);
643
            tcg_gen_movi_i32(TCGV_LOW(ret), 0);
644
        }
645
    } else {
646
        TCGv_i32 t0, t1;
647

    
648
        t0 = tcg_temp_new_i32();
649
        t1 = tcg_temp_new_i32();
650
        if (right) {
651
            tcg_gen_shli_i32(t0, TCGV_HIGH(arg1), 32 - c);
652
            if (arith)
653
                tcg_gen_sari_i32(t1, TCGV_HIGH(arg1), c);
654
            else
655
                tcg_gen_shri_i32(t1, TCGV_HIGH(arg1), c);
656
            tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_LOW(arg1), c);
657
            tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(ret), t0);
658
            tcg_gen_mov_i32(TCGV_HIGH(ret), t1);
659
        } else {
660
            tcg_gen_shri_i32(t0, TCGV_LOW(arg1), 32 - c);
661
            /* Note: ret can be the same as arg1, so we use t1 */
662
            tcg_gen_shli_i32(t1, TCGV_LOW(arg1), c);
663
            tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c);
664
            tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t0);
665
            tcg_gen_mov_i32(TCGV_LOW(ret), t1);
666
        }
667
        tcg_temp_free_i32(t0);
668
        tcg_temp_free_i32(t1);
669
    }
670
}
671
#endif
672

    
673

    
674
static void tcg_reg_alloc_start(TCGContext *s)
675
{
676
    int i;
677
    TCGTemp *ts;
678
    for(i = 0; i < s->nb_globals; i++) {
679
        ts = &s->temps[i];
680
        if (ts->fixed_reg) {
681
            ts->val_type = TEMP_VAL_REG;
682
        } else {
683
            ts->val_type = TEMP_VAL_MEM;
684
        }
685
    }
686
    for(i = s->nb_globals; i < s->nb_temps; i++) {
687
        ts = &s->temps[i];
688
        ts->val_type = TEMP_VAL_DEAD;
689
        ts->mem_allocated = 0;
690
        ts->fixed_reg = 0;
691
    }
692
    for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
693
        s->reg_to_temp[i] = -1;
694
    }
695
}
696

    
697
static char *tcg_get_arg_str_idx(TCGContext *s, char *buf, int buf_size,
698
                                 int idx)
699
{
700
    TCGTemp *ts;
701

    
702
    ts = &s->temps[idx];
703
    if (idx < s->nb_globals) {
704
        pstrcpy(buf, buf_size, ts->name);
705
    } else {
706
        if (ts->temp_local) 
707
            snprintf(buf, buf_size, "loc%d", idx - s->nb_globals);
708
        else
709
            snprintf(buf, buf_size, "tmp%d", idx - s->nb_globals);
710
    }
711
    return buf;
712
}
713

    
714
char *tcg_get_arg_str_i32(TCGContext *s, char *buf, int buf_size, TCGv_i32 arg)
715
{
716
    return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I32(arg));
717
}
718

    
719
char *tcg_get_arg_str_i64(TCGContext *s, char *buf, int buf_size, TCGv_i64 arg)
720
{
721
    return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I64(arg));
722
}
723

    
724
static int helper_cmp(const void *p1, const void *p2)
725
{
726
    const TCGHelperInfo *th1 = p1;
727
    const TCGHelperInfo *th2 = p2;
728
    if (th1->func < th2->func)
729
        return -1;
730
    else if (th1->func == th2->func)
731
        return 0;
732
    else
733
        return 1;
734
}
735

    
736
/* find helper definition (Note: A hash table would be better) */
737
static TCGHelperInfo *tcg_find_helper(TCGContext *s, tcg_target_ulong val)
738
{
739
    int m, m_min, m_max;
740
    TCGHelperInfo *th;
741
    tcg_target_ulong v;
742

    
743
    if (unlikely(!s->helpers_sorted)) {
744
        qsort(s->helpers, s->nb_helpers, sizeof(TCGHelperInfo), 
745
              helper_cmp);
746
        s->helpers_sorted = 1;
747
    }
748

    
749
    /* binary search */
750
    m_min = 0;
751
    m_max = s->nb_helpers - 1;
752
    while (m_min <= m_max) {
753
        m = (m_min + m_max) >> 1;
754
        th = &s->helpers[m];
755
        v = th->func;
756
        if (v == val)
757
            return th;
758
        else if (val < v) {
759
            m_max = m - 1;
760
        } else {
761
            m_min = m + 1;
762
        }
763
    }
764
    return NULL;
765
}
766

    
767
static const char * const cond_name[] =
768
{
769
    [TCG_COND_EQ] = "eq",
770
    [TCG_COND_NE] = "ne",
771
    [TCG_COND_LT] = "lt",
772
    [TCG_COND_GE] = "ge",
773
    [TCG_COND_LE] = "le",
774
    [TCG_COND_GT] = "gt",
775
    [TCG_COND_LTU] = "ltu",
776
    [TCG_COND_GEU] = "geu",
777
    [TCG_COND_LEU] = "leu",
778
    [TCG_COND_GTU] = "gtu"
779
};
780

    
781
void tcg_dump_ops(TCGContext *s, FILE *outfile)
782
{
783
    const uint16_t *opc_ptr;
784
    const TCGArg *args;
785
    TCGArg arg;
786
    int c, i, k, nb_oargs, nb_iargs, nb_cargs, first_insn;
787
    const TCGOpDef *def;
788
    char buf[128];
789

    
790
    first_insn = 1;
791
    opc_ptr = gen_opc_buf;
792
    args = gen_opparam_buf;
793
    while (opc_ptr < gen_opc_ptr) {
794
        c = *opc_ptr++;
795
        def = &tcg_op_defs[c];
796
        if (c == INDEX_op_debug_insn_start) {
797
            uint64_t pc;
798
#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
799
            pc = ((uint64_t)args[1] << 32) | args[0];
800
#else
801
            pc = args[0];
802
#endif
803
            if (!first_insn) 
804
                fprintf(outfile, "\n");
805
            fprintf(outfile, " ---- 0x%" PRIx64, pc);
806
            first_insn = 0;
807
            nb_oargs = def->nb_oargs;
808
            nb_iargs = def->nb_iargs;
809
            nb_cargs = def->nb_cargs;
810
        } else if (c == INDEX_op_call) {
811
            TCGArg arg;
812

    
813
            /* variable number of arguments */
814
            arg = *args++;
815
            nb_oargs = arg >> 16;
816
            nb_iargs = arg & 0xffff;
817
            nb_cargs = def->nb_cargs;
818

    
819
            fprintf(outfile, " %s ", def->name);
820

    
821
            /* function name */
822
            fprintf(outfile, "%s",
823
                    tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + nb_iargs - 1]));
824
            /* flags */
825
            fprintf(outfile, ",$0x%" TCG_PRIlx,
826
                    args[nb_oargs + nb_iargs]);
827
            /* nb out args */
828
            fprintf(outfile, ",$%d", nb_oargs);
829
            for(i = 0; i < nb_oargs; i++) {
830
                fprintf(outfile, ",");
831
                fprintf(outfile, "%s",
832
                        tcg_get_arg_str_idx(s, buf, sizeof(buf), args[i]));
833
            }
834
            for(i = 0; i < (nb_iargs - 1); i++) {
835
                fprintf(outfile, ",");
836
                if (args[nb_oargs + i] == TCG_CALL_DUMMY_ARG) {
837
                    fprintf(outfile, "<dummy>");
838
                } else {
839
                    fprintf(outfile, "%s",
840
                            tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + i]));
841
                }
842
            }
843
        } else if (c == INDEX_op_movi_i32 
844
#if TCG_TARGET_REG_BITS == 64
845
                   || c == INDEX_op_movi_i64
846
#endif
847
                   ) {
848
            tcg_target_ulong val;
849
            TCGHelperInfo *th;
850

    
851
            nb_oargs = def->nb_oargs;
852
            nb_iargs = def->nb_iargs;
853
            nb_cargs = def->nb_cargs;
854
            fprintf(outfile, " %s %s,$", def->name, 
855
                    tcg_get_arg_str_idx(s, buf, sizeof(buf), args[0]));
856
            val = args[1];
857
            th = tcg_find_helper(s, val);
858
            if (th) {
859
                fprintf(outfile, "%s", th->name);
860
            } else {
861
                if (c == INDEX_op_movi_i32)
862
                    fprintf(outfile, "0x%x", (uint32_t)val);
863
                else
864
                    fprintf(outfile, "0x%" PRIx64 , (uint64_t)val);
865
            }
866
        } else {
867
            fprintf(outfile, " %s ", def->name);
868
            if (c == INDEX_op_nopn) {
869
                /* variable number of arguments */
870
                nb_cargs = *args;
871
                nb_oargs = 0;
872
                nb_iargs = 0;
873
            } else {
874
                nb_oargs = def->nb_oargs;
875
                nb_iargs = def->nb_iargs;
876
                nb_cargs = def->nb_cargs;
877
            }
878
            
879
            k = 0;
880
            for(i = 0; i < nb_oargs; i++) {
881
                if (k != 0)
882
                    fprintf(outfile, ",");
883
                fprintf(outfile, "%s",
884
                        tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
885
            }
886
            for(i = 0; i < nb_iargs; i++) {
887
                if (k != 0)
888
                    fprintf(outfile, ",");
889
                fprintf(outfile, "%s",
890
                        tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
891
            }
892
            switch (c) {
893
            case INDEX_op_brcond_i32:
894
#if TCG_TARGET_REG_BITS == 32
895
            case INDEX_op_brcond2_i32:
896
#elif TCG_TARGET_REG_BITS == 64
897
            case INDEX_op_brcond_i64:
898
#endif
899
            case INDEX_op_setcond_i32:
900
#if TCG_TARGET_REG_BITS == 32
901
            case INDEX_op_setcond2_i32:
902
#elif TCG_TARGET_REG_BITS == 64
903
            case INDEX_op_setcond_i64:
904
#endif
905
                if (args[k] < ARRAY_SIZE(cond_name) && cond_name[args[k]])
906
                    fprintf(outfile, ",%s", cond_name[args[k++]]);
907
                else
908
                    fprintf(outfile, ",$0x%" TCG_PRIlx, args[k++]);
909
                i = 1;
910
                break;
911
            default:
912
                i = 0;
913
                break;
914
            }
915
            for(; i < nb_cargs; i++) {
916
                if (k != 0)
917
                    fprintf(outfile, ",");
918
                arg = args[k++];
919
                fprintf(outfile, "$0x%" TCG_PRIlx, arg);
920
            }
921
        }
922
        fprintf(outfile, "\n");
923
        args += nb_iargs + nb_oargs + nb_cargs;
924
    }
925
}
926

    
927
/* we give more priority to constraints with less registers */
928
static int get_constraint_priority(const TCGOpDef *def, int k)
929
{
930
    const TCGArgConstraint *arg_ct;
931

    
932
    int i, n;
933
    arg_ct = &def->args_ct[k];
934
    if (arg_ct->ct & TCG_CT_ALIAS) {
935
        /* an alias is equivalent to a single register */
936
        n = 1;
937
    } else {
938
        if (!(arg_ct->ct & TCG_CT_REG))
939
            return 0;
940
        n = 0;
941
        for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
942
            if (tcg_regset_test_reg(arg_ct->u.regs, i))
943
                n++;
944
        }
945
    }
946
    return TCG_TARGET_NB_REGS - n + 1;
947
}
948

    
949
/* sort from highest priority to lowest */
950
static void sort_constraints(TCGOpDef *def, int start, int n)
951
{
952
    int i, j, p1, p2, tmp;
953

    
954
    for(i = 0; i < n; i++)
955
        def->sorted_args[start + i] = start + i;
956
    if (n <= 1)
957
        return;
958
    for(i = 0; i < n - 1; i++) {
959
        for(j = i + 1; j < n; j++) {
960
            p1 = get_constraint_priority(def, def->sorted_args[start + i]);
961
            p2 = get_constraint_priority(def, def->sorted_args[start + j]);
962
            if (p1 < p2) {
963
                tmp = def->sorted_args[start + i];
964
                def->sorted_args[start + i] = def->sorted_args[start + j];
965
                def->sorted_args[start + j] = tmp;
966
            }
967
        }
968
    }
969
}
970

    
971
void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs)
972
{
973
    int op;
974
    TCGOpDef *def;
975
    const char *ct_str;
976
    int i, nb_args;
977

    
978
    for(;;) {
979
        if (tdefs->op < 0)
980
            break;
981
        op = tdefs->op;
982
        assert(op >= 0 && op < NB_OPS);
983
        def = &tcg_op_defs[op];
984
        nb_args = def->nb_iargs + def->nb_oargs;
985
        for(i = 0; i < nb_args; i++) {
986
            ct_str = tdefs->args_ct_str[i];
987
            tcg_regset_clear(def->args_ct[i].u.regs);
988
            def->args_ct[i].ct = 0;
989
            if (ct_str[0] >= '0' && ct_str[0] <= '9') {
990
                int oarg;
991
                oarg = ct_str[0] - '0';
992
                assert(oarg < def->nb_oargs);
993
                assert(def->args_ct[oarg].ct & TCG_CT_REG);
994
                /* TCG_CT_ALIAS is for the output arguments. The input
995
                   argument is tagged with TCG_CT_IALIAS. */
996
                def->args_ct[i] = def->args_ct[oarg];
997
                def->args_ct[oarg].ct = TCG_CT_ALIAS;
998
                def->args_ct[oarg].alias_index = i;
999
                def->args_ct[i].ct |= TCG_CT_IALIAS;
1000
                def->args_ct[i].alias_index = oarg;
1001
            } else {
1002
                for(;;) {
1003
                    if (*ct_str == '\0')
1004
                        break;
1005
                    switch(*ct_str) {
1006
                    case 'i':
1007
                        def->args_ct[i].ct |= TCG_CT_CONST;
1008
                        ct_str++;
1009
                        break;
1010
                    default:
1011
                        if (target_parse_constraint(&def->args_ct[i], &ct_str) < 0) {
1012
                            fprintf(stderr, "Invalid constraint '%s' for arg %d of operation '%s'\n",
1013
                                    ct_str, i, def->name);
1014
                            exit(1);
1015
                        }
1016
                    }
1017
                }
1018
            }
1019
        }
1020

    
1021
        /* sort the constraints (XXX: this is just an heuristic) */
1022
        sort_constraints(def, 0, def->nb_oargs);
1023
        sort_constraints(def, def->nb_oargs, def->nb_iargs);
1024

    
1025
#if 0
1026
        {
1027
            int i;
1028

1029
            printf("%s: sorted=", def->name);
1030
            for(i = 0; i < def->nb_oargs + def->nb_iargs; i++)
1031
                printf(" %d", def->sorted_args[i]);
1032
            printf("\n");
1033
        }
1034
#endif
1035
        tdefs++;
1036
    }
1037

    
1038
}
1039

    
1040
#ifdef USE_LIVENESS_ANALYSIS
1041

    
1042
/* set a nop for an operation using 'nb_args' */
1043
static inline void tcg_set_nop(TCGContext *s, uint16_t *opc_ptr, 
1044
                               TCGArg *args, int nb_args)
1045
{
1046
    if (nb_args == 0) {
1047
        *opc_ptr = INDEX_op_nop;
1048
    } else {
1049
        *opc_ptr = INDEX_op_nopn;
1050
        args[0] = nb_args;
1051
        args[nb_args - 1] = nb_args;
1052
    }
1053
}
1054

    
1055
/* liveness analysis: end of function: globals are live, temps are
1056
   dead. */
1057
/* XXX: at this stage, not used as there would be little gains because
1058
   most TBs end with a conditional jump. */
1059
static inline void tcg_la_func_end(TCGContext *s, uint8_t *dead_temps)
1060
{
1061
    memset(dead_temps, 0, s->nb_globals);
1062
    memset(dead_temps + s->nb_globals, 1, s->nb_temps - s->nb_globals);
1063
}
1064

    
1065
/* liveness analysis: end of basic block: globals are live, temps are
1066
   dead, local temps are live. */
1067
static inline void tcg_la_bb_end(TCGContext *s, uint8_t *dead_temps)
1068
{
1069
    int i;
1070
    TCGTemp *ts;
1071

    
1072
    memset(dead_temps, 0, s->nb_globals);
1073
    ts = &s->temps[s->nb_globals];
1074
    for(i = s->nb_globals; i < s->nb_temps; i++) {
1075
        if (ts->temp_local)
1076
            dead_temps[i] = 0;
1077
        else
1078
            dead_temps[i] = 1;
1079
        ts++;
1080
    }
1081
}
1082

    
1083
/* Liveness analysis : update the opc_dead_iargs array to tell if a
1084
   given input arguments is dead. Instructions updating dead
1085
   temporaries are removed. */
1086
static void tcg_liveness_analysis(TCGContext *s)
1087
{
1088
    int i, op_index, op, nb_args, nb_iargs, nb_oargs, arg, nb_ops;
1089
    TCGArg *args;
1090
    const TCGOpDef *def;
1091
    uint8_t *dead_temps;
1092
    unsigned int dead_iargs;
1093
    
1094
    gen_opc_ptr++; /* skip end */
1095

    
1096
    nb_ops = gen_opc_ptr - gen_opc_buf;
1097

    
1098
    s->op_dead_iargs = tcg_malloc(nb_ops * sizeof(uint16_t));
1099
    
1100
    dead_temps = tcg_malloc(s->nb_temps);
1101
    memset(dead_temps, 1, s->nb_temps);
1102

    
1103
    args = gen_opparam_ptr;
1104
    op_index = nb_ops - 1;
1105
    while (op_index >= 0) {
1106
        op = gen_opc_buf[op_index];
1107
        def = &tcg_op_defs[op];
1108
        switch(op) {
1109
        case INDEX_op_call:
1110
            {
1111
                int call_flags;
1112

    
1113
                nb_args = args[-1];
1114
                args -= nb_args;
1115
                nb_iargs = args[0] & 0xffff;
1116
                nb_oargs = args[0] >> 16;
1117
                args++;
1118
                call_flags = args[nb_oargs + nb_iargs];
1119

    
1120
                /* pure functions can be removed if their result is not
1121
                   used */
1122
                if (call_flags & TCG_CALL_PURE) {
1123
                    for(i = 0; i < nb_oargs; i++) {
1124
                        arg = args[i];
1125
                        if (!dead_temps[arg])
1126
                            goto do_not_remove_call;
1127
                    }
1128
                    tcg_set_nop(s, gen_opc_buf + op_index, 
1129
                                args - 1, nb_args);
1130
                } else {
1131
                do_not_remove_call:
1132

    
1133
                    /* output args are dead */
1134
                    for(i = 0; i < nb_oargs; i++) {
1135
                        arg = args[i];
1136
                        dead_temps[arg] = 1;
1137
                    }
1138
                    
1139
                    if (!(call_flags & TCG_CALL_CONST)) {
1140
                        /* globals are live (they may be used by the call) */
1141
                        memset(dead_temps, 0, s->nb_globals);
1142
                    }
1143

    
1144
                    /* input args are live */
1145
                    dead_iargs = 0;
1146
                    for(i = 0; i < nb_iargs; i++) {
1147
                        arg = args[i + nb_oargs];
1148
                        if (arg != TCG_CALL_DUMMY_ARG) {
1149
                            if (dead_temps[arg]) {
1150
                                dead_iargs |= (1 << i);
1151
                            }
1152
                            dead_temps[arg] = 0;
1153
                        }
1154
                    }
1155
                    s->op_dead_iargs[op_index] = dead_iargs;
1156
                }
1157
                args--;
1158
            }
1159
            break;
1160
        case INDEX_op_set_label:
1161
            args--;
1162
            /* mark end of basic block */
1163
            tcg_la_bb_end(s, dead_temps);
1164
            break;
1165
        case INDEX_op_debug_insn_start:
1166
            args -= def->nb_args;
1167
            break;
1168
        case INDEX_op_nopn:
1169
            nb_args = args[-1];
1170
            args -= nb_args;
1171
            break;
1172
        case INDEX_op_discard:
1173
            args--;
1174
            /* mark the temporary as dead */
1175
            dead_temps[args[0]] = 1;
1176
            break;
1177
        case INDEX_op_end:
1178
            break;
1179
            /* XXX: optimize by hardcoding common cases (e.g. triadic ops) */
1180
        default:
1181
            args -= def->nb_args;
1182
            nb_iargs = def->nb_iargs;
1183
            nb_oargs = def->nb_oargs;
1184

    
1185
            /* Test if the operation can be removed because all
1186
               its outputs are dead. We assume that nb_oargs == 0
1187
               implies side effects */
1188
            if (!(def->flags & TCG_OPF_SIDE_EFFECTS) && nb_oargs != 0) {
1189
                for(i = 0; i < nb_oargs; i++) {
1190
                    arg = args[i];
1191
                    if (!dead_temps[arg])
1192
                        goto do_not_remove;
1193
                }
1194
                tcg_set_nop(s, gen_opc_buf + op_index, args, def->nb_args);
1195
#ifdef CONFIG_PROFILER
1196
                s->del_op_count++;
1197
#endif
1198
            } else {
1199
            do_not_remove:
1200

    
1201
                /* output args are dead */
1202
                for(i = 0; i < nb_oargs; i++) {
1203
                    arg = args[i];
1204
                    dead_temps[arg] = 1;
1205
                }
1206

    
1207
                /* if end of basic block, update */
1208
                if (def->flags & TCG_OPF_BB_END) {
1209
                    tcg_la_bb_end(s, dead_temps);
1210
                } else if (def->flags & TCG_OPF_CALL_CLOBBER) {
1211
                    /* globals are live */
1212
                    memset(dead_temps, 0, s->nb_globals);
1213
                }
1214

    
1215
                /* input args are live */
1216
                dead_iargs = 0;
1217
                for(i = 0; i < nb_iargs; i++) {
1218
                    arg = args[i + nb_oargs];
1219
                    if (dead_temps[arg]) {
1220
                        dead_iargs |= (1 << i);
1221
                    }
1222
                    dead_temps[arg] = 0;
1223
                }
1224
                s->op_dead_iargs[op_index] = dead_iargs;
1225
            }
1226
            break;
1227
        }
1228
        op_index--;
1229
    }
1230

    
1231
    if (args != gen_opparam_buf)
1232
        tcg_abort();
1233
}
1234
#else
1235
/* dummy liveness analysis */
1236
void tcg_liveness_analysis(TCGContext *s)
1237
{
1238
    int nb_ops;
1239
    nb_ops = gen_opc_ptr - gen_opc_buf;
1240

    
1241
    s->op_dead_iargs = tcg_malloc(nb_ops * sizeof(uint16_t));
1242
    memset(s->op_dead_iargs, 0, nb_ops * sizeof(uint16_t));
1243
}
1244
#endif
1245

    
1246
#ifndef NDEBUG
1247
static void dump_regs(TCGContext *s)
1248
{
1249
    TCGTemp *ts;
1250
    int i;
1251
    char buf[64];
1252

    
1253
    for(i = 0; i < s->nb_temps; i++) {
1254
        ts = &s->temps[i];
1255
        printf("  %10s: ", tcg_get_arg_str_idx(s, buf, sizeof(buf), i));
1256
        switch(ts->val_type) {
1257
        case TEMP_VAL_REG:
1258
            printf("%s", tcg_target_reg_names[ts->reg]);
1259
            break;
1260
        case TEMP_VAL_MEM:
1261
            printf("%d(%s)", (int)ts->mem_offset, tcg_target_reg_names[ts->mem_reg]);
1262
            break;
1263
        case TEMP_VAL_CONST:
1264
            printf("$0x%" TCG_PRIlx, ts->val);
1265
            break;
1266
        case TEMP_VAL_DEAD:
1267
            printf("D");
1268
            break;
1269
        default:
1270
            printf("???");
1271
            break;
1272
        }
1273
        printf("\n");
1274
    }
1275

    
1276
    for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
1277
        if (s->reg_to_temp[i] >= 0) {
1278
            printf("%s: %s\n", 
1279
                   tcg_target_reg_names[i], 
1280
                   tcg_get_arg_str_idx(s, buf, sizeof(buf), s->reg_to_temp[i]));
1281
        }
1282
    }
1283
}
1284

    
1285
static void check_regs(TCGContext *s)
1286
{
1287
    int reg, k;
1288
    TCGTemp *ts;
1289
    char buf[64];
1290

    
1291
    for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1292
        k = s->reg_to_temp[reg];
1293
        if (k >= 0) {
1294
            ts = &s->temps[k];
1295
            if (ts->val_type != TEMP_VAL_REG ||
1296
                ts->reg != reg) {
1297
                printf("Inconsistency for register %s:\n", 
1298
                       tcg_target_reg_names[reg]);
1299
                goto fail;
1300
            }
1301
        }
1302
    }
1303
    for(k = 0; k < s->nb_temps; k++) {
1304
        ts = &s->temps[k];
1305
        if (ts->val_type == TEMP_VAL_REG &&
1306
            !ts->fixed_reg &&
1307
            s->reg_to_temp[ts->reg] != k) {
1308
                printf("Inconsistency for temp %s:\n", 
1309
                       tcg_get_arg_str_idx(s, buf, sizeof(buf), k));
1310
        fail:
1311
                printf("reg state:\n");
1312
                dump_regs(s);
1313
                tcg_abort();
1314
        }
1315
    }
1316
}
1317
#endif
1318

    
1319
static void temp_allocate_frame(TCGContext *s, int temp)
1320
{
1321
    TCGTemp *ts;
1322
    ts = &s->temps[temp];
1323
    s->current_frame_offset = (s->current_frame_offset + sizeof(tcg_target_long) - 1) & ~(sizeof(tcg_target_long) - 1);
1324
    if (s->current_frame_offset + sizeof(tcg_target_long) > s->frame_end)
1325
        tcg_abort();
1326
    ts->mem_offset = s->current_frame_offset;
1327
    ts->mem_reg = s->frame_reg;
1328
    ts->mem_allocated = 1;
1329
    s->current_frame_offset += sizeof(tcg_target_long);
1330
}
1331

    
1332
/* free register 'reg' by spilling the corresponding temporary if necessary */
1333
static void tcg_reg_free(TCGContext *s, int reg)
1334
{
1335
    TCGTemp *ts;
1336
    int temp;
1337

    
1338
    temp = s->reg_to_temp[reg];
1339
    if (temp != -1) {
1340
        ts = &s->temps[temp];
1341
        assert(ts->val_type == TEMP_VAL_REG);
1342
        if (!ts->mem_coherent) {
1343
            if (!ts->mem_allocated) 
1344
                temp_allocate_frame(s, temp);
1345
            tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1346
        }
1347
        ts->val_type = TEMP_VAL_MEM;
1348
        s->reg_to_temp[reg] = -1;
1349
    }
1350
}
1351

    
1352
/* Allocate a register belonging to reg1 & ~reg2 */
1353
static int tcg_reg_alloc(TCGContext *s, TCGRegSet reg1, TCGRegSet reg2)
1354
{
1355
    int i, reg;
1356
    TCGRegSet reg_ct;
1357

    
1358
    tcg_regset_andnot(reg_ct, reg1, reg2);
1359

    
1360
    /* first try free registers */
1361
    for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1362
        reg = tcg_target_reg_alloc_order[i];
1363
        if (tcg_regset_test_reg(reg_ct, reg) && s->reg_to_temp[reg] == -1)
1364
            return reg;
1365
    }
1366

    
1367
    /* XXX: do better spill choice */
1368
    for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1369
        reg = tcg_target_reg_alloc_order[i];
1370
        if (tcg_regset_test_reg(reg_ct, reg)) {
1371
            tcg_reg_free(s, reg);
1372
            return reg;
1373
        }
1374
    }
1375

    
1376
    tcg_abort();
1377
}
1378

    
1379
/* save a temporary to memory. 'allocated_regs' is used in case a
1380
   temporary registers needs to be allocated to store a constant. */
1381
static void temp_save(TCGContext *s, int temp, TCGRegSet allocated_regs)
1382
{
1383
    TCGTemp *ts;
1384
    int reg;
1385

    
1386
    ts = &s->temps[temp];
1387
    if (!ts->fixed_reg) {
1388
        switch(ts->val_type) {
1389
        case TEMP_VAL_REG:
1390
            tcg_reg_free(s, ts->reg);
1391
            break;
1392
        case TEMP_VAL_DEAD:
1393
            ts->val_type = TEMP_VAL_MEM;
1394
            break;
1395
        case TEMP_VAL_CONST:
1396
            reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], 
1397
                                allocated_regs);
1398
            if (!ts->mem_allocated) 
1399
                temp_allocate_frame(s, temp);
1400
            tcg_out_movi(s, ts->type, reg, ts->val);
1401
            tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1402
            ts->val_type = TEMP_VAL_MEM;
1403
            break;
1404
        case TEMP_VAL_MEM:
1405
            break;
1406
        default:
1407
            tcg_abort();
1408
        }
1409
    }
1410
}
1411

    
1412
/* save globals to their cannonical location and assume they can be
1413
   modified be the following code. 'allocated_regs' is used in case a
1414
   temporary registers needs to be allocated to store a constant. */
1415
static void save_globals(TCGContext *s, TCGRegSet allocated_regs)
1416
{
1417
    int i;
1418

    
1419
    for(i = 0; i < s->nb_globals; i++) {
1420
        temp_save(s, i, allocated_regs);
1421
    }
1422
}
1423

    
1424
/* at the end of a basic block, we assume all temporaries are dead and
1425
   all globals are stored at their canonical location. */
1426
static void tcg_reg_alloc_bb_end(TCGContext *s, TCGRegSet allocated_regs)
1427
{
1428
    TCGTemp *ts;
1429
    int i;
1430

    
1431
    for(i = s->nb_globals; i < s->nb_temps; i++) {
1432
        ts = &s->temps[i];
1433
        if (ts->temp_local) {
1434
            temp_save(s, i, allocated_regs);
1435
        } else {
1436
            if (ts->val_type == TEMP_VAL_REG) {
1437
                s->reg_to_temp[ts->reg] = -1;
1438
            }
1439
            ts->val_type = TEMP_VAL_DEAD;
1440
        }
1441
    }
1442

    
1443
    save_globals(s, allocated_regs);
1444
}
1445

    
1446
#define IS_DEAD_IARG(n) ((dead_iargs >> (n)) & 1)
1447

    
1448
static void tcg_reg_alloc_movi(TCGContext *s, const TCGArg *args)
1449
{
1450
    TCGTemp *ots;
1451
    tcg_target_ulong val;
1452

    
1453
    ots = &s->temps[args[0]];
1454
    val = args[1];
1455

    
1456
    if (ots->fixed_reg) {
1457
        /* for fixed registers, we do not do any constant
1458
           propagation */
1459
        tcg_out_movi(s, ots->type, ots->reg, val);
1460
    } else {
1461
        /* The movi is not explicitly generated here */
1462
        if (ots->val_type == TEMP_VAL_REG)
1463
            s->reg_to_temp[ots->reg] = -1;
1464
        ots->val_type = TEMP_VAL_CONST;
1465
        ots->val = val;
1466
    }
1467
}
1468

    
1469
static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
1470
                              const TCGArg *args,
1471
                              unsigned int dead_iargs)
1472
{
1473
    TCGTemp *ts, *ots;
1474
    int reg;
1475
    const TCGArgConstraint *arg_ct;
1476

    
1477
    ots = &s->temps[args[0]];
1478
    ts = &s->temps[args[1]];
1479
    arg_ct = &def->args_ct[0];
1480

    
1481
    /* XXX: always mark arg dead if IS_DEAD_IARG(0) */
1482
    if (ts->val_type == TEMP_VAL_REG) {
1483
        if (IS_DEAD_IARG(0) && !ts->fixed_reg && !ots->fixed_reg) {
1484
            /* the mov can be suppressed */
1485
            if (ots->val_type == TEMP_VAL_REG)
1486
                s->reg_to_temp[ots->reg] = -1;
1487
            reg = ts->reg;
1488
            s->reg_to_temp[reg] = -1;
1489
            ts->val_type = TEMP_VAL_DEAD;
1490
        } else {
1491
            if (ots->val_type == TEMP_VAL_REG) {
1492
                reg = ots->reg;
1493
            } else {
1494
                reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1495
            }
1496
            if (ts->reg != reg) {
1497
                tcg_out_mov(s, reg, ts->reg);
1498
            }
1499
        }
1500
    } else if (ts->val_type == TEMP_VAL_MEM) {
1501
        if (ots->val_type == TEMP_VAL_REG) {
1502
            reg = ots->reg;
1503
        } else {
1504
            reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1505
        }
1506
        tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1507
    } else if (ts->val_type == TEMP_VAL_CONST) {
1508
        if (ots->fixed_reg) {
1509
            reg = ots->reg;
1510
            tcg_out_movi(s, ots->type, reg, ts->val);
1511
        } else {
1512
            /* propagate constant */
1513
            if (ots->val_type == TEMP_VAL_REG)
1514
                s->reg_to_temp[ots->reg] = -1;
1515
            ots->val_type = TEMP_VAL_CONST;
1516
            ots->val = ts->val;
1517
            return;
1518
        }
1519
    } else {
1520
        tcg_abort();
1521
    }
1522
    s->reg_to_temp[reg] = args[0];
1523
    ots->reg = reg;
1524
    ots->val_type = TEMP_VAL_REG;
1525
    ots->mem_coherent = 0;
1526
}
1527

    
1528
static void tcg_reg_alloc_op(TCGContext *s, 
1529
                             const TCGOpDef *def, int opc,
1530
                             const TCGArg *args,
1531
                             unsigned int dead_iargs)
1532
{
1533
    TCGRegSet allocated_regs;
1534
    int i, k, nb_iargs, nb_oargs, reg;
1535
    TCGArg arg;
1536
    const TCGArgConstraint *arg_ct;
1537
    TCGTemp *ts;
1538
    TCGArg new_args[TCG_MAX_OP_ARGS];
1539
    int const_args[TCG_MAX_OP_ARGS];
1540

    
1541
    nb_oargs = def->nb_oargs;
1542
    nb_iargs = def->nb_iargs;
1543

    
1544
    /* copy constants */
1545
    memcpy(new_args + nb_oargs + nb_iargs, 
1546
           args + nb_oargs + nb_iargs, 
1547
           sizeof(TCGArg) * def->nb_cargs);
1548

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

    
1676
    /* emit instruction */
1677
    tcg_out_op(s, opc, new_args, const_args);
1678
    
1679
    /* move the outputs in the correct register if needed */
1680
    for(i = 0; i < nb_oargs; i++) {
1681
        ts = &s->temps[args[i]];
1682
        reg = new_args[i];
1683
        if (ts->fixed_reg && ts->reg != reg) {
1684
            tcg_out_mov(s, ts->reg, reg);
1685
        }
1686
    }
1687
}
1688

    
1689
#ifdef TCG_TARGET_STACK_GROWSUP
1690
#define STACK_DIR(x) (-(x))
1691
#else
1692
#define STACK_DIR(x) (x)
1693
#endif
1694

    
1695
static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
1696
                              int opc, const TCGArg *args,
1697
                              unsigned int dead_iargs)
1698
{
1699
    int nb_iargs, nb_oargs, flags, nb_regs, i, reg, nb_params;
1700
    TCGArg arg, func_arg;
1701
    TCGTemp *ts;
1702
    tcg_target_long stack_offset, call_stack_size, func_addr;
1703
    int const_func_arg, allocate_args;
1704
    TCGRegSet allocated_regs;
1705
    const TCGArgConstraint *arg_ct;
1706

    
1707
    arg = *args++;
1708

    
1709
    nb_oargs = arg >> 16;
1710
    nb_iargs = arg & 0xffff;
1711
    nb_params = nb_iargs - 1;
1712

    
1713
    flags = args[nb_oargs + nb_iargs];
1714

    
1715
    nb_regs = tcg_target_get_call_iarg_regs_count(flags);
1716
    if (nb_regs > nb_params)
1717
        nb_regs = nb_params;
1718

    
1719
    /* assign stack slots first */
1720
    /* XXX: preallocate call stack */
1721
    call_stack_size = (nb_params - nb_regs) * sizeof(tcg_target_long);
1722
    call_stack_size = (call_stack_size + TCG_TARGET_STACK_ALIGN - 1) & 
1723
        ~(TCG_TARGET_STACK_ALIGN - 1);
1724
    allocate_args = (call_stack_size > TCG_STATIC_CALL_ARGS_SIZE);
1725
    if (allocate_args) {
1726
        tcg_out_addi(s, TCG_REG_CALL_STACK, -STACK_DIR(call_stack_size));
1727
    }
1728

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

    
1844
    tcg_out_op(s, opc, &func_arg, &const_func_arg);
1845
    
1846
    if (allocate_args) {
1847
        tcg_out_addi(s, TCG_REG_CALL_STACK, STACK_DIR(call_stack_size));
1848
    }
1849

    
1850
    /* assign output registers and emit moves if needed */
1851
    for(i = 0; i < nb_oargs; i++) {
1852
        arg = args[i];
1853
        ts = &s->temps[arg];
1854
        reg = tcg_target_call_oarg_regs[i];
1855
        assert(s->reg_to_temp[reg] == -1);
1856
        if (ts->fixed_reg) {
1857
            if (ts->reg != reg) {
1858
                tcg_out_mov(s, ts->reg, reg);
1859
            }
1860
        } else {
1861
            if (ts->val_type == TEMP_VAL_REG)
1862
                s->reg_to_temp[ts->reg] = -1;
1863
            ts->val_type = TEMP_VAL_REG;
1864
            ts->reg = reg;
1865
            ts->mem_coherent = 0; 
1866
            s->reg_to_temp[reg] = arg;
1867
        }
1868
    }
1869
    
1870
    return nb_iargs + nb_oargs + def->nb_cargs + 1;
1871
}
1872

    
1873
#ifdef CONFIG_PROFILER
1874

    
1875
static int64_t tcg_table_op_count[NB_OPS];
1876

    
1877
static void dump_op_count(void)
1878
{
1879
    int i;
1880
    FILE *f;
1881
    f = fopen("/tmp/op.log", "w");
1882
    for(i = INDEX_op_end; i < NB_OPS; i++) {
1883
        fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name, tcg_table_op_count[i]);
1884
    }
1885
    fclose(f);
1886
}
1887
#endif
1888

    
1889

    
1890
static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
1891
                                      long search_pc)
1892
{
1893
    int opc, op_index;
1894
    const TCGOpDef *def;
1895
    unsigned int dead_iargs;
1896
    const TCGArg *args;
1897

    
1898
#ifdef DEBUG_DISAS
1899
    if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
1900
        qemu_log("OP:\n");
1901
        tcg_dump_ops(s, logfile);
1902
        qemu_log("\n");
1903
    }
1904
#endif
1905

    
1906
#ifdef CONFIG_PROFILER
1907
    s->la_time -= profile_getclock();
1908
#endif
1909
    tcg_liveness_analysis(s);
1910
#ifdef CONFIG_PROFILER
1911
    s->la_time += profile_getclock();
1912
#endif
1913

    
1914
#ifdef DEBUG_DISAS
1915
    if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_OPT))) {
1916
        qemu_log("OP after liveness analysis:\n");
1917
        tcg_dump_ops(s, logfile);
1918
        qemu_log("\n");
1919
    }
1920
#endif
1921

    
1922
    tcg_reg_alloc_start(s);
1923

    
1924
    s->code_buf = gen_code_buf;
1925
    s->code_ptr = gen_code_buf;
1926

    
1927
    args = gen_opparam_buf;
1928
    op_index = 0;
1929

    
1930
    for(;;) {
1931
        opc = gen_opc_buf[op_index];
1932
#ifdef CONFIG_PROFILER
1933
        tcg_table_op_count[opc]++;
1934
#endif
1935
        def = &tcg_op_defs[opc];
1936
#if 0
1937
        printf("%s: %d %d %d\n", def->name,
1938
               def->nb_oargs, def->nb_iargs, def->nb_cargs);
1939
        //        dump_regs(s);
1940
#endif
1941
        switch(opc) {
1942
        case INDEX_op_mov_i32:
1943
#if TCG_TARGET_REG_BITS == 64
1944
        case INDEX_op_mov_i64:
1945
#endif
1946
            dead_iargs = s->op_dead_iargs[op_index];
1947
            tcg_reg_alloc_mov(s, def, args, dead_iargs);
1948
            break;
1949
        case INDEX_op_movi_i32:
1950
#if TCG_TARGET_REG_BITS == 64
1951
        case INDEX_op_movi_i64:
1952
#endif
1953
            tcg_reg_alloc_movi(s, args);
1954
            break;
1955
        case INDEX_op_debug_insn_start:
1956
            /* debug instruction */
1957
            break;
1958
        case INDEX_op_nop:
1959
        case INDEX_op_nop1:
1960
        case INDEX_op_nop2:
1961
        case INDEX_op_nop3:
1962
            break;
1963
        case INDEX_op_nopn:
1964
            args += args[0];
1965
            goto next;
1966
        case INDEX_op_discard:
1967
            {
1968
                TCGTemp *ts;
1969
                ts = &s->temps[args[0]];
1970
                /* mark the temporary as dead */
1971
                if (!ts->fixed_reg) {
1972
                    if (ts->val_type == TEMP_VAL_REG)
1973
                        s->reg_to_temp[ts->reg] = -1;
1974
                    ts->val_type = TEMP_VAL_DEAD;
1975
                }
1976
            }
1977
            break;
1978
        case INDEX_op_set_label:
1979
            tcg_reg_alloc_bb_end(s, s->reserved_regs);
1980
            tcg_out_label(s, args[0], (long)s->code_ptr);
1981
            break;
1982
        case INDEX_op_call:
1983
            dead_iargs = s->op_dead_iargs[op_index];
1984
            args += tcg_reg_alloc_call(s, def, opc, args, dead_iargs);
1985
            goto next;
1986
        case INDEX_op_end:
1987
            goto the_end;
1988
        default:
1989
            /* Note: in order to speed up the code, it would be much
1990
               faster to have specialized register allocator functions for
1991
               some common argument patterns */
1992
            dead_iargs = s->op_dead_iargs[op_index];
1993
            tcg_reg_alloc_op(s, def, opc, args, dead_iargs);
1994
            break;
1995
        }
1996
        args += def->nb_args;
1997
    next:
1998
        if (search_pc >= 0 && search_pc < s->code_ptr - gen_code_buf) {
1999
            return op_index;
2000
        }
2001
        op_index++;
2002
#ifndef NDEBUG
2003
        check_regs(s);
2004
#endif
2005
    }
2006
 the_end:
2007
    return -1;
2008
}
2009

    
2010
int tcg_gen_code(TCGContext *s, uint8_t *gen_code_buf)
2011
{
2012
#ifdef CONFIG_PROFILER
2013
    {
2014
        int n;
2015
        n = (gen_opc_ptr - gen_opc_buf);
2016
        s->op_count += n;
2017
        if (n > s->op_count_max)
2018
            s->op_count_max = n;
2019

    
2020
        s->temp_count += s->nb_temps;
2021
        if (s->nb_temps > s->temp_count_max)
2022
            s->temp_count_max = s->nb_temps;
2023
    }
2024
#endif
2025

    
2026
    tcg_gen_code_common(s, gen_code_buf, -1);
2027

    
2028
    /* flush instruction cache */
2029
    flush_icache_range((unsigned long)gen_code_buf, 
2030
                       (unsigned long)s->code_ptr);
2031
    return s->code_ptr -  gen_code_buf;
2032
}
2033

    
2034
/* Return the index of the micro operation such as the pc after is <
2035
   offset bytes from the start of the TB.  The contents of gen_code_buf must
2036
   not be changed, though writing the same values is ok.
2037
   Return -1 if not found. */
2038
int tcg_gen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, long offset)
2039
{
2040
    return tcg_gen_code_common(s, gen_code_buf, offset);
2041
}
2042

    
2043
#ifdef CONFIG_PROFILER
2044
void tcg_dump_info(FILE *f,
2045
                   int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
2046
{
2047
    TCGContext *s = &tcg_ctx;
2048
    int64_t tot;
2049

    
2050
    tot = s->interm_time + s->code_time;
2051
    cpu_fprintf(f, "JIT cycles          %" PRId64 " (%0.3f s at 2.4 GHz)\n",
2052
                tot, tot / 2.4e9);
2053
    cpu_fprintf(f, "translated TBs      %" PRId64 " (aborted=%" PRId64 " %0.1f%%)\n", 
2054
                s->tb_count, 
2055
                s->tb_count1 - s->tb_count,
2056
                s->tb_count1 ? (double)(s->tb_count1 - s->tb_count) / s->tb_count1 * 100.0 : 0);
2057
    cpu_fprintf(f, "avg ops/TB          %0.1f max=%d\n", 
2058
                s->tb_count ? (double)s->op_count / s->tb_count : 0, s->op_count_max);
2059
    cpu_fprintf(f, "deleted ops/TB      %0.2f\n",
2060
                s->tb_count ? 
2061
                (double)s->del_op_count / s->tb_count : 0);
2062
    cpu_fprintf(f, "avg temps/TB        %0.2f max=%d\n",
2063
                s->tb_count ? 
2064
                (double)s->temp_count / s->tb_count : 0,
2065
                s->temp_count_max);
2066
    
2067
    cpu_fprintf(f, "cycles/op           %0.1f\n", 
2068
                s->op_count ? (double)tot / s->op_count : 0);
2069
    cpu_fprintf(f, "cycles/in byte      %0.1f\n", 
2070
                s->code_in_len ? (double)tot / s->code_in_len : 0);
2071
    cpu_fprintf(f, "cycles/out byte     %0.1f\n", 
2072
                s->code_out_len ? (double)tot / s->code_out_len : 0);
2073
    if (tot == 0)
2074
        tot = 1;
2075
    cpu_fprintf(f, "  gen_interm time   %0.1f%%\n", 
2076
                (double)s->interm_time / tot * 100.0);
2077
    cpu_fprintf(f, "  gen_code time     %0.1f%%\n", 
2078
                (double)s->code_time / tot * 100.0);
2079
    cpu_fprintf(f, "liveness/code time  %0.1f%%\n", 
2080
                (double)s->la_time / (s->code_time ? s->code_time : 1) * 100.0);
2081
    cpu_fprintf(f, "cpu_restore count   %" PRId64 "\n",
2082
                s->restore_count);
2083
    cpu_fprintf(f, "  avg cycles        %0.1f\n",
2084
                s->restore_count ? (double)s->restore_time / s->restore_count : 0);
2085

    
2086
    dump_op_count();
2087
}
2088
#else
2089
void tcg_dump_info(FILE *f,
2090
                   int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
2091
{
2092
    cpu_fprintf(f, "[TCG profiler not compiled]\n");
2093
}
2094
#endif