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

/* define it to use liveness analysis (better code) */
#define USE_LIVENESS_ANALYSIS
K
Kirill Batuzov 已提交
27
#define USE_TCG_OPTIMIZATIONS
B
bellard 已提交
28

P
Peter Maydell 已提交
29
#include "qemu/osdep.h"
30

31 32 33
/* Define to jump the ELF file used to communicate with GDB.  */
#undef DEBUG_JIT

34
#include "qemu/cutils.h"
35 36
#include "qemu/host-utils.h"
#include "qemu/timer.h"
B
bellard 已提交
37

38
/* Note: the long term plan is to reduce the dependencies on the QEMU
B
bellard 已提交
39 40 41 42 43
   CPU definitions. Currently they are used for qemu_ld/st
   instructions */
#define NO_CPU_IO_DEFS
#include "cpu.h"

44 45 46 47 48
#include "qemu/host-utils.h"
#include "qemu/timer.h"
#include "exec/cpu-common.h"
#include "exec/exec-all.h"

B
bellard 已提交
49
#include "tcg-op.h"
50

R
Richard Henderson 已提交
51
#if UINTPTR_MAX == UINT32_MAX
52
# define ELF_CLASS  ELFCLASS32
R
Richard Henderson 已提交
53 54
#else
# define ELF_CLASS  ELFCLASS64
55 56 57 58 59 60 61
#endif
#ifdef HOST_WORDS_BIGENDIAN
# define ELF_DATA   ELFDATA2MSB
#else
# define ELF_DATA   ELFDATA2LSB
#endif

B
bellard 已提交
62
#include "elf.h"
63
#include "exec/log.h"
B
bellard 已提交
64

65 66
/* Forward declarations for functions declared in tcg-target.inc.c and
   used here. */
67 68
static void tcg_target_init(TCGContext *s);
static void tcg_target_qemu_prologue(TCGContext *s);
69
static void patch_reloc(tcg_insn_unit *code_ptr, int type,
70
                        intptr_t value, intptr_t addend);
B
bellard 已提交
71

72 73 74 75 76 77 78 79 80 81 82 83 84 85
/* The CIE and FDE header definitions will be common to all hosts.  */
typedef struct {
    uint32_t len __attribute__((aligned((sizeof(void *)))));
    uint32_t id;
    uint8_t version;
    char augmentation[1];
    uint8_t code_align;
    uint8_t data_align;
    uint8_t return_column;
} DebugFrameCIE;

typedef struct QEMU_PACKED {
    uint32_t len __attribute__((aligned((sizeof(void *)))));
    uint32_t cie_offset;
R
Richard Henderson 已提交
86 87
    uintptr_t func_start;
    uintptr_t func_len;
88 89
} DebugFrameFDEHeader;

90 91 92 93 94
typedef struct QEMU_PACKED {
    DebugFrameCIE cie;
    DebugFrameFDEHeader fde;
} DebugFrameHeader;

95
static void tcg_register_jit_int(void *buf, size_t size,
96 97
                                 const void *debug_frame,
                                 size_t debug_frame_size)
98 99
    __attribute__((unused));

100
/* Forward declarations for functions declared and used in tcg-target.inc.c. */
101
static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str);
102
static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg1,
103
                       intptr_t arg2);
104
static void tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg);
105
static void tcg_out_movi(TCGContext *s, TCGType type,
106
                         TCGReg ret, tcg_target_long arg);
107 108
static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
                       const int *const_args);
109
static void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, TCGReg arg1,
110
                       intptr_t arg2);
111 112
static bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val,
                        TCGReg base, intptr_t ofs);
113
static void tcg_out_call(TCGContext *s, tcg_insn_unit *target);
114
static int tcg_target_const_match(tcg_target_long val, TCGType type,
115
                                  const TCGArgConstraint *arg_ct);
R
Richard Henderson 已提交
116
static void tcg_out_tb_init(TCGContext *s);
117
static bool tcg_out_tb_finalize(TCGContext *s);
R
Richard Henderson 已提交
118

119

B
bellard 已提交
120

121 122
static TCGRegSet tcg_target_available_regs[2];
static TCGRegSet tcg_target_call_clobber_regs;
B
bellard 已提交
123

124
#if TCG_TARGET_INSN_UNIT_SIZE == 1
125
static __attribute__((unused)) inline void tcg_out8(TCGContext *s, uint8_t v)
B
bellard 已提交
126 127 128 129
{
    *s->code_ptr++ = v;
}

130 131
static __attribute__((unused)) inline void tcg_patch8(tcg_insn_unit *p,
                                                      uint8_t v)
132
{
133
    *p = v;
134
}
135
#endif
136

137
#if TCG_TARGET_INSN_UNIT_SIZE <= 2
138
static __attribute__((unused)) inline void tcg_out16(TCGContext *s, uint16_t v)
B
bellard 已提交
139
{
140 141 142 143 144 145 146
    if (TCG_TARGET_INSN_UNIT_SIZE == 2) {
        *s->code_ptr++ = v;
    } else {
        tcg_insn_unit *p = s->code_ptr;
        memcpy(p, &v, sizeof(v));
        s->code_ptr = p + (2 / TCG_TARGET_INSN_UNIT_SIZE);
    }
B
bellard 已提交
147 148
}

149 150
static __attribute__((unused)) inline void tcg_patch16(tcg_insn_unit *p,
                                                       uint16_t v)
151
{
152 153 154 155 156
    if (TCG_TARGET_INSN_UNIT_SIZE == 2) {
        *p = v;
    } else {
        memcpy(p, &v, sizeof(v));
    }
157
}
158
#endif
159

160
#if TCG_TARGET_INSN_UNIT_SIZE <= 4
161
static __attribute__((unused)) inline void tcg_out32(TCGContext *s, uint32_t v)
B
bellard 已提交
162
{
163 164 165 166 167 168 169
    if (TCG_TARGET_INSN_UNIT_SIZE == 4) {
        *s->code_ptr++ = v;
    } else {
        tcg_insn_unit *p = s->code_ptr;
        memcpy(p, &v, sizeof(v));
        s->code_ptr = p + (4 / TCG_TARGET_INSN_UNIT_SIZE);
    }
B
bellard 已提交
170 171
}

172 173
static __attribute__((unused)) inline void tcg_patch32(tcg_insn_unit *p,
                                                       uint32_t v)
174
{
175 176 177 178 179
    if (TCG_TARGET_INSN_UNIT_SIZE == 4) {
        *p = v;
    } else {
        memcpy(p, &v, sizeof(v));
    }
180
}
181
#endif
182

183
#if TCG_TARGET_INSN_UNIT_SIZE <= 8
184
static __attribute__((unused)) inline void tcg_out64(TCGContext *s, uint64_t v)
185
{
186 187 188 189 190 191 192
    if (TCG_TARGET_INSN_UNIT_SIZE == 8) {
        *s->code_ptr++ = v;
    } else {
        tcg_insn_unit *p = s->code_ptr;
        memcpy(p, &v, sizeof(v));
        s->code_ptr = p + (8 / TCG_TARGET_INSN_UNIT_SIZE);
    }
193 194
}

195 196
static __attribute__((unused)) inline void tcg_patch64(tcg_insn_unit *p,
                                                       uint64_t v)
197
{
198 199 200 201 202
    if (TCG_TARGET_INSN_UNIT_SIZE == 8) {
        *p = v;
    } else {
        memcpy(p, &v, sizeof(v));
    }
203
}
204
#endif
205

B
bellard 已提交
206 207
/* label relocation processing */

208
static void tcg_out_reloc(TCGContext *s, tcg_insn_unit *code_ptr, int type,
209
                          TCGLabel *l, intptr_t addend)
B
bellard 已提交
210 211 212 213
{
    TCGRelocation *r;

    if (l->has_value) {
P
pbrook 已提交
214 215 216
        /* FIXME: This may break relocations on RISC targets that
           modify instruction fields in place.  The caller may not have 
           written the initial value.  */
A
aurel32 已提交
217
        patch_reloc(code_ptr, type, l->u.value, addend);
B
bellard 已提交
218 219 220 221 222 223 224 225 226 227 228
    } else {
        /* add a new relocation entry */
        r = tcg_malloc(sizeof(TCGRelocation));
        r->type = type;
        r->ptr = code_ptr;
        r->addend = addend;
        r->next = l->u.first_reloc;
        l->u.first_reloc = r;
    }
}

229
static void tcg_out_label(TCGContext *s, TCGLabel *l, tcg_insn_unit *ptr)
B
bellard 已提交
230
{
231
    intptr_t value = (intptr_t)ptr;
232
    TCGRelocation *r;
B
bellard 已提交
233

234
    tcg_debug_assert(!l->has_value);
235 236

    for (r = l->u.first_reloc; r != NULL; r = r->next) {
A
aurel32 已提交
237
        patch_reloc(r->ptr, r->type, value, r->addend);
B
bellard 已提交
238
    }
239

B
bellard 已提交
240
    l->has_value = 1;
241
    l->u.value_ptr = ptr;
B
bellard 已提交
242 243
}

244
TCGLabel *gen_new_label(void)
B
bellard 已提交
245 246
{
    TCGContext *s = &tcg_ctx;
247
    TCGLabel *l = tcg_malloc(sizeof(TCGLabel));
B
bellard 已提交
248

249 250 251
    *l = (TCGLabel){
        .id = s->nb_labels++
    };
252 253

    return l;
B
bellard 已提交
254 255
}

256
#include "tcg-target.inc.c"
B
bellard 已提交
257 258 259 260 261 262 263 264 265

/* pool based memory allocation */
void *tcg_malloc_internal(TCGContext *s, int size)
{
    TCGPool *p;
    int pool_size;
    
    if (size > TCG_POOL_CHUNK_SIZE) {
        /* big malloc: insert a new pool (XXX: could optimize) */
266
        p = g_malloc(sizeof(TCGPool) + size);
B
bellard 已提交
267
        p->size = size;
268 269 270
        p->next = s->pool_first_large;
        s->pool_first_large = p;
        return p->data;
B
bellard 已提交
271 272 273 274 275 276 277 278 279 280
    } else {
        p = s->pool_current;
        if (!p) {
            p = s->pool_first;
            if (!p)
                goto new_pool;
        } else {
            if (!p->next) {
            new_pool:
                pool_size = TCG_POOL_CHUNK_SIZE;
281
                p = g_malloc(sizeof(TCGPool) + pool_size);
B
bellard 已提交
282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300
                p->size = pool_size;
                p->next = NULL;
                if (s->pool_current) 
                    s->pool_current->next = p;
                else
                    s->pool_first = p;
            } else {
                p = p->next;
            }
        }
    }
    s->pool_current = p;
    s->pool_cur = p->data + size;
    s->pool_end = p->data + p->size;
    return p->data;
}

void tcg_pool_reset(TCGContext *s)
{
301 302 303 304 305 306
    TCGPool *p, *t;
    for (p = s->pool_first_large; p; p = t) {
        t = p->next;
        g_free(p);
    }
    s->pool_first_large = NULL;
B
bellard 已提交
307 308 309 310
    s->pool_cur = s->pool_end = NULL;
    s->pool_current = NULL;
}

311 312 313
typedef struct TCGHelperInfo {
    void *func;
    const char *name;
314 315
    unsigned flags;
    unsigned sizemask;
316 317
} TCGHelperInfo;

318 319
#include "exec/helper-proto.h"

320
static const TCGHelperInfo all_helpers[] = {
321
#include "exec/helper-tcg.h"
322 323
};

324 325
static int indirect_reg_alloc_order[ARRAY_SIZE(tcg_target_reg_alloc_order)];

B
bellard 已提交
326 327
void tcg_context_init(TCGContext *s)
{
328
    int op, total_args, n, i;
B
bellard 已提交
329 330 331
    TCGOpDef *def;
    TCGArgConstraint *args_ct;
    int *sorted_args;
332
    GHashTable *helper_table;
B
bellard 已提交
333 334 335 336 337 338 339 340 341 342 343 344 345

    memset(s, 0, sizeof(*s));
    s->nb_globals = 0;
    
    /* Count total number of arguments and allocate the corresponding
       space */
    total_args = 0;
    for(op = 0; op < NB_OPS; op++) {
        def = &tcg_op_defs[op];
        n = def->nb_iargs + def->nb_oargs;
        total_args += n;
    }

346 347
    args_ct = g_malloc(sizeof(TCGArgConstraint) * total_args);
    sorted_args = g_malloc(sizeof(int) * total_args);
B
bellard 已提交
348 349 350 351 352 353 354 355 356

    for(op = 0; op < NB_OPS; op++) {
        def = &tcg_op_defs[op];
        def->args_ct = args_ct;
        def->sorted_args = sorted_args;
        n = def->nb_iargs + def->nb_oargs;
        sorted_args += n;
        args_ct += n;
    }
357 358

    /* Register helpers.  */
359 360 361
    /* Use g_direct_hash/equal for direct pointer comparisons on func.  */
    s->helpers = helper_table = g_hash_table_new(NULL, NULL);

362
    for (i = 0; i < ARRAY_SIZE(all_helpers); ++i) {
363
        g_hash_table_insert(helper_table, (gpointer)all_helpers[i].func,
364
                            (gpointer)&all_helpers[i]);
365
    }
366

B
bellard 已提交
367
    tcg_target_init(s);
368 369 370 371 372 373 374 375 376 377 378 379 380 381 382

    /* Reverse the order of the saved registers, assuming they're all at
       the start of tcg_target_reg_alloc_order.  */
    for (n = 0; n < ARRAY_SIZE(tcg_target_reg_alloc_order); ++n) {
        int r = tcg_target_reg_alloc_order[n];
        if (tcg_regset_test_reg(tcg_target_call_clobber_regs, r)) {
            break;
        }
    }
    for (i = 0; i < n; ++i) {
        indirect_reg_alloc_order[i] = tcg_target_reg_alloc_order[n - 1 - i];
    }
    for (; i < ARRAY_SIZE(tcg_target_reg_alloc_order); ++i) {
        indirect_reg_alloc_order[i] = tcg_target_reg_alloc_order[i];
    }
383
}
384

385 386
void tcg_prologue_init(TCGContext *s)
{
387 388 389 390 391 392 393 394 395 396
    size_t prologue_size, total_size;
    void *buf0, *buf1;

    /* Put the prologue at the beginning of code_gen_buffer.  */
    buf0 = s->code_gen_buffer;
    s->code_ptr = buf0;
    s->code_buf = buf0;
    s->code_gen_prologue = buf0;

    /* Generate the prologue.  */
397
    tcg_target_qemu_prologue(s);
398 399 400 401 402 403 404 405 406 407 408
    buf1 = s->code_ptr;
    flush_icache_range((uintptr_t)buf0, (uintptr_t)buf1);

    /* Deduct the prologue from the buffer.  */
    prologue_size = tcg_current_code_size(s);
    s->code_gen_ptr = buf1;
    s->code_gen_buffer = buf1;
    s->code_buf = buf1;
    total_size = s->code_gen_buffer_size - prologue_size;
    s->code_gen_buffer_size = total_size;

409 410 411
    /* Compute a high-water mark, at which we voluntarily flush the buffer
       and start over.  The size here is arbitrary, significantly larger
       than we expect the code generation for any one opcode to require.  */
412
    s->code_gen_highwater = s->code_gen_buffer + (total_size - 1024);
413 414

    tcg_register_jit(s->code_gen_buffer, total_size);
415 416 417

#ifdef DEBUG_DISAS
    if (qemu_loglevel_mask(CPU_LOG_TB_OUT_ASM)) {
418 419
        qemu_log("PROLOGUE: [size=%zu]\n", prologue_size);
        log_disas(buf0, prologue_size);
420 421 422 423
        qemu_log("\n");
        qemu_log_flush();
    }
#endif
B
bellard 已提交
424 425 426 427 428 429
}

