Statistics
| Branch: | Revision:

root / tcg / tcg.c @ bdffd4a9

History | View | Annotate | Download (62.7 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
TCGv tcg_const_local_i32(int32_t val)
479
{
480
    TCGv t0;
481
    t0 = tcg_temp_local_new(TCG_TYPE_I32);
482
    tcg_gen_movi_i32(t0, val);
483
    return t0;
484
}
485

    
486
TCGv tcg_const_local_i64(int64_t val)
487
{
488
    TCGv t0;
489
    t0 = tcg_temp_local_new(TCG_TYPE_I64);
490
    tcg_gen_movi_i64(t0, val);
491
    return t0;
492
}
493

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

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

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

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

    
539

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

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

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

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

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

    
684
static char *tcg_get_arg_str_idx(TCGContext *s, char *buf, int buf_size,
685
                                 int idx)
686
{
687
    TCGTemp *ts;
688

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

    
701
char *tcg_get_arg_str(TCGContext *s, char *buf, int buf_size, TCGv arg)
702
{
703
    return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV(arg));
704
}
705

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

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

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

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

    
749
static const char * const cond_name[] =
750
{
751
    [TCG_COND_EQ] = "eq",
752
    [TCG_COND_NE] = "ne",
753
    [TCG_COND_LT] = "lt",
754
    [TCG_COND_GE] = "ge",
755
    [TCG_COND_LE] = "le",
756
    [TCG_COND_GT] = "gt",
757
    [TCG_COND_LTU] = "ltu",
758
    [TCG_COND_GEU] = "geu",
759
    [TCG_COND_LEU] = "leu",
760
    [TCG_COND_GTU] = "gtu"
761
};
762

    
763
void tcg_dump_ops(TCGContext *s, FILE *outfile)
764
{
765
    const uint16_t *opc_ptr;
766
    const TCGArg *args;
767
    TCGArg arg;
768
    int c, i, k, nb_oargs, nb_iargs, nb_cargs, first_insn;
769
    const TCGOpDef *def;
770
    char buf[128];
771

    
772
    first_insn = 1;
773
    opc_ptr = gen_opc_buf;
774
    args = gen_opparam_buf;
775
    while (opc_ptr < gen_opc_ptr) {
776
        c = *opc_ptr++;
777
        def = &tcg_op_defs[c];
778
        if (c == INDEX_op_debug_insn_start) {
779
            uint64_t pc;
780
#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
781
            pc = ((uint64_t)args[1] << 32) | args[0];
782
#else
783
            pc = args[0];
784
#endif
785
            if (!first_insn) 
786
                fprintf(outfile, "\n");
787
            fprintf(outfile, " ---- 0x%" PRIx64, pc);
788
            first_insn = 0;
789
            nb_oargs = def->nb_oargs;
790
            nb_iargs = def->nb_iargs;
791
            nb_cargs = def->nb_cargs;
792
        } else if (c == INDEX_op_call) {
793
            TCGArg arg;
794

    
795
            /* variable number of arguments */
796
            arg = *args++;
797
            nb_oargs = arg >> 16;
798
            nb_iargs = arg & 0xffff;
799
            nb_cargs = def->nb_cargs;
800

    
801
            fprintf(outfile, " %s ", def->name);
802

    
803
            /* function name */
804
            fprintf(outfile, "%s",
805
                    tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + nb_iargs - 1]));
806
            /* flags */
807
            fprintf(outfile, ",$0x%" TCG_PRIlx,
808
                    args[nb_oargs + nb_iargs]);
809
            /* nb out args */
810
            fprintf(outfile, ",$%d", nb_oargs);
811
            for(i = 0; i < nb_oargs; i++) {
812
                fprintf(outfile, ",");
813
                fprintf(outfile, "%s",
814
                        tcg_get_arg_str_idx(s, buf, sizeof(buf), args[i]));
815
            }
816
            for(i = 0; i < (nb_iargs - 1); i++) {
817
                fprintf(outfile, ",");
818
                if (args[nb_oargs + i] == TCG_CALL_DUMMY_ARG) {
819
                    fprintf(outfile, "<dummy>");
820
                } else {
821
                    fprintf(outfile, "%s",
822
                            tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + i]));
823
                }
824
            }
