Statistics
| Branch: | Revision:

root / tcg / tcg.c @ 379f6698

History | View | Annotate | Download (61.8 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 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, iargs, oargs, cargs, flags) { #s, iargs, oargs, 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
static void tcg_reg_alloc_start(TCGContext *s)
674
{
675
    int i;
676
    TCGTemp *ts;
677
    for(i = 0; i < s->nb_globals; i++) {
678
        ts = &s->temps[i];
679
        if (ts->fixed_reg) {
680
            ts->val_type = TEMP_VAL_REG;
681
        } else {
682
            ts->val_type = TEMP_VAL_MEM;
683
        }
684
    }
685
    for(i = s->nb_globals; i < s->nb_temps; i++) {
686
        ts = &s->temps[i];
687
        ts->val_type = TEMP_VAL_DEAD;
688
        ts->mem_allocated = 0;
689
        ts->fixed_reg = 0;
690
    }
691
    for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
692
        s->reg_to_temp[i] = -1;
693
    }
694
}
695

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
918
/* we give more priority to constraints with less registers */
919
static int get_constraint_priority(const TCGOpDef *def, int k)
920
{
921
    const TCGArgConstraint *arg_ct;
922

    
923
    int i, n;
924
    arg_ct = &def->args_ct[k];
925
    if (arg_ct->ct & TCG_CT_ALIAS) {
926
        /* an alias is equivalent to a single register */
927
        n = 1;
928
    } else {
929
        if (!(arg_ct->ct & TCG_CT_REG))
930
            return 0;
931
        n = 0;
932
        for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
933
            if (tcg_regset_test_reg(arg_ct->u.regs, i))
934
                n++;
935
        }
936
    }
937
    return TCG_TARGET_NB_REGS - n + 1;
938
}
939

    
940
/* sort from highest priority to lowest */
941
static void sort_constraints(TCGOpDef *def, int start, int n)
942
{
943
    int i, j, p1, p2, tmp;
944

    
945
    for(i = 0; i < n; i++)
946
        def->sorted_args[start + i] = start + i;
947
    if (n <= 1)
948
        return;
949
    for(i = 0; i < n - 1; i++) {
950
        for(j = i + 1; j < n; j++) {
951
            p1 = get_constraint_priority(def, def->sorted_args[start + i]);
952
            p2 = get_constraint_priority(def, def->sorted_args[start + j]);
953
            if (p1 < p2) {
954
                tmp = def->sorted_args[start + i];
955
                def->sorted_args[start + i] = def->sorted_args[start + j];
956
                def->sorted_args[start + j] = tmp;
957
            }
958
        }
959
    }
960
}
961

    
962
void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs)
963
{
964
    int op;
965
    TCGOpDef *def;
966
    const char *ct_str;
967
    int i, nb_args;
968

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

    
1012
        /* sort the constraints (XXX: this is just an heuristic) */
1013
        sort_constraints(def, 0, def->nb_oargs);
1014
        sort_constraints(def, def->nb_oargs, def->nb_iargs);
1015

    
1016
#if 0
1017
        {
1018
            int i;
1019

1020
            printf("%s: sorted=", def->name);
1021
            for(i = 0; i < def->nb_oargs + def->nb_iargs; i++)
1022
                printf(" %d", def->sorted_args[i]);
1023
            printf("\n");
1024
        }
1025
#endif
1026
        tdefs++;
1027
    }
1028

    
1029
}
1030

    
1031
#ifdef USE_LIVENESS_ANALYSIS
1032

    
1033
/* set a nop for an operation using 'nb_args' */
1034
static inline void tcg_set_nop(TCGContext *s, uint16_t *opc_ptr, 
1035
                               TCGArg *args, int nb_args)
1036
{
1037
    if (nb_args == 0) {
1038
        *opc_ptr = INDEX_op_nop;
1039
    } else {
1040
        *opc_ptr = INDEX_op_nopn;
1041
        args[0] = nb_args;
1042
        args[nb_args - 1] = nb_args;
1043
    }
1044
}
1045

    
1046
/* liveness analysis: end of function: globals are live, temps are
1047
   dead. */
1048
/* XXX: at this stage, not used as there would be little gains because
1049
   most TBs end with a conditional jump. */
