Statistics
| Branch: | Revision:

root / tcg / tcg.c @ f54b3f92

History | View | Annotate | Download (53.3 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

    
247
void tcg_set_frame(TCGContext *s, int reg,
248
                   tcg_target_long start, tcg_target_long size)
249
{
250
    s->frame_start = start;
251
    s->frame_end = start + size;
252
    s->frame_reg = reg;
253
}
254

    
255
void tcg_set_macro_func(TCGContext *s, TCGMacroFunc *func)
256
{
257
    s->macro_func = func;
258
}
259

    
260
void tcg_func_start(TCGContext *s)
261
{
262
    tcg_pool_reset(s);
263
    s->nb_temps = s->nb_globals;
264
    s->labels = tcg_malloc(sizeof(TCGLabel) * TCG_MAX_LABELS);
265
    s->nb_labels = 0;
266
    s->current_frame_offset = s->frame_start;
267

    
268
    gen_opc_ptr = gen_opc_buf;
269
    gen_opparam_ptr = gen_opparam_buf;
270
}
271

    
272
static inline void tcg_temp_alloc(TCGContext *s, int n)
273
{
274
    if (n > TCG_MAX_TEMPS)
275
        tcg_abort();
276
}
277

    
278
TCGv tcg_global_reg_new(TCGType type, int reg, const char *name)
279
{
280
    TCGContext *s = &tcg_ctx;
281
    TCGTemp *ts;
282
    int idx;
283

    
284
#if TCG_TARGET_REG_BITS == 32
285
    if (type != TCG_TYPE_I32)
286
        tcg_abort();
287
#endif
288
    if (tcg_regset_test_reg(s->reserved_regs, reg))
289
        tcg_abort();
290
    idx = s->nb_globals;
291
    tcg_temp_alloc(s, s->nb_globals + 1);
292
    ts = &s->temps[s->nb_globals];
293
    ts->base_type = type;
294
    ts->type = type;
295
    ts->fixed_reg = 1;
296
    ts->reg = reg;
297
    ts->val_type = TEMP_VAL_REG;
298
    ts->name = name;
299
    s->nb_globals++;
300
    tcg_regset_set_reg(s->reserved_regs, reg);
301
    return MAKE_TCGV(idx);
302
}
303

    
304
TCGv tcg_global_mem_new(TCGType type, int reg, tcg_target_long offset,
305
                        const char *name)
306
{
307
    TCGContext *s = &tcg_ctx;
308
    TCGTemp *ts;
309
    int idx;
310

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

    
333
        ts->base_type = type;
334
        ts->type = TCG_TYPE_I32;
335
        ts->fixed_reg = 0;
336
        ts->mem_allocated = 1;
337
        ts->mem_reg = reg;
338
#ifdef TCG_TARGET_WORDS_BIGENDIAN
339
        ts->mem_offset = offset;
340
#else
341
        ts->mem_offset = offset + 4;
342
#endif
343
        ts->val_type = TEMP_VAL_MEM;
344
        pstrcpy(buf, sizeof(buf), name);
345
        pstrcat(buf, sizeof(buf), "_1");
346
        ts->name = strdup(buf);
347

    
348
        s->nb_globals += 2;
349
    } else
350
#endif
351
    {
352
        tcg_temp_alloc(s, s->nb_globals + 1);
353
        ts = &s->temps[s->nb_globals];
354
        ts->base_type = type;
355
        ts->type = type;
356
        ts->fixed_reg = 0;
357
        ts->mem_allocated = 1;
358
        ts->mem_reg = reg;
359
        ts->mem_offset = offset;
360
        ts->val_type = TEMP_VAL_MEM;
361
        ts->name = name;
362
        s->nb_globals++;
363
    }
364
    return MAKE_TCGV(idx);
365
}
366

    
367
TCGv tcg_temp_new(TCGType type)
368
{
369
    TCGContext *s = &tcg_ctx;
370
    TCGTemp *ts;
371
    int idx;
372

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

    
408
TCGv tcg_const_i32(int32_t val)
409
{
410
    TCGContext *s = &tcg_ctx;
411
    TCGTemp *ts;
412
    int idx;
413

    
414
    idx = s->nb_temps;
415
    tcg_temp_alloc(s, idx + 1);
416
    ts = &s->temps[idx];
417
    ts->base_type = ts->type = TCG_TYPE_I32;
418
    ts->val_type = TEMP_VAL_CONST;
419
    ts->name = NULL;
420
    ts->val = val;
421
    s->nb_temps++;
422
    return MAKE_TCGV(idx);
423
}
424

    
425
TCGv tcg_const_i64(int64_t val)
426
{
427
    TCGContext *s = &tcg_ctx;
428
    TCGTemp *ts;
429
    int idx;
430

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

    
459
void tcg_register_helper(void *func, const char *name)
460
{
461
    TCGContext *s = &tcg_ctx;
462
    int n;
463
    if ((s->nb_helpers + 1) > s->allocated_helpers) {
464
        n = s->allocated_helpers;
465
        if (n == 0) {
466
            n = 4;
467
        } else {
468
            n *= 2;
469
        }
470
        s->helpers = realloc(s->helpers, n * sizeof(TCGHelperInfo));
471
        s->allocated_helpers = n;
472
    }
473
    s->helpers[s->nb_helpers].func = func;
474
    s->helpers[s->nb_helpers].name = name;
475
    s->nb_helpers++;
476
}
477

    
478
const char *tcg_helper_get_name(TCGContext *s, void *func)
479
{
480
    int i;
481

    
482
    for(i = 0; i < s->nb_helpers; i++) {
483
        if (s->helpers[i].func == func)
484
            return s->helpers[i].name;
485
    }
486
    return NULL;
487
}
488

    
489
static inline TCGType tcg_get_base_type(TCGContext *s, TCGv arg)
490
{
491
    return s->temps[GET_TCGV(arg)].base_type;
492
}
493

    
494
static void tcg_gen_call_internal(TCGContext *s, TCGv func, 
495
                                  unsigned int flags,
496
                                  unsigned int nb_rets, const TCGv *rets,
497
                                  unsigned int nb_params, const TCGv *params)
498
{
499
    int i;
500
    *gen_opc_ptr++ = INDEX_op_call;
501
    *gen_opparam_ptr++ = (nb_rets << 16) | (nb_params + 1);
502
    for(i = 0; i < nb_rets; i++) {
503
        *gen_opparam_ptr++ = GET_TCGV(rets[i]);
504
    }
505
    for(i = 0; i < nb_params; i++) {
506
        *gen_opparam_ptr++ = GET_TCGV(params[i]);
507
    }
508
    *gen_opparam_ptr++ = GET_TCGV(func);
509

    
510
    *gen_opparam_ptr++ = flags;
511
    /* total parameters, needed to go backward in the instruction stream */
512
    *gen_opparam_ptr++ = 1 + nb_rets + nb_params + 3;
513
}
514

    
515

    
516
#if TCG_TARGET_REG_BITS < 64
517
/* Note: we convert the 64 bit args to 32 bit */
518
void tcg_gen_call(TCGContext *s, TCGv func, unsigned int flags,
519
                  unsigned int nb_rets, const TCGv *rets,
520
                  unsigned int nb_params, const TCGv *args1)
521
{
522
    TCGv ret, *args2, rets_2[2], arg;
523
    int j, i, call_type;
524

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

    
575
#if TCG_TARGET_REG_BITS == 32
576
void tcg_gen_shifti_i64(TCGv ret, TCGv arg1, 
577
                        int c, int right, int arith)
578
{
579
    if (c == 0)
580
        return;
581
    if (c >= 32) {
582
        c -= 32;
583
        if (right) {
584
            if (arith) {
585
                tcg_gen_sari_i32(ret, TCGV_HIGH(arg1), c);
586
                tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 31);
587
            } else {
588
                tcg_gen_shri_i32(ret, TCGV_HIGH(arg1), c);
589
                tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
590
            }
591
        } else {
592
            tcg_gen_shli_i32(TCGV_HIGH(ret), arg1, c);
593
            tcg_gen_movi_i32(ret, 0);
594
        }
595
    } else {
596
        TCGv t0, t1;
597

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

    
621
void tcg_reg_alloc_start(TCGContext *s)
622
{
623
    int i;
624
    TCGTemp *ts;
625
    for(i = 0; i < s->nb_globals; i++) {
626
        ts = &s->temps[i];
627
        if (ts->fixed_reg) {
628
            ts->val_type = TEMP_VAL_REG;
629
        } else {
630
            ts->val_type = TEMP_VAL_MEM;
631
        }
632
    }
633
    for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
634
        s->reg_to_temp[i] = -1;
635
    }
636
}
637

    
638
static char *tcg_get_arg_str_idx(TCGContext *s, char *buf, int buf_size,
639
                                 int idx)
640
{
641
    TCGTemp *ts;
642

    
643
    ts = &s->temps[idx];
644
    if (idx < s->nb_globals) {
645
        pstrcpy(buf, buf_size, ts->name);
646
    } else {
647
        if (ts->val_type == TEMP_VAL_CONST) {
648
            snprintf(buf, buf_size, "$0x%" TCG_PRIlx , ts->val);
649
        } else {
650
            snprintf(buf, buf_size, "tmp%d", idx - s->nb_globals);
651
        }
652
    }
653
    return buf;
654
}
655

    
656
char *tcg_get_arg_str(TCGContext *s, char *buf, int buf_size, TCGv arg)
657
{
658
    return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV(arg));
659
}
660

    
661
void tcg_dump_ops(TCGContext *s, FILE *outfile)
662
{
663
    const uint16_t *opc_ptr;
664
    const TCGArg *args;
665
    TCGArg arg;
666
    int c, i, k, nb_oargs, nb_iargs, nb_cargs;
667
    const TCGOpDef *def;
668
    char buf[128];
669

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

    
694
        k = 0;
695
        for(i = 0; i < nb_oargs; i++) {
696
            if (k != 0)
697
                fprintf(outfile, ",");
698
            fprintf(outfile, "%s",
699
                    tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
700
        }
701
        for(i = 0; i < nb_iargs; i++) {
702
            if (k != 0)
703
                fprintf(outfile, ",");
704
            /* XXX: dump helper name for call */
705
            fprintf(outfile, "%s",
706
                    tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
707
        }
708
        for(i = 0; i < nb_cargs; i++) {
709
            if (k != 0)
710
                fprintf(outfile, ",");
711
            arg = args[k++];
712
            fprintf(outfile, "$0x%" TCG_PRIlx, arg);
713
        }
714
        fprintf(outfile, "\n");
715
        args += nb_iargs + nb_oargs + nb_cargs;
716
    }
717
}
718

    
719
/* we give more priority to constraints with less registers */
720
static int get_constraint_priority(const TCGOpDef *def, int k)
721
{
722
    const TCGArgConstraint *arg_ct;
723

    
724
    int i, n;
725
    arg_ct = &def->args_ct[k];
726
    if (arg_ct->ct & TCG_CT_ALIAS) {
727
        /* an alias is equivalent to a single register */
728
        n = 1;
729
    } else {
730
        if (!(arg_ct->ct & TCG_CT_REG))
731
            return 0;
732
        n = 0;
733
        for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
734
            if (tcg_regset_test_reg(arg_ct->u.regs, i))
735
                n++;
736
        }
737
    }
738
    return TCG_TARGET_NB_REGS - n + 1;
739
}
740

    
741
/* sort from highest priority to lowest */
742
static void sort_constraints(TCGOpDef *def, int start, int n)
743
{
744
    int i, j, p1, p2, tmp;
745

    
746
    for(i = 0; i < n; i++)
747
        def->sorted_args[start + i] = start + i;
748
    if (n <= 1)
749
        return;
750
    for(i = 0; i < n - 1; i++) {
751
        for(j = i + 1; j < n; j++) {
752
            p1 = get_constraint_priority(def, def->sorted_args[start + i]);
753
            p2 = get_constraint_priority(def, def->sorted_args[start + j]);
754
            if (p1 < p2) {
755
                tmp = def->sorted_args[start + i];
756
                def->sorted_args[start + i] = def->sorted_args[start + j];
757
                def->sorted_args[start + j] = tmp;
758
            }
759
        }
760
    }
761
}
762

    
763
void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs)
764
{
765
    int op;
766
    TCGOpDef *def;
767
    const char *ct_str;
768
    int i, nb_args;
769

    
770
    for(;;) {
771
        if (tdefs->op < 0)
772
            break;
773
        op = tdefs->op;
774
        assert(op >= 0 && op < NB_OPS);
775
        def = &tcg_op_defs[op];
776
        nb_args = def->nb_iargs + def->nb_oargs;
777
        for(i = 0; i < nb_args; i++) {
778
            ct_str = tdefs->args_ct_str[i];
779
            tcg_regset_clear(def->args_ct[i].u.regs);
780
            def->args_ct[i].ct = 0;
781
            if (ct_str[0] >= '0' && ct_str[0] <= '9') {
782
                int oarg;
783
                oarg = ct_str[0] - '0';
784
                assert(oarg < def->nb_oargs);
785
                assert(def->args_ct[oarg].ct & TCG_CT_REG);
786
                /* TCG_CT_ALIAS is for the output arguments. The input
787
                   argument is tagged with TCG_CT_IALIAS. */
788
                def->args_ct[i] = def->args_ct[oarg];
789
                def->args_ct[oarg].ct = TCG_CT_ALIAS;
790
                def->args_ct[oarg].alias_index = i;
791
                def->args_ct[i].ct |= TCG_CT_IALIAS;
792
                def->args_ct[i].alias_index = oarg;
793
            } else {
794
                for(;;) {
795
                    if (*ct_str == '\0')
796
                        break;
797
                    switch(*ct_str) {
798
                    case 'i':
799
                        def->args_ct[i].ct |= TCG_CT_CONST;
800
                        ct_str++;
801
                        break;
802
                    default:
803
                        if (target_parse_constraint(&def->args_ct[i], &ct_str) < 0) {
804
                            fprintf(stderr, "Invalid constraint '%s' for arg %d of operation '%s'\n",
805
                                    ct_str, i, def->name);
806
                            exit(1);
807
                        }
808
                    }
809
                }
810
            }
811
        }
812

    
813
        /* sort the constraints (XXX: this is just an heuristic) */
814
        sort_constraints(def, 0, def->nb_oargs);
815
        sort_constraints(def, def->nb_oargs, def->nb_iargs);
816

    
817
#if 0
818
        {
819
            int i;
820

821
            printf("%s: sorted=", def->name);
822
            for(i = 0; i < def->nb_oargs + def->nb_iargs; i++)
823
                printf(" %d", def->sorted_args[i]);
824
            printf("\n");
825
        }
826
#endif
827
        tdefs++;
828
    }
829

    
830
}
831

    
832
#ifdef USE_LIVENESS_ANALYSIS
833

    
834
/* set a nop for an operation using 'nb_args' */
835
static inline void tcg_set_nop(TCGContext *s, uint16_t *opc_ptr, 
836
                               TCGArg *args, int nb_args)
837
{
838
    if (nb_args == 0) {
839
        *opc_ptr = INDEX_op_nop;
840
    } else {
841
        *opc_ptr = INDEX_op_nopn;
842
        args[0] = nb_args;
843
        args[nb_args - 1] = nb_args;
844
    }
845
}
846

    
847
/* liveness analysis: end of basic block: globals are live, temps are dead */
848
static inline void tcg_la_bb_end(TCGContext *s, uint8_t *dead_temps)
849
{
850
    memset(dead_temps, 0, s->nb_globals);
851
    memset(dead_temps + s->nb_globals, 1, s->nb_temps - s->nb_globals);
852
}
853

    
854
/* Liveness analysis : update the opc_dead_iargs array to tell if a
855
   given input arguments is dead. Instructions updating dead
856
   temporaries are removed. */
857
void tcg_liveness_analysis(TCGContext *s)
858
{
859
    int i, op_index, op, nb_args, nb_iargs, nb_oargs, arg, nb_ops;
860
    TCGArg *args;
861
    const TCGOpDef *def;
862
    uint8_t *dead_temps;
863
    unsigned int dead_iargs;
864
    
865
    gen_opc_ptr++; /* skip end */
866

    
867
    nb_ops = gen_opc_ptr - gen_opc_buf;
868

    
869
    /* XXX: make it really dynamic */
870
    s->op_dead_iargs = tcg_malloc(OPC_BUF_SIZE * sizeof(uint16_t));
871
    
872
    dead_temps = tcg_malloc(s->nb_temps);
873
    memset(dead_temps, 1, s->nb_temps);
874

    
875
    args = gen_opparam_ptr;
876
    op_index = nb_ops - 1;
877
    while (op_index >= 0) {
878
        op = gen_opc_buf[op_index];
879
        def = &tcg_op_defs[op];
880
        switch(op) {
881
        case INDEX_op_call:
882
            nb_args = args[-1];
883
            args -= nb_args;
884
            nb_iargs = args[0] & 0xffff;
885
            nb_oargs = args[0] >> 16;
886
            args++;
887

    
888
            /* output args are dead */
889
            for(i = 0; i < nb_oargs; i++) {
890
                arg = args[i];
891
                dead_temps[arg] = 1;
892
            }
893
            
894
            /* globals are live (they may be used by the call) */
895
            memset(dead_temps, 0, s->nb_globals);
896

    
897
            /* input args are live */
898
            dead_iargs = 0;
899
            for(i = 0; i < nb_iargs; i++) {
900
                arg = args[i + nb_oargs];
901
                if (dead_temps[arg]) {
902
                    dead_iargs |= (1 << i);
903
                }
904
                dead_temps[arg] = 0;
905
            }
906
            s->op_dead_iargs[op_index] = dead_iargs;
907
            args--;
908
            break;
909
        case INDEX_op_set_label:
910
            args--;
911
            /* mark end of basic block */
912
            tcg_la_bb_end(s, dead_temps);
913
            break;
914
        case INDEX_op_nopn:
915
            nb_args = args[-1];
916
            args -= nb_args;
917
            break;
918
        case INDEX_op_discard:
919
            args--;
920
            /* mark the temporary as dead */
921
            dead_temps[args[0]] = 1;
922
            break;
923
        case INDEX_op_macro_2:
924
            {
925
                int dead_args[2], macro_id;
926
                int saved_op_index, saved_arg_index;
927
                int macro_op_index, macro_arg_index;
928
                int macro_end_op_index, macro_end_arg_index;
929
                int last_nb_temps;
930
                
931
                nb_args = 3;
932
                args -= nb_args;
933
                dead_args[0] = dead_temps[args[0]];
934
                dead_args[1] = dead_temps[args[1]];
935
                macro_id = args[2];
936

    
937
                /* call the macro function which generate code
938
                   depending on the live outputs */
939
                saved_op_index = op_index;
940
                saved_arg_index = args - gen_opparam_buf;
941

    
942
                /* add a macro start instruction */
943
                *gen_opc_ptr++ = INDEX_op_macro_start;
944
                *gen_opparam_ptr++ = saved_op_index;
945
                *gen_opparam_ptr++ = saved_arg_index;
946

    
947
                macro_op_index = gen_opc_ptr - gen_opc_buf;
948
                macro_arg_index = gen_opparam_ptr -  gen_opparam_buf;
949

    
950
                last_nb_temps = s->nb_temps;
951

    
952
                s->macro_func(s, macro_id, dead_args);
953

    
954
                /* realloc temp info (XXX: make it faster) */
955
                if (s->nb_temps > last_nb_temps) {
956
                    uint8_t *new_dead_temps;
957

    
958
                    new_dead_temps = tcg_malloc(s->nb_temps);
959
                    memcpy(new_dead_temps, dead_temps, last_nb_temps);
960
                    memset(new_dead_temps + last_nb_temps, 1, 
961
                           s->nb_temps - last_nb_temps);
962
                    dead_temps = new_dead_temps;
963
                }
964

    
965
                macro_end_op_index = gen_opc_ptr - gen_opc_buf;
966
                macro_end_arg_index = gen_opparam_ptr - gen_opparam_buf;
967

    
968
                /* end of macro: add a goto to the next instruction */
969
                *gen_opc_ptr++ = INDEX_op_macro_end;
970
                *gen_opparam_ptr++ = op_index + 1;
971
                *gen_opparam_ptr++ = saved_arg_index + nb_args;
972

    
973
                /* modify the macro operation to be a macro_goto */
974
                gen_opc_buf[op_index] = INDEX_op_macro_goto;
975
                args[0] = macro_op_index;
976
                args[1] = macro_arg_index;
977
                args[2] = 0; /* dummy third arg to match the 
978
                                macro parameters */
979

    
980
                /* set the next instruction to the end of the macro */
981
                op_index = macro_end_op_index;
982
                args = macro_end_arg_index + gen_opparam_buf;
983
            }
984
            break;
985
        case INDEX_op_macro_start:
986
            args -= 2;
987
            op_index = args[0];
988
            args = gen_opparam_buf + args[1];
989
            break;
990
        case INDEX_op_macro_goto:
991
        case INDEX_op_macro_end:
992
            tcg_abort(); /* should never happen in liveness analysis */
993
        case INDEX_op_end:
994
            break;
995
            /* XXX: optimize by hardcoding common cases (e.g. triadic ops) */
996
        default:
997
            if (op > INDEX_op_end) {
998
                args -= def->nb_args;
999
                nb_iargs = def->nb_iargs;
1000
                nb_oargs = def->nb_oargs;
1001

    
1002
                /* Test if the operation can be removed because all
1003
                   its outputs are dead. We assume that nb_oargs == 0
1004
                   implies side effects */
1005
                if (!(def->flags & TCG_OPF_SIDE_EFFECTS) && nb_oargs != 0) {
1006
                    for(i = 0; i < nb_oargs; i++) {
1007
                        arg = args[i];
1008
                        if (!dead_temps[arg])
1009
                            goto do_not_remove;
1010
                    }
1011
                    tcg_set_nop(s, gen_opc_buf + op_index, args, def->nb_args);
1012
#ifdef CONFIG_PROFILER
1013
                    {
1014
                        extern int64_t dyngen_tcg_del_op_count;
1015
                        dyngen_tcg_del_op_count++;
1016
                    }
1017
#endif
1018
                } else {
1019
                do_not_remove:
1020

    
1021
                    /* output args are dead */
1022
                    for(i = 0; i < nb_oargs; i++) {
1023
                        arg = args[i];
1024
                        dead_temps[arg] = 1;
1025
                    }
1026
                    
1027
                    /* if end of basic block, update */
1028
                    if (def->flags & TCG_OPF_BB_END) {
1029
                        tcg_la_bb_end(s, dead_temps);
1030
                    }
1031
                    
1032
                    /* input args are live */
1033
                    dead_iargs = 0;
1034
                    for(i = 0; i < nb_iargs; i++) {
1035
                        arg = args[i + nb_oargs];
1036
                        if (dead_temps[arg]) {
1037
                            dead_iargs |= (1 << i);
1038
                        }
1039
                        dead_temps[arg] = 0;
1040
                    }
1041
                    s->op_dead_iargs[op_index] = dead_iargs;
1042
                }
1043
            } else {
1044
                /* legacy dyngen operations */
1045
                args -= def->nb_args;
1046
                /* mark end of basic block */
1047
                tcg_la_bb_end(s, dead_temps);
1048
            }
1049
            break;
1050
        }
1051
        op_index--;
1052
    }
1053

    
1054
    if (args != gen_opparam_buf)
1055
        tcg_abort();
1056
}
1057
#else
1058
/* dummy liveness analysis */
1059
void tcg_liveness_analysis(TCGContext *s)
1060
{
1061
    int nb_ops;
1062
    nb_ops = gen_opc_ptr - gen_opc_buf;
1063

    
1064
    s->op_dead_iargs = tcg_malloc(nb_ops * sizeof(uint16_t));
1065
    memset(s->op_dead_iargs, 0, nb_ops * sizeof(uint16_t));
1066
}
1067
#endif
1068

    
1069
#ifndef NDEBUG
1070
static void dump_regs(TCGContext *s)
1071
{
1072
    TCGTemp *ts;
1073
    int i;
1074
    char buf[64];
1075

    
1076
    for(i = 0; i < s->nb_temps; i++) {
1077
        ts = &s->temps[i];
1078
        printf("  %10s: ", tcg_get_arg_str_idx(s, buf, sizeof(buf), i));
1079
        switch(ts->val_type) {
1080
        case TEMP_VAL_REG:
1081
            printf("%s", tcg_target_reg_names[ts->reg]);
1082
            break;
1083
        case TEMP_VAL_MEM:
1084
            printf("%d(%s)", (int)ts->mem_offset, tcg_target_reg_names[ts->mem_reg]);
1085
            break;
1086
        case TEMP_VAL_CONST:
1087
            printf("$0x%" TCG_PRIlx, ts->val);
1088
            break;
1089
        case TEMP_VAL_DEAD:
1090
            printf("D");
1091
            break;
1092
        default:
1093
            printf("???");
1094
            break;
1095
        }
1096
        printf("\n");
1097
    }
1098

    
1099
    for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
1100
        if (s->reg_to_temp[i] >= 0) {
1101
            printf("%s: %s\n", 
1102
                   tcg_target_reg_names[i], 
1103
                   tcg_get_arg_str_idx(s, buf, sizeof(buf), s->reg_to_temp[i]));
1104
        }
1105
    }
1106
}
1107

    
1108
static void check_regs(TCGContext *s)
1109
{
1110
    int reg, k;
1111
    TCGTemp *ts;
1112
    char buf[64];
1113

    
1114
    for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1115
        k = s->reg_to_temp[reg];
1116
        if (k >= 0) {
1117
            ts = &s->temps[k];
1118
            if (ts->val_type != TEMP_VAL_REG ||
1119
                ts->reg != reg) {
1120
                printf("Inconsistency for register %s:\n", 
1121
                       tcg_target_reg_names[reg]);
1122
                printf("reg state:\n");
1123
                dump_regs(s);
1124
                tcg_abort();
1125
            }
1126
        }
1127
    }
