Statistics
| Branch: | Revision:

root / tcg / tcg.c @ b03cce8e

History | View | Annotate | Download (55.2 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
TCGv tcg_global_mem_new(TCGType type, int reg, tcg_target_long offset,
312
                        const char *name)
313
{
314
    TCGContext *s = &tcg_ctx;
315
    TCGTemp *ts;
316
    int idx;
317

    
318
    idx = s->nb_globals;
319
#if TCG_TARGET_REG_BITS == 32
320
    if (type == TCG_TYPE_I64) {
321
        char buf[64];
322
        tcg_temp_alloc(s, s->nb_globals + 1);
323
        ts = &s->temps[s->nb_globals];
324
        ts->base_type = type;
325
        ts->type = TCG_TYPE_I32;
326
        ts->fixed_reg = 0;
327
        ts->mem_allocated = 1;
328
        ts->mem_reg = reg;
329
#ifdef TCG_TARGET_WORDS_BIGENDIAN
330
        ts->mem_offset = offset + 4;
331
#else
332
        ts->mem_offset = offset;
333
#endif
334
        ts->val_type = TEMP_VAL_MEM;
335
        pstrcpy(buf, sizeof(buf), name);
336
        pstrcat(buf, sizeof(buf), "_0");
337
        ts->name = strdup(buf);
338
        ts++;
339

    
340
        ts->base_type = type;
341
        ts->type = TCG_TYPE_I32;
342
        ts->fixed_reg = 0;
343
        ts->mem_allocated = 1;
344
        ts->mem_reg = reg;
345
#ifdef TCG_TARGET_WORDS_BIGENDIAN
346
        ts->mem_offset = offset;
347
#else
348
        ts->mem_offset = offset + 4;
349
#endif
350
        ts->val_type = TEMP_VAL_MEM;
351
        pstrcpy(buf, sizeof(buf), name);
352
        pstrcat(buf, sizeof(buf), "_1");
353
        ts->name = strdup(buf);
354

    
355
        s->nb_globals += 2;
356
    } else
357
#endif
358
    {
359
        tcg_temp_alloc(s, s->nb_globals + 1);
360
        ts = &s->temps[s->nb_globals];
361
        ts->base_type = type;
362
        ts->type = type;
363
        ts->fixed_reg = 0;
364
        ts->mem_allocated = 1;
365
        ts->mem_reg = reg;
366
        ts->mem_offset = offset;
367
        ts->val_type = TEMP_VAL_MEM;
368
        ts->name = name;
369
        s->nb_globals++;
370
    }
371
    return MAKE_TCGV(idx);
372
}
373

    
374
TCGv tcg_temp_new(TCGType type)
375
{
376
    TCGContext *s = &tcg_ctx;
377
    TCGTemp *ts;
378
    int idx;
379

    
380
    idx = s->nb_temps;
381
#if TCG_TARGET_REG_BITS == 32
382
    if (type == TCG_TYPE_I64) {
383
        tcg_temp_alloc(s, s->nb_temps + 1);
384
        ts = &s->temps[s->nb_temps];
385
        ts->base_type = type;
386
        ts->type = TCG_TYPE_I32;
387
        ts->fixed_reg = 0;
388
        ts->val_type = TEMP_VAL_DEAD;
389
        ts->mem_allocated = 0;
390
        ts->name = NULL;
391
        ts++;
392
        ts->base_type = TCG_TYPE_I32;
393
        ts->type = TCG_TYPE_I32;
394
        ts->val_type = TEMP_VAL_DEAD;
395
        ts->fixed_reg = 0;
396
        ts->mem_allocated = 0;
397
        ts->name = NULL;
398
        s->nb_temps += 2;
399
    } else
400
#endif
401
    {
402
        tcg_temp_alloc(s, s->nb_temps + 1);
403
        ts = &s->temps[s->nb_temps];
404
        ts->base_type = type;
405
        ts->type = type;
406
        ts->fixed_reg = 0;
407
        ts->val_type = TEMP_VAL_DEAD;
408
        ts->mem_allocated = 0;
409
        ts->name = NULL;
410
        s->nb_temps++;
411
    }
412
    return MAKE_TCGV(idx);
413
}
414

    
415
TCGv tcg_const_i32(int32_t val)
416
{
417
    TCGContext *s = &tcg_ctx;
418
    TCGTemp *ts;
419
    int idx;
420

    
421
    idx = s->nb_temps;
422
    tcg_temp_alloc(s, idx + 1);
423
    ts = &s->temps[idx];
424
    ts->base_type = ts->type = TCG_TYPE_I32;
425
    ts->val_type = TEMP_VAL_CONST;
426
    ts->name = NULL;
427
    ts->val = val;
428
    s->nb_temps++;
429
    return MAKE_TCGV(idx);
430
}
431

    
432
TCGv tcg_const_i64(int64_t val)
433
{
434
    TCGContext *s = &tcg_ctx;
435
    TCGTemp *ts;
436
    int idx;
437

    
438
    idx = s->nb_temps;
439
#if TCG_TARGET_REG_BITS == 32
440
    tcg_temp_alloc(s, idx + 2);
441
    ts = &s->temps[idx];
442
    ts->base_type = TCG_TYPE_I64;
443
    ts->type = TCG_TYPE_I32;
444
    ts->val_type = TEMP_VAL_CONST;
445
    ts->name = NULL;
446
    ts->val = val;
447
    ts++;
448
    ts->base_type = TCG_TYPE_I32;
449
    ts->type = TCG_TYPE_I32;
450
    ts->val_type = TEMP_VAL_CONST;
451
    ts->name = NULL;
452
    ts->val = val >> 32;
453
    s->nb_temps += 2;
454
#else
455
    tcg_temp_alloc(s, idx + 1);
456
    ts = &s->temps[idx];
457
    ts->base_type = ts->type = TCG_TYPE_I64;
458
    ts->val_type = TEMP_VAL_CONST;
459
    ts->name = NULL;
460
    ts->val = val;
461
    s->nb_temps++;
462
#endif    
463
    return MAKE_TCGV(idx);
464
}
465

    
466
void tcg_register_helper(void *func, const char *name)
467
{
468
    TCGContext *s = &tcg_ctx;
469
    int n;
470
    if ((s->nb_helpers + 1) > s->allocated_helpers) {
471
        n = s->allocated_helpers;
472
        if (n == 0) {
473
            n = 4;
474
        } else {
475
            n *= 2;
476
        }
477
        s->helpers = realloc(s->helpers, n * sizeof(TCGHelperInfo));
478
        s->allocated_helpers = n;
479
    }
480
    s->helpers[s->nb_helpers].func = func;
481
    s->helpers[s->nb_helpers].name = name;
482
    s->nb_helpers++;
483
}
484

    
485
const char *tcg_helper_get_name(TCGContext *s, void *func)
486
{
487
    int i;
488

    
489
    for(i = 0; i < s->nb_helpers; i++) {
490
        if (s->helpers[i].func == func)
491
            return s->helpers[i].name;
492
    }
493
    return NULL;
494
}
495

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

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

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

    
522

    
523
#if TCG_TARGET_REG_BITS < 64
524
/* Note: we convert the 64 bit args to 32 bit */
525
void tcg_gen_call(TCGContext *s, TCGv func, unsigned int flags,
526
                  unsigned int nb_rets, const TCGv *rets,
527
                  unsigned int nb_params, const TCGv *args1)
528
{
529
    TCGv ret, *args2, rets_2[2], arg;
530
    int j, i, call_type;
531

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

    
582
#if TCG_TARGET_REG_BITS == 32
583
void tcg_gen_shifti_i64(TCGv ret, TCGv arg1, 
584
                        int c, int right, int arith)
585
{
586
    if (c == 0)
587
        return;
588
    if (c >= 32) {
589
        c -= 32;
590
        if (right) {
591
            if (arith) {
592
                tcg_gen_sari_i32(ret, TCGV_HIGH(arg1), c);
593
                tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 31);
594
            } else {
595
                tcg_gen_shri_i32(ret, TCGV_HIGH(arg1), c);
596
                tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
597
            }
598
        } else {
599
            tcg_gen_shli_i32(TCGV_HIGH(ret), arg1, c);
600
            tcg_gen_movi_i32(ret, 0);
601
        }
602
    } else {
603
        TCGv t0, t1;
604

    
605
        t0 = tcg_temp_new(TCG_TYPE_I32);
606
        t1 = tcg_temp_new(TCG_TYPE_I32);
607
        if (right) {
608
            tcg_gen_shli_i32(t0, TCGV_HIGH(arg1), 32 - c);
609
            if (arith)
610
                tcg_gen_sari_i32(t1, TCGV_HIGH(arg1), c);
611
            else 
612
                tcg_gen_shri_i32(t1, TCGV_HIGH(arg1), c);
613
            tcg_gen_shri_i32(ret, arg1, c); 
614
            tcg_gen_or_i32(ret, ret, t0);
615
            tcg_gen_mov_i32(TCGV_HIGH(ret), t1);
616
        } else {
617
            tcg_gen_shri_i32(t0, arg1, 32 - c);
618
            /* Note: ret can be the same as arg1, so we use t1 */
619
            tcg_gen_shli_i32(t1, arg1, c); 
620
            tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c);
621
            tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t0);
622
            tcg_gen_mov_i32(ret, t1);
623
        }
624
    }
