Statistics
| Branch: | Revision:

root / tcg / tcg.c @ b314f270

History | View | Annotate | Download (61.8 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_func_start(TCGContext *s)
263
{
264
    int i;
265
    tcg_pool_reset(s);
266
    s->nb_temps = s->nb_globals;
267
    for(i = 0; i < (TCG_TYPE_COUNT * 2); i++)
268
        s->first_free_temp[i] = -1;
269
    s->labels = tcg_malloc(sizeof(TCGLabel) * TCG_MAX_LABELS);
270
    s->nb_labels = 0;
271
    s->current_frame_offset = s->frame_start;
272

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

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

    
283
TCGv tcg_global_reg_new(TCGType type, int reg, const char *name)
284
{
285
    TCGContext *s = &tcg_ctx;
286
    TCGTemp *ts;
287
    int idx;
288

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

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

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

    
331
    ts++;
332
    ts->base_type = type;
333
    ts->type = TCG_TYPE_I32;
334
    ts->fixed_reg = 1;
335
    ts->reg = reg2;
336
    pstrcpy(buf, sizeof(buf), name);
337
    pstrcat(buf, sizeof(buf), "_1");
338
    ts->name = strdup(buf);
339

    
340
    s->nb_globals += 2;
341
    return MAKE_TCGV(idx);
342
}
343
#endif
344

    
345
TCGv tcg_global_mem_new(TCGType type, int reg, tcg_target_long offset,
346
                        const char *name)
347
{
348
    TCGContext *s = &tcg_ctx;
349
    TCGTemp *ts;
350
    int idx;
351

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

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

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

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

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

    
456
void tcg_temp_free(TCGv arg)
457
{
458
    TCGContext *s = &tcg_ctx;
459
    TCGTemp *ts;
460
    int idx = GET_TCGV(arg);
461
    int k;
462

    
463
    assert(idx >= s->nb_globals && idx < s->nb_temps);
464
    ts = &s->temps[idx];
465
    assert(ts->temp_allocated != 0);
466
    ts->temp_allocated = 0;
467
    k = ts->base_type;
468
    if (ts->temp_local)
469
        k += TCG_TYPE_COUNT;
470
    ts->next_free_temp = s->first_free_temp[k];
471
    s->first_free_temp[k] = idx;
472
}
473

    
474

    
475
TCGv tcg_const_i32(int32_t val)
476
{
477
    TCGv t0;
478
    t0 = tcg_temp_new(TCG_TYPE_I32);
479
    tcg_gen_movi_i32(t0, val);
480
    return t0;
481
}
482

    
483
TCGv tcg_const_i64(int64_t val)
484
{
485
    TCGv t0;
486
    t0 = tcg_temp_new(TCG_TYPE_I64);
487
    tcg_gen_movi_i64(t0, val);
488
    return t0;
489
}
490

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

    
510
static inline TCGType tcg_get_base_type(TCGContext *s, TCGv arg)
511
{
512
    return s->temps[GET_TCGV(arg)].base_type;
513
}
514

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

    
531
    *gen_opparam_ptr++ = flags;
532
    /* total parameters, needed to go backward in the instruction stream */
533
    *gen_opparam_ptr++ = 1 + nb_rets + nb_params + 3;
534
}
535

    
536

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

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

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

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

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

    
681
static char *tcg_get_arg_str_idx(TCGContext *s, char *buf, int buf_size,
682
                                 int idx)
683
{
684
    TCGTemp *ts;
685

    
686
    ts = &s->temps[idx];
687
    if (idx < s->nb_globals) {
688
        pstrcpy(buf, buf_size, ts->name);
689
    } else {
690
        if (ts->temp_local) 
691
            snprintf(buf, buf_size, "loc%d", idx - s->nb_globals);
692
        else
693
            snprintf(buf, buf_size, "tmp%d", idx - s->nb_globals);
694
    }
695
    return buf;
696
}
697

    
698
char *tcg_get_arg_str(TCGContext *s, char *buf, int buf_size, TCGv arg)
699
{
700
    return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV(arg));
701
}
702

    
703
static int helper_cmp(const void *p1, const void *p2)
704
{
705
    const TCGHelperInfo *th1 = p1;
706
    const TCGHelperInfo *th2 = p2;
707
    if (th1->func < th2->func)
708
        return -1;
709
    else if (th1->func == th2->func)
710
        return 0;
711
    else
712
        return 1;
713
}
714

    
715
/* find helper definition (Note: A hash table would be better) */
716
static TCGHelperInfo *tcg_find_helper(TCGContext *s, tcg_target_ulong val)
717
{
718
    int m, m_min, m_max;
719
    TCGHelperInfo *th;
720
    tcg_target_ulong v;
721

    
722
    if (unlikely(!s->helpers_sorted)) {
723
        qsort(s->helpers, s->nb_helpers, sizeof(TCGHelperInfo), 
724
              helper_cmp);
725
        s->helpers_sorted = 1;
726
    }
727

    
728
    /* binary search */
729
    m_min = 0;
730
    m_max = s->nb_helpers - 1;
731
    while (m_min <= m_max) {
732
        m = (m_min + m_max) >> 1;
733
        th = &s->helpers[m];
734
        v = th->func;
735
        if (v == val)
736
            return th;
737
        else if (val < v) {
738
            m_max = m - 1;
739
        } else {
740
            m_min = m + 1;
741
        }
742
    }
743
    return NULL;
744
}
745

    
746
void tcg_dump_ops(TCGContext *s, FILE *outfile)
747
{
748
    const uint16_t *opc_ptr;
749
    const TCGArg *args;
750
    TCGArg arg;
751
    int c, i, k, nb_oargs, nb_iargs, nb_cargs, first_insn;
752
    const TCGOpDef *def;
753
    char buf[128];
754

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

    
778
            /* variable number of arguments */
779
            arg = *args++;
780
            nb_oargs = arg >> 16;
781
            nb_iargs = arg & 0xffff;
782
            nb_cargs = def->nb_cargs;
783

    
784
            fprintf(outfile, " %s ", def->name);
785

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

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

    
869
/* we give more priority to constraints with less registers */
870
static int get_constraint_priority(const TCGOpDef *def, int k)
871
{
872
    const TCGArgConstraint *arg_ct;
873

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

    
891
/* sort from highest priority to lowest */
892
static void sort_constraints(TCGOpDef *def, int start, int n)
893
{
894
    int i, j, p1, p2, tmp;
895

    
896
    for(i = 0; i < n; i++)
897
        def->sorted_args[start + i] = start + i;
898
    if (n <= 1)
899
        return;
900
    for(i = 0; i < n - 1; i++) {
901
        for(j = i + 1; j < n; j++) {
902
            p1 = get_constraint_priority(def, def->sorted_args[start + i]);
903
            p2 = get_constraint_priority(def, def->sorted_args[start + j]);
904
            if (p1 < p2) {
905
                tmp = def->sorted_args[start + i];
906
                def->sorted_args[start + i] = def->sorted_args[start + j];
907
                def->sorted_args[start + j] = tmp;
908
            }
909
        }
910
    }
911
}
912

    
913
void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs)
914
{
915
    int op;
916
    TCGOpDef *def;
917
    const char *ct_str;
918
    int i, nb_args;
919

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

    
963
        /* sort the constraints (XXX: this is just an heuristic) */
964
        sort_constraints(def, 0, def->nb_oargs);
965
        sort_constraints(def, def->nb_oargs, def->nb_iargs);
966

    
967
#if 0
968
        {
969
            int i;
970

971
            printf("%s: sorted=", def->name);
972
            for(i = 0; i < def->nb_oargs + def->nb_iargs; i++)
973
                printf(" %d", def->sorted_args[i]);
974
            printf("\n");
975
        }
976
#endif
977
        tdefs++;
978
    }
979

    
980
}
981

    
982
#ifdef USE_LIVENESS_ANALYSIS
983

    
984
/* set a nop for an operation using 'nb_args' */
985
static inline void tcg_set_nop(TCGContext *s, uint16_t *opc_ptr, 
986
                               TCGArg *args, int nb_args)
987
{
988
    if (nb_args == 0) {
989
        *opc_ptr = INDEX_op_nop;
990
    } else {
991
        *opc_ptr = INDEX_op_nopn;
992
        args[0] = nb_args;
993
        args[nb_args - 1] = nb_args;
994
    }
995
}
996

    
997
/* liveness analysis: end of function: globals are live, temps are
998
   dead. */
999
/* XXX: at this stage, not used as there would be little gains because
1000
   most TBs end with a conditional jump. */
1001
static inline void tcg_la_func_end(TCGContext *s, uint8_t *dead_temps)
1002
{
1003
    memset(dead_temps, 0, s->nb_globals);
1004
    memset(dead_temps + s->nb_globals, 1, s->nb_temps - s->nb_globals);
1005
}
1006

    
1007
/* liveness analysis: end of basic block: globals are live, temps are
1008
   dead, local temps are live. */
1009
static inline void tcg_la_bb_end(TCGContext *s, uint8_t *dead_temps)
1010
{
1011
    int i;
1012
    TCGTemp *ts;
1013

    
1014
    memset(dead_temps, 0, s->nb_globals);
1015
    ts = &s->temps[s->nb_globals];
1016
    for(i = s->nb_globals; i < s->nb_temps; i++) {
1017
        if (ts->temp_local)
1018
            dead_temps[i] = 0;
1019
        else
1020
            dead_temps[i] = 1;
1021
        ts++;
1022
    }
1023
}
1024

    
1025
/* Liveness analysis : update the opc_dead_iargs array to tell if a
1026
   given input arguments is dead. Instructions updating dead
1027
   temporaries are removed. */
1028
void tcg_liveness_analysis(TCGContext *s)
1029
{
1030
    int i, op_index, op, nb_args, nb_iargs, nb_oargs, arg, nb_ops;
1031
    TCGArg *args;
1032
    const TCGOpDef *def;
1033
    uint8_t *dead_temps;
1034
    unsigned int dead_iargs;
1035
    
1036
    gen_opc_ptr++; /* skip end */
1037

    
1038
    nb_ops = gen_opc_ptr - gen_opc_buf;
1039

    
1040
    /* XXX: make it really dynamic */
1041
    s->op_dead_iargs = tcg_malloc(OPC_BUF_SIZE * sizeof(uint16_t));
1042
    
1043
    dead_temps = tcg_malloc(s->nb_temps);
1044
    memset(dead_temps, 1, s->nb_temps);
1045

    
1046
    args = gen_opparam_ptr;
1047
    op_index = nb_ops - 1;
1048
    while (op_index >= 0) {
1049
        op = gen_opc_buf[op_index];
1050
        def = &tcg_op_defs[op];
1051
        switch(op) {
1052
        case INDEX_op_call:
1053
            {
1054
                int call_flags;
1055

    
1056
                nb_args = args[-1];
1057
                args -= nb_args;
1058
                nb_iargs = args[0] & 0xffff;
1059
                nb_oargs = args[0] >> 16;
1060
                args++;
1061
                call_flags = args[nb_oargs + nb_iargs];
1062

    
1063
                /* pure functions can be removed if their result is not
1064
                   used */
1065
                if (call_flags & TCG_CALL_PURE) {
1066
                    for(i = 0; i < nb_oargs; i++) {
1067
                        arg = args[i];
1068
                        if (!dead_temps[arg])
1069
                            goto do_not_remove_call;
1070
                    }
1071
                    tcg_set_nop(s, gen_opc_buf + op_index, 
1072
                                args - 1, nb_args);
1073
                } else {
1074
                do_not_remove_call:
1075

    
1076
                    /* output args are dead */
1077
                    for(i = 0; i < nb_oargs; i++) {
1078
                        arg = args[i];
1079
                        dead_temps[arg] = 1;
1080
                    }
1081
                    
1082
                    /* globals are live (they may be used by the call) */
1083
                    memset(dead_temps, 0, s->nb_globals);
1084
                    
1085
                    /* input args are live */
1086
                    dead_iargs = 0;
1087
                    for(i = 0; i < nb_iargs; i++) {
1088
                        arg = args[i + nb_oargs];
1089
                        if (arg != TCG_CALL_DUMMY_ARG) {
1090
                            if (dead_temps[arg]) {
1091
                                dead_iargs |= (1 << i);
1092
                            }
1093
                            dead_temps[arg] = 0;
1094
                        }
1095
                    }
1096
                    s->op_dead_iargs[op_index] = dead_iargs;
1097
                }
1098
                args--;
1099
            }
1100
            break;
1101
        case INDEX_op_set_label:
1102
            args--;
1103
            /* mark end of basic block */
1104
            tcg_la_bb_end(s, dead_temps);
1105
            break;
1106
        case INDEX_op_debug_insn_start:
1107
            args -= def->nb_args;
1108
            break;
1109
        case INDEX_op_nopn:
1110
            nb_args = args[-1];
1111
            args -= nb_args;
1112
            break;
1113
        case INDEX_op_discard:
1114
            args--;
1115
            /* mark the temporary as dead */
1116
            dead_temps[args[0]] = 1;
1117
            break;
1118
        case INDEX_op_end:
1119
            break;
1120
            /* XXX: optimize by hardcoding common cases (e.g. triadic ops) */
1121
        default:
1122
            if (op > INDEX_op_end) {
1123
                args -= def->nb_args;
1124
                nb_iargs = def->nb_iargs;
1125
                nb_oargs = def->nb_oargs;
1126

    
1127
                /* Test if the operation can be removed because all
1128
                   its outputs are dead. We assume that nb_oargs == 0
1129
                   implies side effects */
1130
                if (!(def->flags & TCG_OPF_SIDE_EFFECTS) && nb_oargs != 0) {
1131
                    for(i = 0; i < nb_oargs; i++) {
1132
                        arg = args[i];
1133
                        if (!dead_temps[arg])
1134
                            goto do_not_remove;
1135
                    }
1136
                    tcg_set_nop(s, gen_opc_buf + op_index, args, def->nb_args);
1137
#ifdef CONFIG_PROFILER
1138
                    s->del_op_count++;
1139
#endif
1140
                } else {
1141
                do_not_remove:
1142

    
1143
                    /* output args are dead */
1144
                    for(i = 0; i < nb_oargs; i++) {
1145
                        arg = args[i];
1146
                        dead_temps[arg] = 1;
1147
                    }
1148
                    
1149
                    /* if end of basic block, update */
1150
                    if (def->flags & TCG_OPF_BB_END) {
1151
                        tcg_la_bb_end(s, dead_temps);
1152
                    } else if (def->flags & TCG_OPF_CALL_CLOBBER) {
1153
                        /* globals are live */
1154
                        memset(dead_temps, 0, s->nb_globals);
1155
                    }
1156
                    
1157
                    /* input args are live */
1158
                    dead_iargs = 0;
1159
                    for(i = 0; i < nb_iargs; i++) {
1160
                        arg = args[i + nb_oargs];
1161
                        if (dead_temps[arg]) {
1162
                            dead_iargs |= (1 << i);
1163
                        }
1164
                        dead_temps[arg] = 0;
1165
                    }
1166
                    s->op_dead_iargs[op_index] = dead_iargs;
1167
                }
1168
            } else {
1169
                /* legacy dyngen operations */
1170
                args -= def->nb_args;
1171
                /* mark end of basic block */
1172
                tcg_la_bb_end(s, dead_temps);
1173
            }
1174
            break;
1175
        }
1176
        op_index--;
1177
    }
1178

    
1179
    if (args != gen_opparam_buf)
1180
        tcg_abort();
1181
}
1182
#else
1183
/* dummy liveness analysis */
1184
void tcg_liveness_analysis(TCGContext *s)
1185
{
1186
    int nb_ops;
1187
    nb_ops = gen_opc_ptr - gen_opc_buf;
1188

    
1189
    s->op_dead_iargs = tcg_malloc(nb_ops * sizeof(uint16_t));
1190
    memset(s->op_dead_iargs, 0, nb_ops * sizeof(uint16_t));
1191
}
1192
#endif
1193

    
1194
#ifndef NDEBUG
1195
static void dump_regs(TCGContext *s)
1196
{
1197
    TCGTemp *ts;
1198
    int i;
1199
    char buf[64];
1200

    
1201
    for(i = 0; i < s->nb_temps; i++) {
1202
        ts = &s->temps[i];
1203
        printf("  %10s: ", tcg_get_arg_str_idx(s, buf, sizeof(buf), i));
1204
        switch(ts->val_type) {
1205
        case TEMP_VAL_REG:
1206
            printf("%s", tcg_target_reg_names[ts->reg]);
1207
            break;
1208
        case TEMP_VAL_MEM:
1209
            printf("%d(%s)", (int)ts->mem_offset, tcg_target_reg_names[ts->mem_reg]);
1210
            break;
1211
        case TEMP_VAL_CONST:
1212
            printf("$0x%" TCG_PRIlx, ts->val);
1213
            break;
1214
        case TEMP_VAL_DEAD:
1215
            printf("D");
1216
            break;
1217
        default:
1218
            printf("???");
1219
            break;
1220
        }
1221
        printf("\n");
1222
    }
1223

    
1224
    for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
1225
        if (s->reg_to_temp[i] >= 0) {
1226
            printf("%s: %s\n", 
1227
                   tcg_target_reg_names[i], 
1228
                   tcg_get_arg_str_idx(s, buf, sizeof(buf), s->reg_to_temp[i]));
1229
        }
1230
    }
1231
}
1232

    
1233
static void check_regs(TCGContext *s)
1234
{
1235
    int reg, k;
1236
    TCGTemp *ts;
1237
    char buf[64];
1238

    
1239
    for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1240
        k = s->reg_to_temp[reg];
1241
        if (k >= 0) {
1242
            ts = &s->temps[k];
1243
            if (ts->val_type != TEMP_VAL_REG ||
1244
                ts->reg != reg) {
1245
                printf("Inconsistency for register %s:\n", 
1246
                       tcg_target_reg_names[reg]);
1247
                goto fail;
1248
            }
1249
        }
1250
    }
