Statistics
| Branch: | Revision:

root / tcg / tcg.c @ a23a9ec6

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

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

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

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

    
54

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

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

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

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

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

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

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

    
90
/* label relocation processing */
91

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

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

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

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

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

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

    
148
#include "tcg-target.c"
149

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

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

    
199
/* free all the pool */
200
void tcg_pool_free(TCGContext *s)
201
{
202
    TCGPool *p, *p1;
203

    
204
    for(p = s->pool_first; p != NULL; p = p1) {
205
        p1 = p->next;
206
        qemu_free(p);
207
    }
208
    s->pool_first = NULL;
209
    s->pool_cur = s->pool_end = NULL;
210
}
211

    
212
void tcg_context_init(TCGContext *s)
213
{
214
    int op, total_args, n;
215
    TCGOpDef *def;
216
    TCGArgConstraint *args_ct;
217
    int *sorted_args;
218

    
219
    memset(s, 0, sizeof(*s));
220
    s->temps = s->static_temps;
221
    s->nb_globals = 0;
222
    
223
    /* Count total number of arguments and allocate the corresponding
224
       space */
225
    total_args = 0;
226
    for(op = 0; op < NB_OPS; op++) {
227
        def = &tcg_op_defs[op];
228
        n = def->nb_iargs + def->nb_oargs;
229
        total_args += n;
230
    }
231

    
232
    args_ct = qemu_malloc(sizeof(TCGArgConstraint) * total_args);
233
    sorted_args = qemu_malloc(sizeof(int) * total_args);
234

    
235
    for(op = 0; op < NB_OPS; op++) {
236
        def = &tcg_op_defs[op];
237
        def->args_ct = args_ct;
238
        def->sorted_args = sorted_args;
239
        n = def->nb_iargs + def->nb_oargs;
240
        sorted_args += n;
241
        args_ct += n;
242
    }
243
    
244
    tcg_target_init(s);
245

    
246
    /* init global prologue and epilogue */
247
    s->code_buf = code_gen_prologue;
248
    s->code_ptr = s->code_buf;
249
    tcg_target_qemu_prologue(s);
250
    flush_icache_range((unsigned long)s->code_buf, 
251
                       (unsigned long)s->code_ptr);
252
}
253

    
254
void tcg_set_frame(TCGContext *s, int reg,
255
                   tcg_target_long start, tcg_target_long size)
256
{
257
    s->frame_start = start;
258
    s->frame_end = start + size;
259
    s->frame_reg = reg;
260
}
261

    
262
void tcg_set_macro_func(TCGContext *s, TCGMacroFunc *func)
263
{
264
    s->macro_func = func;
265
}
266

    
267
void tcg_func_start(TCGContext *s)
268
{
269
    tcg_pool_reset(s);
270
    s->nb_temps = s->nb_globals;
271
    s->labels = tcg_malloc(sizeof(TCGLabel) * TCG_MAX_LABELS);
272
    s->nb_labels = 0;
273
    s->current_frame_offset = s->frame_start;
274

    
275
    gen_opc_ptr = gen_opc_buf;
276
    gen_opparam_ptr = gen_opparam_buf;
277
}
278

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

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

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

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

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

    
335
    ts++;
336
    ts->base_type = type;
337
    ts->type = TCG_TYPE_I32;
338
    ts->fixed_reg = 1;
339
    ts->reg = reg2;
340
    ts->val_type = TEMP_VAL_REG;
341
    pstrcpy(buf, sizeof(buf), name);
342
    pstrcat(buf, sizeof(buf), "_1");
343
    ts->name = strdup(buf);
344

    
345
    s->nb_globals += 2;
346
    return MAKE_TCGV(idx);
347
}
348
#endif
349

    
350
TCGv tcg_global_mem_new(TCGType type, int reg, tcg_target_long offset,
351
                        const char *name)
352
{
353
    TCGContext *s = &tcg_ctx;
354
    TCGTemp *ts;
355
    int idx;
356

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

    
379
        ts->base_type = type;
380
        ts->type = TCG_TYPE_I32;
381
        ts->fixed_reg = 0;
382
        ts->mem_allocated = 1;
383
        ts->mem_reg = reg;
384
#ifdef TCG_TARGET_WORDS_BIGENDIAN
385
        ts->mem_offset = offset;
386
#else
387
        ts->mem_offset = offset + 4;
388
#endif
389
        ts->val_type = TEMP_VAL_MEM;
390
        pstrcpy(buf, sizeof(buf), name);
391
        pstrcat(buf, sizeof(buf), "_1");
392
        ts->name = strdup(buf);
393

    
394
        s->nb_globals += 2;
395
    } else
396
#endif
397
    {
398
        tcg_temp_alloc(s, s->nb_globals + 1);
399
        ts = &s->temps[s->nb_globals];
400
        ts->base_type = type;
401
        ts->type = type;
402
        ts->fixed_reg = 0;
403
        ts->mem_allocated = 1;
404
        ts->mem_reg = reg;
405
        ts->mem_offset = offset;
406
        ts->val_type = TEMP_VAL_MEM;
407
        ts->name = name;
408
        s->nb_globals++;
409
    }
410
    return MAKE_TCGV(idx);
