Statistics
| Branch: | Revision:

root / tcg / i386 / tcg-target.c @ 6b64b624

History | View | Annotate | Download (60.5 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 5d8a4f8f Richard Henderson
#if TCG_TARGET_REG_BITS == 64
28 5d8a4f8f Richard Henderson
    "%rax", "%rcx", "%rdx", "%rbx", "%rsp", "%rbp", "%rsi", "%rdi",
29 5d8a4f8f Richard Henderson
    "%r8",  "%r9",  "%r10", "%r11", "%r12", "%r13", "%r14", "%r15",
30 5d8a4f8f Richard Henderson
#else
31 5d8a4f8f Richard Henderson
    "%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi",
32 5d8a4f8f Richard Henderson
#endif
33 c896fe29 bellard
};
34 d4a9eb1f blueswir1
#endif
35 c896fe29 bellard
36 d4a9eb1f blueswir1
static const int tcg_target_reg_alloc_order[] = {
37 5d8a4f8f Richard Henderson
#if TCG_TARGET_REG_BITS == 64
38 5d8a4f8f Richard Henderson
    TCG_REG_RBP,
39 5d8a4f8f Richard Henderson
    TCG_REG_RBX,
40 5d8a4f8f Richard Henderson
    TCG_REG_R12,
41 5d8a4f8f Richard Henderson
    TCG_REG_R13,
42 5d8a4f8f Richard Henderson
    TCG_REG_R14,
43 5d8a4f8f Richard Henderson
    TCG_REG_R15,
44 5d8a4f8f Richard Henderson
    TCG_REG_R10,
45 5d8a4f8f Richard Henderson
    TCG_REG_R11,
46 5d8a4f8f Richard Henderson
    TCG_REG_R9,
47 5d8a4f8f Richard Henderson
    TCG_REG_R8,
48 5d8a4f8f Richard Henderson
    TCG_REG_RCX,
49 5d8a4f8f Richard Henderson
    TCG_REG_RDX,
50 5d8a4f8f Richard Henderson
    TCG_REG_RSI,
51 5d8a4f8f Richard Henderson
    TCG_REG_RDI,
52 5d8a4f8f Richard Henderson
    TCG_REG_RAX,
53 5d8a4f8f Richard Henderson
#else
54 c896fe29 bellard
    TCG_REG_EBX,
55 c896fe29 bellard
    TCG_REG_ESI,
56 c896fe29 bellard
    TCG_REG_EDI,
57 c896fe29 bellard
    TCG_REG_EBP,
58 6648e296 Richard Henderson
    TCG_REG_ECX,
59 6648e296 Richard Henderson
    TCG_REG_EDX,
60 6648e296 Richard Henderson
    TCG_REG_EAX,
61 5d8a4f8f Richard Henderson
#endif
62 c896fe29 bellard
};
63 c896fe29 bellard
64 5d8a4f8f Richard Henderson
static const int tcg_target_call_iarg_regs[] = {
65 5d8a4f8f Richard Henderson
#if TCG_TARGET_REG_BITS == 64
66 5d8a4f8f Richard Henderson
    TCG_REG_RDI,
67 5d8a4f8f Richard Henderson
    TCG_REG_RSI,
68 5d8a4f8f Richard Henderson
    TCG_REG_RDX,
69 5d8a4f8f Richard Henderson
    TCG_REG_RCX,
70 5d8a4f8f Richard Henderson
    TCG_REG_R8,
71 5d8a4f8f Richard Henderson
    TCG_REG_R9,
72 5d8a4f8f Richard Henderson
#else
73 5d8a4f8f Richard Henderson
    TCG_REG_EAX,
74 5d8a4f8f Richard Henderson
    TCG_REG_EDX,
75 5d8a4f8f Richard Henderson
    TCG_REG_ECX
76 5d8a4f8f Richard Henderson
#endif
77 5d8a4f8f Richard Henderson
};
78 5d8a4f8f Richard Henderson
79 5d8a4f8f Richard Henderson
static const int tcg_target_call_oarg_regs[2] = {
80 5d8a4f8f Richard Henderson
    TCG_REG_EAX,
81 5d8a4f8f Richard Henderson
    TCG_REG_EDX
82 5d8a4f8f Richard Henderson
};
83 c896fe29 bellard
84 b03cce8e bellard
static uint8_t *tb_ret_addr;
85 b03cce8e bellard
86 78686523 Richard Henderson
static void patch_reloc(uint8_t *code_ptr, int type,
87 f54b3f92 aurel32
                        tcg_target_long value, tcg_target_long addend)
88 c896fe29 bellard
{
89 f54b3f92 aurel32
    value += addend;
90 c896fe29 bellard
    switch(type) {
91 c896fe29 bellard
    case R_386_PC32:
92 5d8a4f8f Richard Henderson
        value -= (uintptr_t)code_ptr;
93 5d8a4f8f Richard Henderson
        if (value != (int32_t)value) {
94 5d8a4f8f Richard Henderson
            tcg_abort();
95 5d8a4f8f Richard Henderson
        }
96 5d8a4f8f Richard Henderson
        *(uint32_t *)code_ptr = value;
97 c896fe29 bellard
        break;
98 f75b56c1 Richard Henderson
    case R_386_PC8:
99 5d8a4f8f Richard Henderson
        value -= (uintptr_t)code_ptr;
100 f75b56c1 Richard Henderson
        if (value != (int8_t)value) {
101 f75b56c1 Richard Henderson
            tcg_abort();
102 f75b56c1 Richard Henderson
        }
103 f75b56c1 Richard Henderson
        *(uint8_t *)code_ptr = value;
104 f75b56c1 Richard Henderson
        break;
105 c896fe29 bellard
    default:
106 c896fe29 bellard
        tcg_abort();
107 c896fe29 bellard
    }
108 c896fe29 bellard
}
109 c896fe29 bellard
110 c896fe29 bellard
/* maximum number of register used for input function arguments */
111 c896fe29 bellard
static inline int tcg_target_get_call_iarg_regs_count(int flags)
112 c896fe29 bellard
{
113 5d8a4f8f Richard Henderson
    if (TCG_TARGET_REG_BITS == 64) {
114 5d8a4f8f Richard Henderson
        return 6;
115 5d8a4f8f Richard Henderson
    }
116 5d8a4f8f Richard Henderson
117 c896fe29 bellard
    flags &= TCG_CALL_TYPE_MASK;
118 c896fe29 bellard
    switch(flags) {
119 c896fe29 bellard
    case TCG_CALL_TYPE_STD:
120 c896fe29 bellard
        return 0;
121 c896fe29 bellard
    case TCG_CALL_TYPE_REGPARM_1:
122 c896fe29 bellard
    case TCG_CALL_TYPE_REGPARM_2:
123 c896fe29 bellard
    case TCG_CALL_TYPE_REGPARM:
124 c896fe29 bellard
        return flags - TCG_CALL_TYPE_REGPARM_1 + 1;
125 c896fe29 bellard
    default:
126 c896fe29 bellard
        tcg_abort();
127 c896fe29 bellard
    }
128 c896fe29 bellard
}
129 c896fe29 bellard
130 c896fe29 bellard
/* parse target specific constraints */
131 d4a9eb1f blueswir1
static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
132 c896fe29 bellard
{
133 c896fe29 bellard
    const char *ct_str;
134 c896fe29 bellard
135 c896fe29 bellard
    ct_str = *pct_str;
136 c896fe29 bellard
    switch(ct_str[0]) {
137 c896fe29 bellard
    case 'a':
138 c896fe29 bellard
        ct->ct |= TCG_CT_REG;
139 c896fe29 bellard
        tcg_regset_set_reg(ct->u.regs, TCG_REG_EAX);
140 c896fe29 bellard
        break;
141 c896fe29 bellard
    case 'b':
142 c896fe29 bellard
        ct->ct |= TCG_CT_REG;
143 c896fe29 bellard
        tcg_regset_set_reg(ct->u.regs, TCG_REG_EBX);
144 c896fe29 bellard
        break;
145 c896fe29 bellard
    case 'c':
146 c896fe29 bellard
        ct->ct |= TCG_CT_REG;
147 c896fe29 bellard
        tcg_regset_set_reg(ct->u.regs, TCG_REG_ECX);
148 c896fe29 bellard
        break;
149 c896fe29 bellard
    case 'd':
150 c896fe29 bellard
        ct->ct |= TCG_CT_REG;
151 c896fe29 bellard
        tcg_regset_set_reg(ct->u.regs, TCG_REG_EDX);
152 c896fe29 bellard
        break;
153 c896fe29 bellard
    case 'S':
154 c896fe29 bellard
        ct->ct |= TCG_CT_REG;
155 c896fe29 bellard
        tcg_regset_set_reg(ct->u.regs, TCG_REG_ESI);
156 c896fe29 bellard
        break;
157 c896fe29 bellard
    case 'D':
158 c896fe29 bellard
        ct->ct |= TCG_CT_REG;
159 c896fe29 bellard
        tcg_regset_set_reg(ct->u.regs, TCG_REG_EDI);
160 c896fe29 bellard
        break;
161 c896fe29 bellard
    case 'q':
162 c896fe29 bellard
        ct->ct |= TCG_CT_REG;
163 5d8a4f8f Richard Henderson
        if (TCG_TARGET_REG_BITS == 64) {
164 5d8a4f8f Richard Henderson
            tcg_regset_set32(ct->u.regs, 0, 0xffff);
165 5d8a4f8f Richard Henderson
        } else {
166 5d8a4f8f Richard Henderson
            tcg_regset_set32(ct->u.regs, 0, 0xf);
167 5d8a4f8f Richard Henderson
        }
168 c896fe29 bellard
        break;
169 c896fe29 bellard
    case 'r':
170 c896fe29 bellard
        ct->ct |= TCG_CT_REG;
171 5d8a4f8f Richard Henderson
        if (TCG_TARGET_REG_BITS == 64) {
172 5d8a4f8f Richard Henderson
            tcg_regset_set32(ct->u.regs, 0, 0xffff);
173 5d8a4f8f Richard Henderson
        } else {
174 5d8a4f8f Richard Henderson
            tcg_regset_set32(ct->u.regs, 0, 0xff);
175 5d8a4f8f Richard Henderson
        }
176 c896fe29 bellard
        break;
177 c896fe29 bellard
178 c896fe29 bellard
        /* qemu_ld/st address constraint */
179 c896fe29 bellard
    case 'L':
180 c896fe29 bellard
        ct->ct |= TCG_CT_REG;
181 5d8a4f8f Richard Henderson
        if (TCG_TARGET_REG_BITS == 64) {
182 5d8a4f8f Richard Henderson
            tcg_regset_set32(ct->u.regs, 0, 0xffff);
183 5d8a4f8f Richard Henderson
            tcg_regset_reset_reg(ct->u.regs, TCG_REG_RSI);
184 5d8a4f8f Richard Henderson
            tcg_regset_reset_reg(ct->u.regs, TCG_REG_RDI);
185 5d8a4f8f Richard Henderson
        } else {
186 5d8a4f8f Richard Henderson
            tcg_regset_set32(ct->u.regs, 0, 0xff);
187 5d8a4f8f Richard Henderson
            tcg_regset_reset_reg(ct->u.regs, TCG_REG_EAX);
188 5d8a4f8f Richard Henderson
            tcg_regset_reset_reg(ct->u.regs, TCG_REG_EDX);
189 5d8a4f8f Richard Henderson
        }
190 5d8a4f8f Richard Henderson
        break;
191 5d8a4f8f Richard Henderson
192 5d8a4f8f Richard Henderson
    case 'e':
193 5d8a4f8f Richard Henderson
        ct->ct |= TCG_CT_CONST_S32;
194 5d8a4f8f Richard Henderson
        break;
195 5d8a4f8f Richard Henderson
    case 'Z':
196 5d8a4f8f Richard Henderson
        ct->ct |= TCG_CT_CONST_U32;
197 c896fe29 bellard
        break;
198 5d8a4f8f Richard Henderson
199 c896fe29 bellard
    default:
200 c896fe29 bellard
        return -1;
201 c896fe29 bellard
    }
202 c896fe29 bellard
    ct_str++;
203 c896fe29 bellard
    *pct_str = ct_str;
204 c896fe29 bellard
    return 0;
205 c896fe29 bellard
}
206 c896fe29 bellard
207 c896fe29 bellard
/* test if a constant matches the constraint */
208 c896fe29 bellard
static inline int tcg_target_const_match(tcg_target_long val,
209 c896fe29 bellard
                                         const TCGArgConstraint *arg_ct)
210 c896fe29 bellard
{
211 5d8a4f8f Richard Henderson
    int ct = arg_ct->ct;
212 5d8a4f8f Richard Henderson
    if (ct & TCG_CT_CONST) {
213 c896fe29 bellard
        return 1;
214 5d8a4f8f Richard Henderson
    }
215 5d8a4f8f Richard Henderson
    if ((ct & TCG_CT_CONST_S32) && val == (int32_t)val) {
216 5d8a4f8f Richard Henderson
        return 1;
217 5d8a4f8f Richard Henderson
    }
218 5d8a4f8f Richard Henderson
    if ((ct & TCG_CT_CONST_U32) && val == (uint32_t)val) {
219 5d8a4f8f Richard Henderson
        return 1;
220 5d8a4f8f Richard Henderson
    }
221 5d8a4f8f Richard Henderson
    return 0;
222 c896fe29 bellard
}
223 c896fe29 bellard
224 5d8a4f8f Richard Henderson
#if TCG_TARGET_REG_BITS == 64
225 5d8a4f8f Richard Henderson
# define LOWREGMASK(x)        ((x) & 7)
226 5d8a4f8f Richard Henderson
#else
227 5d8a4f8f Richard Henderson
# define LOWREGMASK(x)        (x)
228 5d8a4f8f Richard Henderson
#endif
229 5d8a4f8f Richard Henderson
230 96b4cf38 Richard Henderson
#define P_EXT                0x100                /* 0x0f opcode prefix */
231 96b4cf38 Richard Henderson
#define P_DATA16        0x200                /* 0x66 opcode prefix */
232 5d8a4f8f Richard Henderson
#if TCG_TARGET_REG_BITS == 64
233 5d8a4f8f Richard Henderson
# define P_ADDR32        0x400                /* 0x67 opcode prefix */
234 5d8a4f8f Richard Henderson
# define P_REXW                0x800                /* Set REX.W = 1 */
235 5d8a4f8f Richard Henderson
# define P_REXB_R        0x1000                /* REG field as byte register */
236 5d8a4f8f Richard Henderson
# define P_REXB_RM        0x2000                /* R/M field as byte register */
237 5d8a4f8f Richard Henderson
#else
238 5d8a4f8f Richard Henderson
# define P_ADDR32        0
239 5d8a4f8f Richard Henderson
# define P_REXW                0
240 5d8a4f8f Richard Henderson
# define P_REXB_R        0
241 5d8a4f8f Richard Henderson
# define P_REXB_RM        0
242 5d8a4f8f Richard Henderson
#endif
243 fcb5dac1 Richard Henderson
244 a369a702 Richard Henderson
#define OPC_ARITH_EvIz        (0x81)
245 a369a702 Richard Henderson
#define OPC_ARITH_EvIb        (0x83)
246 81570a70 Richard Henderson
#define OPC_ARITH_GvEv        (0x03)                /* ... plus (ARITH_FOO << 3) */
247 81570a70 Richard Henderson
#define OPC_ADD_GvEv        (OPC_ARITH_GvEv | (ARITH_ADD << 3))
248 fcb5dac1 Richard Henderson
#define OPC_BSWAP        (0xc8 | P_EXT)
249 aadb21a4 Richard Henderson
#define OPC_CALL_Jz        (0xe8)
250 81570a70 Richard Henderson
#define OPC_CMP_GvEv        (OPC_ARITH_GvEv | (ARITH_CMP << 3))
251 81570a70 Richard Henderson
#define OPC_DEC_r32        (0x48)
252 0566d387 Richard Henderson
#define OPC_IMUL_GvEv        (0xaf | P_EXT)
253 0566d387 Richard Henderson
#define OPC_IMUL_GvEvIb        (0x6b)
254 0566d387 Richard Henderson
#define OPC_IMUL_GvEvIz        (0x69)
255 81570a70 Richard Henderson
#define OPC_INC_r32        (0x40)
256 da441cff Richard Henderson
#define OPC_JCC_long        (0x80 | P_EXT)        /* ... plus condition code */
257 da441cff Richard Henderson
#define OPC_JCC_short        (0x70)                /* ... plus condition code */
258 da441cff Richard Henderson
#define OPC_JMP_long        (0xe9)
259 da441cff Richard Henderson
#define OPC_JMP_short        (0xeb)
260 34a6d0b7 Richard Henderson
#define OPC_LEA         (0x8d)
261 af266089 Richard Henderson
#define OPC_MOVB_EvGv        (0x88)                /* stores, more or less */
262 af266089 Richard Henderson
#define OPC_MOVL_EvGv        (0x89)                /* stores, more or less */
263 af266089 Richard Henderson
#define OPC_MOVL_GvEv        (0x8b)                /* loads, more or less */
264 5d8a4f8f Richard Henderson
#define OPC_MOVL_EvIz        (0xc7)
265 ef10b106 Richard Henderson
#define OPC_MOVL_Iv     (0xb8)
266 6817c355 Richard Henderson
#define OPC_MOVSBL        (0xbe | P_EXT)
267 6817c355 Richard Henderson
#define OPC_MOVSWL        (0xbf | P_EXT)
268 5d8a4f8f Richard Henderson
#define OPC_MOVSLQ        (0x63 | P_REXW)
269 55e082a7 Richard Henderson
#define OPC_MOVZBL        (0xb6 | P_EXT)
270 55e082a7 Richard Henderson
#define OPC_MOVZWL        (0xb7 | P_EXT)
271 6858614e Richard Henderson
#define OPC_POP_r32        (0x58)
272 6858614e Richard Henderson
#define OPC_PUSH_r32        (0x50)
273 6858614e Richard Henderson
#define OPC_PUSH_Iv        (0x68)
274 6858614e Richard Henderson
#define OPC_PUSH_Ib        (0x6a)
275 3c3accc6 Richard Henderson
#define OPC_RET                (0xc3)
276 5d8a4f8f Richard Henderson
#define OPC_SETCC        (0x90 | P_EXT | P_REXB_RM) /* ... plus cc */
277 f53dba01 Richard Henderson
#define OPC_SHIFT_1        (0xd1)
278 f53dba01 Richard Henderson
#define OPC_SHIFT_Ib        (0xc1)
279 f53dba01 Richard Henderson
#define OPC_SHIFT_cl        (0xd3)
280 81570a70 Richard Henderson
#define OPC_TESTL        (0x85)
281 b3e66df7 Richard Henderson
#define OPC_XCHG_ax_r32        (0x90)
282 fcb5dac1 Richard Henderson
283 9363dedb Richard Henderson
#define OPC_GRP3_Ev        (0xf7)
284 9363dedb Richard Henderson
#define OPC_GRP5        (0xff)
285 9363dedb Richard Henderson
286 9363dedb Richard Henderson
/* Group 1 opcode extensions for 0x80-0x83.
287 9363dedb Richard Henderson
   These are also used as modifiers for OPC_ARITH.  */
