Statistics
| Branch: | Revision:

root / tcg / tcg.c @ f48f3ede

History | View | Annotate | Download (62.4 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
void tcg_context_init(TCGContext *s)
200
{
201
    int op, total_args, n;
202
    TCGOpDef *def;
203
    TCGArgConstraint *args_ct;
204
    int *sorted_args;
205

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

    
219
    args_ct = qemu_malloc(sizeof(TCGArgConstraint) * total_args);
220
    sorted_args = qemu_malloc(sizeof(int) * total_args);
221

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

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

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

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

    
260
    gen_opc_ptr = gen_opc_buf;
261
    gen_opparam_ptr = gen_opparam_buf;
262
}
263

    
264
static inline void tcg_temp_alloc(TCGContext *s, int n)
265
{
266
    if (n > TCG_MAX_TEMPS)
267
        tcg_abort();
268
}
269

    
270
TCGv tcg_global_reg_new(TCGType type, int reg, const char *name)
271
{
272
    TCGContext *s = &tcg_ctx;
273
    TCGTemp *ts;
274
    int idx;
275

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

    
295
#if TCG_TARGET_REG_BITS == 32
296
/* temporary hack to avoid register shortage for tcg_qemu_st64() */
297
TCGv tcg_global_reg2_new_hack(TCGType type, int reg1, int reg2, 
298
                              const char *name)
299
{
300
    TCGContext *s = &tcg_ctx;
301
    TCGTemp *ts;
302
    int idx;
303
    char buf[64];
304

    
305
    if (type != TCG_TYPE_I64)
306
        tcg_abort();
307
    idx = s->nb_globals;
308
    tcg_temp_alloc(s, s->nb_globals + 2);
309
    ts = &s->temps[s->nb_globals];
310
    ts->base_type = type;
311
    ts->type = TCG_TYPE_I32;
312
    ts->fixed_reg = 1;
313
    ts->reg = reg1;
314
    pstrcpy(buf, sizeof(buf), name);
315
    pstrcat(buf, sizeof(buf), "_0");
316
    ts->name = strdup(buf);
317

    
318
    ts++;
319
    ts->base_type = type;
320
    ts->type = TCG_TYPE_I32;
321
    ts->fixed_reg = 1;
322
    ts->reg = reg2;
323
    pstrcpy(buf, sizeof(buf), name);
324
    pstrcat(buf, sizeof(buf), "_1");
325
    ts->name = strdup(buf);
326

    
327
    s->nb_globals += 2;
328
    return MAKE_TCGV(idx);
329
}
330
#endif
331

    
332
TCGv tcg_global_mem_new(TCGType type, int reg, tcg_target_long offset,
333
                        const char *name)
334
{
335
    TCGContext *s = &tcg_ctx;
336
    TCGTemp *ts;
337
    int idx;
338

    
339
    idx = s->nb_globals;
340
#if TCG_TARGET_REG_BITS == 32
341
    if (type == TCG_TYPE_I64) {
342
        char buf[64];
343
        tcg_temp_alloc(s, s->nb_globals + 2);
344
        ts = &s->temps[s->nb_globals];
345
        ts->base_type = type;
346
        ts->type = TCG_TYPE_I32;
347
        ts->fixed_reg = 0;
348
        ts->mem_allocated = 1;
349
        ts->mem_reg = reg;
350
#ifdef TCG_TARGET_WORDS_BIGENDIAN
351
        ts->mem_offset = offset + 4;
352
#else
353
        ts->mem_offset = offset;
354
#endif
355
        pstrcpy(buf, sizeof(buf), name);
356
        pstrcat(buf, sizeof(buf), "_0");
357
        ts->name = strdup(buf);
358
        ts++;
359

    
360
        ts->base_type = type;
361
        ts->type = TCG_TYPE_I32;
362
        ts->fixed_reg = 0;
363
        ts->mem_allocated = 1;
364
        ts->mem_reg = reg;
365
#ifdef TCG_TARGET_WORDS_BIGENDIAN
366
        ts->mem_offset = offset;
367
#else
368
        ts->mem_offset = offset + 4;
369
#endif
370
        pstrcpy(buf, sizeof(buf), name);
371
        pstrcat(buf, sizeof(buf), "_1");
372
        ts->name = strdup(buf);
373

    
374
        s->nb_globals += 2;
375
    } else
376
#endif
377
    {
378
        tcg_temp_alloc(s, s->nb_globals + 1);
379
        ts = &s->temps[s->nb_globals];
380
        ts->base_type = type;
381
        ts->type = type;
382
        ts->fixed_reg = 0;
383
        ts->mem_allocated = 1;
384
        ts->mem_reg = reg;
385
        ts->mem_offset = offset;
386
        ts->name = name;
387
        s->nb_globals++;
388
    }
389
    return MAKE_TCGV(idx);
390
}
391

    
392
TCGv tcg_temp_new_internal(TCGType type, int temp_local)
393
{
394
    TCGContext *s = &tcg_ctx;
395
    TCGTemp *ts;
396
    int idx, k;
397

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

    
443
void tcg_temp_free(TCGv arg)
444
{
445
    TCGContext *s = &tcg_ctx;
446
    TCGTemp *ts;
447
    int idx = GET_TCGV(arg);
448
    int k;
449

    
450
    assert(idx >= s->nb_globals && idx < s->nb_temps);
451
    ts = &s->temps[idx];
452
    assert(ts->temp_allocated != 0);
453
    ts->temp_allocated = 0;
454
    k = ts->base_type;
455
    if (ts->temp_local)
456
        k += TCG_TYPE_COUNT;
457
    ts->next_free_temp = s->first_free_temp[k];
458
    s->first_free_temp[k] = idx;
459
}
460

    
461

    
462
TCGv tcg_const_i32(int32_t val)
463
{
464
    TCGv t0;
465
    t0 = tcg_temp_new(TCG_TYPE_I32);
466
    tcg_gen_movi_i32(t0, val);
467
    return t0;
468
}
469

    
470
TCGv tcg_const_i64(int64_t val)
471
{
472
    TCGv t0;
473
    t0 = tcg_temp_new(TCG_TYPE_I64);
474
    tcg_gen_movi_i64(t0, val);
475
    return t0;
476
}
477

    
478
void tcg_register_helper(void *func, const char *name)
479
{
480
    TCGContext *s = &tcg_ctx;
481
    int n;
482
    if ((s->nb_helpers + 1) > s->allocated_helpers) {
483
        n = s->allocated_helpers;
484
        if (n == 0) {
485
            n = 4;
486
        } else {
487
            n *= 2;
488
        }
489
        s->helpers = realloc(s->helpers, n * sizeof(TCGHelperInfo));
490
        s->allocated_helpers = n;
491
    }
492
    s->helpers[s->nb_helpers].func = (tcg_target_ulong)func;
493
    s->helpers[s->nb_helpers].name = name;
494
    s->nb_helpers++;
495
}
496

    
497
static inline TCGType tcg_get_base_type(TCGContext *s, TCGv arg)
498
{
499
    return s->temps[GET_TCGV(arg)].base_type;
500
}
501

    
502
static void tcg_gen_call_internal(TCGContext *s, TCGv func, 
503
                                  unsigned int flags,
504
                                  unsigned int nb_rets, const TCGv *rets,
505
                                  unsigned int nb_params, const TCGv *params)
506
{
507
    int i;
508
    *gen_opc_ptr++ = INDEX_op_call;
509
    *gen_opparam_ptr++ = (nb_rets << 16) | (nb_params + 1);
510
    for(i = 0; i < nb_rets; i++) {
511
        *gen_opparam_ptr++ = GET_TCGV(rets[i]);
512
    }
513
    for(i = 0; i < nb_params; i++) {
514
        *gen_opparam_ptr++ = GET_TCGV(params[i]);
515
    }
516
    *gen_opparam_ptr++ = GET_TCGV(func);
517

    
518
    *gen_opparam_ptr++ = flags;
519
    /* total parameters, needed to go backward in the instruction stream */
520
    *gen_opparam_ptr++ = 1 + nb_rets + nb_params + 3;
521
}
522

    
523

    
524
#if TCG_TARGET_REG_BITS < 64
525
/* Note: we convert the 64 bit args to 32 bit and do some alignment
526
   and endian swap. Maybe it would be better to do the alignment
527
   and endian swap in tcg_reg_alloc_call(). */
528
void tcg_gen_call(TCGContext *s, TCGv func, unsigned int flags,
529
                  unsigned int nb_rets, const TCGv *rets,
530
                  unsigned int nb_params, const TCGv *args1)
531
{
532
    TCGv ret, *args2, rets_2[2], arg;
533
    int j, i, call_type;
534

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

    
596
#if TCG_TARGET_REG_BITS == 32
597
void tcg_gen_shifti_i64(TCGv ret, TCGv arg1, 
598
                        int c, int right, int arith)
599
{
600
    if (c == 0) {
601
        tcg_gen_mov_i32(ret, arg1);
602
        tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
603
    } else if (c >= 32) {
604
        c -= 32;
605
        if (right) {
606
            if (arith) {
607
                tcg_gen_sari_i32(ret, TCGV_HIGH(arg1), c);
608
                tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 31);
609
            } else {
610
                tcg_gen_shri_i32(ret, TCGV_HIGH(arg1), c);
611
                tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
612
            }
613
        } else {
614
            tcg_gen_shli_i32(TCGV_HIGH(ret), arg1, c);
615
            tcg_gen_movi_i32(ret, 0);
616
        }
617
    } else {
618
        TCGv t0, t1;
619

    
620
        t0 = tcg_temp_new(TCG_TYPE_I32);
621
        t1 = tcg_temp_new(TCG_TYPE_I32);
622
        if (right) {
623
            tcg_gen_shli_i32(t0, TCGV_HIGH(arg1), 32 - c);
624
            if (arith)
625
                tcg_gen_sari_i32(t1, TCGV_HIGH(arg1), c);
626
            else 
627
                tcg_gen_shri_i32(t1, TCGV_HIGH(arg1), c);
628
            tcg_gen_shri_i32(ret, arg1, c); 
629
            tcg_gen_or_i32(ret, ret, t0);
630
            tcg_gen_mov_i32(TCGV_HIGH(ret), t1);
631
        } else {
632
            tcg_gen_shri_i32(t0, arg1, 32 - c);
633
            /* Note: ret can be the same as arg1, so we use t1 */
634
            tcg_gen_shli_i32(t1, arg1, c); 
635
            tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c);
636
            tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t0);
637
            tcg_gen_mov_i32(ret, t1);
638
        }
639
        tcg_temp_free(t0);
640
        tcg_temp_free(t1);
641
    }
642
}
643
#endif
644

    
645
static void tcg_reg_alloc_start(TCGContext *s)
646
{
647
    int i;
648
    TCGTemp *ts;
649
    for(i = 0; i < s->nb_globals; i++) {
650
        ts = &s->temps[i];
651
        if (ts->fixed_reg) {
652
            ts->val_type = TEMP_VAL_REG;
653
        } else {
654
            ts->val_type = TEMP_VAL_MEM;
655
        }
656
    }
657
    for(i = s->nb_globals; i < s->nb_temps; i++) {
658
        ts = &s->temps[i];
659
        ts->val_type = TEMP_VAL_DEAD;
660
        ts->mem_allocated = 0;
661
        ts->fixed_reg = 0;
662
    }
663
    for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
664
        s->reg_to_temp[i] = -1;
665
    }
666
}
667

    
668
static char *tcg_get_arg_str_idx(TCGContext *s, char *buf, int buf_size,
669
                                 int idx)