411
}
412

    
413
TCGv tcg_temp_new(TCGType type)
414
{
415
    TCGContext *s = &tcg_ctx;
416
    TCGTemp *ts;
417
    int idx;
418

    
419
    idx = s->nb_temps;
420
#if TCG_TARGET_REG_BITS == 32
421
    if (type == TCG_TYPE_I64) {
422
        tcg_temp_alloc(s, s->nb_temps + 1);
423
        ts = &s->temps[s->nb_temps];
424
        ts->base_type = type;
425
        ts->type = TCG_TYPE_I32;
426
        ts->fixed_reg = 0;
427
        ts->val_type = TEMP_VAL_DEAD;
428
        ts->mem_allocated = 0;
429
        ts->name = NULL;
430
        ts++;
431
        ts->base_type = TCG_TYPE_I32;
432
        ts->type = TCG_TYPE_I32;
433
        ts->val_type = TEMP_VAL_DEAD;
434
        ts->fixed_reg = 0;
435
        ts->mem_allocated = 0;
436
        ts->name = NULL;
437
        s->nb_temps += 2;
438
    } else
439
#endif
440
    {
441
        tcg_temp_alloc(s, s->nb_temps + 1);
442
        ts = &s->temps[s->nb_temps];
443
        ts->base_type = type;
444
        ts->type = type;
445
        ts->fixed_reg = 0;
446
        ts->val_type = TEMP_VAL_DEAD;
447
        ts->mem_allocated = 0;
448
        ts->name = NULL;
449
        s->nb_temps++;
450
    }
451
    return MAKE_TCGV(idx);
452
}
453

    
454
TCGv tcg_const_i32(int32_t val)
455
{
456
    TCGContext *s = &tcg_ctx;
457
    TCGTemp *ts;
458
    int idx;
459

    
460
    idx = s->nb_temps;
461
    tcg_temp_alloc(s, idx + 1);
462
    ts = &s->temps[idx];
463
    ts->base_type = ts->type = TCG_TYPE_I32;
464
    ts->val_type = TEMP_VAL_CONST;
465
    ts->name = NULL;
466
    ts->val = val;
467
    s->nb_temps++;
468
    return MAKE_TCGV(idx);
469
}
470

    
471
TCGv tcg_const_i64(int64_t val)
472
{
473
    TCGContext *s = &tcg_ctx;
474
    TCGTemp *ts;
475
    int idx;
476

    
477
    idx = s->nb_temps;
478
#if TCG_TARGET_REG_BITS == 32
479
    tcg_temp_alloc(s, idx + 2);
480
    ts = &s->temps[idx];
481
    ts->base_type = TCG_TYPE_I64;
482
    ts->type = TCG_TYPE_I32;
483
    ts->val_type = TEMP_VAL_CONST;
484
    ts->name = NULL;
485
    ts->val = val;
486
    ts++;
487
    ts->base_type = TCG_TYPE_I32;
488
    ts->type = TCG_TYPE_I32;
489
    ts->val_type = TEMP_VAL_CONST;
490
    ts->name = NULL;
491
    ts->val = val >> 32;
492
    s->nb_temps += 2;
493
#else
494
    tcg_temp_alloc(s, idx + 1);
495
    ts = &s->temps[idx];
496
    ts->base_type = ts->type = TCG_TYPE_I64;
497
    ts->val_type = TEMP_VAL_CONST;
498
    ts->name = NULL;
499
    ts->val = val;
500
    s->nb_temps++;
501
#endif    
502
    return MAKE_TCGV(idx);
503
}
504

    
505
void tcg_register_helper(void *func, const char *name)
506
{
507
    TCGContext *s = &tcg_ctx;
508
    int n;
509
    if ((s->nb_helpers + 1) > s->allocated_helpers) {
510
        n = s->allocated_helpers;
511
        if (n == 0) {
512
            n = 4;
513
        } else {
514
            n *= 2;
515
        }
516
        s->helpers = realloc(s->helpers, n * sizeof(TCGHelperInfo));
517
        s->allocated_helpers = n;
518
    }
519
    s->helpers[s->nb_helpers].func = (tcg_target_ulong)func;
520
    s->helpers[s->nb_helpers].name = name;
521
    s->nb_helpers++;
522
}
523

    
524
static inline TCGType tcg_get_base_type(TCGContext *s, TCGv arg)
525
{
526
    return s->temps[GET_TCGV(arg)].base_type;
527
}
528

    
529
static void tcg_gen_call_internal(TCGContext *s, TCGv func, 
530
                                  unsigned int flags,
531
                                  unsigned int nb_rets, const TCGv *rets,
532
                                  unsigned int nb_params, const TCGv *params)
533
{
534
    int i;
535
    *gen_opc_ptr++ = INDEX_op_call;
536
    *gen_opparam_ptr++ = (nb_rets << 16) | (nb_params + 1);
537
    for(i = 0; i < nb_rets; i++) {
538
        *gen_opparam_ptr++ = GET_TCGV(rets[i]);
539
    }
540
    for(i = 0; i < nb_params; i++) {
541
        *gen_opparam_ptr++ = GET_TCGV(params[i]);
542
    }
543
    *gen_opparam_ptr++ = GET_TCGV(func);
544

    
545
    *gen_opparam_ptr++ = flags;
546
    /* total parameters, needed to go backward in the instruction stream */
547
    *gen_opparam_ptr++ = 1 + nb_rets + nb_params + 3;
548
}
549

    
550

    
551
#if TCG_TARGET_REG_BITS < 64
552
/* Note: we convert the 64 bit args to 32 bit and do some alignment
553
   and endian swap. Maybe it would be better to do the alignment
554
   and endian swap in tcg_reg_alloc_call(). */
555
void tcg_gen_call(TCGContext *s, TCGv func, unsigned int flags,
556
                  unsigned int nb_rets, const TCGv *rets,
557
                  unsigned int nb_params, const TCGv *args1)
558
{
559
    TCGv ret, *args2, rets_2[2], arg;
560
    int j, i, call_type;
561

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

    
623
#if TCG_TARGET_REG_BITS == 32
624
void tcg_gen_shifti_i64(TCGv ret, TCGv arg1, 
625
                        int c, int right, int arith)
626
{
627
    if (c == 0) {
628
        tcg_gen_mov_i32(ret, arg1);
629
        tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
630
    } else if (c >= 32) {
631
        c -= 32;
632
        if (right) {
633
            if (arith) {
634
                tcg_gen_sari_i32(ret, TCGV_HIGH(arg1), c);
635
                tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 31);
636
            } else {
637
                tcg_gen_shri_i32(ret, TCGV_HIGH(arg1), c);
638
                tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
639
            }
640
        } else {
641
            tcg_gen_shli_i32(TCGV_HIGH(ret), arg1, c);
642
            tcg_gen_movi_i32(ret, 0);
643
        }
644
    } else {
645
        TCGv t0, t1;
646

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

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

    
687
static char *tcg_get_arg_str_idx(TCGContext *s, char *buf, int buf_size,
688
                                 int idx)
689
{
690
    TCGTemp *ts;
691

    
692
    ts = &s->temps[idx];
693
    if (idx < s->nb_globals) {
694
        pstrcpy(buf, buf_size, ts->name);
695
    } else {
696
        if (ts->val_type == TEMP_VAL_CONST) {
697
            snprintf(buf, buf_size, "$0x%" TCG_PRIlx , ts->val);
698
        } else {
699
            snprintf(buf, buf_size, "tmp%d", idx - s->nb_globals);
700
        }
701
    }
702
    return buf;
703
}
704

    
705
char *tcg_get_arg_str(TCGContext *s, char *buf, int buf_size, TCGv arg)
706
{
707
    return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV(arg));
708
}
709

    
710
/* find helper definition (XXX: inefficient) */
711
static TCGHelperInfo *tcg_find_helper(TCGContext *s, tcg_target_ulong val)
712
{
713
    int i;
714
    for(i = 0; i < s->nb_helpers; i++) {
715
        if (s->helpers[i].func == val) 
716
            return &s->helpers[i];
717
    }
718
    return NULL;
719
}
720

    
721
static const char *tcg_get_helper_str_idx(TCGContext *s, char *buf, int buf_size,
722
                                          int idx)
723
{
724
    TCGTemp *ts;
725
    TCGHelperInfo *th;
726

    
727
    ts = &s->temps[idx];
728
    if (ts->val_type == TEMP_VAL_CONST) {
729
        /* find helper name (XXX: inefficient) */
730
        th = tcg_find_helper(s, ts->val);
731
        if (th) {
732
            pstrcpy(buf, buf_size, "$");
733
            pstrcat(buf, buf_size, th->name);
734
            return buf;
735
        }
736
    }
737
    return tcg_get_arg_str_idx(s, buf, buf_size, idx);
738
}
739

    
740

    
741
void tcg_dump_ops(TCGContext *s, FILE *outfile)
742
{
743
    const uint16_t *opc_ptr;
744
    const TCGArg *args;
745
    TCGArg arg;
746
    int c, i, k, nb_oargs, nb_iargs, nb_cargs, first_insn;
747
    const TCGOpDef *def;
748
    char buf[128];
749

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

    
773
            /* variable number of arguments */
774
            arg = *args++;
775
            nb_oargs = arg >> 16;
776
            nb_iargs = arg & 0xffff;
777
            nb_cargs = def->nb_cargs;
778

    
779
            fprintf(outfile, " %s ", def->name);
780

    
781
            /* function name */
782
            fprintf(outfile, "%s",
783
                    tcg_get_helper_str_idx(s, buf, sizeof(buf), args[nb_oargs + nb_iargs - 1]));
784
            /* flags */
785
            fprintf(outfile, ",$0x%" TCG_PRIlx,
786
                    args[nb_oargs + nb_iargs]);
787
            /* nb out args */
788
            fprintf(outfile, ",$%d", nb_oargs);
789
            for(i = 0; i < nb_oargs; i++) {
790
                fprintf(outfile, ",");
791
                fprintf(outfile, "%s",
792
                        tcg_get_arg_str_idx(s, buf, sizeof(buf), args[i]));
793
            }
794
            for(i = 0; i < (nb_iargs - 1); i++) {
795
                fprintf(outfile, ",");
796
                if (args[nb_oargs + i] == TCG_CALL_DUMMY_ARG) {
797
                    fprintf(outfile, "<dummy>");
798
                } else {
799
                    fprintf(outfile, "%s",
800
                            tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + i]));
801
                }
802
            }
