Statistics
| Branch: | Revision:

root / tcg / i386 / tcg-target.c @ 9db3ba4d

History | View | Annotate | Download (33.9 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
        /* movzbl */
529
        tcg_out_modrm(s, 0xb6 | P_EXT, data_reg, TCG_REG_EAX);
530
        break;
531
    case 1:
532
        /* movzwl */
533
        tcg_out_modrm(s, 0xb7 | P_EXT, data_reg, TCG_REG_EAX);
534
        break;
535
    case 2:
536
    default:
537
        tcg_out_mov(s, data_reg, TCG_REG_EAX);
538
        break;
539
    case 3:
540
        if (data_reg == TCG_REG_EDX) {
541
            tcg_out_opc(s, 0x90 + TCG_REG_EDX); /* xchg %edx, %eax */
542
            tcg_out_mov(s, data_reg2, TCG_REG_EAX);
543
        } else {
544
            tcg_out_mov(s, data_reg, TCG_REG_EAX);
545
            tcg_out_mov(s, data_reg2, TCG_REG_EDX);
546
        }
547
        break;
548
    }
549

    
550
    /* jmp label2 */
551
    tcg_out8(s, 0xeb);
552
    label2_ptr = s->code_ptr;
553
    s->code_ptr++;
554
    
555
    /* label1: */
556
    *label1_ptr = s->code_ptr - label1_ptr - 1;
557

    
558
    /* add x(r1), r0 */
559
    tcg_out_modrm_offset(s, 0x03, r0, r1, offsetof(CPUTLBEntry, addend) - 
560
                         offsetof(CPUTLBEntry, addr_read));
561
#else
562
    r0 = addr_reg;
563
#endif
564

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

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

    
626
            tcg_out_modrm_offset(s, 0x8b, data_reg2, r0, 0);
627
            /* bswap */
628
            tcg_out_opc(s, (0xc8 + data_reg2) | P_EXT);
629
        }
630
        break;
631
    default:
632
        tcg_abort();
633
    }
634

    
635
#if defined(CONFIG_SOFTMMU)
636
    /* label2: */
637
    *label2_ptr = s->code_ptr - label2_ptr - 1;
638
#endif
639
}
640

    
641

    
642
static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
643
                            int opc)