1251
    for(k = 0; k < s->nb_temps; k++) {
1252
        ts = &s->temps[k];
1253
        if (ts->val_type == TEMP_VAL_REG &&
1254
            !ts->fixed_reg &&
1255
            s->reg_to_temp[ts->reg] != k) {
1256
                printf("Inconsistency for temp %s:\n", 
1257
                       tcg_get_arg_str_idx(s, buf, sizeof(buf), k));
1258
        fail:
1259
                printf("reg state:\n");
1260
                dump_regs(s);
1261
                tcg_abort();
1262
        }
1263
    }
1264
}
1265
#endif
1266

    
1267
static void temp_allocate_frame(TCGContext *s, int temp)
1268
{
1269
    TCGTemp *ts;
1270
    ts = &s->temps[temp];
1271
    s->current_frame_offset = (s->current_frame_offset + sizeof(tcg_target_long) - 1) & ~(sizeof(tcg_target_long) - 1);
1272
    if (s->current_frame_offset + sizeof(tcg_target_long) > s->frame_end)
1273
        tcg_abort();
1274
    ts->mem_offset = s->current_frame_offset;
1275
    ts->mem_reg = s->frame_reg;
1276
    ts->mem_allocated = 1;
1277
    s->current_frame_offset += sizeof(tcg_target_long);
1278
}
1279

    
1280
/* free register 'reg' by spilling the corresponding temporary if necessary */
1281
static void tcg_reg_free(TCGContext *s, int reg)
1282
{
1283
    TCGTemp *ts;
1284
    int temp;
1285

    
1286
    temp = s->reg_to_temp[reg];
1287
    if (temp != -1) {
1288
        ts = &s->temps[temp];
1289
        assert(ts->val_type == TEMP_VAL_REG);
1290
        if (!ts->mem_coherent) {
1291
            if (!ts->mem_allocated) 
1292
                temp_allocate_frame(s, temp);
1293
            tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1294
        }
1295
        ts->val_type = TEMP_VAL_MEM;
1296
        s->reg_to_temp[reg] = -1;
1297
    }
1298
}
1299

    
1300
/* Allocate a register belonging to reg1 & ~reg2 */
1301
static int tcg_reg_alloc(TCGContext *s, TCGRegSet reg1, TCGRegSet reg2)
1302
{
1303
    int i, reg;
1304
    TCGRegSet reg_ct;
1305

    
1306
    tcg_regset_andnot(reg_ct, reg1, reg2);
1307

    
1308
    /* first try free registers */
1309
    for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1310
        reg = tcg_target_reg_alloc_order[i];
1311
        if (tcg_regset_test_reg(reg_ct, reg) && s->reg_to_temp[reg] == -1)
1312
            return reg;
1313
    }
