Statistics
| Branch: | Revision:

root / tcg / tcg.c @ e4d58b41

History | View | Annotate | Download (64 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 use liveness analysis (better code) */
26
#define USE_LIVENESS_ANALYSIS
27

    
28
#include "config.h"
29

    
30
#if !defined(CONFIG_DEBUG_TCG) && !defined(NDEBUG)
31
/* define it to suppress various consistency checks (faster) */
32
#define NDEBUG
33
#endif
34

    
35
#include <stdarg.h>
36
#include <stdlib.h>
37
#include <stdio.h>
38
#include <string.h>
39
#include <inttypes.h>
40
#ifdef _WIN32
41
#include <malloc.h>
42
#endif
43
#ifdef _AIX
44
#include <alloca.h>
45
#endif
46

    
47
#include "qemu-common.h"
48
#include "cache-utils.h"
49
#include "host-utils.h"
50
#include "qemu-timer.h"
51

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

    
59
#include "tcg-op.h"
60
#include "elf.h"
61

    
62
#if defined(CONFIG_USE_GUEST_BASE) && !defined(TCG_TARGET_HAS_GUEST_BASE)
63
#error GUEST_BASE not supported on this host.
64
#endif
65

    
66
static void tcg_target_init(TCGContext *s);
67
static void tcg_target_qemu_prologue(TCGContext *s);
68
static void patch_reloc(uint8_t *code_ptr, int type, 
69
                        tcg_target_long value, tcg_target_long addend);
70

    
71
static TCGOpDef tcg_op_defs[] = {
72
#define DEF(s, n, copy_size) { #s, 0, 0, n, n, 0, copy_size },
73
#define DEF2(s, oargs, iargs, cargs, flags) { #s, oargs, iargs, cargs, iargs + oargs + cargs, flags, 0 },
74
#include "tcg-opc.h"
75
#undef DEF
76
#undef DEF2
77
};
78

    
79
static TCGRegSet tcg_target_available_regs[2];
80
static TCGRegSet tcg_target_call_clobber_regs;
81

    
82
/* XXX: move that inside the context */
83
uint16_t *gen_opc_ptr;
84
TCGArg *gen_opparam_ptr;
85

    
86
static inline void tcg_out8(TCGContext *s, uint8_t v)
87
{
88
    *s->code_ptr++ = v;
89
}
90

    
91
static inline void tcg_out16(TCGContext *s, uint16_t v)
92
{
93
    *(uint16_t *)s->code_ptr = v;
94
    s->code_ptr += 2;
95
}
96

    
97
static inline void tcg_out32(TCGContext *s, uint32_t v)
98
{
99
    *(uint32_t *)s->code_ptr = v;
100
    s->code_ptr += 4;
101
}
102

    
103
/* label relocation processing */
104

    
105
static void tcg_out_reloc(TCGContext *s, uint8_t *code_ptr, int type,
106
                          int label_index, long addend)
107
{
108
    TCGLabel *l;
109
    TCGRelocation *r;
110

    
111
    l = &s->labels[label_index];
112
    if (l->has_value) {
113
        /* FIXME: This may break relocations on RISC targets that
114
           modify instruction fields in place.  The caller may not have 
115
           written the initial value.  */
116
        patch_reloc(code_ptr, type, l->u.value, addend);
117
    } else {
118
        /* add a new relocation entry */
119
        r = tcg_malloc(sizeof(TCGRelocation));
120
        r->type = type;
121
        r->ptr = code_ptr;
122
        r->addend = addend;
123
        r->next = l->u.first_reloc;
124
        l->u.first_reloc = r;
125
    }
126
}
127

    
128
static void tcg_out_label(TCGContext *s, int label_index, 
129
                          tcg_target_long value)
130
{
131
    TCGLabel *l;
132
    TCGRelocation *r;
133

    
134
    l = &s->labels[label_index];
135
    if (l->has_value)
136
        tcg_abort();
137
    r = l->u.first_reloc;
138
    while (r != NULL) {
139
        patch_reloc(r->ptr, r->type, value, r->addend);
140
        r = r->next;
141
    }
142
    l->has_value = 1;
143
    l->u.value = value;
144
}
145

    
146
int gen_new_label(void)
147
{
148
    TCGContext *s = &tcg_ctx;
149
    int idx;
150
    TCGLabel *l;
151

    
152
    if (s->nb_labels >= TCG_MAX_LABELS)
153
        tcg_abort();
154
    idx = s->nb_labels++;
155
    l = &s->labels[idx];
156
    l->has_value = 0;
157
    l->u.first_reloc = NULL;
158
    return idx;
159
}
160

    
161
#include "tcg-target.c"
162

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

    
206
void tcg_pool_reset(TCGContext *s)
207
{
208
    s->pool_cur = s->pool_end = NULL;
209
    s->pool_current = 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

    
247
void tcg_prologue_init(TCGContext *s)
248
{
249
    /* init global prologue and epilogue */
250
    s->code_buf = code_gen_prologue;
251
    s->code_ptr = s->code_buf;
252
    tcg_target_qemu_prologue(s);
253
    flush_icache_range((unsigned long)s->code_buf, 
254
                       (unsigned long)s->code_ptr);
255
}
256

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

    
265
void tcg_func_start(TCGContext *s)
266
{
267
    int i;
268
    tcg_pool_reset(s);
269
    s->nb_temps = s->nb_globals;
270
    for(i = 0; i < (TCG_TYPE_COUNT * 2); i++)
271
        s->first_free_temp[i] = -1;
272
    s->labels = tcg_malloc(sizeof(TCGLabel) * TCG_MAX_LABELS);
273
    s->nb_labels = 0;
274
    s->current_frame_offset = s->frame_start;
275

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

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

    
286
static inline int tcg_global_reg_new_internal(TCGType type, int reg,
287
                                              const char *name)
288
{
289
    TCGContext *s = &tcg_ctx;
290
    TCGTemp *ts;
291
    int idx;
292

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

    
312
TCGv_i32 tcg_global_reg_new_i32(int reg, const char *name)
313
{
314
    int idx;
315

    
316
    idx = tcg_global_reg_new_internal(TCG_TYPE_I32, reg, name);
317
    return MAKE_TCGV_I32(idx);
318
}
319

    
320
TCGv_i64 tcg_global_reg_new_i64(int reg, const char *name)
321
{
322
    int idx;
323

    
324
    idx = tcg_global_reg_new_internal(TCG_TYPE_I64, reg, name);
325
    return MAKE_TCGV_I64(idx);
326
}
327

    
328
static inline int tcg_global_mem_new_internal(TCGType type, int reg,
329
                                              tcg_target_long offset,
330
                                              const char *name)
331
{
332
    TCGContext *s = &tcg_ctx;
333
    TCGTemp *ts;
334
    int idx;
335

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

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

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

    
389
TCGv_i32 tcg_global_mem_new_i32(int reg, tcg_target_long offset,
390
                                const char *name)
391
{
392
    int idx;
393

    
394
    idx = tcg_global_mem_new_internal(TCG_TYPE_I32, reg, offset, name);
395
    return MAKE_TCGV_I32(idx);
396
}
397

    
398
TCGv_i64 tcg_global_mem_new_i64(int reg, tcg_target_long offset,
399
                                const char *name)
400
{
401
    int idx;
402

    
403
    idx = tcg_global_mem_new_internal(TCG_TYPE_I64, reg, offset, name);
404
    return MAKE_TCGV_I64(idx);
405
}
406

    
407
static inline int tcg_temp_new_internal(TCGType type, int temp_local)
408
{
409
    TCGContext *s = &tcg_ctx;
410
    TCGTemp *ts;
411
    int idx, k;
412

    
413
    k = type;
414
    if (temp_local)
415
        k += TCG_TYPE_COUNT;
416
    idx = s->first_free_temp[k];
417
    if (idx != -1) {
418
        /* There is already an available temp with the
419
           right type */
420
        ts = &s->temps[idx];
421
        s->first_free_temp[k] = ts->next_free_temp;
422
        ts->temp_allocated = 1;
423
        assert(ts->temp_local == temp_local);
424
    } else {
425
        idx = s->nb_temps;
426
#if TCG_TARGET_REG_BITS == 32
427
        if (type == TCG_TYPE_I64) {
428
            tcg_temp_alloc(s, s->nb_temps + 2);
429
            ts = &s->temps[s->nb_temps];
430
            ts->base_type = type;
431
            ts->type = TCG_TYPE_I32;
432
            ts->temp_allocated = 1;
433
            ts->temp_local = temp_local;
434
            ts->name = NULL;
435
            ts++;
436
            ts->base_type = TCG_TYPE_I32;
437
            ts->type = TCG_TYPE_I32;
438
            ts->temp_allocated = 1;
439
            ts->temp_local = temp_local;
440
            ts->name = NULL;
441
            s->nb_temps += 2;
442
        } else
443
#endif
444
        {
445
            tcg_temp_alloc(s, s->nb_temps + 1);
446
            ts = &s->temps[s->nb_temps];
447
            ts->base_type = type;
448
            ts->type = type;
449
            ts->temp_allocated = 1;
450
            ts->temp_local = temp_local;
451
            ts->name = NULL;
452
            s->nb_temps++;
453
        }
454
    }
455
    return idx;
456
}
457

    
458
TCGv_i32 tcg_temp_new_internal_i32(int temp_local)
459
{
460
    int idx;
461

    
462
    idx = tcg_temp_new_internal(TCG_TYPE_I32, temp_local);
463
    return MAKE_TCGV_I32(idx);
464
}
465

    
466
TCGv_i64 tcg_temp_new_internal_i64(int temp_local)
467
{
468
    int idx;
469

    
470
    idx = tcg_temp_new_internal(TCG_TYPE_I64, temp_local);
471
    return MAKE_TCGV_I64(idx);
472
}
473

    
474
static inline void tcg_temp_free_internal(int idx)
475
{
476
    TCGContext *s = &tcg_ctx;
477
    TCGTemp *ts;
478
    int k;
479

    
480
    assert(idx >= s->nb_globals && idx < s->nb_temps);
481
    ts = &s->temps[idx];
482
    assert(ts->temp_allocated != 0);
483
    ts->temp_allocated = 0;
484
    k = ts->base_type;
485
    if (ts->temp_local)
486
        k += TCG_TYPE_COUNT;
487
    ts->next_free_temp = s->first_free_temp[k];
488
    s->first_free_temp[k] = idx;
489
}
490

    
491
void tcg_temp_free_i32(TCGv_i32 arg)
492
{
493
    tcg_temp_free_internal(GET_TCGV_I32(arg));
494
}
495

    
496
void tcg_temp_free_i64(TCGv_i64 arg)
497
{
498
    tcg_temp_free_internal(GET_TCGV_I64(arg));
499
}
500

    
501
TCGv_i32 tcg_const_i32(int32_t val)
502
{
503
    TCGv_i32 t0;
504
    t0 = tcg_temp_new_i32();
505
    tcg_gen_movi_i32(t0, val);
506
    return t0;
507
}
508

    
509
TCGv_i64 tcg_const_i64(int64_t val)
510
{
511
    TCGv_i64 t0;
512
    t0 = tcg_temp_new_i64();
513
    tcg_gen_movi_i64(t0, val);
514
    return t0;
515
}
516

    
517
TCGv_i32 tcg_const_local_i32(int32_t val)
518
{
519
    TCGv_i32 t0;
520
    t0 = tcg_temp_local_new_i32();
521
    tcg_gen_movi_i32(t0, val);
522
    return t0;
523
}
524

    
525
TCGv_i64 tcg_const_local_i64(int64_t val)
526
{
527
    TCGv_i64 t0;
528
    t0 = tcg_temp_local_new_i64();
529
    tcg_gen_movi_i64(t0, val);
530
    return t0;
531
}
532

    
533
void tcg_register_helper(void *func, const char *name)
534
{
535
    TCGContext *s = &tcg_ctx;
536
    int n;
537
    if ((s->nb_helpers + 1) > s->allocated_helpers) {
538
        n = s->allocated_helpers;
539
        if (n == 0) {
540
            n = 4;
541
        } else {
542
            n *= 2;
543
        }
544
        s->helpers = realloc(s->helpers, n * sizeof(TCGHelperInfo));
545
        s->allocated_helpers = n;
546
    }
547
    s->helpers[s->nb_helpers].func = (tcg_target_ulong)func;
548
    s->helpers[s->nb_helpers].name = name;
549
    s->nb_helpers++;
550
}
551

    
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_callN(TCGContext *s, TCGv_ptr func, unsigned int flags,
556
                   int sizemask, TCGArg ret, int nargs, TCGArg *args)
557
{
558
#ifdef TCG_TARGET_I386
559
    int call_type;
560
#endif
561
    int i;
562
    int real_args;
563
    int nb_rets;
564
    TCGArg *nparam;
565
    *gen_opc_ptr++ = INDEX_op_call;
566
    nparam = gen_opparam_ptr++;
567
#ifdef TCG_TARGET_I386
568
    call_type = (flags & TCG_CALL_TYPE_MASK);
569
#endif
570
    if (ret != TCG_CALL_DUMMY_ARG) {
571
#if TCG_TARGET_REG_BITS < 64
572
        if (sizemask & 1) {
573
#ifdef TCG_TARGET_WORDS_BIGENDIAN
574
            *gen_opparam_ptr++ = ret + 1;
575
            *gen_opparam_ptr++ = ret;
576
#else
577
            *gen_opparam_ptr++ = ret;
578
            *gen_opparam_ptr++ = ret + 1;
579
#endif
580
            nb_rets = 2;
581
        } else
582
#endif
583
        {
584
            *gen_opparam_ptr++ = ret;
585
            nb_rets = 1;
586
        }
587
    } else {
588
        nb_rets = 0;
589
    }
590
    real_args = 0;
591
    for (i = 0; i < nargs; i++) {
592
#if TCG_TARGET_REG_BITS < 64
593
        if (sizemask & (2 << i)) {
594
#ifdef TCG_TARGET_I386
595
            /* REGPARM case: if the third parameter is 64 bit, it is
596
               allocated on the stack */
597
            if (i == 2 && call_type == TCG_CALL_TYPE_REGPARM) {
598
                call_type = TCG_CALL_TYPE_REGPARM_2;
599
                flags = (flags & ~TCG_CALL_TYPE_MASK) | call_type;
600
            }
601
#endif
602
#ifdef TCG_TARGET_CALL_ALIGN_ARGS
603
            /* some targets want aligned 64 bit args */
604
            if (real_args & 1) {
605
                *gen_opparam_ptr++ = TCG_CALL_DUMMY_ARG;
606
                real_args++;
607
            }
608
#endif
609
            /* If stack grows up, then we will be placing successive
610
               arguments at lower addresses, which means we need to
611
               reverse the order compared to how we would normally
612
               treat either big or little-endian.  For those arguments
613
               that will wind up in registers, this still works for
614
               HPPA (the only current STACK_GROWSUP target) since the
615
               argument registers are *also* allocated in decreasing
616
               order.  If another such target is added, this logic may
617
               have to get more complicated to differentiate between
618
               stack arguments and register arguments.  */
619
#if defined(TCG_TARGET_WORDS_BIGENDIAN) != defined(TCG_TARGET_STACK_GROWSUP)
620
            *gen_opparam_ptr++ = args[i] + 1;
621
            *gen_opparam_ptr++ = args[i];
622
#else
623
            *gen_opparam_ptr++ = args[i];
624
            *gen_opparam_ptr++ = args[i] + 1;
625
#endif
626
            real_args += 2;
627
        } else
628
#endif
629
        {
630
            *gen_opparam_ptr++ = args[i];
631
            real_args++;
632
        }
633
    }
634
    *gen_opparam_ptr++ = GET_TCGV_PTR(func);
635

    
636
    *gen_opparam_ptr++ = flags;
637

    
638
    *nparam = (nb_rets << 16) | (real_args + 1);
639

    
640
    /* total parameters, needed to go backward in the instruction stream */
641
    *gen_opparam_ptr++ = 1 + nb_rets + real_args + 3;
642
}
643

    
644
#if TCG_TARGET_REG_BITS == 32
645
void tcg_gen_shifti_i64(TCGv_i64 ret, TCGv_i64 arg1,
646
                        int c, int right, int arith)
647
{
648
    if (c == 0) {
649
        tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg1));
650
        tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
651
    } else if (c >= 32) {
652
        c -= 32;
653
        if (right) {
654
            if (arith) {
655
                tcg_gen_sari_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
656
                tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 31);
657
            } else {
658
                tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
659
                tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
660
            }
661
        } else {
662
            tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_LOW(arg1), c);
663
            tcg_gen_movi_i32(TCGV_LOW(ret), 0);
664
        }
665
    } else {
666
        TCGv_i32 t0, t1;
667

    
668
        t0 = tcg_temp_new_i32();
669
        t1 = tcg_temp_new_i32();
670
        if (right) {
671
            tcg_gen_shli_i32(t0, TCGV_HIGH(arg1), 32 - c);
672
            if (arith)
673
                tcg_gen_sari_i32(t1, TCGV_HIGH(arg1), c);
674
            else
675
                tcg_gen_shri_i32(t1, TCGV_HIGH(arg1), c);
676
            tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_LOW(arg1), c);
677
            tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(ret), t0);
678
            tcg_gen_mov_i32(TCGV_HIGH(ret), t1);
679
        } else {
680
            tcg_gen_shri_i32(t0, TCGV_LOW(arg1), 32 - c);
681
            /* Note: ret can be the same as arg1, so we use t1 */
682
            tcg_gen_shli_i32(t1, TCGV_LOW(arg1), c);
683
            tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c);
684
            tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t0);
