Statistics
| Branch: | Revision:

root / tcg / tcg.c @ a810a2de

History | View | Annotate | Download (63.6 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 suppress various consistency checks (faster) */
26
#define NDEBUG
27

    
28
/* define it to use liveness analysis (better code) */
29
#define USE_LIVENESS_ANALYSIS
30

    
31
#include <assert.h>
32
#include <stdarg.h>
33
#include <stdlib.h>
34
#include <stdio.h>
35
#include <string.h>
36
#include <inttypes.h>
37
#ifdef _WIN32
38
#include <malloc.h>
39
#endif
40
#ifdef _AIX
41
#include <alloca.h>
42
#endif
43

    
44
#include "config.h"
45
#include "qemu-common.h"
46

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

    
54
#include "tcg-op.h"
55
#include "elf.h"
56

    
57

    
58
static void patch_reloc(uint8_t *code_ptr, int type, 
59
                        tcg_target_long value, tcg_target_long addend);
60

    
61
TCGOpDef tcg_op_defs[] = {
62
#define DEF(s, n, copy_size) { #s, 0, 0, n, n, 0, copy_size },
63
#define DEF2(s, iargs, oargs, cargs, flags) { #s, iargs, oargs, cargs, iargs + oargs + cargs, flags, 0 },
64
#include "tcg-opc.h"
65
#undef DEF
66
#undef DEF2
67
};
68

    
69
static TCGRegSet tcg_target_available_regs[2];
70
static TCGRegSet tcg_target_call_clobber_regs;
71

    
72
/* XXX: move that inside the context */
73
uint16_t *gen_opc_ptr;
74
TCGArg *gen_opparam_ptr;
75

    
76
static inline void tcg_out8(TCGContext *s, uint8_t v)
77
{
78
    *s->code_ptr++ = v;
79
}
80

    
81
static inline void tcg_out16(TCGContext *s, uint16_t v)
82
{
83
    *(uint16_t *)s->code_ptr = v;
84
    s->code_ptr += 2;
85
}
86

    
87
static inline void tcg_out32(TCGContext *s, uint32_t v)
88
{
89
    *(uint32_t *)s->code_ptr = v;
90
    s->code_ptr += 4;
91
}
92

    
93
/* label relocation processing */
94

    
95
void tcg_out_reloc(TCGContext *s, uint8_t *code_ptr, int type, 
96
                   int label_index, long addend)
97
{
98
    TCGLabel *l;
99
    TCGRelocation *r;
100

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

    
118
static void tcg_out_label(TCGContext *s, int label_index, 
119
                          tcg_target_long value)
120
{
121
    TCGLabel *l;
122
    TCGRelocation *r;
123

    
124
    l = &s->labels[label_index];
125
    if (l->has_value)
126
        tcg_abort();
127
    r = l->u.first_reloc;
128
    while (r != NULL) {
129
        patch_reloc(r->ptr, r->type, value, r->addend);
130
        r = r->next;
131
    }
132
    l->has_value = 1;
133
    l->u.value = value;
134
}
135

    
136
int gen_new_label(void)
137
{
138
    TCGContext *s = &tcg_ctx;
139
    int idx;
140
    TCGLabel *l;
141

    
142
    if (s->nb_labels >= TCG_MAX_LABELS)
143
        tcg_abort();
144
    idx = s->nb_labels++;
145
    l = &s->labels[idx];
146
    l->has_value = 0;
147
    l->u.first_reloc = NULL;
148
    return idx;
149
}
150

    
151
#include "tcg-target.c"
152

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

    
196
void tcg_pool_reset(TCGContext *s)
197
{
198
    s->pool_cur = s->pool_end = NULL;
199
    s->pool_current = NULL;
200
}
201

    
202
void tcg_context_init(TCGContext *s)
203
{
204
    int op, total_args, n;
205
    TCGOpDef *def;
206
    TCGArgConstraint *args_ct;
207
    int *sorted_args;
208

    
209
    memset(s, 0, sizeof(*s));
210
    s->temps = s->static_temps;
211
    s->nb_globals = 0;
212
    
213
    /* Count total number of arguments and allocate the corresponding
214
       space */
215
    total_args = 0;
216
    for(op = 0; op < NB_OPS; op++) {
217
        def = &tcg_op_defs[op];
218
        n = def->nb_iargs + def->nb_oargs;
219
        total_args += n;
220
    }
221

    
222
    args_ct = qemu_malloc(sizeof(TCGArgConstraint) * total_args);
223
    sorted_args = qemu_malloc(sizeof(int) * total_args);
224

    
225
    for(op = 0; op < NB_OPS; op++) {
226
        def = &tcg_op_defs[op];
227
        def->args_ct = args_ct;
228
        def->sorted_args = sorted_args;
229
        n = def->nb_iargs + def->nb_oargs;
230
        sorted_args += n;
231
        args_ct += n;
232
    }
233
    
234
    tcg_target_init(s);
235

    
236
    /* init global prologue and epilogue */
237
    s->code_buf = code_gen_prologue;
238
    s->code_ptr = s->code_buf;
239
    tcg_target_qemu_prologue(s);
240
    flush_icache_range((unsigned long)s->code_buf, 
241
                       (unsigned long)s->code_ptr);
242
}
243

    
244
void tcg_set_frame(TCGContext *s, int reg,
245
                   tcg_target_long start, tcg_target_long size)
246
{
247
    s->frame_start = start;
248
    s->frame_end = start + size;
249
    s->frame_reg = reg;
250
}
251

    
252
void tcg_func_start(TCGContext *s)
253
{
254
    int i;
255
    tcg_pool_reset(s);
256
    s->nb_temps = s->nb_globals;
257
    for(i = 0; i < (TCG_TYPE_COUNT * 2); i++)
258
        s->first_free_temp[i] = -1;
259
    s->labels = tcg_malloc(sizeof(TCGLabel) * TCG_MAX_LABELS);
260
    s->nb_labels = 0;
261
    s->current_frame_offset = s->frame_start;
262

    
263
    gen_opc_ptr = gen_opc_buf;
264
    gen_opparam_ptr = gen_opparam_buf;
265
}
266

    
267
static inline void tcg_temp_alloc(TCGContext *s, int n)
268
{
269
    if (n > TCG_MAX_TEMPS)
270
        tcg_abort();
271
}
272

    
273
static inline int tcg_global_reg_new_internal(TCGType type, int reg,
274
                                              const char *name)
275
{
276
    TCGContext *s = &tcg_ctx;
277
    TCGTemp *ts;
278
    int idx;
279

    
280
#if TCG_TARGET_REG_BITS == 32
281
    if (type != TCG_TYPE_I32)
282
        tcg_abort();
283
#endif
284
    if (tcg_regset_test_reg(s->reserved_regs, reg))
285
        tcg_abort();
286
    idx = s->nb_globals;
287
    tcg_temp_alloc(s, s->nb_globals + 1);
288
    ts = &s->temps[s->nb_globals];
289
    ts->base_type = type;
290
    ts->type = type;
291
    ts->fixed_reg = 1;
292
    ts->reg = reg;
293
    ts->name = name;
294
    s->nb_globals++;
295
    tcg_regset_set_reg(s->reserved_regs, reg);
296
    return idx;
297
}
298

    
299
TCGv_i32 tcg_global_reg_new_i32(int reg, const char *name)
300
{
301
    int idx;
302

    
303
    idx = tcg_global_reg_new_internal(TCG_TYPE_I32, reg, name);
304
    return MAKE_TCGV_I32(idx);
305
}
306

    
307
TCGv_i64 tcg_global_reg_new_i64(int reg, const char *name)
308
{
309
    int idx;
310

    
311
    idx = tcg_global_reg_new_internal(TCG_TYPE_I64, reg, name);
312
    return MAKE_TCGV_I64(idx);
313
}
314

    
315
#if TCG_TARGET_REG_BITS == 32
316
/* temporary hack to avoid register shortage for tcg_qemu_st64() */
317
TCGv_i64 tcg_global_reg2_new_hack(TCGType type, int reg1, int reg2,
318
                                  const char *name)
319
{
320
    TCGContext *s = &tcg_ctx;
321
    TCGTemp *ts;
322
    int idx;
323
    char buf[64];
324

    
325
    if (type != TCG_TYPE_I64)
326
        tcg_abort();
327
    idx = s->nb_globals;
328
    tcg_temp_alloc(s, s->nb_globals + 2);
329
    ts = &s->temps[s->nb_globals];
330
    ts->base_type = type;
331
    ts->type = TCG_TYPE_I32;
332
    ts->fixed_reg = 1;
333
    ts->reg = reg1;
334
    pstrcpy(buf, sizeof(buf), name);
335
    pstrcat(buf, sizeof(buf), "_0");
336
    ts->name = strdup(buf);
337

    
338
    ts++;
339
    ts->base_type = type;
340
    ts->type = TCG_TYPE_I32;
341
    ts->fixed_reg = 1;
342
    ts->reg = reg2;
343
    pstrcpy(buf, sizeof(buf), name);
344
    pstrcat(buf, sizeof(buf), "_1");
345
    ts->name = strdup(buf);
346

    
347
    s->nb_globals += 2;
348
    return MAKE_TCGV_I64(idx);
349
}
350
#endif
351

    
352
static inline int tcg_global_mem_new_internal(TCGType type, int reg,
353
                                              tcg_target_long offset,
354
                                              const char *name)
355
{
356
    TCGContext *s = &tcg_ctx;
357
    TCGTemp *ts;
358
    int idx;
359

    
360
    idx = s->nb_globals;
361
#if TCG_TARGET_REG_BITS == 32
362
    if (type == TCG_TYPE_I64) {
363
        char buf[64];
364
        tcg_temp_alloc(s, s->nb_globals + 2);
365
        ts = &s->temps[s->nb_globals];
366
        ts->base_type = type;
367
        ts->type = TCG_TYPE_I32;
368
        ts->fixed_reg = 0;
369
        ts->mem_allocated = 1;
370
        ts->mem_reg = reg;
371
#ifdef TCG_TARGET_WORDS_BIGENDIAN
372
        ts->mem_offset = offset + 4;
373
#else
374
        ts->mem_offset = offset;
375
#endif
376
        pstrcpy(buf, sizeof(buf), name);
377
        pstrcat(buf, sizeof(buf), "_0");
378
        ts->name = strdup(buf);
379
        ts++;
380

    
381
        ts->base_type = type;
382
        ts->type = TCG_TYPE_I32;
383
        ts->fixed_reg = 0;
384
        ts->mem_allocated = 1;
385
        ts->mem_reg = reg;
386
#ifdef TCG_TARGET_WORDS_BIGENDIAN
387
        ts->mem_offset = offset;
388
#else
389
        ts->mem_offset = offset + 4;
390
#endif
391
        pstrcpy(buf, sizeof(buf), name);
392
        pstrcat(buf, sizeof(buf), "_1");
393
        ts->name = strdup(buf);
394

    
395
        s->nb_globals += 2;
396
    } else
397
#endif
398
    {
399
        tcg_temp_alloc(s, s->nb_globals + 1);
400
        ts = &s->temps[s->nb_globals];
401
        ts->base_type = type;
402
        ts->type = type;
403
        ts->fixed_reg = 0;
404
        ts->mem_allocated = 1;
405
        ts->mem_reg = reg;
406
        ts->mem_offset = offset;
407
        ts->name = name;
408
        s->nb_globals++;
409
    }
410
    return idx;
411
}
412

    
413
TCGv_i32 tcg_global_mem_new_i32(int reg, tcg_target_long offset,
414
                                const char *name)
415
{
416
    int idx;
417

    
418
    idx = tcg_global_mem_new_internal(TCG_TYPE_I32, reg, offset, name);
419
    return MAKE_TCGV_I32(idx);
420
}
421

    
422
TCGv_i64 tcg_global_mem_new_i64(int reg, tcg_target_long offset,
423
                                const char *name)
424
{
425
    int idx;
426

    
427
    idx = tcg_global_mem_new_internal(TCG_TYPE_I64, reg, offset, name);
428
    return MAKE_TCGV_I64(idx);
429
}
430

    
431
static inline int tcg_temp_new_internal(TCGType type, int temp_local)
432
{
433
    TCGContext *s = &tcg_ctx;
434
    TCGTemp *ts;
435
    int idx, k;
436

    
437
    k = type;
438
    if (temp_local)
439
        k += TCG_TYPE_COUNT;
440
    idx = s->first_free_temp[k];
441
    if (idx != -1) {
442
        /* There is already an available temp with the
443
           right type */
444
        ts = &s->temps[idx];
445
        s->first_free_temp[k] = ts->next_free_temp;
446
        ts->temp_allocated = 1;
447
        assert(ts->temp_local == temp_local);
448
    } else {
449
        idx = s->nb_temps;
450
#if TCG_TARGET_REG_BITS == 32
451
        if (type == TCG_TYPE_I64) {
452
            tcg_temp_alloc(s, s->nb_temps + 2);
453
            ts = &s->temps[s->nb_temps];
454
            ts->base_type = type;
455
            ts->type = TCG_TYPE_I32;
456
            ts->temp_allocated = 1;
457
            ts->temp_local = temp_local;
458
            ts->name = NULL;
459
            ts++;
460
            ts->base_type = TCG_TYPE_I32;
461
            ts->type = TCG_TYPE_I32;
462
            ts->temp_allocated = 1;
463
            ts->temp_local = temp_local;
464
            ts->name = NULL;
465
            s->nb_temps += 2;
466
        } else
467
#endif
468
        {
469
            tcg_temp_alloc(s, s->nb_temps + 1);
470
            ts = &s->temps[s->nb_temps];
471
            ts->base_type = type;
472
            ts->type = type;
473
            ts->temp_allocated = 1;
474
            ts->temp_local = temp_local;
475
            ts->name = NULL;
476
            s->nb_temps++;
477
        }
478
    }
479
    return idx;
480
}
481

    
482
TCGv_i32 tcg_temp_new_internal_i32(int temp_local)
483
{
484
    int idx;
485

    
486
    idx = tcg_temp_new_internal(TCG_TYPE_I32, temp_local);
487
    return MAKE_TCGV_I32(idx);
488
}
489

    
490
TCGv_i64 tcg_temp_new_internal_i64(int temp_local)
491
{
492
    int idx;
493

    
494
    idx = tcg_temp_new_internal(TCG_TYPE_I64, temp_local);
495
    return MAKE_TCGV_I64(idx);
496
}
497

    
498
static inline void tcg_temp_free_internal(int idx)
499
{
500
    TCGContext *s = &tcg_ctx;
501
    TCGTemp *ts;
502
    int k;
503

    
504
    assert(idx >= s->nb_globals && idx < s->nb_temps);
505
    ts = &s->temps[idx];
506
    assert(ts->temp_allocated != 0);
507
    ts->temp_allocated = 0;
508
    k = ts->base_type;
509
    if (ts->temp_local)
510
        k += TCG_TYPE_COUNT;
511
    ts->next_free_temp = s->first_free_temp[k];
512
    s->first_free_temp[k] = idx;
513
}
514

    
515
void tcg_temp_free_i32(TCGv_i32 arg)
516
{
517
    tcg_temp_free_internal(GET_TCGV_I32(arg));
518
}
519

    
520
void tcg_temp_free_i64(TCGv_i64 arg)
521
{
522
    tcg_temp_free_internal(GET_TCGV_I64(arg));
523
}
524

    
525
TCGv_i32 tcg_const_i32(int32_t val)
526
{
527
    TCGv_i32 t0;
528
    t0 = tcg_temp_new_i32();
529
    tcg_gen_movi_i32(t0, val);
530
    return t0;
531
}
532

    
533
TCGv_i64 tcg_const_i64(int64_t val)
534
{
535
    TCGv_i64 t0;
536
    t0 = tcg_temp_new_i64();
537
    tcg_gen_movi_i64(t0, val);
538
    return t0;
539
}
540

    
541
TCGv_i32 tcg_const_local_i32(int32_t val)
542
{
543
    TCGv_i32 t0;
544
    t0 = tcg_temp_local_new_i32();
545
    tcg_gen_movi_i32(t0, val);
546
    return t0;
547
}
548

    
549
TCGv_i64 tcg_const_local_i64(int64_t val)
550
{
551
    TCGv_i64 t0;
552
    t0 = tcg_temp_local_new_i64();
553
    tcg_gen_movi_i64(t0, val);
554
    return t0;
555
}
556

    
557
void tcg_register_helper(void *func, const char *name)
558
{
559
    TCGContext *s = &tcg_ctx;
560
    int n;
561
    if ((s->nb_helpers + 1) > s->allocated_helpers) {
562
        n = s->allocated_helpers;
563
        if (n == 0) {
564
            n = 4;
565
        } else {
566
            n *= 2;
567
        }
568
        s->helpers = realloc(s->helpers, n * sizeof(TCGHelperInfo));
569
        s->allocated_helpers = n;
570
    }
571
    s->helpers[s->nb_helpers].func = (tcg_target_ulong)func;
572
    s->helpers[s->nb_helpers].name = name;
573
    s->nb_helpers++;
574
}
575

    
576
/* Note: we convert the 64 bit args to 32 bit and do some alignment
577
   and endian swap. Maybe it would be better to do the alignment
578
   and endian swap in tcg_reg_alloc_call(). */
579
void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags,
580
                   int sizemask, TCGArg ret, int nargs, TCGArg *args)
581
{
582
    int call_type;
583
    int i;
584
    int real_args;
585
    int nb_rets;
586
    TCGArg *nparam;
587
    *gen_opc_ptr++ = INDEX_op_call;
588
    nparam = gen_opparam_ptr++;
589
    call_type = (flags & TCG_CALL_TYPE_MASK);
590
    if (ret != TCG_CALL_DUMMY_ARG) {
591
#if TCG_TARGET_REG_BITS < 64
592
        if (sizemask & 1) {
593
#ifdef TCG_TARGET_WORDS_BIGENDIAN
594
            *gen_opparam_ptr++ = ret + 1;
595
            *gen_opparam_ptr++ = ret;
596
#else
597
            *gen_opparam_ptr++ = ret;
598
            *gen_opparam_ptr++ = ret + 1;
599
#endif
600
            nb_rets = 2;
601
        } else
602
#endif
603
        {
604
            *gen_opparam_ptr++ = ret;
605
            nb_rets = 1;
606
        }
607
    } else {
608
        nb_rets = 0;
609
    }
610
    real_args = 0;
611
    for (i = 0; i < nargs; i++) {
612
#if TCG_TARGET_REG_BITS < 64
613
        if (sizemask & (2 << i)) {
614
#ifdef TCG_TARGET_I386
615
            /* REGPARM case: if the third parameter is 64 bit, it is
616
               allocated on the stack */
617
            if (i == 2 && call_type == TCG_CALL_TYPE_REGPARM) {
618
                call_type = TCG_CALL_TYPE_REGPARM_2;
619
                flags = (flags & ~TCG_CALL_TYPE_MASK) | call_type;
620
            }
621
#endif
622
#ifdef TCG_TARGET_CALL_ALIGN_ARGS
623
            /* some targets want aligned 64 bit args */
624
            if (real_args & 1) {
625
                *gen_opparam_ptr++ = TCG_CALL_DUMMY_ARG;
626
                real_args++;
627
            }
628
#endif
629
#ifdef TCG_TARGET_WORDS_BIGENDIAN
630
            *gen_opparam_ptr++ = args[i] + 1;
631
            *gen_opparam_ptr++ = args[i];
632
#else
633
            *gen_opparam_ptr++ = args[i];
634
            *gen_opparam_ptr++ = args[i] + 1;
635
#endif
636
            real_args += 2;
637
        } else
638
#endif
639
        {
640
            *gen_opparam_ptr++ = args[i];
641
            real_args++;
642
        }
643
    }
644
    *gen_opparam_ptr++ = GET_TCGV_PTR(func);
645

    
646
    *gen_opparam_ptr++ = flags;
647

    
648
    *nparam = (nb_rets << 16) | (real_args + 1);
649

    
650
    /* total parameters, needed to go backward in the instruction stream */
651
    *gen_opparam_ptr++ = 1 + nb_rets + real_args + 3;
652
}
653

    
654
#if TCG_TARGET_REG_BITS == 32
655
void tcg_gen_shifti_i64(TCGv_i64 ret, TCGv_i64 arg1,
656
                        int c, int right, int arith)
657
{
658
    if (c == 0) {
659
        tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg1));
660
        tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
661
    } else if (c >= 32) {
662
        c -= 32;
663
        if (right) {
664
            if (arith) {
665
                tcg_gen_sari_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
666
                tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 31);
667
            } else {
668
                tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
669
                tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
670
            }
671
        } else {
672
            tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_LOW(arg1), c);