void tcg_func_start(TCGContext *s)
{
    tcg_pool_reset(s);
    s->nb_temps = s->nb_globals;
430 431 432 433

    /* No temps have been previously allocated for size or locality.  */
    memset(s->free_temps, 0, sizeof(s->free_temps));

B
bellard 已提交
434 435 436
    s->nb_labels = 0;
    s->current_frame_offset = s->frame_start;

437 438 439 440
#ifdef CONFIG_DEBUG_TCG
    s->goto_tb_issue_mask = 0;
#endif

R
Richard Henderson 已提交
441 442 443
    s->gen_op_buf[0].next = 1;
    s->gen_op_buf[0].prev = 0;
    s->gen_next_op_idx = 1;
444
    s->gen_next_parm_idx = 0;
445

R
Richard Henderson 已提交
446
    s->be = tcg_malloc(sizeof(TCGBackendData));
B
bellard 已提交
447 448
}

449
static inline int temp_idx(TCGContext *s, TCGTemp *ts)
B
bellard 已提交
450
{
451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467
    ptrdiff_t n = ts - s->temps;
    tcg_debug_assert(n >= 0 && n < s->nb_temps);
    return n;
}

static inline TCGTemp *tcg_temp_alloc(TCGContext *s)
{
    int n = s->nb_temps++;
    tcg_debug_assert(n < TCG_MAX_TEMPS);
    return memset(&s->temps[n], 0, sizeof(TCGTemp));
}

static inline TCGTemp *tcg_global_alloc(TCGContext *s)
{
    tcg_debug_assert(s->nb_globals == s->nb_temps);
    s->nb_globals++;
    return tcg_temp_alloc(s);
B
bellard 已提交
468 469
}

470
static int tcg_global_reg_new_internal(TCGContext *s, TCGType type,
471
                                       TCGReg reg, const char *name)
B
bellard 已提交
472 473 474
{
    TCGTemp *ts;

475
    if (TCG_TARGET_REG_BITS == 32 && type != TCG_TYPE_I32) {
B
bellard 已提交
476
        tcg_abort();
477
    }
478 479

    ts = tcg_global_alloc(s);
B
bellard 已提交
480 481 482 483 484 485
    ts->base_type = type;
    ts->type = type;
    ts->fixed_reg = 1;
    ts->reg = reg;
    ts->name = name;
    tcg_regset_set_reg(s->reserved_regs, reg);
486 487

    return temp_idx(s, ts);
P
pbrook 已提交
488 489
}

490
void tcg_set_frame(TCGContext *s, TCGReg reg, intptr_t start, intptr_t size)
491 492 493 494 495 496 497 498
{
    int idx;
    s->frame_start = start;
    s->frame_end = start + size;
    idx = tcg_global_reg_new_internal(s, TCG_TYPE_PTR, reg, "_frame");
    s->frame_temp = &s->temps[idx];
}

499
TCGv_i32 tcg_global_reg_new_i32(TCGReg reg, const char *name)
P
pbrook 已提交
500
{
501
    TCGContext *s = &tcg_ctx;
P
pbrook 已提交
502 503
    int idx;

504 505 506 507
    if (tcg_regset_test_reg(s->reserved_regs, reg)) {
        tcg_abort();
    }
    idx = tcg_global_reg_new_internal(s, TCG_TYPE_I32, reg, name);
P
pbrook 已提交
508 509 510
    return MAKE_TCGV_I32(idx);
}

511
TCGv_i64 tcg_global_reg_new_i64(TCGReg reg, const char *name)
P
pbrook 已提交
512
{
513
    TCGContext *s = &tcg_ctx;
P
pbrook 已提交
514 515
    int idx;

516 517 518 519
    if (tcg_regset_test_reg(s->reserved_regs, reg)) {
        tcg_abort();
    }
    idx = tcg_global_reg_new_internal(s, TCG_TYPE_I64, reg, name);
P
pbrook 已提交
520
    return MAKE_TCGV_I64(idx);
B
bellard 已提交
521 522
}

523 524
int tcg_global_mem_new_internal(TCGType type, TCGv_ptr base,
                                intptr_t offset, const char *name)
B
bellard 已提交
525 526
{
    TCGContext *s = &tcg_ctx;
527 528
    TCGTemp *base_ts = &s->temps[GET_TCGV_PTR(base)];
    TCGTemp *ts = tcg_global_alloc(s);
529
    int indirect_reg = 0, bigendian = 0;
530 531 532
#ifdef HOST_WORDS_BIGENDIAN
    bigendian = 1;
#endif
B
bellard 已提交
533

534 535 536 537 538
    if (!base_ts->fixed_reg) {
        indirect_reg = 1;
        base_ts->indirect_base = 1;
    }

539 540
    if (TCG_TARGET_REG_BITS == 32 && type == TCG_TYPE_I64) {
        TCGTemp *ts2 = tcg_global_alloc(s);
B
bellard 已提交
541
        char buf[64];
542 543

        ts->base_type = TCG_TYPE_I64;
B
bellard 已提交
544
        ts->type = TCG_TYPE_I32;
545
        ts->indirect_reg = indirect_reg;
B
bellard 已提交
546
        ts->mem_allocated = 1;
547
        ts->mem_base = base_ts;
548
        ts->mem_offset = offset + bigendian * 4;
B
bellard 已提交
549 550 551 552
        pstrcpy(buf, sizeof(buf), name);
        pstrcat(buf, sizeof(buf), "_0");
        ts->name = strdup(buf);

553 554 555
        tcg_debug_assert(ts2 == ts + 1);
        ts2->base_type = TCG_TYPE_I64;
        ts2->type = TCG_TYPE_I32;
556
        ts2->indirect_reg = indirect_reg;
557 558 559
        ts2->mem_allocated = 1;
        ts2->mem_base = base_ts;
        ts2->mem_offset = offset + (1 - bigendian) * 4;
B
bellard 已提交
560 561
        pstrcpy(buf, sizeof(buf), name);
        pstrcat(buf, sizeof(buf), "_1");
562
        ts2->name = strdup(buf);
563
    } else {
B
bellard 已提交
564 565
        ts->base_type = type;
        ts->type = type;
566
        ts->indirect_reg = indirect_reg;
B
bellard 已提交
567
        ts->mem_allocated = 1;
568
        ts->mem_base = base_ts;
B
bellard 已提交
569 570 571
        ts->mem_offset = offset;
        ts->name = name;
    }
572
    return temp_idx(s, ts);
P
pbrook 已提交
573 574
}

575
static int tcg_temp_new_internal(TCGType type, int temp_local)
B
bellard 已提交
576 577 578
{
    TCGContext *s = &tcg_ctx;
    TCGTemp *ts;
B
bellard 已提交
579
    int idx, k;
B
bellard 已提交
580

581 582 583 584 585 586
    k = type + (temp_local ? TCG_TYPE_COUNT : 0);
    idx = find_first_bit(s->free_temps[k].l, TCG_MAX_TEMPS);
    if (idx < TCG_MAX_TEMPS) {
        /* There is already an available temp with the right type.  */
        clear_bit(idx, s->free_temps[k].l);

587 588
        ts = &s->temps[idx];
        ts->temp_allocated = 1;
589 590
        tcg_debug_assert(ts->base_type == type);
        tcg_debug_assert(ts->temp_local == temp_local);
591
    } else {
592 593 594 595
        ts = tcg_temp_alloc(s);
        if (TCG_TARGET_REG_BITS == 32 && type == TCG_TYPE_I64) {
            TCGTemp *ts2 = tcg_temp_alloc(s);

596
            ts->base_type = type;
597 598
            ts->type = TCG_TYPE_I32;
            ts->temp_allocated = 1;
B
bellard 已提交
599
            ts->temp_local = temp_local;
600 601 602 603 604 605 606

            tcg_debug_assert(ts2 == ts + 1);
            ts2->base_type = TCG_TYPE_I64;
            ts2->type = TCG_TYPE_I32;
            ts2->temp_allocated = 1;
            ts2->temp_local = temp_local;
        } else {
607 608 609
            ts->base_type = type;
            ts->type = type;
            ts->temp_allocated = 1;
B
bellard 已提交
610
            ts->temp_local = temp_local;
611
        }
612
        idx = temp_idx(s, ts);
B
bellard 已提交
613
    }
614 615 616 617

#if defined(CONFIG_DEBUG_TCG)
    s->temps_in_use++;
#endif
P
pbrook 已提交
618
    return idx;
B
bellard 已提交
619 620
}

P
pbrook 已提交
621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636
TCGv_i32 tcg_temp_new_internal_i32(int temp_local)
{
    int idx;

    idx = tcg_temp_new_internal(TCG_TYPE_I32, temp_local);
    return MAKE_TCGV_I32(idx);
}

TCGv_i64 tcg_temp_new_internal_i64(int temp_local)
{
    int idx;

    idx = tcg_temp_new_internal(TCG_TYPE_I64, temp_local);
    return MAKE_TCGV_I64(idx);
}

637
static void tcg_temp_free_internal(int idx)
B
bellard 已提交
638 639 640
{
    TCGContext *s = &tcg_ctx;
    TCGTemp *ts;
B
bellard 已提交
641
    int k;
B
bellard 已提交
642

643 644 645 646 647 648 649
#if defined(CONFIG_DEBUG_TCG)
    s->temps_in_use--;
    if (s->temps_in_use < 0) {
        fprintf(stderr, "More temporaries freed than allocated!\n");
    }
#endif

650
    tcg_debug_assert(idx >= s->nb_globals && idx < s->nb_temps);
B
bellard 已提交
651
    ts = &s->temps[idx];
652
    tcg_debug_assert(ts->temp_allocated != 0);
653
    ts->temp_allocated = 0;
654

655
    k = ts->base_type + (ts->temp_local ? TCG_TYPE_COUNT : 0);
656
    set_bit(idx, s->free_temps[k].l);
B
bellard 已提交
657 658
}

P
pbrook 已提交
659 660 661 662 663 664 665 666 667
void tcg_temp_free_i32(TCGv_i32 arg)
{
    tcg_temp_free_internal(GET_TCGV_I32(arg));
}

void tcg_temp_free_i64(TCGv_i64 arg)
{
    tcg_temp_free_internal(GET_TCGV_I64(arg));
}
668

P
pbrook 已提交
669
TCGv_i32 tcg_const_i32(int32_t val)
B
bellard 已提交
670
{
P
pbrook 已提交
671 672
    TCGv_i32 t0;
    t0 = tcg_temp_new_i32();
673 674 675
    tcg_gen_movi_i32(t0, val);
    return t0;
}
B
bellard 已提交
676

P
pbrook 已提交
677
TCGv_i64 tcg_const_i64(int64_t val)
678
{
P
pbrook 已提交
679 680
    TCGv_i64 t0;
    t0 = tcg_temp_new_i64();
681 682
    tcg_gen_movi_i64(t0, val);
    return t0;
B
bellard 已提交
683 684
}

P
pbrook 已提交
685
TCGv_i32 tcg_const_local_i32(int32_t val)
A
aurel32 已提交
686
{
P
pbrook 已提交
687 688
    TCGv_i32 t0;
    t0 = tcg_temp_local_new_i32();
A
aurel32 已提交
689 690 691 692
    tcg_gen_movi_i32(t0, val);
    return t0;
}

P
pbrook 已提交
693
TCGv_i64 tcg_const_local_i64(int64_t val)
A
aurel32 已提交
694
{
P
pbrook 已提交
695 696
    TCGv_i64 t0;
    t0 = tcg_temp_local_new_i64();
A
aurel32 已提交
697 698 699 700
    tcg_gen_movi_i64(t0, val);
    return t0;
}

701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721
#if defined(CONFIG_DEBUG_TCG)
void tcg_clear_temp_count(void)
{
    TCGContext *s = &tcg_ctx;
    s->temps_in_use = 0;
}

int tcg_check_temp_count(void)
{
    TCGContext *s = &tcg_ctx;
    if (s->temps_in_use) {
        /* Clear the count so that we don't give another
         * warning immediately next time around.
         */
        s->temps_in_use = 0;
        return 1;
    }
    return 0;
}
#endif

B
bellard 已提交
722 723 724
/* Note: we convert the 64 bit args to 32 bit and do some alignment
   and endian swap. Maybe it would be better to do the alignment
   and endian swap in tcg_reg_alloc_call(). */
725 726
void tcg_gen_callN(TCGContext *s, void *func, TCGArg ret,
                   int nargs, TCGArg *args)