625
}
626
#endif
627

    
628
void tcg_reg_alloc_start(TCGContext *s)
629
{
630
    int i;
631
    TCGTemp *ts;
632
    for(i = 0; i < s->nb_globals; i++) {
633
        ts = &s->temps[i];
634
        if (ts->fixed_reg) {
635
            ts->val_type = TEMP_VAL_REG;
636
        } else {
637
            ts->val_type = TEMP_VAL_MEM;
638
        }
639
    }
640
    for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
641
        s->reg_to_temp[i] = -1;
642
    }
643
}
644

    
645
static char *tcg_get_arg_str_idx(TCGContext *s, char *buf, int buf_size,
646
                                 int idx)
647
{
648
    TCGTemp *ts;
649

    
650
    ts = &s->temps[idx];
651
    if (idx < s->nb_globals) {
652
        pstrcpy(buf, buf_size, ts->name);
653
    } else {
654
        if (ts->val_type == TEMP_VAL_CONST) {
655
            snprintf(buf, buf_size, "$0x%" TCG_PRIlx , ts->val);
656
        } else {
657
            snprintf(buf, buf_size, "tmp%d", idx - s->nb_globals);
658
        }
659
    }
660
    return buf;
661
}
662

    
663
char *tcg_get_arg_str(TCGContext *s, char *buf, int buf_size, TCGv arg)
664
{
665
    return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV(arg));
666
}
667

    
668
void tcg_dump_ops(TCGContext *s, FILE *outfile)
669
{
670
    const uint16_t *opc_ptr;
671
    const TCGArg *args;
672
    TCGArg arg;
673
    int c, i, k, nb_oargs, nb_iargs, nb_cargs;
674
    const TCGOpDef *def;
675
    char buf[128];
676

    
677
    opc_ptr = gen_opc_buf;
678
    args = gen_opparam_buf;
679
    while (opc_ptr < gen_opc_ptr) {
680
        c = *opc_ptr++;
681
        def = &tcg_op_defs[c];
682
        fprintf(outfile, " %s ", def->name);
683
        if (c == INDEX_op_call) {
684
            TCGArg arg;
685
            /* variable number of arguments */
686
            arg = *args++;
687
            nb_oargs = arg >> 16;
688
            nb_iargs = arg & 0xffff;
689
            nb_cargs = def->nb_cargs;
690

    
691
            /* function name */
692
            /* XXX: dump helper name for call */
693
            fprintf(outfile, "%s",
694
                    tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + nb_iargs - 1]));
695
            /* flags */
696
            fprintf(outfile, ",$0x%" TCG_PRIlx,
697
                    args[nb_oargs + nb_iargs]);
698
            /* nb out args */
699
            fprintf(outfile, ",$%d", nb_oargs);
700
            for(i = 0; i < nb_oargs; i++) {
701
                fprintf(outfile, ",");
702
                fprintf(outfile, "%s",
703
                        tcg_get_arg_str_idx(s, buf, sizeof(buf), args[i]));
704
            }
705
            for(i = 0; i < (nb_iargs - 1); i++) {
706
                fprintf(outfile, ",");
707
                fprintf(outfile, "%s",
708
                        tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + i]));
709
            }
710
        } else {
711
            if (c == INDEX_op_nopn) {
712
                /* variable number of arguments */
713
                nb_cargs = *args;
714
                nb_oargs = 0;
715
                nb_iargs = 0;
716
            } else {
717
                nb_oargs = def->nb_oargs;
718
                nb_iargs = def->nb_iargs;
719
                nb_cargs = def->nb_cargs;
720
            }
721
            
722
            k = 0;
723
            for(i = 0; i < nb_oargs; i++) {
724
                if (k != 0)
725
                    fprintf(outfile, ",");
726
                fprintf(outfile, "%s",
727
                        tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
728
            }
729
            for(i = 0; i < nb_iargs; i++) {
730
                if (k != 0)
731
                    fprintf(outfile, ",");
732
                fprintf(outfile, "%s",
733
                        tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
734
            }
735
            for(i = 0; i < nb_cargs; i++) {
736
                if (k != 0)
737
                    fprintf(outfile, ",");
738
                arg = args[k++];
739
                fprintf(outfile, "$0x%" TCG_PRIlx, arg);
740
            }
741
        }
742
        fprintf(outfile, "\n");
743
        args += nb_iargs + nb_oargs + nb_cargs;
744
    }
745
}
746

    
747
/* we give more priority to constraints with less registers */
748
static int get_constraint_priority(const TCGOpDef *def, int k)
749
{
750
    const TCGArgConstraint *arg_ct;
751

    
752
    int i, n;
753
    arg_ct = &def->args_ct[k];
754
    if (arg_ct->ct & TCG_CT_ALIAS) {
755
        /* an alias is equivalent to a single register */
756
        n = 1;
757
    } else {
758
        if (!(arg_ct->ct & TCG_CT_REG))
759
            return 0;
760
        n = 0;
761
        for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
762
            if (tcg_regset_test_reg(arg_ct->u.regs, i))
763
                n++;
764
        }
765
    }
766
    return TCG_TARGET_NB_REGS - n + 1;
