~vcs-imports/qemu/git

« back to all changes in this revision

Viewing changes to tcg/tcg.c

  • Committer: blueswir1
  • Date: 2007-11-25 08:48:16 UTC
  • Revision ID: git-v1:b76482e76560345c00e7d6c89199ced204a926d2
 Fix buffer mux handling for unconnected serial ports


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3737 c046a42c-6fe2-441c-8c8c-71466251a162

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
 
static TCGRegSet tcg_target_available_regs[2];
67
 
static 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
 
void tcg_context_init(TCGContext *s)
200
 
{
201
 
    int op, total_args, n;
202
 
    TCGOpDef *def;
203
 
    TCGArgConstraint *args_ct;
204
 
    int *sorted_args;
205
 
 
206
 
    memset(s, 0, sizeof(*s));
207
 
    s->temps = s->static_temps;
208
 
    s->nb_globals = 0;
209
 
    
210
 
    /* Count total number of arguments and allocate the corresponding
211
 
       space */
212
 
    total_args = 0;
213
 
    for(op = 0; op < NB_OPS; op++) {
214
 
        def = &tcg_op_defs[op];
215
 
        n = def->nb_iargs + def->nb_oargs;
216
 
        total_args += n;
217
 
    }
218
 
 
219
 
    args_ct = qemu_malloc(sizeof(TCGArgConstraint) * total_args);
220
 
    sorted_args = qemu_malloc(sizeof(int) * total_args);
221
 
 
222
 
    for(op = 0; op < NB_OPS; op++) {
223
 
        def = &tcg_op_defs[op];
224
 
        def->args_ct = args_ct;
225
 
        def->sorted_args = sorted_args;
226
 
        n = def->nb_iargs + def->nb_oargs;
227
 
        sorted_args += n;
228
 
        args_ct += n;
229
 
    }
230
 
    
231
 
    tcg_target_init(s);
232
 
 
233
 
    /* init global prologue and epilogue */
234
 
    s->code_buf = code_gen_prologue;
235
 
    s->code_ptr = s->code_buf;
236
 
    tcg_target_qemu_prologue(s);
237
 
    flush_icache_range((unsigned long)s->code_buf, 
238
 
                       (unsigned long)s->code_ptr);
239
 
}
240
 
 
241
 
void tcg_set_frame(TCGContext *s, int reg,
242
 
                   tcg_target_long start, tcg_target_long size)
243
 
{
244
 
    s->frame_start = start;
245
 
    s->frame_end = start + size;
246
 
    s->frame_reg = reg;
247
 
}
248
 
 
249
 
void tcg_func_start(TCGContext *s)
250
 
{
251
 
    int i;
252
 
    tcg_pool_reset(s);
253
 
    s->nb_temps = s->nb_globals;
254
 
    for(i = 0; i < (TCG_TYPE_COUNT * 2); i++)
255
 
        s->first_free_temp[i] = -1;
256
 
    s->labels = tcg_malloc(sizeof(TCGLabel) * TCG_MAX_LABELS);
257
 
    s->nb_labels = 0;
258
 
    s->current_frame_offset = s->frame_start;
259
 
 
260
 
    gen_opc_ptr = gen_opc_buf;
261
 
    gen_opparam_ptr = gen_opparam_buf;
262
 
}
263
 
 
264
 
static inline void tcg_temp_alloc(TCGContext *s, int n)
265
 
{
266
 
    if (n > TCG_MAX_TEMPS)
267
 
        tcg_abort();
268
 
}
269
 
 
270
 
TCGv tcg_global_reg_new(TCGType type, int reg, const char *name)
271
 
{
272
 
    TCGContext *s = &tcg_ctx;
273
 
    TCGTemp *ts;
274
 
    int idx;
275
 
 
276
 
#if TCG_TARGET_REG_BITS == 32
277
 
    if (type != TCG_TYPE_I32)
278
 
        tcg_abort();
279
 
#endif
280
 
    if (tcg_regset_test_reg(s->reserved_regs, reg))
281
 
        tcg_abort();
282
 
    idx = s->nb_globals;
283
 
    tcg_temp_alloc(s, s->nb_globals + 1);
284
 
    ts = &s->temps[s->nb_globals];
285
 
    ts->base_type = type;
286
 
    ts->type = type;
287
 
    ts->fixed_reg = 1;
288
 
    ts->reg = reg;
289
 
    ts->name = name;
290
 
    s->nb_globals++;
291
 
    tcg_regset_set_reg(s->reserved_regs, reg);
292
 
    return MAKE_TCGV(idx);
293
 
}
294
 
 
295
 
#if TCG_TARGET_REG_BITS == 32
296
 
/* temporary hack to avoid register shortage for tcg_qemu_st64() */
297
 
TCGv tcg_global_reg2_new_hack(TCGType type, int reg1, int reg2, 
298
 
                              const char *name)
299
 
{
300
 
    TCGContext *s = &tcg_ctx;
301
 
    TCGTemp *ts;
302
 
    int idx;
303
 
    char buf[64];
304
 
 
305
 
    if (type != TCG_TYPE_I64)
306
 
        tcg_abort();
307
 
    idx = s->nb_globals;
308
 
    tcg_temp_alloc(s, s->nb_globals + 2);
309
 
    ts = &s->temps[s->nb_globals];
310
 
    ts->base_type = type;
311
 
    ts->type = TCG_TYPE_I32;
312
 
    ts->fixed_reg = 1;
313
 
    ts->reg = reg1;
314
 
    pstrcpy(buf, sizeof(buf), name);
315
 
    pstrcat(buf, sizeof(buf), "_0");
316
 
    ts->name = strdup(buf);
317
 
 
318
 
    ts++;
319
 
    ts->base_type = type;
320
 
    ts->type = TCG_TYPE_I32;
321
 
    ts->fixed_reg = 1;
322
 
    ts->reg = reg2;
323
 
    pstrcpy(buf, sizeof(buf), name);
324
 
    pstrcat(buf, sizeof(buf), "_1");
325
 
    ts->name = strdup(buf);
326
 
 
327
 
    s->nb_globals += 2;
328
 
    return MAKE_TCGV(idx);
329
 
}
330
 
#endif
331
 
 
332
 
TCGv tcg_global_mem_new(TCGType type, int reg, tcg_target_long offset,
333
 
                        const char *name)
334
 
{
335
 
    TCGContext *s = &tcg_ctx;
336
 
    TCGTemp *ts;
337
 
    int idx;
338
 
 
339
 
    idx = s->nb_globals;
340
 
#if TCG_TARGET_REG_BITS == 32
341
 
    if (type == TCG_TYPE_I64) {
342
 
        char buf[64];
343
 
        tcg_temp_alloc(s, s->nb_globals + 2);
344
 
        ts = &s->temps[s->nb_globals];
345
 
        ts->base_type = type;
346
 
        ts->type = TCG_TYPE_I32;
347
 
        ts->fixed_reg = 0;
348
 
        ts->mem_allocated = 1;
349
 
        ts->mem_reg = reg;
350
 
#ifdef TCG_TARGET_WORDS_BIGENDIAN
351
 
        ts->mem_offset = offset + 4;
352
 
#else
353
 
        ts->mem_offset = offset;
354
 
#endif
355
 
        pstrcpy(buf, sizeof(buf), name);
356
 
        pstrcat(buf, sizeof(buf), "_0");
357
 
        ts->name = strdup(buf);
358
 
        ts++;
359
 
 
360
 
        ts->base_type = type;
361
 
        ts->type = TCG_TYPE_I32;
362
 
        ts->fixed_reg = 0;
363
 
        ts->mem_allocated = 1;
364
 
        ts->mem_reg = reg;
365
 
#ifdef TCG_TARGET_WORDS_BIGENDIAN
366
 
        ts->mem_offset = offset;
367
 
#else
368
 
        ts->mem_offset = offset + 4;
369
 
#endif
370
 
        pstrcpy(buf, sizeof(buf), name);
371
 
        pstrcat(buf, sizeof(buf), "_1");
372
 
        ts->name = strdup(buf);
373
 
 
374
 
        s->nb_globals += 2;
375
 
    } else
376
 
#endif
377
 
    {
378
 
        tcg_temp_alloc(s, s->nb_globals + 1);
379
 
        ts = &s->temps[s->nb_globals];
380
 
        ts->base_type = type;
381
 
        ts->type = type;
382
 
        ts->fixed_reg = 0;
383
 
        ts->mem_allocated = 1;
384
 
        ts->mem_reg = reg;
385
 
        ts->mem_offset = offset;
386
 
        ts->name = name;
387
 
        s->nb_globals++;
388
 
    }
389
 
    return MAKE_TCGV(idx);
390
 
}
391
 
 
392
 
TCGv tcg_temp_new_internal(TCGType type, int temp_local)
393
 
{
394
 
    TCGContext *s = &tcg_ctx;
395
 
    TCGTemp *ts;
396
 
    int idx, k;
397
 
 
398
 
    k = type;
399
 
    if (temp_local)
400
 
        k += TCG_TYPE_COUNT;
401
 
    idx = s->first_free_temp[k];
402
 
    if (idx != -1) {
403
 
        /* There is already an available temp with the
404
 
           right type */
405
 
        ts = &s->temps[idx];
406
 
        s->first_free_temp[k] = ts->next_free_temp;
407
 
        ts->temp_allocated = 1;
408
 
        assert(ts->temp_local == temp_local);
409
 
    } else {
410
 
        idx = s->nb_temps;
411
 
#if TCG_TARGET_REG_BITS == 32
412
 
        if (type == TCG_TYPE_I64) {
413
 
            tcg_temp_alloc(s, s->nb_temps + 2);
414
 
            ts = &s->temps[s->nb_temps];
415
 
            ts->base_type = type;
416
 
            ts->type = TCG_TYPE_I32;
417
 
            ts->temp_allocated = 1;
418
 
            ts->temp_local = temp_local;
419
 
            ts->name = NULL;
420
 
            ts++;
421
 
            ts->base_type = TCG_TYPE_I32;
422
 
            ts->type = TCG_TYPE_I32;
423
 
            ts->temp_allocated = 1;
424
 
            ts->temp_local = temp_local;
425
 
            ts->name = NULL;
426
 
            s->nb_temps += 2;
427
 
        } else
428
 
#endif
429
 
        {
430
 
            tcg_temp_alloc(s, s->nb_temps + 1);
431
 
            ts = &s->temps[s->nb_temps];
432
 
            ts->base_type = type;
433
 
            ts->type = type;
434
 
            ts->temp_allocated = 1;
435
 
            ts->temp_local = temp_local;
436
 
            ts->name = NULL;
437
 
            s->nb_temps++;
438
 
        }
439
 
    }
440
 
    return MAKE_TCGV(idx);
441
 
}
442
 
 
443
 
