Statistics
| Branch: | Revision:

root / tcg / i386 / tcg-target.c @ d4a9eb1f

History | View | Annotate | Download (33.7 kB)

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

    
25
#ifndef NDEBUG
26
static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
27
    "%eax",
28
    "%ecx",
29
    "%edx",
30
    "%ebx",
31
    "%esp",
32
    "%ebp",
33
    "%esi",
34
    "%edi",
35
};
36
#endif
37

    
38
static const int tcg_target_reg_alloc_order[] = {
39
    TCG_REG_EAX,
40
    TCG_REG_EDX,
41
    TCG_REG_ECX,
42
    TCG_REG_EBX,
43
    TCG_REG_ESI,
44
    TCG_REG_EDI,
45
    TCG_REG_EBP,
46
};
47

    
48
static const int tcg_target_call_iarg_regs[3] = { TCG_REG_EAX, TCG_REG_EDX, TCG_REG_ECX };
49
static const int tcg_target_call_oarg_regs[2] = { TCG_REG_EAX, TCG_REG_EDX };
50

    
51
static uint8_t *tb_ret_addr;
52

    
53
static void patch_reloc(uint8_t *code_ptr, int type, 
54
                        tcg_target_long value, tcg_target_long addend)
55
{
56
    value += addend;
57
    switch(type) {
58
    case R_386_32:
59
        *(uint32_t *)code_ptr = value;
60
        break;
61
    case R_386_PC32:
62
        *(uint32_t *)code_ptr = value - (long)code_ptr;
63
        break;
64
    default:
65
        tcg_abort();
66
    }
67
}
68

    
69
/* maximum number of register used for input function arguments */
70
static inline int tcg_target_get_call_iarg_regs_count(int flags)
71
{
72
    flags &= TCG_CALL_TYPE_MASK;
73
    switch(flags) {
74
    case TCG_CALL_TYPE_STD:
75
        return 0;
76
    case TCG_CALL_TYPE_REGPARM_1:
77
    case TCG_CALL_TYPE_REGPARM_2:
78
    case TCG_CALL_TYPE_REGPARM:
79
        return flags - TCG_CALL_TYPE_REGPARM_1 + 1;
80
    default:
81
        tcg_abort();
82
    }
83
}
84

    
85
/* parse target specific constraints */
86
static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
87
{
88
    const char *ct_str;
89

    
90
    ct_str = *pct_str;
91
    switch(ct_str[0]) {
92
    case 'a':
93
        ct->ct |= TCG_CT_REG;
94
        tcg_regset_set_reg(ct->u.regs, TCG_REG_EAX);
95
        break;
96
    case 'b':
97
        ct->ct |= TCG_CT_REG;
98
        tcg_regset_set_reg(ct->u.regs, TCG_REG_EBX);
99
        break;
100
    case 'c':
101
        ct->ct |= TCG_CT_REG;
102
        tcg_regset_set_reg(ct->u.regs, TCG_REG_ECX);
103
        break;
104
    case 'd':
105
        ct->ct |= TCG_CT_REG;
106
        tcg_regset_set_reg(ct->u.regs, TCG_REG_EDX);
107
        break;
108
    case 'S':
109
        ct->ct |= TCG_CT_REG;
110
        tcg_regset_set_reg(ct->u.regs, TCG_REG_ESI);
111
        break;
112
    case 'D':
113
        ct->ct |= TCG_CT_REG;
114
        tcg_regset_set_reg(ct->u.regs, TCG_REG_EDI);
115
        break;
116
    case 'q':
117
        ct->ct |= TCG_CT_REG;
118
        tcg_regset_set32(ct->u.regs, 0, 0xf);
119
        break;
120
    case 'r':
121
        ct->ct |= TCG_CT_REG;
122
        tcg_regset_set32(ct->u.regs, 0, 0xff);
123
        break;
124

    
125
        /* qemu_ld/st address constraint */
126
    case 'L':
127
        ct->ct |= TCG_CT_REG;
128
        tcg_regset_set32(ct->u.regs, 0, 0xff);
129
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_EAX);
130
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_EDX);
131
        break;
132
    default:
133
        return -1;
134
    }
135
    ct_str++;
136
    *pct_str = ct_str;
137
    return 0;
138
}
139

    
140
/* test if a constant matches the constraint */
141
static inline int tcg_target_const_match(tcg_target_long val,
142
                                         const TCGArgConstraint *arg_ct)
143
{
144
    int ct;
145
    ct = arg_ct->ct;
146
    if (ct & TCG_CT_CONST)
147
        return 1;
148
    else
149
        return 0;
150
}
151

    
152
#define ARITH_ADD 0
153
#define ARITH_OR  1
154
#define ARITH_ADC 2
155
#define ARITH_SBB 3
156
#define ARITH_AND 4
157
#define ARITH_SUB 5
158
#define ARITH_XOR 6
159
#define ARITH_CMP 7
160

    
161
#define SHIFT_SHL 4
162
#define SHIFT_SHR 5
163
#define SHIFT_SAR 7
164

    
165
#define JCC_JMP (-1)
166
#define JCC_JO  0x0
167
#define JCC_JNO 0x1
168
#define JCC_JB  0x2
169
#define JCC_JAE 0x3
170
#define JCC_JE  0x4
171
#define JCC_JNE 0x5
172
#define JCC_JBE 0x6
173
#define JCC_JA  0x7
174
#define JCC_JS  0x8
175
#define JCC_JNS 0x9
176
#define JCC_JP  0xa
177
#define JCC_JNP 0xb
178
#define JCC_JL  0xc
179
#define JCC_JGE 0xd
180
#define JCC_JLE 0xe
181
#define JCC_JG  0xf
182

    
183
#define P_EXT   0x100 /* 0x0f opcode prefix */
184

    
185
static const uint8_t tcg_cond_to_jcc[10] = {
186
    [TCG_COND_EQ] = JCC_JE,
187
    [TCG_COND_NE] = JCC_JNE,
188
    [TCG_COND_LT] = JCC_JL,
189
    [TCG_COND_GE] = JCC_JGE,
190
    [TCG_COND_LE] = JCC_JLE,
191
    [TCG_COND_GT] = JCC_JG,
192
    [TCG_COND_LTU] = JCC_JB,
193
    [TCG_COND_GEU] = JCC_JAE,
194
    [TCG_COND_LEU] = JCC_JBE,
195
    [TCG_COND_GTU] = JCC_JA,
196
};
197

    
198
static inline void tcg_out_opc(TCGContext *s, int opc)
199
{
200
    if (opc & P_EXT)
201
        tcg_out8(s, 0x0f);
202
    tcg_out8(s, opc);
203
}
204

    
205
static inline void tcg_out_modrm(TCGContext *s, int opc, int r, int rm)
206
{
207
    tcg_out_opc(s, opc);
208
    tcg_out8(s, 0xc0 | (r << 3) | rm);
209
}
210

    
211
/* rm == -1 means no register index */
212
static inline void tcg_out_modrm_offset(TCGContext *s, int opc, int r, int rm, 
213
                                        int32_t offset)
