Statistics
| Branch: | Revision:

root / tcg / tcg.c @ 813da627

History | View | Annotate | Download (72.8 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
#define USE_TCG_OPTIMIZATIONS
28

    
29
#include "config.h"
30

    
31
/* Define to jump the ELF file used to communicate with GDB.  */
32
#undef DEBUG_JIT
33

    
34
#if !defined(CONFIG_DEBUG_TCG) && !defined(NDEBUG)
35
/* define it to suppress various consistency checks (faster) */
36
#define NDEBUG
37
#endif
38

    
39
#include "qemu-common.h"
40
#include "cache-utils.h"
41
#include "host-utils.h"
42
#include "qemu-timer.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

    
50
#include "tcg-op.h"
51

    
52
#if TCG_TARGET_REG_BITS == 64
53
# define ELF_CLASS  ELFCLASS64
54
#else
55
# define ELF_CLASS  ELFCLASS32
56
#endif
57
#ifdef HOST_WORDS_BIGENDIAN
58
# define ELF_DATA   ELFDATA2MSB
59
#else
60
# define ELF_DATA   ELFDATA2LSB
61
#endif
62

    
63
#include "elf.h"
64

    
65
#if defined(CONFIG_USE_GUEST_BASE) && !defined(TCG_TARGET_HAS_GUEST_BASE)
66
#error GUEST_BASE not supported on this host.
67
#endif
68

    
69
/* Forward declarations for functions declared in tcg-target.c and used here. */
70
static void tcg_target_init(TCGContext *s);
71
static void tcg_target_qemu_prologue(TCGContext *s);
72
static void patch_reloc(uint8_t *code_ptr, int type, 
73
                        tcg_target_long value, tcg_target_long addend);
74

    
75
static void tcg_register_jit_int(void *buf, size_t size,
76
                                 void *debug_frame, size_t debug_frame_size)
77
    __attribute__((unused));
78

    
79
/* Forward declarations for functions declared and used in tcg-target.c. */
80
static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str);
81
static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg1,
82
                       tcg_target_long arg2);
83
static void tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg);
84
static void tcg_out_movi(TCGContext *s, TCGType type,
85
                         TCGReg ret, tcg_target_long arg);
86
static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
87
                       const int *const_args);
88
static void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, TCGReg arg1,
89
                       tcg_target_long arg2);
90
static int tcg_target_const_match(tcg_target_long val,
91
                                  const TCGArgConstraint *arg_ct);
92
static int tcg_target_get_call_iarg_regs_count(int flags);
93

    
94
TCGOpDef tcg_op_defs[] = {
95
#define DEF(s, oargs, iargs, cargs, flags) { #s, oargs, iargs, cargs, iargs + oargs + cargs, flags },
96
#include "tcg-opc.h"
97
#undef DEF
98
};
99
const size_t tcg_op_defs_max = ARRAY_SIZE(tcg_op_defs);
100

    
101
static TCGRegSet tcg_target_available_regs[2];
102
static TCGRegSet tcg_target_call_clobber_regs;
103

    
104
/* XXX: move that inside the context */
105
uint16_t *gen_opc_ptr;
106
TCGArg *gen_opparam_ptr;
107

    
108
static inline void tcg_out8(TCGContext *s, uint8_t v)
109
{
110
    *s->code_ptr++ = v;
111
}
112

    
113
static inline void tcg_out16(TCGContext *s, uint16_t v)
114
{
115
    *(uint16_t *)s->code_ptr = v;
116
    s->code_ptr += 2;
117
}
118

    
119
static inline void tcg_out32(TCGContext *s, uint32_t v)
120
{
121
    *(uint32_t *)s->code_ptr = v;
122
    s->code_ptr += 4;
123
}
124

    
125
/* label relocation processing */
126

    
127
static void tcg_out_reloc(TCGContext *s, uint8_t *code_ptr, int type,
128
                          int label_index, long addend)
129
{
130
    TCGLabel *l;
131
    TCGRelocation *r;
132

    
133
    l = &s->labels[label_index];
134
    if (l->has_value) {
135
        /* FIXME: This may break relocations on RISC targets that
136
           modify instruction fields in place.  The caller may not have 
137
           written the initial value.  */
138
        patch_reloc(code_ptr, type, l->u.value, addend);
139
    } else {
140
        /* add a new relocation entry */
141
        r = tcg_malloc(sizeof(TCGRelocation));
142
        r->type = type;
143
        r->ptr = code_ptr;
144
        r->addend = addend;
145
        r->next = l->u.first_reloc;
146
        l->u.first_reloc = r;
147
    }
148
}
149

    
150
static void tcg_out_label(TCGContext *s, int label_index, void *ptr)
151
{
152
    TCGLabel *l;
153
    TCGRelocation *r;
154
    tcg_target_long value = (tcg_target_long)ptr;
155

    
156
    l = &s->labels[label_index];
157
    if (l->has_value)
158
        tcg_abort();
159
    r = l->u.first_reloc;
160
    while (r != NULL) {
161
        patch_reloc(r->ptr, r->type, value, r->addend);
162
        r = r->next;
163
    }
164
    l->has_value = 1;
165
    l->u.value = value;
166
}
167

    
168
int gen_new_label(void)
169
{
170
    TCGContext *s = &tcg_ctx;
171
    int idx;
172
    TCGLabel *l;
173

    
174
    if (s->nb_labels >= TCG_MAX_LABELS)
175
        tcg_abort();
176
    idx = s->nb_labels++;
177
    l = &s->labels[idx];
178
    l->has_value = 0;
179
    l->u.first_reloc = NULL;
180
    return idx;
181
}
182

    
183
#include "tcg-target.c"
184

    
185
/* pool based memory allocation */
186
void *tcg_malloc_internal(TCGContext *s, int size)
187
{
188
    TCGPool *p;
189
    int pool_size;
190
    
191
    if (size > TCG_POOL_CHUNK_SIZE) {
192
        /* big malloc: insert a new pool (XXX: could optimize) */
193
        p = g_malloc(sizeof(TCGPool) + size);
194
        p->size = size;
195
        p->next = s->pool_first_large;
196
        s->pool_first_large = p;
197
        return p->data;
198
    } else {
199
        p = s->pool_current;
200
        if (!p) {
201
            p = s->pool_first;
202
            if (!p)
203
                goto new_pool;
204
        } else {
205
            if (!p->next) {
206
            new_pool:
207
                pool_size = TCG_POOL_CHUNK_SIZE;
208
                p = g_malloc(sizeof(TCGPool) + pool_size);
209
                p->size = pool_size;
210
                p->next = NULL;
211
                if (s->pool_current) 
212
                    s->pool_current->next = p;
213
                else
214
                    s->pool_first = p;
215
            } else {
216
                p = p->next;
217
            }
218
        }
219
    }
220
    s->pool_current = p;
221
    s->pool_cur = p->data + size;
222
    s->pool_end = p->data + p->size;
223
    return p->data;
224
}
225

    
226
void tcg_pool_reset(TCGContext *s)
227
{
228
    TCGPool *p, *t;
229
    for (p = s->pool_first_large; p; p = t) {
230
        t = p->next;
231
        g_free(p);
232
    }
233
    s->pool_first_large = NULL;
234
    s->pool_cur = s->pool_end = NULL;
235
    s->pool_current = NULL;
236
}
237

    
238
void tcg_context_init(TCGContext *s)
239
{
240
    int op, total_args, n;
241
    TCGOpDef *def;
242
    TCGArgConstraint *args_ct;
243
    int *sorted_args;
244

    
245
    memset(s, 0, sizeof(*s));
246
    s->temps = s->static_temps;
247
    s->nb_globals = 0;
248
    
249
    /* Count total number of arguments and allocate the corresponding
250
       space */
251
    total_args = 0;
252
    for(op = 0; op < NB_OPS; op++) {
253
        def = &tcg_op_defs[op];
254
        n = def->nb_iargs + def->nb_oargs;
255
        total_args += n;
256
    }
257

    
258
    args_ct = g_malloc(sizeof(TCGArgConstraint) * total_args);
259
    sorted_args = g_malloc(sizeof(int) * total_args);
260

    
261
    for(op = 0; op < NB_OPS; op++) {
262
        def = &tcg_op_defs[op];
263
        def->args_ct = args_ct;
264
        def->sorted_args = sorted_args;
265
        n = def->nb_iargs + def->nb_oargs;
266
        sorted_args += n;
267
        args_ct += n;
268
    }
269
    
270
    tcg_target_init(s);
271
}
272

    
273
void tcg_prologue_init(TCGContext *s)
274
{
275
    /* init global prologue and epilogue */
276
    s->code_buf = code_gen_prologue;
277
    s->code_ptr = s->code_buf;
278
    tcg_target_qemu_prologue(s);
279
    flush_icache_range((tcg_target_ulong)s->code_buf,
280
                       (tcg_target_ulong)s->code_ptr);
281
}
282

    
283
void tcg_set_frame(TCGContext *s, int reg,
284
                   tcg_target_long start, tcg_target_long size)
285
{
286
    s->frame_start = start;
287
    s->frame_end = start + size;
288
    s->frame_reg = reg;
289
}
290

    
291
void tcg_func_start(TCGContext *s)
292
{
293
    int i;
294
    tcg_pool_reset(s);
295
    s->nb_temps = s->nb_globals;
296
    for(i = 0; i < (TCG_TYPE_COUNT * 2); i++)
297
        s->first_free_temp[i] = -1;
298
    s->labels = tcg_malloc(sizeof(TCGLabel) * TCG_MAX_LABELS);
299
    s->nb_labels = 0;
300
    s->current_frame_offset = s->frame_start;
301

    
302
    gen_opc_ptr = gen_opc_buf;
303
    gen_opparam_ptr = gen_opparam_buf;
304
}
305

    
306
static inline void tcg_temp_alloc(TCGContext *s, int n)
307
{
308
    if (n > TCG_MAX_TEMPS)
309
        tcg_abort();
310
}
311

    
312
static inline int tcg_global_reg_new_internal(TCGType type, int reg,
313
                                              const char *name)
314
{
315
    TCGContext *s = &tcg_ctx;
316
    TCGTemp *ts;
317
    int idx;
318

    
319
#if TCG_TARGET_REG_BITS == 32
320
    if (type != TCG_TYPE_I32)
321
        tcg_abort();
322
#endif
323
    if (tcg_regset_test_reg(s->reserved_regs, reg))
324
        tcg_abort();
325
    idx = s->nb_globals;
326
    tcg_temp_alloc(s, s->nb_globals + 1);
327
    ts = &s->temps[s->nb_globals];
328
    ts->base_type = type;
329
    ts->type = type;
330
    ts->fixed_reg = 1;
331
    ts->reg = reg;
332
    ts->name = name;
333
    s->nb_globals++;
334
    tcg_regset_set_reg(s->reserved_regs, reg);
335
    return idx;
336
}
337

    
338
TCGv_i32 tcg_global_reg_new_i32(int reg, const char *name)
339
{
340
    int idx;
341

    
342
    idx = tcg_global_reg_new_internal(TCG_TYPE_I32, reg, name);
343
    return MAKE_TCGV_I32(idx);
344
}
345

    
346
TCGv_i64 tcg_global_reg_new_i64(int reg, const char *name)
347
{
348
    int idx;
349

    
350
    idx = tcg_global_reg_new_internal(TCG_TYPE_I64, reg, name);
351
    return MAKE_TCGV_I64(idx);
352
}
353

    
354
static inline int tcg_global_mem_new_internal(TCGType type, int reg,
355
                                              tcg_target_long offset,
356
                                              const char *name)