673
            tcg_gen_movi_i32(TCGV_LOW(ret), 0);
674
        }
675
    } else {
676
        TCGv_i32 t0, t1;
677

    
678
        t0 = tcg_temp_new_i32();
679
        t1 = tcg_temp_new_i32();
680
        if (right) {
681
            tcg_gen_shli_i32(t0, TCGV_HIGH(arg1), 32 - c);
682
            if (arith)
683
                tcg_gen_sari_i32(t1, TCGV_HIGH(arg1), c);
684
            else
685
                tcg_gen_shri_i32(t1, TCGV_HIGH(arg1), c);
686
            tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_LOW(arg1), c);
687
            tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(ret), t0);
688
            tcg_gen_mov_i32(TCGV_HIGH(ret), t1);
689
        } else {
690
            tcg_gen_shri_i32(t0, TCGV_LOW(arg1), 32 - c);
691
            /* Note: ret can be the same as arg1, so we use t1 */
692
            tcg_gen_shli_i32(t1, TCGV_LOW(arg1), c);
693
            tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c);
694
            tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t0);
695
            tcg_gen_mov_i32(TCGV_LOW(ret), t1);
696
        }
697
        tcg_temp_free_i32(t0);
698
        tcg_temp_free_i32(t1);
699
    }
700
}
701
#endif
702

    
703
static void tcg_reg_alloc_start(TCGContext *s)
704
{
705
    int i;
706
    TCGTemp *ts;
707
    for(i = 0; i < s->nb_globals; i++) {
708
        ts = &s->temps[i];
709
        if (ts->fixed_reg) {
710
            ts->val_type = TEMP_VAL_REG;
711
        } else {
712
            ts->val_type = TEMP_VAL_MEM;
713
        }
714
    }
715
    for(i = s->nb_globals; i < s->nb_temps; i++) {
716
        ts = &s->temps[i];
717
        ts->val_type = TEMP_VAL_DEAD;
718
        ts->mem_allocated = 0;
719
        ts->fixed_reg = 0;
720
    }
721
    for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
722
        s->reg_to_temp[i] = -1;
723
    }
