Statistics
| Branch: | Revision:

root / tcg / tcg.c @ 55616505

History | View | Annotate | Download (61.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 use liveness analysis (better code) */
26
#define USE_LIVENESS_ANALYSIS
27

    
28
#include "config.h"
29

    
30
#ifndef DEBUG_TCG
31
/* define it to suppress various consistency checks (faster) */
32
#define NDEBUG
33
#endif
34

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

    
47
#include "qemu-common.h"
48
#include "cache-utils.h"
49

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

    
57
#include "tcg-op.h"
58
#include "elf.h"
59

    
60

    
61
static void patch_reloc(uint8_t *code_ptr, int type, 
62
                        tcg_target_long value, tcg_target_long addend);
63

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

    
72
static TCGRegSet tcg_target_available_regs[2];
73
static TCGRegSet tcg_target_call_clobber_regs;
74

    
75
/* XXX: move that inside the context */
76
uint16_t *gen_opc_ptr;
77
TCGArg *gen_opparam_ptr;
78

    
79
static inline void tcg_out8(TCGContext *s, uint8_t v)
80
{
81
    *s->code_ptr++ = v;
82
}
83

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

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

    
96
/* label relocation processing */
97

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

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

    
121
static void tcg_out_label(TCGContext *s, int label_index, 
122
                          tcg_target_long value)
123
{
124
    TCGLabel *l;
125
    TCGRelocation *r;
126

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

    
139
int gen_new_label(void)
140
{
141
    TCGContext *s = &tcg_ctx;
142
    int idx;
143
    TCGLabel *l;
144

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

    
154
#include "tcg-target.c"
155

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

    
199
void tcg_pool_reset(TCGContext *s)
200
{
201
    s->pool_cur = s->pool_end = NULL;
202
    s->pool_current = NULL;
203
}
204

    
205
void tcg_context_init(TCGContext *s)
206
{
207
    int op, total_args, n;
208
    TCGOpDef *def;
209
    TCGArgConstraint *args_ct;
210
    int *sorted_args;
211

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

    
225
    args_ct = qemu_malloc(sizeof(TCGArgConstraint) * total_args);
226
    sorted_args = qemu_malloc(sizeof(int) * total_args);
227

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

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

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

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

    
266
    gen_opc_ptr = gen_opc_buf;
267
    gen_opparam_ptr = gen_opparam_buf;
268
}
269

    
270
static inline void tcg_temp_alloc(TCGContext *s, int n)
271
{
272
    if (n > TCG_MAX_TEMPS)
273
        tcg_abort();
274
}
275

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

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

    
302
TCGv_i32 tcg_global_reg_new_i32(int reg, const char *name)
303
{
304
    int idx;
305

    
306
    idx = tcg_global_reg_new_internal(TCG_TYPE_I32, reg, name);
307
    return MAKE_TCGV_I32(idx);
308
}
309

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

    
314
    idx = tcg_global_reg_new_internal(TCG_TYPE_I64, reg, name);
315
    return MAKE_TCGV_I64(idx);
316
}
317

    
318
static inline int tcg_global_mem_new_internal(TCGType type, int reg,
319
                                              tcg_target_long offset,
320
                                              const char *name)
321
{
322
    TCGContext *s = &tcg_ctx;
323
    TCGTemp *ts;
324
    int idx;
325

    
326
    idx = s->nb_globals;
327
#if TCG_TARGET_REG_BITS == 32
328
    if (type == TCG_TYPE_I64) {
329
        char buf[64];
330
        tcg_temp_alloc(s, s->nb_globals + 2);
331
        ts = &s->temps[s->nb_globals];
332
        ts->base_type = type;
333
        ts->type = TCG_TYPE_I32;
334
        ts->fixed_reg = 0;
335
        ts->mem_allocated = 1;
336
        ts->mem_reg = reg;
337
#ifdef TCG_TARGET_WORDS_BIGENDIAN
338
        ts->mem_offset = offset + 4;
339
#else
340
        ts->mem_offset = offset;
341
#endif
342
        pstrcpy(buf, sizeof(buf), name);
343
        pstrcat(buf, sizeof(buf), "_0");
344
        ts->name = strdup(buf);
345
        ts++;
346

    
347
        ts->base_type = type;
348
        ts->type = TCG_TYPE_I32;
349
        ts->fixed_reg = 0;
350
        ts->mem_allocated = 1;
351
        ts->mem_reg = reg;
352
#ifdef TCG_TARGET_WORDS_BIGENDIAN
353
        ts->mem_offset = offset;
354
#else
355
        ts->mem_offset = offset + 4;
356
#endif
357
        pstrcpy(buf, sizeof(buf), name);
358
        pstrcat(buf, sizeof(buf), "_1");
359
        ts->name = strdup(buf);
360

    
361
        s->nb_globals += 2;
362
    } else
363
#endif
364
    {
365
        tcg_temp_alloc(s, s->nb_globals + 1);
366
        ts = &s->temps[s->nb_globals];
367
        ts->base_type = type;
368
        ts->type = type;
369
        ts->fixed_reg = 0;
370
        ts->mem_allocated = 1;
371
        ts->mem_reg = reg;
372
        ts->mem_offset = offset;
373
        ts->name = name;
374
        s->nb_globals++;
375
    }
376
    return idx;
377
}
378

    
379
TCGv_i32 tcg_global_mem_new_i32(int reg, tcg_target_long offset,
380
                                const char *name)
381
{
382
    int idx;
383

    
384
    idx = tcg_global_mem_new_internal(TCG_TYPE_I32, reg, offset, name);
385
    return MAKE_TCGV_I32(idx);
386
}
387

    
388
TCGv_i64 tcg_global_mem_new_i64(int reg, tcg_target_long offset,
389
                                const char *name)
390
{
391
    int idx;
392

    
393
    idx = tcg_global_mem_new_internal(TCG_TYPE_I64, reg, offset, name);
394
    return MAKE_TCGV_I64(idx);
395
}
396

    
397
static inline int tcg_temp_new_internal(TCGType type, int temp_local)
398
{
399
    TCGContext *s = &tcg_ctx;
400
    TCGTemp *ts;
401
    int idx, k;
402

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

    
448
TCGv_i32 tcg_temp_new_internal_i32(int temp_local)
449
{
450
    int idx;
451

    
452
    idx = tcg_temp_new_internal(TCG_TYPE_I32, temp_local);
453
    return MAKE_TCGV_I32(idx);
454
}
455

    
456
TCGv_i64 tcg_temp_new_internal_i64(int temp_local)
457
{
458
    int idx;
459

    
460
    idx = tcg_temp_new_internal(TCG_TYPE_I64, temp_local);
461
    return MAKE_TCGV_I64(idx);
462
}
463

    
464
static inline void tcg_temp_free_internal(int idx)
465
{
466
    TCGContext *s = &tcg_ctx;
467
    TCGTemp *ts;
468
    int k;
469

    
470
    assert(idx >= s->nb_globals && idx < s->nb_temps);
471
    ts = &s->temps[idx];
472
    assert(ts->temp_allocated != 0);
473
    ts->temp_allocated = 0;
474
    k = ts->base_type;
475
    if (ts->temp_local)
476
        k += TCG_TYPE_COUNT;
477
    ts->next_free_temp = s->first_free_temp[k];
478
    s->first_free_temp[k] = idx;
479
}
480

    
481
void tcg_temp_free_i32(TCGv_i32 arg)
482
{
483
    tcg_temp_free_internal(GET_TCGV_I32(arg));
484
}
485

    
486
void tcg_temp_free_i64(TCGv_i64 arg)
487
{
488
    tcg_temp_free_internal(GET_TCGV_I64(arg));
489
}
490

    
491
TCGv_i32 tcg_const_i32(int32_t val)
492
{
493
    TCGv_i32 t0;
494
    t0 = tcg_temp_new_i32();
495
    tcg_gen_movi_i32(t0, val);
496
    return t0;
497
}
498

    
499
TCGv_i64 tcg_const_i64(int64_t val)
500
{
501
    TCGv_i64 t0;
502
    t0 = tcg_temp_new_i64();
503
    tcg_gen_movi_i64(t0, val);
504
    return t0;
505
}
506

    
507
TCGv_i32 tcg_const_local_i32(int32_t val)
508
{
509
    TCGv_i32 t0;
510
    t0 = tcg_temp_local_new_i32();
511
    tcg_gen_movi_i32(t0, val);
512
    return t0;
513
}
514

    
515
TCGv_i64 tcg_const_local_i64(int64_t val)
516
{
517
    TCGv_i64 t0;
518
    t0 = tcg_temp_local_new_i64();
519
    tcg_gen_movi_i64(t0, val);
520
    return t0;
521
}
522

    
523
void tcg_register_helper(void *func, const char *name)
524
{
525
    TCGContext *s = &tcg_ctx;
526
    int n;
527
    if ((s->nb_helpers + 1) > s->allocated_helpers) {
528
        n = s->allocated_helpers;
529
        if (n == 0) {
530
            n = 4;
531
        } else {
532
            n *= 2;
533
        }
534
        s->helpers = realloc(s->helpers, n * sizeof(TCGHelperInfo));
535
        s->allocated_helpers = n;
536
    }
537
    s->helpers[s->nb_helpers].func = (tcg_target_ulong)func;
538
    s->helpers[s->nb_helpers].name = name;
539
    s->nb_helpers++;
540
}
541

    
542
/* Note: we convert the 64 bit args to 32 bit and do some alignment
543
   and endian swap. Maybe it would be better to do the alignment
544
   and endian swap in tcg_reg_alloc_call(). */
545
void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags,
546
                   int sizemask, TCGArg ret, int nargs, TCGArg *args)
547
{
548
    int call_type;
549
    int i;
550
    int real_args;
551
    int nb_rets;
552
    TCGArg *nparam;
553
    *gen_opc_ptr++ = INDEX_op_call;
554
    nparam = gen_opparam_ptr++;
555
    call_type = (flags & TCG_CALL_TYPE_MASK);
556
    if (ret != TCG_CALL_DUMMY_ARG) {
557
#if TCG_TARGET_REG_BITS < 64
558
        if (sizemask & 1) {
559
#ifdef TCG_TARGET_WORDS_BIGENDIAN
560
            *gen_opparam_ptr++ = ret + 1;
561
            *gen_opparam_ptr++ = ret;
562
#else
563
            *gen_opparam_ptr++ = ret;
564
            *gen_opparam_ptr++ = ret + 1;
565
#endif
566
            nb_rets = 2;
567
        } else
568
#endif
569
        {
570
            *gen_opparam_ptr++ = ret;
571
            nb_rets = 1;
572
        }
573
    } else {
574
        nb_rets = 0;
575
    }
576
    real_args = 0;
577
    for (i = 0; i < nargs; i++) {
578
#if TCG_TARGET_REG_BITS < 64
579
        if (sizemask & (2 << i)) {
580
#ifdef TCG_TARGET_I386
581
            /* REGPARM case: if the third parameter is 64 bit, it is
582
               allocated on the stack */
583
            if (i == 2 && call_type == TCG_CALL_TYPE_REGPARM) {
584
                call_type = TCG_CALL_TYPE_REGPARM_2;
585
                flags = (flags & ~TCG_CALL_TYPE_MASK) | call_type;
586
            }
587
#endif
588
#ifdef TCG_TARGET_CALL_ALIGN_ARGS
589
            /* some targets want aligned 64 bit args */
590
            if (real_args & 1) {
591
                *gen_opparam_ptr++ = TCG_CALL_DUMMY_ARG;
592
                real_args++;
593
            }
594
#endif
595
#ifdef TCG_TARGET_WORDS_BIGENDIAN
596
            *gen_opparam_ptr++ = args[i] + 1;
597
            *gen_opparam_ptr++ = args[i];
598
#else
599
            *gen_opparam_ptr++ = args[i];
600
            *gen_opparam_ptr++ = args[i] + 1;
601
#endif
602
            real_args += 2;
603
        } else
604
#endif
605
        {
606
            *gen_opparam_ptr++ = args[i];
607
            real_args++;
608
        }
609
    }
610
    *gen_opparam_ptr++ = GET_TCGV_PTR(func);
611

    
612
    *gen_opparam_ptr++ = flags;
613

    
614
    *nparam = (nb_rets << 16) | (real_args + 1);
615

    
616
    /* total parameters, needed to go backward in the instruction stream */
617
    *gen_opparam_ptr++ = 1 + nb_rets + real_args + 3;
618
}
619

    
620
#if TCG_TARGET_REG_BITS == 32
621
void tcg_gen_shifti_i64(TCGv_i64 ret, TCGv_i64 arg1,
622
                        int c, int right, int arith)
623
{
624
    if (c == 0) {
625
        tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg1));
626
        tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
627
    } else if (c >= 32) {
628
        c -= 32;
629
        if (right) {
630
            if (arith) {
631
                tcg_gen_sari_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
632
                tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 31);
633
            } else {
634
                tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
635
                tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
636
            }
637
        } else {
638
            tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_LOW(arg1), c);
639
            tcg_gen_movi_i32(TCGV_LOW(ret), 0);
640
        }
