Statistics
| Branch: | Revision:

root / tcg / tcg.c @ 9002ec79

History | View | Annotate | Download (63.9 kB)

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

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

    
28
#include "config.h"
29

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

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

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

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

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

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

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

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

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

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

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

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

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

    
101
/* label relocation processing */
102

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

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

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

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

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

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

    
159
#include "tcg-target.c"
160

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
456
TCGv_i32 tcg_temp_new_internal_i32(int temp_local)
457
{
458
    int idx;
459

    
460
    idx = tcg_temp_new_internal(TCG_TYPE_I32, temp_local);
461
    return MAKE_TCGV_I32(idx);
462
}
463

    
464
TCGv_i64 tcg_temp_new_internal_i64(int temp_local)
465
{
466
    int idx;
467

    
468
    idx = tcg_temp_new_internal(TCG_TYPE_I64, temp_local);
469
    return MAKE_TCGV_I64(idx);
470
}
471

    
472
static inline void tcg_temp_free_internal(int idx)
473
{
474
    TCGContext *s = &tcg_ctx;
475
    TCGTemp *ts;
476
    int k;
477

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

    
489
void tcg_temp_free_i32(TCGv_i32 arg)
490
{
491
    tcg_temp_free_internal(GET_TCGV_I32(arg));
492
}
493

    
494
void tcg_temp_free_i64(TCGv_i64 arg)
495
{
496
    tcg_temp_free_internal(GET_TCGV_I64(arg));
497
}
498

    
499
TCGv_i32 tcg_const_i32(int32_t val)
500
{
501
    TCGv_i32 t0;
502
    t0 = tcg_temp_new_i32();
503
    tcg_gen_movi_i32(t0, val);
504
    return t0;
505
}
506

    
507
TCGv_i64 tcg_const_i64(int64_t val)
508
{
509
    TCGv_i64 t0;
510
    t0 = tcg_temp_new_i64();
511
    tcg_gen_movi_i64(t0, val);
512
    return t0;
513
}
514

    
515
TCGv_i32 tcg_const_local_i32(int32_t val)
516
{
517
    TCGv_i32 t0;
518
    t0 = tcg_temp_local_new_i32();
519
    tcg_gen_movi_i32(t0, val);
520
    return t0;
521
}
522

    
523
TCGv_i64 tcg_const_local_i64(int64_t val)
524
{
525
    TCGv_i64 t0;
526
    t0 = tcg_temp_local_new_i64();
527
    tcg_gen_movi_i64(t0, val);
528
    return t0;
529
}
530

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

    
550
/* Note: we convert the 64 bit args to 32 bit and do some alignment
551
   and endian swap. Maybe it would be better to do the alignment
552
   and endian swap in tcg_reg_alloc_call(). */
553
void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags,
554
                   int sizemask, TCGArg ret, int nargs, TCGArg *args)
555
{
556
#ifdef TCG_TARGET_I386
557
    int call_type;
558
#endif
559
    int i;
560
    int real_args;
561
    int nb_rets;
562
    TCGArg *nparam;
563
    *gen_opc_ptr++ = INDEX_op_call;
564
    nparam = gen_opparam_ptr++;
565
#ifdef TCG_TARGET_I386
566
    call_type = (flags & TCG_CALL_TYPE_MASK);
567
#endif
568
    if (ret != TCG_CALL_DUMMY_ARG) {
569
#if TCG_TARGET_REG_BITS < 64
570
        if (sizemask & 1) {
571
#ifdef TCG_TARGET_WORDS_BIGENDIAN
572
            *gen_opparam_ptr++ = ret + 1;
573
            *gen_opparam_ptr++ = ret;
574
#else
575
            *gen_opparam_ptr++ = ret;
576
            *gen_opparam_ptr++ = ret + 1;
577
#endif
578
            nb_rets = 2;
579
        } else
580
#endif
581
        {
582
            *gen_opparam_ptr++ = ret;
583
            nb_rets = 1;
584
        }
585
    } else {
586
        nb_rets = 0;
587
    }
588
    real_args = 0;
589
    for (i = 0; i < nargs; i++) {
590
#if TCG_TARGET_REG_BITS < 64
591
        if (sizemask & (2 << i)) {
592
#ifdef TCG_TARGET_I386
593
            /* REGPARM case: if the third parameter is 64 bit, it is
594
               allocated on the stack */
595
            if (i == 2 && call_type == TCG_CALL_TYPE_REGPARM) {
596
                call_type = TCG_CALL_TYPE_REGPARM_2;
597
                flags = (flags & ~TCG_CALL_TYPE_MASK) | call_type;
598
            }
599
#endif
600
#ifdef TCG_TARGET_CALL_ALIGN_ARGS
601
            /* some targets want aligned 64 bit args */
602
            if (real_args & 1) {
603
                *gen_opparam_ptr++ = TCG_CALL_DUMMY_ARG;
604
                real_args++;
605
            }
606
#endif
607
            /* If stack grows up, then we will be placing successive
608
               arguments at lower addresses, which means we need to
609
               reverse the order compared to how we would normally
610
               treat either big or little-endian.  For those arguments
611
               that will wind up in registers, this still works for
612
               HPPA (the only current STACK_GROWSUP target) since the
613
               argument registers are *also* allocated in decreasing
614
               order.  If another such target is added, this logic may
615
               have to get more complicated to differentiate between
616
               stack arguments and register arguments.  */
617
#if defined(TCG_TARGET_WORDS_BIGENDIAN) != defined(TCG_TARGET_STACK_GROWSUP)
618
            *gen_opparam_ptr++ = args[i] + 1;
619
            *gen_opparam_ptr++ = args[i];
620
#else
621
            *gen_opparam_ptr++ = args[i];
622
            *gen_opparam_ptr++ = args[i] + 1;
623
#endif
624
            real_args += 2;
625
        } else
626
#endif
627
        {
628
            *gen_opparam_ptr++ = args[i];
629
            real_args++;
630
        }
631
    }
632
    *gen_opparam_ptr++ = GET_TCGV_PTR(func);
633

    
634
    *gen_opparam_ptr++ = flags;
635

    
636
    *nparam = (nb_rets << 16) | (real_args + 1);
637

    
638
    /* total parameters, needed to go backward in the instruction stream */
639
    *gen_opparam_ptr++ = 1 + nb_rets + real_args + 3;
640
}
641

    
642
#if TCG_TARGET_REG_BITS == 32
643
void tcg_gen_shifti_i64(TCGv_i64 ret, TCGv_i64 arg1,
644
                        int c, int right, int arith)
645
{
646
    if (c == 0) {
647
        tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg1));
648
        tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
649
    } else if (c >= 32) {
650
        c -= 32;
651
        if (right) {
652
            if (arith) {
653
                tcg_gen_sari_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
654
                tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 31);
655
            } else {
656
                tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
657
                tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
658
            }
659
        } else {
660
            tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_LOW(arg1), c);
661
            tcg_gen_movi_i32(TCGV_LOW(ret), 0);
662
        }
663
    } else {
664
        TCGv_i32 t0, t1;
665

    
666
        t0 = tcg_temp_new_i32();
667
        t1 = tcg_temp_new_i32();
668
        if (right) {
669
            tcg_gen_shli_i32(t0, TCGV_HIGH(arg1), 32 - c);
670
            if (arith)
671
                tcg_gen_sari_i32(t1, TCGV_HIGH(arg1), c);
672
            else
673
                tcg_gen_shri_i32(t1, TCGV_HIGH(arg1), c);
674
            tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_LOW(arg1), c);
675
            tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(ret), t0);
676
            tcg_gen_mov_i32(TCGV_HIGH(ret), t1);
677
        } else {
678
            tcg_gen_shri_i32(t0, TCGV_LOW(arg1), 32 - c);
679
            /* Note: ret can be the same as arg1, so we use t1 */
680
            tcg_gen_shli_i32(t1, TCGV_LOW(arg1), c);
681
            tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c);
682
            tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t0);
683
            tcg_gen_mov_i32(TCGV_LOW(ret), t1);
684
        }
685
        tcg_temp_free_i32(t0);
686
        tcg_temp_free_i32(t1);
687
    }
