Statistics
| Branch: | Revision:

root / tcg / tcg.c @ 39cf05d3

History | View | Annotate | Download (57.9 kB)

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

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

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

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

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

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

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

    
54

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

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

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

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

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

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

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

    
90
/* label relocation processing */
91

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

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

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

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

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

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

    
148
#include "tcg-target.c"
149

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
524
const char *tcg_helper_get_name(TCGContext *s, void *func)
525
{
526
    int i;
527

    
528
    for(i = 0; i < s->nb_helpers; i++) {
529
        if (s->helpers[i].func == func)
530
            return s->helpers[i].name;
531
    }
532
    return NULL;
533
}
534

    
535
static inline TCGType tcg_get_base_type(TCGContext *s, TCGv arg)
536
{
537
    return s->temps[GET_TCGV(arg)].base_type;
538
}
539

    
540
static void tcg_gen_call_internal(TCGContext *s, TCGv func, 
541
                                  unsigned int flags,
542
                                  unsigned int nb_rets, const TCGv *rets,
543
                                  unsigned int nb_params, const TCGv *params)
544
{
545
    int i;
546
    *gen_opc_ptr++ = INDEX_op_call;
547
    *gen_opparam_ptr++ = (nb_rets << 16) | (nb_params + 1);
548
    for(i = 0; i < nb_rets; i++) {
549
        *gen_opparam_ptr++ = GET_TCGV(rets[i]);
550
    }
551
    for(i = 0; i < nb_params; i++) {
552
        *gen_opparam_ptr++ = GET_TCGV(params[i]);
553
    }
554
    *gen_opparam_ptr++ = GET_TCGV(func);
555

    
556
    *gen_opparam_ptr++ = flags;
557
    /* total parameters, needed to go backward in the instruction stream */
558
    *gen_opparam_ptr++ = 1 + nb_rets + nb_params + 3;
559
}
560

    
561

    
562
#if TCG_TARGET_REG_BITS < 64
563
/* Note: we convert the 64 bit args to 32 bit and do some alignment
564
   and endian swap. Maybe it would be better to do the alignment
565
   and endian swap in tcg_reg_alloc_call(). */
566
void tcg_gen_call(TCGContext *s, TCGv func, unsigned int flags,
567
                  unsigned int nb_rets, const TCGv *rets,
568
                  unsigned int nb_params, const TCGv *args1)
569
{
570
    TCGv ret, *args2, rets_2[2], arg;
571
    int j, i, call_type;
572

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

    
634
#if TCG_TARGET_REG_BITS == 32
635
void tcg_gen_shifti_i64(TCGv ret, TCGv arg1, 
636
                        int c, int right, int arith)
637
{
638
    if (c == 0) {
639
        tcg_gen_mov_i32(ret, arg1);
640
        tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
641
    } else if (c >= 32) {
642
        c -= 32;
643
        if (right) {
644
            if (arith) {
645
                tcg_gen_sari_i32(ret, TCGV_HIGH(arg1), c);
646
                tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 31);
647
            } else {
648
                tcg_gen_shri_i32(ret, TCGV_HIGH(arg1), c);
649
                tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
650
            }
651
        } else {
652
            tcg_gen_shli_i32(TCGV_HIGH(ret), arg1, c);
653
            tcg_gen_movi_i32(ret, 0);
654
        }
655
    } else {
656
        TCGv t0, t1;
657

    
658
        t0 = tcg_temp_new(TCG_TYPE_I32);
659
        t1 = tcg_temp_new(TCG_TYPE_I32);
660
        if (right) {
661
            tcg_gen_shli_i32(t0, TCGV_HIGH(arg1), 32 - c);
662
            if (arith)
663
                tcg_gen_sari_i32(t1, TCGV_HIGH(arg1), c);
664
            else 
665
                tcg_gen_shri_i32(t1, TCGV_HIGH(arg1), c);
666
            tcg_gen_shri_i32(ret, arg1, c); 
667
            tcg_gen_or_i32(ret, ret, t0);
668
            tcg_gen_mov_i32(TCGV_HIGH(ret), t1);
669
        } else {
670
            tcg_gen_shri_i32(t0, arg1, 32 - c);
671
            /* Note: ret can be the same as arg1, so we use t1 */
672
            tcg_gen_shli_i32(t1, arg1, c); 
673
            tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c);
674
            tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t0);
675
            tcg_gen_mov_i32(ret, t1);
676
        }
677
    }
678
}
679
#endif
680

    
681
void tcg_reg_alloc_start(TCGContext *s)
682
{
683
    int i;
684
    TCGTemp *ts;
685
    for(i = 0; i < s->nb_globals; i++) {
686
        ts = &s->temps[i];
687
        if (ts->fixed_reg) {
688
            ts->val_type = TEMP_VAL_REG;
689
        } else {
690
            ts->val_type = TEMP_VAL_MEM;
691
        }
692
    }
693
    for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
694
        s->reg_to_temp[i] = -1;
695
    }
696
}
697

    
698
static char *tcg_get_arg_str_idx(TCGContext *s, char *buf, int buf_size,
699
                                 int idx)
700
{
701
    TCGTemp *ts;
702

    
703
    ts = &s->temps[idx];
704
    if (idx < s->nb_globals) {
705
        pstrcpy(buf, buf_size, ts->name);
706
    } else {
707
        if (ts->val_type == TEMP_VAL_CONST) {
708
            snprintf(buf, buf_size, "$0x%" TCG_PRIlx , ts->val);
709
        } else {
710
            snprintf(buf, buf_size, "tmp%d", idx - s->nb_globals);
711
        }
712
    }
713
    return buf;
714
}
715

    
716
char *tcg_get_arg_str(TCGContext *s, char *buf, int buf_size, TCGv arg)
717
{
718
    return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV(arg));