825
        } else if (c == INDEX_op_movi_i32 
826
#if TCG_TARGET_REG_BITS == 64
827
                   || c == INDEX_op_movi_i64
828
#endif
829
                   ) {
830
            tcg_target_ulong val;
831
            TCGHelperInfo *th;
832

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

    
901
/* we give more priority to constraints with less registers */
902
static int get_constraint_priority(const TCGOpDef *def, int k)
903
{
904
    const TCGArgConstraint *arg_ct;
905

    
906
    int i, n;
907
    arg_ct = &def->args_ct[k];
908
    if (arg_ct->ct & TCG_CT_ALIAS) {
909
        /* an alias is equivalent to a single register */
910
        n = 1;
911
    } else {
912
        if (!(arg_ct->ct & TCG_CT_REG))
913
            return 0;
914
        n = 0;
915
        for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
916
            if (tcg_regset_test_reg(arg_ct->u.regs, i))
917
                n++;
918
        }
919
    }
920
    return TCG_TARGET_NB_REGS - n + 1;
921
}
922

    
923
/* sort from highest priority to lowest */
924
static void sort_constraints(TCGOpDef *def, int start, int n)
925
{
926
    int i, j, p1, p2, tmp;
927

    
928
    for(i = 0; i < n; i++)
929
        def->sorted_args[start + i] = start + i;
930
    if (n <= 1)
931
        return;
932
    for(i = 0; i < n - 1; i++) {
933
        for(j = i + 1; j < n; j++) {
934
            p1 = get_constraint_priority(def, def->sorted_args[start + i]);
935
            p2 = get_constraint_priority(def, def->sorted_args[start + j]);
936
            if (p1 < p2) {
937
                tmp = def->sorted_args[start + i];
938
                def->sorted_args[start + i] = def->sorted_args[start + j];
939
                def->sorted_args[start + j] = tmp;
940
            }
941
        }
942
    }
943
}
944

    
945
void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs)
946
{
947
    int op;
948
    TCGOpDef *def;
949
    const char *ct_str;
950
    int i, nb_args;
951

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

    
995
        /* sort the constraints (XXX: this is just an heuristic) */
996
        sort_constraints(def, 0, def->nb_oargs);
997
        sort_constraints(def, def->nb_oargs, def->nb_iargs);
998

    
999
#if 0
1000
        {
1001
            int i;
1002

1003
            printf("%s: sorted=", def->name);
1004
            for(i = 0; i < def->nb_oargs + def->nb_iargs; i++)
1005
                printf(" %d", def->sorted_args[i]);
1006
            printf("\n");
1007
        }
1008
#endif
1009
        tdefs++;
1010
    }
1011

    
1012
}
1013

    
1014
#ifdef USE_LIVENESS_ANALYSIS
1015

    
1016
/* set a nop for an operation using 'nb_args' */
1017
static inline void tcg_set_nop(TCGContext *s, uint16_t *opc_ptr, 
1018
                               TCGArg *args, int nb_args)
1019
{
1020
    if (nb_args == 0) {
1021
        *opc_ptr = INDEX_op_nop;
1022
    } else {
1023
        *opc_ptr = INDEX_op_nopn;
1024
        args[0] = nb_args;
1025
        args[nb_args - 1] = nb_args;
1026
    }
1027
}
1028

    
1029
/* liveness analysis: end of function: globals are live, temps are
1030
   dead. */
1031
/* XXX: at this stage, not used as there would be little gains because
1032
   most TBs end with a conditional jump. */
1033
static inline void tcg_la_func_end(TCGContext *s, uint8_t *dead_temps)
1034
{
1035
    memset(dead_temps, 0, s->nb_globals);
1036
    memset(dead_temps + s->nb_globals, 1, s->nb_temps - s->nb_globals);
1037
}
1038

    
1039
/* liveness analysis: end of basic block: globals are live, temps are
1040
   dead, local temps are live. */