685
            tcg_gen_mov_i32(TCGV_LOW(ret), t1);
686
        }
687
        tcg_temp_free_i32(t0);
688
        tcg_temp_free_i32(t1);
689
    }
690
}
691
#endif
692

    
693

    
694
static void tcg_reg_alloc_start(TCGContext *s)
695
{
696
    int i;
697
    TCGTemp *ts;
698
    for(i = 0; i < s->nb_globals; i++) {
699
        ts = &s->temps[i];
700
        if (ts->fixed_reg) {
701
            ts->val_type = TEMP_VAL_REG;
702
        } else {
703
            ts->val_type = TEMP_VAL_MEM;
704
        }
705
    }
706
    for(i = s->nb_globals; i < s->nb_temps; i++) {
707
        ts = &s->temps[i];
708
        ts->val_type = TEMP_VAL_DEAD;
709
        ts->mem_allocated = 0;
710
        ts->fixed_reg = 0;
711
    }
712
    for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
713
        s->reg_to_temp[i] = -1;
714
    }
715
}
716

    
717
static char *tcg_get_arg_str_idx(TCGContext *s, char *buf, int buf_size,
718
                                 int idx)
719
{
720
    TCGTemp *ts;
721

    
722
    ts = &s->temps[idx];
723
    if (idx < s->nb_globals) {
724
        pstrcpy(buf, buf_size, ts->name);
725
    } else {
726
        if (ts->temp_local) 
727
            snprintf(buf, buf_size, "loc%d", idx - s->nb_globals);
728
        else
729
            snprintf(buf, buf_size, "tmp%d", idx - s->nb_globals);
730
    }
731
    return buf;
732
}
733

    
734
char *tcg_get_arg_str_i32(TCGContext *s, char *buf, int buf_size, TCGv_i32 arg)
735
{
736
    return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I32(arg));