719
}
720

    
721
void tcg_dump_ops(TCGContext *s, FILE *outfile)
722
{
723
    const uint16_t *opc_ptr;
724
    const TCGArg *args;
725
    TCGArg arg;
726
    int c, i, k, nb_oargs, nb_iargs, nb_cargs;
727
    const TCGOpDef *def;
728
    char buf[128];
729

    
730
    opc_ptr = gen_opc_buf;
731
    args = gen_opparam_buf;
732
    while (opc_ptr < gen_opc_ptr) {
733
        c = *opc_ptr++;
734
        def = &tcg_op_defs[c];
735
        fprintf(outfile, " %s ", def->name);
736
        if (c == INDEX_op_call) {
737
            TCGArg arg;
738
            /* variable number of arguments */
739
            arg = *args++;
740
            nb_oargs = arg >> 16;
741
            nb_iargs = arg & 0xffff;
742
            nb_cargs = def->nb_cargs;
743

    
744
            /* function name */
745
            /* XXX: dump helper name for call */
746
            fprintf(outfile, "%s",
747
                    tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + nb_iargs - 1]));
748
            /* flags */
749
            fprintf(outfile, ",$0x%" TCG_PRIlx,
750
                    args[nb_oargs + nb_iargs]);
751
            /* nb out args */
752
            fprintf(outfile, ",$%d", nb_oargs);
753
            for(i = 0; i < nb_oargs; i++) {
754
                fprintf(outfile, ",");
755
                fprintf(outfile, "%s",
756
                        tcg_get_arg_str_idx(s, buf, sizeof(buf), args[i]));
757
            }
758
            for(i = 0; i < (nb_iargs - 1); i++) {
759
                fprintf(outfile, ",");
760
                if (args[nb_oargs + i] == TCG_CALL_DUMMY_ARG) {
761
                    fprintf(outfile, "<dummy>");
762
                } else {
763
                    fprintf(outfile, "%s",
764
                            tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + i]));
765
                }
766
            }
767
        } else {
768
            if (c == INDEX_op_nopn) {
769
                /* variable number of arguments */
770
                nb_cargs = *args;
771
                nb_oargs = 0;
772
                nb_iargs = 0;
773
            } else {
774
                nb_oargs = def->nb_oargs;
775
                nb_iargs = def->nb_iargs;
776
                nb_cargs = def->nb_cargs;
777
            }
778
            
779
            k = 0;
780
            for(i = 0; i < nb_oargs; i++) {
781
                if (k != 0)
782
                    fprintf(outfile, ",");
783
                fprintf(outfile, "%s",
784
                        tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
785
            }
786
            for(i = 0; i < nb_iargs; i++) {
787
                if (k != 0)
788
                    fprintf(outfile, ",");
789
                fprintf(outfile, "%s",
790
                        tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
791
            }
792
            for(i = 0; i < nb_cargs; i++) {
793
                if (k != 0)
794
                    fprintf(outfile, ",");
795
                arg = args[k++];
796
                fprintf(outfile, "$0x%" TCG_PRIlx, arg);
797
            }
798
        }
799
        fprintf(outfile, "\n");
800
        args += nb_iargs + nb_oargs + nb_cargs;
801
    }
802
}
803

    
804
/* we give more priority to constraints with less registers */
805
static int get_constraint_priority(const TCGOpDef *def, int k)
806
{
807
    const TCGArgConstraint *arg_ct;
808

    
809
    int i, n;
810
    arg_ct = &def->args_ct[k];
811
    if (arg_ct->ct & TCG_CT_ALIAS) {
812
        /* an alias is equivalent to a single register */
813
        n = 1;
814
    } else {
815
        if (!(arg_ct->ct & TCG_CT_REG))
816
            return 0;
817
        n = 0;
818
        for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
819
            if (tcg_regset_test_reg(arg_ct->u.regs, i))
820
                n++;
821
        }
822
    }
823
    return TCG_TARGET_NB_REGS - n + 1;
824
}
825

    
826
/* sort from highest priority to lowest */
827
static void sort_constraints(TCGOpDef *def, int start, int n)
828
{
829
    int i, j, p1, p2, tmp;
830

    
831
    for(i = 0; i < n; i++)
832
        def->sorted_args[start + i] = start + i;
833
    if (n <= 1)
834
        return;
835
    for(i = 0; i < n - 1; i++) {
836
        for(j = i + 1; j < n; j++) {
837
            p1 = get_constraint_priority(def, def->sorted_args[start + i]);
838
            p2 = get_constraint_priority(def, def->sorted_args[start + j]);
839
            if (p1 < p2) {
840
                tmp = def->sorted_args[start + i];
841
                def->sorted_args[start + i] = def->sorted_args[start + j];
842
                def->sorted_args[start + j] = tmp;
843
            }
844
        }
845
    }
846
}
847

    
848
void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs)
849
{
850
    int op;
851
    TCGOpDef *def;
852
    const char *ct_str;
853
    int i, nb_args;
854

    
855
    for(;;) {
856
        if (tdefs->op < 0)
857
            break;
858
        op = tdefs->op;
859
        assert(op >= 0 && op < NB_OPS);
860
        def = &tcg_op_defs[op];
861
        nb_args = def->nb_iargs + def->nb_oargs;
862
        for(i = 0; i < nb_args; i++) {
863
            ct_str = tdefs->args_ct_str[i];
864
            tcg_regset_clear(def->args_ct[i].u.regs);
865
            def->args_ct[i].ct = 0;
866
            if (ct_str[0] >= '0' && ct_str[0] <= '9') {
867
                int oarg;
868
                oarg = ct_str[0] - '0';
869
                assert(oarg < def->nb_oargs);
870
                assert(def->args_ct[oarg].ct & TCG_CT_REG);
871
                /* TCG_CT_ALIAS is for the output arguments. The input
872
                   argument is tagged with TCG_CT_IALIAS. */
873
                def->args_ct[i] = def->args_ct[oarg];
874
                def->args_ct[oarg].ct = TCG_CT_ALIAS;
875
                def->args_ct[oarg].alias_index = i;
876
                def->args_ct[i].ct |= TCG_CT_IALIAS;
877
                def->args_ct[i].alias_index = oarg;
878
            } else {
879
                for(;;) {
880
                    if (*ct_str == '\0')
881
                        break;
882
                    switch(*ct_str) {
883
                    case 'i':
884
                        def->args_ct[i].ct |= TCG_CT_CONST;
885
                        ct_str++;
886
                        break;
887
                    default:
888
                        if (target_parse_constraint(&def->args_ct[i], &ct_str) < 0) {
889
                            fprintf(stderr, "Invalid constraint '%s' for arg %d of operation '%s'\n",
890
                                    ct_str, i, def->name);
891
                            exit(1);
892
                        }
893
                    }
894
                }
895
            }
896
        }
897

    
898
        /* sort the constraints (XXX: this is just an heuristic) */
899
        sort_constraints(def, 0, def->nb_oargs);
900
        sort_constraints(def, def->nb_oargs, def->nb_iargs);
901

    
902
#if 0
903
        {
904
            int i;
905

906
            printf("%s: sorted=", def->name);
907
            for(i = 0; i < def->nb_oargs + def->nb_iargs; i++)
908
                printf(" %d", def->sorted_args[i]);
909
            printf("\n");
910
        }
911
#endif
912
        tdefs++;
913
    }
914

    
915
}
916

    
917
#ifdef USE_LIVENESS_ANALYSIS
918

    
919
/* set a nop for an operation using 'nb_args' */
920
static inline void tcg_set_nop(TCGContext *s, uint16_t *opc_ptr, 
921
                               TCGArg *args, int nb_args)
