Statistics
| Branch: | Revision:

root / tcg / tcg.c @ b3db8758

History | View | Annotate | Download (53.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 "osdep.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);
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
/* XXX: factorize */
151
static void pstrcpy(char *buf, int buf_size, const char *str)
152
{
153
    int c;
154
    char *q = buf;
155

    
156
    if (buf_size <= 0)
157
        return;
158

    
159
    for(;;) {
160
        c = *str++;
161
        if (c == 0 || q >= buf + buf_size - 1)
162
            break;
163
        *q++ = c;
164
    }
165
    *q = '\0';
166
}
167

    
168
#if TCG_TARGET_REG_BITS == 32
169
/* strcat and truncate. */
170
static char *pstrcat(char *buf, int buf_size, const char *s)
171
{
172
    int len;
173
    len = strlen(buf);
174
    if (len < buf_size)
175
        pstrcpy(buf + len, buf_size - len, s);
176
    return buf;
177
}
178
#endif
179

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

    
223
void tcg_pool_reset(TCGContext *s)
224
{
225
    s->pool_cur = s->pool_end = NULL;
226
    s->pool_current = NULL;
227
}
228

    
229
/* free all the pool */
230
void tcg_pool_free(TCGContext *s)
231
{
232
    TCGPool *p, *p1;
233

    
234
    for(p = s->pool_first; p != NULL; p = p1) {
235
        p1 = p->next;
236
        qemu_free(p);
237
    }
238
    s->pool_first = NULL;
239
    s->pool_cur = s->pool_end = NULL;
240
}
241

    
242
void tcg_context_init(TCGContext *s)
243
{
244
    int op, total_args, n;
245
    TCGOpDef *def;
246
    TCGArgConstraint *args_ct;
247
    int *sorted_args;
248

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

    
262
    args_ct = qemu_malloc(sizeof(TCGArgConstraint) * total_args);
263
    sorted_args = qemu_malloc(sizeof(int) * total_args);
264

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

    
277
void tcg_set_frame(TCGContext *s, int reg,
278
                   tcg_target_long start, tcg_target_long size)
279
{
280
    s->frame_start = start;
281
    s->frame_end = start + size;
282
    s->frame_reg = reg;
283
}
284

    
285
void tcg_set_macro_func(TCGContext *s, TCGMacroFunc *func)
286
{
287
    s->macro_func = func;
288
}
289

    
290
void tcg_func_start(TCGContext *s)
291
{
292
    tcg_pool_reset(s);
293
    s->nb_temps = s->nb_globals;
294
    s->labels = tcg_malloc(sizeof(TCGLabel) * TCG_MAX_LABELS);
295
    s->nb_labels = 0;
296
    s->current_frame_offset = s->frame_start;
297

    
298
    gen_opc_ptr = gen_opc_buf;
299
    gen_opparam_ptr = gen_opparam_buf;
300
}
301

    
302
static inline void tcg_temp_alloc(TCGContext *s, int n)
303
{
304
    if (n > TCG_MAX_TEMPS)
305
        tcg_abort();
306
}
307

    
308
TCGv tcg_global_reg_new(TCGType type, int reg, const char *name)
309
{
310
    TCGContext *s = &tcg_ctx;
311
    TCGTemp *ts;
312
    int idx;
313

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

    
334
TCGv tcg_global_mem_new(TCGType type, int reg, tcg_target_long offset,
335
                        const char *name)
336
{
337
    TCGContext *s = &tcg_ctx;
338
    TCGTemp *ts;
339
    int idx;
340

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

    
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;
370
#else
371
        ts->mem_offset = offset + 4;
372
#endif
373
        ts->val_type = TEMP_VAL_MEM;
374
        pstrcpy(buf, sizeof(buf), name);
375
        pstrcat(buf, sizeof(buf), "_1");
376
        ts->name = strdup(buf);
377

    
378
        s->nb_globals += 2;
379
    } else
380
#endif
381
    {
382
        tcg_temp_alloc(s, s->nb_globals + 1);
383
        ts = &s->temps[s->nb_globals];
384
        ts->base_type = type;
385
        ts->type = type;
386
        ts->fixed_reg = 0;
387
        ts->mem_allocated = 1;
388
        ts->mem_reg = reg;
389
        ts->mem_offset = offset;
390
        ts->val_type = TEMP_VAL_MEM;
391
        ts->name = name;
392
        s->nb_globals++;
393
    }
394
    return MAKE_TCGV(idx);
395
}
396

    
397
TCGv tcg_temp_new(TCGType type)
398
{
399
    TCGContext *s = &tcg_ctx;
400
    TCGTemp *ts;
401
    int idx;
402

    
403
    idx = s->nb_temps;
404
#if TCG_TARGET_REG_BITS == 32
405
    if (type == TCG_TYPE_I64) {
406
        tcg_temp_alloc(s, s->nb_temps + 1);
407
        ts = &s->temps[s->nb_temps];
408
        ts->base_type = type;
409
        ts->type = TCG_TYPE_I32;
410
        ts->fixed_reg = 0;
411
        ts->val_type = TEMP_VAL_DEAD;
412
        ts->mem_allocated = 0;
413
        ts->name = NULL;
414
        ts++;
415
        ts->base_type = TCG_TYPE_I32;
416
        ts->type = TCG_TYPE_I32;
417
        ts->val_type = TEMP_VAL_DEAD;
418
        ts->fixed_reg = 0;
419
        ts->mem_allocated = 0;
420
        ts->name = NULL;
421
        s->nb_temps += 2;
422
    } else
423
#endif
424
    {
425
        tcg_temp_alloc(s, s->nb_temps + 1);
426
        ts = &s->temps[s->nb_temps];
427
        ts->base_type = type;
428
        ts->type = type;
429
        ts->fixed_reg = 0;
430
        ts->val_type = TEMP_VAL_DEAD;
431
        ts->mem_allocated = 0;
432
        ts->name = NULL;
433
        s->nb_temps++;
434
    }
435
    return MAKE_TCGV(idx);
436
}
437

    
438
TCGv tcg_const_i32(int32_t val)
439
{
440
    TCGContext *s = &tcg_ctx;
441
    TCGTemp *ts;
442
    int idx;
443

    
444
    idx = s->nb_temps;
445
    tcg_temp_alloc(s, idx + 1);
446
    ts = &s->temps[idx];
447
    ts->base_type = ts->type = TCG_TYPE_I32;
448
    ts->val_type = TEMP_VAL_CONST;
449
    ts->name = NULL;
450
    ts->val = val;
451
    s->nb_temps++;
452
    return MAKE_TCGV(idx);
453
}
454

    
455
TCGv tcg_const_i64(int64_t val)
456
{
457
    TCGContext *s = &tcg_ctx;
458
    TCGTemp *ts;
459
    int idx;
460

    
461
    idx = s->nb_temps;
462
#if TCG_TARGET_REG_BITS == 32
463
    tcg_temp_alloc(s, idx + 2);
464
    ts = &s->temps[idx];
465
    ts->base_type = TCG_TYPE_I64;
466
    ts->type = TCG_TYPE_I32;
467
    ts->val_type = TEMP_VAL_CONST;
468
    ts->name = NULL;
469
    ts->val = val;
470
    ts++;
471
    ts->base_type = TCG_TYPE_I32;
472
    ts->type = TCG_TYPE_I32;
473
    ts->val_type = TEMP_VAL_CONST;
474
    ts->name = NULL;
475
    ts->val = val >> 32;
476
    s->nb_temps += 2;
477
#else
478
    tcg_temp_alloc(s, idx + 1);
479
    ts = &s->temps[idx];
480
    ts->base_type = ts->type = TCG_TYPE_I64;
481
    ts->val_type = TEMP_VAL_CONST;
482
    ts->name = NULL;
483
    ts->val = val;
484
    s->nb_temps++;
485
#endif    
486
    return MAKE_TCGV(idx);
487
}
488

    
489
void tcg_register_helper(void *func, const char *name)
490
{
491
    TCGContext *s = &tcg_ctx;
492
    int n;
493
    if ((s->nb_helpers + 1) > s->allocated_helpers) {
494
        n = s->allocated_helpers;
495
        if (n == 0) {
496
            n = 4;
497
        } else {
498
            n *= 2;
499
        }
500
        s->helpers = realloc(s->helpers, n * sizeof(TCGHelperInfo));
501
        s->allocated_helpers = n;
502
    }
503
    s->helpers[s->nb_helpers].func = func;
504
    s->helpers[s->nb_helpers].name = name;
505
    s->nb_helpers++;
506
}
507

    
508
const char *tcg_helper_get_name(TCGContext *s, void *func)
509
{
510
    int i;
511

    
512
    for(i = 0; i < s->nb_helpers; i++) {
513
        if (s->helpers[i].func == func)
514
            return s->helpers[i].name;
515
    }
516
    return NULL;
517
}
518

    
519
static inline TCGType tcg_get_base_type(TCGContext *s, TCGv arg)
520
{
521
    return s->temps[GET_TCGV(arg)].base_type;
522
}
523

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

    
540
    *gen_opparam_ptr++ = flags;
541
    /* total parameters, needed to go backward in the instruction stream */
542
    *gen_opparam_ptr++ = 1 + nb_rets + nb_params + 3;
543
}
544

    
545

    
546
#if TCG_TARGET_REG_BITS < 64
547
/* Note: we convert the 64 bit args to 32 bit */
548
void tcg_gen_call(TCGContext *s, TCGv func, unsigned int flags,
549
                  unsigned int nb_rets, const TCGv *rets,
550
                  unsigned int nb_params, const TCGv *args1)
551
{
552
    TCGv ret, *args2, rets_2[2], arg;
553
    int j, i, call_type;
554

    
555
    if (nb_rets == 1) {
556
        ret = rets[0];
557
        if (tcg_get_base_type(s, ret) == TCG_TYPE_I64) {
558
            nb_rets = 2;
559
            rets_2[0] = ret;
560
            rets_2[1] = TCGV_HIGH(ret);
561
            rets = rets_2;
562
        }
563
    }
564
    args2 = alloca((nb_params * 2) * sizeof(TCGv));
565
    j = 0;
566
    call_type = (flags & TCG_CALL_TYPE_MASK);
567
    for(i = 0; i < nb_params; i++) {
568
        arg = args1[i];
569
        if (tcg_get_base_type(s, arg) == TCG_TYPE_I64) {
570
#ifdef TCG_TARGET_I386
571
            /* REGPARM case: if the third parameter is 64 bit, it is
572
               allocated on the stack */
573
            if (j == 2 && call_type == TCG_CALL_TYPE_REGPARM) {
574
                call_type = TCG_CALL_TYPE_REGPARM_2;
575
                flags = (flags & ~TCG_CALL_TYPE_MASK) | call_type;
576
            }
577
            args2[j++] = arg;
578
            args2[j++] = TCGV_HIGH(arg);
579
#else
580
#ifdef TCG_TARGET_WORDS_BIGENDIAN
581
            args2[j++] = TCGV_HIGH(arg);
582
            args2[j++] = arg;
583
#else
584
            args2[j++] = arg;
585
            args2[j++] = TCGV_HIGH(arg);
586
#endif
587
#endif
588
        } else {
589
            args2[j++] = arg;
590
        }
591
    }
592
    tcg_gen_call_internal(s, func, flags, 
593
                          nb_rets, rets, j, args2);
594
}
595
#else
596
void tcg_gen_call(TCGContext *s, TCGv func, unsigned int flags,
597
                  unsigned int nb_rets, const TCGv *rets,
598
                  unsigned int nb_params, const TCGv *args1)
599
{
600
    tcg_gen_call_internal(s, func, flags, 
601
                          nb_rets, rets, nb_params, args1);
602
}
603
#endif
604

    
605
#if TCG_TARGET_REG_BITS == 32
606
void tcg_gen_shifti_i64(TCGv ret, TCGv arg1, 
607
                        int c, int right, int arith)
608
{
609
    if (c == 0)
610
        return;
611
    if (c >= 32) {
612
        c -= 32;
613
        if (right) {
614
            if (arith) {
615
                tcg_gen_sari_i32(ret, TCGV_HIGH(arg1), c);
616
                tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 31);
617
            } else {
618
                tcg_gen_shri_i32(ret, TCGV_HIGH(arg1), c);
619
                tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
620
            }
621
        } else {
622
            tcg_gen_shli_i32(TCGV_HIGH(ret), arg1, c);
623
            tcg_gen_movi_i32(ret, 0);
624
        }
625
    } else {
626
        TCGv t0, t1;
627

    
628
        t0 = tcg_temp_new(TCG_TYPE_I32);
629
        t1 = tcg_temp_new(TCG_TYPE_I32);
630
        if (right) {
631
            tcg_gen_shli_i32(t0, TCGV_HIGH(arg1), 32 - c);
632
            if (arith)
633
                tcg_gen_sari_i32(t1, TCGV_HIGH(arg1), c);
634
            else 
635
                tcg_gen_shri_i32(t1, TCGV_HIGH(arg1), c);
636
            tcg_gen_shri_i32(ret, arg1, c); 
637
            tcg_gen_or_i32(ret, ret, t0);
638
            tcg_gen_mov_i32(TCGV_HIGH(ret), t1);
639
        } else {
640
            tcg_gen_shri_i32(t0, arg1, 32 - c);
641
            /* Note: ret can be the same as arg1, so we use t1 */
642
            tcg_gen_shli_i32(t1, arg1, c); 
643
            tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c);
644
            tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t0);
645
            tcg_gen_mov_i32(ret, t1);
646
        }