void tcg_temp_free(TCGv arg)
444
 
{
445
 
    TCGContext *s = &tcg_ctx;
446
 
    TCGTemp *ts;
447
 
    int idx = GET_TCGV(arg);
448
 
    int k;
449
 
 
450
 
    assert(idx >= s->nb_globals && idx < s->nb_temps);
451
 
    ts = &s->temps[idx];
452
 
    assert(ts->temp_allocated != 0);
453
 
    ts->temp_allocated = 0;
454
 
    k = ts->base_type;
455
 
    if (ts->temp_local)
456
 
        k += TCG_TYPE_COUNT;
457
 
    ts->next_free_temp = s->first_free_temp[k];
458
 
    s->first_free_temp[k] = idx;
459
 
}
460
 
 
461
 
 
462
 
TCGv tcg_const_i32(int32_t val)
463
 
{
464
 
    TCGv t0;
465
 
    t0 = tcg_temp_new(TCG_TYPE_I32);
466
 
    tcg_gen_movi_i32(t0, val);
467
 
    return t0;
468
 
}
469
 
 
470
 
TCGv tcg_const_i64(int64_t val)
471
 
{
472
 
    TCGv t0;
473
 
    t0 = tcg_temp_new(TCG_TYPE_I64);
474
 
    tcg_gen_movi_i64(t0, val);
475
 
    return t0;
476
 
}
477
 
 
478
 
TCGv tcg_const_local_i32(int32_t val)
479
 
{
480
 
    TCGv t0;
481
 
    t0 = tcg_temp_local_new(TCG_TYPE_I32);
482
 
    tcg_gen_movi_i32(t0, val);
483
 
    return t0;
484
 
}
485
 
 
486
 
TCGv tcg_const_local_i64(int64_t val)
487
 
{
488
 
    TCGv t0;
489
 
    t0 = tcg_temp_local_new(TCG_TYPE_I64);
490
 
    tcg_gen_movi_i64(t0, val);
491
 
    return t0;
492
 
}
493
 
 
494
 
void tcg_register_helper(void *func, const char *name)
495
 
{
496
 
    TCGContext *s = &tcg_ctx;
497
 
    int n;
498
 
    if ((s->nb_helpers + 1) > s->allocated_helpers) {
499
 
        n = s->allocated_helpers;
500
 
        if (n == 0) {
501
 
            n = 4;
502
 
        } else {
503
 
            n *= 2;
504
 
        }
505
 
        s->helpers = realloc(s->helpers, n * sizeof(TCGHelperInfo));
506
 
        s->allocated_helpers = n;
507
 
    }
508
 
    s->helpers[s->nb_helpers].func = (tcg_target_ulong)func;
509
 
    s->helpers[s->nb_helpers].name = name;
510
 
    s->nb_helpers++;
511
 
}
512
 
 
513
 
static inline TCGType tcg_get_base_type(TCGContext *s, TCGv arg)
514
 
{
515
 
    return s->temps[GET_TCGV(arg)].base_type;
516
 
}
517
 
 
518
 
static void tcg_gen_call_internal(TCGContext *s, TCGv func, 
519
 
                                  unsigned int flags,
520
 
                                  unsigned int nb_rets, const TCGv *rets,
521
 
                                  unsigned int nb_params, const TCGv *params)
522
 
{
523
 
    int i;
524
 
    *gen_opc_ptr++ = INDEX_op_call;
525
 
    *gen_opparam_ptr++ = (nb_rets << 16) | (nb_params + 1);
526
 
    for(i = 0; i < nb_rets; i++) {
527
 
        *gen_opparam_ptr++ = GET_TCGV(rets[i]);
528
 
    }
529
 
    for(i = 0; i < nb_params; i++) {
530
 
        *gen_opparam_ptr++ = GET_TCGV(params[i]);
531
 
    }
532
 
    *gen_opparam_ptr++ = GET_TCGV(func);
533
 
 
534
 
    *gen_opparam_ptr++ = flags;
535
 
    /* total parameters, needed to go backward in the instruction stream */
536
 
    *gen_opparam_ptr++ = 1 + nb_rets + nb_params + 3;
537
 
}
538
 
 
539
 
 
540
 
#if TCG_TARGET_REG_BITS < 64
541
 
/* Note: we convert the 64 bit args to 32 bit and do some alignment
542
 
   and endian swap. Maybe it would be better to do the alignment
543
 
   and endian swap in tcg_reg_alloc_call(). */
544
 
void tcg_gen_call(TCGContext *s, TCGv func, unsigned int flags,
545
 
                  unsigned int nb_rets, const TCGv *rets,
546
 
                  unsigned int nb_params, const TCGv *args1)
547
 
{
548
 
    TCGv ret, *args2, rets_2[2], arg;
549
 
    int j, i, call_type;
550
 
 
551
 
    if (nb_rets == 1) {
552
 
        ret = rets[0];
553
 
        if (tcg_get_base_type(s, ret) == TCG_TYPE_I64) {
554
 
            nb_rets = 2;
555
 
#ifdef TCG_TARGET_WORDS_BIGENDIAN
556
 
            rets_2[0] = TCGV_HIGH(ret);
557
 
            rets_2[1] = ret;
558
 
#else
559
 
            rets_2[0] = ret;
560
 
            rets_2[1] = TCGV_HIGH(ret);
561
 
#endif
562
 
            rets = rets_2;
563
 
        }
564
 
    }
565
 
    args2 = alloca((nb_params * 3) * sizeof(TCGv));
566
 
    j = 0;
567
 
    call_type = (flags & TCG_CALL_TYPE_MASK);
568
 
    for(i = 0; i < nb_params; i++) {
569
 
        arg = args1[i];
570
 
        if (tcg_get_base_type(s, arg) == TCG_TYPE_I64) {
571
 
#ifdef TCG_TARGET_I386
572
 
            /* REGPARM case: if the third parameter is 64 bit, it is
573
 
               allocated on the stack */
574
 
            if (j == 2 && call_type == TCG_CALL_TYPE_REGPARM) {
575
 
                call_type = TCG_CALL_TYPE_REGPARM_2;
576
 
                flags = (flags & ~TCG_CALL_TYPE_MASK) | call_type;
577
 
            }
578
 
            args2[j++] = arg;
579
 
            args2[j++] = TCGV_HIGH(arg);
580
 
#else
581
 
#ifdef TCG_TARGET_CALL_ALIGN_ARGS
582
 
            /* some targets want aligned 64 bit args */
583
 
            if (j & 1) {
584
 
                args2[j++] = TCG_CALL_DUMMY_ARG;
585
 
            }
586
 
#endif
587
 
#ifdef TCG_TARGET_WORDS_BIGENDIAN
588
 
            args2[j++] = TCGV_HIGH(arg);
589
 
            args2[j++] = arg;
590
 
#else
591
 
            args2[j++] = arg;
592
 
            args2[j++] = TCGV_HIGH(arg);
593
 
#endif
594
 
#endif
595
 
        } else {
596
 
            args2[j++] = arg;
597
 
        }
598
 
    }
599
 
    tcg_gen_call_internal(s, func, flags, 
600
 
                          nb_rets, rets, j, args2);
601
 
}
602
 
#else
603
 
void tcg_gen_call(TCGContext *s, TCGv func, unsigned int flags,
604
 
                  unsigned int nb_rets, const TCGv *rets,
605
 
                  unsigned int nb_params, const TCGv *args1)
606
 
{
607
 
    tcg_gen_call_internal(s, func, flags, 
608
 
                          nb_rets, rets, nb_params, args1);
609
 
}
610
 
#endif
611
 
 
612
 
#if TCG_TARGET_REG_BITS == 32
613
 
void tcg_gen_shifti_i64(TCGv ret, TCGv arg1, 
614
 
                        int c, int right, int arith)
615
 
{
616
 
    if (c == 0) {
617
 
        tcg_gen_mov_i32(ret, arg1);
618
 
        tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
619
 
    } else if (c >= 32) {
620
 
        c -= 32;
621
 
        if (right) {
622
 
            if (arith) {
623
 
                tcg_gen_sari_i32(ret, TCGV_HIGH(arg1), c);
624
 
                tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 31);
625
 
            } else {
626
 
                tcg_gen_shri_i32(ret, TCGV_HIGH(arg1), c);
627
 
                tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
628
 
            }
629
 
        } else {
630
 
            tcg_gen_shli_i32(TCGV_HIGH(ret), arg1, c);
631
 
            tcg_gen_movi_i32(ret, 0);
632
 
        }
633
 
    } else {
634
 
        TCGv t0, t1;
635
 
 
636
 
        t0 = tcg_temp_new(TCG_TYPE_I32);
637
 
        t1 = tcg_temp_new(TCG_TYPE_I32);
638
 
        if (right) {
639
 
            tcg_gen_shli_i32(t0, TCGV_HIGH(arg1), 32 - c);
640
 
            if (arith)
641
 
                tcg_gen_sari_i32(t1, TCGV_HIGH(arg1), c);
642
 
            else 
643
 
                tcg_gen_shri_i32(t1, TCGV_HIGH(arg1), c);
644
 
            tcg_gen_shri_i32(ret, arg1, c); 
645
 
            tcg_gen_or_i32(ret, ret, t0);
646
 
            tcg_gen_mov_i32(TCGV_HIGH(ret), t1);
647
 
        } else {
648
 
            tcg_gen_shri_i32(t0, arg1, 32 - c);
649
 
            /* Note: ret can be the same as arg1, so we use t1 */
650
 
            tcg_gen_shli_i32(t1, arg1, c); 
651
 
            tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c);
652
 
            tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t0);
653
 
            tcg_gen_mov_i32(ret, t1);
654
 
        }
655
 
        tcg_temp_free(t0);
656
 
        tcg_temp_free(t1);
657
 
    }
658
 
}
659
 
#endif
660
 
 
661
 
static void tcg_reg_alloc_start(TCGContext *s)
662
 
{
663
 
    int i;
664
 
    TCGTemp *ts;
665
 
    for(i = 0; i < s->nb_globals; i++) {
666
 
        ts = &s->temps[i];
667
 
        if (ts->fixed_reg) {
668
 
            ts->val_type = TEMP_VAL_REG;
669
 
        } else {
670
 
            ts->val_type = TEMP_VAL_MEM;
671
 
        }
672
 
    }
673
 
    for(i = s->nb_globals; i < s->nb_temps; i++) {
674
 
        ts = &s->temps[i];
675
 
        ts->val_type = TEMP_VAL_DEAD;
676
 
        ts->mem_allocated = 0;
677
 
        ts->fixed_reg = 0;
678
 
    }
679
 
    for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
680
 
        s->reg_to_temp[i] = -1;
681
 
    }