922
{
923
    if (nb_args == 0) {
924
        *opc_ptr = INDEX_op_nop;
925
    } else {
926
        *opc_ptr = INDEX_op_nopn;
927
        args[0] = nb_args;
928
        args[nb_args - 1] = nb_args;
929
    }
930
}
931

    
932
/* liveness analysis: end of basic block: globals are live, temps are dead */
933
static inline void tcg_la_bb_end(TCGContext *s, uint8_t *dead_temps)
934
{
935
    memset(dead_temps, 0, s->nb_globals);
936
    memset(dead_temps + s->nb_globals, 1, s->nb_temps - s->nb_globals);
937
}
938

    
939
/* Liveness analysis : update the opc_dead_iargs array to tell if a
940
   given input arguments is dead. Instructions updating dead
941
   temporaries are removed. */
942
void tcg_liveness_analysis(TCGContext *s)
943
{
944
    int i, op_index, op, nb_args, nb_iargs, nb_oargs, arg, nb_ops;
945
    TCGArg *args;
946
    const TCGOpDef *def;
947
    uint8_t *dead_temps;
948
    unsigned int dead_iargs;
949
    
950
    gen_opc_ptr++; /* skip end */
951

    
952
    nb_ops = gen_opc_ptr - gen_opc_buf;
953

    
954
    /* XXX: make it really dynamic */
955
    s->op_dead_iargs = tcg_malloc(OPC_BUF_SIZE * sizeof(uint16_t));
956
    
957
    dead_temps = tcg_malloc(s->nb_temps);
958
    memset(dead_temps, 1, s->nb_temps);
959

    
960
    args = gen_opparam_ptr;
961
    op_index = nb_ops - 1;
962
    while (op_index >= 0) {
963
        op = gen_opc_buf[op_index];
964
        def = &tcg_op_defs[op];
965
        switch(op) {
966
        case INDEX_op_call:
967
            {
968
                int call_flags;
969

    
970
                nb_args = args[-1];
971
                args -= nb_args;
972
                nb_iargs = args[0] & 0xffff;
973
                nb_oargs = args[0] >> 16;
974
                args++;
975
                call_flags = args[nb_oargs + nb_iargs];
976

    
977
                /* pure functions can be removed if their result is not
978
                   used */
979
                if (call_flags & TCG_CALL_PURE) {
980
                    for(i = 0; i < nb_oargs; i++) {
981
                        arg = args[i];
982
                        if (!dead_temps[arg])
983
                            goto do_not_remove_call;
984
                    }
985
                    tcg_set_nop(s, gen_opc_buf + op_index, 
986
                                args - 1, nb_args);
987
                } else {
988
                do_not_remove_call:
989

    
990
                    /* output args are dead */
991
                    for(i = 0; i < nb_oargs; i++) {
992
                        arg = args[i];
993
                        dead_temps[arg] = 1;
994
                    }
995
                    
996
                    /* globals are live (they may be used by the call) */
997
                    memset(dead_temps, 0, s->nb_globals);
998
                    
999
                    /* input args are live */
1000
                    dead_iargs = 0;
1001
                    for(i = 0; i < nb_iargs; i++) {
1002
                        arg = args[i + nb_oargs];
1003
                        if (arg != TCG_CALL_DUMMY_ARG) {
1004
                            if (dead_temps[arg]) {
1005
                                dead_iargs |= (1 << i);
1006
                            }
1007
                            dead_temps[arg] = 0;
1008
                        }
1009
                    }
1010
                    s->op_dead_iargs[op_index] = dead_iargs;
1011
                }
1012
                args--;
1013
            }
1014
            break;
1015
        case INDEX_op_set_label:
1016
            args--;
1017
            /* mark end of basic block */
1018
            tcg_la_bb_end(s, dead_temps);
1019
            break;
1020
        case INDEX_op_nopn:
1021
            nb_args = args[-1];
1022
            args -= nb_args;
1023
            break;
1024
        case INDEX_op_discard:
1025
            args--;
1026
            /* mark the temporary as dead */
1027
            dead_temps[args[0]] = 1;
1028
            break;
1029
        case INDEX_op_macro_2:
1030
            {
1031
                int dead_args[2], macro_id;
1032
                int saved_op_index, saved_arg_index;
1033
                int macro_op_index, macro_arg_index;
1034
                int macro_end_op_index, macro_end_arg_index;
1035
                int last_nb_temps;
1036
                
1037
                nb_args = 3;
1038
                args -= nb_args;
1039
                dead_args[0] = dead_temps[args[0]];
1040
                dead_args[1] = dead_temps[args[1]];
1041
                macro_id = args[2];
1042

    
1043
                /* call the macro function which generate code
1044
                   depending on the live outputs */
1045
                saved_op_index = op_index;
1046
                saved_arg_index = args - gen_opparam_buf;
1047

    
1048
                /* add a macro start instruction */
1049
                *gen_opc_ptr++ = INDEX_op_macro_start;
1050
                *gen_opparam_ptr++ = saved_op_index;
1051
                *gen_opparam_ptr++ = saved_arg_index;
1052

    
1053
                macro_op_index = gen_opc_ptr - gen_opc_buf;
1054
                macro_arg_index = gen_opparam_ptr -  gen_opparam_buf;
1055

    
1056
                last_nb_temps = s->nb_temps;
1057

    
1058
                s->macro_func(s, macro_id, dead_args);
1059

    
1060
                /* realloc temp info (XXX: make it faster) */
1061
                if (s->nb_temps > last_nb_temps) {
1062
                    uint8_t *new_dead_temps;
1063

    
1064
                    new_dead_temps = tcg_malloc(s->nb_temps);
1065
                    memcpy(new_dead_temps, dead_temps, last_nb_temps);
1066
                    memset(new_dead_temps + last_nb_temps, 1, 
1067
                           s->nb_temps - last_nb_temps);
1068
                    dead_temps = new_dead_temps;
1069
                }
1070

    
1071
                macro_end_op_index = gen_opc_ptr - gen_opc_buf;
1072
                macro_end_arg_index = gen_opparam_ptr - gen_opparam_buf;
1073

    
1074
                /* end of macro: add a goto to the next instruction */
1075
                *gen_opc_ptr++ = INDEX_op_macro_end;
1076
                *gen_opparam_ptr++ = op_index + 1;
1077
                *gen_opparam_ptr++ = saved_arg_index + nb_args;
1078

    
1079
                /* modify the macro operation to be a macro_goto */
1080
                gen_opc_buf[op_index] = INDEX_op_macro_goto;
1081
                args[0] = macro_op_index;
1082
                args[1] = macro_arg_index;
1083
                args[2] = 0; /* dummy third arg to match the 
1084
                                macro parameters */
1085

    
1086
                /* set the next instruction to the end of the macro */
1087
                op_index = macro_end_op_index;
1088
                args = macro_end_arg_index + gen_opparam_buf;
1089
            }
1090
            break;
1091
        case INDEX_op_macro_start:
1092
            args -= 2;
1093
            op_index = args[0];
1094
            args = gen_opparam_buf + args[1];
1095
            break;
1096
        case INDEX_op_macro_goto:
1097
        case INDEX_op_macro_end:
1098
            tcg_abort(); /* should never happen in liveness analysis */
1099
        case INDEX_op_end:
1100
            break;
1101
            /* XXX: optimize by hardcoding common cases (e.g. triadic ops) */
1102
        default:
1103
            if (op > INDEX_op_end) {
1104
                args -= def->nb_args;
1105
                nb_iargs = def->nb_iargs;
1106
                nb_oargs = def->nb_oargs;
1107

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

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

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

    
1173
    s->op_dead_iargs = tcg_malloc(nb_ops * sizeof(uint16_t));
1174
    memset(s->op_dead_iargs, 0, nb_ops * sizeof(uint16_t));
1175
}
1176
#endif
1177

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

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

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

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

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

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

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

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

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

    
1295
    tcg_regset_andnot(reg_ct, reg1, reg2);
1296

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

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

    
1313
    tcg_abort();
1314
}
1315

    
1316
/* save globals to their cannonical location and assume they can be
1317
   modified be the following code. */
1318
static void save_globals(TCGContext *s)
1319
{
1320
    TCGTemp *ts;
1321
    int i;
1322

    
1323
    for(i = 0; i < s->nb_globals; i++) {
1324
        ts = &s->temps[i];
1325
        if (!ts->fixed_reg) {
1326
            if (ts->val_type == TEMP_VAL_REG) {
1327
                tcg_reg_free(s, ts->reg);
1328
            } else if (ts->val_type == TEMP_VAL_DEAD) {
1329
                ts->val_type = TEMP_VAL_MEM;
1330
            }
1331
        }
1332
    }
1333
}
1334

    
1335
/* at the end of a basic block, we assume all temporaries are dead and
1336
   all globals are stored at their canonical location */
1337
/* XXX: optimize by handling constants in another array ? */
1338
void tcg_reg_alloc_bb_end(TCGContext *s)
1339
{
1340
    TCGTemp *ts;
1341
    int i;
1342

    
1343
    save_globals(s);
1344

    
1345
    for(i = s->nb_globals; i < s->nb_temps; i++) {
1346
        ts = &s->temps[i];
1347
        if (ts->val_type != TEMP_VAL_CONST) {
1348
            if (ts->val_type == TEMP_VAL_REG) {
1349
                s->reg_to_temp[ts->reg] = -1;
1350
            }
1351
            ts->val_type = TEMP_VAL_DEAD;
1352
        }
1353
    }
1354
}
1355

    
1356
#define IS_DEAD_IARG(n) ((dead_iargs >> (n)) & 1)
1357

    
1358
static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
1359
                              const TCGArg *args,
1360
                              unsigned int dead_iargs)
1361
{
1362
    TCGTemp *ts, *ots;
1363
    int reg;
1364
    const TCGArgConstraint *arg_ct;
1365

    
1366
    ots = &s->temps[args[0]];
1367
    ts = &s->temps[args[1]];
1368
    arg_ct = &def->args_ct[0];
1369

    
1370
    if (ts->val_type == TEMP_VAL_REG) {
1371
        if (IS_DEAD_IARG(0) && !ts->fixed_reg && !ots->fixed_reg) {
1372
            /* the mov can be suppressed */
1373
            if (ots->val_type == TEMP_VAL_REG)
1374
                s->reg_to_temp[ots->reg] = -1;
1375
            reg = ts->reg;
1376
            s->reg_to_temp[reg] = -1;
1377
            ts->val_type = TEMP_VAL_DEAD;
1378
        } else {
1379
            if (ots->val_type == TEMP_VAL_REG) {
1380
                reg = ots->reg;
1381
            } else {
1382
                reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1383
            }
1384
            if (ts->reg != reg) {
1385
                tcg_out_mov(s, reg, ts->reg);
1386
            }
1387
        }
1388
    } else if (ts->val_type == TEMP_VAL_MEM) {
1389
        if (ots->val_type == TEMP_VAL_REG) {
1390
            reg = ots->reg;
1391
        } else {
1392
            reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1393
        }
1394
        tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1395
    } else if (ts->val_type == TEMP_VAL_CONST) {
1396
        if (ots->val_type == TEMP_VAL_REG) {
1397
            reg = ots->reg;
1398
        } else {
1399
            reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1400
        }
1401
        tcg_out_movi(s, ots->type, reg, ts->val);
1402
    } else {
1403
        tcg_abort();
1404
    }
1405
    s->reg_to_temp[reg] = args[0];
1406
    ots->reg = reg;
1407
    ots->val_type = TEMP_VAL_REG;
1408
    ots->mem_coherent = 0;
1409
}
1410

    
1411
static void tcg_reg_alloc_op(TCGContext *s, 
1412
                             const TCGOpDef *def, int opc,
1413
                             const TCGArg *args,
1414
                             unsigned int dead_iargs)
1415
{
1416
    TCGRegSet allocated_regs;
1417
    int i, k, nb_iargs, nb_oargs, reg;
1418
    TCGArg arg;
1419
    const TCGArgConstraint *arg_ct;
1420
    TCGTemp *ts;
1421
    TCGArg new_args[TCG_MAX_OP_ARGS];
1422
    int const_args[TCG_MAX_OP_ARGS];
1423

    
1424
    nb_oargs = def->nb_oargs;
1425
    nb_iargs = def->nb_iargs;
1426

    
1427
    /* copy constants */
1428
    memcpy(new_args + nb_oargs + nb_iargs, 
1429
           args + nb_oargs + nb_iargs, 
1430
           sizeof(TCGArg) * def->nb_cargs);
1431

    
1432
    /* satisfy input constraints */ 
1433
    tcg_regset_set(allocated_regs, s->reserved_regs);
1434
    for(k = 0; k < nb_iargs; k++) {
1435
        i = def->sorted_args[nb_oargs + k];
1436
        arg = args[i];
1437
        arg_ct = &def->args_ct[i];
1438
        ts = &s->temps[arg];
1439
        if (ts->val_type == TEMP_VAL_MEM) {
1440
            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1441
            tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1442
            ts->val_type = TEMP_VAL_REG;
1443
            ts->reg = reg;
1444
            ts->mem_coherent = 1;
1445
            s->reg_to_temp[reg] = arg;
1446
        } else if (ts->val_type == TEMP_VAL_CONST) {
1447
            if (tcg_target_const_match(ts->val, arg_ct)) {
1448
                /* constant is OK for instruction */
1449
                const_args[i] = 1;
1450
                new_args[i] = ts->val;
1451
                goto iarg_end;
1452
            } else {
1453
                /* need to move to a register*/
1454
                reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1455
                tcg_out_movi(s, ts->type, reg, ts->val);
1456
                goto iarg_end1;
1457
            }
1458
        }
1459
        assert(ts->val_type == TEMP_VAL_REG);
1460
        if (arg_ct->ct & TCG_CT_IALIAS) {
1461
            if (ts->fixed_reg) {
1462
                /* if fixed register, we must allocate a new register
1463
                   if the alias is not the same register */
1464
                if (arg != args[arg_ct->alias_index])
1465
                    goto allocate_in_reg;
1466
            } else {
1467
                /* if the input is aliased to an output and if it is
1468
                   not dead after the instruction, we must allocate
1469
                   a new register and move it */
1470
                if (!IS_DEAD_IARG(i - nb_oargs)) 
1471
                    goto allocate_in_reg;
1472
            }
1473
        }
1474
        reg = ts->reg;
1475
        if (tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1476
            /* nothing to do : the constraint is satisfied */
1477
        } else {
1478
        allocate_in_reg:
1479
            /* allocate a new register matching the constraint 
1480
               and move the temporary register into it */
1481
            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1482
            tcg_out_mov(s, reg, ts->reg);
1483
        }
1484
    iarg_end1:
1485
        new_args[i] = reg;
1486
        const_args[i] = 0;
1487
        tcg_regset_set_reg(allocated_regs, reg);
1488
    iarg_end: ;
1489
    }
1490
    
1491
    /* mark dead temporaries and free the associated registers */
1492
    for(i = 0; i < nb_iargs; i++) {
1493
        arg = args[nb_oargs + i];
1494
        if (IS_DEAD_IARG(i)) {
1495
            ts = &s->temps[arg];
1496
            if (ts->val_type != TEMP_VAL_CONST && !ts->fixed_reg) {
1497
                if (ts->val_type == TEMP_VAL_REG)
1498
                    s->reg_to_temp[ts->reg] = -1;
1499
                ts->val_type = TEMP_VAL_DEAD;
1500
            }
1501
        }
1502
    }
1503

    
1504
    if (def->flags & TCG_OPF_CALL_CLOBBER) {
1505
        /* XXX: permit generic clobber register list ? */ 
1506
        for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1507
            if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
1508
                tcg_reg_free(s, reg);
1509
            }
1510
        }
1511
        /* XXX: for load/store we could do that only for the slow path
1512
           (i.e. when a memory callback is called) */
1513

    
1514
        /* store globals and free associated registers (we assume the insn
1515
           can modify any global. */
1516
        save_globals(s);
1517
    }