647
    }
648
}
649
#endif
650

    
651
void tcg_reg_alloc_start(TCGContext *s)
652
{
653
    int i;
654
    TCGTemp *ts;
655
    for(i = 0; i < s->nb_globals; i++) {
656
        ts = &s->temps[i];
657
        if (ts->fixed_reg) {
658
            ts->val_type = TEMP_VAL_REG;
659
        } else {
660
            ts->val_type = TEMP_VAL_MEM;
661
        }
662
    }
663
    for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
664
        s->reg_to_temp[i] = -1;
665
    }
666
}
667

    
668
static char *tcg_get_arg_str_idx(TCGContext *s, char *buf, int buf_size,
669
                                 int idx)
670
{
671
    TCGTemp *ts;
672

    
673
    ts = &s->temps[idx];
674
    if (idx < s->nb_globals) {
675
        pstrcpy(buf, buf_size, ts->name);
676
    } else {
677
        if (ts->val_type == TEMP_VAL_CONST) {
678
            snprintf(buf, buf_size, "$0x%" TCG_PRIlx , ts->val);
679
        } else {
680
            snprintf(buf, buf_size, "tmp%d", idx - s->nb_globals);
681
        }
682
    }
683
    return buf;
684
}
685

    
686
char *tcg_get_arg_str(TCGContext *s, char *buf, int buf_size, TCGv arg)
687
{
688
    return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV(arg));