688
}
689
#endif
690

    
691

    
692
static void tcg_reg_alloc_start(TCGContext *s)
693
{
694
    int i;
695
    TCGTemp *ts;
696
    for(i = 0; i < s->nb_globals; i++) {
697
        ts = &s->temps[i];
698
        if (ts->fixed_reg) {
699
            ts->val_type = TEMP_VAL_REG;
700
        } else {
701
            ts->val_type = TEMP_VAL_MEM;
702
        }
703
    }
704
    for(i = s->nb_globals; i < s->nb_temps; i++) {
705
        ts = &s->temps[i];
706
        ts->val_type = TEMP_VAL_DEAD;
707
        ts->mem_allocated = 0;
708
        ts->fixed_reg = 0;
709
    }
710
    for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
711
        s->reg_to_temp[i] = -1;
712
    }
713
}
714

    
715
static char *tcg_get_arg_str_idx(TCGContext *s, char *buf, int buf_size,
716
                                 int idx)
717
{
718
    TCGTemp *ts;
719

    
720
    ts = &s->temps[idx];
721
    if (idx < s->nb_globals) {
722
        pstrcpy(buf, buf_size, ts->name);
723
    } else {
724
        if (ts->temp_local) 
725
            snprintf(buf, buf_size, "loc%d", idx - s->nb_globals);
726
        else
727
            snprintf(buf, buf_size, "tmp%d", idx - s->nb_globals);
728
    }
729
    return buf;
730
}
731

    
732
char *tcg_get_arg_str_i32(TCGContext *s, char *buf, int buf_size, TCGv_i32 arg)
733
{
734
    return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I32(arg));
735
}
736

    
737
char *tcg_get_arg_str_i64(TCGContext *s, char *buf, int buf_size, TCGv_i64 arg)
738
{
739
    return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I64(arg));
740
}
741

    
742
static int helper_cmp(const void *p1, const void *p2)
743
{
744
    const TCGHelperInfo *th1 = p1;
745
    const TCGHelperInfo *th2 = p2;
746
    if (th1->func < th2->func)
747
        return -1;
748
    else if (th1->func == th2->func)
749
        return 0;
750
    else
751
        return 1;
752
}
753

    
754
/* find helper definition (Note: A hash table would be better) */
755
static TCGHelperInfo *tcg_find_helper(TCGContext *s, tcg_target_ulong val)
756
{
757
    int m, m_min, m_max;
758
    TCGHelperInfo *th;
759
    tcg_target_ulong v;
760

    
761
    if (unlikely(!s->helpers_sorted)) {
762
        qsort(s->helpers, s->nb_helpers, sizeof(TCGHelperInfo), 
763
              helper_cmp);
764
        s->helpers_sorted = 1;
765
    }
766

    
767
    /* binary search */
768
    m_min = 0;
769
    m_max = s->nb_helpers - 1;
770
    while (m_min <= m_max) {
771
        m = (m_min + m_max) >> 1;
772
        th = &s->helpers[m];
773
        v = th->func;
774
        if (v == val)
775
            return th;
776
        else if (val < v) {
777
            m_max = m - 1;
778
        } else {
779
            m_min = m + 1;
780
        }
781
    }
782
    return NULL;
783
}
784

    
785
static const char * const cond_name[] =
786
{
787
    [TCG_COND_EQ] = "eq",
788
    [TCG_COND_NE] = "ne",
789
    [TCG_COND_LT] = "lt",
790
    [TCG_COND_GE] = "ge",
791
    [TCG_COND_LE] = "le",
792
    [TCG_COND_GT] = "gt",
793
    [TCG_COND_LTU] = "ltu",
794
    [TCG_COND_GEU] = "geu",
795
    [TCG_COND_LEU] = "leu",
796
    [TCG_COND_GTU] = "gtu"
797
};
798

    
799
void tcg_dump_ops(TCGContext *s, FILE *outfile)
800
{
801
    const uint16_t *opc_ptr;
802
    const TCGArg *args;
803
    TCGArg arg;
804
    TCGOpcode c;
805
    int i, k, nb_oargs, nb_iargs, nb_cargs, first_insn;
806
    const TCGOpDef *def;
807
    char buf[128];
808

    
809
    first_insn = 1;
810
    opc_ptr = gen_opc_buf;
811
    args = gen_opparam_buf;
812
    while (opc_ptr < gen_opc_ptr) {
813
        c = *opc_ptr++;
814
        def = &tcg_op_defs[c];
815
        if (c == INDEX_op_debug_insn_start) {
816
            uint64_t pc;
817
#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
818
            pc = ((uint64_t)args[1] << 32) | args[0];
819
#else
820
            pc = args[0];
821
#endif
822
            if (!first_insn) 
823
                fprintf(outfile, "\n");
824
            fprintf(outfile, " ---- 0x%" PRIx64, pc);
825
            first_insn = 0;
826
            nb_oargs = def->nb_oargs;
827
            nb_iargs = def->nb_iargs;
828
            nb_cargs = def->nb_cargs;
829
        } else if (c == INDEX_op_call) {
830
            TCGArg arg;
831

    
832
            /* variable number of arguments */
833
            arg = *args++;
834
            nb_oargs = arg >> 16;
835
            nb_iargs = arg & 0xffff;
836
            nb_cargs = def->nb_cargs;
837

    
838
            fprintf(outfile, " %s ", def->name);
839

    
840
            /* function name */
841
            fprintf(outfile, "%s",
842
                    tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + nb_iargs - 1]));
843
            /* flags */
844
            fprintf(outfile, ",$0x%" TCG_PRIlx,
845
                    args[nb_oargs + nb_iargs]);
846
            /* nb out args */
847
            fprintf(outfile, ",$%d", nb_oargs);
848
            for(i = 0; i < nb_oargs; i++) {
849
                fprintf(outfile, ",");
850
                fprintf(outfile, "%s",
851
                        tcg_get_arg_str_idx(s, buf, sizeof(buf), args[i]));
852
            }
853
            for(i = 0; i < (nb_iargs - 1); i++) {
854
                fprintf(outfile, ",");
855
                if (args[nb_oargs + i] == TCG_CALL_DUMMY_ARG) {
856
                    fprintf(outfile, "<dummy>");
857
                } else {
858
                    fprintf(outfile, "%s",
859
                            tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + i]));
860
                }
861
            }
862
        } else if (c == INDEX_op_movi_i32 
863
#if TCG_TARGET_REG_BITS == 64
864
                   || c == INDEX_op_movi_i64
865
#endif
866
                   ) {
867
            tcg_target_ulong val;
868
            TCGHelperInfo *th;
869

    
870
            nb_oargs = def->nb_oargs;
871
            nb_iargs = def->nb_iargs;
872
            nb_cargs = def->nb_cargs;
873
            fprintf(outfile, " %s %s,$", def->name, 
874
                    tcg_get_arg_str_idx(s, buf, sizeof(buf), args[0]));
875
            val = args[1];
876
            th = tcg_find_helper(s, val);
877
            if (th) {
878
                fprintf(outfile, "%s", th->name);
879
            } else {
880
                if (c == INDEX_op_movi_i32)
881
                    fprintf(outfile, "0x%x", (uint32_t)val);
882
                else
883
                    fprintf(outfile, "0x%" PRIx64 , (uint64_t)val);
884
            }
885
        } else {
886
            fprintf(outfile, " %s ", def->name);
887
            if (c == INDEX_op_nopn) {
888
                /* variable number of arguments */
889
                nb_cargs = *args;
890
                nb_oargs = 0;
891
                nb_iargs = 0;
892
            } else {
893
                nb_oargs = def->nb_oargs;
894
                nb_iargs = def->nb_iargs;
895
                nb_cargs = def->nb_cargs;
896
            }
897
            
898
            k = 0;
899
            for(i = 0; i < nb_oargs; i++) {
900
                if (k != 0)
901
                    fprintf(outfile, ",");
902
                fprintf(outfile, "%s",
903
                        tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
904
            }
905
            for(i = 0; i < nb_iargs; i++) {
906
                if (k != 0)
907
                    fprintf(outfile, ",");
908
                fprintf(outfile, "%s",
909
                        tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
910
            }
911
            switch (c) {
912
            case INDEX_op_brcond_i32:
913
#if TCG_TARGET_REG_BITS == 32
914
            case INDEX_op_brcond2_i32:
915
#elif TCG_TARGET_REG_BITS == 64
916
            case INDEX_op_brcond_i64:
917
#endif
918
            case INDEX_op_setcond_i32:
919
#if TCG_TARGET_REG_BITS == 32
920
            case INDEX_op_setcond2_i32:
921
#elif TCG_TARGET_REG_BITS == 64
922
            case INDEX_op_setcond_i64:
923
#endif
924
                if (args[k] < ARRAY_SIZE(cond_name) && cond_name[args[k]])
925
                    fprintf(outfile, ",%s", cond_name[args[k++]]);
926
                else
927
                    fprintf(outfile, ",$0x%" TCG_PRIlx, args[k++]);
928
                i = 1;
929
                break;
930
            default:
931
                i = 0;
932
                break;
933
            }
934
            for(; i < nb_cargs; i++) {
935
                if (k != 0)
936
                    fprintf(outfile, ",");
937
                arg = args[k++];
938
                fprintf(outfile, "$0x%" TCG_PRIlx, arg);
939
            }
940
        }
941
        fprintf(outfile, "\n");
942
        args += nb_iargs + nb_oargs + nb_cargs;
943
    }
944
}
945

    
946
/* we give more priority to constraints with less registers */
947
static int get_constraint_priority(const TCGOpDef *def, int k)
948
{
949
    const TCGArgConstraint *arg_ct;
950

    
951
    int i, n;
952
    arg_ct = &def->args_ct[k];
953
    if (arg_ct->ct & TCG_CT_ALIAS) {
954
        /* an alias is equivalent to a single register */
955
        n = 1;
956
    } else {
957
        if (!(arg_ct->ct & TCG_CT_REG))
958
            return 0;
959
        n = 0;
960
        for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
961
            if (tcg_regset_test_reg(arg_ct->u.regs, i))
962
                n++;
963
        }
964
    }