682
 
}
683
 
 
684
 
static char *tcg_get_arg_str_idx(TCGContext *s, char *buf, int buf_size,
685
 
                                 int idx)
686
 
{
687
 
    TCGTemp *ts;
688
 
 
689
 
    ts = &s->temps[idx];
690
 
    if (idx < s->nb_globals) {
691
 
        pstrcpy(buf, buf_size, ts->name);
692
 
    } else {
693
 
        if (ts->temp_local) 
694
 
            snprintf(buf, buf_size, "loc%d", idx - s->nb_globals);
695
 
        else
696
 
            snprintf(buf, buf_size, "tmp%d", idx - s->nb_globals);
697
 
    }
698
 
    return buf;
699
 
}
700
 
 
701
 
char *tcg_get_arg_str(TCGContext *s, char *buf, int buf_size, TCGv arg)
702
 
{
703
 
    return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV(arg));
704
 
}
705
 
 
706
 
static int helper_cmp(const void *p1, const void *p2)
707
 
{
708
 
    const TCGHelperInfo *th1 = p1;
709
 
    const TCGHelperInfo *th2 = p2;
710
 
    if (th1->func < th2->func)
711
 
        return -1;
712
 
    else if (th1->func == th2->func)
713
 
        return 0;
714
 
    else
715
 
        return 1;
716
 
}
717
 
 
718
 
/* find helper definition (Note: A hash table would be better) */
719
 
static TCGHelperInfo *tcg_find_helper(TCGContext *s, tcg_target_ulong val)
720
 
{
721
 
    int m, m_min, m_max;
722
 
    TCGHelperInfo *th;
723
 
    tcg_target_ulong v;
724
 
 
725
 
    if (unlikely(!s->helpers_sorted)) {
726
 
        qsort(s->helpers, s->nb_helpers, sizeof(TCGHelperInfo), 
727
 
              helper_cmp);
728
 
        s->helpers_sorted = 1;
729
 
    }
730
 
 
731
 
    /* binary search */
732
 
    m_min = 0;
733
 
    m_max = s->nb_helpers - 1;
734
 
    while (m_min <= m_max) {
735
 
        m = (m_min + m_max) >> 1;
736
 
        th = &s->helpers[m];
737
 
        v = th->func;
738
 
        if (v == val)
739
 
            return th;
740
 
        else if (val < v) {
741
 
            m_max = m - 1;
742
 
        } else {
743
 
            m_min = m + 1;
744
 
        }
745
 
    }
746
 
    return NULL;
747
 
}
748
 
 
749
 
static const char * const cond_name[] =
750
 
{
751
 
    [TCG_COND_EQ] = "eq",
752
 
    [TCG_COND_NE] = "ne",
753
 
    [TCG_COND_LT] = "lt",
754
 
    [TCG_COND_GE] = "ge",
755
 
    [TCG_COND_LE] = "le",
756
 
    [TCG_COND_GT] = "gt",
757
 
    [TCG_COND_LTU] = "ltu",
758
 
    [TCG_COND_GEU] = "geu",
759
 
    [TCG_COND_LEU] = "leu",
760
 
    [TCG_COND_GTU] = "gtu"
761
 
};
762
 
 
763
 
void tcg_dump_ops(TCGContext *s, FILE *outfile)
764
 
{
765
 
    const uint16_t *opc_ptr;
766
 
    const TCGArg *args;
767
 
    TCGArg arg;
768
 
    int c, i, k, nb_oargs, nb_iargs, nb_cargs, first_insn;
769
 
    const TCGOpDef *def;
770
 
    char buf[128];
771
 
 
772
 
    first_insn = 1;
773
 
    opc_ptr = gen_opc_buf;
774
 
    args = gen_opparam_buf;
775
 
    while (opc_ptr < gen_opc_ptr) {
776
 
        c = *opc_ptr++;
777
 
        def = &tcg_op_defs[c];
778
 
        if (c == INDEX_op_debug_insn_start) {
779
 
            uint64_t pc;
780
 
#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
781
 
            pc = ((uint64_t)args[1] << 32) | args[0];
782
 
#else
783
 
            pc = args[0];
784
 
#endif
785
 
            if (!first_insn) 
786
 
                fprintf(outfile, "\n");
787
 
            fprintf(outfile, " ---- 0x%" PRIx64, pc);
788
 
            first_insn = 0;
789
 
            nb_oargs = def->nb_oargs;
790
 
            nb_iargs = def->nb_iargs;
791
 
            nb_cargs = def->nb_cargs;
792
 
        } else if (c == INDEX_op_call) {
793
 
            TCGArg arg;
794
 
 
795
 
            /* variable number of arguments */
796
 
            arg = *args++;
797
 
            nb_oargs = arg >> 16;
798
 
            nb_iargs = arg & 0xffff;
799
 
            nb_cargs = def->nb_cargs;
800
 
 
801
 
            fprintf(outfile, " %s ", def->name);
802
 
 
803
 
            /* function name */
804
 
            fprintf(outfile, "%s",
805
 
                    tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + nb_iargs - 1]));
806
 
            /* flags */
807
 
            fprintf(outfile, ",$0x%" TCG_PRIlx,
808
 
                    args[nb_oargs + nb_iargs]);
809
 
            /* nb out args */
810
 
            fprintf(outfile, ",$%d", nb_oargs);
811
 
            for(i = 0; i < nb_oargs; i++) {
812
 
                fprintf(outfile, ",");
813
 
                fprintf(outfile, "%s",
814
 
                        tcg_get_arg_str_idx(s, buf, sizeof(buf), args[i]));
815
 
            }
816
 
            for(i = 0; i < (nb_iargs - 1); i++) {
817
 
                fprintf(outfile, ",");
818
 
                if (args[nb_oargs + i] == TCG_CALL_DUMMY_ARG) {
819
 
                    fprintf(outfile, "<dummy>");
820
 
                } else {
821
 
                    fprintf(outfile, "%s",
822
 
                            tcg_get_arg_str_idx(s, buf, sizeof(buf), args[nb_oargs + i]));
823
 
                }
824
 
            }
825
 
        } else if (c == INDEX_op_movi_i32 
826
 
#if TCG_TARGET_REG_BITS == 64
827
 
                   || c == INDEX_op_movi_i64
828
 
#endif
829
 
                   ) {
830
 
            tcg_target_ulong val;
831
 
            TCGHelperInfo *th;
832
 
 
833
 
            nb_oargs = def->nb_oargs;
834
 
            nb_iargs = def->nb_iargs;
835
 
            nb_cargs = def->nb_cargs;
836
 
            fprintf(outfile, " %s %s,$", def->name, 
837
 
                    tcg_get_arg_str_idx(s, buf, sizeof(buf), args[0]));
838
 
            val = args[1];
839
 
            th = tcg_find_helper(s, val);
840
 
            if (th) {
841
 
                fprintf(outfile, th->name);
842
 
            } else {
843
 
                if (c == INDEX_op_movi_i32)
844
 
                    fprintf(outfile, "0x%x", (uint32_t)val);
845
 
                else
846
 
                    fprintf(outfile, "0x%" PRIx64 , (uint64_t)val);
847
 
            }
848
 
        } else {
849
 
            fprintf(outfile, " %s ", def->name);
850
 
            if (c == INDEX_op_nopn) {
851
 
                /* variable number of arguments */
852
 
                nb_cargs = *args;
853
 
                nb_oargs = 0;
854
 
                nb_iargs = 0;
855
 
            } else {
856
 
                nb_oargs = def->nb_oargs;
857
 
                nb_iargs = def->nb_iargs;
858
 
                nb_cargs = def->nb_cargs;
859
 
            }
860
 
            
861
 
            k = 0;
862
 
            for(i = 0; i < nb_oargs; i++) {
863
 
                if (k != 0)
864
 
                    fprintf(outfile, ",");
865
 
                fprintf(outfile, "%s",
866
 
                        tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
867
 
            }
868
 
            for(i = 0; i < nb_iargs; i++) {
869
 
                if (k != 0)
870
 
                    fprintf(outfile, ",");
871
 
                fprintf(outfile, "%s",
872
 
                        tcg_get_arg_str_idx(s, buf, sizeof(buf), args[k++]));
873
 
            }
874
 
            if (c == INDEX_op_brcond_i32
875
 
#if TCG_TARGET_REG_BITS == 32
876
 
                || c == INDEX_op_brcond2_i32
877
 
#elif TCG_TARGET_REG_BITS == 64
878
 
                || c == INDEX_op_brcond_i64
879
 
#endif
880
 
                ) {
881
 
                if (args[k] < ARRAY_SIZE(cond_name) && cond_name[args[k]])
882
 
                    fprintf(outfile, ",%s", cond_name[args[k++]]);
883
 
                else
884
 
                    fprintf(outfile, ",$0x%" TCG_PRIlx, args[k++]);
885
 
                i = 1;
886
 
            }
887
 
            else
888
 
                i = 0;
889
 
            for(; i < nb_cargs; i++) {
890
 
                if (k != 0)
891
 
                    fprintf(outfile, ",");
892
 
                arg = args[k++];
893
 
                fprintf(outfile, "$0x%" TCG_PRIlx, arg);
894
 
            }
895
 
        }
896
 
        fprintf(outfile, "\n");
897
 
        args += nb_iargs + nb_oargs + nb_cargs;
898
 
    }
899
 
}
900
 
 
901
 
/* we give more priority to constraints with less registers */
902
 
static int get_constraint_priority(const TCGOpDef *def, int k)
903
 
{
904
 
    const TCGArgConstraint *arg_ct;
905
 
 
906
 
    int i, n;
907
 
    arg_ct = &def->args_ct[k];
908
 
    if (arg_ct->ct & TCG_CT_ALIAS) {
909
 
        /* an alias is equivalent to a single register */
910
 
        n = 1;
911
 
    } else {
912
 
        if (!(arg_ct->ct & TCG_CT_REG))
913
 
            return 0;
914
 
        n = 0;
915
 
        for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
916
 
            if (tcg_regset_test_reg(arg_ct->u.regs, i))
917
 
                n++;
918
 
        }
919
 
    }
920
 
    return TCG_TARGET_NB_REGS - n + 1;
921
 
}
922
 
 
923
 
/* sort from highest priority to lowest */
924
 
static void sort_constraints(TCGOpDef *def, int start, int n)
925
 