737
}
738

    
739
char *tcg_get_arg_str_i64(TCGContext *s, char *buf, int buf_size, TCGv_i64 arg)
740
{
741
    return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I64(arg));
742
}
743

    
744
static int helper_cmp(const void *p1, const void *p2)
745
{
746
    const TCGHelperInfo *th1 = p1;
747
    const TCGHelperInfo *th2 = p2;
748
    if (th1->func < th2->func)
749
        return -1;
750
    else if (th1->func == th2->func)
751
        return 0;
752
    else
753
        return 1;
754
}
755

    
756
/* find helper definition (Note: A hash table would be better) */
757
static TCGHelperInfo *tcg_find_helper(TCGContext *s, tcg_target_ulong val)
758
{
759
    int m, m_min, m_max;
760
    TCGHelperInfo *th;
761
    tcg_target_ulong v;
762

    
763
    if (unlikely(!s->helpers_sorted)) {
764
        qsort(s->helpers, s->nb_helpers, sizeof(TCGHelperInfo), 
765
              helper_cmp);
766
        s->helpers_sorted = 1;
767
    }
768

    
769
    /* binary search */
770
    m_min = 0;
771
    m_max = s->nb_helpers - 1;
772
    while (m_min <= m_max) {
773
        m = (m_min + m_max) >> 1;
774
        th = &s->helpers[m];
775
        v = th->func;
776
        if (v == val)
777
            return th;
778
        else if (val < v) {
779
            m_max = m - 1;
780
        } else {
781
            m_min = m + 1;
782
        }
783
    }
784
    return NULL;
785
}
786

    
787
static const char * const cond_name[] =
788
{
789
    [TCG_COND_EQ] = "eq",
790
    [TCG_COND_NE] = "ne",
791
    [TCG_COND_LT] = "lt",
792
    [TCG_COND_GE] = "ge",
793
    [TCG_COND_LE] = "le",
794
    [TCG_COND_GT] = "gt",
795
    [TCG_COND_LTU] = "ltu",
796
    [TCG_COND_GEU] = "geu",
797
    [TCG_COND_LEU] = "leu",
798
    [TCG_COND_GTU] = "gtu"
799
};
800

    
801
void tcg_dump_ops(TCGContext *s, FILE *outfile)
802
{
803
    const uint16_t *opc_ptr;
804
    const TCGArg *args;
805
    TCGArg arg;
806
    TCGOpcode c;
807
    int i, k, nb_oargs, nb_iargs, nb_cargs, first_insn;
808
    const TCGOpDef *def;
809
    char buf[128];
810

    
811
    first_insn = 1;
812
    opc_ptr = gen_opc_buf;
813
    args = gen_opparam_buf;
814
    while (opc_ptr < gen_opc_ptr) {
815
        c = *opc_ptr++;
816
        def = &tcg_op_defs[c];
817
        if (c == INDEX_op_debug_insn_start) {
818
            uint64_t pc;
819
#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
820
            pc = ((uint64_t)args[1] << 32) | args[0];
821
#else
822
            pc = args[0];
823
#endif
824
            if (!first_insn) 
825
                fprintf(outfile, "\n");
826
            fprintf(outfile, " ---- 0x%" PRIx64, pc);
827
            first_insn = 0;
828
            nb_oargs = def->nb_oargs;
829
            nb_iargs = def->nb_iargs;
830
            nb_cargs = def->nb_cargs;
831
        } else if (c == INDEX_op_call) {
832
            TCGArg arg;
833

    
834
            /* variable number of arguments */
835
            arg = *args++;
836
            nb_oargs = arg >> 16;
837
            nb_iargs = arg & 0xffff;
838
            nb_cargs = def->nb_cargs;
839

    
840
            fprintf(outfile, " %s ", def->name);
841

    
842
            /* function name */
843
            fprintf(outfile, "%s",
844
                    tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + nb_iargs - 1]));
845
            /* flags */
846
            fprintf(outfile, ",$0x%" TCG_PRIlx,
847
                    args[nb_oargs + nb_iargs]);
848
            /* nb out args */
849
            fprintf(outfile, ",$%d", nb_oargs);
850
            for(i = 0; i < nb_oargs; i++) {
851
                fprintf(outfile, ",");
852
                fprintf(outfile, "%s",
853
                        tcg_get_arg_str_idx(s, buf, sizeof(buf), args[i]));
854
            }
855
            for(i = 0; i < (nb_iargs - 1); i++) {
856
                fprintf(outfile, ",");
857
                if (args[nb_oargs + i] == TCG_CALL_DUMMY_ARG) {
858
                    fprintf(outfile, "<dummy>");
859
                } else {
860
                    fprintf(outfile, "%s",
861
                            tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + i]));
862
                }
863
            }
864
        } else if (c == INDEX_op_movi_i32 
865
#if TCG_TARGET_REG_BITS == 64
866
                   || c == INDEX_op_movi_i64
867
#endif
868
                   ) {
869
            tcg_target_ulong val;
870
            TCGHelperInfo *th;
871

    
872
            nb_oargs = def->nb_oargs;
873
            nb_iargs = def->nb_iargs;
874
            nb_cargs = def->nb_cargs;
875
            fprintf(outfile, " %s %s,$", def->name, 
876
                    tcg_get_arg_str_idx(s, buf, sizeof(buf), args[0]));
877
            val = args[1];
878
            th = tcg_find_helper(s, val);
879
            if (th) {
880
                fprintf(outfile, "%s", th->name);
881
            } else {
882
                if (c == INDEX_op_movi_i32)
883
                    fprintf(outfile, "0x%x", (uint32_t)val);
884
                else
885
                    fprintf(outfile, "0x%" PRIx64 , (uint64_t)val);
886
            }
887
        } else {
888
            fprintf(outfile, " %s ", def->name);
889
            if (c == INDEX_op_nopn) {
890
                /* variable number of arguments */
891
                nb_cargs = *args;
892
                nb_oargs = 0;
893
                nb_iargs = 0;
894
            } else {
895
                nb_oargs = def->nb_oargs;
896
                nb_iargs = def->nb_iargs;
897
                nb_cargs = def->nb_cargs;
898
            }
899
            
900
            k = 0;
901
            for(i = 0; i < nb_oargs; i++) {
902
                if (k != 0)
903
                    fprintf(outfile, ",");
904
                fprintf(outfile, "%s",
905
                        tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
906
            }
907
            for(i = 0; i < nb_iargs; i++) {
908
                if (k != 0)
909
                    fprintf(outfile, ",");
910
                fprintf(outfile, "%s",
911
                        tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
912
            }
913
            switch (c) {
914
            case INDEX_op_brcond_i32:
915
#if TCG_TARGET_REG_BITS == 32
916
            case INDEX_op_brcond2_i32:
917
#elif TCG_TARGET_REG_BITS == 64
918
            case INDEX_op_brcond_i64:
919
#endif
920
            case INDEX_op_setcond_i32:
921
#if TCG_TARGET_REG_BITS == 32
922
            case INDEX_op_setcond2_i32:
923
#elif TCG_TARGET_REG_BITS == 64
924
            case INDEX_op_setcond_i64:
925
#endif
926
                if (args[k] < ARRAY_SIZE(cond_name) && cond_name[args[k]])
927
                    fprintf(outfile, ",%s", cond_name[args[k++]]);
928
                else
929
                    fprintf(outfile, ",$0x%" TCG_PRIlx, args[k++]);
930
                i = 1;
931
                break;
932
            default:
933
                i = 0;
934
                break;
935
            }
936
            for(; i < nb_cargs; i++) {
937
                if (k != 0)
938
                    fprintf(outfile, ",");
939
                arg = args[k++];
940
                fprintf(outfile, "$0x%" TCG_PRIlx, arg);
941
            }
942
        }
943
        fprintf(outfile, "\n");
944
        args += nb_iargs + nb_oargs + nb_cargs;
945
    }
946
}
947

    
948
/* we give more priority to constraints with less registers */
949
static int get_constraint_priority(const TCGOpDef *def, int k)
950
{
951
    const TCGArgConstraint *arg_ct;
952

    
953
    int i, n;
954
    arg_ct = &def->args_ct[k];
955
    if (arg_ct->ct & TCG_CT_ALIAS) {
956
        /* an alias is equivalent to a single register */
957
        n = 1;
958
    } else {
959
        if (!(arg_ct->ct & TCG_CT_REG))
960
            return 0;
961
        n = 0;
962
        for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
963
            if (tcg_regset_test_reg(arg_ct->u.regs, i))
964
                n++;
965
        }
966
    }
967
    return TCG_TARGET_NB_REGS - n + 1;