803
        } else {
804
            fprintf(outfile, " %s ", def->name);
805
            if (c == INDEX_op_nopn) {
806
                /* variable number of arguments */
807
                nb_cargs = *args;
808
                nb_oargs = 0;
809
                nb_iargs = 0;
810
            } else {
811
                nb_oargs = def->nb_oargs;
812
                nb_iargs = def->nb_iargs;
813
                nb_cargs = def->nb_cargs;
814
            }
815
            
816
            k = 0;
817
            for(i = 0; i < nb_oargs; i++) {
818
                if (k != 0)
819
                    fprintf(outfile, ",");
820
                fprintf(outfile, "%s",
821
                        tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
822
            }
823
            for(i = 0; i < nb_iargs; i++) {
824
                if (k != 0)
825
                    fprintf(outfile, ",");
826
                fprintf(outfile, "%s",
827
                        tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
828
            }
829
            for(i = 0; i < nb_cargs; i++) {
830
                if (k != 0)
831
                    fprintf(outfile, ",");
832
                arg = args[k++];
833
                fprintf(outfile, "$0x%" TCG_PRIlx, arg);
834
            }
835
        }
836
        fprintf(outfile, "\n");
837
        args += nb_iargs + nb_oargs + nb_cargs;
838
    }
839
}
840

    
841
/* we give more priority to constraints with less registers */
842
static int get_constraint_priority(const TCGOpDef *def, int k)
843
{
844
    const TCGArgConstraint *arg_ct;
845

    
846
    int i, n;
847
    arg_ct = &def->args_ct[k];
848
    if (arg_ct->ct & TCG_CT_ALIAS) {
849
        /* an alias is equivalent to a single register */
850
        n = 1;
851
    } else {
852
        if (!(arg_ct->ct & TCG_CT_REG))
853
            return 0;
854
        n = 0;
855
        for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
856
            if (tcg_regset_test_reg(arg_ct->u.regs, i))
857
                n++;
858
        }
859
    }
860
    return TCG_TARGET_NB_REGS - n + 1;
861
}
862

    
863
/* sort from highest priority to lowest */
864
static void sort_constraints(TCGOpDef *def, int start, int n)
865
{
866
    int i, j, p1, p2, tmp;
867

    
868
    for(i = 0; i < n; i++)
869
        def->sorted_args[start + i] = start + i;
870
    if (n <= 1)
871
        return;
872
    for(i = 0; i < n - 1; i++) {
873
        for(j = i + 1; j < n; j++) {
874
            p1 = get_constraint_priority(def, def->sorted_args[start + i]);
875
            p2 = get_constraint_priority(def, def->sorted_args[start + j]);
876
            if (p1 < p2) {
877
                tmp = def->sorted_args[start + i];
878
                def->sorted_args[start + i] = def->sorted_args[start + j];
879
                def->sorted_args[start + j] = tmp;
880
            }
881
        }
882
    }
883
}
884

    
885
void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs)
886
{
887
    int op;
888
    TCGOpDef *def;
889
    const char *ct_str;
890
    int i, nb_args;
891

    
892
    for(;;) {
893
        if (tdefs->op < 0)
894
            break;
895
        op = tdefs->op;
896
        assert(op >= 0 && op < NB_OPS);
897
        def = &tcg_op_defs[op];
898
        nb_args = def->nb_iargs + def->nb_oargs;
899
        for(i = 0; i < nb_args; i++) {
900
            ct_str = tdefs->args_ct_str[i];
901
            tcg_regset_clear(def->args_ct[i].u.regs);
902
            def->args_ct[i].ct = 0;
903
            if (ct_str[0] >= '0' && ct_str[0] <= '9') {
904
                int oarg;
905
                oarg = ct_str[0] - '0';
906
                assert(oarg < def->nb_oargs);
907
                assert(def->args_ct[oarg].ct & TCG_CT_REG);
908
                /* TCG_CT_ALIAS is for the output arguments. The input
909
                   argument is tagged with TCG_CT_IALIAS. */
910
                def->args_ct[i] = def->args_ct[oarg];
911
                def->args_ct[oarg].ct = TCG_CT_ALIAS;
912
                def->args_ct[oarg].alias_index = i;
913
                def->args_ct[i].ct |= TCG_CT_IALIAS;
914
                def->args_ct[i].alias_index = oarg;
915
            } else {
916
                for(;;) {
917
                    if (*ct_str == '\0')
918
                        break;
919
                    switch(*ct_str) {
920
                    case 'i':
921
                        def->args_ct[i].ct |= TCG_CT_CONST;
922
                        ct_str++;
923
                        break;
924
                    default:
925
                        if (target_parse_constraint(&def->args_ct[i], &ct_str) < 0) {
926
                            fprintf(stderr, "Invalid constraint '%s' for arg %d of operation '%s'\n",
927
                                    ct_str, i, def->name);
928
                            exit(1);
929
                        }
930
                    }
931
                }
932
            }
933
        }
934

    
935
        /* sort the constraints (XXX: this is just an heuristic) */
936
        sort_constraints(def, 0, def->nb_oargs);
937
        sort_constraints(def, def->nb_oargs, def->nb_iargs);
938

    
939
#if 0
940
        {
941
            int i;
942

943
            printf("%s: sorted=", def->name);
944
            for(i = 0; i < def->nb_oargs + def->nb_iargs; i++)
945
                printf(" %d", def->sorted_args[i]);
946
            printf("\n");
947
        }
948
#endif
949
        tdefs++;
950
    }
951

    
952
}
953

    
954
#ifdef USE_LIVENESS_ANALYSIS
955

    
956
/* set a nop for an operation using 'nb_args' */
957
static inline void tcg_set_nop(TCGContext *s, uint16_t *opc_ptr, 
958
                               TCGArg *args, int nb_args)
