Statistics
| Branch: | Revision:

root / tcg / tcg.c @ e8996ee0

History | View | Annotate | Download (64 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

    
41
#include "config.h"
42
#include "qemu-common.h"
43

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

    
51
#include "tcg-op.h"
52
#include "elf.h"
53

    
54

    
55
static void patch_reloc(uint8_t *code_ptr, int type, 
56
                        tcg_target_long value, tcg_target_long addend);
57

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

    
66
TCGRegSet tcg_target_available_regs[2];
67
TCGRegSet tcg_target_call_clobber_regs;
68

    
69
/* XXX: move that inside the context */
70
uint16_t *gen_opc_ptr;
71
TCGArg *gen_opparam_ptr;
72

    
73
static inline void tcg_out8(TCGContext *s, uint8_t v)
74
{
75
    *s->code_ptr++ = v;
76
}
77

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

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

    
90
/* label relocation processing */
91

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

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

    
115
static void tcg_out_label(TCGContext *s, int label_index, 
116
                          tcg_target_long value)
117
{
118
    TCGLabel *l;
119
    TCGRelocation *r;
120

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

    
133
int gen_new_label(void)
134
{
135
    TCGContext *s = &tcg_ctx;
136
    int idx;
137
    TCGLabel *l;
138

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

    
148
#include "tcg-target.c"
149

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

    
193
void tcg_pool_reset(TCGContext *s)
194
{
195
    s->pool_cur = s->pool_end = NULL;
196
    s->pool_current = NULL;
197
}
198

    
199
/* free all the pool */
200
void tcg_pool_free(TCGContext *s)
201
{
202
    TCGPool *p, *p1;
203

    
204
    for(p = s->pool_first; p != NULL; p = p1) {
205
        p1 = p->next;
206
        qemu_free(p);
207
    }
208
    s->pool_first = NULL;
209
    s->pool_cur = s->pool_end = NULL;
210
}
211

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

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

    
232
    args_ct = qemu_malloc(sizeof(TCGArgConstraint) * total_args);
233
    sorted_args = qemu_malloc(sizeof(int) * total_args);
234

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

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

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

    
262
void tcg_set_macro_func(TCGContext *s, TCGMacroFunc *func)
263
{
264
    s->macro_func = func;
265
}
266

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

    
278
    gen_opc_ptr = gen_opc_buf;
279
    gen_opparam_ptr = gen_opparam_buf;
280
}
281

    
282
static inline void tcg_temp_alloc(TCGContext *s, int n)
283
{
284
    if (n > TCG_MAX_TEMPS)
285
        tcg_abort();
286
}
287

    
288
TCGv tcg_global_reg_new(TCGType type, int reg, const char *name)
289
{
290
    TCGContext *s = &tcg_ctx;
291
    TCGTemp *ts;
292
    int idx;
293

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

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

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

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

    
345
    s->nb_globals += 2;
346
    return MAKE_TCGV(idx);
347
}
348
#endif
349

    
350
TCGv tcg_global_mem_new(TCGType type, int reg, tcg_target_long offset,
351
                        const char *name)
352
{
353
    TCGContext *s = &tcg_ctx;
354
    TCGTemp *ts;
355
    int idx;
356

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

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

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

    
410
TCGv tcg_temp_new(TCGType type)
411
{
412
    TCGContext *s = &tcg_ctx;
413
    TCGTemp *ts;
414
    int idx;
415

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

    
454
void tcg_temp_free(TCGv arg)
455
{
456
    TCGContext *s = &tcg_ctx;
457
    TCGTemp *ts;
458
    int idx = GET_TCGV(arg);
459
    TCGType type;
460

    
461
    assert(idx >= s->nb_globals && idx < s->nb_temps);
462
    ts = &s->temps[idx];
463
    assert(ts->temp_allocated != 0);
464
    ts->temp_allocated = 0;
465
    type = ts->base_type;
466
    ts->next_free_temp = s->first_free_temp[type];
467
    s->first_free_temp[type] = idx;
468
}
469

    
470

    
471
TCGv tcg_const_i32(int32_t val)
472
{
473
    TCGv t0;
474
    t0 = tcg_temp_new(TCG_TYPE_I32);
475
    tcg_gen_movi_i32(t0, val);
476
    return t0;
477
}
478

    
479
TCGv tcg_const_i64(int64_t val)
480
{
481
    TCGv t0;
482
    t0 = tcg_temp_new(TCG_TYPE_I64);
483
    tcg_gen_movi_i64(t0, val);
484
    return t0;
485
}
486

    
487
void tcg_register_helper(void *func, const char *name)
488
{
489
    TCGContext *s = &tcg_ctx;
490
    int n;
491
    if ((s->nb_helpers + 1) > s->allocated_helpers) {
492
        n = s->allocated_helpers;
493
        if (n == 0) {
494
            n = 4;
495
        } else {
496
            n *= 2;
497
        }
498
        s->helpers = realloc(s->helpers, n * sizeof(TCGHelperInfo));
499
        s->allocated_helpers = n;
500
    }
501
    s->helpers[s->nb_helpers].func = (tcg_target_ulong)func;
502
    s->helpers[s->nb_helpers].name = name;
503
    s->nb_helpers++;
504
}
505

    
506
static inline TCGType tcg_get_base_type(TCGContext *s, TCGv arg)
507
{
508
    return s->temps[GET_TCGV(arg)].base_type;
509
}
510

    
511
static void tcg_gen_call_internal(TCGContext *s, TCGv func, 
512
                                  unsigned int flags,
513
                                  unsigned int nb_rets, const TCGv *rets,
514
                                  unsigned int nb_params, const TCGv *params)
515
{
516
    int i;
517
    *gen_opc_ptr++ = INDEX_op_call;
518
    *gen_opparam_ptr++ = (nb_rets << 16) | (nb_params + 1);
519
    for(i = 0; i < nb_rets; i++) {
520
        *gen_opparam_ptr++ = GET_TCGV(rets[i]);
521
    }
522
    for(i = 0; i < nb_params; i++) {
523
        *gen_opparam_ptr++ = GET_TCGV(params[i]);
524
    }
525
    *gen_opparam_ptr++ = GET_TCGV(func);
526

    
527
    *gen_opparam_ptr++ = flags;
528
    /* total parameters, needed to go backward in the instruction stream */
529
    *gen_opparam_ptr++ = 1 + nb_rets + nb_params + 3;
530
}
531

    
532

    
533
#if TCG_TARGET_REG_BITS < 64
534
/* Note: we convert the 64 bit args to 32 bit and do some alignment
535
   and endian swap. Maybe it would be better to do the alignment
536
   and endian swap in tcg_reg_alloc_call(). */
537
void tcg_gen_call(TCGContext *s, TCGv func, unsigned int flags,
538
                  unsigned int nb_rets, const TCGv *rets,
539
                  unsigned int nb_params, const TCGv *args1)
540
{
541
    TCGv ret, *args2, rets_2[2], arg;
542
    int j, i, call_type;
543

    
544
    if (nb_rets == 1) {
545
        ret = rets[0];
546
        if (tcg_get_base_type(s, ret) == TCG_TYPE_I64) {
547
            nb_rets = 2;
548
#ifdef TCG_TARGET_WORDS_BIGENDIAN
549
            rets_2[0] = TCGV_HIGH(ret);
550
            rets_2[1] = ret;
551
#else
552
            rets_2[0] = ret;
553
            rets_2[1] = TCGV_HIGH(ret);
554
#endif
555
            rets = rets_2;
556
        }
557
    }
558
    args2 = alloca((nb_params * 3) * sizeof(TCGv));
559
    j = 0;
560
    call_type = (flags & TCG_CALL_TYPE_MASK);
561
    for(i = 0; i < nb_params; i++) {
562
        arg = args1[i];
563
        if (tcg_get_base_type(s, arg) == TCG_TYPE_I64) {
564
#ifdef TCG_TARGET_I386
565
            /* REGPARM case: if the third parameter is 64 bit, it is
566
               allocated on the stack */
567
            if (j == 2 && call_type == TCG_CALL_TYPE_REGPARM) {
568
                call_type = TCG_CALL_TYPE_REGPARM_2;
569
                flags = (flags & ~TCG_CALL_TYPE_MASK) | call_type;
570
            }
571
            args2[j++] = arg;
572
            args2[j++] = TCGV_HIGH(arg);
573
#else
574
#ifdef TCG_TARGET_CALL_ALIGN_ARGS
575
            /* some targets want aligned 64 bit args */
576
            if (j & 1) {
577
                args2[j++] = TCG_CALL_DUMMY_ARG;
578
            }
579
#endif
580
#ifdef TCG_TARGET_WORDS_BIGENDIAN
581
            args2[j++] = TCGV_HIGH(arg);
582
            args2[j++] = arg;
583
#else
584
            args2[j++] = arg;
585
            args2[j++] = TCGV_HIGH(arg);
586
#endif
587
#endif
588
        } else {
589
            args2[j++] = arg;
590
        }
591
    }
592
    tcg_gen_call_internal(s, func, flags, 
593
                          nb_rets, rets, j, args2);
594
}
595
#else
596
void tcg_gen_call(TCGContext *s, TCGv func, unsigned int flags,
597
                  unsigned int nb_rets, const TCGv *rets,
598
                  unsigned int nb_params, const TCGv *args1)
599
{
600
    tcg_gen_call_internal(s, func, flags, 
601
                          nb_rets, rets, nb_params, args1);
602
}
603
#endif
604

    
605
#if TCG_TARGET_REG_BITS == 32
606
void tcg_gen_shifti_i64(TCGv ret, TCGv arg1, 
607
                        int c, int right, int arith)
608
{
609
    if (c == 0) {
610
        tcg_gen_mov_i32(ret, arg1);
611
        tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
612
    } else if (c >= 32) {
613
        c -= 32;
614
        if (right) {
615
            if (arith) {
616
                tcg_gen_sari_i32(ret, TCGV_HIGH(arg1), c);
617
                tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 31);
618
            } else {
619
                tcg_gen_shri_i32(ret, TCGV_HIGH(arg1), c);
620
                tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
621
            }
622
        } else {
623
            tcg_gen_shli_i32(TCGV_HIGH(ret), arg1, c);
624
            tcg_gen_movi_i32(ret, 0);
625
        }
626
    } else {
627
        TCGv t0, t1;
628

    
629
        t0 = tcg_temp_new(TCG_TYPE_I32);
630
        t1 = tcg_temp_new(TCG_TYPE_I32);
631
        if (right) {
632
            tcg_gen_shli_i32(t0, TCGV_HIGH(arg1), 32 - c);
633
            if (arith)
634
                tcg_gen_sari_i32(t1, TCGV_HIGH(arg1), c);
635
            else 
636
                tcg_gen_shri_i32(t1, TCGV_HIGH(arg1), c);
637
            tcg_gen_shri_i32(ret, arg1, c); 
638
            tcg_gen_or_i32(ret, ret, t0);
639
            tcg_gen_mov_i32(TCGV_HIGH(ret), t1);
640
        } else {
641
            tcg_gen_shri_i32(t0, arg1, 32 - c);
642
            /* Note: ret can be the same as arg1, so we use t1 */
643
            tcg_gen_shli_i32(t1, arg1, c); 
644
            tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c);
645
            tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t0);
646
            tcg_gen_mov_i32(ret, t1);
647
        }
648
        tcg_temp_free(t0);
649
        tcg_temp_free(t1);
650
    }
651
}
652
#endif
653

    
654
void tcg_reg_alloc_start(TCGContext *s)
655
{
656
    int i;
657
    TCGTemp *ts;
658
    for(i = 0; i < s->nb_globals; i++) {
659
        ts = &s->temps[i];
660
        if (ts->fixed_reg) {
661
            ts->val_type = TEMP_VAL_REG;
662
        } else {
663
            ts->val_type = TEMP_VAL_MEM;
664
        }
665
    }
666
    for(i = s->nb_globals; i < s->nb_temps; i++) {
667
        ts = &s->temps[i];
668
        ts->val_type = TEMP_VAL_DEAD;
669
        ts->mem_allocated = 0;
670
        ts->fixed_reg = 0;
671
    }
672
    for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
673
        s->reg_to_temp[i] = -1;
674
    }
675
}
676

    
677
static char *tcg_get_arg_str_idx(TCGContext *s, char *buf, int buf_size,
678
                                 int idx)
