Statistics
| Branch: | Revision:

root / tcg / i386 / tcg-target.c @ 1d2699ae

History | View | Annotate | Download (39.6 kB)

1 c896fe29 bellard
/*
2 c896fe29 bellard
 * Tiny Code Generator for QEMU
3 c896fe29 bellard
 *
4 c896fe29 bellard
 * Copyright (c) 2008 Fabrice Bellard
5 c896fe29 bellard
 *
6 c896fe29 bellard
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 c896fe29 bellard
 * of this software and associated documentation files (the "Software"), to deal
8 c896fe29 bellard
 * in the Software without restriction, including without limitation the rights
9 c896fe29 bellard
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 c896fe29 bellard
 * copies of the Software, and to permit persons to whom the Software is
11 c896fe29 bellard
 * furnished to do so, subject to the following conditions:
12 c896fe29 bellard
 *
13 c896fe29 bellard
 * The above copyright notice and this permission notice shall be included in
14 c896fe29 bellard
 * all copies or substantial portions of the Software.
15 c896fe29 bellard
 *
16 c896fe29 bellard
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 c896fe29 bellard
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 c896fe29 bellard
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 c896fe29 bellard
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 c896fe29 bellard
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 c896fe29 bellard
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 c896fe29 bellard
 * THE SOFTWARE.
23 c896fe29 bellard
 */
24 d4a9eb1f blueswir1
25 d4a9eb1f blueswir1
#ifndef NDEBUG
26 d4a9eb1f blueswir1
static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
27 c896fe29 bellard
    "%eax",
28 c896fe29 bellard
    "%ecx",
29 c896fe29 bellard
    "%edx",
30 c896fe29 bellard
    "%ebx",
31 c896fe29 bellard
    "%esp",
32 c896fe29 bellard
    "%ebp",
33 c896fe29 bellard
    "%esi",
34 c896fe29 bellard
    "%edi",
35 c896fe29 bellard
};
36 d4a9eb1f blueswir1
#endif
37 c896fe29 bellard
38 d4a9eb1f blueswir1
static const int tcg_target_reg_alloc_order[] = {
39 c896fe29 bellard
    TCG_REG_EAX,
40 c896fe29 bellard
    TCG_REG_EDX,
41 c896fe29 bellard
    TCG_REG_ECX,
42 c896fe29 bellard
    TCG_REG_EBX,
43 c896fe29 bellard
    TCG_REG_ESI,
44 c896fe29 bellard
    TCG_REG_EDI,
45 c896fe29 bellard
    TCG_REG_EBP,
46 c896fe29 bellard
};
47 c896fe29 bellard
48 d4a9eb1f blueswir1
static const int tcg_target_call_iarg_regs[3] = { TCG_REG_EAX, TCG_REG_EDX, TCG_REG_ECX };
49 d4a9eb1f blueswir1
static const int tcg_target_call_oarg_regs[2] = { TCG_REG_EAX, TCG_REG_EDX };
50 c896fe29 bellard
51 b03cce8e bellard
static uint8_t *tb_ret_addr;
52 b03cce8e bellard
53 c896fe29 bellard
static void patch_reloc(uint8_t *code_ptr, int type, 
54 f54b3f92 aurel32
                        tcg_target_long value, tcg_target_long addend)
55 c896fe29 bellard
{
56 f54b3f92 aurel32
    value += addend;
57 c896fe29 bellard
    switch(type) {
58 c896fe29 bellard
    case R_386_32:
59 c896fe29 bellard
        *(uint32_t *)code_ptr = value;
60 c896fe29 bellard
        break;
61 c896fe29 bellard
    case R_386_PC32:
62 c896fe29 bellard
        *(uint32_t *)code_ptr = value - (long)code_ptr;
63 c896fe29 bellard
        break;
64 f75b56c1 Richard Henderson
    case R_386_PC8:
65 f75b56c1 Richard Henderson
        value -= (long)code_ptr;
66 f75b56c1 Richard Henderson
        if (value != (int8_t)value) {
67 f75b56c1 Richard Henderson
            tcg_abort();
68 f75b56c1 Richard Henderson
        }
69 f75b56c1 Richard Henderson
        *(uint8_t *)code_ptr = value;
70 f75b56c1 Richard Henderson
        break;
71 c896fe29 bellard
    default:
72 c896fe29 bellard
        tcg_abort();
73 c896fe29 bellard
    }
74 c896fe29 bellard
}
75 c896fe29 bellard
76 c896fe29 bellard
/* maximum number of register used for input function arguments */
77 c896fe29 bellard
static inline int tcg_target_get_call_iarg_regs_count(int flags)
78 c896fe29 bellard
{
79 c896fe29 bellard
    flags &= TCG_CALL_TYPE_MASK;
80 c896fe29 bellard
    switch(flags) {
81 c896fe29 bellard
    case TCG_CALL_TYPE_STD:
82 c896fe29 bellard
        return 0;
83 c896fe29 bellard
    case TCG_CALL_TYPE_REGPARM_1:
84 c896fe29 bellard
    case TCG_CALL_TYPE_REGPARM_2:
85 c896fe29 bellard
    case TCG_CALL_TYPE_REGPARM:
86 c896fe29 bellard
        return flags - TCG_CALL_TYPE_REGPARM_1 + 1;
87 c896fe29 bellard
    default:
88 c896fe29 bellard
        tcg_abort();
89 c896fe29 bellard
    }
90 c896fe29 bellard
}
91 c896fe29 bellard
92 c896fe29 bellard
/* parse target specific constraints */
93 d4a9eb1f blueswir1
static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
94 c896fe29 bellard
{
95 c896fe29 bellard
    const char *ct_str;
96 c896fe29 bellard
97 c896fe29 bellard
    ct_str = *pct_str;
98 c896fe29 bellard
    switch(ct_str[0]) {
99 c896fe29 bellard
    case 'a':
100 c896fe29 bellard
        ct->ct |= TCG_CT_REG;
101 c896fe29 bellard
        tcg_regset_set_reg(ct->u.regs, TCG_REG_EAX);
102 c896fe29 bellard
        break;
103 c896fe29 bellard
    case 'b':
104 c896fe29 bellard
        ct->ct |= TCG_CT_REG;
105 c896fe29 bellard
        tcg_regset_set_reg(ct->u.regs, TCG_REG_EBX);
106 c896fe29 bellard
        break;
107 c896fe29 bellard
    case 'c':
108 c896fe29 bellard
        ct->ct |= TCG_CT_REG;
109 c896fe29 bellard
        tcg_regset_set_reg(ct->u.regs, TCG_REG_ECX);
110 c896fe29 bellard
        break;
111 c896fe29 bellard
    case 'd':
112 c896fe29 bellard
        ct->ct |= TCG_CT_REG;
113 c896fe29 bellard
        tcg_regset_set_reg(ct->u.regs, TCG_REG_EDX);
114 c896fe29 bellard
        break;
115 c896fe29 bellard
    case 'S':
116 c896fe29 bellard
        ct->ct |= TCG_CT_REG;
117 c896fe29 bellard
        tcg_regset_set_reg(ct->u.regs, TCG_REG_ESI);
118 c896fe29 bellard
        break;
119 c896fe29 bellard
    case 'D':
120 c896fe29 bellard
        ct->ct |= TCG_CT_REG;
121 c896fe29 bellard
        tcg_regset_set_reg(ct->u.regs, TCG_REG_EDI);
122 c896fe29 bellard
        break;
123 c896fe29 bellard
    case 'q':
124 c896fe29 bellard
        ct->ct |= TCG_CT_REG;
125 c896fe29 bellard
        tcg_regset_set32(ct->u.regs, 0, 0xf);
126 c896fe29 bellard
        break;
127 c896fe29 bellard
    case 'r':
128 c896fe29 bellard
        ct->ct |= TCG_CT_REG;
129 c896fe29 bellard
        tcg_regset_set32(ct->u.regs, 0, 0xff);
130 c896fe29 bellard
        break;
131 c896fe29 bellard
132 c896fe29 bellard
        /* qemu_ld/st address constraint */
133 c896fe29 bellard
    case 'L':
134 c896fe29 bellard
        ct->ct |= TCG_CT_REG;
135 c896fe29 bellard
        tcg_regset_set32(ct->u.regs, 0, 0xff);
136 c896fe29 bellard
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_EAX);
137 c896fe29 bellard
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_EDX);
138 c896fe29 bellard
        break;
139 c896fe29 bellard
    default:
140 c896fe29 bellard
        return -1;
141 c896fe29 bellard
    }
142 c896fe29 bellard
    ct_str++;
143 c896fe29 bellard
    *pct_str = ct_str;
144 c896fe29 bellard
    return 0;
145 c896fe29 bellard
}
146 c896fe29 bellard
147 c896fe29 bellard
/* test if a constant matches the constraint */
148 c896fe29 bellard
static inline int tcg_target_const_match(tcg_target_long val,
149 c896fe29 bellard
                                         const TCGArgConstraint *arg_ct)
150 c896fe29 bellard
{
151 c896fe29 bellard
    int ct;
152 c896fe29 bellard
    ct = arg_ct->ct;
153 c896fe29 bellard
    if (ct & TCG_CT_CONST)
154 c896fe29 bellard
        return 1;
155 c896fe29 bellard
    else
156 c896fe29 bellard
        return 0;
157 c896fe29 bellard
}
158 c896fe29 bellard
159 c896fe29 bellard
#define ARITH_ADD 0
160 c896fe29 bellard
#define ARITH_OR  1
161 c896fe29 bellard
#define ARITH_ADC 2
162 c896fe29 bellard
#define ARITH_SBB 3
163 c896fe29 bellard
#define ARITH_AND 4
164 c896fe29 bellard
#define ARITH_SUB 5
165 c896fe29 bellard
#define ARITH_XOR 6
166 c896fe29 bellard
#define ARITH_CMP 7
167 c896fe29 bellard
168 9619376c aurel32
#define SHIFT_ROL 0
169 9619376c aurel32
#define SHIFT_ROR 1
170 c896fe29 bellard
#define SHIFT_SHL 4
171 c896fe29 bellard
#define SHIFT_SHR 5
172 c896fe29 bellard
#define SHIFT_SAR 7
173 c896fe29 bellard
174 c896fe29 bellard
#define JCC_JMP (-1)
175 c896fe29 bellard
#define JCC_JO  0x0
176 c896fe29 bellard
#define JCC_JNO 0x1
177 c896fe29 bellard
#define JCC_JB  0x2
178 c896fe29 bellard
#define JCC_JAE 0x3
179 c896fe29 bellard
#define JCC_JE  0x4
180 c896fe29 bellard
#define JCC_JNE 0x5
181 c896fe29 bellard
#define JCC_JBE 0x6
182 c896fe29 bellard
#define JCC_JA  0x7
183 c896fe29 bellard
#define JCC_JS  0x8
184 c896fe29 bellard
#define JCC_JNS 0x9
185 c896fe29 bellard
#define JCC_JP  0xa
186 c896fe29 bellard
#define JCC_JNP 0xb
187 c896fe29 bellard
#define JCC_JL  0xc
188 c896fe29 bellard
#define JCC_JGE 0xd
189 c896fe29 bellard
#define JCC_JLE 0xe
190 c896fe29 bellard
#define JCC_JG  0xf
191 c896fe29 bellard
192 c896fe29 bellard
#define P_EXT   0x100 /* 0x0f opcode prefix */
193 c896fe29 bellard
194 c896fe29 bellard
static const uint8_t tcg_cond_to_jcc[10] = {
195 c896fe29 bellard
    [TCG_COND_EQ] = JCC_JE,
196 c896fe29 bellard
    [TCG_COND_NE] = JCC_JNE,
197 c896fe29 bellard
    [TCG_COND_LT] = JCC_JL,
198 c896fe29 bellard
    [TCG_COND_GE] = JCC_JGE,
199 c896fe29 bellard
    [TCG_COND_LE] = JCC_JLE,
200 c896fe29 bellard
    [TCG_COND_GT] = JCC_JG,
201 c896fe29 bellard
    [TCG_COND_LTU] = JCC_JB,
202 c896fe29 bellard
    [TCG_COND_GEU] = JCC_JAE,
203 c896fe29 bellard
    [TCG_COND_LEU] = JCC_JBE,
204 c896fe29 bellard
    [TCG_COND_GTU] = JCC_JA,
205 c896fe29 bellard
};
206 c896fe29 bellard
207 c896fe29 bellard
static inline void tcg_out_opc(TCGContext *s, int opc)
208 c896fe29 bellard
{
209 c896fe29 bellard
    if (opc & P_EXT)
210 c896fe29 bellard
        tcg_out8(s, 0x0f);
211 c896fe29 bellard
    tcg_out8(s, opc);
212 c896fe29 bellard
}
213 c896fe29 bellard
214 c896fe29 bellard
static inline void tcg_out_modrm(TCGContext *s, int opc, int r, int rm)
215 c896fe29 bellard
{
216 c896fe29 bellard
    tcg_out_opc(s, opc);
217 c896fe29 bellard
    tcg_out8(s, 0xc0 | (r << 3) | rm);
218 c896fe29 bellard
}
219 c896fe29 bellard
220 c896fe29 bellard
/* rm == -1 means no register index */
221 c896fe29 bellard
static inline void tcg_out_modrm_offset(TCGContext *s, int opc, int r, int rm, 
222 c896fe29 bellard
                                        int32_t offset)