1041
static inline void tcg_la_bb_end(TCGContext *s, uint8_t *dead_temps)
1042
{
1043
    int i;
1044
    TCGTemp *ts;
1045

    
1046
    memset(dead_temps, 0, s->nb_globals);
1047
    ts = &s->temps[s->nb_globals];
1048
    for(i = s->nb_globals; i < s->nb_temps; i++) {
1049
        if (ts->temp_local)
1050
            dead_temps[i] = 0;
1051
        else
1052
            dead_temps[i] = 1;
1053
        ts++;
1054
    }
1055
}
1056

    
1057
/* Liveness analysis : update the opc_dead_iargs array to tell if a
1058
   given input arguments is dead. Instructions updating dead
1059
   temporaries are removed. */
1060
static void tcg_liveness_analysis(TCGContext *s)
1061
{
1062
    int i, op_index, op, nb_args, nb_iargs, nb_oargs, arg, nb_ops;
1063
    TCGArg *args;
1064
    const TCGOpDef *def;
1065
    uint8_t *dead_temps;
1066
    unsigned int dead_iargs;
1067
    
1068
    gen_opc_ptr++; /* skip end */
1069

    
1070
    nb_ops = gen_opc_ptr - gen_opc_buf;
1071

    
1072
    /* XXX: make it really dynamic */
1073
    s->op_dead_iargs = tcg_malloc(OPC_BUF_SIZE * sizeof(uint16_t));
1074
    
1075
    dead_temps = tcg_malloc(s->nb_temps);
1076
    memset(dead_temps, 1, s->nb_temps);
1077

    
1078
    args = gen_opparam_ptr;
1079
    op_index = nb_ops - 1;
1080
    while (op_index >= 0) {
1081
        op = gen_opc_buf[op_index];
1082
        def = &tcg_op_defs[op];
1083
        switch(op) {
1084
        case INDEX_op_call:
1085
            {
1086
                int call_flags;
1087

    
1088
                nb_args = args[-1];
1089
                args -= nb_args;
1090
                nb_iargs = args[0] & 0xffff;
1091
                nb_oargs = args[0] >> 16;
1092
                args++;
1093
                call_flags = args[nb_oargs + nb_iargs];
1094

    
1095
                /* pure functions can be removed if their result is not
1096
                   used */
1097
                if (call_flags & TCG_CALL_PURE) {
1098
                    for(i = 0; i < nb_oargs; i++) {
1099
                        arg = args[i];
1100
                        if (!dead_temps[arg])
1101
                            goto do_not_remove_call;
1102
                    }
1103
                    tcg_set_nop(s, gen_opc_buf + op_index, 
1104
                                args - 1, nb_args);
1105
                } else {
1106
                do_not_remove_call:
1107

    
1108
                    /* output args are dead */
1109
                    for(i = 0; i < nb_oargs; i++) {
1110
                        arg = args[i];
1111
                        dead_temps[arg] = 1;
1112
                    }
1113
                    
1114
                    /* globals are live (they may be used by the call) */
1115
                    memset(dead_temps, 0, s->nb_globals);
1116
                    
1117
                    /* input args are live */
1118
                    dead_iargs = 0;
1119
                    for(i = 0; i < nb_iargs; i++) {
1120
                        arg = args[i + nb_oargs];
1121
                        if (arg != TCG_CALL_DUMMY_ARG) {
1122
                            if (dead_temps[arg]) {
1123
                                dead_iargs |= (1 << i);
1124
                            }
1125
                            dead_temps[arg] = 0;
1126
                        }
1127
                    }
1128
                    s->op_dead_iargs[op_index] = dead_iargs;
1129
                }
1130
                args--;
1131
            }
1132
            break;
1133
        case INDEX_op_set_label:
1134
            args--;
1135
            /* mark end of basic block */
1136
            tcg_la_bb_end(s, dead_temps);
1137
            break;
1138
        case INDEX_op_debug_insn_start:
1139
            args -= def->nb_args;
1140
            break;
1141
        case INDEX_op_nopn:
1142
            nb_args = args[-1];
1143
            args -= nb_args;
1144
            break;
1145
        case INDEX_op_discard:
1146
            args--;
1147
            /* mark the temporary as dead */
1148
            dead_temps[args[0]] = 1;
1149
            break;
1150
        case INDEX_op_end:
1151
            break;
1152
            /* XXX: optimize by hardcoding common cases (e.g. triadic ops) */
1153
        default:
1154
            if (op > INDEX_op_end) {
1155
                args -= def->nb_args;
1156
                nb_iargs = def->nb_iargs;
1157
                nb_oargs = def->nb_oargs;
1158

    
1159
                /* Test if the operation can be removed because all
1160
                   its outputs are dead. We assume that nb_oargs == 0
1161
                   implies side effects */
1162
                if (!(def->flags & TCG_OPF_SIDE_EFFECTS) && nb_oargs != 0) {
1163
                    for(i = 0; i < nb_oargs; i++) {
1164
                        arg = args[i];
1165
                        if (!dead_temps[arg])
1166
                            goto do_not_remove;
1167
                    }
1168
                    tcg_set_nop(s, gen_opc_buf + op_index, args, def->nb_args);
1169
#ifdef CONFIG_PROFILER
1170
                    s->del_op_count++;
1171
#endif
1172
                } else {
1173
                do_not_remove:
1174

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

    
1211
    if (args != gen_opparam_buf)
1212
        tcg_abort();
1213
}
1214
#else
1215
/* dummy liveness analysis */
1216
void tcg_liveness_analysis(TCGContext *s)
1217
{
1218
    int nb_ops;
1219
    nb_ops = gen_opc_ptr - gen_opc_buf;
1220

    
1221
    s->op_dead_iargs = tcg_malloc(nb_ops * sizeof(uint16_t));
1222
    memset(s->op_dead_iargs, 0, nb_ops * sizeof(uint16_t));
1223
}
1224
#endif
1225

    
1226
#ifndef NDEBUG
1227
static void dump_regs(TCGContext *s)
1228
{
1229
    TCGTemp *ts;
1230
    int i;
1231
    char buf[64];
1232

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

    
1256
    for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
1257
        if (s->reg_to_temp[i] >= 0) {
1258
            printf("%s: %s\n", 
1259
                   tcg_target_reg_names[i], 
1260
                   tcg_get_arg_str_idx(s, buf, sizeof(buf), s->reg_to_temp[i]));
1261
        }
1262
    }
1263
}
1264

    
1265
static void check_regs(TCGContext *s)
1266
{
1267
    int reg, k;
1268
    TCGTemp *ts;
1269
    char buf[64];
1270

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

    
1299
static void temp_allocate_frame(TCGContext *s, int temp)
1300
{
1301
    TCGTemp *ts;
1302
    ts = &s->temps[temp];
1303
    s->current_frame_offset = (s->current_frame_offset + sizeof(tcg_target_long) - 1) & ~(sizeof(tcg_target_long) - 1);
1304
    if (s->current_frame_offset + sizeof(tcg_target_long) > s->frame_end)
1305
        tcg_abort();
1306
    ts->mem_offset = s->current_frame_offset;
1307
    ts->mem_reg = s->frame_reg;
1308
    ts->mem_allocated = 1;
1309
    s->current_frame_offset += sizeof(tcg_target_long);
1310
}
1311

    
1312
/* free register 'reg' by spilling the corresponding temporary if necessary */
1313
static void tcg_reg_free(TCGContext *s, int reg)
1314
{
1315
    TCGTemp *ts;
1316
    int temp;
1317

    
1318
    temp = s->reg_to_temp[reg];
1319
    if (temp != -1) {
1320
        ts = &s->temps[temp];
1321
        assert(ts->val_type == TEMP_VAL_REG);
1322
        if (!ts->mem_coherent) {
1323
            if (!ts->mem_allocated) 
1324
                temp_allocate_frame(s, temp);
1325
            tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1326
        }
1327
        ts->val_type = TEMP_VAL_MEM;
1328
        s->reg_to_temp[reg] = -1;
1329
    }
1330
}
1331

    
1332
/* Allocate a register belonging to reg1 & ~reg2 */
1333
static int tcg_reg_alloc(TCGContext *s, TCGRegSet reg1, TCGRegSet reg2)
1334
{
1335
    int i, reg;
1336
    TCGRegSet reg_ct;
1337

    
1338
    tcg_regset_andnot(reg_ct, reg1, reg2);
1339

    
1340
    /* first try free registers */
1341
    for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1342
        reg = tcg_target_reg_alloc_order[i];
1343
        if (tcg_regset_test_reg(reg_ct, reg) && s->reg_to_temp[reg] == -1)
1344
            return reg;
1345
    }
1346

    
1347
    /* XXX: do better spill choice */
1348
    for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1349
        reg = tcg_target_reg_alloc_order[i];
1350
        if (tcg_regset_test_reg(reg_ct, reg)) {
1351
            tcg_reg_free(s, reg);
1352
            return reg;
1353
        }
1354
    }
1355

    
1356
    tcg_abort();
1357
}
1358

    
1359
/* save a temporary to memory. 'allocated_regs' is used in case a
1360
   temporary registers needs to be allocated to store a constant. */
1361
static void temp_save(TCGContext *s, int temp, TCGRegSet allocated_regs)
1362
{
1363
    TCGTemp *ts;
1364
    int reg;
1365

    
1366
    ts = &s->temps[temp];
1367
    if (!ts->fixed_reg) {
1368
        switch(ts->val_type) {
1369
        case TEMP_VAL_REG:
1370
            tcg_reg_free(s, ts->reg);
1371
            break;
1372
        case TEMP_VAL_DEAD:
1373
            ts->val_type = TEMP_VAL_MEM;
1374
            break;
1375
        case TEMP_VAL_CONST:
1376
            reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], 
1377
                                allocated_regs);
1378
            if (!ts->mem_allocated) 
1379
                temp_allocate_frame(s, temp);
1380
            tcg_out_movi(s, ts->type, reg, ts->val);
1381
            tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1382
            ts->val_type = TEMP_VAL_MEM;
1383
            break;
1384
        case TEMP_VAL_MEM:
1385
            break;
1386
        default:
1387
            tcg_abort();
1388
        }
1389
    }
1390
}
1391

    
1392
/* save globals to their cannonical location and assume they can be
1393
   modified be the following code. 'allocated_regs' is used in case a
1394
   temporary registers needs to be allocated to store a constant. */