644
{
645
    int addr_reg, data_reg, data_reg2, r0, r1, mem_index, s_bits, bswap;
646
#if defined(CONFIG_SOFTMMU)
647
    uint8_t *label1_ptr, *label2_ptr;
648
#endif
649
#if TARGET_LONG_BITS == 64
650
#if defined(CONFIG_SOFTMMU)
651
    uint8_t *label3_ptr;
652
#endif
653
    int addr_reg2;
654
#endif
655

    
656
    data_reg = *args++;
657
    if (opc == 3)
658
        data_reg2 = *args++;
659
    else
660
        data_reg2 = 0;
661
    addr_reg = *args++;
662
#if TARGET_LONG_BITS == 64
663
    addr_reg2 = *args++;
664
#endif
665
    mem_index = *args;
666

    
667
    s_bits = opc;
668

    
669
    r0 = TCG_REG_EAX;
670
    r1 = TCG_REG_EDX;
671

    
672
#if defined(CONFIG_SOFTMMU)
673
    tcg_out_mov(s, r1, addr_reg); 
674

    
675
    tcg_out_mov(s, r0, addr_reg); 
676
 
677
    tcg_out_modrm(s, 0xc1, 5, r1); /* shr $x, r1 */
678
    tcg_out8(s, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS); 
679
    
680
    tcg_out_modrm(s, 0x81, 4, r0); /* andl $x, r0 */
681
    tcg_out32(s, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
682
    
683
    tcg_out_modrm(s, 0x81, 4, r1); /* andl $x, r1 */
684
    tcg_out32(s, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
685

    
686
    tcg_out_opc(s, 0x8d); /* lea offset(r1, %ebp), r1 */
687
    tcg_out8(s, 0x80 | (r1 << 3) | 0x04);
688
    tcg_out8(s, (5 << 3) | r1);
689
    tcg_out32(s, offsetof(CPUState, tlb_table[mem_index][0].addr_write));
690

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

    
710
    /* je label1 */
711
    tcg_out8(s, 0x70 + JCC_JE);
712
    label1_ptr = s->code_ptr;
713
    s->code_ptr++;
714
    
715
    /* label3: */
716
    *label3_ptr = s->code_ptr - label3_ptr - 1;
717
#endif
718

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

    
792
    /* add x(r1), r0 */
793
    tcg_out_modrm_offset(s, 0x03, r0, r1, offsetof(CPUTLBEntry, addend) - 
794
                         offsetof(CPUTLBEntry, addr_write));
795
#else
796
    r0 = addr_reg;
797
#endif
798

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

    
850
#if defined(CONFIG_SOFTMMU)
851
    /* label2: */
852
    *label2_ptr = s->code_ptr - label2_ptr - 1;
853
#endif
854
}
855

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

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

    
1061
    default:
1062
        tcg_abort();
1063
    }
1064
}
1065

    
1066
static const TCGTargetOpDef x86_op_defs[] = {
1067
    { INDEX_op_exit_tb, { } },
1068
    { INDEX_op_goto_tb, { } },
1069
    { INDEX_op_call, { "ri" } },
1070
    { INDEX_op_jmp, { "ri" } },
1071
    { INDEX_op_br, { } },
1072
    { INDEX_op_mov_i32, { "r", "r" } },
1073
    { INDEX_op_movi_i32, { "r" } },
1074
    { INDEX_op_ld8u_i32, { "r", "r" } },
1075
    { INDEX_op_ld8s_i32, { "r", "r" } },
1076
    { INDEX_op_ld16u_i32, { "r", "r" } },
1077
    { INDEX_op_ld16s_i32, { "r", "r" } },
1078
    { INDEX_op_ld_i32, { "r", "r" } },
1079
    { INDEX_op_st8_i32, { "q", "r" } },
1080
    { INDEX_op_st16_i32, { "r", "r" } },
1081
    { INDEX_op_st_i32, { "r", "r" } },
1082

    
1083
    { INDEX_op_add_i32, { "r", "0", "ri" } },
1084
    { INDEX_op_sub_i32, { "r", "0", "ri" } },
1085
    { INDEX_op_mul_i32, { "r", "0", "ri" } },
1086
    { INDEX_op_mulu2_i32, { "a", "d", "a", "r" } },
1087
    { INDEX_op_div2_i32, { "a", "d", "0", "1", "r" } },
1088
    { INDEX_op_divu2_i32, { "a", "d", "0", "1", "r" } },
1089
    { INDEX_op_and_i32, { "r", "0", "ri" } },
1090
    { INDEX_op_or_i32, { "r", "0", "ri" } },
1091
    { INDEX_op_xor_i32, { "r", "0", "ri" } },
1092

    
1093
    { INDEX_op_shl_i32, { "r", "0", "ci" } },
1094
    { INDEX_op_shr_i32, { "r", "0", "ci" } },
1095
    { INDEX_op_sar_i32, { "r", "0", "ci" } },
1096

    
1097
    { INDEX_op_brcond_i32, { "r", "ri" } },
1098

    
1099
    { INDEX_op_add2_i32, { "r", "r", "0", "1", "ri", "ri" } },
1100
    { INDEX_op_sub2_i32, { "r", "r", "0", "1", "ri", "ri" } },
1101
    { INDEX_op_brcond2_i32, { "r", "r", "ri", "ri" } },
1102

    
1103
#if TARGET_LONG_BITS == 32
1104
    { INDEX_op_qemu_ld8u, { "r", "L" } },
1105
    { INDEX_op_qemu_ld8s, { "r", "L" } },
1106
    { INDEX_op_qemu_ld16u, { "r", "L" } },
1107
    { INDEX_op_qemu_ld16s, { "r", "L" } },
1108
    { INDEX_op_qemu_ld32u, { "r", "L" } },
1109
    { INDEX_op_qemu_ld64, { "r", "r", "L" } },
1110

    
1111
    { INDEX_op_qemu_st8, { "cb", "L" } },
1112
    { INDEX_op_qemu_st16, { "L", "L" } },
1113
    { INDEX_op_qemu_st32, { "L", "L" } },
1114
    { INDEX_op_qemu_st64, { "L", "L", "L" } },
1115
#else
1116
    { INDEX_op_qemu_ld8u, { "r", "L", "L" } },
1117
    { INDEX_op_qemu_ld8s, { "r", "L", "L" } },
1118
    { INDEX_op_qemu_ld16u, { "r", "L", "L" } },
1119
    { INDEX_op_qemu_ld16s, { "r", "L", "L" } },
1120
    { INDEX_op_qemu_ld32u, { "r", "L", "L" } },
1121
    { INDEX_op_qemu_ld64, { "r", "r", "L", "L" } },
1122

    
1123
    { INDEX_op_qemu_st8, { "cb", "L", "L" } },
1124
    { INDEX_op_qemu_st16, { "L", "L", "L" } },
1125
    { INDEX_op_qemu_st32, { "L", "L", "L" } },
1126
    { INDEX_op_qemu_st64, { "L", "L", "L", "L" } },
1127
#endif
1128
    { -1 },
1129
};
1130

    
1131
static int tcg_target_callee_save_regs[] = {
1132
    /*    TCG_REG_EBP, */ /* currently used for the global env, so no
1133
                             need to save */
1134
    TCG_REG_EBX,
1135
    TCG_REG_ESI,
1136
    TCG_REG_EDI,
1137
};
1138

    
1139
static inline void tcg_out_push(TCGContext *s, int reg)
1140
{
1141
    tcg_out_opc(s, 0x50 + reg);
1142
}
1143

    
1144
static inline void tcg_out_pop(TCGContext *s, int reg)
1145
{
1146
    tcg_out_opc(s, 0x58 + reg);
1147
}
1148

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

    
1167
    tcg_out_modrm(s, 0xff, 4, TCG_REG_EAX); /* jmp *%eax */
1168
    
1169
    /* TB epilogue */
1170
    tb_ret_addr = s->code_ptr;
1171
    tcg_out_addi(s, TCG_REG_ESP, stack_addend);
1172
    for(i = ARRAY_SIZE(tcg_target_callee_save_regs) - 1; i >= 0; i--) {
1173
        tcg_out_pop(s, tcg_target_callee_save_regs[i]);
1174
    }
1175
    tcg_out8(s, 0xc3); /* ret */
1176
}
1177

    
1178
void tcg_target_init(TCGContext *s)
1179
{
1180
    /* fail safe */
1181
    if ((1 << CPU_TLB_ENTRY_BITS) != sizeof(CPUTLBEntry))
1182
        tcg_abort();
1183

    
1184
    tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xff);
1185
    tcg_regset_set32(tcg_target_call_clobber_regs, 0,
1186
                     (1 << TCG_REG_EAX) | 
1187
                     (1 << TCG_REG_EDX) | 
1188
                     (1 << TCG_REG_ECX));
1189
    
1190
    tcg_regset_clear(s->reserved_regs);
1191
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_ESP);
1192

    
1193
    tcg_add_target_add_op_defs(x86_op_defs);
1194
}