968
}
969

    
970
/* sort from highest priority to lowest */
971
static void sort_constraints(TCGOpDef *def, int start, int n)
972
{
973
    int i, j, p1, p2, tmp;
974

    
975
    for(i = 0; i < n; i++)
976
        def->sorted_args[start + i] = start + i;
977
    if (n <= 1)
978
        return;
979
    for(i = 0; i < n - 1; i++) {
980
        for(j = i + 1; j < n; j++) {
981
            p1 = get_constraint_priority(def, def->sorted_args[start + i]);
982
            p2 = get_constraint_priority(def, def->sorted_args[start + j]);
983
            if (p1 < p2) {
984
                tmp = def->sorted_args[start + i];
985
                def->sorted_args[start + i] = def->sorted_args[start + j];
986
                def->sorted_args[start + j] = tmp;
987
            }
988
        }
989
    }
990
}
991

    
992
void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs)
993
{
994
    TCGOpcode op;
995
    TCGOpDef *def;
996
    const char *ct_str;
997
    int i, nb_args;
998

    
999
    for(;;) {
1000
        if (tdefs->op == (TCGOpcode)-1)
1001
            break;
1002
        op = tdefs->op;
1003
        assert(op >= 0 && op < NB_OPS);
1004
        def = &tcg_op_defs[op];
1005
#if defined(CONFIG_DEBUG_TCG)
1006
        /* Duplicate entry in op definitions? */
1007
        assert(!def->used);
1008
        def->used = 1;
1009
#endif
1010
        nb_args = def->nb_iargs + def->nb_oargs;
1011
        for(i = 0; i < nb_args; i++) {
1012
            ct_str = tdefs->args_ct_str[i];
1013
            /* Incomplete TCGTargetOpDef entry? */
1014
            assert(ct_str != NULL);
1015
            tcg_regset_clear(def->args_ct[i].u.regs);
1016
            def->args_ct[i].ct = 0;
1017
            if (ct_str[0] >= '0' && ct_str[0] <= '9') {
1018
                int oarg;
1019
                oarg = ct_str[0] - '0';
1020
                assert(oarg < def->nb_oargs);
1021
                assert(def->args_ct[oarg].ct & TCG_CT_REG);
1022
                /* TCG_CT_ALIAS is for the output arguments. The input
1023
                   argument is tagged with TCG_CT_IALIAS. */
1024
                def->args_ct[i] = def->args_ct[oarg];
1025
                def->args_ct[oarg].ct = TCG_CT_ALIAS;
1026
                def->args_ct[oarg].alias_index = i;
1027
                def->args_ct[i].ct |= TCG_CT_IALIAS;
1028
                def->args_ct[i].alias_index = oarg;
1029
            } else {
1030
                for(;;) {
1031
                    if (*ct_str == '\0')
1032
                        break;
1033
                    switch(*ct_str) {
1034
                    case 'i':
1035
                        def->args_ct[i].ct |= TCG_CT_CONST;
1036
                        ct_str++;
1037
                        break;
1038
                    default:
1039
                        if (target_parse_constraint(&def->args_ct[i], &ct_str) < 0) {
1040
                            fprintf(stderr, "Invalid constraint '%s' for arg %d of operation '%s'\n",
1041
                                    ct_str, i, def->name);
1042
                            exit(1);
1043
                        }
1044
                    }
1045
                }
1046
            }
1047
        }
1048

    
1049
        /* TCGTargetOpDef entry with too much information? */
1050
        assert(i == TCG_MAX_OP_ARGS || tdefs->args_ct_str[i] == NULL);
1051

    
1052
        /* sort the constraints (XXX: this is just an heuristic) */
1053
        sort_constraints(def, 0, def->nb_oargs);
1054
        sort_constraints(def, def->nb_oargs, def->nb_iargs);
1055

    
1056
#if 0
1057
        {
1058
            int i;
1059

1060
            printf("%s: sorted=", def->name);
1061
            for(i = 0; i < def->nb_oargs + def->nb_iargs; i++)
1062
                printf(" %d", def->sorted_args[i]);
1063
            printf("\n");
1064
        }
1065
#endif
1066
        tdefs++;
1067
    }
1068

    
1069
#if defined(CONFIG_DEBUG_TCG)
1070
    i = 0;
1071
    for (op = 0; op < ARRAY_SIZE(tcg_op_defs); op++) {
1072
        if (op < INDEX_op_call || op == INDEX_op_debug_insn_start) {
1073
            /* Wrong entry in op definitions? */
1074
            if (tcg_op_defs[op].used) {
1075
                fprintf(stderr, "Invalid op definition for %s\n",
1076
                        tcg_op_defs[op].name);
1077
                i = 1;
1078
            }
1079
        } else {
1080
            /* Missing entry in op definitions? */
1081
            if (!tcg_op_defs[op].used) {
1082
                fprintf(stderr, "Missing op definition for %s\n",
1083
                        tcg_op_defs[op].name);
1084
                i = 1;
1085
            }
1086
        }
1087
    }
1088
    if (i == 1) {
1089
        tcg_abort();
1090
    }
1091
#endif
1092
}
1093

    
1094
#ifdef USE_LIVENESS_ANALYSIS
1095

    
1096
/* set a nop for an operation using 'nb_args' */
1097
static inline void tcg_set_nop(TCGContext *s, uint16_t *opc_ptr, 
1098
                               TCGArg *args, int nb_args)
1099
{
1100
    if (nb_args == 0) {
1101
        *opc_ptr = INDEX_op_nop;
1102
    } else {
1103
        *opc_ptr = INDEX_op_nopn;
1104
        args[0] = nb_args;
1105
        args[nb_args - 1] = nb_args;
1106
    }
1107
}
1108

    
1109
/* liveness analysis: end of function: globals are live, temps are
1110
   dead. */
1111
/* XXX: at this stage, not used as there would be little gains because
1112
   most TBs end with a conditional jump. */
1113
static inline void tcg_la_func_end(TCGContext *s, uint8_t *dead_temps)
1114
{
1115
    memset(dead_temps, 0, s->nb_globals);
1116
    memset(dead_temps + s->nb_globals, 1, s->nb_temps - s->nb_globals);
1117
}
1118

    
1119
/* liveness analysis: end of basic block: globals are live, temps are
1120
   dead, local temps are live. */
1121
static inline void tcg_la_bb_end(TCGContext *s, uint8_t *dead_temps)
1122
{
1123
    int i;
1124
    TCGTemp *ts;
1125

    
1126
    memset(dead_temps, 0, s->nb_globals);
1127
    ts = &s->temps[s->nb_globals];
1128
    for(i = s->nb_globals; i < s->nb_temps; i++) {
1129
        if (ts->temp_local)
1130
            dead_temps[i] = 0;
1131
        else
1132
            dead_temps[i] = 1;
1133
        ts++;
1134
    }
1135
}
1136

    
1137
/* Liveness analysis : update the opc_dead_iargs array to tell if a
1138
   given input arguments is dead. Instructions updating dead
1139
   temporaries are removed. */
