Statistics
| Branch: | Revision:

root / tcg / tcg.c @ 79d342dc

History | View | Annotate | Download (61.5 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
#ifdef _AIX
41
#include <alloca.h>
42
#endif
43

    
44
#include "config.h"
45
#include "qemu-common.h"
46
#include "cache-utils.h"
47

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

    
55
#include "tcg-op.h"
56
#include "elf.h"
57

    
58

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

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

    
70
static TCGRegSet tcg_target_available_regs[2];
71
static TCGRegSet tcg_target_call_clobber_regs;
72

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

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

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

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

    
94
/* label relocation processing */
95

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

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

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

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

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

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

    
152
#include "tcg-target.c"
153

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

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

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

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

    
223
    args_ct = qemu_malloc(sizeof(TCGArgConstraint) * total_args);
224
    sorted_args = qemu_malloc(sizeof(int) * total_args);
225

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

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

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

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

    
264
    gen_opc_ptr = gen_opc_buf;
265
    gen_opparam_ptr = gen_opparam_buf;
266
}
267

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

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

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

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

    
304
    idx = tcg_global_reg_new_internal(TCG_TYPE_I32, reg, name);
305
    return MAKE_TCGV_I32(idx);
306
}
307

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

    
312
    idx = tcg_global_reg_new_internal(TCG_TYPE_I64, reg, name);
313
    return MAKE_TCGV_I64(idx);
314
}
315

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

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

    
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;
352
#else
353
        ts->mem_offset = offset + 4;
354
#endif
355
        pstrcpy(buf, sizeof(buf), name);
356
        pstrcat(buf, sizeof(buf), "_1");
357
        ts->name = strdup(buf);
358

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

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

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

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

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

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

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

    
446
TCGv_i32 tcg_temp_new_internal_i32(int temp_local)
447
{
448
    int idx;
449

    
450
    idx = tcg_temp_new_internal(TCG_TYPE_I32, temp_local);
451
    return MAKE_TCGV_I32(idx);
452
}
453

    
454
TCGv_i64 tcg_temp_new_internal_i64(int temp_local)
455
{
456
    int idx;
457

    
458
    idx = tcg_temp_new_internal(TCG_TYPE_I64, temp_local);
459
    return MAKE_TCGV_I64(idx);
460
}
461

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

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

    
479
void tcg_temp_free_i32(TCGv_i32 arg)
480
{
481
    tcg_temp_free_internal(GET_TCGV_I32(arg));
482
}
483

    
484
void tcg_temp_free_i64(TCGv_i64 arg)
485
{
486
    tcg_temp_free_internal(GET_TCGV_I64(arg));
487
}
488

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

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

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

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

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

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

    
610
    *gen_opparam_ptr++ = flags;
611

    
612
    *nparam = (nb_rets << 16) | (real_args + 1);
613

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
812
            fprintf(outfile, " %s ", def->name);
813

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

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

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

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

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

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

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

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

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

    
1010
#if 0
1011
        {
1012
            int i;
1013

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

    
1023
}
1024

    
1025
#ifdef USE_LIVENESS_ANALYSIS
1026

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

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

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

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

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

    
1081
    nb_ops = gen_opc_ptr - gen_opc_buf;
1082

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

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

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

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

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

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

    
1185
                /* output args are dead */
1186
                for(i = 0; i < nb_oargs; i++) {
1187
                    arg = args[i];
1188
                    dead_temps[arg] = 1;
1189
                }
1190

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

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

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

    
1225
    s->op_dead_iargs = tcg_malloc(nb_ops * sizeof(uint16_t));
1226
    memset(s->op_dead_iargs, 0, nb_ops * sizeof(uint16_t));
1227
}
1228
#endif
1229

    
1230
#ifndef NDEBUG
1231
static void dump_regs(TCGContext *s)
1232
{
1233
    TCGTemp *ts;
1234
    int i;
1235
    char buf[64];
1236

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

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

    
1269
static void check_regs(TCGContext *s)
1270
{
1271
    int reg, k;
1272
    TCGTemp *ts;
1273
    char buf[64];
1274

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

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

    
1316
/* free register 'reg' by spilling the corresponding temporary if necessary */
1317
static void tcg_reg_free(TCGContext *s, int reg)
1318
{
1319
    TCGTemp *ts;
1320
    int temp;
1321

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

    
1336
/* Allocate a register belonging to reg1 & ~reg2 */
1337
static int tcg_reg_alloc(TCGContext *s, TCGRegSet reg1, TCGRegSet reg2)
1338
{
1339
    int i, reg;
1340
    TCGRegSet reg_ct;
1341

    
1342
    tcg_regset_andnot(reg_ct, reg1, reg2);
1343

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

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

    
1360
    tcg_abort();
1361
}
1362

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

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

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

    
1403
    for(i = 0; i < s->nb_globals; i++) {
1404
        temp_save(s, i, allocated_regs);
1405
    }
1406
}
1407

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

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

    
1427
    save_globals(s, allocated_regs);
1428
}
1429

    
1430
#define IS_DEAD_IARG(n) ((dead_iargs >> (n)) & 1)
1431

    
1432
static void tcg_reg_alloc_movi(TCGContext *s, const TCGArg *args)
1433
{
1434
    TCGTemp *ots;
1435
    tcg_target_ulong val;
1436

    
1437
    ots = &s->temps[args[0]];
1438
    val = args[1];
1439

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

    
1453
static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
1454
                              const TCGArg *args,
1455
                              unsigned int dead_iargs)
1456
{
1457
    TCGTemp *ts, *ots;
1458
    int reg;
1459
    const TCGArgConstraint *arg_ct;
1460

    
1461
    ots = &s->temps[args[0]];
1462
    ts = &s->temps[args[1]];
1463
    arg_ct = &def->args_ct[0];
1464

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

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

    
1525
    nb_oargs = def->nb_oargs;
1526
    nb_iargs = def->nb_iargs;
1527

    
1528
    /* copy constants */
1529
    memcpy(new_args + nb_oargs + nb_iargs, 
1530
           args + nb_oargs + nb_iargs, 
1531
           sizeof(TCGArg) * def->nb_cargs);
1532

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

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

    
1673
#ifdef TCG_TARGET_STACK_GROWSUP
1674
#define STACK_DIR(x) (-(x))
1675
#else
1676
#define STACK_DIR(x) (x)
1677
#endif
1678

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

    
1691
    arg = *args++;
1692

    
1693
    nb_oargs = arg >> 16;
1694
    nb_iargs = arg & 0xffff;
1695
    nb_params = nb_iargs - 1;
1696

    
1697
    flags = args[nb_oargs + nb_iargs];
1698

    
1699
    nb_regs = tcg_target_get_call_iarg_regs_count(flags);
1700
    if (nb_regs > nb_params)
1701
        nb_regs = nb_params;
1702

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

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

    
1826
    tcg_out_op(s, opc, &func_arg, &const_func_arg);
1827
    
1828
    if (allocate_args) {
1829
        tcg_out_addi(s, TCG_REG_CALL_STACK, STACK_DIR(call_stack_size));
1830
    }
1831

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

    
1855
#ifdef CONFIG_PROFILER
1856

    
1857
static int64_t tcg_table_op_count[NB_OPS];
1858

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

    
1871

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

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

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

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

    
1904
    tcg_reg_alloc_start(s);
1905

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

    
1909
    args = gen_opparam_buf;
1910
    op_index = 0;
1911

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

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

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

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

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

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

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

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