Statistics
| Branch: | Revision:

root / tcg / tcg.c @ 8fcd3692

History | View | Annotate | Download (61.6 kB)

1
/*
2
 * Tiny Code Generator for QEMU
3
 *
4
 * Copyright (c) 2008 Fabrice Bellard
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7
 * of this software and associated documentation files (the "Software"), to deal
8
 * in the Software without restriction, including without limitation the rights
9
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
 * copies of the Software, and to permit persons to whom the Software is
11
 * furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
 * THE SOFTWARE.
23
 */
24

    
25
/* define it to suppress various consistency checks (faster) */
26
#define NDEBUG
27

    
28
/* define it to use liveness analysis (better code) */
29
#define USE_LIVENESS_ANALYSIS
30

    
31
#include <assert.h>
32
#include <stdarg.h>
33
#include <stdlib.h>
34
#include <stdio.h>
35
#include <string.h>
36
#include <inttypes.h>
37
#ifdef _WIN32
38
#include <malloc.h>
39
#endif
40

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

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

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

    
54

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

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

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

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

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

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

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

    
90
/* label relocation processing */
91

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

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

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

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

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

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

    
148
#include "tcg-target.c"
149

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

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

    
199
void tcg_context_init(TCGContext *s)
200
{
201
    int op, total_args, n;
202
    TCGOpDef *def;
203
    TCGArgConstraint *args_ct;
204
    int *sorted_args;
205

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
461

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

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

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

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

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

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

    
523

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

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

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

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

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

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

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

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

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

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

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

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

    
733
void tcg_dump_ops(TCGContext *s, FILE *outfile)
734
{
735
    const uint16_t *opc_ptr;
736
    const TCGArg *args;
737
    TCGArg arg;
738
    int c, i, k, nb_oargs, nb_iargs, nb_cargs, first_insn;
739
    const TCGOpDef *def;
740
    char buf[128];
741

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

    
765
            /* variable number of arguments */
766
            arg = *args++;
767
            nb_oargs = arg >> 16;
768
            nb_iargs = arg & 0xffff;
769
            nb_cargs = def->nb_cargs;
770

    
771
            fprintf(outfile, " %s ", def->name);
772

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

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

    
856
/* we give more priority to constraints with less registers */
857
static int get_constraint_priority(const TCGOpDef *def, int k)
858
{
859
    const TCGArgConstraint *arg_ct;
860

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

    
878
/* sort from highest priority to lowest */
879
static void sort_constraints(TCGOpDef *def, int start, int n)
880
{
881
    int i, j, p1, p2, tmp;
882

    
883
    for(i = 0; i < n; i++)
884
        def->sorted_args[start + i] = start + i;
885
    if (n <= 1)
886
        return;
887
    for(i = 0; i < n - 1; i++) {
888
        for(j = i + 1; j < n; j++) {
889
            p1 = get_constraint_priority(def, def->sorted_args[start + i]);
890
            p2 = get_constraint_priority(def, def->sorted_args[start + j]);
891
            if (p1 < p2) {
892
                tmp = def->sorted_args[start + i];
893
                def->sorted_args[start + i] = def->sorted_args[start + j];
894
                def->sorted_args[start + j] = tmp;
895
            }
896
        }
897
    }
898
}
899

    
900
void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs)
901
{
902
    int op;
903
    TCGOpDef *def;
904
    const char *ct_str;
905
    int i, nb_args;
906

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

    
950
        /* sort the constraints (XXX: this is just an heuristic) */
951
        sort_constraints(def, 0, def->nb_oargs);
952
        sort_constraints(def, def->nb_oargs, def->nb_iargs);
953

    
954
#if 0
955
        {
956
            int i;
957

958
            printf("%s: sorted=", def->name);
959
            for(i = 0; i < def->nb_oargs + def->nb_iargs; i++)
960
                printf(" %d", def->sorted_args[i]);
961
            printf("\n");
962
        }
963
#endif
964
        tdefs++;
965
    }
966

    
967
}
968

    
969
#ifdef USE_LIVENESS_ANALYSIS
970

    
971
/* set a nop for an operation using 'nb_args' */
972
static inline void tcg_set_nop(TCGContext *s, uint16_t *opc_ptr, 
973
                               TCGArg *args, int nb_args)
974
{
975
    if (nb_args == 0) {
976
        *opc_ptr = INDEX_op_nop;
977
    } else {
978
        *opc_ptr = INDEX_op_nopn;
979
        args[0] = nb_args;
980
        args[nb_args - 1] = nb_args;
981
    }
982
}
983

    
984
/* liveness analysis: end of function: globals are live, temps are
985
   dead. */
986
/* XXX: at this stage, not used as there would be little gains because
987
   most TBs end with a conditional jump. */
988
static inline void tcg_la_func_end(TCGContext *s, uint8_t *dead_temps)
989
{
990
    memset(dead_temps, 0, s->nb_globals);
991
    memset(dead_temps + s->nb_globals, 1, s->nb_temps - s->nb_globals);
992
}
993

    
994
/* liveness analysis: end of basic block: globals are live, temps are
995
   dead, local temps are live. */
996
static inline void tcg_la_bb_end(TCGContext *s, uint8_t *dead_temps)
997
{
998
    int i;
999
    TCGTemp *ts;
1000

    
1001
    memset(dead_temps, 0, s->nb_globals);
1002
    ts = &s->temps[s->nb_globals];
1003
    for(i = s->nb_globals; i < s->nb_temps; i++) {
1004
        if (ts->temp_local)
1005
            dead_temps[i] = 0;
1006
        else
1007
            dead_temps[i] = 1;
1008
        ts++;
1009
    }
1010
}
1011

    
1012
/* Liveness analysis : update the opc_dead_iargs array to tell if a
1013
   given input arguments is dead. Instructions updating dead
1014
   temporaries are removed. */
1015
static void tcg_liveness_analysis(TCGContext *s)
1016
{
1017
    int i, op_index, op, nb_args, nb_iargs, nb_oargs, arg, nb_ops;
1018
    TCGArg *args;
1019
    const TCGOpDef *def;
1020
    uint8_t *dead_temps;
1021
    unsigned int dead_iargs;
1022
    
1023
    gen_opc_ptr++; /* skip end */
1024

    
1025
    nb_ops = gen_opc_ptr - gen_opc_buf;
1026

    
1027
    /* XXX: make it really dynamic */
1028
    s->op_dead_iargs = tcg_malloc(OPC_BUF_SIZE * sizeof(uint16_t));
1029
    
1030
    dead_temps = tcg_malloc(s->nb_temps);
1031
    memset(dead_temps, 1, s->nb_temps);
1032

    
1033
    args = gen_opparam_ptr;
1034
    op_index = nb_ops - 1;
1035
    while (op_index >= 0) {
1036
        op = gen_opc_buf[op_index];
1037
        def = &tcg_op_defs[op];
1038
        switch(op) {
1039
        case INDEX_op_call:
1040
            {
1041
                int call_flags;
1042

    
1043
                nb_args = args[-1];
1044
                args -= nb_args;
1045
                nb_iargs = args[0] & 0xffff;
1046
                nb_oargs = args[0] >> 16;
1047
                args++;
1048
                call_flags = args[nb_oargs + nb_iargs];
1049

    
1050
                /* pure functions can be removed if their result is not
1051
                   used */
1052
                if (call_flags & TCG_CALL_PURE) {
1053
                    for(i = 0; i < nb_oargs; i++) {
1054
                        arg = args[i];
1055
                        if (!dead_temps[arg])
1056
                            goto do_not_remove_call;
1057
                    }
1058
                    tcg_set_nop(s, gen_opc_buf + op_index, 
1059
                                args - 1, nb_args);
1060
                } else {
1061
                do_not_remove_call:
1062

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

    
1114
                /* Test if the operation can be removed because all
1115
                   its outputs are dead. We assume that nb_oargs == 0
1116
                   implies side effects */
1117
                if (!(def->flags & TCG_OPF_SIDE_EFFECTS) && nb_oargs != 0) {
1118
                    for(i = 0; i < nb_oargs; i++) {
1119
                        arg = args[i];
1120
                        if (!dead_temps[arg])
1121
                            goto do_not_remove;
1122
                    }
1123
                    tcg_set_nop(s, gen_opc_buf + op_index, args, def->nb_args);
1124
#ifdef CONFIG_PROFILER
1125
                    s->del_op_count++;
1126
#endif
1127
                } else {
1128
                do_not_remove:
1129

    
1130
                    /* output args are dead */
1131
                    for(i = 0; i < nb_oargs; i++) {
1132
                        arg = args[i];
1133
                        dead_temps[arg] = 1;
1134
                    }
1135
                    
1136
                    /* if end of basic block, update */
1137
                    if (def->flags & TCG_OPF_BB_END) {
1138
                        tcg_la_bb_end(s, dead_temps);
1139
                    } else if (def->flags & TCG_OPF_CALL_CLOBBER) {
1140
                        /* globals are live */
1141
                        memset(dead_temps, 0, s->nb_globals);
1142
                    }
1143
                    
1144
                    /* input args are live */
1145
                    dead_iargs = 0;
1146
                    for(i = 0; i < nb_iargs; i++) {
1147
                        arg = args[i + nb_oargs];
1148
                        if (dead_temps[arg]) {
1149
                            dead_iargs |= (1 << i);
1150
                        }
1151
                        dead_temps[arg] = 0;
1152
                    }
1153
                    s->op_dead_iargs[op_index] = dead_iargs;
1154
                }
1155
            } else {
1156
                /* legacy dyngen operations */
1157
                args -= def->nb_args;
1158
                /* mark end of basic block */
1159
                tcg_la_bb_end(s, dead_temps);
1160
            }
1161
            break;
1162
        }
1163
        op_index--;
1164
    }
1165

    
1166
    if (args != gen_opparam_buf)
1167
        tcg_abort();
1168
}
1169
#else
1170
/* dummy liveness analysis */
1171
void tcg_liveness_analysis(TCGContext *s)
1172
{
1173
    int nb_ops;
1174
    nb_ops = gen_opc_ptr - gen_opc_buf;
1175

    
1176
    s->op_dead_iargs = tcg_malloc(nb_ops * sizeof(uint16_t));
1177
    memset(s->op_dead_iargs, 0, nb_ops * sizeof(uint16_t));
1178
}
1179
#endif
1180

    
1181
#ifndef NDEBUG
1182
static void dump_regs(TCGContext *s)
1183
{
1184
    TCGTemp *ts;
1185
    int i;
1186
    char buf[64];
1187

    
1188
    for(i = 0; i < s->nb_temps; i++) {
1189
        ts = &s->temps[i];
1190
        printf("  %10s: ", tcg_get_arg_str_idx(s, buf, sizeof(buf), i));
1191
        switch(ts->val_type) {
1192
        case TEMP_VAL_REG:
1193
            printf("%s", tcg_target_reg_names[ts->reg]);
1194
            break;
1195
        case TEMP_VAL_MEM:
1196
            printf("%d(%s)", (int)ts->mem_offset, tcg_target_reg_names[ts->mem_reg]);
1197
            break;
1198
        case TEMP_VAL_CONST:
1199
            printf("$0x%" TCG_PRIlx, ts->val);
1200
            break;
1201
        case TEMP_VAL_DEAD:
1202
            printf("D");
1203
            break;
1204
        default:
1205
            printf("???");
1206
            break;
1207
        }
1208
        printf("\n");
1209
    }
1210

    
1211
    for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
1212
        if (s->reg_to_temp[i] >= 0) {
1213
            printf("%s: %s\n", 
1214
                   tcg_target_reg_names[i], 
1215
                   tcg_get_arg_str_idx(s, buf, sizeof(buf), s->reg_to_temp[i]));
1216
        }
1217
    }
1218
}
1219

    
1220
static void check_regs(TCGContext *s)
1221
{
1222
    int reg, k;
1223
    TCGTemp *ts;
1224
    char buf[64];
1225

    
1226
    for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1227
        k = s->reg_to_temp[reg];
1228
        if (k >= 0) {
1229
            ts = &s->temps[k];
1230
            if (ts->val_type != TEMP_VAL_REG ||
1231
                ts->reg != reg) {
1232
                printf("Inconsistency for register %s:\n", 
1233
                       tcg_target_reg_names[reg]);
1234
                goto fail;
1235
            }
1236
        }
1237
    }
1238
    for(k = 0; k < s->nb_temps; k++) {
1239
        ts = &s->temps[k];
1240
        if (ts->val_type == TEMP_VAL_REG &&
1241
            !ts->fixed_reg &&
1242
            s->reg_to_temp[ts->reg] != k) {
1243
                printf("Inconsistency for temp %s:\n", 
1244
                       tcg_get_arg_str_idx(s, buf, sizeof(buf), k));
1245
        fail:
1246
                printf("reg state:\n");
1247
                dump_regs(s);
1248
                tcg_abort();
1249
        }
1250
    }
1251
}
1252
#endif
1253

    
1254
static void temp_allocate_frame(TCGContext *s, int temp)
1255
{
1256
    TCGTemp *ts;
1257
    ts = &s->temps[temp];
1258
    s->current_frame_offset = (s->current_frame_offset + sizeof(tcg_target_long) - 1) & ~(sizeof(tcg_target_long) - 1);
1259
    if (s->current_frame_offset + sizeof(tcg_target_long) > s->frame_end)
1260
        tcg_abort();
1261
    ts->mem_offset = s->current_frame_offset;
1262
    ts->mem_reg = s->frame_reg;
1263
    ts->mem_allocated = 1;
1264
    s->current_frame_offset += sizeof(tcg_target_long);
1265
}
1266

    
1267
/* free register 'reg' by spilling the corresponding temporary if necessary */
1268
static void tcg_reg_free(TCGContext *s, int reg)
1269
{
1270
    TCGTemp *ts;
1271
    int temp;
1272

    
1273
    temp = s->reg_to_temp[reg];
1274
    if (temp != -1) {
1275
        ts = &s->temps[temp];
1276
        assert(ts->val_type == TEMP_VAL_REG);
1277
        if (!ts->mem_coherent) {
1278
            if (!ts->mem_allocated) 
1279
                temp_allocate_frame(s, temp);
1280
            tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1281
        }
1282
        ts->val_type = TEMP_VAL_MEM;
1283
        s->reg_to_temp[reg] = -1;
1284
    }
1285
}
1286

    
1287
/* Allocate a register belonging to reg1 & ~reg2 */
1288
static int tcg_reg_alloc(TCGContext *s, TCGRegSet reg1, TCGRegSet reg2)
1289
{
1290
    int i, reg;
1291
    TCGRegSet reg_ct;
1292

    
1293
    tcg_regset_andnot(reg_ct, reg1, reg2);
1294

    
1295
    /* first try free registers */
1296
    for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1297
        reg = tcg_target_reg_alloc_order[i];
1298
        if (tcg_regset_test_reg(reg_ct, reg) && s->reg_to_temp[reg] == -1)
1299
            return reg;
1300
    }