357
{
358
    TCGContext *s = &tcg_ctx;
359
    TCGTemp *ts;
360
    int idx;
361

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

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

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

    
415
TCGv_i32 tcg_global_mem_new_i32(int reg, tcg_target_long offset,
416
                                const char *name)
417
{
418
    int idx;
419

    
420
    idx = tcg_global_mem_new_internal(TCG_TYPE_I32, reg, offset, name);
421
    return MAKE_TCGV_I32(idx);
422
}
423

    
424
TCGv_i64 tcg_global_mem_new_i64(int reg, tcg_target_long offset,
425
                                const char *name)
426
{
427
    int idx;
428

    
429
    idx = tcg_global_mem_new_internal(TCG_TYPE_I64, reg, offset, name);
430
    return MAKE_TCGV_I64(idx);
431
}
432

    
433
static inline int tcg_temp_new_internal(TCGType type, int temp_local)
434
{
435
    TCGContext *s = &tcg_ctx;
436
    TCGTemp *ts;
437
    int idx, k;
438

    
439
    k = type;
440
    if (temp_local)
441
        k += TCG_TYPE_COUNT;
442
    idx = s->first_free_temp[k];
443
    if (idx != -1) {
444
        /* There is already an available temp with the
445
           right type */
446
        ts = &s->temps[idx];
447
        s->first_free_temp[k] = ts->next_free_temp;
448
        ts->temp_allocated = 1;
449
        assert(ts->temp_local == temp_local);
450
    } else {
451
        idx = s->nb_temps;
452
#if TCG_TARGET_REG_BITS == 32
453
        if (type == TCG_TYPE_I64) {
454
            tcg_temp_alloc(s, s->nb_temps + 2);
455
            ts = &s->temps[s->nb_temps];
456
            ts->base_type = type;
457
            ts->type = TCG_TYPE_I32;
458
            ts->temp_allocated = 1;
459
            ts->temp_local = temp_local;
460
            ts->name = NULL;
461
            ts++;
462
            ts->base_type = TCG_TYPE_I32;
463
            ts->type = TCG_TYPE_I32;
464
            ts->temp_allocated = 1;
465
            ts->temp_local = temp_local;
466
            ts->name = NULL;
467
            s->nb_temps += 2;
468
        } else
469
#endif
470
        {
471
            tcg_temp_alloc(s, s->nb_temps + 1);
472
            ts = &s->temps[s->nb_temps];
473
            ts->base_type = type;
474
            ts->type = type;
475
            ts->temp_allocated = 1;
476
            ts->temp_local = temp_local;
477
            ts->name = NULL;
478
            s->nb_temps++;
479
        }
480
    }
481

    
482
#if defined(CONFIG_DEBUG_TCG)
483
    s->temps_in_use++;
484
#endif
485
    return idx;
486
}
487

    
488
TCGv_i32 tcg_temp_new_internal_i32(int temp_local)
489
{
490
    int idx;
491

    
492
    idx = tcg_temp_new_internal(TCG_TYPE_I32, temp_local);
493
    return MAKE_TCGV_I32(idx);
494
}
495

    
496
TCGv_i64 tcg_temp_new_internal_i64(int temp_local)
497
{
498
    int idx;
499

    
500
    idx = tcg_temp_new_internal(TCG_TYPE_I64, temp_local);
501
    return MAKE_TCGV_I64(idx);
502
}
503

    
504
static inline void tcg_temp_free_internal(int idx)
505
{
506
    TCGContext *s = &tcg_ctx;
507
    TCGTemp *ts;
508
    int k;
509

    
510
#if defined(CONFIG_DEBUG_TCG)
511
    s->temps_in_use--;
512
    if (s->temps_in_use < 0) {
513
        fprintf(stderr, "More temporaries freed than allocated!\n");
514
    }
515
#endif
516

    
517
    assert(idx >= s->nb_globals && idx < s->nb_temps);
518
    ts = &s->temps[idx];
519
    assert(ts->temp_allocated != 0);
520
    ts->temp_allocated = 0;
521
    k = ts->base_type;
522
    if (ts->temp_local)
523
        k += TCG_TYPE_COUNT;
524
    ts->next_free_temp = s->first_free_temp[k];
525
    s->first_free_temp[k] = idx;
526
}
527

    
528
void tcg_temp_free_i32(TCGv_i32 arg)
529
{
530
    tcg_temp_free_internal(GET_TCGV_I32(arg));
531
}
532

    
533
void tcg_temp_free_i64(TCGv_i64 arg)
534
{
535
    tcg_temp_free_internal(GET_TCGV_I64(arg));
536
}
537

    
538
TCGv_i32 tcg_const_i32(int32_t val)
539
{
540
    TCGv_i32 t0;
541
    t0 = tcg_temp_new_i32();
542
    tcg_gen_movi_i32(t0, val);
543
    return t0;
544
}
545

    
546
TCGv_i64 tcg_const_i64(int64_t val)
547
{
548
    TCGv_i64 t0;
549
    t0 = tcg_temp_new_i64();
550
    tcg_gen_movi_i64(t0, val);
551
    return t0;
552
}
553

    
554
TCGv_i32 tcg_const_local_i32(int32_t val)
555
{
556
    TCGv_i32 t0;
557
    t0 = tcg_temp_local_new_i32();
558
    tcg_gen_movi_i32(t0, val);
559
    return t0;
560
}
561

    
562
TCGv_i64 tcg_const_local_i64(int64_t val)
563
{
564
    TCGv_i64 t0;
565
    t0 = tcg_temp_local_new_i64();
566
    tcg_gen_movi_i64(t0, val);
567
    return t0;
568
}
569

    
570
#if defined(CONFIG_DEBUG_TCG)
571
void tcg_clear_temp_count(void)
572
{
573
    TCGContext *s = &tcg_ctx;
574
    s->temps_in_use = 0;
575
}
576

    
577
int tcg_check_temp_count(void)
578
{
579
    TCGContext *s = &tcg_ctx;
580
    if (s->temps_in_use) {
581
        /* Clear the count so that we don't give another
582
         * warning immediately next time around.
583
         */
584
        s->temps_in_use = 0;
585
        return 1;
586
    }
587
    return 0;
588
}
589
#endif
590

    
591
void tcg_register_helper(void *func, const char *name)
592
{
593
    TCGContext *s = &tcg_ctx;
594
    int n;
595
    if ((s->nb_helpers + 1) > s->allocated_helpers) {
596
        n = s->allocated_helpers;
597
        if (n == 0) {
598
            n = 4;
599
        } else {
600
            n *= 2;
601
        }
602
        s->helpers = realloc(s->helpers, n * sizeof(TCGHelperInfo));
603
        s->allocated_helpers = n;
604
    }
605
    s->helpers[s->nb_helpers].func = (tcg_target_ulong)func;
606
    s->helpers[s->nb_helpers].name = name;
607
    s->nb_helpers++;
608
}
609

    
610
/* Note: we convert the 64 bit args to 32 bit and do some alignment
611
   and endian swap. Maybe it would be better to do the alignment
612
   and endian swap in tcg_reg_alloc_call(). */
613
void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags,
614
                   int sizemask, TCGArg ret, int nargs, TCGArg *args)
615
{
616
    int i;
617
    int real_args;
618
    int nb_rets;
619
    TCGArg *nparam;
620

    
621
#if defined(TCG_TARGET_EXTEND_ARGS) && TCG_TARGET_REG_BITS == 64
622
    for (i = 0; i < nargs; ++i) {
623
        int is_64bit = sizemask & (1 << (i+1)*2);
624
        int is_signed = sizemask & (2 << (i+1)*2);
625
        if (!is_64bit) {
626
            TCGv_i64 temp = tcg_temp_new_i64();
627
            TCGv_i64 orig = MAKE_TCGV_I64(args[i]);
628
            if (is_signed) {
629
                tcg_gen_ext32s_i64(temp, orig);
630
            } else {
631
                tcg_gen_ext32u_i64(temp, orig);
632
            }
633
            args[i] = GET_TCGV_I64(temp);
634
        }
635
    }
636
#endif /* TCG_TARGET_EXTEND_ARGS */
637

    
638
    *gen_opc_ptr++ = INDEX_op_call;
639
    nparam = gen_opparam_ptr++;
640
    if (ret != TCG_CALL_DUMMY_ARG) {
641
#if TCG_TARGET_REG_BITS < 64
642
        if (sizemask & 1) {
643
#ifdef TCG_TARGET_WORDS_BIGENDIAN
644
            *gen_opparam_ptr++ = ret + 1;
645
            *gen_opparam_ptr++ = ret;
646
#else
647
            *gen_opparam_ptr++ = ret;
648
            *gen_opparam_ptr++ = ret + 1;
649
#endif
650
            nb_rets = 2;
651
        } else
652
#endif
653
        {
654
            *gen_opparam_ptr++ = ret;
655
            nb_rets = 1;
656
        }
657
    } else {
658
        nb_rets = 0;
659
    }
660
    real_args = 0;
661
    for (i = 0; i < nargs; i++) {
662
#if TCG_TARGET_REG_BITS < 64
663
        int is_64bit = sizemask & (1 << (i+1)*2);
664
        if (is_64bit) {
665
#ifdef TCG_TARGET_CALL_ALIGN_ARGS
666
            /* some targets want aligned 64 bit args */
667
            if (real_args & 1) {
668
                *gen_opparam_ptr++ = TCG_CALL_DUMMY_ARG;
669
                real_args++;
670
            }
671
#endif
672
            /* If stack grows up, then we will be placing successive
673
               arguments at lower addresses, which means we need to
674
               reverse the order compared to how we would normally
675
               treat either big or little-endian.  For those arguments
676
               that will wind up in registers, this still works for
677
               HPPA (the only current STACK_GROWSUP target) since the
678
               argument registers are *also* allocated in decreasing
679
               order.  If another such target is added, this logic may
680
               have to get more complicated to differentiate between
681
               stack arguments and register arguments.  */
682
#if defined(TCG_TARGET_WORDS_BIGENDIAN) != defined(TCG_TARGET_STACK_GROWSUP)
683
            *gen_opparam_ptr++ = args[i] + 1;
684
            *gen_opparam_ptr++ = args[i];
685
#else
686
            *gen_opparam_ptr++ = args[i];
687
            *gen_opparam_ptr++ = args[i] + 1;
688
#endif
689
            real_args += 2;
690
            continue;
691
        }
692
#endif /* TCG_TARGET_REG_BITS < 64 */
693

    
694
        *gen_opparam_ptr++ = args[i];
695
        real_args++;
696
    }
697
    *gen_opparam_ptr++ = GET_TCGV_PTR(func);
698

    
699
    *gen_opparam_ptr++ = flags;
700

    
701
    *nparam = (nb_rets << 16) | (real_args + 1);
702

    
703
    /* total parameters, needed to go backward in the instruction stream */
704
    *gen_opparam_ptr++ = 1 + nb_rets + real_args + 3;
705

    
706
#if defined(TCG_TARGET_EXTEND_ARGS) && TCG_TARGET_REG_BITS == 64
707
    for (i = 0; i < nargs; ++i) {
708
        int is_64bit = sizemask & (1 << (i+1)*2);
709
        if (!is_64bit) {
710
            TCGv_i64 temp = MAKE_TCGV_I64(args[i]);
711
            tcg_temp_free_i64(temp);
712
        }
713
    }
714
#endif /* TCG_TARGET_EXTEND_ARGS */
715
}
716

    
717
#if TCG_TARGET_REG_BITS == 32
718
void tcg_gen_shifti_i64(TCGv_i64 ret, TCGv_i64 arg1,
719
                        int c, int right, int arith)