223 c896fe29 bellard
{
224 c896fe29 bellard
    tcg_out_opc(s, opc);
225 c896fe29 bellard
    if (rm == -1) {
226 c896fe29 bellard
        tcg_out8(s, 0x05 | (r << 3));
227 c896fe29 bellard
        tcg_out32(s, offset);
228 c896fe29 bellard
    } else if (offset == 0 && rm != TCG_REG_EBP) {
229 c896fe29 bellard
        if (rm == TCG_REG_ESP) {
230 c896fe29 bellard
            tcg_out8(s, 0x04 | (r << 3));
231 c896fe29 bellard
            tcg_out8(s, 0x24);
232 c896fe29 bellard
        } else {
233 c896fe29 bellard
            tcg_out8(s, 0x00 | (r << 3) | rm);
234 c896fe29 bellard
        }
235 c896fe29 bellard
    } else if ((int8_t)offset == offset) {
236 c896fe29 bellard
        if (rm == TCG_REG_ESP) {
237 c896fe29 bellard
            tcg_out8(s, 0x44 | (r << 3));
238 c896fe29 bellard
            tcg_out8(s, 0x24);
239 c896fe29 bellard
        } else {
240 c896fe29 bellard
            tcg_out8(s, 0x40 | (r << 3) | rm);
241 c896fe29 bellard
        }
242 c896fe29 bellard
        tcg_out8(s, offset);
243 c896fe29 bellard
    } else {
244 c896fe29 bellard
        if (rm == TCG_REG_ESP) {
245 c896fe29 bellard
            tcg_out8(s, 0x84 | (r << 3));
246 c896fe29 bellard
            tcg_out8(s, 0x24);
247 c896fe29 bellard
        } else {
248 c896fe29 bellard
            tcg_out8(s, 0x80 | (r << 3) | rm);
249 c896fe29 bellard
        }
250 c896fe29 bellard
        tcg_out32(s, offset);
251 c896fe29 bellard
    }
252 c896fe29 bellard
}
253 c896fe29 bellard
254 c896fe29 bellard
static inline void tcg_out_mov(TCGContext *s, int ret, int arg)
255 c896fe29 bellard
{
256 c896fe29 bellard
    if (arg != ret)
257 c896fe29 bellard
        tcg_out_modrm(s, 0x8b, ret, arg);
258 c896fe29 bellard
}
259 c896fe29 bellard
260 c896fe29 bellard
static inline void tcg_out_movi(TCGContext *s, TCGType type,
261 c896fe29 bellard
                                int ret, int32_t arg)
262 c896fe29 bellard
{
263 c896fe29 bellard
    if (arg == 0) {
264 c896fe29 bellard
        /* xor r0,r0 */
265 c896fe29 bellard
        tcg_out_modrm(s, 0x01 | (ARITH_XOR << 3), ret, ret);
266 c896fe29 bellard
    } else {
267 c896fe29 bellard
        tcg_out8(s, 0xb8 + ret);
268 c896fe29 bellard
        tcg_out32(s, arg);
269 c896fe29 bellard
    }
270 c896fe29 bellard
}
271 c896fe29 bellard
272 e4d5434c blueswir1
static inline void tcg_out_ld(TCGContext *s, TCGType type, int ret,
273 e4d5434c blueswir1
                              int arg1, tcg_target_long arg2)
274 c896fe29 bellard
{
275 c896fe29 bellard
    /* movl */
276 c896fe29 bellard
    tcg_out_modrm_offset(s, 0x8b, ret, arg1, arg2);
277 c896fe29 bellard
}
278 c896fe29 bellard
279 e4d5434c blueswir1
static inline void tcg_out_st(TCGContext *s, TCGType type, int arg,
280 e4d5434c blueswir1
                              int arg1, tcg_target_long arg2)
281 c896fe29 bellard
{
282 c896fe29 bellard
    /* movl */
283 c896fe29 bellard
    tcg_out_modrm_offset(s, 0x89, arg, arg1, arg2);
284 c896fe29 bellard
}
285 c896fe29 bellard
286 17cf428f Aurelien Jarno
static inline void tgen_arithi(TCGContext *s, int c, int r0, int32_t val, int cf)
287 c896fe29 bellard
{
288 17cf428f Aurelien Jarno
    if (!cf && ((c == ARITH_ADD && val == 1) || (c == ARITH_SUB && val == -1))) {
289 17cf428f Aurelien Jarno
        /* inc */
290 17cf428f Aurelien Jarno
        tcg_out_opc(s, 0x40 + r0);
291 17cf428f Aurelien Jarno
    } else if (!cf && ((c == ARITH_ADD && val == -1) || (c == ARITH_SUB && val == 1))) {
292 17cf428f Aurelien Jarno
        /* dec */
293 17cf428f Aurelien Jarno
        tcg_out_opc(s, 0x48 + r0);
294 17cf428f Aurelien Jarno
    } else if (val == (int8_t)val) {
295 c896fe29 bellard
        tcg_out_modrm(s, 0x83, c, r0);
296 c896fe29 bellard
        tcg_out8(s, val);
297 b70650cb Aurelien Jarno
    } else if (c == ARITH_AND && val == 0xffu && r0 < 4) {
298 b70650cb Aurelien Jarno
        /* movzbl */
299 b70650cb Aurelien Jarno
        tcg_out_modrm(s, 0xb6 | P_EXT, r0, r0);
300 b70650cb Aurelien Jarno
    } else if (c == ARITH_AND && val == 0xffffu) {
301 b70650cb Aurelien Jarno
        /* movzwl */
302 b70650cb Aurelien Jarno
        tcg_out_modrm(s, 0xb7 | P_EXT, r0, r0);
303 c896fe29 bellard
    } else {
304 c896fe29 bellard
        tcg_out_modrm(s, 0x81, c, r0);
305 c896fe29 bellard
        tcg_out32(s, val);
306 c896fe29 bellard
    }
307 c896fe29 bellard
}
308 c896fe29 bellard
309 3e9a474e aurel32
static void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
310 c896fe29 bellard
{
311 c896fe29 bellard
    if (val != 0)
312 17cf428f Aurelien Jarno
        tgen_arithi(s, ARITH_ADD, reg, val, 0);
313 c896fe29 bellard
}
314 c896fe29 bellard
315 f75b56c1 Richard Henderson
/* Use SMALL != 0 to force a short forward branch.  */
316 f75b56c1 Richard Henderson
static void tcg_out_jxx(TCGContext *s, int opc, int label_index, int small)
317 c896fe29 bellard
{
318 c896fe29 bellard
    int32_t val, val1;
319 c896fe29 bellard
    TCGLabel *l = &s->labels[label_index];
320 c896fe29 bellard
    
321 c896fe29 bellard
    if (l->has_value) {
322 c896fe29 bellard
        val = l->u.value - (tcg_target_long)s->code_ptr;
323 c896fe29 bellard
        val1 = val - 2;
324 c896fe29 bellard
        if ((int8_t)val1 == val1) {
325 f75b56c1 Richard Henderson
            if (opc == -1) {
326 c896fe29 bellard
                tcg_out8(s, 0xeb);
327 f75b56c1 Richard Henderson
            } else {
328 c896fe29 bellard
                tcg_out8(s, 0x70 + opc);
329 f75b56c1 Richard Henderson
            }
330 c896fe29 bellard
            tcg_out8(s, val1);
331 c896fe29 bellard
        } else {
332 f75b56c1 Richard Henderson
            if (small) {
333 f75b56c1 Richard Henderson
                tcg_abort();
334 f75b56c1 Richard Henderson
            }
335 c896fe29 bellard
            if (opc == -1) {
336 c896fe29 bellard
                tcg_out8(s, 0xe9);
337 c896fe29 bellard
                tcg_out32(s, val - 5);
338 c896fe29 bellard
            } else {
339 c896fe29 bellard
                tcg_out8(s, 0x0f);
340 c896fe29 bellard
                tcg_out8(s, 0x80 + opc);
341 c896fe29 bellard
                tcg_out32(s, val - 6);
342 c896fe29 bellard
            }
343 c896fe29 bellard
        }
344 f75b56c1 Richard Henderson
    } else if (small) {
345 f75b56c1 Richard Henderson
        if (opc == -1) {
346 f75b56c1 Richard Henderson
            tcg_out8(s, 0xeb);
347 f75b56c1 Richard Henderson
        } else {
348 f75b56c1 Richard Henderson
            tcg_out8(s, 0x70 + opc);
349 f75b56c1 Richard Henderson
        }
350 f75b56c1 Richard Henderson
        tcg_out_reloc(s, s->code_ptr, R_386_PC8, label_index, -1);
351 f75b56c1 Richard Henderson
        s->code_ptr += 1;
352 c896fe29 bellard
    } else {
353 c896fe29 bellard
        if (opc == -1) {
354 c896fe29 bellard
            tcg_out8(s, 0xe9);
355 c896fe29 bellard
        } else {
356 c896fe29 bellard
            tcg_out8(s, 0x0f);
357 c896fe29 bellard
            tcg_out8(s, 0x80 + opc);
358 c896fe29 bellard
        }
359 c896fe29 bellard
        tcg_out_reloc(s, s->code_ptr, R_386_PC32, label_index, -4);
360 623e265c pbrook
        s->code_ptr += 4;
361 c896fe29 bellard
    }
362 c896fe29 bellard
}
363 c896fe29 bellard
364 1d2699ae Richard Henderson
static void tcg_out_cmp(TCGContext *s, TCGArg arg1, TCGArg arg2,
365 1d2699ae Richard Henderson
                        int const_arg2)