288 c896fe29 bellard
#define ARITH_ADD 0
289 c896fe29 bellard
#define ARITH_OR  1
290 c896fe29 bellard
#define ARITH_ADC 2
291 c896fe29 bellard
#define ARITH_SBB 3
292 c896fe29 bellard
#define ARITH_AND 4
293 c896fe29 bellard
#define ARITH_SUB 5
294 c896fe29 bellard
#define ARITH_XOR 6
295 c896fe29 bellard
#define ARITH_CMP 7
296 c896fe29 bellard
297 da441cff Richard Henderson
/* Group 2 opcode extensions for 0xc0, 0xc1, 0xd0-0xd3.  */
298 9619376c aurel32
#define SHIFT_ROL 0
299 9619376c aurel32
#define SHIFT_ROR 1
300 c896fe29 bellard
#define SHIFT_SHL 4
301 c896fe29 bellard
#define SHIFT_SHR 5
302 c896fe29 bellard
#define SHIFT_SAR 7
303 c896fe29 bellard
304 9363dedb Richard Henderson
/* Group 3 opcode extensions for 0xf6, 0xf7.  To be used with OPC_GRP3.  */
305 9363dedb Richard Henderson
#define EXT3_NOT   2
306 9363dedb Richard Henderson
#define EXT3_NEG   3
307 9363dedb Richard Henderson
#define EXT3_MUL   4
308 9363dedb Richard Henderson
#define EXT3_IMUL  5
309 9363dedb Richard Henderson
#define EXT3_DIV   6
310 9363dedb Richard Henderson
#define EXT3_IDIV  7
311 9363dedb Richard Henderson
312 9363dedb Richard Henderson
/* Group 5 opcode extensions for 0xff.  To be used with OPC_GRP5.  */
313 5d8a4f8f Richard Henderson
#define EXT5_INC_Ev        0
314 5d8a4f8f Richard Henderson
#define EXT5_DEC_Ev        1
315 9363dedb Richard Henderson
#define EXT5_CALLN_Ev        2
316 9363dedb Richard Henderson
#define EXT5_JMPN_Ev        4
317 da441cff Richard Henderson
318 da441cff Richard Henderson
/* Condition codes to be added to OPC_JCC_{long,short}.  */
319 c896fe29 bellard
#define JCC_JMP (-1)
320 c896fe29 bellard
#define JCC_JO  0x0
321 c896fe29 bellard
#define JCC_JNO 0x1
322 c896fe29 bellard
#define JCC_JB  0x2
323 c896fe29 bellard
#define JCC_JAE 0x3
324 c896fe29 bellard
#define JCC_JE  0x4
325 c896fe29 bellard
#define JCC_JNE 0x5
326 c896fe29 bellard
#define JCC_JBE 0x6
327 c896fe29 bellard
#define JCC_JA  0x7
328 c896fe29 bellard
#define JCC_JS  0x8
329 c896fe29 bellard
#define JCC_JNS 0x9
330 c896fe29 bellard
#define JCC_JP  0xa
331 c896fe29 bellard
#define JCC_JNP 0xb
332 c896fe29 bellard
#define JCC_JL  0xc
333 c896fe29 bellard
#define JCC_JGE 0xd
334 c896fe29 bellard
#define JCC_JLE 0xe
335 c896fe29 bellard
#define JCC_JG  0xf
336 c896fe29 bellard
337 c896fe29 bellard
static const uint8_t tcg_cond_to_jcc[10] = {
338 c896fe29 bellard
    [TCG_COND_EQ] = JCC_JE,
339 c896fe29 bellard
    [TCG_COND_NE] = JCC_JNE,
340 c896fe29 bellard
    [TCG_COND_LT] = JCC_JL,
341 c896fe29 bellard
    [TCG_COND_GE] = JCC_JGE,
342 c896fe29 bellard
    [TCG_COND_LE] = JCC_JLE,
343 c896fe29 bellard
    [TCG_COND_GT] = JCC_JG,
344 c896fe29 bellard
    [TCG_COND_LTU] = JCC_JB,
345 c896fe29 bellard
    [TCG_COND_GEU] = JCC_JAE,
346 c896fe29 bellard
    [TCG_COND_LEU] = JCC_JBE,
347 c896fe29 bellard
    [TCG_COND_GTU] = JCC_JA,
348 c896fe29 bellard
};
349 c896fe29 bellard
350 5d8a4f8f Richard Henderson
#if TCG_TARGET_REG_BITS == 64
351 5d8a4f8f Richard Henderson
static void tcg_out_opc(TCGContext *s, int opc, int r, int rm, int x)
352 5d8a4f8f Richard Henderson
{
353 5d8a4f8f Richard Henderson
    int rex;
354 5d8a4f8f Richard Henderson
355 5d8a4f8f Richard Henderson
    if (opc & P_DATA16) {
356 5d8a4f8f Richard Henderson
        /* We should never be asking for both 16 and 64-bit operation.  */
357 5d8a4f8f Richard Henderson
        assert((opc & P_REXW) == 0);
358 5d8a4f8f Richard Henderson
        tcg_out8(s, 0x66);
359 5d8a4f8f Richard Henderson
    }
360 5d8a4f8f Richard Henderson
    if (opc & P_ADDR32) {
361 5d8a4f8f Richard Henderson
        tcg_out8(s, 0x67);
362 5d8a4f8f Richard Henderson
    }
363 5d8a4f8f Richard Henderson
364 5d8a4f8f Richard Henderson
    rex = 0;
365 5d8a4f8f Richard Henderson
    rex |= (opc & P_REXW) >> 8;                /* REX.W */
366 5d8a4f8f Richard Henderson
    rex |= (r & 8) >> 1;                /* REX.R */
367 5d8a4f8f Richard Henderson
    rex |= (x & 8) >> 2;                /* REX.X */
368 5d8a4f8f Richard Henderson
    rex |= (rm & 8) >> 3;                /* REX.B */
369 5d8a4f8f Richard Henderson
370 5d8a4f8f Richard Henderson
    /* P_REXB_{R,RM} indicates that the given register is the low byte.
371 5d8a4f8f Richard Henderson
       For %[abcd]l we need no REX prefix, but for %{si,di,bp,sp}l we do,
372 5d8a4f8f Richard Henderson
       as otherwise the encoding indicates %[abcd]h.  Note that the values
373 5d8a4f8f Richard Henderson
       that are ORed in merely indicate that the REX byte must be present;
374 5d8a4f8f Richard Henderson
       those bits get discarded in output.  */
375 5d8a4f8f Richard Henderson
    rex |= opc & (r >= 4 ? P_REXB_R : 0);
376 5d8a4f8f Richard Henderson
    rex |= opc & (rm >= 4 ? P_REXB_RM : 0);
377 5d8a4f8f Richard Henderson
378 5d8a4f8f Richard Henderson
    if (rex) {
379 5d8a4f8f Richard Henderson
        tcg_out8(s, (uint8_t)(rex | 0x40));
380 5d8a4f8f Richard Henderson
    }
381 5d8a4f8f Richard Henderson
382 5d8a4f8f Richard Henderson
    if (opc & P_EXT) {
383 5d8a4f8f Richard Henderson
        tcg_out8(s, 0x0f);
384 5d8a4f8f Richard Henderson
    }
385 5d8a4f8f Richard Henderson
    tcg_out8(s, opc);
386 5d8a4f8f Richard Henderson
}
387 5d8a4f8f Richard Henderson
#else
388 5d8a4f8f Richard Henderson
static void tcg_out_opc(TCGContext *s, int opc)
389 c896fe29 bellard
{
390 96b4cf38 Richard Henderson
    if (opc & P_DATA16) {
391 96b4cf38 Richard Henderson
        tcg_out8(s, 0x66);
392 96b4cf38 Richard Henderson
    }
393 96b4cf38 Richard Henderson
    if (opc & P_EXT) {
394 c896fe29 bellard
        tcg_out8(s, 0x0f);
395 96b4cf38 Richard Henderson
    }
396 c896fe29 bellard
    tcg_out8(s, opc);
397 c896fe29 bellard
}
398 5d8a4f8f Richard Henderson
/* Discard the register arguments to tcg_out_opc early, so as not to penalize
399 5d8a4f8f Richard Henderson
   the 32-bit compilation paths.  This method works with all versions of gcc,
400 5d8a4f8f Richard Henderson
   whereas relying on optimization may not be able to exclude them.  */
401 5d8a4f8f Richard Henderson
#define tcg_out_opc(s, opc, r, rm, x)  (tcg_out_opc)(s, opc)
402 5d8a4f8f Richard Henderson
#endif
403 c896fe29 bellard
404 5d8a4f8f Richard Henderson
static void tcg_out_modrm(TCGContext *s, int opc, int r, int rm)
405 c896fe29 bellard
{
406 5d8a4f8f Richard Henderson
    tcg_out_opc(s, opc, r, rm, 0);
407 5d8a4f8f Richard Henderson
    tcg_out8(s, 0xc0 | (LOWREGMASK(r) << 3) | LOWREGMASK(rm));
408 c896fe29 bellard
}
409 c896fe29 bellard
410 34a6d0b7 Richard Henderson
/* Output an opcode with a full "rm + (index<<shift) + offset" address mode.
411 5d8a4f8f Richard Henderson
   We handle either RM and INDEX missing with a negative value.  In 64-bit
412 5d8a4f8f Richard Henderson
   mode for absolute addresses, ~RM is the size of the immediate operand
413 5d8a4f8f Richard Henderson
   that will follow the instruction.  */
414 34a6d0b7 Richard Henderson
415 34a6d0b7 Richard Henderson
static void tcg_out_modrm_sib_offset(TCGContext *s, int opc, int r, int rm,
416 5d8a4f8f Richard Henderson
                                     int index, int shift,
417 5d8a4f8f Richard Henderson
                                     tcg_target_long offset)
418 c896fe29 bellard
{
419 34a6d0b7 Richard Henderson
    int mod, len;
420 34a6d0b7 Richard Henderson
421 5d8a4f8f Richard Henderson
    if (index < 0 && rm < 0) {
422 5d8a4f8f Richard Henderson
        if (TCG_TARGET_REG_BITS == 64) {
423 5d8a4f8f Richard Henderson
            /* Try for a rip-relative addressing mode.  This has replaced
424 5d8a4f8f Richard Henderson
               the 32-bit-mode absolute addressing encoding.  */
425 5d8a4f8f Richard Henderson
            tcg_target_long pc = (tcg_target_long)s->code_ptr + 5 + ~rm;
426 5d8a4f8f Richard Henderson
            tcg_target_long disp = offset - pc;
427 5d8a4f8f Richard Henderson
            if (disp == (int32_t)disp) {
428 5d8a4f8f Richard Henderson
                tcg_out_opc(s, opc, r, 0, 0);
429 5d8a4f8f Richard Henderson
                tcg_out8(s, (LOWREGMASK(r) << 3) | 5);
430 5d8a4f8f Richard Henderson
                tcg_out32(s, disp);
431 5d8a4f8f Richard Henderson
                return;
432 5d8a4f8f Richard Henderson
            }
433 34a6d0b7 Richard Henderson
434 5d8a4f8f Richard Henderson
            /* Try for an absolute address encoding.  This requires the
435 5d8a4f8f Richard Henderson
               use of the MODRM+SIB encoding and is therefore larger than
436 5d8a4f8f Richard Henderson
               rip-relative addressing.  */
437 5d8a4f8f Richard Henderson
            if (offset == (int32_t)offset) {
438 5d8a4f8f Richard Henderson
                tcg_out_opc(s, opc, r, 0, 0);
439 5d8a4f8f Richard Henderson
                tcg_out8(s, (LOWREGMASK(r) << 3) | 4);
440 5d8a4f8f Richard Henderson
                tcg_out8(s, (4 << 3) | 5);
441 5d8a4f8f Richard Henderson
                tcg_out32(s, offset);
442 5d8a4f8f Richard Henderson
                return;
443 5d8a4f8f Richard Henderson
            }
444 5d8a4f8f Richard Henderson
445 5d8a4f8f Richard Henderson
            /* ??? The memory isn't directly addressable.  */
446 5d8a4f8f Richard Henderson
            tcg_abort();
447 5d8a4f8f Richard Henderson
        } else {
448 5d8a4f8f Richard Henderson
            /* Absolute address.  */
449 5d8a4f8f Richard Henderson
            tcg_out_opc(s, opc, r, 0, 0);
450 5d8a4f8f Richard Henderson
            tcg_out8(s, (r << 3) | 5);
451 5d8a4f8f Richard Henderson
            tcg_out32(s, offset);
452 5d8a4f8f Richard Henderson
            return;
453 5d8a4f8f Richard Henderson
        }
454 5d8a4f8f Richard Henderson
    }
455 34a6d0b7 Richard Henderson
456 34a6d0b7 Richard Henderson
    /* Find the length of the immediate addend.  Note that the encoding
457 34a6d0b7 Richard Henderson
       that would be used for (%ebp) indicates absolute addressing.  */
458 5d8a4f8f Richard Henderson
    if (rm < 0) {
459 34a6d0b7 Richard Henderson
        mod = 0, len = 4, rm = 5;
460 5d8a4f8f Richard Henderson
    } else if (offset == 0 && LOWREGMASK(rm) != TCG_REG_EBP) {
461 34a6d0b7 Richard Henderson
        mod = 0, len = 0;
462 34a6d0b7 Richard Henderson
    } else if (offset == (int8_t)offset) {
463 34a6d0b7 Richard Henderson
        mod = 0x40, len = 1;
464 c896fe29 bellard
    } else {
465 34a6d0b7 Richard Henderson
        mod = 0x80, len = 4;
466 34a6d0b7 Richard Henderson
    }
467 34a6d0b7 Richard Henderson
468 34a6d0b7 Richard Henderson
    /* Use a single byte MODRM format if possible.  Note that the encoding
469 34a6d0b7 Richard Henderson
       that would be used for %esp is the escape to the two byte form.  */
470 5d8a4f8f Richard Henderson
    if (index < 0 && LOWREGMASK(rm) != TCG_REG_ESP) {
471 34a6d0b7 Richard Henderson
        /* Single byte MODRM format.  */
472 5d8a4f8f Richard Henderson
        tcg_out_opc(s, opc, r, rm, 0);
473 5d8a4f8f Richard Henderson
        tcg_out8(s, mod | (LOWREGMASK(r) << 3) | LOWREGMASK(rm));
474 34a6d0b7 Richard Henderson
    } else {
475 34a6d0b7 Richard Henderson
        /* Two byte MODRM+SIB format.  */
476 34a6d0b7 Richard Henderson
477 34a6d0b7 Richard Henderson
        /* Note that the encoding that would place %esp into the index
478 5d8a4f8f Richard Henderson
           field indicates no index register.  In 64-bit mode, the REX.X
479 5d8a4f8f Richard Henderson
           bit counts, so %r12 can be used as the index.  */
480 5d8a4f8f Richard Henderson
        if (index < 0) {
481 34a6d0b7 Richard Henderson
            index = 4;
482 c896fe29 bellard
        } else {
483 34a6d0b7 Richard Henderson
            assert(index != TCG_REG_ESP);
484 c896fe29 bellard
        }
485 34a6d0b7 Richard Henderson
486 5d8a4f8f Richard Henderson
        tcg_out_opc(s, opc, r, rm, index);
487 5d8a4f8f Richard Henderson
        tcg_out8(s, mod | (LOWREGMASK(r) << 3) | 4);
488 5d8a4f8f Richard Henderson
        tcg_out8(s, (shift << 6) | (LOWREGMASK(index) << 3) | LOWREGMASK(rm));
489 34a6d0b7 Richard Henderson
    }
490 34a6d0b7 Richard Henderson
491 34a6d0b7 Richard Henderson
    if (len == 1) {
492 34a6d0b7 Richard Henderson
        tcg_out8(s, offset);
493 34a6d0b7 Richard Henderson
    } else if (len == 4) {
494 c896fe29 bellard
        tcg_out32(s, offset);
495 c896fe29 bellard
    }
496 c896fe29 bellard
}
497 c896fe29 bellard
498 5d8a4f8f Richard Henderson
/* A simplification of the above with no index or shift.  */
499 5d8a4f8f Richard Henderson
static inline void tcg_out_modrm_offset(TCGContext *s, int opc, int r,
500 5d8a4f8f Richard Henderson
                                        int rm, tcg_target_long offset)
501 34a6d0b7 Richard Henderson
{
502 34a6d0b7 Richard Henderson
    tcg_out_modrm_sib_offset(s, opc, r, rm, -1, 0, offset);
503 34a6d0b7 Richard Henderson
}
504 34a6d0b7 Richard Henderson
505 81570a70 Richard Henderson
/* Generate dest op= src.  Uses the same ARITH_* codes as tgen_arithi.  */
506 81570a70 Richard Henderson
static inline void tgen_arithr(TCGContext *s, int subop, int dest, int src)
507 81570a70 Richard Henderson
{
508 5d8a4f8f Richard Henderson
    /* Propagate an opcode prefix, such as P_REXW.  */
509 5d8a4f8f Richard Henderson
    int ext = subop & ~0x7;
510 5d8a4f8f Richard Henderson
    subop &= 0x7;
511 5d8a4f8f Richard Henderson
512 5d8a4f8f Richard Henderson
    tcg_out_modrm(s, OPC_ARITH_GvEv + (subop << 3) + ext, dest, src);
513 81570a70 Richard Henderson
}
514 81570a70 Richard Henderson
515 3b6dac34 Richard Henderson
static inline void tcg_out_mov(TCGContext *s, TCGType type, int ret, int arg)
516 c896fe29 bellard
{
517 af266089 Richard Henderson
    if (arg != ret) {
518 5d8a4f8f Richard Henderson
        int opc = OPC_MOVL_GvEv + (type == TCG_TYPE_I64 ? P_REXW : 0);
519 5d8a4f8f Richard Henderson
        tcg_out_modrm(s, opc, ret, arg);
520 af266089 Richard Henderson
    }
521 c896fe29 bellard
}
522 c896fe29 bellard
523 5d8a4f8f Richard Henderson
static void tcg_out_movi(TCGContext *s, TCGType type,
524 5d8a4f8f Richard Henderson
                         int ret, tcg_target_long arg)