B
bellard 已提交
727
{
728
    int i, real_args, nb_rets, pi, pi_first;
729
    unsigned sizemask, flags;
730 731 732
    TCGHelperInfo *info;

    info = g_hash_table_lookup(s->helpers, (gpointer)func);
733 734
    flags = info->flags;
    sizemask = info->sizemask;
735

736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765
#if defined(__sparc__) && !defined(__arch64__) \
    && !defined(CONFIG_TCG_INTERPRETER)
    /* We have 64-bit values in one register, but need to pass as two
       separate parameters.  Split them.  */
    int orig_sizemask = sizemask;
    int orig_nargs = nargs;
    TCGv_i64 retl, reth;

    TCGV_UNUSED_I64(retl);
    TCGV_UNUSED_I64(reth);
    if (sizemask != 0) {
        TCGArg *split_args = __builtin_alloca(sizeof(TCGArg) * nargs * 2);
        for (i = real_args = 0; i < nargs; ++i) {
            int is_64bit = sizemask & (1 << (i+1)*2);
            if (is_64bit) {
                TCGv_i64 orig = MAKE_TCGV_I64(args[i]);
                TCGv_i32 h = tcg_temp_new_i32();
                TCGv_i32 l = tcg_temp_new_i32();
                tcg_gen_extr_i64_i32(l, h, orig);
                split_args[real_args++] = GET_TCGV_I32(h);
                split_args[real_args++] = GET_TCGV_I32(l);
            } else {
                split_args[real_args++] = args[i];
            }
        }
        nargs = real_args;
        args = split_args;
        sizemask = 0;
    }
#elif defined(TCG_TARGET_EXTEND_ARGS) && TCG_TARGET_REG_BITS == 64
766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781
    for (i = 0; i < nargs; ++i) {
        int is_64bit = sizemask & (1 << (i+1)*2);
        int is_signed = sizemask & (2 << (i+1)*2);
        if (!is_64bit) {
            TCGv_i64 temp = tcg_temp_new_i64();
            TCGv_i64 orig = MAKE_TCGV_I64(args[i]);
            if (is_signed) {
                tcg_gen_ext32s_i64(temp, orig);
            } else {
                tcg_gen_ext32u_i64(temp, orig);
            }
            args[i] = GET_TCGV_I64(temp);
        }
    }
#endif /* TCG_TARGET_EXTEND_ARGS */

782
    pi_first = pi = s->gen_next_parm_idx;
P
pbrook 已提交
783
    if (ret != TCG_CALL_DUMMY_ARG) {
784 785 786 787 788 789 790 791
#if defined(__sparc__) && !defined(__arch64__) \
    && !defined(CONFIG_TCG_INTERPRETER)
        if (orig_sizemask & 1) {
            /* The 32-bit ABI is going to return the 64-bit value in
               the %o0/%o1 register pair.  Prepare for this by using
               two return temporaries, and reassemble below.  */
            retl = tcg_temp_new_i64();
            reth = tcg_temp_new_i64();
792 793
            s->gen_opparam_buf[pi++] = GET_TCGV_I64(reth);
            s->gen_opparam_buf[pi++] = GET_TCGV_I64(retl);
794 795
            nb_rets = 2;
        } else {
796
            s->gen_opparam_buf[pi++] = ret;
797 798 799 800
            nb_rets = 1;
        }
#else
        if (TCG_TARGET_REG_BITS < 64 && (sizemask & 1)) {
801
#ifdef HOST_WORDS_BIGENDIAN
802 803
            s->gen_opparam_buf[pi++] = ret + 1;
            s->gen_opparam_buf[pi++] = ret;
B
bellard 已提交
804
#else
805 806
            s->gen_opparam_buf[pi++] = ret;
            s->gen_opparam_buf[pi++] = ret + 1;
B
bellard 已提交
807
#endif
P
pbrook 已提交
808
            nb_rets = 2;
809
        } else {
810
            s->gen_opparam_buf[pi++] = ret;
P
pbrook 已提交
811
            nb_rets = 1;
B
bellard 已提交
812
        }
813
#endif
P
pbrook 已提交
814 815
    } else {
        nb_rets = 0;
B
bellard 已提交
816
    }
P
pbrook 已提交
817 818
    real_args = 0;
    for (i = 0; i < nargs; i++) {
819
        int is_64bit = sizemask & (1 << (i+1)*2);
820
        if (TCG_TARGET_REG_BITS < 64 && is_64bit) {
B
bellard 已提交
821 822
#ifdef TCG_TARGET_CALL_ALIGN_ARGS
            /* some targets want aligned 64 bit args */
M
malc 已提交
823
            if (real_args & 1) {
824
                s->gen_opparam_buf[pi++] = TCG_CALL_DUMMY_ARG;
M
malc 已提交
825
                real_args++;
B
bellard 已提交
826 827
            }
#endif
828 829 830 831 832 833 834 835 836 837
	    /* If stack grows up, then we will be placing successive
	       arguments at lower addresses, which means we need to
	       reverse the order compared to how we would normally
	       treat either big or little-endian.  For those arguments
	       that will wind up in registers, this still works for
	       HPPA (the only current STACK_GROWSUP target) since the
	       argument registers are *also* allocated in decreasing
	       order.  If another such target is added, this logic may
	       have to get more complicated to differentiate between
	       stack arguments and register arguments.  */
838
#if defined(HOST_WORDS_BIGENDIAN) != defined(TCG_TARGET_STACK_GROWSUP)
839 840
            s->gen_opparam_buf[pi++] = args[i] + 1;
            s->gen_opparam_buf[pi++] = args[i];
B
bellard 已提交
841
#else
842 843
            s->gen_opparam_buf[pi++] = args[i];
            s->gen_opparam_buf[pi++] = args[i] + 1;
B
bellard 已提交
844
#endif
P
pbrook 已提交
845
            real_args += 2;
846
            continue;
B
bellard 已提交
847
        }
848

849
        s->gen_opparam_buf[pi++] = args[i];
850
        real_args++;
B
bellard 已提交
851
    }
852 853
    s->gen_opparam_buf[pi++] = (uintptr_t)func;
    s->gen_opparam_buf[pi++] = flags;
P
pbrook 已提交
854

855 856 857
    i = s->gen_next_op_idx;
    tcg_debug_assert(i < OPC_BUF_SIZE);
    tcg_debug_assert(pi <= OPPARAM_BUF_SIZE);
P
pbrook 已提交
858

859 860 861 862 863 864 865 866 867 868 869 870 871
    /* Set links for sequential allocation during translation.  */
    s->gen_op_buf[i] = (TCGOp){
        .opc = INDEX_op_call,
        .callo = nb_rets,
        .calli = real_args,
        .args = pi_first,
        .prev = i - 1,
        .next = i + 1
    };

    /* Make sure the calli field didn't overflow.  */
    tcg_debug_assert(s->gen_op_buf[i].calli == real_args);

R
Richard Henderson 已提交
872
    s->gen_op_buf[0].prev = i;
873 874
    s->gen_next_op_idx = i + 1;
    s->gen_next_parm_idx = pi;
875

876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898
#if defined(__sparc__) && !defined(__arch64__) \
    && !defined(CONFIG_TCG_INTERPRETER)
    /* Free all of the parts we allocated above.  */
    for (i = real_args = 0; i < orig_nargs; ++i) {
        int is_64bit = orig_sizemask & (1 << (i+1)*2);
        if (is_64bit) {
            TCGv_i32 h = MAKE_TCGV_I32(args[real_args++]);
            TCGv_i32 l = MAKE_TCGV_I32(args[real_args++]);
            tcg_temp_free_i32(h);
            tcg_temp_free_i32(l);
        } else {
            real_args++;
        }
    }
    if (orig_sizemask & 1) {
        /* The 32-bit ABI returned two 32-bit pieces.  Re-assemble them.
           Note that describing these as TCGv_i64 eliminates an unnecessary
           zero-extension that tcg_gen_concat_i32_i64 would create.  */
        tcg_gen_concat32_i64(MAKE_TCGV_I64(ret), retl, reth);
        tcg_temp_free_i64(retl);
        tcg_temp_free_i64(reth);
    }
#elif defined(TCG_TARGET_EXTEND_ARGS) && TCG_TARGET_REG_BITS == 64
899 900 901 902 903 904 905 906
    for (i = 0; i < nargs; ++i) {
        int is_64bit = sizemask & (1 << (i+1)*2);
        if (!is_64bit) {
            TCGv_i64 temp = MAKE_TCGV_I64(args[i]);
            tcg_temp_free_i64(temp);
        }
    }
#endif /* TCG_TARGET_EXTEND_ARGS */
B
bellard 已提交
907 908
}

909
static void tcg_reg_alloc_start(TCGContext *s)
B
bellard 已提交
910 911 912 913 914 915 916 917 918 919 920
{
    int i;
    TCGTemp *ts;
    for(i = 0; i < s->nb_globals; i++) {
        ts = &s->temps[i];
        if (ts->fixed_reg) {
            ts->val_type = TEMP_VAL_REG;
        } else {
            ts->val_type = TEMP_VAL_MEM;
        }
    }
921 922
    for(i = s->nb_globals; i < s->nb_temps; i++) {
        ts = &s->temps[i];
923 924 925 926 927
        if (ts->temp_local) {
            ts->val_type = TEMP_VAL_MEM;
        } else {
            ts->val_type = TEMP_VAL_DEAD;
        }
928 929 930
        ts->mem_allocated = 0;
        ts->fixed_reg = 0;
    }
931 932

    memset(s->reg_to_temp, 0, sizeof(s->reg_to_temp));
B
bellard 已提交
933 934
}

935 936
static char *tcg_get_arg_str_ptr(TCGContext *s, char *buf, int buf_size,
                                 TCGTemp *ts)
B
bellard 已提交
937
{
938
    int idx = temp_idx(s, ts);
P
pbrook 已提交
939 940 941

    if (idx < s->nb_globals) {
        pstrcpy(buf, buf_size, ts->name);
942 943
    } else if (ts->temp_local) {
        snprintf(buf, buf_size, "loc%d", idx - s->nb_globals);
B
bellard 已提交
944
    } else {
945
        snprintf(buf, buf_size, "tmp%d", idx - s->nb_globals);
B
bellard 已提交
946 947 948 949
    }
    return buf;
}

950 951 952
static char *tcg_get_arg_str_idx(TCGContext *s, char *buf,
                                 int buf_size, int idx)
{
953
    tcg_debug_assert(idx >= 0 && idx < s->nb_temps);
954 955 956
    return tcg_get_arg_str_ptr(s, buf, buf_size, &s->temps[idx]);
}

957 958
/* Find helper name.  */
static inline const char *tcg_find_helper(TCGContext *s, uintptr_t val)
B
bellard 已提交
959
{
960 961
    const char *ret = NULL;
    if (s->helpers) {
962 963 964 965
        TCGHelperInfo *info = g_hash_table_lookup(s->helpers, (gpointer)val);
        if (info) {
            ret = info->name;
        }
B
bellard 已提交
966
    }
967
    return ret;
B
bellard 已提交
968 969
}

970 971
static const char * const cond_name[] =
{
972 973
    [TCG_COND_NEVER] = "never",
    [TCG_COND_ALWAYS] = "always",
974 975 976 977 978 979 980 981 982 983 984 985
    [TCG_COND_EQ] = "eq",
    [TCG_COND_NE] = "ne",
    [TCG_COND_LT] = "lt",
    [TCG_COND_GE] = "ge",
    [TCG_COND_LE] = "le",
    [TCG_COND_GT] = "gt",
    [TCG_COND_LTU] = "ltu",
    [TCG_COND_GEU] = "geu",
    [TCG_COND_LEU] = "leu",
    [TCG_COND_GTU] = "gtu"
};

R
Richard Henderson 已提交
986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001
static const char * const ldst_name[] =
{
    [MO_UB]   = "ub",
    [MO_SB]   = "sb",
    [MO_LEUW] = "leuw",
    [MO_LESW] = "lesw",
    [MO_LEUL] = "leul",
    [MO_LESL] = "lesl",
    [MO_LEQ]  = "leq",
    [MO_BEUW] = "beuw",
    [MO_BESW] = "besw",
    [MO_BEUL] = "beul",
    [MO_BESL] = "besl",
    [MO_BEQ]  = "beq",
};

1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017
static const char * const alignment_name[(MO_AMASK >> MO_ASHIFT) + 1] = {
#ifdef ALIGNED_ONLY
    [MO_UNALN >> MO_ASHIFT]    = "un+",
    [MO_ALIGN >> MO_ASHIFT]    = "",
#else
    [MO_UNALN >> MO_ASHIFT]    = "",
    [MO_ALIGN >> MO_ASHIFT]    = "al+",
#endif
    [MO_ALIGN_2 >> MO_ASHIFT]  = "al2+",
    [MO_ALIGN_4 >> MO_ASHIFT]  = "al4+",
    [MO_ALIGN_8 >> MO_ASHIFT]  = "al8+",
    [MO_ALIGN_16 >> MO_ASHIFT] = "al16+",
    [MO_ALIGN_32 >> MO_ASHIFT] = "al32+",
    [MO_ALIGN_64 >> MO_ASHIFT] = "al64+",
};

B
Blue Swirl 已提交
1018
void tcg_dump_ops(TCGContext *s)
B
bellard 已提交
1019 1020
{
    char buf[128];
1021 1022 1023
    TCGOp *op;
    int oi;

R
Richard Henderson 已提交
1024
    for (oi = s->gen_op_buf[0].next; oi != 0; oi = op->next) {
1025 1026 1027 1028
        int i, k, nb_oargs, nb_iargs, nb_cargs;
        const TCGOpDef *def;
        const TCGArg *args;
        TCGOpcode c;
B
bellard 已提交
1029

1030 1031
        op = &s->gen_op_buf[oi];
        c = op->opc;
B
bellard 已提交
1032
        def = &tcg_op_defs[c];
1033 1034
        args = &s->gen_opparam_buf[op->args];

1035
        if (c == INDEX_op_insn_start) {
R
Richard Henderson 已提交
1036
            qemu_log("%s ----", oi != s->gen_op_buf[0].next ? "\n" : "");
1037 1038 1039

            for (i = 0; i < TARGET_INSN_START_WORDS; ++i) {
                target_ulong a;
1040
#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
1041
                a = ((target_ulong)args[i * 2 + 1] << 32) | args[i * 2];
1042
#else
1043
                a = args[i];
1044
#endif
1045
                qemu_log(" " TARGET_FMT_lx, a);
B
Blue Swirl 已提交
1046
            }
1047
        } else if (c == INDEX_op_call) {
B
bellard 已提交
1048
            /* variable number of arguments */
1049 1050
            nb_oargs = op->callo;
            nb_iargs = op->calli;
B
bellard 已提交
1051 1052
            nb_cargs = def->nb_cargs;

1053 1054 1055 1056 1057 1058
            /* function name, flags, out args */
            qemu_log(" %s %s,$0x%" TCG_PRIlx ",$%d", def->name,
                     tcg_find_helper(s, args[nb_oargs + nb_iargs]),
                     args[nb_oargs + nb_iargs + 1], nb_oargs);
            for (i = 0; i < nb_oargs; i++) {
                qemu_log(",%s", tcg_get_arg_str_idx(s, buf, sizeof(buf),
B
Blue Swirl 已提交
1059
                                                   args[i]));
1060
            }
1061 1062 1063 1064 1065
            for (i = 0; i < nb_iargs; i++) {
                TCGArg arg = args[nb_oargs + i];
                const char *t = "<dummy>";
                if (arg != TCG_CALL_DUMMY_ARG) {
                    t = tcg_get_arg_str_idx(s, buf, sizeof(buf), arg);
B
Blue Swirl 已提交
1066
                }
1067
                qemu_log(",%s", t);
1068
            }
1069
        } else {
B
Blue Swirl 已提交
1070
            qemu_log(" %s ", def->name);
1071 1072 1073 1074 1075

            nb_oargs = def->nb_oargs;
            nb_iargs = def->nb_iargs;
            nb_cargs = def->nb_cargs;

1076
            k = 0;
1077
            for (i = 0; i < nb_oargs; i++) {
B
Blue Swirl 已提交
1078 1079 1080 1081 1082
                if (k != 0) {
                    qemu_log(",");
                }
                qemu_log("%s", tcg_get_arg_str_idx(s, buf, sizeof(buf),
                                                   args[k++]));
1083
            }
1084
            for (i = 0; i < nb_iargs; i++) {
B
Blue Swirl 已提交
1085 1086 1087 1088 1089
                if (k != 0) {
                    qemu_log(",");
                }
                qemu_log("%s", tcg_get_arg_str_idx(s, buf, sizeof(buf),
                                                   args[k++]));
1090
            }
1091 1092 1093
            switch (c) {
            case INDEX_op_brcond_i32:
            case INDEX_op_setcond_i32:
R
Richard Henderson 已提交
1094 1095
            case INDEX_op_movcond_i32:
            case INDEX_op_brcond2_i32:
1096
            case INDEX_op_setcond2_i32:
R
Richard Henderson 已提交
1097
            case INDEX_op_brcond_i64:
1098
            case INDEX_op_setcond_i64:
R
Richard Henderson 已提交
1099
            case INDEX_op_movcond_i64:
B
Blue Swirl 已提交
1100 1101 1102 1103 1104
                if (args[k] < ARRAY_SIZE(cond_name) && cond_name[args[k]]) {
                    qemu_log(",%s", cond_name[args[k++]]);
                } else {
                    qemu_log(",$0x%" TCG_PRIlx, args[k++]);
                }
1105
                i = 1;
1106
                break;
R
Richard Henderson 已提交
1107 1108 1109 1110
            case INDEX_op_qemu_ld_i32:
            case INDEX_op_qemu_st_i32:
            case INDEX_op_qemu_ld_i64:
            case INDEX_op_qemu_st_i64:
1111 1112 1113 1114 1115
                {
                    TCGMemOpIdx oi = args[k++];
                    TCGMemOp op = get_memop(oi);
                    unsigned ix = get_mmuidx(oi);

1116
                    if (op & ~(MO_AMASK | MO_BSWAP | MO_SSIZE)) {
1117
                        qemu_log(",$0x%x,%u", op, ix);
1118
                    } else {
1119 1120
                        const char *s_al, *s_op;
                        s_al = alignment_name[(op & MO_AMASK) >> MO_ASHIFT];
1121 1122
                        s_op = ldst_name[op & (MO_BSWAP | MO_SSIZE)];
                        qemu_log(",%s%s,%u", s_al, s_op, ix);
1123 1124
                    }
                    i = 1;
R
Richard Henderson 已提交
1125 1126
                }
                break;
1127
            default:
1128
                i = 0;
1129 1130
                break;
            }
1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144
            switch (c) {
            case INDEX_op_set_label:
            case INDEX_op_br:
            case INDEX_op_brcond_i32:
            case INDEX_op_brcond_i64:
            case INDEX_op_brcond2_i32:
                qemu_log("%s$L%d", k ? "," : "", arg_label(args[k])->id);
                i++, k++;
                break;
            default:
                break;
            }
            for (; i < nb_cargs; i++, k++) {
                qemu_log("%s$0x%" TCG_PRIlx, k ? "," : "", args[k]);
1145
            }
B
bellard 已提交
1146
        }
B
Blue Swirl 已提交
1147
        qemu_log("\n");
B
bellard 已提交
1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196
    }
}

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

    int i, n;
    arg_ct = &def->args_ct[k];
    if (arg_ct->ct & TCG_CT_ALIAS) {
        /* an alias is equivalent to a single register */
        n = 1;
    } else {
        if (!(arg_ct->ct & TCG_CT_REG))
            return 0;
        n = 0;
        for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
            if (tcg_regset_test_reg(arg_ct->u.regs, i))
                n++;
        }
    }
    return TCG_TARGET_NB_REGS - n + 1;
}

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

    for(i = 0; i < n; i++)
        def->sorted_args[start + i] = start + i;
    if (n <= 1)
        return;
    for(i = 0; i < n - 1; i++) {
        for(j = i + 1; j < n; j++) {
            p1 = get_constraint_priority(def, def->sorted_args[start + i]);
            p2 = get_constraint_priority(def, def->sorted_args[start + j]);
            if (p1 < p2) {
                tmp = def->sorted_args[start + i];
                def->sorted_args[start + i] = def->sorted_args[start + j];
                def->sorted_args[start + j] = tmp;
            }
        }
    }
}