724
}
725

    
726
static char *tcg_get_arg_str_idx(TCGContext *s, char *buf, int buf_size,
727
                                 int idx)
728
{
729
    TCGTemp *ts;
730

    
731
    ts = &s->temps[idx];
732
    if (idx < s->nb_globals) {
733
        pstrcpy(buf, buf_size, ts->name);
734
    } else {
735
        if (ts->temp_local) 
736
            snprintf(buf, buf_size, "loc%d", idx - s->nb_globals);
737
        else
738
            snprintf(buf, buf_size, "tmp%d", idx - s->nb_globals);
739
    }
740
    return buf;
741
}
742

    
743
char *tcg_get_arg_str_i32(TCGContext *s, char *buf, int buf_size, TCGv_i32 arg)
744
{
745
    return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I32(arg));
746
}
747

    
748
char *tcg_get_arg_str_i64(TCGContext *s, char *buf, int buf_size, TCGv_i64 arg)
749
{
750
    return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I64(arg));
751
}
752

    
753
static int helper_cmp(const void *p1, const void *p2)
754
{
755
    const TCGHelperInfo *th1 = p1;
756
    const TCGHelperInfo *th2 = p2;
757
    if (th1->func < th2->func)
758
        return -1;
759
    else if (th1->func == th2->func)
760
        return 0;
761
    else
762
        return 1;
763
}
764

    
765
/* find helper definition (Note: A hash table would be better) */
766
static TCGHelperInfo *tcg_find_helper(TCGContext *s, tcg_target_ulong val)
767
{
768
    int m, m_min, m_max;
769
    TCGHelperInfo *th;
770
    tcg_target_ulong v;
771

    
772
    if (unlikely(!s->helpers_sorted)) {
773
        qsort(s->helpers, s->nb_helpers, sizeof(TCGHelperInfo), 
774
              helper_cmp);
775
        s->helpers_sorted = 1;
776
    }
777

    
778
    /* binary search */
779
    m_min = 0;
780
    m_max = s->nb_helpers - 1;
781
    while (m_min <= m_max) {
782
        m = (m_min + m_max) >> 1;
783
        th = &s->helpers[m];
784
        v = th->func;
785
        if (v == val)
786
            return th;
787
        else if (val < v) {
788
            m_max = m - 1;
789
        } else {
790
            m_min = m + 1;
791
        }
792
    }
793
    return NULL;
794
}
795

    
796
static const char * const cond_name[] =
797
{
798
    [TCG_COND_EQ] = "eq",
799
    [TCG_COND_NE] = "ne",
800
    [TCG_COND_LT] = "lt",
801
    [TCG_COND_GE] = "ge",
802
    [TCG_COND_LE] = "le",
803
    [TCG_COND_GT] = "gt",
804
    [TCG_COND_LTU] = "ltu",
805
    [TCG_COND_GEU] = "geu",
806
    [TCG_COND_LEU] = "leu",
807
    [TCG_COND_GTU] = "gtu"
808
};
809

    
810
void tcg_dump_ops(TCGContext *s, FILE *outfile)
811
{
812
    const uint16_t *opc_ptr;
813
    const TCGArg *args;
814
    TCGArg arg;
815
    int c, i, k, nb_oargs, nb_iargs, nb_cargs, first_insn;
816
    const TCGOpDef *def;
817
    char buf[128];
818

    
819
    first_insn = 1;
820
    opc_ptr = gen_opc_buf;
821
    args = gen_opparam_buf;
822
    while (opc_ptr < gen_opc_ptr) {
823
        c = *opc_ptr++;
824
        def = &tcg_op_defs[c];
825
        if (c == INDEX_op_debug_insn_start) {
826
            uint64_t pc;
827
#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
828
            pc = ((uint64_t)args[1] << 32) | args[0];
829
#else
830
            pc = args[0];
831
#endif
832
            if (!first_insn) 
833
                fprintf(outfile, "\n");
834
            fprintf(outfile, " ---- 0x%" PRIx64, pc);
835
            first_insn = 0;
836
            nb_oargs = def->nb_oargs;
837
            nb_iargs = def->nb_iargs;
838
            nb_cargs = def->nb_cargs;
839
        } else if (c == INDEX_op_call) {
840
            TCGArg arg;
841

    
842
            /* variable number of arguments */
843
            arg = *args++;
844
            nb_oargs = arg >> 16;
845
            nb_iargs = arg & 0xffff;
846
            nb_cargs = def->nb_cargs;
847

    
848
            fprintf(outfile, " %s ", def->name);
849

    
850
            /* function name */
851
            fprintf(outfile, "%s",
852
                    tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + nb_iargs - 1]));
853
            /* flags */
854
            fprintf(outfile, ",$0x%" TCG_PRIlx,
855
                    args[nb_oargs + nb_iargs]);
856
            /* nb out args */
857
            fprintf(outfile, ",$%d", nb_oargs);
858
            for(i = 0; i < nb_oargs; i++) {
859
                fprintf(outfile, ",");
860
                fprintf(outfile, "%s",
861
                        tcg_get_arg_str_idx(s, buf, sizeof(buf), args[i]));
862
            }
863
            for(i = 0; i < (nb_iargs - 1); i++) {
864
                fprintf(outfile, ",");
865
                if (args[nb_oargs + i] == TCG_CALL_DUMMY_ARG) {
866
                    fprintf(outfile, "<dummy>");
867
                } else {
868
                    fprintf(outfile, "%s",
869
                            tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + i]));
870
                }