679
{
680
    TCGTemp *ts;
681

    
682
    ts = &s->temps[idx];
683
    if (idx < s->nb_globals) {
684
        pstrcpy(buf, buf_size, ts->name);
685
    } else {
686
        snprintf(buf, buf_size, "tmp%d", idx - s->nb_globals);
687
    }
688
    return buf;
689
}
690

    
691
char *tcg_get_arg_str(TCGContext *s, char *buf, int buf_size, TCGv arg)
692
{
693
    return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV(arg));
694
}
695

    
696
static int helper_cmp(const void *p1, const void *p2)
697
{
698
    const TCGHelperInfo *th1 = p1;
699
    const TCGHelperInfo *th2 = p2;
700
    if (th1->func < th2->func)
701
        return -1;
702
    else if (th1->func == th2->func)
703
        return 0;
704
    else
705
        return 1;
706
}
707

    
708
/* find helper definition (Note: A hash table would be better) */
709
static TCGHelperInfo *tcg_find_helper(TCGContext *s, tcg_target_ulong val)
710
{
711
    int m, m_min, m_max;
712
    TCGHelperInfo *th;
713
    tcg_target_ulong v;
714

    
715
    if (unlikely(!s->helpers_sorted)) {
716
        qsort(s->helpers, s->nb_helpers, sizeof(TCGHelperInfo), 
717
              helper_cmp);
718
        s->helpers_sorted = 1;
719
    }
720

    
721
    /* binary search */
722
    m_min = 0;
723
    m_max = s->nb_helpers - 1;
724
    while (m_min <= m_max) {
725
        m = (m_min + m_max) >> 1;
726
        th = &s->helpers[m];
727
        v = th->func;
728
        if (v == val)
729
            return th;
730
        else if (val < v) {
731
            m_max = m - 1;
732
        } else {
733
            m_min = m + 1;
734
        }
735
    }
736
    return NULL;
737
}
738

    
739
void tcg_dump_ops(TCGContext *s, FILE *outfile)
740
{
741
    const uint16_t *opc_ptr;
742
    const TCGArg *args;
743
    TCGArg arg;
744
    int c, i, k, nb_oargs, nb_iargs, nb_cargs, first_insn;
745
    const TCGOpDef *def;
746
    char buf[128];
747

    
748
    first_insn = 1;
749
    opc_ptr = gen_opc_buf;
750
    args = gen_opparam_buf;
751
    while (opc_ptr < gen_opc_ptr) {
752
        c = *opc_ptr++;
753
        def = &tcg_op_defs[c];
754
        if (c == INDEX_op_debug_insn_start) {
755
            uint64_t pc;
756
#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
757
            pc = ((uint64_t)args[1] << 32) | args[0];
758
#else
759
            pc = args[0];
760
#endif
761
            if (!first_insn) 
762
                fprintf(outfile, "\n");
763
            fprintf(outfile, " ---- 0x%" PRIx64, pc);
764
            first_insn = 0;
765
            nb_oargs = def->nb_oargs;
766
            nb_iargs = def->nb_iargs;
767
            nb_cargs = def->nb_cargs;
768
        } else if (c == INDEX_op_call) {
769
            TCGArg arg;
770

    
771
            /* variable number of arguments */
772
            arg = *args++;
773
            nb_oargs = arg >> 16;
774
            nb_iargs = arg & 0xffff;
775
            nb_cargs = def->nb_cargs;
776

    
777
            fprintf(outfile, " %s ", def->name);
778

    
779
            /* function name */
780
            fprintf(outfile, "%s",
781
                    tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + nb_iargs - 1]));
782
            /* flags */
783
            fprintf(outfile, ",$0x%" TCG_PRIlx,
784
                    args[nb_oargs + nb_iargs]);
785
            /* nb out args */
786
            fprintf(outfile, ",$%d", nb_oargs);
787
            for(i = 0; i < nb_oargs; i++) {
788
                fprintf(outfile, ",");
789
                fprintf(outfile, "%s",
790
                        tcg_get_arg_str_idx(s, buf, sizeof(buf), args[i]));
791
            }
792
            for(i = 0; i < (nb_iargs - 1); i++) {
793
                fprintf(outfile, ",");
794
                if (args[nb_oargs + i] == TCG_CALL_DUMMY_ARG) {
795
                    fprintf(outfile, "<dummy>");
796
                } else {
797
                    fprintf(outfile, "%s",
798
                            tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + i]));
799
                }