1314

    
1315
    /* XXX: do better spill choice */
1316
    for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1317
        reg = tcg_target_reg_alloc_order[i];
1318
        if (tcg_regset_test_reg(reg_ct, reg)) {
1319
            tcg_reg_free(s, reg);
1320
            return reg;
1321
        }
1322
    }
1323

    
1324
    tcg_abort();
1325
}
1326

    
1327
/* save a temporary to memory. 'allocated_regs' is used in case a
1328
   temporary registers needs to be allocated to store a constant. */
1329
static void temp_save(TCGContext *s, int temp, TCGRegSet allocated_regs)
1330
{
1331
    TCGTemp *ts;
1332
    int reg;
1333

    
1334
    ts = &s->temps[temp];
1335
    if (!ts->fixed_reg) {
1336
        switch(ts->val_type) {
1337
        case TEMP_VAL_REG:
1338
            tcg_reg_free(s, ts->reg);
1339
            break;
1340
        case TEMP_VAL_DEAD:
1341
            ts->val_type = TEMP_VAL_MEM;
1342
            break;
1343
        case TEMP_VAL_CONST:
1344
            reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], 
1345
                                allocated_regs);
1346
            if (!ts->mem_allocated) 
1347
                temp_allocate_frame(s, temp);
1348
            tcg_out_movi(s, ts->type, reg, ts->val);
1349
            tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1350
            ts->val_type = TEMP_VAL_MEM;
1351
            break;
1352
        case TEMP_VAL_MEM:
1353
            break;
1354
        default:
1355
            tcg_abort();
1356
        }