871
            }
872
        } else if (c == INDEX_op_movi_i32 
873
#if TCG_TARGET_REG_BITS == 64
874
                   || c == INDEX_op_movi_i64
875
#endif
876
                   ) {
877
            tcg_target_ulong val;
878
            TCGHelperInfo *th;
879

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

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

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

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

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

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

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

    
1061
#ifdef USE_LIVENESS_ANALYSIS
1062

    
1063
/* set a nop for an operation using 'nb_args' */
1064
static inline void tcg_set_nop(TCGContext *s, uint16_t *opc_ptr, 
1065
                               TCGArg *args, int nb_args)
1066
{
1067
    if (nb_args == 0) {
1068
        *opc_ptr = INDEX_op_nop;
1069
    } else {
1070
        *opc_ptr = INDEX_op_nopn;
1071
        args[0] = nb_args;
1072
        args[nb_args - 1] = nb_args;
1073
    }
1074
}
1075

    
1076
/* liveness analysis: end of function: globals are live, temps are
1077
   dead. */
1078
/* XXX: at this stage, not used as there would be little gains because
1079
   most TBs end with a conditional jump. */
1080
static inline void tcg_la_func_end(TCGContext *s, uint8_t *dead_temps)
1081
{
1082
    memset(dead_temps, 0, s->nb_globals);
1083
    memset(dead_temps + s->nb_globals, 1, s->nb_temps - s->nb_globals);
1084
}
1085

    
1086
/* liveness analysis: end of basic block: globals are live, temps are
1087
   dead, local temps are live. */
1088
static inline void tcg_la_bb_end(TCGContext *s, uint8_t *dead_temps)
1089
{
1090
    int i;
1091
    TCGTemp *ts;
1092

    
1093
    memset(dead_temps, 0, s->nb_globals);
1094
    ts = &s->temps[s->nb_globals];
1095
    for(i = s->nb_globals; i < s->nb_temps; i++) {
1096
        if (ts->temp_local)
1097
            dead_temps[i] = 0;
1098
        else
1099
            dead_temps[i] = 1;
1100
        ts++;
1101
    }
1102
}
1103

    
1104
/* Liveness analysis : update the opc_dead_iargs array to tell if a
1105
   given input arguments is dead. Instructions updating dead
1106
   temporaries are removed. */
1107
static void tcg_liveness_analysis(TCGContext *s)
1108
{
1109
    int i, op_index, op, nb_args, nb_iargs, nb_oargs, arg, nb_ops;
1110
    TCGArg *args;
1111
    const TCGOpDef *def;
1112
    uint8_t *dead_temps;
1113
    unsigned int dead_iargs;
1114
    
1115
    gen_opc_ptr++; /* skip end */
1116

    
1117
    nb_ops = gen_opc_ptr - gen_opc_buf;
1118

    
1119
    /* XXX: make it really dynamic */
1120
    s->op_dead_iargs = tcg_malloc(OPC_BUF_SIZE * sizeof(uint16_t));
1121
    
1122
    dead_temps = tcg_malloc(s->nb_temps);
1123
    memset(dead_temps, 1, s->nb_temps);
1124

    
1125
    args = gen_opparam_ptr;
1126
    op_index = nb_ops - 1;
1127
    while (op_index >= 0) {
1128
        op = gen_opc_buf[op_index];
1129
        def = &tcg_op_defs[op];
1130
        switch(op) {
1131
        case INDEX_op_call:
1132
            {
1133
                int call_flags;
1134

    
1135
                nb_args = args[-1];
1136
                args -= nb_args;
1137
                nb_iargs = args[0] & 0xffff;
1138
                nb_oargs = args[0] >> 16;
1139
                args++;
1140
                call_flags = args[nb_oargs + nb_iargs];
1141

    
1142
                /* pure functions can be removed if their result is not
1143
                   used */
1144
                if (call_flags & TCG_CALL_PURE) {
1145
                    for(i = 0; i < nb_oargs; i++) {
1146
                        arg = args[i];
1147
                        if (!dead_temps[arg])
1148
                            goto do_not_remove_call;
1149
                    }
1150
                    tcg_set_nop(s, gen_opc_buf + op_index, 
1151
                                args - 1, nb_args);
1152
                } else {
1153
                do_not_remove_call:
1154

    
1155
                    /* output args are dead */
1156
                    for(i = 0; i < nb_oargs; i++) {
1157
                        arg = args[i];
1158
                        dead_temps[arg] = 1;
1159
                    }
1160
                    
1161
                    /* globals are live (they may be used by the call) */
1162
                    memset(dead_temps, 0, s->nb_globals);
1163
                    
1164
                    /* input args are live */
1165
                    dead_iargs = 0;
1166
                    for(i = 0; i < nb_iargs; i++) {
1167
                        arg = args[i + nb_oargs];
1168
                        if (arg != TCG_CALL_DUMMY_ARG) {
1169
                            if (dead_temps[arg]) {
1170
                                dead_iargs |= (1 << i);
1171
                            }
1172
                            dead_temps[arg] = 0;
1173
                        }
1174
                    }
1175
                    s->op_dead_iargs[op_index] = dead_iargs;
1176
                }
1177
                args--;
1178
            }
1179
            break;
1180
        case INDEX_op_set_label:
1181
            args--;
1182
            /* mark end of basic block */
1183
            tcg_la_bb_end(s, dead_temps);
1184
            break;
1185
        case INDEX_op_debug_insn_start:
1186
            args -= def->nb_args;
1187
            break;
1188
        case INDEX_op_nopn:
1189
            nb_args = args[-1];
1190
            args -= nb_args;
1191
            break;
1192
        case INDEX_op_discard:
1193
            args--;
1194
            /* mark the temporary as dead */
1195
            dead_temps[args[0]] = 1;
1196
            break;
1197
        case INDEX_op_end:
1198
            break;
1199
            /* XXX: optimize by hardcoding common cases (e.g. triadic ops) */
1200
        default:
1201
            if (op > INDEX_op_end) {
1202
                args -= def->nb_args;
1203
                nb_iargs = def->nb_iargs;
1204
                nb_oargs = def->nb_oargs;
1205

    
1206
                /* Test if the operation can be removed because all
1207
                   its outputs are dead. We assume that nb_oargs == 0
1208
                   implies side effects */
1209
                if (!(def->flags & TCG_OPF_SIDE_EFFECTS) && nb_oargs != 0) {
1210
                    for(i = 0; i < nb_oargs; i++) {
1211
                        arg = args[i];
1212
                        if (!dead_temps[arg])
1213
                            goto do_not_remove;
1214
                    }
1215
                    tcg_set_nop(s, gen_opc_buf + op_index, args, def->nb_args);
1216
#ifdef CONFIG_PROFILER
1217
                    s->del_op_count++;
1218
#endif
1219
                } else {
1220
                do_not_remove:
1221

    
1222
                    /* output args are dead */
1223
                    for(i = 0; i < nb_oargs; i++) {
1224
                        arg = args[i];
1225
                        dead_temps[arg] = 1;
1226
                    }
1227
                    
1228
                    /* if end of basic block, update */
1229
                    if (def->flags & TCG_OPF_BB_END) {
1230
                        tcg_la_bb_end(s, dead_temps);
1231
                    } else if (def->flags & TCG_OPF_CALL_CLOBBER) {
1232
                        /* globals are live */
1233
                        memset(dead_temps, 0, s->nb_globals);
1234
                    }
1235
                    
1236
                    /* input args are live */
1237
                    dead_iargs = 0;
1238
                    for(i = 0; i < nb_iargs; i++) {
1239
                        arg = args[i + nb_oargs];
1240
                        if (dead_temps[arg]) {
1241
                            dead_iargs |= (1 << i);
1242
                        }
1243
                        dead_temps[arg] = 0;
1244
                    }
1245
                    s->op_dead_iargs[op_index] = dead_iargs;
1246
                }
1247
            } else {
1248
                /* legacy dyngen operations */
1249
                args -= def->nb_args;
1250
                /* mark end of basic block */
1251
                tcg_la_bb_end(s, dead_temps);
1252
            }
1253
            break;
1254
        }
1255
        op_index--;
1256
    }
1257

    
1258
    if (args != gen_opparam_buf)
1259
        tcg_abort();
1260
}
1261
#else
1262
/* dummy liveness analysis */
1263
void tcg_liveness_analysis(TCGContext *s)
1264
{
1265
    int nb_ops;
1266
    nb_ops = gen_opc_ptr - gen_opc_buf;
1267

    
1268
    s->op_dead_iargs = tcg_malloc(nb_ops * sizeof(uint16_t));
1269
    memset(s->op_dead_iargs, 0, nb_ops * sizeof(uint16_t));
1270
}
1271
#endif
1272

    
1273
#ifndef NDEBUG
1274
static void dump_regs(TCGContext *s)
1275
{
1276
    TCGTemp *ts;
1277
    int i;
1278
    char buf[64];
1279

    
1280
    for(i = 0; i < s->nb_temps; i++) {
1281
        ts = &s->temps[i];
1282
        printf("  %10s: ", tcg_get_arg_str_idx(s, buf, sizeof(buf), i));
1283
        switch(ts->val_type) {
1284
        case TEMP_VAL_REG:
1285
            printf("%s", tcg_target_reg_names[ts->reg]);
1286
            break;
1287
        case TEMP_VAL_MEM:
1288
            printf("%d(%s)", (int)ts->mem_offset, tcg_target_reg_names[ts->mem_reg]);
1289
            break;
1290
        case TEMP_VAL_CONST:
1291
            printf("$0x%" TCG_PRIlx, ts->val);
1292
            break;
1293
        case TEMP_VAL_DEAD:
1294
            printf("D");
1295
            break;
1296
        default:
1297
            printf("???");
1298
            break;
1299
        }
1300
        printf("\n");
1301
    }
1302

    
1303
    for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
1304
        if (s->reg_to_temp[i] >= 0) {
1305
            printf("%s: %s\n", 
1306
                   tcg_target_reg_names[i], 
1307
                   tcg_get_arg_str_idx(s, buf, sizeof(buf), s->reg_to_temp[i]));
1308
        }
1309
    }
1310
}
1311

    
1312
static void check_regs(TCGContext *s)
1313
{
1314
    int reg, k;
1315
    TCGTemp *ts;
1316
    char buf[64];
1317

    
1318
    for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1319
        k = s->reg_to_temp[reg];
1320
        if (k >= 0) {
1321
            ts = &s->temps[k];
1322
            if (ts->val_type != TEMP_VAL_REG ||
1323
                ts->reg != reg) {
1324
                printf("Inconsistency for register %s:\n", 
1325
                       tcg_target_reg_names[reg]);
1326
                goto fail;
1327
            }
1328
        }
1329
    }