{
926
 
    int i, j, p1, p2, tmp;
927
 
 
928
 
    for(i = 0; i < n; i++)
929
 
        def->sorted_args[start + i] = start + i;
930
 
    if (n <= 1)
931
 
        return;
932
 
    for(i = 0; i < n - 1; i++) {
933
 
        for(j = i + 1; j < n; j++) {
934
 
            p1 = get_constraint_priority(def, def->sorted_args[start + i]);
935
 
            p2 = get_constraint_priority(def, def->sorted_args[start + j]);
936
 
            if (p1 < p2) {
937
 
                tmp = def->sorted_args[start + i];
938
 
                def->sorted_args[start + i] = def->sorted_args[start + j];
939
 
                def->sorted_args[start + j] = tmp;
940
 
            }
941
 
        }
942
 
    }
943
 
}
944
 
 
945
 
void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs)
946
 
{
947
 
    int op;
948
 
    TCGOpDef *def;
949
 
    const char *ct_str;
950
 
    int i, nb_args;
951
 
 
952
 
    for(;;) {
953
 
        if (tdefs->op < 0)
954
 
            break;
955
 
        op = tdefs->op;
956
 
        assert(op >= 0 && op < NB_OPS);
957
 
        def = &tcg_op_defs[op];
958
 
        nb_args = def->nb_iargs + def->nb_oargs;
959
 
        for(i = 0; i < nb_args; i++) {
960
 
            ct_str = tdefs->args_ct_str[i];
961
 
            tcg_regset_clear(def->args_ct[i].u.regs);
962
 
            def->args_ct[i].ct = 0;
963
 
            if (ct_str[0] >= '0' && ct_str[0] <= '9') {
964
 
                int oarg;
965
 
                oarg = ct_str[0] - '0';
966
 
                assert(oarg < def->nb_oargs);
967
 
                assert(def->args_ct[oarg].ct & TCG_CT_REG);
968
 
                /* TCG_CT_ALIAS is for the output arguments. The input
969
 
                   argument is tagged with TCG_CT_IALIAS. */
970
 
                def->args_ct[i] = def->args_ct[oarg];
971
 
                def->args_ct[oarg].ct = TCG_CT_ALIAS;
972
 
                def->args_ct[oarg].alias_index = i;
973
 
                def->args_ct[i].ct |= TCG_CT_IALIAS;
974
 
                def->args_ct[i].alias_index = oarg;
975
 
            } else {
976
 
                for(;;) {
977
 
                    if (*ct_str == '\0')
978
 
                        break;
979
 
                    switch(*ct_str) {
980
 
                    case 'i':
981
 
                        def->args_ct[i].ct |= TCG_CT_CONST;
982
 
                        ct_str++;
983
 
                        break;
984
 
                    default:
985
 
                        if (target_parse_constraint(&def->args_ct[i], &ct_str) < 0) {
986
 
                            fprintf(stderr, "Invalid constraint '%s' for arg %d of operation '%s'\n",
987
 
                                    ct_str, i, def->name);
988
 
                            exit(1);
989
 
                        }
990
 
                    }
991
 
                }
992
 
            }
993
 
        }
994
 
 
995
 
        /* sort the constraints (XXX: this is just an heuristic) */
996
 
        sort_constraints(def, 0, def->nb_oargs);
997
 
        sort_constraints(def, def->nb_oargs, def->nb_iargs);
998
 
 
999
 
#if 0
1000
 
        {
1001
 
            int i;
1002
 
 
1003
 
            printf("%s: sorted=", def->name);
1004
 
            for(i = 0; i < def->nb_oargs + def->nb_iargs; i++)
1005
 
                printf(" %d", def->sorted_args[i]);
1006
 
            printf("\n");
1007
 
        }
1008
 
#endif
1009
 
        tdefs++;
1010
 
    }
1011
 
 
1012
 
}
1013
 
 
1014
 
#ifdef USE_LIVENESS_ANALYSIS
1015
 
 
1016
 
/* set a nop for an operation using 'nb_args' */
1017
 
static inline void tcg_set_nop(TCGContext *s, uint16_t *opc_ptr, 
1018
 
                               TCGArg *args, int nb_args)
1019
 
{
1020
 
    if (nb_args == 0) {
1021
 
        *opc_ptr = INDEX_op_nop;
1022
 
    } else {
1023
 
        *opc_ptr = INDEX_op_nopn;
1024
 
        args[0] = nb_args;
1025
 
        args[nb_args - 1] = nb_args;
1026
 
    }
1027
 
}
1028
 
 
1029
 
/* liveness analysis: end of function: globals are live, temps are
1030
 
   dead. */
1031
 
/* XXX: at this stage, not used as there would be little gains because
1032
 
   most TBs end with a conditional jump. */
1033
 
static inline void tcg_la_func_end(TCGContext *s, uint8_t *dead_temps)
1034
 
{
1035
 
    memset(dead_temps, 0, s->nb_globals);
1036
 
    memset(dead_temps + s->nb_globals, 1, s->nb_temps - s->nb_globals);
1037
 
}
1038
 
 
1039
 
/* liveness analysis: end of basic block: globals are live, temps are
1040
 
   dead, local temps are live. */
1041
 
static inline void tcg_la_bb_end(TCGContext *s, uint8_t *dead_temps)
1042
 
{
1043
 
    int i;
1044
 
    TCGTemp *ts;
1045
 
 
1046
 
    memset(dead_temps, 0, s->nb_globals);
1047
 
    ts = &s->temps[s->nb_globals];
1048
 
    for(i = s->nb_globals; i < s->nb_temps; i++) {
1049
 
        if (ts->temp_local)
1050
 
            dead_temps[i] = 0;
1051
 
        else
1052
 
            dead_temps[i] = 1;
1053
 
        ts++;
1054
 
    }
1055
 
}
1056
 
 
1057
 
/* Liveness analysis : update the opc_dead_iargs array to tell if a
1058
 
   given input arguments is dead. Instructions updating dead
1059
 
   temporaries are removed. */
1060
 
static void tcg_liveness_analysis(TCGContext *s)
1061
 
{
1062
 
    int i, op_index, op, nb_args, nb_iargs, nb_oargs, arg, nb_ops;
1063
 
    TCGArg *args;
1064
 
    const TCGOpDef *def;
1065
 
    uint8_t *dead_temps;
1066
 
    unsigned int dead_iargs;
1067
 
    
1068
 
    gen_opc_ptr++; /* skip end */
1069
 
 
1070
 
    nb_ops = gen_opc_ptr - gen_opc_buf;
1071
 
 
1072
 
    /* XXX: make it really dynamic */
1073
 
    s->op_dead_iargs = tcg_malloc(OPC_BUF_SIZE * sizeof(uint16_t));
1074
 
    
1075
 
    dead_temps = tcg_malloc(s->nb_temps);
1076
 
    memset(dead_temps, 1, s->nb_temps);
1077
 
 
1078
 
    args = gen_opparam_ptr;
1079
 
    op_index = nb_ops - 1;
1080
 
    while (op_index >= 0) {
1081
 
        op = gen_opc_buf[op_index];
1082
 
        def = &tcg_op_defs[op];
1083
 
        switch(op) {
1084
 
        case INDEX_op_call:
1085
 
            {
1086
 
                int call_flags;
1087
 
 
1088
 
                nb_args = args[-1];
1089
 
                args -= nb_args;
1090
 
                nb_iargs = args[0] & 0xffff;
1091
 
                nb_oargs = args[0] >> 16;
1092
 
                args++;
1093
 
                call_flags = args[nb_oargs + nb_iargs];
1094
 
 
1095
 
                /* pure functions can be removed if their result is not
1096
 
                   used */
1097
 
                if (call_flags & TCG_CALL_PURE) {
1098
 
                    for(i = 0; i < nb_oargs; i++) {
1099
 
                        arg = args[i];
1100
 
                        if (!dead_temps[arg])
1101
 
                            goto do_not_remove_call;
1102
 
                    }
1103
 
                    tcg_set_nop(s, gen_opc_buf + op_index, 
1104
 
                                args - 1, nb_args);
1105
 
                } else {
1106
 
                do_not_remove_call:
1107
 
 
1108
 
                    /* output args are dead */
1109
 
                    for(i = 0; i < nb_oargs; i++) {
1110
 
                        arg = args[i];
1111
 
                        dead_temps[arg] = 1;
1112
 
                    }
1113
 
                    
1114
 
                    /* globals are live (they may be used by the call) */
1115
 
                    memset(dead_temps, 0, s->nb_globals);
1116
 
                    
1117
 
                    /* input args are live */
1118
 
                    dead_iargs = 0;
1119
 
                    for(i = 0; i < nb_iargs; i++) {
1120
 
                        arg = args[i + nb_oargs];
1121
 
                        if (arg != TCG_CALL_DUMMY_ARG) {
1122
 
                            if (dead_temps[arg]) {
1123
 
                                dead_iargs |= (1 << i);
1124
 
                            }
1125
 
                            dead_temps[arg] = 0;
1126
 
                        }
1127
 
                    }
1128
 
                    s->op_dead_iargs[op_index] = dead_iargs;
1129
 
                }
1130
 
                args--;
1131
 
            }
1132
 
            break;
1133
 
        case INDEX_op_set_label:
1134
 
            args--;
1135
 
            /* mark end of basic block */
1136
 
            tcg_la_bb_end(s, dead_temps);
1137
 
            break;
1138
 
        case INDEX_op_debug_insn_start:
1139
 
            args -= def->nb_args;
1140
 
            break;
1141
 
        case INDEX_op_nopn:
1142
 
            nb_args = args[-1];
1143
 
            args -= nb_args;
1144
 
            break;
1145
 
        case INDEX_op_discard:
1146
 
            args--;
1147
 
            /* mark the temporary as dead */
1148
 
            dead_temps[args[0]] = 1;
1149
 
            break;
1150
 
        case INDEX_op_end:
1151
 
            break;
1152
 
            /* XXX: optimize by hardcoding common cases (e.g. triadic ops) */
1153
 
        default:
1154
 
            if (op > INDEX_op_end) {
1155
 
                args -= def->nb_args;
1156
 
                nb_iargs = def->nb_iargs;
1157
 
                nb_oargs = def->nb_oargs;
1158
 
 
1159
 
                /* Test if the operation can be removed because all
1160
 
                   its outputs are dead. We assume that nb_oargs == 0
1161
 
                   implies side effects */
1162
 
                if (!(def->flags & TCG_OPF_SIDE_EFFECTS) && nb_oargs != 0) {
1163
 
                    for(i = 0; i < nb_oargs; i++) {
1164
 
                        arg = args[i];
1165
 
                        if (!dead_temps[arg])
1166
 
                            goto do_not_remove;
1167
 
                    }
1168
 
                    tcg_set_nop(s, gen_opc_buf + op_index, args, def->nb_args);
1169
 
#ifdef CONFIG_PROFILER
1170
 
                    s->del_op_count++;
1171
 
#endif
1172
 
                } else {
1173
 
                do_not_remove:
1174
 
 
1175
 
                    /* output args are dead */
1176
 
                    for(i = 0; i < nb_oargs; i++) {
1177
 
                        arg = args[i];
1178
 
                        dead_temps[arg] = 1;
1179
 
                    }
1180
 
                    
1181
 
                    /* if end of basic block, update */
1182
 
                    if (def->flags & TCG_OPF_BB_END) {
1183
 
                        tcg_la_bb_end(s, dead_temps);
1184
 
                    } else if (def->flags & TCG_OPF_CALL_CLOBBER) {
1185
 
                        /* globals are live */
1186
 
                        memset(dead_temps, 0, s->nb_globals);
1187
 
                    }
1188
 
                    
1189
 
                    /* input args are live */
1190
 
                    dead_iargs = 0;
1191
 
                    for(i = 0; i < nb_iargs; i++) {
1192
 
                        arg = args[i + nb_oargs];
1193
 
                        if (dead_temps[arg]) {
1194
 
                            dead_iargs |= (1 << i);
1195
 
                        }
1196
 
                        dead_temps[arg] = 0;
1197
 
                    }
1198
 
                    s->op_dead_iargs[op_index] = dead_iargs;
1199
 
                }
1200
 
            } else {
1201
 
                /* legacy dyngen operations */
1202
 
                args -= def->nb_args;
1203
 
                /* mark end of basic block */
1204
 
                tcg_la_bb_end(s, dead_temps);
1205
 
            }
1206
 
            break;
1207
 
        }
1208
 
        op_index--;
1209
 
    }
1210
 
 
1211
 
    if (args != gen_opparam_buf)
1212
 
        tcg_abort();
1213
 
}
1214
 