670
{
671
    TCGTemp *ts;
672

    
673
    ts = &s->temps[idx];
674
    if (idx < s->nb_globals) {
675
        pstrcpy(buf, buf_size, ts->name);
676
    } else {
677
        if (ts->temp_local) 
678
            snprintf(buf, buf_size, "loc%d", idx - s->nb_globals);
679
        else
680
            snprintf(buf, buf_size, "tmp%d", idx - s->nb_globals);
681
    }
682
    return buf;
683
}
684

    
685
char *tcg_get_arg_str(TCGContext *s, char *buf, int buf_size, TCGv arg)
686
{
687
    return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV(arg));
688
}
689

    
690
static int helper_cmp(const void *p1, const void *p2)
691
{
692
    const TCGHelperInfo *th1 = p1;
693
    const TCGHelperInfo *th2 = p2;
694
    if (th1->func < th2->func)
695
        return -1;
696
    else if (th1->func == th2->func)
697
        return 0;
698
    else
699
        return 1;
700
}
701

    
702
/* find helper definition (Note: A hash table would be better) */
703
static TCGHelperInfo *tcg_find_helper(TCGContext *s, tcg_target_ulong val)
704
{
705
    int m, m_min, m_max;
706
    TCGHelperInfo *th;
707
    tcg_target_ulong v;
708

    
709
    if (unlikely(!s->helpers_sorted)) {
710
        qsort(s->helpers, s->nb_helpers, sizeof(TCGHelperInfo), 
711
              helper_cmp);
712
        s->helpers_sorted = 1;
713
    }
714

    
715
    /* binary search */
716
    m_min = 0;
717
    m_max = s->nb_helpers - 1;
718
    while (m_min <= m_max) {
719
        m = (m_min + m_max) >> 1;
720
        th = &s->helpers[m];
721
        v = th->func;
722
        if (v == val)
723
            return th;
724
        else if (val < v) {
725
            m_max = m - 1;
726
        } else {
727
            m_min = m + 1;
728
        }
729
    }
730
    return NULL;
731
}
732

    
733
static const char * const cond_name[] =
734
{
735
    [TCG_COND_EQ] = "eq",
736
    [TCG_COND_NE] = "ne",
737
    [TCG_COND_LT] = "lt",
738
    [TCG_COND_GE] = "ge",
739
    [TCG_COND_LE] = "le",
740
    [TCG_COND_GT] = "gt",
741
    [TCG_COND_LTU] = "ltu",
742
    [TCG_COND_GEU] = "geu",
743
    [TCG_COND_LEU] = "leu",
744
    [TCG_COND_GTU] = "gtu"
745
};
746

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

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

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

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

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

    
817
            nb_oargs = def->nb_oargs;