1518

    
1519
    /* satisfy the output constraints */
1520
    tcg_regset_set(allocated_regs, s->reserved_regs);
1521
    for(k = 0; k < nb_oargs; k++) {
1522
        i = def->sorted_args[k];
1523
        arg = args[i];
1524
        arg_ct = &def->args_ct[i];
1525
        ts = &s->temps[arg];
1526
        if (arg_ct->ct & TCG_CT_ALIAS) {
1527
            reg = new_args[arg_ct->alias_index];
1528
        } else {
1529
            /* if fixed register, we try to use it */
1530
            reg = ts->reg;
1531
            if (ts->fixed_reg &&
1532
                tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1533
                goto oarg_end;
1534
            }
1535
            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1536
        }
1537
        tcg_regset_set_reg(allocated_regs, reg);
1538
        /* if a fixed register is used, then a move will be done afterwards */
1539
        if (!ts->fixed_reg) {
1540
            if (ts->val_type == TEMP_VAL_REG)
1541
                s->reg_to_temp[ts->reg] = -1;
1542
            ts->val_type = TEMP_VAL_REG;
1543
            ts->reg = reg;
1544
            /* temp value is modified, so the value kept in memory is
1545
               potentially not the same */
1546
            ts->mem_coherent = 0; 
1547
            s->reg_to_temp[reg] = arg;
1548
        }
1549
    oarg_end:
1550
        new_args[i] = reg;
1551
    }