525 c896fe29 bellard
{
526 c896fe29 bellard
    if (arg == 0) {
527 81570a70 Richard Henderson
        tgen_arithr(s, ARITH_XOR, ret, ret);
528 5d8a4f8f Richard Henderson
        return;
529 5d8a4f8f Richard Henderson
    } else if (arg == (uint32_t)arg || type == TCG_TYPE_I32) {
530 5d8a4f8f Richard Henderson
        tcg_out_opc(s, OPC_MOVL_Iv + LOWREGMASK(ret), 0, ret, 0);
531 5d8a4f8f Richard Henderson
        tcg_out32(s, arg);
532 5d8a4f8f Richard Henderson
    } else if (arg == (int32_t)arg) {
533 5d8a4f8f Richard Henderson
        tcg_out_modrm(s, OPC_MOVL_EvIz + P_REXW, 0, ret);
534 5d8a4f8f Richard Henderson
        tcg_out32(s, arg);
535 c896fe29 bellard
    } else {
536 5d8a4f8f Richard Henderson
        tcg_out_opc(s, OPC_MOVL_Iv + P_REXW + LOWREGMASK(ret), 0, ret, 0);
537 c896fe29 bellard
        tcg_out32(s, arg);
538 5d8a4f8f Richard Henderson
        tcg_out32(s, arg >> 31 >> 1);
539 c896fe29 bellard
    }
540 c896fe29 bellard
}
541 c896fe29 bellard
542 6858614e Richard Henderson
static inline void tcg_out_pushi(TCGContext *s, tcg_target_long val)
543 6858614e Richard Henderson
{
544 6858614e Richard Henderson
    if (val == (int8_t)val) {
545 5d8a4f8f Richard Henderson
        tcg_out_opc(s, OPC_PUSH_Ib, 0, 0, 0);
546 6858614e Richard Henderson
        tcg_out8(s, val);
547 5d8a4f8f Richard Henderson
    } else if (val == (int32_t)val) {
548 5d8a4f8f Richard Henderson
        tcg_out_opc(s, OPC_PUSH_Iv, 0, 0, 0);
549 6858614e Richard Henderson
        tcg_out32(s, val);
550 5d8a4f8f Richard Henderson
    } else {
551 5d8a4f8f Richard Henderson
        tcg_abort();
552 6858614e Richard Henderson
    }
553 6858614e Richard Henderson
}
554 6858614e Richard Henderson
555 6858614e Richard Henderson
static inline void tcg_out_push(TCGContext *s, int reg)
556 6858614e Richard Henderson
{
557 5d8a4f8f Richard Henderson
    tcg_out_opc(s, OPC_PUSH_r32 + LOWREGMASK(reg), 0, reg, 0);
558 6858614e Richard Henderson
}
559 6858614e Richard Henderson
560 6858614e Richard Henderson
static inline void tcg_out_pop(TCGContext *s, int reg)
561 6858614e Richard Henderson
{
562 5d8a4f8f Richard Henderson
    tcg_out_opc(s, OPC_POP_r32 + LOWREGMASK(reg), 0, reg, 0);
563 6858614e Richard Henderson
}
564 6858614e Richard Henderson
565 e4d5434c blueswir1
static inline void tcg_out_ld(TCGContext *s, TCGType type, int ret,
566 e4d5434c blueswir1
                              int arg1, tcg_target_long arg2)
567 c896fe29 bellard
{
568 5d8a4f8f Richard Henderson
    int opc = OPC_MOVL_GvEv + (type == TCG_TYPE_I64 ? P_REXW : 0);
569 5d8a4f8f Richard Henderson
    tcg_out_modrm_offset(s, opc, ret, arg1, arg2);
570 c896fe29 bellard
}
571 c896fe29 bellard
572 e4d5434c blueswir1
static inline void tcg_out_st(TCGContext *s, TCGType type, int arg,
573 e4d5434c blueswir1
                              int arg1, tcg_target_long arg2)
574 c896fe29 bellard
{
575 5d8a4f8f Richard Henderson
    int opc = OPC_MOVL_EvGv + (type == TCG_TYPE_I64 ? P_REXW : 0);
576 5d8a4f8f Richard Henderson
    tcg_out_modrm_offset(s, opc, arg, arg1, arg2);
577 c896fe29 bellard
}
578 c896fe29 bellard
579 f53dba01 Richard Henderson
static void tcg_out_shifti(TCGContext *s, int subopc, int reg, int count)
580 f53dba01 Richard Henderson
{
581 96b4cf38 Richard Henderson
    /* Propagate an opcode prefix, such as P_DATA16.  */
582 96b4cf38 Richard Henderson
    int ext = subopc & ~0x7;
583 96b4cf38 Richard Henderson
    subopc &= 0x7;
584 96b4cf38 Richard Henderson
585 f53dba01 Richard Henderson
    if (count == 1) {
586 5d8a4f8f Richard Henderson
        tcg_out_modrm(s, OPC_SHIFT_1 + ext, subopc, reg);
587 f53dba01 Richard Henderson
    } else {
588 5d8a4f8f Richard Henderson
        tcg_out_modrm(s, OPC_SHIFT_Ib + ext, subopc, reg);
589 f53dba01 Richard Henderson
        tcg_out8(s, count);
590 f53dba01 Richard Henderson
    }
591 f53dba01 Richard Henderson
}
592 f53dba01 Richard Henderson
593 fcb5dac1 Richard Henderson
static inline void tcg_out_bswap32(TCGContext *s, int reg)
594 fcb5dac1 Richard Henderson
{
595 5d8a4f8f Richard Henderson
    tcg_out_opc(s, OPC_BSWAP + LOWREGMASK(reg), 0, reg, 0);
596 fcb5dac1 Richard Henderson
}
597 fcb5dac1 Richard Henderson
598 fcb5dac1 Richard Henderson
static inline void tcg_out_rolw_8(TCGContext *s, int reg)
599 fcb5dac1 Richard Henderson
{
600 5d8a4f8f Richard Henderson
    tcg_out_shifti(s, SHIFT_ROL + P_DATA16, reg, 8);
601 fcb5dac1 Richard Henderson
}
602 fcb5dac1 Richard Henderson
603 55e082a7 Richard Henderson
static inline void tcg_out_ext8u(TCGContext *s, int dest, int src)
604 55e082a7 Richard Henderson
{
605 55e082a7 Richard Henderson
    /* movzbl */
606 5d8a4f8f Richard Henderson
    assert(src < 4 || TCG_TARGET_REG_BITS == 64);
607 5d8a4f8f Richard Henderson
    tcg_out_modrm(s, OPC_MOVZBL + P_REXB_RM, dest, src);
608 55e082a7 Richard Henderson
}
609 55e082a7 Richard Henderson
610 5d8a4f8f Richard Henderson
static void tcg_out_ext8s(TCGContext *s, int dest, int src, int rexw)
611 6817c355 Richard Henderson
{
612 6817c355 Richard Henderson
    /* movsbl */
613 5d8a4f8f Richard Henderson
    assert(src < 4 || TCG_TARGET_REG_BITS == 64);
614 5d8a4f8f Richard Henderson
    tcg_out_modrm(s, OPC_MOVSBL + P_REXB_RM + rexw, dest, src);
615 6817c355 Richard Henderson
}
616 6817c355 Richard Henderson
617 55e082a7 Richard Henderson
static inline void tcg_out_ext16u(TCGContext *s, int dest, int src)
618 55e082a7 Richard Henderson
{
619 55e082a7 Richard Henderson
    /* movzwl */
620 55e082a7 Richard Henderson
    tcg_out_modrm(s, OPC_MOVZWL, dest, src);
621 55e082a7 Richard Henderson
}
622 55e082a7 Richard Henderson
623 5d8a4f8f Richard Henderson
static inline void tcg_out_ext16s(TCGContext *s, int dest, int src, int rexw)
624 6817c355 Richard Henderson
{
625 5d8a4f8f Richard Henderson
    /* movsw[lq] */
626 5d8a4f8f Richard Henderson
    tcg_out_modrm(s, OPC_MOVSWL + rexw, dest, src);
627 6817c355 Richard Henderson
}
628 6817c355 Richard Henderson
629 5d8a4f8f Richard Henderson
static inline void tcg_out_ext32u(TCGContext *s, int dest, int src)
630 c896fe29 bellard
{
631 5d8a4f8f Richard Henderson
    /* 32-bit mov zero extends.  */
632 5d8a4f8f Richard Henderson
    tcg_out_modrm(s, OPC_MOVL_GvEv, dest, src);
633 5d8a4f8f Richard Henderson
}
634 5d8a4f8f Richard Henderson
635 5d8a4f8f Richard Henderson
static inline void tcg_out_ext32s(TCGContext *s, int dest, int src)
636 5d8a4f8f Richard Henderson
{
637 5d8a4f8f Richard Henderson
    tcg_out_modrm(s, OPC_MOVSLQ, dest, src);
638 5d8a4f8f Richard Henderson
}
639 5d8a4f8f Richard Henderson
640 5d8a4f8f Richard Henderson
static inline void tcg_out_bswap64(TCGContext *s, int reg)
641 5d8a4f8f Richard Henderson
{
642 5d8a4f8f Richard Henderson
    tcg_out_opc(s, OPC_BSWAP + P_REXW + LOWREGMASK(reg), 0, reg, 0);
643 5d8a4f8f Richard Henderson
}
644 5d8a4f8f Richard Henderson
645 5d8a4f8f Richard Henderson
static void tgen_arithi(TCGContext *s, int c, int r0,
646 5d8a4f8f Richard Henderson
                        tcg_target_long val, int cf)
647 5d8a4f8f Richard Henderson
{
648 5d8a4f8f Richard Henderson
    int rexw = 0;
649 5d8a4f8f Richard Henderson
650 5d8a4f8f Richard Henderson
    if (TCG_TARGET_REG_BITS == 64) {
651 5d8a4f8f Richard Henderson
        rexw = c & -8;
652 5d8a4f8f Richard Henderson
        c &= 7;
653 5d8a4f8f Richard Henderson
    }
654 5d8a4f8f Richard Henderson
655 81570a70 Richard Henderson
    /* ??? While INC is 2 bytes shorter than ADDL $1, they also induce
656 81570a70 Richard Henderson
       partial flags update stalls on Pentium4 and are not recommended
657 81570a70 Richard Henderson
       by current Intel optimization manuals.  */
658 81570a70 Richard Henderson
    if (!cf && (c == ARITH_ADD || c == ARITH_SUB) && (val == 1 || val == -1)) {
659 447d681e Aurelien Jarno
        int is_inc = (c == ARITH_ADD) ^ (val < 0);
660 5d8a4f8f Richard Henderson
        if (TCG_TARGET_REG_BITS == 64) {
661 5d8a4f8f Richard Henderson
            /* The single-byte increment encodings are re-tasked as the
662 5d8a4f8f Richard Henderson
               REX prefixes.  Use the MODRM encoding.  */
663 5d8a4f8f Richard Henderson
            tcg_out_modrm(s, OPC_GRP5 + rexw,
664 5d8a4f8f Richard Henderson
                          (is_inc ? EXT5_INC_Ev : EXT5_DEC_Ev), r0);
665 5d8a4f8f Richard Henderson
        } else {
666 5d8a4f8f Richard Henderson
            tcg_out8(s, (is_inc ? OPC_INC_r32 : OPC_DEC_r32) + r0);
667 5d8a4f8f Richard Henderson
        }
668 5d8a4f8f Richard Henderson
        return;
669 5d8a4f8f Richard Henderson
    }
670 5d8a4f8f Richard Henderson
671 5d8a4f8f Richard Henderson
    if (c == ARITH_AND) {
672 5d8a4f8f Richard Henderson
        if (TCG_TARGET_REG_BITS == 64) {
673 5d8a4f8f Richard Henderson
            if (val == 0xffffffffu) {
674 5d8a4f8f Richard Henderson
                tcg_out_ext32u(s, r0, r0);
675 5d8a4f8f Richard Henderson
                return;
676 5d8a4f8f Richard Henderson
            }
677 5d8a4f8f Richard Henderson
            if (val == (uint32_t)val) {
678 5d8a4f8f Richard Henderson
                /* AND with no high bits set can use a 32-bit operation.  */
679 5d8a4f8f Richard Henderson
                rexw = 0;
680 5d8a4f8f Richard Henderson
            }
681 5d8a4f8f Richard Henderson
        }
682 dc397ca3 Aurelien Jarno
        if (val == 0xffu && (r0 < 4 || TCG_TARGET_REG_BITS == 64)) {
683 5d8a4f8f Richard Henderson
            tcg_out_ext8u(s, r0, r0);
684 5d8a4f8f Richard Henderson
            return;
685 5d8a4f8f Richard Henderson
        }
686 5d8a4f8f Richard Henderson
        if (val == 0xffffu) {
687 5d8a4f8f Richard Henderson
            tcg_out_ext16u(s, r0, r0);
688 5d8a4f8f Richard Henderson
            return;
689 5d8a4f8f Richard Henderson
        }
690 5d8a4f8f Richard Henderson
    }
691 5d8a4f8f Richard Henderson
692 5d8a4f8f Richard Henderson
    if (val == (int8_t)val) {
693 5d8a4f8f Richard Henderson
        tcg_out_modrm(s, OPC_ARITH_EvIb + rexw, c, r0);
694 c896fe29 bellard
        tcg_out8(s, val);
695 5d8a4f8f Richard Henderson
        return;
696 5d8a4f8f Richard Henderson
    }
697 5d8a4f8f Richard Henderson
    if (rexw == 0 || val == (int32_t)val) {
698 5d8a4f8f Richard Henderson
        tcg_out_modrm(s, OPC_ARITH_EvIz + rexw, c, r0);
699 c896fe29 bellard
        tcg_out32(s, val);
700 5d8a4f8f Richard Henderson
        return;
701 c896fe29 bellard
    }
702 5d8a4f8f Richard Henderson
703 5d8a4f8f Richard Henderson
    tcg_abort();
704 c896fe29 bellard
}
705 c896fe29 bellard
706 3e9a474e aurel32
static void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
707 c896fe29 bellard
{
708 5d8a4f8f Richard Henderson
    if (val != 0) {
709 5d8a4f8f Richard Henderson
        tgen_arithi(s, ARITH_ADD + P_REXW, reg, val, 0);
710 5d8a4f8f Richard Henderson
    }
711 c896fe29 bellard
}
712 c896fe29 bellard
713 f75b56c1 Richard Henderson
/* Use SMALL != 0 to force a short forward branch.  */
714 f75b56c1 Richard Henderson
static void tcg_out_jxx(TCGContext *s, int opc, int label_index, int small)
715 c896fe29 bellard
{
716 c896fe29 bellard
    int32_t val, val1;
717 c896fe29 bellard
    TCGLabel *l = &s->labels[label_index];
718 78686523 Richard Henderson
719 c896fe29 bellard
    if (l->has_value) {
720 c896fe29 bellard
        val = l->u.value - (tcg_target_long)s->code_ptr;
721 c896fe29 bellard
        val1 = val - 2;
722 c896fe29 bellard
        if ((int8_t)val1 == val1) {
723 f75b56c1 Richard Henderson
            if (opc == -1) {
724 da441cff Richard Henderson
                tcg_out8(s, OPC_JMP_short);
725 f75b56c1 Richard Henderson
            } else {
726 da441cff Richard Henderson
                tcg_out8(s, OPC_JCC_short + opc);
727 f75b56c1 Richard Henderson
            }
728 c896fe29 bellard
            tcg_out8(s, val1);
729 c896fe29 bellard
        } else {
730 f75b56c1 Richard Henderson
            if (small) {
731 f75b56c1 Richard Henderson
                tcg_abort();
732 f75b56c1 Richard Henderson
            }
733 c896fe29 bellard
            if (opc == -1) {
734 da441cff Richard Henderson
                tcg_out8(s, OPC_JMP_long);
735 c896fe29 bellard
                tcg_out32(s, val - 5);
736 c896fe29 bellard
            } else {
737 5d8a4f8f Richard Henderson
                tcg_out_opc(s, OPC_JCC_long + opc, 0, 0, 0);
738 c896fe29 bellard
                tcg_out32(s, val - 6);
739 c896fe29 bellard
            }
740 c896fe29 bellard
        }
741 f75b56c1 Richard Henderson
    } else if (small) {
742 f75b56c1 Richard Henderson
        if (opc == -1) {
743 da441cff Richard Henderson
            tcg_out8(s, OPC_JMP_short);
744 f75b56c1 Richard Henderson
        } else {
745 da441cff Richard Henderson
            tcg_out8(s, OPC_JCC_short + opc);
746 f75b56c1 Richard Henderson
        }
747 f75b56c1 Richard Henderson
        tcg_out_reloc(s, s->code_ptr, R_386_PC8, label_index, -1);
748 f75b56c1 Richard Henderson
        s->code_ptr += 1;
749 c896fe29 bellard
    } else {
750 c896fe29 bellard
        if (opc == -1) {
751 da441cff Richard Henderson
            tcg_out8(s, OPC_JMP_long);
752 c896fe29 bellard
        } else {
753 5d8a4f8f Richard Henderson
            tcg_out_opc(s, OPC_JCC_long + opc, 0, 0, 0);
754 c896fe29 bellard
        }
755 c896fe29 bellard
        tcg_out_reloc(s, s->code_ptr, R_386_PC32, label_index, -4);
756 623e265c pbrook
        s->code_ptr += 4;
757 c896fe29 bellard
    }
758 c896fe29 bellard
}
759 c896fe29 bellard
760 1d2699ae Richard Henderson
static void tcg_out_cmp(TCGContext *s, TCGArg arg1, TCGArg arg2,
761 5d8a4f8f Richard Henderson
                        int const_arg2, int rexw)
762 c896fe29 bellard
{
763 c896fe29 bellard
    if (const_arg2) {
764 c896fe29 bellard
        if (arg2 == 0) {
765 c896fe29 bellard
            /* test r, r */
766 5d8a4f8f Richard Henderson
            tcg_out_modrm(s, OPC_TESTL + rexw, arg1, arg1);
767 c896fe29 bellard
        } else {
768 5d8a4f8f Richard Henderson
            tgen_arithi(s, ARITH_CMP + rexw, arg1, arg2, 0);
769 c896fe29 bellard
        }
770 c896fe29 bellard
    } else {
771 5d8a4f8f Richard Henderson
        tgen_arithr(s, ARITH_CMP + rexw, arg1, arg2);
772 c896fe29 bellard
    }
773 1d2699ae Richard Henderson
}
774 1d2699ae Richard Henderson
775 5d8a4f8f Richard Henderson
static void tcg_out_brcond32(TCGContext *s, TCGCond cond,
776 5d8a4f8f Richard Henderson
                             TCGArg arg1, TCGArg arg2, int const_arg2,
777 5d8a4f8f Richard Henderson
                             int label_index, int small)
778 1d2699ae Richard Henderson
{
779 5d8a4f8f Richard Henderson
    tcg_out_cmp(s, arg1, arg2, const_arg2, 0);
780 f75b56c1 Richard Henderson
    tcg_out_jxx(s, tcg_cond_to_jcc[cond], label_index, small);
781 c896fe29 bellard
}
782 c896fe29 bellard
783 5d8a4f8f Richard Henderson
#if TCG_TARGET_REG_BITS == 64
784 5d8a4f8f Richard Henderson
static void tcg_out_brcond64(TCGContext *s, TCGCond cond,
785 5d8a4f8f Richard Henderson
                             TCGArg arg1, TCGArg arg2, int const_arg2,
786 5d8a4f8f Richard Henderson
                             int label_index, int small)