818
            nb_iargs = def->nb_iargs;
819
            nb_cargs = def->nb_cargs;
820
            fprintf(outfile, " %s %s,$", def->name, 
821
                    tcg_get_arg_str_idx(s, buf, sizeof(buf), args[0]));
822
            val = args[1];
823
            th = tcg_find_helper(s, val);
824
            if (th) {
825
                fprintf(outfile, th->name);
826
            } else {
827
                if (c == INDEX_op_movi_i32)
828
                    fprintf(outfile, "0x%x", (uint32_t)val);
829
                else
830
                    fprintf(outfile, "0x%" PRIx64 , (uint64_t)val);
831
            }
832
        } else {
833
            fprintf(outfile, " %s ", def->name);
834
            if (c == INDEX_op_nopn) {
835
                /* variable number of arguments */
836
                nb_cargs = *args;
837
                nb_oargs = 0;
838
                nb_iargs = 0;
839
            } else {
840
                nb_oargs = def->nb_oargs;
841
                nb_iargs = def->nb_iargs;
842
                nb_cargs = def->nb_cargs;
843
            }
844
            
845
            k = 0;
846
            for(i = 0; i < nb_oargs; i++) {
847
                if (k != 0)
848
                    fprintf(outfile, ",");
849
                fprintf(outfile, "%s",
850
                        tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
851
            }
852
            for(i = 0; i < nb_iargs; i++) {
853
                if (k != 0)
854
                    fprintf(outfile, ",");
855
                fprintf(outfile, "%s",
856
                        tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
857
            }
858
            if (c == INDEX_op_brcond_i32
859
#if TCG_TARGET_REG_BITS == 32
860
                || c == INDEX_op_brcond2_i32
861
#elif TCG_TARGET_REG_BITS == 64
862
                || c == INDEX_op_brcond_i64
863
#endif
864
                ) {
865
                if (args[k] < ARRAY_SIZE(cond_name) && cond_name[args[k]])
866
                    fprintf(outfile, ",%s", cond_name[args[k++]]);
867
                else
868
                    fprintf(outfile, ",$0x%" TCG_PRIlx, args[k++]);
869
                i = 1;
870
            }
871
            else
872
                i = 0;
873
            for(; i < nb_cargs; i++) {
874
                if (k != 0)
875
                    fprintf(outfile, ",");
876
                arg = args[k++];
877
                fprintf(outfile, "$0x%" TCG_PRIlx, arg);
878
            }
879
        }
880
        fprintf(outfile, "\n");
881
        args += nb_iargs + nb_oargs + nb_cargs;
882
    }
883
}
884

    
885
/* we give more priority to constraints with less registers */
886
static int get_constraint_priority(const TCGOpDef *def, int k)
887
{
888
    const TCGArgConstraint *arg_ct;
889

    
890
    int i, n;
891
    arg_ct = &def->args_ct[k];
892
    if (arg_ct->ct & TCG_CT_ALIAS) {
893
        /* an alias is equivalent to a single register */
894
        n = 1;
895
    } else {
896
        if (!(arg_ct->ct & TCG_CT_REG))
897
            return 0;
898
        n = 0;
899
        for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
900
            if (tcg_regset_test_reg(arg_ct->u.regs, i))
901
                n++;
902
        }
903
    }
904
    return TCG_TARGET_NB_REGS - n + 1;