641
    } else {
642
        TCGv_i32 t0, t1;
643

    
644
        t0 = tcg_temp_new_i32();
645
        t1 = tcg_temp_new_i32();
646
        if (right) {
647
            tcg_gen_shli_i32(t0, TCGV_HIGH(arg1), 32 - c);
648
            if (arith)
649
                tcg_gen_sari_i32(t1, TCGV_HIGH(arg1), c);
650
            else
651
                tcg_gen_shri_i32(t1, TCGV_HIGH(arg1), c);
652
            tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_LOW(arg1), c);
653
            tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(ret), t0);
654
            tcg_gen_mov_i32(TCGV_HIGH(ret), t1);
655
        } else {
656
            tcg_gen_shri_i32(t0, TCGV_LOW(arg1), 32 - c);
657
            /* Note: ret can be the same as arg1, so we use t1 */
658
            tcg_gen_shli_i32(t1, TCGV_LOW(arg1), c);
659
            tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c);
660
            tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t0);
661
            tcg_gen_mov_i32(TCGV_LOW(ret), t1);
662
        }
663
        tcg_temp_free_i32(t0);
664
        tcg_temp_free_i32(t1);
665
    }
666
}
667
#endif
668

    
669
static void tcg_reg_alloc_start(TCGContext *s)
670
{
671
    int i;
672
    TCGTemp *ts;
673
    for(i = 0; i < s->nb_globals; i++) {
674
        ts = &s->temps[i];
675
        if (ts->fixed_reg) {
676
            ts->val_type = TEMP_VAL_REG;
677
        } else {
678
            ts->val_type = TEMP_VAL_MEM;
679
        }
680
    }
681
    for(i = s->nb_globals; i < s->nb_temps; i++) {
682
        ts = &s->temps[i];
683
        ts->val_type = TEMP_VAL_DEAD;
684
        ts->mem_allocated = 0;
685
        ts->fixed_reg = 0;
686
    }
687
    for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
688
        s->reg_to_temp[i] = -1;
689
    }
