Statistics
| Branch: | Revision:

root / tcg / tcg.c @ 655feed5

History | View | Annotate | Download (63.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
#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

    
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
            /* If stack grows up, then we will be placing successive
600
               arguments at lower addresses, which means we need to
601
               reverse the order compared to how we would normally
602
               treat either big or little-endian.  For those arguments
603
               that will wind up in registers, this still works for
604
               HPPA (the only current STACK_GROWSUP target) since the
605
               argument registers are *also* allocated in decreasing
606
               order.  If another such target is added, this logic may
607
               have to get more complicated to differentiate between
608
               stack arguments and register arguments.  */
609
#if defined(TCG_TARGET_WORDS_BIGENDIAN) != defined(TCG_TARGET_STACK_GROWSUP)
610
            *gen_opparam_ptr++ = args[i] + 1;
611
            *gen_opparam_ptr++ = args[i];
612
#else
613
            *gen_opparam_ptr++ = args[i];
614
            *gen_opparam_ptr++ = args[i] + 1;
615
#endif
616
            real_args += 2;
617
        } else
618
#endif
619
        {
620
            *gen_opparam_ptr++ = args[i];
621
            real_args++;
622
        }
623
    }
624
    *gen_opparam_ptr++ = GET_TCGV_PTR(func);
625

    
626
    *gen_opparam_ptr++ = flags;
627

    
628
    *nparam = (nb_rets << 16) | (real_args + 1);
629

    
630
    /* total parameters, needed to go backward in the instruction stream */
631
    *gen_opparam_ptr++ = 1 + nb_rets + real_args + 3;
632
}
633

    
634
#if TCG_TARGET_REG_BITS == 32
635
void tcg_gen_shifti_i64(TCGv_i64 ret, TCGv_i64 arg1,
636
                        int c, int right, int arith)
637
{
638
    if (c == 0) {
639
        tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg1));
640
        tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
641
    } else if (c >= 32) {
642
        c -= 32;
643
        if (right) {
644
            if (arith) {
645
                tcg_gen_sari_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
646
                tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 31);
647
            } else {
648
                tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
649
                tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
650
            }
651
        } else {
652
            tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_LOW(arg1), c);
653
            tcg_gen_movi_i32(TCGV_LOW(ret), 0);
654
        }
655
    } else {
656
        TCGv_i32 t0, t1;
657

    
658
        t0 = tcg_temp_new_i32();
659
        t1 = tcg_temp_new_i32();
660
        if (right) {
661
            tcg_gen_shli_i32(t0, TCGV_HIGH(arg1), 32 - c);
662
            if (arith)
663
                tcg_gen_sari_i32(t1, TCGV_HIGH(arg1), c);
664
            else
665
                tcg_gen_shri_i32(t1, TCGV_HIGH(arg1), c);
666
            tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_LOW(arg1), c);
667
            tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(ret), t0);
668
            tcg_gen_mov_i32(TCGV_HIGH(ret), t1);
669
        } else {
670
            tcg_gen_shri_i32(t0, TCGV_LOW(arg1), 32 - c);
671
            /* Note: ret can be the same as arg1, so we use t1 */
672
            tcg_gen_shli_i32(t1, TCGV_LOW(arg1), c);
673
            tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c);
674
            tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t0);
675
            tcg_gen_mov_i32(TCGV_LOW(ret), t1);
676
        }
677
        tcg_temp_free_i32(t0);
678
        tcg_temp_free_i32(t1);
679
    }
680
}
681
#endif
682

    
683

    
684
static void tcg_reg_alloc_start(TCGContext *s)
685
{
686
    int i;
687
    TCGTemp *ts;
688
    for(i = 0; i < s->nb_globals; i++) {
689
        ts = &s->temps[i];
690
        if (ts->fixed_reg) {
691
            ts->val_type = TEMP_VAL_REG;
692
        } else {
693
            ts->val_type = TEMP_VAL_MEM;
694
        }
695
    }
696
    for(i = s->nb_globals; i < s->nb_temps; i++) {
697
        ts = &s->temps[i];
698
        ts->val_type = TEMP_VAL_DEAD;
699
        ts->mem_allocated = 0;
700
        ts->fixed_reg = 0;
701
    }
702
    for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
703
        s->reg_to_temp[i] = -1;
704
    }
705
}
706

    
707
static char *tcg_get_arg_str_idx(TCGContext *s, char *buf, int buf_size,
708
                                 int idx)