905
}
906

    
907
/* sort from highest priority to lowest */
908
static void sort_constraints(TCGOpDef *def, int start, int n)
909
{
910
    int i, j, p1, p2, tmp;
911

    
912
    for(i = 0; i < n; i++)
913
        def->sorted_args[start + i] = start + i;
914
    if (n <= 1)
915
        return;
916
    for(i = 0; i < n - 1; i++) {
917
        for(j = i + 1; j < n; j++) {
918
            p1 = get_constraint_priority(def, def->sorted_args[start + i]);
919
            p2 = get_constraint_priority(def, def->sorted_args[start + j]);
920
            if (p1 < p2) {
921
                tmp = def->sorted_args[start + i];
922
                def->sorted_args[start + i] = def->sorted_args[start + j];
923
                def->sorted_args[start + j] = tmp;
924
            }
925
        }
926
    }
927
}
928

    
929
void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs)
930
{
931
    int op;
932
    TCGOpDef *def;
933
    const char *ct_str;
934
    int i, nb_args;
935

    
936
    for(;;) {
937
        if (tdefs->op < 0)
938
            break;
939
        op = tdefs->op;
940
        assert(op >= 0 && op < NB_OPS);
941
        def = &tcg_op_defs[op];
942
        nb_args = def->nb_iargs + def->nb_oargs;
943
        for(i = 0; i < nb_args; i++) {
944
            ct_str = tdefs->args_ct_str[i];
945
            tcg_regset_clear(def->args_ct[i].u.regs);
946
            def->args_ct[i].ct = 0;
947
            if (ct_str[0] >= '0' && ct_str[0] <= '9') {
948
                int oarg;
949
                oarg = ct_str[0] - '0';
950
                assert(oarg < def->nb_oargs);
951
                assert(def->args_ct[oarg].ct & TCG_CT_REG);
952
                /* TCG_CT_ALIAS is for the output arguments. The input
953
                   argument is tagged with TCG_CT_IALIAS. */
954
                def->args_ct[i] = def->args_ct[oarg];
955
                def->args_ct[oarg].ct = TCG_CT_ALIAS;
956
                def->args_ct[oarg].alias_index = i;
957
                def->args_ct[i].ct |= TCG_CT_IALIAS;
958
                def->args_ct[i].alias_index = oarg;
959
            } else {
960
                for(;;) {
961
                    if (*ct_str == '\0')
962
                        break;
963
                    switch(*ct_str) {
964
                    case 'i':
965
                        def->args_ct[i].ct |= TCG_CT_CONST;
966
                        ct_str++;
967
                        break;
968
                    default:
969
                        if (target_parse_constraint(&def->args_ct[i], &ct_str) < 0) {
970
                            fprintf(stderr, "Invalid constraint '%s' for arg %d of operation '%s'\n",
971
                                    ct_str, i, def->name);
972
                            exit(1);
973
                        }
974
                    }
975
                }
976
            }
977
        }
978

    
979
        /* sort the constraints (XXX: this is just an heuristic) */
980
        sort_constraints(def, 0, def->nb_oargs);
981
        sort_constraints(def, def->nb_oargs, def->nb_iargs);
982

    
983
#if 0
984
        {
985
            int i;
986

987
            printf("%s: sorted=", def->name);
988
            for(i = 0; i < def->nb_oargs + def->nb_iargs; i++)
989
                printf(" %d", def->sorted_args[i]);
990
            printf("\n");
991
        }
992
#endif
993
        tdefs++;
994
    }
995

    
996
}
997

    
998
#ifdef USE_LIVENESS_ANALYSIS
999

    
1000
/* set a nop for an operation using 'nb_args' */
1001
static inline void tcg_set_nop(TCGContext *s, uint16_t *opc_ptr, 
1002
                               TCGArg *args, int nb_args)
1003
{
1004
    if (nb_args == 0) {
1005
        *opc_ptr = INDEX_op_nop;
1006
    } else {
1007
        *opc_ptr = INDEX_op_nopn;
1008
        args[0] = nb_args;
1009
        args[nb_args - 1] = nb_args;
1010
    }
1011
}
1012

    
1013
/* liveness analysis: end of function: globals are live, temps are
1014
   dead. */
1015
/* XXX: at this stage, not used as there would be little gains because
1016
   most TBs end with a conditional jump. */
1017
static inline void tcg_la_func_end(TCGContext *s, uint8_t *dead_temps)
1018
{
1019
    memset(dead_temps, 0, s->nb_globals);
1020
    memset(dead_temps + s->nb_globals, 1, s->nb_temps - s->nb_globals);
1021
}
1022

    
1023
/* liveness analysis: end of basic block: globals are live, temps are
1024
   dead, local temps are live. */
1025
static inline void tcg_la_bb_end(TCGContext *s, uint8_t *dead_temps)
1026
{
1027
    int i;
1028
    TCGTemp *ts;
1029

    
1030
    memset(dead_temps, 0, s->nb_globals);
1031
    ts = &s->temps[s->nb_globals];
1032
    for(i = s->nb_globals; i < s->nb_temps; i++) {
1033
        if (ts->temp_local)
1034
            dead_temps[i] = 0;
1035
        else
1036
            dead_temps[i] = 1;
1037
        ts++;
1038
    }
1039
}
1040

    
1041
/* Liveness analysis : update the opc_dead_iargs array to tell if a
1042
   given input arguments is dead. Instructions updating dead
1043
   temporaries are removed. */