1301

    
1302
    /* XXX: do better spill choice */
1303
    for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1304
        reg = tcg_target_reg_alloc_order[i];
1305
        if (tcg_regset_test_reg(reg_ct, reg)) {
1306
            tcg_reg_free(s, reg);
1307
            return reg;
1308
        }
1309
    }
1310

    
1311
    tcg_abort();
1312
}
1313

    
1314
/* save a temporary to memory. 'allocated_regs' is used in case a
1315
   temporary registers needs to be allocated to store a constant. */
1316
static void temp_save(TCGContext *s, int temp, TCGRegSet allocated_regs)
1317
{
1318
    TCGTemp *ts;
1319
    int reg;
1320

    
1321
    ts = &s->temps[temp];
1322
    if (!ts->fixed_reg) {
1323
        switch(ts->val_type) {
1324
        case TEMP_VAL_REG:
1325
            tcg_reg_free(s, ts->reg);
1326
            break;
1327
        case TEMP_VAL_DEAD:
1328
            ts->val_type = TEMP_VAL_MEM;
1329
            break;
1330
        case TEMP_VAL_CONST:
1331
            reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], 
1332
                                allocated_regs);
1333
            if (!ts->mem_allocated) 
1334
                temp_allocate_frame(s, temp);
1335
            tcg_out_movi(s, ts->type, reg, ts->val);
1336
            tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1337
            ts->val_type = TEMP_VAL_MEM;
1338
            break;
1339
        case TEMP_VAL_MEM:
1340
            break;
1341
        default:
1342
            tcg_abort();
1343
        }