689
}
690

    
691
void tcg_dump_ops(TCGContext *s, FILE *outfile)
692
{
693
    const uint16_t *opc_ptr;
694
    const TCGArg *args;
695
    TCGArg arg;
696
    int c, i, k, nb_oargs, nb_iargs, nb_cargs;
697
    const TCGOpDef *def;
698
    char buf[128];
699

    
700
    opc_ptr = gen_opc_buf;
701
    args = gen_opparam_buf;
702
    while (opc_ptr < gen_opc_ptr) {
703
        c = *opc_ptr++;
704
        def = &tcg_op_defs[c];
705
        fprintf(outfile, " %s ", def->name);
706
        if (c == INDEX_op_call) {
707
            TCGArg arg;
708
            /* variable number of arguments */
709
            arg = *args++;
710
            nb_oargs = arg >> 16;
711
            nb_iargs = arg & 0xffff;
712
            nb_cargs = def->nb_cargs;
713
        } else if (c == INDEX_op_nopn) {
714
            /* variable number of arguments */
715
            nb_cargs = *args;
716
            nb_oargs = 0;
717
            nb_iargs = 0;
718
        } else {
719
            nb_oargs = def->nb_oargs;
720
            nb_iargs = def->nb_iargs;
721
            nb_cargs = def->nb_cargs;
722
        }
723

    
724
        k = 0;
725
        for(i = 0; i < nb_oargs; i++) {
726
            if (k != 0)
727
                fprintf(outfile, ",");
728
            fprintf(outfile, "%s",
729
                    tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
730
        }
731
        for(i = 0; i < nb_iargs; i++) {
732
            if (k != 0)
733
                fprintf(outfile, ",");
734
            /* XXX: dump helper name for call */
735
            fprintf(outfile, "%s",
736
                    tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
737
        }
738
        for(i = 0; i < nb_cargs; i++) {
739
            if (k != 0)
740
                fprintf(outfile, ",");
741
            arg = args[k++];
742
            fprintf(outfile, "$0x%" TCG_PRIlx, arg);
743
        }
744
        fprintf(outfile, "\n");
745
        args += nb_iargs + nb_oargs + nb_cargs;
746
    }
747
}
748

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

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

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

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

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

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

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

    
847
#if 0
848
        {
849
            int i;
850

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

    
860
}
861

    
862
#ifdef USE_LIVENESS_ANALYSIS
863

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

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

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

    
897
    nb_ops = gen_opc_ptr - gen_opc_buf;
898

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

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

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

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

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

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

    
977
                macro_op_index = gen_opc_ptr - gen_opc_buf;
978
                macro_arg_index = gen_opparam_ptr -  gen_opparam_buf;
979

    
980
                last_nb_temps = s->nb_temps;
981

    
982
                s->macro_func(s, macro_id, dead_args);
983

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

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

    
995
                macro_end_op_index = gen_opc_ptr - gen_opc_buf;
996
                macro_end_arg_index = gen_opparam_ptr - gen_opparam_buf;
997

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1186
/* free register 'reg' by spilling the corresponding temporary if necessary */
1187
static void tcg_reg_free(TCGContext *s, int reg)
1188
{
1189
    TCGTemp *ts;
1190
    int temp;
1191

    
1192
    temp = s->reg_to_temp[reg];
1193
    if (temp != -1) {
1194
        ts = &s->temps[temp];
1195
        assert(ts->val_type == TEMP_VAL_REG);
1196
        if (!ts->mem_coherent) {
1197
            if (!ts->mem_allocated) 
1198
                temp_allocate_frame(s, temp);
1199
            tcg_out_st(s, reg, ts->mem_reg, ts->mem_offset);
1200
        }
1201
        ts->val_type = TEMP_VAL_MEM;
1202
        s->reg_to_temp[reg] = -1;
1203
    }
1204
}
1205

    
1206
/* Allocate a register belonging to reg1 & ~reg2 */
1207
static int tcg_reg_alloc(TCGContext *s, TCGRegSet reg1, TCGRegSet reg2)
1208
{
1209
    int i, reg;
1210
    TCGRegSet reg_ct;
1211

    
1212
    tcg_regset_andnot(reg_ct, reg1, reg2);
1213

    
1214
    /* first try free registers */
1215
    for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
1216
        reg = tcg_target_reg_alloc_order[i];
1217
        if (tcg_regset_test_reg(reg_ct, reg) && s->reg_to_temp[reg] == -1)
1218
            return reg;
1219
    }
1220

    
1221
    /* XXX: do better spill choice */
1222
    for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
1223
        reg = tcg_target_reg_alloc_order[i];
1224
        if (tcg_regset_test_reg(reg_ct, reg)) {
1225
            tcg_reg_free(s, reg);
1226
            return reg;
1227
        }
1228
    }
1229

    
1230
    tcg_abort();
1231
}
1232

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

    
1241
    for(i = 0; i < s->nb_globals; i++) {
1242
        ts = &s->temps[i];
1243
        if (!ts->fixed_reg) {
1244
            if (ts->val_type == TEMP_VAL_REG) {
1245
                tcg_reg_free(s, ts->reg);
1246
            }
1247
        }
1248
    }