366 c896fe29 bellard
{
367 c896fe29 bellard
    if (const_arg2) {
368 c896fe29 bellard
        if (arg2 == 0) {
369 c896fe29 bellard
            /* test r, r */
370 c896fe29 bellard
            tcg_out_modrm(s, 0x85, arg1, arg1);
371 c896fe29 bellard
        } else {
372 17cf428f Aurelien Jarno
            tgen_arithi(s, ARITH_CMP, arg1, arg2, 0);
373 c896fe29 bellard
        }
374 c896fe29 bellard
    } else {
375 bb210e78 bellard
        tcg_out_modrm(s, 0x01 | (ARITH_CMP << 3), arg2, arg1);
376 c896fe29 bellard
    }
377 1d2699ae Richard Henderson
}
378 1d2699ae Richard Henderson
379 1d2699ae Richard Henderson
static void tcg_out_brcond(TCGContext *s, int cond,
380 1d2699ae Richard Henderson
                           TCGArg arg1, TCGArg arg2, int const_arg2,
381 1d2699ae Richard Henderson
                           int label_index, int small)
382 1d2699ae Richard Henderson
{
383 1d2699ae Richard Henderson
    tcg_out_cmp(s, arg1, arg2, const_arg2);
384 f75b56c1 Richard Henderson
    tcg_out_jxx(s, tcg_cond_to_jcc[cond], label_index, small);
385 c896fe29 bellard
}
386 c896fe29 bellard
387 c896fe29 bellard
/* XXX: we implement it at the target level to avoid having to
388 c896fe29 bellard
   handle cross basic blocks temporaries */
389 f75b56c1 Richard Henderson
static void tcg_out_brcond2(TCGContext *s, const TCGArg *args,
390 f75b56c1 Richard Henderson
                            const int *const_args, int small)
391 c896fe29 bellard
{
392 c896fe29 bellard
    int label_next;
393 c896fe29 bellard
    label_next = gen_new_label();
394 c896fe29 bellard
    switch(args[4]) {
395 c896fe29 bellard
    case TCG_COND_EQ:
396 f75b56c1 Richard Henderson
        tcg_out_brcond(s, TCG_COND_NE, args[0], args[2], const_args[2],
397 f75b56c1 Richard Henderson
                       label_next, 1);
398 f75b56c1 Richard Henderson
        tcg_out_brcond(s, TCG_COND_EQ, args[1], args[3], const_args[3],
399 f75b56c1 Richard Henderson
                       args[5], small);
400 c896fe29 bellard
        break;
401 c896fe29 bellard
    case TCG_COND_NE:
402 f75b56c1 Richard Henderson
        tcg_out_brcond(s, TCG_COND_NE, args[0], args[2], const_args[2],
403 f75b56c1 Richard Henderson
                       args[5], small);
404 f75b56c1 Richard Henderson
        tcg_out_brcond(s, TCG_COND_NE, args[1], args[3], const_args[3],
405 f75b56c1 Richard Henderson
                       args[5], small);
406 c896fe29 bellard
        break;
407 c896fe29 bellard
    case TCG_COND_LT:
408 f75b56c1 Richard Henderson
        tcg_out_brcond(s, TCG_COND_LT, args[1], args[3], const_args[3],
409 f75b56c1 Richard Henderson
                       args[5], small);
410 f75b56c1 Richard Henderson
        tcg_out_jxx(s, JCC_JNE, label_next, 1);
411 f75b56c1 Richard Henderson
        tcg_out_brcond(s, TCG_COND_LTU, args[0], args[2], const_args[2],
412 f75b56c1 Richard Henderson
                       args[5], small);
413 c896fe29 bellard
        break;
414 c896fe29 bellard
    case TCG_COND_LE:
415 f75b56c1 Richard Henderson
        tcg_out_brcond(s, TCG_COND_LT, args[1], args[3], const_args[3],
416 f75b56c1 Richard Henderson
                       args[5], small);
417 f75b56c1 Richard Henderson
        tcg_out_jxx(s, JCC_JNE, label_next, 1);
418 f75b56c1 Richard Henderson
        tcg_out_brcond(s, TCG_COND_LEU, args[0], args[2], const_args[2],
419 f75b56c1 Richard Henderson
                       args[5], small);
420 c896fe29 bellard
        break;
421 c896fe29 bellard
    case TCG_COND_GT:
422 f75b56c1 Richard Henderson
        tcg_out_brcond(s, TCG_COND_GT, args[1], args[3], const_args[3],
423 f75b56c1 Richard Henderson
                       args[5], small);
424 f75b56c1 Richard Henderson
        tcg_out_jxx(s, JCC_JNE, label_next, 1);
425 f75b56c1 Richard Henderson
        tcg_out_brcond(s, TCG_COND_GTU, args[0], args[2], const_args[2],
426 f75b56c1 Richard Henderson
                       args[5], small);
427 c896fe29 bellard
        break;
428 c896fe29 bellard
    case TCG_COND_GE:
429 f75b56c1 Richard Henderson
        tcg_out_brcond(s, TCG_COND_GT, args[1], args[3], const_args[3],
430 f75b56c1 Richard Henderson
                       args[5], small);
431 f75b56c1 Richard Henderson
        tcg_out_jxx(s, JCC_JNE, label_next, 1);
432 f75b56c1 Richard Henderson
        tcg_out_brcond(s, TCG_COND_GEU, args[0], args[2], const_args[2],
433 f75b56c1 Richard Henderson
                       args[5], small);
434 c896fe29 bellard
        break;
435 c896fe29 bellard
    case TCG_COND_LTU:
436 f75b56c1 Richard Henderson
        tcg_out_brcond(s, TCG_COND_LTU, args[1], args[3], const_args[3],
437 f75b56c1 Richard Henderson
                       args[5], small);
438 f75b56c1 Richard Henderson
        tcg_out_jxx(s, JCC_JNE, label_next, 1);
439 f75b56c1 Richard Henderson
        tcg_out_brcond(s, TCG_COND_LTU, args[0], args[2], const_args[2],
440 f75b56c1 Richard Henderson
                       args[5], small);
441 c896fe29 bellard
        break;
442 c896fe29 bellard
    case TCG_COND_LEU:
443 f75b56c1 Richard Henderson
        tcg_out_brcond(s, TCG_COND_LTU, args[1], args[3], const_args[3],
444 f75b56c1 Richard Henderson
                       args[5], small);
445 f75b56c1 Richard Henderson
        tcg_out_jxx(s, JCC_JNE, label_next, 1);
446 f75b56c1 Richard Henderson
        tcg_out_brcond(s, TCG_COND_LEU, args[0], args[2], const_args[2],
447 f75b56c1 Richard Henderson
                       args[5], small);
448 c896fe29 bellard
        break;
449 c896fe29 bellard
    case TCG_COND_GTU:
450 f75b56c1 Richard Henderson
        tcg_out_brcond(s, TCG_COND_GTU, args[1], args[3], const_args[3],
451 f75b56c1 Richard Henderson
                       args[5], small);
452 f75b56c1 Richard Henderson
        tcg_out_jxx(s, JCC_JNE, label_next, 1);
453 f75b56c1 Richard Henderson
        tcg_out_brcond(s, TCG_COND_GTU, args[0], args[2], const_args[2],
454 f75b56c1 Richard Henderson
                       args[5], small);
455 c896fe29 bellard
        break;
456 c896fe29 bellard
    case TCG_COND_GEU:
457 f75b56c1 Richard Henderson
        tcg_out_brcond(s, TCG_COND_GTU, args[1], args[3], const_args[3],
458 f75b56c1 Richard Henderson
                       args[5], small);
459 f75b56c1 Richard Henderson
        tcg_out_jxx(s, JCC_JNE, label_next, 1);
460 f75b56c1 Richard Henderson
        tcg_out_brcond(s, TCG_COND_GEU, args[0], args[2], const_args[2],
461 f75b56c1 Richard Henderson
                       args[5], small);
462 c896fe29 bellard
        break;
463 c896fe29 bellard
    default:
464 c896fe29 bellard
        tcg_abort();
465 c896fe29 bellard
    }
466 c896fe29 bellard
    tcg_out_label(s, label_next, (tcg_target_long)s->code_ptr);
467 c896fe29 bellard
}
468 c896fe29 bellard
469 1d2699ae Richard Henderson
static void tcg_out_setcond(TCGContext *s, int cond, TCGArg dest,
470 1d2699ae Richard Henderson
                            TCGArg arg1, TCGArg arg2, int const_arg2)
471 1d2699ae Richard Henderson
{
472 1d2699ae Richard Henderson
    tcg_out_cmp(s, arg1, arg2, const_arg2);
473 1d2699ae Richard Henderson
    /* setcc */
474 1d2699ae Richard Henderson
    tcg_out_modrm(s, 0x90 | tcg_cond_to_jcc[cond] | P_EXT, 0, dest);
475 1d2699ae Richard Henderson
    tgen_arithi(s, ARITH_AND, dest, 0xff, 0);
476 1d2699ae Richard Henderson
}
477 1d2699ae Richard Henderson
478 1d2699ae Richard Henderson
static void tcg_out_setcond2(TCGContext *s, const TCGArg *args,
479 1d2699ae Richard Henderson
                             const int *const_args)
480 1d2699ae Richard Henderson
{
481 1d2699ae Richard Henderson
    TCGArg new_args[6];
482 1d2699ae Richard Henderson
    int label_true, label_over;
483 1d2699ae Richard Henderson
484 1d2699ae Richard Henderson
    memcpy(new_args, args+1, 5*sizeof(TCGArg));
485 1d2699ae Richard Henderson
486 1d2699ae Richard Henderson
    if (args[0] == args[1] || args[0] == args[2]
487 1d2699ae Richard Henderson
        || (!const_args[3] && args[0] == args[3])
488 1d2699ae Richard Henderson
        || (!const_args[4] && args[0] == args[4])) {
489 1d2699ae Richard Henderson
        /* When the destination overlaps with one of the argument
490 1d2699ae Richard Henderson
           registers, don't do anything tricky.  */
491 1d2699ae Richard Henderson
        label_true = gen_new_label();
492 1d2699ae Richard Henderson
        label_over = gen_new_label();
493 1d2699ae Richard Henderson
494 1d2699ae Richard Henderson
        new_args[5] = label_true;
495 1d2699ae Richard Henderson
        tcg_out_brcond2(s, new_args, const_args+1, 1);
496 1d2699ae Richard Henderson
497 1d2699ae Richard Henderson
        tcg_out_movi(s, TCG_TYPE_I32, args[0], 0);
498 1d2699ae Richard Henderson
        tcg_out_jxx(s, JCC_JMP, label_over, 1);
499 1d2699ae Richard Henderson
        tcg_out_label(s, label_true, (tcg_target_long)s->code_ptr);
500 1d2699ae Richard Henderson
501 1d2699ae Richard Henderson
        tcg_out_movi(s, TCG_TYPE_I32, args[0], 1);
502 1d2699ae Richard Henderson
        tcg_out_label(s, label_over, (tcg_target_long)s->code_ptr);
503 1d2699ae Richard Henderson
    } else {
504 1d2699ae Richard Henderson
        /* When the destination does not overlap one of the arguments,
505 1d2699ae Richard Henderson
           clear the destination first, jump if cond false, and emit an
506 1d2699ae Richard Henderson
           increment in the true case.  This results in smaller code.  */
507 1d2699ae Richard Henderson
508 1d2699ae Richard Henderson
        tcg_out_movi(s, TCG_TYPE_I32, args[0], 0);
509 1d2699ae Richard Henderson
510 1d2699ae Richard Henderson
        label_over = gen_new_label();
511 1d2699ae Richard Henderson
        new_args[4] = tcg_invert_cond(new_args[4]);
512 1d2699ae Richard Henderson
        new_args[5] = label_over;
513 1d2699ae Richard Henderson
        tcg_out_brcond2(s, new_args, const_args+1, 1);
514 1d2699ae Richard Henderson
515 1d2699ae Richard Henderson
        tgen_arithi(s, ARITH_ADD, args[0], 1, 0);
516 1d2699ae Richard Henderson
        tcg_out_label(s, label_over, (tcg_target_long)s->code_ptr);
517 1d2699ae Richard Henderson
    }
518 1d2699ae Richard Henderson
}
519 1d2699ae Richard Henderson
520 c896fe29 bellard
#if defined(CONFIG_SOFTMMU)
521 79383c9c blueswir1
522 79383c9c blueswir1
#include "../../softmmu_defs.h"
523 c896fe29 bellard
524 c896fe29 bellard
static void *qemu_ld_helpers[4] = {
525 c896fe29 bellard
    __ldb_mmu,
526 c896fe29 bellard
    __ldw_mmu,
527 c896fe29 bellard
    __ldl_mmu,
528 c896fe29 bellard
    __ldq_mmu,
529 c896fe29 bellard
};
530 c896fe29 bellard
531 c896fe29 bellard
static void *qemu_st_helpers[4] = {
532 c896fe29 bellard
    __stb_mmu,
533 c896fe29 bellard
    __stw_mmu,
534 c896fe29 bellard
    __stl_mmu,
535 c896fe29 bellard
    __stq_mmu,
536 c896fe29 bellard
};
537 c896fe29 bellard
#endif
538 c896fe29 bellard
539 379f6698 Paul Brook
#ifndef CONFIG_USER_ONLY
540 379f6698 Paul Brook
#define GUEST_BASE 0
541 379f6698 Paul Brook
#endif
542 379f6698 Paul Brook
543 c896fe29 bellard
/* XXX: qemu_ld and qemu_st could be modified to clobber only EDX and
544 c896fe29 bellard
   EAX. It will be useful once fixed registers globals are less
545 c896fe29 bellard
   common. */