1552

    
1553
    if (def->flags & TCG_OPF_BB_END)
1554
        tcg_reg_alloc_bb_end(s);
1555

    
1556
    /* emit instruction */
1557
    tcg_out_op(s, opc, new_args, const_args);
1558
    
1559
    /* move the outputs in the correct register if needed */
1560
    for(i = 0; i < nb_oargs; i++) {
1561
        ts = &s->temps[args[i]];
1562
        reg = new_args[i];
1563
        if (ts->fixed_reg && ts->reg != reg) {
1564
            tcg_out_mov(s, ts->reg, reg);
1565
        }
1566
    }
1567
}
1568

    
1569
#ifdef TCG_TARGET_STACK_GROWSUP
1570
#define STACK_DIR(x) (-(x))
1571
#else
1572
#define STACK_DIR(x) (x)
1573
#endif
1574

    
1575
static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
1576
                              int opc, const TCGArg *args,
1577
                              unsigned int dead_iargs)
1578
{
1579
    int nb_iargs, nb_oargs, flags, nb_regs, i, reg, nb_params;
1580
    TCGArg arg, func_arg;
1581
    TCGTemp *ts;
1582
    tcg_target_long stack_offset, call_stack_size, func_addr;
1583
    int const_func_arg, allocate_args;
1584
    TCGRegSet allocated_regs;
1585
    const TCGArgConstraint *arg_ct;
1586

    
1587
    arg = *args++;
1588

    
1589
    nb_oargs = arg >> 16;
1590
    nb_iargs = arg & 0xffff;
1591
    nb_params = nb_iargs - 1;
1592

    
1593
    flags = args[nb_oargs + nb_iargs];
1594

    
1595
    nb_regs = tcg_target_get_call_iarg_regs_count(flags);
1596
    if (nb_regs > nb_params)
1597
        nb_regs = nb_params;
1598

    
1599
    /* assign stack slots first */
1600
    /* XXX: preallocate call stack */
1601
    call_stack_size = (nb_params - nb_regs) * sizeof(tcg_target_long);
1602
    call_stack_size = (call_stack_size + TCG_TARGET_STACK_ALIGN - 1) & 
1603
        ~(TCG_TARGET_STACK_ALIGN - 1);
1604
    allocate_args = (call_stack_size > TCG_STATIC_CALL_ARGS_SIZE);
1605
    if (allocate_args) {
1606
        tcg_out_addi(s, TCG_REG_CALL_STACK, -STACK_DIR(call_stack_size));
1607
    }
1608

    
1609
    stack_offset = TCG_TARGET_CALL_STACK_OFFSET;
1610
    for(i = nb_regs; i < nb_params; i++) {
1611
        arg = args[nb_oargs + i];
1612
#ifdef TCG_TARGET_STACK_GROWSUP
1613
        stack_offset -= sizeof(tcg_target_long);
1614
#endif
1615
        if (arg != TCG_CALL_DUMMY_ARG) {
1616
            ts = &s->temps[arg];
1617
            if (ts->val_type == TEMP_VAL_REG) {
1618
                tcg_out_st(s, ts->type, ts->reg, TCG_REG_CALL_STACK, stack_offset);
1619
            } else if (ts->val_type == TEMP_VAL_MEM) {
1620
                reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], 
1621
                                    s->reserved_regs);
1622
                /* XXX: not correct if reading values from the stack */
1623
                tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1624
                tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
1625
            } else if (ts->val_type == TEMP_VAL_CONST) {
1626
                reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], 
1627
                                    s->reserved_regs);
