Statistics
| Branch: | Revision:

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

History | View | Annotate | Download (39.5 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_EBX,
40
    TCG_REG_ESI,
41
    TCG_REG_EDI,
42
    TCG_REG_EBP,
43
    TCG_REG_ECX,
44
    TCG_REG_EDX,
45
    TCG_REG_EAX,
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
    case R_386_PC8:
65
        value -= (long)code_ptr;
66
        if (value != (int8_t)value) {
67
            tcg_abort();
68
        }
69
        *(uint8_t *)code_ptr = value;
70
        break;
71
    default:
72
        tcg_abort();
73
    }
74
}
75

    
76
/* maximum number of register used for input function arguments */
77
static inline int tcg_target_get_call_iarg_regs_count(int flags)
78
{
79
    flags &= TCG_CALL_TYPE_MASK;
80
    switch(flags) {
81
    case TCG_CALL_TYPE_STD:
82
        return 0;
83
    case TCG_CALL_TYPE_REGPARM_1:
84
    case TCG_CALL_TYPE_REGPARM_2:
85
    case TCG_CALL_TYPE_REGPARM:
86
        return flags - TCG_CALL_TYPE_REGPARM_1 + 1;
87
    default:
88
        tcg_abort();
89
    }
90
}
91

    
92
/* parse target specific constraints */
93
static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
94
{
95
    const char *ct_str;
96

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

    
132
        /* qemu_ld/st address constraint */
133
    case 'L':
134
        ct->ct |= TCG_CT_REG;
135
        tcg_regset_set32(ct->u.regs, 0, 0xff);
136
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_EAX);
137
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_EDX);
138
        break;
139
    default:
140
        return -1;
141
    }
142
    ct_str++;
143
    *pct_str = ct_str;
144
    return 0;
145
}
146

    
147
/* test if a constant matches the constraint */
148
static inline int tcg_target_const_match(tcg_target_long val,
149
                                         const TCGArgConstraint *arg_ct)
150
{
151
    int ct;
152
    ct = arg_ct->ct;
153
    if (ct & TCG_CT_CONST)
154
        return 1;
155
    else
156
        return 0;
157
}
158

    
159
#define P_EXT   0x100 /* 0x0f opcode prefix */
160

    
161
#define OPC_BSWAP        (0xc8 | P_EXT)
162
#define OPC_MOVB_EvGv        (0x88)                /* stores, more or less */
163
#define OPC_MOVL_EvGv        (0x89)                /* stores, more or less */
164
#define OPC_MOVL_GvEv        (0x8b)                /* loads, more or less */
165
#define OPC_SHIFT_1        (0xd1)
166
#define OPC_SHIFT_Ib        (0xc1)
167
#define OPC_SHIFT_cl        (0xd3)
168

    
169
#define ARITH_ADD 0
170
#define ARITH_OR  1
171
#define ARITH_ADC 2
172
#define ARITH_SBB 3
173
#define ARITH_AND 4
174
#define ARITH_SUB 5
175
#define ARITH_XOR 6
176
#define ARITH_CMP 7
177

    
178
#define SHIFT_ROL 0
179
#define SHIFT_ROR 1
180
#define SHIFT_SHL 4
181
#define SHIFT_SHR 5
182
#define SHIFT_SAR 7
183

    
184
#define JCC_JMP (-1)
185
#define JCC_JO  0x0
186
#define JCC_JNO 0x1
187
#define JCC_JB  0x2
188
#define JCC_JAE 0x3
189
#define JCC_JE  0x4
190
#define JCC_JNE 0x5
191
#define JCC_JBE 0x6
192
#define JCC_JA  0x7
193
#define JCC_JS  0x8
194
#define JCC_JNS 0x9
195
#define JCC_JP  0xa
196
#define JCC_JNP 0xb
197
#define JCC_JL  0xc
198
#define JCC_JGE 0xd
199
#define JCC_JLE 0xe
200
#define JCC_JG  0xf
201

    
202
#define P_EXT   0x100 /* 0x0f opcode prefix */
203

    
204
static const uint8_t tcg_cond_to_jcc[10] = {
205
    [TCG_COND_EQ] = JCC_JE,
206
    [TCG_COND_NE] = JCC_JNE,
207
    [TCG_COND_LT] = JCC_JL,
208
    [TCG_COND_GE] = JCC_JGE,
209
    [TCG_COND_LE] = JCC_JLE,
210
    [TCG_COND_GT] = JCC_JG,
211
    [TCG_COND_LTU] = JCC_JB,
212
    [TCG_COND_GEU] = JCC_JAE,
213
    [TCG_COND_LEU] = JCC_JBE,
214
    [TCG_COND_GTU] = JCC_JA,
215
};
216

    
217
static inline void tcg_out_opc(TCGContext *s, int opc)
218
{
219
    if (opc & P_EXT)
220
        tcg_out8(s, 0x0f);
221
    tcg_out8(s, opc);
222
}
223

    
224
static inline void tcg_out_modrm(TCGContext *s, int opc, int r, int rm)
225
{
226
    tcg_out_opc(s, opc);
227
    tcg_out8(s, 0xc0 | (r << 3) | rm);
228
}
229

    
230
/* rm == -1 means no register index */
231
static inline void tcg_out_modrm_offset(TCGContext *s, int opc, int r, int rm, 
232
                                        int32_t offset)
233
{
234
    tcg_out_opc(s, opc);
235
    if (rm == -1) {
236
        tcg_out8(s, 0x05 | (r << 3));
237
        tcg_out32(s, offset);
238
    } else if (offset == 0 && rm != TCG_REG_EBP) {
239
        if (rm == TCG_REG_ESP) {
240
            tcg_out8(s, 0x04 | (r << 3));
241
            tcg_out8(s, 0x24);
242
        } else {
243
            tcg_out8(s, 0x00 | (r << 3) | rm);
244
        }
245
    } else if ((int8_t)offset == offset) {
246
        if (rm == TCG_REG_ESP) {
247
            tcg_out8(s, 0x44 | (r << 3));
248
            tcg_out8(s, 0x24);
249
        } else {
250
            tcg_out8(s, 0x40 | (r << 3) | rm);
251
        }
252
        tcg_out8(s, offset);
253
    } else {
254
        if (rm == TCG_REG_ESP) {
255
            tcg_out8(s, 0x84 | (r << 3));
256
            tcg_out8(s, 0x24);
257
        } else {
258
            tcg_out8(s, 0x80 | (r << 3) | rm);
259
        }
260
        tcg_out32(s, offset);
261
    }
262
}
263

    
264
static inline void tcg_out_mov(TCGContext *s, int ret, int arg)
265
{
266
    if (arg != ret) {
267
        tcg_out_modrm(s, OPC_MOVL_GvEv, ret, arg);
268
    }
269
}
270

    
271
static inline void tcg_out_movi(TCGContext *s, TCGType type,
272
                                int ret, int32_t arg)