709
{
710
    TCGTemp *ts;
711

    
712
    ts = &s->temps[idx];
713
    if (idx < s->nb_globals) {
714
        pstrcpy(buf, buf_size, ts->name);
715
    } else {
716
        if (ts->temp_local) 
717
            snprintf(buf, buf_size, "loc%d", idx - s->nb_globals);
718
        else
719
            snprintf(buf, buf_size, "tmp%d", idx - s->nb_globals);
720
    }
721
    return buf;
722
}
723

    
724
char *tcg_get_arg_str_i32(TCGContext *s, char *buf, int buf_size, TCGv_i32 arg)
725
{
726
    return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I32(arg));
727
}
728

    
729
char *tcg_get_arg_str_i64(TCGContext *s, char *buf, int buf_size, TCGv_i64 arg)
730
{
731
    return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I64(arg));
732
}
733

    
734
static int helper_cmp(const void *p1, const void *p2)
735
{
736
    const TCGHelperInfo *th1 = p1;
737
    const TCGHelperInfo *th2 = p2;
738
    if (th1->func < th2->func)
739
        return -1;
740
    else if (th1->func == th2->func)
741
        return 0;
742
    else
743
        return 1;
744
}
745

    
746
/* find helper definition (Note: A hash table would be better) */
747
static TCGHelperInfo *tcg_find_helper(TCGContext *s, tcg_target_ulong val)
748
{
749
    int m, m_min, m_max;
750
    TCGHelperInfo *th;
751
    tcg_target_ulong v;
752

    
753
    if (unlikely(!s->helpers_sorted)) {
754
        qsort(s->helpers, s->nb_helpers, sizeof(TCGHelperInfo), 
755
              helper_cmp);
756
        s->helpers_sorted = 1;
757
    }
758

    
759
    /* binary search */
760
    m_min = 0;
761
    m_max = s->nb_helpers - 1;
762
    while (m_min <= m_max) {
763
        m = (m_min + m_max) >> 1;
764
        th = &s->helpers[m];
765
        v = th->func;
766
        if (v == val)
767
            return th;
768
        else if (val < v) {
769
            m_max = m - 1;
770
        } else {
771
            m_min = m + 1;
772
        }
773
    }
774
    return NULL;
775
}
776

    
777
static const char * const cond_name[] =
778
{
779
    [TCG_COND_EQ] = "eq",
780
    [TCG_COND_NE] = "ne",
781
    [TCG_COND_LT] = "lt",
782
    [TCG_COND_GE] = "ge",
783
    [TCG_COND_LE] = "le",
784
    [TCG_COND_GT] = "gt",
785
    [TCG_COND_LTU] = "ltu",
786
    [TCG_COND_GEU] = "geu",
787
    [TCG_COND_LEU] = "leu",
788
    [TCG_COND_GTU] = "gtu"
789
};
790

    
791
void tcg_dump_ops(TCGContext *s, FILE *outfile)
792
{
793
    const uint16_t *opc_ptr;
794
    const TCGArg *args;
795
    TCGArg arg;
796
    TCGOpcode c;
797
    int i, k, nb_oargs, nb_iargs, nb_cargs, first_insn;
798
    const TCGOpDef *def;
799
    char buf[128];
800

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

    
824
            /* variable number of arguments */
825
            arg = *args++;
826
            nb_oargs = arg >> 16;
827
            nb_iargs = arg & 0xffff;
828
            nb_cargs = def->nb_cargs;
829

    
830
            fprintf(outfile, " %s ", def->name);
831

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

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

    
938
/* we give more priority to constraints with less registers */
939
static int get_constraint_priority(const TCGOpDef *def, int k)
940
{
941
    const TCGArgConstraint *arg_ct;
942

    
943
    int i, n;
944
    arg_ct = &def->args_ct[k];
945
    if (arg_ct->ct & TCG_CT_ALIAS) {
946
        /* an alias is equivalent to a single register */
947
        n = 1;
948
    } else {
949
        if (!(arg_ct->ct & TCG_CT_REG))
950
            return 0;
951
        n = 0;
952
        for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
953
            if (tcg_regset_test_reg(arg_ct->u.regs, i))
954
                n++;
955
        }
956
    }
957
    return TCG_TARGET_NB_REGS - n + 1;
958
}
959

    
960
/* sort from highest priority to lowest */
961
static void sort_constraints(TCGOpDef *def, int start, int n)
962
{
963
    int i, j, p1, p2, tmp;
964

    
965
    for(i = 0; i < n; i++)
966
        def->sorted_args[start + i] = start + i;
967
    if (n <= 1)
968
        return;
969
    for(i = 0; i < n - 1; i++) {
970
        for(j = i + 1; j < n; j++) {
971
            p1 = get_constraint_priority(def, def->sorted_args[start + i]);
972
            p2 = get_constraint_priority(def, def->sorted_args[start + j]);
973
            if (p1 < p2) {
974
                tmp = def->sorted_args[start + i];
975
                def->sorted_args[start + i] = def->sorted_args[start + j];
976
                def->sorted_args[start + j] = tmp;
977
            }
978
        }
979
    }
980
}
981

    
982
void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs)
983
{
984
    TCGOpcode op;
985
    TCGOpDef *def;
986
    const char *ct_str;
987
    int i, nb_args;
988

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

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

    
1042
        /* sort the constraints (XXX: this is just an heuristic) */
1043
        sort_constraints(def, 0, def->nb_oargs);
1044
        sort_constraints(def, def->nb_oargs, def->nb_iargs);
1045

    
1046
#if 0
1047
        {
1048
            int i;
1049

1050
            printf("%s: sorted=", def->name);
1051
            for(i = 0; i < def->nb_oargs + def->nb_iargs; i++)
1052
                printf(" %d", def->sorted_args[i]);
1053
            printf("\n");
1054
        }
1055
#endif
1056
        tdefs++;
1057
    }