800
            }
801
        } else if (c == INDEX_op_movi_i32 
802
#if TCG_TARGET_REG_BITS == 64
803
                   || c == INDEX_op_movi_i64
804
#endif
805
                   ) {
806
            tcg_target_ulong val;
807
            TCGHelperInfo *th;
808

    
809
            nb_oargs = def->nb_oargs;
810
            nb_iargs = def->nb_iargs;
811
            nb_cargs = def->nb_cargs;
812
            fprintf(outfile, " %s %s,$", def->name, 
813
                    tcg_get_arg_str_idx(s, buf, sizeof(buf), args[0]));
814
            val = args[1];
815
            th = tcg_find_helper(s, val);
816
            if (th) {
817
                fprintf(outfile, th->name);
818
            } else {
819
                if (c == INDEX_op_movi_i32)
820
                    fprintf(outfile, "0x%x", (uint32_t)val);
821
                else
822
                    fprintf(outfile, "0x%" PRIx64 , (uint64_t)val);
823
            }
824
        } else {
825
            fprintf(outfile, " %s ", def->name);
826
            if (c == INDEX_op_nopn) {
827
                /* variable number of arguments */
828
                nb_cargs = *args;
829
                nb_oargs = 0;
830
                nb_iargs = 0;
831
            } else {
832
                nb_oargs = def->nb_oargs;
833
                nb_iargs = def->nb_iargs;
834
                nb_cargs = def->nb_cargs;
835
            }
836
            
837
            k = 0;
838
            for(i = 0; i < nb_oargs; i++) {
839
                if (k != 0)
840
                    fprintf(outfile, ",");
841
                fprintf(outfile, "%s",
842
                        tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
843
            }
844
            for(i = 0; i < nb_iargs; i++) {
845
                if (k != 0)
846
                    fprintf(outfile, ",");
847
                fprintf(outfile, "%s",
848
                        tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
849
            }
850
            for(i = 0; i < nb_cargs; i++) {
851
                if (k != 0)
852
                    fprintf(outfile, ",");
853
                arg = args[k++];
854
                fprintf(outfile, "$0x%" TCG_PRIlx, arg);
855
            }
856
        }
857
        fprintf(outfile, "\n");
858
        args += nb_iargs + nb_oargs + nb_cargs;
859
    }
860
}
861

    
862
/* we give more priority to constraints with less registers */
863
static int get_constraint_priority(const TCGOpDef *def, int k)
864
{
865
    const TCGArgConstraint *arg_ct;
866

    
867
    int i, n;
868
    arg_ct = &def->args_ct[k];
869
    if (arg_ct->ct & TCG_CT_ALIAS) {
870
        /* an alias is equivalent to a single register */
871
        n = 1;
872
    } else {
873
        if (!(arg_ct->ct & TCG_CT_REG))
874
            return 0;
875
        n = 0;
876
        for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
877
            if (tcg_regset_test_reg(arg_ct->u.regs, i))
878
                n++;
879
        }
880
    }
881
    return TCG_TARGET_NB_REGS - n + 1;
