Statistics
| Branch: | Revision:

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

History | View | Annotate | Download (43.9 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_EBX,
40 c896fe29 bellard
    TCG_REG_ESI,
41 c896fe29 bellard
    TCG_REG_EDI,
42 c896fe29 bellard
    TCG_REG_EBP,
43 6648e296 Richard Henderson
    TCG_REG_ECX,
44 6648e296 Richard Henderson
    TCG_REG_EDX,
45 6648e296 Richard Henderson
    TCG_REG_EAX,
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 78686523 Richard Henderson
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 96b4cf38 Richard Henderson
#define P_EXT                0x100                /* 0x0f opcode prefix */
160 96b4cf38 Richard Henderson
#define P_DATA16        0x200                /* 0x66 opcode prefix */
161 fcb5dac1 Richard Henderson
162 a369a702 Richard Henderson
#define OPC_ARITH_EvIz        (0x81)
163 a369a702 Richard Henderson
#define OPC_ARITH_EvIb        (0x83)
164 81570a70 Richard Henderson
#define OPC_ARITH_GvEv        (0x03)                /* ... plus (ARITH_FOO << 3) */
165 81570a70 Richard Henderson
#define OPC_ADD_GvEv        (OPC_ARITH_GvEv | (ARITH_ADD << 3))
166 fcb5dac1 Richard Henderson
#define OPC_BSWAP        (0xc8 | P_EXT)
167 aadb21a4 Richard Henderson
#define OPC_CALL_Jz        (0xe8)
168 81570a70 Richard Henderson
#define OPC_CMP_GvEv        (OPC_ARITH_GvEv | (ARITH_CMP << 3))
169 81570a70 Richard Henderson
#define OPC_DEC_r32        (0x48)
170 0566d387 Richard Henderson
#define OPC_IMUL_GvEv        (0xaf | P_EXT)
171 0566d387 Richard Henderson
#define OPC_IMUL_GvEvIb        (0x6b)
172 0566d387 Richard Henderson
#define OPC_IMUL_GvEvIz        (0x69)
173 81570a70 Richard Henderson
#define OPC_INC_r32        (0x40)
174 da441cff Richard Henderson
#define OPC_JCC_long        (0x80 | P_EXT)        /* ... plus condition code */
175 da441cff Richard Henderson
#define OPC_JCC_short        (0x70)                /* ... plus condition code */
176 da441cff Richard Henderson
#define OPC_JMP_long        (0xe9)
177 da441cff Richard Henderson
#define OPC_JMP_short        (0xeb)
178 34a6d0b7 Richard Henderson
#define OPC_LEA         (0x8d)
179 af266089 Richard Henderson
#define OPC_MOVB_EvGv        (0x88)                /* stores, more or less */
180 af266089 Richard Henderson
#define OPC_MOVL_EvGv        (0x89)                /* stores, more or less */
181 af266089 Richard Henderson
#define OPC_MOVL_GvEv        (0x8b)                /* loads, more or less */
182 ef10b106 Richard Henderson
#define OPC_MOVL_Iv     (0xb8)
183 6817c355 Richard Henderson
#define OPC_MOVSBL        (0xbe | P_EXT)
184 6817c355 Richard Henderson
#define OPC_MOVSWL        (0xbf | P_EXT)
185 55e082a7 Richard Henderson
#define OPC_MOVZBL        (0xb6 | P_EXT)
186 55e082a7 Richard Henderson
#define OPC_MOVZWL        (0xb7 | P_EXT)
187 6858614e Richard Henderson
#define OPC_POP_r32        (0x58)
188 6858614e Richard Henderson
#define OPC_PUSH_r32        (0x50)
189 6858614e Richard Henderson
#define OPC_PUSH_Iv        (0x68)
190 6858614e Richard Henderson
#define OPC_PUSH_Ib        (0x6a)
191 3c3accc6 Richard Henderson
#define OPC_RET                (0xc3)
192 32a8ffb9 Richard Henderson
#define OPC_SETCC        (0x90 | P_EXT)        /* ... plus condition code */
193 f53dba01 Richard Henderson
#define OPC_SHIFT_1        (0xd1)
194 f53dba01 Richard Henderson
#define OPC_SHIFT_Ib        (0xc1)
195 f53dba01 Richard Henderson
#define OPC_SHIFT_cl        (0xd3)
196 81570a70 Richard Henderson
#define OPC_TESTL        (0x85)
197 b3e66df7 Richard Henderson
#define OPC_XCHG_ax_r32        (0x90)
198 fcb5dac1 Richard Henderson
199 9363dedb Richard Henderson
#define OPC_GRP3_Ev        (0xf7)
200 9363dedb Richard Henderson
#define OPC_GRP5        (0xff)
201 9363dedb Richard Henderson
202 9363dedb Richard Henderson
/* Group 1 opcode extensions for 0x80-0x83.
203 9363dedb Richard Henderson
   These are also used as modifiers for OPC_ARITH.  */
204 c896fe29 bellard
#define ARITH_ADD 0
205 c896fe29 bellard
#define ARITH_OR  1
206 c896fe29 bellard
#define ARITH_ADC 2
207 c896fe29 bellard
#define ARITH_SBB 3
208 c896fe29 bellard
#define ARITH_AND 4
209 c896fe29 bellard
#define ARITH_SUB 5
210 c896fe29 bellard
#define ARITH_XOR 6
211 c896fe29 bellard
#define ARITH_CMP 7
212 c896fe29 bellard
213 da441cff Richard Henderson
/* Group 2 opcode extensions for 0xc0, 0xc1, 0xd0-0xd3.  */
214 9619376c aurel32
#define SHIFT_ROL 0
215 9619376c aurel32
#define SHIFT_ROR 1
216 c896fe29 bellard
#define SHIFT_SHL 4
217 c896fe29 bellard
#define SHIFT_SHR 5
218 c896fe29 bellard
#define SHIFT_SAR 7
219 c896fe29 bellard
220 9363dedb Richard Henderson
/* Group 3 opcode extensions for 0xf6, 0xf7.  To be used with OPC_GRP3.  */
221 9363dedb Richard Henderson
#define EXT3_NOT   2
222 9363dedb Richard Henderson
#define EXT3_NEG   3
223 9363dedb Richard Henderson
#define EXT3_MUL   4
224 9363dedb Richard Henderson
#define EXT3_IMUL  5
225 9363dedb Richard Henderson
#define EXT3_DIV   6
226 9363dedb Richard Henderson
#define EXT3_IDIV  7
227 9363dedb Richard Henderson
228 9363dedb Richard Henderson
/* Group 5 opcode extensions for 0xff.  To be used with OPC_GRP5.  */
229 9363dedb Richard Henderson
#define EXT5_CALLN_Ev        2
230 9363dedb Richard Henderson
#define EXT5_JMPN_Ev        4
231 da441cff Richard Henderson
232 da441cff Richard Henderson
/* Condition codes to be added to OPC_JCC_{long,short}.  */
233 c896fe29 bellard
#define JCC_JMP (-1)
234 c896fe29 bellard
#define JCC_JO  0x0
235 c896fe29 bellard
#define JCC_JNO 0x1
236 c896fe29 bellard
#define JCC_JB  0x2
237 c896fe29 bellard
#define JCC_JAE 0x3
238 c896fe29 bellard
#define JCC_JE  0x4
239 c896fe29 bellard
#define JCC_JNE 0x5
240 c896fe29 bellard
#define JCC_JBE 0x6
241 c896fe29 bellard
#define JCC_JA  0x7
242 c896fe29 bellard
#define JCC_JS  0x8
243 c896fe29 bellard
#define JCC_JNS 0x9
244 c896fe29 bellard
#define JCC_JP  0xa
245 c896fe29 bellard
#define JCC_JNP 0xb
246 c896fe29 bellard
#define JCC_JL  0xc
247 c896fe29 bellard
#define JCC_JGE 0xd
248 c896fe29 bellard
#define JCC_JLE 0xe
249 c896fe29 bellard
#define JCC_JG  0xf
250 c896fe29 bellard
251 c896fe29 bellard
static const uint8_t tcg_cond_to_jcc[10] = {
252 c896fe29 bellard
    [TCG_COND_EQ] = JCC_JE,
253 c896fe29 bellard
    [TCG_COND_NE] = JCC_JNE,
254 c896fe29 bellard
    [TCG_COND_LT] = JCC_JL,
255 c896fe29 bellard
    [TCG_COND_GE] = JCC_JGE,
256 c896fe29 bellard
    [TCG_COND_LE] = JCC_JLE,
257 c896fe29 bellard
    [TCG_COND_GT] = JCC_JG,
258 c896fe29 bellard
    [TCG_COND_LTU] = JCC_JB,
259 c896fe29 bellard
    [TCG_COND_GEU] = JCC_JAE,
260 c896fe29 bellard
    [TCG_COND_LEU] = JCC_JBE,
261 c896fe29 bellard
    [TCG_COND_GTU] = JCC_JA,
262 c896fe29 bellard
};
263 c896fe29 bellard
264 c896fe29 bellard
static inline void tcg_out_opc(TCGContext *s, int opc)
265 c896fe29 bellard
{
266 96b4cf38 Richard Henderson
    if (opc & P_DATA16) {
267 96b4cf38 Richard Henderson
        tcg_out8(s, 0x66);
268 96b4cf38 Richard Henderson
    }
269 96b4cf38 Richard Henderson
    if (opc & P_EXT) {
270 c896fe29 bellard
        tcg_out8(s, 0x0f);
271 96b4cf38 Richard Henderson
    }
272 c896fe29 bellard
    tcg_out8(s, opc);
273 c896fe29 bellard
}
274 c896fe29 bellard
275 c896fe29 bellard
static inline void tcg_out_modrm(TCGContext *s, int opc, int r, int rm)
276 c896fe29 bellard
{
277 c896fe29 bellard
    tcg_out_opc(s, opc);
278 c896fe29 bellard
    tcg_out8(s, 0xc0 | (r << 3) | rm);
279 c896fe29 bellard
}
280 c896fe29 bellard
281 34a6d0b7 Richard Henderson
/* Output an opcode with a full "rm + (index<<shift) + offset" address mode.
282 34a6d0b7 Richard Henderson
   We handle either RM and INDEX missing with a -1 value.  */
283 34a6d0b7 Richard Henderson
284 34a6d0b7 Richard Henderson
static void tcg_out_modrm_sib_offset(TCGContext *s, int opc, int r, int rm,
285 34a6d0b7 Richard Henderson
                                     int index, int shift, int32_t offset)
286 c896fe29 bellard
{
287 34a6d0b7 Richard Henderson
    int mod, len;
288 34a6d0b7 Richard Henderson
289 34a6d0b7 Richard Henderson
    if (index == -1 && rm == -1) {
290 34a6d0b7 Richard Henderson
        /* Absolute address.  */
291 34a6d0b7 Richard Henderson
        tcg_out_opc(s, opc);
292 34a6d0b7 Richard Henderson
        tcg_out8(s, (r << 3) | 5);
293 34a6d0b7 Richard Henderson
        tcg_out32(s, offset);
294 34a6d0b7 Richard Henderson
        return;
295 34a6d0b7 Richard Henderson
    }
296 34a6d0b7 Richard Henderson
297 c896fe29 bellard
    tcg_out_opc(s, opc);
298 34a6d0b7 Richard Henderson
299 34a6d0b7 Richard Henderson
    /* Find the length of the immediate addend.  Note that the encoding
300 34a6d0b7 Richard Henderson
       that would be used for (%ebp) indicates absolute addressing.  */
301 c896fe29 bellard
    if (rm == -1) {
302 34a6d0b7 Richard Henderson
        mod = 0, len = 4, rm = 5;
303 c896fe29 bellard
    } else if (offset == 0 && rm != TCG_REG_EBP) {
304 34a6d0b7 Richard Henderson
        mod = 0, len = 0;
305 34a6d0b7 Richard Henderson
    } else if (offset == (int8_t)offset) {
306 34a6d0b7 Richard Henderson
        mod = 0x40, len = 1;
307 c896fe29 bellard
    } else {
308 34a6d0b7 Richard Henderson
        mod = 0x80, len = 4;
309 34a6d0b7 Richard Henderson
    }
310 34a6d0b7 Richard Henderson
311 34a6d0b7 Richard Henderson
    /* Use a single byte MODRM format if possible.  Note that the encoding
312 34a6d0b7 Richard Henderson
       that would be used for %esp is the escape to the two byte form.  */
313 34a6d0b7 Richard Henderson
    if (index == -1 && rm != TCG_REG_ESP) {
314 34a6d0b7 Richard Henderson
        /* Single byte MODRM format.  */
315 34a6d0b7 Richard Henderson
        tcg_out8(s, mod | (r << 3) | rm);
316 34a6d0b7 Richard Henderson
    } else {
317 34a6d0b7 Richard Henderson
        /* Two byte MODRM+SIB format.  */
318 34a6d0b7 Richard Henderson
319 34a6d0b7 Richard Henderson
        /* Note that the encoding that would place %esp into the index
320 34a6d0b7 Richard Henderson
           field indicates no index register.  */
321 34a6d0b7 Richard Henderson
        if (index == -1) {
322 34a6d0b7 Richard Henderson
            index = 4;
323 c896fe29 bellard
        } else {
324 34a6d0b7 Richard Henderson
            assert(index != TCG_REG_ESP);
325 c896fe29 bellard
        }
326 34a6d0b7 Richard Henderson
327 34a6d0b7 Richard Henderson
        tcg_out8(s, mod | (r << 3) | 4);
328 34a6d0b7 Richard Henderson
        tcg_out8(s, (shift << 6) | (index << 3) | rm);
329 34a6d0b7 Richard Henderson
    }
330 34a6d0b7 Richard Henderson
331 34a6d0b7 Richard Henderson
    if (len == 1) {
332 34a6d0b7 Richard Henderson
        tcg_out8(s, offset);
333 34a6d0b7 Richard Henderson
    } else if (len == 4) {
334 c896fe29 bellard
        tcg_out32(s, offset);
335 c896fe29 bellard
    }
336 c896fe29 bellard
}
337 c896fe29 bellard
338 34a6d0b7 Richard Henderson
/* rm == -1 means no register index */
339 34a6d0b7 Richard Henderson
static inline void tcg_out_modrm_offset(TCGContext *s, int opc, int r, int rm,
340 34a6d0b7 Richard Henderson
                                        int32_t offset)
341 34a6d0b7 Richard Henderson
{
342 34a6d0b7 Richard Henderson
    tcg_out_modrm_sib_offset(s, opc, r, rm, -1, 0, offset);
343 34a6d0b7 Richard Henderson
}
344 34a6d0b7 Richard Henderson
345 81570a70 Richard Henderson
/* Generate dest op= src.  Uses the same ARITH_* codes as tgen_arithi.  */
346 81570a70 Richard Henderson
static inline void tgen_arithr(TCGContext *s, int subop, int dest, int src)
347 81570a70 Richard Henderson
{
348 81570a70 Richard Henderson
    tcg_out_modrm(s, OPC_ARITH_GvEv + (subop << 3), dest, src);
349 81570a70 Richard Henderson
}
350 81570a70 Richard Henderson
351 c896fe29 bellard
static inline void tcg_out_mov(TCGContext *s, int ret, int arg)
352 c896fe29 bellard
{
353 af266089 Richard Henderson
    if (arg != ret) {
354 af266089 Richard Henderson
        tcg_out_modrm(s, OPC_MOVL_GvEv, ret, arg);
355 af266089 Richard Henderson
    }
356 c896fe29 bellard
}
357 c896fe29 bellard
358 c896fe29 bellard
static inline void tcg_out_movi(TCGContext *s, TCGType type,
359 c896fe29 bellard
                                int ret, int32_t arg)
360 c896fe29 bellard
{
361 c896fe29 bellard
    if (arg == 0) {
362 81570a70 Richard Henderson
        tgen_arithr(s, ARITH_XOR, ret, ret);
363 c896fe29 bellard
    } else {
364 ef10b106 Richard Henderson
        tcg_out8(s, OPC_MOVL_Iv + ret);
365 c896fe29 bellard
        tcg_out32(s, arg);
366 c896fe29 bellard
    }
367 c896fe29 bellard
}
368 c896fe29 bellard
369 6858614e Richard Henderson
static inline void tcg_out_pushi(TCGContext *s, tcg_target_long val)
370 6858614e Richard Henderson
{
371 6858614e Richard Henderson
    if (val == (int8_t)val) {
372 6858614e Richard Henderson
        tcg_out_opc(s, OPC_PUSH_Ib);
373 6858614e Richard Henderson
        tcg_out8(s, val);
374 6858614e Richard Henderson
    } else {
375 6858614e Richard Henderson
        tcg_out_opc(s, OPC_PUSH_Iv);
376 6858614e Richard Henderson
        tcg_out32(s, val);
377 6858614e Richard Henderson
    }
378 6858614e Richard Henderson
}
379 6858614e Richard Henderson
380 6858614e Richard Henderson
static inline void tcg_out_push(TCGContext *s, int reg)
381 6858614e Richard Henderson
{
382 6858614e Richard Henderson
    tcg_out_opc(s, OPC_PUSH_r32 + reg);
383 6858614e Richard Henderson
}
384 6858614e Richard Henderson
385 6858614e Richard Henderson
static inline void tcg_out_pop(TCGContext *s, int reg)
386 6858614e Richard Henderson
{
387 6858614e Richard Henderson
    tcg_out_opc(s, OPC_POP_r32 + reg);
388 6858614e Richard Henderson
}
389 6858614e Richard Henderson
390 e4d5434c blueswir1
static inline void tcg_out_ld(TCGContext *s, TCGType type, int ret,
391 e4d5434c blueswir1
                              int arg1, tcg_target_long arg2)
392 c896fe29 bellard
{
393 af266089 Richard Henderson
    tcg_out_modrm_offset(s, OPC_MOVL_GvEv, ret, arg1, arg2);
394 c896fe29 bellard
}
395 c896fe29 bellard
396 e4d5434c blueswir1
static inline void tcg_out_st(TCGContext *s, TCGType type, int arg,
397 e4d5434c blueswir1
                              int arg1, tcg_target_long arg2)
398 c896fe29 bellard
{
399 af266089 Richard Henderson
    tcg_out_modrm_offset(s, OPC_MOVL_EvGv, arg, arg1, arg2);
400 c896fe29 bellard
}
401 c896fe29 bellard
402 f53dba01 Richard Henderson
static void tcg_out_shifti(TCGContext *s, int subopc, int reg, int count)
403 f53dba01 Richard Henderson
{
404 96b4cf38 Richard Henderson
    /* Propagate an opcode prefix, such as P_DATA16.  */
405 96b4cf38 Richard Henderson
    int ext = subopc & ~0x7;
406 96b4cf38 Richard Henderson
    subopc &= 0x7;
407 96b4cf38 Richard Henderson
408 f53dba01 Richard Henderson
    if (count == 1) {
409 96b4cf38 Richard Henderson
        tcg_out_modrm(s, OPC_SHIFT_1 | ext, subopc, reg);
410 f53dba01 Richard Henderson
    } else {
411 96b4cf38 Richard Henderson
        tcg_out_modrm(s, OPC_SHIFT_Ib | ext, subopc, reg);
412 f53dba01 Richard Henderson
        tcg_out8(s, count);
413 f53dba01 Richard Henderson
    }
414 f53dba01 Richard Henderson
}
415 f53dba01 Richard Henderson
416 fcb5dac1 Richard Henderson
static inline void tcg_out_bswap32(TCGContext *s, int reg)
417 fcb5dac1 Richard Henderson
{
418 fcb5dac1 Richard Henderson
    tcg_out_opc(s, OPC_BSWAP + reg);
419 fcb5dac1 Richard Henderson
}
420 fcb5dac1 Richard Henderson
421 fcb5dac1 Richard Henderson
static inline void tcg_out_rolw_8(TCGContext *s, int reg)
422 fcb5dac1 Richard Henderson
{
423 96b4cf38 Richard Henderson
    tcg_out_shifti(s, SHIFT_ROL | P_DATA16, reg, 8);
424 fcb5dac1 Richard Henderson
}
425 fcb5dac1 Richard Henderson
426 55e082a7 Richard Henderson
static inline void tcg_out_ext8u(TCGContext *s, int dest, int src)
427 55e082a7 Richard Henderson
{
428 55e082a7 Richard Henderson
    /* movzbl */
429 55e082a7 Richard Henderson
    assert(src < 4);
430 55e082a7 Richard Henderson
    tcg_out_modrm(s, OPC_MOVZBL, dest, src);
431 55e082a7 Richard Henderson
}
432 55e082a7 Richard Henderson
433 6817c355 Richard Henderson
static void tcg_out_ext8s(TCGContext *s, int dest, int src)
434 6817c355 Richard Henderson
{
435 6817c355 Richard Henderson
    /* movsbl */
436 6817c355 Richard Henderson
    assert(src < 4);
437 6817c355 Richard Henderson
    tcg_out_modrm(s, OPC_MOVSBL, dest, src);
438 6817c355 Richard Henderson
}
439 6817c355 Richard Henderson
440 55e082a7 Richard Henderson
static inline void tcg_out_ext16u(TCGContext *s, int dest, int src)
441 55e082a7 Richard Henderson
{
442 55e082a7 Richard Henderson
    /* movzwl */
443 55e082a7 Richard Henderson
    tcg_out_modrm(s, OPC_MOVZWL, dest, src);
444 55e082a7 Richard Henderson
}
445 55e082a7 Richard Henderson
446 6817c355 Richard Henderson
static inline void tcg_out_ext16s(TCGContext *s, int dest, int src)
447 6817c355 Richard Henderson
{
448 6817c355 Richard Henderson
    /* movswl */
449 6817c355 Richard Henderson
    tcg_out_modrm(s, OPC_MOVSWL, dest, src);
450 6817c355 Richard Henderson
}
451 6817c355 Richard Henderson
452 81570a70 Richard Henderson
static inline void tgen_arithi(TCGContext *s, int c, int r0,
453 81570a70 Richard Henderson
                               int32_t val, int cf)
454 c896fe29 bellard
{
455 81570a70 Richard Henderson
    /* ??? While INC is 2 bytes shorter than ADDL $1, they also induce
456 81570a70 Richard Henderson
       partial flags update stalls on Pentium4 and are not recommended
457 81570a70 Richard Henderson
       by current Intel optimization manuals.  */
458 81570a70 Richard Henderson
    if (!cf && (c == ARITH_ADD || c == ARITH_SUB) && (val == 1 || val == -1)) {
459 81570a70 Richard Henderson
        int opc = ((c == ARITH_ADD) ^ (val < 0) ? OPC_INC_r32 : OPC_DEC_r32);
460 81570a70 Richard Henderson
        tcg_out_opc(s, opc + r0);
461 17cf428f Aurelien Jarno
    } else if (val == (int8_t)val) {
462 a369a702 Richard Henderson
        tcg_out_modrm(s, OPC_ARITH_EvIb, c, r0);
463 c896fe29 bellard
        tcg_out8(s, val);
464 b70650cb Aurelien Jarno
    } else if (c == ARITH_AND && val == 0xffu && r0 < 4) {
465 55e082a7 Richard Henderson
        tcg_out_ext8u(s, r0, r0);
466 b70650cb Aurelien Jarno
    } else if (c == ARITH_AND && val == 0xffffu) {
467 55e082a7 Richard Henderson
        tcg_out_ext16u(s, r0, r0);
468 c896fe29 bellard
    } else {
469 a369a702 Richard Henderson
        tcg_out_modrm(s, OPC_ARITH_EvIz, c, r0);
470 c896fe29 bellard
        tcg_out32(s, val);
471 c896fe29 bellard
    }
472 c896fe29 bellard
}
473 c896fe29 bellard
474 3e9a474e aurel32
static void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
475 c896fe29 bellard
{
476 c896fe29 bellard
    if (val != 0)
477 17cf428f Aurelien Jarno
        tgen_arithi(s, ARITH_ADD, reg, val, 0);
478 c896fe29 bellard
}
479 c896fe29 bellard
480 f75b56c1 Richard Henderson
/* Use SMALL != 0 to force a short forward branch.  */
481 f75b56c1 Richard Henderson
static void tcg_out_jxx(TCGContext *s, int opc, int label_index, int small)
482 c896fe29 bellard
{
483 c896fe29 bellard
    int32_t val, val1;
484 c896fe29 bellard
    TCGLabel *l = &s->labels[label_index];
485 78686523 Richard Henderson
486 c896fe29 bellard
    if (l->has_value) {
487 c896fe29 bellard
        val = l->u.value - (tcg_target_long)s->code_ptr;
488 c896fe29 bellard
        val1 = val - 2;
489 c896fe29 bellard
        if ((int8_t)val1 == val1) {
490 f75b56c1 Richard Henderson
            if (opc == -1) {
491 da441cff Richard Henderson
                tcg_out8(s, OPC_JMP_short);
492 f75b56c1 Richard Henderson
            } else {
493 da441cff Richard Henderson
                tcg_out8(s, OPC_JCC_short + opc);
494 f75b56c1 Richard Henderson
            }
495 c896fe29 bellard
            tcg_out8(s, val1);
496 c896fe29 bellard
        } else {
497 f75b56c1 Richard Henderson
            if (small) {
498 f75b56c1 Richard Henderson
                tcg_abort();
499 f75b56c1 Richard Henderson
            }
500 c896fe29 bellard
            if (opc == -1) {
501 da441cff Richard Henderson
                tcg_out8(s, OPC_JMP_long);
502 c896fe29 bellard
                tcg_out32(s, val - 5);
503 c896fe29 bellard
            } else {
504 da441cff Richard Henderson
                tcg_out_opc(s, OPC_JCC_long + opc);
505 c896fe29 bellard
                tcg_out32(s, val - 6);
506 c896fe29 bellard
            }
507 c896fe29 bellard
        }
508 f75b56c1 Richard Henderson
    } else if (small) {
509 f75b56c1 Richard Henderson
        if (opc == -1) {
510 da441cff Richard Henderson
            tcg_out8(s, OPC_JMP_short);
511 f75b56c1 Richard Henderson
        } else {
512 da441cff Richard Henderson
            tcg_out8(s, OPC_JCC_short + opc);
513 f75b56c1 Richard Henderson
        }
514 f75b56c1 Richard Henderson
        tcg_out_reloc(s, s->code_ptr, R_386_PC8, label_index, -1);
515 f75b56c1 Richard Henderson
        s->code_ptr += 1;
516 c896fe29 bellard
    } else {
517 c896fe29 bellard
        if (opc == -1) {
518 da441cff Richard Henderson
            tcg_out8(s, OPC_JMP_long);
519 c896fe29 bellard
        } else {
520 da441cff Richard Henderson
            tcg_out_opc(s, OPC_JCC_long + opc);
521 c896fe29 bellard
        }
522 c896fe29 bellard
        tcg_out_reloc(s, s->code_ptr, R_386_PC32, label_index, -4);
523 623e265c pbrook
        s->code_ptr += 4;
524 c896fe29 bellard
    }
525 c896fe29 bellard
}
526 c896fe29 bellard
527 1d2699ae Richard Henderson
static void tcg_out_cmp(TCGContext *s, TCGArg arg1, TCGArg arg2,
528 1d2699ae Richard Henderson
                        int const_arg2)
529 c896fe29 bellard
{
530 c896fe29 bellard
    if (const_arg2) {
531 c896fe29 bellard
        if (arg2 == 0) {
532 c896fe29 bellard
            /* test r, r */
533 81570a70 Richard Henderson
            tcg_out_modrm(s, OPC_TESTL, arg1, arg1);
534 c896fe29 bellard
        } else {
535 17cf428f Aurelien Jarno
            tgen_arithi(s, ARITH_CMP, arg1, arg2, 0);
536 c896fe29 bellard
        }
537 c896fe29 bellard
    } else {
538 81570a70 Richard Henderson
        tgen_arithr(s, ARITH_CMP, arg1, arg2);
539 c896fe29 bellard
    }
540 1d2699ae Richard Henderson
}
541 1d2699ae Richard Henderson
542 8a56e840 Richard Henderson
static void tcg_out_brcond(TCGContext *s, TCGCond cond,
543 1d2699ae Richard Henderson
                           TCGArg arg1, TCGArg arg2, int const_arg2,
544 1d2699ae Richard Henderson
                           int label_index, int small)
545 1d2699ae Richard Henderson
{
546 1d2699ae Richard Henderson
    tcg_out_cmp(s, arg1, arg2, const_arg2);
547 f75b56c1 Richard Henderson
    tcg_out_jxx(s, tcg_cond_to_jcc[cond], label_index, small);
548 c896fe29 bellard
}
549 c896fe29 bellard
550 c896fe29 bellard
/* XXX: we implement it at the target level to avoid having to
551 c896fe29 bellard
   handle cross basic blocks temporaries */
552 f75b56c1 Richard Henderson
static void tcg_out_brcond2(TCGContext *s, const TCGArg *args,
553 f75b56c1 Richard Henderson
                            const int *const_args, int small)
554 c896fe29 bellard
{
555 c896fe29 bellard
    int label_next;
556 c896fe29 bellard
    label_next = gen_new_label();
557 c896fe29 bellard
    switch(args[4]) {
558 c896fe29 bellard
    case TCG_COND_EQ:
559 f75b56c1 Richard Henderson
        tcg_out_brcond(s, TCG_COND_NE, args[0], args[2], const_args[2],
560 f75b56c1 Richard Henderson
                       label_next, 1);
561 f75b56c1 Richard Henderson
        tcg_out_brcond(s, TCG_COND_EQ, args[1], args[3], const_args[3],
562 f75b56c1 Richard Henderson
                       args[5], small);
563 c896fe29 bellard
        break;
564 c896fe29 bellard
    case TCG_COND_NE:
565 f75b56c1 Richard Henderson
        tcg_out_brcond(s, TCG_COND_NE, args[0], args[2], const_args[2],
566 f75b56c1 Richard Henderson
                       args[5], small);
567 f75b56c1 Richard Henderson
        tcg_out_brcond(s, TCG_COND_NE, args[1], args[3], const_args[3],
568 f75b56c1 Richard Henderson
                       args[5], small);
569 c896fe29 bellard
        break;
570 c896fe29 bellard
    case TCG_COND_LT:
571 f75b56c1 Richard Henderson
        tcg_out_brcond(s, TCG_COND_LT, args[1], args[3], const_args[3],
572 f75b56c1 Richard Henderson
                       args[5], small);
573 f75b56c1 Richard Henderson
        tcg_out_jxx(s, JCC_JNE, label_next, 1);
574 f75b56c1 Richard Henderson
        tcg_out_brcond(s, TCG_COND_LTU, args[0], args[2], const_args[2],
575 f75b56c1 Richard Henderson
                       args[5], small);
576 c896fe29 bellard
        break;
577 c896fe29 bellard
    case TCG_COND_LE:
578 f75b56c1 Richard Henderson
        tcg_out_brcond(s, TCG_COND_LT, args[1], args[3], const_args[3],
579 f75b56c1 Richard Henderson
                       args[5], small);
580 f75b56c1 Richard Henderson
        tcg_out_jxx(s, JCC_JNE, label_next, 1);
581 f75b56c1 Richard Henderson
        tcg_out_brcond(s, TCG_COND_LEU, args[0], args[2], const_args[2],
582 f75b56c1 Richard Henderson
                       args[5], small);
583 c896fe29 bellard
        break;
584 c896fe29 bellard
    case TCG_COND_GT:
585 f75b56c1 Richard Henderson
        tcg_out_brcond(s, TCG_COND_GT, args[1], args[3], const_args[3],
586 f75b56c1 Richard Henderson
                       args[5], small);
587 f75b56c1 Richard Henderson
        tcg_out_jxx(s, JCC_JNE, label_next, 1);
588 f75b56c1 Richard Henderson
        tcg_out_brcond(s, TCG_COND_GTU, args[0], args[2], const_args[2],
589 f75b56c1 Richard Henderson
                       args[5], small);
590 c896fe29 bellard
        break;
591 c896fe29 bellard
    case TCG_COND_GE:
592 f75b56c1 Richard Henderson
        tcg_out_brcond(s, TCG_COND_GT, args[1], args[3], const_args[3],
593 f75b56c1 Richard Henderson
                       args[5], small);
594 f75b56c1 Richard Henderson
        tcg_out_jxx(s, JCC_JNE, label_next, 1);
595 f75b56c1 Richard Henderson
        tcg_out_brcond(s, TCG_COND_GEU, args[0], args[2], const_args[2],
596 f75b56c1 Richard Henderson
                       args[5], small);
597 c896fe29 bellard
        break;
598 c896fe29 bellard
    case TCG_COND_LTU:
599 f75b56c1 Richard Henderson
        tcg_out_brcond(s, TCG_COND_LTU, args[1], args[3], const_args[3],
600 f75b56c1 Richard Henderson
                       args[5], small);
601 f75b56c1 Richard Henderson
        tcg_out_jxx(s, JCC_JNE, label_next, 1);
602 f75b56c1 Richard Henderson
        tcg_out_brcond(s, TCG_COND_LTU, args[0], args[2], const_args[2],
603 f75b56c1 Richard Henderson
                       args[5], small);
604 c896fe29 bellard
        break;
605 c896fe29 bellard
    case TCG_COND_LEU:
606 f75b56c1 Richard Henderson
        tcg_out_brcond(s, TCG_COND_LTU, args[1], args[3], const_args[3],
607 f75b56c1 Richard Henderson
                       args[5], small);
608 f75b56c1 Richard Henderson
        tcg_out_jxx(s, JCC_JNE, label_next, 1);
609 f75b56c1 Richard Henderson
        tcg_out_brcond(s, TCG_COND_LEU, args[0], args[2], const_args[2],
610 f75b56c1 Richard Henderson
                       args[5], small);
611 c896fe29 bellard
        break;
612 c896fe29 bellard
    case TCG_COND_GTU:
613 f75b56c1 Richard Henderson
        tcg_out_brcond(s, TCG_COND_GTU, args[1], args[3], const_args[3],
614 f75b56c1 Richard Henderson
                       args[5], small);
615 f75b56c1 Richard Henderson
        tcg_out_jxx(s, JCC_JNE, label_next, 1);
616 f75b56c1 Richard Henderson
        tcg_out_brcond(s, TCG_COND_GTU, args[0], args[2], const_args[2],
617 f75b56c1 Richard Henderson
                       args[5], small);
618 c896fe29 bellard
        break;
619 c896fe29 bellard
    case TCG_COND_GEU:
620 f75b56c1 Richard Henderson
        tcg_out_brcond(s, TCG_COND_GTU, args[1], args[3], const_args[3],
621 f75b56c1 Richard Henderson
                       args[5], small);
622 f75b56c1 Richard Henderson
        tcg_out_jxx(s, JCC_JNE, label_next, 1);
623 f75b56c1 Richard Henderson
        tcg_out_brcond(s, TCG_COND_GEU, args[0], args[2], const_args[2],
624 f75b56c1 Richard Henderson
                       args[5], small);
625 c896fe29 bellard
        break;
626 c896fe29 bellard
    default:
627 c896fe29 bellard
        tcg_abort();
628 c896fe29 bellard
    }
629 c896fe29 bellard
    tcg_out_label(s, label_next, (tcg_target_long)s->code_ptr);
630 c896fe29 bellard
}
631 c896fe29 bellard
632 8a56e840 Richard Henderson
static void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGArg dest,
633 1d2699ae Richard Henderson
                            TCGArg arg1, TCGArg arg2, int const_arg2)