273
{
274
    if (arg == 0) {
275
        /* xor r0,r0 */
276
        tcg_out_modrm(s, 0x01 | (ARITH_XOR << 3), ret, ret);
277
    } else {
278
        tcg_out8(s, 0xb8 + ret);
279
        tcg_out32(s, arg);
280
    }
281
}
282

    
283
static inline void tcg_out_ld(TCGContext *s, TCGType type, int ret,
284
                              int arg1, tcg_target_long arg2)
285
{
286
    tcg_out_modrm_offset(s, OPC_MOVL_GvEv, ret, arg1, arg2);
287
}
288

    
289
static inline void tcg_out_st(TCGContext *s, TCGType type, int arg,
290
                              int arg1, tcg_target_long arg2)
291
{
292
    tcg_out_modrm_offset(s, OPC_MOVL_EvGv, arg, arg1, arg2);
293
}
294

    
295
static void tcg_out_shifti(TCGContext *s, int subopc, int reg, int count)
296
{
297
    if (count == 1) {
298
        tcg_out_modrm(s, OPC_SHIFT_1, subopc, reg);
299
    } else {
300
        tcg_out_modrm(s, OPC_SHIFT_Ib, subopc, reg);
301
        tcg_out8(s, count);
302
    }
303
}
304

    
305
static inline void tcg_out_bswap32(TCGContext *s, int reg)
306
{
307
    tcg_out_opc(s, OPC_BSWAP + reg);
308
}
309

    
310
static inline void tcg_out_rolw_8(TCGContext *s, int reg)
311
{
312
    tcg_out8(s, 0x66);
313
    tcg_out_shifti(s, SHIFT_ROL, reg, 8);
314
}
315

    
316
static inline void tgen_arithi(TCGContext *s, int c, int r0, int32_t val, int cf)
317
{
318
    if (!cf && ((c == ARITH_ADD && val == 1) || (c == ARITH_SUB && val == -1))) {
319
        /* inc */
320
        tcg_out_opc(s, 0x40 + r0);
321
    } else if (!cf && ((c == ARITH_ADD && val == -1) || (c == ARITH_SUB && val == 1))) {
322
        /* dec */
323
        tcg_out_opc(s, 0x48 + r0);
324
    } else if (val == (int8_t)val) {
325
        tcg_out_modrm(s, 0x83, c, r0);
326
        tcg_out8(s, val);
327
    } else if (c == ARITH_AND && val == 0xffu && r0 < 4) {
328
        /* movzbl */
329
        tcg_out_modrm(s, 0xb6 | P_EXT, r0, r0);
330
    } else if (c == ARITH_AND && val == 0xffffu) {
331
        /* movzwl */
332
        tcg_out_modrm(s, 0xb7 | P_EXT, r0, r0);
333
    } else {
334
        tcg_out_modrm(s, 0x81, c, r0);
335
        tcg_out32(s, val);
336
    }
337
}
338

    
339
static void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
340
{
341
    if (val != 0)
342
        tgen_arithi(s, ARITH_ADD, reg, val, 0);
343
}
344

    
345
/* Use SMALL != 0 to force a short forward branch.  */
346
static void tcg_out_jxx(TCGContext *s, int opc, int label_index, int small)
347
{
348
    int32_t val, val1;
349
    TCGLabel *l = &s->labels[label_index];
350
    
351
    if (l->has_value) {
352
        val = l->u.value - (tcg_target_long)s->code_ptr;
353
        val1 = val - 2;
354
        if ((int8_t)val1 == val1) {
355
            if (opc == -1) {
356
                tcg_out8(s, 0xeb);
357
            } else {
358
                tcg_out8(s, 0x70 + opc);
359
            }
360
            tcg_out8(s, val1);
361
        } else {
362
            if (small) {
363
                tcg_abort();
364
            }
365
            if (opc == -1) {
366
                tcg_out8(s, 0xe9);
367
                tcg_out32(s, val - 5);
368
            } else {
369
                tcg_out8(s, 0x0f);
370
                tcg_out8(s, 0x80 + opc);
371
                tcg_out32(s, val - 6);
372
            }
373
        }
374
    } else if (small) {
375
        if (opc == -1) {
376
            tcg_out8(s, 0xeb);
377
        } else {
378
            tcg_out8(s, 0x70 + opc);
379
        }
380
        tcg_out_reloc(s, s->code_ptr, R_386_PC8, label_index, -1);
381
        s->code_ptr += 1;
382
    } else {
383
        if (opc == -1) {
384
            tcg_out8(s, 0xe9);
385
        } else {
386
            tcg_out8(s, 0x0f);
387
            tcg_out8(s, 0x80 + opc);
388
        }
389
        tcg_out_reloc(s, s->code_ptr, R_386_PC32, label_index, -4);
390
        s->code_ptr += 4;
391
    }
392
}
393

    
394
static void tcg_out_cmp(TCGContext *s, TCGArg arg1, TCGArg arg2,
395
                        int const_arg2)
396
{
397
    if (const_arg2) {
398
        if (arg2 == 0) {
399
            /* test r, r */
400
            tcg_out_modrm(s, 0x85, arg1, arg1);
401
        } else {
402
            tgen_arithi(s, ARITH_CMP, arg1, arg2, 0);
403
        }
404
    } else {
405
        tcg_out_modrm(s, 0x01 | (ARITH_CMP << 3), arg2, arg1);
406
    }
407
}
408

    
409
static void tcg_out_brcond(TCGContext *s, TCGCond cond,
410
                           TCGArg arg1, TCGArg arg2, int const_arg2,
411
                           int label_index, int small)
412
{
413
    tcg_out_cmp(s, arg1, arg2, const_arg2);
414
    tcg_out_jxx(s, tcg_cond_to_jcc[cond], label_index, small);
415
}
416

    
417
/* XXX: we implement it at the target level to avoid having to
418
   handle cross basic blocks temporaries */
419
static void tcg_out_brcond2(TCGContext *s, const TCGArg *args,
420
                            const int *const_args, int small)