1249

    
1250
    for(i = s->nb_globals; i < s->nb_temps; i++) {
1251
        ts = &s->temps[i];
1252
        if (ts->val_type != TEMP_VAL_CONST) {
1253
            if (ts->val_type == TEMP_VAL_REG) {
1254
                s->reg_to_temp[ts->reg] = -1;
1255
            }
1256
            ts->val_type = TEMP_VAL_DEAD;
1257
        }
1258
    }
1259
}
1260

    
1261
#define IS_DEAD_IARG(n) ((dead_iargs >> (n)) & 1)
1262

    
1263
static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
1264
                              const TCGArg *args,
1265
                              unsigned int dead_iargs)
1266
{
1267
    TCGTemp *ts, *ots;
1268
    int reg;
1269
    const TCGArgConstraint *arg_ct;
1270

    
1271
    ots = &s->temps[args[0]];
1272
    ts = &s->temps[args[1]];
1273
    arg_ct = &def->args_ct[0];
1274

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

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

    
1329
    nb_oargs = def->nb_oargs;
1330
    nb_iargs = def->nb_iargs;
1331

    
1332
    /* copy constants */
1333
    memcpy(new_args + nb_oargs + nb_iargs, 
1334
           args + nb_oargs + nb_iargs, 
1335
           sizeof(TCGArg) * def->nb_cargs);
1336

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

    
1409
    /* XXX: permit generic clobber register list ? */ 
1410
    if (def->flags & TCG_OPF_CALL_CLOBBER) {
1411
        for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1412
            if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
1413
                tcg_reg_free(s, reg);
1414
            }
1415
        }