767
}
768

    
769
/* sort from highest priority to lowest */
770
static void sort_constraints(TCGOpDef *def, int start, int n)
771
{
772
    int i, j, p1, p2, tmp;
773

    
774
    for(i = 0; i < n; i++)
775
        def->sorted_args[start + i] = start + i;
776
    if (n <= 1)
777
        return;
778
    for(i = 0; i < n - 1; i++) {
779
        for(j = i + 1; j < n; j++) {
780
            p1 = get_constraint_priority(def, def->sorted_args[start + i]);
781
            p2 = get_constraint_priority(def, def->sorted_args[start + j]);
782
            if (p1 < p2) {
783
                tmp = def->sorted_args[start + i];
784
                def->sorted_args[start + i] = def->sorted_args[start + j];
785
                def->sorted_args[start + j] = tmp;
786
            }
787
        }
788
    }
789
}
790

    
791
void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs)
792
{
793
    int op;
794
    TCGOpDef *def;
795
    const char *ct_str;
796
    int i, nb_args;
797

    
798
    for(;;) {
799
        if (tdefs->op < 0)
800
            break;
801
        op = tdefs->op;
802
        assert(op >= 0 && op < NB_OPS);
803
        def = &tcg_op_defs[op];
804
        nb_args = def->nb_iargs + def->nb_oargs;
805
        for(i = 0; i < nb_args; i++) {
806
            ct_str = tdefs->args_ct_str[i];
807
            tcg_regset_clear(def->args_ct[i].u.regs);
808
            def->args_ct[i].ct = 0;
809
            if (ct_str[0] >= '0' && ct_str[0] <= '9') {
810
                int oarg;
811
                oarg = ct_str[0] - '0';
812
                assert(oarg < def->nb_oargs);
813
                assert(def->args_ct[oarg].ct & TCG_CT_REG);
814
                /* TCG_CT_ALIAS is for the output arguments. The input
815
                   argument is tagged with TCG_CT_IALIAS. */
816
                def->args_ct[i] = def->args_ct[oarg];
817
                def->args_ct[oarg].ct = TCG_CT_ALIAS;
818
                def->args_ct[oarg].alias_index = i;
819
                def->args_ct[i].ct |= TCG_CT_IALIAS;
820
                def->args_ct[i].alias_index = oarg;
821
            } else {
822
                for(;;) {
823
                    if (*ct_str == '\0')
824
                        break;
825
                    switch(*ct_str) {
826
                    case 'i':
827
                        def->args_ct[i].ct |= TCG_CT_CONST;
828
                        ct_str++;
829
                        break;
830
                    default:
831
                        if (target_parse_constraint(&def->args_ct[i], &ct_str) < 0) {
832
                            fprintf(stderr, "Invalid constraint '%s' for arg %d of operation '%s'\n",
833
                                    ct_str, i, def->name);
834
                            exit(1);
835
                        }
836
                    }
837
                }
838
            }
839
        }
840

    
841
        /* sort the constraints (XXX: this is just an heuristic) */
842
        sort_constraints(def, 0, def->nb_oargs);
843
        sort_constraints(def, def->nb_oargs, def->nb_iargs);
844

    
845
#if 0
846
        {
847
            int i;
848

849
            printf("%s: sorted=", def->name);
850
            for(i = 0; i < def->nb_oargs + def->nb_iargs; i++)
851
                printf(" %d", def->sorted_args[i]);
852
            printf("\n");
853
        }
854
#endif
855
        tdefs++;
856
    }
857

    
858
}
859

    
860
#ifdef USE_LIVENESS_ANALYSIS
861

    
862
/* set a nop for an operation using 'nb_args' */
863
static inline void tcg_set_nop(TCGContext *s, uint16_t *opc_ptr, 
864
                               TCGArg *args, int nb_args)
865
{
866
    if (nb_args == 0) {
867
        *opc_ptr = INDEX_op_nop;
868
    } else {
869
        *opc_ptr = INDEX_op_nopn;
870
        args[0] = nb_args;
871
        args[nb_args - 1] = nb_args;
872
    }
873
}
874

    
875
/* liveness analysis: end of basic block: globals are live, temps are dead */
876
static inline void tcg_la_bb_end(TCGContext *s, uint8_t *dead_temps)
877
{
878
    memset(dead_temps, 0, s->nb_globals);
879
    memset(dead_temps + s->nb_globals, 1, s->nb_temps - s->nb_globals);
880
}
881

    
882
/* Liveness analysis : update the opc_dead_iargs array to tell if a
883
   given input arguments is dead. Instructions updating dead
884
   temporaries are removed. */