#else
1215
 
/* dummy liveness analysis */
1216
 
void tcg_liveness_analysis(TCGContext *s)
1217
 
{
1218
 
    int nb_ops;
1219
 
    nb_ops = gen_opc_ptr - gen_opc_buf;
1220
 
 
1221
 
    s->op_dead_iargs = tcg_malloc(nb_ops * sizeof(uint16_t));
1222
 
    memset(s->op_dead_iargs, 0, nb_ops * sizeof(uint16_t));
1223
 
}
1224
 
#endif
1225
 
 
1226
 
#ifndef NDEBUG
1227
 
static void dump_regs(TCGContext *s)
1228
 
{
1229
 
    TCGTemp *ts;
1230
 
    int i;
1231
 
    char buf[64];
1232
 
 
1233
 
    for(i = 0; i < s->nb_temps; i++) {
1234
 
        ts = &s->temps[i];
1235
 
        printf("  %10s: ", tcg_get_arg_str_idx(s, buf, sizeof(buf), i));
1236
 
        switch(ts->val_type) {
1237
 
        case TEMP_VAL_REG:
1238
 
            printf("%s", tcg_target_reg_names[ts->reg]);
1239
 
            break;
1240
 
        case TEMP_VAL_MEM:
1241
 
            printf("%d(%s)", (int)ts->mem_offset, tcg_target_reg_names[ts->mem_reg]);
1242
 
            break;
1243
 
        case TEMP_VAL_CONST:
1244
 
            printf("$0x%" TCG_PRIlx, ts->val);
1245
 
            break;
1246
 
        case TEMP_VAL_DEAD:
1247
 
            printf("D");
1248
 
            break;
1249
 
        default:
1250
 
            printf("???");
1251
 
            break;
1252
 
        }
1253
 
        printf("\n");
1254
 
    }
1255
 
 
1256
 
    for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
1257
 
        if (s->reg_to_temp[i] >= 0) {
1258
 
            printf("%s: %s\n", 
1259
 
                   tcg_target_reg_names[i], 
1260
 
                   tcg_get_arg_str_idx(s, buf, sizeof(buf), s->reg_to_temp[i]));
1261
 
        }
1262
 
    }
1263
 
}
1264
 
 
1265
 
static void check_regs(TCGContext *s)
1266
 
{
1267
 
    int reg, k;
1268
 
    TCGTemp *ts;
1269
 
    char buf[64];
1270
 
 
1271
 
    for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1272
 
        k = s->reg_to_temp[reg];
1273
 
        if (k >= 0) {
1274
 
            ts = &s->temps[k];
1275
 
            if (ts->val_type != TEMP_VAL_REG ||
1276
 
                ts->reg != reg) {
1277
 
                printf("Inconsistency for register %s:\n", 
1278
 
                       tcg_target_reg_names[reg]);
1279
 
                goto fail;
1280
 
            }
1281
 
        }
1282
 
    }
1283
 
    for(k = 0; k < s->nb_temps; k++) {
1284
 
        ts = &s->temps[k];
1285
 
        if (ts->val_type == TEMP_VAL_REG &&
1286
 
            !ts->fixed_reg &&
1287
 
            s->reg_to_temp[ts->reg] != k) {
1288
 
                printf("Inconsistency for temp %s:\n", 
1289
 
                       tcg_get_arg_str_idx(s, buf, sizeof(buf), k));
1290
 
        fail:
1291
 
                printf("reg state:\n");
1292
 
                dump_regs(s);
1293
 
                tcg_abort();
1294
 
        }
1295
 
    }
1296
 
}
1297
 
#endif
1298
 
 
1299
 
static void temp_allocate_frame(TCGContext *s, int temp)
1300
 
{
1301
 
    TCGTemp *ts;
1302
 
    ts = &s->temps[temp];
1303
 
    s->current_frame_offset = (s->current_frame_offset + sizeof(tcg_target_long) - 1) & ~(sizeof(tcg_target_long) - 1);
1304
 
    if (s->current_frame_offset + sizeof(tcg_target_long) > s->frame_end)
1305
 
        tcg_abort();
1306
 
    ts->mem_offset = s->current_frame_offset;
1307
 
    ts->mem_reg = s->frame_reg;
1308
 
    ts->mem_allocated = 1;
1309
 
    s->current_frame_offset += sizeof(tcg_target_long);
1310
 
}
1311
 
 
1312
 
/* free register 'reg' by spilling the corresponding temporary if necessary */
1313
 
static void tcg_reg_free(TCGContext *s, int reg)
1314
 
{
1315
 
    TCGTemp *ts;
1316
 
    int temp;
1317
 
 
1318
 
    temp = s->reg_to_temp[reg];
1319
 
    if (temp != -1) {
1320
 
        ts = &s->temps[temp];
1321
 
        assert(ts->val_type == TEMP_VAL_REG);
1322
 
        if (!ts->mem_coherent) {
1323
 
            if (!ts->mem_allocated) 
1324
 
                temp_allocate_frame(s, temp);
1325
 
            tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1326
 
        }
1327
 
        ts->val_type = TEMP_VAL_MEM;
1328
 
        s->reg_to_temp[reg] = -1;
1329
 
    }
1330
 
}
1331
 
 
1332
 
/* Allocate a register belonging to reg1 & ~reg2 */
1333
 
static int tcg_reg_alloc(TCGContext *s, TCGRegSet reg1, TCGRegSet reg2)
1334
 
{
1335
 
    int i, reg;
1336
 
    TCGRegSet reg_ct;
1337
 
 
1338
 
    tcg_regset_andnot(reg_ct, reg1, reg2);
1339
 
 
1340
 
    /* first try free registers */
1341
 
    for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1342
 
        reg = tcg_target_reg_alloc_order[i];
1343
 
        if (tcg_regset_test_reg(reg_ct, reg) && s->reg_to_temp[reg] == -1)
1344
 
            return reg;
1345
 
    }
1346
 
 
1347
 
    /* XXX: do better spill choice */
1348
 
    for(i = 0; i < ARRAY_SIZE(tcg_target_reg_alloc_order); i++) {
1349
 
        reg = tcg_target_reg_alloc_order[i];
1350
 
        if (tcg_regset_test_reg(reg_ct, reg)) {
1351
 
            tcg_reg_free(s, reg);
1352
 
            return reg;
1353
 
        }
1354
 
    }
1355
 
 
1356
 
    tcg_abort();
1357
 
}
1358
 
 
1359
 
/* save a temporary to memory. 'allocated_regs' is used in case a
1360
 
   temporary registers needs to be allocated to store a constant. */
1361
 
static void temp_save(TCGContext *s, int temp, TCGRegSet allocated_regs)
1362
 
{
1363
 
    TCGTemp *ts;
1364
 
    int reg;
1365
 
 
1366
 
    ts = &s->temps[temp];
1367
 
    if (!ts->fixed_reg) {
1368
 
        switch(ts->val_type) {
1369
 
        case TEMP_VAL_REG:
1370
 
            tcg_reg_free(s, ts->reg);
1371
 
            break;
1372
 
        case TEMP_VAL_DEAD:
1373
 
            ts->val_type = TEMP_VAL_MEM;
1374
 
            break;
1375
 
        case TEMP_VAL_CONST:
1376
 
            reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], 
1377
 
                                allocated_regs);
1378
 
            if (!ts->mem_allocated) 
1379
 
                temp_allocate_frame(s, temp);
1380
 
            tcg_out_movi(s, ts->type, reg, ts->val);
1381
 
            tcg_out_st(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1382
 
            ts->val_type = TEMP_VAL_MEM;
1383
 
            break;
1384
 
        case TEMP_VAL_MEM:
1385
 
            break;
1386
 
        default:
1387
 
            tcg_abort();
1388
 
        }
1389
 
    }
1390
 
}
1391
 
 
1392
 
/* save globals to their cannonical location and assume they can be
1393
 
   modified be the following code. 'allocated_regs' is used in case a
1394
 
   temporary registers needs to be allocated to store a constant. */
1395
 
static void save_globals(TCGContext *s, TCGRegSet allocated_regs)
1396
 
{
1397
 
    int i;
1398
 
 
1399
 
    for(i = 0; i < s->nb_globals; i++) {
1400
 
        temp_save(s, i, allocated_regs);
1401
 
    }
1402
 
}
1403
 
 
1404
 
/* at the end of a basic block, we assume all temporaries are dead and
1405
 
   all globals are stored at their canonical location. */
1406
 
static void tcg_reg_alloc_bb_end(TCGContext *s, TCGRegSet allocated_regs)
1407
 