1058

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

    
1084
#ifdef USE_LIVENESS_ANALYSIS
1085

    
1086
/* set a nop for an operation using 'nb_args' */
1087
static inline void tcg_set_nop(TCGContext *s, uint16_t *opc_ptr, 
1088
                               TCGArg *args, int nb_args)
1089
{
1090
    if (nb_args == 0) {
1091
        *opc_ptr = INDEX_op_nop;
1092
    } else {
1093
        *opc_ptr = INDEX_op_nopn;
1094
        args[0] = nb_args;
1095
        args[nb_args - 1] = nb_args;
1096
    }
1097
}
1098

    
1099
/* liveness analysis: end of function: globals are live, temps are
1100
   dead. */
1101
/* XXX: at this stage, not used as there would be little gains because
1102
   most TBs end with a conditional jump. */
1103
static inline void tcg_la_func_end(TCGContext *s, uint8_t *dead_temps)
1104
{
1105
    memset(dead_temps, 0, s->nb_globals);
1106
    memset(dead_temps + s->nb_globals, 1, s->nb_temps - s->nb_globals);
1107
}
1108

    
1109
/* liveness analysis: end of basic block: globals are live, temps are
1110
   dead, local temps are live. */
1111
static inline void tcg_la_bb_end(TCGContext *s, uint8_t *dead_temps)
1112
{
1113
    int i;
1114
    TCGTemp *ts;
1115

    
1116
    memset(dead_temps, 0, s->nb_globals);
1117
    ts = &s->temps[s->nb_globals];
1118
    for(i = s->nb_globals; i < s->nb_temps; i++) {
1119
        if (ts->temp_local)
1120
            dead_temps[i] = 0;
1121
        else
1122
            dead_temps[i] = 1;
1123
        ts++;
1124
    }
1125
}
1126

    
1127
/* Liveness analysis : update the opc_dead_iargs array to tell if a
1128
   given input arguments is dead. Instructions updating dead
1129
   temporaries are removed. */