720
{
721
    if (c == 0) {
722
        tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg1));
723
        tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
724
    } else if (c >= 32) {
725
        c -= 32;
726
        if (right) {
727
            if (arith) {
728
                tcg_gen_sari_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
729
                tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 31);
730
            } else {
731
                tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
732
                tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
733
            }
734
        } else {
735
            tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_LOW(arg1), c);
736
            tcg_gen_movi_i32(TCGV_LOW(ret), 0);
737
        }
738
    } else {
739
        TCGv_i32 t0, t1;
740

    
741
        t0 = tcg_temp_new_i32();
742
        t1 = tcg_temp_new_i32();
743
        if (right) {
744
            tcg_gen_shli_i32(t0, TCGV_HIGH(arg1), 32 - c);
745
            if (arith)
746
                tcg_gen_sari_i32(t1, TCGV_HIGH(arg1), c);
747
            else
748
                tcg_gen_shri_i32(t1, TCGV_HIGH(arg1), c);
749
            tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_LOW(arg1), c);
750
            tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(ret), t0);
751
            tcg_gen_mov_i32(TCGV_HIGH(ret), t1);
752
        } else {
753
            tcg_gen_shri_i32(t0, TCGV_LOW(arg1), 32 - c);
754
            /* Note: ret can be the same as arg1, so we use t1 */
755
            tcg_gen_shli_i32(t1, TCGV_LOW(arg1), c);
756
            tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c);
757
            tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t0);
758
            tcg_gen_mov_i32(TCGV_LOW(ret), t1);
759
        }
760
        tcg_temp_free_i32(t0);
761
        tcg_temp_free_i32(t1);
762
    }
763
}
764
#endif
765

    
766

    
767
static void tcg_reg_alloc_start(TCGContext *s)
768
{
769
    int i;
770
    TCGTemp *ts;
771
    for(i = 0; i < s->nb_globals; i++) {
772
        ts = &s->temps[i];
773
        if (ts->fixed_reg) {
774
            ts->val_type = TEMP_VAL_REG;
775
        } else {
776
            ts->val_type = TEMP_VAL_MEM;
777
        }
778
    }
779
    for(i = s->nb_globals; i < s->nb_temps; i++) {
780
        ts = &s->temps[i];
781
        ts->val_type = TEMP_VAL_DEAD;
782
        ts->mem_allocated = 0;
783
        ts->fixed_reg = 0;
784
    }
785
    for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
786
        s->reg_to_temp[i] = -1;
787
    }
788
}
789

    
790
static char *tcg_get_arg_str_idx(TCGContext *s, char *buf, int buf_size,
791
                                 int idx)
792
{
793
    TCGTemp *ts;
794

    
795
    assert(idx >= 0 && idx < s->nb_temps);
796
    ts = &s->temps[idx];
797
    assert(ts);
798
    if (idx < s->nb_globals) {
799
        pstrcpy(buf, buf_size, ts->name);
800
    } else {
801
        if (ts->temp_local) 
802
            snprintf(buf, buf_size, "loc%d", idx - s->nb_globals);
803
        else
804
            snprintf(buf, buf_size, "tmp%d", idx - s->nb_globals);
805
    }
806
    return buf;
807
}
808

    
809
char *tcg_get_arg_str_i32(TCGContext *s, char *buf, int buf_size, TCGv_i32 arg)
810
{
811
    return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I32(arg));
812
}
813

    
814
char *tcg_get_arg_str_i64(TCGContext *s, char *buf, int buf_size, TCGv_i64 arg)
815
{
816
    return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I64(arg));
817
}
818

    
819
static int helper_cmp(const void *p1, const void *p2)
820
{
821
    const TCGHelperInfo *th1 = p1;
822
    const TCGHelperInfo *th2 = p2;
823
    if (th1->func < th2->func)
824
        return -1;
825
    else if (th1->func == th2->func)
826
        return 0;
827
    else
828
        return 1;
829
}
830

    
831
/* find helper definition (Note: A hash table would be better) */
832
static TCGHelperInfo *tcg_find_helper(TCGContext *s, tcg_target_ulong val)
833
{
834
    int m, m_min, m_max;
835
    TCGHelperInfo *th;
836
    tcg_target_ulong v;
837

    
838
    if (unlikely(!s->helpers_sorted)) {
839
        qsort(s->helpers, s->nb_helpers, sizeof(TCGHelperInfo), 
840
              helper_cmp);
841
        s->helpers_sorted = 1;
842
    }
843

    
844
    /* binary search */
845
    m_min = 0;
846
    m_max = s->nb_helpers - 1;
847
    while (m_min <= m_max) {
848
        m = (m_min + m_max) >> 1;
849
        th = &s->helpers[m];
850
        v = th->func;
851
        if (v == val)
852
            return th;
853
        else if (val < v) {
854
            m_max = m - 1;
855
        } else {
856
            m_min = m + 1;
857
        }
858
    }
859
    return NULL;
860
}
861

    
862
static const char * const cond_name[] =
863
{
864
    [TCG_COND_EQ] = "eq",
865
    [TCG_COND_NE] = "ne",
866
    [TCG_COND_LT] = "lt",
867
    [TCG_COND_GE] = "ge",
868
    [TCG_COND_LE] = "le",
869
    [TCG_COND_GT] = "gt",
870
    [TCG_COND_LTU] = "ltu",
871
    [TCG_COND_GEU] = "geu",
872
    [TCG_COND_LEU] = "leu",
873
    [TCG_COND_GTU] = "gtu"
874
};
875

    
876
void tcg_dump_ops(TCGContext *s, FILE *outfile)
877
{
878
    const uint16_t *opc_ptr;
879
    const TCGArg *args;
880
    TCGArg arg;
881
    TCGOpcode c;
882
    int i, k, nb_oargs, nb_iargs, nb_cargs, first_insn;
883
    const TCGOpDef *def;
884
    char buf[128];
885

    
886
    first_insn = 1;
887
    opc_ptr = gen_opc_buf;
888
    args = gen_opparam_buf;
889
    while (opc_ptr < gen_opc_ptr) {
890
        c = *opc_ptr++;
891
        def = &tcg_op_defs[c];
892
        if (c == INDEX_op_debug_insn_start) {
893
            uint64_t pc;
894
#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
895
            pc = ((uint64_t)args[1] << 32) | args[0];
896
#else
897
            pc = args[0];
898
#endif
899
            if (!first_insn) 
900
                fprintf(outfile, "\n");
901
            fprintf(outfile, " ---- 0x%" PRIx64, pc);
902
            first_insn = 0;
903
            nb_oargs = def->nb_oargs;
904
            nb_iargs = def->nb_iargs;
905
            nb_cargs = def->nb_cargs;
906
        } else if (c == INDEX_op_call) {
907
            TCGArg arg;
908

    
909
            /* variable number of arguments */
910
            arg = *args++;
911
            nb_oargs = arg >> 16;
912
            nb_iargs = arg & 0xffff;
913
            nb_cargs = def->nb_cargs;
914

    
915
            fprintf(outfile, " %s ", def->name);
916

    
917
            /* function name */
918
            fprintf(outfile, "%s",
919
                    tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + nb_iargs - 1]));
920
            /* flags */
921
            fprintf(outfile, ",$0x%" TCG_PRIlx,
922
                    args[nb_oargs + nb_iargs]);
923
            /* nb out args */
924
            fprintf(outfile, ",$%d", nb_oargs);
925
            for(i = 0; i < nb_oargs; i++) {
926
                fprintf(outfile, ",");
927
                fprintf(outfile, "%s",
928
                        tcg_get_arg_str_idx(s, buf, sizeof(buf), args[i]));
929
            }
930
            for(i = 0; i < (nb_iargs - 1); i++) {
931
                fprintf(outfile, ",");
932
                if (args[nb_oargs + i] == TCG_CALL_DUMMY_ARG) {
933
                    fprintf(outfile, "<dummy>");
934
                } else {
935
                    fprintf(outfile, "%s",
936
                            tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + i]));
937
                }
938
            }
939
        } else if (c == INDEX_op_movi_i32 
940
#if TCG_TARGET_REG_BITS == 64
941
                   || c == INDEX_op_movi_i64
942
#endif
943
                   ) {
944
            tcg_target_ulong val;
945
            TCGHelperInfo *th;
946

    
947
            nb_oargs = def->nb_oargs;
948
            nb_iargs = def->nb_iargs;
949
            nb_cargs = def->nb_cargs;
950
            fprintf(outfile, " %s %s,$", def->name, 
951
                    tcg_get_arg_str_idx(s, buf, sizeof(buf), args[0]));
952
            val = args[1];
953
            th = tcg_find_helper(s, val);
954
            if (th) {
955
                fprintf(outfile, "%s", th->name);
956
            } else {
957
                if (c == INDEX_op_movi_i32)
958
                    fprintf(outfile, "0x%x", (uint32_t)val);
959
                else
960
                    fprintf(outfile, "0x%" PRIx64 , (uint64_t)val);
961
            }
962
        } else {
963
            fprintf(outfile, " %s ", def->name);
964
            if (c == INDEX_op_nopn) {
965
                /* variable number of arguments */
966
                nb_cargs = *args;
967
                nb_oargs = 0;
968
                nb_iargs = 0;
969
            } else {
970
                nb_oargs = def->nb_oargs;
971
                nb_iargs = def->nb_iargs;
972
                nb_cargs = def->nb_cargs;
973
            }
974
            
975
            k = 0;
976
            for(i = 0; i < nb_oargs; i++) {
977
                if (k != 0)
978
                    fprintf(outfile, ",");
979
                fprintf(outfile, "%s",
980
                        tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
981
            }
982
            for(i = 0; i < nb_iargs; i++) {
983
                if (k != 0)
984
                    fprintf(outfile, ",");
985
                fprintf(outfile, "%s",
986
                        tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
987
            }
988
            switch (c) {
989
            case INDEX_op_brcond_i32:
990
#if TCG_TARGET_REG_BITS == 32
991
            case INDEX_op_brcond2_i32:
992
#elif TCG_TARGET_REG_BITS == 64
993
            case INDEX_op_brcond_i64:
994
#endif
995
            case INDEX_op_setcond_i32:
996
#if TCG_TARGET_REG_BITS == 32
997
            case INDEX_op_setcond2_i32:
998
#elif TCG_TARGET_REG_BITS == 64
999
            case INDEX_op_setcond_i64:
1000
#endif
1001
                if (args[k] < ARRAY_SIZE(cond_name) && cond_name[args[k]])
1002
                    fprintf(outfile, ",%s", cond_name[args[k++]]);
1003
                else
1004
                    fprintf(outfile, ",$0x%" TCG_PRIlx, args[k++]);
1005
                i = 1;
1006
                break;
1007
            default:
1008
                i = 0;
1009
                break;
1010
            }
1011
            for(; i < nb_cargs; i++) {
1012
                if (k != 0)
1013
                    fprintf(outfile, ",");
1014
                arg = args[k++];
1015
                fprintf(outfile, "$0x%" TCG_PRIlx, arg);
1016
            }
1017
        }
1018
        fprintf(outfile, "\n");
1019
        args += nb_iargs + nb_oargs + nb_cargs;
1020
    }
1021
}
1022

    
1023
/* we give more priority to constraints with less registers */
1024
static int get_constraint_priority(const TCGOpDef *def, int k)
1025
{
1026
    const TCGArgConstraint *arg_ct;
1027

    
1028
    int i, n;
1029
    arg_ct = &def->args_ct[k];
1030
    if (arg_ct->ct & TCG_CT_ALIAS) {
1031
        /* an alias is equivalent to a single register */
1032
        n = 1;
1033
    } else {
1034
        if (!(arg_ct->ct & TCG_CT_REG))
1035
            return 0;
1036
        n = 0;
1037
        for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
1038
            if (tcg_regset_test_reg(arg_ct->u.regs, i))
1039
                n++;
1040
        }
1041
    }