959
{
960
    if (nb_args == 0) {
961
        *opc_ptr = INDEX_op_nop;
962
    } else {
963
        *opc_ptr = INDEX_op_nopn;
964
        args[0] = nb_args;
965
        args[nb_args - 1] = nb_args;
966
    }
967
}
968

    
969
/* liveness analysis: end of basic block: globals are live, temps are dead */
970
static inline void tcg_la_bb_end(TCGContext *s, uint8_t *dead_temps)
971
{
972
    memset(dead_temps, 0, s->nb_globals);
973
    memset(dead_temps + s->nb_globals, 1, s->nb_temps - s->nb_globals);
974
}
975

    
976
/* Liveness analysis : update the opc_dead_iargs array to tell if a
977
   given input arguments is dead. Instructions updating dead
978
   temporaries are removed. */
979
void tcg_liveness_analysis(TCGContext *s)
980
{
981
    int i, op_index, op, nb_args, nb_iargs, nb_oargs, arg, nb_ops;
982
    TCGArg *args;
983
    const TCGOpDef *def;
984
    uint8_t *dead_temps;
985
    unsigned int dead_iargs;
986
    
987
    gen_opc_ptr++; /* skip end */
988

    
989
    nb_ops = gen_opc_ptr - gen_opc_buf;
990

    
991
    /* XXX: make it really dynamic */
992
    s->op_dead_iargs = tcg_malloc(OPC_BUF_SIZE * sizeof(uint16_t));
993
    
994
    dead_temps = tcg_malloc(s->nb_temps);
995
    memset(dead_temps, 1, s->nb_temps);
996

    
997
    args = gen_opparam_ptr;
998
    op_index = nb_ops - 1;
999
    while (op_index >= 0) {
1000
        op = gen_opc_buf[op_index];
1001
        def = &tcg_op_defs[op];
1002
        switch(op) {
1003
        case INDEX_op_call:
1004
            {
1005
                int call_flags;
1006

    
1007
                nb_args = args[-1];
1008
                args -= nb_args;
1009
                nb_iargs = args[0] & 0xffff;
1010
                nb_oargs = args[0] >> 16;
1011
                args++;
1012
                call_flags = args[nb_oargs + nb_iargs];
1013

    
1014
                /* pure functions can be removed if their result is not
1015
                   used */
1016
                if (call_flags & TCG_CALL_PURE) {
1017
                    for(i = 0; i < nb_oargs; i++) {
1018
                        arg = args[i];
1019
                        if (!dead_temps[arg])
1020
                            goto do_not_remove_call;
1021
                    }
1022
                    tcg_set_nop(s, gen_opc_buf + op_index, 
1023
                                args - 1, nb_args);
1024
                } else {
1025
                do_not_remove_call:
1026

    
1027
                    /* output args are dead */
1028
                    for(i = 0; i < nb_oargs; i++) {
1029
                        arg = args[i];
1030
                        dead_temps[arg] = 1;
1031
                    }
1032
                    
1033
                    /* globals are live (they may be used by the call) */
1034
                    memset(dead_temps, 0, s->nb_globals);
1035
                    
1036
                    /* input args are live */
1037
                    dead_iargs = 0;
1038
                    for(i = 0; i < nb_iargs; i++) {
1039
                        arg = args[i + nb_oargs];
1040
                        if (arg != TCG_CALL_DUMMY_ARG) {
1041
                            if (dead_temps[arg]) {
1042
                                dead_iargs |= (1 << i);
1043
                            }
1044
                            dead_temps[arg] = 0;
1045
                        }
1046
                    }
1047
                    s->op_dead_iargs[op_index] = dead_iargs;
1048
                }
1049
                args--;
1050
            }
1051
            break;
1052
        case INDEX_op_set_label:
1053
            args--;
1054
            /* mark end of basic block */
1055
            tcg_la_bb_end(s, dead_temps);
1056
            break;
1057
        case INDEX_op_debug_insn_start:
1058
            args -= def->nb_args;
1059
            break;
1060
        case INDEX_op_nopn:
1061
            nb_args = args[-1];
1062
            args -= nb_args;
1063
            break;
1064
        case INDEX_op_discard:
1065
            args--;
1066
            /* mark the temporary as dead */
1067
            dead_temps[args[0]] = 1;
1068
            break;
1069
        case INDEX_op_macro_2:
1070
            {
1071
                int dead_args[2], macro_id;
1072
                int saved_op_index, saved_arg_index;
1073
                int macro_op_index, macro_arg_index;
1074
                int macro_end_op_index, macro_end_arg_index;
1075
                int last_nb_temps;
1076
                
1077
                nb_args = 3;
1078
                args -= nb_args;
1079
                dead_args[0] = dead_temps[args[0]];
1080
                dead_args[1] = dead_temps[args[1]];
1081
                macro_id = args[2];
1082

    
1083
                /* call the macro function which generate code
1084
                   depending on the live outputs */
1085
                saved_op_index = op_index;
1086
                saved_arg_index = args - gen_opparam_buf;
1087

    
1088
                /* add a macro start instruction */
1089
                *gen_opc_ptr++ = INDEX_op_macro_start;
1090
                *gen_opparam_ptr++ = saved_op_index;
1091
                *gen_opparam_ptr++ = saved_arg_index;
1092

    
1093
                macro_op_index = gen_opc_ptr - gen_opc_buf;
1094
                macro_arg_index = gen_opparam_ptr -  gen_opparam_buf;
1095

    
1096
                last_nb_temps = s->nb_temps;
1097

    
1098
                s->macro_func(s, macro_id, dead_args);
1099

    
1100
                /* realloc temp info (XXX: make it faster) */
1101
                if (s->nb_temps > last_nb_temps) {
1102
                    uint8_t *new_dead_temps;
1103

    
1104
                    new_dead_temps = tcg_malloc(s->nb_temps);
1105
                    memcpy(new_dead_temps, dead_temps, last_nb_temps);
1106
                    memset(new_dead_temps + last_nb_temps, 1, 
1107
                           s->nb_temps - last_nb_temps);
1108
                    dead_temps = new_dead_temps;
1109
                }
1110

    
1111
                macro_end_op_index = gen_opc_ptr - gen_opc_buf;
1112
                macro_end_arg_index = gen_opparam_ptr - gen_opparam_buf;
1113

    
1114
                /* end of macro: add a goto to the next instruction */
1115
                *gen_opc_ptr++ = INDEX_op_macro_end;
1116
                *gen_opparam_ptr++ = op_index + 1;
1117
                *gen_opparam_ptr++ = saved_arg_index + nb_args;
1118

    
1119
                /* modify the macro operation to be a macro_goto */
1120
                gen_opc_buf[op_index] = INDEX_op_macro_goto;
1121
                args[0] = macro_op_index;
1122
                args[1] = macro_arg_index;
1123
                args[2] = 0; /* dummy third arg to match the 
1124
                                macro parameters */
1125

    
1126
                /* set the next instruction to the end of the macro */
1127
                op_index = macro_end_op_index;
1128
                args = macro_end_arg_index + gen_opparam_buf;
1129
            }
1130
            break;
1131
        case INDEX_op_macro_start:
1132
            args -= 2;
1133
            op_index = args[0];
1134
            args = gen_opparam_buf + args[1];
1135
            break;
1136
        case INDEX_op_macro_goto:
1137
        case INDEX_op_macro_end:
1138
            tcg_abort(); /* should never happen in liveness analysis */
1139
        case INDEX_op_end:
1140
            break;
1141
            /* XXX: optimize by hardcoding common cases (e.g. triadic ops) */
1142
        default:
1143
            if (op > INDEX_op_end) {
1144
                args -= def->nb_args;
1145
                nb_iargs = def->nb_iargs;
1146
                nb_oargs = def->nb_oargs;
1147

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

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

    
1200
    if (args != gen_opparam_buf)
1201
        tcg_abort();
1202
}
1203
#else
1204
/* dummy liveness analysis */
1205
void tcg_liveness_analysis(TCGContext *s)
1206
{
1207
    int nb_ops;
1208
    nb_ops = gen_opc_ptr - gen_opc_buf;
1209

    
1210
    s->op_dead_iargs = tcg_malloc(nb_ops * sizeof(uint16_t));
1211
    memset(s->op_dead_iargs, 0, nb_ops * sizeof(uint16_t));
1212
}
1213
#endif
1214

    
1215
#ifndef NDEBUG
1216
static void dump_regs(TCGContext *s)
1217
{
1218
    TCGTemp *ts;
1219
    int i;
1220
    char buf[64];
1221

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

    
1245
    for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
1246
        if (s->reg_to_temp[i] >= 0) {
1247
            printf("%s: %s\n", 
1248
                   tcg_target_reg_names[i], 
1249
                   tcg_get_arg_str_idx(s, buf, sizeof(buf), s->reg_to_temp[i]));
1250
        }
1251
    }
1252
}
1253

    
1254
static void check_regs(TCGContext *s)
1255
{
1256
    int reg, k;
1257
    TCGTemp *ts;
1258
    char buf[64];
1259

    
1260
    for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1261
        k = s->reg_to_temp[reg];
1262
        if (k >= 0) {
1263
            ts = &s->temps[k];
1264
            if (ts->val_type != TEMP_VAL_REG ||
1265
                ts->reg != reg) {
1266
                printf("Inconsistency for register %s:\n", 
1267
                       tcg_target_reg_names[reg]);
1268
                goto fail;
1269
            }
1270
        }
1271
    }
1272
    for(k = 0; k < s->nb_temps; k++) {
1273
        ts = &s->temps[k];
1274
        if (ts->val_type == TEMP_VAL_REG &&
1275
            !ts->fixed_reg &&
1276
            s->reg_to_temp[ts->reg] != k) {
1277
                printf("Inconsistency for temp %s:\n", 
1278
                       tcg_get_arg_str_idx(s, buf, sizeof(buf), k));
1279
        fail:
1280
                printf("reg state:\n");
1281
                dump_regs(s);
1282
                tcg_abort();
1283
        }
1284
        if (ts->val_type == TEMP_VAL_CONST && k < s->nb_globals) {
1285
            printf("constant forbidden in global %s\n",
1286
                   tcg_get_arg_str_idx(s, buf, sizeof(buf), k));
1287
            goto fail;
1288
        }
1289
    }
1290
}
1291
#endif
1292

    
1293
static void temp_allocate_frame(TCGContext *s, int temp)
1294
{
1295
    TCGTemp *ts;
1296
    ts = &s->temps[temp];
1297
    s->current_frame_offset = (s->current_frame_offset + sizeof(tcg_target_long) - 1) & ~(sizeof(tcg_target_long) - 1);
1298
    if (s->current_frame_offset + sizeof(tcg_target_long) > s->frame_end)
1299
        tcg_abort();
1300
    ts->mem_offset = s->current_frame_offset;
1301
    ts->mem_reg = s->frame_reg;
1302
    ts->mem_allocated = 1;
1303
    s->current_frame_offset += sizeof(tcg_target_long);
1304
}
1305

    
1306
/* free register 'reg' by spilling the corresponding temporary if necessary */
1307
static void tcg_reg_free(TCGContext *s, int reg)
1308
{
1309
    TCGTemp *ts;
1310
    int temp;
1311

    
1312
    temp = s->reg_to_temp[reg];
1313
    if (temp != -1) {
1314
        ts = &s->temps[temp];
1315
        assert(ts->val_type == TEMP_VAL_REG);
1316
        if (!ts->mem_coherent) {
1317
            if (!ts->mem_allocated) 
1318
                temp_allocate_frame(s, temp);
1319
            tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1320
        }
1321
        ts->val_type = TEMP_VAL_MEM;
1322
        s->reg_to_temp[reg] = -1;
1323
    }
1324
}
1325

    
1326
/* Allocate a register belonging to reg1 & ~reg2 */
1327
static int tcg_reg_alloc(TCGContext *s, TCGRegSet reg1, TCGRegSet reg2)
1328
{
1329
    int i, reg;
1330
    TCGRegSet reg_ct;
1331

    
1332
    tcg_regset_andnot(reg_ct, reg1, reg2);
1333

    
1334
    /* first try free registers */
1335
    for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1336
        reg = tcg_target_reg_alloc_order[i];
1337
        if (tcg_regset_test_reg(reg_ct, reg) && s->reg_to_temp[reg] == -1)
1338
            return reg;
1339
    }
1340

    
1341
    /* XXX: do better spill choice */
1342
    for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1343
        reg = tcg_target_reg_alloc_order[i];
1344
        if (tcg_regset_test_reg(reg_ct, reg)) {
1345
            tcg_reg_free(s, reg);
1346
            return reg;
1347
        }
1348
    }