void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs)
{
1197
    TCGOpcode op;
B
bellard 已提交
1198 1199 1200 1201 1202
    TCGOpDef *def;
    const char *ct_str;
    int i, nb_args;

    for(;;) {
1203
        if (tdefs->op == (TCGOpcode)-1)
B
bellard 已提交
1204 1205
            break;
        op = tdefs->op;
1206
        tcg_debug_assert((unsigned)op < NB_OPS);
B
bellard 已提交
1207
        def = &tcg_op_defs[op];
1208 1209
#if defined(CONFIG_DEBUG_TCG)
        /* Duplicate entry in op definitions? */
1210
        tcg_debug_assert(!def->used);
1211 1212
        def->used = 1;
#endif
B
bellard 已提交
1213 1214 1215
        nb_args = def->nb_iargs + def->nb_oargs;
        for(i = 0; i < nb_args; i++) {
            ct_str = tdefs->args_ct_str[i];
1216
            /* Incomplete TCGTargetOpDef entry? */
1217
            tcg_debug_assert(ct_str != NULL);
B
bellard 已提交
1218 1219 1220 1221 1222
            tcg_regset_clear(def->args_ct[i].u.regs);
            def->args_ct[i].ct = 0;
            if (ct_str[0] >= '0' && ct_str[0] <= '9') {
                int oarg;
                oarg = ct_str[0] - '0';
1223 1224
                tcg_debug_assert(oarg < def->nb_oargs);
                tcg_debug_assert(def->args_ct[oarg].ct & TCG_CT_REG);
B
bellard 已提交
1225
                /* TCG_CT_ALIAS is for the output arguments. The input
1226
                   argument is tagged with TCG_CT_IALIAS. */
B
bellard 已提交
1227
                def->args_ct[i] = def->args_ct[oarg];
1228 1229
                def->args_ct[oarg].ct = TCG_CT_ALIAS;
                def->args_ct[oarg].alias_index = i;
B
bellard 已提交
1230
                def->args_ct[i].ct |= TCG_CT_IALIAS;
1231
                def->args_ct[i].alias_index = oarg;
B
bellard 已提交
1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251
            } else {
                for(;;) {
                    if (*ct_str == '\0')
                        break;
                    switch(*ct_str) {
                    case 'i':
                        def->args_ct[i].ct |= TCG_CT_CONST;
                        ct_str++;
                        break;
                    default:
                        if (target_parse_constraint(&def->args_ct[i], &ct_str) < 0) {
                            fprintf(stderr, "Invalid constraint '%s' for arg %d of operation '%s'\n",
                                    ct_str, i, def->name);
                            exit(1);
                        }
                    }
                }
            }
        }

1252
        /* TCGTargetOpDef entry with too much information? */
1253
        tcg_debug_assert(i == TCG_MAX_OP_ARGS || tdefs->args_ct_str[i] == NULL);
1254

B
bellard 已提交
1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271
        /* sort the constraints (XXX: this is just an heuristic) */
        sort_constraints(def, 0, def->nb_oargs);
        sort_constraints(def, def->nb_oargs, def->nb_iargs);

#if 0
        {
            int i;

            printf("%s: sorted=", def->name);
            for(i = 0; i < def->nb_oargs + def->nb_iargs; i++)
                printf(" %d", def->sorted_args[i]);
            printf("\n");
        }
#endif
        tdefs++;
    }

1272
#if defined(CONFIG_DEBUG_TCG)
1273
    i = 0;
1274
    for (op = 0; op < tcg_op_defs_max; op++) {
1275
        const TCGOpDef *def = &tcg_op_defs[op];
1276
        if (def->flags & TCG_OPF_NOT_PRESENT) {
1277
            /* Wrong entry in op definitions? */
1278 1279
            if (def->used) {
                fprintf(stderr, "Invalid op definition for %s\n", def->name);
1280 1281
                i = 1;
            }
1282 1283
        } else {
            /* Missing entry in op definitions? */
1284 1285
            if (!def->used) {
                fprintf(stderr, "Missing op definition for %s\n", def->name);
1286 1287
                i = 1;
            }
1288 1289
        }
    }
1290 1291 1292
    if (i == 1) {
        tcg_abort();
    }
1293
#endif
B
bellard 已提交
1294 1295
}

1296 1297 1298 1299 1300
void tcg_op_remove(TCGContext *s, TCGOp *op)
{
    int next = op->next;
    int prev = op->prev;

R
Richard Henderson 已提交
1301 1302 1303 1304 1305
    /* We should never attempt to remove the list terminator.  */
    tcg_debug_assert(op != &s->gen_op_buf[0]);

    s->gen_op_buf[next].prev = prev;
    s->gen_op_buf[prev].next = next;
1306

R
Richard Henderson 已提交
1307
    memset(op, 0, sizeof(*op));
1308 1309 1310 1311 1312 1313

#ifdef CONFIG_PROFILER
    s->del_op_count++;
#endif
}

B
bellard 已提交
1314
#ifdef USE_LIVENESS_ANALYSIS
A
Aurelien Jarno 已提交
1315 1316 1317 1318
/* liveness analysis: end of function: all temps are dead, and globals
   should be in memory. */
static inline void tcg_la_func_end(TCGContext *s, uint8_t *dead_temps,
                                   uint8_t *mem_temps)
B
bellard 已提交
1319
{
A
Aurelien Jarno 已提交
1320 1321 1322
    memset(dead_temps, 1, s->nb_temps);
    memset(mem_temps, 1, s->nb_globals);
    memset(mem_temps + s->nb_globals, 0, s->nb_temps - s->nb_globals);
B
bellard 已提交
1323 1324
}

A
Aurelien Jarno 已提交
1325 1326 1327 1328
/* liveness analysis: end of basic block: all temps are dead, globals
   and local temps should be in memory. */
static inline void tcg_la_bb_end(TCGContext *s, uint8_t *dead_temps,
                                 uint8_t *mem_temps)
B
bellard 已提交
1329 1330 1331
{
    int i;

A
Aurelien Jarno 已提交
1332 1333
    memset(dead_temps, 1, s->nb_temps);
    memset(mem_temps, 1, s->nb_globals);
B
bellard 已提交
1334
    for(i = s->nb_globals; i < s->nb_temps; i++) {
A
Aurelien Jarno 已提交
1335
        mem_temps[i] = s->temps[i].temp_local;
B
bellard 已提交
1336 1337 1338
    }
}

1339
/* Liveness analysis : update the opc_arg_life array to tell if a
B
bellard 已提交
1340 1341
   given input arguments is dead. Instructions updating dead
   temporaries are removed. */
1342
static void tcg_liveness_analysis(TCGContext *s)
B
bellard 已提交
1343
{
A
Aurelien Jarno 已提交
1344
    uint8_t *dead_temps, *mem_temps;
1345
    int oi, oi_prev, nb_ops;
B
bellard 已提交
1346

1347
    nb_ops = s->gen_next_op_idx;
1348 1349
    s->op_arg_life = tcg_malloc(nb_ops * sizeof(TCGLifeData));

B
bellard 已提交
1350
    dead_temps = tcg_malloc(s->nb_temps);
A
Aurelien Jarno 已提交
1351 1352
    mem_temps = tcg_malloc(s->nb_temps);
    tcg_la_func_end(s, dead_temps, mem_temps);
B
bellard 已提交
1353

R
Richard Henderson 已提交
1354
    for (oi = s->gen_op_buf[0].prev; oi != 0; oi = oi_prev) {
1355 1356 1357
        int i, nb_iargs, nb_oargs;
        TCGOpcode opc_new, opc_new2;
        bool have_opc_new2;
1358
        TCGLifeData arg_life = 0;
1359 1360 1361 1362 1363 1364 1365 1366 1367 1368
        TCGArg arg;

        TCGOp * const op = &s->gen_op_buf[oi];
        TCGArg * const args = &s->gen_opparam_buf[op->args];
        TCGOpcode opc = op->opc;
        const TCGOpDef *def = &tcg_op_defs[opc];

        oi_prev = op->prev;

        switch (opc) {
B
bellard 已提交
1369
        case INDEX_op_call:
1370 1371
            {
                int call_flags;
B
bellard 已提交
1372

1373 1374
                nb_oargs = op->callo;
                nb_iargs = op->calli;
1375
                call_flags = args[nb_oargs + nb_iargs + 1];
1376

1377
                /* pure functions can be removed if their result is unused */
A
Aurelien Jarno 已提交
1378
                if (call_flags & TCG_CALL_NO_SIDE_EFFECTS) {
1379
                    for (i = 0; i < nb_oargs; i++) {
1380
                        arg = args[i];
A
Aurelien Jarno 已提交
1381
                        if (!dead_temps[arg] || mem_temps[arg]) {
1382
                            goto do_not_remove_call;
A
Aurelien Jarno 已提交
1383
                        }
1384
                    }
1385
                    goto do_remove;
1386 1387
                } else {
                do_not_remove_call:
B
bellard 已提交
1388

1389
                    /* output args are dead */
1390
                    for (i = 0; i < nb_oargs; i++) {
1391
                        arg = args[i];
1392
                        if (dead_temps[arg]) {
1393
                            arg_life |= DEAD_ARG << i;
1394
                        }
A
Aurelien Jarno 已提交
1395
                        if (mem_temps[arg]) {
1396
                            arg_life |= SYNC_ARG << i;
A
Aurelien Jarno 已提交
1397
                        }
1398
                        dead_temps[arg] = 1;
A
Aurelien Jarno 已提交
1399
                        mem_temps[arg] = 0;
1400
                    }
A
Aurelien Jarno 已提交
1401 1402 1403 1404 1405 1406 1407

                    if (!(call_flags & TCG_CALL_NO_READ_GLOBALS)) {
                        /* globals should be synced to memory */
                        memset(mem_temps, 1, s->nb_globals);
                    }
                    if (!(call_flags & (TCG_CALL_NO_WRITE_GLOBALS |
                                        TCG_CALL_NO_READ_GLOBALS))) {
A
Aurelien Jarno 已提交
1408 1409
                        /* globals should go back to memory */
                        memset(dead_temps, 1, s->nb_globals);
A
aurel32 已提交
1410 1411
                    }

1412
                    /* record arguments that die in this helper */
1413
                    for (i = nb_oargs; i < nb_iargs + nb_oargs; i++) {
1414
                        arg = args[i];
B
bellard 已提交
1415 1416
                        if (arg != TCG_CALL_DUMMY_ARG) {
                            if (dead_temps[arg]) {
1417
                                arg_life |= DEAD_ARG << i;
B
bellard 已提交
1418
                            }
1419 1420
                        }
                    }
V
Veres Lajos 已提交
1421
                    /* input arguments are live for preceding opcodes */
1422 1423 1424 1425
                    for (i = nb_oargs; i < nb_oargs + nb_iargs; i++) {
                        arg = args[i];
                        dead_temps[arg] = 0;
                    }
B
bellard 已提交
1426 1427 1428
                }
            }
            break;
1429
        case INDEX_op_insn_start:
B
bellard 已提交
1430
            break;
1431 1432 1433
        case INDEX_op_discard:
            /* mark the temporary as dead */
            dead_temps[args[0]] = 1;
A
Aurelien Jarno 已提交
1434
            mem_temps[args[0]] = 0;
1435
            break;
1436 1437

        case INDEX_op_add2_i32:
1438
            opc_new = INDEX_op_add_i32;
1439
            goto do_addsub2;
1440
        case INDEX_op_sub2_i32:
1441
            opc_new = INDEX_op_sub_i32;
1442 1443
            goto do_addsub2;
        case INDEX_op_add2_i64:
1444
            opc_new = INDEX_op_add_i64;
1445 1446
            goto do_addsub2;
        case INDEX_op_sub2_i64:
1447
            opc_new = INDEX_op_sub_i64;
1448
        do_addsub2:
1449 1450 1451 1452 1453 1454
            nb_iargs = 4;
            nb_oargs = 2;
            /* Test if the high part of the operation is dead, but not
               the low part.  The result can be optimized to a simple
               add or sub.  This happens often for x86_64 guest when the
               cpu mode is set to 32 bit.  */
1455 1456
            if (dead_temps[args[1]] && !mem_temps[args[1]]) {
                if (dead_temps[args[0]] && !mem_temps[args[0]]) {
1457 1458
                    goto do_remove;
                }
1459 1460 1461
                /* Replace the opcode and adjust the args in place,
                   leaving 3 unused args at the end.  */
                op->opc = opc = opc_new;
1462 1463 1464 1465 1466 1467 1468 1469
                args[1] = args[2];
                args[2] = args[4];
                /* Fall through and mark the single-word operation live.  */
                nb_iargs = 2;
                nb_oargs = 1;
            }
            goto do_not_remove;

R
Richard Henderson 已提交
1470
        case INDEX_op_mulu2_i32:
1471 1472 1473
            opc_new = INDEX_op_mul_i32;
            opc_new2 = INDEX_op_muluh_i32;
            have_opc_new2 = TCG_TARGET_HAS_muluh_i32;
1474
            goto do_mul2;
1475
        case INDEX_op_muls2_i32:
1476 1477 1478
            opc_new = INDEX_op_mul_i32;
            opc_new2 = INDEX_op_mulsh_i32;
            have_opc_new2 = TCG_TARGET_HAS_mulsh_i32;
1479 1480
            goto do_mul2;
        case INDEX_op_mulu2_i64:
1481 1482 1483
            opc_new = INDEX_op_mul_i64;
            opc_new2 = INDEX_op_muluh_i64;
            have_opc_new2 = TCG_TARGET_HAS_muluh_i64;
1484
            goto do_mul2;
1485
        case INDEX_op_muls2_i64:
1486 1487 1488
            opc_new = INDEX_op_mul_i64;
            opc_new2 = INDEX_op_mulsh_i64;
            have_opc_new2 = TCG_TARGET_HAS_mulsh_i64;
1489
            goto do_mul2;
1490
        do_mul2:
R
Richard Henderson 已提交
1491 1492
            nb_iargs = 2;
            nb_oargs = 2;
1493 1494
            if (dead_temps[args[1]] && !mem_temps[args[1]]) {
                if (dead_temps[args[0]] && !mem_temps[args[0]]) {
1495
                    /* Both parts of the operation are dead.  */
R
Richard Henderson 已提交
1496 1497
                    goto do_remove;
                }
1498
                /* The high part of the operation is dead; generate the low. */
1499
                op->opc = opc = opc_new;
R
Richard Henderson 已提交
1500 1501
                args[1] = args[2];
                args[2] = args[3];
1502
            } else if (have_opc_new2 && dead_temps[args[0]]
1503
                       && !mem_temps[args[0]]) {
1504 1505
                /* The low part of the operation is dead; generate the high. */
                op->opc = opc = opc_new2;
1506 1507 1508 1509 1510
                args[0] = args[1];
                args[1] = args[2];
                args[2] = args[3];
            } else {
                goto do_not_remove;
R
Richard Henderson 已提交
1511
            }
1512 1513
            /* Mark the single-word operation live.  */
            nb_oargs = 1;
R
Richard Henderson 已提交
1514 1515
            goto do_not_remove;

B
bellard 已提交
1516
        default:
1517
            /* XXX: optimize by hardcoding common cases (e.g. triadic ops) */
A
aurel32 已提交
1518 1519
            nb_iargs = def->nb_iargs;
            nb_oargs = def->nb_oargs;
B
bellard 已提交
1520

A
aurel32 已提交
1521 1522 1523 1524
            /* Test if the operation can be removed because all
               its outputs are dead. We assume that nb_oargs == 0
               implies side effects */
            if (!(def->flags & TCG_OPF_SIDE_EFFECTS) && nb_oargs != 0) {
1525
                for (i = 0; i < nb_oargs; i++) {
A
aurel32 已提交
1526
                    arg = args[i];
A
Aurelien Jarno 已提交
1527
                    if (!dead_temps[arg] || mem_temps[arg]) {
A
aurel32 已提交
1528
                        goto do_not_remove;
A
Aurelien Jarno 已提交
1529
                    }
A
aurel32 已提交
1530
                }
1531
            do_remove:
1532
                tcg_op_remove(s, op);
A
aurel32 已提交
1533 1534 1535
            } else {
            do_not_remove:
                /* output args are dead */
1536
                for (i = 0; i < nb_oargs; i++) {
A
aurel32 已提交
1537
                    arg = args[i];
1538
                    if (dead_temps[arg]) {
1539
                        arg_life |= DEAD_ARG << i;
1540
                    }
A
Aurelien Jarno 已提交
1541
                    if (mem_temps[arg]) {
1542
                        arg_life |= SYNC_ARG << i;
A
Aurelien Jarno 已提交
1543
                    }
A
aurel32 已提交
1544
                    dead_temps[arg] = 1;
A
Aurelien Jarno 已提交
1545
                    mem_temps[arg] = 0;
A
aurel32 已提交
1546 1547 1548 1549
                }

                /* if end of basic block, update */
                if (def->flags & TCG_OPF_BB_END) {
A
Aurelien Jarno 已提交
1550
                    tcg_la_bb_end(s, dead_temps, mem_temps);
1551 1552
                } else if (def->flags & TCG_OPF_SIDE_EFFECTS) {
                    /* globals should be synced to memory */
A
Aurelien Jarno 已提交
1553
                    memset(mem_temps, 1, s->nb_globals);
A
aurel32 已提交
1554 1555
                }

1556
                /* record arguments that die in this opcode */
1557
                for (i = nb_oargs; i < nb_oargs + nb_iargs; i++) {
1558
                    arg = args[i];
A
aurel32 已提交
1559
                    if (dead_temps[arg]) {
1560
                        arg_life |= DEAD_ARG << i;
B
bellard 已提交
1561
                    }
1562
                }
V
Veres Lajos 已提交
1563
                /* input arguments are live for preceding opcodes */
1564 1565
                for (i = nb_oargs; i < nb_oargs + nb_iargs; i++) {
                    arg = args[i];
A
aurel32 已提交
1566
                    dead_temps[arg] = 0;
B
bellard 已提交
1567 1568 1569 1570
                }
            }
            break;
        }
1571
        s->op_arg_life[oi] = arg_life;
1572
    }
B
bellard 已提交
1573 1574 1575
}
#else
/* dummy liveness analysis */
M
malc 已提交
1576
static void tcg_liveness_analysis(TCGContext *s)
B
bellard 已提交
1577
{
1578
    int nb_ops = s->gen_next_op_idx;
B
bellard 已提交
1579

1580 1581
    s->op_dead_args = tcg_malloc(nb_ops * sizeof(uint16_t));
    memset(s->op_dead_args, 0, nb_ops * sizeof(uint16_t));
1582 1583
    s->op_sync_args = tcg_malloc(nb_ops * sizeof(uint8_t));
    memset(s->op_sync_args, 0, nb_ops * sizeof(uint8_t));
B
bellard 已提交
1584 1585 1586
}
#endif