1042
    return TCG_TARGET_NB_REGS - n + 1;
1043
}
1044

    
1045
/* sort from highest priority to lowest */
1046
static void sort_constraints(TCGOpDef *def, int start, int n)
1047
{
1048
    int i, j, p1, p2, tmp;
1049

    
1050
    for(i = 0; i < n; i++)
1051
        def->sorted_args[start + i] = start + i;
1052
    if (n <= 1)
1053
        return;
1054
    for(i = 0; i < n - 1; i++) {
1055
        for(j = i + 1; j < n; j++) {
1056
            p1 = get_constraint_priority(def, def->sorted_args[start + i]);
1057
            p2 = get_constraint_priority(def, def->sorted_args[start + j]);
1058
            if (p1 < p2) {
1059
                tmp = def->sorted_args[start + i];
1060
                def->sorted_args[start + i] = def->sorted_args[start + j];
1061
                def->sorted_args[start + j] = tmp;
1062
            }
1063
        }
1064
    }
1065
}
1066

    
1067
void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs)
1068
{
1069
    TCGOpcode op;
1070
    TCGOpDef *def;
1071
    const char *ct_str;
1072
    int i, nb_args;
1073

    
1074
    for(;;) {
1075
        if (tdefs->op == (TCGOpcode)-1)
1076
            break;
1077
        op = tdefs->op;
1078
        assert((unsigned)op < NB_OPS);
1079
        def = &tcg_op_defs[op];
1080
#if defined(CONFIG_DEBUG_TCG)
1081
        /* Duplicate entry in op definitions? */
1082
        assert(!def->used);
1083
        def->used = 1;
1084
#endif
1085
        nb_args = def->nb_iargs + def->nb_oargs;
1086
        for(i = 0; i < nb_args; i++) {
1087
            ct_str = tdefs->args_ct_str[i];
1088
            /* Incomplete TCGTargetOpDef entry? */
1089
            assert(ct_str != NULL);
1090
            tcg_regset_clear(def->args_ct[i].u.regs);
1091
            def->args_ct[i].ct = 0;
1092
            if (ct_str[0] >= '0' && ct_str[0] <= '9') {
1093
                int oarg;
1094
                oarg = ct_str[0] - '0';
1095
                assert(oarg < def->nb_oargs);
1096
                assert(def->args_ct[oarg].ct & TCG_CT_REG);
1097
                /* TCG_CT_ALIAS is for the output arguments. The input
1098
                   argument is tagged with TCG_CT_IALIAS. */
1099
                def->args_ct[i] = def->args_ct[oarg];
1100
                def->args_ct[oarg].ct = TCG_CT_ALIAS;
1101
                def->args_ct[oarg].alias_index = i;
1102
                def->args_ct[i].ct |= TCG_CT_IALIAS;
1103
                def->args_ct[i].alias_index = oarg;
1104
            } else {
1105
                for(;;) {
1106
                    if (*ct_str == '\0')
1107
                        break;
1108
                    switch(*ct_str) {
1109
                    case 'i':
1110
                        def->args_ct[i].ct |= TCG_CT_CONST;
1111
                        ct_str++;
1112
                        break;
1113
                    default:
1114
                        if (target_parse_constraint(&def->args_ct[i], &ct_str) < 0) {
1115
                            fprintf(stderr, "Invalid constraint '%s' for arg %d of operation '%s'\n",
1116
                                    ct_str, i, def->name);
1117
                            exit(1);
1118
                        }
1119
                    }
1120
                }
1121
            }
1122
        }
1123

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

    
1127
        /* sort the constraints (XXX: this is just an heuristic) */
1128
        sort_constraints(def, 0, def->nb_oargs);
1129
        sort_constraints(def, def->nb_oargs, def->nb_iargs);
1130

    
1131
#if 0
1132
        {
1133
            int i;
1134

1135
            printf("%s: sorted=", def->name);
1136
            for(i = 0; i < def->nb_oargs + def->nb_iargs; i++)
1137
                printf(" %d", def->sorted_args[i]);
1138
            printf("\n");
1139
        }
1140
#endif
1141
        tdefs++;
1142
    }
1143

    
1144
#if defined(CONFIG_DEBUG_TCG)
1145
    i = 0;
1146
    for (op = 0; op < ARRAY_SIZE(tcg_op_defs); op++) {
1147
        const TCGOpDef *def = &tcg_op_defs[op];
1148
        if (op < INDEX_op_call
1149
            || op == INDEX_op_debug_insn_start
1150
            || (def->flags & TCG_OPF_NOT_PRESENT)) {
1151
            /* Wrong entry in op definitions? */
1152
            if (def->used) {
1153
                fprintf(stderr, "Invalid op definition for %s\n", def->name);
1154
                i = 1;
1155
            }
1156
        } else {
1157
            /* Missing entry in op definitions? */
1158
            if (!def->used) {
1159
                fprintf(stderr, "Missing op definition for %s\n", def->name);
1160
                i = 1;
1161
            }
1162
        }
1163
    }
1164
    if (i == 1) {
1165
        tcg_abort();
1166
    }
1167
#endif
1168
}
1169

    
1170
#ifdef USE_LIVENESS_ANALYSIS
1171

    
1172
/* set a nop for an operation using 'nb_args' */
1173
static inline void tcg_set_nop(TCGContext *s, uint16_t *opc_ptr, 
1174
                               TCGArg *args, int nb_args)
1175
{
1176
    if (nb_args == 0) {
1177
        *opc_ptr = INDEX_op_nop;
1178
    } else {
1179
        *opc_ptr = INDEX_op_nopn;
1180
        args[0] = nb_args;
1181
        args[nb_args - 1] = nb_args;
1182
    }
1183
}
1184

    
1185
/* liveness analysis: end of function: globals are live, temps are
1186
   dead. */
1187
/* XXX: at this stage, not used as there would be little gains because
1188
   most TBs end with a conditional jump. */
1189
static inline void tcg_la_func_end(TCGContext *s, uint8_t *dead_temps)
1190
{
1191
    memset(dead_temps, 0, s->nb_globals);
1192
    memset(dead_temps + s->nb_globals, 1, s->nb_temps - s->nb_globals);
1193
}
1194

    
1195
/* liveness analysis: end of basic block: globals are live, temps are
1196
   dead, local temps are live. */
1197
static inline void tcg_la_bb_end(TCGContext *s, uint8_t *dead_temps)
1198
{
1199
    int i;
1200
    TCGTemp *ts;
1201

    
1202
    memset(dead_temps, 0, s->nb_globals);
1203
    ts = &s->temps[s->nb_globals];
1204
    for(i = s->nb_globals; i < s->nb_temps; i++) {
1205
        if (ts->temp_local)
1206
            dead_temps[i] = 0;
1207
        else
1208
            dead_temps[i] = 1;
1209
        ts++;
1210
    }
1211
}
1212

    
1213
/* Liveness analysis : update the opc_dead_args array to tell if a
1214
   given input arguments is dead. Instructions updating dead
1215
   temporaries are removed. */
1216
static void tcg_liveness_analysis(TCGContext *s)
1217
{
1218
    int i, op_index, nb_args, nb_iargs, nb_oargs, arg, nb_ops;
1219
    TCGOpcode op;
1220
    TCGArg *args;
1221
    const TCGOpDef *def;
1222
    uint8_t *dead_temps;
1223
    unsigned int dead_args;
1224
    
1225
    gen_opc_ptr++; /* skip end */
1226

    
1227
    nb_ops = gen_opc_ptr - gen_opc_buf;
1228

    
1229
    s->op_dead_args = tcg_malloc(nb_ops * sizeof(uint16_t));
1230
    
1231
    dead_temps = tcg_malloc(s->nb_temps);
1232
    memset(dead_temps, 1, s->nb_temps);
1233

    
1234
    args = gen_opparam_ptr;
1235
    op_index = nb_ops - 1;
1236
    while (op_index >= 0) {
1237
        op = gen_opc_buf[op_index];
1238
        def = &tcg_op_defs[op];
1239
        switch(op) {
1240
        case INDEX_op_call:
1241
            {
1242
                int call_flags;
1243

    
1244
                nb_args = args[-1];
1245
                args -= nb_args;
1246
                nb_iargs = args[0] & 0xffff;
1247
                nb_oargs = args[0] >> 16;
1248
                args++;
1249
                call_flags = args[nb_oargs + nb_iargs];
1250

    
1251
                /* pure functions can be removed if their result is not
1252
                   used */
1253
                if (call_flags & TCG_CALL_PURE) {
1254
                    for(i = 0; i < nb_oargs; i++) {
1255
                        arg = args[i];
1256
                        if (!dead_temps[arg])
1257
                            goto do_not_remove_call;
1258
                    }
1259
                    tcg_set_nop(s, gen_opc_buf + op_index, 
1260
                                args - 1, nb_args);
1261
                } else {
1262
                do_not_remove_call:
1263

    
1264
                    /* output args are dead */
1265
                    dead_args = 0;
1266
                    for(i = 0; i < nb_oargs; i++) {
1267
                        arg = args[i];
1268
                        if (dead_temps[arg]) {
1269
                            dead_args |= (1 << i);
1270
                        }
1271
                        dead_temps[arg] = 1;
1272
                    }
1273
                    
1274
                    if (!(call_flags & TCG_CALL_CONST)) {
1275
                        /* globals are live (they may be used by the call) */
1276
                        memset(dead_temps, 0, s->nb_globals);
1277
                    }
1278

    
1279
                    /* input args are live */
1280
                    for(i = nb_oargs; i < nb_iargs + nb_oargs; i++) {
1281
                        arg = args[i];
1282
                        if (arg != TCG_CALL_DUMMY_ARG) {
1283
                            if (dead_temps[arg]) {
1284
                                dead_args |= (1 << i);
1285
                            }
1286
                            dead_temps[arg] = 0;
1287
                        }
1288
                    }
1289
                    s->op_dead_args[op_index] = dead_args;
1290
                }
1291
                args--;
1292
            }
1293
            break;
1294
        case INDEX_op_set_label:
1295
            args--;
1296
            /* mark end of basic block */
1297
            tcg_la_bb_end(s, dead_temps);
1298
            break;
1299
        case INDEX_op_debug_insn_start:
1300
            args -= def->nb_args;
1301
            break;
1302
        case INDEX_op_nopn:
1303
            nb_args = args[-1];
1304
            args -= nb_args;
1305
            break;
1306
        case INDEX_op_discard:
1307
            args--;
1308
            /* mark the temporary as dead */
1309
            dead_temps[args[0]] = 1;
1310
            break;
1311
        case INDEX_op_end:
1312
            break;
1313
            /* XXX: optimize by hardcoding common cases (e.g. triadic ops) */
1314
        default:
1315
            args -= def->nb_args;
1316
            nb_iargs = def->nb_iargs;
1317
            nb_oargs = def->nb_oargs;
1318

    
1319
            /* Test if the operation can be removed because all
1320
               its outputs are dead. We assume that nb_oargs == 0
1321
               implies side effects */
1322
            if (!(def->flags & TCG_OPF_SIDE_EFFECTS) && nb_oargs != 0) {
1323
                for(i = 0; i < nb_oargs; i++) {
1324
                    arg = args[i];
1325
                    if (!dead_temps[arg])
1326
                        goto do_not_remove;
1327
                }
1328
                tcg_set_nop(s, gen_opc_buf + op_index, args, def->nb_args);
1329
#ifdef CONFIG_PROFILER
1330
                s->del_op_count++;
1331
#endif
1332
            } else {
1333
            do_not_remove:
1334

    
1335
                /* output args are dead */
1336
                dead_args = 0;
1337
                for(i = 0; i < nb_oargs; i++) {
1338
                    arg = args[i];
1339
                    if (dead_temps[arg]) {
1340
                        dead_args |= (1 << i);
1341
                    }
1342
                    dead_temps[arg] = 1;
1343
                }
1344

    
1345
                /* if end of basic block, update */
1346
                if (def->flags & TCG_OPF_BB_END) {
1347
                    tcg_la_bb_end(s, dead_temps);
1348
                } else if (def->flags & TCG_OPF_CALL_CLOBBER) {
1349
                    /* globals are live */
1350
                    memset(dead_temps, 0, s->nb_globals);
1351
                }
1352

    
1353
                /* input args are live */
1354
                for(i = nb_oargs; i < nb_oargs + nb_iargs; i++) {
1355
                    arg = args[i];
1356
                    if (dead_temps[arg]) {
1357
                        dead_args |= (1 << i);
1358
                    }
1359
                    dead_temps[arg] = 0;
1360
                }
1361
                s->op_dead_args[op_index] = dead_args;
1362
            }
1363
            break;
1364
        }
1365
        op_index--;
1366
    }
1367

    
1368
    if (args != gen_opparam_buf)
1369
        tcg_abort();
1370
}
1371
#else
1372
/* dummy liveness analysis */
1373
static void tcg_liveness_analysis(TCGContext *s)
1374
{
1375
    int nb_ops;
1376
    nb_ops = gen_opc_ptr - gen_opc_buf;
1377

    
1378
    s->op_dead_args = tcg_malloc(nb_ops * sizeof(uint16_t));
1379
    memset(s->op_dead_args, 0, nb_ops * sizeof(uint16_t));
1380
}
1381
#endif
1382

    
1383
#ifndef NDEBUG
1384
static void dump_regs(TCGContext *s)
1385
{
1386
    TCGTemp *ts;
1387
    int i;
1388
    char buf[64];
1389

    
1390
    for(i = 0; i < s->nb_temps; i++) {
1391
        ts = &s->temps[i];
1392
        printf("  %10s: ", tcg_get_arg_str_idx(s, buf, sizeof(buf), i));
1393
        switch(ts->val_type) {
1394
        case TEMP_VAL_REG:
1395
            printf("%s", tcg_target_reg_names[ts->reg]);
1396
            break;
1397
        case TEMP_VAL_MEM:
1398
            printf("%d(%s)", (int)ts->mem_offset, tcg_target_reg_names[ts->mem_reg]);
1399
            break;
1400
        case TEMP_VAL_CONST:
1401
            printf("$0x%" TCG_PRIlx, ts->val);
1402
            break;
1403
        case TEMP_VAL_DEAD:
1404
            printf("D");
1405
            break;
1406
        default:
1407
            printf("???");
1408
            break;
1409
        }
1410
        printf("\n");
1411
    }
1412

    
1413
    for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
1414
        if (s->reg_to_temp[i] >= 0) {
1415
            printf("%s: %s\n", 
1416
                   tcg_target_reg_names[i], 
1417
                   tcg_get_arg_str_idx(s, buf, sizeof(buf), s->reg_to_temp[i]));
1418
        }
1419
    }