885
void tcg_liveness_analysis(TCGContext *s)
886
{
887
    int i, op_index, op, nb_args, nb_iargs, nb_oargs, arg, nb_ops;
888
    TCGArg *args;
889
    const TCGOpDef *def;
890
    uint8_t *dead_temps;
891
    unsigned int dead_iargs;
892
    
893
    gen_opc_ptr++; /* skip end */
894

    
895
    nb_ops = gen_opc_ptr - gen_opc_buf;
896

    
897
    /* XXX: make it really dynamic */
898
    s->op_dead_iargs = tcg_malloc(OPC_BUF_SIZE * sizeof(uint16_t));
899
    
900
    dead_temps = tcg_malloc(s->nb_temps);
901
    memset(dead_temps, 1, s->nb_temps);
902

    
903
    args = gen_opparam_ptr;
904
    op_index = nb_ops - 1;
905
    while (op_index >= 0) {
906
        op = gen_opc_buf[op_index];
907
        def = &tcg_op_defs[op];
908
        switch(op) {
909
        case INDEX_op_call:
910
            nb_args = args[-1];
911
            args -= nb_args;
912
            nb_iargs = args[0] & 0xffff;
913
            nb_oargs = args[0] >> 16;
914
            args++;
915

    
916
            /* output args are dead */
917
            for(i = 0; i < nb_oargs; i++) {
918
                arg = args[i];
919
                dead_temps[arg] = 1;
920
            }
921
            
922
            /* globals are live (they may be used by the call) */
923
            memset(dead_temps, 0, s->nb_globals);
924

    
925
            /* input args are live */
926
            dead_iargs = 0;
927
            for(i = 0; i < nb_iargs; i++) {
928
                arg = args[i + nb_oargs];
929
                if (dead_temps[arg]) {
930
                    dead_iargs |= (1 << i);
931
                }
932
                dead_temps[arg] = 0;
933
            }
934
            s->op_dead_iargs[op_index] = dead_iargs;
935
            args--;
936
            break;
937
        case INDEX_op_set_label:
938
            args--;
939
            /* mark end of basic block */
940
            tcg_la_bb_end(s, dead_temps);
941
            break;
942
        case INDEX_op_nopn:
943
            nb_args = args[-1];
944
            args -= nb_args;
945
            break;
946
        case INDEX_op_discard:
947
            args--;
948
            /* mark the temporary as dead */
949
            dead_temps[args[0]] = 1;
950
            break;
951
        case INDEX_op_macro_2:
952
            {
953
                int dead_args[2], macro_id;
954
                int saved_op_index, saved_arg_index;
955
                int macro_op_index, macro_arg_index;
956
                int macro_end_op_index, macro_end_arg_index;
957
                int last_nb_temps;
958
                
959
                nb_args = 3;
960
                args -= nb_args;
961
                dead_args[0] = dead_temps[args[0]];
962
                dead_args[1] = dead_temps[args[1]];
963
                macro_id = args[2];
964

    
965
                /* call the macro function which generate code
966
                   depending on the live outputs */
967
                saved_op_index = op_index;
968
                saved_arg_index = args - gen_opparam_buf;
969

    
970
                /* add a macro start instruction */
971
                *gen_opc_ptr++ = INDEX_op_macro_start;
972
                *gen_opparam_ptr++ = saved_op_index;
973
                *gen_opparam_ptr++ = saved_arg_index;
974

    
975
                macro_op_index = gen_opc_ptr - gen_opc_buf;
976
                macro_arg_index = gen_opparam_ptr -  gen_opparam_buf;
977

    
978
                last_nb_temps = s->nb_temps;
979

    
980
                s->macro_func(s, macro_id, dead_args);
981

    
982
                /* realloc temp info (XXX: make it faster) */
983
                if (s->nb_temps > last_nb_temps) {
984
                    uint8_t *new_dead_temps;
985

    
986
                    new_dead_temps = tcg_malloc(s->nb_temps);
987
                    memcpy(new_dead_temps, dead_temps, last_nb_temps);
988
                    memset(new_dead_temps + last_nb_temps, 1, 
989
                           s->nb_temps - last_nb_temps);
990
                    dead_temps = new_dead_temps;
991
                }
992

    
993
                macro_end_op_index = gen_opc_ptr - gen_opc_buf;
994
                macro_end_arg_index = gen_opparam_ptr - gen_opparam_buf;
995

    
996
                /* end of macro: add a goto to the next instruction */
997
                *gen_opc_ptr++ = INDEX_op_macro_end;
998
                *gen_opparam_ptr++ = op_index + 1;
999
                *gen_opparam_ptr++ = saved_arg_index + nb_args;
1000

    
1001
                /* modify the macro operation to be a macro_goto */
1002
                gen_opc_buf[op_index] = INDEX_op_macro_goto;
1003
                args[0] = macro_op_index;
1004
                args[1] = macro_arg_index;
1005
                args[2] = 0; /* dummy third arg to match the 
1006
                                macro parameters */
1007

    
1008
                /* set the next instruction to the end of the macro */
1009
                op_index = macro_end_op_index;
1010
                args = macro_end_arg_index + gen_opparam_buf;
1011
            }
1012
            break;
1013
        case INDEX_op_macro_start:
1014
            args -= 2;
1015
            op_index = args[0];
1016
            args = gen_opparam_buf + args[1];
1017
            break;
1018
        case INDEX_op_macro_goto:
1019
        case INDEX_op_macro_end:
1020
            tcg_abort(); /* should never happen in liveness analysis */
1021
        case INDEX_op_end:
1022
            break;
1023
            /* XXX: optimize by hardcoding common cases (e.g. triadic ops) */
1024
        default:
1025
            if (op > INDEX_op_end) {
1026
                args -= def->nb_args;
1027
                nb_iargs = def->nb_iargs;
1028
                nb_oargs = def->nb_oargs;
1029

    
1030
                /* Test if the operation can be removed because all
1031
                   its outputs are dead. We assume that nb_oargs == 0
1032
                   implies side effects */
1033
                if (!(def->flags & TCG_OPF_SIDE_EFFECTS) && nb_oargs != 0) {
1034
                    for(i = 0; i < nb_oargs; i++) {
1035
                        arg = args[i];
1036
                        if (!dead_temps[arg])
1037
                            goto do_not_remove;
1038
                    }
1039
                    tcg_set_nop(s, gen_opc_buf + op_index, args, def->nb_args);
1040
#ifdef CONFIG_PROFILER
1041
                    {
1042
                        extern int64_t dyngen_tcg_del_op_count;
1043
                        dyngen_tcg_del_op_count++;
1044
                    }
1045
#endif
1046
                } else {
1047
                do_not_remove:
1048

    
1049
                    /* output args are dead */
1050
                    for(i = 0; i < nb_oargs; i++) {
1051
                        arg = args[i];
1052
                        dead_temps[arg] = 1;
1053
                    }
1054
                    
1055
                    /* if end of basic block, update */
1056
                    if (def->flags & TCG_OPF_BB_END) {
1057
                        tcg_la_bb_end(s, dead_temps);
1058
                    } else if (def->flags & TCG_OPF_CALL_CLOBBER) {
1059
                        /* globals are live */
1060
                        memset(dead_temps, 0, s->nb_globals);
1061
                    }
1062
                    
1063
                    /* input args are live */
1064
                    dead_iargs = 0;
1065
                    for(i = 0; i < nb_iargs; i++) {
1066
                        arg = args[i + nb_oargs];
1067
                        if (dead_temps[arg]) {
1068
                            dead_iargs |= (1 << i);
1069
                        }
1070
                        dead_temps[arg] = 0;
1071
                    }
1072
                    s->op_dead_iargs[op_index] = dead_iargs;
1073
                }
1074
            } else {
1075
                /* legacy dyngen operations */
1076
                args -= def->nb_args;
1077
                /* mark end of basic block */
1078
                tcg_la_bb_end(s, dead_temps);
1079
            }
1080
            break;
1081
        }
1082
        op_index--;
1083
    }
1084

    
1085
    if (args != gen_opparam_buf)
1086
        tcg_abort();
1087
}
1088
#else
1089
/* dummy liveness analysis */
1090
void tcg_liveness_analysis(TCGContext *s)
1091
{
1092
    int nb_ops;
1093
    nb_ops = gen_opc_ptr - gen_opc_buf;
1094

    
1095
    s->op_dead_iargs = tcg_malloc(nb_ops * sizeof(uint16_t));
1096
    memset(s->op_dead_iargs, 0, nb_ops * sizeof(uint16_t));
1097
}
1098
#endif
1099

    
1100
#ifndef NDEBUG
1101
static void dump_regs(TCGContext *s)
1102
{
1103
    TCGTemp *ts;
1104
    int i;
1105
    char buf[64];
1106

    
1107
    for(i = 0; i < s->nb_temps; i++) {
1108
        ts = &s->temps[i];
1109
        printf("  %10s: ", tcg_get_arg_str_idx(s, buf, sizeof(buf), i));
1110
        switch(ts->val_type) {
1111
        case TEMP_VAL_REG:
1112
            printf("%s", tcg_target_reg_names[ts->reg]);
1113
            break;
1114
        case TEMP_VAL_MEM:
1115
            printf("%d(%s)", (int)ts->mem_offset, tcg_target_reg_names[ts->mem_reg]);
1116
            break;
1117
        case TEMP_VAL_CONST:
1118
            printf("$0x%" TCG_PRIlx, ts->val);
1119
            break;
1120
        case TEMP_VAL_DEAD:
1121
            printf("D");
1122
            break;
1123
        default:
1124
            printf("???");
1125
            break;
1126
        }
1127
        printf("\n");
1128
    }
1129

    
1130
    for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
1131
        if (s->reg_to_temp[i] >= 0) {
1132
            printf("%s: %s\n", 
1133
                   tcg_target_reg_names[i], 
1134
                   tcg_get_arg_str_idx(s, buf, sizeof(buf), s->reg_to_temp[i]));
1135
        }
1136
    }