421
{
422
    int label_next;
423
    label_next = gen_new_label();
424
    switch(args[4]) {
425
    case TCG_COND_EQ:
426
        tcg_out_brcond(s, TCG_COND_NE, args[0], args[2], const_args[2],
427
                       label_next, 1);
428
        tcg_out_brcond(s, TCG_COND_EQ, args[1], args[3], const_args[3],
429
                       args[5], small);
430
        break;
431
    case TCG_COND_NE:
432
        tcg_out_brcond(s, TCG_COND_NE, args[0], args[2], const_args[2],
433
                       args[5], small);
434
        tcg_out_brcond(s, TCG_COND_NE, args[1], args[3], const_args[3],
435
                       args[5], small);
436
        break;
437
    case TCG_COND_LT:
438
        tcg_out_brcond(s, TCG_COND_LT, args[1], args[3], const_args[3],
439
                       args[5], small);
440
        tcg_out_jxx(s, JCC_JNE, label_next, 1);
441
        tcg_out_brcond(s, TCG_COND_LTU, args[0], args[2], const_args[2],
442
                       args[5], small);
443
        break;
444
    case TCG_COND_LE:
445
        tcg_out_brcond(s, TCG_COND_LT, args[1], args[3], const_args[3],
446
                       args[5], small);
447
        tcg_out_jxx(s, JCC_JNE, label_next, 1);
448
        tcg_out_brcond(s, TCG_COND_LEU, args[0], args[2], const_args[2],
449
                       args[5], small);
450
        break;
451
    case TCG_COND_GT:
452
        tcg_out_brcond(s, TCG_COND_GT, args[1], args[3], const_args[3],
453
                       args[5], small);
454
        tcg_out_jxx(s, JCC_JNE, label_next, 1);
455
        tcg_out_brcond(s, TCG_COND_GTU, args[0], args[2], const_args[2],
456
                       args[5], small);
457
        break;
458
    case TCG_COND_GE:
459
        tcg_out_brcond(s, TCG_COND_GT, args[1], args[3], const_args[3],
460
                       args[5], small);
461
        tcg_out_jxx(s, JCC_JNE, label_next, 1);
462
        tcg_out_brcond(s, TCG_COND_GEU, args[0], args[2], const_args[2],
463
                       args[5], small);
464
        break;
465
    case TCG_COND_LTU:
466
        tcg_out_brcond(s, TCG_COND_LTU, args[1], args[3], const_args[3],
467
                       args[5], small);
468
        tcg_out_jxx(s, JCC_JNE, label_next, 1);
469
        tcg_out_brcond(s, TCG_COND_LTU, args[0], args[2], const_args[2],
470
                       args[5], small);
471
        break;
472
    case TCG_COND_LEU:
473
        tcg_out_brcond(s, TCG_COND_LTU, args[1], args[3], const_args[3],
474
                       args[5], small);
475
        tcg_out_jxx(s, JCC_JNE, label_next, 1);
476
        tcg_out_brcond(s, TCG_COND_LEU, args[0], args[2], const_args[2],
477
                       args[5], small);
478
        break;
479
    case TCG_COND_GTU:
480
        tcg_out_brcond(s, TCG_COND_GTU, args[1], args[3], const_args[3],
481
                       args[5], small);
482
        tcg_out_jxx(s, JCC_JNE, label_next, 1);
483
        tcg_out_brcond(s, TCG_COND_GTU, args[0], args[2], const_args[2],
484
                       args[5], small);
485
        break;
486
    case TCG_COND_GEU:
487
        tcg_out_brcond(s, TCG_COND_GTU, args[1], args[3], const_args[3],
488
                       args[5], small);
489
        tcg_out_jxx(s, JCC_JNE, label_next, 1);
490
        tcg_out_brcond(s, TCG_COND_GEU, args[0], args[2], const_args[2],
491
                       args[5], small);
492
        break;
493
    default:
494
        tcg_abort();
495
    }
496
    tcg_out_label(s, label_next, (tcg_target_long)s->code_ptr);
497
}
498

    
499
static void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGArg dest,
500
                            TCGArg arg1, TCGArg arg2, int const_arg2)
501
{
502
    tcg_out_cmp(s, arg1, arg2, const_arg2);
503
    /* setcc */
504
    tcg_out_modrm(s, 0x90 | tcg_cond_to_jcc[cond] | P_EXT, 0, dest);
505
    tgen_arithi(s, ARITH_AND, dest, 0xff, 0);
506
}
507

    
508
static void tcg_out_setcond2(TCGContext *s, const TCGArg *args,
509
                             const int *const_args)
510
{
511
    TCGArg new_args[6];
512
    int label_true, label_over;
513

    
514
    memcpy(new_args, args+1, 5*sizeof(TCGArg));
515

    
516
    if (args[0] == args[1] || args[0] == args[2]
517
        || (!const_args[3] && args[0] == args[3])
518
        || (!const_args[4] && args[0] == args[4])) {
519
        /* When the destination overlaps with one of the argument
520
           registers, don't do anything tricky.  */
521
        label_true = gen_new_label();
522
        label_over = gen_new_label();
523

    
524
        new_args[5] = label_true;
525
        tcg_out_brcond2(s, new_args, const_args+1, 1);
526

    
527
        tcg_out_movi(s, TCG_TYPE_I32, args[0], 0);
528
        tcg_out_jxx(s, JCC_JMP, label_over, 1);
529
        tcg_out_label(s, label_true, (tcg_target_long)s->code_ptr);
530

    
531
        tcg_out_movi(s, TCG_TYPE_I32, args[0], 1);
532
        tcg_out_label(s, label_over, (tcg_target_long)s->code_ptr);
533
    } else {
534
        /* When the destination does not overlap one of the arguments,
535
           clear the destination first, jump if cond false, and emit an
536
           increment in the true case.  This results in smaller code.  */
537

    
538
        tcg_out_movi(s, TCG_TYPE_I32, args[0], 0);
539

    
540
        label_over = gen_new_label();
541
        new_args[4] = tcg_invert_cond(new_args[4]);
542
        new_args[5] = label_over;
543
        tcg_out_brcond2(s, new_args, const_args+1, 1);
544

    
545
        tgen_arithi(s, ARITH_ADD, args[0], 1, 0);
546
        tcg_out_label(s, label_over, (tcg_target_long)s->code_ptr);
547
    }
548
}
549

    
550
#if defined(CONFIG_SOFTMMU)
551

    
552
#include "../../softmmu_defs.h"
553

    
554
static void *qemu_ld_helpers[4] = {
555
    __ldb_mmu,
556
    __ldw_mmu,
557
    __ldl_mmu,
558
    __ldq_mmu,
559
};
560

    
561
static void *qemu_st_helpers[4] = {
562
    __stb_mmu,
563
    __stw_mmu,
564
    __stl_mmu,
565
    __stq_mmu,
566
};
567
#endif
568

    
569
#ifndef CONFIG_USER_ONLY
570
#define GUEST_BASE 0
571
#endif
572

    
573
/* XXX: qemu_ld and qemu_st could be modified to clobber only EDX and
574
   EAX. It will be useful once fixed registers globals are less
575
   common. */
576
static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
577
                            int opc)