965
    return TCG_TARGET_NB_REGS - n + 1;
966
}
967

    
968
/* sort from highest priority to lowest */
969
static void sort_constraints(TCGOpDef *def, int start, int n)
970
{
971
    int i, j, p1, p2, tmp;
972

    
973
    for(i = 0; i < n; i++)
974
        def->sorted_args[start + i] = start + i;
975
    if (n <= 1)
976
        return;
977
    for(i = 0; i < n - 1; i++) {
978
        for(j = i + 1; j < n; j++) {
979
            p1 = get_constraint_priority(def, def->sorted_args[start + i]);
980
            p2 = get_constraint_priority(def, def->sorted_args[start + j]);
981
            if (p1 < p2) {
982
                tmp = def->sorted_args[start + i];
983
                def->sorted_args[start + i] = def->sorted_args[start + j];
984
                def->sorted_args[start + j] = tmp;
985
            }
986
        }
987
    }
988
}
989

    
990
void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs)
991
{
992
    TCGOpcode op;
993
    TCGOpDef *def;
994
    const char *ct_str;
995
    int i, nb_args;
996

    
997
    for(;;) {
998
        if (tdefs->op == (TCGOpcode)-1)
999
            break;
1000
        op = tdefs->op;
1001
        assert(op >= 0 && op < NB_OPS);
1002
        def = &tcg_op_defs[op];
1003
#if defined(CONFIG_DEBUG_TCG)
1004
        /* Duplicate entry in op definitions? */
1005
        assert(!def->used);
1006
        def->used = 1;
1007
#endif
1008
        nb_args = def->nb_iargs + def->nb_oargs;
1009
        for(i = 0; i < nb_args; i++) {
1010
            ct_str = tdefs->args_ct_str[i];
1011
            /* Incomplete TCGTargetOpDef entry? */
1012
            assert(ct_str != NULL);
1013
            tcg_regset_clear(def->args_ct[i].u.regs);
1014
            def->args_ct[i].ct = 0;
1015
            if (ct_str[0] >= '0' && ct_str[0] <= '9') {
1016
                int oarg;
1017
                oarg = ct_str[0] - '0';
1018
                assert(oarg < def->nb_oargs);
1019
                assert(def->args_ct[oarg].ct & TCG_CT_REG);
1020
                /* TCG_CT_ALIAS is for the output arguments. The input
1021
                   argument is tagged with TCG_CT_IALIAS. */
1022
                def->args_ct[i] = def->args_ct[oarg];
1023
                def->args_ct[oarg].ct = TCG_CT_ALIAS;
1024
                def->args_ct[oarg].alias_index = i;
1025
                def->args_ct[i].ct |= TCG_CT_IALIAS;
1026
                def->args_ct[i].alias_index = oarg;
1027
            } else {
1028
                for(;;) {
1029
                    if (*ct_str == '\0')
1030
                        break;
1031
                    switch(*ct_str) {
1032
                    case 'i':
1033
                        def->args_ct[i].ct |= TCG_CT_CONST;
1034
                        ct_str++;
1035
                        break;
1036
                    default:
1037
                        if (target_parse_constraint(&def->args_ct[i], &ct_str) < 0) {
1038
                            fprintf(stderr, "Invalid constraint '%s' for arg %d of operation '%s'\n",
1039
                                    ct_str, i, def->name);
1040
                            exit(1);
1041
                        }
1042
                    }
1043
                }
1044
            }
1045
        }
1046

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

    
1050
        /* sort the constraints (XXX: this is just an heuristic) */
1051
        sort_constraints(def, 0, def->nb_oargs);
1052
        sort_constraints(def, def->nb_oargs, def->nb_iargs);
1053

    
1054
#if 0
1055
        {
1056
            int i;
1057

1058
            printf("%s: sorted=", def->name);
1059
            for(i = 0; i < def->nb_oargs + def->nb_iargs; i++)
1060
                printf(" %d", def->sorted_args[i]);
1061
            printf("\n");
1062
        }
1063
#endif
1064
        tdefs++;
1065
    }
1066

    
1067
#if defined(CONFIG_DEBUG_TCG)
1068
    i = 0;
1069
    for (op = 0; op < ARRAY_SIZE(tcg_op_defs); op++) {
1070
        if (op < INDEX_op_call || op == INDEX_op_debug_insn_start) {
1071
            /* Wrong entry in op definitions? */
1072
            if (tcg_op_defs[op].used) {
1073
                fprintf(stderr, "Invalid op definition for %s\n",
1074
                        tcg_op_defs[op].name);
1075
                i = 1;
1076
            }
1077
        } else {
1078
            /* Missing entry in op definitions? */
1079
            if (!tcg_op_defs[op].used) {
1080
                fprintf(stderr, "Missing op definition for %s\n",
1081
                        tcg_op_defs[op].name);
1082
                i = 1;
1083
            }
1084
        }
1085
    }
1086
    if (i == 1) {
1087
        tcg_abort();
1088
    }
1089
#endif
1090
}
1091

    
1092
#ifdef USE_LIVENESS_ANALYSIS
1093

    
1094
/* set a nop for an operation using 'nb_args' */
1095
static inline void tcg_set_nop(TCGContext *s, uint16_t *opc_ptr, 
1096
                               TCGArg *args, int nb_args)
1097
{
1098
    if (nb_args == 0) {
1099
        *opc_ptr = INDEX_op_nop;
1100
    } else {
1101
        *opc_ptr = INDEX_op_nopn;
1102
        args[0] = nb_args;
1103
        args[nb_args - 1] = nb_args;
1104
    }
1105
}
1106

    
1107
/* liveness analysis: end of function: globals are live, temps are
1108
   dead. */
1109
/* XXX: at this stage, not used as there would be little gains because
1110
   most TBs end with a conditional jump. */
1111
static inline void tcg_la_func_end(TCGContext *s, uint8_t *dead_temps)
1112
{
1113
    memset(dead_temps, 0, s->nb_globals);
1114
    memset(dead_temps + s->nb_globals, 1, s->nb_temps - s->nb_globals);
1115
}
1116

    
1117
/* liveness analysis: end of basic block: globals are live, temps are
1118
   dead, local temps are live. */