1344
    }
1345
}
1346

    
1347
/* save globals to their cannonical location and assume they can be
1348
   modified be the following code. 'allocated_regs' is used in case a
1349
   temporary registers needs to be allocated to store a constant. */
1350
static void save_globals(TCGContext *s, TCGRegSet allocated_regs)
1351
{
1352
    int i;
1353

    
1354
    for(i = 0; i < s->nb_globals; i++) {
1355
        temp_save(s, i, allocated_regs);
1356
    }
1357
}
1358

    
1359
/* at the end of a basic block, we assume all temporaries are dead and
1360
   all globals are stored at their canonical location. */
1361
static void tcg_reg_alloc_bb_end(TCGContext *s, TCGRegSet allocated_regs)
1362
{
1363
    TCGTemp *ts;
1364
    int i;
1365

    
1366
    for(i = s->nb_globals; i < s->nb_temps; i++) {
1367
        ts = &s->temps[i];
1368
        if (ts->temp_local) {
1369
            temp_save(s, i, allocated_regs);
1370
        } else {
1371
            if (ts->val_type == TEMP_VAL_REG) {
1372
                s->reg_to_temp[ts->reg] = -1;
1373
            }
1374
            ts->val_type = TEMP_VAL_DEAD;
1375
        }
1376
    }
1377

    
1378
    save_globals(s, allocated_regs);
1379
}
1380

    
1381
#define IS_DEAD_IARG(n) ((dead_iargs >> (n)) & 1)
1382

    
1383
static void tcg_reg_alloc_movi(TCGContext *s, const TCGArg *args)
1384
{
1385
    TCGTemp *ots;
1386
    tcg_target_ulong val;
1387

    
1388
    ots = &s->temps[args[0]];
1389
    val = args[1];
1390

    
1391
    if (ots->fixed_reg) {
1392
        /* for fixed registers, we do not do any constant
1393
           propagation */
1394
        tcg_out_movi(s, ots->type, ots->reg, val);
1395
    } else {
1396
        /* The movi is not explicitly generated here */
1397
        if (ots->val_type == TEMP_VAL_REG)
1398
            s->reg_to_temp[ots->reg] = -1;
1399
        ots->val_type = TEMP_VAL_CONST;
1400
        ots->val = val;
1401
    }
1402
}
1403

    
1404
static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
1405
                              const TCGArg *args,