1587
#ifdef CONFIG_DEBUG_TCG
B
bellard 已提交
1588 1589 1590 1591 1592 1593 1594 1595
static void dump_regs(TCGContext *s)
{
    TCGTemp *ts;
    int i;
    char buf[64];

    for(i = 0; i < s->nb_temps; i++) {
        ts = &s->temps[i];
P
pbrook 已提交
1596
        printf("  %10s: ", tcg_get_arg_str_idx(s, buf, sizeof(buf), i));
B
bellard 已提交
1597 1598 1599 1600 1601
        switch(ts->val_type) {
        case TEMP_VAL_REG:
            printf("%s", tcg_target_reg_names[ts->reg]);
            break;
        case TEMP_VAL_MEM:
1602 1603
            printf("%d(%s)", (int)ts->mem_offset,
                   tcg_target_reg_names[ts->mem_base->reg]);
B
bellard 已提交
1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618
            break;
        case TEMP_VAL_CONST:
            printf("$0x%" TCG_PRIlx, ts->val);
            break;
        case TEMP_VAL_DEAD:
            printf("D");
            break;
        default:
            printf("???");
            break;
        }
        printf("\n");
    }

    for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
1619
        if (s->reg_to_temp[i] != NULL) {
B
bellard 已提交
1620 1621
            printf("%s: %s\n", 
                   tcg_target_reg_names[i], 
1622
                   tcg_get_arg_str_ptr(s, buf, sizeof(buf), s->reg_to_temp[i]));
B
bellard 已提交
1623 1624 1625 1626 1627 1628
        }
    }
}

static void check_regs(TCGContext *s)
{
1629
    int reg;
1630
    int k;
B
bellard 已提交
1631 1632 1633
    TCGTemp *ts;
    char buf[64];

1634 1635 1636 1637
    for (reg = 0; reg < TCG_TARGET_NB_REGS; reg++) {
        ts = s->reg_to_temp[reg];
        if (ts != NULL) {
            if (ts->val_type != TEMP_VAL_REG || ts->reg != reg) {
B
bellard 已提交
1638 1639
                printf("Inconsistency for register %s:\n", 
                       tcg_target_reg_names[reg]);
1640
                goto fail;
B
bellard 已提交
1641 1642 1643
            }
        }
    }
1644
    for (k = 0; k < s->nb_temps; k++) {
B
bellard 已提交
1645
        ts = &s->temps[k];
1646 1647 1648 1649
        if (ts->val_type == TEMP_VAL_REG && !ts->fixed_reg
            && s->reg_to_temp[ts->reg] != ts) {
            printf("Inconsistency for temp %s:\n",
                   tcg_get_arg_str_ptr(s, buf, sizeof(buf), ts));
1650
        fail:
1651 1652 1653
            printf("reg state:\n");
            dump_regs(s);
            tcg_abort();
B
bellard 已提交
1654 1655 1656 1657 1658 1659 1660 1661 1662
        }
    }
}
#endif

static void temp_allocate_frame(TCGContext *s, int temp)
{
    TCGTemp *ts;
    ts = &s->temps[temp];
1663 1664
#if !(defined(__sparc__) && TCG_TARGET_REG_BITS == 64)
    /* Sparc64 stack is accessed with offset of 2047 */
1665 1666 1667
    s->current_frame_offset = (s->current_frame_offset +
                               (tcg_target_long)sizeof(tcg_target_long) - 1) &
        ~(sizeof(tcg_target_long) - 1);
1668
#endif
1669 1670
    if (s->current_frame_offset + (tcg_target_long)sizeof(tcg_target_long) >
        s->frame_end) {
1671
        tcg_abort();
1672
    }
B
bellard 已提交
1673
    ts->mem_offset = s->current_frame_offset;
1674
    ts->mem_base = s->frame_temp;
B
bellard 已提交
1675
    ts->mem_allocated = 1;
1676
    s->current_frame_offset += sizeof(tcg_target_long);
B
bellard 已提交
1677 1678
}

1679 1680
static void temp_load(TCGContext *, TCGTemp *, TCGRegSet, TCGRegSet);

1681 1682 1683
/* Mark a temporary as free or dead.  If 'free_or_dead' is negative,
   mark it free; otherwise mark it dead.  */
static void temp_free_or_dead(TCGContext *s, TCGTemp *ts, int free_or_dead)
A
Aurelien Jarno 已提交
1684
{
1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695
    if (ts->fixed_reg) {
        return;
    }
    if (ts->val_type == TEMP_VAL_REG) {
        s->reg_to_temp[ts->reg] = NULL;
    }
    ts->val_type = (free_or_dead < 0
                    || ts->temp_local
                    || temp_idx(s, ts) < s->nb_globals
                    ? TEMP_VAL_MEM : TEMP_VAL_DEAD);
}
A
Aurelien Jarno 已提交
1696

1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713
/* Mark a temporary as dead.  */
static inline void temp_dead(TCGContext *s, TCGTemp *ts)
{
    temp_free_or_dead(s, ts, 1);
}

/* Sync a temporary to memory. 'allocated_regs' is used in case a temporary
   registers needs to be allocated to store a constant.  If 'free_or_dead'
   is non-zero, subsequently release the temporary; if it is positive, the
   temp is dead; if it is negative, the temp is free.  */
static void temp_sync(TCGContext *s, TCGTemp *ts,
                      TCGRegSet allocated_regs, int free_or_dead)
{
    if (ts->fixed_reg) {
        return;
    }
    if (!ts->mem_coherent) {
A
Aurelien Jarno 已提交
1714
        if (!ts->mem_allocated) {
1715
            temp_allocate_frame(s, temp_idx(s, ts));
1716 1717 1718 1719 1720
        }
        if (ts->indirect_reg) {
            if (ts->val_type == TEMP_VAL_REG) {
                tcg_regset_set_reg(allocated_regs, ts->reg);
            }
1721 1722 1723
            temp_load(s, ts->mem_base,
                      tcg_target_available_regs[TCG_TYPE_PTR],
                      allocated_regs);
A
Aurelien Jarno 已提交
1724
        }
1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754
        switch (ts->val_type) {
        case TEMP_VAL_CONST:
            /* If we're going to free the temp immediately, then we won't
               require it later in a register, so attempt to store the
               constant to memory directly.  */
            if (free_or_dead
                && tcg_out_sti(s, ts->type, ts->val,
                               ts->mem_base->reg, ts->mem_offset)) {
                break;
            }
            temp_load(s, ts, tcg_target_available_regs[ts->type],
                      allocated_regs);
            /* fallthrough */

        case TEMP_VAL_REG:
            tcg_out_st(s, ts->type, ts->reg,
                       ts->mem_base->reg, ts->mem_offset);
            break;

        case TEMP_VAL_MEM:
            break;

        case TEMP_VAL_DEAD:
        default:
            tcg_abort();
        }
        ts->mem_coherent = 1;
    }
    if (free_or_dead) {
        temp_free_or_dead(s, ts, free_or_dead);
A
Aurelien Jarno 已提交
1755 1756 1757
    }
}

B
bellard 已提交
1758
/* free register 'reg' by spilling the corresponding temporary if necessary */
1759
static void tcg_reg_free(TCGContext *s, TCGReg reg, TCGRegSet allocated_regs)
B
bellard 已提交
1760
{
1761 1762
    TCGTemp *ts = s->reg_to_temp[reg];
    if (ts != NULL) {
1763
        temp_sync(s, ts, allocated_regs, -1);
B
bellard 已提交
1764 1765 1766 1767
    }
}

/* Allocate a register belonging to reg1 & ~reg2 */
1768
static TCGReg tcg_reg_alloc(TCGContext *s, TCGRegSet desired_regs,
1769
                            TCGRegSet allocated_regs, bool rev)
B
bellard 已提交
1770
{
1771 1772
    int i, n = ARRAY_SIZE(tcg_target_reg_alloc_order);
    const int *order;
1773
    TCGReg reg;
B
bellard 已提交
1774 1775
    TCGRegSet reg_ct;

1776
    tcg_regset_andnot(reg_ct, desired_regs, allocated_regs);
1777
    order = rev ? indirect_reg_alloc_order : tcg_target_reg_alloc_order;
B
bellard 已提交
1778 1779

    /* first try free registers */
1780 1781
    for(i = 0; i < n; i++) {
        reg = order[i];
1782
        if (tcg_regset_test_reg(reg_ct, reg) && s->reg_to_temp[reg] == NULL)
B
bellard 已提交
1783 1784 1785 1786
            return reg;
    }

    /* XXX: do better spill choice */
1787 1788
    for(i = 0; i < n; i++) {
        reg = order[i];
B
bellard 已提交
1789
        if (tcg_regset_test_reg(reg_ct, reg)) {
1790
            tcg_reg_free(s, reg, allocated_regs);
B
bellard 已提交
1791 1792 1793 1794 1795 1796 1797
            return reg;
        }
    }

    tcg_abort();
}

R
Richard Henderson 已提交
1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808
/* Make sure the temporary is in a register.  If needed, allocate the register
   from DESIRED while avoiding ALLOCATED.  */