1128
    for(k = 0; k < s->nb_temps; k++) {
1129
        ts = &s->temps[k];
1130
        if (ts->val_type == TEMP_VAL_REG &&
1131
            !ts->fixed_reg &&
1132
            s->reg_to_temp[ts->reg] != k) {
1133
                printf("Inconsistency for temp %s:\n", 
1134
                       tcg_get_arg_str_idx(s, buf, sizeof(buf), k));
1135
                printf("reg state:\n");
1136
                dump_regs(s);
1137
                tcg_abort();
1138
        }
1139
    }
1140
}
1141
#endif
1142

    
1143
static void temp_allocate_frame(TCGContext *s, int temp)
1144
{
1145
    TCGTemp *ts;
1146
    ts = &s->temps[temp];
1147
    s->current_frame_offset = (s->current_frame_offset + sizeof(tcg_target_long) - 1) & ~(sizeof(tcg_target_long) - 1);
1148
    if (s->current_frame_offset + sizeof(tcg_target_long) > s->frame_end)
1149
        tcg_abort();
1150
    ts->mem_offset = s->current_frame_offset;
1151
    ts->mem_reg = s->frame_reg;
1152
    ts->mem_allocated = 1;
1153
    s->current_frame_offset += sizeof(tcg_target_long);
1154
}
1155

    
1156
/* free register 'reg' by spilling the corresponding temporary if necessary */
1157
static void tcg_reg_free(TCGContext *s, int reg)
1158
{
1159
    TCGTemp *ts;
1160
    int temp;
1161

    
1162
    temp = s->reg_to_temp[reg];
1163
    if (temp != -1) {
1164
        ts = &s->temps[temp];
1165
        assert(ts->val_type == TEMP_VAL_REG);
1166
        if (!ts->mem_coherent) {
1167
            if (!ts->mem_allocated) 
1168
                temp_allocate_frame(s, temp);
1169
            tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1170
        }
1171
        ts->val_type = TEMP_VAL_MEM;
1172
        s->reg_to_temp[reg] = -1;
1173
    }
1174
}
1175

    
1176
/* Allocate a register belonging to reg1 & ~reg2 */
1177
static int tcg_reg_alloc(TCGContext *s, TCGRegSet reg1, TCGRegSet reg2)
1178
{
1179
    int i, reg;
1180
    TCGRegSet reg_ct;
1181

    
1182
    tcg_regset_andnot(reg_ct, reg1, reg2);
1183

    
1184
    /* first try free registers */
1185
    for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1186
        reg = tcg_target_reg_alloc_order[i];
1187
        if (tcg_regset_test_reg(reg_ct, reg) && s->reg_to_temp[reg] == -1)
1188
            return reg;
1189
    }