787 5d8a4f8f Richard Henderson
{
788 5d8a4f8f Richard Henderson
    tcg_out_cmp(s, arg1, arg2, const_arg2, P_REXW);
789 5d8a4f8f Richard Henderson
    tcg_out_jxx(s, tcg_cond_to_jcc[cond], label_index, small);
790 5d8a4f8f Richard Henderson
}
791 5d8a4f8f Richard Henderson
#else
792 c896fe29 bellard
/* XXX: we implement it at the target level to avoid having to
793 c896fe29 bellard
   handle cross basic blocks temporaries */
794 f75b56c1 Richard Henderson
static void tcg_out_brcond2(TCGContext *s, const TCGArg *args,
795 f75b56c1 Richard Henderson
                            const int *const_args, int small)
796 c896fe29 bellard
{
797 c896fe29 bellard
    int label_next;
798 c896fe29 bellard
    label_next = gen_new_label();
799 c896fe29 bellard
    switch(args[4]) {
800 c896fe29 bellard
    case TCG_COND_EQ:
801 5d8a4f8f Richard Henderson
        tcg_out_brcond32(s, TCG_COND_NE, args[0], args[2], const_args[2],
802 5d8a4f8f Richard Henderson
                         label_next, 1);
803 5d8a4f8f Richard Henderson
        tcg_out_brcond32(s, TCG_COND_EQ, args[1], args[3], const_args[3],
804 5d8a4f8f Richard Henderson
                         args[5], small);
805 c896fe29 bellard
        break;
806 c896fe29 bellard
    case TCG_COND_NE:
807 5d8a4f8f Richard Henderson
        tcg_out_brcond32(s, TCG_COND_NE, args[0], args[2], const_args[2],
808 5d8a4f8f Richard Henderson
                         args[5], small);
809 5d8a4f8f Richard Henderson
        tcg_out_brcond32(s, TCG_COND_NE, args[1], args[3], const_args[3],
810 5d8a4f8f Richard Henderson
                         args[5], small);
811 c896fe29 bellard
        break;
812 c896fe29 bellard
    case TCG_COND_LT:
813 5d8a4f8f Richard Henderson
        tcg_out_brcond32(s, TCG_COND_LT, args[1], args[3], const_args[3],
814 5d8a4f8f Richard Henderson
                         args[5], small);
815 f75b56c1 Richard Henderson
        tcg_out_jxx(s, JCC_JNE, label_next, 1);
816 5d8a4f8f Richard Henderson
        tcg_out_brcond32(s, TCG_COND_LTU, args[0], args[2], const_args[2],
817 5d8a4f8f Richard Henderson
                         args[5], small);
818 c896fe29 bellard
        break;
819 c896fe29 bellard
    case TCG_COND_LE:
820 5d8a4f8f Richard Henderson
        tcg_out_brcond32(s, TCG_COND_LT, args[1], args[3], const_args[3],
821 5d8a4f8f Richard Henderson
                         args[5], small);
822 f75b56c1 Richard Henderson
        tcg_out_jxx(s, JCC_JNE, label_next, 1);
823 5d8a4f8f Richard Henderson
        tcg_out_brcond32(s, TCG_COND_LEU, args[0], args[2], const_args[2],
824 5d8a4f8f Richard Henderson
                         args[5], small);
825 c896fe29 bellard
        break;
826 c896fe29 bellard
    case TCG_COND_GT:
827 5d8a4f8f Richard Henderson
        tcg_out_brcond32(s, TCG_COND_GT, args[1], args[3], const_args[3],
828 5d8a4f8f Richard Henderson
                         args[5], small);
829 f75b56c1 Richard Henderson
        tcg_out_jxx(s, JCC_JNE, label_next, 1);
830 5d8a4f8f Richard Henderson
        tcg_out_brcond32(s, TCG_COND_GTU, args[0], args[2], const_args[2],
831 5d8a4f8f Richard Henderson
                         args[5], small);
832 c896fe29 bellard
        break;
833 c896fe29 bellard
    case TCG_COND_GE:
834 5d8a4f8f Richard Henderson
        tcg_out_brcond32(s, TCG_COND_GT, args[1], args[3], const_args[3],
835 5d8a4f8f Richard Henderson
                         args[5], small);
836 f75b56c1 Richard Henderson
        tcg_out_jxx(s, JCC_JNE, label_next, 1);
837 5d8a4f8f Richard Henderson
        tcg_out_brcond32(s, TCG_COND_GEU, args[0], args[2], const_args[2],
838 5d8a4f8f Richard Henderson
                         args[5], small);
839 c896fe29 bellard
        break;
840 c896fe29 bellard
    case TCG_COND_LTU:
841 5d8a4f8f Richard Henderson
        tcg_out_brcond32(s, TCG_COND_LTU, args[1], args[3], const_args[3],
842 5d8a4f8f Richard Henderson
                         args[5], small);
843 f75b56c1 Richard Henderson
        tcg_out_jxx(s, JCC_JNE, label_next, 1);
844 5d8a4f8f Richard Henderson
        tcg_out_brcond32(s, TCG_COND_LTU, args[0], args[2], const_args[2],
845 5d8a4f8f Richard Henderson
                         args[5], small);
846 c896fe29 bellard
        break;
847 c896fe29 bellard
    case TCG_COND_LEU:
848 5d8a4f8f Richard Henderson
        tcg_out_brcond32(s, TCG_COND_LTU, args[1], args[3], const_args[3],
849 5d8a4f8f Richard Henderson
                         args[5], small);
850 f75b56c1 Richard Henderson
        tcg_out_jxx(s, JCC_JNE, label_next, 1);
851 5d8a4f8f Richard Henderson
        tcg_out_brcond32(s, TCG_COND_LEU, args[0], args[2], const_args[2],
852 5d8a4f8f Richard Henderson
                         args[5], small);
853 c896fe29 bellard
        break;
854 c896fe29 bellard
    case TCG_COND_GTU:
855 5d8a4f8f Richard Henderson
        tcg_out_brcond32(s, TCG_COND_GTU, args[1], args[3], const_args[3],
856 5d8a4f8f Richard Henderson
                         args[5], small);
857 f75b56c1 Richard Henderson
        tcg_out_jxx(s, JCC_JNE, label_next, 1);
858 5d8a4f8f Richard Henderson
        tcg_out_brcond32(s, TCG_COND_GTU, args[0], args[2], const_args[2],
859 5d8a4f8f Richard Henderson
                         args[5], small);
860 c896fe29 bellard
        break;
861 c896fe29 bellard
    case TCG_COND_GEU:
862 5d8a4f8f Richard Henderson
        tcg_out_brcond32(s, TCG_COND_GTU, args[1], args[3], const_args[3],
863 5d8a4f8f Richard Henderson
                         args[5], small);
864 f75b56c1 Richard Henderson
        tcg_out_jxx(s, JCC_JNE, label_next, 1);
865 5d8a4f8f Richard Henderson
        tcg_out_brcond32(s, TCG_COND_GEU, args[0], args[2], const_args[2],
866 5d8a4f8f Richard Henderson
                         args[5], small);
867 c896fe29 bellard
        break;
868 c896fe29 bellard
    default:
869 c896fe29 bellard
        tcg_abort();
870 c896fe29 bellard
    }
871 c896fe29 bellard
    tcg_out_label(s, label_next, (tcg_target_long)s->code_ptr);
872 c896fe29 bellard
}
873 5d8a4f8f Richard Henderson
#endif
874 c896fe29 bellard
875 5d8a4f8f Richard Henderson
static void tcg_out_setcond32(TCGContext *s, TCGCond cond, TCGArg dest,
876 5d8a4f8f Richard Henderson
                              TCGArg arg1, TCGArg arg2, int const_arg2)
877 1d2699ae Richard Henderson
{
878 5d8a4f8f Richard Henderson
    tcg_out_cmp(s, arg1, arg2, const_arg2, 0);
879 32a8ffb9 Richard Henderson
    tcg_out_modrm(s, OPC_SETCC | tcg_cond_to_jcc[cond], 0, dest);
880 a369a702 Richard Henderson
    tcg_out_ext8u(s, dest, dest);
881 1d2699ae Richard Henderson
}
882 1d2699ae Richard Henderson
883 5d8a4f8f Richard Henderson
#if TCG_TARGET_REG_BITS == 64
884 5d8a4f8f Richard Henderson
static void tcg_out_setcond64(TCGContext *s, TCGCond cond, TCGArg dest,
885 5d8a4f8f Richard Henderson
                              TCGArg arg1, TCGArg arg2, int const_arg2)
886 5d8a4f8f Richard Henderson
{
887 5d8a4f8f Richard Henderson
    tcg_out_cmp(s, arg1, arg2, const_arg2, P_REXW);
888 5d8a4f8f Richard Henderson
    tcg_out_modrm(s, OPC_SETCC | tcg_cond_to_jcc[cond], 0, dest);
889 5d8a4f8f Richard Henderson
    tcg_out_ext8u(s, dest, dest);
890 5d8a4f8f Richard Henderson
}
891 5d8a4f8f Richard Henderson
#else
892 1d2699ae Richard Henderson
static void tcg_out_setcond2(TCGContext *s, const TCGArg *args,
893 1d2699ae Richard Henderson
                             const int *const_args)
894 1d2699ae Richard Henderson
{
895 1d2699ae Richard Henderson
    TCGArg new_args[6];
896 1d2699ae Richard Henderson
    int label_true, label_over;
897 1d2699ae Richard Henderson
898 1d2699ae Richard Henderson
    memcpy(new_args, args+1, 5*sizeof(TCGArg));
899 1d2699ae Richard Henderson
900 1d2699ae Richard Henderson
    if (args[0] == args[1] || args[0] == args[2]
901 1d2699ae Richard Henderson
        || (!const_args[3] && args[0] == args[3])
902 1d2699ae Richard Henderson
        || (!const_args[4] && args[0] == args[4])) {
903 1d2699ae Richard Henderson
        /* When the destination overlaps with one of the argument
904 1d2699ae Richard Henderson
           registers, don't do anything tricky.  */
905 1d2699ae Richard Henderson
        label_true = gen_new_label();
906 1d2699ae Richard Henderson
        label_over = gen_new_label();
907 1d2699ae Richard Henderson
908 1d2699ae Richard Henderson
        new_args[5] = label_true;
909 1d2699ae Richard Henderson
        tcg_out_brcond2(s, new_args, const_args+1, 1);
910 1d2699ae Richard Henderson
911 1d2699ae Richard Henderson
        tcg_out_movi(s, TCG_TYPE_I32, args[0], 0);
912 1d2699ae Richard Henderson
        tcg_out_jxx(s, JCC_JMP, label_over, 1);
913 1d2699ae Richard Henderson
        tcg_out_label(s, label_true, (tcg_target_long)s->code_ptr);
914 1d2699ae Richard Henderson
915 1d2699ae Richard Henderson
        tcg_out_movi(s, TCG_TYPE_I32, args[0], 1);
916 1d2699ae Richard Henderson
        tcg_out_label(s, label_over, (tcg_target_long)s->code_ptr);
917 1d2699ae Richard Henderson
    } else {
918 1d2699ae Richard Henderson
        /* When the destination does not overlap one of the arguments,
919 1d2699ae Richard Henderson
           clear the destination first, jump if cond false, and emit an
920 1d2699ae Richard Henderson
           increment in the true case.  This results in smaller code.  */
921 1d2699ae Richard Henderson
922 1d2699ae Richard Henderson
        tcg_out_movi(s, TCG_TYPE_I32, args[0], 0);
923 1d2699ae Richard Henderson
924 1d2699ae Richard Henderson
        label_over = gen_new_label();
925 1d2699ae Richard Henderson
        new_args[4] = tcg_invert_cond(new_args[4]);
926 1d2699ae Richard Henderson
        new_args[5] = label_over;
927 1d2699ae Richard Henderson
        tcg_out_brcond2(s, new_args, const_args+1, 1);
928 1d2699ae Richard Henderson
929 1d2699ae Richard Henderson
        tgen_arithi(s, ARITH_ADD, args[0], 1, 0);
930 1d2699ae Richard Henderson
        tcg_out_label(s, label_over, (tcg_target_long)s->code_ptr);
931 1d2699ae Richard Henderson
    }
932 1d2699ae Richard Henderson
}
933 5d8a4f8f Richard Henderson
#endif
934 5d8a4f8f Richard Henderson
935 5d8a4f8f Richard Henderson
static void tcg_out_branch(TCGContext *s, int call, tcg_target_long dest)
936 5d8a4f8f Richard Henderson
{
937 5d8a4f8f Richard Henderson
    tcg_target_long disp = dest - (tcg_target_long)s->code_ptr - 5;
938 5d8a4f8f Richard Henderson
939 5d8a4f8f Richard Henderson
    if (disp == (int32_t)disp) {
940 5d8a4f8f Richard Henderson
        tcg_out_opc(s, call ? OPC_CALL_Jz : OPC_JMP_long, 0, 0, 0);
941 5d8a4f8f Richard Henderson
        tcg_out32(s, disp);
942 5d8a4f8f Richard Henderson
    } else {
943 5d8a4f8f Richard Henderson
        tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R10, dest);
944 5d8a4f8f Richard Henderson
        tcg_out_modrm(s, OPC_GRP5,
945 5d8a4f8f Richard Henderson
                      call ? EXT5_CALLN_Ev : EXT5_JMPN_Ev, TCG_REG_R10);
946 5d8a4f8f Richard Henderson
    }
947 5d8a4f8f Richard Henderson
}
948 5d8a4f8f Richard Henderson
949 5d8a4f8f Richard Henderson
static inline void tcg_out_calli(TCGContext *s, tcg_target_long dest)
950 5d8a4f8f Richard Henderson
{
951 5d8a4f8f Richard Henderson
    tcg_out_branch(s, 1, dest);
952 5d8a4f8f Richard Henderson
}
953 1d2699ae Richard Henderson
954 5d8a4f8f Richard Henderson
static void tcg_out_jmp(TCGContext *s, tcg_target_long dest)
955 aadb21a4 Richard Henderson
{
956 5d8a4f8f Richard Henderson
    tcg_out_branch(s, 0, dest);
957 aadb21a4 Richard Henderson
}
958 aadb21a4 Richard Henderson
959 c896fe29 bellard
#if defined(CONFIG_SOFTMMU)
960 79383c9c blueswir1
961 79383c9c blueswir1
#include "../../softmmu_defs.h"
962 c896fe29 bellard
963 c896fe29 bellard
static void *qemu_ld_helpers[4] = {
964 c896fe29 bellard
    __ldb_mmu,
965 c896fe29 bellard
    __ldw_mmu,
966 c896fe29 bellard
    __ldl_mmu,
967 c896fe29 bellard
    __ldq_mmu,
968 c896fe29 bellard
};
969 c896fe29 bellard
970 c896fe29 bellard
static void *qemu_st_helpers[4] = {
971 c896fe29 bellard
    __stb_mmu,
972 c896fe29 bellard
    __stw_mmu,
973 c896fe29 bellard
    __stl_mmu,
974 c896fe29 bellard
    __stq_mmu,
975 c896fe29 bellard
};
976 8516a044 Richard Henderson
977 8516a044 Richard Henderson
/* Perform the TLB load and compare.
978 8516a044 Richard Henderson

979 8516a044 Richard Henderson
   Inputs:
980 8516a044 Richard Henderson
   ADDRLO_IDX contains the index into ARGS of the low part of the
981 8516a044 Richard Henderson
   address; the high part of the address is at ADDR_LOW_IDX+1.
982 8516a044 Richard Henderson

983 8516a044 Richard Henderson
   MEM_INDEX and S_BITS are the memory context and log2 size of the load.
984 8516a044 Richard Henderson

985 8516a044 Richard Henderson
   WHICH is the offset into the CPUTLBEntry structure of the slot to read.
986 8516a044 Richard Henderson
   This should be offsetof addr_read or addr_write.
987 8516a044 Richard Henderson

988 8516a044 Richard Henderson
   Outputs:
989 8516a044 Richard Henderson
   LABEL_PTRS is filled with 1 (32-bit addresses) or 2 (64-bit addresses)
990 8516a044 Richard Henderson
   positions of the displacements of forward jumps to the TLB miss case.
991 8516a044 Richard Henderson

992 5d8a4f8f Richard Henderson
   First argument register is loaded with the low part of the address.
993 5d8a4f8f Richard Henderson
   In the TLB hit case, it has been adjusted as indicated by the TLB
994 5d8a4f8f Richard Henderson
   and so is a host address.  In the TLB miss case, it continues to
995 5d8a4f8f Richard Henderson
   hold a guest address.
996 8516a044 Richard Henderson

997 5d8a4f8f Richard Henderson
   Second argument register is clobbered.  */
998 8516a044 Richard Henderson
999 c28b14c6 Aurelien Jarno
static inline void tcg_out_tlb_load(TCGContext *s, int addrlo_idx,
1000 c28b14c6 Aurelien Jarno
                                    int mem_index, int s_bits,
1001 4309a79b Aurelien Jarno
                                    const TCGArg *args,
1002 c28b14c6 Aurelien Jarno
                                    uint8_t **label_ptr, int which)