1119
static inline void tcg_la_bb_end(TCGContext *s, uint8_t *dead_temps)
1120
{
1121
    int i;
1122
    TCGTemp *ts;
1123

    
1124
    memset(dead_temps, 0, s->nb_globals);
1125
    ts = &s->temps[s->nb_globals];
1126
    for(i = s->nb_globals; i < s->nb_temps; i++) {
1127
        if (ts->temp_local)
1128
            dead_temps[i] = 0;
1129
        else
1130
            dead_temps[i] = 1;
1131
        ts++;
1132
    }
1133
}
1134

    
1135
/* Liveness analysis : update the opc_dead_iargs array to tell if a
1136
   given input arguments is dead. Instructions updating dead
1137
   temporaries are removed. */
1138
static void tcg_liveness_analysis(TCGContext *s)
1139
{
1140
    int i, op_index, nb_args, nb_iargs, nb_oargs, arg, nb_ops;
1141
    TCGOpcode op;
1142
    TCGArg *args;
1143
    const TCGOpDef *def;
1144
    uint8_t *dead_temps;
1145
    unsigned int dead_iargs;
1146
    
1147
    gen_opc_ptr++; /* skip end */
1148

    
1149
    nb_ops = gen_opc_ptr - gen_opc_buf;
1150

    
1151
    s->op_dead_iargs = tcg_malloc(nb_ops * sizeof(uint16_t));
1152
    
1153
    dead_temps = tcg_malloc(s->nb_temps);
1154
    memset(dead_temps, 1, s->nb_temps);
1155

    
1156
    args = gen_opparam_ptr;
1157
    op_index = nb_ops - 1;
1158
    while (op_index >= 0) {
1159
        op = gen_opc_buf[op_index];
1160
        def = &tcg_op_defs[op];
1161
        switch(op) {
1162
        case INDEX_op_call:
1163
            {
1164
                int call_flags;
1165

    
1166
                nb_args = args[-1];
1167
                args -= nb_args;
1168
                nb_iargs = args[0] & 0xffff;
1169
                nb_oargs = args[0] >> 16;
1170
                args++;
1171
                call_flags = args[nb_oargs + nb_iargs];
1172

    
1173
                /* pure functions can be removed if their result is not
1174
                   used */
1175
                if (call_flags & TCG_CALL_PURE) {
1176
                    for(i = 0; i < nb_oargs; i++) {
1177
                        arg = args[i];
1178
                        if (!dead_temps[arg])
1179
                            goto do_not_remove_call;
1180
                    }
1181
                    tcg_set_nop(s, gen_opc_buf + op_index, 
1182
                                args - 1, nb_args);
1183
                } else {
1184
                do_not_remove_call:
1185

    
1186
                    /* output args are dead */
1187
                    for(i = 0; i < nb_oargs; i++) {
1188
                        arg = args[i];
1189
                        dead_temps[arg] = 1;
1190
                    }
1191
                    
1192
                    if (!(call_flags & TCG_CALL_CONST)) {
1193
                        /* globals are live (they may be used by the call) */
1194
                        memset(dead_temps, 0, s->nb_globals);
1195
                    }
1196

    
1197
                    /* input args are live */
1198
                    dead_iargs = 0;
1199
                    for(i = 0; i < nb_iargs; i++) {
1200
                        arg = args[i + nb_oargs];
1201
                        if (arg != TCG_CALL_DUMMY_ARG) {
1202
                            if (dead_temps[arg]) {
1203
                                dead_iargs |= (1 << i);
1204
                            }
1205
                            dead_temps[arg] = 0;
1206
                        }
1207
                    }
1208
                    s->op_dead_iargs[op_index] = dead_iargs;
1209
                }
1210
                args--;
1211
            }
1212
            break;
1213
        case INDEX_op_set_label:
1214
            args--;
1215
            /* mark end of basic block */
1216
            tcg_la_bb_end(s, dead_temps);
1217
            break;
1218
        case INDEX_op_debug_insn_start:
1219
            args -= def->nb_args;
1220
            break;
1221
        case INDEX_op_nopn:
1222
            nb_args = args[-1];
1223
            args -= nb_args;
1224
            break;
1225
        case INDEX_op_discard:
1226
            args--;
1227
            /* mark the temporary as dead */
1228
            dead_temps[args[0]] = 1;
1229
            break;
1230
        case INDEX_op_end:
1231
            break;
1232
            /* XXX: optimize by hardcoding common cases (e.g. triadic ops) */
1233
        default:
1234
            args -= def->nb_args;
1235
            nb_iargs = def->nb_iargs;
1236
            nb_oargs = def->nb_oargs;
1237

    
1238
            /* Test if the operation can be removed because all
1239
               its outputs are dead. We assume that nb_oargs == 0
1240
               implies side effects */
1241
            if (!(def->flags & TCG_OPF_SIDE_EFFECTS) && nb_oargs != 0) {
1242
                for(i = 0; i < nb_oargs; i++) {
1243
                    arg = args[i];
1244
                    if (!dead_temps[arg])
1245
                        goto do_not_remove;
1246
                }
1247
                tcg_set_nop(s, gen_opc_buf + op_index, args, def->nb_args);
1248
#ifdef CONFIG_PROFILER
1249
                s->del_op_count++;
1250
#endif
1251
            } else {
1252
            do_not_remove:
1253

    
1254
                /* output args are dead */
1255
                for(i = 0; i < nb_oargs; i++) {
1256
                    arg = args[i];
1257
                    dead_temps[arg] = 1;
1258
                }
1259

    
1260
                /* if end of basic block, update */
1261
                if (def->flags & TCG_OPF_BB_END) {
1262
                    tcg_la_bb_end(s, dead_temps);
1263
                } else if (def->flags & TCG_OPF_CALL_CLOBBER) {
1264
                    /* globals are live */
1265
                    memset(dead_temps, 0, s->nb_globals);
1266
                }
1267

    
1268
                /* input args are live */
1269
                dead_iargs = 0;
1270
                for(i = 0; i < nb_iargs; i++) {
1271
                    arg = args[i + nb_oargs];
1272
                    if (dead_temps[arg]) {
1273
                        dead_iargs |= (1 << i);
1274
                    }
1275
                    dead_temps[arg] = 0;
1276
                }
1277
                s->op_dead_iargs[op_index] = dead_iargs;
1278
            }
1279
            break;
1280
        }
1281
        op_index--;
1282
    }
1283

    
1284
    if (args != gen_opparam_buf)
1285
        tcg_abort();
1286
}
1287
#else
1288
/* dummy liveness analysis */
1289
static void tcg_liveness_analysis(TCGContext *s)
1290
{
1291
    int nb_ops;
1292
    nb_ops = gen_opc_ptr - gen_opc_buf;
1293

    
1294
    s->op_dead_iargs = tcg_malloc(nb_ops * sizeof(uint16_t));
1295
    memset(s->op_dead_iargs, 0, nb_ops * sizeof(uint16_t));
1296
}
1297
#endif
1298

    
1299
#ifndef NDEBUG
1300
static void dump_regs(TCGContext *s)
1301
{
1302
    TCGTemp *ts;
1303
    int i;
1304
    char buf[64];
1305

    
1306
    for(i = 0; i < s->nb_temps; i++) {
1307
        ts = &s->temps[i];
1308
        printf("  %10s: ", tcg_get_arg_str_idx(s, buf, sizeof(buf), i));
1309
        switch(ts->val_type) {
1310
        case TEMP_VAL_REG:
1311
            printf("%s", tcg_target_reg_names[ts->reg]);
1312
            break;
1313
        case TEMP_VAL_MEM:
1314
            printf("%d(%s)", (int)ts->mem_offset, tcg_target_reg_names[ts->mem_reg]);
1315
            break;
1316
        case TEMP_VAL_CONST:
1317
            printf("$0x%" TCG_PRIlx, ts->val);
1318
            break;
1319
        case TEMP_VAL_DEAD:
1320
            printf("D");
1321
            break;
1322
        default:
1323
            printf("???");
1324
            break;
1325
        }
1326
        printf("\n");
1327
    }
1328

    
1329
    for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
1330
        if (s->reg_to_temp[i] >= 0) {
1331
            printf("%s: %s\n", 
1332
                   tcg_target_reg_names[i], 
1333
                   tcg_get_arg_str_idx(s, buf, sizeof(buf), s->reg_to_temp[i]));
1334
        }
1335
    }