1416
    }
1417

    
1418
    /* satisfy the output constraints */
1419
    tcg_regset_set(allocated_regs, s->reserved_regs);
1420
    for(k = 0; k < nb_oargs; k++) {
1421
        i = def->sorted_args[k];
1422
        arg = args[i];
1423
        arg_ct = &def->args_ct[i];
1424
        ts = &s->temps[arg];
1425
        if (arg_ct->ct & TCG_CT_ALIAS) {
1426
            reg = new_args[arg_ct->alias_index];
1427
        } else {
1428
            /* if fixed register, we try to use it */
1429
            reg = ts->reg;
1430
            if (ts->fixed_reg &&
1431
                tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1432
                goto oarg_end;
1433
            }
1434
            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1435
        }
1436
        tcg_regset_set_reg(allocated_regs, reg);
1437
        /* if a fixed register is used, then a move will be done afterwards */
1438
        if (!ts->fixed_reg) {
1439
            if (ts->val_type == TEMP_VAL_REG)
1440
                s->reg_to_temp[ts->reg] = -1;
1441
            ts->val_type = TEMP_VAL_REG;
1442
            ts->reg = reg;
1443
            /* temp value is modified, so the value kept in memory is
1444
               potentially not the same */
1445
            ts->mem_coherent = 0; 
1446
            s->reg_to_temp[reg] = arg;
1447
        }
1448
    oarg_end:
1449
        new_args[i] = reg;
1450
    }
1451

    
1452
    if (def->flags & TCG_OPF_BB_END)
1453
        tcg_reg_alloc_bb_end(s);
1454

    
1455
    /* emit instruction */
1456
    tcg_out_op(s, opc, new_args, const_args);
1457
    
1458
    /* move the outputs in the correct register if needed */
1459
    for(i = 0; i < nb_oargs; i++) {
1460
        ts = &s->temps[args[i]];
1461
        reg = new_args[i];
1462
        if (ts->fixed_reg && ts->reg != reg) {
1463
            tcg_out_mov(s, ts->reg, reg);
1464
        }
1465
    }
1466
}
1467

    
1468
static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
1469
                              int opc, const TCGArg *args,
1470
                              unsigned int dead_iargs)