1050
static inline void tcg_la_func_end(TCGContext *s, uint8_t *dead_temps)
1051
{
1052
    memset(dead_temps, 0, s->nb_globals);
1053
    memset(dead_temps + s->nb_globals, 1, s->nb_temps - s->nb_globals);
1054
}
1055

    
1056
/* liveness analysis: end of basic block: globals are live, temps are
1057
   dead, local temps are live. */
1058
static inline void tcg_la_bb_end(TCGContext *s, uint8_t *dead_temps)
1059
{
1060
    int i;
1061
    TCGTemp *ts;
1062

    
1063
    memset(dead_temps, 0, s->nb_globals);
1064
    ts = &s->temps[s->nb_globals];
1065
    for(i = s->nb_globals; i < s->nb_temps; i++) {
1066
        if (ts->temp_local)
1067
            dead_temps[i] = 0;
1068
        else
1069
            dead_temps[i] = 1;
1070
        ts++;
1071
    }
1072
}
1073

    
1074
/* Liveness analysis : update the opc_dead_iargs array to tell if a
1075
   given input arguments is dead. Instructions updating dead
1076
   temporaries are removed. */
1077
static void tcg_liveness_analysis(TCGContext *s)
1078
{
1079
    int i, op_index, op, nb_args, nb_iargs, nb_oargs, arg, nb_ops;
1080
    TCGArg *args;
1081
    const TCGOpDef *def;
1082
    uint8_t *dead_temps;
1083
    unsigned int dead_iargs;
1084
    
1085
    gen_opc_ptr++; /* skip end */
1086

    
1087
    nb_ops = gen_opc_ptr - gen_opc_buf;
1088

    
1089
    /* XXX: make it really dynamic */
1090
    s->op_dead_iargs = tcg_malloc(OPC_BUF_SIZE * sizeof(uint16_t));
1091
    
1092
    dead_temps = tcg_malloc(s->nb_temps);
1093
    memset(dead_temps, 1, s->nb_temps);
1094

    
1095
    args = gen_opparam_ptr;
1096
    op_index = nb_ops - 1;
1097
    while (op_index >= 0) {
1098
        op = gen_opc_buf[op_index];
1099
        def = &tcg_op_defs[op];
1100
        switch(op) {
1101
        case INDEX_op_call:
1102
            {
1103
                int call_flags;
1104

    
1105
                nb_args = args[-1];
1106
                args -= nb_args;
1107
                nb_iargs = args[0] & 0xffff;
1108
                nb_oargs = args[0] >> 16;
1109
                args++;
1110
                call_flags = args[nb_oargs + nb_iargs];
1111

    
1112
                /* pure functions can be removed if their result is not
1113
                   used */
1114
                if (call_flags & TCG_CALL_PURE) {
1115
                    for(i = 0; i < nb_oargs; i++) {
1116
                        arg = args[i];
1117
                        if (!dead_temps[arg])
1118
                            goto do_not_remove_call;
1119
                    }
1120
                    tcg_set_nop(s, gen_opc_buf + op_index, 
1121
                                args - 1, nb_args);
1122
                } else {
1123
                do_not_remove_call:
1124

    
1125
                    /* output args are dead */
1126
                    for(i = 0; i < nb_oargs; i++) {
1127
                        arg = args[i];
1128
                        dead_temps[arg] = 1;
1129
                    }
1130
                    
1131
                    if (!(call_flags & TCG_CALL_CONST)) {
1132
                        /* globals are live (they may be used by the call) */
1133
                        memset(dead_temps, 0, s->nb_globals);
1134
                    }
1135

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

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

    
1193
                /* output args are dead */
1194
                for(i = 0; i < nb_oargs; i++) {
1195
                    arg = args[i];
1196
                    dead_temps[arg] = 1;
1197
                }
1198

    
1199
                /* if end of basic block, update */
1200
                if (def->flags & TCG_OPF_BB_END) {
1201
                    tcg_la_bb_end(s, dead_temps);
1202
                } else if (def->flags & TCG_OPF_CALL_CLOBBER) {
1203
                    /* globals are live */
1204
                    memset(dead_temps, 0, s->nb_globals);
1205
                }
1206

    
1207
                /* input args are live */
1208
                dead_iargs = 0;
1209
                for(i = 0; i < nb_iargs; i++) {
1210
                    arg = args[i + nb_oargs];
1211
                    if (dead_temps[arg]) {
1212
                        dead_iargs |= (1 << i);
1213
                    }
1214
                    dead_temps[arg] = 0;
1215
                }
1216
                s->op_dead_iargs[op_index] = dead_iargs;
1217
            }
1218
            break;
1219
        }
1220
        op_index--;
1221
    }
1222

    
1223
    if (args != gen_opparam_buf)
1224
        tcg_abort();
1225
}
1226
#else
1227
/* dummy liveness analysis */
1228
void tcg_liveness_analysis(TCGContext *s)
1229
{
1230
    int nb_ops;
1231
    nb_ops = gen_opc_ptr - gen_opc_buf;
1232

    
1233
    s->op_dead_iargs = tcg_malloc(nb_ops * sizeof(uint16_t));
1234
    memset(s->op_dead_iargs, 0, nb_ops * sizeof(uint16_t));
1235
}
1236
#endif
1237

    
1238
#ifndef NDEBUG
1239
static void dump_regs(TCGContext *s)
1240
{
1241
    TCGTemp *ts;
1242
    int i;
1243
    char buf[64];
1244

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

    
1268
    for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
1269
        if (s->reg_to_temp[i] >= 0) {
1270
            printf("%s: %s\n", 
1271
                   tcg_target_reg_names[i], 
1272
                   tcg_get_arg_str_idx(s, buf, sizeof(buf), s->reg_to_temp[i]));
1273
        }
1274
    }
1275
}
1276

    
1277
static void check_regs(TCGContext *s)
1278
{
1279
    int reg, k;
1280
    TCGTemp *ts;
1281
    char buf[64];
1282

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

    
1311
static void temp_allocate_frame(TCGContext *s, int temp)
1312
{
1313
    TCGTemp *ts;
1314
    ts = &s->temps[temp];
1315
    s->current_frame_offset = (s->current_frame_offset + sizeof(tcg_target_long) - 1) & ~(sizeof(tcg_target_long) - 1);
1316
    if (s->current_frame_offset + sizeof(tcg_target_long) > s->frame_end)
1317
        tcg_abort();
1318
    ts->mem_offset = s->current_frame_offset;
1319
    ts->mem_reg = s->frame_reg;
1320
    ts->mem_allocated = 1;
1321
    s->current_frame_offset += sizeof(tcg_target_long);
1322
}
1323

    
1324
/* free register 'reg' by spilling the corresponding temporary if necessary */
1325
static void tcg_reg_free(TCGContext *s, int reg)
1326
{
1327
    TCGTemp *ts;
1328
    int temp;
1329

    
1330
    temp = s->reg_to_temp[reg];
1331
    if (temp != -1) {
1332
        ts = &s->temps[temp];
1333
        assert(ts->val_type == TEMP_VAL_REG);
1334
        if (!ts->mem_coherent) {
1335
            if (!ts->mem_allocated) 
1336
                temp_allocate_frame(s, temp);
1337
            tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1338
        }
1339
        ts->val_type = TEMP_VAL_MEM;
1340
        s->reg_to_temp[reg] = -1;
1341
    }
1342
}
1343

    
1344
/* Allocate a register belonging to reg1 & ~reg2 */
1345
static int tcg_reg_alloc(TCGContext *s, TCGRegSet reg1, TCGRegSet reg2)
1346
{
1347
    int i, reg;
1348
    TCGRegSet reg_ct;
1349

    
1350
    tcg_regset_andnot(reg_ct, reg1, reg2);
1351

    
1352
    /* first try free registers */
1353
    for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1354
        reg = tcg_target_reg_alloc_order[i];
1355
        if (tcg_regset_test_reg(reg_ct, reg) && s->reg_to_temp[reg] == -1)
1356
            return reg;
1357
    }
1358

    
1359
    /* XXX: do better spill choice */
1360
    for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1361
        reg = tcg_target_reg_alloc_order[i];
1362
        if (tcg_regset_test_reg(reg_ct, reg)) {
1363
            tcg_reg_free(s, reg);
1364
            return reg;
1365
        }
1366
    }