1406
                              unsigned int dead_iargs)
1407
{
1408
    TCGTemp *ts, *ots;
1409
    int reg;
1410
    const TCGArgConstraint *arg_ct;
1411

    
1412
    ots = &s->temps[args[0]];
1413
    ts = &s->temps[args[1]];
1414
    arg_ct = &def->args_ct[0];
1415

    
1416
    /* XXX: always mark arg dead if IS_DEAD_IARG(0) */
1417
    if (ts->val_type == TEMP_VAL_REG) {
1418
        if (IS_DEAD_IARG(0) && !ts->fixed_reg && !ots->fixed_reg) {
1419
            /* the mov can be suppressed */
1420
            if (ots->val_type == TEMP_VAL_REG)
1421
                s->reg_to_temp[ots->reg] = -1;
1422
            reg = ts->reg;
1423
            s->reg_to_temp[reg] = -1;
1424
            ts->val_type = TEMP_VAL_DEAD;
1425
        } else {
1426
            if (ots->val_type == TEMP_VAL_REG) {
1427
                reg = ots->reg;
1428
            } else {
1429
                reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1430
            }
1431
            if (ts->reg != reg) {
1432
                tcg_out_mov(s, reg, ts->reg);
1433
            }
1434
        }
1435
    } else if (ts->val_type == TEMP_VAL_MEM) {
1436
        if (ots->val_type == TEMP_VAL_REG) {
1437
            reg = ots->reg;
1438
        } else {
1439
            reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1440
        }
1441
        tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1442
    } else if (ts->val_type == TEMP_VAL_CONST) {
1443
        if (ots->fixed_reg) {
1444
            reg = ots->reg;
1445
            tcg_out_movi(s, ots->type, reg, ts->val);
1446
        } else {
1447
            /* propagate constant */
1448
            if (ots->val_type == TEMP_VAL_REG)
1449
                s->reg_to_temp[ots->reg] = -1;
1450
            ots->val_type = TEMP_VAL_CONST;
1451
            ots->val = ts->val;
1452
            return;
1453
        }
1454
    } else {
1455
        tcg_abort();
1456
    }
1457
    s->reg_to_temp[reg] = args[0];
1458
    ots->reg = reg;
1459
    ots->val_type = TEMP_VAL_REG;
1460
    ots->mem_coherent = 0;
1461
}
1462

    
1463
static void tcg_reg_alloc_op(TCGContext *s, 
1464
                             const TCGOpDef *def, int opc,
1465
                             const TCGArg *args,
1466
                             unsigned int dead_iargs)