1190

    
1191
    /* XXX: do better spill choice */
1192
    for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1193
        reg = tcg_target_reg_alloc_order[i];
1194
        if (tcg_regset_test_reg(reg_ct, reg)) {
1195
            tcg_reg_free(s, reg);
1196
            return reg;
1197
        }
1198
    }
1199

    
1200
    tcg_abort();
1201
}
1202

    
1203
/* at the end of a basic block, we assume all temporaries are dead and
1204
   all globals are stored at their canonical location */
1205
/* XXX: optimize by handling constants in another array ? */
1206
void tcg_reg_alloc_bb_end(TCGContext *s)
1207
{
1208
    TCGTemp *ts;
1209
    int i;
1210

    
1211
    for(i = 0; i < s->nb_globals; i++) {
1212
        ts = &s->temps[i];
1213
        if (!ts->fixed_reg) {
1214
            if (ts->val_type == TEMP_VAL_REG) {
1215
                tcg_reg_free(s, ts->reg);
1216
            }
1217
        }
1218
    }
1219

    
1220
    for(i = s->nb_globals; i < s->nb_temps; i++) {
1221
        ts = &s->temps[i];
1222
        if (ts->val_type != TEMP_VAL_CONST) {
1223
            if (ts->val_type == TEMP_VAL_REG) {
1224
                s->reg_to_temp[ts->reg] = -1;
1225
            }
1226
            ts->val_type = TEMP_VAL_DEAD;
1227
        }
1228
    }
1229
}
1230

    
1231
#define IS_DEAD_IARG(n) ((dead_iargs >> (n)) & 1)
1232

    
1233
static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
1234
                              const TCGArg *args,