{
1408
 
    TCGTemp *ts;
1409
 
    int i;
1410
 
 
1411
 
    for(i = s->nb_globals; i < s->nb_temps; i++) {
1412
 
        ts = &s->temps[i];
1413
 
        if (ts->temp_local) {
1414
 
            temp_save(s, i, allocated_regs);
1415
 
        } else {
1416
 
            if (ts->val_type == TEMP_VAL_REG) {
1417
 
                s->reg_to_temp[ts->reg] = -1;
1418
 
            }
1419
 
            ts->val_type = TEMP_VAL_DEAD;
1420
 
        }
1421
 
    }
1422
 
 
1423
 
    save_globals(s, allocated_regs);
1424
 
}
1425
 
 
1426
 
#define IS_DEAD_IARG(n) ((dead_iargs >> (n)) & 1)
1427
 
 
1428
 
static void tcg_reg_alloc_movi(TCGContext *s, const TCGArg *args)
1429
 
{
1430
 
    TCGTemp *ots;
1431
 
    tcg_target_ulong val;
1432
 
 
1433
 
    ots = &s->temps[args[0]];
1434
 
    val = args[1];
1435
 
 
1436
 
    if (ots->fixed_reg) {
1437
 
        /* for fixed registers, we do not do any constant
1438
 
           propagation */
1439
 
        tcg_out_movi(s, ots->type, ots->reg, val);
1440
 
    } else {
1441
 
        /* The movi is not explicitly generated here */
1442
 
        if (ots->val_type == TEMP_VAL_REG)
1443
 
            s->reg_to_temp[ots->reg] = -1;
1444
 
        ots->val_type = TEMP_VAL_CONST;
1445
 
        ots->val = val;
1446
 
    }
1447
 
}
1448
 
 
1449
 
static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
1450
 
                              const TCGArg *args,
1451
 
                              unsigned int dead_iargs)
1452
 
{
1453
 
    TCGTemp *ts, *ots;
1454
 
    int reg;
1455
 
    const TCGArgConstraint *arg_ct;
1456
 
 
1457
 
    ots = &s->temps[args[0]];
1458
 
    ts = &s->temps[args[1]];
1459
 
    arg_ct = &def->args_ct[0];
1460
 
 
1461
 
    /* XXX: always mark arg dead if IS_DEAD_IARG(0) */
1462
 
    if (ts->val_type == TEMP_VAL_REG) {
1463
 
        if (IS_DEAD_IARG(0) && !ts->fixed_reg && !ots->fixed_reg) {
1464
 
            /* the mov can be suppressed */
1465
 
            if (ots->val_type == TEMP_VAL_REG)
1466
 
                s->reg_to_temp[ots->reg] = -1;
1467
 
            reg = ts->reg;
1468
 
            s->reg_to_temp[reg] = -1;
1469
 
            ts->val_type = TEMP_VAL_DEAD;
1470
 
        } else {
1471
 
            if (ots->val_type == TEMP_VAL_REG) {
1472
 
                reg = ots->reg;
1473
 
            } else {
1474
 
                reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1475
 
            }
1476
 
            if (ts->reg != reg) {
1477
 
                tcg_out_mov(s, reg, ts->reg);
1478
 
            }
1479
 
        }
1480
 
    } else if (ts->val_type == TEMP_VAL_MEM) {
1481
 
        if (ots->val_type == TEMP_VAL_REG) {
1482
 
            reg = ots->reg;
1483
 
        } else {
1484
 
            reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
1485
 
        }
1486
 
        tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1487
 
    } else if (ts->val_type == TEMP_VAL_CONST) {
1488
 
        if (ots->fixed_reg) {
1489
 
            reg = ots->reg;
1490
 
            tcg_out_movi(s, ots->type, reg, ts->val);
1491
 
        } else {
1492
 
            /* propagate constant */
1493
 
            if (ots->val_type == TEMP_VAL_REG)
1494
 
                s->reg_to_temp[ots->reg] = -1;
1495
 
            ots->val_type = TEMP_VAL_CONST;
1496
 
            ots->val = ts->val;
1497
 
            return;
1498
 
        }
1499
 
    } else {
1500
 
        tcg_abort();
1501
 
    }
1502
 
    s->reg_to_temp[reg] = args[0];
1503
 
    ots->reg = reg;
1504
 
    ots->val_type = TEMP_VAL_REG;
1505
 
    ots->mem_coherent = 0;
1506
 
}
1507
 
 
1508
 
static void tcg_reg_alloc_op(TCGContext *s, 
1509
 
                             const TCGOpDef *def, int opc,
1510
 
                             const TCGArg *args,
1511
 
                             unsigned int dead_iargs)
1512
 
{
1513
 
    TCGRegSet allocated_regs;
1514
 
    int i, k, nb_iargs, nb_oargs, reg;
1515
 
    TCGArg arg;
1516
 
    const TCGArgConstraint *arg_ct;
1517
 
    TCGTemp *ts;
1518
 
    TCGArg new_args[TCG_MAX_OP_ARGS];
1519
 
    int const_args[TCG_MAX_OP_ARGS];
1520
 
 
1521
 
    nb_oargs = def->nb_oargs;
1522
 
    nb_iargs = def->nb_iargs;
1523
 
 
1524
 
    /* copy constants */
1525
 
    memcpy(new_args + nb_oargs + nb_iargs, 
1526
 
           args + nb_oargs + nb_iargs, 
1527
 
           sizeof(TCGArg) * def->nb_cargs);
1528
 
 
1529
 
    /* satisfy input constraints */ 
1530
 
    tcg_regset_set(allocated_regs, s->reserved_regs);
1531
 
    for(k = 0; k < nb_iargs; k++) {
1532
 
        i = def->sorted_args[nb_oargs + k];
1533
 
        arg = args[i];
1534
 
        arg_ct = &def->args_ct[i];
1535
 
        ts = &s->temps[arg];
1536
 
        if (ts->val_type == TEMP_VAL_MEM) {
1537
 
            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1538
 
            tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1539
 
            ts->val_type = TEMP_VAL_REG;
1540
 
            ts->reg = reg;
1541
 
            ts->mem_coherent = 1;
1542
 
            s->reg_to_temp[reg] = arg;
1543
 
        } else if (ts->val_type == TEMP_VAL_CONST) {
1544
 
            if (tcg_target_const_match(ts->val, arg_ct)) {
1545
 
                /* constant is OK for instruction */
1546
 
                const_args[i] = 1;
1547
 
                new_args[i] = ts->val;
1548
 
                goto iarg_end;
1549
 
            } else {
1550
 
                /* need to move to a register */
1551
 
                reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1552
 
                tcg_out_movi(s, ts->type, reg, ts->val);
1553
 
                ts->val_type = TEMP_VAL_REG;
1554
 
                ts->reg = reg;
1555
 
                ts->mem_coherent = 0;
1556
 
                s->reg_to_temp[reg] = arg;
1557
 
            }
1558
 
        }
1559
 
        assert(ts->val_type == TEMP_VAL_REG);
1560
 
        if (arg_ct->ct & TCG_CT_IALIAS) {
1561
 
            if (ts->fixed_reg) {
1562
 
                /* if fixed register, we must allocate a new register
1563
 
                   if the alias is not the same register */
1564
 
                if (arg != args[arg_ct->alias_index])
1565
 
                    goto allocate_in_reg;
1566
 
            } else {
1567
 
                /* if the input is aliased to an output and if it is
1568
 
                   not dead after the instruction, we must allocate
1569
 
                   a new register and move it */
1570
 
                if (!IS_DEAD_IARG(i - nb_oargs)) 
1571
 
                    goto allocate_in_reg;
1572
 
            }
1573
 
        }
1574
 
        reg = ts->reg;
1575
 
        if (tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1576
 
            /* nothing to do : the constraint is satisfied */
1577
 
        } else {
1578
 
        allocate_in_reg:
1579
 
            /* allocate a new register matching the constraint 
1580
 
               and move the temporary register into it */
1581
 
            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1582
 
            tcg_out_mov(s, reg, ts->reg);
1583
 
        }
1584
 
        new_args[i] = reg;
1585
 
        const_args[i] = 0;
1586
 
        tcg_regset_set_reg(allocated_regs, reg);
1587
 
    iarg_end: ;
1588
 
    }
1589
 
    
1590
 
    if (def->flags & TCG_OPF_BB_END) {
1591
 
        tcg_reg_alloc_bb_end(s, allocated_regs);
1592
 
    } else {
1593
 
        /* mark dead temporaries and free the associated registers */
1594
 
        for(i = 0; i < nb_iargs; i++) {
1595
 
            arg = args[nb_oargs + i];
1596
 
            if (IS_DEAD_IARG(i)) {
1597
 
                ts = &s->temps[arg];
1598
 
                if (!ts->fixed_reg) {
1599
 
                    if (ts->val_type == TEMP_VAL_REG)
1600
 
                        s->reg_to_temp[ts->reg] = -1;
1601
 
                    ts->val_type = TEMP_VAL_DEAD;
1602
 
                }
1603
 
            }
1604
 
        }
1605
 
        
1606
 
        if (def->flags & TCG_OPF_CALL_CLOBBER) {
1607
 
            /* XXX: permit generic clobber register list ? */ 
1608
 
            for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1609
 
                if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
1610
 
                    tcg_reg_free(s, reg);
1611
 
                }
1612
 
            }
1613
 
            /* XXX: for load/store we could do that only for the slow path
1614
 
               (i.e. when a memory callback is called) */
1615
 
            
1616
 
            /* store globals and free associated registers (we assume the insn
1617
 
               can modify any global. */
1618
 
            save_globals(s, allocated_regs);
1619
 
        }
1620
 
        
1621
 
        /* satisfy the output constraints */
1622
 
        tcg_regset_set(allocated_regs, s->reserved_regs);
1623
 
        for(k = 0; k < nb_oargs; k++) {
1624
 
            i = def->sorted_args[k];
1625
 
            arg = args[i];
1626
 
            arg_ct = &def->args_ct[i];
1627
 
            ts = &s->temps[arg];
1628
 
            if (arg_ct->ct & TCG_CT_ALIAS) {
1629
 
                reg = new_args[arg_ct->alias_index];
1630
 
            } else {
1631
 
                /* if fixed register, we try to use it */
1632
 
                reg = ts->reg;
1633
 
                if (ts->fixed_reg &&
1634
 
                    tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1635
 
                    goto oarg_end;
1636
 
                }
1637
 
                reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1638
 
            }
1639
 
            tcg_regset_set_reg(allocated_regs, reg);
1640
 
            /* if a fixed register is used, then a move will be done afterwards */
1641
 
            if (!ts->fixed_reg) {
1642
 
                if (ts->val_type == TEMP_VAL_REG)
1643
 
                    s->reg_to_temp[ts->reg] = -1;
1644
 
                ts->val_type = TEMP_VAL_REG;
1645
 
                ts->reg = reg;
1646
 
                /* temp value is modified, so the value kept in memory is
1647
 
                   potentially not the same */
1648
 
                ts->mem_coherent = 0; 
1649
 
                s->reg_to_temp[reg] = arg;
1650
 
            }
1651
 
        oarg_end:
1652
 
            new_args[i] = reg;
1653
 
        }