1420
}
1421

    
1422
static void check_regs(TCGContext *s)
1423
{
1424
    int reg, k;
1425
    TCGTemp *ts;
1426
    char buf[64];
1427

    
1428
    for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1429
        k = s->reg_to_temp[reg];
1430
        if (k >= 0) {
1431
            ts = &s->temps[k];
1432
            if (ts->val_type != TEMP_VAL_REG ||
1433
                ts->reg != reg) {
1434
                printf("Inconsistency for register %s:\n", 
1435
                       tcg_target_reg_names[reg]);
1436
                goto fail;
1437
            }
1438
        }
1439
    }
1440
    for(k = 0; k < s->nb_temps; k++) {
1441
        ts = &s->temps[k];
1442
        if (ts->val_type == TEMP_VAL_REG &&
1443
            !ts->fixed_reg &&
1444
            s->reg_to_temp[ts->reg] != k) {
1445
                printf("Inconsistency for temp %s:\n", 
1446
                       tcg_get_arg_str_idx(s, buf, sizeof(buf), k));
1447
        fail:
1448
                printf("reg state:\n");
1449
                dump_regs(s);
1450
                tcg_abort();
1451
        }
1452
    }
1453
}
1454
#endif
1455

    
1456
static void temp_allocate_frame(TCGContext *s, int temp)
1457
{
1458
    TCGTemp *ts;
1459
    ts = &s->temps[temp];
1460
#ifndef __sparc_v9__ /* Sparc64 stack is accessed with offset of 2047 */
1461
    s->current_frame_offset = (s->current_frame_offset +
1462
                               (tcg_target_long)sizeof(tcg_target_long) - 1) &
1463
        ~(sizeof(tcg_target_long) - 1);
1464
#endif
1465
    if (s->current_frame_offset + (tcg_target_long)sizeof(tcg_target_long) >
1466
        s->frame_end) {
1467
        tcg_abort();
1468
    }
1469
    ts->mem_offset = s->current_frame_offset;
1470
    ts->mem_reg = s->frame_reg;
1471
    ts->mem_allocated = 1;
1472
    s->current_frame_offset += (tcg_target_long)sizeof(tcg_target_long);
1473
}
1474

    
1475
/* free register 'reg' by spilling the corresponding temporary if necessary */
1476
static void tcg_reg_free(TCGContext *s, int reg)
1477
{
1478
    TCGTemp *ts;
1479
    int temp;
1480

    
1481
    temp = s->reg_to_temp[reg];
1482
    if (temp != -1) {
1483
        ts = &s->temps[temp];
1484
        assert(ts->val_type == TEMP_VAL_REG);
1485
        if (!ts->mem_coherent) {
1486
            if (!ts->mem_allocated) 
1487
                temp_allocate_frame(s, temp);
1488
            tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1489
        }
1490
        ts->val_type = TEMP_VAL_MEM;
1491
        s->reg_to_temp[reg] = -1;
1492
    }
1493
}
1494

    
1495
/* Allocate a register belonging to reg1 & ~reg2 */
1496
static int tcg_reg_alloc(TCGContext *s, TCGRegSet reg1, TCGRegSet reg2)
1497
{
1498
    int i, reg;
1499
    TCGRegSet reg_ct;
1500

    
1501
    tcg_regset_andnot(reg_ct, reg1, reg2);
1502

    
1503
    /* first try free registers */
1504
    for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1505
        reg = tcg_target_reg_alloc_order[i];
1506
        if (tcg_regset_test_reg(reg_ct, reg) && s->reg_to_temp[reg] == -1)
1507
            return reg;
1508
    }
1509

    
1510
    /* XXX: do better spill choice */
1511
    for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1512
        reg = tcg_target_reg_alloc_order[i];
1513
        if (tcg_regset_test_reg(reg_ct, reg)) {
1514
            tcg_reg_free(s, reg);
1515
            return reg;
1516
        }
1517
    }
1518

    
1519
    tcg_abort();
1520
}
1521

    
1522
/* save a temporary to memory. 'allocated_regs' is used in case a
1523
   temporary registers needs to be allocated to store a constant. */
1524
static void temp_save(TCGContext *s, int temp, TCGRegSet allocated_regs)
1525
{
1526
    TCGTemp *ts;
1527
    int reg;
1528

    
1529
    ts = &s->temps[temp];
1530
    if (!ts->fixed_reg) {
1531
        switch(ts->val_type) {
1532
        case TEMP_VAL_REG:
1533
            tcg_reg_free(s, ts->reg);
1534
            break;
1535
        case TEMP_VAL_DEAD:
1536
            ts->val_type = TEMP_VAL_MEM;
1537
            break;
1538
        case TEMP_VAL_CONST:
1539
            reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], 
1540
                                allocated_regs);
1541
            if (!ts->mem_allocated) 
1542
                temp_allocate_frame(s, temp);
1543
            tcg_out_movi(s, ts->type, reg, ts->val);
1544
            tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1545
            ts->val_type = TEMP_VAL_MEM;
1546
            break;
1547
        case TEMP_VAL_MEM:
1548
            break;
1549
        default:
1550
            tcg_abort();
1551
        }
1552
    }
1553
}
1554

    
1555
/* save globals to their canonical location and assume they can be
1556
   modified be the following code. 'allocated_regs' is used in case a
1557
   temporary registers needs to be allocated to store a constant. */
1558
static void save_globals(TCGContext *s, TCGRegSet allocated_regs)
1559
{
1560
    int i;
1561

    
1562
    for(i = 0; i < s->nb_globals; i++) {
1563
        temp_save(s, i, allocated_regs);
1564
    }
1565
}
1566

    
1567
/* at the end of a basic block, we assume all temporaries are dead and
1568
   all globals are stored at their canonical location. */
1569
static void tcg_reg_alloc_bb_end(TCGContext *s, TCGRegSet allocated_regs)
1570
{
1571
    TCGTemp *ts;
1572
    int i;
1573

    
1574
    for(i = s->nb_globals; i < s->nb_temps; i++) {
1575
        ts = &s->temps[i];
1576
        if (ts->temp_local) {
1577
            temp_save(s, i, allocated_regs);
1578
        } else {
1579
            if (ts->val_type == TEMP_VAL_REG) {
1580
                s->reg_to_temp[ts->reg] = -1;
1581
            }
1582
            ts->val_type = TEMP_VAL_DEAD;
1583
        }
1584
    }
1585

    
1586
    save_globals(s, allocated_regs);
1587
}
1588

    
1589
#define IS_DEAD_ARG(n) ((dead_args >> (n)) & 1)
1590

    
1591
static void tcg_reg_alloc_movi(TCGContext *s, const TCGArg *args)
1592
{
1593
    TCGTemp *ots;
1594
    tcg_target_ulong val;
1595

    
1596
    ots = &s->temps[args[0]];
1597
    val = args[1];
1598

    
1599
    if (ots->fixed_reg) {
1600
        /* for fixed registers, we do not do any constant
1601
           propagation */
1602
        tcg_out_movi(s, ots->type, ots->reg, val);
1603
    } else {
1604
        /* The movi is not explicitly generated here */
1605
        if (ots->val_type == TEMP_VAL_REG)
1606
            s->reg_to_temp[ots->reg] = -1;
1607
        ots->val_type = TEMP_VAL_CONST;
1608
        ots->val = val;
1609
    }
1610
}
1611

    
1612
static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
1613
                              const TCGArg *args,
1614
                              unsigned int dead_args)