1471
{
1472
    int nb_iargs, nb_oargs, flags, nb_regs, i, reg, nb_params;
1473
    TCGArg arg, func_arg;
1474
    TCGTemp *ts;
1475
    tcg_target_long stack_offset, call_stack_size;
1476
    int const_func_arg;
1477
    TCGRegSet allocated_regs;
1478
    const TCGArgConstraint *arg_ct;
1479

    
1480
    arg = *args++;
1481

    
1482
    nb_oargs = arg >> 16;
1483
    nb_iargs = arg & 0xffff;
1484
    nb_params = nb_iargs - 1;
1485

    
1486
    flags = args[nb_oargs + nb_iargs];
1487

    
1488
    nb_regs = tcg_target_get_call_iarg_regs_count(flags);
1489
    if (nb_regs > nb_params)
1490
        nb_regs = nb_params;
1491

    
1492
    /* assign stack slots first */
1493
    /* XXX: preallocate call stack */
1494
    call_stack_size = (nb_params - nb_regs) * sizeof(tcg_target_long);
1495
    call_stack_size = (call_stack_size + TCG_TARGET_STACK_ALIGN - 1) & 
1496
        ~(TCG_TARGET_STACK_ALIGN - 1);
1497
    tcg_out_addi(s, TCG_REG_CALL_STACK, -call_stack_size);
1498

    
1499
    stack_offset = 0;
1500
    for(i = nb_regs; i < nb_params; i++) {
1501
        arg = args[nb_oargs + i];
1502
        ts = &s->temps[arg];
1503
        if (ts->val_type == TEMP_VAL_REG) {
1504
            tcg_out_st(s, ts->reg, TCG_REG_CALL_STACK, stack_offset);
1505
        } else if (ts->val_type == TEMP_VAL_MEM) {
1506
            reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], 
1507
                                s->reserved_regs);
1508
            /* XXX: not correct if reading values from the stack */
1509
            tcg_out_ld(s, reg, ts->mem_reg, ts->mem_offset);
1510
            tcg_out_st(s, reg, TCG_REG_CALL_STACK, stack_offset);
1511
        } else if (ts->val_type == TEMP_VAL_CONST) {
1512
            reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], 
1513
                                s->reserved_regs);
1514
            /* XXX: sign extend may be needed on some targets */
1515
            tcg_out_movi(s, ts->type, reg, ts->val);
1516
            tcg_out_st(s, reg, TCG_REG_CALL_STACK, stack_offset);
1517
        } else {
1518
            tcg_abort();
1519
        }
1520
        stack_offset += sizeof(tcg_target_long);
1521
    }
1522
    
1523
    /* assign input registers */
1524
    tcg_regset_set(allocated_regs, s->reserved_regs);
1525
    for(i = 0; i < nb_regs; i++) {
1526
        arg = args[nb_oargs + i];
1527
        ts = &s->temps[arg];
1528
        reg = tcg_target_call_iarg_regs[i];
1529
        tcg_reg_free(s, reg);
1530
        if (ts->val_type == TEMP_VAL_REG) {
1531
            if (ts->reg != reg) {
1532
                tcg_out_mov(s, reg, ts->reg);
1533
            }
1534
        } else if (ts->val_type == TEMP_VAL_MEM) {
1535
            tcg_out_ld(s, reg, ts->mem_reg, ts->mem_offset);
1536
        } else if (ts->val_type == TEMP_VAL_CONST) {
1537
            /* XXX: sign extend ? */
1538
            tcg_out_movi(s, ts->type, reg, ts->val);
1539
        } else {
1540
            tcg_abort();
1541
        }
1542
        tcg_regset_set_reg(allocated_regs, reg);
1543
    }
1544
    
1545
    /* assign function address */
1546
    func_arg = args[nb_oargs + nb_iargs - 1];
1547
    arg_ct = &def->args_ct[0];
1548
    ts = &s->temps[func_arg];
1549
    const_func_arg = 0;
1550
    if (ts->val_type == TEMP_VAL_MEM) {
1551
        reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1552
        tcg_out_ld(s, reg, ts->mem_reg, ts->mem_offset);
1553
        func_arg = reg;
1554
    } else if (ts->val_type == TEMP_VAL_REG) {
1555
        reg = ts->reg;
1556
        if (!tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1557
            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1558
            tcg_out_mov(s, reg, ts->reg);
1559
        }
1560
        func_arg = reg;
1561
    } else if (ts->val_type == TEMP_VAL_CONST) {
1562
        if (tcg_target_const_match(ts->val, arg_ct)) {
1563
            const_func_arg = 1;
1564
            func_arg = ts->val;
1565
        } else {
1566
            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1567
            tcg_out_movi(s, ts->type, reg, ts->val);
1568
            func_arg = reg;
1569
        }
1570
    } else {
1571
        tcg_abort();
1572
    }
1573
    
1574
    /* mark dead temporaries and free the associated registers */