1349

    
1350
    tcg_abort();
1351
}
1352

    
1353
/* save globals to their cannonical location and assume they can be
1354
   modified be the following code. */
1355
static void save_globals(TCGContext *s)
1356
{
1357
    TCGTemp *ts;
1358
    int i;
1359

    
1360
    for(i = 0; i < s->nb_globals; i++) {
1361
        ts = &s->temps[i];
1362
        if (!ts->fixed_reg) {
1363
            if (ts->val_type == TEMP_VAL_REG) {
1364
                tcg_reg_free(s, ts->reg);
1365
            } else if (ts->val_type == TEMP_VAL_DEAD) {
1366
                ts->val_type = TEMP_VAL_MEM;
1367
            }
1368
        }
1369
    }
1370
}
1371

    
1372
/* at the end of a basic block, we assume all temporaries are dead and
1373
   all globals are stored at their canonical location */
1374
/* XXX: optimize by handling constants in another array ? */
1375
void tcg_reg_alloc_bb_end(TCGContext *s)
1376
{
1377
    TCGTemp *ts;
1378
    int i;
1379

    
1380
    save_globals(s);
1381

    
1382
    for(i = s->nb_globals; i < s->nb_temps; i++) {
1383
        ts = &s->temps[i];
1384
        if (ts->val_type != TEMP_VAL_CONST) {
1385
            if (ts->val_type == TEMP_VAL_REG) {
1386
                s->reg_to_temp[ts->reg] = -1;
1387
            }
1388
            ts->val_type = TEMP_VAL_DEAD;
1389
        }
1390
    }
1391
}
1392

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

    
1395
static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
1396
                              const TCGArg *args,