1357
    }
1358
}
1359

    
1360
/* save globals to their cannonical location and assume they can be
1361
   modified be the following code. 'allocated_regs' is used in case a
1362
   temporary registers needs to be allocated to store a constant. */
1363
static void save_globals(TCGContext *s, TCGRegSet allocated_regs)
1364
{
1365
    int i;
1366

    
1367
    for(i = 0; i < s->nb_globals; i++) {
1368
        temp_save(s, i, allocated_regs);
1369
    }
1370
}
1371

    
1372
/* at the end of a basic block, we assume all temporaries are dead and
1373
   all globals are stored at their canonical location. */
1374
static void tcg_reg_alloc_bb_end(TCGContext *s, TCGRegSet allocated_regs)
1375
{
1376
    TCGTemp *ts;
1377
    int i;
1378

    
1379
    for(i = s->nb_globals; i < s->nb_temps; i++) {
1380
        ts = &s->temps[i];
1381
        if (ts->temp_local) {
1382
            temp_save(s, i, allocated_regs);
1383
        } else {
1384
            if (ts->val_type == TEMP_VAL_REG) {
1385
                s->reg_to_temp[ts->reg] = -1;
1386
            }
1387
            ts->val_type = TEMP_VAL_DEAD;
1388
        }
1389
    }
1390

    
1391
    save_globals(s, allocated_regs);
1392
}
1393

    
1394
#define IS_DEAD_IARG(n) ((dead_iargs >> (n)) & 1)
1395

    
1396
static void tcg_reg_alloc_movi(TCGContext *s, const TCGArg *args)
1397
{
1398
    TCGTemp *ots;
1399
    tcg_target_ulong val;
1400

    
1401
    ots = &s->temps[args[0]];
1402
    val = args[1];
1403

    
1404
    if (ots->fixed_reg) {
1405
        /* for fixed registers, we do not do any constant
1406
           propagation */
1407
        tcg_out_movi(s, ots->type, ots->reg, val);
1408
    } else {
1409
        /* The movi is not explicitely generated here */
1410
        if (ots->val_type == TEMP_VAL_REG)
1411
            s->reg_to_temp[ots->reg] = -1;
1412
        ots->val_type = TEMP_VAL_CONST;
1413
        ots->val = val;
1414
    }
1415
}
1416

    
1417
static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
1418
                              const TCGArg *args,