1330
    for(k = 0; k < s->nb_temps; k++) {
1331
        ts = &s->temps[k];
1332
        if (ts->val_type == TEMP_VAL_REG &&
1333
            !ts->fixed_reg &&
1334
            s->reg_to_temp[ts->reg] != k) {
1335
                printf("Inconsistency for temp %s:\n", 
1336
                       tcg_get_arg_str_idx(s, buf, sizeof(buf), k));
1337
        fail:
1338
                printf("reg state:\n");
1339
                dump_regs(s);
1340
                tcg_abort();
1341
        }
1342
    }
1343
}
1344
#endif
1345

    
1346
static void temp_allocate_frame(TCGContext *s, int temp)
1347
{
1348
    TCGTemp *ts;
1349
    ts = &s->temps[temp];
1350
    s->current_frame_offset = (s->current_frame_offset + sizeof(tcg_target_long) - 1) & ~(sizeof(tcg_target_long) - 1);
1351
    if (s->current_frame_offset + sizeof(tcg_target_long) > s->frame_end)
1352
        tcg_abort();
1353
    ts->mem_offset = s->current_frame_offset;
1354
    ts->mem_reg = s->frame_reg;
1355
    ts->mem_allocated = 1;
1356
    s->current_frame_offset += sizeof(tcg_target_long);
1357
}
1358

    
1359
/* free register 'reg' by spilling the corresponding temporary if necessary */
1360
static void tcg_reg_free(TCGContext *s, int reg)
1361
{
1362
    TCGTemp *ts;
1363
    int temp;
1364

    
1365
    temp = s->reg_to_temp[reg];
1366
    if (temp != -1) {
1367
        ts = &s->temps[temp];
1368
        assert(ts->val_type == TEMP_VAL_REG);
1369
        if (!ts->mem_coherent) {
1370
            if (!ts->mem_allocated) 
1371
                temp_allocate_frame(s, temp);
1372
            tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1373
        }
1374
        ts->val_type = TEMP_VAL_MEM;
1375
        s->reg_to_temp[reg] = -1;
1376
    }
1377
}
1378

    
1379
/* Allocate a register belonging to reg1 & ~reg2 */
1380
static int tcg_reg_alloc(TCGContext *s, TCGRegSet reg1, TCGRegSet reg2)
1381
{
1382
    int i, reg;
1383
    TCGRegSet reg_ct;
1384

    
1385
    tcg_regset_andnot(reg_ct, reg1, reg2);
1386

    
1387
    /* first try free registers */
1388
    for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1389
        reg = tcg_target_reg_alloc_order[i];
1390
        if (tcg_regset_test_reg(reg_ct, reg) && s->reg_to_temp[reg] == -1)
1391
            return reg;
1392
    }