214
{
215
    tcg_out_opc(s, opc);
216
    if (rm == -1) {
217
        tcg_out8(s, 0x05 | (r << 3));
218
        tcg_out32(s, offset);
219
    } else if (offset == 0 && rm != TCG_REG_EBP) {
220
        if (rm == TCG_REG_ESP) {
221
            tcg_out8(s, 0x04 | (r << 3));
222
            tcg_out8(s, 0x24);
223
        } else {
224
            tcg_out8(s, 0x00 | (r << 3) | rm);
225
        }
226
    } else if ((int8_t)offset == offset) {
227
        if (rm == TCG_REG_ESP) {
228
            tcg_out8(s, 0x44 | (r << 3));
229
            tcg_out8(s, 0x24);
230
        } else {
231
            tcg_out8(s, 0x40 | (r << 3) | rm);
232
        }
233
        tcg_out8(s, offset);
234
    } else {
235
        if (rm == TCG_REG_ESP) {
236
            tcg_out8(s, 0x84 | (r << 3));
237
            tcg_out8(s, 0x24);
238
        } else {
239
            tcg_out8(s, 0x80 | (r << 3) | rm);
240
        }
241
        tcg_out32(s, offset);
242
    }
243
}
244

    
245
static inline void tcg_out_mov(TCGContext *s, int ret, int arg)
246
{
247
    if (arg != ret)
248
        tcg_out_modrm(s, 0x8b, ret, arg);
249
}
250

    
251
static inline void tcg_out_movi(TCGContext *s, TCGType type,
252
                                int ret, int32_t arg)
253
{
254
    if (arg == 0) {
255
        /* xor r0,r0 */
256
        tcg_out_modrm(s, 0x01 | (ARITH_XOR << 3), ret, ret);
257
    } else {
258
        tcg_out8(s, 0xb8 + ret);
259
        tcg_out32(s, arg);
260
    }
261
}
262

    
263
static inline void tcg_out_ld(TCGContext *s, TCGType type, int ret,
264
                              int arg1, tcg_target_long arg2)
265
{
266
    /* movl */
267
    tcg_out_modrm_offset(s, 0x8b, ret, arg1, arg2);
268
}
269

    
270
static inline void tcg_out_st(TCGContext *s, TCGType type, int arg,
271
                              int arg1, tcg_target_long arg2)
272
{
273
    /* movl */
274
    tcg_out_modrm_offset(s, 0x89, arg, arg1, arg2);
275
}
276

    
277
static inline void tgen_arithi(TCGContext *s, int c, int r0, int32_t val)
278
{
279
    if (val == (int8_t)val) {
280
        tcg_out_modrm(s, 0x83, c, r0);
281
        tcg_out8(s, val);
282
    } else {
283
        tcg_out_modrm(s, 0x81, c, r0);
284
        tcg_out32(s, val);
285
    }
286
}
287

    
288
void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
289
{
290
    if (val != 0)
291
        tgen_arithi(s, ARITH_ADD, reg, val);
292
}
293

    
294
static void tcg_out_jxx(TCGContext *s, int opc, int label_index)
295
{
296
    int32_t val, val1;
297
    TCGLabel *l = &s->labels[label_index];
298
    
299
    if (l->has_value) {
300
        val = l->u.value - (tcg_target_long)s->code_ptr;
301
        val1 = val - 2;
302
        if ((int8_t)val1 == val1) {
303
            if (opc == -1)
304
                tcg_out8(s, 0xeb);
305
            else
306
                tcg_out8(s, 0x70 + opc);
307
            tcg_out8(s, val1);
308
        } else {
309
            if (opc == -1) {
310
                tcg_out8(s, 0xe9);
311
                tcg_out32(s, val - 5);
312
            } else {
313
                tcg_out8(s, 0x0f);
314
                tcg_out8(s, 0x80 + opc);
315
                tcg_out32(s, val - 6);
316
            }
317
        }
318
    } else {
319
        if (opc == -1) {
320
            tcg_out8(s, 0xe9);
321
        } else {
322
            tcg_out8(s, 0x0f);
323
            tcg_out8(s, 0x80 + opc);
324
        }
325
        tcg_out_reloc(s, s->code_ptr, R_386_PC32, label_index, -4);
326
        s->code_ptr += 4;
327
    }
328
}
329

    
330
static void tcg_out_brcond(TCGContext *s, int cond, 
331
                           TCGArg arg1, TCGArg arg2, int const_arg2,
332
                           int label_index)
333
{
334
    if (const_arg2) {
335
        if (arg2 == 0) {
336
            /* test r, r */
337
            tcg_out_modrm(s, 0x85, arg1, arg1);
338
        } else {
339
            tgen_arithi(s, ARITH_CMP, arg1, arg2);
340
        }
341
    } else {
342
        tcg_out_modrm(s, 0x01 | (ARITH_CMP << 3), arg2, arg1);
343
    }
344
    tcg_out_jxx(s, tcg_cond_to_jcc[cond], label_index);
345
}
346

    
347
/* XXX: we implement it at the target level to avoid having to
348
   handle cross basic blocks temporaries */
349
static void tcg_out_brcond2(TCGContext *s,
350
                            const TCGArg *args, const int *const_args)