1044
static void tcg_liveness_analysis(TCGContext *s)
1045
{
1046
    int i, op_index, op, nb_args, nb_iargs, nb_oargs, arg, nb_ops;
1047
    TCGArg *args;
1048
    const TCGOpDef *def;
1049
    uint8_t *dead_temps;
1050
    unsigned int dead_iargs;
1051
    
1052
    gen_opc_ptr++; /* skip end */
1053

    
1054
    nb_ops = gen_opc_ptr - gen_opc_buf;
1055

    
1056
    /* XXX: make it really dynamic */
1057
    s->op_dead_iargs = tcg_malloc(OPC_BUF_SIZE * sizeof(uint16_t));
1058
    
1059
    dead_temps = tcg_malloc(s->nb_temps);
1060
    memset(dead_temps, 1, s->nb_temps);
1061

    
1062
    args = gen_opparam_ptr;
1063
    op_index = nb_ops - 1;
1064
    while (op_index >= 0) {
1065
        op = gen_opc_buf[op_index];
1066
        def = &tcg_op_defs[op];
1067
        switch(op) {
1068
        case INDEX_op_call:
1069
            {
1070
                int call_flags;
1071

    
1072
                nb_args = args[-1];
1073
                args -= nb_args;
1074
                nb_iargs = args[0] & 0xffff;
1075
                nb_oargs = args[0] >> 16;
1076
                args++;
1077
                call_flags = args[nb_oargs + nb_iargs];
1078

    
1079
                /* pure functions can be removed if their result is not
1080
                   used */
1081
                if (call_flags & TCG_CALL_PURE) {
1082
                    for(i = 0; i < nb_oargs; i++) {
1083
                        arg = args[i];
1084
                        if (!dead_temps[arg])
1085
                            goto do_not_remove_call;
1086
                    }
1087
                    tcg_set_nop(s, gen_opc_buf + op_index, 
1088
                                args - 1, nb_args);
1089
                } else {
1090
                do_not_remove_call:
1091

    
1092
                    /* output args are dead */
1093
                    for(i = 0; i < nb_oargs; i++) {
1094
                        arg = args[i];
1095
                        dead_temps[arg] = 1;
1096
                    }
1097
                    
1098
                    /* globals are live (they may be used by the call) */
1099
                    memset(dead_temps, 0, s->nb_globals);
1100
                    
1101
                    /* input args are live */
1102
                    dead_iargs = 0;
1103
                    for(i = 0; i < nb_iargs; i++) {
1104
                        arg = args[i + nb_oargs];
1105
                        if (arg != TCG_CALL_DUMMY_ARG) {
1106
                            if (dead_temps[arg]) {
1107
                                dead_iargs |= (1 << i);
1108
                            }
1109
                            dead_temps[arg] = 0;
1110
                        }
1111
                    }
1112
                    s->op_dead_iargs[op_index] = dead_iargs;
1113
                }
1114
                args--;
1115
            }
1116
            break;
1117
        case INDEX_op_set_label:
1118
            args--;
1119
            /* mark end of basic block */
1120
            tcg_la_bb_end(s, dead_temps);
1121
            break;
1122
        case INDEX_op_debug_insn_start:
1123
            args -= def->nb_args;
1124
            break;
1125
        case INDEX_op_nopn:
1126
            nb_args = args[-1];
1127
            args -= nb_args;
1128
            break;
1129
        case INDEX_op_discard:
1130
            args--;
1131
            /* mark the temporary as dead */
1132
            dead_temps[args[0]] = 1;
1133
            break;
1134
        case INDEX_op_end:
1135
            break;
1136
            /* XXX: optimize by hardcoding common cases (e.g. triadic ops) */
1137
        default:
1138
            if (op > INDEX_op_end) {
1139
                args -= def->nb_args;
1140
                nb_iargs = def->nb_iargs;
1141
                nb_oargs = def->nb_oargs;
1142

    
1143
                /* Test if the operation can be removed because all
1144
                   its outputs are dead. We assume that nb_oargs == 0
1145
                   implies side effects */
1146
                if (!(def->flags & TCG_OPF_SIDE_EFFECTS) && nb_oargs != 0) {
1147
                    for(i = 0; i < nb_oargs; i++) {
1148
                        arg = args[i];
1149
                        if (!dead_temps[arg])
1150
                            goto do_not_remove;
1151
                    }
1152
                    tcg_set_nop(s, gen_opc_buf + op_index, args, def->nb_args);
1153
#ifdef CONFIG_PROFILER
1154
                    s->del_op_count++;
1155
#endif
1156
                } else {
1157
                do_not_remove:
1158

    
1159
                    /* output args are dead */
1160
                    for(i = 0; i < nb_oargs; i++) {
1161
                        arg = args[i];
1162
                        dead_temps[arg] = 1;
1163
                    }
1164
                    
1165
                    /* if end of basic block, update */
1166
                    if (def->flags & TCG_OPF_BB_END) {
1167
                        tcg_la_bb_end(s, dead_temps);
1168
                    } else if (def->flags & TCG_OPF_CALL_CLOBBER) {
1169
                        /* globals are live */
1170
                        memset(dead_temps, 0, s->nb_globals);
1171
                    }
1172
                    
1173
                    /* input args are live */
1174
                    dead_iargs = 0;
1175
                    for(i = 0; i < nb_iargs; i++) {
1176
                        arg = args[i + nb_oargs];
1177
                        if (dead_temps[arg]) {
1178
                            dead_iargs |= (1 << i);
1179
                        }
1180
                        dead_temps[arg] = 0;
1181
                    }
1182
                    s->op_dead_iargs[op_index] = dead_iargs;
1183
                }
1184
            } else {
1185
                /* legacy dyngen operations */
1186
                args -= def->nb_args;
1187
                /* mark end of basic block */
1188
                tcg_la_bb_end(s, dead_temps);
1189
            }
1190
            break;
1191
        }
1192
        op_index--;
1193
    }
1194

    
1195
    if (args != gen_opparam_buf)
1196
        tcg_abort();
1197
}
1198
#else
1199
/* dummy liveness analysis */
1200
void tcg_liveness_analysis(TCGContext *s)
1201
{
1202
    int nb_ops;
1203
    nb_ops = gen_opc_ptr - gen_opc_buf;
1204

    
1205
    s->op_dead_iargs = tcg_malloc(nb_ops * sizeof(uint16_t));
1206
    memset(s->op_dead_iargs, 0, nb_ops * sizeof(uint16_t));
1207
}
1208
#endif
1209

    
1210
#ifndef NDEBUG
1211
static void dump_regs(TCGContext *s)
1212
{
1213
    TCGTemp *ts;
1214
    int i;
1215
    char buf[64];
1216

    
1217
    for(i = 0; i < s->nb_temps; i++) {
1218
        ts = &s->temps[i];
1219
        printf("  %10s: ", tcg_get_arg_str_idx(s, buf, sizeof(buf), i));
1220
        switch(ts->val_type) {
1221
        case TEMP_VAL_REG:
1222
            printf("%s", tcg_target_reg_names[ts->reg]);
1223
            break;
1224
        case TEMP_VAL_MEM:
1225
            printf("%d(%s)", (int)ts->mem_offset, tcg_target_reg_names[ts->mem_reg]);
1226
            break;
1227
        case TEMP_VAL_CONST:
1228
            printf("$0x%" TCG_PRIlx, ts->val);
1229
            break;
1230
        case TEMP_VAL_DEAD:
1231
            printf("D");
1232
            break;
1233
        default:
1234
            printf("???");
1235
            break;
1236
        }
1237
        printf("\n");
1238
    }
1239

    
1240
    for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
1241
        if (s->reg_to_temp[i] >= 0) {
1242
            printf("%s: %s\n", 
1243
                   tcg_target_reg_names[i], 
1244
                   tcg_get_arg_str_idx(s, buf, sizeof(buf), s->reg_to_temp[i]));
1245
        }
1246
    }