1137
}
1138

    
1139
static void check_regs(TCGContext *s)
1140
{
1141
    int reg, k;
1142
    TCGTemp *ts;
1143
    char buf[64];
1144

    
1145
    for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1146
        k = s->reg_to_temp[reg];
1147
        if (k >= 0) {
1148
            ts = &s->temps[k];
1149
            if (ts->val_type != TEMP_VAL_REG ||
1150
                ts->reg != reg) {
1151
                printf("Inconsistency for register %s:\n", 
1152
                       tcg_target_reg_names[reg]);
1153
                goto fail;
1154
            }
1155
        }
1156
    }
1157
    for(k = 0; k < s->nb_temps; k++) {
1158
        ts = &s->temps[k];
1159
        if (ts->val_type == TEMP_VAL_REG &&
1160
            !ts->fixed_reg &&
1161
            s->reg_to_temp[ts->reg] != k) {
1162
                printf("Inconsistency for temp %s:\n", 
1163
                       tcg_get_arg_str_idx(s, buf, sizeof(buf), k));
1164
        fail:
1165
                printf("reg state:\n");
1166
                dump_regs(s);
1167
                tcg_abort();
1168
        }
1169
        if (ts->val_type == TEMP_VAL_CONST && k < s->nb_globals) {
1170
            printf("constant forbidden in global %s\n",
1171
                   tcg_get_arg_str_idx(s, buf, sizeof(buf), k));
1172
            goto fail;
1173
        }
1174
    }
1175
}
1176
#endif
1177

    
1178
static void temp_allocate_frame(TCGContext *s, int temp)
1179
{
1180
    TCGTemp *ts;
1181
    ts = &s->temps[temp];
1182
    s->current_frame_offset = (s->current_frame_offset + sizeof(tcg_target_long) - 1) & ~(sizeof(tcg_target_long) - 1);
1183
    if (s->current_frame_offset + sizeof(tcg_target_long) > s->frame_end)
1184
        tcg_abort();
1185
    ts->mem_offset = s->current_frame_offset;
1186
    ts->mem_reg = s->frame_reg;
1187
    ts->mem_allocated = 1;
1188
    s->current_frame_offset += sizeof(tcg_target_long);
1189
}
1190

    
1191
/* free register 'reg' by spilling the corresponding temporary if necessary */
1192
static void tcg_reg_free(TCGContext *s, int reg)
1193
{
1194
    TCGTemp *ts;
1195
    int temp;
1196

    
1197
    temp = s->reg_to_temp[reg];
1198
    if (temp != -1) {
1199
        ts = &s->temps[temp];
1200
        assert(ts->val_type == TEMP_VAL_REG);
1201
        if (!ts->mem_coherent) {
1202
            if (!ts->mem_allocated) 
1203
                temp_allocate_frame(s, temp);
1204
            tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1205
        }
1206
        ts->val_type = TEMP_VAL_MEM;
1207
        s->reg_to_temp[reg] = -1;
1208
    }
1209
}
1210

    
1211
/* Allocate a register belonging to reg1 & ~reg2 */
1212
static int tcg_reg_alloc(TCGContext *s, TCGRegSet reg1, TCGRegSet reg2)
1213
{
1214
    int i, reg;
1215
    TCGRegSet reg_ct;
1216

    
1217
    tcg_regset_andnot(reg_ct, reg1, reg2);
1218

    
1219
    /* first try free registers */
1220
    for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1221
        reg = tcg_target_reg_alloc_order[i];
1222
        if (tcg_regset_test_reg(reg_ct, reg) && s->reg_to_temp[reg] == -1)
1223
            return reg;
1224
    }
1225

    
1226
    /* XXX: do better spill choice */
1227
    for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1228
        reg = tcg_target_reg_alloc_order[i];
1229
        if (tcg_regset_test_reg(reg_ct, reg)) {
1230
            tcg_reg_free(s, reg);
1231
            return reg;
1232
        }
1233
    }
1234

    
1235
    tcg_abort();
1236
}
1237

    
1238
/* at the end of a basic block, we assume all temporaries are dead and
1239
   all globals are stored at their canonical location */
1240
/* XXX: optimize by handling constants in another array ? */
1241
void tcg_reg_alloc_bb_end(TCGContext *s)
1242
{
1243
    TCGTemp *ts;
1244
    int i;
1245

    
1246
    for(i = 0; i < s->nb_globals; i++) {
1247
        ts = &s->temps[i];
1248
        if (!ts->fixed_reg) {
1249
            if (ts->val_type == TEMP_VAL_REG) {
1250
                tcg_reg_free(s, ts->reg);
1251
            }
1252
        }
1253
    }
1254

    
1255
    for(i = s->nb_globals; i < s->nb_temps; i++) {
1256
        ts = &s->temps[i];
1257
        if (ts->val_type != TEMP_VAL_CONST) {
1258
            if (ts->val_type == TEMP_VAL_REG) {
1259
                s->reg_to_temp[ts->reg] = -1;
1260
            }
1261
            ts->val_type = TEMP_VAL_DEAD;
1262
        }
1263
    }
1264
}
1265

    
1266
#define IS_DEAD_IARG(n) ((dead_iargs >> (n)) & 1)
1267

    
1268
static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
1269
                              const TCGArg *args,
1270
                              unsigned int dead_iargs)
1271
{
1272
    TCGTemp *ts, *ots;
1273
    int reg;
1274
    const TCGArgConstraint *arg_ct;
1275

    
1276
    ots = &s->temps[args[0]];
1277
    ts = &s->temps[args[1]];
1278
    arg_ct = &def->args_ct[0];
1279

    
1280
    if (ts->val_type == TEMP_VAL_REG) {
1281
        if (IS_DEAD_IARG(0) && !ts->fixed_reg && !ots->fixed_reg) {
1282
            /* the mov can be suppressed */
1283
            if (ots->val_type == TEMP_VAL_REG)
1284
                s->reg_to_temp[ots->reg] = -1;
1285
            reg = ts->reg;
1286
            s->reg_to_temp[reg] = -1;
1287
            ts->val_type = TEMP_VAL_DEAD;
1288
        } else {
1289
            if (ots->val_type == TEMP_VAL_REG) {
1290
                reg = ots->reg;
1291
            } else {
1292
                reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1293
            }
1294
            if (ts->reg != reg) {
1295
                tcg_out_mov(s, reg, ts->reg);
1296
            }
1297
        }
1298
    } else if (ts->val_type == TEMP_VAL_MEM) {
1299
        if (ots->val_type == TEMP_VAL_REG) {
1300
            reg = ots->reg;
1301
        } else {
1302
            reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1303
        }
1304
        tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1305
    } else if (ts->val_type == TEMP_VAL_CONST) {
1306
        if (ots->val_type == TEMP_VAL_REG) {
1307
            reg = ots->reg;
1308
        } else {
1309
            reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1310
        }
1311
        tcg_out_movi(s, ots->type, reg, ts->val);
1312
    } else {
1313
        tcg_abort();
1314
    }
1315
    s->reg_to_temp[reg] = args[0];
1316
    ots->reg = reg;
1317
    ots->val_type = TEMP_VAL_REG;
1318
    ots->mem_coherent = 0;
1319
}
1320

    
1321
static void tcg_reg_alloc_op(TCGContext *s, 
1322
                             const TCGOpDef *def, int opc,
1323
                             const TCGArg *args,
1324
                             unsigned int dead_iargs)