1367

    
1368
    tcg_abort();
1369
}
1370

    
1371
/* save a temporary to memory. 'allocated_regs' is used in case a
1372
   temporary registers needs to be allocated to store a constant. */
1373
static void temp_save(TCGContext *s, int temp, TCGRegSet allocated_regs)
1374
{
1375
    TCGTemp *ts;
1376
    int reg;
1377

    
1378
    ts = &s->temps[temp];
1379
    if (!ts->fixed_reg) {
1380
        switch(ts->val_type) {
1381
        case TEMP_VAL_REG:
1382
            tcg_reg_free(s, ts->reg);
1383
            break;
1384
        case TEMP_VAL_DEAD:
1385
            ts->val_type = TEMP_VAL_MEM;
1386
            break;
1387
        case TEMP_VAL_CONST:
1388
            reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], 
1389
                                allocated_regs);
1390
            if (!ts->mem_allocated) 
1391
                temp_allocate_frame(s, temp);
1392
            tcg_out_movi(s, ts->type, reg, ts->val);
1393
            tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1394
            ts->val_type = TEMP_VAL_MEM;
1395
            break;
1396
        case TEMP_VAL_MEM:
1397
            break;
1398
        default:
1399
            tcg_abort();
1400
        }
1401
    }
1402
}
1403

    
1404
/* save globals to their cannonical location and assume they can be
1405
   modified be the following code. 'allocated_regs' is used in case a
1406
   temporary registers needs to be allocated to store a constant. */