634 1d2699ae Richard Henderson
{
635 1d2699ae Richard Henderson
    tcg_out_cmp(s, arg1, arg2, const_arg2);
636 32a8ffb9 Richard Henderson
    tcg_out_modrm(s, OPC_SETCC | tcg_cond_to_jcc[cond], 0, dest);
637 a369a702 Richard Henderson
    tcg_out_ext8u(s, dest, dest);
638 1d2699ae Richard Henderson
}
639 1d2699ae Richard Henderson
640 1d2699ae Richard Henderson
static void tcg_out_setcond2(TCGContext *s, const TCGArg *args,
641 1d2699ae Richard Henderson
                             const int *const_args)
642 1d2699ae Richard Henderson
{
643 1d2699ae Richard Henderson
    TCGArg new_args[6];
644 1d2699ae Richard Henderson
    int label_true, label_over;
645 1d2699ae Richard Henderson
646 1d2699ae Richard Henderson
    memcpy(new_args, args+1, 5*sizeof(TCGArg));
647 1d2699ae Richard Henderson
648 1d2699ae Richard Henderson
    if (args[0] == args[1] || args[0] == args[2]
649 1d2699ae Richard Henderson
        || (!const_args[3] && args[0] == args[3])
650 1d2699ae Richard Henderson
        || (!const_args[4] && args[0] == args[4])) {
651 1d2699ae Richard Henderson
        /* When the destination overlaps with one of the argument
652 1d2699ae Richard Henderson
           registers, don't do anything tricky.  */
653 1d2699ae Richard Henderson
        label_true = gen_new_label();
654 1d2699ae Richard Henderson
        label_over = gen_new_label();
655 1d2699ae Richard Henderson
656 1d2699ae Richard Henderson
        new_args[5] = label_true;
657 1d2699ae Richard Henderson
        tcg_out_brcond2(s, new_args, const_args+1, 1);
658 1d2699ae Richard Henderson
659 1d2699ae Richard Henderson
        tcg_out_movi(s, TCG_TYPE_I32, args[0], 0);
660 1d2699ae Richard Henderson
        tcg_out_jxx(s, JCC_JMP, label_over, 1);
661 1d2699ae Richard Henderson
        tcg_out_label(s, label_true, (tcg_target_long)s->code_ptr);
662 1d2699ae Richard Henderson
663 1d2699ae Richard Henderson
        tcg_out_movi(s, TCG_TYPE_I32, args[0], 1);
664 1d2699ae Richard Henderson
        tcg_out_label(s, label_over, (tcg_target_long)s->code_ptr);
665 1d2699ae Richard Henderson
    } else {
666 1d2699ae Richard Henderson
        /* When the destination does not overlap one of the arguments,
667 1d2699ae Richard Henderson
           clear the destination first, jump if cond false, and emit an
668 1d2699ae Richard Henderson
           increment in the true case.  This results in smaller code.  */
669 1d2699ae Richard Henderson
670 1d2699ae Richard Henderson
        tcg_out_movi(s, TCG_TYPE_I32, args[0], 0);
671 1d2699ae Richard Henderson
672 1d2699ae Richard Henderson
        label_over = gen_new_label();
673 1d2699ae Richard Henderson
        new_args[4] = tcg_invert_cond(new_args[4]);
674 1d2699ae Richard Henderson
        new_args[5] = label_over;
675 1d2699ae Richard Henderson
        tcg_out_brcond2(s, new_args, const_args+1, 1);
676 1d2699ae Richard Henderson
677 1d2699ae Richard Henderson
        tgen_arithi(s, ARITH_ADD, args[0], 1, 0);
678 1d2699ae Richard Henderson
        tcg_out_label(s, label_over, (tcg_target_long)s->code_ptr);
679 1d2699ae Richard Henderson
    }
680 1d2699ae Richard Henderson
}
681 1d2699ae Richard Henderson
682 aadb21a4 Richard Henderson
static void tcg_out_calli(TCGContext *s, tcg_target_long dest)
683 aadb21a4 Richard Henderson
{
684 aadb21a4 Richard Henderson
    tcg_out_opc(s, OPC_CALL_Jz);
685 aadb21a4 Richard Henderson
    tcg_out32(s, dest - (tcg_target_long)s->code_ptr - 4);
686 aadb21a4 Richard Henderson
}
687 aadb21a4 Richard Henderson
688 c896fe29 bellard
#if defined(CONFIG_SOFTMMU)
689 79383c9c blueswir1
690 79383c9c blueswir1
#include "../../softmmu_defs.h"
691 c896fe29 bellard
692 c896fe29 bellard
static void *qemu_ld_helpers[4] = {
693 c896fe29 bellard
    __ldb_mmu,
694 c896fe29 bellard
    __ldw_mmu,
695 c896fe29 bellard
    __ldl_mmu,
696 c896fe29 bellard
    __ldq_mmu,
697 c896fe29 bellard
};
698 c896fe29 bellard
699 c896fe29 bellard
static void *qemu_st_helpers[4] = {
700 c896fe29 bellard
    __stb_mmu,
701 c896fe29 bellard
    __stw_mmu,
702 c896fe29 bellard
    __stl_mmu,
703 c896fe29 bellard
    __stq_mmu,
704 c896fe29 bellard
};
705 c896fe29 bellard
#endif
706 c896fe29 bellard
707 be5a4eb7 Richard Henderson
static void tcg_out_qemu_ld_direct(TCGContext *s, int datalo, int datahi,
708 be5a4eb7 Richard Henderson
                                   int base, tcg_target_long ofs, int sizeop)