static void temp_load(TCGContext *s, TCGTemp *ts, TCGRegSet desired_regs,
                      TCGRegSet allocated_regs)
{
    TCGReg reg;

    switch (ts->val_type) {
    case TEMP_VAL_REG:
        return;
    case TEMP_VAL_CONST:
1809
        reg = tcg_reg_alloc(s, desired_regs, allocated_regs, ts->indirect_base);
R
Richard Henderson 已提交
1810 1811 1812 1813
        tcg_out_movi(s, ts->type, reg, ts->val);
        ts->mem_coherent = 0;
        break;
    case TEMP_VAL_MEM:
1814
        reg = tcg_reg_alloc(s, desired_regs, allocated_regs, ts->indirect_base);
1815 1816 1817 1818 1819 1820
        if (ts->indirect_reg) {
            tcg_regset_set_reg(allocated_regs, reg);
            temp_load(s, ts->mem_base,
                      tcg_target_available_regs[TCG_TYPE_PTR],
                      allocated_regs);
        }
R
Richard Henderson 已提交
1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832
        tcg_out_ld(s, ts->type, reg, ts->mem_base->reg, ts->mem_offset);
        ts->mem_coherent = 1;
        break;
    case TEMP_VAL_DEAD:
    default:
        tcg_abort();
    }
    ts->reg = reg;
    ts->val_type = TEMP_VAL_REG;
    s->reg_to_temp[reg] = ts;
}

1833 1834 1835
/* Save a temporary to memory. 'allocated_regs' is used in case a
   temporary registers needs to be allocated to store a constant.  */
static void temp_save(TCGContext *s, TCGTemp *ts, TCGRegSet allocated_regs)
A
Aurelien Jarno 已提交
1836
{
1837
#ifdef USE_LIVENESS_ANALYSIS
1838 1839 1840
    /* ??? Liveness does not yet incorporate indirect bases.  */
    if (!ts->indirect_base) {
        /* The liveness analysis already ensures that globals are back
1841
           in memory. Keep an tcg_debug_assert for safety. */
1842 1843 1844 1845
        tcg_debug_assert(ts->val_type == TEMP_VAL_MEM || ts->fixed_reg);
        return;
    }
#endif
1846
    temp_sync(s, ts, allocated_regs, 1);
A
Aurelien Jarno 已提交
1847 1848
}

D
Dong Xu Wang 已提交
1849
/* save globals to their canonical location and assume they can be
1850 1851 1852
   modified be the following code. 'allocated_regs' is used in case a
   temporary registers needs to be allocated to store a constant. */
static void save_globals(TCGContext *s, TCGRegSet allocated_regs)
B
bellard 已提交
1853
{
B
bellard 已提交
1854
    int i;
B
bellard 已提交
1855

1856 1857
    for (i = 0; i < s->nb_globals; i++) {
        temp_save(s, &s->temps[i], allocated_regs);
B
bellard 已提交
1858
    }
B
bellard 已提交
1859 1860
}

1861 1862 1863 1864 1865 1866 1867 1868
/* sync globals to their canonical location and assume they can be
   read by the following code. 'allocated_regs' is used in case a
   temporary registers needs to be allocated to store a constant. */
static void sync_globals(TCGContext *s, TCGRegSet allocated_regs)
{
    int i;

    for (i = 0; i < s->nb_globals; i++) {
1869
        TCGTemp *ts = &s->temps[i];
1870
#ifdef USE_LIVENESS_ANALYSIS
1871 1872 1873 1874 1875 1876 1877
        /* ??? Liveness does not yet incorporate indirect bases.  */
        if (!ts->indirect_base) {
            tcg_debug_assert(ts->val_type != TEMP_VAL_REG
                             || ts->fixed_reg
                             || ts->mem_coherent);
            continue;
        }
1878
#endif
1879
        temp_sync(s, ts, allocated_regs, 0);
1880 1881 1882
    }
}

B
bellard 已提交
1883
/* at the end of a basic block, we assume all temporaries are dead and
1884 1885
   all globals are stored at their canonical location. */
static void tcg_reg_alloc_bb_end(TCGContext *s, TCGRegSet allocated_regs)
B
bellard 已提交
1886 1887 1888
{
    int i;

1889 1890
    for (i = s->nb_globals; i < s->nb_temps; i++) {
        TCGTemp *ts = &s->temps[i];
B
bellard 已提交
1891
        if (ts->temp_local) {
1892
            temp_save(s, ts, allocated_regs);
B
bellard 已提交
1893
        } else {
1894
#ifdef USE_LIVENESS_ANALYSIS
1895 1896 1897
            /* ??? Liveness does not yet incorporate indirect bases.  */
            if (!ts->indirect_base) {
                /* The liveness analysis already ensures that temps are dead.
1898 1899
                   Keep an tcg_debug_assert for safety. */
                tcg_debug_assert(ts->val_type == TEMP_VAL_DEAD);
1900 1901
                continue;
            }
1902
#endif
1903
            temp_dead(s, ts);
B
bellard 已提交
1904 1905
        }
    }
1906 1907

    save_globals(s, allocated_regs);
B
bellard 已提交
1908 1909
}

1910 1911
#define IS_DEAD_ARG(n)   (arg_life & (DEAD_ARG << (n)))
#define NEED_SYNC_ARG(n) (arg_life & (SYNC_ARG << (n)))
B
bellard 已提交
1912

1913
static void tcg_reg_alloc_movi(TCGContext *s, const TCGArg *args,
1914
                               TCGLifeData arg_life)
1915 1916 1917 1918 1919 1920 1921 1922
{
    TCGTemp *ots;
    tcg_target_ulong val;

    ots = &s->temps[args[0]];
    val = args[1];

    if (ots->fixed_reg) {
1923
        /* For fixed registers, we do not do any constant propagation.  */
1924
        tcg_out_movi(s, ots->type, ots->reg, val);
1925
        return;
1926
    }
1927 1928 1929 1930

    /* The movi is not explicitly generated here.  */
    if (ots->val_type == TEMP_VAL_REG) {
        s->reg_to_temp[ots->reg] = NULL;
1931
    }
1932 1933 1934 1935 1936 1937
    ots->val_type = TEMP_VAL_CONST;
    ots->val = val;
    ots->mem_coherent = 0;
    if (NEED_SYNC_ARG(0)) {
        temp_sync(s, ots, s->reserved_regs, IS_DEAD_ARG(0));
    } else if (IS_DEAD_ARG(0)) {
1938
        temp_dead(s, ots);
A
Aurelien Jarno 已提交
1939
    }
1940 1941
}

B
bellard 已提交
1942
static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
1943
                              const TCGArg *args, TCGLifeData arg_life)
B
bellard 已提交
1944
{
A
Aurelien Jarno 已提交
1945
    TCGRegSet allocated_regs;
B
bellard 已提交
1946
    TCGTemp *ts, *ots;
1947
    TCGType otype, itype;
B
bellard 已提交
1948

A
Aurelien Jarno 已提交
1949
    tcg_regset_set(allocated_regs, s->reserved_regs);
B
bellard 已提交
1950 1951
    ots = &s->temps[args[0]];
    ts = &s->temps[args[1]];
1952 1953 1954 1955

    /* Note that otype != itype for no-op truncation.  */
    otype = ots->type;
    itype = ts->type;
A
Aurelien Jarno 已提交
1956 1957 1958 1959 1960 1961 1962

    /* If the source value is not in a register, and we're going to be
       forced to have it in a register in order to perform the copy,
       then copy the SOURCE value into its own register first.  That way
       we don't have to reload SOURCE the next time it is used. */
    if (((NEED_SYNC_ARG(0) || ots->fixed_reg) && ts->val_type != TEMP_VAL_REG)
        || ts->val_type == TEMP_VAL_MEM) {
R
Richard Henderson 已提交
1963
        temp_load(s, ts, tcg_target_available_regs[itype], allocated_regs);
A
Aurelien Jarno 已提交
1964
    }
B
bellard 已提交
1965

A
Aurelien Jarno 已提交
1966 1967 1968
    if (IS_DEAD_ARG(0) && !ots->fixed_reg) {
        /* mov to a non-saved dead register makes no sense (even with
           liveness analysis disabled). */
1969
        tcg_debug_assert(NEED_SYNC_ARG(0));
A
Aurelien Jarno 已提交
1970
        /* The code above should have moved the temp to a register. */
1971
        tcg_debug_assert(ts->val_type == TEMP_VAL_REG);
A
Aurelien Jarno 已提交
1972 1973 1974
        if (!ots->mem_allocated) {
            temp_allocate_frame(s, args[0]);
        }
1975 1976 1977 1978 1979 1980
        if (ots->indirect_reg) {
            tcg_regset_set_reg(allocated_regs, ts->reg);
            temp_load(s, ots->mem_base,
                      tcg_target_available_regs[TCG_TYPE_PTR],
                      allocated_regs);
        }
1981
        tcg_out_st(s, otype, ts->reg, ots->mem_base->reg, ots->mem_offset);
A
Aurelien Jarno 已提交
1982
        if (IS_DEAD_ARG(1)) {
1983
            temp_dead(s, ts);
A
Aurelien Jarno 已提交
1984
        }
1985
        temp_dead(s, ots);
A
Aurelien Jarno 已提交
1986 1987 1988
    } else if (ts->val_type == TEMP_VAL_CONST) {
        /* propagate constant */
        if (ots->val_type == TEMP_VAL_REG) {
1989
            s->reg_to_temp[ots->reg] = NULL;
A
Aurelien Jarno 已提交
1990 1991 1992
        }
        ots->val_type = TEMP_VAL_CONST;
        ots->val = ts->val;
1993
        if (IS_DEAD_ARG(1)) {
1994
            temp_dead(s, ts);
1995
        }
A
Aurelien Jarno 已提交
1996 1997 1998
    } else {
        /* The code in the first if block should have moved the
           temp to a register. */
1999
        tcg_debug_assert(ts->val_type == TEMP_VAL_REG);
2000
        if (IS_DEAD_ARG(1) && !ts->fixed_reg && !ots->fixed_reg) {
B
bellard 已提交
2001
            /* the mov can be suppressed */
A
Aurelien Jarno 已提交
2002
            if (ots->val_type == TEMP_VAL_REG) {
2003
                s->reg_to_temp[ots->reg] = NULL;
A
Aurelien Jarno 已提交
2004 2005
            }
            ots->reg = ts->reg;
2006
            temp_dead(s, ts);
B
bellard 已提交
2007
        } else {
A
Aurelien Jarno 已提交
2008 2009 2010 2011
            if (ots->val_type != TEMP_VAL_REG) {
                /* When allocating a new register, make sure to not spill the
                   input one. */
                tcg_regset_set_reg(allocated_regs, ts->reg);
2012
                ots->reg = tcg_reg_alloc(s, tcg_target_available_regs[otype],
2013
                                         allocated_regs, ots->indirect_base);
B
bellard 已提交
2014
            }
2015
            tcg_out_mov(s, otype, ots->reg, ts->reg);
B
bellard 已提交
2016
        }
A
Aurelien Jarno 已提交
2017 2018
        ots->val_type = TEMP_VAL_REG;
        ots->mem_coherent = 0;
2019
        s->reg_to_temp[ots->reg] = ots;
A
Aurelien Jarno 已提交
2020
        if (NEED_SYNC_ARG(0)) {
2021
            temp_sync(s, ots, allocated_regs, 0);
B
bellard 已提交
2022
        }
2023
    }
B
bellard 已提交
2024 2025 2026
}

static void tcg_reg_alloc_op(TCGContext *s, 
2027
                             const TCGOpDef *def, TCGOpcode opc,
2028
                             const TCGArg *args, TCGLifeData arg_life)
B
bellard 已提交
2029 2030
{
    TCGRegSet allocated_regs;
2031 2032
    int i, k, nb_iargs, nb_oargs;
    TCGReg reg;
B
bellard 已提交
2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053
    TCGArg arg;
    const TCGArgConstraint *arg_ct;
    TCGTemp *ts;
    TCGArg new_args[TCG_MAX_OP_ARGS];
    int const_args[TCG_MAX_OP_ARGS];

    nb_oargs = def->nb_oargs;
    nb_iargs = def->nb_iargs;

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

    /* satisfy input constraints */ 
    tcg_regset_set(allocated_regs, s->reserved_regs);
    for(k = 0; k < nb_iargs; k++) {
        i = def->sorted_args[nb_oargs + k];
        arg = args[i];
        arg_ct = &def->args_ct[i];
        ts = &s->temps[arg];
R
Richard Henderson 已提交
2054 2055 2056 2057 2058 2059 2060

        if (ts->val_type == TEMP_VAL_CONST
            && tcg_target_const_match(ts->val, ts->type, arg_ct)) {
            /* constant is OK for instruction */
            const_args[i] = 1;
            new_args[i] = ts->val;
            goto iarg_end;
B
bellard 已提交
2061
        }
R
Richard Henderson 已提交
2062 2063 2064

        temp_load(s, ts, arg_ct->u.regs, allocated_regs);

2065 2066 2067 2068 2069 2070 2071 2072 2073 2074
        if (arg_ct->ct & TCG_CT_IALIAS) {
            if (ts->fixed_reg) {
                /* if fixed register, we must allocate a new register
                   if the alias is not the same register */
                if (arg != args[arg_ct->alias_index])
                    goto allocate_in_reg;
            } else {
                /* if the input is aliased to an output and if it is
                   not dead after the instruction, we must allocate
                   a new register and move it */
2075
                if (!IS_DEAD_ARG(i)) {
2076
                    goto allocate_in_reg;
2077
                }
2078 2079 2080 2081 2082 2083 2084 2085 2086 2087
                /* check if the current register has already been allocated
                   for another input aliased to an output */
                int k2, i2;
                for (k2 = 0 ; k2 < k ; k2++) {
                    i2 = def->sorted_args[nb_oargs + k2];
                    if ((def->args_ct[i2].ct & TCG_CT_IALIAS) &&
                        (new_args[i2] == ts->reg)) {
                        goto allocate_in_reg;
                    }
                }
2088
            }
B
bellard 已提交
2089 2090 2091 2092 2093 2094 2095 2096
        }
        reg = ts->reg;
        if (tcg_regset_test_reg(arg_ct->u.regs, reg)) {
            /* nothing to do : the constraint is satisfied */
        } else {
        allocate_in_reg:
            /* allocate a new register matching the constraint 
               and move the temporary register into it */
2097 2098
            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs,
                                ts->indirect_base);
2099
            tcg_out_mov(s, ts->type, reg, ts->reg);
B
bellard 已提交
2100 2101 2102 2103 2104 2105 2106
        }
        new_args[i] = reg;
        const_args[i] = 0;
        tcg_regset_set_reg(allocated_regs, reg);
    iarg_end: ;
    }
    
2107 2108 2109
    /* mark dead temporaries and free the associated registers */
    for (i = nb_oargs; i < nb_oargs + nb_iargs; i++) {
        if (IS_DEAD_ARG(i)) {
2110
            temp_dead(s, &s->temps[args[i]]);
2111 2112 2113
        }
    }