578
{
579
    int addr_reg, data_reg, data_reg2, r0, r1, mem_index, s_bits, bswap;
580
#if defined(CONFIG_SOFTMMU)
581
    uint8_t *label1_ptr, *label2_ptr;
582
#endif
583
#if TARGET_LONG_BITS == 64
584
#if defined(CONFIG_SOFTMMU)
585
    uint8_t *label3_ptr;
586
#endif
587
    int addr_reg2;
588
#endif
589

    
590
    data_reg = *args++;
591
    if (opc == 3)
592
        data_reg2 = *args++;
593
    else
594
        data_reg2 = 0;
595
    addr_reg = *args++;
596
#if TARGET_LONG_BITS == 64
597
    addr_reg2 = *args++;
598
#endif
599
    mem_index = *args;
600
    s_bits = opc & 3;
601

    
602
    r0 = TCG_REG_EAX;
603
    r1 = TCG_REG_EDX;
604

    
605
#if defined(CONFIG_SOFTMMU)
606
    tcg_out_mov(s, r1, addr_reg); 
607

    
608
    tcg_out_mov(s, r0, addr_reg); 
609
 
610
    tcg_out_shifti(s, SHIFT_SHR, r1, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
611

    
612
    tcg_out_modrm(s, 0x81, 4, r0); /* andl $x, r0 */
613
    tcg_out32(s, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
614
    
615
    tcg_out_modrm(s, 0x81, 4, r1); /* andl $x, r1 */
616
    tcg_out32(s, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
617

    
618
    tcg_out_opc(s, 0x8d); /* lea offset(r1, %ebp), r1 */
619
    tcg_out8(s, 0x80 | (r1 << 3) | 0x04);
620
    tcg_out8(s, (5 << 3) | r1);
621
    tcg_out32(s, offsetof(CPUState, tlb_table[mem_index][0].addr_read));
622

    
623
    /* cmp 0(r1), r0 */
624
    tcg_out_modrm_offset(s, 0x3b, r0, r1, 0);
625
    
626
    tcg_out_mov(s, r0, addr_reg);
627
    
628
#if TARGET_LONG_BITS == 32
629
    /* je label1 */
630
    tcg_out8(s, 0x70 + JCC_JE);
631
    label1_ptr = s->code_ptr;
632
    s->code_ptr++;
633
#else
634
    /* jne label3 */
635
    tcg_out8(s, 0x70 + JCC_JNE);
636
    label3_ptr = s->code_ptr;
637
    s->code_ptr++;
638
    
639
    /* cmp 4(r1), addr_reg2 */
640
    tcg_out_modrm_offset(s, 0x3b, addr_reg2, r1, 4);
641

    
642
    /* je label1 */
643
    tcg_out8(s, 0x70 + JCC_JE);
644
    label1_ptr = s->code_ptr;
645
    s->code_ptr++;
646
    
647
    /* label3: */
648
    *label3_ptr = s->code_ptr - label3_ptr - 1;
649
#endif
650

    
651
    /* XXX: move that code at the end of the TB */
652
#if TARGET_LONG_BITS == 32
653
    tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_EDX, mem_index);
654
#else
655
    tcg_out_mov(s, TCG_REG_EDX, addr_reg2);
656
    tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_ECX, mem_index);
657
#endif
658
    tcg_out8(s, 0xe8);
659
    tcg_out32(s, (tcg_target_long)qemu_ld_helpers[s_bits] - 
660
              (tcg_target_long)s->code_ptr - 4);
661

    
662
    switch(opc) {
663
    case 0 | 4:
664
        /* movsbl */
665
        tcg_out_modrm(s, 0xbe | P_EXT, data_reg, TCG_REG_EAX);
666
        break;
667
    case 1 | 4:
668
        /* movswl */
669
        tcg_out_modrm(s, 0xbf | P_EXT, data_reg, TCG_REG_EAX);
670
        break;
671
    case 0:
672
        /* movzbl */
673
        tcg_out_modrm(s, 0xb6 | P_EXT, data_reg, TCG_REG_EAX);
674
        break;
675
    case 1:
676
        /* movzwl */
677
        tcg_out_modrm(s, 0xb7 | P_EXT, data_reg, TCG_REG_EAX);
678
        break;
679
    case 2:
680
    default:
681
        tcg_out_mov(s, data_reg, TCG_REG_EAX);
682
        break;
683
    case 3:
684
        if (data_reg == TCG_REG_EDX) {
685
            tcg_out_opc(s, 0x90 + TCG_REG_EDX); /* xchg %edx, %eax */
686
            tcg_out_mov(s, data_reg2, TCG_REG_EAX);
687
        } else {
688
            tcg_out_mov(s, data_reg, TCG_REG_EAX);
689
            tcg_out_mov(s, data_reg2, TCG_REG_EDX);
690
        }
691
        break;
692
    }
693

    
694
    /* jmp label2 */
695
    tcg_out8(s, 0xeb);
696
    label2_ptr = s->code_ptr;
697
    s->code_ptr++;
698
    
699
    /* label1: */
700
    *label1_ptr = s->code_ptr - label1_ptr - 1;
701

    
702
    /* add x(r1), r0 */
703
    tcg_out_modrm_offset(s, 0x03, r0, r1, offsetof(CPUTLBEntry, addend) - 
704
                         offsetof(CPUTLBEntry, addr_read));
705
#else
706
    r0 = addr_reg;
707
#endif
708

    
709
#ifdef TARGET_WORDS_BIGENDIAN
710
    bswap = 1;
711
#else
712
    bswap = 0;
713
#endif
714
    switch(opc) {
715
    case 0:
716
        /* movzbl */
717
        tcg_out_modrm_offset(s, 0xb6 | P_EXT, data_reg, r0, GUEST_BASE);
718
        break;
719
    case 0 | 4:
720
        /* movsbl */
721
        tcg_out_modrm_offset(s, 0xbe | P_EXT, data_reg, r0, GUEST_BASE);
722
        break;
723
    case 1:
724
        /* movzwl */
725
        tcg_out_modrm_offset(s, 0xb7 | P_EXT, data_reg, r0, GUEST_BASE);
726
        if (bswap) {
727
            tcg_out_rolw_8(s, data_reg);
728
        }
729
        break;
730
    case 1 | 4:
731
        /* movswl */
732
        tcg_out_modrm_offset(s, 0xbf | P_EXT, data_reg, r0, GUEST_BASE);
733
        if (bswap) {
734
            tcg_out_rolw_8(s, data_reg);
735

    
736
            /* movswl data_reg, data_reg */
737
            tcg_out_modrm(s, 0xbf | P_EXT, data_reg, data_reg);
738
        }
739
        break;
740
    case 2:
741
        tcg_out_ld(s, TCG_TYPE_I32, data_reg, r0, GUEST_BASE);
742
        if (bswap) {
743
            tcg_out_bswap32(s, data_reg);
744
        }
745
        break;
746
    case 3:
747
        if (bswap) {
748
            int t = data_reg;
749
            data_reg = data_reg2;
750
            data_reg2 = t;
751
        }
752
        if (r0 != data_reg) {
753
            tcg_out_ld(s, TCG_TYPE_I32, data_reg, r0, GUEST_BASE);
754
            tcg_out_ld(s, TCG_TYPE_I32, data_reg2, r0, GUEST_BASE + 4);
755
        } else {
756
            tcg_out_ld(s, TCG_TYPE_I32, data_reg2, r0, GUEST_BASE + 4);
757
            tcg_out_ld(s, TCG_TYPE_I32, data_reg, r0, GUEST_BASE);
758
        }
759
        if (bswap) {
760
            tcg_out_bswap32(s, data_reg);
761
            tcg_out_bswap32(s, data_reg2);
762
        }
763
        break;
764
    default:
765
        tcg_abort();
766
    }
767

    
768
#if defined(CONFIG_SOFTMMU)
769
    /* label2: */
770
    *label2_ptr = s->code_ptr - label2_ptr - 1;
771
#endif
772
}
773

    
774

    
775
static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
776
                            int opc)