1419
                              unsigned int dead_iargs)
1420
{
1421
    TCGTemp *ts, *ots;
1422
    int reg;
1423
    const TCGArgConstraint *arg_ct;
1424

    
1425
    ots = &s->temps[args[0]];
1426
    ts = &s->temps[args[1]];
1427
    arg_ct = &def->args_ct[0];
1428

    
1429
    /* XXX: always mark arg dead if IS_DEAD_IARG(0) */
1430
    if (ts->val_type == TEMP_VAL_REG) {
1431
        if (IS_DEAD_IARG(0) && !ts->fixed_reg && !ots->fixed_reg) {
1432
            /* the mov can be suppressed */
1433
            if (ots->val_type == TEMP_VAL_REG)
1434
                s->reg_to_temp[ots->reg] = -1;
1435
            reg = ts->reg;
1436
            s->reg_to_temp[reg] = -1;
1437
            ts->val_type = TEMP_VAL_DEAD;
1438
        } else {
1439
            if (ots->val_type == TEMP_VAL_REG) {
1440
                reg = ots->reg;
1441
            } else {
1442
                reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1443
            }
1444
            if (ts->reg != reg) {
1445
                tcg_out_mov(s, reg, ts->reg);
1446
            }
1447
        }
1448
    } else if (ts->val_type == TEMP_VAL_MEM) {
1449
        if (ots->val_type == TEMP_VAL_REG) {
1450
            reg = ots->reg;
1451
        } else {
1452
            reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1453
        }
1454
        tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1455
    } else if (ts->val_type == TEMP_VAL_CONST) {
1456
        if (ots->fixed_reg) {
1457
            reg = ots->reg;
1458
            tcg_out_movi(s, ots->type, reg, ts->val);
1459
        } else {
1460
            /* propagate constant */
1461
            if (ots->val_type == TEMP_VAL_REG)
1462
                s->reg_to_temp[ots->reg] = -1;
1463
            ots->val_type = TEMP_VAL_CONST;
1464
            ots->val = ts->val;
1465
            return;
1466
        }
1467
    } else {
1468
        tcg_abort();
1469
    }
1470
    s->reg_to_temp[reg] = args[0];
1471
    ots->reg = reg;
1472
    ots->val_type = TEMP_VAL_REG;
1473
    ots->mem_coherent = 0;
1474
}
1475

    
1476
static void tcg_reg_alloc_op(TCGContext *s, 
1477
                             const TCGOpDef *def, int opc,
1478
                             const TCGArg *args,
1479
                             unsigned int dead_iargs)
1480
{
1481
    TCGRegSet allocated_regs;
1482
    int i, k, nb_iargs, nb_oargs, reg;
1483
    TCGArg arg;
1484
    const TCGArgConstraint *arg_ct;
1485
    TCGTemp *ts;
1486
    TCGArg new_args[TCG_MAX_OP_ARGS];
1487
    int const_args[TCG_MAX_OP_ARGS];
1488

    
1489
    nb_oargs = def->nb_oargs;
1490
    nb_iargs = def->nb_iargs;
1491

    
1492
    /* copy constants */
1493
    memcpy(new_args + nb_oargs + nb_iargs, 
1494
           args + nb_oargs + nb_iargs, 
1495
           sizeof(TCGArg) * def->nb_cargs);
1496

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

    
1624
    /* emit instruction */
1625
    tcg_out_op(s, opc, new_args, const_args);
1626
    
1627
    /* move the outputs in the correct register if needed */
1628
    for(i = 0; i < nb_oargs; i++) {
1629
        ts = &s->temps[args[i]];
1630
        reg = new_args[i];
1631
        if (ts->fixed_reg && ts->reg != reg) {
1632
            tcg_out_mov(s, ts->reg, reg);
1633
        }
1634
    }
1635
}
1636

    
1637
#ifdef TCG_TARGET_STACK_GROWSUP
1638
#define STACK_DIR(x) (-(x))
1639
#else
1640
#define STACK_DIR(x) (x)
1641
#endif
1642

    
1643
static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
1644
                              int opc, const TCGArg *args,
1645
                              unsigned int dead_iargs)