1130
static void tcg_liveness_analysis(TCGContext *s)
1131
{
1132
    int i, op_index, nb_args, nb_iargs, nb_oargs, arg, nb_ops;
1133
    TCGOpcode op;
1134
    TCGArg *args;
1135
    const TCGOpDef *def;
1136
    uint8_t *dead_temps;
1137
    unsigned int dead_iargs;
1138
    
1139
    gen_opc_ptr++; /* skip end */
1140

    
1141
    nb_ops = gen_opc_ptr - gen_opc_buf;
1142

    
1143
    s->op_dead_iargs = tcg_malloc(nb_ops * sizeof(uint16_t));
1144
    
1145
    dead_temps = tcg_malloc(s->nb_temps);
1146
    memset(dead_temps, 1, s->nb_temps);
1147

    
1148
    args = gen_opparam_ptr;
1149
    op_index = nb_ops - 1;
1150
    while (op_index >= 0) {
1151
        op = gen_opc_buf[op_index];
1152
        def = &tcg_op_defs[op];
1153
        switch(op) {
1154
        case INDEX_op_call:
1155
            {
1156
                int call_flags;
1157

    
1158
                nb_args = args[-1];
1159
                args -= nb_args;
1160
                nb_iargs = args[0] & 0xffff;
1161
                nb_oargs = args[0] >> 16;
1162
                args++;
1163
                call_flags = args[nb_oargs + nb_iargs];
1164

    
1165
                /* pure functions can be removed if their result is not
1166
                   used */
1167
                if (call_flags & TCG_CALL_PURE) {
1168
                    for(i = 0; i < nb_oargs; i++) {
1169
                        arg = args[i];
1170
                        if (!dead_temps[arg])
1171
                            goto do_not_remove_call;
1172
                    }
1173
                    tcg_set_nop(s, gen_opc_buf + op_index, 
1174
                                args - 1, nb_args);
1175
                } else {
1176
                do_not_remove_call:
1177

    
1178
                    /* output args are dead */
1179
                    for(i = 0; i < nb_oargs; i++) {
1180
                        arg = args[i];
1181
                        dead_temps[arg] = 1;
1182
                    }
1183
                    
1184
                    if (!(call_flags & TCG_CALL_CONST)) {
1185
                        /* globals are live (they may be used by the call) */
1186
                        memset(dead_temps, 0, s->nb_globals);
1187
                    }
1188

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

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

    
1246
                /* output args are dead */
1247
                for(i = 0; i < nb_oargs; i++) {
1248
                    arg = args[i];
1249
                    dead_temps[arg] = 1;
1250
                }
1251

    
1252
                /* if end of basic block, update */
1253
                if (def->flags & TCG_OPF_BB_END) {
1254
                    tcg_la_bb_end(s, dead_temps);
1255
                } else if (def->flags & TCG_OPF_CALL_CLOBBER) {
1256
                    /* globals are live */
1257
                    memset(dead_temps, 0, s->nb_globals);
1258
                }
1259

    
1260
                /* input args are live */
1261
                dead_iargs = 0;
1262
                for(i = 0; i < nb_iargs; i++) {
1263
                    arg = args[i + nb_oargs];
1264
                    if (dead_temps[arg]) {
1265
                        dead_iargs |= (1 << i);
1266
                    }
1267
                    dead_temps[arg] = 0;
1268
                }
1269
                s->op_dead_iargs[op_index] = dead_iargs;
1270
            }
1271
            break;
1272
        }
1273
        op_index--;
1274
    }
1275

    
1276
    if (args != gen_opparam_buf)
1277
        tcg_abort();
1278
}
1279
#else
1280
/* dummy liveness analysis */
1281
static void tcg_liveness_analysis(TCGContext *s)
1282
{
1283
    int nb_ops;
1284
    nb_ops = gen_opc_ptr - gen_opc_buf;
1285

    
1286
    s->op_dead_iargs = tcg_malloc(nb_ops * sizeof(uint16_t));
1287
    memset(s->op_dead_iargs, 0, nb_ops * sizeof(uint16_t));
1288
}
1289
#endif
1290

    
1291
#ifndef NDEBUG
1292
static void dump_regs(TCGContext *s)
1293
{
1294
    TCGTemp *ts;
1295
    int i;
1296
    char buf[64];
1297

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

    
1321
    for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
1322
        if (s->reg_to_temp[i] >= 0) {
1323
            printf("%s: %s\n", 
1324
                   tcg_target_reg_names[i], 
1325
                   tcg_get_arg_str_idx(s, buf, sizeof(buf), s->reg_to_temp[i]));
1326
        }
1327
    }
1328
}
1329

    
1330
static void check_regs(TCGContext *s)
1331
{
1332
    int reg, k;
1333
    TCGTemp *ts;
1334
    char buf[64];
1335

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

    
1364
static void temp_allocate_frame(TCGContext *s, int temp)
1365
{
1366
    TCGTemp *ts;
1367
    ts = &s->temps[temp];
1368
    s->current_frame_offset = (s->current_frame_offset + sizeof(tcg_target_long) - 1) & ~(sizeof(tcg_target_long) - 1);
1369
    if (s->current_frame_offset + sizeof(tcg_target_long) > s->frame_end)
1370
        tcg_abort();
1371
    ts->mem_offset = s->current_frame_offset;
1372
    ts->mem_reg = s->frame_reg;
1373
    ts->mem_allocated = 1;
1374
    s->current_frame_offset += sizeof(tcg_target_long);
1375
}
1376

    
1377
/* free register 'reg' by spilling the corresponding temporary if necessary */
1378
static void tcg_reg_free(TCGContext *s, int reg)
1379
{
1380
    TCGTemp *ts;
1381
    int temp;
1382

    
1383
    temp = s->reg_to_temp[reg];
1384
    if (temp != -1) {
1385
        ts = &s->temps[temp];
1386
        assert(ts->val_type == TEMP_VAL_REG);
1387
        if (!ts->mem_coherent) {
1388
            if (!ts->mem_allocated) 
1389
                temp_allocate_frame(s, temp);
1390
            tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1391
        }
1392
        ts->val_type = TEMP_VAL_MEM;
1393
        s->reg_to_temp[reg] = -1;
1394
    }
1395
}
1396

    
1397
/* Allocate a register belonging to reg1 & ~reg2 */
1398
static int tcg_reg_alloc(TCGContext *s, TCGRegSet reg1, TCGRegSet reg2)
1399
{
1400
    int i, reg;
1401
    TCGRegSet reg_ct;
1402

    
1403
    tcg_regset_andnot(reg_ct, reg1, reg2);
1404

    
1405
    /* first try free registers */
1406
    for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1407
        reg = tcg_target_reg_alloc_order[i];
1408
        if (tcg_regset_test_reg(reg_ct, reg) && s->reg_to_temp[reg] == -1)
1409
            return reg;
1410
    }
1411

    
1412
    /* XXX: do better spill choice */
1413
    for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1414
        reg = tcg_target_reg_alloc_order[i];
1415
        if (tcg_regset_test_reg(reg_ct, reg)) {
1416
            tcg_reg_free(s, reg);
1417
            return reg;
1418
        }
1419
    }