882
}
883

    
884
/* sort from highest priority to lowest */
885
static void sort_constraints(TCGOpDef *def, int start, int n)
886
{
887
    int i, j, p1, p2, tmp;
888

    
889
    for(i = 0; i < n; i++)
890
        def->sorted_args[start + i] = start + i;
891
    if (n <= 1)
892
        return;
893
    for(i = 0; i < n - 1; i++) {
894
        for(j = i + 1; j < n; j++) {
895
            p1 = get_constraint_priority(def, def->sorted_args[start + i]);
896
            p2 = get_constraint_priority(def, def->sorted_args[start + j]);
897
            if (p1 < p2) {
898
                tmp = def->sorted_args[start + i];
899
                def->sorted_args[start + i] = def->sorted_args[start + j];
900
                def->sorted_args[start + j] = tmp;
901
            }
902
        }
903
    }
904
}
905

    
906
void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs)
907
{
908
    int op;
909
    TCGOpDef *def;
910
    const char *ct_str;
911
    int i, nb_args;
912

    
913
    for(;;) {
914
        if (tdefs->op < 0)
915
            break;
916
        op = tdefs->op;
917
        assert(op >= 0 && op < NB_OPS);
918
        def = &tcg_op_defs[op];
919
        nb_args = def->nb_iargs + def->nb_oargs;
920
        for(i = 0; i < nb_args; i++) {
921
            ct_str = tdefs->args_ct_str[i];
922
            tcg_regset_clear(def->args_ct[i].u.regs);
923
            def->args_ct[i].ct = 0;
924
            if (ct_str[0] >= '0' && ct_str[0] <= '9') {
925
                int oarg;
926
                oarg = ct_str[0] - '0';
927
                assert(oarg < def->nb_oargs);
928
                assert(def->args_ct[oarg].ct & TCG_CT_REG);
929
                /* TCG_CT_ALIAS is for the output arguments. The input
930
                   argument is tagged with TCG_CT_IALIAS. */
931
                def->args_ct[i] = def->args_ct[oarg];
932
                def->args_ct[oarg].ct = TCG_CT_ALIAS;
933
                def->args_ct[oarg].alias_index = i;
934
                def->args_ct[i].ct |= TCG_CT_IALIAS;
935
                def->args_ct[i].alias_index = oarg;
936
            } else {
937
                for(;;) {
938
                    if (*ct_str == '\0')
939
                        break;
940
                    switch(*ct_str) {
941
                    case 'i':
942
                        def->args_ct[i].ct |= TCG_CT_CONST;
943
                        ct_str++;
944
                        break;
945
                    default:
946
                        if (target_parse_constraint(&def->args_ct[i], &ct_str) < 0) {
947
                            fprintf(stderr, "Invalid constraint '%s' for arg %d of operation '%s'\n",
948
                                    ct_str, i, def->name);
949
                            exit(1);
950
                        }
951
                    }
952
                }
953
            }
954
        }
955

    
956
        /* sort the constraints (XXX: this is just an heuristic) */
957
        sort_constraints(def, 0, def->nb_oargs);
958
        sort_constraints(def, def->nb_oargs, def->nb_iargs);
959

    
960
#if 0
961
        {
962
            int i;
963

964
            printf("%s: sorted=", def->name);
965
            for(i = 0; i < def->nb_oargs + def->nb_iargs; i++)
966
                printf(" %d", def->sorted_args[i]);
967
            printf("\n");
968
        }
969
#endif
970
        tdefs++;
971
    }
972

    
973
}
974

    
975
#ifdef USE_LIVENESS_ANALYSIS
976

    
977
/* set a nop for an operation using 'nb_args' */
978
static inline void tcg_set_nop(TCGContext *s, uint16_t *opc_ptr, 
979
                               TCGArg *args, int nb_args)
980
{
981
    if (nb_args == 0) {
982
        *opc_ptr = INDEX_op_nop;
983
    } else {
984
        *opc_ptr = INDEX_op_nopn;
985
        args[0] = nb_args;
986
        args[nb_args - 1] = nb_args;
987
    }
988
}
989

    
990
/* liveness analysis: end of basic block: globals are live, temps are dead */
991
static inline void tcg_la_bb_end(TCGContext *s, uint8_t *dead_temps)
992
{
993
    memset(dead_temps, 0, s->nb_globals);
994
    memset(dead_temps + s->nb_globals, 1, s->nb_temps - s->nb_globals);
995
}
996

    
997
/* Liveness analysis : update the opc_dead_iargs array to tell if a
998
   given input arguments is dead. Instructions updating dead
999
   temporaries are removed. */