1003 8516a044 Richard Henderson
{
1004 8516a044 Richard Henderson
    const int addrlo = args[addrlo_idx];
1005 5d8a4f8f Richard Henderson
    const int r0 = tcg_target_call_iarg_regs[0];
1006 5d8a4f8f Richard Henderson
    const int r1 = tcg_target_call_iarg_regs[1];
1007 5d8a4f8f Richard Henderson
    TCGType type = TCG_TYPE_I32;
1008 5d8a4f8f Richard Henderson
    int rexw = 0;
1009 5d8a4f8f Richard Henderson
1010 5d8a4f8f Richard Henderson
    if (TCG_TARGET_REG_BITS == 64 && TARGET_LONG_BITS == 64) {
1011 5d8a4f8f Richard Henderson
        type = TCG_TYPE_I64;
1012 5d8a4f8f Richard Henderson
        rexw = P_REXW;
1013 5d8a4f8f Richard Henderson
    }
1014 8516a044 Richard Henderson
1015 5d8a4f8f Richard Henderson
    tcg_out_mov(s, type, r1, addrlo);
1016 5d8a4f8f Richard Henderson
    tcg_out_mov(s, type, r0, addrlo);
1017 8516a044 Richard Henderson
1018 5d8a4f8f Richard Henderson
    tcg_out_shifti(s, SHIFT_SHR + rexw, r1,
1019 5d8a4f8f Richard Henderson
                   TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
1020 8516a044 Richard Henderson
1021 5d8a4f8f Richard Henderson
    tgen_arithi(s, ARITH_AND + rexw, r0,
1022 5d8a4f8f Richard Henderson
                TARGET_PAGE_MASK | ((1 << s_bits) - 1), 0);
1023 5d8a4f8f Richard Henderson
    tgen_arithi(s, ARITH_AND + rexw, r1,
1024 5d8a4f8f Richard Henderson
                (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS, 0);
1025 8516a044 Richard Henderson
1026 5d8a4f8f Richard Henderson
    tcg_out_modrm_sib_offset(s, OPC_LEA + P_REXW, r1, TCG_AREG0, r1, 0,
1027 8516a044 Richard Henderson
                             offsetof(CPUState, tlb_table[mem_index][0])
1028 8516a044 Richard Henderson
                             + which);
1029 8516a044 Richard Henderson
1030 8516a044 Richard Henderson
    /* cmp 0(r1), r0 */
1031 5d8a4f8f Richard Henderson
    tcg_out_modrm_offset(s, OPC_CMP_GvEv + rexw, r0, r1, 0);
1032 8516a044 Richard Henderson
1033 5d8a4f8f Richard Henderson
    tcg_out_mov(s, type, r0, addrlo);
1034 8516a044 Richard Henderson
1035 8516a044 Richard Henderson
    /* jne label1 */
1036 8516a044 Richard Henderson
    tcg_out8(s, OPC_JCC_short + JCC_JNE);
1037 8516a044 Richard Henderson
    label_ptr[0] = s->code_ptr;
1038 8516a044 Richard Henderson
    s->code_ptr++;
1039 8516a044 Richard Henderson
1040 5d8a4f8f Richard Henderson
    if (TARGET_LONG_BITS > TCG_TARGET_REG_BITS) {
1041 8516a044 Richard Henderson
        /* cmp 4(r1), addrhi */
1042 8516a044 Richard Henderson
        tcg_out_modrm_offset(s, OPC_CMP_GvEv, args[addrlo_idx+1], r1, 4);
1043 8516a044 Richard Henderson
1044 8516a044 Richard Henderson
        /* jne label1 */
1045 8516a044 Richard Henderson
        tcg_out8(s, OPC_JCC_short + JCC_JNE);
1046 8516a044 Richard Henderson
        label_ptr[1] = s->code_ptr;
1047 8516a044 Richard Henderson
        s->code_ptr++;
1048 8516a044 Richard Henderson
    }
1049 8516a044 Richard Henderson
1050 8516a044 Richard Henderson
    /* TLB Hit.  */
1051 8516a044 Richard Henderson
1052 8516a044 Richard Henderson
    /* add addend(r1), r0 */
1053 5d8a4f8f Richard Henderson
    tcg_out_modrm_offset(s, OPC_ADD_GvEv + P_REXW, r0, r1,
1054 8516a044 Richard Henderson
                         offsetof(CPUTLBEntry, addend) - which);
1055 8516a044 Richard Henderson
}
1056 c896fe29 bellard
#endif
1057 c896fe29 bellard
1058 be5a4eb7 Richard Henderson
static void tcg_out_qemu_ld_direct(TCGContext *s, int datalo, int datahi,
1059 be5a4eb7 Richard Henderson
                                   int base, tcg_target_long ofs, int sizeop)
1060 be5a4eb7 Richard Henderson
{
1061 be5a4eb7 Richard Henderson
#ifdef TARGET_WORDS_BIGENDIAN
1062 be5a4eb7 Richard Henderson
    const int bswap = 1;
1063 be5a4eb7 Richard Henderson
#else
1064 be5a4eb7 Richard Henderson
    const int bswap = 0;
1065 379f6698 Paul Brook
#endif
1066 be5a4eb7 Richard Henderson
    switch (sizeop) {
1067 be5a4eb7 Richard Henderson
    case 0:
1068 be5a4eb7 Richard Henderson
        tcg_out_modrm_offset(s, OPC_MOVZBL, datalo, base, ofs);
1069 be5a4eb7 Richard Henderson
        break;
1070 be5a4eb7 Richard Henderson
    case 0 | 4:
1071 5d8a4f8f Richard Henderson
        tcg_out_modrm_offset(s, OPC_MOVSBL + P_REXW, datalo, base, ofs);
1072 be5a4eb7 Richard Henderson
        break;
1073 be5a4eb7 Richard Henderson
    case 1:
1074 be5a4eb7 Richard Henderson
        tcg_out_modrm_offset(s, OPC_MOVZWL, datalo, base, ofs);
1075 be5a4eb7 Richard Henderson
        if (bswap) {
1076 be5a4eb7 Richard Henderson
            tcg_out_rolw_8(s, datalo);
1077 be5a4eb7 Richard Henderson
        }
1078 be5a4eb7 Richard Henderson
        break;
1079 be5a4eb7 Richard Henderson
    case 1 | 4:
1080 be5a4eb7 Richard Henderson
        if (bswap) {
1081 5d8a4f8f Richard Henderson
            tcg_out_modrm_offset(s, OPC_MOVZWL, datalo, base, ofs);
1082 be5a4eb7 Richard Henderson
            tcg_out_rolw_8(s, datalo);
1083 5d8a4f8f Richard Henderson
            tcg_out_modrm(s, OPC_MOVSWL + P_REXW, datalo, datalo);
1084 5d8a4f8f Richard Henderson
        } else {
1085 5d8a4f8f Richard Henderson
            tcg_out_modrm_offset(s, OPC_MOVSWL + P_REXW, datalo, base, ofs);
1086 be5a4eb7 Richard Henderson
        }
1087 be5a4eb7 Richard Henderson
        break;
1088 be5a4eb7 Richard Henderson
    case 2:
1089 be5a4eb7 Richard Henderson
        tcg_out_ld(s, TCG_TYPE_I32, datalo, base, ofs);
1090 be5a4eb7 Richard Henderson
        if (bswap) {
1091 be5a4eb7 Richard Henderson
            tcg_out_bswap32(s, datalo);
1092 be5a4eb7 Richard Henderson
        }
1093 be5a4eb7 Richard Henderson
        break;
1094 5d8a4f8f Richard Henderson
#if TCG_TARGET_REG_BITS == 64
1095 5d8a4f8f Richard Henderson
    case 2 | 4:
1096 be5a4eb7 Richard Henderson
        if (bswap) {
1097 be5a4eb7 Richard Henderson
            tcg_out_ld(s, TCG_TYPE_I32, datalo, base, ofs);
1098 5d8a4f8f Richard Henderson
            tcg_out_bswap32(s, datalo);
1099 5d8a4f8f Richard Henderson
            tcg_out_ext32s(s, datalo, datalo);
1100 be5a4eb7 Richard Henderson
        } else {
1101 5d8a4f8f Richard Henderson
            tcg_out_modrm_offset(s, OPC_MOVSLQ, datalo, base, ofs);
1102 be5a4eb7 Richard Henderson
        }
1103 5d8a4f8f Richard Henderson
        break;
1104 5d8a4f8f Richard Henderson
#endif
1105 5d8a4f8f Richard Henderson
    case 3:
1106 5d8a4f8f Richard Henderson
        if (TCG_TARGET_REG_BITS == 64) {
1107 5d8a4f8f Richard Henderson
            tcg_out_ld(s, TCG_TYPE_I64, datalo, base, ofs);
1108 5d8a4f8f Richard Henderson
            if (bswap) {
1109 5d8a4f8f Richard Henderson
                tcg_out_bswap64(s, datalo);
1110 5d8a4f8f Richard Henderson
            }
1111 5d8a4f8f Richard Henderson
        } else {
1112 5d8a4f8f Richard Henderson
            if (bswap) {
1113 5d8a4f8f Richard Henderson
                int t = datalo;
1114 5d8a4f8f Richard Henderson
                datalo = datahi;
1115 5d8a4f8f Richard Henderson
                datahi = t;
1116 5d8a4f8f Richard Henderson
            }
1117 5d8a4f8f Richard Henderson
            if (base != datalo) {
1118 5d8a4f8f Richard Henderson
                tcg_out_ld(s, TCG_TYPE_I32, datalo, base, ofs);
1119 5d8a4f8f Richard Henderson
                tcg_out_ld(s, TCG_TYPE_I32, datahi, base, ofs + 4);
1120 5d8a4f8f Richard Henderson
            } else {
1121 5d8a4f8f Richard Henderson
                tcg_out_ld(s, TCG_TYPE_I32, datahi, base, ofs + 4);
1122 5d8a4f8f Richard Henderson
                tcg_out_ld(s, TCG_TYPE_I32, datalo, base, ofs);
1123 5d8a4f8f Richard Henderson
            }
1124 5d8a4f8f Richard Henderson
            if (bswap) {
1125 5d8a4f8f Richard Henderson
                tcg_out_bswap32(s, datalo);
1126 5d8a4f8f Richard Henderson
                tcg_out_bswap32(s, datahi);
1127 5d8a4f8f Richard Henderson
            }
1128 be5a4eb7 Richard Henderson
        }
1129 be5a4eb7 Richard Henderson
        break;
1130 be5a4eb7 Richard Henderson
    default:
1131 be5a4eb7 Richard Henderson
        tcg_abort();
1132 be5a4eb7 Richard Henderson
    }
1133 be5a4eb7 Richard Henderson
}
1134 379f6698 Paul Brook
1135 c896fe29 bellard
/* XXX: qemu_ld and qemu_st could be modified to clobber only EDX and
1136 c896fe29 bellard
   EAX. It will be useful once fixed registers globals are less
1137 c896fe29 bellard
   common. */
1138 c896fe29 bellard
static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
1139 c896fe29 bellard
                            int opc)
1140 c896fe29 bellard
{
1141 1a6dc1e4 Richard Henderson
    int data_reg, data_reg2 = 0;
1142 8516a044 Richard Henderson
    int addrlo_idx;
1143 c896fe29 bellard
#if defined(CONFIG_SOFTMMU)
1144 82bb07db Richard Henderson
    int mem_index, s_bits, arg_idx;
1145 1a6dc1e4 Richard Henderson
    uint8_t *label_ptr[3];
1146 c896fe29 bellard
#endif
1147 c896fe29 bellard
1148 8516a044 Richard Henderson
    data_reg = args[0];
1149 8516a044 Richard Henderson
    addrlo_idx = 1;
1150 5d8a4f8f Richard Henderson
    if (TCG_TARGET_REG_BITS == 32 && opc == 3) {
1151 8516a044 Richard Henderson
        data_reg2 = args[1];
1152 8516a044 Richard Henderson
        addrlo_idx = 2;
1153 1a6dc1e4 Richard Henderson
    }
1154 c896fe29 bellard
1155 c896fe29 bellard
#if defined(CONFIG_SOFTMMU)
1156 5d8a4f8f Richard Henderson
    mem_index = args[addrlo_idx + 1 + (TARGET_LONG_BITS > TCG_TARGET_REG_BITS)];
1157 8516a044 Richard Henderson
    s_bits = opc & 3;
1158 1a6dc1e4 Richard Henderson
1159 8516a044 Richard Henderson
    tcg_out_tlb_load(s, addrlo_idx, mem_index, s_bits, args,
1160 8516a044 Richard Henderson
                     label_ptr, offsetof(CPUTLBEntry, addr_read));
1161 1a6dc1e4 Richard Henderson
1162 1a6dc1e4 Richard Henderson
    /* TLB Hit.  */
1163 5d8a4f8f Richard Henderson
    tcg_out_qemu_ld_direct(s, data_reg, data_reg2,
1164 5d8a4f8f Richard Henderson
                           tcg_target_call_iarg_regs[0], 0, opc);
1165 c896fe29 bellard
1166 1a6dc1e4 Richard Henderson
    /* jmp label2 */
1167 1a6dc1e4 Richard Henderson
    tcg_out8(s, OPC_JMP_short);
1168 1a6dc1e4 Richard Henderson
    label_ptr[2] = s->code_ptr;
1169 c896fe29 bellard
    s->code_ptr++;
1170 78686523 Richard Henderson
1171 1a6dc1e4 Richard Henderson
    /* TLB Miss.  */
1172 1a6dc1e4 Richard Henderson
1173 1a6dc1e4 Richard Henderson
    /* label1: */
1174 1a6dc1e4 Richard Henderson
    *label_ptr[0] = s->code_ptr - label_ptr[0] - 1;
1175 5d8a4f8f Richard Henderson
    if (TARGET_LONG_BITS > TCG_TARGET_REG_BITS) {
1176 1a6dc1e4 Richard Henderson
        *label_ptr[1] = s->code_ptr - label_ptr[1] - 1;
1177 1a6dc1e4 Richard Henderson
    }
1178 c896fe29 bellard
1179 c896fe29 bellard
    /* XXX: move that code at the end of the TB */
1180 5d8a4f8f Richard Henderson
    /* The first argument is already loaded with addrlo.  */
1181 82bb07db Richard Henderson
    arg_idx = 1;
1182 5d8a4f8f Richard Henderson
    if (TCG_TARGET_REG_BITS == 32 && TARGET_LONG_BITS == 64) {
1183 3b6dac34 Richard Henderson
        tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[arg_idx++],
1184 82bb07db Richard Henderson
                    args[addrlo_idx + 1]);
1185 82bb07db Richard Henderson
    }
1186 82bb07db Richard Henderson
    tcg_out_movi(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[arg_idx],
1187 82bb07db Richard Henderson
                 mem_index);
1188 aadb21a4 Richard Henderson
    tcg_out_calli(s, (tcg_target_long)qemu_ld_helpers[s_bits]);
1189 c896fe29 bellard
1190 c896fe29 bellard
    switch(opc) {
1191 c896fe29 bellard
    case 0 | 4:
1192 5d8a4f8f Richard Henderson
        tcg_out_ext8s(s, data_reg, TCG_REG_EAX, P_REXW);
1193 c896fe29 bellard
        break;
1194 c896fe29 bellard
    case 1 | 4:
1195 5d8a4f8f Richard Henderson
        tcg_out_ext16s(s, data_reg, TCG_REG_EAX, P_REXW);
1196 c896fe29 bellard
        break;
1197 c896fe29 bellard
    case 0:
1198 55e082a7 Richard Henderson
        tcg_out_ext8u(s, data_reg, TCG_REG_EAX);
1199 9db3ba4d aurel32
        break;
1200 c896fe29 bellard
    case 1:
1201 55e082a7 Richard Henderson
        tcg_out_ext16u(s, data_reg, TCG_REG_EAX);
1202 9db3ba4d aurel32
        break;
1203 c896fe29 bellard
    case 2:
1204 3b6dac34 Richard Henderson
        tcg_out_mov(s, TCG_TYPE_I32, data_reg, TCG_REG_EAX);
1205 c896fe29 bellard
        break;
1206 5d8a4f8f Richard Henderson
#if TCG_TARGET_REG_BITS == 64
1207 5d8a4f8f Richard Henderson
    case 2 | 4:
1208 5d8a4f8f Richard Henderson
        tcg_out_ext32s(s, data_reg, TCG_REG_EAX);
1209 5d8a4f8f Richard Henderson
        break;
1210 5d8a4f8f Richard Henderson
#endif
1211 c896fe29 bellard
    case 3:
1212 5d8a4f8f Richard Henderson
        if (TCG_TARGET_REG_BITS == 64) {
1213 5d8a4f8f Richard Henderson
            tcg_out_mov(s, TCG_TYPE_I64, data_reg, TCG_REG_RAX);
1214 5d8a4f8f Richard Henderson
        } else if (data_reg == TCG_REG_EDX) {
1215 b3e66df7 Richard Henderson
            /* xchg %edx, %eax */
1216 5d8a4f8f Richard Henderson
            tcg_out_opc(s, OPC_XCHG_ax_r32 + TCG_REG_EDX, 0, 0, 0);
1217 3b6dac34 Richard Henderson
            tcg_out_mov(s, TCG_TYPE_I32, data_reg2, TCG_REG_EAX);
1218 c896fe29 bellard
        } else {
1219 3b6dac34 Richard Henderson
            tcg_out_mov(s, TCG_TYPE_I32, data_reg, TCG_REG_EAX);
1220 3b6dac34 Richard Henderson
            tcg_out_mov(s, TCG_TYPE_I32, data_reg2, TCG_REG_EDX);
1221 c896fe29 bellard
        }
1222 c896fe29 bellard
        break;
1223 5d8a4f8f Richard Henderson
    default:
1224 5d8a4f8f Richard Henderson
        tcg_abort();
1225 c896fe29 bellard
    }
1226 c896fe29 bellard
1227 be5a4eb7 Richard Henderson
    /* label2: */
1228 1a6dc1e4 Richard Henderson
    *label_ptr[2] = s->code_ptr - label_ptr[2] - 1;
1229 c896fe29 bellard
#else
1230 5d8a4f8f Richard Henderson
    {
1231 5d8a4f8f Richard Henderson
        int32_t offset = GUEST_BASE;
1232 5d8a4f8f Richard Henderson
        int base = args[addrlo_idx];
1233 5d8a4f8f Richard Henderson
1234 5d8a4f8f Richard Henderson
        if (TCG_TARGET_REG_BITS == 64) {
1235 5d8a4f8f Richard Henderson
            /* ??? We assume all operations have left us with register
1236 5d8a4f8f Richard Henderson
               contents that are zero extended.  So far this appears to
1237 5d8a4f8f Richard Henderson
               be true.  If we want to enforce this, we can either do
1238 5d8a4f8f Richard Henderson
               an explicit zero-extension here, or (if GUEST_BASE == 0)
1239 5d8a4f8f Richard Henderson
               use the ADDR32 prefix.  For now, do nothing.  */
1240 5d8a4f8f Richard Henderson
1241 5d8a4f8f Richard Henderson
            if (offset != GUEST_BASE) {
1242 5d8a4f8f Richard Henderson
                tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_RDI, GUEST_BASE);
1243 5d8a4f8f Richard Henderson
                tgen_arithr(s, ARITH_ADD + P_REXW, TCG_REG_RDI, base);
1244 5d8a4f8f Richard Henderson
                base = TCG_REG_RDI, offset = 0;
1245 5d8a4f8f Richard Henderson
            }
1246 5d8a4f8f Richard Henderson
        }
1247 5d8a4f8f Richard Henderson
1248 5d8a4f8f Richard Henderson
        tcg_out_qemu_ld_direct(s, data_reg, data_reg2, base, offset, opc);
1249 5d8a4f8f Richard Henderson
    }
1250 c896fe29 bellard
#endif
1251 be5a4eb7 Richard Henderson
}
1252 c896fe29 bellard
1253 be5a4eb7 Richard Henderson
static void tcg_out_qemu_st_direct(TCGContext *s, int datalo, int datahi,
1254 be5a4eb7 Richard Henderson
                                   int base, tcg_target_long ofs, int sizeop)