690
}
691

    
692
static char *tcg_get_arg_str_idx(TCGContext *s, char *buf, int buf_size,
693
                                 int idx)
694
{
695
    TCGTemp *ts;
696

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

    
709
char *tcg_get_arg_str_i32(TCGContext *s, char *buf, int buf_size, TCGv_i32 arg)
710
{
711
    return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I32(arg));
712
}
713

    
714
char *tcg_get_arg_str_i64(TCGContext *s, char *buf, int buf_size, TCGv_i64 arg)
715
{
716
    return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I64(arg));
717
}
718

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

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

    
738
    if (unlikely(!s->helpers_sorted)) {
739
        qsort(s->helpers, s->nb_helpers, sizeof(TCGHelperInfo), 
740
              helper_cmp);
741
        s->helpers_sorted = 1;
742
    }
743

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

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

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

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

    
808
            /* variable number of arguments */
809
            arg = *args++;
810
            nb_oargs = arg >> 16;
811
            nb_iargs = arg & 0xffff;
812
            nb_cargs = def->nb_cargs;
813

    
814
            fprintf(outfile, " %s ", def->name);
815

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

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

    
914
/* we give more priority to constraints with less registers */
915
static int get_constraint_priority(const TCGOpDef *def, int k)
916
{
917
    const TCGArgConstraint *arg_ct;
918

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

    
936
/* sort from highest priority to lowest */
937
static void sort_constraints(TCGOpDef *def, int start, int n)
938
{
939
    int i, j, p1, p2, tmp;
940

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

    
958
void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs)
959
{
960
    int op;
961
    TCGOpDef *def;
962
    const char *ct_str;
963
    int i, nb_args;
964

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

    
1008
        /* sort the constraints (XXX: this is just an heuristic) */
1009
        sort_constraints(def, 0, def->nb_oargs);
1010
        sort_constraints(def, def->nb_oargs, def->nb_iargs);
1011

    
1012
#if 0
1013
        {
1014
            int i;
1015

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

    
1025
}
1026

    
1027
#ifdef USE_LIVENESS_ANALYSIS
1028

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

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

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

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

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

    
1083
    nb_ops = gen_opc_ptr - gen_opc_buf;
1084

    
1085
    /* XXX: make it really dynamic */
1086
    s->op_dead_iargs = tcg_malloc(OPC_BUF_SIZE * sizeof(uint16_t));
1087
    
1088
    dead_temps = tcg_malloc(s->nb_temps);
1089
    memset(dead_temps, 1, s->nb_temps);
1090

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

    
1101
                nb_args = args[-1];
1102
                args -= nb_args;
1103
                nb_iargs = args[0] & 0xffff;
1104
                nb_oargs = args[0] >> 16;
1105
                args++;
1106
                call_flags = args[nb_oargs + nb_iargs];
1107

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

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

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

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

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

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

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

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

    
1229
    s->op_dead_iargs = tcg_malloc(nb_ops * sizeof(uint16_t));
1230
    memset(s->op_dead_iargs, 0, nb_ops * sizeof(uint16_t));
1231
}
1232
#endif
1233

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

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

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

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

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

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

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

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

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

    
1346
    tcg_regset_andnot(reg_ct, reg1, reg2);
1347

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

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

    
1364
    tcg_abort();
1365
}
1366

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

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

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

    
1407
    for(i = 0; i < s->nb_globals; i++) {
1408
        temp_save(s, i, allocated_regs);
1409
    }