1395
static void save_globals(TCGContext *s, TCGRegSet allocated_regs)
1396
{
1397
    int i;
1398

    
1399
    for(i = 0; i < s->nb_globals; i++) {
1400
        temp_save(s, i, allocated_regs);
1401
    }
1402
}
1403

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

    
1411
    for(i = s->nb_globals; i < s->nb_temps; i++) {
1412
        ts = &s->temps[i];
1413
        if (ts->temp_local) {
1414
            temp_save(s, i, allocated_regs);
1415
        } else {
1416
            if (ts->val_type == TEMP_VAL_REG) {
1417
                s->reg_to_temp[ts->reg] = -1;
1418
            }
1419
            ts->val_type = TEMP_VAL_DEAD;
1420
        }
1421
    }
1422

    
1423
    save_globals(s, allocated_regs);
1424
}
1425

    
1426
#define IS_DEAD_IARG(n) ((dead_iargs >> (n)) & 1)
1427

    
1428
static void tcg_reg_alloc_movi(TCGContext *s, const TCGArg *args)
1429
{
1430
    TCGTemp *ots;
1431
    tcg_target_ulong val;
1432

    
1433
    ots = &s->temps[args[0]];
1434
    val = args[1];
1435

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

    
1449
static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
1450
                              const TCGArg *args,
1451
                              unsigned int dead_iargs)