1235
                              unsigned int dead_iargs)
1236
{
1237
    TCGTemp *ts, *ots;
1238
    int reg;
1239
    const TCGArgConstraint *arg_ct;
1240

    
1241
    ots = &s->temps[args[0]];
1242
    ts = &s->temps[args[1]];
1243
    arg_ct = &def->args_ct[0];
1244

    
1245
    if (ts->val_type == TEMP_VAL_REG) {
1246
        if (IS_DEAD_IARG(0) && !ts->fixed_reg && !ots->fixed_reg) {
1247
            /* the mov can be suppressed */
1248
            if (ots->val_type == TEMP_VAL_REG)
1249
                s->reg_to_temp[ots->reg] = -1;
1250
            reg = ts->reg;
1251
            s->reg_to_temp[reg] = -1;
1252
            ts->val_type = TEMP_VAL_DEAD;
1253
        } else {
1254
            if (ots->val_type == TEMP_VAL_REG) {
1255
                reg = ots->reg;
1256
            } else {
1257
                reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1258
            }
1259
            if (ts->reg != reg) {
1260
                tcg_out_mov(s, reg, ts->reg);
1261
            }
1262
        }
1263
    } else if (ts->val_type == TEMP_VAL_MEM) {
1264
        if (ots->val_type == TEMP_VAL_REG) {
1265
            reg = ots->reg;
1266
        } else {
1267
            reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1268
        }
1269
        tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1270
    } else if (ts->val_type == TEMP_VAL_CONST) {
1271
        if (ots->val_type == TEMP_VAL_REG) {
1272
            reg = ots->reg;
1273
        } else {
1274
            reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1275
        }
1276
        tcg_out_movi(s, ots->type, reg, ts->val);
1277
    } else {
1278
        tcg_abort();
1279
    }
1280
    s->reg_to_temp[reg] = args[0];
1281
    ots->reg = reg;
1282
    ots->val_type = TEMP_VAL_REG;
1283
    ots->mem_coherent = 0;
1284
}
1285

    
1286
static void tcg_reg_alloc_op(TCGContext *s, 
1287
                             const TCGOpDef *def, int opc,
1288
                             const TCGArg *args,
1289
                             unsigned int dead_iargs)