1255 be5a4eb7 Richard Henderson
{
1256 c896fe29 bellard
#ifdef TARGET_WORDS_BIGENDIAN
1257 be5a4eb7 Richard Henderson
    const int bswap = 1;
1258 c896fe29 bellard
#else
1259 be5a4eb7 Richard Henderson
    const int bswap = 0;
1260 c896fe29 bellard
#endif
1261 be5a4eb7 Richard Henderson
    /* ??? Ideally we wouldn't need a scratch register.  For user-only,
1262 be5a4eb7 Richard Henderson
       we could perform the bswap twice to restore the original value
1263 be5a4eb7 Richard Henderson
       instead of moving to the scratch.  But as it is, the L constraint
1264 5d8a4f8f Richard Henderson
       means that the second argument reg is definitely free here.  */
1265 5d8a4f8f Richard Henderson
    int scratch = tcg_target_call_iarg_regs[1];
1266 be5a4eb7 Richard Henderson
1267 be5a4eb7 Richard Henderson
    switch (sizeop) {
1268 c896fe29 bellard
    case 0:
1269 5d8a4f8f Richard Henderson
        tcg_out_modrm_offset(s, OPC_MOVB_EvGv + P_REXB_R, datalo, base, ofs);
1270 c896fe29 bellard
        break;
1271 c896fe29 bellard
    case 1:
1272 c896fe29 bellard
        if (bswap) {
1273 3b6dac34 Richard Henderson
            tcg_out_mov(s, TCG_TYPE_I32, scratch, datalo);
1274 be5a4eb7 Richard Henderson
            tcg_out_rolw_8(s, scratch);
1275 be5a4eb7 Richard Henderson
            datalo = scratch;
1276 c896fe29 bellard
        }
1277 5d8a4f8f Richard Henderson
        tcg_out_modrm_offset(s, OPC_MOVL_EvGv + P_DATA16, datalo, base, ofs);
1278 c896fe29 bellard
        break;
1279 c896fe29 bellard
    case 2:
1280 c896fe29 bellard
        if (bswap) {
1281 3b6dac34 Richard Henderson
            tcg_out_mov(s, TCG_TYPE_I32, scratch, datalo);
1282 be5a4eb7 Richard Henderson
            tcg_out_bswap32(s, scratch);
1283 be5a4eb7 Richard Henderson
            datalo = scratch;
1284 c896fe29 bellard
        }
1285 be5a4eb7 Richard Henderson
        tcg_out_st(s, TCG_TYPE_I32, datalo, base, ofs);
1286 c896fe29 bellard
        break;
1287 c896fe29 bellard
    case 3:
1288 5d8a4f8f Richard Henderson
        if (TCG_TARGET_REG_BITS == 64) {
1289 5d8a4f8f Richard Henderson
            if (bswap) {
1290 5d8a4f8f Richard Henderson
                tcg_out_mov(s, TCG_TYPE_I64, scratch, datalo);
1291 5d8a4f8f Richard Henderson
                tcg_out_bswap64(s, scratch);
1292 5d8a4f8f Richard Henderson
                datalo = scratch;
1293 5d8a4f8f Richard Henderson
            }
1294 5d8a4f8f Richard Henderson
            tcg_out_st(s, TCG_TYPE_I64, datalo, base, ofs);
1295 5d8a4f8f Richard Henderson
        } else if (bswap) {
1296 3b6dac34 Richard Henderson
            tcg_out_mov(s, TCG_TYPE_I32, scratch, datahi);
1297 be5a4eb7 Richard Henderson
            tcg_out_bswap32(s, scratch);
1298 be5a4eb7 Richard Henderson
            tcg_out_st(s, TCG_TYPE_I32, scratch, base, ofs);
1299 3b6dac34 Richard Henderson
            tcg_out_mov(s, TCG_TYPE_I32, scratch, datalo);
1300 be5a4eb7 Richard Henderson
            tcg_out_bswap32(s, scratch);
1301 be5a4eb7 Richard Henderson
            tcg_out_st(s, TCG_TYPE_I32, scratch, base, ofs + 4);
1302 c896fe29 bellard
        } else {
1303 be5a4eb7 Richard Henderson
            tcg_out_st(s, TCG_TYPE_I32, datalo, base, ofs);
1304 be5a4eb7 Richard Henderson
            tcg_out_st(s, TCG_TYPE_I32, datahi, base, ofs + 4);
1305 c896fe29 bellard
        }
1306 c896fe29 bellard
        break;
1307 c896fe29 bellard
    default:
1308 c896fe29 bellard
        tcg_abort();
1309 c896fe29 bellard
    }
1310 c896fe29 bellard
}
1311 c896fe29 bellard
1312 c896fe29 bellard
static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
1313 c896fe29 bellard
                            int opc)
1314 c896fe29 bellard
{
1315 1a6dc1e4 Richard Henderson
    int data_reg, data_reg2 = 0;
1316 8516a044 Richard Henderson
    int addrlo_idx;
1317 c896fe29 bellard
#if defined(CONFIG_SOFTMMU)
1318 8516a044 Richard Henderson
    int mem_index, s_bits;
1319 aadb21a4 Richard Henderson
    int stack_adjust;
1320 1a6dc1e4 Richard Henderson
    uint8_t *label_ptr[3];
1321 c896fe29 bellard
#endif
1322 c896fe29 bellard
1323 8516a044 Richard Henderson
    data_reg = args[0];
1324 8516a044 Richard Henderson
    addrlo_idx = 1;
1325 5d8a4f8f Richard Henderson
    if (TCG_TARGET_REG_BITS == 32 && opc == 3) {
1326 8516a044 Richard Henderson
        data_reg2 = args[1];
1327 8516a044 Richard Henderson
        addrlo_idx = 2;
1328 1a6dc1e4 Richard Henderson
    }
1329 c896fe29 bellard
1330 c896fe29 bellard
#if defined(CONFIG_SOFTMMU)
1331 5d8a4f8f Richard Henderson
    mem_index = args[addrlo_idx + 1 + (TARGET_LONG_BITS > TCG_TARGET_REG_BITS)];
1332 8516a044 Richard Henderson
    s_bits = opc;
1333 1a6dc1e4 Richard Henderson
1334 8516a044 Richard Henderson
    tcg_out_tlb_load(s, addrlo_idx, mem_index, s_bits, args,
1335 8516a044 Richard Henderson
                     label_ptr, offsetof(CPUTLBEntry, addr_write));
1336 1a6dc1e4 Richard Henderson
1337 1a6dc1e4 Richard Henderson
    /* TLB Hit.  */
1338 5d8a4f8f Richard Henderson
    tcg_out_qemu_st_direct(s, data_reg, data_reg2,
1339 5d8a4f8f Richard Henderson
                           tcg_target_call_iarg_regs[0], 0, opc);
1340 c896fe29 bellard
1341 1a6dc1e4 Richard Henderson
    /* jmp label2 */
1342 1a6dc1e4 Richard Henderson
    tcg_out8(s, OPC_JMP_short);
1343 1a6dc1e4 Richard Henderson
    label_ptr[2] = s->code_ptr;
1344 c896fe29 bellard
    s->code_ptr++;
1345 78686523 Richard Henderson
1346 1a6dc1e4 Richard Henderson
    /* TLB Miss.  */
1347 1a6dc1e4 Richard Henderson
1348 1a6dc1e4 Richard Henderson
    /* label1: */
1349 1a6dc1e4 Richard Henderson
    *label_ptr[0] = s->code_ptr - label_ptr[0] - 1;
1350 5d8a4f8f Richard Henderson
    if (TARGET_LONG_BITS > TCG_TARGET_REG_BITS) {
1351 1a6dc1e4 Richard Henderson
        *label_ptr[1] = s->code_ptr - label_ptr[1] - 1;
1352 1a6dc1e4 Richard Henderson
    }
1353 c896fe29 bellard
1354 c896fe29 bellard
    /* XXX: move that code at the end of the TB */
1355 5d8a4f8f Richard Henderson
    if (TCG_TARGET_REG_BITS == 64) {
1356 5d8a4f8f Richard Henderson
        tcg_out_mov(s, (opc == 3 ? TCG_TYPE_I64 : TCG_TYPE_I32),
1357 5d8a4f8f Richard Henderson
                    TCG_REG_RSI, data_reg);
1358 5d8a4f8f Richard Henderson
        tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_RDX, mem_index);
1359 5d8a4f8f Richard Henderson
        stack_adjust = 0;
1360 5d8a4f8f Richard Henderson
    } else if (TARGET_LONG_BITS == 32) {
1361 3b6dac34 Richard Henderson
        tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_EDX, data_reg);
1362 82bb07db Richard Henderson
        if (opc == 3) {
1363 3b6dac34 Richard Henderson
            tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_ECX, data_reg2);
1364 82bb07db Richard Henderson
            tcg_out_pushi(s, mem_index);
1365 82bb07db Richard Henderson
            stack_adjust = 4;
1366 82bb07db Richard Henderson
        } else {
1367 82bb07db Richard Henderson
            tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_ECX, mem_index);
1368 82bb07db Richard Henderson
            stack_adjust = 0;
1369 c896fe29 bellard
        }
1370 c896fe29 bellard
    } else {
1371 82bb07db Richard Henderson
        if (opc == 3) {
1372 3b6dac34 Richard Henderson
            tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_EDX, args[addrlo_idx + 1]);
1373 82bb07db Richard Henderson
            tcg_out_pushi(s, mem_index);
1374 82bb07db Richard Henderson
            tcg_out_push(s, data_reg2);
1375 82bb07db Richard Henderson
            tcg_out_push(s, data_reg);
1376 82bb07db Richard Henderson
            stack_adjust = 12;
1377 82bb07db Richard Henderson
        } else {
1378 3b6dac34 Richard Henderson
            tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_EDX, args[addrlo_idx + 1]);
1379 82bb07db Richard Henderson
            switch(opc) {
1380 82bb07db Richard Henderson
            case 0:
1381 82bb07db Richard Henderson
                tcg_out_ext8u(s, TCG_REG_ECX, data_reg);
1382 82bb07db Richard Henderson
                break;
1383 82bb07db Richard Henderson
            case 1:
1384 82bb07db Richard Henderson
                tcg_out_ext16u(s, TCG_REG_ECX, data_reg);
1385 82bb07db Richard Henderson
                break;
1386 82bb07db Richard Henderson
            case 2:
1387 3b6dac34 Richard Henderson
                tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_ECX, data_reg);
1388 82bb07db Richard Henderson
                break;
1389 82bb07db Richard Henderson
            }
1390 82bb07db Richard Henderson
            tcg_out_pushi(s, mem_index);
1391 82bb07db Richard Henderson
            stack_adjust = 4;
1392 c896fe29 bellard
        }
1393 c896fe29 bellard
    }
1394 aadb21a4 Richard Henderson
1395 aadb21a4 Richard Henderson
    tcg_out_calli(s, (tcg_target_long)qemu_st_helpers[s_bits]);
1396 aadb21a4 Richard Henderson
1397 5d8a4f8f Richard Henderson
    if (stack_adjust == (TCG_TARGET_REG_BITS / 8)) {
1398 aadb21a4 Richard Henderson
        /* Pop and discard.  This is 2 bytes smaller than the add.  */
1399 aadb21a4 Richard Henderson
        tcg_out_pop(s, TCG_REG_ECX);
1400 aadb21a4 Richard Henderson
    } else if (stack_adjust != 0) {
1401 aadb21a4 Richard Henderson
        tcg_out_addi(s, TCG_REG_ESP, stack_adjust);
1402 aadb21a4 Richard Henderson
    }
1403 aadb21a4 Richard Henderson
1404 c896fe29 bellard
    /* label2: */
1405 1a6dc1e4 Richard Henderson
    *label_ptr[2] = s->code_ptr - label_ptr[2] - 1;
1406 be5a4eb7 Richard Henderson
#else
1407 5d8a4f8f Richard Henderson
    {
1408 5d8a4f8f Richard Henderson
        int32_t offset = GUEST_BASE;
1409 5d8a4f8f Richard Henderson
        int base = args[addrlo_idx];
1410 5d8a4f8f Richard Henderson
1411 5d8a4f8f Richard Henderson
        if (TCG_TARGET_REG_BITS == 64) {
1412 5d8a4f8f Richard Henderson
            /* ??? We assume all operations have left us with register
1413 5d8a4f8f Richard Henderson
               contents that are zero extended.  So far this appears to
1414 5d8a4f8f Richard Henderson
               be true.  If we want to enforce this, we can either do
1415 5d8a4f8f Richard Henderson
               an explicit zero-extension here, or (if GUEST_BASE == 0)
1416 5d8a4f8f Richard Henderson
               use the ADDR32 prefix.  For now, do nothing.  */
1417 5d8a4f8f Richard Henderson
1418 5d8a4f8f Richard Henderson
            if (offset != GUEST_BASE) {
1419 5d8a4f8f Richard Henderson
                tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_RDI, GUEST_BASE);
1420 5d8a4f8f Richard Henderson
                tgen_arithr(s, ARITH_ADD + P_REXW, TCG_REG_RDI, base);
1421 5d8a4f8f Richard Henderson
                base = TCG_REG_RDI, offset = 0;
1422 5d8a4f8f Richard Henderson
            }
1423 5d8a4f8f Richard Henderson
        }
1424 5d8a4f8f Richard Henderson
1425 5d8a4f8f Richard Henderson
        tcg_out_qemu_st_direct(s, data_reg, data_reg2, base, offset, opc);
1426 5d8a4f8f Richard Henderson
    }
1427 c896fe29 bellard
#endif
1428 c896fe29 bellard
}
1429 c896fe29 bellard
1430 a9751609 Richard Henderson
static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
1431 c896fe29 bellard
                              const TCGArg *args, const int *const_args)