1336
}
1337

    
1338
static void check_regs(TCGContext *s)
1339
{
1340
    int reg, k;
1341
    TCGTemp *ts;
1342
    char buf[64];
1343

    
1344
    for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1345
        k = s->reg_to_temp[reg];
1346
        if (k >= 0) {
1347
            ts = &s->temps[k];
1348
            if (ts->val_type != TEMP_VAL_REG ||
1349
                ts->reg != reg) {
1350
                printf("Inconsistency for register %s:\n", 
1351
                       tcg_target_reg_names[reg]);
1352
                goto fail;
1353
            }
1354
        }
1355
    }
1356
    for(k = 0; k < s->nb_temps; k++) {
1357
        ts = &s->temps[k];
1358
        if (ts->val_type == TEMP_VAL_REG &&
1359
            !ts->fixed_reg &&
1360
            s->reg_to_temp[ts->reg] != k) {
1361
                printf("Inconsistency for temp %s:\n", 
1362
                       tcg_get_arg_str_idx(s, buf, sizeof(buf), k));
1363
        fail:
1364
                printf("reg state:\n");
1365
                dump_regs(s);
1366
                tcg_abort();
1367
        }
1368
    }
1369
}
1370
#endif
1371

    
1372
static void temp_allocate_frame(TCGContext *s, int temp)
1373
{
1374
    TCGTemp *ts;
1375
    ts = &s->temps[temp];
1376
    s->current_frame_offset = (s->current_frame_offset + sizeof(tcg_target_long) - 1) & ~(sizeof(tcg_target_long) - 1);
1377
    if (s->current_frame_offset + sizeof(tcg_target_long) > s->frame_end)
1378
        tcg_abort();
1379
    ts->mem_offset = s->current_frame_offset;
1380
    ts->mem_reg = s->frame_reg;
1381
    ts->mem_allocated = 1;
1382
    s->current_frame_offset += sizeof(tcg_target_long);
1383
}
1384

    
1385
/* free register 'reg' by spilling the corresponding temporary if necessary */
1386
static void tcg_reg_free(TCGContext *s, int reg)
1387
{
1388
    TCGTemp *ts;
1389
    int temp;
1390

    
1391
    temp = s->reg_to_temp[reg];
1392
    if (temp != -1) {
1393
        ts = &s->temps[temp];
1394
        assert(ts->val_type == TEMP_VAL_REG);
1395
        if (!ts->mem_coherent) {
1396
            if (!ts->mem_allocated) 
1397
                temp_allocate_frame(s, temp);
1398
            tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1399
        }
1400
        ts->val_type = TEMP_VAL_MEM;
1401
        s->reg_to_temp[reg] = -1;
1402
    }
1403
}
1404

    
1405
/* Allocate a register belonging to reg1 & ~reg2 */
1406
static int tcg_reg_alloc(TCGContext *s, TCGRegSet reg1, TCGRegSet reg2)
1407
{
1408
    int i, reg;
1409
    TCGRegSet reg_ct;
1410

    
1411
    tcg_regset_andnot(reg_ct, reg1, reg2);
1412

    
1413
    /* first try free registers */
1414
    for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1415
        reg = tcg_target_reg_alloc_order[i];
1416
        if (tcg_regset_test_reg(reg_ct, reg) && s->reg_to_temp[reg] == -1)
1417
            return reg;
1418
    }
1419

    
1420
    /* XXX: do better spill choice */
1421
    for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1422
        reg = tcg_target_reg_alloc_order[i];
1423
        if (tcg_regset_test_reg(reg_ct, reg)) {
1424
            tcg_reg_free(s, reg);
1425
            return reg;
1426
        }
1427
    }
1428

    
1429
    tcg_abort();
1430
}
1431

    
1432
/* save a temporary to memory. 'allocated_regs' is used in case a
1433
   temporary registers needs to be allocated to store a constant. */
1434
static void temp_save(TCGContext *s, int temp, TCGRegSet allocated_regs)
1435
{
1436
    TCGTemp *ts;
1437
    int reg;
1438

    
1439
    ts = &s->temps[temp];
1440
    if (!ts->fixed_reg) {
1441
        switch(ts->val_type) {
1442
        case TEMP_VAL_REG:
1443
            tcg_reg_free(s, ts->reg);
1444
            break;
1445
        case TEMP_VAL_DEAD:
1446
            ts->val_type = TEMP_VAL_MEM;
1447
            break;
1448
        case TEMP_VAL_CONST:
1449
            reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], 
1450
                                allocated_regs);
1451
            if (!ts->mem_allocated) 
1452
                temp_allocate_frame(s, temp);
1453
            tcg_out_movi(s, ts->type, reg, ts->val);
1454
            tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1455
            ts->val_type = TEMP_VAL_MEM;
1456
            break;
1457
        case TEMP_VAL_MEM:
1458
            break;
1459
        default:
1460
            tcg_abort();
1461
        }
1462
    }
1463
}
1464

    
1465
/* save globals to their cannonical location and assume they can be
1466
   modified be the following code. 'allocated_regs' is used in case a
1467
   temporary registers needs to be allocated to store a constant. */
1468
static void save_globals(TCGContext *s, TCGRegSet allocated_regs)
1469
{
1470
    int i;
1471

    
1472
    for(i = 0; i < s->nb_globals; i++) {
1473
        temp_save(s, i, allocated_regs);
1474
    }
1475
}
1476

    
1477
/* at the end of a basic block, we assume all temporaries are dead and
1478
   all globals are stored at their canonical location. */
1479
static void tcg_reg_alloc_bb_end(TCGContext *s, TCGRegSet allocated_regs)
1480
{
1481
    TCGTemp *ts;
1482
    int i;
1483

    
1484
    for(i = s->nb_globals; i < s->nb_temps; i++) {
1485
        ts = &s->temps[i];
1486
        if (ts->temp_local) {
1487
            temp_save(s, i, allocated_regs);
1488
        } else {
1489
            if (ts->val_type == TEMP_VAL_REG) {
1490
                s->reg_to_temp[ts->reg] = -1;
1491
            }
1492
            ts->val_type = TEMP_VAL_DEAD;
1493
        }
1494
    }
1495

    
1496
    save_globals(s, allocated_regs);
1497
}
1498

    
1499
#define IS_DEAD_IARG(n) ((dead_iargs >> (n)) & 1)
1500

    
1501
static void tcg_reg_alloc_movi(TCGContext *s, const TCGArg *args)
1502
{
1503
    TCGTemp *ots;
1504
    tcg_target_ulong val;
1505

    
1506
    ots = &s->temps[args[0]];
1507
    val = args[1];
1508

    
1509
    if (ots->fixed_reg) {
1510
        /* for fixed registers, we do not do any constant
1511
           propagation */
1512
        tcg_out_movi(s, ots->type, ots->reg, val);
1513
    } else {
1514
        /* The movi is not explicitly generated here */
1515
        if (ots->val_type == TEMP_VAL_REG)
1516
            s->reg_to_temp[ots->reg] = -1;
1517
        ots->val_type = TEMP_VAL_CONST;
1518
        ots->val = val;
1519
    }
1520
}
1521

    
1522
static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
1523
                              const TCGArg *args,
1524
                              unsigned int dead_iargs)