1290
{
1291
    TCGRegSet allocated_regs;
1292
    int i, k, nb_iargs, nb_oargs, reg;
1293
    TCGArg arg;
1294
    const TCGArgConstraint *arg_ct;
1295
    TCGTemp *ts;
1296
    TCGArg new_args[TCG_MAX_OP_ARGS];
1297
    int const_args[TCG_MAX_OP_ARGS];
1298

    
1299
    nb_oargs = def->nb_oargs;
1300
    nb_iargs = def->nb_iargs;
1301

    
1302
    /* copy constants */
1303
    memcpy(new_args + nb_oargs + nb_iargs, 
1304
           args + nb_oargs + nb_iargs, 
1305
           sizeof(TCGArg) * def->nb_cargs);
1306

    
1307
    /* satisfy input constraints */ 
1308
    tcg_regset_set(allocated_regs, s->reserved_regs);
1309
    for(k = 0; k < nb_iargs; k++) {
1310
        i = def->sorted_args[nb_oargs + k];
1311
        arg = args[i];
1312
        arg_ct = &def->args_ct[i];
1313
        ts = &s->temps[arg];
1314
        if (ts->val_type == TEMP_VAL_MEM) {
1315
            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1316
            tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1317
            ts->val_type = TEMP_VAL_REG;
1318
            ts->reg = reg;
1319
            ts->mem_coherent = 1;
1320
            s->reg_to_temp[reg] = arg;
1321
        } else if (ts->val_type == TEMP_VAL_CONST) {
1322
            if (tcg_target_const_match(ts->val, arg_ct)) {
1323
                /* constant is OK for instruction */
1324
                const_args[i] = 1;
1325
                new_args[i] = ts->val;
1326
                goto iarg_end;
1327
            } else {
1328
                /* need to move to a register*/
1329
                reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1330
                tcg_out_movi(s, ts->type, reg, ts->val);
1331
                goto iarg_end1;
1332
            }
1333
        }
1334
        assert(ts->val_type == TEMP_VAL_REG);
1335
        if (arg_ct->ct & TCG_CT_IALIAS) {
1336
            if (ts->fixed_reg) {
1337
                /* if fixed register, we must allocate a new register
1338
                   if the alias is not the same register */
1339
                if (arg != args[arg_ct->alias_index])
1340
                    goto allocate_in_reg;
1341
            } else {
1342
                /* if the input is aliased to an output and if it is
1343
                   not dead after the instruction, we must allocate
1344
                   a new register and move it */
1345
                if (!IS_DEAD_IARG(i - nb_oargs)) 
1346
                    goto allocate_in_reg;
1347
            }
1348
        }
1349
        reg = ts->reg;
1350
        if (tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1351
            /* nothing to do : the constraint is satisfied */
1352
        } else {
1353
        allocate_in_reg:
1354
            /* allocate a new register matching the constraint 
1355
               and move the temporary register into it */
1356
            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1357
            tcg_out_mov(s, reg, ts->reg);
1358
        }
1359
    iarg_end1:
1360
        new_args[i] = reg;
1361
        const_args[i] = 0;
1362
        tcg_regset_set_reg(allocated_regs, reg);
1363
    iarg_end: ;
1364
    }
1365
    
1366
    /* mark dead temporaries and free the associated registers */
1367
    for(i = 0; i < nb_iargs; i++) {
1368
        arg = args[nb_oargs + i];
1369
        if (IS_DEAD_IARG(i)) {
1370
            ts = &s->temps[arg];
1371
            if (ts->val_type != TEMP_VAL_CONST && !ts->fixed_reg) {
1372
                if (ts->val_type == TEMP_VAL_REG)
1373
                    s->reg_to_temp[ts->reg] = -1;
1374
                ts->val_type = TEMP_VAL_DEAD;
1375
            }
1376
        }
1377
    }
1378

    
1379
    /* XXX: permit generic clobber register list ? */ 
1380
    if (def->flags & TCG_OPF_CALL_CLOBBER) {
1381
        for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1382
            if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
1383
                tcg_reg_free(s, reg);
1384
            }
1385
        }