1420

    
1421
    tcg_abort();
1422
}
1423

    
1424
/* save a temporary to memory. 'allocated_regs' is used in case a
1425
   temporary registers needs to be allocated to store a constant. */
1426
static void temp_save(TCGContext *s, int temp, TCGRegSet allocated_regs)
1427
{
1428
    TCGTemp *ts;
1429
    int reg;
1430

    
1431
    ts = &s->temps[temp];
1432
    if (!ts->fixed_reg) {
1433
        switch(ts->val_type) {
1434
        case TEMP_VAL_REG:
1435
            tcg_reg_free(s, ts->reg);
1436
            break;
1437
        case TEMP_VAL_DEAD:
1438
            ts->val_type = TEMP_VAL_MEM;
1439
            break;
1440
        case TEMP_VAL_CONST:
1441
            reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], 
1442
                                allocated_regs);
1443
            if (!ts->mem_allocated) 
1444
                temp_allocate_frame(s, temp);
1445
            tcg_out_movi(s, ts->type, reg, ts->val);
1446
            tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1447
            ts->val_type = TEMP_VAL_MEM;
1448
            break;
1449
        case TEMP_VAL_MEM:
1450
            break;
1451
        default:
1452
            tcg_abort();
1453
        }
1454
    }
1455
}
1456

    
1457
/* save globals to their cannonical location and assume they can be
1458
   modified be the following code. 'allocated_regs' is used in case a
1459
   temporary registers needs to be allocated to store a constant. */
1460
static void save_globals(TCGContext *s, TCGRegSet allocated_regs)
1461
{
1462
    int i;
1463

    
1464
    for(i = 0; i < s->nb_globals; i++) {
1465
        temp_save(s, i, allocated_regs);
1466
    }
1467
}
1468

    
1469
/* at the end of a basic block, we assume all temporaries are dead and
1470
   all globals are stored at their canonical location. */