1000
void tcg_liveness_analysis(TCGContext *s)
1001
{
1002
    int i, op_index, op, nb_args, nb_iargs, nb_oargs, arg, nb_ops;
1003
    TCGArg *args;
1004
    const TCGOpDef *def;
1005
    uint8_t *dead_temps;
1006
    unsigned int dead_iargs;
1007
    
1008
    gen_opc_ptr++; /* skip end */
1009

    
1010
    nb_ops = gen_opc_ptr - gen_opc_buf;
1011

    
1012
    /* XXX: make it really dynamic */
1013
    s->op_dead_iargs = tcg_malloc(OPC_BUF_SIZE * sizeof(uint16_t));
1014
    
1015
    dead_temps = tcg_malloc(s->nb_temps);
1016
    memset(dead_temps, 1, s->nb_temps);
1017

    
1018
    args = gen_opparam_ptr;
1019
    op_index = nb_ops - 1;
1020
    while (op_index >= 0) {
1021
        op = gen_opc_buf[op_index];
1022
        def = &tcg_op_defs[op];
1023
        switch(op) {
1024
        case INDEX_op_call:
1025
            {
1026
                int call_flags;
1027

    
1028
                nb_args = args[-1];
1029
                args -= nb_args;
1030
                nb_iargs = args[0] & 0xffff;
1031
                nb_oargs = args[0] >> 16;
1032
                args++;
1033
                call_flags = args[nb_oargs + nb_iargs];
1034

    
1035
                /* pure functions can be removed if their result is not
1036
                   used */
1037
                if (call_flags & TCG_CALL_PURE) {
1038
                    for(i = 0; i < nb_oargs; i++) {
1039
                        arg = args[i];
1040
                        if (!dead_temps[arg])
1041
                            goto do_not_remove_call;
1042
                    }
1043
                    tcg_set_nop(s, gen_opc_buf + op_index, 
1044
                                args - 1, nb_args);
1045
                } else {
1046
                do_not_remove_call:
1047

    
1048
                    /* output args are dead */
1049
                    for(i = 0; i < nb_oargs; i++) {
1050
                        arg = args[i];
1051
                        dead_temps[arg] = 1;
1052
                    }
1053
                    
1054
                    /* globals are live (they may be used by the call) */
1055
                    memset(dead_temps, 0, s->nb_globals);
1056
                    
1057
                    /* input args are live */
1058
                    dead_iargs = 0;
1059
                    for(i = 0; i < nb_iargs; i++) {
1060
                        arg = args[i + nb_oargs];
1061
                        if (arg != TCG_CALL_DUMMY_ARG) {
1062
                            if (dead_temps[arg]) {
1063
                                dead_iargs |= (1 << i);
1064
                            }
1065
                            dead_temps[arg] = 0;
1066
                        }
1067
                    }
1068
                    s->op_dead_iargs[op_index] = dead_iargs;
1069
                }
1070
                args--;
1071
            }
1072
            break;
1073
        case INDEX_op_set_label:
1074
            args--;
1075
            /* mark end of basic block */
1076
            tcg_la_bb_end(s, dead_temps);
1077
            break;
1078
        case INDEX_op_debug_insn_start:
1079
            args -= def->nb_args;
1080
            break;
1081
        case INDEX_op_nopn:
1082
            nb_args = args[-1];
1083
            args -= nb_args;
1084
            break;
1085
        case INDEX_op_discard:
1086
            args--;
1087
            /* mark the temporary as dead */
1088
            dead_temps[args[0]] = 1;
1089
            break;
1090
        case INDEX_op_macro_2:
1091
            {
1092
                int dead_args[2], macro_id;
1093
                int saved_op_index, saved_arg_index;
1094
                int macro_op_index, macro_arg_index;
1095
                int macro_end_op_index, macro_end_arg_index;
1096
                int last_nb_temps;
1097
                
1098
                nb_args = 3;
1099
                args -= nb_args;
1100
                dead_args[0] = dead_temps[args[0]];
1101
                dead_args[1] = dead_temps[args[1]];
1102
                macro_id = args[2];
1103

    
1104
                /* call the macro function which generate code
1105
                   depending on the live outputs */
1106
                saved_op_index = op_index;
1107
                saved_arg_index = args - gen_opparam_buf;
1108

    
1109
                /* add a macro start instruction */
1110
                *gen_opc_ptr++ = INDEX_op_macro_start;
1111
                *gen_opparam_ptr++ = saved_op_index;
1112
                *gen_opparam_ptr++ = saved_arg_index;
1113

    
1114
                macro_op_index = gen_opc_ptr - gen_opc_buf;
1115
                macro_arg_index = gen_opparam_ptr -  gen_opparam_buf;
1116

    
1117
                last_nb_temps = s->nb_temps;
1118

    
1119
                s->macro_func(s, macro_id, dead_args);
1120

    
1121
                /* realloc temp info (XXX: make it faster) */
1122
                if (s->nb_temps > last_nb_temps) {
1123
                    uint8_t *new_dead_temps;
1124

    
1125
                    new_dead_temps = tcg_malloc(s->nb_temps);
1126
                    memcpy(new_dead_temps, dead_temps, last_nb_temps);
1127
                    memset(new_dead_temps + last_nb_temps, 1, 
1128
                           s->nb_temps - last_nb_temps);
1129
                    dead_temps = new_dead_temps;
1130
                }
1131

    
1132
                macro_end_op_index = gen_opc_ptr - gen_opc_buf;
1133
                macro_end_arg_index = gen_opparam_ptr - gen_opparam_buf;
1134

    
1135
                /* end of macro: add a goto to the next instruction */
1136
                *gen_opc_ptr++ = INDEX_op_macro_end;
1137
                *gen_opparam_ptr++ = op_index + 1;
1138
                *gen_opparam_ptr++ = saved_arg_index + nb_args;
1139

    
1140
                /* modify the macro operation to be a macro_goto */
1141
                gen_opc_buf[op_index] = INDEX_op_macro_goto;
1142
                args[0] = macro_op_index;
1143
                args[1] = macro_arg_index;
1144
                args[2] = 0; /* dummy third arg to match the 
1145
                                macro parameters */
1146

    
1147
                /* set the next instruction to the end of the macro */
1148
                op_index = macro_end_op_index;
1149
                args = macro_end_arg_index + gen_opparam_buf;
1150
            }
1151
            break;
1152
        case INDEX_op_macro_start:
1153
            args -= 2;
1154
            op_index = args[0];
1155
            args = gen_opparam_buf + args[1];
1156
            break;
1157
        case INDEX_op_macro_goto:
1158
        case INDEX_op_macro_end:
1159
            tcg_abort(); /* should never happen in liveness analysis */
1160
        case INDEX_op_end:
1161
            break;
1162
            /* XXX: optimize by hardcoding common cases (e.g. triadic ops) */
1163
        default:
1164
            if (op > INDEX_op_end) {
1165
                args -= def->nb_args;
1166
                nb_iargs = def->nb_iargs;
1167
                nb_oargs = def->nb_oargs;
1168

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

    
1185
                    /* output args are dead */
1186
                    for(i = 0; i < nb_oargs; i++) {
1187
                        arg = args[i];
1188
                        dead_temps[arg] = 1;
1189
                    }
1190
                    
1191
                    /* if end of basic block, update */
1192
                    if (def->flags & TCG_OPF_BB_END) {
1193
                        tcg_la_bb_end(s, dead_temps);
1194
                    } else if (def->flags & TCG_OPF_CALL_CLOBBER) {
1195
                        /* globals are live */
1196
                        memset(dead_temps, 0, s->nb_globals);
1197
                    }
1198
                    
1199
                    /* input args are live */
1200
                    dead_iargs = 0;
1201
                    for(i = 0; i < nb_iargs; i++) {
1202
                        arg = args[i + nb_oargs];
1203
                        if (dead_temps[arg]) {
1204
                            dead_iargs |= (1 << i);
1205
                        }
1206
                        dead_temps[arg] = 0;
1207
                    }
1208
                    s->op_dead_iargs[op_index] = dead_iargs;
1209
                }
1210
            } else {
1211
                /* legacy dyngen operations */
1212
                args -= def->nb_args;
1213
                /* mark end of basic block */
1214
                tcg_la_bb_end(s, dead_temps);
1215
            }
1216
            break;
1217
        }
1218
        op_index--;
1219
    }
1220

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

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

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

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

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

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

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

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

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

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

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

    
1348
    tcg_regset_andnot(reg_ct, reg1, reg2);
1349

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

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

    
1366
    tcg_abort();
1367
}
1368

    
1369
/* save globals to their cannonical location and assume they can be
1370
   modified be the following code. 'allocated_regs' is used in case a
1371
   temporary registers needs to be allocated to store a constant. */