1410
}
1411

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

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

    
1431
    save_globals(s, allocated_regs);
1432
}
1433

    
1434
#define IS_DEAD_IARG(n) ((dead_iargs >> (n)) & 1)
1435

    
1436
static void tcg_reg_alloc_movi(TCGContext *s, const TCGArg *args)
1437
{
1438
    TCGTemp *ots;
1439
    tcg_target_ulong val;
1440

    
1441
    ots = &s->temps[args[0]];
1442
    val = args[1];
1443

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

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

    
1465
    ots = &s->temps[args[0]];
1466
    ts = &s->temps[args[1]];
1467
    arg_ct = &def->args_ct[0];
1468

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

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

    
1529
    nb_oargs = def->nb_oargs;
1530
    nb_iargs = def->nb_iargs;
1531

    
1532
    /* copy constants */
1533
    memcpy(new_args + nb_oargs + nb_iargs, 
1534
           args + nb_oargs + nb_iargs, 
1535
           sizeof(TCGArg) * def->nb_cargs);
1536

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

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

    
1677
#ifdef TCG_TARGET_STACK_GROWSUP
1678
#define STACK_DIR(x) (-(x))
1679
#else
1680
#define STACK_DIR(x) (x)
1681
#endif
1682

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

    
1695
    arg = *args++;
1696

    
1697
    nb_oargs = arg >> 16;
1698
    nb_iargs = arg & 0xffff;
1699
    nb_params = nb_iargs - 1;
1700

    
1701
    flags = args[nb_oargs + nb_iargs];
1702

    
1703
    nb_regs = tcg_target_get_call_iarg_regs_count(flags);
1704
    if (nb_regs > nb_params)
1705
        nb_regs = nb_params;
1706

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

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

    
1832
    tcg_out_op(s, opc, &func_arg, &const_func_arg);
1833
    
1834
    if (allocate_args) {
1835
        tcg_out_addi(s, TCG_REG_CALL_STACK, STACK_DIR(call_stack_size));
1836
    }
1837

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

    
1861
#ifdef CONFIG_PROFILER
1862

    
1863
static int64_t tcg_table_op_count[NB_OPS];
1864

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

    
1877

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

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

    
1894
#ifdef CONFIG_PROFILER
1895
    s->la_time -= profile_getclock();
1896
#endif
1897
    tcg_liveness_analysis(s);
1898
#ifdef CONFIG_PROFILER
1899
    s->la_time += profile_getclock();
1900
#endif
1901

    
1902
#ifdef DEBUG_DISAS
1903
    if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_OPT))) {
1904
        qemu_log("OP after la:\n");
1905
        tcg_dump_ops(s, logfile);
1906
        qemu_log("\n");
1907
    }
1908
#endif
1909

    
1910
    tcg_reg_alloc_start(s);
1911

    
1912
    s->code_buf = gen_code_buf;
1913
    s->code_ptr = gen_code_buf;
1914

    
1915
    args = gen_opparam_buf;
1916
    op_index = 0;
1917

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

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

    
2008
        s->temp_count += s->nb_temps;
2009
        if (s->nb_temps > s->temp_count_max)
2010
            s->temp_count_max = s->nb_temps;
2011
    }
2012
#endif
2013

    
2014
    tcg_gen_code_common(s, gen_code_buf, -1);
2015

    
2016
    /* flush instruction cache */
2017
    flush_icache_range((unsigned long)gen_code_buf, 
2018
                       (unsigned long)s->code_ptr);
2019
    return s->code_ptr -  gen_code_buf;
2020
}
2021

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

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

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