1615
{
1616
    TCGTemp *ts, *ots;
1617
    int reg;
1618
    const TCGArgConstraint *arg_ct;
1619

    
1620
    ots = &s->temps[args[0]];
1621
    ts = &s->temps[args[1]];
1622
    arg_ct = &def->args_ct[0];
1623

    
1624
    /* XXX: always mark arg dead if IS_DEAD_ARG(1) */
1625
    if (ts->val_type == TEMP_VAL_REG) {
1626
        if (IS_DEAD_ARG(1) && !ts->fixed_reg && !ots->fixed_reg) {
1627
            /* the mov can be suppressed */
1628
            if (ots->val_type == TEMP_VAL_REG)
1629
                s->reg_to_temp[ots->reg] = -1;
1630
            reg = ts->reg;
1631
            s->reg_to_temp[reg] = -1;
1632
            ts->val_type = TEMP_VAL_DEAD;
1633
        } else {
1634
            if (ots->val_type == TEMP_VAL_REG) {
1635
                reg = ots->reg;
1636
            } else {
1637
                reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1638
            }
1639
            if (ts->reg != reg) {
1640
                tcg_out_mov(s, ots->type, reg, ts->reg);
1641
            }
1642
        }
1643
    } else if (ts->val_type == TEMP_VAL_MEM) {
1644
        if (ots->val_type == TEMP_VAL_REG) {
1645
            reg = ots->reg;
1646
        } else {
1647
            reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1648
        }
1649
        tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1650
    } else if (ts->val_type == TEMP_VAL_CONST) {
1651
        if (ots->fixed_reg) {
1652
            reg = ots->reg;
1653
            tcg_out_movi(s, ots->type, reg, ts->val);
1654
        } else {
1655
            /* propagate constant */
1656
            if (ots->val_type == TEMP_VAL_REG)
1657
                s->reg_to_temp[ots->reg] = -1;
1658
            ots->val_type = TEMP_VAL_CONST;
1659
            ots->val = ts->val;
1660
            return;
1661
        }
1662
    } else {
1663
        tcg_abort();
1664
    }
1665
    s->reg_to_temp[reg] = args[0];
1666
    ots->reg = reg;
1667
    ots->val_type = TEMP_VAL_REG;
1668
    ots->mem_coherent = 0;
1669
}
1670

    
1671
static void tcg_reg_alloc_op(TCGContext *s, 
1672
                             const TCGOpDef *def, TCGOpcode opc,
1673
                             const TCGArg *args,
1674
                             unsigned int dead_args)
1675
{
1676
    TCGRegSet allocated_regs;
1677
    int i, k, nb_iargs, nb_oargs, reg;
1678
    TCGArg arg;
1679
    const TCGArgConstraint *arg_ct;
1680
    TCGTemp *ts;
1681
    TCGArg new_args[TCG_MAX_OP_ARGS];
1682
    int const_args[TCG_MAX_OP_ARGS];
1683

    
1684
    nb_oargs = def->nb_oargs;
1685
    nb_iargs = def->nb_iargs;
1686

    
1687
    /* copy constants */
1688
    memcpy(new_args + nb_oargs + nb_iargs, 
1689
           args + nb_oargs + nb_iargs, 
1690
           sizeof(TCGArg) * def->nb_cargs);
1691

    
1692
    /* satisfy input constraints */ 
1693
    tcg_regset_set(allocated_regs, s->reserved_regs);
1694
    for(k = 0; k < nb_iargs; k++) {
1695
        i = def->sorted_args[nb_oargs + k];
1696
        arg = args[i];
1697
        arg_ct = &def->args_ct[i];
1698
        ts = &s->temps[arg];
1699
        if (ts->val_type == TEMP_VAL_MEM) {
1700
            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1701
            tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1702
            ts->val_type = TEMP_VAL_REG;
1703
            ts->reg = reg;
1704
            ts->mem_coherent = 1;
1705
            s->reg_to_temp[reg] = arg;
1706
        } else if (ts->val_type == TEMP_VAL_CONST) {
1707
            if (tcg_target_const_match(ts->val, arg_ct)) {
1708
                /* constant is OK for instruction */
1709
                const_args[i] = 1;
1710
                new_args[i] = ts->val;
1711
                goto iarg_end;
1712
            } else {
1713
                /* need to move to a register */
1714
                reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1715
                tcg_out_movi(s, ts->type, reg, ts->val);
1716
                ts->val_type = TEMP_VAL_REG;
1717
                ts->reg = reg;
1718
                ts->mem_coherent = 0;
1719
                s->reg_to_temp[reg] = arg;
1720
            }
1721
        }
1722
        assert(ts->val_type == TEMP_VAL_REG);
1723
        if (arg_ct->ct & TCG_CT_IALIAS) {
1724
            if (ts->fixed_reg) {
1725
                /* if fixed register, we must allocate a new register
1726
                   if the alias is not the same register */
1727
                if (arg != args[arg_ct->alias_index])
1728
                    goto allocate_in_reg;
1729
            } else {
1730
                /* if the input is aliased to an output and if it is
1731
                   not dead after the instruction, we must allocate
1732
                   a new register and move it */
1733
                if (!IS_DEAD_ARG(i)) {
1734
                    goto allocate_in_reg;
1735
                }
1736
            }
1737
        }
1738
        reg = ts->reg;
1739
        if (tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1740
            /* nothing to do : the constraint is satisfied */
1741
        } else {
1742
        allocate_in_reg:
1743
            /* allocate a new register matching the constraint 
1744
               and move the temporary register into it */
1745
            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1746
            tcg_out_mov(s, ts->type, reg, ts->reg);
1747
        }
1748
        new_args[i] = reg;
1749
        const_args[i] = 0;
1750
        tcg_regset_set_reg(allocated_regs, reg);
1751
    iarg_end: ;
1752
    }
1753
    
1754
    if (def->flags & TCG_OPF_BB_END) {
1755
        tcg_reg_alloc_bb_end(s, allocated_regs);
1756
    } else {
1757
        /* mark dead temporaries and free the associated registers */
1758
        for(i = nb_oargs; i < nb_oargs + nb_iargs; i++) {
1759
            arg = args[i];
1760
            if (IS_DEAD_ARG(i)) {
1761
                ts = &s->temps[arg];
1762
                if (!ts->fixed_reg) {
1763
                    if (ts->val_type == TEMP_VAL_REG)
1764
                        s->reg_to_temp[ts->reg] = -1;
1765
                    ts->val_type = TEMP_VAL_DEAD;
1766
                }
1767
            }
1768
        }
1769
        
1770
        if (def->flags & TCG_OPF_CALL_CLOBBER) {
1771
            /* XXX: permit generic clobber register list ? */ 
1772
            for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1773
                if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
1774
                    tcg_reg_free(s, reg);
1775
                }
1776
            }
1777
            /* XXX: for load/store we could do that only for the slow path
1778
               (i.e. when a memory callback is called) */
1779
            
1780
            /* store globals and free associated registers (we assume the insn
1781
               can modify any global. */
1782
            save_globals(s, allocated_regs);
1783
        }
1784
        
1785
        /* satisfy the output constraints */
1786
        tcg_regset_set(allocated_regs, s->reserved_regs);
1787
        for(k = 0; k < nb_oargs; k++) {
1788
            i = def->sorted_args[k];
1789
            arg = args[i];
1790
            arg_ct = &def->args_ct[i];
1791
            ts = &s->temps[arg];
1792
            if (arg_ct->ct & TCG_CT_ALIAS) {
1793
                reg = new_args[arg_ct->alias_index];
1794
            } else {
1795
                /* if fixed register, we try to use it */
1796
                reg = ts->reg;
1797
                if (ts->fixed_reg &&
1798
                    tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1799
                    goto oarg_end;
1800
                }
1801
                reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1802
            }
1803
            tcg_regset_set_reg(allocated_regs, reg);
1804
            /* if a fixed register is used, then a move will be done afterwards */
1805
            if (!ts->fixed_reg) {
1806
                if (ts->val_type == TEMP_VAL_REG)
1807
                    s->reg_to_temp[ts->reg] = -1;
1808
                if (IS_DEAD_ARG(i)) {
1809
                    ts->val_type = TEMP_VAL_DEAD;
1810
                } else {
1811
                    ts->val_type = TEMP_VAL_REG;
1812
                    ts->reg = reg;
1813
                    /* temp value is modified, so the value kept in memory is
1814
                       potentially not the same */
1815
                    ts->mem_coherent = 0;
1816
                    s->reg_to_temp[reg] = arg;
1817
               }
1818
            }
1819
        oarg_end:
1820
            new_args[i] = reg;
1821
        }
1822
    }
1823

    
1824
    /* emit instruction */
1825
    tcg_out_op(s, opc, new_args, const_args);
1826
    
1827
    /* move the outputs in the correct register if needed */
1828
    for(i = 0; i < nb_oargs; i++) {
1829
        ts = &s->temps[args[i]];
1830
        reg = new_args[i];
1831
        if (ts->fixed_reg && ts->reg != reg) {
1832
            tcg_out_mov(s, ts->type, ts->reg, reg);
1833
        }
1834
    }
1835
}
1836

    
1837
#ifdef TCG_TARGET_STACK_GROWSUP
1838
#define STACK_DIR(x) (-(x))
1839
#else
1840
#define STACK_DIR(x) (x)
1841
#endif
1842

    
1843
static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
1844
                              TCGOpcode opc, const TCGArg *args,
1845
                              unsigned int dead_args)
1846
{
1847
    int nb_iargs, nb_oargs, flags, nb_regs, i, reg, nb_params;
1848
    TCGArg arg, func_arg;
1849
    TCGTemp *ts;
1850
    tcg_target_long stack_offset, call_stack_size, func_addr;
1851
    int const_func_arg, allocate_args;
1852
    TCGRegSet allocated_regs;
1853
    const TCGArgConstraint *arg_ct;
1854

    
1855
    arg = *args++;
1856

    
1857
    nb_oargs = arg >> 16;
1858
    nb_iargs = arg & 0xffff;
1859
    nb_params = nb_iargs - 1;
1860

    
1861
    flags = args[nb_oargs + nb_iargs];
1862

    
1863
    nb_regs = tcg_target_get_call_iarg_regs_count(flags);
1864
    if (nb_regs > nb_params)
1865
        nb_regs = nb_params;
1866

    
1867
    /* assign stack slots first */
1868
    call_stack_size = (nb_params - nb_regs) * sizeof(tcg_target_long);
1869
    call_stack_size = (call_stack_size + TCG_TARGET_STACK_ALIGN - 1) & 
1870
        ~(TCG_TARGET_STACK_ALIGN - 1);
1871
    allocate_args = (call_stack_size > TCG_STATIC_CALL_ARGS_SIZE);
1872
    if (allocate_args) {
1873
        /* XXX: if more than TCG_STATIC_CALL_ARGS_SIZE is needed,
1874
           preallocate call stack */
1875
        tcg_abort();
1876
    }
1877

    
1878
    stack_offset = TCG_TARGET_CALL_STACK_OFFSET;
1879
    for(i = nb_regs; i < nb_params; i++) {
1880
        arg = args[nb_oargs + i];
1881
#ifdef TCG_TARGET_STACK_GROWSUP
1882
        stack_offset -= sizeof(tcg_target_long);
1883
#endif
1884
        if (arg != TCG_CALL_DUMMY_ARG) {
1885
            ts = &s->temps[arg];
1886
            if (ts->val_type == TEMP_VAL_REG) {
1887
                tcg_out_st(s, ts->type, ts->reg, TCG_REG_CALL_STACK, stack_offset);
1888
            } else if (ts->val_type == TEMP_VAL_MEM) {
1889
                reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], 
1890
                                    s->reserved_regs);
1891
                /* XXX: not correct if reading values from the stack */
1892
                tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1893
                tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
1894
            } else if (ts->val_type == TEMP_VAL_CONST) {
1895
                reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], 
1896
                                    s->reserved_regs);