1654
 
    }
1655
 
 
1656
 
    /* emit instruction */
1657
 
    tcg_out_op(s, opc, new_args, const_args);
1658
 
    
1659
 
    /* move the outputs in the correct register if needed */
1660
 
    for(i = 0; i < nb_oargs; i++) {
1661
 
        ts = &s->temps[args[i]];
1662
 
        reg = new_args[i];
1663
 
        if (ts->fixed_reg && ts->reg != reg) {
1664
 
            tcg_out_mov(s, ts->reg, reg);
1665
 
        }
1666
 
    }
1667
 
}
1668
 
 
1669
 
#ifdef TCG_TARGET_STACK_GROWSUP
1670
 
#define STACK_DIR(x) (-(x))
1671
 
#else
1672
 
#define STACK_DIR(x) (x)
1673
 
#endif
1674
 
 
1675
 
static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
1676
 
                              int opc, const TCGArg *args,
1677
 
                              unsigned int dead_iargs)
1678
 
{
1679
 
    int nb_iargs, nb_oargs, flags, nb_regs, i, reg, nb_params;
1680
 
    TCGArg arg, func_arg;
1681
 
    TCGTemp *ts;
1682
 
    tcg_target_long stack_offset, call_stack_size, func_addr;
1683
 
    int const_func_arg, allocate_args;
1684
 
    TCGRegSet allocated_regs;
1685
 
    const TCGArgConstraint *arg_ct;
1686
 
 
1687
 
    arg = *args++;
1688
 
 
1689
 
    nb_oargs = arg >> 16;
1690
 
    nb_iargs = arg & 0xffff;
1691
 
    nb_params = nb_iargs - 1;
1692
 
 
1693
 
    flags = args[nb_oargs + nb_iargs];
1694
 
 
1695
 
    nb_regs = tcg_target_get_call_iarg_regs_count(flags);
1696
 
    if (nb_regs > nb_params)
1697
 
        nb_regs = nb_params;
1698
 
 
1699
 
    /* assign stack slots first */
1700
 
    /* XXX: preallocate call stack */
1701
 
    call_stack_size = (nb_params - nb_regs) * sizeof(tcg_target_long);
1702
 
    call_stack_size = (call_stack_size + TCG_TARGET_STACK_ALIGN - 1) & 
1703
 
        ~(TCG_TARGET_STACK_ALIGN - 1);
1704
 
    allocate_args = (call_stack_size > TCG_STATIC_CALL_ARGS_SIZE);
1705
 
    if (allocate_args) {
1706
 
        tcg_out_addi(s, TCG_REG_CALL_STACK, -STACK_DIR(call_stack_size));
1707
 
    }
1708
 
 
1709
 
    stack_offset = TCG_TARGET_CALL_STACK_OFFSET;
1710
 
    for(i = nb_regs; i < nb_params; i++) {
1711
 
        arg = args[nb_oargs + i];
1712
 
#ifdef TCG_TARGET_STACK_GROWSUP
1713
 
        stack_offset -= sizeof(tcg_target_long);
1714
 
#endif
1715
 
        if (arg != TCG_CALL_DUMMY_ARG) {
1716
 
            ts = &s->temps[arg];
1717
 
            if (ts->val_type == TEMP_VAL_REG) {
1718
 
                tcg_out_st(s, ts->type, ts->reg, TCG_REG_CALL_STACK, stack_offset);
1719
 
            } else if (ts->val_type == TEMP_VAL_MEM) {
1720
 
                reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], 
1721
 
                                    s->reserved_regs);
1722
 
                /* XXX: not correct if reading values from the stack */
1723
 
                tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1724
 
                tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
1725
 
            } else if (ts->val_type == TEMP_VAL_CONST) {
1726
 
                reg = tcg_reg_alloc(s, tcg_target_available_regs[ts->type], 
1727
 
                                    s->reserved_regs);
1728
 
                /* XXX: sign extend may be needed on some targets */
1729
 
                tcg_out_movi(s, ts->type, reg, ts->val);
1730
 
                tcg_out_st(s, ts->type, reg, TCG_REG_CALL_STACK, stack_offset);
1731
 
            } else {
1732
 
                tcg_abort();
1733
 
            }
1734
 
        }
1735
 
#ifndef TCG_TARGET_STACK_GROWSUP
1736
 
        stack_offset += sizeof(tcg_target_long);
1737
 
#endif
1738
 
    }
1739
 
    
1740
 
    /* assign input registers */
1741
 
    tcg_regset_set(allocated_regs, s->reserved_regs);
1742
 
    for(i = 0; i < nb_regs; i++) {
1743
 
        arg = args[nb_oargs + i];
1744
 
        if (arg != TCG_CALL_DUMMY_ARG) {
1745
 
            ts = &s->temps[arg];
1746
 
            reg = tcg_target_call_iarg_regs[i];
1747
 
            tcg_reg_free(s, reg);
1748
 
            if (ts->val_type == TEMP_VAL_REG) {
1749
 
                if (ts->reg != reg) {
1750
 
                    tcg_out_mov(s, reg, ts->reg);
1751
 
                }
1752
 
            } else if (ts->val_type == TEMP_VAL_MEM) {
1753
 
                tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1754
 
            } else if (ts->val_type == TEMP_VAL_CONST) {
1755
 
                /* XXX: sign extend ? */
1756
 
                tcg_out_movi(s, ts->type, reg, ts->val);
1757
 
            } else {
1758
 
                tcg_abort();
1759
 
            }
1760
 
            tcg_regset_set_reg(allocated_regs, reg);
1761
 
        }
1762
 
    }
1763
 
    
1764
 
    /* assign function address */
1765
 
    func_arg = args[nb_oargs + nb_iargs - 1];
1766
 
    arg_ct = &def->args_ct[0];
1767
 
    ts = &s->temps[func_arg];
1768
 
    func_addr = ts->val;
1769
 
    const_func_arg = 0;
1770
 
    if (ts->val_type == TEMP_VAL_MEM) {
1771
 
        reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1772
 
        tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
1773
 
        func_arg = reg;
1774
 
        tcg_regset_set_reg(allocated_regs, reg);
1775
 
    } else if (ts->val_type == TEMP_VAL_REG) {
1776
 
        reg = ts->reg;
1777
 
        if (!tcg_regset_test_reg(arg_ct->u.regs, reg)) {
1778
 
            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1779
 
            tcg_out_mov(s, reg, ts->reg);
1780
 
        }
1781
 
        func_arg = reg;
1782
 
        tcg_regset_set_reg(allocated_regs, reg);
1783
 
    } else if (ts->val_type == TEMP_VAL_CONST) {
1784
 
        if (tcg_target_const_match(func_addr, arg_ct)) {
1785
 
            const_func_arg = 1;
1786
 
            func_arg = func_addr;
1787
 
        } else {
1788
 
            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
1789
 
            tcg_out_movi(s, ts->type, reg, func_addr);
1790
 
            func_arg = reg;
1791
 
            tcg_regset_set_reg(allocated_regs, reg);
1792
 
        }
1793
 
    } else {
1794
 
        tcg_abort();
1795
 
    }
1796
 
        
1797
 
    
1798
 
    /* mark dead temporaries and free the associated registers */
1799
 
    for(i = 0; i < nb_iargs; i++) {
1800
 
        arg = args[nb_oargs + i];
1801
 
        if (IS_DEAD_IARG(i)) {
1802
 
            ts = &s->temps[arg];
1803
 
            if (!ts->fixed_reg) {
1804
 
                if (ts->val_type == TEMP_VAL_REG)
1805
 
                    s->reg_to_temp[ts->reg] = -1;
1806
 
                ts->val_type = TEMP_VAL_DEAD;
1807
 
            }
1808
 
        }
1809
 
    }
1810
 
    
1811
 
    /* clobber call registers */
1812
 
    for(reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
1813
 
        if (tcg_regset_test_reg(tcg_target_call_clobber_regs, reg)) {
1814
 
            tcg_reg_free(s, reg);
1815
 
        }
1816
 
    }
1817
 
    
1818
 
    /* store globals and free associated registers (we assume the call
1819
 
       can modify any global. */
1820
 
    save_globals(s, allocated_regs);
1821
 
 
1822
 
    tcg_out_op(s, opc, &func_arg, &const_func_arg);
1823
 
    
1824
 
    if (allocate_args) {
1825
 
        tcg_out_addi(s, TCG_REG_CALL_STACK, STACK_DIR(call_stack_size));
1826
 
    }
1827
 
 
1828
 
    /* assign output registers and emit moves if needed */
1829
 
    for(i = 0; i < nb_oargs; i++) {
1830
 
        arg = args[i];
1831
 
        ts = &s->temps[arg];
1832
 
        reg = tcg_target_call_oarg_regs[i];
1833
 
        assert(s->reg_to_temp[reg] == -1);
1834
 
        if (ts->fixed_reg) {
1835
 
            if (ts->reg != reg) {
1836
 
                tcg_out_mov(s, ts->reg, reg);
1837
 
            }
1838
 
        } else {
1839
 
            if (ts->val_type == TEMP_VAL_REG)
1840
 
                s->reg_to_temp[ts->reg] = -1;
1841
 
            ts->val_type = TEMP_VAL_REG;
1842
 
            ts->reg = reg;
1843
 
            ts->mem_coherent = 0; 
1844
 
            s->reg_to_temp[reg] = arg;
1845
 
        }
1846
 
    }
1847
 
    
1848
 
    return nb_iargs + nb_oargs + def->nb_cargs + 1;
1849
 
}
1850
 
 
1851
 
#ifdef CONFIG_PROFILER
1852
 
 
1853
 
static int64_t dyngen_table_op_count[NB_OPS];
1854
 
 
1855
 
void dump_op_count(void)
1856
 
{
1857
 
    int i;
1858
 
    FILE *f;
1859
 
    f = fopen("/tmp/op1.log", "w");
1860
 
    for(i = 0; i < INDEX_op_end; i++) {
1861
 
        fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name, dyngen_table_op_count[i]);
1862
 
    }
1863
 
    fclose(f);
1864
 
    f = fopen("/tmp/op2.log", "w");
1865
 
    for(i = INDEX_op_end; i < NB_OPS; i++) {
1866
 
        fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name, dyngen_table_op_count[i]);
1867
 
    }
1868
 
    fclose(f);
1869
 
}
1870
 
#endif
1871
 
 
1872
 
 
1873
 
static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
1874
 
                                      long search_pc)