1467
{
1468
    TCGRegSet allocated_regs;
1469
    int i, k, nb_iargs, nb_oargs, reg;
1470
    TCGArg arg;
1471
    const TCGArgConstraint *arg_ct;
1472
    TCGTemp *ts;
1473
    TCGArg new_args[TCG_MAX_OP_ARGS];
1474
    int const_args[TCG_MAX_OP_ARGS];
1475

    
1476
    nb_oargs = def->nb_oargs;
1477
    nb_iargs = def->nb_iargs;
1478

    
1479
    /* copy constants */
1480
    memcpy(new_args + nb_oargs + nb_iargs, 
1481
           args + nb_oargs + nb_iargs, 
1482
           sizeof(TCGArg) * def->nb_cargs);
1483

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

    
1611
    /* emit instruction */
1612
    tcg_out_op(s, opc, new_args, const_args);
1613
    
1614
    /* move the outputs in the correct register if needed */
1615
    for(i = 0; i < nb_oargs; i++) {
1616
        ts = &s->temps[args[i]];
1617
        reg = new_args[i];
1618
        if (ts->fixed_reg && ts->reg != reg) {
1619
            tcg_out_mov(s, ts->reg, reg);
1620
        }
1621
    }
1622
}
1623

    
1624
#ifdef TCG_TARGET_STACK_GROWSUP
1625
#define STACK_DIR(x) (-(x))
1626
#else
1627
#define STACK_DIR(x) (x)
1628
#endif
1629

    
1630
static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
1631
                              int opc, const TCGArg *args,