1432 c896fe29 bellard
{
1433 5d8a4f8f Richard Henderson
    int c, rexw = 0;
1434 5d8a4f8f Richard Henderson
1435 5d8a4f8f Richard Henderson
#if TCG_TARGET_REG_BITS == 64
1436 5d8a4f8f Richard Henderson
# define OP_32_64(x) \
1437 5d8a4f8f Richard Henderson
        case glue(glue(INDEX_op_, x), _i64): \
1438 5d8a4f8f Richard Henderson
            rexw = P_REXW; /* FALLTHRU */    \
1439 5d8a4f8f Richard Henderson
        case glue(glue(INDEX_op_, x), _i32)
1440 5d8a4f8f Richard Henderson
#else
1441 5d8a4f8f Richard Henderson
# define OP_32_64(x) \
1442 5d8a4f8f Richard Henderson
        case glue(glue(INDEX_op_, x), _i32)
1443 5d8a4f8f Richard Henderson
#endif
1444 78686523 Richard Henderson
1445 c896fe29 bellard
    switch(opc) {
1446 c896fe29 bellard
    case INDEX_op_exit_tb:
1447 5d8a4f8f Richard Henderson
        tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_EAX, args[0]);
1448 5d8a4f8f Richard Henderson
        tcg_out_jmp(s, (tcg_target_long) tb_ret_addr);
1449 c896fe29 bellard
        break;
1450 c896fe29 bellard
    case INDEX_op_goto_tb:
1451 c896fe29 bellard
        if (s->tb_jmp_offset) {
1452 c896fe29 bellard
            /* direct jump method */
1453 da441cff Richard Henderson
            tcg_out8(s, OPC_JMP_long); /* jmp im */
1454 c896fe29 bellard
            s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
1455 c896fe29 bellard
            tcg_out32(s, 0);
1456 c896fe29 bellard
        } else {
1457 c896fe29 bellard
            /* indirect jump method */
1458 9363dedb Richard Henderson
            tcg_out_modrm_offset(s, OPC_GRP5, EXT5_JMPN_Ev, -1,
1459 c896fe29 bellard
                                 (tcg_target_long)(s->tb_next + args[0]));
1460 c896fe29 bellard
        }
1461 c896fe29 bellard
        s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
1462 c896fe29 bellard
        break;
1463 c896fe29 bellard
    case INDEX_op_call:
1464 c896fe29 bellard
        if (const_args[0]) {
1465 aadb21a4 Richard Henderson
            tcg_out_calli(s, args[0]);
1466 c896fe29 bellard
        } else {
1467 aadb21a4 Richard Henderson
            /* call *reg */
1468 9363dedb Richard Henderson
            tcg_out_modrm(s, OPC_GRP5, EXT5_CALLN_Ev, args[0]);
1469 c896fe29 bellard
        }
1470 c896fe29 bellard
        break;
1471 c896fe29 bellard
    case INDEX_op_jmp:
1472 c896fe29 bellard
        if (const_args[0]) {
1473 5d8a4f8f Richard Henderson
            tcg_out_jmp(s, args[0]);
1474 c896fe29 bellard
        } else {
1475 da441cff Richard Henderson
            /* jmp *reg */
1476 9363dedb Richard Henderson
            tcg_out_modrm(s, OPC_GRP5, EXT5_JMPN_Ev, args[0]);
1477 c896fe29 bellard
        }
1478 c896fe29 bellard
        break;
1479 c896fe29 bellard
    case INDEX_op_br:
1480 f75b56c1 Richard Henderson
        tcg_out_jxx(s, JCC_JMP, args[0], 0);
1481 c896fe29 bellard
        break;
1482 c896fe29 bellard
    case INDEX_op_movi_i32:
1483 c896fe29 bellard
        tcg_out_movi(s, TCG_TYPE_I32, args[0], args[1]);
1484 c896fe29 bellard
        break;
1485 5d8a4f8f Richard Henderson
    OP_32_64(ld8u):
1486 5d8a4f8f Richard Henderson
        /* Note that we can ignore REXW for the zero-extend to 64-bit.  */
1487 55e082a7 Richard Henderson
        tcg_out_modrm_offset(s, OPC_MOVZBL, args[0], args[1], args[2]);
1488 c896fe29 bellard
        break;
1489 5d8a4f8f Richard Henderson
    OP_32_64(ld8s):
1490 5d8a4f8f Richard Henderson
        tcg_out_modrm_offset(s, OPC_MOVSBL + rexw, args[0], args[1], args[2]);
1491 c896fe29 bellard
        break;
1492 5d8a4f8f Richard Henderson
    OP_32_64(ld16u):
1493 5d8a4f8f Richard Henderson
        /* Note that we can ignore REXW for the zero-extend to 64-bit.  */
1494 55e082a7 Richard Henderson
        tcg_out_modrm_offset(s, OPC_MOVZWL, args[0], args[1], args[2]);
1495 c896fe29 bellard
        break;
1496 5d8a4f8f Richard Henderson
    OP_32_64(ld16s):
1497 5d8a4f8f Richard Henderson
        tcg_out_modrm_offset(s, OPC_MOVSWL + rexw, args[0], args[1], args[2]);
1498 c896fe29 bellard
        break;
1499 5d8a4f8f Richard Henderson
#if TCG_TARGET_REG_BITS == 64
1500 5d8a4f8f Richard Henderson
    case INDEX_op_ld32u_i64:
1501 5d8a4f8f Richard Henderson
#endif
1502 c896fe29 bellard
    case INDEX_op_ld_i32:
1503 af266089 Richard Henderson
        tcg_out_ld(s, TCG_TYPE_I32, args[0], args[1], args[2]);
1504 c896fe29 bellard
        break;
1505 5d8a4f8f Richard Henderson
1506 5d8a4f8f Richard Henderson
    OP_32_64(st8):
1507 5d8a4f8f Richard Henderson
        tcg_out_modrm_offset(s, OPC_MOVB_EvGv | P_REXB_R,
1508 5d8a4f8f Richard Henderson
                             args[0], args[1], args[2]);
1509 c896fe29 bellard
        break;
1510 5d8a4f8f Richard Henderson
    OP_32_64(st16):
1511 96b4cf38 Richard Henderson
        tcg_out_modrm_offset(s, OPC_MOVL_EvGv | P_DATA16,
1512 96b4cf38 Richard Henderson
                             args[0], args[1], args[2]);
1513 c896fe29 bellard
        break;
1514 5d8a4f8f Richard Henderson
#if TCG_TARGET_REG_BITS == 64
1515 5d8a4f8f Richard Henderson
    case INDEX_op_st32_i64:
1516 5d8a4f8f Richard Henderson
#endif
1517 c896fe29 bellard
    case INDEX_op_st_i32:
1518 af266089 Richard Henderson
        tcg_out_st(s, TCG_TYPE_I32, args[0], args[1], args[2]);
1519 c896fe29 bellard
        break;
1520 5d8a4f8f Richard Henderson
1521 5d8a4f8f Richard Henderson
    OP_32_64(add):
1522 5d1e4e85 Richard Henderson
        /* For 3-operand addition, use LEA.  */
1523 5d1e4e85 Richard Henderson
        if (args[0] != args[1]) {
1524 5d1e4e85 Richard Henderson
            TCGArg a0 = args[0], a1 = args[1], a2 = args[2], c3 = 0;
1525 5d1e4e85 Richard Henderson
1526 5d1e4e85 Richard Henderson
            if (const_args[2]) {
1527 5d1e4e85 Richard Henderson
                c3 = a2, a2 = -1;
1528 5d1e4e85 Richard Henderson
            } else if (a0 == a2) {
1529 5d1e4e85 Richard Henderson
                /* Watch out for dest = src + dest, since we've removed
1530 5d1e4e85 Richard Henderson
                   the matching constraint on the add.  */
1531 5d8a4f8f Richard Henderson
                tgen_arithr(s, ARITH_ADD + rexw, a0, a1);
1532 5d1e4e85 Richard Henderson
                break;
1533 5d1e4e85 Richard Henderson
            }
1534 5d1e4e85 Richard Henderson
1535 5d8a4f8f Richard Henderson
            tcg_out_modrm_sib_offset(s, OPC_LEA + rexw, a0, a1, a2, 0, c3);
1536 5d1e4e85 Richard Henderson
            break;
1537 5d1e4e85 Richard Henderson
        }
1538 5d1e4e85 Richard Henderson
        c = ARITH_ADD;
1539 5d1e4e85 Richard Henderson
        goto gen_arith;
1540 5d8a4f8f Richard Henderson
    OP_32_64(sub):
1541 c896fe29 bellard
        c = ARITH_SUB;
1542 c896fe29 bellard
        goto gen_arith;
1543 5d8a4f8f Richard Henderson
    OP_32_64(and):
1544 c896fe29 bellard
        c = ARITH_AND;
1545 c896fe29 bellard
        goto gen_arith;
1546 5d8a4f8f Richard Henderson
    OP_32_64(or):
1547 c896fe29 bellard
        c = ARITH_OR;
1548 c896fe29 bellard
        goto gen_arith;
1549 5d8a4f8f Richard Henderson
    OP_32_64(xor):
1550 c896fe29 bellard
        c = ARITH_XOR;
1551 c896fe29 bellard
        goto gen_arith;
1552 c896fe29 bellard
    gen_arith:
1553 c896fe29 bellard
        if (const_args[2]) {
1554 5d8a4f8f Richard Henderson
            tgen_arithi(s, c + rexw, args[0], args[2], 0);
1555 c896fe29 bellard
        } else {
1556 5d8a4f8f Richard Henderson
            tgen_arithr(s, c + rexw, args[0], args[2]);
1557 c896fe29 bellard
        }
1558 c896fe29 bellard
        break;
1559 5d8a4f8f Richard Henderson
1560 5d8a4f8f Richard Henderson
    OP_32_64(mul):
1561 c896fe29 bellard
        if (const_args[2]) {
1562 c896fe29 bellard
            int32_t val;
1563 c896fe29 bellard
            val = args[2];
1564 c896fe29 bellard
            if (val == (int8_t)val) {
1565 5d8a4f8f Richard Henderson
                tcg_out_modrm(s, OPC_IMUL_GvEvIb + rexw, args[0], args[0]);
1566 c896fe29 bellard
                tcg_out8(s, val);
1567 c896fe29 bellard
            } else {
1568 5d8a4f8f Richard Henderson
                tcg_out_modrm(s, OPC_IMUL_GvEvIz + rexw, args[0], args[0]);
1569 c896fe29 bellard
                tcg_out32(s, val);
1570 c896fe29 bellard
            }
1571 c896fe29 bellard
        } else {
1572 5d8a4f8f Richard Henderson
            tcg_out_modrm(s, OPC_IMUL_GvEv + rexw, args[0], args[2]);
1573 c896fe29 bellard
        }
1574 c896fe29 bellard
        break;
1575 5d8a4f8f Richard Henderson
1576 5d8a4f8f Richard Henderson
    OP_32_64(div2):
1577 5d8a4f8f Richard Henderson
        tcg_out_modrm(s, OPC_GRP3_Ev + rexw, EXT3_IDIV, args[4]);
1578 c896fe29 bellard
        break;
1579 5d8a4f8f Richard Henderson
    OP_32_64(divu2):
1580 5d8a4f8f Richard Henderson
        tcg_out_modrm(s, OPC_GRP3_Ev + rexw, EXT3_DIV, args[4]);
1581 c896fe29 bellard
        break;
1582 5d8a4f8f Richard Henderson
1583 5d8a4f8f Richard Henderson
    OP_32_64(shl):
1584 c896fe29 bellard
        c = SHIFT_SHL;
1585 5d8a4f8f Richard Henderson
        goto gen_shift;
1586 5d8a4f8f Richard Henderson
    OP_32_64(shr):
1587 c896fe29 bellard
        c = SHIFT_SHR;
1588 5d8a4f8f Richard Henderson
        goto gen_shift;
1589 5d8a4f8f Richard Henderson
    OP_32_64(sar):
1590 c896fe29 bellard
        c = SHIFT_SAR;
1591 5d8a4f8f Richard Henderson
        goto gen_shift;
1592 5d8a4f8f Richard Henderson
    OP_32_64(rotl):
1593 9619376c aurel32
        c = SHIFT_ROL;
1594 5d8a4f8f Richard Henderson
        goto gen_shift;
1595 5d8a4f8f Richard Henderson
    OP_32_64(rotr):
1596 9619376c aurel32
        c = SHIFT_ROR;
1597 5d8a4f8f Richard Henderson
        goto gen_shift;
1598 5d8a4f8f Richard Henderson
    gen_shift:
1599 5d8a4f8f Richard Henderson
        if (const_args[2]) {
1600 5d8a4f8f Richard Henderson
            tcg_out_shifti(s, c + rexw, args[0], args[2]);
1601 81570a70 Richard Henderson
        } else {
1602 5d8a4f8f Richard Henderson
            tcg_out_modrm(s, OPC_SHIFT_cl + rexw, c, args[0]);
1603 81570a70 Richard Henderson
        }
1604 c896fe29 bellard
        break;
1605 5d8a4f8f Richard Henderson
1606 c896fe29 bellard
    case INDEX_op_brcond_i32:
1607 5d8a4f8f Richard Henderson
        tcg_out_brcond32(s, args[2], args[0], args[1], const_args[1],
1608 5d8a4f8f Richard Henderson
                         args[3], 0);
1609 c896fe29 bellard
        break;
1610 5d8a4f8f Richard Henderson
    case INDEX_op_setcond_i32:
1611 5d8a4f8f Richard Henderson
        tcg_out_setcond32(s, args[3], args[0], args[1],
1612 5d8a4f8f Richard Henderson
                          args[2], const_args[2]);
1613 c896fe29 bellard
        break;
1614 c896fe29 bellard
1615 5d8a4f8f Richard Henderson
    OP_32_64(bswap16):
1616 fcb5dac1 Richard Henderson
        tcg_out_rolw_8(s, args[0]);
1617 5d40cd63 aurel32
        break;
1618 5d8a4f8f Richard Henderson
    OP_32_64(bswap32):
1619 fcb5dac1 Richard Henderson
        tcg_out_bswap32(s, args[0]);
1620 9619376c aurel32
        break;
1621 9619376c aurel32
1622 5d8a4f8f Richard Henderson
    OP_32_64(neg):
1623 5d8a4f8f Richard Henderson
        tcg_out_modrm(s, OPC_GRP3_Ev + rexw, EXT3_NEG, args[0]);
1624 9619376c aurel32
        break;
1625 5d8a4f8f Richard Henderson
    OP_32_64(not):
1626 5d8a4f8f Richard Henderson
        tcg_out_modrm(s, OPC_GRP3_Ev + rexw, EXT3_NOT, args[0]);
1627 9619376c aurel32
        break;
1628 9619376c aurel32
1629 5d8a4f8f Richard Henderson
    OP_32_64(ext8s):
1630 5d8a4f8f Richard Henderson
        tcg_out_ext8s(s, args[0], args[1], rexw);
1631 9619376c aurel32
        break;
1632 5d8a4f8f Richard Henderson
    OP_32_64(ext16s):
1633 5d8a4f8f Richard Henderson
        tcg_out_ext16s(s, args[0], args[1], rexw);
1634 9619376c aurel32
        break;
1635 5d8a4f8f Richard Henderson
    OP_32_64(ext8u):
1636 55e082a7 Richard Henderson
        tcg_out_ext8u(s, args[0], args[1]);
1637 5f0ce17f Aurelien Jarno
        break;
1638 5d8a4f8f Richard Henderson
    OP_32_64(ext16u):
1639 55e082a7 Richard Henderson
        tcg_out_ext16u(s, args[0], args[1]);
1640 5f0ce17f Aurelien Jarno
        break;
1641 9619376c aurel32
1642 c896fe29 bellard
    case INDEX_op_qemu_ld8u:
1643 c896fe29 bellard
        tcg_out_qemu_ld(s, args, 0);
1644 c896fe29 bellard
        break;
1645 c896fe29 bellard
    case INDEX_op_qemu_ld8s:
1646 c896fe29 bellard
        tcg_out_qemu_ld(s, args, 0 | 4);
1647 c896fe29 bellard
        break;
1648 c896fe29 bellard
    case INDEX_op_qemu_ld16u:
1649 c896fe29 bellard
        tcg_out_qemu_ld(s, args, 1);
1650 c896fe29 bellard
        break;
1651 c896fe29 bellard
    case INDEX_op_qemu_ld16s:
1652 c896fe29 bellard
        tcg_out_qemu_ld(s, args, 1 | 4);
1653 c896fe29 bellard
        break;
1654 5d8a4f8f Richard Henderson
#if TCG_TARGET_REG_BITS == 64
1655 5d8a4f8f Richard Henderson
    case INDEX_op_qemu_ld32u:
1656 5d8a4f8f Richard Henderson
#endif
1657 86feb1c8 Richard Henderson
    case INDEX_op_qemu_ld32:
1658 c896fe29 bellard
        tcg_out_qemu_ld(s, args, 2);
1659 c896fe29 bellard
        break;
1660 c896fe29 bellard
    case INDEX_op_qemu_ld64:
1661 c896fe29 bellard
        tcg_out_qemu_ld(s, args, 3);
1662 c896fe29 bellard
        break;
1663 78686523 Richard Henderson
1664 c896fe29 bellard
    case INDEX_op_qemu_st8:
1665 c896fe29 bellard
        tcg_out_qemu_st(s, args, 0);
1666 c896fe29 bellard
        break;
1667 c896fe29 bellard
    case INDEX_op_qemu_st16:
1668 c896fe29 bellard
        tcg_out_qemu_st(s, args, 1);
1669 c896fe29 bellard
        break;
1670 c896fe29 bellard
    case INDEX_op_qemu_st32:
1671 c896fe29 bellard
        tcg_out_qemu_st(s, args, 2);
1672 c896fe29 bellard
        break;
1673 c896fe29 bellard
    case INDEX_op_qemu_st64:
1674 c896fe29 bellard
        tcg_out_qemu_st(s, args, 3);
1675 c896fe29 bellard
        break;
1676 c896fe29 bellard
1677 5d8a4f8f Richard Henderson
#if TCG_TARGET_REG_BITS == 32
1678 5d8a4f8f Richard Henderson
    case INDEX_op_brcond2_i32:
1679 5d8a4f8f Richard Henderson
        tcg_out_brcond2(s, args, const_args, 0);
1680 5d8a4f8f Richard Henderson
        break;
1681 5d8a4f8f Richard Henderson
    case INDEX_op_setcond2_i32:
1682 5d8a4f8f Richard Henderson
        tcg_out_setcond2(s, args, const_args);
1683 5d8a4f8f Richard Henderson
        break;
1684 5d8a4f8f Richard Henderson
    case INDEX_op_mulu2_i32:
1685 5d8a4f8f Richard Henderson
        tcg_out_modrm(s, OPC_GRP3_Ev, EXT3_MUL, args[3]);
1686 5d8a4f8f Richard Henderson
        break;
1687 5d8a4f8f Richard Henderson
    case INDEX_op_add2_i32:
1688 5d8a4f8f Richard Henderson
        if (const_args[4]) {
1689 5d8a4f8f Richard Henderson
            tgen_arithi(s, ARITH_ADD, args[0], args[4], 1);
1690 5d8a4f8f Richard Henderson
        } else {
1691 5d8a4f8f Richard Henderson
            tgen_arithr(s, ARITH_ADD, args[0], args[4]);
1692 5d8a4f8f Richard Henderson
        }
1693 5d8a4f8f Richard Henderson
        if (const_args[5]) {
1694 5d8a4f8f Richard Henderson
            tgen_arithi(s, ARITH_ADC, args[1], args[5], 1);
1695 5d8a4f8f Richard Henderson
        } else {
1696 5d8a4f8f Richard Henderson
            tgen_arithr(s, ARITH_ADC, args[1], args[5]);
1697 5d8a4f8f Richard Henderson
        }
1698 5d8a4f8f Richard Henderson
        break;
1699 5d8a4f8f Richard Henderson
    case INDEX_op_sub2_i32:
1700 5d8a4f8f Richard Henderson
        if (const_args[4]) {
1701 5d8a4f8f Richard Henderson
            tgen_arithi(s, ARITH_SUB, args[0], args[4], 1);
1702 5d8a4f8f Richard Henderson
        } else {
1703 5d8a4f8f Richard Henderson
            tgen_arithr(s, ARITH_SUB, args[0], args[4]);
1704 5d8a4f8f Richard Henderson
        }
1705 5d8a4f8f Richard Henderson
        if (const_args[5]) {
1706 5d8a4f8f Richard Henderson
            tgen_arithi(s, ARITH_SBB, args[1], args[5], 1);
1707 5d8a4f8f Richard Henderson
        } else {
1708 5d8a4f8f Richard Henderson
            tgen_arithr(s, ARITH_SBB, args[1], args[5]);
1709 5d8a4f8f Richard Henderson
        }
1710 5d8a4f8f Richard Henderson
        break;
1711 5d8a4f8f Richard Henderson
#else /* TCG_TARGET_REG_BITS == 64 */
1712 5d8a4f8f Richard Henderson
    case INDEX_op_movi_i64:
1713 5d8a4f8f Richard Henderson
        tcg_out_movi(s, TCG_TYPE_I64, args[0], args[1]);
1714 5d8a4f8f Richard Henderson
        break;
1715 5d8a4f8f Richard Henderson
    case INDEX_op_ld32s_i64:
1716 5d8a4f8f Richard Henderson
        tcg_out_modrm_offset(s, OPC_MOVSLQ, args[0], args[1], args[2]);
1717 5d8a4f8f Richard Henderson
        break;
1718 5d8a4f8f Richard Henderson
    case INDEX_op_ld_i64:
1719 5d8a4f8f Richard Henderson
        tcg_out_ld(s, TCG_TYPE_I64, args[0], args[1], args[2]);
1720 5d8a4f8f Richard Henderson
        break;
1721 5d8a4f8f Richard Henderson
    case INDEX_op_st_i64:
1722 5d8a4f8f Richard Henderson
        tcg_out_st(s, TCG_TYPE_I64, args[0], args[1], args[2]);
1723 5d8a4f8f Richard Henderson
        break;
1724 5d8a4f8f Richard Henderson
    case INDEX_op_qemu_ld32s:
1725 5d8a4f8f Richard Henderson
        tcg_out_qemu_ld(s, args, 2 | 4);
1726 5d8a4f8f Richard Henderson
        break;
1727 5d8a4f8f Richard Henderson
1728 5d8a4f8f Richard Henderson
    case INDEX_op_brcond_i64:
1729 5d8a4f8f Richard Henderson
        tcg_out_brcond64(s, args[2], args[0], args[1], const_args[1],
1730 5d8a4f8f Richard Henderson
                         args[3], 0);
1731 5d8a4f8f Richard Henderson
        break;
1732 5d8a4f8f Richard Henderson
    case INDEX_op_setcond_i64:
1733 5d8a4f8f Richard Henderson
        tcg_out_setcond64(s, args[3], args[0], args[1],
1734 5d8a4f8f Richard Henderson
                          args[2], const_args[2]);
1735 5d8a4f8f Richard Henderson
        break;
1736 5d8a4f8f Richard Henderson
1737 5d8a4f8f Richard Henderson
    case INDEX_op_bswap64_i64:
1738 5d8a4f8f Richard Henderson
        tcg_out_bswap64(s, args[0]);
1739 5d8a4f8f Richard Henderson
        break;
1740 5d8a4f8f Richard Henderson
    case INDEX_op_ext32u_i64:
1741 5d8a4f8f Richard Henderson
        tcg_out_ext32u(s, args[0], args[1]);
1742 5d8a4f8f Richard Henderson
        break;
1743 5d8a4f8f Richard Henderson
    case INDEX_op_ext32s_i64:
1744 5d8a4f8f Richard Henderson
        tcg_out_ext32s(s, args[0], args[1]);
1745 5d8a4f8f Richard Henderson
        break;
1746 5d8a4f8f Richard Henderson
#endif
1747 5d8a4f8f Richard Henderson
1748 c896fe29 bellard
    default:
1749 c896fe29 bellard
        tcg_abort();
1750 c896fe29 bellard
    }