1628
                /* XXX: sign extend may be needed on some targets */
1629
                tcg_out_movi(s, ts->type, reg, ts->val);
1630
                tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
1631
            } else {
1632
                tcg_abort();
1633
            }
1634
        }
1635
#ifndef TCG_TARGET_STACK_GROWSUP
1636
        stack_offset += sizeof(tcg_target_long);
1637
#endif
1638
    }
1639
    
1640
    /* assign input registers */
1641
    tcg_regset_set(allocated_regs, s->reserved_regs);
1642
    for(i = 0; i < nb_regs; i++) {
1643
        arg = args[nb_oargs + i];
1644
        if (arg != TCG_CALL_DUMMY_ARG) {
1645
            ts = &s->temps[arg];
1646
            reg = tcg_target_call_iarg_regs[i];
1647
            tcg_reg_free(s, reg);
1648
            if (ts->val_type == TEMP_VAL_REG) {
1649
                if (ts->reg != reg) {
1650
                    tcg_out_mov(s, reg, ts->reg);
1651
                }
1652
            } else if (ts->val_type == TEMP_VAL_MEM) {
1653
                tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1654
            } else if (ts->val_type == TEMP_VAL_CONST) {
1655
                /* XXX: sign extend ? */
1656
                tcg_out_movi(s, ts->type, reg, ts->val);
1657
            } else {
1658
                tcg_abort();
1659
            }
1660
            tcg_regset_set_reg(allocated_regs, reg);
1661
        }
1662
    }