1325
{
1326
    TCGRegSet allocated_regs;
1327
    int i, k, nb_iargs, nb_oargs, reg;
1328
    TCGArg arg;
1329
    const TCGArgConstraint *arg_ct;
1330
    TCGTemp *ts;
1331
    TCGArg new_args[TCG_MAX_OP_ARGS];
1332
    int const_args[TCG_MAX_OP_ARGS];
1333

    
1334
    nb_oargs = def->nb_oargs;
1335
    nb_iargs = def->nb_iargs;
1336

    
1337
    /* copy constants */
1338
    memcpy(new_args + nb_oargs + nb_iargs, 
1339
           args + nb_oargs + nb_iargs, 
1340
           sizeof(TCGArg) * def->nb_cargs);
1341

    
1342
    /* satisfy input constraints */ 
1343
    tcg_regset_set(allocated_regs, s->reserved_regs);
1344
    for(k = 0; k < nb_iargs; k++) {
1345
        i = def->sorted_args[nb_oargs + k];
1346
        arg = args[i];
1347
        arg_ct = &def->args_ct[i];
1348
        ts = &s->temps[arg];
1349
        if (ts->val_type == TEMP_VAL_MEM) {
1350
            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1351
            tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1352
            ts->val_type = TEMP_VAL_REG;
1353
            ts->reg = reg;
1354
            ts->mem_coherent = 1;
1355
            s->reg_to_temp[reg] = arg;
1356
        } else if (ts->val_type == TEMP_VAL_CONST) {
1357
            if (tcg_target_const_match(ts->val, arg_ct)) {
1358
                /* constant is OK for instruction */
1359
                const_args[i] = 1;
1360
                new_args[i] = ts->val;
1361
                goto iarg_end;
1362
            } else {
1363
                /* need to move to a register*/
1364
                reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1365
                tcg_out_movi(s, ts->type, reg, ts->val);
1366
                goto iarg_end1;
1367
            }
1368
        }
1369
        assert(ts->val_type == TEMP_VAL_REG);
1370
        if (arg_ct->ct & TCG_CT_IALIAS) {
1371
            if (ts->fixed_reg) {
1372
                /* if fixed register, we must allocate a new register
1373
                   if the alias is not the same register */
1374
                if (arg != args[arg_ct->alias_index])
1375
                    goto allocate_in_reg;
1376
            } else {
1377
                /* if the input is aliased to an output and if it is
1378
                   not dead after the instruction, we must allocate
1379
                   a new register and move it */
1380
                if (!IS_DEAD_IARG(i - nb_oargs)) 
1381
                    goto allocate_in_reg;
1382
            }
1383
        }
1384
        reg = ts->reg;
1385
        if (tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1386
            /* nothing to do : the constraint is satisfied */
1387
        } else {
1388
        allocate_in_reg:
1389
            /* allocate a new register matching the constraint 
1390
               and move the temporary register into it */
1391
            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1392
            tcg_out_mov(s, reg, ts->reg);
1393
        }
1394
    iarg_end1:
1395
        new_args[i] = reg;
1396
        const_args[i] = 0;
1397
        tcg_regset_set_reg(allocated_regs, reg);
1398
    iarg_end: ;
1399
    }
1400
    
1401
    /* mark dead temporaries and free the associated registers */
1402
    for(i = 0; i < nb_iargs; i++) {
1403
        arg = args[nb_oargs + i];
1404
        if (IS_DEAD_IARG(i)) {
1405
            ts = &s->temps[arg];
1406
            if (ts->val_type != TEMP_VAL_CONST && !ts->fixed_reg) {
1407
                if (ts->val_type == TEMP_VAL_REG)
1408
                    s->reg_to_temp[ts->reg] = -1;
1409
                ts->val_type = TEMP_VAL_DEAD;
1410
            }
1411
        }
1412
    }
1413

    
1414
    if (def->flags & TCG_OPF_CALL_CLOBBER) {
1415
        /* XXX: permit generic clobber register list ? */ 
1416
        for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1417
            if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
1418
                tcg_reg_free(s, reg);
1419
            }
1420
        }
1421
        /* XXX: for load/store we could do that only for the slow path
1422
           (i.e. when a memory callback is called) */
1423

    
1424
        /* store globals and free associated registers (we assume the insn
1425
           can modify any global. */
1426
        for(i = 0; i < s->nb_globals; i++) {
1427
            ts = &s->temps[i];
1428
            if (!ts->fixed_reg) {
1429
                if (ts->val_type == TEMP_VAL_REG) {
1430
                    tcg_reg_free(s, ts->reg);
1431
                }
1432
            }
1433
        }
1434
    }
1435

    
1436
    /* satisfy the output constraints */
1437
    tcg_regset_set(allocated_regs, s->reserved_regs);
1438
    for(k = 0; k < nb_oargs; k++) {
1439
        i = def->sorted_args[k];
1440
        arg = args[i];
1441
        arg_ct = &def->args_ct[i];
1442
        ts = &s->temps[arg];
1443
        if (arg_ct->ct & TCG_CT_ALIAS) {
1444
            reg = new_args[arg_ct->alias_index];
1445
        } else {
1446
            /* if fixed register, we try to use it */
1447
            reg = ts->reg;
1448
            if (ts->fixed_reg &&
1449
                tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1450
                goto oarg_end;
1451
            }
1452
            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1453
        }
1454
        tcg_regset_set_reg(allocated_regs, reg);
1455
        /* if a fixed register is used, then a move will be done afterwards */
1456
        if (!ts->fixed_reg) {
1457
            if (ts->val_type == TEMP_VAL_REG)
1458
                s->reg_to_temp[ts->reg] = -1;
1459
            ts->val_type = TEMP_VAL_REG;
1460
            ts->reg = reg;
1461
            /* temp value is modified, so the value kept in memory is
1462
               potentially not the same */
1463
            ts->mem_coherent = 0; 
1464
            s->reg_to_temp[reg] = arg;
1465
        }
1466
    oarg_end:
1467
        new_args[i] = reg;
1468
    }
1469

    
1470
    if (def->flags & TCG_OPF_BB_END)
1471
        tcg_reg_alloc_bb_end(s);
1472

    
1473
    /* emit instruction */
1474
    tcg_out_op(s, opc, new_args, const_args);
1475
    
1476
    /* move the outputs in the correct register if needed */
1477
    for(i = 0; i < nb_oargs; i++) {
1478
        ts = &s->temps[args[i]];
1479
        reg = new_args[i];
1480
        if (ts->fixed_reg && ts->reg != reg) {
1481
            tcg_out_mov(s, ts->reg, reg);
1482
        }
1483
    }
1484
}
1485

    
1486
#ifdef TCG_TARGET_STACK_GROWSUP
1487
#define STACK_DIR(x) (-(x))
1488
#else
1489
#define STACK_DIR(x) (x)
1490
#endif
1491

    
1492
static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
1493
                              int opc, const TCGArg *args,
1494
                              unsigned int dead_iargs)