1386
    }
1387

    
1388
    /* satisfy the output constraints */
1389
    tcg_regset_set(allocated_regs, s->reserved_regs);
1390
    for(k = 0; k < nb_oargs; k++) {
1391
        i = def->sorted_args[k];
1392
        arg = args[i];
1393
        arg_ct = &def->args_ct[i];
1394
        ts = &s->temps[arg];
1395
        if (arg_ct->ct & TCG_CT_ALIAS) {
1396
            reg = new_args[arg_ct->alias_index];
1397
        } else {
1398
            /* if fixed register, we try to use it */
1399
            reg = ts->reg;
1400
            if (ts->fixed_reg &&
1401
                tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1402
                goto oarg_end;
1403
            }
1404
            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1405
        }
1406
        tcg_regset_set_reg(allocated_regs, reg);
1407
        /* if a fixed register is used, then a move will be done afterwards */
1408
        if (!ts->fixed_reg) {
1409
            if (ts->val_type == TEMP_VAL_REG)
1410
                s->reg_to_temp[ts->reg] = -1;
1411
            ts->val_type = TEMP_VAL_REG;
1412
            ts->reg = reg;
1413
            /* temp value is modified, so the value kept in memory is
1414
               potentially not the same */
1415
            ts->mem_coherent = 0; 
1416
            s->reg_to_temp[reg] = arg;
1417
        }
1418
    oarg_end:
1419
        new_args[i] = reg;
1420
    }
1421

    
1422
    if (def->flags & TCG_OPF_BB_END)
1423
        tcg_reg_alloc_bb_end(s);
1424

    
1425
    /* emit instruction */
1426
    tcg_out_op(s, opc, new_args, const_args);
1427
    
1428
    /* move the outputs in the correct register if needed */
1429
    for(i = 0; i < nb_oargs; i++) {
1430
        ts = &s->temps[args[i]];
1431
        reg = new_args[i];
1432
        if (ts->fixed_reg && ts->reg != reg) {
1433
            tcg_out_mov(s, ts->reg, reg);
1434
        }
1435
    }
1436
}
1437

    
1438
static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
1439
                              int opc, const TCGArg *args,
1440
                              unsigned int dead_iargs)
1441
{
1442
    int nb_iargs, nb_oargs, flags, nb_regs, i, reg, nb_params;
1443
    TCGArg arg, func_arg;
1444
    TCGTemp *ts;
1445
    tcg_target_long stack_offset, call_stack_size, func_addr;
1446
    int const_func_arg;
1447
    TCGRegSet allocated_regs;
1448
    const TCGArgConstraint *arg_ct;
1449

    
1450
    arg = *args++;
1451

    
1452
    nb_oargs = arg >> 16;
1453
    nb_iargs = arg & 0xffff;
1454
    nb_params = nb_iargs - 1;
1455

    
1456
    flags = args[nb_oargs + nb_iargs];
1457

    
1458
    nb_regs = tcg_target_get_call_iarg_regs_count(flags);
1459
    if (nb_regs > nb_params)
1460
        nb_regs = nb_params;
1461

    
1462
    /* assign stack slots first */
1463
    /* XXX: preallocate call stack */
1464
    call_stack_size = (nb_params - nb_regs) * sizeof(tcg_target_long);
1465
    call_stack_size = (call_stack_size + TCG_TARGET_STACK_ALIGN - 1) & 
1466
        ~(TCG_TARGET_STACK_ALIGN - 1);
1467
#ifdef TCG_TARGET_STACK_GROWSUP
1468
    tcg_out_addi(s, TCG_REG_CALL_STACK, call_stack_size);
1469
#else
1470
    tcg_out_addi(s, TCG_REG_CALL_STACK, -call_stack_size);
1471
#endif
1472

    
1473
    stack_offset = 0;
1474
    for(i = nb_regs; i < nb_params; i++) {
1475
        arg = args[nb_oargs + i];
1476
        ts = &s->temps[arg];
1477
        if (ts->val_type == TEMP_VAL_REG) {
1478
            tcg_out_st(s, ts->type, ts->reg, TCG_REG_CALL_STACK, stack_offset);
1479
        } else if (ts->val_type == TEMP_VAL_MEM) {
1480
            reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], 
1481
                                s->reserved_regs);
1482
            /* XXX: not correct if reading values from the stack */
1483
            tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1484
            tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
1485
        } else if (ts->val_type == TEMP_VAL_CONST) {
1486
            reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], 