1452
{
1453
    TCGTemp *ts, *ots;
1454
    int reg;
1455
    const TCGArgConstraint *arg_ct;
1456

    
1457
    ots = &s->temps[args[0]];
1458
    ts = &s->temps[args[1]];
1459
    arg_ct = &def->args_ct[0];
1460

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

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

    
1521
    nb_oargs = def->nb_oargs;
1522
    nb_iargs = def->nb_iargs;
1523

    
1524
    /* copy constants */
1525
    memcpy(new_args + nb_oargs + nb_iargs, 
1526
           args + nb_oargs + nb_iargs, 
1527
           sizeof(TCGArg) * def->nb_cargs);
1528

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

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

    
1669
#ifdef TCG_TARGET_STACK_GROWSUP
1670
#define STACK_DIR(x) (-(x))
1671
#else
1672
#define STACK_DIR(x) (x)
1673
#endif
1674

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

    
1687
    arg = *args++;
1688

    
1689
    nb_oargs = arg >> 16;
1690
    nb_iargs = arg & 0xffff;
1691
    nb_params = nb_iargs - 1;
1692

    
1693
    flags = args[nb_oargs + nb_iargs];
1694

    
1695
    nb_regs = tcg_target_get_call_iarg_regs_count(flags);
1696
    if (nb_regs > nb_params)
1697
        nb_regs = nb_params;
1698

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

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

    
1822
    tcg_out_op(s, opc, &func_arg, &const_func_arg);
1823
    
1824
    if (allocate_args) {
1825
        tcg_out_addi(s, TCG_REG_CALL_STACK, STACK_DIR(call_stack_size));
1826
    }
1827

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

    
1851
#ifdef CONFIG_PROFILER
1852

    
1853
static int64_t dyngen_table_op_count[NB_OPS];
1854

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

    
1872

    
1873
static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
1874
                                      long search_pc)