1393

    
1394
    /* XXX: do better spill choice */
1395
    for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1396
        reg = tcg_target_reg_alloc_order[i];
1397
        if (tcg_regset_test_reg(reg_ct, reg)) {
1398
            tcg_reg_free(s, reg);
1399
            return reg;
1400
        }
1401
    }
1402

    
1403
    tcg_abort();
1404
}
1405

    
1406
/* save a temporary to memory. 'allocated_regs' is used in case a
1407
   temporary registers needs to be allocated to store a constant. */
1408
static void temp_save(TCGContext *s, int temp, TCGRegSet allocated_regs)
1409
{
1410
    TCGTemp *ts;
1411
    int reg;
1412

    
1413
    ts = &s->temps[temp];
1414
    if (!ts->fixed_reg) {
1415
        switch(ts->val_type) {
1416
        case TEMP_VAL_REG:
1417
            tcg_reg_free(s, ts->reg);
1418
            break;
1419
        case TEMP_VAL_DEAD:
1420
            ts->val_type = TEMP_VAL_MEM;
1421
            break;
1422
        case TEMP_VAL_CONST:
1423
            reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], 
1424
                                allocated_regs);
1425
            if (!ts->mem_allocated) 
1426
                temp_allocate_frame(s, temp);
1427
            tcg_out_movi(s, ts->type, reg, ts->val);
1428
            tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1429
            ts->val_type = TEMP_VAL_MEM;
1430
            break;
1431
        case TEMP_VAL_MEM:
1432
            break;
1433
        default:
1434
            tcg_abort();
1435
        }
1436
    }
1437
}
1438

    
1439
/* save globals to their cannonical location and assume they can be
1440
   modified be the following code. 'allocated_regs' is used in case a
1441
   temporary registers needs to be allocated to store a constant. */
1442
static void save_globals(TCGContext *s, TCGRegSet allocated_regs)
1443
{
1444
    int i;
1445

    
1446
    for(i = 0; i < s->nb_globals; i++) {
1447
        temp_save(s, i, allocated_regs);
1448
    }
1449
}
1450

    
1451
/* at the end of a basic block, we assume all temporaries are dead and
1452
   all globals are stored at their canonical location. */
1453
static void tcg_reg_alloc_bb_end(TCGContext *s, TCGRegSet allocated_regs)
1454
{
1455
    TCGTemp *ts;
1456
    int i;
1457

    
1458
    for(i = s->nb_globals; i < s->nb_temps; i++) {
1459
        ts = &s->temps[i];
1460
        if (ts->temp_local) {
1461
            temp_save(s, i, allocated_regs);
1462
        } else {
1463
            if (ts->val_type == TEMP_VAL_REG) {
1464
                s->reg_to_temp[ts->reg] = -1;
1465
            }
1466
            ts->val_type = TEMP_VAL_DEAD;
1467
        }
1468
    }
1469

    
1470
    save_globals(s, allocated_regs);
1471
}
1472

    
1473
#define IS_DEAD_IARG(n) ((dead_iargs >> (n)) & 1)
1474

    
1475
static void tcg_reg_alloc_movi(TCGContext *s, const TCGArg *args)
1476
{
1477
    TCGTemp *ots;
1478
    tcg_target_ulong val;
1479

    
1480
    ots = &s->temps[args[0]];
1481
    val = args[1];
1482

    
1483
    if (ots->fixed_reg) {
1484
        /* for fixed registers, we do not do any constant
1485
           propagation */
1486
        tcg_out_movi(s, ots->type, ots->reg, val);
1487
    } else {
1488
        /* The movi is not explicitly generated here */
1489
        if (ots->val_type == TEMP_VAL_REG)
1490
            s->reg_to_temp[ots->reg] = -1;
1491
        ots->val_type = TEMP_VAL_CONST;
1492
        ots->val = val;
1493
    }
1494
}
1495

    
1496
static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
1497
                              const TCGArg *args,
