Statistics
| Branch: | Revision:

root / tcg / tcg.c @ 6a957025

History | View | Annotate | Download (61.7 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
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
    s->op_dead_iargs = tcg_malloc(nb_ops * sizeof(uint16_t));
1090
    
1091
    dead_temps = tcg_malloc(s->nb_temps);
1092
    memset(dead_temps, 1, s->nb_temps);
1093

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1349
    tcg_regset_andnot(reg_ct, reg1, reg2);
1350

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

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

    
1367
    tcg_abort();
1368
}
1369

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

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

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

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

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

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

    
1434
    save_globals(s, allocated_regs);
1435
}
1436

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1698
    arg = *args++;
1699

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

    
1704
    flags = args[nb_oargs + nb_iargs];
1705

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

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

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

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

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

    
1864
#ifdef CONFIG_PROFILER
1865

    
1866
static int64_t tcg_table_op_count[NB_OPS];
1867

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

    
1880

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

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

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

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

    
1913
    tcg_reg_alloc_start(s);
1914

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

    
1918
    args = gen_opparam_buf;
1919
    op_index = 0;
1920

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

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

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

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

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

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

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

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

    
2077
    dump_op_count();
2078
}
2079
#else
2080
void tcg_dump_info(FILE *f,
2081
                   int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
2082
{
2083
    cpu_fprintf(f, "[TCG profiler not compiled]\n");
2084
}
2085
#endif