1897
                /* XXX: sign extend may be needed on some targets */
1898
                tcg_out_movi(s, ts->type, reg, ts->val);
1899
                tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
1900
            } else {
1901
                tcg_abort();
1902
            }
1903
        }
1904
#ifndef TCG_TARGET_STACK_GROWSUP
1905
        stack_offset += sizeof(tcg_target_long);
1906
#endif
1907
    }
1908
    
1909
    /* assign input registers */
1910
    tcg_regset_set(allocated_regs, s->reserved_regs);
1911
    for(i = 0; i < nb_regs; i++) {
1912
        arg = args[nb_oargs + i];
1913
        if (arg != TCG_CALL_DUMMY_ARG) {
1914
            ts = &s->temps[arg];
1915
            reg = tcg_target_call_iarg_regs[i];
1916
            tcg_reg_free(s, reg);
1917
            if (ts->val_type == TEMP_VAL_REG) {
1918
                if (ts->reg != reg) {
1919
                    tcg_out_mov(s, ts->type, reg, ts->reg);
1920
                }
1921
            } else if (ts->val_type == TEMP_VAL_MEM) {
1922
                tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1923
            } else if (ts->val_type == TEMP_VAL_CONST) {
1924
                /* XXX: sign extend ? */
1925
                tcg_out_movi(s, ts->type, reg, ts->val);
1926
            } else {
1927
                tcg_abort();
1928
            }
1929
            tcg_regset_set_reg(allocated_regs, reg);
1930
        }
1931
    }
1932
    
1933
    /* assign function address */
1934
    func_arg = args[nb_oargs + nb_iargs - 1];
1935
    arg_ct = &def->args_ct[0];
1936
    ts = &s->temps[func_arg];
1937
    func_addr = ts->val;
1938
    const_func_arg = 0;
1939
    if (ts->val_type == TEMP_VAL_MEM) {
1940
        reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1941
        tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1942
        func_arg = reg;
1943
        tcg_regset_set_reg(allocated_regs, reg);
1944
    } else if (ts->val_type == TEMP_VAL_REG) {
1945
        reg = ts->reg;
1946
        if (!tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1947
            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1948
            tcg_out_mov(s, ts->type, reg, ts->reg);
1949
        }
1950
        func_arg = reg;
1951
        tcg_regset_set_reg(allocated_regs, reg);
1952
    } else if (ts->val_type == TEMP_VAL_CONST) {
1953
        if (tcg_target_const_match(func_addr, arg_ct)) {
1954
            const_func_arg = 1;
1955
            func_arg = func_addr;
1956
        } else {
1957
            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1958
            tcg_out_movi(s, ts->type, reg, func_addr);
1959
            func_arg = reg;
1960
            tcg_regset_set_reg(allocated_regs, reg);
1961
        }
1962
    } else {
1963
        tcg_abort();
1964
    }
1965
        
1966
    
1967
    /* mark dead temporaries and free the associated registers */
1968
    for(i = nb_oargs; i < nb_iargs + nb_oargs; i++) {
1969
        arg = args[i];
1970
        if (IS_DEAD_ARG(i)) {
1971
            ts = &s->temps[arg];
1972
            if (!ts->fixed_reg) {
1973
                if (ts->val_type == TEMP_VAL_REG)
1974
                    s->reg_to_temp[ts->reg] = -1;
1975
                ts->val_type = TEMP_VAL_DEAD;
1976
            }
1977
        }
1978
    }
1979
    
1980
    /* clobber call registers */
1981
    for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1982
        if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
1983
            tcg_reg_free(s, reg);
1984
        }
1985
    }
1986
    
1987
    /* store globals and free associated registers (we assume the call
1988
       can modify any global. */
1989
    if (!(flags & TCG_CALL_CONST)) {
1990
        save_globals(s, allocated_regs);
1991
    }
1992

    
1993
    tcg_out_op(s, opc, &func_arg, &const_func_arg);
1994

    
1995
    /* assign output registers and emit moves if needed */
1996
    for(i = 0; i < nb_oargs; i++) {
1997
        arg = args[i];
1998
        ts = &s->temps[arg];
1999
        reg = tcg_target_call_oarg_regs[i];
2000
        assert(s->reg_to_temp[reg] == -1);
2001
        if (ts->fixed_reg) {
2002
            if (ts->reg != reg) {
2003
                tcg_out_mov(s, ts->type, ts->reg, reg);
2004
            }
2005
        } else {
2006
            if (ts->val_type == TEMP_VAL_REG)
2007
                s->reg_to_temp[ts->reg] = -1;
2008
            if (IS_DEAD_ARG(i)) {
2009
                ts->val_type = TEMP_VAL_DEAD;
2010
            } else {
2011
                ts->val_type = TEMP_VAL_REG;
2012
                ts->reg = reg;
2013
                ts->mem_coherent = 0;
2014
                s->reg_to_temp[reg] = arg;
2015
            }
2016
        }
2017
    }
2018
    
2019
    return nb_iargs + nb_oargs + def->nb_cargs + 1;
2020
}
2021

    
2022
#ifdef CONFIG_PROFILER
2023

    
2024
static int64_t tcg_table_op_count[NB_OPS];
2025

    
2026
static void dump_op_count(void)
2027
{
2028
    int i;
2029
    FILE *f;
2030
    f = fopen("/tmp/op.log", "w");
2031
    for(i = INDEX_op_end; i < NB_OPS; i++) {
2032
        fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name, tcg_table_op_count[i]);
2033
    }
2034
    fclose(f);
2035
}
2036
#endif
2037

    
2038

    
2039
static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
2040
                                      long search_pc)
2041
{
2042
    TCGOpcode opc;
2043
    int op_index;
2044
    const TCGOpDef *def;
2045
    unsigned int dead_args;
2046
    const TCGArg *args;
2047

    
2048
#ifdef DEBUG_DISAS
2049
    if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
2050
        qemu_log("OP:\n");
2051
        tcg_dump_ops(s, logfile);
2052
        qemu_log("\n");
2053
    }
2054
#endif
2055

    
2056
#ifdef USE_TCG_OPTIMIZATIONS
2057
    gen_opparam_ptr =
2058
        tcg_optimize(s, gen_opc_ptr, gen_opparam_buf, tcg_op_defs);
2059
#endif
2060

    
2061
#ifdef CONFIG_PROFILER
2062
    s->la_time -= profile_getclock();
2063
#endif
2064
    tcg_liveness_analysis(s);
2065
#ifdef CONFIG_PROFILER
2066
    s->la_time += profile_getclock();
2067
#endif
2068

    
2069
#ifdef DEBUG_DISAS
2070
    if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_OPT))) {
2071
        qemu_log("OP after liveness analysis:\n");
2072
        tcg_dump_ops(s, logfile);
2073
        qemu_log("\n");
2074
    }
2075
#endif
2076

    
2077
    tcg_reg_alloc_start(s);
2078

    
2079
    s->code_buf = gen_code_buf;
2080
    s->code_ptr = gen_code_buf;
2081

    
2082
    args = gen_opparam_buf;
2083
    op_index = 0;
2084

    
2085
    for(;;) {
2086
        opc = gen_opc_buf[op_index];
2087
#ifdef CONFIG_PROFILER
2088
        tcg_table_op_count[opc]++;
2089
#endif
2090
        def = &tcg_op_defs[opc];
2091
#if 0
2092
        printf("%s: %d %d %d\n", def->name,
2093
               def->nb_oargs, def->nb_iargs, def->nb_cargs);
2094
        //        dump_regs(s);
2095
#endif
2096
        switch(opc) {
2097
        case INDEX_op_mov_i32:
2098
#if TCG_TARGET_REG_BITS == 64
2099
        case INDEX_op_mov_i64:
2100
#endif
2101
            dead_args = s->op_dead_args[op_index];
2102
            tcg_reg_alloc_mov(s, def, args, dead_args);
2103
            break;
2104
        case INDEX_op_movi_i32:
2105
#if TCG_TARGET_REG_BITS == 64
2106
        case INDEX_op_movi_i64:
2107
#endif
2108
            tcg_reg_alloc_movi(s, args);
2109
            break;
2110
        case INDEX_op_debug_insn_start:
2111
            /* debug instruction */
2112
            break;
2113
        case INDEX_op_nop:
2114
        case INDEX_op_nop1:
2115
        case INDEX_op_nop2:
2116
        case INDEX_op_nop3:
2117
            break;
2118
        case INDEX_op_nopn:
2119
            args += args[0];
2120
            goto next;
2121
        case INDEX_op_discard:
2122
            {
2123
                TCGTemp *ts;
2124
                ts = &s->temps[args[0]];
2125
                /* mark the temporary as dead */
2126
                if (!ts->fixed_reg) {
2127
                    if (ts->val_type == TEMP_VAL_REG)
2128
                        s->reg_to_temp[ts->reg] = -1;
2129
                    ts->val_type = TEMP_VAL_DEAD;
2130
                }
2131
            }
2132
            break;
2133
        case INDEX_op_set_label:
2134
            tcg_reg_alloc_bb_end(s, s->reserved_regs);
2135
            tcg_out_label(s, args[0], s->code_ptr);
2136
            break;
2137
        case INDEX_op_call:
2138
            dead_args = s->op_dead_args[op_index];
2139
            args += tcg_reg_alloc_call(s, def, opc, args, dead_args);
2140
            goto next;
2141
        case INDEX_op_end:
2142
            goto the_end;
2143
        default:
2144
            /* Sanity check that we've not introduced any unhandled opcodes. */
2145
            if (def->flags & TCG_OPF_NOT_PRESENT) {
2146
                tcg_abort();
2147
            }
2148
            /* Note: in order to speed up the code, it would be much
2149
               faster to have specialized register allocator functions for
2150
               some common argument patterns */
2151
            dead_args = s->op_dead_args[op_index];
2152
            tcg_reg_alloc_op(s, def, opc, args, dead_args);
2153
            break;
2154
        }
2155
        args += def->nb_args;
2156
    next:
2157
        if (search_pc >= 0 && search_pc < s->code_ptr - gen_code_buf) {
2158
            return op_index;
2159
        }
2160
        op_index++;
2161
#ifndef NDEBUG
2162
        check_regs(s);
2163
#endif
2164
    }
2165
 the_end:
2166
    return -1;
2167
}
2168

    
2169
int tcg_gen_code(TCGContext *s, uint8_t *gen_code_buf)
2170
{
2171
#ifdef CONFIG_PROFILER
2172
    {
2173
        int n;
2174
        n = (gen_opc_ptr - gen_opc_buf);
2175
        s->op_count += n;
2176
        if (n > s->op_count_max)
2177
            s->op_count_max = n;
2178

    
2179
        s->temp_count += s->nb_temps;
2180
        if (s->nb_temps > s->temp_count_max)
2181
            s->temp_count_max = s->nb_temps;
2182
    }
2183
#endif
2184

    
2185
    tcg_gen_code_common(s, gen_code_buf, -1);
2186

    
2187
    /* flush instruction cache */
2188
    flush_icache_range((tcg_target_ulong)gen_code_buf,
2189
                       (tcg_target_ulong)s->code_ptr);
2190

    
2191
    return s->code_ptr -  gen_code_buf;
2192
}
2193

    
2194
/* Return the index of the micro operation such as the pc after is <
2195
   offset bytes from the start of the TB.  The contents of gen_code_buf must
2196
   not be changed, though writing the same values is ok.
2197
   Return -1 if not found. */