1498
                              unsigned int dead_iargs)
1499
{
1500
    TCGTemp *ts, *ots;
1501
    int reg;
1502
    const TCGArgConstraint *arg_ct;
1503

    
1504
    ots = &s->temps[args[0]];
1505
    ts = &s->temps[args[1]];
1506
    arg_ct = &def->args_ct[0];
1507

    
1508
    /* XXX: always mark arg dead if IS_DEAD_IARG(0) */
1509
    if (ts->val_type == TEMP_VAL_REG) {
1510
        if (IS_DEAD_IARG(0) && !ts->fixed_reg && !ots->fixed_reg) {
1511
            /* the mov can be suppressed */
1512
            if (ots->val_type == TEMP_VAL_REG)
1513
                s->reg_to_temp[ots->reg] = -1;
1514
            reg = ts->reg;
1515
            s->reg_to_temp[reg] = -1;
1516
            ts->val_type = TEMP_VAL_DEAD;
1517
        } else {
1518
            if (ots->val_type == TEMP_VAL_REG) {
1519
                reg = ots->reg;
1520
            } else {
1521
                reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1522
            }
1523
            if (ts->reg != reg) {
1524
                tcg_out_mov(s, reg, ts->reg);
1525
            }
1526
        }
1527
    } else if (ts->val_type == TEMP_VAL_MEM) {
1528
        if (ots->val_type == TEMP_VAL_REG) {
1529
            reg = ots->reg;
1530
        } else {
1531
            reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1532
        }
1533
        tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1534
    } else if (ts->val_type == TEMP_VAL_CONST) {
1535
        if (ots->fixed_reg) {
1536
            reg = ots->reg;
1537
            tcg_out_movi(s, ots->type, reg, ts->val);
1538
        } else {
1539
            /* propagate constant */
1540
            if (ots->val_type == TEMP_VAL_REG)
1541
                s->reg_to_temp[ots->reg] = -1;
1542
            ots->val_type = TEMP_VAL_CONST;
1543
            ots->val = ts->val;
1544
            return;
1545
        }
1546
    } else {
1547
        tcg_abort();
1548
    }
1549
    s->reg_to_temp[reg] = args[0];
1550
    ots->reg = reg;
1551
    ots->val_type = TEMP_VAL_REG;
1552
    ots->mem_coherent = 0;
1553
}
1554

    
1555
static void tcg_reg_alloc_op(TCGContext *s, 
1556
                             const TCGOpDef *def, int opc,
1557
                             const TCGArg *args,
1558
                             unsigned int dead_iargs)
1559
{
1560
    TCGRegSet allocated_regs;
1561
    int i, k, nb_iargs, nb_oargs, reg;
1562
    TCGArg arg;
1563
    const TCGArgConstraint *arg_ct;
1564
    TCGTemp *ts;
1565
    TCGArg new_args[TCG_MAX_OP_ARGS];
1566
    int const_args[TCG_MAX_OP_ARGS];
1567

    
1568
    nb_oargs = def->nb_oargs;
1569
    nb_iargs = def->nb_iargs;
1570

    
1571
    /* copy constants */
1572
    memcpy(new_args + nb_oargs + nb_iargs, 
1573
           args + nb_oargs + nb_iargs, 
1574
           sizeof(TCGArg) * def->nb_cargs);
1575

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

    
1703
    /* emit instruction */
1704
    tcg_out_op(s, opc, new_args, const_args);
1705
    
1706
    /* move the outputs in the correct register if needed */
1707
    for(i = 0; i < nb_oargs; i++) {
1708
        ts = &s->temps[args[i]];
1709
        reg = new_args[i];
1710
        if (ts->fixed_reg && ts->reg != reg) {
1711
            tcg_out_mov(s, ts->reg, reg);
1712
        }
1713
    }
1714
}
1715

    
1716
#ifdef TCG_TARGET_STACK_GROWSUP
1717
#define STACK_DIR(x) (-(x))
1718
#else
1719
#define STACK_DIR(x) (x)
1720
#endif
1721

    
1722
static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
1723
                              int opc, const TCGArg *args,
1724
                              unsigned int dead_iargs)
1725
{
1726
    int nb_iargs, nb_oargs, flags, nb_regs, i, reg, nb_params;
1727
    TCGArg arg, func_arg;
1728
    TCGTemp *ts;
1729
    tcg_target_long stack_offset, call_stack_size, func_addr;
1730
    int const_func_arg, allocate_args;
1731
    TCGRegSet allocated_regs;
1732
    const TCGArgConstraint *arg_ct;
1733

    
1734
    arg = *args++;
1735

    
1736
    nb_oargs = arg >> 16;
1737
    nb_iargs = arg & 0xffff;
1738
    nb_params = nb_iargs - 1;
1739

    
1740
    flags = args[nb_oargs + nb_iargs];
1741

    
1742
    nb_regs = tcg_target_get_call_iarg_regs_count(flags);
1743
    if (nb_regs > nb_params)
1744
        nb_regs = nb_params;
1745

    
1746
    /* assign stack slots first */
1747
    /* XXX: preallocate call stack */
1748
    call_stack_size = (nb_params - nb_regs) * sizeof(tcg_target_long);
1749
    call_stack_size = (call_stack_size + TCG_TARGET_STACK_ALIGN - 1) & 
1750
        ~(TCG_TARGET_STACK_ALIGN - 1);
1751
    allocate_args = (call_stack_size > TCG_STATIC_CALL_ARGS_SIZE);
1752
    if (allocate_args) {
1753
        tcg_out_addi(s, TCG_REG_CALL_STACK, -STACK_DIR(call_stack_size));
1754
    }
1755

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

    
1869
    tcg_out_op(s, opc, &func_arg, &const_func_arg);
1870
    
1871
    if (allocate_args) {
1872
        tcg_out_addi(s, TCG_REG_CALL_STACK, STACK_DIR(call_stack_size));
1873
    }
1874

    
1875
    /* assign output registers and emit moves if needed */
1876
    for(i = 0; i < nb_oargs; i++) {
1877
        arg = args[i];
1878
        ts = &s->temps[arg];
1879
        reg = tcg_target_call_oarg_regs[i];
1880
        assert(s->reg_to_temp[reg] == -1);
1881
        if (ts->fixed_reg) {
1882
            if (ts->reg != reg) {
1883
                tcg_out_mov(s, ts->reg, reg);
1884
            }
1885
        } else {
1886
            if (ts->val_type == TEMP_VAL_REG)
1887
                s->reg_to_temp[ts->reg] = -1;
1888
            ts->val_type = TEMP_VAL_REG;
1889
            ts->reg = reg;
1890
            ts->mem_coherent = 0; 
1891
            s->reg_to_temp[reg] = arg;
1892
        }
1893
    }
1894
    
1895
    return nb_iargs + nb_oargs + def->nb_cargs + 1;
1896
}
1897

    
1898
#ifdef CONFIG_PROFILER
1899

    
1900
static int64_t dyngen_table_op_count[NB_OPS];
1901

    
1902
void dump_op_count(void)
1903
{
1904
    int i;
1905
    FILE *f;
1906
    f = fopen("/tmp/op1.log", "w");
1907
    for(i = 0; i < INDEX_op_end; i++) {
1908
        fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name, dyngen_table_op_count[i]);
1909
    }