1247
}
1248

    
1249
static void check_regs(TCGContext *s)
1250
{
1251
    int reg, k;
1252
    TCGTemp *ts;
1253
    char buf[64];
1254

    
1255
    for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1256
        k = s->reg_to_temp[reg];
1257
        if (k >= 0) {
1258
            ts = &s->temps[k];
1259
            if (ts->val_type != TEMP_VAL_REG ||
1260
                ts->reg != reg) {
1261
                printf("Inconsistency for register %s:\n", 
1262
                       tcg_target_reg_names[reg]);
1263
                goto fail;
1264
            }
1265
        }
1266
    }
1267
    for(k = 0; k < s->nb_temps; k++) {
1268
        ts = &s->temps[k];
1269
        if (ts->val_type == TEMP_VAL_REG &&
1270
            !ts->fixed_reg &&
1271
            s->reg_to_temp[ts->reg] != k) {
1272
                printf("Inconsistency for temp %s:\n", 
1273
                       tcg_get_arg_str_idx(s, buf, sizeof(buf), k));
1274
        fail:
1275
                printf("reg state:\n");
1276
                dump_regs(s);
1277
                tcg_abort();
1278
        }
1279
    }
1280
}
1281
#endif
1282

    
1283
static void temp_allocate_frame(TCGContext *s, int temp)
1284
{
1285
    TCGTemp *ts;
1286
    ts = &s->temps[temp];
1287
    s->current_frame_offset = (s->current_frame_offset + sizeof(tcg_target_long) - 1) & ~(sizeof(tcg_target_long) - 1);
1288
    if (s->current_frame_offset + sizeof(tcg_target_long) > s->frame_end)
1289
        tcg_abort();
1290
    ts->mem_offset = s->current_frame_offset;
1291
    ts->mem_reg = s->frame_reg;
1292
    ts->mem_allocated = 1;
1293
    s->current_frame_offset += sizeof(tcg_target_long);
1294
}
1295

    
1296
/* free register 'reg' by spilling the corresponding temporary if necessary */
1297
static void tcg_reg_free(TCGContext *s, int reg)
1298
{
1299
    TCGTemp *ts;
1300
    int temp;
1301

    
1302
    temp = s->reg_to_temp[reg];
1303
    if (temp != -1) {
1304
        ts = &s->temps[temp];
1305
        assert(ts->val_type == TEMP_VAL_REG);
1306
        if (!ts->mem_coherent) {
1307
            if (!ts->mem_allocated) 
1308
                temp_allocate_frame(s, temp);
1309
            tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1310
        }
1311
        ts->val_type = TEMP_VAL_MEM;
1312
        s->reg_to_temp[reg] = -1;
1313
    }
1314
}
1315

    
1316
/* Allocate a register belonging to reg1 & ~reg2 */
1317
static int tcg_reg_alloc(TCGContext *s, TCGRegSet reg1, TCGRegSet reg2)
1318
{
1319
    int i, reg;
1320
    TCGRegSet reg_ct;
1321

    
1322
    tcg_regset_andnot(reg_ct, reg1, reg2);
1323

    
1324
    /* first try free registers */
1325
    for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1326
        reg = tcg_target_reg_alloc_order[i];
1327
        if (tcg_regset_test_reg(reg_ct, reg) && s->reg_to_temp[reg] == -1)
1328
            return reg;
1329
    }
1330

    
1331
    /* XXX: do better spill choice */
1332
    for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1333
        reg = tcg_target_reg_alloc_order[i];
1334
        if (tcg_regset_test_reg(reg_ct, reg)) {
1335
            tcg_reg_free(s, reg);
1336
            return reg;
1337
        }
1338
    }
1339

    
1340
    tcg_abort();
1341
}
1342

    
1343
/* save a temporary to memory. 'allocated_regs' is used in case a
1344
   temporary registers needs to be allocated to store a constant. */
1345
static void temp_save(TCGContext *s, int temp, TCGRegSet allocated_regs)
1346
{
1347
    TCGTemp *ts;
1348
    int reg;
1349

    
1350
    ts = &s->temps[temp];
1351
    if (!ts->fixed_reg) {
1352
        switch(ts->val_type) {
1353
        case TEMP_VAL_REG:
1354
            tcg_reg_free(s, ts->reg);
1355
            break;
1356
        case TEMP_VAL_DEAD:
1357
            ts->val_type = TEMP_VAL_MEM;
1358
            break;
1359
        case TEMP_VAL_CONST:
1360
            reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], 
1361
                                allocated_regs);
1362
            if (!ts->mem_allocated) 
1363
                temp_allocate_frame(s, temp);
1364
            tcg_out_movi(s, ts->type, reg, ts->val);
1365
            tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1366
            ts->val_type = TEMP_VAL_MEM;
1367
            break;
1368
        case TEMP_VAL_MEM:
1369
            break;
1370
        default:
1371
            tcg_abort();
1372
        }