1575
    for(i = 0; i < nb_params; i++) {
1576
        arg = args[nb_oargs + i];
1577
        if (IS_DEAD_IARG(i)) {
1578
            ts = &s->temps[arg];
1579
            if (ts->val_type != TEMP_VAL_CONST && !ts->fixed_reg) {
1580
                if (ts->val_type == TEMP_VAL_REG)
1581
                    s->reg_to_temp[ts->reg] = -1;
1582
                ts->val_type = TEMP_VAL_DEAD;
1583
            }
1584
        }
1585
    }
1586
    
1587
    /* clobber call registers */
1588
    for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1589
        if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
1590
            tcg_reg_free(s, reg);
1591
        }
1592
    }
1593
    
1594
    /* store globals and free associated registers (we assume the call
1595
       can modify any global. */
1596
    for(i = 0; i < s->nb_globals; i++) {
1597
        ts = &s->temps[i];
1598
        if (!ts->fixed_reg) {
1599
            if (ts->val_type == TEMP_VAL_REG) {
1600
                tcg_reg_free(s, ts->reg);
1601
            }
1602
        }
1603
    }
1604

    
1605
    tcg_out_op(s, opc, &func_arg, &const_func_arg);
1606
    
1607
    tcg_out_addi(s, TCG_REG_CALL_STACK, call_stack_size);
1608

    
1609
    /* assign output registers and emit moves if needed */
1610
    for(i = 0; i < nb_oargs; i++) {
1611
        arg = args[i];
1612
        ts = &s->temps[arg];
1613
        reg = tcg_target_call_oarg_regs[i];
1614
        tcg_reg_free(s, reg);
1615
        if (ts->fixed_reg) {
1616
            if (ts->reg != reg) {
1617
                tcg_out_mov(s, ts->reg, reg);
1618
            }
1619
        } else {
1620
            if (ts->val_type == TEMP_VAL_REG)
1621
                s->reg_to_temp[ts->reg] = -1;
1622
            ts->val_type = TEMP_VAL_REG;
1623
            ts->reg = reg;
1624
            ts->mem_coherent = 0; 
1625
            s->reg_to_temp[reg] = arg;
1626
        }
1627
    }
1628
    
1629
    return nb_iargs + nb_oargs + def->nb_cargs + 1;
1630
}
1631

    
1632
#ifdef CONFIG_PROFILER
1633

    
1634
static int64_t dyngen_table_op_count[NB_OPS];
1635

    
1636
void dump_op_count(void)
1637
{
1638
    int i;
1639
    FILE *f;
1640
    f = fopen("/tmp/op1.log", "w");
1641
    for(i = 0; i < INDEX_op_end; i++) {
1642
        fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name, dyngen_table_op_count[i]);
1643
    }
1644
    fclose(f);
1645
    f = fopen("/tmp/op2.log", "w");
1646
    for(i = INDEX_op_end; i < NB_OPS; i++) {
1647
        fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name, dyngen_table_op_count[i]);
1648
    }
1649
    fclose(f);
1650
}
1651
#endif
1652

    
1653

    
1654
static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
1655
                                      long search_pc)