546 c896fe29 bellard
static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
547 c896fe29 bellard
                            int opc)
548 c896fe29 bellard
{
549 c896fe29 bellard
    int addr_reg, data_reg, data_reg2, r0, r1, mem_index, s_bits, bswap;
550 c896fe29 bellard
#if defined(CONFIG_SOFTMMU)
551 c896fe29 bellard
    uint8_t *label1_ptr, *label2_ptr;
552 c896fe29 bellard
#endif
553 c896fe29 bellard
#if TARGET_LONG_BITS == 64
554 c896fe29 bellard
#if defined(CONFIG_SOFTMMU)
555 c896fe29 bellard
    uint8_t *label3_ptr;
556 c896fe29 bellard
#endif
557 c896fe29 bellard
    int addr_reg2;
558 c896fe29 bellard
#endif
559 c896fe29 bellard
560 c896fe29 bellard
    data_reg = *args++;
561 c896fe29 bellard
    if (opc == 3)
562 c896fe29 bellard
        data_reg2 = *args++;
563 c896fe29 bellard
    else
564 c896fe29 bellard
        data_reg2 = 0;
565 c896fe29 bellard
    addr_reg = *args++;
566 c896fe29 bellard
#if TARGET_LONG_BITS == 64
567 c896fe29 bellard
    addr_reg2 = *args++;
568 c896fe29 bellard
#endif
569 c896fe29 bellard
    mem_index = *args;
570 c896fe29 bellard
    s_bits = opc & 3;
571 c896fe29 bellard
572 c896fe29 bellard
    r0 = TCG_REG_EAX;
573 c896fe29 bellard
    r1 = TCG_REG_EDX;
574 c896fe29 bellard
575 c896fe29 bellard
#if defined(CONFIG_SOFTMMU)
576 c896fe29 bellard
    tcg_out_mov(s, r1, addr_reg); 
577 c896fe29 bellard
578 c896fe29 bellard
    tcg_out_mov(s, r0, addr_reg); 
579 c896fe29 bellard
 
580 c896fe29 bellard
    tcg_out_modrm(s, 0xc1, 5, r1); /* shr $x, r1 */
581 c896fe29 bellard
    tcg_out8(s, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS); 
582 c896fe29 bellard
    
583 c896fe29 bellard
    tcg_out_modrm(s, 0x81, 4, r0); /* andl $x, r0 */
584 c896fe29 bellard
    tcg_out32(s, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
585 c896fe29 bellard
    
586 c896fe29 bellard
    tcg_out_modrm(s, 0x81, 4, r1); /* andl $x, r1 */
587 c896fe29 bellard
    tcg_out32(s, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
588 c896fe29 bellard
589 c896fe29 bellard
    tcg_out_opc(s, 0x8d); /* lea offset(r1, %ebp), r1 */
590 c896fe29 bellard
    tcg_out8(s, 0x80 | (r1 << 3) | 0x04);
591 c896fe29 bellard
    tcg_out8(s, (5 << 3) | r1);
592 c896fe29 bellard
    tcg_out32(s, offsetof(CPUState, tlb_table[mem_index][0].addr_read));
593 c896fe29 bellard
594 c896fe29 bellard
    /* cmp 0(r1), r0 */
595 c896fe29 bellard
    tcg_out_modrm_offset(s, 0x3b, r0, r1, 0);
596 c896fe29 bellard
    
597 c896fe29 bellard
    tcg_out_mov(s, r0, addr_reg);
598 c896fe29 bellard
    
599 c896fe29 bellard
#if TARGET_LONG_BITS == 32
600 c896fe29 bellard
    /* je label1 */
601 c896fe29 bellard
    tcg_out8(s, 0x70 + JCC_JE);
602 c896fe29 bellard
    label1_ptr = s->code_ptr;
603 c896fe29 bellard
    s->code_ptr++;
604 c896fe29 bellard
#else
605 c896fe29 bellard
    /* jne label3 */
606 c896fe29 bellard
    tcg_out8(s, 0x70 + JCC_JNE);
607 c896fe29 bellard
    label3_ptr = s->code_ptr;
608 c896fe29 bellard
    s->code_ptr++;
609 c896fe29 bellard
    
610 c896fe29 bellard
    /* cmp 4(r1), addr_reg2 */
611 c896fe29 bellard
    tcg_out_modrm_offset(s, 0x3b, addr_reg2, r1, 4);
612 c896fe29 bellard
613 c896fe29 bellard
    /* je label1 */
614 c896fe29 bellard
    tcg_out8(s, 0x70 + JCC_JE);
615 c896fe29 bellard
    label1_ptr = s->code_ptr;
616 c896fe29 bellard
    s->code_ptr++;
617 c896fe29 bellard
    
618 c896fe29 bellard
    /* label3: */
619 c896fe29 bellard
    *label3_ptr = s->code_ptr - label3_ptr - 1;
620 c896fe29 bellard
#endif
621 c896fe29 bellard
622 c896fe29 bellard
    /* XXX: move that code at the end of the TB */
623 c896fe29 bellard
#if TARGET_LONG_BITS == 32
624 c896fe29 bellard
    tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_EDX, mem_index);
625 c896fe29 bellard
#else
626 c896fe29 bellard
    tcg_out_mov(s, TCG_REG_EDX, addr_reg2);
627 c896fe29 bellard
    tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_ECX, mem_index);
628 c896fe29 bellard
#endif
629 c896fe29 bellard
    tcg_out8(s, 0xe8);
630 c896fe29 bellard
    tcg_out32(s, (tcg_target_long)qemu_ld_helpers[s_bits] - 
631 c896fe29 bellard
              (tcg_target_long)s->code_ptr - 4);
632 c896fe29 bellard
633 c896fe29 bellard
    switch(opc) {
634 c896fe29 bellard
    case 0 | 4:
635 c896fe29 bellard
        /* movsbl */
636 c896fe29 bellard
        tcg_out_modrm(s, 0xbe | P_EXT, data_reg, TCG_REG_EAX);
637 c896fe29 bellard
        break;
638 c896fe29 bellard
    case 1 | 4:
639 c896fe29 bellard
        /* movswl */
640 c896fe29 bellard
        tcg_out_modrm(s, 0xbf | P_EXT, data_reg, TCG_REG_EAX);
641 c896fe29 bellard
        break;
642 c896fe29 bellard
    case 0:
643 9db3ba4d aurel32
        /* movzbl */
644 9db3ba4d aurel32
        tcg_out_modrm(s, 0xb6 | P_EXT, data_reg, TCG_REG_EAX);
645 9db3ba4d aurel32
        break;
646 c896fe29 bellard
    case 1:
647 9db3ba4d aurel32
        /* movzwl */
648 9db3ba4d aurel32
        tcg_out_modrm(s, 0xb7 | P_EXT, data_reg, TCG_REG_EAX);
649 9db3ba4d aurel32
        break;
650 c896fe29 bellard
    case 2:
651 c896fe29 bellard
    default:
652 c896fe29 bellard
        tcg_out_mov(s, data_reg, TCG_REG_EAX);
653 c896fe29 bellard
        break;
654 c896fe29 bellard
    case 3:
655 c896fe29 bellard
        if (data_reg == TCG_REG_EDX) {
656 c896fe29 bellard
            tcg_out_opc(s, 0x90 + TCG_REG_EDX); /* xchg %edx, %eax */
657 c896fe29 bellard
            tcg_out_mov(s, data_reg2, TCG_REG_EAX);
658 c896fe29 bellard
        } else {
659 c896fe29 bellard
            tcg_out_mov(s, data_reg, TCG_REG_EAX);
660 c896fe29 bellard
            tcg_out_mov(s, data_reg2, TCG_REG_EDX);
661 c896fe29 bellard
        }
662 c896fe29 bellard
        break;
663 c896fe29 bellard
    }
664 c896fe29 bellard
665 c896fe29 bellard
    /* jmp label2 */
666 c896fe29 bellard
    tcg_out8(s, 0xeb);
667 c896fe29 bellard
    label2_ptr = s->code_ptr;
668 c896fe29 bellard
    s->code_ptr++;
669 c896fe29 bellard
    
670 c896fe29 bellard
    /* label1: */
671 c896fe29 bellard
    *label1_ptr = s->code_ptr - label1_ptr - 1;
672 c896fe29 bellard
673 c896fe29 bellard
    /* add x(r1), r0 */
674 c896fe29 bellard
    tcg_out_modrm_offset(s, 0x03, r0, r1, offsetof(CPUTLBEntry, addend) - 
675 c896fe29 bellard
                         offsetof(CPUTLBEntry, addr_read));
676 c896fe29 bellard
#else
677 c896fe29 bellard
    r0 = addr_reg;
678 c896fe29 bellard
#endif
679 c896fe29 bellard
680 c896fe29 bellard
#ifdef TARGET_WORDS_BIGENDIAN
681 c896fe29 bellard
    bswap = 1;
682 c896fe29 bellard
#else
683 c896fe29 bellard
    bswap = 0;
684 c896fe29 bellard
#endif
685 c896fe29 bellard
    switch(opc) {
686 c896fe29 bellard
    case 0:
687 c896fe29 bellard
        /* movzbl */
688 379f6698 Paul Brook
        tcg_out_modrm_offset(s, 0xb6 | P_EXT, data_reg, r0, GUEST_BASE);
689 c896fe29 bellard
        break;
690 c896fe29 bellard
    case 0 | 4:
691 c896fe29 bellard
        /* movsbl */
692 379f6698 Paul Brook
        tcg_out_modrm_offset(s, 0xbe | P_EXT, data_reg, r0, GUEST_BASE);
693 c896fe29 bellard
        break;
694 c896fe29 bellard
    case 1:
695 c896fe29 bellard
        /* movzwl */
696 379f6698 Paul Brook
        tcg_out_modrm_offset(s, 0xb7 | P_EXT, data_reg, r0, GUEST_BASE);
697 c896fe29 bellard
        if (bswap) {
698 c896fe29 bellard
            /* rolw $8, data_reg */
699 c896fe29 bellard
            tcg_out8(s, 0x66); 
700 c896fe29 bellard
            tcg_out_modrm(s, 0xc1, 0, data_reg);
701 c896fe29 bellard
            tcg_out8(s, 8);
702 c896fe29 bellard
        }
703 c896fe29 bellard
        break;
704 c896fe29 bellard
    case 1 | 4:
705 c896fe29 bellard
        /* movswl */
706 379f6698 Paul Brook
        tcg_out_modrm_offset(s, 0xbf | P_EXT, data_reg, r0, GUEST_BASE);
707 c896fe29 bellard
        if (bswap) {
708 c896fe29 bellard
            /* rolw $8, data_reg */
709 c896fe29 bellard
            tcg_out8(s, 0x66); 
710 c896fe29 bellard
            tcg_out_modrm(s, 0xc1, 0, data_reg);
711 c896fe29 bellard
            tcg_out8(s, 8);
712 c896fe29 bellard
713 c896fe29 bellard
            /* movswl data_reg, data_reg */
714 c896fe29 bellard
            tcg_out_modrm(s, 0xbf | P_EXT, data_reg, data_reg);
715 c896fe29 bellard
        }
716 c896fe29 bellard
        break;
717 c896fe29 bellard
    case 2:
718 c896fe29 bellard
        /* movl (r0), data_reg */
719 379f6698 Paul Brook
        tcg_out_modrm_offset(s, 0x8b, data_reg, r0, GUEST_BASE);
720 c896fe29 bellard
        if (bswap) {
721 c896fe29 bellard
            /* bswap */
722 c896fe29 bellard
            tcg_out_opc(s, (0xc8 + data_reg) | P_EXT);
723 c896fe29 bellard
        }
724 c896fe29 bellard
        break;
725 c896fe29 bellard
    case 3:
726 c896fe29 bellard
        /* XXX: could be nicer */
727 c896fe29 bellard
        if (r0 == data_reg) {
728 c896fe29 bellard
            r1 = TCG_REG_EDX;
729 c896fe29 bellard
            if (r1 == data_reg)
730 c896fe29 bellard
                r1 = TCG_REG_EAX;
731 c896fe29 bellard
            tcg_out_mov(s, r1, r0);
732 c896fe29 bellard
            r0 = r1;
733 c896fe29 bellard
        }
734 c896fe29 bellard
        if (!bswap) {
735 379f6698 Paul Brook
            tcg_out_modrm_offset(s, 0x8b, data_reg, r0, GUEST_BASE);
736 adea8197 Juan Quintela
            tcg_out_modrm_offset(s, 0x8b, data_reg2, r0, GUEST_BASE + 4);
737 c896fe29 bellard
        } else {
738 379f6698 Paul Brook
            tcg_out_modrm_offset(s, 0x8b, data_reg, r0, GUEST_BASE + 4);
739 c896fe29 bellard
            tcg_out_opc(s, (0xc8 + data_reg) | P_EXT);
740 c896fe29 bellard
741 379f6698 Paul Brook
            tcg_out_modrm_offset(s, 0x8b, data_reg2, r0, GUEST_BASE);
742 c896fe29 bellard
            /* bswap */
743 c896fe29 bellard
            tcg_out_opc(s, (0xc8 + data_reg2) | P_EXT);
744 c896fe29 bellard
        }
745 c896fe29 bellard
        break;
746 c896fe29 bellard
    default:
747 c896fe29 bellard
        tcg_abort();
748 c896fe29 bellard
    }
749 c896fe29 bellard
750 c896fe29 bellard
#if defined(CONFIG_SOFTMMU)
751 c896fe29 bellard
    /* label2: */
752 c896fe29 bellard
    *label2_ptr = s->code_ptr - label2_ptr - 1;
753 c896fe29 bellard
#endif
754 c896fe29 bellard
}
755 c896fe29 bellard
756 c896fe29 bellard
757 c896fe29 bellard
static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
758 c896fe29 bellard
                            int opc)