1875
{
1876
    int opc, op_index;
1877
    const TCGOpDef *def;
1878
    unsigned int dead_iargs;
1879
    const TCGArg *args;
1880

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

    
1889
#ifdef CONFIG_PROFILER
1890
    s->la_time -= profile_getclock();
1891
#endif
1892
    tcg_liveness_analysis(s);
1893
#ifdef CONFIG_PROFILER
1894
    s->la_time += profile_getclock();
1895
#endif
1896

    
1897
#ifdef DEBUG_DISAS
1898
    if (unlikely(loglevel & CPU_LOG_TB_OP_OPT)) {
1899
        fprintf(logfile, "OP after la:\n");
1900
        tcg_dump_ops(s, logfile);
1901
        fprintf(logfile, "\n");
1902
    }
1903
#endif
1904

    
1905
    tcg_reg_alloc_start(s);
1906

    
1907
    s->code_buf = gen_code_buf;
1908
    s->code_ptr = gen_code_buf;
1909

    
1910
    args = gen_opparam_buf;
1911
    op_index = 0;
1912

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

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

    
2009
int dyngen_code(TCGContext *s, uint8_t *gen_code_buf)
2010
{
2011
#ifdef CONFIG_PROFILER
2012
    {
2013
        int n;
2014
        n = (gen_opc_ptr - gen_opc_buf);
2015
        s->op_count += n;
2016
        if (n > s->op_count_max)
2017
            s->op_count_max = n;
2018

    
2019
        s->temp_count += s->nb_temps;
2020
        if (s->nb_temps > s->temp_count_max)
2021
            s->temp_count_max = s->nb_temps;
2022
    }
2023
#endif
2024

    
2025
    tcg_gen_code_common(s, gen_code_buf, -1);
2026

    
2027
    /* flush instruction cache */
2028
    flush_icache_range((unsigned long)gen_code_buf, 
2029
                       (unsigned long)s->code_ptr);
2030
    return s->code_ptr -  gen_code_buf;
2031
}
2032

    
2033
/* Return the index of the micro operation such as the pc after is <
2034
   offset bytes from the start of the TB.  The contents of gen_code_buf must
2035
   not be changed, though writing the same values is ok.
2036
   Return -1 if not found. */
2037
int dyngen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, long offset)
2038
{
2039
    return tcg_gen_code_common(s, gen_code_buf, offset);
2040
}
2041

    
2042
#ifdef CONFIG_PROFILER
2043
void tcg_dump_info(FILE *f,
2044
                   int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
2045
{
2046
    TCGContext *s = &tcg_ctx;
2047
    int64_t tot;
2048

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