709 be5a4eb7 Richard Henderson
{
710 be5a4eb7 Richard Henderson
#ifdef TARGET_WORDS_BIGENDIAN
711 be5a4eb7 Richard Henderson
    const int bswap = 1;
712 be5a4eb7 Richard Henderson
#else
713 be5a4eb7 Richard Henderson
    const int bswap = 0;
714 379f6698 Paul Brook
#endif
715 be5a4eb7 Richard Henderson
    switch (sizeop) {
716 be5a4eb7 Richard Henderson
    case 0:
717 be5a4eb7 Richard Henderson
        /* movzbl */
718 be5a4eb7 Richard Henderson
        tcg_out_modrm_offset(s, OPC_MOVZBL, datalo, base, ofs);
719 be5a4eb7 Richard Henderson
        break;
720 be5a4eb7 Richard Henderson
    case 0 | 4:
721 be5a4eb7 Richard Henderson
        /* movsbl */
722 be5a4eb7 Richard Henderson
        tcg_out_modrm_offset(s, OPC_MOVSBL, datalo, base, ofs);
723 be5a4eb7 Richard Henderson
        break;
724 be5a4eb7 Richard Henderson
    case 1:
725 be5a4eb7 Richard Henderson
        /* movzwl */
726 be5a4eb7 Richard Henderson
        tcg_out_modrm_offset(s, OPC_MOVZWL, datalo, base, ofs);
727 be5a4eb7 Richard Henderson
        if (bswap) {
728 be5a4eb7 Richard Henderson
            tcg_out_rolw_8(s, datalo);
729 be5a4eb7 Richard Henderson
        }
730 be5a4eb7 Richard Henderson
        break;
731 be5a4eb7 Richard Henderson
    case 1 | 4:
732 be5a4eb7 Richard Henderson
        /* movswl */
733 be5a4eb7 Richard Henderson
        tcg_out_modrm_offset(s, OPC_MOVSWL, datalo, base, ofs);
734 be5a4eb7 Richard Henderson
        if (bswap) {
735 be5a4eb7 Richard Henderson
            tcg_out_rolw_8(s, datalo);
736 be5a4eb7 Richard Henderson
            tcg_out_modrm(s, OPC_MOVSWL, datalo, datalo);
737 be5a4eb7 Richard Henderson
        }
738 be5a4eb7 Richard Henderson
        break;
739 be5a4eb7 Richard Henderson
    case 2:
740 be5a4eb7 Richard Henderson
        tcg_out_ld(s, TCG_TYPE_I32, datalo, base, ofs);
741 be5a4eb7 Richard Henderson
        if (bswap) {
742 be5a4eb7 Richard Henderson
            tcg_out_bswap32(s, datalo);
743 be5a4eb7 Richard Henderson
        }
744 be5a4eb7 Richard Henderson
        break;
745 be5a4eb7 Richard Henderson
    case 3:
746 be5a4eb7 Richard Henderson
        if (bswap) {
747 be5a4eb7 Richard Henderson
            int t = datalo;
748 be5a4eb7 Richard Henderson
            datalo = datahi;
749 be5a4eb7 Richard Henderson
            datahi = t;
750 be5a4eb7 Richard Henderson
        }
751 be5a4eb7 Richard Henderson
        if (base != datalo) {
752 be5a4eb7 Richard Henderson
            tcg_out_ld(s, TCG_TYPE_I32, datalo, base, ofs);
753 be5a4eb7 Richard Henderson
            tcg_out_ld(s, TCG_TYPE_I32, datahi, base, ofs + 4);
754 be5a4eb7 Richard Henderson
        } else {
755 be5a4eb7 Richard Henderson
            tcg_out_ld(s, TCG_TYPE_I32, datahi, base, ofs + 4);
756 be5a4eb7 Richard Henderson
            tcg_out_ld(s, TCG_TYPE_I32, datalo, base, ofs);
757 be5a4eb7 Richard Henderson
        }
758 be5a4eb7 Richard Henderson
        if (bswap) {
759 be5a4eb7 Richard Henderson
            tcg_out_bswap32(s, datalo);
760 be5a4eb7 Richard Henderson
            tcg_out_bswap32(s, datahi);
761 be5a4eb7 Richard Henderson
        }
762 be5a4eb7 Richard Henderson
        break;
763 be5a4eb7 Richard Henderson
    default:
764 be5a4eb7 Richard Henderson
        tcg_abort();
765 be5a4eb7 Richard Henderson
    }
766 be5a4eb7 Richard Henderson
}
767 379f6698 Paul Brook
768 c896fe29 bellard
/* XXX: qemu_ld and qemu_st could be modified to clobber only EDX and
769 c896fe29 bellard
   EAX. It will be useful once fixed registers globals are less
770 c896fe29 bellard
   common. */