1471
static void tcg_reg_alloc_bb_end(TCGContext *s, TCGRegSet allocated_regs)
1472
{
1473
    TCGTemp *ts;
1474
    int i;
1475

    
1476
    for(i = s->nb_globals; i < s->nb_temps; i++) {
1477
        ts = &s->temps[i];
1478
        if (ts->temp_local) {
1479
            temp_save(s, i, allocated_regs);
1480
        } else {
1481
            if (ts->val_type == TEMP_VAL_REG) {
1482
                s->reg_to_temp[ts->reg] = -1;
1483
            }
1484
            ts->val_type = TEMP_VAL_DEAD;
1485
        }
1486
    }
1487

    
1488
    save_globals(s, allocated_regs);
1489
}
1490

    
1491
#define IS_DEAD_IARG(n) ((dead_iargs >> (n)) & 1)
1492

    
1493
static void tcg_reg_alloc_movi(TCGContext *s, const TCGArg *args)
1494
{
1495
    TCGTemp *ots;
1496
    tcg_target_ulong val;
1497

    
1498
    ots = &s->temps[args[0]];
1499
    val = args[1];
1500

    
1501
    if (ots->fixed_reg) {
1502
        /* for fixed registers, we do not do any constant
1503
           propagation */
1504
        tcg_out_movi(s, ots->type, ots->reg, val);
1505
    } else {
1506
        /* The movi is not explicitly generated here */
1507
        if (ots->val_type == TEMP_VAL_REG)
1508
            s->reg_to_temp[ots->reg] = -1;
1509
        ots->val_type = TEMP_VAL_CONST;
1510
        ots->val = val;
1511
    }
1512
}
1513

    
1514
static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
1515
                              const TCGArg *args,
1516
                              unsigned int dead_iargs)
1517
{
1518
    TCGTemp *ts, *ots;
1519
    int reg;
1520
    const TCGArgConstraint *arg_ct;
1521

    
1522
    ots = &s->temps[args[0]];
1523
    ts = &s->temps[args[1]];
1524
    arg_ct = &def->args_ct[0];
1525

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

    
1573
static void tcg_reg_alloc_op(TCGContext *s, 
1574
                             const TCGOpDef *def, TCGOpcode opc,
1575
                             const TCGArg *args,
1576
                             unsigned int dead_iargs)
1577
{
1578
    TCGRegSet allocated_regs;
1579
    int i, k, nb_iargs, nb_oargs, reg;
1580
    TCGArg arg;
1581
    const TCGArgConstraint *arg_ct;
1582
    TCGTemp *ts;
1583
    TCGArg new_args[TCG_MAX_OP_ARGS];
1584
    int const_args[TCG_MAX_OP_ARGS];
1585

    
1586
    nb_oargs = def->nb_oargs;
1587
    nb_iargs = def->nb_iargs;
1588

    
1589
    /* copy constants */
1590
    memcpy(new_args + nb_oargs + nb_iargs, 
1591
           args + nb_oargs + nb_iargs, 
1592
           sizeof(TCGArg) * def->nb_cargs);
1593

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

    
1721
    /* emit instruction */
1722
    tcg_out_op(s, opc, new_args, const_args);
1723
    
1724
    /* move the outputs in the correct register if needed */
1725
    for(i = 0; i < nb_oargs; i++) {
1726
        ts = &s->temps[args[i]];
1727
        reg = new_args[i];
1728
        if (ts->fixed_reg && ts->reg != reg) {
1729
            tcg_out_mov(s, ts->reg, reg);
1730
        }
1731
    }
1732
}
1733

    
1734
#ifdef TCG_TARGET_STACK_GROWSUP
1735
#define STACK_DIR(x) (-(x))
1736
#else
1737
#define STACK_DIR(x) (x)
1738
#endif
1739

    
1740
static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
1741
                              TCGOpcode opc, const TCGArg *args,
1742
                              unsigned int dead_iargs)