777
{
778
    int addr_reg, data_reg, data_reg2, r0, r1, mem_index, s_bits, bswap;
779
#if defined(CONFIG_SOFTMMU)
780
    uint8_t *label1_ptr, *label2_ptr;
781
#endif
782
#if TARGET_LONG_BITS == 64
783
#if defined(CONFIG_SOFTMMU)
784
    uint8_t *label3_ptr;
785
#endif
786
    int addr_reg2;
787
#endif
788

    
789
    data_reg = *args++;
790
    if (opc == 3)
791
        data_reg2 = *args++;
792
    else
793
        data_reg2 = 0;
794
    addr_reg = *args++;
795
#if TARGET_LONG_BITS == 64
796
    addr_reg2 = *args++;
797
#endif
798
    mem_index = *args;
799

    
800
    s_bits = opc;
801

    
802
    r0 = TCG_REG_EAX;
803
    r1 = TCG_REG_EDX;
804

    
805
#if defined(CONFIG_SOFTMMU)
806
    tcg_out_mov(s, r1, addr_reg); 
807

    
808
    tcg_out_mov(s, r0, addr_reg); 
809
 
810
    tcg_out_shifti(s, SHIFT_SHR, r1, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
811

    
812
    tcg_out_modrm(s, 0x81, 4, r0); /* andl $x, r0 */
813
    tcg_out32(s, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
814
    
815
    tcg_out_modrm(s, 0x81, 4, r1); /* andl $x, r1 */
816
    tcg_out32(s, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
817

    
818
    tcg_out_opc(s, 0x8d); /* lea offset(r1, %ebp), r1 */
819
    tcg_out8(s, 0x80 | (r1 << 3) | 0x04);
820
    tcg_out8(s, (5 << 3) | r1);
821
    tcg_out32(s, offsetof(CPUState, tlb_table[mem_index][0].addr_write));
822

    
823
    /* cmp 0(r1), r0 */
824
    tcg_out_modrm_offset(s, 0x3b, r0, r1, 0);
825
    
826
    tcg_out_mov(s, r0, addr_reg);
827
    
828
#if TARGET_LONG_BITS == 32
829
    /* je label1 */
830
    tcg_out8(s, 0x70 + JCC_JE);
831
    label1_ptr = s->code_ptr;
832
    s->code_ptr++;
833
#else
834
    /* jne label3 */
835
    tcg_out8(s, 0x70 + JCC_JNE);
836
    label3_ptr = s->code_ptr;
837
    s->code_ptr++;
838
    
839
    /* cmp 4(r1), addr_reg2 */
840
    tcg_out_modrm_offset(s, 0x3b, addr_reg2, r1, 4);
841

    
842
    /* je label1 */
843
    tcg_out8(s, 0x70 + JCC_JE);
844
    label1_ptr = s->code_ptr;
845
    s->code_ptr++;
846
    
847
    /* label3: */
848
    *label3_ptr = s->code_ptr - label3_ptr - 1;
849
#endif
850

    
851
    /* XXX: move that code at the end of the TB */
852
#if TARGET_LONG_BITS == 32
853
    if (opc == 3) {
854
        tcg_out_mov(s, TCG_REG_EDX, data_reg);
855
        tcg_out_mov(s, TCG_REG_ECX, data_reg2);
856
        tcg_out8(s, 0x6a); /* push Ib */
857
        tcg_out8(s, mem_index);
858
        tcg_out8(s, 0xe8);
859
        tcg_out32(s, (tcg_target_long)qemu_st_helpers[s_bits] - 
860
                  (tcg_target_long)s->code_ptr - 4);
861
        tcg_out_addi(s, TCG_REG_ESP, 4);
862
    } else {
863
        switch(opc) {
864
        case 0:
865
            /* movzbl */
866
            tcg_out_modrm(s, 0xb6 | P_EXT, TCG_REG_EDX, data_reg);
867
            break;
868
        case 1:
869
            /* movzwl */
870
            tcg_out_modrm(s, 0xb7 | P_EXT, TCG_REG_EDX, data_reg);
871
            break;
872
        case 2:
873
            tcg_out_mov(s, TCG_REG_EDX, data_reg);
874
            break;
875
        }
876
        tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_ECX, mem_index);
877
        tcg_out8(s, 0xe8);
878
        tcg_out32(s, (tcg_target_long)qemu_st_helpers[s_bits] - 
879
                  (tcg_target_long)s->code_ptr - 4);
880
    }
881
#else
882
    if (opc == 3) {
883
        tcg_out_mov(s, TCG_REG_EDX, addr_reg2);
884
        tcg_out8(s, 0x6a); /* push Ib */
885
        tcg_out8(s, mem_index);
886
        tcg_out_opc(s, 0x50 + data_reg2); /* push */
887
        tcg_out_opc(s, 0x50 + data_reg); /* push */
888
        tcg_out8(s, 0xe8);
889
        tcg_out32(s, (tcg_target_long)qemu_st_helpers[s_bits] - 
890
                  (tcg_target_long)s->code_ptr - 4);
891
        tcg_out_addi(s, TCG_REG_ESP, 12);
892
    } else {
893
        tcg_out_mov(s, TCG_REG_EDX, addr_reg2);
894
        switch(opc) {
895
        case 0:
896
            /* movzbl */
897
            tcg_out_modrm(s, 0xb6 | P_EXT, TCG_REG_ECX, data_reg);
898
            break;
899
        case 1:
900
            /* movzwl */
901
            tcg_out_modrm(s, 0xb7 | P_EXT, TCG_REG_ECX, data_reg);
902
            break;
903
        case 2:
904
            tcg_out_mov(s, TCG_REG_ECX, data_reg);
905
            break;
906
        }
907
        tcg_out8(s, 0x6a); /* push Ib */
908
        tcg_out8(s, mem_index);
909
        tcg_out8(s, 0xe8);
910
        tcg_out32(s, (tcg_target_long)qemu_st_helpers[s_bits] - 
911
                  (tcg_target_long)s->code_ptr - 4);
912
        tcg_out_addi(s, TCG_REG_ESP, 4);
913
    }
914
#endif
915
    
916
    /* jmp label2 */
917
    tcg_out8(s, 0xeb);
918
    label2_ptr = s->code_ptr;
919
    s->code_ptr++;
920
    
921
    /* label1: */
922
    *label1_ptr = s->code_ptr - label1_ptr - 1;
923

    
924
    /* add x(r1), r0 */
925
    tcg_out_modrm_offset(s, 0x03, r0, r1, offsetof(CPUTLBEntry, addend) - 
926
                         offsetof(CPUTLBEntry, addr_write));
927
#else
928
    r0 = addr_reg;
929
#endif
930

    
931
#ifdef TARGET_WORDS_BIGENDIAN
932
    bswap = 1;
933
#else
934
    bswap = 0;
935
#endif
936
    switch(opc) {
937
    case 0:
938
        tcg_out_modrm_offset(s, OPC_MOVB_EvGv, data_reg, r0, GUEST_BASE);
939
        break;
940
    case 1:
941
        if (bswap) {
942
            tcg_out_mov(s, r1, data_reg);
943
            tcg_out_rolw_8(s, r1);
944
            data_reg = r1;
945
        }
946
        /* movw */
947
        tcg_out8(s, 0x66);
948
        tcg_out_modrm_offset(s, OPC_MOVL_EvGv, data_reg, r0, GUEST_BASE);
949
        break;
950
    case 2:
951
        if (bswap) {
952
            tcg_out_mov(s, r1, data_reg);
953
            tcg_out_bswap32(s, r1);
954
            data_reg = r1;
955
        }
956
        tcg_out_st(s, TCG_TYPE_I32, data_reg, r0, GUEST_BASE);
957
        break;
958
    case 3:
959
        if (bswap) {
960
            tcg_out_mov(s, r1, data_reg2);
961
            tcg_out_bswap32(s, r1);
962
            tcg_out_st(s, TCG_TYPE_I32, r1, r0, GUEST_BASE);
963
            tcg_out_mov(s, r1, data_reg);
964
            tcg_out_bswap32(s, r1);
965
            tcg_out_st(s, TCG_TYPE_I32, r1, r0, GUEST_BASE + 4);
966
        } else {
967
            tcg_out_st(s, TCG_TYPE_I32, data_reg, r0, GUEST_BASE);
968
            tcg_out_st(s, TCG_TYPE_I32, data_reg2, r0, GUEST_BASE + 4);
969
        }
970
        break;
971
    default:
972
        tcg_abort();
973
    }
974

    
975
#if defined(CONFIG_SOFTMMU)
976
    /* label2: */
977
    *label2_ptr = s->code_ptr - label2_ptr - 1;
978
#endif
979
}
980

    
981
static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
982
                              const TCGArg *args, const int *const_args)
983
{
984
    int c;
985
    
986
    switch(opc) {
987
    case INDEX_op_exit_tb:
988
        tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_EAX, args[0]);
989
        tcg_out8(s, 0xe9); /* jmp tb_ret_addr */
990
        tcg_out32(s, tb_ret_addr - s->code_ptr - 4);
991
        break;
992
    case INDEX_op_goto_tb:
993
        if (s->tb_jmp_offset) {
994
            /* direct jump method */
995
            tcg_out8(s, 0xe9); /* jmp im */
996
            s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
997
            tcg_out32(s, 0);
998
        } else {
999
            /* indirect jump method */
1000
            /* jmp Ev */
1001
            tcg_out_modrm_offset(s, 0xff, 4, -1, 
1002
                                 (tcg_target_long)(s->tb_next + args[0]));
1003
        }
1004
        s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
1005
        break;
1006
    case INDEX_op_call:
1007
        if (const_args[0]) {
1008
            tcg_out8(s, 0xe8);
1009
            tcg_out32(s, args[0] - (tcg_target_long)s->code_ptr - 4);
1010
        } else {
1011
            tcg_out_modrm(s, 0xff, 2, args[0]);
1012
        }
1013
        break;
1014
    case INDEX_op_jmp:
1015
        if (const_args[0]) {
1016
            tcg_out8(s, 0xe9);
1017
            tcg_out32(s, args[0] - (tcg_target_long)s->code_ptr - 4);
1018
        } else {
1019
            tcg_out_modrm(s, 0xff, 4, args[0]);
1020
        }
1021
        break;
1022
    case INDEX_op_br:
1023
        tcg_out_jxx(s, JCC_JMP, args[0], 0);
1024
        break;
1025
    case INDEX_op_movi_i32:
1026
        tcg_out_movi(s, TCG_TYPE_I32, args[0], args[1]);
1027
        break;
1028
    case INDEX_op_ld8u_i32:
1029
        /* movzbl */
1030
        tcg_out_modrm_offset(s, 0xb6 | P_EXT, args[0], args[1], args[2]);
1031
        break;
1032
    case INDEX_op_ld8s_i32:
1033
        /* movsbl */
1034
        tcg_out_modrm_offset(s, 0xbe | P_EXT, args[0], args[1], args[2]);
1035
        break;
1036
    case INDEX_op_ld16u_i32:
1037
        /* movzwl */
1038
        tcg_out_modrm_offset(s, 0xb7 | P_EXT, args[0], args[1], args[2]);
1039
        break;
1040
    case INDEX_op_ld16s_i32:
1041
        /* movswl */
1042
        tcg_out_modrm_offset(s, 0xbf | P_EXT, args[0], args[1], args[2]);
1043
        break;
1044
    case INDEX_op_ld_i32:
1045
        tcg_out_ld(s, TCG_TYPE_I32, args[0], args[1], args[2]);
1046
        break;
1047
    case INDEX_op_st8_i32:
1048
        /* movb */
1049
        tcg_out_modrm_offset(s, OPC_MOVB_EvGv, args[0], args[1], args[2]);
1050
        break;
1051
    case INDEX_op_st16_i32:
1052
        /* movw */
1053
        tcg_out8(s, 0x66);
1054
        tcg_out_modrm_offset(s, OPC_MOVL_EvGv, args[0], args[1], args[2]);
1055
        break;
1056
    case INDEX_op_st_i32:
1057
        tcg_out_st(s, TCG_TYPE_I32, args[0], args[1], args[2]);
1058
        break;
1059
    case INDEX_op_sub_i32:
1060
        c = ARITH_SUB;
1061
        goto gen_arith;
1062
    case INDEX_op_and_i32:
1063
        c = ARITH_AND;
1064
        goto gen_arith;
1065
    case INDEX_op_or_i32:
1066
        c = ARITH_OR;
1067
        goto gen_arith;
1068
    case INDEX_op_xor_i32:
1069
        c = ARITH_XOR;
1070
        goto gen_arith;
1071
    case INDEX_op_add_i32:
1072
        c = ARITH_ADD;
1073
    gen_arith:
1074
        if (const_args[2]) {
1075
            tgen_arithi(s, c, args[0], args[2], 0);
1076
        } else {
1077
            tcg_out_modrm(s, 0x01 | (c << 3), args[2], args[0]);
1078
        }
1079
        break;
1080
    case INDEX_op_mul_i32:
1081
        if (const_args[2]) {
1082
            int32_t val;
1083
            val = args[2];
1084
            if (val == (int8_t)val) {
1085
                tcg_out_modrm(s, 0x6b, args[0], args[0]);
1086
                tcg_out8(s, val);
1087
            } else {
1088
                tcg_out_modrm(s, 0x69, args[0], args[0]);
1089
                tcg_out32(s, val);
1090
            }
1091
        } else {
1092
            tcg_out_modrm(s, 0xaf | P_EXT, args[0], args[2]);
1093
        }
1094
        break;
1095
    case INDEX_op_mulu2_i32:
1096
        tcg_out_modrm(s, 0xf7, 4, args[3]);
1097
        break;
1098
    case INDEX_op_div2_i32:
1099
        tcg_out_modrm(s, 0xf7, 7, args[4]);
1100
        break;
1101
    case INDEX_op_divu2_i32:
1102
        tcg_out_modrm(s, 0xf7, 6, args[4]);
1103
        break;
1104
    case INDEX_op_shl_i32:
1105
        c = SHIFT_SHL;
1106
    gen_shift32:
1107
        if (const_args[2]) {
1108
            tcg_out_shifti(s, c, args[0], args[2]);
1109
        } else {
1110
            tcg_out_modrm(s, OPC_SHIFT_cl, c, args[0]);
1111
        }
1112
        break;
1113
    case INDEX_op_shr_i32:
1114
        c = SHIFT_SHR;
1115
        goto gen_shift32;
1116
    case INDEX_op_sar_i32:
1117
        c = SHIFT_SAR;
1118
        goto gen_shift32;
1119
    case INDEX_op_rotl_i32:
1120
        c = SHIFT_ROL;
1121
        goto gen_shift32;
1122
    case INDEX_op_rotr_i32:
1123
        c = SHIFT_ROR;
1124
        goto gen_shift32;
1125

    
1126
    case INDEX_op_add2_i32:
1127
        if (const_args[4]) 
1128
            tgen_arithi(s, ARITH_ADD, args[0], args[4], 1);
1129
        else
1130
            tcg_out_modrm(s, 0x01 | (ARITH_ADD << 3), args[4], args[0]);
1131
        if (const_args[5]) 
1132
            tgen_arithi(s, ARITH_ADC, args[1], args[5], 1);
1133
        else
1134
            tcg_out_modrm(s, 0x01 | (ARITH_ADC << 3), args[5], args[1]);
1135
        break;
1136
    case INDEX_op_sub2_i32:
1137
        if (const_args[4]) 
1138
            tgen_arithi(s, ARITH_SUB, args[0], args[4], 1);
1139
        else
1140
            tcg_out_modrm(s, 0x01 | (ARITH_SUB << 3), args[4], args[0]);
1141
        if (const_args[5]) 
1142
            tgen_arithi(s, ARITH_SBB, args[1], args[5], 1);
1143
        else
1144
            tcg_out_modrm(s, 0x01 | (ARITH_SBB << 3), args[5], args[1]);
1145
        break;
1146
    case INDEX_op_brcond_i32:
1147
        tcg_out_brcond(s, args[2], args[0], args[1], const_args[1],
1148
                       args[3], 0);
1149
        break;
1150
    case INDEX_op_brcond2_i32:
1151
        tcg_out_brcond2(s, args, const_args, 0);
1152
        break;
1153

    
1154
    case INDEX_op_bswap16_i32:
1155
        tcg_out_rolw_8(s, args[0]);
1156
        break;
1157
    case INDEX_op_bswap32_i32:
1158
        tcg_out_bswap32(s, args[0]);
1159
        break;
1160

    
1161
    case INDEX_op_neg_i32:
1162
        tcg_out_modrm(s, 0xf7, 3, args[0]);
1163
        break;
1164

    
1165
    case INDEX_op_not_i32:
1166
        tcg_out_modrm(s, 0xf7, 2, args[0]);
1167
        break;
1168

    
1169
    case INDEX_op_ext8s_i32:
1170
        tcg_out_modrm(s, 0xbe | P_EXT, args[0], args[1]);
1171
        break;
1172
    case INDEX_op_ext16s_i32:
1173
        tcg_out_modrm(s, 0xbf | P_EXT, args[0], args[1]);
1174
        break;
1175
    case INDEX_op_ext8u_i32:
1176
        tcg_out_modrm(s, 0xb6 | P_EXT, args[0], args[1]);
1177
        break;
1178
    case INDEX_op_ext16u_i32:
1179
        tcg_out_modrm(s, 0xb7 | P_EXT, args[0], args[1]);
1180
        break;
1181

    
1182
    case INDEX_op_setcond_i32:
1183
        tcg_out_setcond(s, args[3], args[0], args[1], args[2], const_args[2]);
1184
        break;
1185
    case INDEX_op_setcond2_i32:
1186
        tcg_out_setcond2(s, args, const_args);
1187
        break;
1188

    
1189
    case INDEX_op_qemu_ld8u:
1190
        tcg_out_qemu_ld(s, args, 0);
1191
        break;
1192
    case INDEX_op_qemu_ld8s:
1193
        tcg_out_qemu_ld(s, args, 0 | 4);
1194
        break;
1195
    case INDEX_op_qemu_ld16u:
1196
        tcg_out_qemu_ld(s, args, 1);
1197
        break;
1198
    case INDEX_op_qemu_ld16s:
1199
        tcg_out_qemu_ld(s, args, 1 | 4);
1200
        break;
1201
    case INDEX_op_qemu_ld32:
1202
        tcg_out_qemu_ld(s, args, 2);
1203
        break;
1204
    case INDEX_op_qemu_ld64:
1205
        tcg_out_qemu_ld(s, args, 3);
1206
        break;
1207
        
1208
    case INDEX_op_qemu_st8:
1209
        tcg_out_qemu_st(s, args, 0);
1210
        break;
1211
    case INDEX_op_qemu_st16:
1212
        tcg_out_qemu_st(s, args, 1);
1213
        break;
1214
    case INDEX_op_qemu_st32:
1215
        tcg_out_qemu_st(s, args, 2);
1216
        break;
1217
    case INDEX_op_qemu_st64:
1218
        tcg_out_qemu_st(s, args, 3);
1219
        break;
1220

    
1221
    default:
1222
        tcg_abort();
1223
    }
1224
}
1225

    
1226
static const TCGTargetOpDef x86_op_defs[] = {
1227
    { INDEX_op_exit_tb, { } },
1228
    { INDEX_op_goto_tb, { } },
1229
    { INDEX_op_call, { "ri" } },
1230
    { INDEX_op_jmp, { "ri" } },
1231
    { INDEX_op_br, { } },
1232
    { INDEX_op_mov_i32, { "r", "r" } },
1233
    { INDEX_op_movi_i32, { "r" } },
1234
    { INDEX_op_ld8u_i32, { "r", "r" } },
1235
    { INDEX_op_ld8s_i32, { "r", "r" } },
1236
    { INDEX_op_ld16u_i32, { "r", "r" } },
1237
    { INDEX_op_ld16s_i32, { "r", "r" } },
1238
    { INDEX_op_ld_i32, { "r", "r" } },
1239
    { INDEX_op_st8_i32, { "q", "r" } },
1240
    { INDEX_op_st16_i32, { "r", "r" } },
1241
    { INDEX_op_st_i32, { "r", "r" } },
1242

    
1243
    { INDEX_op_add_i32, { "r", "0", "ri" } },
1244
    { INDEX_op_sub_i32, { "r", "0", "ri" } },
1245
    { INDEX_op_mul_i32, { "r", "0", "ri" } },
1246
    { INDEX_op_mulu2_i32, { "a", "d", "a", "r" } },
1247
    { INDEX_op_div2_i32, { "a", "d", "0", "1", "r" } },
1248
    { INDEX_op_divu2_i32, { "a", "d", "0", "1", "r" } },
1249
    { INDEX_op_and_i32, { "r", "0", "ri" } },
1250
    { INDEX_op_or_i32, { "r", "0", "ri" } },
1251
    { INDEX_op_xor_i32, { "r", "0", "ri" } },
1252

    
1253
    { INDEX_op_shl_i32, { "r", "0", "ci" } },
1254
    { INDEX_op_shr_i32, { "r", "0", "ci" } },
1255
    { INDEX_op_sar_i32, { "r", "0", "ci" } },
1256
    { INDEX_op_rotl_i32, { "r", "0", "ci" } },
1257
    { INDEX_op_rotr_i32, { "r", "0", "ci" } },
1258

    
1259
    { INDEX_op_brcond_i32, { "r", "ri" } },
1260

    
1261
    { INDEX_op_add2_i32, { "r", "r", "0", "1", "ri", "ri" } },
1262
    { INDEX_op_sub2_i32, { "r", "r", "0", "1", "ri", "ri" } },
1263
    { INDEX_op_brcond2_i32, { "r", "r", "ri", "ri" } },
1264

    
1265
    { INDEX_op_bswap16_i32, { "r", "0" } },
1266
    { INDEX_op_bswap32_i32, { "r", "0" } },
1267

    
1268
    { INDEX_op_neg_i32, { "r", "0" } },
1269

    
1270
    { INDEX_op_not_i32, { "r", "0" } },
1271

    
1272
    { INDEX_op_ext8s_i32, { "r", "q" } },
1273
    { INDEX_op_ext16s_i32, { "r", "r" } },
1274
    { INDEX_op_ext8u_i32, { "r", "q"} },
1275
    { INDEX_op_ext16u_i32, { "r", "r"} },
1276

    
1277
    { INDEX_op_setcond_i32, { "q", "r", "ri" } },
1278
    { INDEX_op_setcond2_i32, { "r", "r", "r", "ri", "ri" } },
1279

    
1280
#if TARGET_LONG_BITS == 32
1281
    { INDEX_op_qemu_ld8u, { "r", "L" } },
1282
    { INDEX_op_qemu_ld8s, { "r", "L" } },
1283
    { INDEX_op_qemu_ld16u, { "r", "L" } },
1284
    { INDEX_op_qemu_ld16s, { "r", "L" } },
1285
    { INDEX_op_qemu_ld32, { "r", "L" } },
1286
    { INDEX_op_qemu_ld64, { "r", "r", "L" } },
1287

    
1288
    { INDEX_op_qemu_st8, { "cb", "L" } },
1289
    { INDEX_op_qemu_st16, { "L", "L" } },
1290
    { INDEX_op_qemu_st32, { "L", "L" } },
1291
    { INDEX_op_qemu_st64, { "L", "L", "L" } },
1292
#else
1293
    { INDEX_op_qemu_ld8u, { "r", "L", "L" } },
1294
    { INDEX_op_qemu_ld8s, { "r", "L", "L" } },
1295
    { INDEX_op_qemu_ld16u, { "r", "L", "L" } },
1296
    { INDEX_op_qemu_ld16s, { "r", "L", "L" } },
1297
    { INDEX_op_qemu_ld32, { "r", "L", "L" } },
1298
    { INDEX_op_qemu_ld64, { "r", "r", "L", "L" } },
1299

    
1300
    { INDEX_op_qemu_st8, { "cb", "L", "L" } },
1301
    { INDEX_op_qemu_st16, { "L", "L", "L" } },
1302
    { INDEX_op_qemu_st32, { "L", "L", "L" } },
1303
    { INDEX_op_qemu_st64, { "L", "L", "L", "L" } },
1304
#endif
1305
    { -1 },
1306
};
1307

    
1308
static int tcg_target_callee_save_regs[] = {
1309
    /*    TCG_REG_EBP, */ /* currently used for the global env, so no
1310
                             need to save */
1311
    TCG_REG_EBX,
1312
    TCG_REG_ESI,
1313
    TCG_REG_EDI,
1314
};
1315

    
1316
static inline void tcg_out_push(TCGContext *s, int reg)
1317
{
1318
    tcg_out_opc(s, 0x50 + reg);
1319
}
1320

    
1321
static inline void tcg_out_pop(TCGContext *s, int reg)
1322
{
1323
    tcg_out_opc(s, 0x58 + reg);
1324
}
1325

    
1326
/* Generate global QEMU prologue and epilogue code */
1327
void tcg_target_qemu_prologue(TCGContext *s)
1328
{
1329
    int i, frame_size, push_size, stack_addend;
1330
    
1331
    /* TB prologue */
1332
    /* save all callee saved registers */
1333
    for(i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
1334
        tcg_out_push(s, tcg_target_callee_save_regs[i]);
1335
    }
1336
    /* reserve some stack space */
1337
    push_size = 4 + ARRAY_SIZE(tcg_target_callee_save_regs) * 4;
1338
    frame_size = push_size + TCG_STATIC_CALL_ARGS_SIZE;
1339
    frame_size = (frame_size + TCG_TARGET_STACK_ALIGN - 1) & 
1340
        ~(TCG_TARGET_STACK_ALIGN - 1);
1341
    stack_addend = frame_size - push_size;
1342
    tcg_out_addi(s, TCG_REG_ESP, -stack_addend);
1343

    
1344
    tcg_out_modrm(s, 0xff, 4, TCG_REG_EAX); /* jmp *%eax */
1345
    
1346
    /* TB epilogue */
1347
    tb_ret_addr = s->code_ptr;
1348
    tcg_out_addi(s, TCG_REG_ESP, stack_addend);
1349
    for(i = ARRAY_SIZE(tcg_target_callee_save_regs) - 1; i >= 0; i--) {
1350
        tcg_out_pop(s, tcg_target_callee_save_regs[i]);
1351
    }
1352
    tcg_out8(s, 0xc3); /* ret */
1353
}
1354

    
1355
void tcg_target_init(TCGContext *s)
1356
{
1357
#if !defined(CONFIG_USER_ONLY)
1358
    /* fail safe */
1359
    if ((1 << CPU_TLB_ENTRY_BITS) != sizeof(CPUTLBEntry))
1360
        tcg_abort();
1361
#endif
1362

    
1363
    tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xff);
1364

    
1365
    tcg_regset_clear(tcg_target_call_clobber_regs);
1366
    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_EAX);
1367
    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_EDX);
1368
    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_ECX);
1369

    
1370
    tcg_regset_clear(s->reserved_regs);
1371
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_ESP);
1372

    
1373
    tcg_add_target_add_op_defs(x86_op_defs);
1374
}