1656
{
1657
    int opc, op_index, macro_op_index;
1658
    const TCGOpDef *def;
1659
    unsigned int dead_iargs;
1660
    const TCGArg *args;
1661

    
1662
#ifdef DEBUG_DISAS
1663
    if (unlikely(loglevel & CPU_LOG_TB_OP)) {
1664
        fprintf(logfile, "OP:\n");
1665
        tcg_dump_ops(s, logfile);
1666
        fprintf(logfile, "\n");
1667
    }
1668
#endif
1669

    
1670
    tcg_liveness_analysis(s);
1671

    
1672
#ifdef DEBUG_DISAS
1673
    if (unlikely(loglevel & CPU_LOG_TB_OP_OPT)) {
1674
        fprintf(logfile, "OP after la:\n");
1675
        tcg_dump_ops(s, logfile);
1676
        fprintf(logfile, "\n");
1677
    }
1678
#endif
1679

    
1680
    tcg_reg_alloc_start(s);
1681

    
1682
    s->code_buf = gen_code_buf;
1683
    s->code_ptr = gen_code_buf;
1684

    
1685
    macro_op_index = -1;
1686
    args = gen_opparam_buf;
1687
    op_index = 0;
1688

    
1689
#ifdef TCG_TARGET_NEEDS_PROLOGUE
1690
    tcg_target_prologue(s);
1691
#endif
1692

    
1693
    for(;;) {
1694
        opc = gen_opc_buf[op_index];
1695
#ifdef CONFIG_PROFILER
1696
        dyngen_table_op_count[opc]++;
1697
#endif
1698
        def = &tcg_op_defs[opc];
1699
#if 0
1700
        printf("%s: %d %d %d\n", def->name,
1701
               def->nb_oargs, def->nb_iargs, def->nb_cargs);
1702
        //        dump_regs(s);
1703
#endif
1704
        switch(opc) {
1705
        case INDEX_op_mov_i32:
1706
#if TCG_TARGET_REG_BITS == 64
1707
        case INDEX_op_mov_i64:
1708
#endif
1709
            dead_iargs = s->op_dead_iargs[op_index];
1710
            tcg_reg_alloc_mov(s, def, args, dead_iargs);
1711
            break;
1712
        case INDEX_op_nop:
1713
        case INDEX_op_nop1:
1714
        case INDEX_op_nop2:
1715
        case INDEX_op_nop3:
1716
            break;
1717
        case INDEX_op_nopn:
1718
            args += args[0];
1719
            goto next;
1720
        case INDEX_op_discard:
1721
            {
1722
                TCGTemp *ts;
1723
                ts = &s->temps[args[0]];
1724
                /* mark the temporary as dead */
1725
                if (ts->val_type != TEMP_VAL_CONST && !ts->fixed_reg) {
1726
                    if (ts->val_type == TEMP_VAL_REG)
1727
                        s->reg_to_temp[ts->reg] = -1;
1728
                    ts->val_type = TEMP_VAL_DEAD;
1729
                }
1730
            }
1731
            break;
1732
        case INDEX_op_macro_goto:
1733
            macro_op_index = op_index; /* only used for exceptions */
1734
            op_index = args[0] - 1;
1735
            args = gen_opparam_buf + args[1];
1736
            goto next;
1737
        case INDEX_op_macro_end:
1738
            macro_op_index = -1; /* only used for exceptions */
1739
            op_index = args[0] - 1;
1740
            args = gen_opparam_buf + args[1];
1741
            goto next;
1742
        case INDEX_op_macro_start:
1743
            /* must never happen here */
1744
            tcg_abort();
1745
        case INDEX_op_set_label:
1746
            tcg_reg_alloc_bb_end(s);
1747
            tcg_out_label(s, args[0], (long)s->code_ptr);
1748
            break;
1749
        case INDEX_op_call:
1750
            dead_iargs = s->op_dead_iargs[op_index];
1751
            args += tcg_reg_alloc_call(s, def, opc, args, dead_iargs);
1752
            goto next;
1753
        case INDEX_op_end:
1754
            goto the_end;
1755
        case 0 ... INDEX_op_end - 1:
1756
            /* legacy dyngen ops */
1757
#ifdef CONFIG_PROFILER
1758
            {
1759
                extern int64_t dyngen_old_op_count;
1760
                dyngen_old_op_count++;
1761
            }
1762
#endif
1763
            tcg_reg_alloc_bb_end(s);
1764
            if (search_pc >= 0) {
1765
                s->code_ptr += def->copy_size;
1766
                args += def->nb_args;
1767
            } else {
1768
                args = dyngen_op(s, opc, args);
1769
            }
1770
            goto next;
1771
        default:
1772
            /* Note: in order to speed up the code, it would be much
1773
               faster to have specialized register allocator functions for
1774
               some common argument patterns */
1775
            dead_iargs = s->op_dead_iargs[op_index];
1776
            tcg_reg_alloc_op(s, def, opc, args, dead_iargs);
1777
            break;
1778
        }
1779
        args += def->nb_args;
1780
    next: ;
1781
        if (search_pc >= 0 && search_pc < s->code_ptr - gen_code_buf) {
1782
            if (macro_op_index >= 0)
1783
                return macro_op_index;
1784
            else
1785
                return op_index;
1786
        }
1787
        op_index++;
1788
#ifndef NDEBUG
1789
        check_regs(s);
1790
#endif
1791
    }
1792
 the_end:
1793
    return -1;
1794
}
1795

    
1796
int dyngen_code(TCGContext *s, uint8_t *gen_code_buf)
1797
{
1798
#ifdef CONFIG_PROFILER
1799
    {
1800
        extern int64_t dyngen_op_count;
1801
        extern int dyngen_op_count_max;
1802
        int n;
1803
        n = (gen_opc_ptr - gen_opc_buf);
1804
        dyngen_op_count += n;
1805
        if (n > dyngen_op_count_max)
1806
            dyngen_op_count_max = n;
1807
    }
1808
#endif
1809

    
1810
    tcg_gen_code_common(s, gen_code_buf, -1);
1811

    
1812
    /* flush instruction cache */
1813
    flush_icache_range((unsigned long)gen_code_buf, 
1814
                       (unsigned long)s->code_ptr);
1815
    return s->code_ptr -  gen_code_buf;
1816
}
1817

    
1818
/* Return the index of the micro operation such as the pc after is <
1819
   offset bytes from the start of the TB.  The contents of gen_code_buf must
1820
   not be changed, though writing the same values is ok.
1821
   Return -1 if not found. */
1822
int dyngen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, long offset)
1823
{
1824
    return tcg_gen_code_common(s, gen_code_buf, offset);
1825
}