1407
static void save_globals(TCGContext *s, TCGRegSet allocated_regs)
1408
{
1409
    int i;
1410

    
1411
    for(i = 0; i < s->nb_globals; i++) {
1412
        temp_save(s, i, allocated_regs);
1413
    }
1414
}
1415

    
1416
/* at the end of a basic block, we assume all temporaries are dead and
1417
   all globals are stored at their canonical location. */
1418
static void tcg_reg_alloc_bb_end(TCGContext *s, TCGRegSet allocated_regs)
1419
{
1420
    TCGTemp *ts;
1421
    int i;
1422

    
1423
    for(i = s->nb_globals; i < s->nb_temps; i++) {
1424
        ts = &s->temps[i];
1425
        if (ts->temp_local) {
1426
            temp_save(s, i, allocated_regs);
1427
        } else {
1428
            if (ts->val_type == TEMP_VAL_REG) {
1429
                s->reg_to_temp[ts->reg] = -1;
1430
            }
1431
            ts->val_type = TEMP_VAL_DEAD;
1432
        }
1433
    }
1434

    
1435
    save_globals(s, allocated_regs);
1436
}
1437

    
1438
#define IS_DEAD_IARG(n) ((dead_iargs >> (n)) & 1)
1439

    
1440
static void tcg_reg_alloc_movi(TCGContext *s, const TCGArg *args)
1441
{
1442
    TCGTemp *ots;
1443
    tcg_target_ulong val;
1444

    
1445
    ots = &s->temps[args[0]];
1446
    val = args[1];
1447

    
1448
    if (ots->fixed_reg) {
1449
        /* for fixed registers, we do not do any constant
1450
           propagation */
1451
        tcg_out_movi(s, ots->type, ots->reg, val);
1452
    } else {
1453
        /* The movi is not explicitly generated here */
1454
        if (ots->val_type == TEMP_VAL_REG)
1455
            s->reg_to_temp[ots->reg] = -1;
1456
        ots->val_type = TEMP_VAL_CONST;
1457
        ots->val = val;
1458
    }
1459
}
1460

    
1461
static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
1462
                              const TCGArg *args,
1463
                              unsigned int dead_iargs)
1464
{
1465
    TCGTemp *ts, *ots;
1466
    int reg;
1467
    const TCGArgConstraint *arg_ct;
1468

    
1469
    ots = &s->temps[args[0]];
1470
    ts = &s->temps[args[1]];
1471
    arg_ct = &def->args_ct[0];
1472

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

    
1520
static void tcg_reg_alloc_op(TCGContext *s, 
1521
                             const TCGOpDef *def, int opc,
1522
                             const TCGArg *args,
1523
                             unsigned int dead_iargs)
1524
{
1525
    TCGRegSet allocated_regs;
1526
    int i, k, nb_iargs, nb_oargs, reg;
1527
    TCGArg arg;
1528
    const TCGArgConstraint *arg_ct;
1529
    TCGTemp *ts;
1530
    TCGArg new_args[TCG_MAX_OP_ARGS];
1531
    int const_args[TCG_MAX_OP_ARGS];
1532

    
1533
    nb_oargs = def->nb_oargs;
1534
    nb_iargs = def->nb_iargs;
1535

    
1536
    /* copy constants */
1537
    memcpy(new_args + nb_oargs + nb_iargs, 
1538
           args + nb_oargs + nb_iargs, 
1539
           sizeof(TCGArg) * def->nb_cargs);
1540

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

    
1668
    /* emit instruction */
1669
    tcg_out_op(s, opc, new_args, const_args);
1670
    
1671
    /* move the outputs in the correct register if needed */
1672
    for(i = 0; i < nb_oargs; i++) {
1673
        ts = &s->temps[args[i]];
1674
        reg = new_args[i];
1675
        if (ts->fixed_reg && ts->reg != reg) {
1676
            tcg_out_mov(s, ts->reg, reg);
1677
        }
1678
    }
1679
}
1680

    
1681
#ifdef TCG_TARGET_STACK_GROWSUP
1682
#define STACK_DIR(x) (-(x))
1683
#else
1684
#define STACK_DIR(x) (x)
1685
#endif
1686

    
1687
static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
1688
                              int opc, const TCGArg *args,
1689
                              unsigned int dead_iargs)