1372
static void save_globals(TCGContext *s, TCGRegSet allocated_regs)
1373
{
1374
    TCGTemp *ts;
1375
    int i, reg;
1376

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

    
1403
/* at the end of a basic block, we assume all temporaries are dead and
1404
   all globals are stored at their canonical location. */
1405
static void tcg_reg_alloc_bb_end(TCGContext *s, TCGRegSet allocated_regs)
1406
{
1407
    TCGTemp *ts;
1408
    int i;
1409

    
1410
    for(i = s->nb_globals; i < s->nb_temps; i++) {
1411
        ts = &s->temps[i];
1412
        if (ts->val_type == TEMP_VAL_REG) {
1413
            s->reg_to_temp[ts->reg] = -1;
1414
        }
1415
        ts->val_type = TEMP_VAL_DEAD;
1416
    }
1417

    
1418
    save_globals(s, allocated_regs);
1419
}
1420

    
1421
#define IS_DEAD_IARG(n) ((dead_iargs >> (n)) & 1)
1422

    
1423
static void tcg_reg_alloc_movi(TCGContext *s, const TCGArg *args)
1424
{
1425
    TCGTemp *ots;
1426
    tcg_target_ulong val;
1427

    
1428
    ots = &s->temps[args[0]];
1429
    val = args[1];
1430

    
1431
    if (ots->fixed_reg) {
1432
        /* for fixed registers, we do not do any constant
1433
           propagation */
1434
        tcg_out_movi(s, ots->type, ots->reg, val);
1435
    } else {
1436
        /* The movi is not explicitely generated here */
1437
        if (ots->val_type == TEMP_VAL_REG)
1438
            s->reg_to_temp[ots->reg] = -1;
1439
        ots->val_type = TEMP_VAL_CONST;
1440
        ots->val = val;
1441
    }
1442
}
1443

    
1444
static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
1445
                              const TCGArg *args,
1446
                              unsigned int dead_iargs)
1447
{
1448
    TCGTemp *ts, *ots;
1449
    int reg;
1450
    const TCGArgConstraint *arg_ct;
1451

    
1452
    ots = &s->temps[args[0]];
1453
    ts = &s->temps[args[1]];
1454
    arg_ct = &def->args_ct[0];
1455

    
1456
    /* XXX: always mark arg dead if IS_DEAD_IARG(0) */
1457
    if (ts->val_type == TEMP_VAL_REG) {
1458
        if (IS_DEAD_IARG(0) && !ts->fixed_reg && !ots->fixed_reg) {
1459
            /* the mov can be suppressed */
1460
            if (ots->val_type == TEMP_VAL_REG)
1461
                s->reg_to_temp[ots->reg] = -1;
1462
            reg = ts->reg;
1463
            s->reg_to_temp[reg] = -1;
1464
            ts->val_type = TEMP_VAL_DEAD;
1465
        } else {
1466
            if (ots->val_type == TEMP_VAL_REG) {
1467
                reg = ots->reg;
1468
            } else {
1469
                reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1470
            }
1471
            if (ts->reg != reg) {
1472
                tcg_out_mov(s, reg, ts->reg);
1473
            }
1474
        }
1475
    } else if (ts->val_type == TEMP_VAL_MEM) {
1476
        if (ots->val_type == TEMP_VAL_REG) {
1477
            reg = ots->reg;
1478
        } else {
1479
            reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1480
        }
1481
        tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1482
    } else if (ts->val_type == TEMP_VAL_CONST) {
1483
        if (ots->fixed_reg) {
1484
            reg = ots->reg;
1485
            tcg_out_movi(s, ots->type, reg, ts->val);
1486
        } else {
1487
            /* propagate constant */
1488
            if (ots->val_type == TEMP_VAL_REG)
1489
                s->reg_to_temp[ots->reg] = -1;
1490
            ots->val_type = TEMP_VAL_CONST;
1491
            ots->val = ts->val;
1492
            return;
1493
        }
1494
    } else {
1495
        tcg_abort();
1496
    }
1497
    s->reg_to_temp[reg] = args[0];
1498
    ots->reg = reg;
1499
    ots->val_type = TEMP_VAL_REG;
1500
    ots->mem_coherent = 0;
1501
}
1502

    
1503
static void tcg_reg_alloc_op(TCGContext *s, 
1504
                             const TCGOpDef *def, int opc,
1505
                             const TCGArg *args,
1506
                             unsigned int dead_iargs)
1507
{
1508
    TCGRegSet allocated_regs;
1509
    int i, k, nb_iargs, nb_oargs, reg;
1510
    TCGArg arg;
1511
    const TCGArgConstraint *arg_ct;
1512
    TCGTemp *ts;
1513
    TCGArg new_args[TCG_MAX_OP_ARGS];
1514
    int const_args[TCG_MAX_OP_ARGS];
1515

    
1516
    nb_oargs = def->nb_oargs;
1517
    nb_iargs = def->nb_iargs;
1518

    
1519
    /* copy constants */
1520
    memcpy(new_args + nb_oargs + nb_iargs, 
1521
           args + nb_oargs + nb_iargs, 
1522
           sizeof(TCGArg) * def->nb_cargs);
1523

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

    
1651
    /* emit instruction */
1652
    tcg_out_op(s, opc, new_args, const_args);
1653
    
1654
    /* move the outputs in the correct register if needed */
1655
    for(i = 0; i < nb_oargs; i++) {
1656
        ts = &s->temps[args[i]];
1657
        reg = new_args[i];
1658
        if (ts->fixed_reg && ts->reg != reg) {
1659
            tcg_out_mov(s, ts->reg, reg);
1660
        }
1661
    }
1662
}
1663

    
1664
#ifdef TCG_TARGET_STACK_GROWSUP
1665
#define STACK_DIR(x) (-(x))
1666
#else
1667
#define STACK_DIR(x) (x)
1668
#endif
1669

    
1670
static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
1671
                              int opc, const TCGArg *args,
1672
                              unsigned int dead_iargs)