351
{
352
    int label_next;
353
    label_next = gen_new_label();
354
    switch(args[4]) {
355
    case TCG_COND_EQ:
356
        tcg_out_brcond(s, TCG_COND_NE, args[0], args[2], const_args[2], label_next);
357
        tcg_out_brcond(s, TCG_COND_EQ, args[1], args[3], const_args[3], args[5]);
358
        break;
359
    case TCG_COND_NE:
360
        tcg_out_brcond(s, TCG_COND_NE, args[0], args[2], const_args[2], args[5]);
361
        tcg_out_brcond(s, TCG_COND_NE, args[1], args[3], const_args[3], args[5]);
362
        break;
363
    case TCG_COND_LT:
364
        tcg_out_brcond(s, TCG_COND_LT, args[1], args[3], const_args[3], args[5]);
365
        tcg_out_jxx(s, JCC_JNE, label_next);
366
        tcg_out_brcond(s, TCG_COND_LTU, args[0], args[2], const_args[2], args[5]);
367
        break;
368
    case TCG_COND_LE:
369
        tcg_out_brcond(s, TCG_COND_LT, args[1], args[3], const_args[3], args[5]);
370
        tcg_out_jxx(s, JCC_JNE, label_next);
371
        tcg_out_brcond(s, TCG_COND_LEU, args[0], args[2], const_args[2], args[5]);
372
        break;
373
    case TCG_COND_GT:
374
        tcg_out_brcond(s, TCG_COND_GT, args[1], args[3], const_args[3], args[5]);
375
        tcg_out_jxx(s, JCC_JNE, label_next);
376
        tcg_out_brcond(s, TCG_COND_GTU, args[0], args[2], const_args[2], args[5]);
377
        break;
378
    case TCG_COND_GE:
379
        tcg_out_brcond(s, TCG_COND_GT, args[1], args[3], const_args[3], args[5]);
380
        tcg_out_jxx(s, JCC_JNE, label_next);
381
        tcg_out_brcond(s, TCG_COND_GEU, args[0], args[2], const_args[2], args[5]);
382
        break;
383
    case TCG_COND_LTU:
384
        tcg_out_brcond(s, TCG_COND_LTU, args[1], args[3], const_args[3], args[5]);
385
        tcg_out_jxx(s, JCC_JNE, label_next);
386
        tcg_out_brcond(s, TCG_COND_LTU, args[0], args[2], const_args[2], args[5]);
387
        break;
388
    case TCG_COND_LEU:
389
        tcg_out_brcond(s, TCG_COND_LTU, args[1], args[3], const_args[3], args[5]);
390
        tcg_out_jxx(s, JCC_JNE, label_next);
391
        tcg_out_brcond(s, TCG_COND_LEU, args[0], args[2], const_args[2], args[5]);
392
        break;
393
    case TCG_COND_GTU:
394
        tcg_out_brcond(s, TCG_COND_GTU, args[1], args[3], const_args[3], args[5]);
395
        tcg_out_jxx(s, JCC_JNE, label_next);
396
        tcg_out_brcond(s, TCG_COND_GTU, args[0], args[2], const_args[2], args[5]);
397
        break;
398
    case TCG_COND_GEU:
399
        tcg_out_brcond(s, TCG_COND_GTU, args[1], args[3], const_args[3], args[5]);
400
        tcg_out_jxx(s, JCC_JNE, label_next);
401
        tcg_out_brcond(s, TCG_COND_GEU, args[0], args[2], const_args[2], args[5]);
402
        break;
403
    default:
404
        tcg_abort();
405
    }
406
    tcg_out_label(s, label_next, (tcg_target_long)s->code_ptr);
407
}
408

    
409
#if defined(CONFIG_SOFTMMU)
410

    
411
#include "../../softmmu_defs.h"
412

    
413
static void *qemu_ld_helpers[4] = {
414
    __ldb_mmu,
415
    __ldw_mmu,
416
    __ldl_mmu,
417
    __ldq_mmu,
418
};
419

    
420
static void *qemu_st_helpers[4] = {
421
    __stb_mmu,
422
    __stw_mmu,
423
    __stl_mmu,
424
    __stq_mmu,
425
};
426
#endif
427

    
428
/* XXX: qemu_ld and qemu_st could be modified to clobber only EDX and
429
   EAX. It will be useful once fixed registers globals are less
430
   common. */
431
static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
432
                            int opc)