1632
                              unsigned int dead_iargs)
1633
{
1634
    int nb_iargs, nb_oargs, flags, nb_regs, i, reg, nb_params;
1635
    TCGArg arg, func_arg;
1636
    TCGTemp *ts;
1637
    tcg_target_long stack_offset, call_stack_size, func_addr;
1638
    int const_func_arg, allocate_args;
1639
    TCGRegSet allocated_regs;
1640
    const TCGArgConstraint *arg_ct;
1641

    
1642
    arg = *args++;
1643

    
1644
    nb_oargs = arg >> 16;
1645
    nb_iargs = arg & 0xffff;
1646
    nb_params = nb_iargs - 1;
1647

    
1648
    flags = args[nb_oargs + nb_iargs];
1649

    
1650
    nb_regs = tcg_target_get_call_iarg_regs_count(flags);
1651
    if (nb_regs > nb_params)
1652
        nb_regs = nb_params;
1653

    
1654
    /* assign stack slots first */
1655
    /* XXX: preallocate call stack */
1656
    call_stack_size = (nb_params - nb_regs) * sizeof(tcg_target_long);
1657
    call_stack_size = (call_stack_size + TCG_TARGET_STACK_ALIGN - 1) & 
1658
        ~(TCG_TARGET_STACK_ALIGN - 1);
1659
    allocate_args = (call_stack_size > TCG_STATIC_CALL_ARGS_SIZE);
1660
    if (allocate_args) {
1661
        tcg_out_addi(s, TCG_REG_CALL_STACK, -STACK_DIR(call_stack_size));
1662
    }
1663

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

    
1777
    tcg_out_op(s, opc, &func_arg, &const_func_arg);
1778
    
1779
    if (allocate_args) {
1780
        tcg_out_addi(s, TCG_REG_CALL_STACK, STACK_DIR(call_stack_size));
1781
    }
1782

    
1783
    /* assign output registers and emit moves if needed */
1784
    for(i = 0; i < nb_oargs; i++) {
1785
        arg = args[i];
1786
        ts = &s->temps[arg];
1787
        reg = tcg_target_call_oarg_regs[i];
1788
        assert(s->reg_to_temp[reg] == -1);
1789
        if (ts->fixed_reg) {
1790
            if (ts->reg != reg) {
1791
                tcg_out_mov(s, ts->reg, reg);
1792
            }
1793
        } else {
1794
            if (ts->val_type == TEMP_VAL_REG)
1795
                s->reg_to_temp[ts->reg] = -1;
1796
            ts->val_type = TEMP_VAL_REG;
1797
            ts->reg = reg;
1798
            ts->mem_coherent = 0; 
1799
            s->reg_to_temp[reg] = arg;
1800
        }
1801
    }
1802
    
1803
    return nb_iargs + nb_oargs + def->nb_cargs + 1;
1804
}
1805

    
1806
#ifdef CONFIG_PROFILER
1807

    
1808
static int64_t dyngen_table_op_count[NB_OPS];
1809

    
1810
void dump_op_count(void)
1811
{
1812
    int i;
1813
    FILE *f;
1814
    f = fopen("/tmp/op1.log", "w");
1815
    for(i = 0; i < INDEX_op_end; i++) {
1816
        fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name, dyngen_table_op_count[i]);
1817
    }