1673
{
1674
    int nb_iargs, nb_oargs, flags, nb_regs, i, reg, nb_params;
1675
    TCGArg arg, func_arg;
1676
    TCGTemp *ts;
1677
    tcg_target_long stack_offset, call_stack_size, func_addr;
1678
    int const_func_arg, allocate_args;
1679
    TCGRegSet allocated_regs;
1680
    const TCGArgConstraint *arg_ct;
1681

    
1682
    arg = *args++;
1683

    
1684
    nb_oargs = arg >> 16;
1685
    nb_iargs = arg & 0xffff;
1686
    nb_params = nb_iargs - 1;
1687

    
1688
    flags = args[nb_oargs + nb_iargs];
1689

    
1690
    nb_regs = tcg_target_get_call_iarg_regs_count(flags);
1691
    if (nb_regs > nb_params)
1692
        nb_regs = nb_params;
1693

    
1694
    /* assign stack slots first */
1695
    /* XXX: preallocate call stack */
1696
    call_stack_size = (nb_params - nb_regs) * sizeof(tcg_target_long);
1697
    call_stack_size = (call_stack_size + TCG_TARGET_STACK_ALIGN - 1) & 
1698
        ~(TCG_TARGET_STACK_ALIGN - 1);
1699
    allocate_args = (call_stack_size > TCG_STATIC_CALL_ARGS_SIZE);
1700
    if (allocate_args) {
1701
        tcg_out_addi(s, TCG_REG_CALL_STACK, -STACK_DIR(call_stack_size));
1702
    }
1703

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

    
1817
    tcg_out_op(s, opc, &func_arg, &const_func_arg);
1818
    
1819
    if (allocate_args) {
1820
        tcg_out_addi(s, TCG_REG_CALL_STACK, STACK_DIR(call_stack_size));
1821
    }
1822

    
1823
    /* assign output registers and emit moves if needed */
1824
    for(i = 0; i < nb_oargs; i++) {
1825
        arg = args[i];
1826
        ts = &s->temps[arg];
1827
        reg = tcg_target_call_oarg_regs[i];
1828
        assert(s->reg_to_temp[reg] == -1);
1829
        if (ts->fixed_reg) {
1830
            if (ts->reg != reg) {
1831
                tcg_out_mov(s, ts->reg, reg);
1832
            }
1833
        } else {
1834
            if (ts->val_type == TEMP_VAL_REG)
1835
                s->reg_to_temp[ts->reg] = -1;
1836
            ts->val_type = TEMP_VAL_REG;
1837
            ts->reg = reg;
1838
            ts->mem_coherent = 0; 
1839
            s->reg_to_temp[reg] = arg;
1840
        }
1841
    }
1842
    
1843
    return nb_iargs + nb_oargs + def->nb_cargs + 1;
1844
}
1845

    
1846
#ifdef CONFIG_PROFILER
1847

    
1848
static int64_t dyngen_table_op_count[NB_OPS];
1849

    
1850
void dump_op_count(void)
1851
{
1852
    int i;
1853
    FILE *f;
1854
    f = fopen("/tmp/op1.log", "w");
1855
    for(i = 0; i < INDEX_op_end; i++) {
1856
        fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name, dyngen_table_op_count[i]);
1857
    }
1858
    fclose(f);
1859
    f = fopen("/tmp/op2.log", "w");
1860
    for(i = INDEX_op_end; i < NB_OPS; i++) {
1861
        fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name, dyngen_table_op_count[i]);
1862
    }
1863
    fclose(f);
1864
}
1865
#endif
1866

    
1867

    
1868
static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
1869
                                      long search_pc)
1870
{
1871
    int opc, op_index, macro_op_index;
1872
    const TCGOpDef *def;
1873
    unsigned int dead_iargs;
1874
    const TCGArg *args;
1875

    
1876
#ifdef DEBUG_DISAS
1877
    if (unlikely(loglevel & CPU_LOG_TB_OP)) {
1878
        fprintf(logfile, "OP:\n");
1879
        tcg_dump_ops(s, logfile);
1880
        fprintf(logfile, "\n");
1881
    }
1882
#endif
1883

    
1884
#ifdef CONFIG_PROFILER
1885
    s->la_time -= profile_getclock();
1886
#endif
1887
    tcg_liveness_analysis(s);
1888
#ifdef CONFIG_PROFILER
1889
    s->la_time += profile_getclock();
1890
#endif
1891

    
1892
#ifdef DEBUG_DISAS
1893
    if (unlikely(loglevel & CPU_LOG_TB_OP_OPT)) {
1894
        fprintf(logfile, "OP after la:\n");
1895
        tcg_dump_ops(s, logfile);
1896
        fprintf(logfile, "\n");
1897
    }
1898
#endif
1899

    
1900
    tcg_reg_alloc_start(s);
1901

    
1902
    s->code_buf = gen_code_buf;
1903
    s->code_ptr = gen_code_buf;
1904

    
1905
    macro_op_index = -1;
1906
    args = gen_opparam_buf;
1907
    op_index = 0;
1908

    
1909
    for(;;) {
1910
        opc = gen_opc_buf[op_index];
1911
#ifdef CONFIG_PROFILER
1912
        dyngen_table_op_count[opc]++;
1913
#endif
1914
        def = &tcg_op_defs[opc];
1915
#if 0
1916
        printf("%s: %d %d %d\n", def->name,
1917
               def->nb_oargs, def->nb_iargs, def->nb_cargs);
1918
        //        dump_regs(s);
1919
#endif
1920
        switch(opc) {
1921
        case INDEX_op_mov_i32:
1922
#if TCG_TARGET_REG_BITS == 64
1923
        case INDEX_op_mov_i64:
1924
#endif
1925
            dead_iargs = s->op_dead_iargs[op_index];
1926
            tcg_reg_alloc_mov(s, def, args, dead_iargs);
1927
            break;
1928
        case INDEX_op_movi_i32:
1929
#if TCG_TARGET_REG_BITS == 64
1930
        case INDEX_op_movi_i64:
1931
#endif
1932
            tcg_reg_alloc_movi(s, args);
1933
            break;
1934
        case INDEX_op_debug_insn_start:
1935
            /* debug instruction */
1936
            break;
1937
        case INDEX_op_nop:
1938
        case INDEX_op_nop1:
1939
        case INDEX_op_nop2:
1940
        case INDEX_op_nop3:
1941
            break;
1942
        case INDEX_op_nopn:
1943
            args += args[0];
1944
            goto next;
1945
        case INDEX_op_discard:
1946
            {
1947
                TCGTemp *ts;
1948
                ts = &s->temps[args[0]];
1949
                /* mark the temporary as dead */
1950
                if (!ts->fixed_reg) {
1951
                    if (ts->val_type == TEMP_VAL_REG)
1952
                        s->reg_to_temp[ts->reg] = -1;
1953
                    ts->val_type = TEMP_VAL_DEAD;
1954
                }
1955
            }
1956
            break;
1957
        case INDEX_op_macro_goto:
1958
            macro_op_index = op_index; /* only used for exceptions */
1959
            op_index = args[0] - 1;
1960
            args = gen_opparam_buf + args[1];
1961
            goto next;
1962
        case INDEX_op_macro_end:
1963
            macro_op_index = -1; /* only used for exceptions */
1964
            op_index = args[0] - 1;
1965
            args = gen_opparam_buf + args[1];
1966
            goto next;
1967
        case INDEX_op_macro_start:
1968
            /* must never happen here */
1969
            tcg_abort();
1970
        case INDEX_op_set_label:
1971
            tcg_reg_alloc_bb_end(s, s->reserved_regs);
1972
            tcg_out_label(s, args[0], (long)s->code_ptr);
1973
            break;
1974
        case INDEX_op_call:
1975
            dead_iargs = s->op_dead_iargs[op_index];
1976
            args += tcg_reg_alloc_call(s, def, opc, args, dead_iargs);
1977
            goto next;
1978
        case INDEX_op_end:
1979
            goto the_end;
1980

    
1981
#ifdef CONFIG_DYNGEN_OP
1982
        case 0 ... INDEX_op_end - 1:
1983
            /* legacy dyngen ops */
1984
#ifdef CONFIG_PROFILER
1985
            s->old_op_count++;
1986
#endif
1987
            tcg_reg_alloc_bb_end(s, s->reserved_regs);
1988
            if (search_pc >= 0) {
1989
                s->code_ptr += def->copy_size;
1990
                args += def->nb_args;
1991
            } else {
1992
                args = dyngen_op(s, opc, args);
1993
            }
1994
            goto next;
1995
#endif
1996
        default:
1997
            /* Note: in order to speed up the code, it would be much
1998
               faster to have specialized register allocator functions for
1999
               some common argument patterns */
2000
            dead_iargs = s->op_dead_iargs[op_index];
2001
            tcg_reg_alloc_op(s, def, opc, args, dead_iargs);
2002
            break;
2003
        }
2004
        args += def->nb_args;
2005
    next: ;
2006
        if (search_pc >= 0 && search_pc < s->code_ptr - gen_code_buf) {
2007
            if (macro_op_index >= 0)
2008
                return macro_op_index;
2009
            else
2010
                return op_index;
2011
        }
2012
        op_index++;
2013
#ifndef NDEBUG
2014
        check_regs(s);
2015
#endif
2016
    }
2017
 the_end:
2018
    return -1;
2019
}
2020

    
2021
int dyngen_code(TCGContext *s, uint8_t *gen_code_buf)
2022
{
2023
#ifdef CONFIG_PROFILER
2024
    {
2025
        int n;
2026
        n = (gen_opc_ptr - gen_opc_buf);
2027
        s->op_count += n;
2028
        if (n > s->op_count_max)
2029
            s->op_count_max = n;
2030

    
2031
        s->temp_count += s->nb_temps;
2032
        if (s->nb_temps > s->temp_count_max)
2033
            s->temp_count_max = s->nb_temps;
2034
    }
2035
#endif
2036

    
2037
    tcg_gen_code_common(s, gen_code_buf, -1);
2038

    
2039
    /* flush instruction cache */
2040
    flush_icache_range((unsigned long)gen_code_buf, 
2041
                       (unsigned long)s->code_ptr);
2042
    return s->code_ptr -  gen_code_buf;
2043
}
2044

    
2045
/* Return the index of the micro operation such as the pc after is <
2046
   offset bytes from the start of the TB.  The contents of gen_code_buf must
2047
   not be changed, though writing the same values is ok.
2048
   Return -1 if not found. */