1140
static void tcg_liveness_analysis(TCGContext *s)
1141
{
1142
    int i, op_index, nb_args, nb_iargs, nb_oargs, arg, nb_ops;
1143
    TCGOpcode op;
1144
    TCGArg *args;
1145
    const TCGOpDef *def;
1146
    uint8_t *dead_temps;
1147
    unsigned int dead_iargs;
1148
    
1149
    gen_opc_ptr++; /* skip end */
1150

    
1151
    nb_ops = gen_opc_ptr - gen_opc_buf;
1152

    
1153
    s->op_dead_iargs = tcg_malloc(nb_ops * sizeof(uint16_t));
1154
    
1155
    dead_temps = tcg_malloc(s->nb_temps);
1156
    memset(dead_temps, 1, s->nb_temps);
1157

    
1158
    args = gen_opparam_ptr;
1159
    op_index = nb_ops - 1;
1160
    while (op_index >= 0) {
1161
        op = gen_opc_buf[op_index];
1162
        def = &tcg_op_defs[op];
1163
        switch(op) {
1164
        case INDEX_op_call:
1165
            {
1166
                int call_flags;
1167

    
1168
                nb_args = args[-1];
1169
                args -= nb_args;
1170
                nb_iargs = args[0] & 0xffff;
1171
                nb_oargs = args[0] >> 16;
1172
                args++;
1173
                call_flags = args[nb_oargs + nb_iargs];
1174

    
1175
                /* pure functions can be removed if their result is not
1176
                   used */
1177
                if (call_flags & TCG_CALL_PURE) {
1178
                    for(i = 0; i < nb_oargs; i++) {
1179
                        arg = args[i];
1180
                        if (!dead_temps[arg])
1181
                            goto do_not_remove_call;
1182
                    }
1183
                    tcg_set_nop(s, gen_opc_buf + op_index, 
1184
                                args - 1, nb_args);
1185
                } else {
1186
                do_not_remove_call:
1187

    
1188
                    /* output args are dead */
1189
                    for(i = 0; i < nb_oargs; i++) {
1190
                        arg = args[i];
1191
                        dead_temps[arg] = 1;
1192
                    }
1193
                    
1194
                    if (!(call_flags & TCG_CALL_CONST)) {
1195
                        /* globals are live (they may be used by the call) */
1196
                        memset(dead_temps, 0, s->nb_globals);
1197
                    }
1198

    
1199
                    /* input args are live */
1200
                    dead_iargs = 0;
1201
                    for(i = 0; i < nb_iargs; i++) {
1202
                        arg = args[i + nb_oargs];
1203
                        if (arg != TCG_CALL_DUMMY_ARG) {
1204
                            if (dead_temps[arg]) {
1205
                                dead_iargs |= (1 << i);
1206
                            }
1207
                            dead_temps[arg] = 0;
1208
                        }
1209
                    }
1210
                    s->op_dead_iargs[op_index] = dead_iargs;
1211
                }
1212
                args--;
1213
            }
1214
            break;
1215
        case INDEX_op_set_label:
1216
            args--;
1217
            /* mark end of basic block */
1218
            tcg_la_bb_end(s, dead_temps);
1219
            break;
1220
        case INDEX_op_debug_insn_start:
1221
            args -= def->nb_args;
1222
            break;
1223
        case INDEX_op_nopn:
1224
            nb_args = args[-1];
1225
            args -= nb_args;
1226
            break;
1227
        case INDEX_op_discard:
1228
            args--;
1229
            /* mark the temporary as dead */
1230
            dead_temps[args[0]] = 1;
1231
            break;
1232
        case INDEX_op_end:
1233
            break;
1234
            /* XXX: optimize by hardcoding common cases (e.g. triadic ops) */
1235
        default:
1236
            args -= def->nb_args;
1237
            nb_iargs = def->nb_iargs;
1238
            nb_oargs = def->nb_oargs;
1239

    
1240
            /* Test if the operation can be removed because all
1241
               its outputs are dead. We assume that nb_oargs == 0
1242
               implies side effects */
1243
            if (!(def->flags & TCG_OPF_SIDE_EFFECTS) && nb_oargs != 0) {
1244
                for(i = 0; i < nb_oargs; i++) {
1245
                    arg = args[i];
1246
                    if (!dead_temps[arg])
1247
                        goto do_not_remove;
1248
                }
1249
                tcg_set_nop(s, gen_opc_buf + op_index, args, def->nb_args);
1250
#ifdef CONFIG_PROFILER
1251
                s->del_op_count++;
1252
#endif
1253
            } else {
1254
            do_not_remove:
1255

    
1256
                /* output args are dead */
1257
                for(i = 0; i < nb_oargs; i++) {
1258
                    arg = args[i];
1259
                    dead_temps[arg] = 1;
1260
                }
1261

    
1262
                /* if end of basic block, update */
1263
                if (def->flags & TCG_OPF_BB_END) {
1264
                    tcg_la_bb_end(s, dead_temps);
1265
                } else if (def->flags & TCG_OPF_CALL_CLOBBER) {
1266
                    /* globals are live */
1267
                    memset(dead_temps, 0, s->nb_globals);
1268
                }
1269

    
1270
                /* input args are live */
1271
                dead_iargs = 0;
1272
                for(i = 0; i < nb_iargs; i++) {
1273
                    arg = args[i + nb_oargs];
1274
                    if (dead_temps[arg]) {
1275
                        dead_iargs |= (1 << i);
1276
                    }
1277
                    dead_temps[arg] = 0;
1278
                }
1279
                s->op_dead_iargs[op_index] = dead_iargs;
1280
            }
1281
            break;
1282
        }
1283
        op_index--;
1284
    }
1285

    
1286
    if (args != gen_opparam_buf)
1287
        tcg_abort();
1288
}
1289
#else
1290
/* dummy liveness analysis */
1291
static void tcg_liveness_analysis(TCGContext *s)
1292
{
1293
    int nb_ops;
1294
    nb_ops = gen_opc_ptr - gen_opc_buf;
1295

    
1296
    s->op_dead_iargs = tcg_malloc(nb_ops * sizeof(uint16_t));
1297
    memset(s->op_dead_iargs, 0, nb_ops * sizeof(uint16_t));
1298
}
1299
#endif
1300

    
1301
#ifndef NDEBUG
1302
static void dump_regs(TCGContext *s)
1303
{
1304
    TCGTemp *ts;
1305
    int i;
1306
    char buf[64];
1307

    
1308
    for(i = 0; i < s->nb_temps; i++) {
1309
        ts = &s->temps[i];
1310
        printf("  %10s: ", tcg_get_arg_str_idx(s, buf, sizeof(buf), i));
1311
        switch(ts->val_type) {
1312
        case TEMP_VAL_REG:
1313
            printf("%s", tcg_target_reg_names[ts->reg]);
1314
            break;
1315
        case TEMP_VAL_MEM:
1316
            printf("%d(%s)", (int)ts->mem_offset, tcg_target_reg_names[ts->mem_reg]);
1317
            break;
1318
        case TEMP_VAL_CONST:
1319
            printf("$0x%" TCG_PRIlx, ts->val);
1320
            break;
1321
        case TEMP_VAL_DEAD:
1322
            printf("D");
1323
            break;
1324
        default:
1325
            printf("???");
1326
            break;
1327
        }
1328
        printf("\n");
1329
    }
1330

    
1331
    for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
1332
        if (s->reg_to_temp[i] >= 0) {
1333
            printf("%s: %s\n", 
1334
                   tcg_target_reg_names[i], 
1335
                   tcg_get_arg_str_idx(s, buf, sizeof(buf), s->reg_to_temp[i]));
1336
        }
1337
    }
1338
}
1339

    
1340
static void check_regs(TCGContext *s)
1341
{
1342
    int reg, k;
1343
    TCGTemp *ts;
1344
    char buf[64];
1345

    
1346
    for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1347
        k = s->reg_to_temp[reg];
1348
        if (k >= 0) {
1349
            ts = &s->temps[k];
1350
            if (ts->val_type != TEMP_VAL_REG ||
1351
                ts->reg != reg) {
1352
                printf("Inconsistency for register %s:\n", 
1353
                       tcg_target_reg_names[reg]);
1354
                goto fail;
1355
            }
1356
        }
1357
    }
1358
    for(k = 0; k < s->nb_temps; k++) {
1359
        ts = &s->temps[k];
1360
        if (ts->val_type == TEMP_VAL_REG &&
1361
            !ts->fixed_reg &&
1362
            s->reg_to_temp[ts->reg] != k) {
1363
                printf("Inconsistency for temp %s:\n", 
1364
                       tcg_get_arg_str_idx(s, buf, sizeof(buf), k));
1365
        fail:
1366
                printf("reg state:\n");
1367
                dump_regs(s);
1368
                tcg_abort();
1369
        }
1370
    }
1371
}
1372
#endif
1373

    
1374
static void temp_allocate_frame(TCGContext *s, int temp)
1375
{
1376
    TCGTemp *ts;
1377
    ts = &s->temps[temp];
1378
    s->current_frame_offset = (s->current_frame_offset + sizeof(tcg_target_long) - 1) & ~(sizeof(tcg_target_long) - 1);
1379
    if (s->current_frame_offset + sizeof(tcg_target_long) > s->frame_end)
1380
        tcg_abort();
1381
    ts->mem_offset = s->current_frame_offset;
1382
    ts->mem_reg = s->frame_reg;
1383
    ts->mem_allocated = 1;
1384
    s->current_frame_offset += sizeof(tcg_target_long);
1385
}
1386

    
1387
/* free register 'reg' by spilling the corresponding temporary if necessary */
1388
static void tcg_reg_free(TCGContext *s, int reg)
1389
{
1390
    TCGTemp *ts;
1391
    int temp;
1392

    
1393
    temp = s->reg_to_temp[reg];
1394
    if (temp != -1) {
1395
        ts = &s->temps[temp];
1396
        assert(ts->val_type == TEMP_VAL_REG);
1397
        if (!ts->mem_coherent) {
1398
            if (!ts->mem_allocated) 
1399
                temp_allocate_frame(s, temp);
1400
            tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1401
        }
1402
        ts->val_type = TEMP_VAL_MEM;
1403
        s->reg_to_temp[reg] = -1;
1404
    }
1405
}
1406

    
1407
/* Allocate a register belonging to reg1 & ~reg2 */
1408
static int tcg_reg_alloc(TCGContext *s, TCGRegSet reg1, TCGRegSet reg2)
1409
{
1410
    int i, reg;
1411
    TCGRegSet reg_ct;
1412

    
1413
    tcg_regset_andnot(reg_ct, reg1, reg2);
1414

    
1415
    /* first try free registers */
1416
    for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1417
        reg = tcg_target_reg_alloc_order[i];
1418
        if (tcg_regset_test_reg(reg_ct, reg) && s->reg_to_temp[reg] == -1)
1419
            return reg;
1420
    }
1421

    
1422
    /* XXX: do better spill choice */
1423
    for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1424
        reg = tcg_target_reg_alloc_order[i];
1425
        if (tcg_regset_test_reg(reg_ct, reg)) {
1426
            tcg_reg_free(s, reg);
1427
            return reg;
1428
        }
1429
    }
1430

    
1431
    tcg_abort();
1432
}
1433

    
1434
/* save a temporary to memory. 'allocated_regs' is used in case a
1435
   temporary registers needs to be allocated to store a constant. */
1436
static void temp_save(TCGContext *s, int temp, TCGRegSet allocated_regs)
1437
{
1438
    TCGTemp *ts;
1439
    int reg;
1440

    
1441
    ts = &s->temps[temp];
1442
    if (!ts->fixed_reg) {
1443
        switch(ts->val_type) {
1444
        case TEMP_VAL_REG:
1445
            tcg_reg_free(s, ts->reg);
1446
            break;
1447
        case TEMP_VAL_DEAD:
1448
            ts->val_type = TEMP_VAL_MEM;
1449
            break;
1450
        case TEMP_VAL_CONST:
1451
            reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], 
1452
                                allocated_regs);
1453
            if (!ts->mem_allocated) 
1454
                temp_allocate_frame(s, temp);
1455
            tcg_out_movi(s, ts->type, reg, ts->val);
1456
            tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1457
            ts->val_type = TEMP_VAL_MEM;
1458
            break;
1459
        case TEMP_VAL_MEM:
1460
            break;
1461
        default:
1462
            tcg_abort();
1463
        }