759 c896fe29 bellard
{
760 c896fe29 bellard
    int addr_reg, data_reg, data_reg2, r0, r1, mem_index, s_bits, bswap;
761 c896fe29 bellard
#if defined(CONFIG_SOFTMMU)
762 c896fe29 bellard
    uint8_t *label1_ptr, *label2_ptr;
763 c896fe29 bellard
#endif
764 c896fe29 bellard
#if TARGET_LONG_BITS == 64
765 c896fe29 bellard
#if defined(CONFIG_SOFTMMU)
766 c896fe29 bellard
    uint8_t *label3_ptr;
767 c896fe29 bellard
#endif
768 c896fe29 bellard
    int addr_reg2;
769 c896fe29 bellard
#endif
770 c896fe29 bellard
771 c896fe29 bellard
    data_reg = *args++;
772 c896fe29 bellard
    if (opc == 3)
773 c896fe29 bellard
        data_reg2 = *args++;
774 c896fe29 bellard
    else
775 c896fe29 bellard
        data_reg2 = 0;
776 c896fe29 bellard
    addr_reg = *args++;
777 c896fe29 bellard
#if TARGET_LONG_BITS == 64
778 c896fe29 bellard
    addr_reg2 = *args++;
779 c896fe29 bellard
#endif
780 c896fe29 bellard
    mem_index = *args;
781 c896fe29 bellard
782 c896fe29 bellard
    s_bits = opc;
783 c896fe29 bellard
784 c896fe29 bellard
    r0 = TCG_REG_EAX;
785 c896fe29 bellard
    r1 = TCG_REG_EDX;
786 c896fe29 bellard
787 c896fe29 bellard
#if defined(CONFIG_SOFTMMU)
788 c896fe29 bellard
    tcg_out_mov(s, r1, addr_reg); 
789 c896fe29 bellard
790 c896fe29 bellard
    tcg_out_mov(s, r0, addr_reg); 
791 c896fe29 bellard
 
792 c896fe29 bellard
    tcg_out_modrm(s, 0xc1, 5, r1); /* shr $x, r1 */
793 c896fe29 bellard
    tcg_out8(s, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS); 
794 c896fe29 bellard
    
795 c896fe29 bellard
    tcg_out_modrm(s, 0x81, 4, r0); /* andl $x, r0 */
796 c896fe29 bellard
    tcg_out32(s, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
797 c896fe29 bellard
    
798 c896fe29 bellard
    tcg_out_modrm(s, 0x81, 4, r1); /* andl $x, r1 */
799 c896fe29 bellard
    tcg_out32(s, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
800 c896fe29 bellard
801 c896fe29 bellard
    tcg_out_opc(s, 0x8d); /* lea offset(r1, %ebp), r1 */
802 c896fe29 bellard
    tcg_out8(s, 0x80 | (r1 << 3) | 0x04);
803 c896fe29 bellard
    tcg_out8(s, (5 << 3) | r1);
804 c896fe29 bellard
    tcg_out32(s, offsetof(CPUState, tlb_table[mem_index][0].addr_write));
805 c896fe29 bellard
806 c896fe29 bellard
    /* cmp 0(r1), r0 */
807 c896fe29 bellard
    tcg_out_modrm_offset(s, 0x3b, r0, r1, 0);
808 c896fe29 bellard
    
809 c896fe29 bellard
    tcg_out_mov(s, r0, addr_reg);
810 c896fe29 bellard
    
811 c896fe29 bellard
#if TARGET_LONG_BITS == 32
812 c896fe29 bellard
    /* je label1 */
813 c896fe29 bellard
    tcg_out8(s, 0x70 + JCC_JE);
814 c896fe29 bellard
    label1_ptr = s->code_ptr;
815 c896fe29 bellard
    s->code_ptr++;
816 c896fe29 bellard
#else
817 c896fe29 bellard
    /* jne label3 */
818 c896fe29 bellard
    tcg_out8(s, 0x70 + JCC_JNE);
819 c896fe29 bellard
    label3_ptr = s->code_ptr;
820 c896fe29 bellard
    s->code_ptr++;
821 c896fe29 bellard
    
822 c896fe29 bellard
    /* cmp 4(r1), addr_reg2 */
823 c896fe29 bellard
    tcg_out_modrm_offset(s, 0x3b, addr_reg2, r1, 4);
824 c896fe29 bellard
825 c896fe29 bellard
    /* je label1 */
826 c896fe29 bellard
    tcg_out8(s, 0x70 + JCC_JE);
827 c896fe29 bellard
    label1_ptr = s->code_ptr;
828 c896fe29 bellard
    s->code_ptr++;
829 c896fe29 bellard
    
830 c896fe29 bellard
    /* label3: */
831 c896fe29 bellard
    *label3_ptr = s->code_ptr - label3_ptr - 1;
832 c896fe29 bellard
#endif
833 c896fe29 bellard
834 c896fe29 bellard
    /* XXX: move that code at the end of the TB */
835 c896fe29 bellard
#if TARGET_LONG_BITS == 32
836 c896fe29 bellard
    if (opc == 3) {
837 c896fe29 bellard
        tcg_out_mov(s, TCG_REG_EDX, data_reg);
838 c896fe29 bellard
        tcg_out_mov(s, TCG_REG_ECX, data_reg2);
839 c896fe29 bellard
        tcg_out8(s, 0x6a); /* push Ib */
840 c896fe29 bellard
        tcg_out8(s, mem_index);
841 c896fe29 bellard
        tcg_out8(s, 0xe8);
842 c896fe29 bellard
        tcg_out32(s, (tcg_target_long)qemu_st_helpers[s_bits] - 
843 c896fe29 bellard
                  (tcg_target_long)s->code_ptr - 4);
844 c896fe29 bellard
        tcg_out_addi(s, TCG_REG_ESP, 4);
845 c896fe29 bellard
    } else {
846 c896fe29 bellard
        switch(opc) {
847 c896fe29 bellard
        case 0:
848 c896fe29 bellard
            /* movzbl */
849 c896fe29 bellard
            tcg_out_modrm(s, 0xb6 | P_EXT, TCG_REG_EDX, data_reg);
850 c896fe29 bellard
            break;
851 c896fe29 bellard
        case 1:
852 c896fe29 bellard
            /* movzwl */
853 c896fe29 bellard
            tcg_out_modrm(s, 0xb7 | P_EXT, TCG_REG_EDX, data_reg);
854 c896fe29 bellard
            break;
855 c896fe29 bellard
        case 2:
856 c896fe29 bellard
            tcg_out_mov(s, TCG_REG_EDX, data_reg);
857 c896fe29 bellard
            break;
858 c896fe29 bellard
        }
859 c896fe29 bellard
        tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_ECX, mem_index);
860 c896fe29 bellard
        tcg_out8(s, 0xe8);
861 c896fe29 bellard
        tcg_out32(s, (tcg_target_long)qemu_st_helpers[s_bits] - 
862 c896fe29 bellard
                  (tcg_target_long)s->code_ptr - 4);
863 c896fe29 bellard
    }
864 c896fe29 bellard
#else
865 c896fe29 bellard
    if (opc == 3) {
866 c896fe29 bellard
        tcg_out_mov(s, TCG_REG_EDX, addr_reg2);
867 c896fe29 bellard
        tcg_out8(s, 0x6a); /* push Ib */
868 c896fe29 bellard
        tcg_out8(s, mem_index);
869 c896fe29 bellard
        tcg_out_opc(s, 0x50 + data_reg2); /* push */
870 c896fe29 bellard
        tcg_out_opc(s, 0x50 + data_reg); /* push */
871 c896fe29 bellard
        tcg_out8(s, 0xe8);
872 c896fe29 bellard
        tcg_out32(s, (tcg_target_long)qemu_st_helpers[s_bits] - 
873 c896fe29 bellard
                  (tcg_target_long)s->code_ptr - 4);
874 c896fe29 bellard
        tcg_out_addi(s, TCG_REG_ESP, 12);
875 c896fe29 bellard
    } else {
876 c896fe29 bellard
        tcg_out_mov(s, TCG_REG_EDX, addr_reg2);
877 c896fe29 bellard
        switch(opc) {
878 c896fe29 bellard
        case 0:
879 c896fe29 bellard
            /* movzbl */
880 c896fe29 bellard
            tcg_out_modrm(s, 0xb6 | P_EXT, TCG_REG_ECX, data_reg);
881 c896fe29 bellard
            break;
882 c896fe29 bellard
        case 1:
883 c896fe29 bellard
            /* movzwl */
884 c896fe29 bellard
            tcg_out_modrm(s, 0xb7 | P_EXT, TCG_REG_ECX, data_reg);
885 c896fe29 bellard
            break;
886 c896fe29 bellard
        case 2:
887 c896fe29 bellard
            tcg_out_mov(s, TCG_REG_ECX, data_reg);
888 c896fe29 bellard
            break;
889 c896fe29 bellard
        }
890 c896fe29 bellard
        tcg_out8(s, 0x6a); /* push Ib */
891 c896fe29 bellard
        tcg_out8(s, mem_index);
892 c896fe29 bellard
        tcg_out8(s, 0xe8);
893 c896fe29 bellard
        tcg_out32(s, (tcg_target_long)qemu_st_helpers[s_bits] - 
894 c896fe29 bellard
                  (tcg_target_long)s->code_ptr - 4);
895 c896fe29 bellard
        tcg_out_addi(s, TCG_REG_ESP, 4);
896 c896fe29 bellard
    }
897 c896fe29 bellard
#endif
898 c896fe29 bellard
    
899 c896fe29 bellard
    /* jmp label2 */
900 c896fe29 bellard
    tcg_out8(s, 0xeb);
901 c896fe29 bellard
    label2_ptr = s->code_ptr;
902 c896fe29 bellard
    s->code_ptr++;
903 c896fe29 bellard
    
904 c896fe29 bellard
    /* label1: */
905 c896fe29 bellard
    *label1_ptr = s->code_ptr - label1_ptr - 1;
906 c896fe29 bellard
907 c896fe29 bellard
    /* add x(r1), r0 */
908 c896fe29 bellard
    tcg_out_modrm_offset(s, 0x03, r0, r1, offsetof(CPUTLBEntry, addend) - 
909 c896fe29 bellard
                         offsetof(CPUTLBEntry, addr_write));
910 c896fe29 bellard
#else
911 c896fe29 bellard
    r0 = addr_reg;
912 c896fe29 bellard
#endif
913 c896fe29 bellard
914 c896fe29 bellard
#ifdef TARGET_WORDS_BIGENDIAN
915 c896fe29 bellard
    bswap = 1;
916 c896fe29 bellard
#else
917 c896fe29 bellard
    bswap = 0;
918 c896fe29 bellard
#endif
919 c896fe29 bellard
    switch(opc) {
920 c896fe29 bellard
    case 0:
921 c896fe29 bellard
        /* movb */
922 379f6698 Paul Brook
        tcg_out_modrm_offset(s, 0x88, data_reg, r0, GUEST_BASE);
923 c896fe29 bellard
        break;
924 c896fe29 bellard
    case 1:
925 c896fe29 bellard
        if (bswap) {
926 c896fe29 bellard
            tcg_out_mov(s, r1, data_reg);
927 c896fe29 bellard
            tcg_out8(s, 0x66); /* rolw $8, %ecx */
928 c896fe29 bellard
            tcg_out_modrm(s, 0xc1, 0, r1);
929 c896fe29 bellard
            tcg_out8(s, 8);
930 c896fe29 bellard
            data_reg = r1;
931 c896fe29 bellard
        }
932 c896fe29 bellard
        /* movw */
933 c896fe29 bellard
        tcg_out8(s, 0x66);
934 379f6698 Paul Brook
        tcg_out_modrm_offset(s, 0x89, data_reg, r0, GUEST_BASE);
935 c896fe29 bellard
        break;
936 c896fe29 bellard
    case 2:
937 c896fe29 bellard
        if (bswap) {
938 c896fe29 bellard
            tcg_out_mov(s, r1, data_reg);
939 c896fe29 bellard
            /* bswap data_reg */
940 c896fe29 bellard
            tcg_out_opc(s, (0xc8 + r1) | P_EXT);
941 c896fe29 bellard
            data_reg = r1;
942 c896fe29 bellard
        }
943 c896fe29 bellard
        /* movl */
944 379f6698 Paul Brook
        tcg_out_modrm_offset(s, 0x89, data_reg, r0, GUEST_BASE);
945 c896fe29 bellard
        break;
946 c896fe29 bellard
    case 3:
947 c896fe29 bellard
        if (bswap) {
948 c896fe29 bellard
            tcg_out_mov(s, r1, data_reg2);
949 c896fe29 bellard
            /* bswap data_reg */
950 c896fe29 bellard
            tcg_out_opc(s, (0xc8 + r1) | P_EXT);
951 379f6698 Paul Brook
            tcg_out_modrm_offset(s, 0x89, r1, r0, GUEST_BASE);
952 c896fe29 bellard
            tcg_out_mov(s, r1, data_reg);
953 c896fe29 bellard
            /* bswap data_reg */
954 c896fe29 bellard
            tcg_out_opc(s, (0xc8 + r1) | P_EXT);
955 379f6698 Paul Brook
            tcg_out_modrm_offset(s, 0x89, r1, r0, GUEST_BASE + 4);
956 c896fe29 bellard
        } else {
957 379f6698 Paul Brook
            tcg_out_modrm_offset(s, 0x89, data_reg, r0, GUEST_BASE);
958 379f6698 Paul Brook
            tcg_out_modrm_offset(s, 0x89, data_reg2, r0, GUEST_BASE + 4);
959 c896fe29 bellard
        }
960 c896fe29 bellard
        break;
961 c896fe29 bellard
    default:
962 c896fe29 bellard
        tcg_abort();
963 c896fe29 bellard
    }
964 c896fe29 bellard
965 c896fe29 bellard
#if defined(CONFIG_SOFTMMU)
966 c896fe29 bellard
    /* label2: */
967 c896fe29 bellard
    *label2_ptr = s->code_ptr - label2_ptr - 1;
968 c896fe29 bellard
#endif
969 c896fe29 bellard
}
970 c896fe29 bellard
971 c896fe29 bellard
static inline void tcg_out_op(TCGContext *s, int opc, 
972 c896fe29 bellard
                              const TCGArg *args, const int *const_args)
973 c896fe29 bellard
{
974 c896fe29 bellard
    int c;
975 c896fe29 bellard
    
976 c896fe29 bellard
    switch(opc) {
977 c896fe29 bellard
    case INDEX_op_exit_tb:
978 c896fe29 bellard
        tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_EAX, args[0]);
979 b03cce8e bellard
        tcg_out8(s, 0xe9); /* jmp tb_ret_addr */
980 b03cce8e bellard
        tcg_out32(s, tb_ret_addr - s->code_ptr - 4);
981 c896fe29 bellard
        break;
982 c896fe29 bellard
    case INDEX_op_goto_tb:
983 c896fe29 bellard
        if (s->tb_jmp_offset) {
984 c896fe29 bellard
            /* direct jump method */
985 c896fe29 bellard
            tcg_out8(s, 0xe9); /* jmp im */
986 c896fe29 bellard
            s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
987 c896fe29 bellard
            tcg_out32(s, 0);
988 c896fe29 bellard
        } else {
989 c896fe29 bellard
            /* indirect jump method */
990 c896fe29 bellard
            /* jmp Ev */
991 c896fe29 bellard
            tcg_out_modrm_offset(s, 0xff, 4, -1, 
992 c896fe29 bellard
                                 (tcg_target_long)(s->tb_next + args[0]));
993 c896fe29 bellard
        }
994 c896fe29 bellard
        s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
995 c896fe29 bellard
        break;
996 c896fe29 bellard
    case INDEX_op_call:
997 c896fe29 bellard
        if (const_args[0]) {
998 c896fe29 bellard
            tcg_out8(s, 0xe8);
999 c896fe29 bellard
            tcg_out32(s, args[0] - (tcg_target_long)s->code_ptr - 4);
1000 c896fe29 bellard
        } else {
1001 c896fe29 bellard
            tcg_out_modrm(s, 0xff, 2, args[0]);
1002 c896fe29 bellard
        }
1003 c896fe29 bellard
        break;
1004 c896fe29 bellard
    case INDEX_op_jmp:
1005 c896fe29 bellard
        if (const_args[0]) {
1006 c896fe29 bellard
            tcg_out8(s, 0xe9);
1007 c896fe29 bellard
            tcg_out32(s, args[0] - (tcg_target_long)s->code_ptr - 4);
1008 c896fe29 bellard
        } else {
1009 c896fe29 bellard
            tcg_out_modrm(s, 0xff, 4, args[0]);
1010 c896fe29 bellard
        }
1011 c896fe29 bellard
        break;
1012 c896fe29 bellard
    case INDEX_op_br:
1013 f75b56c1 Richard Henderson
        tcg_out_jxx(s, JCC_JMP, args[0], 0);
1014 c896fe29 bellard
        break;
1015 c896fe29 bellard
    case INDEX_op_movi_i32:
1016 c896fe29 bellard
        tcg_out_movi(s, TCG_TYPE_I32, args[0], args[1]);
1017 c896fe29 bellard
        break;
1018 c896fe29 bellard
    case INDEX_op_ld8u_i32:
1019 c896fe29 bellard
        /* movzbl */
1020 c896fe29 bellard
        tcg_out_modrm_offset(s, 0xb6 | P_EXT, args[0], args[1], args[2]);
1021 c896fe29 bellard
        break;
1022 c896fe29 bellard
    case INDEX_op_ld8s_i32:
1023 c896fe29 bellard
        /* movsbl */
1024 c896fe29 bellard
        tcg_out_modrm_offset(s, 0xbe | P_EXT, args[0], args[1], args[2]);
1025 c896fe29 bellard
        break;
1026 c896fe29 bellard
    case INDEX_op_ld16u_i32:
1027 c896fe29 bellard
        /* movzwl */
1028 c896fe29 bellard
        tcg_out_modrm_offset(s, 0xb7 | P_EXT, args[0], args[1], args[2]);
1029 c896fe29 bellard
        break;
1030 c896fe29 bellard
    case INDEX_op_ld16s_i32:
1031 c896fe29 bellard
        /* movswl */
1032 c896fe29 bellard
        tcg_out_modrm_offset(s, 0xbf | P_EXT, args[0], args[1], args[2]);
1033 c896fe29 bellard
        break;
1034 c896fe29 bellard
    case INDEX_op_ld_i32:
1035 c896fe29 bellard
        /* movl */
1036 c896fe29 bellard
        tcg_out_modrm_offset(s, 0x8b, args[0], args[1], args[2]);
1037 c896fe29 bellard
        break;
1038 c896fe29 bellard
    case INDEX_op_st8_i32:
1039 c896fe29 bellard
        /* movb */
1040 c896fe29 bellard
        tcg_out_modrm_offset(s, 0x88, args[0], args[1], args[2]);
1041 c896fe29 bellard
        break;
1042 c896fe29 bellard
    case INDEX_op_st16_i32:
1043 c896fe29 bellard
        /* movw */
1044 c896fe29 bellard
        tcg_out8(s, 0x66);
1045 c896fe29 bellard
        tcg_out_modrm_offset(s, 0x89, args[0], args[1], args[2]);
1046 c896fe29 bellard
        break;
1047 c896fe29 bellard
    case INDEX_op_st_i32:
1048 c896fe29 bellard
        /* movl */
1049 c896fe29 bellard
        tcg_out_modrm_offset(s, 0x89, args[0], args[1], args[2]);
1050 c896fe29 bellard
        break;
1051 c896fe29 bellard
    case INDEX_op_sub_i32:
1052 c896fe29 bellard
        c = ARITH_SUB;
1053 c896fe29 bellard
        goto gen_arith;
1054 c896fe29 bellard
    case INDEX_op_and_i32:
1055 c896fe29 bellard
        c = ARITH_AND;
1056 c896fe29 bellard
        goto gen_arith;
1057 c896fe29 bellard
    case INDEX_op_or_i32:
1058 c896fe29 bellard
        c = ARITH_OR;
1059 c896fe29 bellard
        goto gen_arith;
1060 c896fe29 bellard
    case INDEX_op_xor_i32:
1061 c896fe29 bellard
        c = ARITH_XOR;
1062 c896fe29 bellard
        goto gen_arith;
1063 c896fe29 bellard
    case INDEX_op_add_i32:
1064 c896fe29 bellard
        c = ARITH_ADD;
1065 c896fe29 bellard
    gen_arith:
1066 c896fe29 bellard
        if (const_args[2]) {
1067 17cf428f Aurelien Jarno
            tgen_arithi(s, c, args[0], args[2], 0);
1068 c896fe29 bellard
        } else {
1069 c896fe29 bellard
            tcg_out_modrm(s, 0x01 | (c << 3), args[2], args[0]);
1070 c896fe29 bellard
        }
1071 c896fe29 bellard
        break;
1072 c896fe29 bellard
    case INDEX_op_mul_i32:
1073 c896fe29 bellard
        if (const_args[2]) {
1074 c896fe29 bellard
            int32_t val;
1075 c896fe29 bellard
            val = args[2];
1076 c896fe29 bellard
            if (val == (int8_t)val) {
1077 c896fe29 bellard
                tcg_out_modrm(s, 0x6b, args[0], args[0]);
1078 c896fe29 bellard
                tcg_out8(s, val);
1079 c896fe29 bellard
            } else {
1080 c896fe29 bellard
                tcg_out_modrm(s, 0x69, args[0], args[0]);
1081 c896fe29 bellard
                tcg_out32(s, val);
1082 c896fe29 bellard
            }
1083 c896fe29 bellard
        } else {
1084 c896fe29 bellard
            tcg_out_modrm(s, 0xaf | P_EXT, args[0], args[2]);
1085 c896fe29 bellard
        }
1086 c896fe29 bellard
        break;
1087 c896fe29 bellard
    case INDEX_op_mulu2_i32:
1088 c896fe29 bellard
        tcg_out_modrm(s, 0xf7, 4, args[3]);
1089 c896fe29 bellard
        break;
1090 c896fe29 bellard
    case INDEX_op_div2_i32:
1091 c896fe29 bellard
        tcg_out_modrm(s, 0xf7, 7, args[4]);
1092 c896fe29 bellard
        break;
1093 c896fe29 bellard
    case INDEX_op_divu2_i32:
1094 c896fe29 bellard
        tcg_out_modrm(s, 0xf7, 6, args[4]);
1095 c896fe29 bellard
        break;
1096 c896fe29 bellard
    case INDEX_op_shl_i32:
1097 c896fe29 bellard
        c = SHIFT_SHL;
1098 c896fe29 bellard
    gen_shift32:
1099 c896fe29 bellard
        if (const_args[2]) {
1100 c896fe29 bellard
            if (args[2] == 1) {
1101 c896fe29 bellard
                tcg_out_modrm(s, 0xd1, c, args[0]);
1102 c896fe29 bellard
            } else {
1103 c896fe29 bellard
                tcg_out_modrm(s, 0xc1, c, args[0]);
1104 c896fe29 bellard
                tcg_out8(s, args[2]);
1105 c896fe29 bellard
            }
1106 c896fe29 bellard
        } else {
1107 c896fe29 bellard
            tcg_out_modrm(s, 0xd3, c, args[0]);
1108 c896fe29 bellard
        }
1109 c896fe29 bellard
        break;
1110 c896fe29 bellard
    case INDEX_op_shr_i32:
1111 c896fe29 bellard
        c = SHIFT_SHR;
1112 c896fe29 bellard
        goto gen_shift32;
1113 c896fe29 bellard
    case INDEX_op_sar_i32:
1114 c896fe29 bellard
        c = SHIFT_SAR;
1115 c896fe29 bellard
        goto gen_shift32;
1116 9619376c aurel32
    case INDEX_op_rotl_i32:
1117 9619376c aurel32
        c = SHIFT_ROL;
1118 9619376c aurel32
        goto gen_shift32;
1119 9619376c aurel32
    case INDEX_op_rotr_i32:
1120 9619376c aurel32
        c = SHIFT_ROR;
1121 9619376c aurel32
        goto gen_shift32;
1122 9619376c aurel32
1123 c896fe29 bellard
    case INDEX_op_add2_i32:
1124 c896fe29 bellard
        if (const_args[4]) 
1125 17cf428f Aurelien Jarno
            tgen_arithi(s, ARITH_ADD, args[0], args[4], 1);
1126 c896fe29 bellard
        else
1127 c896fe29 bellard
            tcg_out_modrm(s, 0x01 | (ARITH_ADD << 3), args[4], args[0]);
1128 c896fe29 bellard
        if (const_args[5]) 
1129 17cf428f Aurelien Jarno
            tgen_arithi(s, ARITH_ADC, args[1], args[5], 1);
1130 c896fe29 bellard
        else
1131 c896fe29 bellard
            tcg_out_modrm(s, 0x01 | (ARITH_ADC << 3), args[5], args[1]);
1132 c896fe29 bellard
        break;
1133 c896fe29 bellard
    case INDEX_op_sub2_i32:
1134 c896fe29 bellard
        if (const_args[4]) 
1135 17cf428f Aurelien Jarno
            tgen_arithi(s, ARITH_SUB, args[0], args[4], 1);
1136 c896fe29 bellard
        else
1137 c896fe29 bellard
            tcg_out_modrm(s, 0x01 | (ARITH_SUB << 3), args[4], args[0]);
1138 c896fe29 bellard
        if (const_args[5]) 
1139 17cf428f Aurelien Jarno
            tgen_arithi(s, ARITH_SBB, args[1], args[5], 1);
1140 c896fe29 bellard
        else
1141 c896fe29 bellard
            tcg_out_modrm(s, 0x01 | (ARITH_SBB << 3), args[5], args[1]);
1142 c896fe29 bellard
        break;
1143 c896fe29 bellard
    case INDEX_op_brcond_i32:
1144 f75b56c1 Richard Henderson
        tcg_out_brcond(s, args[2], args[0], args[1], const_args[1],
1145 f75b56c1 Richard Henderson
                       args[3], 0);
1146 c896fe29 bellard
        break;
1147 c896fe29 bellard
    case INDEX_op_brcond2_i32:
1148 f75b56c1 Richard Henderson
        tcg_out_brcond2(s, args, const_args, 0);
1149 c896fe29 bellard
        break;
1150 c896fe29 bellard
1151 5d40cd63 aurel32
    case INDEX_op_bswap16_i32:
1152 5d40cd63 aurel32
        tcg_out8(s, 0x66);
1153 5d40cd63 aurel32
        tcg_out_modrm(s, 0xc1, SHIFT_ROL, args[0]);
1154 5d40cd63 aurel32
        tcg_out8(s, 8);
1155 5d40cd63 aurel32
        break;
1156 66896cb8 aurel32
    case INDEX_op_bswap32_i32:
1157 9619376c aurel32
        tcg_out_opc(s, (0xc8 + args[0]) | P_EXT);
1158 9619376c aurel32
        break;
1159 9619376c aurel32
1160 9619376c aurel32
    case INDEX_op_neg_i32:
1161 9619376c aurel32
        tcg_out_modrm(s, 0xf7, 3, args[0]);
1162 9619376c aurel32
        break;
1163 9619376c aurel32
1164 9619376c aurel32
    case INDEX_op_not_i32:
1165 9619376c aurel32
        tcg_out_modrm(s, 0xf7, 2, args[0]);
1166 9619376c aurel32
        break;
1167 9619376c aurel32
1168 9619376c aurel32
    case INDEX_op_ext8s_i32:
1169 9619376c aurel32
        tcg_out_modrm(s, 0xbe | P_EXT, args[0], args[1]);
1170 9619376c aurel32
        break;
1171 9619376c aurel32
    case INDEX_op_ext16s_i32:
1172 9619376c aurel32
        tcg_out_modrm(s, 0xbf | P_EXT, args[0], args[1]);
1173 9619376c aurel32
        break;
1174 5f0ce17f Aurelien Jarno
    case INDEX_op_ext8u_i32:
1175 5f0ce17f Aurelien Jarno
        tcg_out_modrm(s, 0xb6 | P_EXT, args[0], args[1]);
1176 5f0ce17f Aurelien Jarno
        break;
1177 5f0ce17f Aurelien Jarno
    case INDEX_op_ext16u_i32:
1178 5f0ce17f Aurelien Jarno
        tcg_out_modrm(s, 0xb7 | P_EXT, args[0], args[1]);
1179 5f0ce17f Aurelien Jarno
        break;
1180 9619376c aurel32
1181 1d2699ae Richard Henderson
    case INDEX_op_setcond_i32:
1182 1d2699ae Richard Henderson
        tcg_out_setcond(s, args[3], args[0], args[1], args[2], const_args[2]);
1183 1d2699ae Richard Henderson
        break;
1184 1d2699ae Richard Henderson
    case INDEX_op_setcond2_i32:
1185 1d2699ae Richard Henderson
        tcg_out_setcond2(s, args, const_args);
1186 1d2699ae Richard Henderson
        break;
1187 1d2699ae Richard Henderson
1188 c896fe29 bellard
    case INDEX_op_qemu_ld8u:
1189 c896fe29 bellard
        tcg_out_qemu_ld(s, args, 0);
1190 c896fe29 bellard
        break;
1191 c896fe29 bellard
    case INDEX_op_qemu_ld8s:
1192 c896fe29 bellard
        tcg_out_qemu_ld(s, args, 0 | 4);
1193 c896fe29 bellard
        break;
1194 c896fe29 bellard
    case INDEX_op_qemu_ld16u:
1195 c896fe29 bellard
        tcg_out_qemu_ld(s, args, 1);
1196 c896fe29 bellard
        break;
1197 c896fe29 bellard
    case INDEX_op_qemu_ld16s:
1198 c896fe29 bellard
        tcg_out_qemu_ld(s, args, 1 | 4);
1199 c896fe29 bellard
        break;
1200 c896fe29 bellard
    case INDEX_op_qemu_ld32u:
1201 c896fe29 bellard
        tcg_out_qemu_ld(s, args, 2);
1202 c896fe29 bellard
        break;
1203 c896fe29 bellard
    case INDEX_op_qemu_ld64:
1204 c896fe29 bellard
        tcg_out_qemu_ld(s, args, 3);
1205 c896fe29 bellard
        break;
1206 c896fe29 bellard
        
1207 c896fe29 bellard
    case INDEX_op_qemu_st8:
1208 c896fe29 bellard
        tcg_out_qemu_st(s, args, 0);
1209 c896fe29 bellard
        break;
1210 c896fe29 bellard
    case INDEX_op_qemu_st16:
1211 c896fe29 bellard
        tcg_out_qemu_st(s, args, 1);
1212 c896fe29 bellard
        break;
1213 c896fe29 bellard
    case INDEX_op_qemu_st32:
1214 c896fe29 bellard
        tcg_out_qemu_st(s, args, 2);
1215 c896fe29 bellard
        break;
1216 c896fe29 bellard
    case INDEX_op_qemu_st64:
1217 c896fe29 bellard
        tcg_out_qemu_st(s, args, 3);
1218 c896fe29 bellard
        break;
1219 c896fe29 bellard
1220 c896fe29 bellard
    default:
1221 c896fe29 bellard
        tcg_abort();
1222 c896fe29 bellard
    }
1223 c896fe29 bellard
}
1224 c896fe29 bellard
1225 c896fe29 bellard
static const TCGTargetOpDef x86_op_defs[] = {
1226 c896fe29 bellard
    { INDEX_op_exit_tb, { } },
1227 c896fe29 bellard
    { INDEX_op_goto_tb, { } },
1228 c896fe29 bellard
    { INDEX_op_call, { "ri" } },
1229 c896fe29 bellard
    { INDEX_op_jmp, { "ri" } },
1230 c896fe29 bellard
    { INDEX_op_br, { } },
1231 c896fe29 bellard
    { INDEX_op_mov_i32, { "r", "r" } },
1232 c896fe29 bellard
    { INDEX_op_movi_i32, { "r" } },
1233 c896fe29 bellard
    { INDEX_op_ld8u_i32, { "r", "r" } },
1234 c896fe29 bellard
    { INDEX_op_ld8s_i32, { "r", "r" } },
1235 c896fe29 bellard
    { INDEX_op_ld16u_i32, { "r", "r" } },
1236 c896fe29 bellard
    { INDEX_op_ld16s_i32, { "r", "r" } },
1237 c896fe29 bellard
    { INDEX_op_ld_i32, { "r", "r" } },
1238 c896fe29 bellard
    { INDEX_op_st8_i32, { "q", "r" } },
1239 c896fe29 bellard
    { INDEX_op_st16_i32, { "r", "r" } },
1240 c896fe29 bellard
    { INDEX_op_st_i32, { "r", "r" } },
1241 c896fe29 bellard
1242 c896fe29 bellard
    { INDEX_op_add_i32, { "r", "0", "ri" } },
1243 c896fe29 bellard
    { INDEX_op_sub_i32, { "r", "0", "ri" } },
1244 c896fe29 bellard
    { INDEX_op_mul_i32, { "r", "0", "ri" } },
1245 c896fe29 bellard
    { INDEX_op_mulu2_i32, { "a", "d", "a", "r" } },
1246 c896fe29 bellard
    { INDEX_op_div2_i32, { "a", "d", "0", "1", "r" } },
1247 c896fe29 bellard
    { INDEX_op_divu2_i32, { "a", "d", "0", "1", "r" } },
1248 c896fe29 bellard
    { INDEX_op_and_i32, { "r", "0", "ri" } },
1249 c896fe29 bellard
    { INDEX_op_or_i32, { "r", "0", "ri" } },
1250 c896fe29 bellard
    { INDEX_op_xor_i32, { "r", "0", "ri" } },
1251 c896fe29 bellard
1252 c896fe29 bellard
    { INDEX_op_shl_i32, { "r", "0", "ci" } },
1253 c896fe29 bellard
    { INDEX_op_shr_i32, { "r", "0", "ci" } },
1254 c896fe29 bellard
    { INDEX_op_sar_i32, { "r", "0", "ci" } },
1255 9619376c aurel32
    { INDEX_op_rotl_i32, { "r", "0", "ci" } },
1256 9619376c aurel32
    { INDEX_op_rotr_i32, { "r", "0", "ci" } },
1257 c896fe29 bellard
1258 c896fe29 bellard
    { INDEX_op_brcond_i32, { "r", "ri" } },
1259 c896fe29 bellard
1260 c896fe29 bellard
    { INDEX_op_add2_i32, { "r", "r", "0", "1", "ri", "ri" } },
1261 c896fe29 bellard
    { INDEX_op_sub2_i32, { "r", "r", "0", "1", "ri", "ri" } },
1262 c896fe29 bellard
    { INDEX_op_brcond2_i32, { "r", "r", "ri", "ri" } },
1263 c896fe29 bellard
1264 5d40cd63 aurel32
    { INDEX_op_bswap16_i32, { "r", "0" } },
1265 66896cb8 aurel32
    { INDEX_op_bswap32_i32, { "r", "0" } },
1266 9619376c aurel32
1267 9619376c aurel32
    { INDEX_op_neg_i32, { "r", "0" } },
1268 9619376c aurel32
1269 9619376c aurel32
    { INDEX_op_not_i32, { "r", "0" } },
1270 9619376c aurel32
1271 9619376c aurel32
    { INDEX_op_ext8s_i32, { "r", "q" } },
1272 9619376c aurel32
    { INDEX_op_ext16s_i32, { "r", "r" } },
1273 5f0ce17f Aurelien Jarno
    { INDEX_op_ext8u_i32, { "r", "q"} },
1274 5f0ce17f Aurelien Jarno
    { INDEX_op_ext16u_i32, { "r", "r"} },
1275 9619376c aurel32
1276 1d2699ae Richard Henderson
    { INDEX_op_setcond_i32, { "q", "r", "ri" } },
1277 1d2699ae Richard Henderson
    { INDEX_op_setcond2_i32, { "r", "r", "r", "ri", "ri" } },
1278 1d2699ae Richard Henderson
1279 c896fe29 bellard
#if TARGET_LONG_BITS == 32
1280 c896fe29 bellard
    { INDEX_op_qemu_ld8u, { "r", "L" } },
1281 c896fe29 bellard
    { INDEX_op_qemu_ld8s, { "r", "L" } },
1282 c896fe29 bellard
    { INDEX_op_qemu_ld16u, { "r", "L" } },
1283 c896fe29 bellard
    { INDEX_op_qemu_ld16s, { "r", "L" } },
1284 c896fe29 bellard
    { INDEX_op_qemu_ld32u, { "r", "L" } },
1285 c896fe29 bellard
    { INDEX_op_qemu_ld64, { "r", "r", "L" } },
1286 c896fe29 bellard
1287 c896fe29 bellard
    { INDEX_op_qemu_st8, { "cb", "L" } },
1288 c896fe29 bellard
    { INDEX_op_qemu_st16, { "L", "L" } },
1289 c896fe29 bellard
    { INDEX_op_qemu_st32, { "L", "L" } },
1290 c896fe29 bellard
    { INDEX_op_qemu_st64, { "L", "L", "L" } },
1291 c896fe29 bellard
#else
1292 c896fe29 bellard
    { INDEX_op_qemu_ld8u, { "r", "L", "L" } },
1293 c896fe29 bellard
    { INDEX_op_qemu_ld8s, { "r", "L", "L" } },
1294 c896fe29 bellard
    { INDEX_op_qemu_ld16u, { "r", "L", "L" } },
1295 c896fe29 bellard
    { INDEX_op_qemu_ld16s, { "r", "L", "L" } },
1296 c896fe29 bellard
    { INDEX_op_qemu_ld32u, { "r", "L", "L" } },
1297 c896fe29 bellard
    { INDEX_op_qemu_ld64, { "r", "r", "L", "L" } },
1298 c896fe29 bellard
1299 c896fe29 bellard
    { INDEX_op_qemu_st8, { "cb", "L", "L" } },
1300 c896fe29 bellard
    { INDEX_op_qemu_st16, { "L", "L", "L" } },
1301 c896fe29 bellard
    { INDEX_op_qemu_st32, { "L", "L", "L" } },
1302 c896fe29 bellard
    { INDEX_op_qemu_st64, { "L", "L", "L", "L" } },
1303 c896fe29 bellard
#endif
1304 c896fe29 bellard
    { -1 },
1305 c896fe29 bellard
};
1306 c896fe29 bellard
1307 b03cce8e bellard
static int tcg_target_callee_save_regs[] = {
1308 b03cce8e bellard
    /*    TCG_REG_EBP, */ /* currently used for the global env, so no
1309 b03cce8e bellard
                             need to save */
1310 b03cce8e bellard
    TCG_REG_EBX,
1311 b03cce8e bellard
    TCG_REG_ESI,
1312 b03cce8e bellard
    TCG_REG_EDI,
1313 b03cce8e bellard
};
1314 b03cce8e bellard
1315 b03cce8e bellard
static inline void tcg_out_push(TCGContext *s, int reg)
1316 b03cce8e bellard
{
1317 b03cce8e bellard
    tcg_out_opc(s, 0x50 + reg);
1318 b03cce8e bellard
}
1319 b03cce8e bellard
1320 b03cce8e bellard
static inline void tcg_out_pop(TCGContext *s, int reg)
1321 b03cce8e bellard
{
1322 b03cce8e bellard
    tcg_out_opc(s, 0x58 + reg);
1323 b03cce8e bellard
}
1324 b03cce8e bellard
1325 b03cce8e bellard
/* Generate global QEMU prologue and epilogue code */
1326 b03cce8e bellard
void tcg_target_qemu_prologue(TCGContext *s)
1327 b03cce8e bellard
{
1328 b03cce8e bellard
    int i, frame_size, push_size, stack_addend;
1329 b03cce8e bellard
    
1330 b03cce8e bellard
    /* TB prologue */
1331 b03cce8e bellard
    /* save all callee saved registers */
1332 b03cce8e bellard
    for(i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
1333 b03cce8e bellard
        tcg_out_push(s, tcg_target_callee_save_regs[i]);
1334 b03cce8e bellard
    }
1335 b03cce8e bellard
    /* reserve some stack space */
1336 b03cce8e bellard
    push_size = 4 + ARRAY_SIZE(tcg_target_callee_save_regs) * 4;
1337 b03cce8e bellard
    frame_size = push_size + TCG_STATIC_CALL_ARGS_SIZE;
1338 b03cce8e bellard
    frame_size = (frame_size + TCG_TARGET_STACK_ALIGN - 1) & 
1339 b03cce8e bellard
        ~(TCG_TARGET_STACK_ALIGN - 1);
1340 b03cce8e bellard
    stack_addend = frame_size - push_size;
1341 b03cce8e bellard
    tcg_out_addi(s, TCG_REG_ESP, -stack_addend);
1342 b03cce8e bellard
1343 b03cce8e bellard
    tcg_out_modrm(s, 0xff, 4, TCG_REG_EAX); /* jmp *%eax */
1344 b03cce8e bellard
    
1345 b03cce8e bellard
    /* TB epilogue */
1346 b03cce8e bellard
    tb_ret_addr = s->code_ptr;
1347 b03cce8e bellard
    tcg_out_addi(s, TCG_REG_ESP, stack_addend);
1348 b03cce8e bellard
    for(i = ARRAY_SIZE(tcg_target_callee_save_regs) - 1; i >= 0; i--) {
1349 b03cce8e bellard
        tcg_out_pop(s, tcg_target_callee_save_regs[i]);
1350 b03cce8e bellard
    }
1351 b03cce8e bellard
    tcg_out8(s, 0xc3); /* ret */
1352 b03cce8e bellard
}
1353 b03cce8e bellard
1354 c896fe29 bellard
void tcg_target_init(TCGContext *s)
1355 c896fe29 bellard
{
1356 c896fe29 bellard
    /* fail safe */
1357 c896fe29 bellard
    if ((1 << CPU_TLB_ENTRY_BITS) != sizeof(CPUTLBEntry))
1358 c896fe29 bellard
        tcg_abort();
1359 c896fe29 bellard
1360 c896fe29 bellard
    tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xff);
1361 c896fe29 bellard
    tcg_regset_set32(tcg_target_call_clobber_regs, 0,
1362 c896fe29 bellard
                     (1 << TCG_REG_EAX) | 
1363 c896fe29 bellard
                     (1 << TCG_REG_EDX) | 
1364 c896fe29 bellard
                     (1 << TCG_REG_ECX));
1365 c896fe29 bellard
    
1366 c896fe29 bellard
    tcg_regset_clear(s->reserved_regs);
1367 c896fe29 bellard
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_ESP);
1368 c896fe29 bellard
1369 c896fe29 bellard
    tcg_add_target_add_op_defs(x86_op_defs);
1370 c896fe29 bellard
}