1751 5d8a4f8f Richard Henderson
1752 5d8a4f8f Richard Henderson
#undef OP_32_64
1753 c896fe29 bellard
}
1754 c896fe29 bellard
1755 c896fe29 bellard
static const TCGTargetOpDef x86_op_defs[] = {
1756 c896fe29 bellard
    { INDEX_op_exit_tb, { } },
1757 c896fe29 bellard
    { INDEX_op_goto_tb, { } },
1758 c896fe29 bellard
    { INDEX_op_call, { "ri" } },
1759 c896fe29 bellard
    { INDEX_op_jmp, { "ri" } },
1760 c896fe29 bellard
    { INDEX_op_br, { } },
1761 c896fe29 bellard
    { INDEX_op_mov_i32, { "r", "r" } },
1762 c896fe29 bellard
    { INDEX_op_movi_i32, { "r" } },
1763 c896fe29 bellard
    { INDEX_op_ld8u_i32, { "r", "r" } },
1764 c896fe29 bellard
    { INDEX_op_ld8s_i32, { "r", "r" } },
1765 c896fe29 bellard
    { INDEX_op_ld16u_i32, { "r", "r" } },
1766 c896fe29 bellard
    { INDEX_op_ld16s_i32, { "r", "r" } },
1767 c896fe29 bellard
    { INDEX_op_ld_i32, { "r", "r" } },
1768 c896fe29 bellard
    { INDEX_op_st8_i32, { "q", "r" } },
1769 c896fe29 bellard
    { INDEX_op_st16_i32, { "r", "r" } },
1770 c896fe29 bellard
    { INDEX_op_st_i32, { "r", "r" } },
1771 c896fe29 bellard
1772 5d1e4e85 Richard Henderson
    { INDEX_op_add_i32, { "r", "r", "ri" } },
1773 c896fe29 bellard
    { INDEX_op_sub_i32, { "r", "0", "ri" } },
1774 c896fe29 bellard
    { INDEX_op_mul_i32, { "r", "0", "ri" } },
1775 c896fe29 bellard
    { INDEX_op_div2_i32, { "a", "d", "0", "1", "r" } },
1776 c896fe29 bellard
    { INDEX_op_divu2_i32, { "a", "d", "0", "1", "r" } },
1777 c896fe29 bellard
    { INDEX_op_and_i32, { "r", "0", "ri" } },
1778 c896fe29 bellard
    { INDEX_op_or_i32, { "r", "0", "ri" } },
1779 c896fe29 bellard
    { INDEX_op_xor_i32, { "r", "0", "ri" } },
1780 c896fe29 bellard
1781 c896fe29 bellard
    { INDEX_op_shl_i32, { "r", "0", "ci" } },
1782 c896fe29 bellard
    { INDEX_op_shr_i32, { "r", "0", "ci" } },
1783 c896fe29 bellard
    { INDEX_op_sar_i32, { "r", "0", "ci" } },
1784 9619376c aurel32
    { INDEX_op_rotl_i32, { "r", "0", "ci" } },
1785 9619376c aurel32
    { INDEX_op_rotr_i32, { "r", "0", "ci" } },
1786 c896fe29 bellard
1787 c896fe29 bellard
    { INDEX_op_brcond_i32, { "r", "ri" } },
1788 c896fe29 bellard
1789 5d40cd63 aurel32
    { INDEX_op_bswap16_i32, { "r", "0" } },
1790 66896cb8 aurel32
    { INDEX_op_bswap32_i32, { "r", "0" } },
1791 9619376c aurel32
1792 9619376c aurel32
    { INDEX_op_neg_i32, { "r", "0" } },
1793 9619376c aurel32
1794 9619376c aurel32
    { INDEX_op_not_i32, { "r", "0" } },
1795 9619376c aurel32
1796 9619376c aurel32
    { INDEX_op_ext8s_i32, { "r", "q" } },
1797 9619376c aurel32
    { INDEX_op_ext16s_i32, { "r", "r" } },
1798 55e082a7 Richard Henderson
    { INDEX_op_ext8u_i32, { "r", "q" } },
1799 55e082a7 Richard Henderson
    { INDEX_op_ext16u_i32, { "r", "r" } },
1800 9619376c aurel32
1801 1d2699ae Richard Henderson
    { INDEX_op_setcond_i32, { "q", "r", "ri" } },
1802 5d8a4f8f Richard Henderson
1803 5d8a4f8f Richard Henderson
#if TCG_TARGET_REG_BITS == 32
1804 5d8a4f8f Richard Henderson
    { INDEX_op_mulu2_i32, { "a", "d", "a", "r" } },
1805 5d8a4f8f Richard Henderson
    { INDEX_op_add2_i32, { "r", "r", "0", "1", "ri", "ri" } },
1806 5d8a4f8f Richard Henderson
    { INDEX_op_sub2_i32, { "r", "r", "0", "1", "ri", "ri" } },
1807 5d8a4f8f Richard Henderson
    { INDEX_op_brcond2_i32, { "r", "r", "ri", "ri" } },
1808 1d2699ae Richard Henderson
    { INDEX_op_setcond2_i32, { "r", "r", "r", "ri", "ri" } },
1809 5d8a4f8f Richard Henderson
#else
1810 5d8a4f8f Richard Henderson
    { INDEX_op_mov_i64, { "r", "r" } },
1811 5d8a4f8f Richard Henderson
    { INDEX_op_movi_i64, { "r" } },
1812 5d8a4f8f Richard Henderson
    { INDEX_op_ld8u_i64, { "r", "r" } },
1813 5d8a4f8f Richard Henderson
    { INDEX_op_ld8s_i64, { "r", "r" } },
1814 5d8a4f8f Richard Henderson
    { INDEX_op_ld16u_i64, { "r", "r" } },
1815 5d8a4f8f Richard Henderson
    { INDEX_op_ld16s_i64, { "r", "r" } },
1816 5d8a4f8f Richard Henderson
    { INDEX_op_ld32u_i64, { "r", "r" } },
1817 5d8a4f8f Richard Henderson
    { INDEX_op_ld32s_i64, { "r", "r" } },
1818 5d8a4f8f Richard Henderson
    { INDEX_op_ld_i64, { "r", "r" } },
1819 5d8a4f8f Richard Henderson
    { INDEX_op_st8_i64, { "r", "r" } },
1820 5d8a4f8f Richard Henderson
    { INDEX_op_st16_i64, { "r", "r" } },
1821 5d8a4f8f Richard Henderson
    { INDEX_op_st32_i64, { "r", "r" } },
1822 5d8a4f8f Richard Henderson
    { INDEX_op_st_i64, { "r", "r" } },
1823 5d8a4f8f Richard Henderson
1824 5d8a4f8f Richard Henderson
    { INDEX_op_add_i64, { "r", "0", "re" } },
1825 5d8a4f8f Richard Henderson
    { INDEX_op_mul_i64, { "r", "0", "re" } },
1826 5d8a4f8f Richard Henderson
    { INDEX_op_div2_i64, { "a", "d", "0", "1", "r" } },
1827 5d8a4f8f Richard Henderson
    { INDEX_op_divu2_i64, { "a", "d", "0", "1", "r" } },
1828 5d8a4f8f Richard Henderson
    { INDEX_op_sub_i64, { "r", "0", "re" } },
1829 5d8a4f8f Richard Henderson
    { INDEX_op_and_i64, { "r", "0", "reZ" } },
1830 5d8a4f8f Richard Henderson
    { INDEX_op_or_i64, { "r", "0", "re" } },
1831 5d8a4f8f Richard Henderson
    { INDEX_op_xor_i64, { "r", "0", "re" } },
1832 5d8a4f8f Richard Henderson
1833 5d8a4f8f Richard Henderson
    { INDEX_op_shl_i64, { "r", "0", "ci" } },
1834 5d8a4f8f Richard Henderson
    { INDEX_op_shr_i64, { "r", "0", "ci" } },
1835 5d8a4f8f Richard Henderson
    { INDEX_op_sar_i64, { "r", "0", "ci" } },
1836 5d8a4f8f Richard Henderson
    { INDEX_op_rotl_i64, { "r", "0", "ci" } },
1837 5d8a4f8f Richard Henderson
    { INDEX_op_rotr_i64, { "r", "0", "ci" } },
1838 5d8a4f8f Richard Henderson
1839 5d8a4f8f Richard Henderson
    { INDEX_op_brcond_i64, { "r", "re" } },
1840 5d8a4f8f Richard Henderson
    { INDEX_op_setcond_i64, { "r", "r", "re" } },
1841 5d8a4f8f Richard Henderson
1842 5d8a4f8f Richard Henderson
    { INDEX_op_bswap16_i64, { "r", "0" } },
1843 5d8a4f8f Richard Henderson
    { INDEX_op_bswap32_i64, { "r", "0" } },
1844 5d8a4f8f Richard Henderson
    { INDEX_op_bswap64_i64, { "r", "0" } },
1845 5d8a4f8f Richard Henderson
    { INDEX_op_neg_i64, { "r", "0" } },
1846 5d8a4f8f Richard Henderson
    { INDEX_op_not_i64, { "r", "0" } },
1847 5d8a4f8f Richard Henderson
1848 5d8a4f8f Richard Henderson
    { INDEX_op_ext8s_i64, { "r", "r" } },
1849 5d8a4f8f Richard Henderson
    { INDEX_op_ext16s_i64, { "r", "r" } },
1850 5d8a4f8f Richard Henderson
    { INDEX_op_ext32s_i64, { "r", "r" } },
1851 5d8a4f8f Richard Henderson
    { INDEX_op_ext8u_i64, { "r", "r" } },
1852 5d8a4f8f Richard Henderson
    { INDEX_op_ext16u_i64, { "r", "r" } },
1853 5d8a4f8f Richard Henderson
    { INDEX_op_ext32u_i64, { "r", "r" } },
1854 5d8a4f8f Richard Henderson
#endif
1855 1d2699ae Richard Henderson
1856 5d8a4f8f Richard Henderson
#if TCG_TARGET_REG_BITS == 64
1857 5d8a4f8f Richard Henderson
    { INDEX_op_qemu_ld8u, { "r", "L" } },
1858 5d8a4f8f Richard Henderson
    { INDEX_op_qemu_ld8s, { "r", "L" } },
1859 5d8a4f8f Richard Henderson
    { INDEX_op_qemu_ld16u, { "r", "L" } },
1860 5d8a4f8f Richard Henderson
    { INDEX_op_qemu_ld16s, { "r", "L" } },
1861 5d8a4f8f Richard Henderson
    { INDEX_op_qemu_ld32, { "r", "L" } },
1862 5d8a4f8f Richard Henderson
    { INDEX_op_qemu_ld32u, { "r", "L" } },
1863 5d8a4f8f Richard Henderson
    { INDEX_op_qemu_ld32s, { "r", "L" } },
1864 5d8a4f8f Richard Henderson
    { INDEX_op_qemu_ld64, { "r", "L" } },
1865 5d8a4f8f Richard Henderson
1866 5d8a4f8f Richard Henderson
    { INDEX_op_qemu_st8, { "L", "L" } },
1867 5d8a4f8f Richard Henderson
    { INDEX_op_qemu_st16, { "L", "L" } },
1868 5d8a4f8f Richard Henderson
    { INDEX_op_qemu_st32, { "L", "L" } },
1869 5d8a4f8f Richard Henderson
    { INDEX_op_qemu_st64, { "L", "L" } },
1870 5d8a4f8f Richard Henderson
#elif TARGET_LONG_BITS <= TCG_TARGET_REG_BITS
1871 c896fe29 bellard
    { INDEX_op_qemu_ld8u, { "r", "L" } },
1872 c896fe29 bellard
    { INDEX_op_qemu_ld8s, { "r", "L" } },
1873 c896fe29 bellard
    { INDEX_op_qemu_ld16u, { "r", "L" } },
1874 c896fe29 bellard
    { INDEX_op_qemu_ld16s, { "r", "L" } },
1875 86feb1c8 Richard Henderson
    { INDEX_op_qemu_ld32, { "r", "L" } },
1876 c896fe29 bellard
    { INDEX_op_qemu_ld64, { "r", "r", "L" } },
1877 c896fe29 bellard
1878 c896fe29 bellard
    { INDEX_op_qemu_st8, { "cb", "L" } },
1879 c896fe29 bellard
    { INDEX_op_qemu_st16, { "L", "L" } },
1880 c896fe29 bellard
    { INDEX_op_qemu_st32, { "L", "L" } },
1881 c896fe29 bellard
    { INDEX_op_qemu_st64, { "L", "L", "L" } },
1882 c896fe29 bellard
#else
1883 c896fe29 bellard
    { INDEX_op_qemu_ld8u, { "r", "L", "L" } },
1884 c896fe29 bellard
    { INDEX_op_qemu_ld8s, { "r", "L", "L" } },
1885 c896fe29 bellard
    { INDEX_op_qemu_ld16u, { "r", "L", "L" } },
1886 c896fe29 bellard
    { INDEX_op_qemu_ld16s, { "r", "L", "L" } },
1887 86feb1c8 Richard Henderson
    { INDEX_op_qemu_ld32, { "r", "L", "L" } },
1888 c896fe29 bellard
    { INDEX_op_qemu_ld64, { "r", "r", "L", "L" } },
1889 c896fe29 bellard
1890 c896fe29 bellard
    { INDEX_op_qemu_st8, { "cb", "L", "L" } },
1891 c896fe29 bellard
    { INDEX_op_qemu_st16, { "L", "L", "L" } },
1892 c896fe29 bellard
    { INDEX_op_qemu_st32, { "L", "L", "L" } },
1893 c896fe29 bellard
    { INDEX_op_qemu_st64, { "L", "L", "L", "L" } },
1894 c896fe29 bellard
#endif
1895 c896fe29 bellard
    { -1 },
1896 c896fe29 bellard
};
1897 c896fe29 bellard
1898 b03cce8e bellard
static int tcg_target_callee_save_regs[] = {
1899 5d8a4f8f Richard Henderson
#if TCG_TARGET_REG_BITS == 64
1900 5d8a4f8f Richard Henderson
    TCG_REG_RBP,
1901 5d8a4f8f Richard Henderson
    TCG_REG_RBX,
1902 5d8a4f8f Richard Henderson
    TCG_REG_R12,
1903 5d8a4f8f Richard Henderson
    TCG_REG_R13,
1904 5d8a4f8f Richard Henderson
    /* TCG_REG_R14, */ /* Currently used for the global env. */
1905 5d8a4f8f Richard Henderson
    TCG_REG_R15,
1906 5d8a4f8f Richard Henderson
#else
1907 5d8a4f8f Richard Henderson
    /* TCG_REG_EBP, */ /* Currently used for the global env. */
1908 b03cce8e bellard
    TCG_REG_EBX,
1909 b03cce8e bellard
    TCG_REG_ESI,
1910 b03cce8e bellard
    TCG_REG_EDI,
1911 5d8a4f8f Richard Henderson
#endif
1912 b03cce8e bellard
};
1913 b03cce8e bellard
1914 b03cce8e bellard
/* Generate global QEMU prologue and epilogue code */
1915 e4d58b41 Richard Henderson
static void tcg_target_qemu_prologue(TCGContext *s)
1916 b03cce8e bellard
{
1917 b03cce8e bellard
    int i, frame_size, push_size, stack_addend;
1918 78686523 Richard Henderson
1919 b03cce8e bellard
    /* TB prologue */
1920 5d8a4f8f Richard Henderson
1921 5d8a4f8f Richard Henderson
    /* Save all callee saved registers.  */
1922 5d8a4f8f Richard Henderson
    for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
1923 b03cce8e bellard
        tcg_out_push(s, tcg_target_callee_save_regs[i]);
1924 b03cce8e bellard
    }
1925 5d8a4f8f Richard Henderson
1926 5d8a4f8f Richard Henderson
    /* Reserve some stack space.  */
1927 5d8a4f8f Richard Henderson
    push_size = 1 + ARRAY_SIZE(tcg_target_callee_save_regs);
1928 5d8a4f8f Richard Henderson
    push_size *= TCG_TARGET_REG_BITS / 8;
1929 5d8a4f8f Richard Henderson
1930 b03cce8e bellard
    frame_size = push_size + TCG_STATIC_CALL_ARGS_SIZE;
1931 78686523 Richard Henderson
    frame_size = (frame_size + TCG_TARGET_STACK_ALIGN - 1) &
1932 b03cce8e bellard
        ~(TCG_TARGET_STACK_ALIGN - 1);
1933 b03cce8e bellard
    stack_addend = frame_size - push_size;
1934 b03cce8e bellard
    tcg_out_addi(s, TCG_REG_ESP, -stack_addend);
1935 b03cce8e bellard
1936 5d8a4f8f Richard Henderson
    /* jmp *tb.  */
1937 5d8a4f8f Richard Henderson
    tcg_out_modrm(s, OPC_GRP5, EXT5_JMPN_Ev, tcg_target_call_iarg_regs[0]);
1938 78686523 Richard Henderson
1939 b03cce8e bellard
    /* TB epilogue */
1940 b03cce8e bellard
    tb_ret_addr = s->code_ptr;
1941 5d8a4f8f Richard Henderson
1942 b03cce8e bellard
    tcg_out_addi(s, TCG_REG_ESP, stack_addend);
1943 5d8a4f8f Richard Henderson
1944 5d8a4f8f Richard Henderson
    for (i = ARRAY_SIZE(tcg_target_callee_save_regs) - 1; i >= 0; i--) {
1945 b03cce8e bellard
        tcg_out_pop(s, tcg_target_callee_save_regs[i]);
1946 b03cce8e bellard
    }
1947 5d8a4f8f Richard Henderson
    tcg_out_opc(s, OPC_RET, 0, 0, 0);
1948 b03cce8e bellard
}
1949 b03cce8e bellard
1950 e4d58b41 Richard Henderson
static void tcg_target_init(TCGContext *s)
1951 c896fe29 bellard
{
1952 20cb400d Paul Brook
#if !defined(CONFIG_USER_ONLY)
1953 c896fe29 bellard
    /* fail safe */
1954 c896fe29 bellard
    if ((1 << CPU_TLB_ENTRY_BITS) != sizeof(CPUTLBEntry))
1955 c896fe29 bellard
        tcg_abort();
1956 20cb400d Paul Brook
#endif
1957 c896fe29 bellard
1958 5d8a4f8f Richard Henderson
    if (TCG_TARGET_REG_BITS == 64) {
1959 5d8a4f8f Richard Henderson
        tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffff);
1960 5d8a4f8f Richard Henderson
        tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I64], 0, 0xffff);
1961 5d8a4f8f Richard Henderson
    } else {
1962 5d8a4f8f Richard Henderson
        tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xff);
1963 5d8a4f8f Richard Henderson
    }
1964 4ab50ccf Richard Henderson
1965 4ab50ccf Richard Henderson
    tcg_regset_clear(tcg_target_call_clobber_regs);
1966 4ab50ccf Richard Henderson
    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_EAX);
1967 4ab50ccf Richard Henderson
    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_EDX);
1968 4ab50ccf Richard Henderson
    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_ECX);
1969 5d8a4f8f Richard Henderson
    if (TCG_TARGET_REG_BITS == 64) {
1970 5d8a4f8f Richard Henderson
        tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_RDI);
1971 5d8a4f8f Richard Henderson
        tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_RSI);
1972 5d8a4f8f Richard Henderson
        tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R8);
1973 5d8a4f8f Richard Henderson
        tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R9);
1974 5d8a4f8f Richard Henderson
        tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R10);
1975 5d8a4f8f Richard Henderson
        tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R11);
1976 5d8a4f8f Richard Henderson
    }
1977 4ab50ccf Richard Henderson
1978 c896fe29 bellard
    tcg_regset_clear(s->reserved_regs);
1979 c896fe29 bellard
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_ESP);
1980 c896fe29 bellard
1981 c896fe29 bellard
    tcg_add_target_add_op_defs(x86_op_defs);
1982 c896fe29 bellard
}