1487
                                s->reserved_regs);
1488
            /* XXX: sign extend may be needed on some targets */
1489
            tcg_out_movi(s, ts->type, reg, ts->val);
1490
            tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
1491
        } else {
1492
            tcg_abort();
1493
        }
1494
#ifdef TCG_TARGET_STACK_GROWSUP
1495
        stack_offset -= sizeof(tcg_target_long);
1496
#else
1497
        stack_offset += sizeof(tcg_target_long);
1498
#endif
1499
    }
1500
    
1501
    /* assign input registers */
1502
    tcg_regset_set(allocated_regs, s->reserved_regs);
1503
    for(i = 0; i < nb_regs; i++) {
1504
        arg = args[nb_oargs + i];
1505
        ts = &s->temps[arg];
1506
        reg = tcg_target_call_iarg_regs[i];
1507
        tcg_reg_free(s, reg);
1508
        if (ts->val_type == TEMP_VAL_REG) {
1509
            if (ts->reg != reg) {
1510
                tcg_out_mov(s, reg, ts->reg);
1511
            }
1512
        } else if (ts->val_type == TEMP_VAL_MEM) {
1513
            tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1514
        } else if (ts->val_type == TEMP_VAL_CONST) {
1515
            /* XXX: sign extend ? */
1516
            tcg_out_movi(s, ts->type, reg, ts->val);
1517
        } else {
1518
            tcg_abort();
1519
        }
1520
        tcg_regset_set_reg(allocated_regs, reg);
1521
    }
1522
    
1523
    /* assign function address */
1524
    func_arg = args[nb_oargs + nb_iargs - 1];
1525
    arg_ct = &def->args_ct[0];
1526
    ts = &s->temps[func_arg];
1527
    func_addr = ts->val;
1528
#ifdef HOST_HPPA
1529
    func_addr = (tcg_target_long)__canonicalize_funcptr_for_compare((void *)func_addr);
1530
#endif
1531
    const_func_arg = 0;
1532
    if (ts->val_type == TEMP_VAL_MEM) {
1533
        reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1534
        tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1535
        func_arg = reg;
1536
    } else if (ts->val_type == TEMP_VAL_REG) {
1537
        reg = ts->reg;
1538
        if (!tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1539
            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1540
            tcg_out_mov(s, reg, ts->reg);
1541
        }
1542
        func_arg = reg;
1543
    } else if (ts->val_type == TEMP_VAL_CONST) {
1544
        if (tcg_target_const_match(func_addr, arg_ct)) {
1545
            const_func_arg = 1;
1546
            func_arg = func_addr;
1547
        } else {
1548
            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1549
            tcg_out_movi(s, ts->type, reg, func_addr);
1550
            func_arg = reg;
1551
        }
1552
    } else {
1553
        tcg_abort();
1554
    }
1555
    
1556
    /* mark dead temporaries and free the associated registers */
1557
    for(i = 0; i < nb_params; i++) {
1558
        arg = args[nb_oargs + i];
1559
        if (IS_DEAD_IARG(i)) {
1560
            ts = &s->temps[arg];
1561
            if (ts->val_type != TEMP_VAL_CONST && !ts->fixed_reg) {
1562
                if (ts->val_type == TEMP_VAL_REG)
1563
                    s->reg_to_temp[ts->reg] = -1;
1564
                ts->val_type = TEMP_VAL_DEAD;
1565
            }
1566
        }
1567
    }
1568
    
1569
    /* clobber call registers */
1570
    for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1571
        if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
1572
            tcg_reg_free(s, reg);
1573
        }
1574
    }
1575
    
1576
    /* store globals and free associated registers (we assume the call
1577
       can modify any global. */
1578
    for(i = 0; i < s->nb_globals; i++) {
1579
        ts = &s->temps[i];
1580
        if (!ts->fixed_reg) {
1581
            if (ts->val_type == TEMP_VAL_REG) {
1582
                tcg_reg_free(s, ts->reg);
1583
            }
1584
        }
1585
    }
1586

    
1587
    tcg_out_op(s, opc, &func_arg, &const_func_arg);
1588
    
1589
#ifdef TCG_TARGET_STACK_GROWSUP
1590
    tcg_out_addi(s, TCG_REG_CALL_STACK, -call_stack_size);
1591
#else
1592
    tcg_out_addi(s, TCG_REG_CALL_STACK, call_stack_size);
1593
#endif
1594

    
1595
    /* assign output registers and emit moves if needed */
1596
    for(i = 0; i < nb_oargs; i++) {
1597
        arg = args[i];
1598
        ts = &s->temps[arg];
1599
        reg = tcg_target_call_oarg_regs[i];
1600
        tcg_reg_free(s, reg);
1601
        if (ts->fixed_reg) {
1602
            if (ts->reg != reg) {
1603
                tcg_out_mov(s, ts->reg, reg);
1604
            }
1605
        } else {
1606
            if (ts->val_type == TEMP_VAL_REG)
1607
                s->reg_to_temp[ts->reg] = -1;
1608
            ts->val_type = TEMP_VAL_REG;
1609
            ts->reg = reg;
1610
            ts->mem_coherent = 0; 
1611
            s->reg_to_temp[reg] = arg;
1612
        }
1613
    }
1614
    
1615
    return nb_iargs + nb_oargs + def->nb_cargs + 1;
1616
}
1617

    
1618
#ifdef CONFIG_PROFILER
1619

    
1620
static int64_t dyngen_table_op_count[NB_OPS];
1621

    
1622
void dump_op_count(void)
1623
{
1624
    int i;
1625
    FILE *f;
1626
    f = fopen("/tmp/op1.log", "w");
1627
    for(i = 0; i < INDEX_op_end; i++) {
1628
        fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name, dyngen_table_op_count[i]);
1629
    }
1630
    fclose(f);
1631
    f = fopen("/tmp/op2.log", "w");
1632
    for(i = INDEX_op_end; i < NB_OPS; i++) {
1633
        fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name, dyngen_table_op_count[i]);
1634
    }
1635
    fclose(f);