2049
int dyngen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, long offset)
2050
{
2051
    return tcg_gen_code_common(s, gen_code_buf, offset);
2052
}
2053

    
2054
#ifdef CONFIG_PROFILER
2055
void tcg_dump_info(FILE *f,
2056
                   int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
2057
{
2058
    TCGContext *s = &tcg_ctx;
2059
    int64_t tot;
2060

    
2061
    tot = s->interm_time + s->code_time;
2062
    cpu_fprintf(f, "JIT cycles          %" PRId64 " (%0.3f s at 2.4 GHz)\n",
2063
                tot, tot / 2.4e9);
2064
    cpu_fprintf(f, "translated TBs      %" PRId64 " (aborted=%" PRId64 " %0.1f%%)\n", 
2065
                s->tb_count, 
2066
                s->tb_count1 - s->tb_count,
2067
                s->tb_count1 ? (double)(s->tb_count1 - s->tb_count) / s->tb_count1 * 100.0 : 0);
2068
    cpu_fprintf(f, "avg ops/TB          %0.1f max=%d\n", 
2069
                s->tb_count ? (double)s->op_count / s->tb_count : 0, s->op_count_max);
2070
    cpu_fprintf(f, "old ops/total ops   %0.1f%%\n", 
2071
                s->op_count ? (double)s->old_op_count / s->op_count * 100.0 : 0);
2072
    cpu_fprintf(f, "deleted ops/TB      %0.2f\n",
2073
                s->tb_count ? 
2074
                (double)s->del_op_count / s->tb_count : 0);
2075
    cpu_fprintf(f, "avg temps/TB        %0.2f max=%d\n",
2076
                s->tb_count ? 
2077
                (double)s->temp_count / s->tb_count : 0,
2078
                s->temp_count_max);
2079
    
2080
    cpu_fprintf(f, "cycles/op           %0.1f\n", 
2081
                s->op_count ? (double)tot / s->op_count : 0);
2082
    cpu_fprintf(f, "cycles/in byte      %0.1f\n", 
2083
                s->code_in_len ? (double)tot / s->code_in_len : 0);
2084
    cpu_fprintf(f, "cycles/out byte     %0.1f\n", 
2085
                s->code_out_len ? (double)tot / s->code_out_len : 0);
2086
    if (tot == 0)
2087
        tot = 1;
2088
    cpu_fprintf(f, "  gen_interm time   %0.1f%%\n", 
2089
                (double)s->interm_time / tot * 100.0);
2090
    cpu_fprintf(f, "  gen_code time     %0.1f%%\n", 
2091
                (double)s->code_time / tot * 100.0);
2092
    cpu_fprintf(f, "liveness/code time  %0.1f%%\n", 
2093
                (double)s->la_time / (s->code_time ? s->code_time : 1) * 100.0);
2094
    cpu_fprintf(f, "cpu_restore count   %" PRId64 "\n",
2095
                s->restore_count);
2096
    cpu_fprintf(f, "  avg cycles        %0.1f\n",
2097
                s->restore_count ? (double)s->restore_time / s->restore_count : 0);
2098
    {
2099
        extern void dump_op_count(void);
2100
        dump_op_count();
2101
    }
2102
}
2103
#else
2104
void tcg_dump_info(FILE *f,
2105
                   int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
2106
{
2107
    cpu_fprintf(f, "[TCG profiler not compiled]\n");
2108
}
2109
#endif