2114 2115 2116 2117 2118
    if (def->flags & TCG_OPF_BB_END) {
        tcg_reg_alloc_bb_end(s, allocated_regs);
    } else {
        if (def->flags & TCG_OPF_CALL_CLOBBER) {
            /* XXX: permit generic clobber register list ? */ 
2119 2120
            for (i = 0; i < TCG_TARGET_NB_REGS; i++) {
                if (tcg_regset_test_reg(tcg_target_call_clobber_regs, i)) {
2121
                    tcg_reg_free(s, i, allocated_regs);
2122
                }
B
bellard 已提交
2123
            }
2124 2125 2126 2127 2128
        }
        if (def->flags & TCG_OPF_SIDE_EFFECTS) {
            /* sync globals if the op has side effects and might trigger
               an exception. */
            sync_globals(s, allocated_regs);
B
bellard 已提交
2129
        }
2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146
        
        /* satisfy the output constraints */
        tcg_regset_set(allocated_regs, s->reserved_regs);
        for(k = 0; k < nb_oargs; k++) {
            i = def->sorted_args[k];
            arg = args[i];
            arg_ct = &def->args_ct[i];
            ts = &s->temps[arg];
            if (arg_ct->ct & TCG_CT_ALIAS) {
                reg = new_args[arg_ct->alias_index];
            } else {
                /* if fixed register, we try to use it */
                reg = ts->reg;
                if (ts->fixed_reg &&
                    tcg_regset_test_reg(arg_ct->u.regs, reg)) {
                    goto oarg_end;
                }
2147 2148
                reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs,
                                    ts->indirect_base);
B
bellard 已提交
2149
            }
2150 2151 2152
            tcg_regset_set_reg(allocated_regs, reg);
            /* if a fixed register is used, then a move will be done afterwards */
            if (!ts->fixed_reg) {
2153
                if (ts->val_type == TEMP_VAL_REG) {
2154
                    s->reg_to_temp[ts->reg] = NULL;
2155 2156 2157 2158 2159 2160
                }
                ts->val_type = TEMP_VAL_REG;
                ts->reg = reg;
                /* temp value is modified, so the value kept in memory is
                   potentially not the same */
                ts->mem_coherent = 0;
2161
                s->reg_to_temp[reg] = ts;
2162 2163 2164
            }
        oarg_end:
            new_args[i] = reg;
B
bellard 已提交
2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175
        }
    }

    /* emit instruction */
    tcg_out_op(s, opc, new_args, const_args);
    
    /* move the outputs in the correct register if needed */
    for(i = 0; i < nb_oargs; i++) {
        ts = &s->temps[args[i]];
        reg = new_args[i];
        if (ts->fixed_reg && ts->reg != reg) {
2176
            tcg_out_mov(s, ts->type, ts->reg, reg);
B
bellard 已提交
2177
        }
2178
        if (NEED_SYNC_ARG(i)) {
2179 2180
            temp_sync(s, ts, allocated_regs, IS_DEAD_ARG(i));
        } else if (IS_DEAD_ARG(i)) {
2181
            temp_dead(s, ts);
2182
        }
B
bellard 已提交
2183 2184 2185
    }
}

2186 2187 2188 2189 2190 2191
#ifdef TCG_TARGET_STACK_GROWSUP
#define STACK_DIR(x) (-(x))
#else
#define STACK_DIR(x) (x)
#endif

2192
static void tcg_reg_alloc_call(TCGContext *s, int nb_oargs, int nb_iargs,
2193
                               const TCGArg * const args, TCGLifeData arg_life)
B
bellard 已提交
2194
{
2195 2196
    int flags, nb_regs, i;
    TCGReg reg;
2197
    TCGArg arg;
B
bellard 已提交
2198
    TCGTemp *ts;
2199 2200
    intptr_t stack_offset;
    size_t call_stack_size;
2201 2202
    tcg_insn_unit *func_addr;
    int allocate_args;
B
bellard 已提交
2203 2204
    TCGRegSet allocated_regs;

2205 2206
    func_addr = (tcg_insn_unit *)(intptr_t)args[nb_oargs + nb_iargs];
    flags = args[nb_oargs + nb_iargs + 1];
B
bellard 已提交
2207

2208
    nb_regs = ARRAY_SIZE(tcg_target_call_iarg_regs);
2209 2210
    if (nb_regs > nb_iargs) {
        nb_regs = nb_iargs;
2211
    }
B
bellard 已提交
2212 2213

    /* assign stack slots first */
2214
    call_stack_size = (nb_iargs - nb_regs) * sizeof(tcg_target_long);
B
bellard 已提交
2215 2216
    call_stack_size = (call_stack_size + TCG_TARGET_STACK_ALIGN - 1) & 
        ~(TCG_TARGET_STACK_ALIGN - 1);
2217 2218
    allocate_args = (call_stack_size > TCG_STATIC_CALL_ARGS_SIZE);
    if (allocate_args) {
2219 2220 2221
        /* XXX: if more than TCG_STATIC_CALL_ARGS_SIZE is needed,
           preallocate call stack */
        tcg_abort();
2222
    }
B
bellard 已提交
2223 2224

    stack_offset = TCG_TARGET_CALL_STACK_OFFSET;
2225
    for(i = nb_regs; i < nb_iargs; i++) {
B
bellard 已提交
2226
        arg = args[nb_oargs + i];
B
bellard 已提交
2227 2228 2229 2230 2231
#ifdef TCG_TARGET_STACK_GROWSUP
        stack_offset -= sizeof(tcg_target_long);
#endif
        if (arg != TCG_CALL_DUMMY_ARG) {
            ts = &s->temps[arg];
R
Richard Henderson 已提交
2232 2233 2234
            temp_load(s, ts, tcg_target_available_regs[ts->type],
                      s->reserved_regs);
            tcg_out_st(s, ts->type, ts->reg, TCG_REG_CALL_STACK, stack_offset);
B
bellard 已提交
2235
        }
B
bellard 已提交
2236 2237 2238
#ifndef TCG_TARGET_STACK_GROWSUP
        stack_offset += sizeof(tcg_target_long);
#endif
B
bellard 已提交
2239 2240 2241 2242 2243 2244
    }
    
    /* assign input registers */
    tcg_regset_set(allocated_regs, s->reserved_regs);
    for(i = 0; i < nb_regs; i++) {
        arg = args[nb_oargs + i];
B
bellard 已提交
2245 2246 2247
        if (arg != TCG_CALL_DUMMY_ARG) {
            ts = &s->temps[arg];
            reg = tcg_target_call_iarg_regs[i];
2248
            tcg_reg_free(s, reg, allocated_regs);
R
Richard Henderson 已提交
2249

B
bellard 已提交
2250 2251
            if (ts->val_type == TEMP_VAL_REG) {
                if (ts->reg != reg) {
2252
                    tcg_out_mov(s, ts->type, reg, ts->reg);
B
bellard 已提交
2253 2254
                }
            } else {
R
Richard Henderson 已提交
2255 2256 2257 2258 2259
                TCGRegSet arg_set;

                tcg_regset_clear(arg_set);
                tcg_regset_set_reg(arg_set, reg);
                temp_load(s, ts, arg_set, allocated_regs);
B
bellard 已提交
2260
            }
R
Richard Henderson 已提交
2261

B
bellard 已提交
2262
            tcg_regset_set_reg(allocated_regs, reg);
B
bellard 已提交
2263 2264 2265 2266
        }
    }
    
    /* mark dead temporaries and free the associated registers */
2267 2268
    for(i = nb_oargs; i < nb_iargs + nb_oargs; i++) {
        if (IS_DEAD_ARG(i)) {
2269
            temp_dead(s, &s->temps[args[i]]);
B
bellard 已提交
2270 2271 2272 2273
        }
    }
    
    /* clobber call registers */
2274 2275
    for (i = 0; i < TCG_TARGET_NB_REGS; i++) {
        if (tcg_regset_test_reg(tcg_target_call_clobber_regs, i)) {
2276
            tcg_reg_free(s, i, allocated_regs);
B
bellard 已提交
2277 2278
        }
    }
A
Aurelien Jarno 已提交
2279 2280 2281 2282 2283 2284 2285 2286

    /* Save globals if they might be written by the helper, sync them if
       they might be read. */
    if (flags & TCG_CALL_NO_READ_GLOBALS) {
        /* Nothing to do */
    } else if (flags & TCG_CALL_NO_WRITE_GLOBALS) {
        sync_globals(s, allocated_regs);
    } else {
A
aurel32 已提交
2287 2288
        save_globals(s, allocated_regs);
    }
B
bellard 已提交
2289

2290
    tcg_out_call(s, func_addr);
B
bellard 已提交
2291 2292 2293 2294 2295 2296

    /* assign output registers and emit moves if needed */
    for(i = 0; i < nb_oargs; i++) {
        arg = args[i];
        ts = &s->temps[arg];
        reg = tcg_target_call_oarg_regs[i];
2297
        tcg_debug_assert(s->reg_to_temp[reg] == NULL);
2298

B
bellard 已提交
2299 2300
        if (ts->fixed_reg) {
            if (ts->reg != reg) {
2301
                tcg_out_mov(s, ts->type, ts->reg, reg);
B
bellard 已提交
2302 2303
            }
        } else {
2304
            if (ts->val_type == TEMP_VAL_REG) {
2305
                s->reg_to_temp[ts->reg] = NULL;
2306 2307 2308 2309
            }
            ts->val_type = TEMP_VAL_REG;
            ts->reg = reg;
            ts->mem_coherent = 0;
2310
            s->reg_to_temp[reg] = ts;
2311
            if (NEED_SYNC_ARG(i)) {
2312 2313
                temp_sync(s, ts, allocated_regs, IS_DEAD_ARG(i));
            } else if (IS_DEAD_ARG(i)) {
2314
                temp_dead(s, ts);
2315
            }
B
bellard 已提交
2316 2317 2318 2319 2320 2321
        }
    }
}

#ifdef CONFIG_PROFILER

A
aurel32 已提交
2322
static int64_t tcg_table_op_count[NB_OPS];
B
bellard 已提交
2323

2324
void tcg_dump_op_count(FILE *f, fprintf_function cpu_fprintf)
B
bellard 已提交
2325 2326
{
    int i;
Z
zhanghailiang 已提交
2327

R
Richard Henderson 已提交
2328
    for (i = 0; i < NB_OPS; i++) {
2329 2330
        cpu_fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name,
                    tcg_table_op_count[i]);
B
bellard 已提交
2331 2332
    }
}
2333 2334 2335 2336 2337
#else
void tcg_dump_op_count(FILE *f, fprintf_function cpu_fprintf)
{
    cpu_fprintf(f, "[TCG profiler not compiled]\n");
}
B
bellard 已提交
2338 2339 2340
#endif


2341
int tcg_gen_code(TCGContext *s, TranslationBlock *tb)
B
bellard 已提交
2342
{
2343
    int i, oi, oi_next, num_insns;
B
bellard 已提交
2344

2345 2346 2347 2348
#ifdef CONFIG_PROFILER
    {
        int n;

R
Richard Henderson 已提交
2349
        n = s->gen_op_buf[0].prev + 1;
2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362
        s->op_count += n;
        if (n > s->op_count_max) {
            s->op_count_max = n;
        }

        n = s->nb_temps;
        s->temp_count += n;
        if (n > s->temp_count_max) {
            s->temp_count_max = n;
        }
    }
#endif

B
bellard 已提交
2363
#ifdef DEBUG_DISAS
2364 2365
    if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)
                 && qemu_log_in_addr_range(tb->pc))) {
2366
        qemu_log("OP:\n");
B
Blue Swirl 已提交
2367
        tcg_dump_ops(s);
2368
        qemu_log("\n");
B
bellard 已提交
2369 2370 2371
    }
#endif

A
Aurelien Jarno 已提交
2372 2373 2374 2375
#ifdef CONFIG_PROFILER
    s->opt_time -= profile_getclock();
#endif

K
Kirill Batuzov 已提交
2376
#ifdef USE_TCG_OPTIMIZATIONS
2377
    tcg_optimize(s);
K
Kirill Batuzov 已提交
2378 2379
#endif

B
bellard 已提交
2380
#ifdef CONFIG_PROFILER
A
Aurelien Jarno 已提交
2381
    s->opt_time += profile_getclock();
B
bellard 已提交
2382 2383
    s->la_time -= profile_getclock();
#endif
A
Aurelien Jarno 已提交
2384

B
bellard 已提交
2385
    tcg_liveness_analysis(s);
A
Aurelien Jarno 已提交
2386

B
bellard 已提交
2387 2388 2389
#ifdef CONFIG_PROFILER
    s->la_time += profile_getclock();
#endif
B
bellard 已提交
2390 2391

#ifdef DEBUG_DISAS
2392 2393
    if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_OPT)
                 && qemu_log_in_addr_range(tb->pc))) {
A
Aurelien Jarno 已提交
2394
        qemu_log("OP after optimization and liveness analysis:\n");
B
Blue Swirl 已提交
2395
        tcg_dump_ops(s);
2396
        qemu_log("\n");
B
bellard 已提交
2397 2398 2399 2400 2401
    }
#endif

    tcg_reg_alloc_start(s);

2402 2403
    s->code_buf = tb->tc_ptr;
    s->code_ptr = tb->tc_ptr;
B
bellard 已提交
2404

R
Richard Henderson 已提交
2405 2406
    tcg_out_tb_init(s);

2407
    num_insns = -1;
R
Richard Henderson 已提交
2408
    for (oi = s->gen_op_buf[0].next; oi != 0; oi = oi_next) {
2409 2410 2411 2412
        TCGOp * const op = &s->gen_op_buf[oi];
        TCGArg * const args = &s->gen_opparam_buf[op->args];
        TCGOpcode opc = op->opc;
        const TCGOpDef *def = &tcg_op_defs[opc];
2413
        TCGLifeData arg_life = s->op_arg_life[oi];
2414

2415
        oi_next = op->next;
B
bellard 已提交
2416
#ifdef CONFIG_PROFILER
A
aurel32 已提交
2417
        tcg_table_op_count[opc]++;
B
bellard 已提交
2418
#endif
2419 2420

        switch (opc) {
B
bellard 已提交
2421 2422
        case INDEX_op_mov_i32:
        case INDEX_op_mov_i64:
2423
            tcg_reg_alloc_mov(s, def, args, arg_life);
B
bellard 已提交
2424
            break;
2425 2426
        case INDEX_op_movi_i32:
        case INDEX_op_movi_i64:
2427
            tcg_reg_alloc_movi(s, args, arg_life);
2428
            break;
2429
        case INDEX_op_insn_start:
2430 2431 2432 2433
            if (num_insns >= 0) {
                s->gen_insn_end_off[num_insns] = tcg_current_code_size(s);
            }
            num_insns++;
2434 2435 2436 2437 2438 2439 2440
            for (i = 0; i < TARGET_INSN_START_WORDS; ++i) {
                target_ulong a;
#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
                a = ((target_ulong)args[i * 2 + 1] << 32) | args[i * 2];
#else
                a = args[i];
#endif
2441
                s->gen_insn_data[num_insns][i] = a;
2442
            }
B
bellard 已提交
2443
            break;
2444
        case INDEX_op_discard:
2445
            temp_dead(s, &s->temps[args[0]]);
2446
            break;
B
bellard 已提交
2447
        case INDEX_op_set_label:
2448
            tcg_reg_alloc_bb_end(s, s->reserved_regs);
2449
            tcg_out_label(s, arg_label(args[0]), s->code_ptr);
B
bellard 已提交
2450 2451
            break;
        case INDEX_op_call:
2452
            tcg_reg_alloc_call(s, op->callo, op->calli, args, arg_life);
2453
            break;
B
bellard 已提交
2454
        default:
2455 2456 2457 2458
            /* Sanity check that we've not introduced any unhandled opcodes. */
            if (def->flags & TCG_OPF_NOT_PRESENT) {
                tcg_abort();
            }
B
bellard 已提交
2459 2460 2461
            /* Note: in order to speed up the code, it would be much
               faster to have specialized register allocator functions for
               some common argument patterns */
2462
            tcg_reg_alloc_op(s, def, opc, args, arg_life);
B
bellard 已提交
2463 2464
            break;
        }
2465
#ifdef CONFIG_DEBUG_TCG
B
bellard 已提交
2466 2467
        check_regs(s);
#endif
2468 2469 2470 2471
        /* Test for (pending) buffer overflow.  The assumption is that any
           one operation beginning below the high water mark cannot overrun
           the buffer completely.  Thus we can test for overflow after
           generating code without having to check during generation.  */
J
John Clarke 已提交
2472
        if (unlikely((void *)s->code_ptr > s->code_gen_highwater)) {
2473 2474
            return -1;
        }
B
bellard 已提交
2475
    }