1646
{
1647
    int nb_iargs, nb_oargs, flags, nb_regs, i, reg, nb_params;
1648
    TCGArg arg, func_arg;
1649
    TCGTemp *ts;
1650
    tcg_target_long stack_offset, call_stack_size, func_addr;
1651
    int const_func_arg, allocate_args;
1652
    TCGRegSet allocated_regs;
1653
    const TCGArgConstraint *arg_ct;
1654

    
1655
    arg = *args++;
1656

    
1657
    nb_oargs = arg >> 16;
1658
    nb_iargs = arg & 0xffff;
1659
    nb_params = nb_iargs - 1;
1660

    
1661
    flags = args[nb_oargs + nb_iargs];
1662

    
1663
    nb_regs = tcg_target_get_call_iarg_regs_count(flags);
1664
    if (nb_regs > nb_params)
1665
        nb_regs = nb_params;
1666

    
1667
    /* assign stack slots first */
1668
    /* XXX: preallocate call stack */
1669
    call_stack_size = (nb_params - nb_regs) * sizeof(tcg_target_long);
1670
    call_stack_size = (call_stack_size + TCG_TARGET_STACK_ALIGN - 1) & 
1671
        ~(TCG_TARGET_STACK_ALIGN - 1);
1672
    allocate_args = (call_stack_size > TCG_STATIC_CALL_ARGS_SIZE);
1673
    if (allocate_args) {
1674
        tcg_out_addi(s, TCG_REG_CALL_STACK, -STACK_DIR(call_stack_size));
1675
    }
1676

    
1677
    stack_offset = TCG_TARGET_CALL_STACK_OFFSET;
1678
    for(i = nb_regs; i < nb_params; i++) {
1679
        arg = args[nb_oargs + i];
1680
#ifdef TCG_TARGET_STACK_GROWSUP
1681
        stack_offset -= sizeof(tcg_target_long);
1682
#endif
1683
        if (arg != TCG_CALL_DUMMY_ARG) {
1684
            ts = &s->temps[arg];
1685
            if (ts->val_type == TEMP_VAL_REG) {
1686
                tcg_out_st(s, ts->type, ts->reg, TCG_REG_CALL_STACK, stack_offset);
1687
            } else if (ts->val_type == TEMP_VAL_MEM) {
1688
                reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], 
1689
                                    s->reserved_regs);
1690
                /* XXX: not correct if reading values from the stack */
1691
                tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1692
                tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
1693
            } else if (ts->val_type == TEMP_VAL_CONST) {
1694
                reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], 
1695
                                    s->reserved_regs);
1696
                /* XXX: sign extend may be needed on some targets */
1697
                tcg_out_movi(s, ts->type, reg, ts->val);
1698
                tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
1699
            } else {
1700
                tcg_abort();
1701
            }
1702
        }
1703
#ifndef TCG_TARGET_STACK_GROWSUP
1704
        stack_offset += sizeof(tcg_target_long);
1705
#endif
1706
    }
1707
    
1708
    /* assign input registers */
1709
    tcg_regset_set(allocated_regs, s->reserved_regs);
1710
    for(i = 0; i < nb_regs; i++) {
1711
        arg = args[nb_oargs + i];
1712
        if (arg != TCG_CALL_DUMMY_ARG) {
1713
            ts = &s->temps[arg];
1714
            reg = tcg_target_call_iarg_regs[i];
1715
            tcg_reg_free(s, reg);
1716
            if (ts->val_type == TEMP_VAL_REG) {
1717
                if (ts->reg != reg) {
1718
                    tcg_out_mov(s, reg, ts->reg);
1719
                }
1720
            } else if (ts->val_type == TEMP_VAL_MEM) {
1721
                tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1722
            } else if (ts->val_type == TEMP_VAL_CONST) {
1723
                /* XXX: sign extend ? */
1724
                tcg_out_movi(s, ts->type, reg, ts->val);
1725
            } else {
1726
                tcg_abort();
1727
            }
1728
            tcg_regset_set_reg(allocated_regs, reg);
1729
        }
1730
    }
1731
    
1732
    /* assign function address */
1733
    func_arg = args[nb_oargs + nb_iargs - 1];
1734
    arg_ct = &def->args_ct[0];
1735
    ts = &s->temps[func_arg];
1736
    func_addr = ts->val;
1737
    const_func_arg = 0;
1738
    if (ts->val_type == TEMP_VAL_MEM) {
1739
        reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1740
        tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1741
        func_arg = reg;
1742
        tcg_regset_set_reg(allocated_regs, reg);
1743
    } else if (ts->val_type == TEMP_VAL_REG) {
1744
        reg = ts->reg;
1745
        if (!tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1746
            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1747
            tcg_out_mov(s, reg, ts->reg);
1748
        }
1749
        func_arg = reg;
1750
        tcg_regset_set_reg(allocated_regs, reg);
1751
    } else if (ts->val_type == TEMP_VAL_CONST) {
1752
        if (tcg_target_const_match(func_addr, arg_ct)) {
1753
            const_func_arg = 1;
1754
            func_arg = func_addr;
1755
        } else {
1756
            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1757
            tcg_out_movi(s, ts->type, reg, func_addr);
1758
            func_arg = reg;
1759
            tcg_regset_set_reg(allocated_regs, reg);
1760
        }
1761
    } else {
1762
        tcg_abort();
1763
    }
1764
        
1765
    
1766
    /* mark dead temporaries and free the associated registers */
1767
    for(i = 0; i < nb_iargs; i++) {
1768
        arg = args[nb_oargs + i];
1769
        if (IS_DEAD_IARG(i)) {
1770
            ts = &s->temps[arg];
1771
            if (!ts->fixed_reg) {
1772
                if (ts->val_type == TEMP_VAL_REG)
1773
                    s->reg_to_temp[ts->reg] = -1;
1774
                ts->val_type = TEMP_VAL_DEAD;
1775
            }
1776
        }
1777
    }
1778
    
1779
    /* clobber call registers */
1780
    for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1781
        if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
1782
            tcg_reg_free(s, reg);
1783
        }
1784
    }
1785
    
1786
    /* store globals and free associated registers (we assume the call
1787
       can modify any global. */
1788
    save_globals(s, allocated_regs);