1743
{
1744
    int nb_iargs, nb_oargs, flags, nb_regs, i, reg, nb_params;
1745
    TCGArg arg, func_arg;
1746
    TCGTemp *ts;
1747
    tcg_target_long stack_offset, call_stack_size, func_addr;
1748
    int const_func_arg, allocate_args;
1749
    TCGRegSet allocated_regs;
1750
    const TCGArgConstraint *arg_ct;
1751

    
1752
    arg = *args++;
1753

    
1754
    nb_oargs = arg >> 16;
1755
    nb_iargs = arg & 0xffff;
1756
    nb_params = nb_iargs - 1;
1757

    
1758
    flags = args[nb_oargs + nb_iargs];
1759

    
1760
    nb_regs = tcg_target_get_call_iarg_regs_count(flags);
1761
    if (nb_regs > nb_params)
1762
        nb_regs = nb_params;
1763

    
1764
    /* assign stack slots first */
1765
    /* XXX: preallocate call stack */
1766
    call_stack_size = (nb_params - nb_regs) * sizeof(tcg_target_long);
1767
    call_stack_size = (call_stack_size + TCG_TARGET_STACK_ALIGN - 1) & 
1768
        ~(TCG_TARGET_STACK_ALIGN - 1);
1769
    allocate_args = (call_stack_size > TCG_STATIC_CALL_ARGS_SIZE);
1770
    if (allocate_args) {
1771
        tcg_out_addi(s, TCG_REG_CALL_STACK, -STACK_DIR(call_stack_size));
1772
    }
1773

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

    
1889
    tcg_out_op(s, opc, &func_arg, &const_func_arg);
1890
    
1891
    if (allocate_args) {
1892
        tcg_out_addi(s, TCG_REG_CALL_STACK, STACK_DIR(call_stack_size));
1893
    }
1894

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

    
1918
#ifdef CONFIG_PROFILER
1919

    
1920
static int64_t tcg_table_op_count[NB_OPS];
1921

    
1922
static void dump_op_count(void)
1923
{
1924
    int i;
1925
    FILE *f;
1926
    f = fopen("/tmp/op.log", "w");
1927
    for(i = INDEX_op_end; i < NB_OPS; i++) {
1928
        fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name, tcg_table_op_count[i]);
1929
    }
1930
    fclose(f);
1931
}
1932
#endif
1933

    
1934

    
1935
static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
1936
                                      long search_pc)
1937
{
1938
    TCGOpcode opc;
1939
    int op_index;
1940
    const TCGOpDef *def;
1941
    unsigned int dead_iargs;
1942
    const TCGArg *args;
1943

    
1944
#ifdef DEBUG_DISAS
1945
    if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
1946
        qemu_log("OP:\n");
1947
        tcg_dump_ops(s, logfile);
1948
        qemu_log("\n");
1949
    }
1950
#endif
1951

    
1952
#ifdef CONFIG_PROFILER
1953
    s->la_time -= profile_getclock();
1954
#endif
1955
    tcg_liveness_analysis(s);
1956
#ifdef CONFIG_PROFILER
1957
    s->la_time += profile_getclock();
1958
#endif
1959

    
1960
#ifdef DEBUG_DISAS
1961
    if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_OPT))) {
1962
        qemu_log("OP after liveness analysis:\n");
1963
        tcg_dump_ops(s, logfile);
1964
        qemu_log("\n");
1965
    }
1966
#endif
1967

    
1968
    tcg_reg_alloc_start(s);
1969

    
1970
    s->code_buf = gen_code_buf;
1971
    s->code_ptr = gen_code_buf;
1972

    
1973
    args = gen_opparam_buf;
1974
    op_index = 0;
1975

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

    
2056
int tcg_gen_code(TCGContext *s, uint8_t *gen_code_buf)
2057
{
2058
#ifdef CONFIG_PROFILER
2059
    {
2060
        int n;
2061
        n = (gen_opc_ptr - gen_opc_buf);
2062
        s->op_count += n;
2063
        if (n > s->op_count_max)
2064
            s->op_count_max = n;
2065

    
2066
        s->temp_count += s->nb_temps;
2067
        if (s->nb_temps > s->temp_count_max)
2068
            s->temp_count_max = s->nb_temps;
2069
    }
2070
#endif
2071

    
2072
    tcg_gen_code_common(s, gen_code_buf, -1);
2073

    
2074
    /* flush instruction cache */
2075
    flush_icache_range((unsigned long)gen_code_buf, 
2076
                       (unsigned long)s->code_ptr);
2077
    return s->code_ptr -  gen_code_buf;
2078
}
2079

    
2080
/* Return the index of the micro operation such as the pc after is <
2081
   offset bytes from the start of the TB.  The contents of gen_code_buf must
2082
   not be changed, though writing the same values is ok.
2083
   Return -1 if not found. */
2084
int tcg_gen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, long offset)
2085
{
2086
    return tcg_gen_code_common(s, gen_code_buf, offset);
2087
}
2088

    
2089
#ifdef CONFIG_PROFILER
2090
void tcg_dump_info(FILE *f,
2091
                   int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
2092
{
2093
    TCGContext *s = &tcg_ctx;
2094
    int64_t tot;
2095

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

    
2132
    dump_op_count();
2133
}
2134
#else
2135
void tcg_dump_info(FILE *f,
2136
                   int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
2137
{
2138
    cpu_fprintf(f, "[TCG profiler not compiled]\n");
2139
}
2140
#endif