1818
    fclose(f);
1819
    f = fopen("/tmp/op2.log", "w");
1820
    for(i = INDEX_op_end; i < NB_OPS; i++) {
1821
        fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name, dyngen_table_op_count[i]);
1822
    }
1823
    fclose(f);
1824
}
1825
#endif
1826

    
1827

    
1828
static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
1829
                                      long search_pc)
1830
{
1831
    int opc, op_index;
1832
    const TCGOpDef *def;
1833
    unsigned int dead_iargs;
1834
    const TCGArg *args;
1835

    
1836
#ifdef DEBUG_DISAS
1837
    if (unlikely(loglevel & CPU_LOG_TB_OP)) {
1838
        fprintf(logfile, "OP:\n");
1839
        tcg_dump_ops(s, logfile);
1840
        fprintf(logfile, "\n");
1841
    }
1842
#endif
1843

    
1844
#ifdef CONFIG_PROFILER
1845
    s->la_time -= profile_getclock();
1846
#endif
1847
    tcg_liveness_analysis(s);
1848
#ifdef CONFIG_PROFILER
1849
    s->la_time += profile_getclock();
1850
#endif
1851

    
1852
#ifdef DEBUG_DISAS
1853
    if (unlikely(loglevel & CPU_LOG_TB_OP_OPT)) {
1854
        fprintf(logfile, "OP after la:\n");
1855
        tcg_dump_ops(s, logfile);
1856
        fprintf(logfile, "\n");
1857
    }
1858
#endif
1859

    
1860
    tcg_reg_alloc_start(s);
1861

    
1862
    s->code_buf = gen_code_buf;
1863
    s->code_ptr = gen_code_buf;
1864

    
1865
    args = gen_opparam_buf;
1866
    op_index = 0;
1867

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

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

    
1964
int dyngen_code(TCGContext *s, uint8_t *gen_code_buf)
1965
{
1966
#ifdef CONFIG_PROFILER
1967
    {
1968
        int n;
1969
        n = (gen_opc_ptr - gen_opc_buf);
1970
        s->op_count += n;
1971
        if (n > s->op_count_max)
1972
            s->op_count_max = n;
1973

    
1974
        s->temp_count += s->nb_temps;
1975
        if (s->nb_temps > s->temp_count_max)
1976
            s->temp_count_max = s->nb_temps;
1977
    }
1978
#endif
1979

    
1980
    tcg_gen_code_common(s, gen_code_buf, -1);
1981

    
1982
    /* flush instruction cache */
1983
    flush_icache_range((unsigned long)gen_code_buf, 
1984
                       (unsigned long)s->code_ptr);
1985
    return s->code_ptr -  gen_code_buf;
1986
}
1987

    
1988
/* Return the index of the micro operation such as the pc after is <
1989
   offset bytes from the start of the TB.  The contents of gen_code_buf must
1990
   not be changed, though writing the same values is ok.
1991
   Return -1 if not found. */
1992
int dyngen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, long offset)
1993
{
1994
    return tcg_gen_code_common(s, gen_code_buf, offset);
1995
}
1996

    
1997
#ifdef CONFIG_PROFILER
1998
void tcg_dump_info(FILE *f,
1999
                   int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
2000
{
2001
    TCGContext *s = &tcg_ctx;
2002
    int64_t tot;
2003

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