1525
{
1526
    TCGTemp *ts, *ots;
1527
    int reg;
1528
    const TCGArgConstraint *arg_ct;
1529

    
1530
    ots = &s->temps[args[0]];
1531
    ts = &s->temps[args[1]];
1532
    arg_ct = &def->args_ct[0];
1533

    
1534
    /* XXX: always mark arg dead if IS_DEAD_IARG(0) */
1535
    if (ts->val_type == TEMP_VAL_REG) {
1536
        if (IS_DEAD_IARG(0) && !ts->fixed_reg && !ots->fixed_reg) {
1537
            /* the mov can be suppressed */
1538
            if (ots->val_type == TEMP_VAL_REG)
1539
                s->reg_to_temp[ots->reg] = -1;
1540
            reg = ts->reg;
1541
            s->reg_to_temp[reg] = -1;
1542
            ts->val_type = TEMP_VAL_DEAD;
1543
        } else {
1544
            if (ots->val_type == TEMP_VAL_REG) {
1545
                reg = ots->reg;
1546
            } else {
1547
                reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1548
            }
1549
            if (ts->reg != reg) {
1550
                tcg_out_mov(s, reg, ts->reg);
1551
            }
1552
        }
1553
    } else if (ts->val_type == TEMP_VAL_MEM) {
1554
        if (ots->val_type == TEMP_VAL_REG) {
1555
            reg = ots->reg;
1556
        } else {
1557
            reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1558
        }
1559
        tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1560
    } else if (ts->val_type == TEMP_VAL_CONST) {
1561
        if (ots->fixed_reg) {
1562
            reg = ots->reg;
1563
            tcg_out_movi(s, ots->type, reg, ts->val);
1564
        } else {
1565
            /* propagate constant */
1566
            if (ots->val_type == TEMP_VAL_REG)
1567
                s->reg_to_temp[ots->reg] = -1;
1568
            ots->val_type = TEMP_VAL_CONST;
1569
            ots->val = ts->val;
1570
            return;
1571
        }
1572
    } else {
1573
        tcg_abort();
1574
    }
1575
    s->reg_to_temp[reg] = args[0];
1576
    ots->reg = reg;
1577
    ots->val_type = TEMP_VAL_REG;
1578
    ots->mem_coherent = 0;
1579
}
1580

    
1581
static void tcg_reg_alloc_op(TCGContext *s, 
1582
                             const TCGOpDef *def, TCGOpcode opc,
1583
                             const TCGArg *args,
1584
                             unsigned int dead_iargs)
1585
{
1586
    TCGRegSet allocated_regs;
1587
    int i, k, nb_iargs, nb_oargs, reg;
1588
    TCGArg arg;
1589
    const TCGArgConstraint *arg_ct;
1590
    TCGTemp *ts;
1591
    TCGArg new_args[TCG_MAX_OP_ARGS];
1592
    int const_args[TCG_MAX_OP_ARGS];
1593

    
1594
    nb_oargs = def->nb_oargs;
1595
    nb_iargs = def->nb_iargs;
1596

    
1597
    /* copy constants */
1598
    memcpy(new_args + nb_oargs + nb_iargs, 
1599
           args + nb_oargs + nb_iargs, 
1600
           sizeof(TCGArg) * def->nb_cargs);
1601

    
1602
    /* satisfy input constraints */ 
1603
    tcg_regset_set(allocated_regs, s->reserved_regs);
1604
    for(k = 0; k < nb_iargs; k++) {
1605
        i = def->sorted_args[nb_oargs + k];
1606
        arg = args[i];
1607
        arg_ct = &def->args_ct[i];
1608
        ts = &s->temps[arg];
1609
        if (ts->val_type == TEMP_VAL_MEM) {
1610
            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1611
            tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1612
            ts->val_type = TEMP_VAL_REG;
1613
            ts->reg = reg;
1614
            ts->mem_coherent = 1;
1615
            s->reg_to_temp[reg] = arg;
1616
        } else if (ts->val_type == TEMP_VAL_CONST) {
1617
            if (tcg_target_const_match(ts->val, arg_ct)) {
1618
                /* constant is OK for instruction */
1619
                const_args[i] = 1;
1620
                new_args[i] = ts->val;
1621
                goto iarg_end;
1622
            } else {
1623
                /* need to move to a register */
1624
                reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1625
                tcg_out_movi(s, ts->type, reg, ts->val);
1626
                ts->val_type = TEMP_VAL_REG;
1627
                ts->reg = reg;
1628
                ts->mem_coherent = 0;
1629
                s->reg_to_temp[reg] = arg;
1630
            }
1631
        }
1632
        assert(ts->val_type == TEMP_VAL_REG);
1633
        if (arg_ct->ct & TCG_CT_IALIAS) {
1634
            if (ts->fixed_reg) {
1635
                /* if fixed register, we must allocate a new register
1636
                   if the alias is not the same register */
1637
                if (arg != args[arg_ct->alias_index])
1638
                    goto allocate_in_reg;
1639
            } else {
1640
                /* if the input is aliased to an output and if it is
1641
                   not dead after the instruction, we must allocate
1642
                   a new register and move it */
1643
                if (!IS_DEAD_IARG(i - nb_oargs)) 
1644
                    goto allocate_in_reg;
1645
            }
1646
        }
1647
        reg = ts->reg;
1648
        if (tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1649
            /* nothing to do : the constraint is satisfied */
1650
        } else {
1651
        allocate_in_reg:
1652
            /* allocate a new register matching the constraint 
1653
               and move the temporary register into it */
1654
            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1655
            tcg_out_mov(s, reg, ts->reg);
1656
        }
1657
        new_args[i] = reg;
1658
        const_args[i] = 0;
1659
        tcg_regset_set_reg(allocated_regs, reg);
1660
    iarg_end: ;
1661
    }
1662
    
1663
    if (def->flags & TCG_OPF_BB_END) {
1664
        tcg_reg_alloc_bb_end(s, allocated_regs);
1665
    } else {
1666
        /* mark dead temporaries and free the associated registers */
1667
        for(i = 0; i < nb_iargs; i++) {
1668
            arg = args[nb_oargs + i];
1669
            if (IS_DEAD_IARG(i)) {
1670
                ts = &s->temps[arg];
1671
                if (!ts->fixed_reg) {
1672
                    if (ts->val_type == TEMP_VAL_REG)
1673
                        s->reg_to_temp[ts->reg] = -1;
1674
                    ts->val_type = TEMP_VAL_DEAD;
1675
                }
1676
            }
1677
        }
1678
        
1679
        if (def->flags & TCG_OPF_CALL_CLOBBER) {
1680
            /* XXX: permit generic clobber register list ? */ 
1681
            for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1682
                if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
1683
                    tcg_reg_free(s, reg);
1684
                }
1685
            }
1686
            /* XXX: for load/store we could do that only for the slow path
1687
               (i.e. when a memory callback is called) */
1688
            
1689
            /* store globals and free associated registers (we assume the insn
1690
               can modify any global. */
1691
            save_globals(s, allocated_regs);
1692
        }
1693
        
1694
        /* satisfy the output constraints */
1695
        tcg_regset_set(allocated_regs, s->reserved_regs);
1696
        for(k = 0; k < nb_oargs; k++) {
1697
            i = def->sorted_args[k];
1698
            arg = args[i];
1699
            arg_ct = &def->args_ct[i];
1700
            ts = &s->temps[arg];
1701
            if (arg_ct->ct & TCG_CT_ALIAS) {
1702
                reg = new_args[arg_ct->alias_index];
1703
            } else {
1704
                /* if fixed register, we try to use it */
1705
                reg = ts->reg;
1706
                if (ts->fixed_reg &&
1707
                    tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1708
                    goto oarg_end;
1709
                }
1710
                reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1711
            }
1712
            tcg_regset_set_reg(allocated_regs, reg);
1713
            /* if a fixed register is used, then a move will be done afterwards */
1714
            if (!ts->fixed_reg) {
1715
                if (ts->val_type == TEMP_VAL_REG)
1716
                    s->reg_to_temp[ts->reg] = -1;
1717
                ts->val_type = TEMP_VAL_REG;
1718
                ts->reg = reg;
1719
                /* temp value is modified, so the value kept in memory is
1720
                   potentially not the same */
1721
                ts->mem_coherent = 0; 
1722
                s->reg_to_temp[reg] = arg;
1723
            }
1724
        oarg_end:
1725
            new_args[i] = reg;
1726
        }
1727
    }
1728

    
1729
    /* emit instruction */
1730
    tcg_out_op(s, opc, new_args, const_args);
1731
    
1732
    /* move the outputs in the correct register if needed */
1733
    for(i = 0; i < nb_oargs; i++) {
1734
        ts = &s->temps[args[i]];
1735
        reg = new_args[i];
1736
        if (ts->fixed_reg && ts->reg != reg) {
1737
            tcg_out_mov(s, ts->reg, reg);
1738
        }
1739
    }
1740
}
1741

    
1742
#ifdef TCG_TARGET_STACK_GROWSUP
1743
#define STACK_DIR(x) (-(x))
1744
#else
1745
#define STACK_DIR(x) (x)
1746
#endif
1747

    
1748
static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
1749
                              TCGOpcode opc, const TCGArg *args,
1750
                              unsigned int dead_iargs)