1690
{
1691
    int nb_iargs, nb_oargs, flags, nb_regs, i, reg, nb_params;
1692
    TCGArg arg, func_arg;
1693
    TCGTemp *ts;
1694
    tcg_target_long stack_offset, call_stack_size, func_addr;
1695
    int const_func_arg, allocate_args;
1696
    TCGRegSet allocated_regs;
1697
    const TCGArgConstraint *arg_ct;
1698

    
1699
    arg = *args++;
1700

    
1701
    nb_oargs = arg >> 16;
1702
    nb_iargs = arg & 0xffff;
1703
    nb_params = nb_iargs - 1;
1704

    
1705
    flags = args[nb_oargs + nb_iargs];
1706

    
1707
    nb_regs = tcg_target_get_call_iarg_regs_count(flags);
1708
    if (nb_regs > nb_params)
1709
        nb_regs = nb_params;
1710

    
1711
    /* assign stack slots first */
1712
    /* XXX: preallocate call stack */
1713
    call_stack_size = (nb_params - nb_regs) * sizeof(tcg_target_long);
1714
    call_stack_size = (call_stack_size + TCG_TARGET_STACK_ALIGN - 1) & 
1715
        ~(TCG_TARGET_STACK_ALIGN - 1);
1716
    allocate_args = (call_stack_size > TCG_STATIC_CALL_ARGS_SIZE);
1717
    if (allocate_args) {
1718
        tcg_out_addi(s, TCG_REG_CALL_STACK, -STACK_DIR(call_stack_size));
1719
    }
1720

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

    
1836
    tcg_out_op(s, opc, &func_arg, &const_func_arg);
1837
    
1838
    if (allocate_args) {
1839
        tcg_out_addi(s, TCG_REG_CALL_STACK, STACK_DIR(call_stack_size));
1840
    }
1841

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

    
1865
#ifdef CONFIG_PROFILER
1866

    
1867
static int64_t tcg_table_op_count[NB_OPS];
1868

    
1869
void dump_op_count(void)
1870
{
1871
    int i;
1872
    FILE *f;
1873
    f = fopen("/tmp/op.log", "w");
1874
    for(i = INDEX_op_end; i < NB_OPS; i++) {
1875
        fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name, tcg_table_op_count[i]);
1876
    }
1877
    fclose(f);
1878
}
1879
#endif
1880

    
1881

    
1882
static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
1883
                                      long search_pc)
1884
{
1885
    int opc, op_index;
1886
    const TCGOpDef *def;
1887
    unsigned int dead_iargs;
1888
    const TCGArg *args;
1889

    
1890
#ifdef DEBUG_DISAS
1891
    if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
1892
        qemu_log("OP:\n");
1893
        tcg_dump_ops(s, logfile);
1894
        qemu_log("\n");
1895
    }
1896
#endif
1897

    
1898
#ifdef CONFIG_PROFILER
1899
    s->la_time -= profile_getclock();
1900
#endif
1901
    tcg_liveness_analysis(s);
1902
#ifdef CONFIG_PROFILER
1903
    s->la_time += profile_getclock();
1904
#endif
1905

    
1906
#ifdef DEBUG_DISAS
1907
    if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_OPT))) {
1908
        qemu_log("OP after la:\n");
1909
        tcg_dump_ops(s, logfile);
1910
        qemu_log("\n");
1911
    }
1912
#endif
1913

    
1914
    tcg_reg_alloc_start(s);
1915

    
1916
    s->code_buf = gen_code_buf;
1917
    s->code_ptr = gen_code_buf;
1918

    
1919
    args = gen_opparam_buf;