771 c896fe29 bellard
static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
772 c896fe29 bellard
                            int opc)
773 c896fe29 bellard
{
774 be5a4eb7 Richard Henderson
    int addr_reg, data_reg, data_reg2, r0, r1, mem_index, s_bits;
775 c896fe29 bellard
#if defined(CONFIG_SOFTMMU)
776 c896fe29 bellard
    uint8_t *label1_ptr, *label2_ptr;
777 c896fe29 bellard
#endif
778 c896fe29 bellard
#if TARGET_LONG_BITS == 64
779 c896fe29 bellard
#if defined(CONFIG_SOFTMMU)
780 c896fe29 bellard
    uint8_t *label3_ptr;
781 c896fe29 bellard
#endif
782 c896fe29 bellard
    int addr_reg2;
783 c896fe29 bellard
#endif
784 c896fe29 bellard
785 c896fe29 bellard
    data_reg = *args++;
786 c896fe29 bellard
    if (opc == 3)
787 c896fe29 bellard
        data_reg2 = *args++;
788 c896fe29 bellard
    else
789 c896fe29 bellard
        data_reg2 = 0;
790 c896fe29 bellard
    addr_reg = *args++;
791 c896fe29 bellard
#if TARGET_LONG_BITS == 64
792 c896fe29 bellard
    addr_reg2 = *args++;
793 c896fe29 bellard
#endif
794 c896fe29 bellard
    mem_index = *args;
795 c896fe29 bellard
    s_bits = opc & 3;
796 c896fe29 bellard
797 c896fe29 bellard
    r0 = TCG_REG_EAX;
798 c896fe29 bellard
    r1 = TCG_REG_EDX;
799 c896fe29 bellard
800 c896fe29 bellard
#if defined(CONFIG_SOFTMMU)
801 78686523 Richard Henderson
    tcg_out_mov(s, r1, addr_reg);
802 78686523 Richard Henderson
    tcg_out_mov(s, r0, addr_reg);
803 a369a702 Richard Henderson
804 f53dba01 Richard Henderson
    tcg_out_shifti(s, SHIFT_SHR, r1, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
805 f53dba01 Richard Henderson
806 a369a702 Richard Henderson
    tgen_arithi(s, ARITH_AND, r0, TARGET_PAGE_MASK | ((1 << s_bits) - 1), 0);
807 a369a702 Richard Henderson
    tgen_arithi(s, ARITH_AND, r1, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS, 0);
808 c896fe29 bellard
809 34a6d0b7 Richard Henderson
    tcg_out_modrm_sib_offset(s, OPC_LEA, r1, TCG_AREG0, r1, 0,
810 34a6d0b7 Richard Henderson
                             offsetof(CPUState,
811 34a6d0b7 Richard Henderson
                                      tlb_table[mem_index][0].addr_read));
812 c896fe29 bellard
813 c896fe29 bellard
    /* cmp 0(r1), r0 */
814 81570a70 Richard Henderson
    tcg_out_modrm_offset(s, OPC_CMP_GvEv, r0, r1, 0);
815 78686523 Richard Henderson
816 c896fe29 bellard
    tcg_out_mov(s, r0, addr_reg);
817 78686523 Richard Henderson
818 c896fe29 bellard
#if TARGET_LONG_BITS == 32
819 c896fe29 bellard
    /* je label1 */
820 da441cff Richard Henderson
    tcg_out8(s, OPC_JCC_short + JCC_JE);
821 c896fe29 bellard
    label1_ptr = s->code_ptr;
822 c896fe29 bellard
    s->code_ptr++;
823 c896fe29 bellard
#else
824 c896fe29 bellard
    /* jne label3 */
825 da441cff Richard Henderson
    tcg_out8(s, OPC_JCC_short + JCC_JNE);
826 c896fe29 bellard
    label3_ptr = s->code_ptr;
827 c896fe29 bellard
    s->code_ptr++;
828 78686523 Richard Henderson
829 c896fe29 bellard
    /* cmp 4(r1), addr_reg2 */
830 81570a70 Richard Henderson
    tcg_out_modrm_offset(s, OPC_CMP_GvEv, addr_reg2, r1, 4);
831 c896fe29 bellard
832 c896fe29 bellard
    /* je label1 */
833 da441cff Richard Henderson
    tcg_out8(s, OPC_JCC_short + JCC_JE);
834 c896fe29 bellard
    label1_ptr = s->code_ptr;
835 c896fe29 bellard
    s->code_ptr++;
836 78686523 Richard Henderson
837 c896fe29 bellard
    /* label3: */
838 c896fe29 bellard
    *label3_ptr = s->code_ptr - label3_ptr - 1;
839 c896fe29 bellard
#endif
840 c896fe29 bellard
841 c896fe29 bellard
    /* XXX: move that code at the end of the TB */
842 c896fe29 bellard
#if TARGET_LONG_BITS == 32
843 c896fe29 bellard
    tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_EDX, mem_index);
844 c896fe29 bellard
#else
845 c896fe29 bellard
    tcg_out_mov(s, TCG_REG_EDX, addr_reg2);
846 c896fe29 bellard
    tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_ECX, mem_index);