1373
    }
1374
}
1375

    
1376
/* save globals to their cannonical location and assume they can be
1377
   modified be the following code. 'allocated_regs' is used in case a
1378
   temporary registers needs to be allocated to store a constant. */
1379
static void save_globals(TCGContext *s, TCGRegSet allocated_regs)
1380
{
1381
    int i;
1382

    
1383
    for(i = 0; i < s->nb_globals; i++) {
1384
        temp_save(s, i, allocated_regs);
1385
    }
1386
}
1387

    
1388
/* at the end of a basic block, we assume all temporaries are dead and
1389
   all globals are stored at their canonical location. */
1390
static void tcg_reg_alloc_bb_end(TCGContext *s, TCGRegSet allocated_regs)
1391
{
1392
    TCGTemp *ts;
1393
    int i;
1394

    
1395
    for(i = s->nb_globals; i < s->nb_temps; i++) {
1396
        ts = &s->temps[i];
1397
        if (ts->temp_local) {
1398
            temp_save(s, i, allocated_regs);
1399
        } else {
1400
            if (ts->val_type == TEMP_VAL_REG) {
1401
                s->reg_to_temp[ts->reg] = -1;
1402
            }
1403
            ts->val_type = TEMP_VAL_DEAD;
1404
        }
1405
    }
1406

    
1407
    save_globals(s, allocated_regs);
1408
}
1409

    
1410
#define IS_DEAD_IARG(n) ((dead_iargs >> (n)) & 1)
1411

    
1412
static void tcg_reg_alloc_movi(TCGContext *s, const TCGArg *args)
1413
{
1414
    TCGTemp *ots;
1415
    tcg_target_ulong val;
1416

    
1417
    ots = &s->temps[args[0]];
1418
    val = args[1];
1419

    
1420
    if (ots->fixed_reg) {
1421
        /* for fixed registers, we do not do any constant
1422
           propagation */
1423
        tcg_out_movi(s, ots->type, ots->reg, val);
1424
    } else {
1425
        /* The movi is not explicitly generated here */
1426
        if (ots->val_type == TEMP_VAL_REG)
1427
            s->reg_to_temp[ots->reg] = -1;
1428
        ots->val_type = TEMP_VAL_CONST;
1429
        ots->val = val;
1430
    }
1431
}
1432

    
1433
static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
1434
                              const TCGArg *args,
1435
                              unsigned int dead_iargs)
1436
{
1437
    TCGTemp *ts, *ots;
1438
    int reg;
1439
    const TCGArgConstraint *arg_ct;
1440

    
1441
    ots = &s->temps[args[0]];
1442
    ts = &s->temps[args[1]];
1443
    arg_ct = &def->args_ct[0];
1444

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

    
1492
static void tcg_reg_alloc_op(TCGContext *s, 
1493
                             const TCGOpDef *def, int opc,
1494
                             const TCGArg *args,
1495
                             unsigned int dead_iargs)
1496
{
1497
    TCGRegSet allocated_regs;
1498
    int i, k, nb_iargs, nb_oargs, reg;
1499
    TCGArg arg;
1500
    const TCGArgConstraint *arg_ct;
1501
    TCGTemp *ts;
1502
    TCGArg new_args[TCG_MAX_OP_ARGS];
1503
    int const_args[TCG_MAX_OP_ARGS];
1504

    
1505
    nb_oargs = def->nb_oargs;
1506
    nb_iargs = def->nb_iargs;
1507

    
1508
    /* copy constants */
1509
    memcpy(new_args + nb_oargs + nb_iargs, 
1510
           args + nb_oargs + nb_iargs, 
1511
           sizeof(TCGArg) * def->nb_cargs);
1512

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

    
1640
    /* emit instruction */
1641
    tcg_out_op(s, opc, new_args, const_args);
1642
    
1643
    /* move the outputs in the correct register if needed */
1644
    for(i = 0; i < nb_oargs; i++) {
1645
        ts = &s->temps[args[i]];
1646
        reg = new_args[i];
1647
        if (ts->fixed_reg && ts->reg != reg) {
1648
            tcg_out_mov(s, ts->reg, reg);
1649
        }
1650
    }
1651
}
1652

    
1653
#ifdef TCG_TARGET_STACK_GROWSUP
1654
#define STACK_DIR(x) (-(x))
1655
#else
1656
#define STACK_DIR(x) (x)
1657
#endif
1658

    
1659
static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
1660
                              int opc, const TCGArg *args,
1661
                              unsigned int dead_iargs)