433
{
434
    int addr_reg, data_reg, data_reg2, r0, r1, mem_index, s_bits, bswap;
435
#if defined(CONFIG_SOFTMMU)
436
    uint8_t *label1_ptr, *label2_ptr;
437
#endif
438
#if TARGET_LONG_BITS == 64
439
#if defined(CONFIG_SOFTMMU)
440
    uint8_t *label3_ptr;
441
#endif
442
    int addr_reg2;
443
#endif
444

    
445
    data_reg = *args++;
446
    if (opc == 3)
447
        data_reg2 = *args++;
448
    else
449
        data_reg2 = 0;
450
    addr_reg = *args++;
451
#if TARGET_LONG_BITS == 64
452
    addr_reg2 = *args++;
453
#endif
454
    mem_index = *args;
455
    s_bits = opc & 3;
456

    
457
    r0 = TCG_REG_EAX;
458
    r1 = TCG_REG_EDX;
459

    
460
#if defined(CONFIG_SOFTMMU)
461
    tcg_out_mov(s, r1, addr_reg); 
462

    
463
    tcg_out_mov(s, r0, addr_reg); 
464
 
465
    tcg_out_modrm(s, 0xc1, 5, r1); /* shr $x, r1 */
466
    tcg_out8(s, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS); 
467
    
468
    tcg_out_modrm(s, 0x81, 4, r0); /* andl $x, r0 */
469
    tcg_out32(s, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
470
    
471
    tcg_out_modrm(s, 0x81, 4, r1); /* andl $x, r1 */
472
    tcg_out32(s, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
473

    
474
    tcg_out_opc(s, 0x8d); /* lea offset(r1, %ebp), r1 */
475
    tcg_out8(s, 0x80 | (r1 << 3) | 0x04);
476
    tcg_out8(s, (5 << 3) | r1);
477
    tcg_out32(s, offsetof(CPUState, tlb_table[mem_index][0].addr_read));
478

    
479
    /* cmp 0(r1), r0 */
480
    tcg_out_modrm_offset(s, 0x3b, r0, r1, 0);
481
    
482
    tcg_out_mov(s, r0, addr_reg);
483
    
484
#if TARGET_LONG_BITS == 32
485
    /* je label1 */
486
    tcg_out8(s, 0x70 + JCC_JE);
487
    label1_ptr = s->code_ptr;
488
    s->code_ptr++;
489
#else
490
    /* jne label3 */
491
    tcg_out8(s, 0x70 + JCC_JNE);
492
    label3_ptr = s->code_ptr;
493
    s->code_ptr++;
494
    
495
    /* cmp 4(r1), addr_reg2 */
496
    tcg_out_modrm_offset(s, 0x3b, addr_reg2, r1, 4);
497

    
498
    /* je label1 */
499
    tcg_out8(s, 0x70 + JCC_JE);
500
    label1_ptr = s->code_ptr;
501
    s->code_ptr++;
502
    
503
    /* label3: */
504
    *label3_ptr = s->code_ptr - label3_ptr - 1;
505
#endif
506

    
507
    /* XXX: move that code at the end of the TB */
508
#if TARGET_LONG_BITS == 32
509
    tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_EDX, mem_index);
510
#else
511
    tcg_out_mov(s, TCG_REG_EDX, addr_reg2);
512
    tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_ECX, mem_index);
513
#endif
514
    tcg_out8(s, 0xe8);
515
    tcg_out32(s, (tcg_target_long)qemu_ld_helpers[s_bits] - 
516
              (tcg_target_long)s->code_ptr - 4);
517

    
518
    switch(opc) {
519
    case 0 | 4:
520
        /* movsbl */
521
        tcg_out_modrm(s, 0xbe | P_EXT, data_reg, TCG_REG_EAX);
522
        break;
523
    case 1 | 4:
524
        /* movswl */
525
        tcg_out_modrm(s, 0xbf | P_EXT, data_reg, TCG_REG_EAX);
526
        break;
527
    case 0:
528
    case 1:
529
    case 2:
530
    default:
531
        tcg_out_mov(s, data_reg, TCG_REG_EAX);
532
        break;
533
    case 3:
534
        if (data_reg == TCG_REG_EDX) {
535
            tcg_out_opc(s, 0x90 + TCG_REG_EDX); /* xchg %edx, %eax */
536
            tcg_out_mov(s, data_reg2, TCG_REG_EAX);
537
        } else {
538
            tcg_out_mov(s, data_reg, TCG_REG_EAX);
539
            tcg_out_mov(s, data_reg2, TCG_REG_EDX);
540
        }
541
        break;
542
    }
543

    
544
    /* jmp label2 */
545
    tcg_out8(s, 0xeb);
546
    label2_ptr = s->code_ptr;
547
    s->code_ptr++;
548
    
549
    /* label1: */
550
    *label1_ptr = s->code_ptr - label1_ptr - 1;
551

    
552
    /* add x(r1), r0 */
553
    tcg_out_modrm_offset(s, 0x03, r0, r1, offsetof(CPUTLBEntry, addend) - 
554
                         offsetof(CPUTLBEntry, addr_read));
555
#else
556
    r0 = addr_reg;
557
#endif
558

    
559
#ifdef TARGET_WORDS_BIGENDIAN
560
    bswap = 1;
561
#else
562
    bswap = 0;
563
#endif
564
    switch(opc) {
565
    case 0:
566
        /* movzbl */
567
        tcg_out_modrm_offset(s, 0xb6 | P_EXT, data_reg, r0, 0);
568
        break;
569
    case 0 | 4:
570
        /* movsbl */
571
        tcg_out_modrm_offset(s, 0xbe | P_EXT, data_reg, r0, 0);
572
        break;
573
    case 1:
574
        /* movzwl */
575
        tcg_out_modrm_offset(s, 0xb7 | P_EXT, data_reg, r0, 0);
576
        if (bswap) {
577
            /* rolw $8, data_reg */
578
            tcg_out8(s, 0x66); 
579
            tcg_out_modrm(s, 0xc1, 0, data_reg);
580
            tcg_out8(s, 8);
581
        }
582
        break;
583
    case 1 | 4:
584
        /* movswl */
585
        tcg_out_modrm_offset(s, 0xbf | P_EXT, data_reg, r0, 0);
586
        if (bswap) {
587
            /* rolw $8, data_reg */
588
            tcg_out8(s, 0x66); 
589
            tcg_out_modrm(s, 0xc1, 0, data_reg);
590
            tcg_out8(s, 8);
591

    
592
            /* movswl data_reg, data_reg */
593
            tcg_out_modrm(s, 0xbf | P_EXT, data_reg, data_reg);
594
        }
595
        break;
596
    case 2:
597
        /* movl (r0), data_reg */
598
        tcg_out_modrm_offset(s, 0x8b, data_reg, r0, 0);
599
        if (bswap) {
600
            /* bswap */
601
            tcg_out_opc(s, (0xc8 + data_reg) | P_EXT);
602
        }
603
        break;
604
    case 3:
605
        /* XXX: could be nicer */
606
        if (r0 == data_reg) {
607
            r1 = TCG_REG_EDX;
608
            if (r1 == data_reg)
609
                r1 = TCG_REG_EAX;
610
            tcg_out_mov(s, r1, r0);
611
            r0 = r1;
612
        }
613
        if (!bswap) {
614
            tcg_out_modrm_offset(s, 0x8b, data_reg, r0, 0);
615
            tcg_out_modrm_offset(s, 0x8b, data_reg2, r0, 4);
616
        } else {
617
            tcg_out_modrm_offset(s, 0x8b, data_reg, r0, 4);
618
            tcg_out_opc(s, (0xc8 + data_reg) | P_EXT);
619

    
620
            tcg_out_modrm_offset(s, 0x8b, data_reg2, r0, 0);
621
            /* bswap */
622
            tcg_out_opc(s, (0xc8 + data_reg2) | P_EXT);
623
        }
624
        break;
625
    default:
626
        tcg_abort();
627
    }
628

    
629
#if defined(CONFIG_SOFTMMU)
630
    /* label2: */
631
    *label2_ptr = s->code_ptr - label2_ptr - 1;
632
#endif
633
}
634

    
635

    
636
static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
637
                            int opc)