1495
{
1496
    int nb_iargs, nb_oargs, flags, nb_regs, i, reg, nb_params;
1497
    TCGArg arg, func_arg;
1498
    TCGTemp *ts;
1499
    tcg_target_long stack_offset, call_stack_size, func_addr;
1500
    int const_func_arg, allocate_args;
1501
    TCGRegSet allocated_regs;
1502
    const TCGArgConstraint *arg_ct;
1503

    
1504
    arg = *args++;
1505

    
1506
    nb_oargs = arg >> 16;
1507
    nb_iargs = arg & 0xffff;
1508
    nb_params = nb_iargs - 1;
1509

    
1510
    flags = args[nb_oargs + nb_iargs];
1511

    
1512
    nb_regs = tcg_target_get_call_iarg_regs_count(flags);
1513
    if (nb_regs > nb_params)
1514
        nb_regs = nb_params;
1515

    
1516
    /* assign stack slots first */
1517
    /* XXX: preallocate call stack */
1518
    call_stack_size = (nb_params - nb_regs) * sizeof(tcg_target_long);
1519
    call_stack_size = (call_stack_size + TCG_TARGET_STACK_ALIGN - 1) & 
1520
        ~(TCG_TARGET_STACK_ALIGN - 1);
1521
    allocate_args = (call_stack_size > TCG_STATIC_CALL_ARGS_SIZE);
1522
    if (allocate_args) {
1523
        tcg_out_addi(s, TCG_REG_CALL_STACK, -STACK_DIR(call_stack_size));
1524
    }
1525
    /* XXX: on some architectures it does not start at zero */
1526
    stack_offset = 0;
1527
    for(i = nb_regs; i < nb_params; i++) {
1528
        arg = args[nb_oargs + i];
1529
        ts = &s->temps[arg];
1530
        if (ts->val_type == TEMP_VAL_REG) {
1531
            tcg_out_st(s, ts->type, ts->reg, TCG_REG_CALL_STACK, stack_offset);
1532
        } else if (ts->val_type == TEMP_VAL_MEM) {
1533
            reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], 
1534
                                s->reserved_regs);
1535
            /* XXX: not correct if reading values from the stack */
1536
            tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1537
            tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
1538
        } else if (ts->val_type == TEMP_VAL_CONST) {
1539
            reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], 
1540
                                s->reserved_regs);
1541
            /* XXX: sign extend may be needed on some targets */
1542
            tcg_out_movi(s, ts->type, reg, ts->val);
1543
            tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
1544
        } else {
1545
            tcg_abort();
1546
        }
1547
        /* XXX: not necessarily in the same order */
1548
        stack_offset += STACK_DIR(sizeof(tcg_target_long));
1549
    }
1550
    
1551
    /* assign input registers */
1552
    tcg_regset_set(allocated_regs, s->reserved_regs);
1553
    for(i = 0; i < nb_regs; i++) {
1554
        arg = args[nb_oargs + i];
1555
        ts = &s->temps[arg];
1556
        reg = tcg_target_call_iarg_regs[i];
1557
        tcg_reg_free(s, reg);
1558
        if (ts->val_type == TEMP_VAL_REG) {
1559
            if (ts->reg != reg) {
1560
                tcg_out_mov(s, reg, ts->reg);
1561
            }
1562
        } else if (ts->val_type == TEMP_VAL_MEM) {
1563
            tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1564
        } else if (ts->val_type == TEMP_VAL_CONST) {
1565
            /* XXX: sign extend ? */
1566
            tcg_out_movi(s, ts->type, reg, ts->val);
1567
        } else {
1568
            tcg_abort();
1569
        }
1570
        tcg_regset_set_reg(allocated_regs, reg);
1571
    }
1572
    
1573
    /* assign function address */
1574
    func_arg = args[nb_oargs + nb_iargs - 1];
1575
    arg_ct = &def->args_ct[0];
1576
    ts = &s->temps[func_arg];
1577
    func_addr = ts->val;
1578
    const_func_arg = 0;
1579
    if (ts->val_type == TEMP_VAL_MEM) {
1580
        reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1581
        tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1582
        func_arg = reg;
1583
    } else if (ts->val_type == TEMP_VAL_REG) {
1584
        reg = ts->reg;
1585
        if (!tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1586
            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1587
            tcg_out_mov(s, reg, ts->reg);
1588
        }
1589
        func_arg = reg;
1590
    } else if (ts->val_type == TEMP_VAL_CONST) {
1591
        if (tcg_target_const_match(func_addr, arg_ct)) {
1592
            const_func_arg = 1;
1593
            func_arg = func_addr;
1594
        } else {
1595
            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1596
            tcg_out_movi(s, ts->type, reg, func_addr);
1597
            func_arg = reg;
1598
        }
1599
    } else {
1600
        tcg_abort();
1601
    }
1602
    
1603
    /* mark dead temporaries and free the associated registers */
1604
    for(i = 0; i < nb_params; i++) {
1605
        arg = args[nb_oargs + i];
1606
        if (IS_DEAD_IARG(i)) {
1607
            ts = &s->temps[arg];
1608
            if (ts->val_type != TEMP_VAL_CONST && !ts->fixed_reg) {
1609
                if (ts->val_type == TEMP_VAL_REG)
1610
                    s->reg_to_temp[ts->reg] = -1;
1611
                ts->val_type = TEMP_VAL_DEAD;
1612
            }
1613
        }
1614
    }
1615
    
1616
    /* clobber call registers */
1617
    for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1618
        if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
1619
            tcg_reg_free(s, reg);
1620
        }
1621
    }
1622
    
1623
    /* store globals and free associated registers (we assume the call
1624
       can modify any global. */
1625
    for(i = 0; i < s->nb_globals; i++) {
1626
        ts = &s->temps[i];
1627
        if (!ts->fixed_reg) {
1628
            if (ts->val_type == TEMP_VAL_REG) {
1629
                tcg_reg_free(s, ts->reg);
1630
            }
1631
        }
1632
    }
1633

    
1634
    tcg_out_op(s, opc, &func_arg, &const_func_arg);
1635
    
1636
    if (allocate_args) {
1637
        tcg_out_addi(s, TCG_REG_CALL_STACK, STACK_DIR(call_stack_size));
1638
    }
1639

    
1640
    /* assign output registers and emit moves if needed */
1641
    for(i = 0; i < nb_oargs; i++) {
1642
        arg = args[i];
1643
        ts = &s->temps[arg];
1644
        reg = tcg_target_call_oarg_regs[i];
1645
        tcg_reg_free(s, reg);
1646
        if (ts->fixed_reg) {
1647
            if (ts->reg != reg) {
1648
                tcg_out_mov(s, ts->reg, reg);
1649
            }
1650
        } else {
1651
            if (ts->val_type == TEMP_VAL_REG)
1652
                s->reg_to_temp[ts->reg] = -1;
1653
            ts->val_type = TEMP_VAL_REG;
1654
            ts->reg = reg;
1655
            ts->mem_coherent = 0; 
1656
            s->reg_to_temp[reg] = arg;
1657
        }
1658
    }
1659
    
1660
    return nb_iargs + nb_oargs + def->nb_cargs + 1;