1789

    
1790
    tcg_out_op(s, opc, &func_arg, &const_func_arg);
1791
    
1792
    if (allocate_args) {
1793
        tcg_out_addi(s, TCG_REG_CALL_STACK, STACK_DIR(call_stack_size));
1794
    }
1795

    
1796
    /* assign output registers and emit moves if needed */
1797
    for(i = 0; i < nb_oargs; i++) {
1798
        arg = args[i];
1799
        ts = &s->temps[arg];
1800
        reg = tcg_target_call_oarg_regs[i];
1801
        assert(s->reg_to_temp[reg] == -1);
1802
        if (ts->fixed_reg) {
1803
            if (ts->reg != reg) {
1804
                tcg_out_mov(s, ts->reg, reg);
1805
            }
1806
        } else {
1807
            if (ts->val_type == TEMP_VAL_REG)
1808
                s->reg_to_temp[ts->reg] = -1;
1809
            ts->val_type = TEMP_VAL_REG;
1810
            ts->reg = reg;
1811
            ts->mem_coherent = 0; 
1812
            s->reg_to_temp[reg] = arg;
1813
        }
1814
    }
1815
    
1816
    return nb_iargs + nb_oargs + def->nb_cargs + 1;
1817
}
1818

    
1819
#ifdef CONFIG_PROFILER
1820

    
1821
static int64_t dyngen_table_op_count[NB_OPS];
1822

    
1823
void dump_op_count(void)
1824
{
1825
    int i;
1826
    FILE *f;
1827
    f = fopen("/tmp/op1.log", "w");
1828
    for(i = 0; i < INDEX_op_end; i++) {
1829
        fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name, dyngen_table_op_count[i]);
1830
    }
1831
    fclose(f);
1832
    f = fopen("/tmp/op2.log", "w");
1833
    for(i = INDEX_op_end; i < NB_OPS; i++) {
1834
        fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name, dyngen_table_op_count[i]);
1835
    }
1836
    fclose(f);
1837
}
1838
#endif
1839

    
1840

    
1841
static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
1842
                                      long search_pc)
1843
{
1844
    int opc, op_index;
1845
    const TCGOpDef *def;
1846
    unsigned int dead_iargs;
1847
    const TCGArg *args;
1848

    
1849
#ifdef DEBUG_DISAS
1850
    if (unlikely(loglevel & CPU_LOG_TB_OP)) {
1851
        fprintf(logfile, "OP:\n");
1852
        tcg_dump_ops(s, logfile);
1853
        fprintf(logfile, "\n");
1854
    }
1855
#endif
1856

    
1857
#ifdef CONFIG_PROFILER
1858
    s->la_time -= profile_getclock();
1859
#endif
1860
    tcg_liveness_analysis(s);
1861
#ifdef CONFIG_PROFILER
1862
    s->la_time += profile_getclock();
1863
#endif
1864

    
1865
#ifdef DEBUG_DISAS
1866
    if (unlikely(loglevel & CPU_LOG_TB_OP_OPT)) {
1867
        fprintf(logfile, "OP after la:\n");
1868
        tcg_dump_ops(s, logfile);
1869
        fprintf(logfile, "\n");
1870
    }
1871
#endif
1872

    
1873
    tcg_reg_alloc_start(s);
1874

    
1875
    s->code_buf = gen_code_buf;
1876
    s->code_ptr = gen_code_buf;
1877

    
1878
    args = gen_opparam_buf;
1879
    op_index = 0;
1880

    
1881
    for(;;) {
1882
        opc = gen_opc_buf[op_index];
1883
#ifdef CONFIG_PROFILER
1884
        dyngen_table_op_count[opc]++;
1885
#endif
1886
        def = &tcg_op_defs[opc];
1887
#if 0
1888
        printf("%s: %d %d %d\n", def->name,
1889
               def->nb_oargs, def->nb_iargs, def->nb_cargs);
1890
        //        dump_regs(s);
1891
#endif
1892
        switch(opc) {
1893
        case INDEX_op_mov_i32:
1894
#if TCG_TARGET_REG_BITS == 64
1895
        case INDEX_op_mov_i64:
1896
#endif
1897
            dead_iargs = s->op_dead_iargs[op_index];
1898
            tcg_reg_alloc_mov(s, def, args, dead_iargs);
1899
            break;
1900
        case INDEX_op_movi_i32:
1901
#if TCG_TARGET_REG_BITS == 64
1902
        case INDEX_op_movi_i64:
1903
#endif
1904
            tcg_reg_alloc_movi(s, args);
1905
            break;
1906
        case INDEX_op_debug_insn_start:
1907
            /* debug instruction */
1908
            break;
1909
        case INDEX_op_nop:
1910
        case INDEX_op_nop1:
1911
        case INDEX_op_nop2:
1912
        case INDEX_op_nop3:
1913
            break;
1914
        case INDEX_op_nopn:
1915
            args += args[0];
1916
            goto next;
1917
        case INDEX_op_discard:
1918
            {
1919
                TCGTemp *ts;
1920
                ts = &s->temps[args[0]];
1921
                /* mark the temporary as dead */
1922
                if (!ts->fixed_reg) {
1923
                    if (ts->val_type == TEMP_VAL_REG)
1924
                        s->reg_to_temp[ts->reg] = -1;
1925
                    ts->val_type = TEMP_VAL_DEAD;
1926
                }
1927
            }
1928
            break;
1929
        case INDEX_op_set_label:
1930
            tcg_reg_alloc_bb_end(s, s->reserved_regs);
1931
            tcg_out_label(s, args[0], (long)s->code_ptr);
1932
            break;
1933
        case INDEX_op_call:
1934
            dead_iargs = s->op_dead_iargs[op_index];
1935
            args += tcg_reg_alloc_call(s, def, opc, args, dead_iargs);
1936
            goto next;
1937
        case INDEX_op_end:
1938
            goto the_end;
1939

    
1940
#ifdef CONFIG_DYNGEN_OP
1941
        case 0 ... INDEX_op_end - 1:
1942
            /* legacy dyngen ops */
1943
#ifdef CONFIG_PROFILER
1944
            s->old_op_count++;
1945
#endif
1946
            tcg_reg_alloc_bb_end(s, s->reserved_regs);
1947
            if (search_pc >= 0) {
1948
                s->code_ptr += def->copy_size;
1949
                args += def->nb_args;
1950
            } else {
1951
                args = dyngen_op(s, opc, args);
1952
            }
1953
            goto next;
1954
#endif
1955
        default:
1956
            /* Note: in order to speed up the code, it would be much
1957
               faster to have specialized register allocator functions for
1958
               some common argument patterns */
1959
            dead_iargs = s->op_dead_iargs[op_index];
1960
            tcg_reg_alloc_op(s, def, opc, args, dead_iargs);
1961
            break;
1962
        }
1963
        args += def->nb_args;
1964
    next: ;
1965
        if (search_pc >= 0 && search_pc < s->code_ptr - gen_code_buf) {
1966
            return op_index;
1967
        }
1968
        op_index++;
1969
#ifndef NDEBUG
1970
        check_regs(s);
1971
#endif
1972
    }
1973
 the_end:
1974
    return -1;
1975
}
1976

    
1977
int dyngen_code(TCGContext *s, uint8_t *gen_code_buf)
1978
{
1979
#ifdef CONFIG_PROFILER
1980
    {
1981
        int n;
1982
        n = (gen_opc_ptr - gen_opc_buf);
1983
        s->op_count += n;
1984
        if (n > s->op_count_max)
1985
            s->op_count_max = n;
1986

    
1987
        s->temp_count += s->nb_temps;
1988
        if (s->nb_temps > s->temp_count_max)
1989
            s->temp_count_max = s->nb_temps;
1990
    }
1991
#endif
1992

    
1993
    tcg_gen_code_common(s, gen_code_buf, -1);
1994

    
1995
    /* flush instruction cache */
1996
    flush_icache_range((unsigned long)gen_code_buf, 
1997
                       (unsigned long)s->code_ptr);
1998
    return s->code_ptr -  gen_code_buf;
1999
}
2000

    
2001
/* Return the index of the micro operation such as the pc after is <
2002
   offset bytes from the start of the TB.  The contents of gen_code_buf must
2003
   not be changed, though writing the same values is ok.
2004
   Return -1 if not found. */