2476 2477
    tcg_debug_assert(num_insns >= 0);
    s->gen_insn_end_off[num_insns] = tcg_current_code_size(s);
2478

2479
    /* Generate TB finalization at the end of block */
2480 2481 2482
    if (!tcg_out_tb_finalize(s)) {
        return -1;
    }
B
bellard 已提交
2483 2484

    /* flush instruction cache */
2485
    flush_icache_range((uintptr_t)s->code_buf, (uintptr_t)s->code_ptr);
2486

2487
    return tcg_current_code_size(s);
B
bellard 已提交
2488 2489
}

B
bellard 已提交
2490
#ifdef CONFIG_PROFILER
2491
void tcg_dump_info(FILE *f, fprintf_function cpu_fprintf)
B
bellard 已提交
2492 2493
{
    TCGContext *s = &tcg_ctx;
2494 2495 2496
    int64_t tb_count = s->tb_count;
    int64_t tb_div_count = tb_count ? tb_count : 1;
    int64_t tot = s->interm_time + s->code_time;
B
bellard 已提交
2497 2498 2499 2500

    cpu_fprintf(f, "JIT cycles          %" PRId64 " (%0.3f s at 2.4 GHz)\n",
                tot, tot / 2.4e9);
    cpu_fprintf(f, "translated TBs      %" PRId64 " (aborted=%" PRId64 " %0.1f%%)\n", 
2501 2502 2503
                tb_count, s->tb_count1 - tb_count,
                (double)(s->tb_count1 - s->tb_count)
                / (s->tb_count1 ? s->tb_count1 : 1) * 100.0);
B
bellard 已提交
2504
    cpu_fprintf(f, "avg ops/TB          %0.1f max=%d\n", 
2505
                (double)s->op_count / tb_div_count, s->op_count_max);
B
bellard 已提交
2506
    cpu_fprintf(f, "deleted ops/TB      %0.2f\n",
2507
                (double)s->del_op_count / tb_div_count);
B
bellard 已提交
2508
    cpu_fprintf(f, "avg temps/TB        %0.2f max=%d\n",
2509 2510 2511 2512 2513
                (double)s->temp_count / tb_div_count, s->temp_count_max);
    cpu_fprintf(f, "avg host code/TB    %0.1f\n",
                (double)s->code_out_len / tb_div_count);
    cpu_fprintf(f, "avg search data/TB  %0.1f\n",
                (double)s->search_out_len / tb_div_count);
B
bellard 已提交
2514 2515 2516 2517 2518 2519 2520
    
    cpu_fprintf(f, "cycles/op           %0.1f\n", 
                s->op_count ? (double)tot / s->op_count : 0);
    cpu_fprintf(f, "cycles/in byte      %0.1f\n", 
                s->code_in_len ? (double)tot / s->code_in_len : 0);
    cpu_fprintf(f, "cycles/out byte     %0.1f\n", 
                s->code_out_len ? (double)tot / s->code_out_len : 0);
2521 2522 2523
    cpu_fprintf(f, "cycles/search byte     %0.1f\n",
                s->search_out_len ? (double)tot / s->search_out_len : 0);
    if (tot == 0) {
B
bellard 已提交
2524
        tot = 1;
2525
    }
B
bellard 已提交
2526 2527 2528 2529
    cpu_fprintf(f, "  gen_interm time   %0.1f%%\n", 
                (double)s->interm_time / tot * 100.0);
    cpu_fprintf(f, "  gen_code time     %0.1f%%\n", 
                (double)s->code_time / tot * 100.0);
A
Aurelien Jarno 已提交
2530 2531 2532
    cpu_fprintf(f, "optim./code time    %0.1f%%\n",
                (double)s->opt_time / (s->code_time ? s->code_time : 1)
                * 100.0);
B
bellard 已提交
2533 2534 2535 2536 2537 2538 2539 2540
    cpu_fprintf(f, "liveness/code time  %0.1f%%\n", 
                (double)s->la_time / (s->code_time ? s->code_time : 1) * 100.0);
    cpu_fprintf(f, "cpu_restore count   %" PRId64 "\n",
                s->restore_count);
    cpu_fprintf(f, "  avg cycles        %0.1f\n",
                s->restore_count ? (double)s->restore_time / s->restore_count : 0);
}
#else
2541
void tcg_dump_info(FILE *f, fprintf_function cpu_fprintf)
B
bellard 已提交
2542
{
B
bellard 已提交
2543
    cpu_fprintf(f, "[TCG profiler not compiled]\n");
B
bellard 已提交
2544 2545
}
#endif
2546 2547

#ifdef ELF_HOST_MACHINE
2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558
/* In order to use this feature, the backend needs to do three things:

   (1) Define ELF_HOST_MACHINE to indicate both what value to
       put into the ELF image and to indicate support for the feature.

   (2) Define tcg_register_jit.  This should create a buffer containing
       the contents of a .debug_frame section that describes the post-
       prologue unwind info for the tcg machine.

   (3) Call tcg_register_jit_int, with the constructed .debug_frame.
*/
2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604

/* Begin GDB interface.  THE FOLLOWING MUST MATCH GDB DOCS.  */
typedef enum {
    JIT_NOACTION = 0,
    JIT_REGISTER_FN,
    JIT_UNREGISTER_FN
} jit_actions_t;

struct jit_code_entry {
    struct jit_code_entry *next_entry;
    struct jit_code_entry *prev_entry;
    const void *symfile_addr;
    uint64_t symfile_size;
};

struct jit_descriptor {
    uint32_t version;
    uint32_t action_flag;
    struct jit_code_entry *relevant_entry;
    struct jit_code_entry *first_entry;
};

void __jit_debug_register_code(void) __attribute__((noinline));
void __jit_debug_register_code(void)
{
    asm("");
}

/* Must statically initialize the version, because GDB may check
   the version before we can set it.  */
struct jit_descriptor __jit_debug_descriptor = { 1, 0, 0, 0 };

/* End GDB interface.  */

static int find_string(const char *strtab, const char *str)
{
    const char *p = strtab + 1;

    while (1) {
        if (strcmp(p, str) == 0) {
            return p - strtab;
        }
        p += strlen(p) + 1;
    }
}

2605
static void tcg_register_jit_int(void *buf_ptr, size_t buf_size,
2606 2607
                                 const void *debug_frame,
                                 size_t debug_frame_size)
2608
{
2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623
    struct __attribute__((packed)) DebugInfo {
        uint32_t  len;
        uint16_t  version;
        uint32_t  abbrev;
        uint8_t   ptr_size;
        uint8_t   cu_die;
        uint16_t  cu_lang;
        uintptr_t cu_low_pc;
        uintptr_t cu_high_pc;
        uint8_t   fn_die;
        char      fn_name[16];
        uintptr_t fn_low_pc;
        uintptr_t fn_high_pc;
        uint8_t   cu_eoc;
    };
2624 2625 2626 2627

    struct ElfImage {
        ElfW(Ehdr) ehdr;
        ElfW(Phdr) phdr;
2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656
        ElfW(Shdr) shdr[7];
        ElfW(Sym)  sym[2];
        struct DebugInfo di;
        uint8_t    da[24];
        char       str[80];
    };

    struct ElfImage *img;

    static const struct ElfImage img_template = {
        .ehdr = {
            .e_ident[EI_MAG0] = ELFMAG0,
            .e_ident[EI_MAG1] = ELFMAG1,
            .e_ident[EI_MAG2] = ELFMAG2,
            .e_ident[EI_MAG3] = ELFMAG3,
            .e_ident[EI_CLASS] = ELF_CLASS,
            .e_ident[EI_DATA] = ELF_DATA,
            .e_ident[EI_VERSION] = EV_CURRENT,
            .e_type = ET_EXEC,
            .e_machine = ELF_HOST_MACHINE,
            .e_version = EV_CURRENT,
            .e_phoff = offsetof(struct ElfImage, phdr),
            .e_shoff = offsetof(struct ElfImage, shdr),
            .e_ehsize = sizeof(ElfW(Shdr)),
            .e_phentsize = sizeof(ElfW(Phdr)),
            .e_phnum = 1,
            .e_shentsize = sizeof(ElfW(Shdr)),
            .e_shnum = ARRAY_SIZE(img->shdr),
            .e_shstrndx = ARRAY_SIZE(img->shdr) - 1,
2657 2658 2659 2660 2661 2662
#ifdef ELF_HOST_FLAGS
            .e_flags = ELF_HOST_FLAGS,
#endif
#ifdef ELF_OSABI
            .e_ident[EI_OSABI] = ELF_OSABI,
#endif
2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737
        },
        .phdr = {
            .p_type = PT_LOAD,
            .p_flags = PF_X,
        },
        .shdr = {
            [0] = { .sh_type = SHT_NULL },
            /* Trick: The contents of code_gen_buffer are not present in
               this fake ELF file; that got allocated elsewhere.  Therefore
               we mark .text as SHT_NOBITS (similar to .bss) so that readers
               will not look for contents.  We can record any address.  */
            [1] = { /* .text */
                .sh_type = SHT_NOBITS,
                .sh_flags = SHF_EXECINSTR | SHF_ALLOC,
            },
            [2] = { /* .debug_info */
                .sh_type = SHT_PROGBITS,
                .sh_offset = offsetof(struct ElfImage, di),
                .sh_size = sizeof(struct DebugInfo),
            },
            [3] = { /* .debug_abbrev */
                .sh_type = SHT_PROGBITS,
                .sh_offset = offsetof(struct ElfImage, da),
                .sh_size = sizeof(img->da),
            },
            [4] = { /* .debug_frame */
                .sh_type = SHT_PROGBITS,
                .sh_offset = sizeof(struct ElfImage),
            },
            [5] = { /* .symtab */
                .sh_type = SHT_SYMTAB,
                .sh_offset = offsetof(struct ElfImage, sym),
                .sh_size = sizeof(img->sym),
                .sh_info = 1,
                .sh_link = ARRAY_SIZE(img->shdr) - 1,
                .sh_entsize = sizeof(ElfW(Sym)),
            },
            [6] = { /* .strtab */
                .sh_type = SHT_STRTAB,
                .sh_offset = offsetof(struct ElfImage, str),
                .sh_size = sizeof(img->str),
            }
        },
        .sym = {
            [1] = { /* code_gen_buffer */
                .st_info = ELF_ST_INFO(STB_GLOBAL, STT_FUNC),
                .st_shndx = 1,
            }
        },
        .di = {
            .len = sizeof(struct DebugInfo) - 4,
            .version = 2,
            .ptr_size = sizeof(void *),
            .cu_die = 1,
            .cu_lang = 0x8001,  /* DW_LANG_Mips_Assembler */
            .fn_die = 2,
            .fn_name = "code_gen_buffer"
        },
        .da = {
            1,          /* abbrev number (the cu) */
            0x11, 1,    /* DW_TAG_compile_unit, has children */
            0x13, 0x5,  /* DW_AT_language, DW_FORM_data2 */
            0x11, 0x1,  /* DW_AT_low_pc, DW_FORM_addr */
            0x12, 0x1,  /* DW_AT_high_pc, DW_FORM_addr */
            0, 0,       /* end of abbrev */
            2,          /* abbrev number (the fn) */
            0x2e, 0,    /* DW_TAG_subprogram, no children */
            0x3, 0x8,   /* DW_AT_name, DW_FORM_string */
            0x11, 0x1,  /* DW_AT_low_pc, DW_FORM_addr */
            0x12, 0x1,  /* DW_AT_high_pc, DW_FORM_addr */
            0, 0,       /* end of abbrev */
            0           /* no more abbrev */
        },
        .str = "\0" ".text\0" ".debug_info\0" ".debug_abbrev\0"
               ".debug_frame\0" ".symtab\0" ".strtab\0" "code_gen_buffer",
2738 2739 2740 2741 2742
    };

    /* We only need a single jit entry; statically allocate it.  */
    static struct jit_code_entry one_entry;

2743
    uintptr_t buf = (uintptr_t)buf_ptr;
2744
    size_t img_size = sizeof(struct ElfImage) + debug_frame_size;
2745
    DebugFrameHeader *dfh;
2746

2747 2748
    img = g_malloc(img_size);
    *img = img_template;
2749

2750 2751 2752
    img->phdr.p_vaddr = buf;
    img->phdr.p_paddr = buf;
    img->phdr.p_memsz = buf_size;
2753 2754

    img->shdr[1].sh_name = find_string(img->str, ".text");
2755
    img->shdr[1].sh_addr = buf;
2756 2757
    img->shdr[1].sh_size = buf_size;

2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769
    img->shdr[2].sh_name = find_string(img->str, ".debug_info");
    img->shdr[3].sh_name = find_string(img->str, ".debug_abbrev");

    img->shdr[4].sh_name = find_string(img->str, ".debug_frame");
    img->shdr[4].sh_size = debug_frame_size;

    img->shdr[5].sh_name = find_string(img->str, ".symtab");
    img->shdr[6].sh_name = find_string(img->str, ".strtab");

    img->sym[1].st_name = find_string(img->str, "code_gen_buffer");
    img->sym[1].st_value = buf;
    img->sym[1].st_size = buf_size;
2770

2771
    img->di.cu_low_pc = buf;
2772
    img->di.cu_high_pc = buf + buf_size;
2773
    img->di.fn_low_pc = buf;
2774
    img->di.fn_high_pc = buf + buf_size;
2775

2776 2777 2778 2779 2780
    dfh = (DebugFrameHeader *)(img + 1);
    memcpy(dfh, debug_frame, debug_frame_size);
    dfh->fde.func_start = buf;
    dfh->fde.func_len = buf_size;

2781 2782 2783 2784 2785 2786
#ifdef DEBUG_JIT
    /* Enable this block to be able to debug the ELF image file creation.
       One can use readelf, objdump, or other inspection utilities.  */
    {
        FILE *f = fopen("/tmp/qemu.jit", "w+b");
        if (f) {
2787
            if (fwrite(img, img_size, 1, f) != img_size) {
2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803
                /* Avoid stupid unused return value warning for fwrite.  */
            }
            fclose(f);
        }
    }
#endif

    one_entry.symfile_addr = img;
    one_entry.symfile_size = img_size;

    __jit_debug_descriptor.action_flag = JIT_REGISTER_FN;
    __jit_debug_descriptor.relevant_entry = &one_entry;
    __jit_debug_descriptor.first_entry = &one_entry;
    __jit_debug_register_code();
}
#else
2804 2805
/* No support for the feature.  Provide the entry point expected by exec.c,
   and implement the internal function we declared earlier.  */
2806 2807

static void tcg_register_jit_int(void *buf, size_t size,
2808 2809
                                 const void *debug_frame,
                                 size_t debug_frame_size)
2810 2811 2812 2813 2814 2815 2816
{
}

void tcg_register_jit(void *buf, size_t buf_size)
{
}
#endif /* ELF_HOST_MACHINE */