1464
    }
1465
}
1466

    
1467
/* save globals to their cannonical location and assume they can be
1468
   modified be the following code. 'allocated_regs' is used in case a
1469
   temporary registers needs to be allocated to store a constant. */
1470
static void save_globals(TCGContext *s, TCGRegSet allocated_regs)
1471
{
1472
    int i;
1473

    
1474
    for(i = 0; i < s->nb_globals; i++) {
1475
        temp_save(s, i, allocated_regs);
1476
    }
1477
}
1478

    
1479
/* at the end of a basic block, we assume all temporaries are dead and
1480
   all globals are stored at their canonical location. */
1481
static void tcg_reg_alloc_bb_end(TCGContext *s, TCGRegSet allocated_regs)
1482
{
1483
    TCGTemp *ts;
1484
    int i;
1485

    
1486
    for(i = s->nb_globals; i < s->nb_temps; i++) {
1487
        ts = &s->temps[i];
1488
        if (ts->temp_local) {
1489
            temp_save(s, i, allocated_regs);
1490
        } else {
1491
            if (ts->val_type == TEMP_VAL_REG) {
1492
                s->reg_to_temp[ts->reg] = -1;
1493
            }
1494
            ts->val_type = TEMP_VAL_DEAD;
1495
        }
1496
    }
1497

    
1498
    save_globals(s, allocated_regs);
1499
}
1500

    
1501
#define IS_DEAD_IARG(n) ((dead_iargs >> (n)) & 1)
1502

    
1503
static void tcg_reg_alloc_movi(TCGContext *s, const TCGArg *args)
1504
{
1505
    TCGTemp *ots;
1506
    tcg_target_ulong val;
1507

    
1508
    ots = &s->temps[args[0]];
1509
    val = args[1];
1510

    
1511
    if (ots->fixed_reg) {
1512
        /* for fixed registers, we do not do any constant
1513
           propagation */
1514
        tcg_out_movi(s, ots->type, ots->reg, val);
1515
    } else {
1516
        /* The movi is not explicitly generated here */
1517
        if (ots->val_type == TEMP_VAL_REG)
1518
            s->reg_to_temp[ots->reg] = -1;
1519
        ots->val_type = TEMP_VAL_CONST;
1520
        ots->val = val;
1521
    }
1522
}
1523

    
1524
static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
1525
                              const TCGArg *args,
1526
                              unsigned int dead_iargs)
1527
{
1528
    TCGTemp *ts, *ots;
1529
    int reg;
1530
    const TCGArgConstraint *arg_ct;
1531

    
1532
    ots = &s->temps[args[0]];
1533
    ts = &s->temps[args[1]];
1534
    arg_ct = &def->args_ct[0];
1535

    
1536
    /* XXX: always mark arg dead if IS_DEAD_IARG(0) */
1537
    if (ts->val_type == TEMP_VAL_REG) {
1538
        if (IS_DEAD_IARG(0) && !ts->fixed_reg && !ots->fixed_reg) {
1539
            /* the mov can be suppressed */
1540
            if (ots->val_type == TEMP_VAL_REG)
1541
                s->reg_to_temp[ots->reg] = -1;
1542
            reg = ts->reg;
1543
            s->reg_to_temp[reg] = -1;
1544
            ts->val_type = TEMP_VAL_DEAD;
1545
        } else {
1546
            if (ots->val_type == TEMP_VAL_REG) {
1547
                reg = ots->reg;
1548
            } else {
1549
                reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1550
            }
1551
            if (ts->reg != reg) {
1552
                tcg_out_mov(s, ots->type, reg, ts->reg);
1553
            }
1554
        }
1555
    } else if (ts->val_type == TEMP_VAL_MEM) {
1556
        if (ots->val_type == TEMP_VAL_REG) {
1557
            reg = ots->reg;
1558
        } else {
1559
            reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1560
        }
1561
        tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1562
    } else if (ts->val_type == TEMP_VAL_CONST) {
1563
        if (ots->fixed_reg) {
1564
            reg = ots->reg;
1565
            tcg_out_movi(s, ots->type, reg, ts->val);
1566
        } else {
1567
            /* propagate constant */
1568
            if (ots->val_type == TEMP_VAL_REG)
1569
                s->reg_to_temp[ots->reg] = -1;
1570
            ots->val_type = TEMP_VAL_CONST;
1571
            ots->val = ts->val;
1572
            return;
1573
        }
1574
    } else {
1575
        tcg_abort();
1576
    }
1577
    s->reg_to_temp[reg] = args[0];
1578
    ots->reg = reg;
1579
    ots->val_type = TEMP_VAL_REG;
1580
    ots->mem_coherent = 0;
1581
}
1582

    
1583
static void tcg_reg_alloc_op(TCGContext *s, 
1584
                             const TCGOpDef *def, TCGOpcode opc,
1585
                             const TCGArg *args,
1586
                             unsigned int dead_iargs)
1587
{
1588
    TCGRegSet allocated_regs;
1589
    int i, k, nb_iargs, nb_oargs, reg;
1590
    TCGArg arg;
1591
    const TCGArgConstraint *arg_ct;
1592
    TCGTemp *ts;
1593
    TCGArg new_args[TCG_MAX_OP_ARGS];
1594
    int const_args[TCG_MAX_OP_ARGS];
1595

    
1596
    nb_oargs = def->nb_oargs;
1597
    nb_iargs = def->nb_iargs;
1598

    
1599
    /* copy constants */
1600
    memcpy(new_args + nb_oargs + nb_iargs, 
1601
           args + nb_oargs + nb_iargs, 
1602
           sizeof(TCGArg) * def->nb_cargs);
1603

    
1604
    /* satisfy input constraints */ 
1605
    tcg_regset_set(allocated_regs, s->reserved_regs);
1606
    for(k = 0; k < nb_iargs; k++) {
1607
        i = def->sorted_args[nb_oargs + k];
1608
        arg = args[i];
1609
        arg_ct = &def->args_ct[i];
1610
        ts = &s->temps[arg];
1611
        if (ts->val_type == TEMP_VAL_MEM) {
1612
            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1613
            tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1614
            ts->val_type = TEMP_VAL_REG;
1615
            ts->reg = reg;
1616
            ts->mem_coherent = 1;
1617
            s->reg_to_temp[reg] = arg;
1618
        } else if (ts->val_type == TEMP_VAL_CONST) {
1619
            if (tcg_target_const_match(ts->val, arg_ct)) {
1620
                /* constant is OK for instruction */
1621
                const_args[i] = 1;
1622
                new_args[i] = ts->val;
1623
                goto iarg_end;
1624
            } else {
1625
                /* need to move to a register */
1626
                reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1627
                tcg_out_movi(s, ts->type, reg, ts->val);
1628
                ts->val_type = TEMP_VAL_REG;
1629
                ts->reg = reg;
1630
                ts->mem_coherent = 0;
1631
                s->reg_to_temp[reg] = arg;
1632
            }
1633
        }
1634
        assert(ts->val_type == TEMP_VAL_REG);
1635
        if (arg_ct->ct & TCG_CT_IALIAS) {
1636
            if (ts->fixed_reg) {
1637
                /* if fixed register, we must allocate a new register
1638
                   if the alias is not the same register */
1639
                if (arg != args[arg_ct->alias_index])
1640
                    goto allocate_in_reg;
1641
            } else {
1642
                /* if the input is aliased to an output and if it is
1643
                   not dead after the instruction, we must allocate
1644
                   a new register and move it */
1645
                if (!IS_DEAD_IARG(i - nb_oargs)) 
1646
                    goto allocate_in_reg;
1647
            }
1648
        }
1649
        reg = ts->reg;
1650
        if (tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1651
            /* nothing to do : the constraint is satisfied */
1652
        } else {
1653
        allocate_in_reg:
1654
            /* allocate a new register matching the constraint 
1655
               and move the temporary register into it */
1656
            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1657
            tcg_out_mov(s, ts->type, reg, ts->reg);
1658
        }
1659
        new_args[i] = reg;
1660
        const_args[i] = 0;
1661
        tcg_regset_set_reg(allocated_regs, reg);
1662
    iarg_end: ;
1663
    }
1664
    
1665
    if (def->flags & TCG_OPF_BB_END) {
1666
        tcg_reg_alloc_bb_end(s, allocated_regs);
1667
    } else {
1668
        /* mark dead temporaries and free the associated registers */
1669
        for(i = 0; i < nb_iargs; i++) {
1670
            arg = args[nb_oargs + i];
1671
            if (IS_DEAD_IARG(i)) {
1672
                ts = &s->temps[arg];
1673
                if (!ts->fixed_reg) {
1674
                    if (ts->val_type == TEMP_VAL_REG)
1675
                        s->reg_to_temp[ts->reg] = -1;
1676
                    ts->val_type = TEMP_VAL_DEAD;
1677
                }
1678
            }
1679
        }
1680
        
1681
        if (def->flags & TCG_OPF_CALL_CLOBBER) {
1682
            /* XXX: permit generic clobber register list ? */ 
1683
            for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1684
                if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
1685
                    tcg_reg_free(s, reg);
1686
                }
1687
            }
1688
            /* XXX: for load/store we could do that only for the slow path
1689
               (i.e. when a memory callback is called) */
1690
            
1691
            /* store globals and free associated registers (we assume the insn
1692
               can modify any global. */
1693
            save_globals(s, allocated_regs);
1694
        }