2005
int dyngen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, long offset)
2006
{
2007
    return tcg_gen_code_common(s, gen_code_buf, offset);
2008
}
2009

    
2010
#ifdef CONFIG_PROFILER
2011
void tcg_dump_info(FILE *f,
2012
                   int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
2013
{
2014
    TCGContext *s = &tcg_ctx;
2015
    int64_t tot;
2016

    
2017
    tot = s->interm_time + s->code_time;
2018
    cpu_fprintf(f, "JIT cycles          %" PRId64 " (%0.3f s at 2.4 GHz)\n",
2019
                tot, tot / 2.4e9);
2020
    cpu_fprintf(f, "translated TBs      %" PRId64 " (aborted=%" PRId64 " %0.1f%%)\n", 
2021
                s->tb_count, 
2022
                s->tb_count1 - s->tb_count,
2023
                s->tb_count1 ? (double)(s->tb_count1 - s->tb_count) / s->tb_count1 * 100.0 : 0);
2024
    cpu_fprintf(f, "avg ops/TB          %0.1f max=%d\n", 
2025
                s->tb_count ? (double)s->op_count / s->tb_count : 0, s->op_count_max);
2026
    cpu_fprintf(f, "old ops/total ops   %0.1f%%\n", 
2027
                s->op_count ? (double)s->old_op_count / s->op_count * 100.0 : 0);
2028
    cpu_fprintf(f, "deleted ops/TB      %0.2f\n",
2029
                s->tb_count ? 
2030
                (double)s->del_op_count / s->tb_count : 0);
2031
    cpu_fprintf(f, "avg temps/TB        %0.2f max=%d\n",
2032
                s->tb_count ? 
2033
                (double)s->temp_count / s->tb_count : 0,
2034
                s->temp_count_max);
2035
    
2036
    cpu_fprintf(f, "cycles/op           %0.1f\n", 
2037
                s->op_count ? (double)tot / s->op_count : 0);
2038
    cpu_fprintf(f, "cycles/in byte      %0.1f\n", 
2039
                s->code_in_len ? (double)tot / s->code_in_len : 0);
2040
    cpu_fprintf(f, "cycles/out byte     %0.1f\n", 
2041
                s->code_out_len ? (double)tot / s->code_out_len : 0);
2042
    if (tot == 0)
2043
        tot = 1;
2044
    cpu_fprintf(f, "  gen_interm time   %0.1f%%\n", 
2045
                (double)s->interm_time / tot * 100.0);
2046
    cpu_fprintf(f, "  gen_code time     %0.1f%%\n", 
2047
                (double)s->code_time / tot * 100.0);
2048
    cpu_fprintf(f, "liveness/code time  %0.1f%%\n", 
2049
                (double)s->la_time / (s->code_time ? s->code_time : 1) * 100.0);
2050
    cpu_fprintf(f, "cpu_restore count   %" PRId64 "\n",
2051
                s->restore_count);
2052
    cpu_fprintf(f, "  avg cycles        %0.1f\n",
2053
                s->restore_count ? (double)s->restore_time / s->restore_count : 0);
2054
    {
2055
        extern void dump_op_count(void);
2056
        dump_op_count();
2057
    }
2058
}
2059
#else
2060
void tcg_dump_info(FILE *f,
2061
                   int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
2062
{
2063
    cpu_fprintf(f, "[TCG profiler not compiled]\n");
2064
}
2065
#endif