1663
    
1664
    /* assign function address */
1665
    func_arg = args[nb_oargs + nb_iargs - 1];
1666
    arg_ct = &def->args_ct[0];
1667
    ts = &s->temps[func_arg];
1668
    func_addr = ts->val;
1669
    const_func_arg = 0;
1670
    if (ts->val_type == TEMP_VAL_MEM) {
1671
        reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1672
        tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1673
        func_arg = reg;
1674
    } else if (ts->val_type == TEMP_VAL_REG) {
1675
        reg = ts->reg;
1676
        if (!tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1677
            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1678
            tcg_out_mov(s, reg, ts->reg);
1679
        }
1680
        func_arg = reg;
1681
    } else if (ts->val_type == TEMP_VAL_CONST) {
1682
        if (tcg_target_const_match(func_addr, arg_ct)) {
1683
            const_func_arg = 1;
1684
            func_arg = func_addr;
1685
        } else {
1686
            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1687
            tcg_out_movi(s, ts->type, reg, func_addr);
1688
            func_arg = reg;
1689
        }
1690
    } else {
1691
        tcg_abort();
1692
    }
1693
    
1694
    /* mark dead temporaries and free the associated registers */
1695
    for(i = 0; i < nb_iargs; i++) {
1696
        arg = args[nb_oargs + i];
1697
        if (IS_DEAD_IARG(i)) {
1698
            ts = &s->temps[arg];
1699
            if (ts->val_type != TEMP_VAL_CONST && !ts->fixed_reg) {
1700
                if (ts->val_type == TEMP_VAL_REG)
1701
                    s->reg_to_temp[ts->reg] = -1;
1702
                ts->val_type = TEMP_VAL_DEAD;
1703
            }
1704
        }
1705
    }
1706
    
1707
    /* clobber call registers */
1708
    for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1709
        if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
1710
            tcg_reg_free(s, reg);
1711
        }
1712
    }
1713
    
1714
    /* store globals and free associated registers (we assume the call
1715
       can modify any global. */
1716
    save_globals(s);
1717

    
1718
    tcg_out_op(s, opc, &func_arg, &const_func_arg);
1719
    
1720
    if (allocate_args) {
1721
        tcg_out_addi(s, TCG_REG_CALL_STACK, STACK_DIR(call_stack_size));
1722
    }
1723

    
1724
    /* assign output registers and emit moves if needed */
1725
    for(i = 0; i < nb_oargs; i++) {
1726
        arg = args[i];
1727
        ts = &s->temps[arg];
1728
        reg = tcg_target_call_oarg_regs[i];
1729
        tcg_reg_free(s, reg);
1730
        if (ts->fixed_reg) {
1731
            if (ts->reg != reg) {
1732
                tcg_out_mov(s, ts->reg, reg);
1733
            }
1734
        } else {
1735
            if (ts->val_type == TEMP_VAL_REG)
1736
                s->reg_to_temp[ts->reg] = -1;
1737
            ts->val_type = TEMP_VAL_REG;
1738
            ts->reg = reg;
1739
            ts->mem_coherent = 0; 
1740
            s->reg_to_temp[reg] = arg;
1741
        }
1742
    }
1743
    
1744
    return nb_iargs + nb_oargs + def->nb_cargs + 1;
1745
}
1746

    
1747
#ifdef CONFIG_PROFILER
1748

    
1749
static int64_t dyngen_table_op_count[NB_OPS];
1750

    
1751
void dump_op_count(void)
1752
{
1753
    int i;
1754
    FILE *f;
1755
    f = fopen("/tmp/op1.log", "w");
1756
    for(i = 0; i < INDEX_op_end; i++) {
1757
        fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name, dyngen_table_op_count[i]);
1758
    }
1759
    fclose(f);
1760
    f = fopen("/tmp/op2.log", "w");
1761
    for(i = INDEX_op_end; i < NB_OPS; i++) {
1762
        fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name, dyngen_table_op_count[i]);
1763
    }
1764
    fclose(f);
1765
}
1766
#endif
1767

    
1768

    
1769
static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
1770
                                      long search_pc)