1397
                              unsigned int dead_iargs)
1398
{
1399
    TCGTemp *ts, *ots;
1400
    int reg;
1401
    const TCGArgConstraint *arg_ct;
1402

    
1403
    ots = &s->temps[args[0]];
1404
    ts = &s->temps[args[1]];
1405
    arg_ct = &def->args_ct[0];
1406

    
1407
    if (ts->val_type == TEMP_VAL_REG) {
1408
        if (IS_DEAD_IARG(0) && !ts->fixed_reg && !ots->fixed_reg) {
1409
            /* the mov can be suppressed */
1410
            if (ots->val_type == TEMP_VAL_REG)
1411
                s->reg_to_temp[ots->reg] = -1;
1412
            reg = ts->reg;
1413
            s->reg_to_temp[reg] = -1;
1414
            ts->val_type = TEMP_VAL_DEAD;
1415
        } else {
1416
            if (ots->val_type == TEMP_VAL_REG) {
1417
                reg = ots->reg;
1418
            } else {
1419
                reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1420
            }
1421
            if (ts->reg != reg) {
1422
                tcg_out_mov(s, reg, ts->reg);
1423
            }
1424
        }
1425
    } else if (ts->val_type == TEMP_VAL_MEM) {
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
        tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1432
    } else if (ts->val_type == TEMP_VAL_CONST) {
1433
        if (ots->val_type == TEMP_VAL_REG) {
1434
            reg = ots->reg;
1435
        } else {
1436
            reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1437
        }
1438
        tcg_out_movi(s, ots->type, reg, ts->val);
1439
    } else {
1440
        tcg_abort();
1441
    }
1442
    s->reg_to_temp[reg] = args[0];
1443
    ots->reg = reg;
1444
    ots->val_type = TEMP_VAL_REG;
1445
    ots->mem_coherent = 0;
1446
}
1447

    
1448
static void tcg_reg_alloc_op(TCGContext *s, 
1449
                             const TCGOpDef *def, int opc,
1450
                             const TCGArg *args,
1451
                             unsigned int dead_iargs)
1452
{
1453
    TCGRegSet allocated_regs;
1454
    int i, k, nb_iargs, nb_oargs, reg;
1455
    TCGArg arg;
1456
    const TCGArgConstraint *arg_ct;
1457
    TCGTemp *ts;
1458
    TCGArg new_args[TCG_MAX_OP_ARGS];
1459
    int const_args[TCG_MAX_OP_ARGS];
1460

    
1461
    nb_oargs = def->nb_oargs;
1462
    nb_iargs = def->nb_iargs;
1463

    
1464
    /* copy constants */
1465
    memcpy(new_args + nb_oargs + nb_iargs, 
1466
           args + nb_oargs + nb_iargs, 
1467
           sizeof(TCGArg) * def->nb_cargs);
1468

    
1469
    /* satisfy input constraints */ 
1470
    tcg_regset_set(allocated_regs, s->reserved_regs);
1471
    for(k = 0; k < nb_iargs; k++) {
1472
        i = def->sorted_args[nb_oargs + k];
1473
        arg = args[i];
1474
        arg_ct = &def->args_ct[i];
1475
        ts = &s->temps[arg];
1476
        if (ts->val_type == TEMP_VAL_MEM) {
1477
            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1478
            tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1479
            ts->val_type = TEMP_VAL_REG;
1480
            ts->reg = reg;
1481
            ts->mem_coherent = 1;
1482
            s->reg_to_temp[reg] = arg;
1483
        } else if (ts->val_type == TEMP_VAL_CONST) {
1484
            if (tcg_target_const_match(ts->val, arg_ct)) {
1485
                /* constant is OK for instruction */
1486
                const_args[i] = 1;
1487
                new_args[i] = ts->val;
1488
                goto iarg_end;
1489
            } else {
1490
                /* need to move to a register*/
1491
                reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1492
                tcg_out_movi(s, ts->type, reg, ts->val);
1493
                goto iarg_end1;
1494
            }
1495
        }
1496
        assert(ts->val_type == TEMP_VAL_REG);
1497
        if (arg_ct->ct & TCG_CT_IALIAS) {
1498
            if (ts->fixed_reg) {
1499
                /* if fixed register, we must allocate a new register
1500
                   if the alias is not the same register */
1501
                if (arg != args[arg_ct->alias_index])
1502
                    goto allocate_in_reg;
1503
            } else {
1504
                /* if the input is aliased to an output and if it is
1505
                   not dead after the instruction, we must allocate
1506
                   a new register and move it */
1507
                if (!IS_DEAD_IARG(i - nb_oargs)) 
1508
                    goto allocate_in_reg;
1509
            }
1510
        }
1511
        reg = ts->reg;
1512
        if (tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1513
            /* nothing to do : the constraint is satisfied */
1514
        } else {
1515
        allocate_in_reg:
1516
            /* allocate a new register matching the constraint 
1517
               and move the temporary register into it */
1518
            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1519
            tcg_out_mov(s, reg, ts->reg);
1520
        }
1521
    iarg_end1:
1522
        new_args[i] = reg;
1523
        const_args[i] = 0;
1524
        tcg_regset_set_reg(allocated_regs, reg);
1525
    iarg_end: ;
1526
    }
1527
    
1528
    /* mark dead temporaries and free the associated registers */
1529
    for(i = 0; i < nb_iargs; i++) {
1530
        arg = args[nb_oargs + i];
1531
        if (IS_DEAD_IARG(i)) {
1532
            ts = &s->temps[arg];
1533
            if (ts->val_type != TEMP_VAL_CONST && !ts->fixed_reg) {
1534
                if (ts->val_type == TEMP_VAL_REG)
1535
                    s->reg_to_temp[ts->reg] = -1;
1536
                ts->val_type = TEMP_VAL_DEAD;
1537
            }
1538
        }
1539
    }
1540

    
1541
    if (def->flags & TCG_OPF_CALL_CLOBBER) {
1542
        /* XXX: permit generic clobber register list ? */ 
1543
        for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1544
            if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
1545
                tcg_reg_free(s, reg);
1546
            }
1547
        }