847 c896fe29 bellard
#endif
848 aadb21a4 Richard Henderson
    tcg_out_calli(s, (tcg_target_long)qemu_ld_helpers[s_bits]);
849 c896fe29 bellard
850 c896fe29 bellard
    switch(opc) {
851 c896fe29 bellard
    case 0 | 4:
852 6817c355 Richard Henderson
        tcg_out_ext8s(s, data_reg, TCG_REG_EAX);
853 c896fe29 bellard
        break;
854 c896fe29 bellard
    case 1 | 4:
855 6817c355 Richard Henderson
        tcg_out_ext16s(s, data_reg, TCG_REG_EAX);
856 c896fe29 bellard
        break;
857 c896fe29 bellard
    case 0:
858 55e082a7 Richard Henderson
        tcg_out_ext8u(s, data_reg, TCG_REG_EAX);
859 9db3ba4d aurel32
        break;
860 c896fe29 bellard
    case 1:
861 55e082a7 Richard Henderson
        tcg_out_ext16u(s, data_reg, TCG_REG_EAX);
862 9db3ba4d aurel32
        break;
863 c896fe29 bellard
    case 2:
864 c896fe29 bellard
    default:
865 c896fe29 bellard
        tcg_out_mov(s, data_reg, TCG_REG_EAX);
866 c896fe29 bellard
        break;
867 c896fe29 bellard
    case 3:
868 c896fe29 bellard
        if (data_reg == TCG_REG_EDX) {
869 b3e66df7 Richard Henderson
            /* xchg %edx, %eax */
870 b3e66df7 Richard Henderson
            tcg_out_opc(s, OPC_XCHG_ax_r32 + TCG_REG_EDX);
871 c896fe29 bellard
            tcg_out_mov(s, data_reg2, TCG_REG_EAX);
872 c896fe29 bellard
        } else {
873 c896fe29 bellard
            tcg_out_mov(s, data_reg, TCG_REG_EAX);
874 c896fe29 bellard
            tcg_out_mov(s, data_reg2, TCG_REG_EDX);
875 c896fe29 bellard
        }
876 c896fe29 bellard
        break;
877 c896fe29 bellard
    }
878 c896fe29 bellard
879 c896fe29 bellard
    /* jmp label2 */
880 da441cff Richard Henderson
    tcg_out8(s, OPC_JMP_short);
881 c896fe29 bellard
    label2_ptr = s->code_ptr;
882 c896fe29 bellard
    s->code_ptr++;
883 78686523 Richard Henderson
884 c896fe29 bellard
    /* label1: */
885 c896fe29 bellard
    *label1_ptr = s->code_ptr - label1_ptr - 1;
886 c896fe29 bellard
887 c896fe29 bellard
    /* add x(r1), r0 */
888 81570a70 Richard Henderson
    tcg_out_modrm_offset(s, OPC_ADD_GvEv, r0, r1,
889 81570a70 Richard Henderson
                         offsetof(CPUTLBEntry, addend) -
890 c896fe29 bellard
                         offsetof(CPUTLBEntry, addr_read));
891 be5a4eb7 Richard Henderson
892 be5a4eb7 Richard Henderson
    tcg_out_qemu_ld_direct(s, data_reg, data_reg2, r0, 0, opc);
893 be5a4eb7 Richard Henderson
894 be5a4eb7 Richard Henderson
    /* label2: */
895 be5a4eb7 Richard Henderson
    *label2_ptr = s->code_ptr - label2_ptr - 1;
896 c896fe29 bellard
#else
897 be5a4eb7 Richard Henderson
    tcg_out_qemu_ld_direct(s, data_reg, data_reg2, addr_reg, GUEST_BASE, opc);
898 c896fe29 bellard
#endif
899 be5a4eb7 Richard Henderson
}
900 c896fe29 bellard
901 be5a4eb7 Richard Henderson
static void tcg_out_qemu_st_direct(TCGContext *s, int datalo, int datahi,
902 be5a4eb7 Richard Henderson
                                   int base, tcg_target_long ofs, int sizeop)
903 be5a4eb7 Richard Henderson
{
904 c896fe29 bellard
#ifdef TARGET_WORDS_BIGENDIAN
905 be5a4eb7 Richard Henderson
    const int bswap = 1;
906 c896fe29 bellard
#else
907 be5a4eb7 Richard Henderson
    const int bswap = 0;
908 c896fe29 bellard
#endif
909 be5a4eb7 Richard Henderson
    /* ??? Ideally we wouldn't need a scratch register.  For user-only,
910 be5a4eb7 Richard Henderson
       we could perform the bswap twice to restore the original value
911 be5a4eb7 Richard Henderson
       instead of moving to the scratch.  But as it is, the L constraint
912 be5a4eb7 Richard Henderson
       means that EDX is definitely free here.  */
913 be5a4eb7 Richard Henderson
    int scratch = TCG_REG_EDX;
914 be5a4eb7 Richard Henderson
915 be5a4eb7 Richard Henderson
    switch (sizeop) {
916 c896fe29 bellard
    case 0:
917 be5a4eb7 Richard Henderson
        tcg_out_modrm_offset(s, OPC_MOVB_EvGv, datalo, base, ofs);
918 c896fe29 bellard
        break;
919 c896fe29 bellard
    case 1:
920 c896fe29 bellard
        if (bswap) {
921 be5a4eb7 Richard Henderson
            tcg_out_mov(s, scratch, datalo);
922 be5a4eb7 Richard Henderson
            tcg_out_rolw_8(s, scratch);
923 be5a4eb7 Richard Henderson
            datalo = scratch;
924 c896fe29 bellard
        }
925 be5a4eb7 Richard Henderson
        /* movw */
926 be5a4eb7 Richard Henderson
        tcg_out_modrm_offset(s, OPC_MOVL_EvGv | P_DATA16,
927 be5a4eb7 Richard Henderson
                             datalo, base, ofs);
928 c896fe29 bellard
        break;
929 c896fe29 bellard
    case 2:
930 c896fe29 bellard
        if (bswap) {
931 be5a4eb7 Richard Henderson
            tcg_out_mov(s, scratch, datalo);
932 be5a4eb7 Richard Henderson
            tcg_out_bswap32(s, scratch);
933 be5a4eb7 Richard Henderson
            datalo = scratch;
934 c896fe29 bellard
        }
935 be5a4eb7 Richard Henderson
        tcg_out_st(s, TCG_TYPE_I32, datalo, base, ofs);
936 c896fe29 bellard
        break;
937 c896fe29 bellard
    case 3:
938 a042ef94 Richard Henderson
        if (bswap) {
939 be5a4eb7 Richard Henderson
            tcg_out_mov(s, scratch, datahi);
940 be5a4eb7 Richard Henderson
            tcg_out_bswap32(s, scratch);
941 be5a4eb7 Richard Henderson
            tcg_out_st(s, TCG_TYPE_I32, scratch, base, ofs);
942 be5a4eb7 Richard Henderson
            tcg_out_mov(s, scratch, datalo);
943 be5a4eb7 Richard Henderson
            tcg_out_bswap32(s, scratch);
944 be5a4eb7 Richard Henderson
            tcg_out_st(s, TCG_TYPE_I32, scratch, base, ofs + 4);
945 c896fe29 bellard
        } else {
946 be5a4eb7 Richard Henderson
            tcg_out_st(s, TCG_TYPE_I32, datalo, base, ofs);
947 be5a4eb7 Richard Henderson
            tcg_out_st(s, TCG_TYPE_I32, datahi, base, ofs + 4);
948 c896fe29 bellard
        }
949 c896fe29 bellard
        break;
950 c896fe29 bellard
    default:
951 c896fe29 bellard
        tcg_abort();
952 c896fe29 bellard
    }
953 c896fe29 bellard
}
954 c896fe29 bellard
955 c896fe29 bellard
static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
956 c896fe29 bellard
                            int opc)