1771
{
1772
    int opc, op_index, macro_op_index;
1773
    const TCGOpDef *def;
1774
    unsigned int dead_iargs;
1775
    const TCGArg *args;
1776

    
1777
#ifdef DEBUG_DISAS
1778
    if (unlikely(loglevel & CPU_LOG_TB_OP)) {
1779
        fprintf(logfile, "OP:\n");
1780
        tcg_dump_ops(s, logfile);
1781
        fprintf(logfile, "\n");
1782
    }
1783
#endif
1784

    
1785
    tcg_liveness_analysis(s);
1786

    
1787
#ifdef DEBUG_DISAS
1788
    if (unlikely(loglevel & CPU_LOG_TB_OP_OPT)) {
1789
        fprintf(logfile, "OP after la:\n");
1790
        tcg_dump_ops(s, logfile);
1791
        fprintf(logfile, "\n");
1792
    }
1793
#endif
1794

    
1795
    tcg_reg_alloc_start(s);
1796

    
1797
    s->code_buf = gen_code_buf;
1798
    s->code_ptr = gen_code_buf;
1799

    
1800
    macro_op_index = -1;
1801
    args = gen_opparam_buf;
1802
    op_index = 0;
1803

    
1804
    for(;;) {
1805
        opc = gen_opc_buf[op_index];
1806
#ifdef CONFIG_PROFILER
1807
        dyngen_table_op_count[opc]++;
1808
#endif
1809
        def = &tcg_op_defs[opc];
1810
#if 0
1811
        printf("%s: %d %d %d\n", def->name,
1812
               def->nb_oargs, def->nb_iargs, def->nb_cargs);
1813
        //        dump_regs(s);
1814
#endif
1815
        switch(opc) {
1816
        case INDEX_op_mov_i32:
1817
#if TCG_TARGET_REG_BITS == 64
1818
        case INDEX_op_mov_i64:
1819
#endif
1820
            dead_iargs = s->op_dead_iargs[op_index];
1821
            tcg_reg_alloc_mov(s, def, args, dead_iargs);
1822
            break;
1823
        case INDEX_op_nop:
1824
        case INDEX_op_nop1:
1825
        case INDEX_op_nop2:
1826
        case INDEX_op_nop3:
1827
            break;
1828
        case INDEX_op_nopn:
1829
            args += args[0];
1830
            goto next;
1831
        case INDEX_op_discard:
1832
            {
1833
                TCGTemp *ts;
1834
                ts = &s->temps[args[0]];
1835
                /* mark the temporary as dead */
1836
                if (ts->val_type != TEMP_VAL_CONST && !ts->fixed_reg) {
1837
                    if (ts->val_type == TEMP_VAL_REG)
1838
                        s->reg_to_temp[ts->reg] = -1;
1839
                    ts->val_type = TEMP_VAL_DEAD;
1840
                }
1841
            }
1842
            break;
1843
        case INDEX_op_macro_goto:
1844
            macro_op_index = op_index; /* only used for exceptions */
1845
            op_index = args[0] - 1;
1846
            args = gen_opparam_buf + args[1];
1847
            goto next;
1848
        case INDEX_op_macro_end:
1849
            macro_op_index = -1; /* only used for exceptions */
1850
            op_index = args[0] - 1;
1851
            args = gen_opparam_buf + args[1];
1852
            goto next;
1853
        case INDEX_op_macro_start:
1854
            /* must never happen here */
1855
            tcg_abort();
1856
        case INDEX_op_set_label:
1857
            tcg_reg_alloc_bb_end(s);
1858
            tcg_out_label(s, args[0], (long)s->code_ptr);
1859
            break;
1860
        case INDEX_op_call:
1861
            dead_iargs = s->op_dead_iargs[op_index];
1862
            args += tcg_reg_alloc_call(s, def, opc, args, dead_iargs);
1863
            goto next;
1864
        case INDEX_op_end:
1865
            goto the_end;
1866

    
1867
#ifdef CONFIG_DYNGEN_OP
1868
        case 0 ... INDEX_op_end - 1:
1869
            /* legacy dyngen ops */
1870
#ifdef CONFIG_PROFILER
1871
            {
1872
                extern int64_t dyngen_old_op_count;
1873
                dyngen_old_op_count++;
1874
            }
1875
#endif
1876
            tcg_reg_alloc_bb_end(s);
1877
            if (search_pc >= 0) {
1878
                s->code_ptr += def->copy_size;
1879
                args += def->nb_args;
1880
            } else {
1881
                args = dyngen_op(s, opc, args);
1882
            }
1883
            goto next;
1884
#endif
1885
        default:
1886
            /* Note: in order to speed up the code, it would be much
1887
               faster to have specialized register allocator functions for
1888
               some common argument patterns */
1889
            dead_iargs = s->op_dead_iargs[op_index];
1890
            tcg_reg_alloc_op(s, def, opc, args, dead_iargs);
1891
            break;
1892
        }
1893
        args += def->nb_args;
1894
    next: ;
1895
        if (search_pc >= 0 && search_pc < s->code_ptr - gen_code_buf) {
1896
            if (macro_op_index >= 0)
1897
                return macro_op_index;
1898
            else
1899
                return op_index;
1900
        }
1901
        op_index++;
1902
#ifndef NDEBUG
1903
        check_regs(s);
1904
#endif
1905
    }
1906
 the_end:
1907
    return -1;
1908
}
1909

    
1910
int dyngen_code(TCGContext *s, uint8_t *gen_code_buf)
1911
{
1912
#ifdef CONFIG_PROFILER
1913
    {
1914
        extern int64_t dyngen_op_count;
1915
        extern int dyngen_op_count_max;
1916
        int n;
1917
        n = (gen_opc_ptr - gen_opc_buf);
1918
        dyngen_op_count += n;
1919
        if (n > dyngen_op_count_max)
1920
            dyngen_op_count_max = n;
1921
    }
1922
#endif
1923

    
1924
    tcg_gen_code_common(s, gen_code_buf, -1);
1925

    
1926
    /* flush instruction cache */
1927
    flush_icache_range((unsigned long)gen_code_buf, 
1928
                       (unsigned long)s->code_ptr);
1929
    return s->code_ptr -  gen_code_buf;
1930
}
1931

    
1932
/* Return the index of the micro operation such as the pc after is <
1933
   offset bytes from the start of the TB.  The contents of gen_code_buf must
1934
   not be changed, though writing the same values is ok.
1935
   Return -1 if not found. */
1936
int dyngen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, long offset)
1937
{
1938
    return tcg_gen_code_common(s, gen_code_buf, offset);
1939
}