1636
}
1637
#endif
1638

    
1639

    
1640
static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
1641
                                      long search_pc)
1642
{
1643
    int opc, op_index, macro_op_index;
1644
    const TCGOpDef *def;
1645
    unsigned int dead_iargs;
1646
    const TCGArg *args;
1647

    
1648
#ifdef DEBUG_DISAS
1649
    if (unlikely(loglevel & CPU_LOG_TB_OP)) {
1650
        fprintf(logfile, "OP:\n");
1651
        tcg_dump_ops(s, logfile);
1652
        fprintf(logfile, "\n");
1653
    }
1654
#endif
1655

    
1656
    tcg_liveness_analysis(s);
1657

    
1658
#ifdef DEBUG_DISAS
1659
    if (unlikely(loglevel & CPU_LOG_TB_OP_OPT)) {
1660
        fprintf(logfile, "OP after la:\n");
1661
        tcg_dump_ops(s, logfile);
1662
        fprintf(logfile, "\n");
1663
    }
1664
#endif
1665

    
1666
    tcg_reg_alloc_start(s);
1667

    
1668
    s->code_buf = gen_code_buf;
1669
    s->code_ptr = gen_code_buf;
1670

    
1671
    macro_op_index = -1;
1672
    args = gen_opparam_buf;
1673
    op_index = 0;
1674

    
1675
#ifdef TCG_TARGET_NEEDS_PROLOGUE
1676
    tcg_target_prologue(s);
1677
#endif
1678

    
1679
    for(;;) {
1680
        opc = gen_opc_buf[op_index];
1681
#ifdef CONFIG_PROFILER
1682
        dyngen_table_op_count[opc]++;
1683
#endif
1684
        def = &tcg_op_defs[opc];
1685
#if 0
1686
        printf("%s: %d %d %d\n", def->name,
1687
               def->nb_oargs, def->nb_iargs, def->nb_cargs);
1688
        //        dump_regs(s);
1689
#endif
1690
        switch(opc) {
1691
        case INDEX_op_mov_i32:
1692
#if TCG_TARGET_REG_BITS == 64
1693
        case INDEX_op_mov_i64:
1694
#endif
1695
            dead_iargs = s->op_dead_iargs[op_index];
1696
            tcg_reg_alloc_mov(s, def, args, dead_iargs);
1697
            break;
1698
        case INDEX_op_nop:
1699
        case INDEX_op_nop1:
1700
        case INDEX_op_nop2:
1701
        case INDEX_op_nop3:
1702
            break;
1703
        case INDEX_op_nopn:
1704
            args += args[0];
1705
            goto next;
1706
        case INDEX_op_discard:
1707
            {
1708
                TCGTemp *ts;
1709
                ts = &s->temps[args[0]];
1710
                /* mark the temporary as dead */
1711
                if (ts->val_type != TEMP_VAL_CONST && !ts->fixed_reg) {
1712
                    if (ts->val_type == TEMP_VAL_REG)
1713
                        s->reg_to_temp[ts->reg] = -1;
1714
                    ts->val_type = TEMP_VAL_DEAD;
1715
                }
1716
            }
1717
            break;
1718
        case INDEX_op_macro_goto:
1719
            macro_op_index = op_index; /* only used for exceptions */
1720
            op_index = args[0] - 1;
1721
            args = gen_opparam_buf + args[1];
1722
            goto next;
1723
        case INDEX_op_macro_end:
1724
            macro_op_index = -1; /* only used for exceptions */
1725
            op_index = args[0] - 1;
1726
            args = gen_opparam_buf + args[1];
1727
            goto next;
1728
        case INDEX_op_macro_start:
1729
            /* must never happen here */
1730
            tcg_abort();
1731
        case INDEX_op_set_label:
1732
            tcg_reg_alloc_bb_end(s);
1733
            tcg_out_label(s, args[0], (long)s->code_ptr);
1734
            break;
1735
        case INDEX_op_call:
1736
            dead_iargs = s->op_dead_iargs[op_index];
1737
            args += tcg_reg_alloc_call(s, def, opc, args, dead_iargs);
1738
            goto next;
1739
        case INDEX_op_end:
1740
            goto the_end;
1741

    
1742
#ifndef CONFIG_NO_DYNGEN_OP
1743
        case 0 ... INDEX_op_end - 1:
1744
            /* legacy dyngen ops */
1745
#ifdef CONFIG_PROFILER
1746
            {
1747
                extern int64_t dyngen_old_op_count;
1748
                dyngen_old_op_count++;
1749
            }
1750
#endif
1751
            tcg_reg_alloc_bb_end(s);
1752
            if (search_pc >= 0) {
1753
                s->code_ptr += def->copy_size;
1754
                args += def->nb_args;
1755
            } else {
1756
                args = dyngen_op(s, opc, args);
1757
            }
1758
            goto next;
1759
#endif
1760
        default:
1761
            /* Note: in order to speed up the code, it would be much
1762
               faster to have specialized register allocator functions for
1763
               some common argument patterns */
1764
            dead_iargs = s->op_dead_iargs[op_index];
1765
            tcg_reg_alloc_op(s, def, opc, args, dead_iargs);
1766
            break;
1767
        }
1768
        args += def->nb_args;
1769
    next: ;
1770
        if (search_pc >= 0 && search_pc < s->code_ptr - gen_code_buf) {
1771
            if (macro_op_index >= 0)
1772
                return macro_op_index;
1773
            else
1774
                return op_index;
1775
        }
1776
        op_index++;
1777
#ifndef NDEBUG
1778
        check_regs(s);
1779
#endif
1780
    }
1781
 the_end:
1782
    return -1;
1783
}
1784

    
1785
int dyngen_code(TCGContext *s, uint8_t *gen_code_buf)
1786
{
1787
#ifdef CONFIG_PROFILER
1788
    {
1789
        extern int64_t dyngen_op_count;
1790
        extern int dyngen_op_count_max;
1791
        int n;
1792
        n = (gen_opc_ptr - gen_opc_buf);
1793
        dyngen_op_count += n;
1794
        if (n > dyngen_op_count_max)
1795
            dyngen_op_count_max = n;
1796
    }
1797
#endif
1798

    
1799
    tcg_gen_code_common(s, gen_code_buf, -1);
1800

    
1801
    /* flush instruction cache */
1802
    flush_icache_range((unsigned long)gen_code_buf, 
1803
                       (unsigned long)s->code_ptr);
1804
    return s->code_ptr -  gen_code_buf;
1805
}
1806

    
1807
/* Return the index of the micro operation such as the pc after is <
1808
   offset bytes from the start of the TB.  The contents of gen_code_buf must
1809
   not be changed, though writing the same values is ok.
1810
   Return -1 if not found. */
1811
int dyngen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, long offset)
1812
{
1813
    return tcg_gen_code_common(s, gen_code_buf, offset);
1814
}