1548
        /* XXX: for load/store we could do that only for the slow path
1549
           (i.e. when a memory callback is called) */
1550

    
1551
        /* store globals and free associated registers (we assume the insn
1552
           can modify any global. */
1553
        save_globals(s);
1554
    }
1555

    
1556
    /* satisfy the output constraints */
1557
    tcg_regset_set(allocated_regs, s->reserved_regs);
1558
    for(k = 0; k < nb_oargs; k++) {
1559
        i = def->sorted_args[k];
1560
        arg = args[i];
1561
        arg_ct = &def->args_ct[i];
1562
        ts = &s->temps[arg];
1563
        if (arg_ct->ct & TCG_CT_ALIAS) {
1564
            reg = new_args[arg_ct->alias_index];
1565
        } else {
1566
            /* if fixed register, we try to use it */
1567
            reg = ts->reg;
1568
            if (ts->fixed_reg &&
1569
                tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1570
                goto oarg_end;
1571
            }
1572
            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1573
        }
1574
        tcg_regset_set_reg(allocated_regs, reg);
1575
        /* if a fixed register is used, then a move will be done afterwards */
1576
        if (!ts->fixed_reg) {
1577
            if (ts->val_type == TEMP_VAL_REG)
1578
                s->reg_to_temp[ts->reg] = -1;
1579
            ts->val_type = TEMP_VAL_REG;
1580
            ts->reg = reg;
1581
            /* temp value is modified, so the value kept in memory is
1582
               potentially not the same */
1583
            ts->mem_coherent = 0; 
1584
            s->reg_to_temp[reg] = arg;
1585
        }
1586
    oarg_end:
1587
        new_args[i] = reg;
1588
    }
1589

    
1590
    if (def->flags & TCG_OPF_BB_END)
1591
        tcg_reg_alloc_bb_end(s);
1592

    
1593
    /* emit instruction */
1594
    tcg_out_op(s, opc, new_args, const_args);
1595
    
1596
    /* move the outputs in the correct register if needed */
1597
    for(i = 0; i < nb_oargs; i++) {
1598
        ts = &s->temps[args[i]];
1599
        reg = new_args[i];
1600
        if (ts->fixed_reg && ts->reg != reg) {
1601
            tcg_out_mov(s, ts->reg, reg);
1602
        }
1603
    }
1604
}
1605

    
1606
#ifdef TCG_TARGET_STACK_GROWSUP
1607
#define STACK_DIR(x) (-(x))
1608
#else
1609
#define STACK_DIR(x) (x)
1610
#endif
1611

    
1612
static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
1613
                              int opc, const TCGArg *args,
1614
                              unsigned int dead_iargs)
1615
{
1616
    int nb_iargs, nb_oargs, flags, nb_regs, i, reg, nb_params;
1617
    TCGArg arg, func_arg;
1618
    TCGTemp *ts;
1619
    tcg_target_long stack_offset, call_stack_size, func_addr;
1620
    int const_func_arg, allocate_args;
1621
    TCGRegSet allocated_regs;
1622
    const TCGArgConstraint *arg_ct;
1623

    
1624
    arg = *args++;
1625

    
1626
    nb_oargs = arg >> 16;
1627
    nb_iargs = arg & 0xffff;
1628
    nb_params = nb_iargs - 1;
1629

    
1630
    flags = args[nb_oargs + nb_iargs];
1631

    
1632
    nb_regs = tcg_target_get_call_iarg_regs_count(flags);
1633
    if (nb_regs > nb_params)
1634
        nb_regs = nb_params;
1635

    
1636
    /* assign stack slots first */
1637
    /* XXX: preallocate call stack */
1638
    call_stack_size = (nb_params - nb_regs) * sizeof(tcg_target_long);
1639
    call_stack_size = (call_stack_size + TCG_TARGET_STACK_ALIGN - 1) & 
1640
        ~(TCG_TARGET_STACK_ALIGN - 1);
1641
    allocate_args = (call_stack_size > TCG_STATIC_CALL_ARGS_SIZE);
1642
    if (allocate_args) {
1643
        tcg_out_addi(s, TCG_REG_CALL_STACK, -STACK_DIR(call_stack_size));
1644
    }
1645

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

    
1755
    tcg_out_op(s, opc, &func_arg, &const_func_arg);
1756
    
1757
    if (allocate_args) {
1758
        tcg_out_addi(s, TCG_REG_CALL_STACK, STACK_DIR(call_stack_size));
1759
    }
1760

    
1761
    /* assign output registers and emit moves if needed */
1762
    for(i = 0; i < nb_oargs; i++) {
1763
        arg = args[i];
1764
        ts = &s->temps[arg];
1765
        reg = tcg_target_call_oarg_regs[i];
1766
        tcg_reg_free(s, reg);
1767
        if (ts->fixed_reg) {
1768
            if (ts->reg != reg) {
1769
                tcg_out_mov(s, ts->reg, reg);
1770
            }
1771
        } else {
1772
            if (ts->val_type == TEMP_VAL_REG)
1773
                s->reg_to_temp[ts->reg] = -1;
1774
            ts->val_type = TEMP_VAL_REG;
1775
            ts->reg = reg;
1776
            ts->mem_coherent = 0; 
1777
            s->reg_to_temp[reg] = arg;
1778
        }
1779
    }
1780
    
1781
    return nb_iargs + nb_oargs + def->nb_cargs + 1;
1782
}
1783

    
1784
#ifdef CONFIG_PROFILER
1785

    
1786
static int64_t dyngen_table_op_count[NB_OPS];
1787

    
1788
void dump_op_count(void)
1789
{
1790
    int i;
1791
    FILE *f;
1792
    f = fopen("/tmp/op1.log", "w");
1793
    for(i = 0; i < INDEX_op_end; i++) {
1794
        fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name, dyngen_table_op_count[i]);
1795
    }
1796
    fclose(f);
1797
    f = fopen("/tmp/op2.log", "w");
1798
    for(i = INDEX_op_end; i < NB_OPS; i++) {
1799
        fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name, dyngen_table_op_count[i]);
1800
    }
1801
    fclose(f);
1802
}
1803
#endif
1804

    
1805

    
1806
static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
1807
                                      long search_pc)