1920
    op_index = 0;
1921

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

    
2002
int tcg_gen_code(TCGContext *s, uint8_t *gen_code_buf)
2003
{
2004
#ifdef CONFIG_PROFILER
2005
    {
2006
        int n;
2007
        n = (gen_opc_ptr - gen_opc_buf);
2008
        s->op_count += n;
2009
        if (n > s->op_count_max)
2010
            s->op_count_max = n;
2011

    
2012
        s->temp_count += s->nb_temps;
2013
        if (s->nb_temps > s->temp_count_max)
2014
            s->temp_count_max = s->nb_temps;
2015
    }
2016
#endif
2017

    
2018
    tcg_gen_code_common(s, gen_code_buf, -1);
2019

    
2020
    /* flush instruction cache */
2021
    flush_icache_range((unsigned long)gen_code_buf, 
2022
                       (unsigned long)s->code_ptr);
2023
    return s->code_ptr -  gen_code_buf;
2024
}
2025

    
2026
/* Return the index of the micro operation such as the pc after is <
2027
   offset bytes from the start of the TB.  The contents of gen_code_buf must
2028
   not be changed, though writing the same values is ok.
2029
   Return -1 if not found. */
2030
int tcg_gen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, long offset)
2031
{
2032
    return tcg_gen_code_common(s, gen_code_buf, offset);
2033
}
2034

    
2035
#ifdef CONFIG_PROFILER
2036
void tcg_dump_info(FILE *f,
2037
                   int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
2038
{
2039
    TCGContext *s = &tcg_ctx;
2040
    int64_t tot;
2041

    
2042
    tot = s->interm_time + s->code_time;
2043
    cpu_fprintf(f, "JIT cycles          %" PRId64 " (%0.3f s at 2.4 GHz)\n",
2044
                tot, tot / 2.4e9);
2045
    cpu_fprintf(f, "translated TBs      %" PRId64 " (aborted=%" PRId64 " %0.1f%%)\n", 
2046
                s->tb_count, 
2047
                s->tb_count1 - s->tb_count,
2048
                s->tb_count1 ? (double)(s->tb_count1 - s->tb_count) / s->tb_count1 * 100.0 : 0);
2049
    cpu_fprintf(f, "avg ops/TB          %0.1f max=%d\n", 
2050
                s->tb_count ? (double)s->op_count / s->tb_count : 0, s->op_count_max);
2051
    cpu_fprintf(f, "deleted ops/TB      %0.2f\n",
2052
                s->tb_count ? 
2053
                (double)s->del_op_count / s->tb_count : 0);
2054
    cpu_fprintf(f, "avg temps/TB        %0.2f max=%d\n",
2055
                s->tb_count ? 
2056
                (double)s->temp_count / s->tb_count : 0,
2057
                s->temp_count_max);
2058
    
2059
    cpu_fprintf(f, "cycles/op           %0.1f\n", 
2060
                s->op_count ? (double)tot / s->op_count : 0);
2061
    cpu_fprintf(f, "cycles/in byte      %0.1f\n", 
2062
                s->code_in_len ? (double)tot / s->code_in_len : 0);
2063
    cpu_fprintf(f, "cycles/out byte     %0.1f\n", 
2064
                s->code_out_len ? (double)tot / s->code_out_len : 0);
2065
    if (tot == 0)
2066
        tot = 1;
2067
    cpu_fprintf(f, "  gen_interm time   %0.1f%%\n", 
2068
                (double)s->interm_time / tot * 100.0);
2069
    cpu_fprintf(f, "  gen_code time     %0.1f%%\n", 
2070
                (double)s->code_time / tot * 100.0);
2071
    cpu_fprintf(f, "liveness/code time  %0.1f%%\n", 
2072
                (double)s->la_time / (s->code_time ? s->code_time : 1) * 100.0);
2073
    cpu_fprintf(f, "cpu_restore count   %" PRId64 "\n",
2074
                s->restore_count);
2075
    cpu_fprintf(f, "  avg cycles        %0.1f\n",
2076
                s->restore_count ? (double)s->restore_time / s->restore_count : 0);
2077
    {
2078
        extern void dump_op_count(void);
2079
        dump_op_count();
2080
    }
2081
}
2082
#else
2083
void tcg_dump_info(FILE *f,
2084
                   int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
2085
{
2086
    cpu_fprintf(f, "[TCG profiler not compiled]\n");
2087
}
2088
#endif