1910
    fclose(f);
1911
    f = fopen("/tmp/op2.log", "w");
1912
    for(i = INDEX_op_end; i < NB_OPS; i++) {
1913
        fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name, dyngen_table_op_count[i]);
1914
    }
1915
    fclose(f);
1916
}
1917
#endif
1918

    
1919

    
1920
static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
1921
                                      long search_pc)
1922
{
1923
    int opc, op_index;
1924
    const TCGOpDef *def;
1925
    unsigned int dead_iargs;
1926
    const TCGArg *args;
1927

    
1928
#ifdef DEBUG_DISAS
1929
    if (unlikely(loglevel & CPU_LOG_TB_OP)) {
1930
        fprintf(logfile, "OP:\n");
1931
        tcg_dump_ops(s, logfile);
1932
        fprintf(logfile, "\n");
1933
    }
1934
#endif
1935

    
1936
#ifdef CONFIG_PROFILER
1937
    s->la_time -= profile_getclock();
1938
#endif
1939
    tcg_liveness_analysis(s);
1940
#ifdef CONFIG_PROFILER
1941
    s->la_time += profile_getclock();
1942
#endif
1943

    
1944
#ifdef DEBUG_DISAS
1945
    if (unlikely(loglevel & CPU_LOG_TB_OP_OPT)) {
1946
        fprintf(logfile, "OP after la:\n");
1947
        tcg_dump_ops(s, logfile);
1948
        fprintf(logfile, "\n");
1949
    }
1950
#endif
1951

    
1952
    tcg_reg_alloc_start(s);
1953

    
1954
    s->code_buf = gen_code_buf;
1955
    s->code_ptr = gen_code_buf;
1956

    
1957
    args = gen_opparam_buf;
1958
    op_index = 0;
1959

    
1960
    for(;;) {
1961
        opc = gen_opc_buf[op_index];
1962
#ifdef CONFIG_PROFILER
1963
        dyngen_table_op_count[opc]++;
1964
#endif
1965
        def = &tcg_op_defs[opc];
1966
#if 0
1967
        printf("%s: %d %d %d\n", def->name,
1968
               def->nb_oargs, def->nb_iargs, def->nb_cargs);
1969
        //        dump_regs(s);
1970
#endif
1971
        switch(opc) {
1972
        case INDEX_op_mov_i32:
1973
#if TCG_TARGET_REG_BITS == 64
1974
        case INDEX_op_mov_i64:
1975
#endif
1976
            dead_iargs = s->op_dead_iargs[op_index];
1977
            tcg_reg_alloc_mov(s, def, args, dead_iargs);
1978
            break;
1979
        case INDEX_op_movi_i32:
1980
#if TCG_TARGET_REG_BITS == 64
1981
        case INDEX_op_movi_i64:
1982
#endif
1983
            tcg_reg_alloc_movi(s, args);
1984
            break;
1985
        case INDEX_op_debug_insn_start:
1986
            /* debug instruction */
1987
            break;
1988
        case INDEX_op_nop:
1989
        case INDEX_op_nop1:
1990
        case INDEX_op_nop2:
1991
        case INDEX_op_nop3:
1992
            break;
1993
        case INDEX_op_nopn:
1994
            args += args[0];
1995
            goto next;
1996
        case INDEX_op_discard:
1997
            {
1998
                TCGTemp *ts;
1999
                ts = &s->temps[args[0]];
2000
                /* mark the temporary as dead */
2001
                if (!ts->fixed_reg) {
2002
                    if (ts->val_type == TEMP_VAL_REG)
2003
                        s->reg_to_temp[ts->reg] = -1;
2004
                    ts->val_type = TEMP_VAL_DEAD;
2005
                }
2006
            }
2007
            break;
2008
        case INDEX_op_set_label:
2009
            tcg_reg_alloc_bb_end(s, s->reserved_regs);
2010
            tcg_out_label(s, args[0], (long)s->code_ptr);
2011
            break;
2012
        case INDEX_op_call:
2013
            dead_iargs = s->op_dead_iargs[op_index];
2014
            args += tcg_reg_alloc_call(s, def, opc, args, dead_iargs);
2015
            goto next;
2016
        case INDEX_op_end:
2017
            goto the_end;
2018

    
2019
#ifdef CONFIG_DYNGEN_OP
2020
        case 0 ... INDEX_op_end - 1:
2021
            /* legacy dyngen ops */
2022
#ifdef CONFIG_PROFILER
2023
            s->old_op_count++;
2024
#endif
2025
            tcg_reg_alloc_bb_end(s, s->reserved_regs);
2026
            if (search_pc >= 0) {
2027
                s->code_ptr += def->copy_size;
2028
                args += def->nb_args;
2029
            } else {
2030
                args = dyngen_op(s, opc, args);
2031
            }
2032
            goto next;
2033
#endif
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 dyngen_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 dyngen_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, "old ops/total ops   %0.1f%%\n", 
2106
                s->op_count ? (double)s->old_op_count / s->op_count * 100.0 : 0);
2107
    cpu_fprintf(f, "deleted ops/TB      %0.2f\n",
2108
                s->tb_count ? 
2109
                (double)s->del_op_count / s->tb_count : 0);
2110
    cpu_fprintf(f, "avg temps/TB        %0.2f max=%d\n",
2111
                s->tb_count ? 
2112
                (double)s->temp_count / s->tb_count : 0,
2113
                s->temp_count_max);
2114
    
2115
    cpu_fprintf(f, "cycles/op           %0.1f\n", 
2116
                s->op_count ? (double)tot / s->op_count : 0);
2117
    cpu_fprintf(f, "cycles/in byte      %0.1f\n", 
2118
                s->code_in_len ? (double)tot / s->code_in_len : 0);
2119
    cpu_fprintf(f, "cycles/out byte     %0.1f\n", 
2120
                s->code_out_len ? (double)tot / s->code_out_len : 0);
2121
    if (tot == 0)
2122
        tot = 1;
2123
    cpu_fprintf(f, "  gen_interm time   %0.1f%%\n", 
2124
                (double)s->interm_time / tot * 100.0);
2125
    cpu_fprintf(f, "  gen_code time     %0.1f%%\n", 
2126
                (double)s->code_time / tot * 100.0);
2127
    cpu_fprintf(f, "liveness/code time  %0.1f%%\n", 
2128
                (double)s->la_time / (s->code_time ? s->code_time : 1) * 100.0);
2129
    cpu_fprintf(f, "cpu_restore count   %" PRId64 "\n",
2130
                s->restore_count);
2131
    cpu_fprintf(f, "  avg cycles        %0.1f\n",
2132
                s->restore_count ? (double)s->restore_time / s->restore_count : 0);
2133
    {
2134
        extern void dump_op_count(void);
2135
        dump_op_count();
2136
    }
2137
}
2138
#else
2139
void tcg_dump_info(FILE *f,
2140
                   int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
2141
{
2142
    cpu_fprintf(f, "[TCG profiler not compiled]\n");
2143
}
2144
#endif