957 c896fe29 bellard
{
958 be5a4eb7 Richard Henderson
    int addr_reg, data_reg, data_reg2, r0, r1, mem_index, s_bits;
959 c896fe29 bellard
#if defined(CONFIG_SOFTMMU)
960 aadb21a4 Richard Henderson
    int stack_adjust;
961 c896fe29 bellard
    uint8_t *label1_ptr, *label2_ptr;
962 c896fe29 bellard
#endif
963 c896fe29 bellard
#if TARGET_LONG_BITS == 64
964 c896fe29 bellard
#if defined(CONFIG_SOFTMMU)
965 c896fe29 bellard
    uint8_t *label3_ptr;
966 c896fe29 bellard
#endif
967 c896fe29 bellard
    int addr_reg2;
968 c896fe29 bellard
#endif
969 c896fe29 bellard
970 c896fe29 bellard
    data_reg = *args++;
971 c896fe29 bellard
    if (opc == 3)
972 c896fe29 bellard
        data_reg2 = *args++;
973 c896fe29 bellard
    else
974 c896fe29 bellard
        data_reg2 = 0;
975 c896fe29 bellard
    addr_reg = *args++;
976 c896fe29 bellard
#if TARGET_LONG_BITS == 64
977 c896fe29 bellard
    addr_reg2 = *args++;
978 c896fe29 bellard
#endif
979 c896fe29 bellard
    mem_index = *args;
980 c896fe29 bellard
981 c896fe29 bellard
    s_bits = opc;
982 c896fe29 bellard
983 c896fe29 bellard
    r0 = TCG_REG_EAX;
984 c896fe29 bellard
    r1 = TCG_REG_EDX;
985 c896fe29 bellard
986 c896fe29 bellard
#if defined(CONFIG_SOFTMMU)
987 78686523 Richard Henderson
    tcg_out_mov(s, r1, addr_reg);
988 78686523 Richard Henderson
    tcg_out_mov(s, r0, addr_reg);
989 78686523 Richard Henderson
990 f53dba01 Richard Henderson
    tcg_out_shifti(s, SHIFT_SHR, r1, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
991 f53dba01 Richard Henderson
992 a369a702 Richard Henderson
    tgen_arithi(s, ARITH_AND, r0, TARGET_PAGE_MASK | ((1 << s_bits) - 1), 0);
993 a369a702 Richard Henderson
    tgen_arithi(s, ARITH_AND, r1, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS, 0);
994 c896fe29 bellard
995 34a6d0b7 Richard Henderson
    tcg_out_modrm_sib_offset(s, OPC_LEA, r1, TCG_AREG0, r1, 0,
996 34a6d0b7 Richard Henderson
                             offsetof(CPUState,
997 34a6d0b7 Richard Henderson
                                      tlb_table[mem_index][0].addr_write));
998 c896fe29 bellard
999 c896fe29 bellard
    /* cmp 0(r1), r0 */
1000 81570a70 Richard Henderson
    tcg_out_modrm_offset(s, OPC_CMP_GvEv, r0, r1, 0);
1001 78686523 Richard Henderson
1002 c896fe29 bellard
    tcg_out_mov(s, r0, addr_reg);
1003 78686523 Richard Henderson
1004 c896fe29 bellard
#if TARGET_LONG_BITS == 32
1005 c896fe29 bellard
    /* je label1 */
1006 da441cff Richard Henderson
    tcg_out8(s, OPC_JCC_short + JCC_JE);
1007 c896fe29 bellard
    label1_ptr = s->code_ptr;
1008 c896fe29 bellard
    s->code_ptr++;
1009 c896fe29 bellard
#else
1010 c896fe29 bellard
    /* jne label3 */
1011 da441cff Richard Henderson
    tcg_out8(s, OPC_JCC_short + JCC_JNE);
1012 c896fe29 bellard
    label3_ptr = s->code_ptr;
1013 c896fe29 bellard
    s->code_ptr++;
1014 78686523 Richard Henderson
1015 c896fe29 bellard
    /* cmp 4(r1), addr_reg2 */
1016 81570a70 Richard Henderson
    tcg_out_modrm_offset(s, OPC_CMP_GvEv, addr_reg2, r1, 4);
1017 c896fe29 bellard
1018 c896fe29 bellard
    /* je label1 */
1019 da441cff Richard Henderson
    tcg_out8(s, OPC_JCC_short + JCC_JE);
1020 c896fe29 bellard
    label1_ptr = s->code_ptr;
1021 c896fe29 bellard
    s->code_ptr++;
1022 78686523 Richard Henderson
1023 c896fe29 bellard
    /* label3: */
1024 c896fe29 bellard
    *label3_ptr = s->code_ptr - label3_ptr - 1;
1025 c896fe29 bellard
#endif
1026 c896fe29 bellard
1027 c896fe29 bellard
    /* XXX: move that code at the end of the TB */
1028 c896fe29 bellard
#if TARGET_LONG_BITS == 32
1029 c896fe29 bellard
    if (opc == 3) {
1030 c896fe29 bellard
        tcg_out_mov(s, TCG_REG_EDX, data_reg);
1031 c896fe29 bellard
        tcg_out_mov(s, TCG_REG_ECX, data_reg2);
1032 6858614e Richard Henderson
        tcg_out_pushi(s, mem_index);
1033 aadb21a4 Richard Henderson
        stack_adjust = 4;
1034 c896fe29 bellard
    } else {
1035 c896fe29 bellard
        switch(opc) {
1036 c896fe29 bellard
        case 0:
1037 55e082a7 Richard Henderson
            tcg_out_ext8u(s, TCG_REG_EDX, data_reg);
1038 c896fe29 bellard
            break;
1039 c896fe29 bellard
        case 1:
1040 55e082a7 Richard Henderson
            tcg_out_ext16u(s, TCG_REG_EDX, data_reg);
1041 c896fe29 bellard
            break;
1042 c896fe29 bellard
        case 2:
1043 c896fe29 bellard
            tcg_out_mov(s, TCG_REG_EDX, data_reg);
1044 c896fe29 bellard
            break;
1045 c896fe29 bellard
        }
1046 c896fe29 bellard
        tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_ECX, mem_index);
1047 aadb21a4 Richard Henderson
        stack_adjust = 0;
1048 c896fe29 bellard
    }
1049 c896fe29 bellard
#else
1050 c896fe29 bellard
    if (opc == 3) {
1051 c896fe29 bellard
        tcg_out_mov(s, TCG_REG_EDX, addr_reg2);
1052 6858614e Richard Henderson
        tcg_out_pushi(s, mem_index);
1053 6858614e Richard Henderson
        tcg_out_push(s, data_reg2);
1054 6858614e Richard Henderson
        tcg_out_push(s, data_reg);
1055 aadb21a4 Richard Henderson
        stack_adjust = 12;
1056 c896fe29 bellard
    } else {
1057 c896fe29 bellard
        tcg_out_mov(s, TCG_REG_EDX, addr_reg2);
1058 c896fe29 bellard
        switch(opc) {
1059 c896fe29 bellard
        case 0:
1060 55e082a7 Richard Henderson
            tcg_out_ext8u(s, TCG_REG_ECX, data_reg);
1061 c896fe29 bellard
            break;
1062 c896fe29 bellard
        case 1:
1063 55e082a7 Richard Henderson
            tcg_out_ext16u(s, TCG_REG_ECX, data_reg);
1064 c896fe29 bellard
            break;
1065 c896fe29 bellard
        case 2:
1066 c896fe29 bellard
            tcg_out_mov(s, TCG_REG_ECX, data_reg);
1067 c896fe29 bellard
            break;
1068 c896fe29 bellard
        }
1069 6858614e Richard Henderson
        tcg_out_pushi(s, mem_index);
1070 aadb21a4 Richard Henderson
        stack_adjust = 4;
1071 c896fe29 bellard
    }
1072 c896fe29 bellard
#endif
1073 aadb21a4 Richard Henderson
1074 aadb21a4 Richard Henderson
    tcg_out_calli(s, (tcg_target_long)qemu_st_helpers[s_bits]);
1075 aadb21a4 Richard Henderson
1076 aadb21a4 Richard Henderson
    if (stack_adjust == 4) {
1077 aadb21a4 Richard Henderson
        /* Pop and discard.  This is 2 bytes smaller than the add.  */
1078 aadb21a4 Richard Henderson
        tcg_out_pop(s, TCG_REG_ECX);
1079 aadb21a4 Richard Henderson
    } else if (stack_adjust != 0) {
1080 aadb21a4 Richard Henderson
        tcg_out_addi(s, TCG_REG_ESP, stack_adjust);
1081 aadb21a4 Richard Henderson
    }
1082 aadb21a4 Richard Henderson
1083 c896fe29 bellard
    /* jmp label2 */
1084 da441cff Richard Henderson
    tcg_out8(s, OPC_JMP_short);
1085 c896fe29 bellard
    label2_ptr = s->code_ptr;
1086 c896fe29 bellard
    s->code_ptr++;
1087 78686523 Richard Henderson
1088 c896fe29 bellard
    /* label1: */
1089 c896fe29 bellard
    *label1_ptr = s->code_ptr - label1_ptr - 1;
1090 c896fe29 bellard
1091 c896fe29 bellard
    /* add x(r1), r0 */
1092 81570a70 Richard Henderson
    tcg_out_modrm_offset(s, OPC_ADD_GvEv, r0, r1,
1093 81570a70 Richard Henderson
                         offsetof(CPUTLBEntry, addend) -
1094 c896fe29 bellard
                         offsetof(CPUTLBEntry, addr_write));
1095 c896fe29 bellard
1096 be5a4eb7 Richard Henderson
    tcg_out_qemu_st_direct(s, data_reg, data_reg2, r0, 0, opc);
1097 c896fe29 bellard
1098 c896fe29 bellard
    /* label2: */
1099 c896fe29 bellard
    *label2_ptr = s->code_ptr - label2_ptr - 1;
1100 be5a4eb7 Richard Henderson
#else
1101 be5a4eb7 Richard Henderson
    tcg_out_qemu_st_direct(s, data_reg, data_reg2, addr_reg, GUEST_BASE, opc);
1102 c896fe29 bellard
#endif
1103 c896fe29 bellard
}
1104 c896fe29 bellard
1105 a9751609 Richard Henderson
static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
1106 c896fe29 bellard
                              const TCGArg *args, const int *const_args)