1875
 
{
1876
 
    int opc, op_index;
1877
 
    const TCGOpDef *def;
1878
 
    unsigned int dead_iargs;
1879
 
    const TCGArg *args;
1880
 
 
1881
 
#ifdef DEBUG_DISAS
1882
 
    if (unlikely(loglevel & CPU_LOG_TB_OP)) {
1883
 
        fprintf(logfile, "OP:\n");
1884
 
        tcg_dump_ops(s, logfile);
1885
 
        fprintf(logfile, "\n");
1886
 
    }
1887
 
#endif
1888
 
 
1889
 
#ifdef CONFIG_PROFILER
1890
 
    s->la_time -= profile_getclock();
1891
 
#endif
1892
 
    tcg_liveness_analysis(s);
1893
 
#ifdef CONFIG_PROFILER
1894
 
    s->la_time += profile_getclock();
1895
 
#endif
1896
 
 
1897
 
#ifdef DEBUG_DISAS
1898
 
    if (unlikely(loglevel & CPU_LOG_TB_OP_OPT)) {
1899
 
        fprintf(logfile, "OP after la:\n");
1900
 
        tcg_dump_ops(s, logfile);
1901
 
        fprintf(logfile, "\n");
1902
 
    }
1903
 
#endif
1904
 
 
1905
 
    tcg_reg_alloc_start(s);
1906
 
 
1907
 
    s->code_buf = gen_code_buf;
1908
 
    s->code_ptr = gen_code_buf;
1909
 
 
1910
 
    args = gen_opparam_buf;
1911
 
    op_index = 0;
1912
 
 
1913
 
    for(;;) {
1914
 
        opc = gen_opc_buf[op_index];
1915
 
#ifdef CONFIG_PROFILER
1916
 
        dyngen_table_op_count[opc]++;
1917
 
#endif
1918
 
        def = &tcg_op_defs[opc];
1919
 
#if 0
1920
 
        printf("%s: %d %d %d\n", def->name,
1921
 
               def->nb_oargs, def->nb_iargs, def->nb_cargs);
1922
 
        //        dump_regs(s);
1923
 
#endif
1924
 
        switch(opc) {
1925
 
        case INDEX_op_mov_i32:
1926
 
#if TCG_TARGET_REG_BITS == 64
1927
 
        case INDEX_op_mov_i64:
1928
 
#endif
1929
 
            dead_iargs = s->op_dead_iargs[op_index];
1930
 
            tcg_reg_alloc_mov(s, def, args, dead_iargs);
1931
 
            break;
1932
 
        case INDEX_op_movi_i32:
1933
 
#if TCG_TARGET_REG_BITS == 64
1934
 
        case INDEX_op_movi_i64:
1935
 
#endif
1936
 
            tcg_reg_alloc_movi(s, args);
1937
 
            break;
1938
 
        case INDEX_op_debug_insn_start:
1939
 
            /* debug instruction */
1940
 
            break;
1941
 
        case INDEX_op_nop:
1942
 
        case INDEX_op_nop1:
1943
 
        case INDEX_op_nop2:
1944
 
        case INDEX_op_nop3:
1945
 
            break;
1946
 
        case INDEX_op_nopn:
1947
 
            args += args[0];
1948
 
            goto next;
1949
 
        case INDEX_op_discard:
1950
 
            {
1951
 
                TCGTemp *ts;
1952
 
                ts = &s->temps[args[0]];
1953
 
                /* mark the temporary as dead */
1954
 
                if (!ts->fixed_reg) {
1955
 
                    if (ts->val_type == TEMP_VAL_REG)
1956
 
                        s->reg_to_temp[ts->reg] = -1;
1957
 
                    ts->val_type = TEMP_VAL_DEAD;
1958
 
                }
1959
 
            }
1960
 
            break;
1961
 
        case INDEX_op_set_label:
1962
 
            tcg_reg_alloc_bb_end(s, s->reserved_regs);
1963
 
            tcg_out_label(s, args[0], (long)s->code_ptr);
1964
 
            break;
1965
 
        case INDEX_op_call:
1966
 
            dead_iargs = s->op_dead_iargs[op_index];
1967
 
            args += tcg_reg_alloc_call(s, def, opc, args, dead_iargs);
1968
 
            goto next;
1969
 
        case INDEX_op_end:
1970
 
            goto the_end;
1971
 
 
1972
 
#ifdef CONFIG_DYNGEN_OP
1973
 
        case 0 ... INDEX_op_end - 1:
1974
 
            /* legacy dyngen ops */
1975
 
#ifdef CONFIG_PROFILER
1976
 
            s->old_op_count++;
1977
 
#endif
1978
 
            tcg_reg_alloc_bb_end(s, s->reserved_regs);
1979
 
            if (search_pc >= 0) {
1980
 
                s->code_ptr += def->copy_size;
1981
 
                args += def->nb_args;
1982
 
            } else {
1983
 
                args = dyngen_op(s, opc, args);
1984
 
            }
1985
 
            goto next;
1986
 
#endif
1987
 
        default:
1988
 
            /* Note: in order to speed up the code, it would be much
1989
 
               faster to have specialized register allocator functions for
1990
 
               some common argument patterns */
1991
 
            dead_iargs = s->op_dead_iargs[op_index];
1992
 
            tcg_reg_alloc_op(s, def, opc, args, dead_iargs);
1993
 
            break;
1994
 
        }
1995
 
        args += def->nb_args;
1996
 
    next:
1997
 
        if (search_pc >= 0 && search_pc < s->code_ptr - gen_code_buf) {
1998
 
            return op_index;
1999
 
        }
2000
 
        op_index++;
2001
 
#ifndef NDEBUG
2002
 
        check_regs(s);
2003
 
#endif
2004
 
    }
2005
 
 the_end:
2006
 
    return -1;
2007
 
}
2008
 
 
2009
 
int dyngen_code(TCGContext *s, uint8_t *gen_code_buf)
2010
 
{
2011
 
#ifdef CONFIG_PROFILER
2012
 
    {
2013
 
        int n;
2014
 
        n = (gen_opc_ptr - gen_opc_buf);
2015
 
        s->op_count += n;
2016
 
        if (n > s->op_count_max)
2017
 
            s->op_count_max = n;
2018
 
 
2019
 
        s->temp_count += s->nb_temps;
2020
 
        if (s->nb_temps > s->temp_count_max)
2021
 
            s->temp_count_max = s->nb_temps;
2022
 
    }
2023
 
#endif
2024
 
 
2025
 
    tcg_gen_code_common(s, gen_code_buf, -1);
2026
 
 
2027
 
    /* flush instruction cache */
2028
 
    flush_icache_range((unsigned long)gen_code_buf, 
2029
 
                       (unsigned long)s->code_ptr);
2030
 
    return s->code_ptr -  gen_code_buf;
2031
 
}
2032
 
 
2033
 
/* Return the index of the micro operation such as the pc after is <
2034
 
   offset bytes from the start of the TB.  The contents of gen_code_buf must
2035
 
   not be changed, though writing the same values is ok.
2036
 
   Return -1 if not found. */
2037
 
int dyngen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, long offset)
2038
 
{
2039
 
    return tcg_gen_code_common(s, gen_code_buf, offset);
2040
 
}
2041
 
 
2042
 
#ifdef CONFIG_PROFILER
2043
 
void tcg_dump_info(FILE *f,
2044
 
                   int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
2045
 
{
2046
 
    TCGContext *s = &tcg_ctx;
2047
 
    int64_t tot;
2048
 
 
2049
 
    tot = s->interm_time + s->code_time;
2050
 
    cpu_fprintf(f, "JIT cycles          %" PRId64 " (%0.3f s at 2.4 GHz)\n",
2051
 
                tot, tot / 2.4e9);
2052
 
    cpu_fprintf(f, "translated TBs      %" PRId64 " (aborted=%" PRId64 " %0.1f%%)\n", 
2053
 
                s->tb_count, 
2054
 
                s->tb_count1 - s->tb_count,
2055
 
                s->tb_count1 ? (double)(s->tb_count1 - s->tb_count) / s->tb_count1 * 100.0 : 0);
2056
 
    cpu_fprintf(f, "avg ops/TB          %0.1f max=%d\n", 
2057
 
                s->tb_count ? (double)s->op_count / s->tb_count : 0, s->op_count_max);
2058
 
    cpu_fprintf(f, "old ops/total ops   %0.1f%%\n", 
2059
 
                s->op_count ? (double)s->old_op_count / s->op_count * 100.0 : 0);
2060
 
    cpu_fprintf(f, "deleted ops/TB      %0.2f\n",
2061
 
                s->tb_count ? 
2062
 
                (double)s->del_op_count / s->tb_count : 0);
2063
 
    cpu_fprintf(f, "avg temps/TB        %0.2f max=%d\n",
2064
 
                s->tb_count ? 
2065
 
                (double)s->temp_count / s->tb_count : 0,
2066
 
                s->temp_count_max);
2067
 
    
2068
 
    cpu_fprintf(f, "cycles/op           %0.1f\n", 
2069
 
                s->op_count ? (double)tot / s->op_count : 0);
2070
 
    cpu_fprintf(f, "cycles/in byte      %0.1f\n", 
2071
 
                s->code_in_len ? (double)tot / s->code_in_len : 0);
2072
 
    cpu_fprintf(f, "cycles/out byte     %0.1f\n", 
2073
 
                s->code_out_len ? (double)tot / s->code_out_len : 0);
2074
 
    if (tot == 0)
2075
 
        tot = 1;
2076
 
    cpu_fprintf(f, "  gen_interm time   %0.1f%%\n", 
2077
 
                (double)s->interm_time / tot * 100.0);
2078
 
    cpu_fprintf(f, "  gen_code time     %0.1f%%\n", 
2079
 
                (double)s->code_time / tot * 100.0);
2080
 
    cpu_fprintf(f, "liveness/code time  %0.1f%%\n", 
2081
 
                (double)s->la_time / (s->code_time ? s->code_time : 1) * 100.0);
2082
 
    cpu_fprintf(f, "cpu_restore count   %" PRId64 "\n",
2083
 
                s->restore_count);
2084
 
    cpu_fprintf(f, "  avg cycles        %0.1f\n",
2085
 
                s->restore_count ? (double)s->restore_time / s->restore_count : 0);
2086
 
    {
2087
 
        extern void dump_op_count(void);
2088
 
        dump_op_count();
2089
 
    }
2090
 
}
2091
 
#else
2092
 
void tcg_dump_info(FILE *f,
2093
 
                   int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
2094
 
{
2095
 
    cpu_fprintf(f, "[TCG profiler not compiled]\n");
2096
 
}
2097
 
#endif