2198
int tcg_gen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, long offset)
2199
{
2200
    return tcg_gen_code_common(s, gen_code_buf, offset);
2201
}
2202

    
2203
#ifdef CONFIG_PROFILER
2204
void tcg_dump_info(FILE *f, fprintf_function cpu_fprintf)
2205
{
2206
    TCGContext *s = &tcg_ctx;
2207
    int64_t tot;
2208

    
2209
    tot = s->interm_time + s->code_time;
2210
    cpu_fprintf(f, "JIT cycles          %" PRId64 " (%0.3f s at 2.4 GHz)\n",
2211
                tot, tot / 2.4e9);
2212
    cpu_fprintf(f, "translated TBs      %" PRId64 " (aborted=%" PRId64 " %0.1f%%)\n", 
2213
                s->tb_count, 
2214
                s->tb_count1 - s->tb_count,
2215
                s->tb_count1 ? (double)(s->tb_count1 - s->tb_count) / s->tb_count1 * 100.0 : 0);
2216
    cpu_fprintf(f, "avg ops/TB          %0.1f max=%d\n", 
2217
                s->tb_count ? (double)s->op_count / s->tb_count : 0, s->op_count_max);
2218
    cpu_fprintf(f, "deleted ops/TB      %0.2f\n",
2219
                s->tb_count ? 
2220
                (double)s->del_op_count / s->tb_count : 0);
2221
    cpu_fprintf(f, "avg temps/TB        %0.2f max=%d\n",
2222
                s->tb_count ? 
2223
                (double)s->temp_count / s->tb_count : 0,
2224
                s->temp_count_max);
2225
    
2226
    cpu_fprintf(f, "cycles/op           %0.1f\n", 
2227
                s->op_count ? (double)tot / s->op_count : 0);
2228
    cpu_fprintf(f, "cycles/in byte      %0.1f\n", 
2229
                s->code_in_len ? (double)tot / s->code_in_len : 0);
2230
    cpu_fprintf(f, "cycles/out byte     %0.1f\n", 
2231
                s->code_out_len ? (double)tot / s->code_out_len : 0);
2232
    if (tot == 0)
2233
        tot = 1;
2234
    cpu_fprintf(f, "  gen_interm time   %0.1f%%\n", 
2235
                (double)s->interm_time / tot * 100.0);
2236
    cpu_fprintf(f, "  gen_code time     %0.1f%%\n", 
2237
                (double)s->code_time / tot * 100.0);
2238
    cpu_fprintf(f, "liveness/code time  %0.1f%%\n", 
2239
                (double)s->la_time / (s->code_time ? s->code_time : 1) * 100.0);
2240
    cpu_fprintf(f, "cpu_restore count   %" PRId64 "\n",
2241
                s->restore_count);
2242
    cpu_fprintf(f, "  avg cycles        %0.1f\n",
2243
                s->restore_count ? (double)s->restore_time / s->restore_count : 0);
2244

    
2245
    dump_op_count();
2246
}
2247
#else
2248
void tcg_dump_info(FILE *f, fprintf_function cpu_fprintf)
2249
{
2250
    cpu_fprintf(f, "[TCG profiler not compiled]\n");
2251
}
2252
#endif
2253

    
2254
#ifdef ELF_HOST_MACHINE
2255
/* The backend should define ELF_HOST_MACHINE to indicate both what value to
2256
   put into the ELF image and to indicate support for the feature.  */
2257

    
2258
/* Begin GDB interface.  THE FOLLOWING MUST MATCH GDB DOCS.  */
2259
typedef enum {
2260
    JIT_NOACTION = 0,
2261
    JIT_REGISTER_FN,
2262
    JIT_UNREGISTER_FN
2263
} jit_actions_t;
2264

    
2265
struct jit_code_entry {
2266
    struct jit_code_entry *next_entry;
2267
    struct jit_code_entry *prev_entry;
2268
    const void *symfile_addr;
2269
    uint64_t symfile_size;
2270
};
2271

    
2272
struct jit_descriptor {
2273
    uint32_t version;
2274
    uint32_t action_flag;
2275
    struct jit_code_entry *relevant_entry;
2276
    struct jit_code_entry *first_entry;
2277
};
2278

    
2279
void __jit_debug_register_code(void) __attribute__((noinline));
2280
void __jit_debug_register_code(void)
2281
{
2282
    asm("");
2283
}
2284

    
2285
/* Must statically initialize the version, because GDB may check
2286
   the version before we can set it.  */
2287
struct jit_descriptor __jit_debug_descriptor = { 1, 0, 0, 0 };
2288

    
2289
/* End GDB interface.  */
2290

    
2291
static int find_string(const char *strtab, const char *str)
2292
{
2293
    const char *p = strtab + 1;
2294

    
2295
    while (1) {
2296
        if (strcmp(p, str) == 0) {
2297
            return p - strtab;
2298
        }
2299
        p += strlen(p) + 1;
2300
    }
2301
}
2302

    
2303
static void tcg_register_jit_int(void *buf, size_t buf_size,
2304
                                 void *debug_frame, size_t debug_frame_size)
2305
{
2306
    static const char strings[64] =
2307
        "\0"
2308
        ".text\0"
2309
        ".debug_frame\0"
2310
        ".symtab\0"
2311
        ".strtab\0"
2312
        "code_gen_buffer";
2313

    
2314
    struct ElfImage {
2315
        ElfW(Ehdr) ehdr;
2316
        ElfW(Phdr) phdr;
2317
        ElfW(Shdr) shdr[5];
2318
        ElfW(Sym)  sym[1];
2319
        char       str[64];
2320
    };
2321

    
2322
    /* We only need a single jit entry; statically allocate it.  */
2323
    static struct jit_code_entry one_entry;
2324

    
2325
    size_t img_size = sizeof(struct ElfImage) + debug_frame_size;
2326
    struct ElfImage *img = g_malloc0(img_size);
2327

    
2328
    img->ehdr.e_ident[EI_MAG0] = ELFMAG0;
2329
    img->ehdr.e_ident[EI_MAG1] = ELFMAG1;
2330
    img->ehdr.e_ident[EI_MAG2] = ELFMAG2;
2331
    img->ehdr.e_ident[EI_MAG3] = ELFMAG3;
2332
    img->ehdr.e_ident[EI_CLASS] = ELF_CLASS;
2333
    img->ehdr.e_ident[EI_DATA] = ELF_DATA;
2334
    img->ehdr.e_ident[EI_VERSION] = EV_CURRENT;
2335
    img->ehdr.e_type = ET_EXEC;
2336
    img->ehdr.e_machine = ELF_HOST_MACHINE;
2337
    img->ehdr.e_version = EV_CURRENT;
2338
    img->ehdr.e_phoff = offsetof(struct ElfImage, phdr);
2339
    img->ehdr.e_shoff = offsetof(struct ElfImage, shdr);
2340
    img->ehdr.e_ehsize = sizeof(ElfW(Shdr));
2341
    img->ehdr.e_phentsize = sizeof(ElfW(Phdr));
2342
    img->ehdr.e_phnum = 1;
2343
    img->ehdr.e_shentsize = sizeof(img->shdr[0]);
2344
    img->ehdr.e_shnum = ARRAY_SIZE(img->shdr);
2345
    img->ehdr.e_shstrndx = ARRAY_SIZE(img->shdr) - 1;
2346

    
2347
    img->phdr.p_type = PT_LOAD;
2348
    img->phdr.p_offset = (char *)buf - (char *)img;
2349
    img->phdr.p_vaddr = (ElfW(Addr))buf;
2350
    img->phdr.p_paddr = img->phdr.p_vaddr;
2351
    img->phdr.p_filesz = 0;
2352
    img->phdr.p_memsz = buf_size;
2353
    img->phdr.p_flags = PF_X;
2354

    
2355
    memcpy(img->str, strings, sizeof(img->str));
2356

    
2357
    img->shdr[0].sh_type = SHT_NULL;
2358

    
2359
    /* Trick: The contents of code_gen_buffer are not present in this fake
2360
       ELF file; that got allocated elsewhere, discontiguously.  Therefore
2361
       we mark .text as SHT_NOBITS (similar to .bss) so that readers will
2362
       not look for contents.  We can record any address at will.  */
2363
    img->shdr[1].sh_name = find_string(img->str, ".text");
2364
    img->shdr[1].sh_type = SHT_NOBITS;
2365
    img->shdr[1].sh_flags = SHF_EXECINSTR | SHF_ALLOC;
2366
    img->shdr[1].sh_addr = (ElfW(Addr))buf;
2367
    img->shdr[1].sh_size = buf_size;
2368

    
2369
    img->shdr[2].sh_name = find_string(img->str, ".debug_frame");
2370
    img->shdr[2].sh_type = SHT_PROGBITS;
2371
    img->shdr[2].sh_offset = sizeof(*img);
2372
    img->shdr[2].sh_size = debug_frame_size;
2373
    memcpy(img + 1, debug_frame, debug_frame_size);
2374

    
2375
    img->shdr[3].sh_name = find_string(img->str, ".symtab");
2376
    img->shdr[3].sh_type = SHT_SYMTAB;
2377
    img->shdr[3].sh_offset = offsetof(struct ElfImage, sym);
2378
    img->shdr[3].sh_size = sizeof(img->sym);
2379
    img->shdr[3].sh_info = ARRAY_SIZE(img->sym);
2380
    img->shdr[3].sh_link = img->ehdr.e_shstrndx;
2381
    img->shdr[3].sh_entsize = sizeof(ElfW(Sym));
2382

    
2383
    img->shdr[4].sh_name = find_string(img->str, ".strtab");
2384
    img->shdr[4].sh_type = SHT_STRTAB;
2385
    img->shdr[4].sh_offset = offsetof(struct ElfImage, str);
2386
    img->shdr[4].sh_size = sizeof(img->str);
2387

    
2388
    img->sym[0].st_name = find_string(img->str, "code_gen_buffer");
2389
    img->sym[0].st_info = ELF_ST_INFO(STB_GLOBAL, STT_FUNC);
2390
    img->sym[0].st_shndx = 1;
2391
    img->sym[0].st_value = (ElfW(Addr))buf;
2392
    img->sym[0].st_size = buf_size;
2393

    
2394
#ifdef DEBUG_JIT
2395
    /* Enable this block to be able to debug the ELF image file creation.
2396
       One can use readelf, objdump, or other inspection utilities.  */
2397
    {
2398
        FILE *f = fopen("/tmp/qemu.jit", "w+b");
2399
        if (f) {
2400
            if (fwrite(img, img_size, 1, f) != buf_size) {
2401
                /* Avoid stupid unused return value warning for fwrite.  */
2402
            }
2403
            fclose(f);
2404
        }
2405
    }
2406
#endif
2407

    
2408
    one_entry.symfile_addr = img;
2409
    one_entry.symfile_size = img_size;
2410

    
2411
    __jit_debug_descriptor.action_flag = JIT_REGISTER_FN;
2412
    __jit_debug_descriptor.relevant_entry = &one_entry;
2413
    __jit_debug_descriptor.first_entry = &one_entry;
2414
    __jit_debug_register_code();
2415
}
2416
#else
2417
/* No support for the feature.  Provide the entry point expected by exec.c.  */
2418

    
2419
static void tcg_register_jit_int(void *buf, size_t size,
2420
                                 void *debug_frame, size_t debug_frame_size)
2421
{
2422
}
2423

    
2424
void tcg_register_jit(void *buf, size_t buf_size)
2425
{
2426
}
2427
#endif /* ELF_HOST_MACHINE */