1695
        
1696
        /* satisfy the output constraints */
1697
        tcg_regset_set(allocated_regs, s->reserved_regs);
1698
        for(k = 0; k < nb_oargs; k++) {
1699
            i = def->sorted_args[k];
1700
            arg = args[i];
1701
            arg_ct = &def->args_ct[i];
1702
            ts = &s->temps[arg];
1703
            if (arg_ct->ct & TCG_CT_ALIAS) {
1704
                reg = new_args[arg_ct->alias_index];
1705
            } else {
1706
                /* if fixed register, we try to use it */
1707
                reg = ts->reg;
1708
                if (ts->fixed_reg &&
1709
                    tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1710
                    goto oarg_end;
1711
                }
1712
                reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1713
            }
1714
            tcg_regset_set_reg(allocated_regs, reg);
1715
            /* if a fixed register is used, then a move will be done afterwards */
1716
            if (!ts->fixed_reg) {
1717
                if (ts->val_type == TEMP_VAL_REG)
1718
                    s->reg_to_temp[ts->reg] = -1;
1719
                ts->val_type = TEMP_VAL_REG;
1720
                ts->reg = reg;
1721
                /* temp value is modified, so the value kept in memory is
1722
                   potentially not the same */
1723
                ts->mem_coherent = 0; 
1724
                s->reg_to_temp[reg] = arg;
1725
            }
1726
        oarg_end:
1727
            new_args[i] = reg;
1728
        }
1729
    }
1730

    
1731
    /* emit instruction */
1732
    tcg_out_op(s, opc, new_args, const_args);
1733
    
1734
    /* move the outputs in the correct register if needed */
1735
    for(i = 0; i < nb_oargs; i++) {
1736
        ts = &s->temps[args[i]];
1737
        reg = new_args[i];
1738
        if (ts->fixed_reg && ts->reg != reg) {
1739
            tcg_out_mov(s, ts->type, ts->reg, reg);
1740
        }
1741
    }
1742
}
1743

    
1744
#ifdef TCG_TARGET_STACK_GROWSUP
1745
#define STACK_DIR(x) (-(x))
1746
#else
1747
#define STACK_DIR(x) (x)
1748
#endif
1749

    
1750
static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
1751
                              TCGOpcode opc, const TCGArg *args,
1752
                              unsigned int dead_iargs)
1753
{
1754
    int nb_iargs, nb_oargs, flags, nb_regs, i, reg, nb_params;
1755
    TCGArg arg, func_arg;
1756
    TCGTemp *ts;
1757
    tcg_target_long stack_offset, call_stack_size, func_addr;
1758
    int const_func_arg, allocate_args;
1759
    TCGRegSet allocated_regs;
1760
    const TCGArgConstraint *arg_ct;
1761

    
1762
    arg = *args++;
1763

    
1764
    nb_oargs = arg >> 16;
1765
    nb_iargs = arg & 0xffff;
1766
    nb_params = nb_iargs - 1;
1767

    
1768
    flags = args[nb_oargs + nb_iargs];
1769

    
1770
    nb_regs = tcg_target_get_call_iarg_regs_count(flags);
1771
    if (nb_regs > nb_params)
1772
        nb_regs = nb_params;
1773

    
1774
    /* assign stack slots first */
1775
    /* XXX: preallocate call stack */
1776
    call_stack_size = (nb_params - nb_regs) * sizeof(tcg_target_long);
1777
    call_stack_size = (call_stack_size + TCG_TARGET_STACK_ALIGN - 1) & 
1778
        ~(TCG_TARGET_STACK_ALIGN - 1);
1779
    allocate_args = (call_stack_size > TCG_STATIC_CALL_ARGS_SIZE);
1780
    if (allocate_args) {
1781
        tcg_out_addi(s, TCG_REG_CALL_STACK, -STACK_DIR(call_stack_size));
1782
    }
1783

    
1784
    stack_offset = TCG_TARGET_CALL_STACK_OFFSET;
1785
    for(i = nb_regs; i < nb_params; i++) {
1786
        arg = args[nb_oargs + i];
1787
#ifdef TCG_TARGET_STACK_GROWSUP
1788
        stack_offset -= sizeof(tcg_target_long);
1789
#endif
1790
        if (arg != TCG_CALL_DUMMY_ARG) {
1791
            ts = &s->temps[arg];
1792
            if (ts->val_type == TEMP_VAL_REG) {
1793
                tcg_out_st(s, ts->type, ts->reg, TCG_REG_CALL_STACK, stack_offset);
1794
            } else if (ts->val_type == TEMP_VAL_MEM) {
1795
                reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], 
1796
                                    s->reserved_regs);
1797
                /* XXX: not correct if reading values from the stack */
1798
                tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1799
                tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
1800
            } else if (ts->val_type == TEMP_VAL_CONST) {
1801
                reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], 
1802
                                    s->reserved_regs);
1803
                /* XXX: sign extend may be needed on some targets */
1804
                tcg_out_movi(s, ts->type, reg, ts->val);
1805
                tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
1806
            } else {
1807
                tcg_abort();
1808
            }
1809
        }
1810
#ifndef TCG_TARGET_STACK_GROWSUP
1811
        stack_offset += sizeof(tcg_target_long);
1812
#endif
1813
    }
1814
    
1815
    /* assign input registers */
1816
    tcg_regset_set(allocated_regs, s->reserved_regs);
1817
    for(i = 0; i < nb_regs; i++) {
1818
        arg = args[nb_oargs + i];
1819
        if (arg != TCG_CALL_DUMMY_ARG) {
1820
            ts = &s->temps[arg];
1821
            reg = tcg_target_call_iarg_regs[i];
1822
            tcg_reg_free(s, reg);
1823
            if (ts->val_type == TEMP_VAL_REG) {
1824
                if (ts->reg != reg) {
1825
                    tcg_out_mov(s, ts->type, reg, ts->reg);
1826
                }
1827
            } else if (ts->val_type == TEMP_VAL_MEM) {
1828
                tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1829
            } else if (ts->val_type == TEMP_VAL_CONST) {
1830
                /* XXX: sign extend ? */
1831
                tcg_out_movi(s, ts->type, reg, ts->val);
1832
            } else {
1833
                tcg_abort();
1834
            }
1835
            tcg_regset_set_reg(allocated_regs, reg);
1836
        }
1837
    }
1838
    
1839
    /* assign function address */
1840
    func_arg = args[nb_oargs + nb_iargs - 1];
1841
    arg_ct = &def->args_ct[0];
1842
    ts = &s->temps[func_arg];
1843
    func_addr = ts->val;
1844
    const_func_arg = 0;
1845
    if (ts->val_type == TEMP_VAL_MEM) {
1846
        reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1847
        tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1848
        func_arg = reg;
1849
        tcg_regset_set_reg(allocated_regs, reg);
1850
    } else if (ts->val_type == TEMP_VAL_REG) {
1851
        reg = ts->reg;
1852
        if (!tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1853
            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1854
            tcg_out_mov(s, ts->type, reg, ts->reg);
1855
        }
1856
        func_arg = reg;
1857
        tcg_regset_set_reg(allocated_regs, reg);
1858
    } else if (ts->val_type == TEMP_VAL_CONST) {
1859
        if (tcg_target_const_match(func_addr, arg_ct)) {
1860
            const_func_arg = 1;
1861
            func_arg = func_addr;
1862
        } else {
1863
            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1864
            tcg_out_movi(s, ts->type, reg, func_addr);
1865
            func_arg = reg;
1866
            tcg_regset_set_reg(allocated_regs, reg);
1867
        }
1868
    } else {
1869
        tcg_abort();
1870
    }
1871
        
1872
    
1873
    /* mark dead temporaries and free the associated registers */
1874
    for(i = 0; i < nb_iargs; i++) {
1875
        arg = args[nb_oargs + i];
1876
        if (IS_DEAD_IARG(i)) {
1877
            ts = &s->temps[arg];
1878
            if (!ts->fixed_reg) {
1879
                if (ts->val_type == TEMP_VAL_REG)
1880
                    s->reg_to_temp[ts->reg] = -1;
1881
                ts->val_type = TEMP_VAL_DEAD;
1882
            }
1883
        }
1884
    }
1885
    
1886
    /* clobber call registers */
1887
    for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1888
        if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
1889
            tcg_reg_free(s, reg);
1890
        }
1891
    }
1892
    
1893
    /* store globals and free associated registers (we assume the call
1894
       can modify any global. */
1895
    if (!(flags & TCG_CALL_CONST)) {
1896
        save_globals(s, allocated_regs);
1897
    }
1898

    
1899
    tcg_out_op(s, opc, &func_arg, &const_func_arg);
1900
    
1901
    if (allocate_args) {
1902
        tcg_out_addi(s, TCG_REG_CALL_STACK, STACK_DIR(call_stack_size));
1903
    }
1904

    
1905
    /* assign output registers and emit moves if needed */
1906
    for(i = 0; i < nb_oargs; i++) {
1907
        arg = args[i];
1908
        ts = &s->temps[arg];
1909
        reg = tcg_target_call_oarg_regs[i];
1910
        assert(s->reg_to_temp[reg] == -1);
1911
        if (ts->fixed_reg) {
1912
            if (ts->reg != reg) {
1913
                tcg_out_mov(s, ts->type, ts->reg, reg);
1914
            }
1915
        } else {
1916
            if (ts->val_type == TEMP_VAL_REG)
1917
                s->reg_to_temp[ts->reg] = -1;
1918
            ts->val_type = TEMP_VAL_REG;
1919
            ts->reg = reg;
1920
            ts->mem_coherent = 0; 
1921
            s->reg_to_temp[reg] = arg;
1922
        }
1923
    }