1751
{
1752
    int nb_iargs, nb_oargs, flags, nb_regs, i, reg, nb_params;
1753
    TCGArg arg, func_arg;
1754
    TCGTemp *ts;
1755
    tcg_target_long stack_offset, call_stack_size, func_addr;
1756
    int const_func_arg, allocate_args;
1757
    TCGRegSet allocated_regs;
1758
    const TCGArgConstraint *arg_ct;
1759

    
1760
    arg = *args++;
1761

    
1762
    nb_oargs = arg >> 16;
1763
    nb_iargs = arg & 0xffff;
1764
    nb_params = nb_iargs - 1;
1765

    
1766
    flags = args[nb_oargs + nb_iargs];
1767

    
1768
    nb_regs = tcg_target_get_call_iarg_regs_count(flags);
1769
    if (nb_regs > nb_params)
1770
        nb_regs = nb_params;
1771

    
1772
    /* assign stack slots first */
1773
    /* XXX: preallocate call stack */
1774
    call_stack_size = (nb_params - nb_regs) * sizeof(tcg_target_long);
1775
    call_stack_size = (call_stack_size + TCG_TARGET_STACK_ALIGN - 1) & 
1776
        ~(TCG_TARGET_STACK_ALIGN - 1);
1777
    allocate_args = (call_stack_size > TCG_STATIC_CALL_ARGS_SIZE);
1778
    if (allocate_args) {
1779
        tcg_out_addi(s, TCG_REG_CALL_STACK, -STACK_DIR(call_stack_size));
1780
    }
1781

    
1782
    stack_offset = TCG_TARGET_CALL_STACK_OFFSET;
1783
    for(i = nb_regs; i < nb_params; i++) {
1784
        arg = args[nb_oargs + i];
1785
#ifdef TCG_TARGET_STACK_GROWSUP
1786
        stack_offset -= sizeof(tcg_target_long);
1787
#endif
1788
        if (arg != TCG_CALL_DUMMY_ARG) {
1789
            ts = &s->temps[arg];
1790
            if (ts->val_type == TEMP_VAL_REG) {
1791
                tcg_out_st(s, ts->type, ts->reg, TCG_REG_CALL_STACK, stack_offset);
1792
            } else if (ts->val_type == TEMP_VAL_MEM) {
1793
                reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], 
1794
                                    s->reserved_regs);
1795
                /* XXX: not correct if reading values from the stack */
1796
                tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1797
                tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
1798
            } else if (ts->val_type == TEMP_VAL_CONST) {
1799
                reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], 
1800
                                    s->reserved_regs);
1801
                /* XXX: sign extend may be needed on some targets */
1802
                tcg_out_movi(s, ts->type, reg, ts->val);
1803
                tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
1804
            } else {
1805
                tcg_abort();
1806
            }
1807
        }
1808
#ifndef TCG_TARGET_STACK_GROWSUP
1809
        stack_offset += sizeof(tcg_target_long);
1810
#endif
1811
    }
1812
    
1813
    /* assign input registers */
1814
    tcg_regset_set(allocated_regs, s->reserved_regs);
1815
    for(i = 0; i < nb_regs; i++) {
1816
        arg = args[nb_oargs + i];
1817
        if (arg != TCG_CALL_DUMMY_ARG) {
1818
            ts = &s->temps[arg];
1819
            reg = tcg_target_call_iarg_regs[i];
1820
            tcg_reg_free(s, reg);
1821
            if (ts->val_type == TEMP_VAL_REG) {
1822
                if (ts->reg != reg) {
1823
                    tcg_out_mov(s, reg, ts->reg);
1824
                }
1825
            } else if (ts->val_type == TEMP_VAL_MEM) {
1826
                tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1827
            } else if (ts->val_type == TEMP_VAL_CONST) {
1828
                /* XXX: sign extend ? */
1829
                tcg_out_movi(s, ts->type, reg, ts->val);
1830
            } else {
1831
                tcg_abort();
1832
            }
1833
            tcg_regset_set_reg(allocated_regs, reg);
1834
        }
1835
    }
1836
    
1837
    /* assign function address */
1838
    func_arg = args[nb_oargs + nb_iargs - 1];
1839
    arg_ct = &def->args_ct[0];
1840
    ts = &s->temps[func_arg];
1841
    func_addr = ts->val;
1842
    const_func_arg = 0;
1843
    if (ts->val_type == TEMP_VAL_MEM) {
1844
        reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1845
        tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1846
        func_arg = reg;
1847
        tcg_regset_set_reg(allocated_regs, reg);
1848
    } else if (ts->val_type == TEMP_VAL_REG) {
1849
        reg = ts->reg;
1850
        if (!tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1851
            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1852
            tcg_out_mov(s, reg, ts->reg);
1853
        }
1854
        func_arg = reg;
1855
        tcg_regset_set_reg(allocated_regs, reg);
1856
    } else if (ts->val_type == TEMP_VAL_CONST) {
1857
        if (tcg_target_const_match(func_addr, arg_ct)) {
1858
            const_func_arg = 1;
1859
            func_arg = func_addr;
1860
        } else {
1861
            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1862
            tcg_out_movi(s, ts->type, reg, func_addr);
1863
            func_arg = reg;
1864
            tcg_regset_set_reg(allocated_regs, reg);
1865
        }
1866
    } else {
1867
        tcg_abort();
1868
    }
1869
        
1870
    
1871
    /* mark dead temporaries and free the associated registers */
1872
    for(i = 0; i < nb_iargs; i++) {
1873
        arg = args[nb_oargs + i];
1874
        if (IS_DEAD_IARG(i)) {
1875
            ts = &s->temps[arg];
1876
            if (!ts->fixed_reg) {
1877
                if (ts->val_type == TEMP_VAL_REG)
1878
                    s->reg_to_temp[ts->reg] = -1;
1879
                ts->val_type = TEMP_VAL_DEAD;
1880
            }
1881
        }
1882
    }
1883
    
1884
    /* clobber call registers */
1885
    for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1886
        if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
1887
            tcg_reg_free(s, reg);
1888
        }
1889
    }
1890
    
1891
    /* store globals and free associated registers (we assume the call
1892
       can modify any global. */
1893
    if (!(flags & TCG_CALL_CONST)) {
1894
        save_globals(s, allocated_regs);
1895
    }
1896

    
1897
    tcg_out_op(s, opc, &func_arg, &const_func_arg);
1898
    
1899
    if (allocate_args) {
1900
        tcg_out_addi(s, TCG_REG_CALL_STACK, STACK_DIR(call_stack_size));
1901
    }
1902

    
1903
    /* assign output registers and emit moves if needed */
1904
    for(i = 0; i < nb_oargs; i++) {
1905
        arg = args[i];
1906
        ts = &s->temps[arg];
1907
        reg = tcg_target_call_oarg_regs[i];
1908
        assert(s->reg_to_temp[reg] == -1);
1909
        if (ts->fixed_reg) {
1910
            if (ts->reg != reg) {
1911
                tcg_out_mov(s, ts->reg, reg);
1912
            }
1913
        } else {
1914
            if (ts->val_type == TEMP_VAL_REG)
1915
                s->reg_to_temp[ts->reg] = -1;
1916
            ts->val_type = TEMP_VAL_REG;
1917
            ts->reg = reg;
1918
            ts->mem_coherent = 0; 
1919
            s->reg_to_temp[reg] = arg;
1920
        }
1921
    }
1922
    
1923
    return nb_iargs + nb_oargs + def->nb_cargs + 1;
1924
}
1925

    
1926
#ifdef CONFIG_PROFILER
1927

    
1928
static int64_t tcg_table_op_count[NB_OPS];
1929

    
1930
static void dump_op_count(void)
1931
{
1932
    int i;
1933
    FILE *f;
1934
    f = fopen("/tmp/op.log", "w");
1935
    for(i = INDEX_op_end; i < NB_OPS; i++) {
1936
        fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name, tcg_table_op_count[i]);
1937
    }
1938
    fclose(f);
1939
}
1940
#endif
1941

    
1942

    
1943
static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
1944
                                      long search_pc)
1945
{
1946
    TCGOpcode opc;
1947
    int op_index;
1948
    const TCGOpDef *def;
1949
    unsigned int dead_iargs;
1950
    const TCGArg *args;
1951

    
1952
#ifdef DEBUG_DISAS
1953
    if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
1954
        qemu_log("OP:\n");
1955
        tcg_dump_ops(s, logfile);
1956
        qemu_log("\n");
1957
    }