1107 c896fe29 bellard
{
1108 c896fe29 bellard
    int c;
1109 78686523 Richard Henderson
1110 c896fe29 bellard
    switch(opc) {
1111 c896fe29 bellard
    case INDEX_op_exit_tb:
1112 c896fe29 bellard
        tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_EAX, args[0]);
1113 da441cff Richard Henderson
        tcg_out8(s, OPC_JMP_long); /* jmp tb_ret_addr */
1114 b03cce8e bellard
        tcg_out32(s, tb_ret_addr - s->code_ptr - 4);
1115 c896fe29 bellard
        break;
1116 c896fe29 bellard
    case INDEX_op_goto_tb:
1117 c896fe29 bellard
        if (s->tb_jmp_offset) {
1118 c896fe29 bellard
            /* direct jump method */
1119 da441cff Richard Henderson
            tcg_out8(s, OPC_JMP_long); /* jmp im */
1120 c896fe29 bellard
            s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
1121 c896fe29 bellard
            tcg_out32(s, 0);
1122 c896fe29 bellard
        } else {
1123 c896fe29 bellard
            /* indirect jump method */
1124 9363dedb Richard Henderson
            tcg_out_modrm_offset(s, OPC_GRP5, EXT5_JMPN_Ev, -1,
1125 c896fe29 bellard
                                 (tcg_target_long)(s->tb_next + args[0]));
1126 c896fe29 bellard
        }
1127 c896fe29 bellard
        s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
1128 c896fe29 bellard
        break;
1129 c896fe29 bellard
    case INDEX_op_call:
1130 c896fe29 bellard
        if (const_args[0]) {
1131 aadb21a4 Richard Henderson
            tcg_out_calli(s, args[0]);
1132 c896fe29 bellard
        } else {
1133 aadb21a4 Richard Henderson
            /* call *reg */
1134 9363dedb Richard Henderson
            tcg_out_modrm(s, OPC_GRP5, EXT5_CALLN_Ev, args[0]);
1135 c896fe29 bellard
        }
1136 c896fe29 bellard
        break;
1137 c896fe29 bellard
    case INDEX_op_jmp:
1138 c896fe29 bellard
        if (const_args[0]) {
1139 da441cff Richard Henderson
            tcg_out8(s, OPC_JMP_long);
1140 c896fe29 bellard
            tcg_out32(s, args[0] - (tcg_target_long)s->code_ptr - 4);
1141 c896fe29 bellard
        } else {
1142 da441cff Richard Henderson
            /* jmp *reg */
1143 9363dedb Richard Henderson
            tcg_out_modrm(s, OPC_GRP5, EXT5_JMPN_Ev, args[0]);
1144 c896fe29 bellard
        }
1145 c896fe29 bellard
        break;
1146 c896fe29 bellard
    case INDEX_op_br:
1147 f75b56c1 Richard Henderson
        tcg_out_jxx(s, JCC_JMP, args[0], 0);
1148 c896fe29 bellard
        break;
1149 c896fe29 bellard
    case INDEX_op_movi_i32:
1150 c896fe29 bellard
        tcg_out_movi(s, TCG_TYPE_I32, args[0], args[1]);
1151 c896fe29 bellard
        break;
1152 c896fe29 bellard
    case INDEX_op_ld8u_i32:
1153 c896fe29 bellard
        /* movzbl */
1154 55e082a7 Richard Henderson
        tcg_out_modrm_offset(s, OPC_MOVZBL, args[0], args[1], args[2]);
1155 c896fe29 bellard
        break;
1156 c896fe29 bellard
    case INDEX_op_ld8s_i32:
1157 c896fe29 bellard
        /* movsbl */
1158 6817c355 Richard Henderson
        tcg_out_modrm_offset(s, OPC_MOVSBL, args[0], args[1], args[2]);
1159 c896fe29 bellard
        break;
1160 c896fe29 bellard
    case INDEX_op_ld16u_i32:
1161 c896fe29 bellard
        /* movzwl */
1162 55e082a7 Richard Henderson
        tcg_out_modrm_offset(s, OPC_MOVZWL, args[0], args[1], args[2]);
1163 c896fe29 bellard
        break;
1164 c896fe29 bellard
    case INDEX_op_ld16s_i32:
1165 c896fe29 bellard
        /* movswl */
1166 6817c355 Richard Henderson
        tcg_out_modrm_offset(s, OPC_MOVSWL, args[0], args[1], args[2]);
1167 c896fe29 bellard
        break;
1168 c896fe29 bellard
    case INDEX_op_ld_i32:
1169 af266089 Richard Henderson
        tcg_out_ld(s, TCG_TYPE_I32, args[0], args[1], args[2]);
1170 c896fe29 bellard
        break;
1171 c896fe29 bellard
    case INDEX_op_st8_i32:
1172 c896fe29 bellard
        /* movb */
1173 af266089 Richard Henderson
        tcg_out_modrm_offset(s, OPC_MOVB_EvGv, args[0], args[1], args[2]);
1174 c896fe29 bellard
        break;
1175 c896fe29 bellard
    case INDEX_op_st16_i32:
1176 c896fe29 bellard
        /* movw */
1177 96b4cf38 Richard Henderson
        tcg_out_modrm_offset(s, OPC_MOVL_EvGv | P_DATA16,
1178 96b4cf38 Richard Henderson
                             args[0], args[1], args[2]);
1179 c896fe29 bellard
        break;
1180 c896fe29 bellard
    case INDEX_op_st_i32:
1181 af266089 Richard Henderson
        tcg_out_st(s, TCG_TYPE_I32, args[0], args[1], args[2]);
1182 c896fe29 bellard
        break;
1183 5d1e4e85 Richard Henderson
    case INDEX_op_add_i32:
1184 5d1e4e85 Richard Henderson
        /* For 3-operand addition, use LEA.  */
1185 5d1e4e85 Richard Henderson
        if (args[0] != args[1]) {
1186 5d1e4e85 Richard Henderson
            TCGArg a0 = args[0], a1 = args[1], a2 = args[2], c3 = 0;
1187 5d1e4e85 Richard Henderson
1188 5d1e4e85 Richard Henderson
            if (const_args[2]) {
1189 5d1e4e85 Richard Henderson
                c3 = a2, a2 = -1;
1190 5d1e4e85 Richard Henderson
            } else if (a0 == a2) {
1191 5d1e4e85 Richard Henderson
                /* Watch out for dest = src + dest, since we've removed
1192 5d1e4e85 Richard Henderson
                   the matching constraint on the add.  */
1193 5d1e4e85 Richard Henderson
                tgen_arithr(s, ARITH_ADD, a0, a1);
1194 5d1e4e85 Richard Henderson
                break;
1195 5d1e4e85 Richard Henderson
            }
1196 5d1e4e85 Richard Henderson
1197 5d1e4e85 Richard Henderson
            tcg_out_modrm_sib_offset(s, OPC_LEA, a0, a1, a2, 0, c3);
1198 5d1e4e85 Richard Henderson
            break;
1199 5d1e4e85 Richard Henderson
        }
1200 5d1e4e85 Richard Henderson
        c = ARITH_ADD;
1201 5d1e4e85 Richard Henderson
        goto gen_arith;
1202 c896fe29 bellard
    case INDEX_op_sub_i32:
1203 c896fe29 bellard
        c = ARITH_SUB;
1204 c896fe29 bellard
        goto gen_arith;
1205 c896fe29 bellard
    case INDEX_op_and_i32:
1206 c896fe29 bellard
        c = ARITH_AND;
1207 c896fe29 bellard
        goto gen_arith;
1208 c896fe29 bellard
    case INDEX_op_or_i32:
1209 c896fe29 bellard
        c = ARITH_OR;
1210 c896fe29 bellard
        goto gen_arith;
1211 c896fe29 bellard
    case INDEX_op_xor_i32:
1212 c896fe29 bellard
        c = ARITH_XOR;
1213 c896fe29 bellard
        goto gen_arith;
1214 c896fe29 bellard
    gen_arith:
1215 c896fe29 bellard
        if (const_args[2]) {
1216 17cf428f Aurelien Jarno
            tgen_arithi(s, c, args[0], args[2], 0);
1217 c896fe29 bellard
        } else {
1218 81570a70 Richard Henderson
            tgen_arithr(s, c, args[0], args[2]);
1219 c896fe29 bellard
        }
1220 c896fe29 bellard
        break;
1221 c896fe29 bellard
    case INDEX_op_mul_i32:
1222 c896fe29 bellard
        if (const_args[2]) {
1223 c896fe29 bellard
            int32_t val;
1224 c896fe29 bellard
            val = args[2];
1225 c896fe29 bellard
            if (val == (int8_t)val) {
1226 0566d387 Richard Henderson
                tcg_out_modrm(s, OPC_IMUL_GvEvIb, args[0], args[0]);
1227 c896fe29 bellard
                tcg_out8(s, val);
1228 c896fe29 bellard
            } else {
1229 0566d387 Richard Henderson
                tcg_out_modrm(s, OPC_IMUL_GvEvIz, args[0], args[0]);
1230 c896fe29 bellard
                tcg_out32(s, val);
1231 c896fe29 bellard
            }
1232 c896fe29 bellard
        } else {
1233 0566d387 Richard Henderson
            tcg_out_modrm(s, OPC_IMUL_GvEv, args[0], args[2]);
1234 c896fe29 bellard
        }
1235 c896fe29 bellard
        break;
1236 c896fe29 bellard
    case INDEX_op_mulu2_i32:
1237 9363dedb Richard Henderson
        tcg_out_modrm(s, OPC_GRP3_Ev, EXT3_MUL, args[3]);
1238 c896fe29 bellard
        break;
1239 c896fe29 bellard
    case INDEX_op_div2_i32:
1240 9363dedb Richard Henderson
        tcg_out_modrm(s, OPC_GRP3_Ev, EXT3_IDIV, args[4]);
1241 c896fe29 bellard
        break;
1242 c896fe29 bellard
    case INDEX_op_divu2_i32:
1243 9363dedb Richard Henderson
        tcg_out_modrm(s, OPC_GRP3_Ev, EXT3_DIV, args[4]);
1244 c896fe29 bellard
        break;
1245 c896fe29 bellard
    case INDEX_op_shl_i32:
1246 c896fe29 bellard
        c = SHIFT_SHL;
1247 c896fe29 bellard
    gen_shift32:
1248 c896fe29 bellard
        if (const_args[2]) {
1249 f53dba01 Richard Henderson
            tcg_out_shifti(s, c, args[0], args[2]);
1250 c896fe29 bellard
        } else {
1251 f53dba01 Richard Henderson
            tcg_out_modrm(s, OPC_SHIFT_cl, c, args[0]);
1252 c896fe29 bellard
        }
1253 c896fe29 bellard
        break;
1254 c896fe29 bellard
    case INDEX_op_shr_i32:
1255 c896fe29 bellard
        c = SHIFT_SHR;
1256 c896fe29 bellard
        goto gen_shift32;
1257 c896fe29 bellard
    case INDEX_op_sar_i32:
1258 c896fe29 bellard
        c = SHIFT_SAR;
1259 c896fe29 bellard
        goto gen_shift32;
1260 9619376c aurel32
    case INDEX_op_rotl_i32:
1261 9619376c aurel32
        c = SHIFT_ROL;
1262 9619376c aurel32
        goto gen_shift32;
1263 9619376c aurel32
    case INDEX_op_rotr_i32:
1264 9619376c aurel32
        c = SHIFT_ROR;
1265 9619376c aurel32
        goto gen_shift32;
1266 9619376c aurel32
1267 c896fe29 bellard
    case INDEX_op_add2_i32:
1268 81570a70 Richard Henderson
        if (const_args[4]) {
1269 17cf428f Aurelien Jarno
            tgen_arithi(s, ARITH_ADD, args[0], args[4], 1);
1270 81570a70 Richard Henderson
        } else {
1271 81570a70 Richard Henderson
            tgen_arithr(s, ARITH_ADD, args[0], args[4]);
1272 81570a70 Richard Henderson
        }
1273 81570a70 Richard Henderson
        if (const_args[5]) {
1274 17cf428f Aurelien Jarno
            tgen_arithi(s, ARITH_ADC, args[1], args[5], 1);
1275 81570a70 Richard Henderson
        } else {
1276 81570a70 Richard Henderson
            tgen_arithr(s, ARITH_ADC, args[1], args[5]);
1277 81570a70 Richard Henderson
        }
1278 c896fe29 bellard
        break;
1279 c896fe29 bellard
    case INDEX_op_sub2_i32:
1280 81570a70 Richard Henderson
        if (const_args[4]) {
1281 17cf428f Aurelien Jarno
            tgen_arithi(s, ARITH_SUB, args[0], args[4], 1);
1282 81570a70 Richard Henderson
        } else {
1283 81570a70 Richard Henderson
            tgen_arithr(s, ARITH_SUB, args[0], args[4]);
1284 81570a70 Richard Henderson
        }
1285 81570a70 Richard Henderson
        if (const_args[5]) {
1286 17cf428f Aurelien Jarno
            tgen_arithi(s, ARITH_SBB, args[1], args[5], 1);
1287 81570a70 Richard Henderson
        } else {
1288 81570a70 Richard Henderson
            tgen_arithr(s, ARITH_SBB, args[1], args[5]);
1289 81570a70 Richard Henderson
        }
1290 c896fe29 bellard
        break;
1291 c896fe29 bellard
    case INDEX_op_brcond_i32:
1292 f75b56c1 Richard Henderson
        tcg_out_brcond(s, args[2], args[0], args[1], const_args[1],
1293 f75b56c1 Richard Henderson
                       args[3], 0);
1294 c896fe29 bellard
        break;
1295 c896fe29 bellard
    case INDEX_op_brcond2_i32:
1296 f75b56c1 Richard Henderson
        tcg_out_brcond2(s, args, const_args, 0);
1297 c896fe29 bellard
        break;
1298 c896fe29 bellard
1299 5d40cd63 aurel32
    case INDEX_op_bswap16_i32:
1300 fcb5dac1 Richard Henderson
        tcg_out_rolw_8(s, args[0]);
1301 5d40cd63 aurel32
        break;
1302 66896cb8 aurel32
    case INDEX_op_bswap32_i32:
1303 fcb5dac1 Richard Henderson
        tcg_out_bswap32(s, args[0]);
1304 9619376c aurel32
        break;
1305 9619376c aurel32
1306 9619376c aurel32
    case INDEX_op_neg_i32:
1307 9363dedb Richard Henderson
        tcg_out_modrm(s, OPC_GRP3_Ev, EXT3_NEG, args[0]);
1308 9619376c aurel32
        break;
1309 9619376c aurel32
1310 9619376c aurel32
    case INDEX_op_not_i32:
1311 9363dedb Richard Henderson
        tcg_out_modrm(s, OPC_GRP3_Ev, EXT3_NOT, args[0]);
1312 9619376c aurel32
        break;
1313 9619376c aurel32
1314 9619376c aurel32
    case INDEX_op_ext8s_i32:
1315 6817c355 Richard Henderson
        tcg_out_ext8s(s, args[0], args[1]);
1316 9619376c aurel32
        break;
1317 9619376c aurel32
    case INDEX_op_ext16s_i32:
1318 6817c355 Richard Henderson
        tcg_out_ext16s(s, args[0], args[1]);
1319 9619376c aurel32
        break;
1320 5f0ce17f Aurelien Jarno
    case INDEX_op_ext8u_i32:
1321 55e082a7 Richard Henderson
        tcg_out_ext8u(s, args[0], args[1]);
1322 5f0ce17f Aurelien Jarno
        break;
1323 5f0ce17f Aurelien Jarno
    case INDEX_op_ext16u_i32:
1324 55e082a7 Richard Henderson
        tcg_out_ext16u(s, args[0], args[1]);
1325 5f0ce17f Aurelien Jarno
        break;
1326 9619376c aurel32
1327 1d2699ae Richard Henderson
    case INDEX_op_setcond_i32:
1328 1d2699ae Richard Henderson
        tcg_out_setcond(s, args[3], args[0], args[1], args[2], const_args[2]);
1329 1d2699ae Richard Henderson
        break;
1330 1d2699ae Richard Henderson
    case INDEX_op_setcond2_i32:
1331 1d2699ae Richard Henderson
        tcg_out_setcond2(s, args, const_args);
1332 1d2699ae Richard Henderson
        break;
1333 1d2699ae Richard Henderson
1334 c896fe29 bellard
    case INDEX_op_qemu_ld8u:
1335 c896fe29 bellard
        tcg_out_qemu_ld(s, args, 0);
1336 c896fe29 bellard
        break;
1337 c896fe29 bellard
    case INDEX_op_qemu_ld8s:
1338 c896fe29 bellard
        tcg_out_qemu_ld(s, args, 0 | 4);
1339 c896fe29 bellard
        break;
1340 c896fe29 bellard
    case INDEX_op_qemu_ld16u:
1341 c896fe29 bellard
        tcg_out_qemu_ld(s, args, 1);
1342 c896fe29 bellard
        break;
1343 c896fe29 bellard
    case INDEX_op_qemu_ld16s:
1344 c896fe29 bellard
        tcg_out_qemu_ld(s, args, 1 | 4);
1345 c896fe29 bellard
        break;
1346 86feb1c8 Richard Henderson
    case INDEX_op_qemu_ld32:
1347 c896fe29 bellard
        tcg_out_qemu_ld(s, args, 2);
1348 c896fe29 bellard
        break;
1349 c896fe29 bellard
    case INDEX_op_qemu_ld64:
1350 c896fe29 bellard
        tcg_out_qemu_ld(s, args, 3);
1351 c896fe29 bellard
        break;
1352 78686523 Richard Henderson
1353 c896fe29 bellard
    case INDEX_op_qemu_st8:
1354 c896fe29 bellard
        tcg_out_qemu_st(s, args, 0);
1355 c896fe29 bellard
        break;
1356 c896fe29 bellard
    case INDEX_op_qemu_st16:
1357 c896fe29 bellard
        tcg_out_qemu_st(s, args, 1);
1358 c896fe29 bellard
        break;
1359 c896fe29 bellard
    case INDEX_op_qemu_st32:
1360 c896fe29 bellard
        tcg_out_qemu_st(s, args, 2);
1361 c896fe29 bellard
        break;
1362 c896fe29 bellard
    case INDEX_op_qemu_st64:
1363 c896fe29 bellard
        tcg_out_qemu_st(s, args, 3);
1364 c896fe29 bellard
        break;
1365 c896fe29 bellard
1366 c896fe29 bellard
    default:
1367 c896fe29 bellard
        tcg_abort();
1368 c896fe29 bellard
    }