1924
    
1925
    return nb_iargs + nb_oargs + def->nb_cargs + 1;
1926
}
1927

    
1928
#ifdef CONFIG_PROFILER
1929

    
1930
static int64_t tcg_table_op_count[NB_OPS];
1931

    
1932
static void dump_op_count(void)
1933
{
1934
    int i;
1935
    FILE *f;
1936
    f = fopen("/tmp/op.log", "w");
1937
    for(i = INDEX_op_end; i < NB_OPS; i++) {
1938
        fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name, tcg_table_op_count[i]);
1939
    }
1940
    fclose(f);
1941
}
1942
#endif
1943

    
1944

    
1945
static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
1946
                                      long search_pc)
1947
{
1948
    TCGOpcode opc;
1949
    int op_index;
1950
    const TCGOpDef *def;
1951
    unsigned int dead_iargs;
1952
    const TCGArg *args;
1953

    
1954
#ifdef DEBUG_DISAS
1955
    if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
1956
        qemu_log("OP:\n");
1957
        tcg_dump_ops(s, logfile);
1958
        qemu_log("\n");
1959
    }
1960
#endif
1961

    
1962
#ifdef CONFIG_PROFILER
1963
    s->la_time -= profile_getclock();
1964
#endif
1965
    tcg_liveness_analysis(s);
1966
#ifdef CONFIG_PROFILER
1967
    s->la_time += profile_getclock();
1968
#endif
1969

    
1970
#ifdef DEBUG_DISAS
1971
    if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_OPT))) {
1972
        qemu_log("OP after liveness analysis:\n");
1973
        tcg_dump_ops(s, logfile);
1974
        qemu_log("\n");
1975
    }
1976
#endif
1977

    
1978
    tcg_reg_alloc_start(s);
1979

    
1980
    s->code_buf = gen_code_buf;
1981
    s->code_ptr = gen_code_buf;
1982

    
1983
    args = gen_opparam_buf;
1984
    op_index = 0;
1985

    
1986
    for(;;) {
1987
        opc = gen_opc_buf[op_index];
1988
#ifdef CONFIG_PROFILER
1989
        tcg_table_op_count[opc]++;
1990
#endif
1991
        def = &tcg_op_defs[opc];
1992
#if 0
1993
        printf("%s: %d %d %d\n", def->name,
1994
               def->nb_oargs, def->nb_iargs, def->nb_cargs);
1995
        //        dump_regs(s);
1996
#endif
1997
        switch(opc) {
1998
        case INDEX_op_mov_i32:
1999
#if TCG_TARGET_REG_BITS == 64
2000
        case INDEX_op_mov_i64:
2001
#endif
2002
            dead_iargs = s->op_dead_iargs[op_index];
2003
            tcg_reg_alloc_mov(s, def, args, dead_iargs);
2004
            break;
2005
        case INDEX_op_movi_i32:
2006
#if TCG_TARGET_REG_BITS == 64
2007
        case INDEX_op_movi_i64:
2008
#endif
2009
            tcg_reg_alloc_movi(s, args);
2010
            break;
2011
        case INDEX_op_debug_insn_start:
2012
            /* debug instruction */
2013
            break;
2014
        case INDEX_op_nop:
2015
        case INDEX_op_nop1:
2016
        case INDEX_op_nop2:
2017
        case INDEX_op_nop3:
2018
            break;
2019
        case INDEX_op_nopn:
2020
            args += args[0];
2021
            goto next;
2022
        case INDEX_op_discard:
2023
            {
2024
                TCGTemp *ts;
2025
                ts = &s->temps[args[0]];
2026
                /* mark the temporary as dead */
2027
                if (!ts->fixed_reg) {
2028
                    if (ts->val_type == TEMP_VAL_REG)
2029
                        s->reg_to_temp[ts->reg] = -1;
2030
                    ts->val_type = TEMP_VAL_DEAD;
2031
                }
2032
            }
2033
            break;
2034
        case INDEX_op_set_label:
2035
            tcg_reg_alloc_bb_end(s, s->reserved_regs);
2036
            tcg_out_label(s, args[0], (long)s->code_ptr);
2037
            break;
2038
        case INDEX_op_call:
2039
            dead_iargs = s->op_dead_iargs[op_index];
2040
            args += tcg_reg_alloc_call(s, def, opc, args, dead_iargs);
2041
            goto next;
2042
        case INDEX_op_end:
2043
            goto the_end;
2044
        default:
2045
            /* Note: in order to speed up the code, it would be much
2046
               faster to have specialized register allocator functions for
2047
               some common argument patterns */
2048
            dead_iargs = s->op_dead_iargs[op_index];
2049
            tcg_reg_alloc_op(s, def, opc, args, dead_iargs);
2050
            break;
2051
        }
2052
        args += def->nb_args;
2053
    next:
2054
        if (search_pc >= 0 && search_pc < s->code_ptr - gen_code_buf) {
2055
            return op_index;
2056
        }
2057
        op_index++;
2058
#ifndef NDEBUG
2059
        check_regs(s);
2060
#endif
2061
    }
2062
 the_end:
2063
    return -1;
2064
}
2065

    
2066
int tcg_gen_code(TCGContext *s, uint8_t *gen_code_buf)
2067
{
2068
#ifdef CONFIG_PROFILER
2069
    {
2070
        int n;
2071
        n = (gen_opc_ptr - gen_opc_buf);
2072
        s->op_count += n;
2073
        if (n > s->op_count_max)
2074
            s->op_count_max = n;
2075

    
2076
        s->temp_count += s->nb_temps;
2077
        if (s->nb_temps > s->temp_count_max)
2078
            s->temp_count_max = s->nb_temps;
2079
    }
2080
#endif
2081

    
2082
    tcg_gen_code_common(s, gen_code_buf, -1);
2083

    
2084
    /* flush instruction cache */
2085
    flush_icache_range((unsigned long)gen_code_buf, 
2086
                       (unsigned long)s->code_ptr);
2087
    return s->code_ptr -  gen_code_buf;
2088
}
2089

    
2090
/* Return the index of the micro operation such as the pc after is <
2091
   offset bytes from the start of the TB.  The contents of gen_code_buf must
2092
   not be changed, though writing the same values is ok.
2093
   Return -1 if not found. */
2094
int tcg_gen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, long offset)
2095
{
2096
    return tcg_gen_code_common(s, gen_code_buf, offset);
2097
}
2098

    
2099
#ifdef CONFIG_PROFILER
2100
void tcg_dump_info(FILE *f,
2101
                   int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
2102
{
2103
    TCGContext *s = &tcg_ctx;
2104
    int64_t tot;
2105

    
2106
    tot = s->interm_time + s->code_time;
2107
    cpu_fprintf(f, "JIT cycles          %" PRId64 " (%0.3f s at 2.4 GHz)\n",
2108
                tot, tot / 2.4e9);
2109
    cpu_fprintf(f, "translated TBs      %" PRId64 " (aborted=%" PRId64 " %0.1f%%)\n", 
2110
                s->tb_count, 
2111
                s->tb_count1 - s->tb_count,
2112
                s->tb_count1 ? (double)(s->tb_count1 - s->tb_count) / s->tb_count1 * 100.0 : 0);
2113
    cpu_fprintf(f, "avg ops/TB          %0.1f max=%d\n", 
2114
                s->tb_count ? (double)s->op_count / s->tb_count : 0, s->op_count_max);
2115
    cpu_fprintf(f, "deleted ops/TB      %0.2f\n",
2116
                s->tb_count ? 
2117
                (double)s->del_op_count / s->tb_count : 0);
2118
    cpu_fprintf(f, "avg temps/TB        %0.2f max=%d\n",
2119
                s->tb_count ? 
2120
                (double)s->temp_count / s->tb_count : 0,
2121
                s->temp_count_max);
2122
    
2123
    cpu_fprintf(f, "cycles/op           %0.1f\n", 
2124
                s->op_count ? (double)tot / s->op_count : 0);
2125
    cpu_fprintf(f, "cycles/in byte      %0.1f\n", 
2126
                s->code_in_len ? (double)tot / s->code_in_len : 0);
2127
    cpu_fprintf(f, "cycles/out byte     %0.1f\n", 
2128
                s->code_out_len ? (double)tot / s->code_out_len : 0);
2129
    if (tot == 0)
2130
        tot = 1;
2131
    cpu_fprintf(f, "  gen_interm time   %0.1f%%\n", 
2132
                (double)s->interm_time / tot * 100.0);
2133
    cpu_fprintf(f, "  gen_code time     %0.1f%%\n", 
2134
                (double)s->code_time / tot * 100.0);
2135
    cpu_fprintf(f, "liveness/code time  %0.1f%%\n", 
2136
                (double)s->la_time / (s->code_time ? s->code_time : 1) * 100.0);
2137
    cpu_fprintf(f, "cpu_restore count   %" PRId64 "\n",
2138
                s->restore_count);
2139
    cpu_fprintf(f, "  avg cycles        %0.1f\n",
2140
                s->restore_count ? (double)s->restore_time / s->restore_count : 0);
2141

    
2142
    dump_op_count();
2143
}
2144
#else
2145
void tcg_dump_info(FILE *f,
2146
                   int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
2147
{
2148
    cpu_fprintf(f, "[TCG profiler not compiled]\n");
2149
}
2150
#endif