638
{
639
    int addr_reg, data_reg, data_reg2, r0, r1, mem_index, s_bits, bswap;
640
#if defined(CONFIG_SOFTMMU)
641
    uint8_t *label1_ptr, *label2_ptr;
642
#endif
643
#if TARGET_LONG_BITS == 64
644
#if defined(CONFIG_SOFTMMU)
645
    uint8_t *label3_ptr;
646
#endif
647
    int addr_reg2;
648
#endif
649

    
650
    data_reg = *args++;
651
    if (opc == 3)
652
        data_reg2 = *args++;
653
    else
654
        data_reg2 = 0;
655
    addr_reg = *args++;
656
#if TARGET_LONG_BITS == 64
657
    addr_reg2 = *args++;
658
#endif
659
    mem_index = *args;
660

    
661
    s_bits = opc;
662

    
663
    r0 = TCG_REG_EAX;
664
    r1 = TCG_REG_EDX;
665

    
666
#if defined(CONFIG_SOFTMMU)
667
    tcg_out_mov(s, r1, addr_reg); 
668

    
669
    tcg_out_mov(s, r0, addr_reg); 
670
 
671
    tcg_out_modrm(s, 0xc1, 5, r1); /* shr $x, r1 */
672
    tcg_out8(s, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS); 
673
    
674
    tcg_out_modrm(s, 0x81, 4, r0); /* andl $x, r0 */
675
    tcg_out32(s, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
676
    
677
    tcg_out_modrm(s, 0x81, 4, r1); /* andl $x, r1 */
678
    tcg_out32(s, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
679

    
680
    tcg_out_opc(s, 0x8d); /* lea offset(r1, %ebp), r1 */
681
    tcg_out8(s, 0x80 | (r1 << 3) | 0x04);
682
    tcg_out8(s, (5 << 3) | r1);
683
    tcg_out32(s, offsetof(CPUState, tlb_table[mem_index][0].addr_write));
684

    
685
    /* cmp 0(r1), r0 */
686
    tcg_out_modrm_offset(s, 0x3b, r0, r1, 0);
687
    
688
    tcg_out_mov(s, r0, addr_reg);
689
    
690
#if TARGET_LONG_BITS == 32
691
    /* je label1 */
692
    tcg_out8(s, 0x70 + JCC_JE);
693
    label1_ptr = s->code_ptr;
694
    s->code_ptr++;
695
#else
696
    /* jne label3 */
697
    tcg_out8(s, 0x70 + JCC_JNE);
698
    label3_ptr = s->code_ptr;
699
    s->code_ptr++;
700
    
701
    /* cmp 4(r1), addr_reg2 */
702
    tcg_out_modrm_offset(s, 0x3b, addr_reg2, r1, 4);
703

    
704
    /* je label1 */
705
    tcg_out8(s, 0x70 + JCC_JE);
706
    label1_ptr = s->code_ptr;
707
    s->code_ptr++;
708
    
709
    /* label3: */
710
    *label3_ptr = s->code_ptr - label3_ptr - 1;
711
#endif
712

    
713
    /* XXX: move that code at the end of the TB */
714
#if TARGET_LONG_BITS == 32
715
    if (opc == 3) {
716
        tcg_out_mov(s, TCG_REG_EDX, data_reg);
717
        tcg_out_mov(s, TCG_REG_ECX, data_reg2);
718
        tcg_out8(s, 0x6a); /* push Ib */
719
        tcg_out8(s, mem_index);
720
        tcg_out8(s, 0xe8);
721
        tcg_out32(s, (tcg_target_long)qemu_st_helpers[s_bits] - 
722
                  (tcg_target_long)s->code_ptr - 4);
723
        tcg_out_addi(s, TCG_REG_ESP, 4);
724
    } else {
725
        switch(opc) {
726
        case 0:
727
            /* movzbl */
728
            tcg_out_modrm(s, 0xb6 | P_EXT, TCG_REG_EDX, data_reg);
729
            break;
730
        case 1:
731
            /* movzwl */
732
            tcg_out_modrm(s, 0xb7 | P_EXT, TCG_REG_EDX, data_reg);
733
            break;
734
        case 2:
735
            tcg_out_mov(s, TCG_REG_EDX, data_reg);
736
            break;
737
        }
738
        tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_ECX, mem_index);
739
        tcg_out8(s, 0xe8);
740
        tcg_out32(s, (tcg_target_long)qemu_st_helpers[s_bits] - 
741
                  (tcg_target_long)s->code_ptr - 4);
742
    }
743
#else
744
    if (opc == 3) {
745
        tcg_out_mov(s, TCG_REG_EDX, addr_reg2);
746
        tcg_out8(s, 0x6a); /* push Ib */
747
        tcg_out8(s, mem_index);
748
        tcg_out_opc(s, 0x50 + data_reg2); /* push */
749
        tcg_out_opc(s, 0x50 + data_reg); /* push */
750
        tcg_out8(s, 0xe8);
751
        tcg_out32(s, (tcg_target_long)qemu_st_helpers[s_bits] - 
752
                  (tcg_target_long)s->code_ptr - 4);
753
        tcg_out_addi(s, TCG_REG_ESP, 12);
754
    } else {
755
        tcg_out_mov(s, TCG_REG_EDX, addr_reg2);
756
        switch(opc) {
757
        case 0:
758
            /* movzbl */
759
            tcg_out_modrm(s, 0xb6 | P_EXT, TCG_REG_ECX, data_reg);
760
            break;
761
        case 1:
762
            /* movzwl */
763
            tcg_out_modrm(s, 0xb7 | P_EXT, TCG_REG_ECX, data_reg);
764
            break;
765
        case 2:
766
            tcg_out_mov(s, TCG_REG_ECX, data_reg);
767
            break;
768
        }
769
        tcg_out8(s, 0x6a); /* push Ib */
770
        tcg_out8(s, mem_index);
771
        tcg_out8(s, 0xe8);
772
        tcg_out32(s, (tcg_target_long)qemu_st_helpers[s_bits] - 
773
                  (tcg_target_long)s->code_ptr - 4);
774
        tcg_out_addi(s, TCG_REG_ESP, 4);
775
    }
776
#endif
777
    
778
    /* jmp label2 */
779
    tcg_out8(s, 0xeb);
780
    label2_ptr = s->code_ptr;
781
    s->code_ptr++;
782
    
783
    /* label1: */
784
    *label1_ptr = s->code_ptr - label1_ptr - 1;
785

    
786
    /* add x(r1), r0 */
787
    tcg_out_modrm_offset(s, 0x03, r0, r1, offsetof(CPUTLBEntry, addend) - 
788
                         offsetof(CPUTLBEntry, addr_write));
789
#else
790
    r0 = addr_reg;
791
#endif
792

    
793
#ifdef TARGET_WORDS_BIGENDIAN
794
    bswap = 1;
795
#else
796
    bswap = 0;
797
#endif
798
    switch(opc) {
799
    case 0:
800
        /* movb */
801
        tcg_out_modrm_offset(s, 0x88, data_reg, r0, 0);
802
        break;
803
    case 1:
804
        if (bswap) {
805
            tcg_out_mov(s, r1, data_reg);
806
            tcg_out8(s, 0x66); /* rolw $8, %ecx */
807
            tcg_out_modrm(s, 0xc1, 0, r1);
808
            tcg_out8(s, 8);
809
            data_reg = r1;
810
        }
811
        /* movw */
812
        tcg_out8(s, 0x66);
813
        tcg_out_modrm_offset(s, 0x89, data_reg, r0, 0);
814
        break;
815
    case 2:
816
        if (bswap) {
817
            tcg_out_mov(s, r1, data_reg);
818
            /* bswap data_reg */
819
            tcg_out_opc(s, (0xc8 + r1) | P_EXT);
820
            data_reg = r1;
821
        }
822
        /* movl */
823
        tcg_out_modrm_offset(s, 0x89, data_reg, r0, 0);
824
        break;
825
    case 3:
826
        if (bswap) {
827
            tcg_out_mov(s, r1, data_reg2);
828
            /* bswap data_reg */
829
            tcg_out_opc(s, (0xc8 + r1) | P_EXT);
830
            tcg_out_modrm_offset(s, 0x89, r1, r0, 0);
831
            tcg_out_mov(s, r1, data_reg);
832
            /* bswap data_reg */
833
            tcg_out_opc(s, (0xc8 + r1) | P_EXT);
834
            tcg_out_modrm_offset(s, 0x89, r1, r0, 4);
835
        } else {
836
            tcg_out_modrm_offset(s, 0x89, data_reg, r0, 0);
837
            tcg_out_modrm_offset(s, 0x89, data_reg2, r0, 4);
838
        }
839
        break;
840
    default:
841
        tcg_abort();
842
    }
843

    
844
#if defined(CONFIG_SOFTMMU)
845
    /* label2: */
846
    *label2_ptr = s->code_ptr - label2_ptr - 1;
847
#endif
848
}
849

    
850
static inline void tcg_out_op(TCGContext *s, int opc, 
851
                              const TCGArg *args, const int *const_args)
852
{
853
    int c;
854
    
855
    switch(opc) {
856
    case INDEX_op_exit_tb:
857
        tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_EAX, args[0]);
858
        tcg_out8(s, 0xe9); /* jmp tb_ret_addr */
859
        tcg_out32(s, tb_ret_addr - s->code_ptr - 4);
860
        break;
861
    case INDEX_op_goto_tb:
862
        if (s->tb_jmp_offset) {
863
            /* direct jump method */
864
            tcg_out8(s, 0xe9); /* jmp im */
865
            s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
866
            tcg_out32(s, 0);
867
        } else {
868
            /* indirect jump method */
869
            /* jmp Ev */
870
            tcg_out_modrm_offset(s, 0xff, 4, -1, 
871
                                 (tcg_target_long)(s->tb_next + args[0]));
872
        }
873
        s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
874
        break;
875
    case INDEX_op_call:
876
        if (const_args[0]) {
877
            tcg_out8(s, 0xe8);
878
            tcg_out32(s, args[0] - (tcg_target_long)s->code_ptr - 4);
879
        } else {
880
            tcg_out_modrm(s, 0xff, 2, args[0]);
881
        }
882
        break;
883
    case INDEX_op_jmp:
884
        if (const_args[0]) {
885
            tcg_out8(s, 0xe9);
886
            tcg_out32(s, args[0] - (tcg_target_long)s->code_ptr - 4);
887
        } else {
888
            tcg_out_modrm(s, 0xff, 4, args[0]);
889
        }
890
        break;
891
    case INDEX_op_br:
892
        tcg_out_jxx(s, JCC_JMP, args[0]);
893
        break;
894
    case INDEX_op_movi_i32:
895
        tcg_out_movi(s, TCG_TYPE_I32, args[0], args[1]);
896
        break;
897
    case INDEX_op_ld8u_i32:
898
        /* movzbl */
899
        tcg_out_modrm_offset(s, 0xb6 | P_EXT, args[0], args[1], args[2]);
900
        break;
901
    case INDEX_op_ld8s_i32:
902
        /* movsbl */
903
        tcg_out_modrm_offset(s, 0xbe | P_EXT, args[0], args[1], args[2]);
904
        break;
905
    case INDEX_op_ld16u_i32:
906
        /* movzwl */
907
        tcg_out_modrm_offset(s, 0xb7 | P_EXT, args[0], args[1], args[2]);
908
        break;
909
    case INDEX_op_ld16s_i32:
910
        /* movswl */
911
        tcg_out_modrm_offset(s, 0xbf | P_EXT, args[0], args[1], args[2]);
912
        break;
913
    case INDEX_op_ld_i32:
914
        /* movl */
915
        tcg_out_modrm_offset(s, 0x8b, args[0], args[1], args[2]);
916
        break;
917
    case INDEX_op_st8_i32:
918
        /* movb */
919
        tcg_out_modrm_offset(s, 0x88, args[0], args[1], args[2]);
920
        break;
921
    case INDEX_op_st16_i32:
922
        /* movw */
923
        tcg_out8(s, 0x66);
924
        tcg_out_modrm_offset(s, 0x89, args[0], args[1], args[2]);
925
        break;
926
    case INDEX_op_st_i32:
927
        /* movl */
928
        tcg_out_modrm_offset(s, 0x89, args[0], args[1], args[2]);
929
        break;
930
    case INDEX_op_sub_i32:
931
        c = ARITH_SUB;
932
        goto gen_arith;
933
    case INDEX_op_and_i32:
934
        c = ARITH_AND;
935
        goto gen_arith;
936
    case INDEX_op_or_i32:
937
        c = ARITH_OR;
938
        goto gen_arith;
939
    case INDEX_op_xor_i32:
940
        c = ARITH_XOR;
941
        goto gen_arith;
942
    case INDEX_op_add_i32:
943
        c = ARITH_ADD;
944
    gen_arith:
945
        if (const_args[2]) {
946
            tgen_arithi(s, c, args[0], args[2]);
947
        } else {
948
            tcg_out_modrm(s, 0x01 | (c << 3), args[2], args[0]);
949
        }
950
        break;
951
    case INDEX_op_mul_i32:
952
        if (const_args[2]) {
953
            int32_t val;
954
            val = args[2];
955
            if (val == (int8_t)val) {
956
                tcg_out_modrm(s, 0x6b, args[0], args[0]);
957
                tcg_out8(s, val);
958
            } else {
959
                tcg_out_modrm(s, 0x69, args[0], args[0]);
960
                tcg_out32(s, val);
961
            }
962
        } else {
963
            tcg_out_modrm(s, 0xaf | P_EXT, args[0], args[2]);
964
        }
965
        break;
966
    case INDEX_op_mulu2_i32:
967
        tcg_out_modrm(s, 0xf7, 4, args[3]);
968
        break;
969
    case INDEX_op_div2_i32:
970
        tcg_out_modrm(s, 0xf7, 7, args[4]);
971
        break;
972
    case INDEX_op_divu2_i32:
973
        tcg_out_modrm(s, 0xf7, 6, args[4]);
974
        break;
975
    case INDEX_op_shl_i32:
976
        c = SHIFT_SHL;
977
    gen_shift32:
978
        if (const_args[2]) {
979
            if (args[2] == 1) {
980
                tcg_out_modrm(s, 0xd1, c, args[0]);
981
            } else {
982
                tcg_out_modrm(s, 0xc1, c, args[0]);
983
                tcg_out8(s, args[2]);
984
            }
985
        } else {
986
            tcg_out_modrm(s, 0xd3, c, args[0]);
987
        }
988
        break;
989
    case INDEX_op_shr_i32:
990
        c = SHIFT_SHR;
991
        goto gen_shift32;
992
    case INDEX_op_sar_i32:
993
        c = SHIFT_SAR;
994
        goto gen_shift32;
995
        
996
    case INDEX_op_add2_i32:
997
        if (const_args[4]) 
998
            tgen_arithi(s, ARITH_ADD, args[0], args[4]);
999
        else
1000
            tcg_out_modrm(s, 0x01 | (ARITH_ADD << 3), args[4], args[0]);
1001
        if (const_args[5]) 
1002
            tgen_arithi(s, ARITH_ADC, args[1], args[5]);
1003
        else
1004
            tcg_out_modrm(s, 0x01 | (ARITH_ADC << 3), args[5], args[1]);
1005
        break;
1006
    case INDEX_op_sub2_i32:
1007
        if (const_args[4]) 
1008
            tgen_arithi(s, ARITH_SUB, args[0], args[4]);
1009
        else
1010
            tcg_out_modrm(s, 0x01 | (ARITH_SUB << 3), args[4], args[0]);
1011
        if (const_args[5]) 
1012
            tgen_arithi(s, ARITH_SBB, args[1], args[5]);
1013
        else
1014
            tcg_out_modrm(s, 0x01 | (ARITH_SBB << 3), args[5], args[1]);
1015
        break;
1016
    case INDEX_op_brcond_i32:
1017
        tcg_out_brcond(s, args[2], args[0], args[1], const_args[1], args[3]);
1018
        break;
1019
    case INDEX_op_brcond2_i32:
1020
        tcg_out_brcond2(s, args, const_args);
1021
        break;
1022

    
1023
    case INDEX_op_qemu_ld8u:
1024
        tcg_out_qemu_ld(s, args, 0);
1025
        break;
1026
    case INDEX_op_qemu_ld8s:
1027
        tcg_out_qemu_ld(s, args, 0 | 4);
1028
        break;
1029
    case INDEX_op_qemu_ld16u:
1030
        tcg_out_qemu_ld(s, args, 1);
1031
        break;
1032
    case INDEX_op_qemu_ld16s:
1033
        tcg_out_qemu_ld(s, args, 1 | 4);
1034
        break;
1035
    case INDEX_op_qemu_ld32u:
1036
        tcg_out_qemu_ld(s, args, 2);
1037
        break;
1038
    case INDEX_op_qemu_ld64:
1039
        tcg_out_qemu_ld(s, args, 3);
1040
        break;
1041
        
1042
    case INDEX_op_qemu_st8:
1043
        tcg_out_qemu_st(s, args, 0);
1044
        break;
1045
    case INDEX_op_qemu_st16:
1046
        tcg_out_qemu_st(s, args, 1);
1047
        break;
1048
    case INDEX_op_qemu_st32:
1049
        tcg_out_qemu_st(s, args, 2);
1050
        break;
1051
    case INDEX_op_qemu_st64:
1052
        tcg_out_qemu_st(s, args, 3);
1053
        break;
1054

    
1055
    default:
1056
        tcg_abort();
1057
    }
1058
}
1059

    
1060
static const TCGTargetOpDef x86_op_defs[] = {
1061
    { INDEX_op_exit_tb, { } },
1062
    { INDEX_op_goto_tb, { } },
1063
    { INDEX_op_call, { "ri" } },
1064
    { INDEX_op_jmp, { "ri" } },
1065
    { INDEX_op_br, { } },
1066
    { INDEX_op_mov_i32, { "r", "r" } },
1067
    { INDEX_op_movi_i32, { "r" } },
1068
    { INDEX_op_ld8u_i32, { "r", "r" } },
1069
    { INDEX_op_ld8s_i32, { "r", "r" } },
1070
    { INDEX_op_ld16u_i32, { "r", "r" } },
1071
    { INDEX_op_ld16s_i32, { "r", "r" } },
1072
    { INDEX_op_ld_i32, { "r", "r" } },
1073
    { INDEX_op_st8_i32, { "q", "r" } },
1074
    { INDEX_op_st16_i32, { "r", "r" } },
1075
    { INDEX_op_st_i32, { "r", "r" } },
1076

    
1077
    { INDEX_op_add_i32, { "r", "0", "ri" } },
1078
    { INDEX_op_sub_i32, { "r", "0", "ri" } },
1079
    { INDEX_op_mul_i32, { "r", "0", "ri" } },
1080
    { INDEX_op_mulu2_i32, { "a", "d", "a", "r" } },
1081
    { INDEX_op_div2_i32, { "a", "d", "0", "1", "r" } },
1082
    { INDEX_op_divu2_i32, { "a", "d", "0", "1", "r" } },
1083
    { INDEX_op_and_i32, { "r", "0", "ri" } },
1084
    { INDEX_op_or_i32, { "r", "0", "ri" } },
1085
    { INDEX_op_xor_i32, { "r", "0", "ri" } },
1086

    
1087
    { INDEX_op_shl_i32, { "r", "0", "ci" } },
1088
    { INDEX_op_shr_i32, { "r", "0", "ci" } },
1089
    { INDEX_op_sar_i32, { "r", "0", "ci" } },
1090

    
1091
    { INDEX_op_brcond_i32, { "r", "ri" } },
1092

    
1093
    { INDEX_op_add2_i32, { "r", "r", "0", "1", "ri", "ri" } },
1094
    { INDEX_op_sub2_i32, { "r", "r", "0", "1", "ri", "ri" } },
1095
    { INDEX_op_brcond2_i32, { "r", "r", "ri", "ri" } },
1096

    
1097
#if TARGET_LONG_BITS == 32
1098
    { INDEX_op_qemu_ld8u, { "r", "L" } },
1099
    { INDEX_op_qemu_ld8s, { "r", "L" } },
1100
    { INDEX_op_qemu_ld16u, { "r", "L" } },
1101
    { INDEX_op_qemu_ld16s, { "r", "L" } },
1102
    { INDEX_op_qemu_ld32u, { "r", "L" } },
1103
    { INDEX_op_qemu_ld64, { "r", "r", "L" } },
1104

    
1105
    { INDEX_op_qemu_st8, { "cb", "L" } },
1106
    { INDEX_op_qemu_st16, { "L", "L" } },
1107
    { INDEX_op_qemu_st32, { "L", "L" } },
1108
    { INDEX_op_qemu_st64, { "L", "L", "L" } },
1109
#else
1110
    { INDEX_op_qemu_ld8u, { "r", "L", "L" } },
1111
    { INDEX_op_qemu_ld8s, { "r", "L", "L" } },
1112
    { INDEX_op_qemu_ld16u, { "r", "L", "L" } },
1113
    { INDEX_op_qemu_ld16s, { "r", "L", "L" } },
1114
    { INDEX_op_qemu_ld32u, { "r", "L", "L" } },
1115
    { INDEX_op_qemu_ld64, { "r", "r", "L", "L" } },
1116

    
1117
    { INDEX_op_qemu_st8, { "cb", "L", "L" } },
1118
    { INDEX_op_qemu_st16, { "L", "L", "L" } },
1119
    { INDEX_op_qemu_st32, { "L", "L", "L" } },
1120
    { INDEX_op_qemu_st64, { "L", "L", "L", "L" } },
1121
#endif
1122
    { -1 },
1123
};
1124

    
1125
static int tcg_target_callee_save_regs[] = {
1126
    /*    TCG_REG_EBP, */ /* currently used for the global env, so no
1127
                             need to save */
1128
    TCG_REG_EBX,
1129
    TCG_REG_ESI,
1130
    TCG_REG_EDI,
1131
};
1132

    
1133
static inline void tcg_out_push(TCGContext *s, int reg)
1134
{
1135
    tcg_out_opc(s, 0x50 + reg);
1136
}
1137

    
1138
static inline void tcg_out_pop(TCGContext *s, int reg)
1139
{
1140
    tcg_out_opc(s, 0x58 + reg);
1141
}
1142

    
1143
/* Generate global QEMU prologue and epilogue code */
1144
void tcg_target_qemu_prologue(TCGContext *s)
1145
{
1146
    int i, frame_size, push_size, stack_addend;
1147
    
1148
    /* TB prologue */
1149
    /* save all callee saved registers */
1150
    for(i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
1151
        tcg_out_push(s, tcg_target_callee_save_regs[i]);
1152
    }
1153
    /* reserve some stack space */
1154
    push_size = 4 + ARRAY_SIZE(tcg_target_callee_save_regs) * 4;
1155
    frame_size = push_size + TCG_STATIC_CALL_ARGS_SIZE;
1156
    frame_size = (frame_size + TCG_TARGET_STACK_ALIGN - 1) & 
1157
        ~(TCG_TARGET_STACK_ALIGN - 1);
1158
    stack_addend = frame_size - push_size;
1159
    tcg_out_addi(s, TCG_REG_ESP, -stack_addend);
1160

    
1161
    tcg_out_modrm(s, 0xff, 4, TCG_REG_EAX); /* jmp *%eax */
1162
    
1163
    /* TB epilogue */
1164
    tb_ret_addr = s->code_ptr;
1165
    tcg_out_addi(s, TCG_REG_ESP, stack_addend);
1166
    for(i = ARRAY_SIZE(tcg_target_callee_save_regs) - 1; i >= 0; i--) {
1167
        tcg_out_pop(s, tcg_target_callee_save_regs[i]);
1168
    }
1169
    tcg_out8(s, 0xc3); /* ret */
1170
}
1171

    
1172
void tcg_target_init(TCGContext *s)
1173
{
1174
    /* fail safe */
1175
    if ((1 << CPU_TLB_ENTRY_BITS) != sizeof(CPUTLBEntry))
1176
        tcg_abort();
1177

    
1178
    tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xff);
1179
    tcg_regset_set32(tcg_target_call_clobber_regs, 0,
1180
                     (1 << TCG_REG_EAX) | 
1181
                     (1 << TCG_REG_EDX) | 
1182
                     (1 << TCG_REG_ECX));
1183
    
1184
    tcg_regset_clear(s->reserved_regs);
1185
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_ESP);
1186

    
1187
    tcg_add_target_add_op_defs(x86_op_defs);
1188
}