1369 c896fe29 bellard
}
1370 c896fe29 bellard
1371 c896fe29 bellard
static const TCGTargetOpDef x86_op_defs[] = {
1372 c896fe29 bellard
    { INDEX_op_exit_tb, { } },
1373 c896fe29 bellard
    { INDEX_op_goto_tb, { } },
1374 c896fe29 bellard
    { INDEX_op_call, { "ri" } },
1375 c896fe29 bellard
    { INDEX_op_jmp, { "ri" } },
1376 c896fe29 bellard
    { INDEX_op_br, { } },
1377 c896fe29 bellard
    { INDEX_op_mov_i32, { "r", "r" } },
1378 c896fe29 bellard
    { INDEX_op_movi_i32, { "r" } },
1379 c896fe29 bellard
    { INDEX_op_ld8u_i32, { "r", "r" } },
1380 c896fe29 bellard
    { INDEX_op_ld8s_i32, { "r", "r" } },
1381 c896fe29 bellard
    { INDEX_op_ld16u_i32, { "r", "r" } },
1382 c896fe29 bellard
    { INDEX_op_ld16s_i32, { "r", "r" } },
1383 c896fe29 bellard
    { INDEX_op_ld_i32, { "r", "r" } },
1384 c896fe29 bellard
    { INDEX_op_st8_i32, { "q", "r" } },
1385 c896fe29 bellard
    { INDEX_op_st16_i32, { "r", "r" } },
1386 c896fe29 bellard
    { INDEX_op_st_i32, { "r", "r" } },
1387 c896fe29 bellard
1388 5d1e4e85 Richard Henderson
    { INDEX_op_add_i32, { "r", "r", "ri" } },
1389 c896fe29 bellard
    { INDEX_op_sub_i32, { "r", "0", "ri" } },
1390 c896fe29 bellard
    { INDEX_op_mul_i32, { "r", "0", "ri" } },
1391 c896fe29 bellard
    { INDEX_op_mulu2_i32, { "a", "d", "a", "r" } },
1392 c896fe29 bellard
    { INDEX_op_div2_i32, { "a", "d", "0", "1", "r" } },
1393 c896fe29 bellard
    { INDEX_op_divu2_i32, { "a", "d", "0", "1", "r" } },
1394 c896fe29 bellard
    { INDEX_op_and_i32, { "r", "0", "ri" } },
1395 c896fe29 bellard
    { INDEX_op_or_i32, { "r", "0", "ri" } },
1396 c896fe29 bellard
    { INDEX_op_xor_i32, { "r", "0", "ri" } },
1397 c896fe29 bellard
1398 c896fe29 bellard
    { INDEX_op_shl_i32, { "r", "0", "ci" } },
1399 c896fe29 bellard
    { INDEX_op_shr_i32, { "r", "0", "ci" } },
1400 c896fe29 bellard
    { INDEX_op_sar_i32, { "r", "0", "ci" } },
1401 9619376c aurel32
    { INDEX_op_rotl_i32, { "r", "0", "ci" } },
1402 9619376c aurel32
    { INDEX_op_rotr_i32, { "r", "0", "ci" } },
1403 c896fe29 bellard
1404 c896fe29 bellard
    { INDEX_op_brcond_i32, { "r", "ri" } },
1405 c896fe29 bellard
1406 c896fe29 bellard
    { INDEX_op_add2_i32, { "r", "r", "0", "1", "ri", "ri" } },
1407 c896fe29 bellard
    { INDEX_op_sub2_i32, { "r", "r", "0", "1", "ri", "ri" } },
1408 c896fe29 bellard
    { INDEX_op_brcond2_i32, { "r", "r", "ri", "ri" } },
1409 c896fe29 bellard
1410 5d40cd63 aurel32
    { INDEX_op_bswap16_i32, { "r", "0" } },
1411 66896cb8 aurel32
    { INDEX_op_bswap32_i32, { "r", "0" } },
1412 9619376c aurel32
1413 9619376c aurel32
    { INDEX_op_neg_i32, { "r", "0" } },
1414 9619376c aurel32
1415 9619376c aurel32
    { INDEX_op_not_i32, { "r", "0" } },
1416 9619376c aurel32
1417 9619376c aurel32
    { INDEX_op_ext8s_i32, { "r", "q" } },
1418 9619376c aurel32
    { INDEX_op_ext16s_i32, { "r", "r" } },
1419 55e082a7 Richard Henderson
    { INDEX_op_ext8u_i32, { "r", "q" } },
1420 55e082a7 Richard Henderson
    { INDEX_op_ext16u_i32, { "r", "r" } },
1421 9619376c aurel32
1422 1d2699ae Richard Henderson
    { INDEX_op_setcond_i32, { "q", "r", "ri" } },
1423 1d2699ae Richard Henderson
    { INDEX_op_setcond2_i32, { "r", "r", "r", "ri", "ri" } },
1424 1d2699ae Richard Henderson
1425 c896fe29 bellard
#if TARGET_LONG_BITS == 32
1426 c896fe29 bellard
    { INDEX_op_qemu_ld8u, { "r", "L" } },
1427 c896fe29 bellard
    { INDEX_op_qemu_ld8s, { "r", "L" } },
1428 c896fe29 bellard
    { INDEX_op_qemu_ld16u, { "r", "L" } },
1429 c896fe29 bellard
    { INDEX_op_qemu_ld16s, { "r", "L" } },
1430 86feb1c8 Richard Henderson
    { INDEX_op_qemu_ld32, { "r", "L" } },
1431 c896fe29 bellard
    { INDEX_op_qemu_ld64, { "r", "r", "L" } },
1432 c896fe29 bellard
1433 c896fe29 bellard
    { INDEX_op_qemu_st8, { "cb", "L" } },
1434 c896fe29 bellard
    { INDEX_op_qemu_st16, { "L", "L" } },
1435 c896fe29 bellard
    { INDEX_op_qemu_st32, { "L", "L" } },
1436 c896fe29 bellard
    { INDEX_op_qemu_st64, { "L", "L", "L" } },
1437 c896fe29 bellard
#else
1438 c896fe29 bellard
    { INDEX_op_qemu_ld8u, { "r", "L", "L" } },
1439 c896fe29 bellard
    { INDEX_op_qemu_ld8s, { "r", "L", "L" } },
1440 c896fe29 bellard
    { INDEX_op_qemu_ld16u, { "r", "L", "L" } },
1441 c896fe29 bellard
    { INDEX_op_qemu_ld16s, { "r", "L", "L" } },
1442 86feb1c8 Richard Henderson
    { INDEX_op_qemu_ld32, { "r", "L", "L" } },
1443 c896fe29 bellard
    { INDEX_op_qemu_ld64, { "r", "r", "L", "L" } },
1444 c896fe29 bellard
1445 c896fe29 bellard
    { INDEX_op_qemu_st8, { "cb", "L", "L" } },
1446 c896fe29 bellard
    { INDEX_op_qemu_st16, { "L", "L", "L" } },
1447 c896fe29 bellard
    { INDEX_op_qemu_st32, { "L", "L", "L" } },
1448 c896fe29 bellard
    { INDEX_op_qemu_st64, { "L", "L", "L", "L" } },
1449 c896fe29 bellard
#endif
1450 c896fe29 bellard
    { -1 },
1451 c896fe29 bellard
};
1452 c896fe29 bellard
1453 b03cce8e bellard
static int tcg_target_callee_save_regs[] = {
1454 b03cce8e bellard
    /*    TCG_REG_EBP, */ /* currently used for the global env, so no
1455 b03cce8e bellard
                             need to save */
1456 b03cce8e bellard
    TCG_REG_EBX,
1457 b03cce8e bellard
    TCG_REG_ESI,
1458 b03cce8e bellard
    TCG_REG_EDI,
1459 b03cce8e bellard
};
1460 b03cce8e bellard
1461 b03cce8e bellard
/* Generate global QEMU prologue and epilogue code */
1462 b03cce8e bellard
void tcg_target_qemu_prologue(TCGContext *s)
1463 b03cce8e bellard
{
1464 b03cce8e bellard
    int i, frame_size, push_size, stack_addend;
1465 78686523 Richard Henderson
1466 b03cce8e bellard
    /* TB prologue */
1467 b03cce8e bellard
    /* save all callee saved registers */
1468 b03cce8e bellard
    for(i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
1469 b03cce8e bellard
        tcg_out_push(s, tcg_target_callee_save_regs[i]);
1470 b03cce8e bellard
    }
1471 b03cce8e bellard
    /* reserve some stack space */
1472 b03cce8e bellard
    push_size = 4 + ARRAY_SIZE(tcg_target_callee_save_regs) * 4;
1473 b03cce8e bellard
    frame_size = push_size + TCG_STATIC_CALL_ARGS_SIZE;
1474 78686523 Richard Henderson
    frame_size = (frame_size + TCG_TARGET_STACK_ALIGN - 1) &
1475 b03cce8e bellard
        ~(TCG_TARGET_STACK_ALIGN - 1);
1476 b03cce8e bellard
    stack_addend = frame_size - push_size;
1477 b03cce8e bellard
    tcg_out_addi(s, TCG_REG_ESP, -stack_addend);
1478 b03cce8e bellard
1479 9363dedb Richard Henderson
    tcg_out_modrm(s, OPC_GRP5, EXT5_JMPN_Ev, TCG_REG_EAX); /* jmp *%eax */
1480 78686523 Richard Henderson
1481 b03cce8e bellard
    /* TB epilogue */
1482 b03cce8e bellard
    tb_ret_addr = s->code_ptr;
1483 b03cce8e bellard
    tcg_out_addi(s, TCG_REG_ESP, stack_addend);
1484 b03cce8e bellard
    for(i = ARRAY_SIZE(tcg_target_callee_save_regs) - 1; i >= 0; i--) {
1485 b03cce8e bellard
        tcg_out_pop(s, tcg_target_callee_save_regs[i]);
1486 b03cce8e bellard
    }
1487 3c3accc6 Richard Henderson
    tcg_out_opc(s, OPC_RET);
1488 b03cce8e bellard
}
1489 b03cce8e bellard
1490 c896fe29 bellard
void tcg_target_init(TCGContext *s)
1491 c896fe29 bellard
{
1492 20cb400d Paul Brook
#if !defined(CONFIG_USER_ONLY)
1493 c896fe29 bellard
    /* fail safe */
1494 c896fe29 bellard
    if ((1 << CPU_TLB_ENTRY_BITS) != sizeof(CPUTLBEntry))
1495 c896fe29 bellard
        tcg_abort();
1496 20cb400d Paul Brook
#endif
1497 c896fe29 bellard
1498 c896fe29 bellard
    tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xff);
1499 4ab50ccf Richard Henderson
1500 4ab50ccf Richard Henderson
    tcg_regset_clear(tcg_target_call_clobber_regs);
1501 4ab50ccf Richard Henderson
    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_EAX);
1502 4ab50ccf Richard Henderson
    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_EDX);
1503 4ab50ccf Richard Henderson
    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_ECX);
1504 4ab50ccf Richard Henderson
1505 c896fe29 bellard
    tcg_regset_clear(s->reserved_regs);
1506 c896fe29 bellard
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_ESP);
1507 c896fe29 bellard
1508 c896fe29 bellard
    tcg_add_target_add_op_defs(x86_op_defs);
1509 c896fe29 bellard
}