1662
{
1663
    int nb_iargs, nb_oargs, flags, nb_regs, i, reg, nb_params;
1664
    TCGArg arg, func_arg;
1665
    TCGTemp *ts;
1666
    tcg_target_long stack_offset, call_stack_size, func_addr;
1667
    int const_func_arg, allocate_args;
1668
    TCGRegSet allocated_regs;
1669
    const TCGArgConstraint *arg_ct;
1670

    
1671
    arg = *args++;
1672

    
1673
    nb_oargs = arg >> 16;
1674
    nb_iargs = arg & 0xffff;
1675
    nb_params = nb_iargs - 1;
1676

    
1677
    flags = args[nb_oargs + nb_iargs];
1678

    
1679
    nb_regs = tcg_target_get_call_iarg_regs_count(flags);
1680
    if (nb_regs > nb_params)
1681
        nb_regs = nb_params;
1682

    
1683
    /* assign stack slots first */
1684
    /* XXX: preallocate call stack */
1685
    call_stack_size = (nb_params - nb_regs) * sizeof(tcg_target_long);
1686
    call_stack_size = (call_stack_size + TCG_TARGET_STACK_ALIGN - 1) & 
1687
        ~(TCG_TARGET_STACK_ALIGN - 1);
1688
    allocate_args = (call_stack_size > TCG_STATIC_CALL_ARGS_SIZE);
1689
    if (allocate_args) {
1690
        tcg_out_addi(s, TCG_REG_CALL_STACK, -STACK_DIR(call_stack_size));
1691
    }
1692

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

    
1806
    tcg_out_op(s, opc, &func_arg, &const_func_arg);
1807
    
1808
    if (allocate_args) {
1809
        tcg_out_addi(s, TCG_REG_CALL_STACK, STACK_DIR(call_stack_size));
1810
    }
1811

    
1812
    /* assign output registers and emit moves if needed */
1813
    for(i = 0; i < nb_oargs; i++) {
1814
        arg = args[i];
1815
        ts = &s->temps[arg];
1816
        reg = tcg_target_call_oarg_regs[i];
1817
        assert(s->reg_to_temp[reg] == -1);
1818
        if (ts->fixed_reg) {
1819
            if (ts->reg != reg) {
1820
                tcg_out_mov(s, ts->reg, reg);
1821
            }
1822
        } else {
1823
            if (ts->val_type == TEMP_VAL_REG)
1824
                s->reg_to_temp[ts->reg] = -1;
1825
            ts->val_type = TEMP_VAL_REG;
1826
            ts->reg = reg;
1827
            ts->mem_coherent = 0; 
1828
            s->reg_to_temp[reg] = arg;
1829
        }
1830
    }
1831
    
1832
    return nb_iargs + nb_oargs + def->nb_cargs + 1;
1833
}
1834

    
1835
#ifdef CONFIG_PROFILER
1836

    
1837
static int64_t dyngen_table_op_count[NB_OPS];
1838

    
1839
void dump_op_count(void)
1840
{
1841
    int i;
1842
    FILE *f;
1843
    f = fopen("/tmp/op1.log", "w");
1844
    for(i = 0; i < INDEX_op_end; i++) {
1845
        fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name, dyngen_table_op_count[i]);
1846
    }
1847
    fclose(f);
1848
    f = fopen("/tmp/op2.log", "w");
1849
    for(i = INDEX_op_end; i < NB_OPS; i++) {
1850
        fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name, dyngen_table_op_count[i]);
1851
    }
1852
    fclose(f);
1853
}
1854
#endif
1855

    
1856

    
1857
static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
1858
                                      long search_pc)
1859
{
1860
    int opc, op_index;
1861
    const TCGOpDef *def;
1862
    unsigned int dead_iargs;
1863
    const TCGArg *args;
1864

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

    
1873
#ifdef CONFIG_PROFILER
1874
    s->la_time -= profile_getclock();
1875
#endif
1876
    tcg_liveness_analysis(s);
1877
#ifdef CONFIG_PROFILER
1878
    s->la_time += profile_getclock();
1879
#endif
1880

    
1881
#ifdef DEBUG_DISAS
1882
    if (unlikely(loglevel & CPU_LOG_TB_OP_OPT)) {
1883
        fprintf(logfile, "OP after la:\n");
1884
        tcg_dump_ops(s, logfile);
1885
        fprintf(logfile, "\n");
1886
    }
1887
#endif
1888

    
1889
    tcg_reg_alloc_start(s);
1890

    
1891
    s->code_buf = gen_code_buf;
1892
    s->code_ptr = gen_code_buf;
1893

    
1894
    args = gen_opparam_buf;
1895
    op_index = 0;
1896

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

    
1956
#ifdef CONFIG_DYNGEN_OP
1957
        case 0 ... INDEX_op_end - 1:
1958
            /* legacy dyngen ops */
1959
#ifdef CONFIG_PROFILER
1960
            s->old_op_count++;
1961
#endif
1962
            tcg_reg_alloc_bb_end(s, s->reserved_regs);
1963
            if (search_pc >= 0) {
1964
                s->code_ptr += def->copy_size;
1965
                args += def->nb_args;
1966
            } else {
1967
                args = dyngen_op(s, opc, args);
1968
            }
1969
            goto next;
1970
#endif
1971
        default:
1972
            /* Note: in order to speed up the code, it would be much
1973
               faster to have specialized register allocator functions for
1974
               some common argument patterns */
1975
            dead_iargs = s->op_dead_iargs[op_index];
1976
            tcg_reg_alloc_op(s, def, opc, args, dead_iargs);
1977
            break;
1978
        }
1979
        args += def->nb_args;
1980
    next:
1981
        if (search_pc >= 0 && search_pc < s->code_ptr - gen_code_buf) {
1982
            return op_index;
1983
        }
1984
        op_index++;
1985
#ifndef NDEBUG
1986
        check_regs(s);
1987
#endif
1988
    }
1989
 the_end:
1990
    return -1;
1991
}
1992

    
1993
int dyngen_code(TCGContext *s, uint8_t *gen_code_buf)
1994
{
1995
#ifdef CONFIG_PROFILER
1996
    {
1997
        int n;
1998
        n = (gen_opc_ptr - gen_opc_buf);
1999
        s->op_count += n;
2000
        if (n > s->op_count_max)
2001
            s->op_count_max = n;
2002

    
2003
        s->temp_count += s->nb_temps;
2004
        if (s->nb_temps > s->temp_count_max)
2005
            s->temp_count_max = s->nb_temps;
2006
    }
2007
#endif
2008

    
2009
    tcg_gen_code_common(s, gen_code_buf, -1);
2010

    
2011
    /* flush instruction cache */
2012
    flush_icache_range((unsigned long)gen_code_buf, 
2013
                       (unsigned long)s->code_ptr);
2014
    return s->code_ptr -  gen_code_buf;
2015
}
2016

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

    
2026
#ifdef CONFIG_PROFILER
2027
void tcg_dump_info(FILE *f,
2028
                   int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
2029
{
2030
    TCGContext *s = &tcg_ctx;
2031
    int64_t tot;
2032

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