1958
#endif
1959

    
1960
#ifdef CONFIG_PROFILER
1961
    s->la_time -= profile_getclock();
1962
#endif
1963
    tcg_liveness_analysis(s);
1964
#ifdef CONFIG_PROFILER
1965
    s->la_time += profile_getclock();
1966
#endif
1967

    
1968
#ifdef DEBUG_DISAS
1969
    if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_OPT))) {
1970
        qemu_log("OP after liveness analysis:\n");
1971
        tcg_dump_ops(s, logfile);
1972
        qemu_log("\n");
1973
    }
1974
#endif
1975

    
1976
    tcg_reg_alloc_start(s);
1977

    
1978
    s->code_buf = gen_code_buf;
1979
    s->code_ptr = gen_code_buf;
1980

    
1981
    args = gen_opparam_buf;
1982
    op_index = 0;
1983

    
1984
    for(;;) {
1985
        opc = gen_opc_buf[op_index];
1986
#ifdef CONFIG_PROFILER
1987
        tcg_table_op_count[opc]++;
1988
#endif
1989
        def = &tcg_op_defs[opc];
1990
#if 0
1991
        printf("%s: %d %d %d\n", def->name,
1992
               def->nb_oargs, def->nb_iargs, def->nb_cargs);
1993
        //        dump_regs(s);
1994
#endif
1995
        switch(opc) {
1996
        case INDEX_op_mov_i32:
1997
#if TCG_TARGET_REG_BITS == 64
1998
        case INDEX_op_mov_i64:
1999
#endif
2000
            dead_iargs = s->op_dead_iargs[op_index];
2001
            tcg_reg_alloc_mov(s, def, args, dead_iargs);
2002
            break;
2003
        case INDEX_op_movi_i32:
2004
#if TCG_TARGET_REG_BITS == 64
2005
        case INDEX_op_movi_i64:
2006
#endif
2007
            tcg_reg_alloc_movi(s, args);
2008
            break;
2009
        case INDEX_op_debug_insn_start:
2010
            /* debug instruction */
2011
            break;
2012
        case INDEX_op_nop:
2013
        case INDEX_op_nop1:
2014
        case INDEX_op_nop2:
2015
        case INDEX_op_nop3:
2016
            break;
2017
        case INDEX_op_nopn:
2018
            args += args[0];
2019
            goto next;
2020
        case INDEX_op_discard:
2021
            {
2022
                TCGTemp *ts;
2023
                ts = &s->temps[args[0]];
2024
                /* mark the temporary as dead */
2025
                if (!ts->fixed_reg) {
2026
                    if (ts->val_type == TEMP_VAL_REG)
2027
                        s->reg_to_temp[ts->reg] = -1;
2028
                    ts->val_type = TEMP_VAL_DEAD;
2029
                }
2030
            }
2031
            break;
2032
        case INDEX_op_set_label:
2033
            tcg_reg_alloc_bb_end(s, s->reserved_regs);
2034
            tcg_out_label(s, args[0], (long)s->code_ptr);
2035
            break;
2036
        case INDEX_op_call:
2037
            dead_iargs = s->op_dead_iargs[op_index];
2038
            args += tcg_reg_alloc_call(s, def, opc, args, dead_iargs);
2039
            goto next;
2040
        case INDEX_op_end:
2041
            goto the_end;
2042
        default:
2043
            /* Note: in order to speed up the code, it would be much
2044
               faster to have specialized register allocator functions for
2045
               some common argument patterns */
2046
            dead_iargs = s->op_dead_iargs[op_index];
2047
            tcg_reg_alloc_op(s, def, opc, args, dead_iargs);
2048
            break;
2049
        }
2050
        args += def->nb_args;
2051
    next:
2052
        if (search_pc >= 0 && search_pc < s->code_ptr - gen_code_buf) {
2053
            return op_index;
2054
        }
2055
        op_index++;
2056
#ifndef NDEBUG
2057
        check_regs(s);
2058
#endif
2059
    }
2060
 the_end:
2061
    return -1;
2062
}
2063

    
2064
int tcg_gen_code(TCGContext *s, uint8_t *gen_code_buf)
2065
{
2066
#ifdef CONFIG_PROFILER
2067
    {
2068
        int n;
2069
        n = (gen_opc_ptr - gen_opc_buf);
2070
        s->op_count += n;
2071
        if (n > s->op_count_max)
2072
            s->op_count_max = n;
2073

    
2074
        s->temp_count += s->nb_temps;
2075
        if (s->nb_temps > s->temp_count_max)
2076
            s->temp_count_max = s->nb_temps;
2077
    }
2078
#endif
2079

    
2080
    tcg_gen_code_common(s, gen_code_buf, -1);
2081

    
2082
    /* flush instruction cache */
2083
    flush_icache_range((unsigned long)gen_code_buf, 
2084
                       (unsigned long)s->code_ptr);
2085
    return s->code_ptr -  gen_code_buf;
2086
}
2087

    
2088
/* Return the index of the micro operation such as the pc after is <
2089
   offset bytes from the start of the TB.  The contents of gen_code_buf must
2090
   not be changed, though writing the same values is ok.
2091
   Return -1 if not found. */
2092
int tcg_gen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, long offset)
2093
{
2094
    return tcg_gen_code_common(s, gen_code_buf, offset);
2095
}
2096

    
2097
#ifdef CONFIG_PROFILER
2098
void tcg_dump_info(FILE *f,
2099
                   int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
2100
{
2101
    TCGContext *s = &tcg_ctx;
2102
    int64_t tot;
2103

    
2104
    tot = s->interm_time + s->code_time;
2105
    cpu_fprintf(f, "JIT cycles          %" PRId64 " (%0.3f s at 2.4 GHz)\n",
2106
                tot, tot / 2.4e9);
2107
    cpu_fprintf(f, "translated TBs      %" PRId64 " (aborted=%" PRId64 " %0.1f%%)\n", 
2108
                s->tb_count, 
2109
                s->tb_count1 - s->tb_count,
2110
                s->tb_count1 ? (double)(s->tb_count1 - s->tb_count) / s->tb_count1 * 100.0 : 0);
2111
    cpu_fprintf(f, "avg ops/TB          %0.1f max=%d\n", 
2112
                s->tb_count ? (double)s->op_count / s->tb_count : 0, s->op_count_max);
2113
    cpu_fprintf(f, "deleted ops/TB      %0.2f\n",
2114
                s->tb_count ? 
2115
                (double)s->del_op_count / s->tb_count : 0);
2116
    cpu_fprintf(f, "avg temps/TB        %0.2f max=%d\n",
2117
                s->tb_count ? 
2118
                (double)s->temp_count / s->tb_count : 0,
2119
                s->temp_count_max);
2120
    
2121
    cpu_fprintf(f, "cycles/op           %0.1f\n", 
2122
                s->op_count ? (double)tot / s->op_count : 0);
2123
    cpu_fprintf(f, "cycles/in byte      %0.1f\n", 
2124
                s->code_in_len ? (double)tot / s->code_in_len : 0);
2125
    cpu_fprintf(f, "cycles/out byte     %0.1f\n", 
2126
                s->code_out_len ? (double)tot / s->code_out_len : 0);
2127
    if (tot == 0)
2128
        tot = 1;
2129
    cpu_fprintf(f, "  gen_interm time   %0.1f%%\n", 
2130
                (double)s->interm_time / tot * 100.0);
2131
    cpu_fprintf(f, "  gen_code time     %0.1f%%\n", 
2132
                (double)s->code_time / tot * 100.0);
2133
    cpu_fprintf(f, "liveness/code time  %0.1f%%\n", 
2134
                (double)s->la_time / (s->code_time ? s->code_time : 1) * 100.0);
2135
    cpu_fprintf(f, "cpu_restore count   %" PRId64 "\n",
2136
                s->restore_count);
2137
    cpu_fprintf(f, "  avg cycles        %0.1f\n",
2138
                s->restore_count ? (double)s->restore_time / s->restore_count : 0);
2139

    
2140
    dump_op_count();
2141
}
2142
#else
2143
void tcg_dump_info(FILE *f,
2144
                   int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
2145
{
2146
    cpu_fprintf(f, "[TCG profiler not compiled]\n");
2147
}
2148
#endif