1808
{
1809
    int opc, op_index, macro_op_index;
1810
    const TCGOpDef *def;
1811
    unsigned int dead_iargs;
1812
    const TCGArg *args;
1813

    
1814
#ifdef DEBUG_DISAS
1815
    if (unlikely(loglevel & CPU_LOG_TB_OP)) {
1816
        fprintf(logfile, "OP:\n");
1817
        tcg_dump_ops(s, logfile);
1818
        fprintf(logfile, "\n");
1819
    }
1820
#endif
1821

    
1822
#ifdef CONFIG_PROFILER
1823
    s->la_time -= profile_getclock();
1824
#endif
1825
    tcg_liveness_analysis(s);
1826
#ifdef CONFIG_PROFILER
1827
    s->la_time += profile_getclock();
1828
#endif
1829

    
1830
#ifdef DEBUG_DISAS
1831
    if (unlikely(loglevel & CPU_LOG_TB_OP_OPT)) {
1832
        fprintf(logfile, "OP after la:\n");
1833
        tcg_dump_ops(s, logfile);
1834
        fprintf(logfile, "\n");
1835
    }
1836
#endif
1837

    
1838
    tcg_reg_alloc_start(s);
1839

    
1840
    s->code_buf = gen_code_buf;
1841
    s->code_ptr = gen_code_buf;
1842

    
1843
    macro_op_index = -1;
1844
    args = gen_opparam_buf;
1845
    op_index = 0;
1846

    
1847
    for(;;) {
1848
        opc = gen_opc_buf[op_index];
1849
#ifdef CONFIG_PROFILER
1850
        dyngen_table_op_count[opc]++;
1851
#endif
1852
        def = &tcg_op_defs[opc];
1853
#if 0
1854
        printf("%s: %d %d %d\n", def->name,
1855
               def->nb_oargs, def->nb_iargs, def->nb_cargs);
1856
        //        dump_regs(s);
1857
#endif
1858
        switch(opc) {
1859
        case INDEX_op_mov_i32:
1860
#if TCG_TARGET_REG_BITS == 64
1861
        case INDEX_op_mov_i64:
1862
#endif
1863
            dead_iargs = s->op_dead_iargs[op_index];
1864
            tcg_reg_alloc_mov(s, def, args, dead_iargs);
1865
            break;
1866
        case INDEX_op_debug_insn_start:
1867
            /* debug instruction */
1868
            break;
1869
        case INDEX_op_nop:
1870
        case INDEX_op_nop1:
1871
        case INDEX_op_nop2:
1872
        case INDEX_op_nop3:
1873
            break;
1874
        case INDEX_op_nopn:
1875
            args += args[0];
1876
            goto next;
1877
        case INDEX_op_discard:
1878
            {
1879
                TCGTemp *ts;
1880
                ts = &s->temps[args[0]];
1881
                /* mark the temporary as dead */
1882
                if (ts->val_type != TEMP_VAL_CONST && !ts->fixed_reg) {
1883
                    if (ts->val_type == TEMP_VAL_REG)
1884
                        s->reg_to_temp[ts->reg] = -1;
1885
                    ts->val_type = TEMP_VAL_DEAD;
1886
                }
1887
            }
1888
            break;
1889
        case INDEX_op_macro_goto:
1890
            macro_op_index = op_index; /* only used for exceptions */
1891
            op_index = args[0] - 1;
1892
            args = gen_opparam_buf + args[1];
1893
            goto next;
1894
        case INDEX_op_macro_end:
1895
            macro_op_index = -1; /* only used for exceptions */
1896
            op_index = args[0] - 1;
1897
            args = gen_opparam_buf + args[1];
1898
            goto next;
1899
        case INDEX_op_macro_start:
1900
            /* must never happen here */
1901
            tcg_abort();
1902
        case INDEX_op_set_label:
1903
            tcg_reg_alloc_bb_end(s);
1904
            tcg_out_label(s, args[0], (long)s->code_ptr);
1905
            break;
1906
        case INDEX_op_call:
1907
            dead_iargs = s->op_dead_iargs[op_index];
1908
            args += tcg_reg_alloc_call(s, def, opc, args, dead_iargs);
1909
            goto next;
1910
        case INDEX_op_end:
1911
            goto the_end;
1912

    
1913
#ifdef CONFIG_DYNGEN_OP
1914
        case 0 ... INDEX_op_end - 1:
1915
            /* legacy dyngen ops */
1916
#ifdef CONFIG_PROFILER
1917
            s->old_op_count++;
1918
#endif
1919
            tcg_reg_alloc_bb_end(s);
1920
            if (search_pc >= 0) {
1921
                s->code_ptr += def->copy_size;
1922
                args += def->nb_args;
1923
            } else {
1924
                args = dyngen_op(s, opc, args);
1925
            }
1926
            goto next;
1927
#endif
1928
        default:
1929
            /* Note: in order to speed up the code, it would be much
1930
               faster to have specialized register allocator functions for
1931
               some common argument patterns */
1932
            dead_iargs = s->op_dead_iargs[op_index];
1933
            tcg_reg_alloc_op(s, def, opc, args, dead_iargs);
1934
            break;
1935
        }
1936
        args += def->nb_args;
1937
    next: ;
1938
        if (search_pc >= 0 && search_pc < s->code_ptr - gen_code_buf) {
1939
            if (macro_op_index >= 0)
1940
                return macro_op_index;
1941
            else
1942
                return op_index;
1943
        }
1944
        op_index++;
1945
#ifndef NDEBUG
1946
        check_regs(s);
1947
#endif
1948
    }
1949
 the_end:
1950
    return -1;
1951
}
1952

    
1953
int dyngen_code(TCGContext *s, uint8_t *gen_code_buf)
1954
{
1955
#ifdef CONFIG_PROFILER
1956
    {
1957
        int n;
1958
        n = (gen_opc_ptr - gen_opc_buf);
1959
        s->op_count += n;
1960
        if (n > s->op_count_max)
1961
            s->op_count_max = n;
1962

    
1963
        s->temp_count += s->nb_temps;
1964
        if (s->nb_temps > s->temp_count_max)
1965
            s->temp_count_max = s->nb_temps;
1966
    }
1967
#endif
1968

    
1969
    tcg_gen_code_common(s, gen_code_buf, -1);
1970

    
1971
    /* flush instruction cache */
1972
    flush_icache_range((unsigned long)gen_code_buf, 
1973
                       (unsigned long)s->code_ptr);
1974
    return s->code_ptr -  gen_code_buf;
1975
}
1976

    
1977
/* Return the index of the micro operation such as the pc after is <
1978
   offset bytes from the start of the TB.  The contents of gen_code_buf must
1979
   not be changed, though writing the same values is ok.
1980
   Return -1 if not found. */
1981
int dyngen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, long offset)
1982
{
1983
    return tcg_gen_code_common(s, gen_code_buf, offset);
1984
}
1985

    
1986
#ifdef CONFIG_PROFILER
1987
void tcg_dump_info(FILE *f,
1988
                   int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
1989
{
1990
    TCGContext *s = &tcg_ctx;
1991
    int64_t tot;
1992

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