1661
}
1662

    
1663
#ifdef CONFIG_PROFILER
1664

    
1665
static int64_t dyngen_table_op_count[NB_OPS];
1666

    
1667
void dump_op_count(void)
1668
{
1669
    int i;
1670
    FILE *f;
1671
    f = fopen("/tmp/op1.log", "w");
1672
    for(i = 0; i < INDEX_op_end; i++) {
1673
        fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name, dyngen_table_op_count[i]);
1674
    }
1675
    fclose(f);
1676
    f = fopen("/tmp/op2.log", "w");
1677
    for(i = INDEX_op_end; i < NB_OPS; i++) {
1678
        fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name, dyngen_table_op_count[i]);
1679
    }
1680
    fclose(f);
1681
}
1682
#endif
1683

    
1684

    
1685
static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
1686
                                      long search_pc)
1687
{
1688
    int opc, op_index, macro_op_index;
1689
    const TCGOpDef *def;
1690
    unsigned int dead_iargs;
1691
    const TCGArg *args;
1692

    
1693
#ifdef DEBUG_DISAS
1694
    if (unlikely(loglevel & CPU_LOG_TB_OP)) {
1695
        fprintf(logfile, "OP:\n");
1696
        tcg_dump_ops(s, logfile);
1697
        fprintf(logfile, "\n");
1698
    }
1699
#endif
1700

    
1701
    tcg_liveness_analysis(s);
1702

    
1703
#ifdef DEBUG_DISAS
1704
    if (unlikely(loglevel & CPU_LOG_TB_OP_OPT)) {
1705
        fprintf(logfile, "OP after la:\n");
1706
        tcg_dump_ops(s, logfile);
1707
        fprintf(logfile, "\n");
1708
    }
1709
#endif
1710

    
1711
    tcg_reg_alloc_start(s);
1712

    
1713
    s->code_buf = gen_code_buf;
1714
    s->code_ptr = gen_code_buf;
1715

    
1716
    macro_op_index = -1;
1717
    args = gen_opparam_buf;
1718
    op_index = 0;
1719

    
1720
    for(;;) {
1721
        opc = gen_opc_buf[op_index];
1722
#ifdef CONFIG_PROFILER
1723
        dyngen_table_op_count[opc]++;
1724
#endif
1725
        def = &tcg_op_defs[opc];
1726
#if 0
1727
        printf("%s: %d %d %d\n", def->name,
1728
               def->nb_oargs, def->nb_iargs, def->nb_cargs);
1729
        //        dump_regs(s);
1730
#endif
1731
        switch(opc) {
1732
        case INDEX_op_mov_i32:
1733
#if TCG_TARGET_REG_BITS == 64
1734
        case INDEX_op_mov_i64:
1735
#endif
1736
            dead_iargs = s->op_dead_iargs[op_index];
1737
            tcg_reg_alloc_mov(s, def, args, dead_iargs);
1738
            break;
1739
        case INDEX_op_nop:
1740
        case INDEX_op_nop1:
1741
        case INDEX_op_nop2:
1742
        case INDEX_op_nop3:
1743
            break;
1744
        case INDEX_op_nopn:
1745
            args += args[0];
1746
            goto next;
1747
        case INDEX_op_discard:
1748
            {
1749
                TCGTemp *ts;
1750
                ts = &s->temps[args[0]];
1751
                /* mark the temporary as dead */
1752
                if (ts->val_type != TEMP_VAL_CONST && !ts->fixed_reg) {
1753
                    if (ts->val_type == TEMP_VAL_REG)
1754
                        s->reg_to_temp[ts->reg] = -1;
1755
                    ts->val_type = TEMP_VAL_DEAD;
1756
                }
1757
            }
1758
            break;
1759
        case INDEX_op_macro_goto:
1760
            macro_op_index = op_index; /* only used for exceptions */
1761
            op_index = args[0] - 1;
1762
            args = gen_opparam_buf + args[1];
1763
            goto next;
1764
        case INDEX_op_macro_end:
1765
            macro_op_index = -1; /* only used for exceptions */
1766
            op_index = args[0] - 1;
1767
            args = gen_opparam_buf + args[1];
1768
            goto next;
1769
        case INDEX_op_macro_start:
1770
            /* must never happen here */
1771
            tcg_abort();
1772
        case INDEX_op_set_label:
1773
            tcg_reg_alloc_bb_end(s);
1774
            tcg_out_label(s, args[0], (long)s->code_ptr);
1775
            break;
1776
        case INDEX_op_call:
1777
            dead_iargs = s->op_dead_iargs[op_index];
1778
            args += tcg_reg_alloc_call(s, def, opc, args, dead_iargs);
1779
            goto next;
1780
        case INDEX_op_end:
1781
            goto the_end;
1782

    
1783
#ifndef CONFIG_NO_DYNGEN_OP
1784
        case 0 ... INDEX_op_end - 1:
1785
            /* legacy dyngen ops */
1786
#ifdef CONFIG_PROFILER
1787
            {
1788
                extern int64_t dyngen_old_op_count;
1789
                dyngen_old_op_count++;
1790
            }
1791
#endif
1792
            tcg_reg_alloc_bb_end(s);
1793
            if (search_pc >= 0) {
1794
                s->code_ptr += def->copy_size;
1795
                args += def->nb_args;
1796
            } else {
1797
                args = dyngen_op(s, opc, args);
1798
            }
1799
            goto next;
1800
#endif
1801
        default:
1802
            /* Note: in order to speed up the code, it would be much
1803
               faster to have specialized register allocator functions for
1804
               some common argument patterns */
1805
            dead_iargs = s->op_dead_iargs[op_index];
1806
            tcg_reg_alloc_op(s, def, opc, args, dead_iargs);
1807
            break;
1808
        }
1809
        args += def->nb_args;
1810
    next: ;
1811
        if (search_pc >= 0 && search_pc < s->code_ptr - gen_code_buf) {
1812
            if (macro_op_index >= 0)
1813
                return macro_op_index;
1814
            else
1815
                return op_index;
1816
        }
1817
        op_index++;
1818
#ifndef NDEBUG
1819
        check_regs(s);
1820
#endif
1821
    }
1822
 the_end:
1823
    return -1;
1824
}
1825

    
1826
int dyngen_code(TCGContext *s, uint8_t *gen_code_buf)
1827
{
1828
#ifdef CONFIG_PROFILER
1829
    {
1830
        extern int64_t dyngen_op_count;
1831
        extern int dyngen_op_count_max;
1832
        int n;
1833
        n = (gen_opc_ptr - gen_opc_buf);
1834
        dyngen_op_count += n;
1835
        if (n > dyngen_op_count_max)
1836
            dyngen_op_count_max = n;
1837
    }
1838
#endif
1839

    
1840
    tcg_gen_code_common(s, gen_code_buf, -1);
1841

    
1842
    /* flush instruction cache */
1843
    flush_icache_range((unsigned long)gen_code_buf, 
1844
                       (unsigned long)s->code_ptr);
1845
    return s->code_ptr -  gen_code_buf;
1846
}
1847

    
1848
/* Return the index of the micro operation such as the pc after is <
1849
   offset bytes from the start of the TB.  The contents of gen_code_buf must
1850
   not be changed, though writing the same values is ok.
1851
   Return -1 if not found. */
1852
int dyngen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, long offset)
1853
{
1854
    return tcg_gen_code_common(s, gen_code_buf, offset);
1855
}