]> Git Repo - qemu.git/blame - target/i386/translate.c
target/i386: move cpu_T0 to DisasContext
[qemu.git] / target / i386 / translate.c
CommitLineData
2c0262af
FB
1/*
2 * i386 translation
5fafdf24 3 *
2c0262af
FB
4 * Copyright (c) 2003 Fabrice Bellard
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
8167ee88 17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
2c0262af 18 */
b6a0aa05 19#include "qemu/osdep.h"
2c0262af 20
bec93d72 21#include "qemu/host-utils.h"
2c0262af 22#include "cpu.h"
76cad711 23#include "disas/disas.h"
63c91552 24#include "exec/exec-all.h"
57fec1fe 25#include "tcg-op.h"
f08b6170 26#include "exec/cpu_ldst.h"
77fc6f5e 27#include "exec/translator.h"
2c0262af 28
2ef6175a
RH
29#include "exec/helper-proto.h"
30#include "exec/helper-gen.h"
a7812ae4 31
a7e30d84 32#include "trace-tcg.h"
508127e2 33#include "exec/log.h"
a7e30d84 34
2c0262af
FB
35#define PREFIX_REPZ 0x01
36#define PREFIX_REPNZ 0x02
37#define PREFIX_LOCK 0x04
38#define PREFIX_DATA 0x08
39#define PREFIX_ADR 0x10
701ed211 40#define PREFIX_VEX 0x20
2c0262af 41
14ce26e7 42#ifdef TARGET_X86_64
14ce26e7
FB
43#define CODE64(s) ((s)->code64)
44#define REX_X(s) ((s)->rex_x)
45#define REX_B(s) ((s)->rex_b)
14ce26e7 46#else
14ce26e7
FB
47#define CODE64(s) 0
48#define REX_X(s) 0
49#define REX_B(s) 0
50#endif
51
bec93d72
RH
52#ifdef TARGET_X86_64
53# define ctztl ctz64
54# define clztl clz64
55#else
56# define ctztl ctz32
57# define clztl clz32
58#endif
59
1906b2af 60/* For a switch indexed by MODRM, match all memory operands for a given OP. */
880f8486 61#define CASE_MODRM_MEM_OP(OP) \
1906b2af
RH
62 case (0 << 6) | (OP << 3) | 0 ... (0 << 6) | (OP << 3) | 7: \
63 case (1 << 6) | (OP << 3) | 0 ... (1 << 6) | (OP << 3) | 7: \
64 case (2 << 6) | (OP << 3) | 0 ... (2 << 6) | (OP << 3) | 7
65
880f8486
PB
66#define CASE_MODRM_OP(OP) \
67 case (0 << 6) | (OP << 3) | 0 ... (0 << 6) | (OP << 3) | 7: \
68 case (1 << 6) | (OP << 3) | 0 ... (1 << 6) | (OP << 3) | 7: \
69 case (2 << 6) | (OP << 3) | 0 ... (2 << 6) | (OP << 3) | 7: \
70 case (3 << 6) | (OP << 3) | 0 ... (3 << 6) | (OP << 3) | 7
71
57fec1fe
FB
72//#define MACRO_TEST 1
73
57fec1fe 74/* global register indexes */
93a3e108 75static TCGv cpu_cc_dst, cpu_cc_src, cpu_cc_src2;
a7812ae4 76static TCGv_i32 cpu_cc_op;
cc739bb0 77static TCGv cpu_regs[CPU_NB_REGS];
3558f805 78static TCGv cpu_seg_base[6];
149b427b
RH
79static TCGv_i64 cpu_bndl[4];
80static TCGv_i64 cpu_bndu[4];
1e4840bf 81/* local temps */
c66f9727 82static TCGv cpu_T1;
57fec1fe 83/* local register indexes (only used inside old micro ops) */
a7812ae4
PB
84static TCGv cpu_tmp0, cpu_tmp4;
85static TCGv_ptr cpu_ptr0, cpu_ptr1;
86static TCGv_i32 cpu_tmp2_i32, cpu_tmp3_i32;
87static TCGv_i64 cpu_tmp1_i64;
57fec1fe 88
022c62cb 89#include "exec/gen-icount.h"
2e70f6ef 90
57fec1fe
FB
91#ifdef TARGET_X86_64
92static int x86_64_hregs;
ae063a68
FB
93#endif
94
2c0262af 95typedef struct DisasContext {
6cf147aa
LV
96 DisasContextBase base;
97
2c0262af
FB
98 /* current insn context */
99 int override; /* -1 if no override */
100 int prefix;
1d71ddb1 101 TCGMemOp aflag;
ab4e4aec 102 TCGMemOp dflag;
b9f9c5b4 103 target_ulong pc_start;
14ce26e7 104 target_ulong pc; /* pc = eip + cs_base */
2c0262af 105 /* current block context */
14ce26e7 106 target_ulong cs_base; /* base of CS segment */
2c0262af
FB
107 int pe; /* protected mode */
108 int code32; /* 32 bit code segment */
14ce26e7
FB
109#ifdef TARGET_X86_64
110 int lma; /* long mode active */
111 int code64; /* 64 bit code segment */
112 int rex_x, rex_b;
113#endif
701ed211 114 int vex_l; /* vex vector length */
1d349821 115 int vex_v; /* vex vvvv register, without 1's complement. */
2c0262af 116 int ss32; /* 32 bit stack segment */
fee71888 117 CCOp cc_op; /* current CC operation */
e207582f 118 bool cc_op_dirty;
2c0262af
FB
119 int addseg; /* non zero if either DS/ES/SS have a non zero base */
120 int f_st; /* currently unused */
121 int vm86; /* vm86 mode */
122 int cpl;
123 int iopl;
124 int tf; /* TF cpu flag */
125 int jmp_opt; /* use direct block chaining for direct jumps */
c4d4525c 126 int repz_opt; /* optimize jumps within repz instructions */
2c0262af 127 int mem_index; /* select memory access functions */
c068688b 128 uint64_t flags; /* all execution flags */
2c0262af 129 int popl_esp_hack; /* for correct popl with esp base handling */
14ce26e7
FB
130 int rip_offset; /* only used in x86_64, but left for simplicity */
131 int cpuid_features;
3d7374c5 132 int cpuid_ext_features;
e771edab 133 int cpuid_ext2_features;
12e26b75 134 int cpuid_ext3_features;
a9321a4d 135 int cpuid_7_0_ebx_features;
c9cfe8f9 136 int cpuid_xsave_features;
93a3e108
EC
137
138 /* TCG local temps */
139 TCGv cc_srcT;
6b672b5d 140 TCGv A0;
c66f9727 141 TCGv T0;
93a3e108 142
b066c537 143 sigjmp_buf jmpbuf;
2c0262af
FB
144} DisasContext;
145
146static void gen_eob(DisasContext *s);
1ebb1af1 147static void gen_jr(DisasContext *s, TCGv dest);
14ce26e7
FB
148static void gen_jmp(DisasContext *s, target_ulong eip);
149static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num);
d67dc9e6 150static void gen_op(DisasContext *s1, int op, TCGMemOp ot, int d);
2c0262af
FB
151
152/* i386 arith/logic operations */
153enum {
5fafdf24
TS
154 OP_ADDL,
155 OP_ORL,
156 OP_ADCL,
2c0262af 157 OP_SBBL,
5fafdf24
TS
158 OP_ANDL,
159 OP_SUBL,
160 OP_XORL,
2c0262af
FB
161 OP_CMPL,
162};
163
164/* i386 shift ops */
165enum {
5fafdf24
TS
166 OP_ROL,
167 OP_ROR,
168 OP_RCL,
169 OP_RCR,
170 OP_SHL,
171 OP_SHR,
2c0262af
FB
172 OP_SHL1, /* undocumented */
173 OP_SAR = 7,
174};
175
8e1c85e3
FB
176enum {
177 JCC_O,
178 JCC_B,
179 JCC_Z,
180 JCC_BE,
181 JCC_S,
182 JCC_P,
183 JCC_L,
184 JCC_LE,
185};
186
2c0262af
FB
187enum {
188 /* I386 int registers */
189 OR_EAX, /* MUST be even numbered */
190 OR_ECX,
191 OR_EDX,
192 OR_EBX,
193 OR_ESP,
194 OR_EBP,
195 OR_ESI,
196 OR_EDI,
14ce26e7
FB
197
198 OR_TMP0 = 16, /* temporary operand register */
2c0262af
FB
199 OR_TMP1,
200 OR_A0, /* temporary register used when doing address evaluation */
2c0262af
FB
201};
202
b666265b 203enum {
a3251186
RH
204 USES_CC_DST = 1,
205 USES_CC_SRC = 2,
988c3eb0
RH
206 USES_CC_SRC2 = 4,
207 USES_CC_SRCT = 8,
b666265b
RH
208};
209
210/* Bit set if the global variable is live after setting CC_OP to X. */
211static const uint8_t cc_op_live[CC_OP_NB] = {
988c3eb0 212 [CC_OP_DYNAMIC] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
b666265b
RH
213 [CC_OP_EFLAGS] = USES_CC_SRC,
214 [CC_OP_MULB ... CC_OP_MULQ] = USES_CC_DST | USES_CC_SRC,
215 [CC_OP_ADDB ... CC_OP_ADDQ] = USES_CC_DST | USES_CC_SRC,
988c3eb0 216 [CC_OP_ADCB ... CC_OP_ADCQ] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
a3251186 217 [CC_OP_SUBB ... CC_OP_SUBQ] = USES_CC_DST | USES_CC_SRC | USES_CC_SRCT,
988c3eb0 218 [CC_OP_SBBB ... CC_OP_SBBQ] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
b666265b
RH
219 [CC_OP_LOGICB ... CC_OP_LOGICQ] = USES_CC_DST,
220 [CC_OP_INCB ... CC_OP_INCQ] = USES_CC_DST | USES_CC_SRC,
221 [CC_OP_DECB ... CC_OP_DECQ] = USES_CC_DST | USES_CC_SRC,
222 [CC_OP_SHLB ... CC_OP_SHLQ] = USES_CC_DST | USES_CC_SRC,
223 [CC_OP_SARB ... CC_OP_SARQ] = USES_CC_DST | USES_CC_SRC,
bc4b43dc 224 [CC_OP_BMILGB ... CC_OP_BMILGQ] = USES_CC_DST | USES_CC_SRC,
cd7f97ca
RH
225 [CC_OP_ADCX] = USES_CC_DST | USES_CC_SRC,
226 [CC_OP_ADOX] = USES_CC_SRC | USES_CC_SRC2,
227 [CC_OP_ADCOX] = USES_CC_DST | USES_CC_SRC | USES_CC_SRC2,
436ff2d2 228 [CC_OP_CLR] = 0,
4885c3c4 229 [CC_OP_POPCNT] = USES_CC_SRC,
b666265b
RH
230};
231
e207582f 232static void set_cc_op(DisasContext *s, CCOp op)
3ca51d07 233{
b666265b
RH
234 int dead;
235
236 if (s->cc_op == op) {
237 return;
238 }
239
240 /* Discard CC computation that will no longer be used. */
241 dead = cc_op_live[s->cc_op] & ~cc_op_live[op];
242 if (dead & USES_CC_DST) {
243 tcg_gen_discard_tl(cpu_cc_dst);
e207582f 244 }
b666265b
RH
245 if (dead & USES_CC_SRC) {
246 tcg_gen_discard_tl(cpu_cc_src);
247 }
988c3eb0
RH
248 if (dead & USES_CC_SRC2) {
249 tcg_gen_discard_tl(cpu_cc_src2);
250 }
a3251186 251 if (dead & USES_CC_SRCT) {
93a3e108 252 tcg_gen_discard_tl(s->cc_srcT);
a3251186 253 }
b666265b 254
e2f515cf
RH
255 if (op == CC_OP_DYNAMIC) {
256 /* The DYNAMIC setting is translator only, and should never be
257 stored. Thus we always consider it clean. */
258 s->cc_op_dirty = false;
259 } else {
260 /* Discard any computed CC_OP value (see shifts). */
261 if (s->cc_op == CC_OP_DYNAMIC) {
262 tcg_gen_discard_i32(cpu_cc_op);
263 }
264 s->cc_op_dirty = true;
265 }
b666265b 266 s->cc_op = op;
e207582f
RH
267}
268
e207582f
RH
269static void gen_update_cc_op(DisasContext *s)
270{
271 if (s->cc_op_dirty) {
773cdfcc 272 tcg_gen_movi_i32(cpu_cc_op, s->cc_op);
e207582f
RH
273 s->cc_op_dirty = false;
274 }
3ca51d07
RH
275}
276
14ce26e7
FB
277#ifdef TARGET_X86_64
278
279#define NB_OP_SIZES 4
280
14ce26e7
FB
281#else /* !TARGET_X86_64 */
282
283#define NB_OP_SIZES 3
284
14ce26e7
FB
285#endif /* !TARGET_X86_64 */
286
e2542fe2 287#if defined(HOST_WORDS_BIGENDIAN)
57fec1fe
FB
288#define REG_B_OFFSET (sizeof(target_ulong) - 1)
289#define REG_H_OFFSET (sizeof(target_ulong) - 2)
290#define REG_W_OFFSET (sizeof(target_ulong) - 2)
291#define REG_L_OFFSET (sizeof(target_ulong) - 4)
292#define REG_LH_OFFSET (sizeof(target_ulong) - 8)
14ce26e7 293#else
57fec1fe
FB
294#define REG_B_OFFSET 0
295#define REG_H_OFFSET 1
296#define REG_W_OFFSET 0
297#define REG_L_OFFSET 0
298#define REG_LH_OFFSET 4
14ce26e7 299#endif
57fec1fe 300
96d7073f
PM
301/* In instruction encodings for byte register accesses the
302 * register number usually indicates "low 8 bits of register N";
303 * however there are some special cases where N 4..7 indicates
304 * [AH, CH, DH, BH], ie "bits 15..8 of register N-4". Return
305 * true for this special case, false otherwise.
306 */
307static inline bool byte_reg_is_xH(int reg)
308{
309 if (reg < 4) {
310 return false;
311 }
312#ifdef TARGET_X86_64
313 if (reg >= 8 || x86_64_hregs) {
314 return false;
315 }
316#endif
317 return true;
318}
319
ab4e4aec
RH
320/* Select the size of a push/pop operation. */
321static inline TCGMemOp mo_pushpop(DisasContext *s, TCGMemOp ot)
322{
323 if (CODE64(s)) {
324 return ot == MO_16 ? MO_16 : MO_64;
325 } else {
326 return ot;
327 }
328}
329
64ae256c
RH
330/* Select the size of the stack pointer. */
331static inline TCGMemOp mo_stacksize(DisasContext *s)
332{
333 return CODE64(s) ? MO_64 : s->ss32 ? MO_32 : MO_16;
334}
335
ab4e4aec
RH
336/* Select only size 64 else 32. Used for SSE operand sizes. */
337static inline TCGMemOp mo_64_32(TCGMemOp ot)
338{
339#ifdef TARGET_X86_64
340 return ot == MO_64 ? MO_64 : MO_32;
341#else
342 return MO_32;
343#endif
344}
345
346/* Select size 8 if lsb of B is clear, else OT. Used for decoding
347 byte vs word opcodes. */
348static inline TCGMemOp mo_b_d(int b, TCGMemOp ot)
349{
350 return b & 1 ? ot : MO_8;
351}
352
353/* Select size 8 if lsb of B is clear, else OT capped at 32.
354 Used for decoding operand size of port opcodes. */
355static inline TCGMemOp mo_b_d32(int b, TCGMemOp ot)
356{
357 return b & 1 ? (ot == MO_16 ? MO_16 : MO_32) : MO_8;
358}
359
d67dc9e6 360static void gen_op_mov_reg_v(TCGMemOp ot, int reg, TCGv t0)
57fec1fe
FB
361{
362 switch(ot) {
4ba9938c 363 case MO_8:
96d7073f 364 if (!byte_reg_is_xH(reg)) {
c832e3de 365 tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], t0, 0, 8);
57fec1fe 366 } else {
c832e3de 367 tcg_gen_deposit_tl(cpu_regs[reg - 4], cpu_regs[reg - 4], t0, 8, 8);
57fec1fe
FB
368 }
369 break;
4ba9938c 370 case MO_16:
c832e3de 371 tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], t0, 0, 16);
57fec1fe 372 break;
4ba9938c 373 case MO_32:
cc739bb0
LD
374 /* For x86_64, this sets the higher half of register to zero.
375 For i386, this is equivalent to a mov. */
376 tcg_gen_ext32u_tl(cpu_regs[reg], t0);
57fec1fe 377 break;
cc739bb0 378#ifdef TARGET_X86_64
4ba9938c 379 case MO_64:
cc739bb0 380 tcg_gen_mov_tl(cpu_regs[reg], t0);
57fec1fe 381 break;
14ce26e7 382#endif
d67dc9e6
RH
383 default:
384 tcg_abort();
57fec1fe
FB
385 }
386}
2c0262af 387
d67dc9e6 388static inline void gen_op_mov_v_reg(TCGMemOp ot, TCGv t0, int reg)
57fec1fe 389{
4ba9938c 390 if (ot == MO_8 && byte_reg_is_xH(reg)) {
04fc2f1c 391 tcg_gen_extract_tl(t0, cpu_regs[reg - 4], 8, 8);
96d7073f 392 } else {
cc739bb0 393 tcg_gen_mov_tl(t0, cpu_regs[reg]);
57fec1fe
FB
394 }
395}
396
57fec1fe
FB
397static void gen_add_A0_im(DisasContext *s, int val)
398{
6b672b5d 399 tcg_gen_addi_tl(s->A0, s->A0, val);
4e85057b 400 if (!CODE64(s)) {
6b672b5d 401 tcg_gen_ext32u_tl(s->A0, s->A0);
4e85057b 402 }
57fec1fe 403}
2c0262af 404
74bdfbda 405static inline void gen_op_jmp_v(TCGv dest)
57fec1fe 406{
74bdfbda 407 tcg_gen_st_tl(dest, cpu_env, offsetof(CPUX86State, eip));
57fec1fe
FB
408}
409
d3f4bbe3 410static inline void gen_op_add_reg_im(TCGMemOp size, int reg, int32_t val)
57fec1fe 411{
d3f4bbe3
RH
412 tcg_gen_addi_tl(cpu_tmp0, cpu_regs[reg], val);
413 gen_op_mov_reg_v(size, reg, cpu_tmp0);
57fec1fe
FB
414}
415
c66f9727 416static inline void gen_op_add_reg_T0(DisasContext *s, TCGMemOp size, int reg)
57fec1fe 417{
c66f9727 418 tcg_gen_add_tl(cpu_tmp0, cpu_regs[reg], s->T0);
d3f4bbe3 419 gen_op_mov_reg_v(size, reg, cpu_tmp0);
6e0d8677 420}
57fec1fe 421
323d1876 422static inline void gen_op_ld_v(DisasContext *s, int idx, TCGv t0, TCGv a0)
57fec1fe 423{
3c5f4116 424 tcg_gen_qemu_ld_tl(t0, a0, s->mem_index, idx | MO_LE);
57fec1fe 425}
2c0262af 426
323d1876 427static inline void gen_op_st_v(DisasContext *s, int idx, TCGv t0, TCGv a0)
57fec1fe 428{
3523e4bd 429 tcg_gen_qemu_st_tl(t0, a0, s->mem_index, idx | MO_LE);
57fec1fe 430}
4f31916f 431
d4faa3e0
RH
432static inline void gen_op_st_rm_T0_A0(DisasContext *s, int idx, int d)
433{
434 if (d == OR_TMP0) {
c66f9727 435 gen_op_st_v(s, idx, s->T0, s->A0);
d4faa3e0 436 } else {
c66f9727 437 gen_op_mov_reg_v(idx, d, s->T0);
d4faa3e0
RH
438 }
439}
440
14ce26e7
FB
441static inline void gen_jmp_im(target_ulong pc)
442{
57fec1fe 443 tcg_gen_movi_tl(cpu_tmp0, pc);
74bdfbda 444 gen_op_jmp_v(cpu_tmp0);
14ce26e7
FB
445}
446
ca2f29f5
RH
447/* Compute SEG:REG into A0. SEG is selected from the override segment
448 (OVR_SEG) and the default segment (DEF_SEG). OVR_SEG may be -1 to
449 indicate no override. */
77ebcad0
RH
450static void gen_lea_v_seg(DisasContext *s, TCGMemOp aflag, TCGv a0,
451 int def_seg, int ovr_seg)
2c0262af 452{
ca2f29f5 453 switch (aflag) {
14ce26e7 454#ifdef TARGET_X86_64
1d71ddb1 455 case MO_64:
ca2f29f5 456 if (ovr_seg < 0) {
6b672b5d 457 tcg_gen_mov_tl(s->A0, a0);
ca2f29f5 458 return;
14ce26e7 459 }
1d71ddb1 460 break;
14ce26e7 461#endif
1d71ddb1 462 case MO_32:
2c0262af 463 /* 32 bit address */
620abfb0
PB
464 if (ovr_seg < 0 && s->addseg) {
465 ovr_seg = def_seg;
466 }
ca2f29f5 467 if (ovr_seg < 0) {
6b672b5d 468 tcg_gen_ext32u_tl(s->A0, a0);
620abfb0 469 return;
2c0262af 470 }
1d71ddb1
RH
471 break;
472 case MO_16:
ca2f29f5 473 /* 16 bit address */
6b672b5d
EC
474 tcg_gen_ext16u_tl(s->A0, a0);
475 a0 = s->A0;
e2e02a82
PB
476 if (ovr_seg < 0) {
477 if (s->addseg) {
478 ovr_seg = def_seg;
479 } else {
480 return;
481 }
482 }
1d71ddb1
RH
483 break;
484 default:
485 tcg_abort();
2c0262af 486 }
2c0262af 487
ca2f29f5 488 if (ovr_seg >= 0) {
3558f805 489 TCGv seg = cpu_seg_base[ovr_seg];
ca2f29f5
RH
490
491 if (aflag == MO_64) {
6b672b5d 492 tcg_gen_add_tl(s->A0, a0, seg);
ca2f29f5 493 } else if (CODE64(s)) {
6b672b5d
EC
494 tcg_gen_ext32u_tl(s->A0, a0);
495 tcg_gen_add_tl(s->A0, s->A0, seg);
2c0262af 496 } else {
6b672b5d
EC
497 tcg_gen_add_tl(s->A0, a0, seg);
498 tcg_gen_ext32u_tl(s->A0, s->A0);
2c0262af 499 }
2c0262af
FB
500 }
501}
502
ca2f29f5
RH
503static inline void gen_string_movl_A0_ESI(DisasContext *s)
504{
77ebcad0 505 gen_lea_v_seg(s, s->aflag, cpu_regs[R_ESI], R_DS, s->override);
ca2f29f5
RH
506}
507
508static inline void gen_string_movl_A0_EDI(DisasContext *s)
509{
77ebcad0 510 gen_lea_v_seg(s, s->aflag, cpu_regs[R_EDI], R_ES, -1);
ca2f29f5
RH
511}
512
c66f9727 513static inline void gen_op_movl_T0_Dshift(DisasContext *s, TCGMemOp ot)
6e0d8677 514{
c66f9727
EC
515 tcg_gen_ld32s_tl(s->T0, cpu_env, offsetof(CPUX86State, df));
516 tcg_gen_shli_tl(s->T0, s->T0, ot);
2c0262af
FB
517};
518
d67dc9e6 519static TCGv gen_ext_tl(TCGv dst, TCGv src, TCGMemOp size, bool sign)
6e0d8677 520{
d824df34 521 switch (size) {
4ba9938c 522 case MO_8:
d824df34
PB
523 if (sign) {
524 tcg_gen_ext8s_tl(dst, src);
525 } else {
526 tcg_gen_ext8u_tl(dst, src);
527 }
528 return dst;
4ba9938c 529 case MO_16:
d824df34
PB
530 if (sign) {
531 tcg_gen_ext16s_tl(dst, src);
532 } else {
533 tcg_gen_ext16u_tl(dst, src);
534 }
535 return dst;
536#ifdef TARGET_X86_64
4ba9938c 537 case MO_32:
d824df34
PB
538 if (sign) {
539 tcg_gen_ext32s_tl(dst, src);
540 } else {
541 tcg_gen_ext32u_tl(dst, src);
542 }
543 return dst;
544#endif
6e0d8677 545 default:
d824df34 546 return src;
6e0d8677
FB
547 }
548}
3b46e624 549
d67dc9e6 550static void gen_extu(TCGMemOp ot, TCGv reg)
d824df34
PB
551{
552 gen_ext_tl(reg, reg, ot, false);
553}
554
d67dc9e6 555static void gen_exts(TCGMemOp ot, TCGv reg)
6e0d8677 556{
d824df34 557 gen_ext_tl(reg, reg, ot, true);
6e0d8677 558}
2c0262af 559
42a268c2 560static inline void gen_op_jnz_ecx(TCGMemOp size, TCGLabel *label1)
6e0d8677 561{
cc739bb0 562 tcg_gen_mov_tl(cpu_tmp0, cpu_regs[R_ECX]);
c92aa1ad 563 gen_extu(size, cpu_tmp0);
cb63669a 564 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_tmp0, 0, label1);
6e0d8677
FB
565}
566
42a268c2 567static inline void gen_op_jz_ecx(TCGMemOp size, TCGLabel *label1)
6e0d8677 568{
cc739bb0 569 tcg_gen_mov_tl(cpu_tmp0, cpu_regs[R_ECX]);
c92aa1ad 570 gen_extu(size, cpu_tmp0);
cb63669a 571 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_tmp0, 0, label1);
6e0d8677 572}
2c0262af 573
d67dc9e6 574static void gen_helper_in_func(TCGMemOp ot, TCGv v, TCGv_i32 n)
a7812ae4
PB
575{
576 switch (ot) {
4ba9938c 577 case MO_8:
3f7d8464 578 gen_helper_inb(v, cpu_env, n);
93ab25d7 579 break;
4ba9938c 580 case MO_16:
3f7d8464 581 gen_helper_inw(v, cpu_env, n);
93ab25d7 582 break;
4ba9938c 583 case MO_32:
3f7d8464 584 gen_helper_inl(v, cpu_env, n);
93ab25d7 585 break;
d67dc9e6
RH
586 default:
587 tcg_abort();
a7812ae4 588 }
a7812ae4 589}
2c0262af 590
d67dc9e6 591static void gen_helper_out_func(TCGMemOp ot, TCGv_i32 v, TCGv_i32 n)
a7812ae4
PB
592{
593 switch (ot) {
4ba9938c 594 case MO_8:
3f7d8464 595 gen_helper_outb(cpu_env, v, n);
93ab25d7 596 break;
4ba9938c 597 case MO_16:
3f7d8464 598 gen_helper_outw(cpu_env, v, n);
93ab25d7 599 break;
4ba9938c 600 case MO_32:
3f7d8464 601 gen_helper_outl(cpu_env, v, n);
93ab25d7 602 break;
d67dc9e6
RH
603 default:
604 tcg_abort();
a7812ae4 605 }
a7812ae4 606}
f115e911 607
d67dc9e6 608static void gen_check_io(DisasContext *s, TCGMemOp ot, target_ulong cur_eip,
b8b6a50b 609 uint32_t svm_flags)
f115e911 610{
b8b6a50b
FB
611 target_ulong next_eip;
612
f115e911 613 if (s->pe && (s->cpl > s->iopl || s->vm86)) {
c66f9727 614 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, s->T0);
a7812ae4 615 switch (ot) {
4ba9938c 616 case MO_8:
4a7443be
BS
617 gen_helper_check_iob(cpu_env, cpu_tmp2_i32);
618 break;
4ba9938c 619 case MO_16:
4a7443be
BS
620 gen_helper_check_iow(cpu_env, cpu_tmp2_i32);
621 break;
4ba9938c 622 case MO_32:
4a7443be
BS
623 gen_helper_check_iol(cpu_env, cpu_tmp2_i32);
624 break;
d67dc9e6
RH
625 default:
626 tcg_abort();
a7812ae4 627 }
b8b6a50b 628 }
872929aa 629 if(s->flags & HF_SVMI_MASK) {
100ec099
PD
630 gen_update_cc_op(s);
631 gen_jmp_im(cur_eip);
b8b6a50b
FB
632 svm_flags |= (1 << (4 + ot));
633 next_eip = s->pc - s->cs_base;
c66f9727 634 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, s->T0);
052e80d5
BS
635 gen_helper_svm_check_io(cpu_env, cpu_tmp2_i32,
636 tcg_const_i32(svm_flags),
a7812ae4 637 tcg_const_i32(next_eip - cur_eip));
f115e911
FB
638 }
639}
640
d67dc9e6 641static inline void gen_movs(DisasContext *s, TCGMemOp ot)
2c0262af
FB
642{
643 gen_string_movl_A0_ESI(s);
c66f9727 644 gen_op_ld_v(s, ot, s->T0, s->A0);
2c0262af 645 gen_string_movl_A0_EDI(s);
c66f9727
EC
646 gen_op_st_v(s, ot, s->T0, s->A0);
647 gen_op_movl_T0_Dshift(s, ot);
648 gen_op_add_reg_T0(s, s->aflag, R_ESI);
649 gen_op_add_reg_T0(s, s->aflag, R_EDI);
2c0262af
FB
650}
651
c66f9727 652static void gen_op_update1_cc(DisasContext *s)
b6abf97d 653{
c66f9727 654 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
b6abf97d
FB
655}
656
c66f9727 657static void gen_op_update2_cc(DisasContext *s)
b6abf97d 658{
1d1cc4d0 659 tcg_gen_mov_tl(cpu_cc_src, cpu_T1);
c66f9727 660 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
b6abf97d
FB
661}
662
c66f9727 663static void gen_op_update3_cc(DisasContext *s, TCGv reg)
988c3eb0
RH
664{
665 tcg_gen_mov_tl(cpu_cc_src2, reg);
1d1cc4d0 666 tcg_gen_mov_tl(cpu_cc_src, cpu_T1);
c66f9727 667 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
988c3eb0
RH
668}
669
c66f9727 670static inline void gen_op_testl_T0_T1_cc(DisasContext *s)
b6abf97d 671{
c66f9727 672 tcg_gen_and_tl(cpu_cc_dst, s->T0, cpu_T1);
b6abf97d
FB
673}
674
93a3e108 675static void gen_op_update_neg_cc(DisasContext *s)
b6abf97d 676{
c66f9727
EC
677 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
678 tcg_gen_neg_tl(cpu_cc_src, s->T0);
93a3e108 679 tcg_gen_movi_tl(s->cc_srcT, 0);
b6abf97d
FB
680}
681
d229edce
RH
682/* compute all eflags to cc_src */
683static void gen_compute_eflags(DisasContext *s)
8e1c85e3 684{
988c3eb0 685 TCGv zero, dst, src1, src2;
db9f2597
RH
686 int live, dead;
687
d229edce
RH
688 if (s->cc_op == CC_OP_EFLAGS) {
689 return;
690 }
436ff2d2 691 if (s->cc_op == CC_OP_CLR) {
d2fe51bd 692 tcg_gen_movi_tl(cpu_cc_src, CC_Z | CC_P);
436ff2d2
RH
693 set_cc_op(s, CC_OP_EFLAGS);
694 return;
695 }
db9f2597 696
f764718d 697 zero = NULL;
db9f2597
RH
698 dst = cpu_cc_dst;
699 src1 = cpu_cc_src;
988c3eb0 700 src2 = cpu_cc_src2;
db9f2597
RH
701
702 /* Take care to not read values that are not live. */
703 live = cc_op_live[s->cc_op] & ~USES_CC_SRCT;
988c3eb0 704 dead = live ^ (USES_CC_DST | USES_CC_SRC | USES_CC_SRC2);
db9f2597
RH
705 if (dead) {
706 zero = tcg_const_tl(0);
707 if (dead & USES_CC_DST) {
708 dst = zero;
709 }
710 if (dead & USES_CC_SRC) {
711 src1 = zero;
712 }
988c3eb0
RH
713 if (dead & USES_CC_SRC2) {
714 src2 = zero;
715 }
db9f2597
RH
716 }
717
773cdfcc 718 gen_update_cc_op(s);
988c3eb0 719 gen_helper_cc_compute_all(cpu_cc_src, dst, src1, src2, cpu_cc_op);
d229edce 720 set_cc_op(s, CC_OP_EFLAGS);
db9f2597
RH
721
722 if (dead) {
723 tcg_temp_free(zero);
724 }
8e1c85e3
FB
725}
726
bec93d72
RH
727typedef struct CCPrepare {
728 TCGCond cond;
729 TCGv reg;
730 TCGv reg2;
731 target_ulong imm;
732 target_ulong mask;
733 bool use_reg2;
734 bool no_setcond;
735} CCPrepare;
736
06847f1f 737/* compute eflags.C to reg */
bec93d72 738static CCPrepare gen_prepare_eflags_c(DisasContext *s, TCGv reg)
06847f1f
RH
739{
740 TCGv t0, t1;
bec93d72 741 int size, shift;
06847f1f
RH
742
743 switch (s->cc_op) {
744 case CC_OP_SUBB ... CC_OP_SUBQ:
a3251186 745 /* (DATA_TYPE)CC_SRCT < (DATA_TYPE)CC_SRC */
06847f1f
RH
746 size = s->cc_op - CC_OP_SUBB;
747 t1 = gen_ext_tl(cpu_tmp0, cpu_cc_src, size, false);
748 /* If no temporary was used, be careful not to alias t1 and t0. */
11f4e8f8 749 t0 = t1 == cpu_cc_src ? cpu_tmp0 : reg;
93a3e108 750 tcg_gen_mov_tl(t0, s->cc_srcT);
06847f1f
RH
751 gen_extu(size, t0);
752 goto add_sub;
753
754 case CC_OP_ADDB ... CC_OP_ADDQ:
755 /* (DATA_TYPE)CC_DST < (DATA_TYPE)CC_SRC */
756 size = s->cc_op - CC_OP_ADDB;
757 t1 = gen_ext_tl(cpu_tmp0, cpu_cc_src, size, false);
758 t0 = gen_ext_tl(reg, cpu_cc_dst, size, false);
759 add_sub:
bec93d72
RH
760 return (CCPrepare) { .cond = TCG_COND_LTU, .reg = t0,
761 .reg2 = t1, .mask = -1, .use_reg2 = true };
06847f1f 762
06847f1f 763 case CC_OP_LOGICB ... CC_OP_LOGICQ:
436ff2d2 764 case CC_OP_CLR:
4885c3c4 765 case CC_OP_POPCNT:
bec93d72 766 return (CCPrepare) { .cond = TCG_COND_NEVER, .mask = -1 };
06847f1f
RH
767
768 case CC_OP_INCB ... CC_OP_INCQ:
769 case CC_OP_DECB ... CC_OP_DECQ:
bec93d72
RH
770 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
771 .mask = -1, .no_setcond = true };
06847f1f
RH
772
773 case CC_OP_SHLB ... CC_OP_SHLQ:
774 /* (CC_SRC >> (DATA_BITS - 1)) & 1 */
775 size = s->cc_op - CC_OP_SHLB;
bec93d72
RH
776 shift = (8 << size) - 1;
777 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
778 .mask = (target_ulong)1 << shift };
06847f1f
RH
779
780 case CC_OP_MULB ... CC_OP_MULQ:
bec93d72
RH
781 return (CCPrepare) { .cond = TCG_COND_NE,
782 .reg = cpu_cc_src, .mask = -1 };
06847f1f 783
bc4b43dc
RH
784 case CC_OP_BMILGB ... CC_OP_BMILGQ:
785 size = s->cc_op - CC_OP_BMILGB;
786 t0 = gen_ext_tl(reg, cpu_cc_src, size, false);
787 return (CCPrepare) { .cond = TCG_COND_EQ, .reg = t0, .mask = -1 };
788
cd7f97ca
RH
789 case CC_OP_ADCX:
790 case CC_OP_ADCOX:
791 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_dst,
792 .mask = -1, .no_setcond = true };
793
06847f1f
RH
794 case CC_OP_EFLAGS:
795 case CC_OP_SARB ... CC_OP_SARQ:
796 /* CC_SRC & 1 */
bec93d72
RH
797 return (CCPrepare) { .cond = TCG_COND_NE,
798 .reg = cpu_cc_src, .mask = CC_C };
06847f1f
RH
799
800 default:
801 /* The need to compute only C from CC_OP_DYNAMIC is important
802 in efficiently implementing e.g. INC at the start of a TB. */
803 gen_update_cc_op(s);
988c3eb0
RH
804 gen_helper_cc_compute_c(reg, cpu_cc_dst, cpu_cc_src,
805 cpu_cc_src2, cpu_cc_op);
bec93d72
RH
806 return (CCPrepare) { .cond = TCG_COND_NE, .reg = reg,
807 .mask = -1, .no_setcond = true };
06847f1f
RH
808 }
809}
810
1608ecca 811/* compute eflags.P to reg */
bec93d72 812static CCPrepare gen_prepare_eflags_p(DisasContext *s, TCGv reg)
1608ecca 813{
d229edce 814 gen_compute_eflags(s);
bec93d72
RH
815 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
816 .mask = CC_P };
1608ecca
PB
817}
818
819/* compute eflags.S to reg */
bec93d72 820static CCPrepare gen_prepare_eflags_s(DisasContext *s, TCGv reg)
1608ecca 821{
086c4077
RH
822 switch (s->cc_op) {
823 case CC_OP_DYNAMIC:
824 gen_compute_eflags(s);
825 /* FALLTHRU */
826 case CC_OP_EFLAGS:
cd7f97ca
RH
827 case CC_OP_ADCX:
828 case CC_OP_ADOX:
829 case CC_OP_ADCOX:
bec93d72
RH
830 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
831 .mask = CC_S };
436ff2d2 832 case CC_OP_CLR:
4885c3c4 833 case CC_OP_POPCNT:
436ff2d2 834 return (CCPrepare) { .cond = TCG_COND_NEVER, .mask = -1 };
086c4077
RH
835 default:
836 {
d67dc9e6 837 TCGMemOp size = (s->cc_op - CC_OP_ADDB) & 3;
086c4077 838 TCGv t0 = gen_ext_tl(reg, cpu_cc_dst, size, true);
bec93d72 839 return (CCPrepare) { .cond = TCG_COND_LT, .reg = t0, .mask = -1 };
086c4077 840 }
086c4077 841 }
1608ecca
PB
842}
843
844/* compute eflags.O to reg */
bec93d72 845static CCPrepare gen_prepare_eflags_o(DisasContext *s, TCGv reg)
1608ecca 846{
cd7f97ca
RH
847 switch (s->cc_op) {
848 case CC_OP_ADOX:
849 case CC_OP_ADCOX:
850 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src2,
851 .mask = -1, .no_setcond = true };
436ff2d2 852 case CC_OP_CLR:
4885c3c4 853 case CC_OP_POPCNT:
436ff2d2 854 return (CCPrepare) { .cond = TCG_COND_NEVER, .mask = -1 };
cd7f97ca
RH
855 default:
856 gen_compute_eflags(s);
857 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
858 .mask = CC_O };
859 }
1608ecca
PB
860}
861
862/* compute eflags.Z to reg */
bec93d72 863static CCPrepare gen_prepare_eflags_z(DisasContext *s, TCGv reg)
1608ecca 864{
086c4077
RH
865 switch (s->cc_op) {
866 case CC_OP_DYNAMIC:
867 gen_compute_eflags(s);
868 /* FALLTHRU */
869 case CC_OP_EFLAGS:
cd7f97ca
RH
870 case CC_OP_ADCX:
871 case CC_OP_ADOX:
872 case CC_OP_ADCOX:
bec93d72
RH
873 return (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
874 .mask = CC_Z };
436ff2d2
RH
875 case CC_OP_CLR:
876 return (CCPrepare) { .cond = TCG_COND_ALWAYS, .mask = -1 };
4885c3c4
RH
877 case CC_OP_POPCNT:
878 return (CCPrepare) { .cond = TCG_COND_EQ, .reg = cpu_cc_src,
879 .mask = -1 };
086c4077
RH
880 default:
881 {
d67dc9e6 882 TCGMemOp size = (s->cc_op - CC_OP_ADDB) & 3;
086c4077 883 TCGv t0 = gen_ext_tl(reg, cpu_cc_dst, size, false);
bec93d72 884 return (CCPrepare) { .cond = TCG_COND_EQ, .reg = t0, .mask = -1 };
086c4077 885 }
bec93d72
RH
886 }
887}
888
c365395e
PB
889/* perform a conditional store into register 'reg' according to jump opcode
890 value 'b'. In the fast case, T0 is guaranted not to be used. */
276e6b5f 891static CCPrepare gen_prepare_cc(DisasContext *s, int b, TCGv reg)
8e1c85e3 892{
d67dc9e6
RH
893 int inv, jcc_op, cond;
894 TCGMemOp size;
276e6b5f 895 CCPrepare cc;
c365395e
PB
896 TCGv t0;
897
898 inv = b & 1;
8e1c85e3 899 jcc_op = (b >> 1) & 7;
c365395e
PB
900
901 switch (s->cc_op) {
69d1aa31
RH
902 case CC_OP_SUBB ... CC_OP_SUBQ:
903 /* We optimize relational operators for the cmp/jcc case. */
c365395e
PB
904 size = s->cc_op - CC_OP_SUBB;
905 switch (jcc_op) {
906 case JCC_BE:
93a3e108 907 tcg_gen_mov_tl(cpu_tmp4, s->cc_srcT);
c365395e
PB
908 gen_extu(size, cpu_tmp4);
909 t0 = gen_ext_tl(cpu_tmp0, cpu_cc_src, size, false);
276e6b5f
RH
910 cc = (CCPrepare) { .cond = TCG_COND_LEU, .reg = cpu_tmp4,
911 .reg2 = t0, .mask = -1, .use_reg2 = true };
c365395e 912 break;
8e1c85e3 913
c365395e 914 case JCC_L:
276e6b5f 915 cond = TCG_COND_LT;
c365395e
PB
916 goto fast_jcc_l;
917 case JCC_LE:
276e6b5f 918 cond = TCG_COND_LE;
c365395e 919 fast_jcc_l:
93a3e108 920 tcg_gen_mov_tl(cpu_tmp4, s->cc_srcT);
c365395e
PB
921 gen_exts(size, cpu_tmp4);
922 t0 = gen_ext_tl(cpu_tmp0, cpu_cc_src, size, true);
276e6b5f
RH
923 cc = (CCPrepare) { .cond = cond, .reg = cpu_tmp4,
924 .reg2 = t0, .mask = -1, .use_reg2 = true };
c365395e 925 break;
8e1c85e3 926
c365395e 927 default:
8e1c85e3 928 goto slow_jcc;
c365395e 929 }
8e1c85e3 930 break;
c365395e 931
8e1c85e3
FB
932 default:
933 slow_jcc:
69d1aa31
RH
934 /* This actually generates good code for JC, JZ and JS. */
935 switch (jcc_op) {
936 case JCC_O:
937 cc = gen_prepare_eflags_o(s, reg);
938 break;
939 case JCC_B:
940 cc = gen_prepare_eflags_c(s, reg);
941 break;
942 case JCC_Z:
943 cc = gen_prepare_eflags_z(s, reg);
944 break;
945 case JCC_BE:
946 gen_compute_eflags(s);
947 cc = (CCPrepare) { .cond = TCG_COND_NE, .reg = cpu_cc_src,
948 .mask = CC_Z | CC_C };
949 break;
950 case JCC_S:
951 cc = gen_prepare_eflags_s(s, reg);
952 break;
953 case JCC_P:
954 cc = gen_prepare_eflags_p(s, reg);
955 break;
956 case JCC_L:
957 gen_compute_eflags(s);
11f4e8f8 958 if (reg == cpu_cc_src) {
69d1aa31
RH
959 reg = cpu_tmp0;
960 }
961 tcg_gen_shri_tl(reg, cpu_cc_src, 4); /* CC_O -> CC_S */
962 tcg_gen_xor_tl(reg, reg, cpu_cc_src);
963 cc = (CCPrepare) { .cond = TCG_COND_NE, .reg = reg,
964 .mask = CC_S };
965 break;
966 default:
967 case JCC_LE:
968 gen_compute_eflags(s);
11f4e8f8 969 if (reg == cpu_cc_src) {
69d1aa31
RH
970 reg = cpu_tmp0;
971 }
972 tcg_gen_shri_tl(reg, cpu_cc_src, 4); /* CC_O -> CC_S */
973 tcg_gen_xor_tl(reg, reg, cpu_cc_src);
974 cc = (CCPrepare) { .cond = TCG_COND_NE, .reg = reg,
975 .mask = CC_S | CC_Z };
976 break;
977 }
c365395e 978 break;
8e1c85e3 979 }
276e6b5f
RH
980
981 if (inv) {
982 cc.cond = tcg_invert_cond(cc.cond);
983 }
984 return cc;
8e1c85e3
FB
985}
986
cc8b6f5b
PB
987static void gen_setcc1(DisasContext *s, int b, TCGv reg)
988{
989 CCPrepare cc = gen_prepare_cc(s, b, reg);
990
991 if (cc.no_setcond) {
992 if (cc.cond == TCG_COND_EQ) {
993 tcg_gen_xori_tl(reg, cc.reg, 1);
994 } else {
995 tcg_gen_mov_tl(reg, cc.reg);
996 }
997 return;
998 }
999
1000 if (cc.cond == TCG_COND_NE && !cc.use_reg2 && cc.imm == 0 &&
1001 cc.mask != 0 && (cc.mask & (cc.mask - 1)) == 0) {
1002 tcg_gen_shri_tl(reg, cc.reg, ctztl(cc.mask));
1003 tcg_gen_andi_tl(reg, reg, 1);
1004 return;
1005 }
1006 if (cc.mask != -1) {
1007 tcg_gen_andi_tl(reg, cc.reg, cc.mask);
1008 cc.reg = reg;
1009 }
1010 if (cc.use_reg2) {
1011 tcg_gen_setcond_tl(cc.cond, reg, cc.reg, cc.reg2);
1012 } else {
1013 tcg_gen_setcondi_tl(cc.cond, reg, cc.reg, cc.imm);
1014 }
1015}
1016
1017static inline void gen_compute_eflags_c(DisasContext *s, TCGv reg)
1018{
1019 gen_setcc1(s, JCC_B << 1, reg);
1020}
276e6b5f 1021
8e1c85e3
FB
1022/* generate a conditional jump to label 'l1' according to jump opcode
1023 value 'b'. In the fast case, T0 is guaranted not to be used. */
42a268c2 1024static inline void gen_jcc1_noeob(DisasContext *s, int b, TCGLabel *l1)
dc259201 1025{
c66f9727 1026 CCPrepare cc = gen_prepare_cc(s, b, s->T0);
dc259201
RH
1027
1028 if (cc.mask != -1) {
c66f9727
EC
1029 tcg_gen_andi_tl(s->T0, cc.reg, cc.mask);
1030 cc.reg = s->T0;
dc259201
RH
1031 }
1032 if (cc.use_reg2) {
1033 tcg_gen_brcond_tl(cc.cond, cc.reg, cc.reg2, l1);
1034 } else {
1035 tcg_gen_brcondi_tl(cc.cond, cc.reg, cc.imm, l1);
1036 }
1037}
1038
1039/* Generate a conditional jump to label 'l1' according to jump opcode
1040 value 'b'. In the fast case, T0 is guaranted not to be used.
1041 A translation block must end soon. */
42a268c2 1042static inline void gen_jcc1(DisasContext *s, int b, TCGLabel *l1)
8e1c85e3 1043{
c66f9727 1044 CCPrepare cc = gen_prepare_cc(s, b, s->T0);
8e1c85e3 1045
dc259201 1046 gen_update_cc_op(s);
943131ca 1047 if (cc.mask != -1) {
c66f9727
EC
1048 tcg_gen_andi_tl(s->T0, cc.reg, cc.mask);
1049 cc.reg = s->T0;
943131ca 1050 }
dc259201 1051 set_cc_op(s, CC_OP_DYNAMIC);
943131ca
PB
1052 if (cc.use_reg2) {
1053 tcg_gen_brcond_tl(cc.cond, cc.reg, cc.reg2, l1);
1054 } else {
1055 tcg_gen_brcondi_tl(cc.cond, cc.reg, cc.imm, l1);
8e1c85e3
FB
1056 }
1057}
1058
14ce26e7
FB
1059/* XXX: does not work with gdbstub "ice" single step - not a
1060 serious problem */
42a268c2 1061static TCGLabel *gen_jz_ecx_string(DisasContext *s, target_ulong next_eip)
2c0262af 1062{
42a268c2
RH
1063 TCGLabel *l1 = gen_new_label();
1064 TCGLabel *l2 = gen_new_label();
1d71ddb1 1065 gen_op_jnz_ecx(s->aflag, l1);
14ce26e7
FB
1066 gen_set_label(l2);
1067 gen_jmp_tb(s, next_eip, 1);
1068 gen_set_label(l1);
1069 return l2;
2c0262af
FB
1070}
1071
d67dc9e6 1072static inline void gen_stos(DisasContext *s, TCGMemOp ot)
2c0262af 1073{
c66f9727 1074 gen_op_mov_v_reg(MO_32, s->T0, R_EAX);
2c0262af 1075 gen_string_movl_A0_EDI(s);
c66f9727
EC
1076 gen_op_st_v(s, ot, s->T0, s->A0);
1077 gen_op_movl_T0_Dshift(s, ot);
1078 gen_op_add_reg_T0(s, s->aflag, R_EDI);
2c0262af
FB
1079}
1080
d67dc9e6 1081static inline void gen_lods(DisasContext *s, TCGMemOp ot)
2c0262af
FB
1082{
1083 gen_string_movl_A0_ESI(s);
c66f9727
EC
1084 gen_op_ld_v(s, ot, s->T0, s->A0);
1085 gen_op_mov_reg_v(ot, R_EAX, s->T0);
1086 gen_op_movl_T0_Dshift(s, ot);
1087 gen_op_add_reg_T0(s, s->aflag, R_ESI);
2c0262af
FB
1088}
1089
d67dc9e6 1090static inline void gen_scas(DisasContext *s, TCGMemOp ot)
2c0262af 1091{
2c0262af 1092 gen_string_movl_A0_EDI(s);
6b672b5d 1093 gen_op_ld_v(s, ot, cpu_T1, s->A0);
63633fe6 1094 gen_op(s, OP_CMPL, ot, R_EAX);
c66f9727
EC
1095 gen_op_movl_T0_Dshift(s, ot);
1096 gen_op_add_reg_T0(s, s->aflag, R_EDI);
2c0262af
FB
1097}
1098
d67dc9e6 1099static inline void gen_cmps(DisasContext *s, TCGMemOp ot)
2c0262af 1100{
2c0262af 1101 gen_string_movl_A0_EDI(s);
6b672b5d 1102 gen_op_ld_v(s, ot, cpu_T1, s->A0);
63633fe6
RH
1103 gen_string_movl_A0_ESI(s);
1104 gen_op(s, OP_CMPL, ot, OR_TMP0);
c66f9727
EC
1105 gen_op_movl_T0_Dshift(s, ot);
1106 gen_op_add_reg_T0(s, s->aflag, R_ESI);
1107 gen_op_add_reg_T0(s, s->aflag, R_EDI);
2c0262af
FB
1108}
1109
5223a942
EH
1110static void gen_bpt_io(DisasContext *s, TCGv_i32 t_port, int ot)
1111{
1112 if (s->flags & HF_IOBPT_MASK) {
1113 TCGv_i32 t_size = tcg_const_i32(1 << ot);
1114 TCGv t_next = tcg_const_tl(s->pc - s->cs_base);
1115
1116 gen_helper_bpt_io(cpu_env, t_port, t_size, t_next);
1117 tcg_temp_free_i32(t_size);
1118 tcg_temp_free(t_next);
1119 }
1120}
1121
1122
d67dc9e6 1123static inline void gen_ins(DisasContext *s, TCGMemOp ot)
2c0262af 1124{
c5a49c63 1125 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 1126 gen_io_start();
bd79255d 1127 }
2c0262af 1128 gen_string_movl_A0_EDI(s);
6e0d8677
FB
1129 /* Note: we must do this dummy write first to be restartable in
1130 case of page fault. */
c66f9727
EC
1131 tcg_gen_movi_tl(s->T0, 0);
1132 gen_op_st_v(s, ot, s->T0, s->A0);
24b9c00f 1133 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[R_EDX]);
b6abf97d 1134 tcg_gen_andi_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0xffff);
c66f9727
EC
1135 gen_helper_in_func(ot, s->T0, cpu_tmp2_i32);
1136 gen_op_st_v(s, ot, s->T0, s->A0);
1137 gen_op_movl_T0_Dshift(s, ot);
1138 gen_op_add_reg_T0(s, s->aflag, R_EDI);
5223a942 1139 gen_bpt_io(s, cpu_tmp2_i32, ot);
c5a49c63 1140 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 1141 gen_io_end();
bd79255d 1142 }
2c0262af
FB
1143}
1144
d67dc9e6 1145static inline void gen_outs(DisasContext *s, TCGMemOp ot)
2c0262af 1146{
c5a49c63 1147 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 1148 gen_io_start();
bd79255d 1149 }
2c0262af 1150 gen_string_movl_A0_ESI(s);
c66f9727 1151 gen_op_ld_v(s, ot, s->T0, s->A0);
b8b6a50b 1152
24b9c00f 1153 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[R_EDX]);
b6abf97d 1154 tcg_gen_andi_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0xffff);
c66f9727 1155 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, s->T0);
a7812ae4 1156 gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32);
c66f9727
EC
1157 gen_op_movl_T0_Dshift(s, ot);
1158 gen_op_add_reg_T0(s, s->aflag, R_ESI);
5223a942 1159 gen_bpt_io(s, cpu_tmp2_i32, ot);
c5a49c63 1160 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 1161 gen_io_end();
bd79255d 1162 }
2c0262af
FB
1163}
1164
1165/* same method as Valgrind : we generate jumps to current or next
1166 instruction */
1167#define GEN_REPZ(op) \
d67dc9e6 1168static inline void gen_repz_ ## op(DisasContext *s, TCGMemOp ot, \
14ce26e7 1169 target_ulong cur_eip, target_ulong next_eip) \
2c0262af 1170{ \
42a268c2 1171 TCGLabel *l2; \
2c0262af 1172 gen_update_cc_op(s); \
14ce26e7 1173 l2 = gen_jz_ecx_string(s, next_eip); \
2c0262af 1174 gen_ ## op(s, ot); \
1d71ddb1 1175 gen_op_add_reg_im(s->aflag, R_ECX, -1); \
2c0262af
FB
1176 /* a loop would cause two single step exceptions if ECX = 1 \
1177 before rep string_insn */ \
c4d4525c 1178 if (s->repz_opt) \
1d71ddb1 1179 gen_op_jz_ecx(s->aflag, l2); \
2c0262af
FB
1180 gen_jmp(s, cur_eip); \
1181}
1182
1183#define GEN_REPZ2(op) \
d67dc9e6 1184static inline void gen_repz_ ## op(DisasContext *s, TCGMemOp ot, \
14ce26e7
FB
1185 target_ulong cur_eip, \
1186 target_ulong next_eip, \
2c0262af
FB
1187 int nz) \
1188{ \
42a268c2 1189 TCGLabel *l2; \
2c0262af 1190 gen_update_cc_op(s); \
14ce26e7 1191 l2 = gen_jz_ecx_string(s, next_eip); \
2c0262af 1192 gen_ ## op(s, ot); \
1d71ddb1 1193 gen_op_add_reg_im(s->aflag, R_ECX, -1); \
773cdfcc 1194 gen_update_cc_op(s); \
b27fc131 1195 gen_jcc1(s, (JCC_Z << 1) | (nz ^ 1), l2); \
c4d4525c 1196 if (s->repz_opt) \
1d71ddb1 1197 gen_op_jz_ecx(s->aflag, l2); \
2c0262af
FB
1198 gen_jmp(s, cur_eip); \
1199}
1200
1201GEN_REPZ(movs)
1202GEN_REPZ(stos)
1203GEN_REPZ(lods)
1204GEN_REPZ(ins)
1205GEN_REPZ(outs)
1206GEN_REPZ2(scas)
1207GEN_REPZ2(cmps)
1208
a7812ae4
PB
1209static void gen_helper_fp_arith_ST0_FT0(int op)
1210{
1211 switch (op) {
d3eb5eae
BS
1212 case 0:
1213 gen_helper_fadd_ST0_FT0(cpu_env);
1214 break;
1215 case 1:
1216 gen_helper_fmul_ST0_FT0(cpu_env);
1217 break;
1218 case 2:
1219 gen_helper_fcom_ST0_FT0(cpu_env);
1220 break;
1221 case 3:
1222 gen_helper_fcom_ST0_FT0(cpu_env);
1223 break;
1224 case 4:
1225 gen_helper_fsub_ST0_FT0(cpu_env);
1226 break;
1227 case 5:
1228 gen_helper_fsubr_ST0_FT0(cpu_env);
1229 break;
1230 case 6:
1231 gen_helper_fdiv_ST0_FT0(cpu_env);
1232 break;
1233 case 7:
1234 gen_helper_fdivr_ST0_FT0(cpu_env);
1235 break;
a7812ae4
PB
1236 }
1237}
2c0262af
FB
1238
1239/* NOTE the exception in "r" op ordering */
a7812ae4
PB
1240static void gen_helper_fp_arith_STN_ST0(int op, int opreg)
1241{
1242 TCGv_i32 tmp = tcg_const_i32(opreg);
1243 switch (op) {
d3eb5eae
BS
1244 case 0:
1245 gen_helper_fadd_STN_ST0(cpu_env, tmp);
1246 break;
1247 case 1:
1248 gen_helper_fmul_STN_ST0(cpu_env, tmp);
1249 break;
1250 case 4:
1251 gen_helper_fsubr_STN_ST0(cpu_env, tmp);
1252 break;
1253 case 5:
1254 gen_helper_fsub_STN_ST0(cpu_env, tmp);
1255 break;
1256 case 6:
1257 gen_helper_fdivr_STN_ST0(cpu_env, tmp);
1258 break;
1259 case 7:
1260 gen_helper_fdiv_STN_ST0(cpu_env, tmp);
1261 break;
a7812ae4
PB
1262 }
1263}
2c0262af
FB
1264
1265/* if d == OR_TMP0, it means memory operand (address in A0) */
d67dc9e6 1266static void gen_op(DisasContext *s1, int op, TCGMemOp ot, int d)
2c0262af 1267{
2c0262af 1268 if (d != OR_TMP0) {
c66f9727 1269 gen_op_mov_v_reg(ot, s1->T0, d);
a7cee522 1270 } else if (!(s1->prefix & PREFIX_LOCK)) {
c66f9727 1271 gen_op_ld_v(s1, ot, s1->T0, s1->A0);
2c0262af
FB
1272 }
1273 switch(op) {
1274 case OP_ADCL:
cc8b6f5b 1275 gen_compute_eflags_c(s1, cpu_tmp4);
a7cee522 1276 if (s1->prefix & PREFIX_LOCK) {
c66f9727
EC
1277 tcg_gen_add_tl(s1->T0, cpu_tmp4, cpu_T1);
1278 tcg_gen_atomic_add_fetch_tl(s1->T0, s1->A0, s1->T0,
a7cee522
EC
1279 s1->mem_index, ot | MO_LE);
1280 } else {
c66f9727
EC
1281 tcg_gen_add_tl(s1->T0, s1->T0, cpu_T1);
1282 tcg_gen_add_tl(s1->T0, s1->T0, cpu_tmp4);
a7cee522
EC
1283 gen_op_st_rm_T0_A0(s1, ot, d);
1284 }
c66f9727 1285 gen_op_update3_cc(s1, cpu_tmp4);
988c3eb0 1286 set_cc_op(s1, CC_OP_ADCB + ot);
cad3a37d 1287 break;
2c0262af 1288 case OP_SBBL:
cc8b6f5b 1289 gen_compute_eflags_c(s1, cpu_tmp4);
a7cee522 1290 if (s1->prefix & PREFIX_LOCK) {
c66f9727
EC
1291 tcg_gen_add_tl(s1->T0, cpu_T1, cpu_tmp4);
1292 tcg_gen_neg_tl(s1->T0, s1->T0);
1293 tcg_gen_atomic_add_fetch_tl(s1->T0, s1->A0, s1->T0,
a7cee522
EC
1294 s1->mem_index, ot | MO_LE);
1295 } else {
c66f9727
EC
1296 tcg_gen_sub_tl(s1->T0, s1->T0, cpu_T1);
1297 tcg_gen_sub_tl(s1->T0, s1->T0, cpu_tmp4);
a7cee522
EC
1298 gen_op_st_rm_T0_A0(s1, ot, d);
1299 }
c66f9727 1300 gen_op_update3_cc(s1, cpu_tmp4);
988c3eb0 1301 set_cc_op(s1, CC_OP_SBBB + ot);
cad3a37d 1302 break;
2c0262af 1303 case OP_ADDL:
a7cee522 1304 if (s1->prefix & PREFIX_LOCK) {
c66f9727 1305 tcg_gen_atomic_add_fetch_tl(s1->T0, s1->A0, cpu_T1,
a7cee522
EC
1306 s1->mem_index, ot | MO_LE);
1307 } else {
c66f9727 1308 tcg_gen_add_tl(s1->T0, s1->T0, cpu_T1);
a7cee522
EC
1309 gen_op_st_rm_T0_A0(s1, ot, d);
1310 }
c66f9727 1311 gen_op_update2_cc(s1);
3ca51d07 1312 set_cc_op(s1, CC_OP_ADDB + ot);
2c0262af
FB
1313 break;
1314 case OP_SUBL:
a7cee522 1315 if (s1->prefix & PREFIX_LOCK) {
c66f9727
EC
1316 tcg_gen_neg_tl(s1->T0, cpu_T1);
1317 tcg_gen_atomic_fetch_add_tl(s1->cc_srcT, s1->A0, s1->T0,
a7cee522 1318 s1->mem_index, ot | MO_LE);
c66f9727 1319 tcg_gen_sub_tl(s1->T0, s1->cc_srcT, cpu_T1);
a7cee522 1320 } else {
c66f9727
EC
1321 tcg_gen_mov_tl(s1->cc_srcT, s1->T0);
1322 tcg_gen_sub_tl(s1->T0, s1->T0, cpu_T1);
a7cee522
EC
1323 gen_op_st_rm_T0_A0(s1, ot, d);
1324 }
c66f9727 1325 gen_op_update2_cc(s1);
3ca51d07 1326 set_cc_op(s1, CC_OP_SUBB + ot);
2c0262af
FB
1327 break;
1328 default:
1329 case OP_ANDL:
a7cee522 1330 if (s1->prefix & PREFIX_LOCK) {
c66f9727 1331 tcg_gen_atomic_and_fetch_tl(s1->T0, s1->A0, cpu_T1,
a7cee522
EC
1332 s1->mem_index, ot | MO_LE);
1333 } else {
c66f9727 1334 tcg_gen_and_tl(s1->T0, s1->T0, cpu_T1);
a7cee522
EC
1335 gen_op_st_rm_T0_A0(s1, ot, d);
1336 }
c66f9727 1337 gen_op_update1_cc(s1);
3ca51d07 1338 set_cc_op(s1, CC_OP_LOGICB + ot);
57fec1fe 1339 break;
2c0262af 1340 case OP_ORL:
a7cee522 1341 if (s1->prefix & PREFIX_LOCK) {
c66f9727 1342 tcg_gen_atomic_or_fetch_tl(s1->T0, s1->A0, cpu_T1,
a7cee522
EC
1343 s1->mem_index, ot | MO_LE);
1344 } else {
c66f9727 1345 tcg_gen_or_tl(s1->T0, s1->T0, cpu_T1);
a7cee522
EC
1346 gen_op_st_rm_T0_A0(s1, ot, d);
1347 }
c66f9727 1348 gen_op_update1_cc(s1);
3ca51d07 1349 set_cc_op(s1, CC_OP_LOGICB + ot);
57fec1fe 1350 break;
2c0262af 1351 case OP_XORL:
a7cee522 1352 if (s1->prefix & PREFIX_LOCK) {
c66f9727 1353 tcg_gen_atomic_xor_fetch_tl(s1->T0, s1->A0, cpu_T1,
a7cee522
EC
1354 s1->mem_index, ot | MO_LE);
1355 } else {
c66f9727 1356 tcg_gen_xor_tl(s1->T0, s1->T0, cpu_T1);
a7cee522
EC
1357 gen_op_st_rm_T0_A0(s1, ot, d);
1358 }
c66f9727 1359 gen_op_update1_cc(s1);
3ca51d07 1360 set_cc_op(s1, CC_OP_LOGICB + ot);
2c0262af
FB
1361 break;
1362 case OP_CMPL:
1d1cc4d0 1363 tcg_gen_mov_tl(cpu_cc_src, cpu_T1);
c66f9727
EC
1364 tcg_gen_mov_tl(s1->cc_srcT, s1->T0);
1365 tcg_gen_sub_tl(cpu_cc_dst, s1->T0, cpu_T1);
3ca51d07 1366 set_cc_op(s1, CC_OP_SUBB + ot);
2c0262af
FB
1367 break;
1368 }
b6abf97d
FB
1369}
1370
2c0262af 1371/* if d == OR_TMP0, it means memory operand (address in A0) */
d67dc9e6 1372static void gen_inc(DisasContext *s1, TCGMemOp ot, int d, int c)
2c0262af 1373{
60e57346 1374 if (s1->prefix & PREFIX_LOCK) {
c66f9727
EC
1375 tcg_gen_movi_tl(s1->T0, c > 0 ? 1 : -1);
1376 tcg_gen_atomic_add_fetch_tl(s1->T0, s1->A0, s1->T0,
60e57346 1377 s1->mem_index, ot | MO_LE);
909be183 1378 } else {
60e57346 1379 if (d != OR_TMP0) {
c66f9727 1380 gen_op_mov_v_reg(ot, s1->T0, d);
60e57346 1381 } else {
c66f9727 1382 gen_op_ld_v(s1, ot, s1->T0, s1->A0);
60e57346 1383 }
c66f9727 1384 tcg_gen_addi_tl(s1->T0, s1->T0, (c > 0 ? 1 : -1));
60e57346 1385 gen_op_st_rm_T0_A0(s1, ot, d);
909be183 1386 }
60e57346 1387
cc8b6f5b 1388 gen_compute_eflags_c(s1, cpu_cc_src);
c66f9727 1389 tcg_gen_mov_tl(cpu_cc_dst, s1->T0);
60e57346 1390 set_cc_op(s1, (c > 0 ? CC_OP_INCB : CC_OP_DECB) + ot);
2c0262af
FB
1391}
1392
d67dc9e6
RH
1393static void gen_shift_flags(DisasContext *s, TCGMemOp ot, TCGv result,
1394 TCGv shm1, TCGv count, bool is_right)
f437d0a3
RH
1395{
1396 TCGv_i32 z32, s32, oldop;
1397 TCGv z_tl;
1398
1399 /* Store the results into the CC variables. If we know that the
1400 variable must be dead, store unconditionally. Otherwise we'll
1401 need to not disrupt the current contents. */
1402 z_tl = tcg_const_tl(0);
1403 if (cc_op_live[s->cc_op] & USES_CC_DST) {
1404 tcg_gen_movcond_tl(TCG_COND_NE, cpu_cc_dst, count, z_tl,
1405 result, cpu_cc_dst);
1406 } else {
1407 tcg_gen_mov_tl(cpu_cc_dst, result);
1408 }
1409 if (cc_op_live[s->cc_op] & USES_CC_SRC) {
1410 tcg_gen_movcond_tl(TCG_COND_NE, cpu_cc_src, count, z_tl,
1411 shm1, cpu_cc_src);
1412 } else {
1413 tcg_gen_mov_tl(cpu_cc_src, shm1);
1414 }
1415 tcg_temp_free(z_tl);
1416
1417 /* Get the two potential CC_OP values into temporaries. */
1418 tcg_gen_movi_i32(cpu_tmp2_i32, (is_right ? CC_OP_SARB : CC_OP_SHLB) + ot);
1419 if (s->cc_op == CC_OP_DYNAMIC) {
1420 oldop = cpu_cc_op;
1421 } else {
1422 tcg_gen_movi_i32(cpu_tmp3_i32, s->cc_op);
1423 oldop = cpu_tmp3_i32;
1424 }
1425
1426 /* Conditionally store the CC_OP value. */
1427 z32 = tcg_const_i32(0);
1428 s32 = tcg_temp_new_i32();
1429 tcg_gen_trunc_tl_i32(s32, count);
1430 tcg_gen_movcond_i32(TCG_COND_NE, cpu_cc_op, s32, z32, cpu_tmp2_i32, oldop);
1431 tcg_temp_free_i32(z32);
1432 tcg_temp_free_i32(s32);
1433
1434 /* The CC_OP value is no longer predictable. */
1435 set_cc_op(s, CC_OP_DYNAMIC);
1436}
1437
d67dc9e6 1438static void gen_shift_rm_T1(DisasContext *s, TCGMemOp ot, int op1,
b6abf97d 1439 int is_right, int is_arith)
2c0262af 1440{
4ba9938c 1441 target_ulong mask = (ot == MO_64 ? 0x3f : 0x1f);
3b46e624 1442
b6abf97d 1443 /* load */
82786041 1444 if (op1 == OR_TMP0) {
c66f9727 1445 gen_op_ld_v(s, ot, s->T0, s->A0);
82786041 1446 } else {
c66f9727 1447 gen_op_mov_v_reg(ot, s->T0, op1);
82786041 1448 }
b6abf97d 1449
1d1cc4d0
RH
1450 tcg_gen_andi_tl(cpu_T1, cpu_T1, mask);
1451 tcg_gen_subi_tl(cpu_tmp0, cpu_T1, 1);
b6abf97d
FB
1452
1453 if (is_right) {
1454 if (is_arith) {
c66f9727
EC
1455 gen_exts(ot, s->T0);
1456 tcg_gen_sar_tl(cpu_tmp0, s->T0, cpu_tmp0);
1457 tcg_gen_sar_tl(s->T0, s->T0, cpu_T1);
b6abf97d 1458 } else {
c66f9727
EC
1459 gen_extu(ot, s->T0);
1460 tcg_gen_shr_tl(cpu_tmp0, s->T0, cpu_tmp0);
1461 tcg_gen_shr_tl(s->T0, s->T0, cpu_T1);
b6abf97d
FB
1462 }
1463 } else {
c66f9727
EC
1464 tcg_gen_shl_tl(cpu_tmp0, s->T0, cpu_tmp0);
1465 tcg_gen_shl_tl(s->T0, s->T0, cpu_T1);
b6abf97d
FB
1466 }
1467
1468 /* store */
d4faa3e0 1469 gen_op_st_rm_T0_A0(s, ot, op1);
82786041 1470
c66f9727 1471 gen_shift_flags(s, ot, s->T0, cpu_tmp0, cpu_T1, is_right);
b6abf97d
FB
1472}
1473
d67dc9e6 1474static void gen_shift_rm_im(DisasContext *s, TCGMemOp ot, int op1, int op2,
c1c37968
FB
1475 int is_right, int is_arith)
1476{
4ba9938c 1477 int mask = (ot == MO_64 ? 0x3f : 0x1f);
c1c37968
FB
1478
1479 /* load */
1480 if (op1 == OR_TMP0)
c66f9727 1481 gen_op_ld_v(s, ot, s->T0, s->A0);
c1c37968 1482 else
c66f9727 1483 gen_op_mov_v_reg(ot, s->T0, op1);
c1c37968
FB
1484
1485 op2 &= mask;
1486 if (op2 != 0) {
1487 if (is_right) {
1488 if (is_arith) {
c66f9727
EC
1489 gen_exts(ot, s->T0);
1490 tcg_gen_sari_tl(cpu_tmp4, s->T0, op2 - 1);
1491 tcg_gen_sari_tl(s->T0, s->T0, op2);
c1c37968 1492 } else {
c66f9727
EC
1493 gen_extu(ot, s->T0);
1494 tcg_gen_shri_tl(cpu_tmp4, s->T0, op2 - 1);
1495 tcg_gen_shri_tl(s->T0, s->T0, op2);
c1c37968
FB
1496 }
1497 } else {
c66f9727
EC
1498 tcg_gen_shli_tl(cpu_tmp4, s->T0, op2 - 1);
1499 tcg_gen_shli_tl(s->T0, s->T0, op2);
c1c37968
FB
1500 }
1501 }
1502
1503 /* store */
d4faa3e0
RH
1504 gen_op_st_rm_T0_A0(s, ot, op1);
1505
c1c37968
FB
1506 /* update eflags if non zero shift */
1507 if (op2 != 0) {
2a449d14 1508 tcg_gen_mov_tl(cpu_cc_src, cpu_tmp4);
c66f9727 1509 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
3ca51d07 1510 set_cc_op(s, (is_right ? CC_OP_SARB : CC_OP_SHLB) + ot);
c1c37968
FB
1511 }
1512}
1513
d67dc9e6 1514static void gen_rot_rm_T1(DisasContext *s, TCGMemOp ot, int op1, int is_right)
b6abf97d 1515{
4ba9938c 1516 target_ulong mask = (ot == MO_64 ? 0x3f : 0x1f);
34d80a55 1517 TCGv_i32 t0, t1;
b6abf97d
FB
1518
1519 /* load */
1e4840bf 1520 if (op1 == OR_TMP0) {
c66f9727 1521 gen_op_ld_v(s, ot, s->T0, s->A0);
1e4840bf 1522 } else {
c66f9727 1523 gen_op_mov_v_reg(ot, s->T0, op1);
1e4840bf 1524 }
b6abf97d 1525
1d1cc4d0 1526 tcg_gen_andi_tl(cpu_T1, cpu_T1, mask);
b6abf97d 1527
34d80a55 1528 switch (ot) {
4ba9938c 1529 case MO_8:
34d80a55 1530 /* Replicate the 8-bit input so that a 32-bit rotate works. */
c66f9727
EC
1531 tcg_gen_ext8u_tl(s->T0, s->T0);
1532 tcg_gen_muli_tl(s->T0, s->T0, 0x01010101);
34d80a55 1533 goto do_long;
4ba9938c 1534 case MO_16:
34d80a55 1535 /* Replicate the 16-bit input so that a 32-bit rotate works. */
c66f9727 1536 tcg_gen_deposit_tl(s->T0, s->T0, s->T0, 16, 16);
34d80a55
RH
1537 goto do_long;
1538 do_long:
1539#ifdef TARGET_X86_64
4ba9938c 1540 case MO_32:
c66f9727 1541 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, s->T0);
1d1cc4d0 1542 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T1);
34d80a55
RH
1543 if (is_right) {
1544 tcg_gen_rotr_i32(cpu_tmp2_i32, cpu_tmp2_i32, cpu_tmp3_i32);
1545 } else {
1546 tcg_gen_rotl_i32(cpu_tmp2_i32, cpu_tmp2_i32, cpu_tmp3_i32);
1547 }
c66f9727 1548 tcg_gen_extu_i32_tl(s->T0, cpu_tmp2_i32);
34d80a55
RH
1549 break;
1550#endif
1551 default:
1552 if (is_right) {
c66f9727 1553 tcg_gen_rotr_tl(s->T0, s->T0, cpu_T1);
34d80a55 1554 } else {
c66f9727 1555 tcg_gen_rotl_tl(s->T0, s->T0, cpu_T1);
34d80a55
RH
1556 }
1557 break;
b6abf97d 1558 }
b6abf97d 1559
b6abf97d 1560 /* store */
d4faa3e0 1561 gen_op_st_rm_T0_A0(s, ot, op1);
b6abf97d 1562
34d80a55
RH
1563 /* We'll need the flags computed into CC_SRC. */
1564 gen_compute_eflags(s);
b6abf97d 1565
34d80a55
RH
1566 /* The value that was "rotated out" is now present at the other end
1567 of the word. Compute C into CC_DST and O into CC_SRC2. Note that
1568 since we've computed the flags into CC_SRC, these variables are
1569 currently dead. */
b6abf97d 1570 if (is_right) {
c66f9727
EC
1571 tcg_gen_shri_tl(cpu_cc_src2, s->T0, mask - 1);
1572 tcg_gen_shri_tl(cpu_cc_dst, s->T0, mask);
089305ac 1573 tcg_gen_andi_tl(cpu_cc_dst, cpu_cc_dst, 1);
34d80a55 1574 } else {
c66f9727
EC
1575 tcg_gen_shri_tl(cpu_cc_src2, s->T0, mask);
1576 tcg_gen_andi_tl(cpu_cc_dst, s->T0, 1);
b6abf97d 1577 }
34d80a55
RH
1578 tcg_gen_andi_tl(cpu_cc_src2, cpu_cc_src2, 1);
1579 tcg_gen_xor_tl(cpu_cc_src2, cpu_cc_src2, cpu_cc_dst);
1580
1581 /* Now conditionally store the new CC_OP value. If the shift count
1582 is 0 we keep the CC_OP_EFLAGS setting so that only CC_SRC is live.
1583 Otherwise reuse CC_OP_ADCOX which have the C and O flags split out
1584 exactly as we computed above. */
1585 t0 = tcg_const_i32(0);
1586 t1 = tcg_temp_new_i32();
1d1cc4d0 1587 tcg_gen_trunc_tl_i32(t1, cpu_T1);
34d80a55
RH
1588 tcg_gen_movi_i32(cpu_tmp2_i32, CC_OP_ADCOX);
1589 tcg_gen_movi_i32(cpu_tmp3_i32, CC_OP_EFLAGS);
1590 tcg_gen_movcond_i32(TCG_COND_NE, cpu_cc_op, t1, t0,
1591 cpu_tmp2_i32, cpu_tmp3_i32);
1592 tcg_temp_free_i32(t0);
1593 tcg_temp_free_i32(t1);
1594
1595 /* The CC_OP value is no longer predictable. */
1596 set_cc_op(s, CC_OP_DYNAMIC);
b6abf97d
FB
1597}
1598
d67dc9e6 1599static void gen_rot_rm_im(DisasContext *s, TCGMemOp ot, int op1, int op2,
8cd6345d 1600 int is_right)
1601{
4ba9938c 1602 int mask = (ot == MO_64 ? 0x3f : 0x1f);
34d80a55 1603 int shift;
8cd6345d 1604
1605 /* load */
1606 if (op1 == OR_TMP0) {
c66f9727 1607 gen_op_ld_v(s, ot, s->T0, s->A0);
8cd6345d 1608 } else {
c66f9727 1609 gen_op_mov_v_reg(ot, s->T0, op1);
8cd6345d 1610 }
1611
8cd6345d 1612 op2 &= mask;
8cd6345d 1613 if (op2 != 0) {
34d80a55
RH
1614 switch (ot) {
1615#ifdef TARGET_X86_64
4ba9938c 1616 case MO_32:
c66f9727 1617 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, s->T0);
34d80a55
RH
1618 if (is_right) {
1619 tcg_gen_rotri_i32(cpu_tmp2_i32, cpu_tmp2_i32, op2);
1620 } else {
1621 tcg_gen_rotli_i32(cpu_tmp2_i32, cpu_tmp2_i32, op2);
1622 }
c66f9727 1623 tcg_gen_extu_i32_tl(s->T0, cpu_tmp2_i32);
34d80a55
RH
1624 break;
1625#endif
1626 default:
1627 if (is_right) {
c66f9727 1628 tcg_gen_rotri_tl(s->T0, s->T0, op2);
34d80a55 1629 } else {
c66f9727 1630 tcg_gen_rotli_tl(s->T0, s->T0, op2);
34d80a55
RH
1631 }
1632 break;
4ba9938c 1633 case MO_8:
34d80a55
RH
1634 mask = 7;
1635 goto do_shifts;
4ba9938c 1636 case MO_16:
34d80a55
RH
1637 mask = 15;
1638 do_shifts:
1639 shift = op2 & mask;
1640 if (is_right) {
1641 shift = mask + 1 - shift;
1642 }
c66f9727
EC
1643 gen_extu(ot, s->T0);
1644 tcg_gen_shli_tl(cpu_tmp0, s->T0, shift);
1645 tcg_gen_shri_tl(s->T0, s->T0, mask + 1 - shift);
1646 tcg_gen_or_tl(s->T0, s->T0, cpu_tmp0);
34d80a55 1647 break;
8cd6345d 1648 }
8cd6345d 1649 }
1650
1651 /* store */
d4faa3e0 1652 gen_op_st_rm_T0_A0(s, ot, op1);
8cd6345d 1653
1654 if (op2 != 0) {
34d80a55 1655 /* Compute the flags into CC_SRC. */
d229edce 1656 gen_compute_eflags(s);
0ff6addd 1657
34d80a55
RH
1658 /* The value that was "rotated out" is now present at the other end
1659 of the word. Compute C into CC_DST and O into CC_SRC2. Note that
1660 since we've computed the flags into CC_SRC, these variables are
1661 currently dead. */
8cd6345d 1662 if (is_right) {
c66f9727
EC
1663 tcg_gen_shri_tl(cpu_cc_src2, s->T0, mask - 1);
1664 tcg_gen_shri_tl(cpu_cc_dst, s->T0, mask);
38ebb396 1665 tcg_gen_andi_tl(cpu_cc_dst, cpu_cc_dst, 1);
34d80a55 1666 } else {
c66f9727
EC
1667 tcg_gen_shri_tl(cpu_cc_src2, s->T0, mask);
1668 tcg_gen_andi_tl(cpu_cc_dst, s->T0, 1);
8cd6345d 1669 }
34d80a55
RH
1670 tcg_gen_andi_tl(cpu_cc_src2, cpu_cc_src2, 1);
1671 tcg_gen_xor_tl(cpu_cc_src2, cpu_cc_src2, cpu_cc_dst);
1672 set_cc_op(s, CC_OP_ADCOX);
8cd6345d 1673 }
8cd6345d 1674}
1675
b6abf97d 1676/* XXX: add faster immediate = 1 case */
d67dc9e6 1677static void gen_rotc_rm_T1(DisasContext *s, TCGMemOp ot, int op1,
b6abf97d
FB
1678 int is_right)
1679{
d229edce 1680 gen_compute_eflags(s);
c7b3c873 1681 assert(s->cc_op == CC_OP_EFLAGS);
b6abf97d
FB
1682
1683 /* load */
1684 if (op1 == OR_TMP0)
c66f9727 1685 gen_op_ld_v(s, ot, s->T0, s->A0);
b6abf97d 1686 else
c66f9727 1687 gen_op_mov_v_reg(ot, s->T0, op1);
b6abf97d 1688
a7812ae4
PB
1689 if (is_right) {
1690 switch (ot) {
4ba9938c 1691 case MO_8:
c66f9727 1692 gen_helper_rcrb(s->T0, cpu_env, s->T0, cpu_T1);
7923057b 1693 break;
4ba9938c 1694 case MO_16:
c66f9727 1695 gen_helper_rcrw(s->T0, cpu_env, s->T0, cpu_T1);
7923057b 1696 break;
4ba9938c 1697 case MO_32:
c66f9727 1698 gen_helper_rcrl(s->T0, cpu_env, s->T0, cpu_T1);
7923057b 1699 break;
a7812ae4 1700#ifdef TARGET_X86_64
4ba9938c 1701 case MO_64:
c66f9727 1702 gen_helper_rcrq(s->T0, cpu_env, s->T0, cpu_T1);
7923057b 1703 break;
a7812ae4 1704#endif
d67dc9e6
RH
1705 default:
1706 tcg_abort();
a7812ae4
PB
1707 }
1708 } else {
1709 switch (ot) {
4ba9938c 1710 case MO_8:
c66f9727 1711 gen_helper_rclb(s->T0, cpu_env, s->T0, cpu_T1);
7923057b 1712 break;
4ba9938c 1713 case MO_16:
c66f9727 1714 gen_helper_rclw(s->T0, cpu_env, s->T0, cpu_T1);
7923057b 1715 break;
4ba9938c 1716 case MO_32:
c66f9727 1717 gen_helper_rcll(s->T0, cpu_env, s->T0, cpu_T1);
7923057b 1718 break;
a7812ae4 1719#ifdef TARGET_X86_64
4ba9938c 1720 case MO_64:
c66f9727 1721 gen_helper_rclq(s->T0, cpu_env, s->T0, cpu_T1);
7923057b 1722 break;
a7812ae4 1723#endif
d67dc9e6
RH
1724 default:
1725 tcg_abort();
a7812ae4
PB
1726 }
1727 }
b6abf97d 1728 /* store */
d4faa3e0 1729 gen_op_st_rm_T0_A0(s, ot, op1);
b6abf97d
FB
1730}
1731
1732/* XXX: add faster immediate case */
d67dc9e6 1733static void gen_shiftd_rm_T1(DisasContext *s, TCGMemOp ot, int op1,
f437d0a3 1734 bool is_right, TCGv count_in)
b6abf97d 1735{
4ba9938c 1736 target_ulong mask = (ot == MO_64 ? 63 : 31);
f437d0a3 1737 TCGv count;
b6abf97d
FB
1738
1739 /* load */
1e4840bf 1740 if (op1 == OR_TMP0) {
c66f9727 1741 gen_op_ld_v(s, ot, s->T0, s->A0);
1e4840bf 1742 } else {
c66f9727 1743 gen_op_mov_v_reg(ot, s->T0, op1);
1e4840bf 1744 }
b6abf97d 1745
f437d0a3
RH
1746 count = tcg_temp_new();
1747 tcg_gen_andi_tl(count, count_in, mask);
1e4840bf 1748
f437d0a3 1749 switch (ot) {
4ba9938c 1750 case MO_16:
f437d0a3
RH
1751 /* Note: we implement the Intel behaviour for shift count > 16.
1752 This means "shrdw C, B, A" shifts A:B:A >> C. Build the B:A
1753 portion by constructing it as a 32-bit value. */
b6abf97d 1754 if (is_right) {
c66f9727
EC
1755 tcg_gen_deposit_tl(cpu_tmp0, s->T0, cpu_T1, 16, 16);
1756 tcg_gen_mov_tl(cpu_T1, s->T0);
1757 tcg_gen_mov_tl(s->T0, cpu_tmp0);
b6abf97d 1758 } else {
c66f9727 1759 tcg_gen_deposit_tl(cpu_T1, s->T0, cpu_T1, 16, 16);
b6abf97d 1760 }
f437d0a3
RH
1761 /* FALLTHRU */
1762#ifdef TARGET_X86_64
4ba9938c 1763 case MO_32:
f437d0a3
RH
1764 /* Concatenate the two 32-bit values and use a 64-bit shift. */
1765 tcg_gen_subi_tl(cpu_tmp0, count, 1);
b6abf97d 1766 if (is_right) {
c66f9727
EC
1767 tcg_gen_concat_tl_i64(s->T0, s->T0, cpu_T1);
1768 tcg_gen_shr_i64(cpu_tmp0, s->T0, cpu_tmp0);
1769 tcg_gen_shr_i64(s->T0, s->T0, count);
f437d0a3 1770 } else {
c66f9727
EC
1771 tcg_gen_concat_tl_i64(s->T0, cpu_T1, s->T0);
1772 tcg_gen_shl_i64(cpu_tmp0, s->T0, cpu_tmp0);
1773 tcg_gen_shl_i64(s->T0, s->T0, count);
f437d0a3 1774 tcg_gen_shri_i64(cpu_tmp0, cpu_tmp0, 32);
c66f9727 1775 tcg_gen_shri_i64(s->T0, s->T0, 32);
f437d0a3
RH
1776 }
1777 break;
1778#endif
1779 default:
1780 tcg_gen_subi_tl(cpu_tmp0, count, 1);
1781 if (is_right) {
c66f9727 1782 tcg_gen_shr_tl(cpu_tmp0, s->T0, cpu_tmp0);
b6abf97d 1783
f437d0a3 1784 tcg_gen_subfi_tl(cpu_tmp4, mask + 1, count);
c66f9727 1785 tcg_gen_shr_tl(s->T0, s->T0, count);
1d1cc4d0 1786 tcg_gen_shl_tl(cpu_T1, cpu_T1, cpu_tmp4);
b6abf97d 1787 } else {
c66f9727 1788 tcg_gen_shl_tl(cpu_tmp0, s->T0, cpu_tmp0);
4ba9938c 1789 if (ot == MO_16) {
f437d0a3
RH
1790 /* Only needed if count > 16, for Intel behaviour. */
1791 tcg_gen_subfi_tl(cpu_tmp4, 33, count);
1d1cc4d0 1792 tcg_gen_shr_tl(cpu_tmp4, cpu_T1, cpu_tmp4);
f437d0a3
RH
1793 tcg_gen_or_tl(cpu_tmp0, cpu_tmp0, cpu_tmp4);
1794 }
1795
1796 tcg_gen_subfi_tl(cpu_tmp4, mask + 1, count);
c66f9727 1797 tcg_gen_shl_tl(s->T0, s->T0, count);
1d1cc4d0 1798 tcg_gen_shr_tl(cpu_T1, cpu_T1, cpu_tmp4);
b6abf97d 1799 }
f437d0a3 1800 tcg_gen_movi_tl(cpu_tmp4, 0);
1d1cc4d0
RH
1801 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_T1, count, cpu_tmp4,
1802 cpu_tmp4, cpu_T1);
c66f9727 1803 tcg_gen_or_tl(s->T0, s->T0, cpu_T1);
f437d0a3 1804 break;
b6abf97d 1805 }
b6abf97d 1806
b6abf97d 1807 /* store */
d4faa3e0 1808 gen_op_st_rm_T0_A0(s, ot, op1);
1e4840bf 1809
c66f9727 1810 gen_shift_flags(s, ot, s->T0, cpu_tmp0, count, is_right);
f437d0a3 1811 tcg_temp_free(count);
b6abf97d
FB
1812}
1813
d67dc9e6 1814static void gen_shift(DisasContext *s1, int op, TCGMemOp ot, int d, int s)
b6abf97d
FB
1815{
1816 if (s != OR_TMP1)
1d1cc4d0 1817 gen_op_mov_v_reg(ot, cpu_T1, s);
b6abf97d
FB
1818 switch(op) {
1819 case OP_ROL:
1820 gen_rot_rm_T1(s1, ot, d, 0);
1821 break;
1822 case OP_ROR:
1823 gen_rot_rm_T1(s1, ot, d, 1);
1824 break;
1825 case OP_SHL:
1826 case OP_SHL1:
1827 gen_shift_rm_T1(s1, ot, d, 0, 0);
1828 break;
1829 case OP_SHR:
1830 gen_shift_rm_T1(s1, ot, d, 1, 0);
1831 break;
1832 case OP_SAR:
1833 gen_shift_rm_T1(s1, ot, d, 1, 1);
1834 break;
1835 case OP_RCL:
1836 gen_rotc_rm_T1(s1, ot, d, 0);
1837 break;
1838 case OP_RCR:
1839 gen_rotc_rm_T1(s1, ot, d, 1);
1840 break;
1841 }
2c0262af
FB
1842}
1843
d67dc9e6 1844static void gen_shifti(DisasContext *s1, int op, TCGMemOp ot, int d, int c)
2c0262af 1845{
c1c37968 1846 switch(op) {
8cd6345d 1847 case OP_ROL:
1848 gen_rot_rm_im(s1, ot, d, c, 0);
1849 break;
1850 case OP_ROR:
1851 gen_rot_rm_im(s1, ot, d, c, 1);
1852 break;
c1c37968
FB
1853 case OP_SHL:
1854 case OP_SHL1:
1855 gen_shift_rm_im(s1, ot, d, c, 0, 0);
1856 break;
1857 case OP_SHR:
1858 gen_shift_rm_im(s1, ot, d, c, 1, 0);
1859 break;
1860 case OP_SAR:
1861 gen_shift_rm_im(s1, ot, d, c, 1, 1);
1862 break;
1863 default:
1864 /* currently not optimized */
1d1cc4d0 1865 tcg_gen_movi_tl(cpu_T1, c);
c1c37968
FB
1866 gen_shift(s1, op, ot, d, OR_TMP1);
1867 break;
1868 }
2c0262af
FB
1869}
1870
b066c537
PB
1871#define X86_MAX_INSN_LENGTH 15
1872
e3af7c78
PB
1873static uint64_t advance_pc(CPUX86State *env, DisasContext *s, int num_bytes)
1874{
1875 uint64_t pc = s->pc;
1876
1877 s->pc += num_bytes;
b066c537
PB
1878 if (unlikely(s->pc - s->pc_start > X86_MAX_INSN_LENGTH)) {
1879 /* If the instruction's 16th byte is on a different page than the 1st, a
1880 * page fault on the second page wins over the general protection fault
1881 * caused by the instruction being too long.
1882 * This can happen even if the operand is only one byte long!
1883 */
1884 if (((s->pc - 1) ^ (pc - 1)) & TARGET_PAGE_MASK) {
1885 volatile uint8_t unused =
1886 cpu_ldub_code(env, (s->pc - 1) & TARGET_PAGE_MASK);
1887 (void) unused;
1888 }
1889 siglongjmp(s->jmpbuf, 1);
1890 }
1891
e3af7c78
PB
1892 return pc;
1893}
1894
1895static inline uint8_t x86_ldub_code(CPUX86State *env, DisasContext *s)
1896{
1897 return cpu_ldub_code(env, advance_pc(env, s, 1));
1898}
1899
1900static inline int16_t x86_ldsw_code(CPUX86State *env, DisasContext *s)
1901{
1902 return cpu_ldsw_code(env, advance_pc(env, s, 2));
1903}
1904
1905static inline uint16_t x86_lduw_code(CPUX86State *env, DisasContext *s)
1906{
1907 return cpu_lduw_code(env, advance_pc(env, s, 2));
1908}
1909
1910static inline uint32_t x86_ldl_code(CPUX86State *env, DisasContext *s)
1911{
1912 return cpu_ldl_code(env, advance_pc(env, s, 4));
1913}
1914
1915#ifdef TARGET_X86_64
1916static inline uint64_t x86_ldq_code(CPUX86State *env, DisasContext *s)
1917{
1918 return cpu_ldq_code(env, advance_pc(env, s, 8));
1919}
1920#endif
1921
a074ce42
RH
1922/* Decompose an address. */
1923
1924typedef struct AddressParts {
1925 int def_seg;
1926 int base;
1927 int index;
1928 int scale;
1929 target_long disp;
1930} AddressParts;
1931
1932static AddressParts gen_lea_modrm_0(CPUX86State *env, DisasContext *s,
1933 int modrm)
2c0262af 1934{
a074ce42 1935 int def_seg, base, index, scale, mod, rm;
14ce26e7 1936 target_long disp;
a074ce42 1937 bool havesib;
2c0262af 1938
d6a29149 1939 def_seg = R_DS;
a074ce42
RH
1940 index = -1;
1941 scale = 0;
1942 disp = 0;
1943
2c0262af
FB
1944 mod = (modrm >> 6) & 3;
1945 rm = modrm & 7;
a074ce42
RH
1946 base = rm | REX_B(s);
1947
1948 if (mod == 3) {
1949 /* Normally filtered out earlier, but including this path
1950 simplifies multi-byte nop, as well as bndcl, bndcu, bndcn. */
1951 goto done;
1952 }
2c0262af 1953
1d71ddb1
RH
1954 switch (s->aflag) {
1955 case MO_64:
1956 case MO_32:
2c0262af 1957 havesib = 0;
a074ce42 1958 if (rm == 4) {
e3af7c78 1959 int code = x86_ldub_code(env, s);
2c0262af 1960 scale = (code >> 6) & 3;
14ce26e7 1961 index = ((code >> 3) & 7) | REX_X(s);
7865eec4
RH
1962 if (index == 4) {
1963 index = -1; /* no index */
1964 }
a074ce42
RH
1965 base = (code & 7) | REX_B(s);
1966 havesib = 1;
2c0262af
FB
1967 }
1968
1969 switch (mod) {
1970 case 0:
14ce26e7 1971 if ((base & 7) == 5) {
2c0262af 1972 base = -1;
e3af7c78 1973 disp = (int32_t)x86_ldl_code(env, s);
14ce26e7 1974 if (CODE64(s) && !havesib) {
a074ce42 1975 base = -2;
14ce26e7
FB
1976 disp += s->pc + s->rip_offset;
1977 }
2c0262af
FB
1978 }
1979 break;
1980 case 1:
e3af7c78 1981 disp = (int8_t)x86_ldub_code(env, s);
2c0262af
FB
1982 break;
1983 default:
1984 case 2:
e3af7c78 1985 disp = (int32_t)x86_ldl_code(env, s);
2c0262af
FB
1986 break;
1987 }
3b46e624 1988
7865eec4
RH
1989 /* For correct popl handling with esp. */
1990 if (base == R_ESP && s->popl_esp_hack) {
1991 disp += s->popl_esp_hack;
1992 }
d6a29149
RH
1993 if (base == R_EBP || base == R_ESP) {
1994 def_seg = R_SS;
2c0262af 1995 }
1d71ddb1
RH
1996 break;
1997
1998 case MO_16:
d6a29149 1999 if (mod == 0) {
2c0262af 2000 if (rm == 6) {
a074ce42 2001 base = -1;
e3af7c78 2002 disp = x86_lduw_code(env, s);
d6a29149 2003 break;
2c0262af 2004 }
d6a29149 2005 } else if (mod == 1) {
e3af7c78 2006 disp = (int8_t)x86_ldub_code(env, s);
d6a29149 2007 } else {
e3af7c78 2008 disp = (int16_t)x86_lduw_code(env, s);
2c0262af 2009 }
7effd625 2010
7effd625 2011 switch (rm) {
2c0262af 2012 case 0:
a074ce42
RH
2013 base = R_EBX;
2014 index = R_ESI;
2c0262af
FB
2015 break;
2016 case 1:
a074ce42
RH
2017 base = R_EBX;
2018 index = R_EDI;
2c0262af
FB
2019 break;
2020 case 2:
a074ce42
RH
2021 base = R_EBP;
2022 index = R_ESI;
d6a29149 2023 def_seg = R_SS;
2c0262af
FB
2024 break;
2025 case 3:
a074ce42
RH
2026 base = R_EBP;
2027 index = R_EDI;
d6a29149 2028 def_seg = R_SS;
2c0262af
FB
2029 break;
2030 case 4:
a074ce42 2031 base = R_ESI;
2c0262af
FB
2032 break;
2033 case 5:
a074ce42 2034 base = R_EDI;
2c0262af
FB
2035 break;
2036 case 6:
a074ce42 2037 base = R_EBP;
d6a29149 2038 def_seg = R_SS;
2c0262af
FB
2039 break;
2040 default:
2041 case 7:
a074ce42 2042 base = R_EBX;
2c0262af
FB
2043 break;
2044 }
1d71ddb1
RH
2045 break;
2046
2047 default:
2048 tcg_abort();
2c0262af 2049 }
d6a29149 2050
a074ce42
RH
2051 done:
2052 return (AddressParts){ def_seg, base, index, scale, disp };
2c0262af
FB
2053}
2054
a074ce42 2055/* Compute the address, with a minimum number of TCG ops. */
6b672b5d 2056static TCGv gen_lea_modrm_1(DisasContext *s, AddressParts a)
e17a36ce 2057{
f764718d 2058 TCGv ea = NULL;
3b46e624 2059
a074ce42
RH
2060 if (a.index >= 0) {
2061 if (a.scale == 0) {
2062 ea = cpu_regs[a.index];
2063 } else {
6b672b5d
EC
2064 tcg_gen_shli_tl(s->A0, cpu_regs[a.index], a.scale);
2065 ea = s->A0;
e17a36ce 2066 }
a074ce42 2067 if (a.base >= 0) {
6b672b5d
EC
2068 tcg_gen_add_tl(s->A0, ea, cpu_regs[a.base]);
2069 ea = s->A0;
e17a36ce 2070 }
a074ce42
RH
2071 } else if (a.base >= 0) {
2072 ea = cpu_regs[a.base];
2073 }
f764718d 2074 if (!ea) {
6b672b5d
EC
2075 tcg_gen_movi_tl(s->A0, a.disp);
2076 ea = s->A0;
a074ce42 2077 } else if (a.disp != 0) {
6b672b5d
EC
2078 tcg_gen_addi_tl(s->A0, ea, a.disp);
2079 ea = s->A0;
a074ce42 2080 }
1d71ddb1 2081
a074ce42
RH
2082 return ea;
2083}
1d71ddb1 2084
a074ce42
RH
2085static void gen_lea_modrm(CPUX86State *env, DisasContext *s, int modrm)
2086{
2087 AddressParts a = gen_lea_modrm_0(env, s, modrm);
6b672b5d 2088 TCGv ea = gen_lea_modrm_1(s, a);
a074ce42
RH
2089 gen_lea_v_seg(s, s->aflag, ea, a.def_seg, s->override);
2090}
2091
2092static void gen_nop_modrm(CPUX86State *env, DisasContext *s, int modrm)
2093{
2094 (void)gen_lea_modrm_0(env, s, modrm);
e17a36ce
FB
2095}
2096
523e28d7
RH
2097/* Used for BNDCL, BNDCU, BNDCN. */
2098static void gen_bndck(CPUX86State *env, DisasContext *s, int modrm,
2099 TCGCond cond, TCGv_i64 bndv)
2100{
6b672b5d 2101 TCGv ea = gen_lea_modrm_1(s, gen_lea_modrm_0(env, s, modrm));
523e28d7
RH
2102
2103 tcg_gen_extu_tl_i64(cpu_tmp1_i64, ea);
2104 if (!CODE64(s)) {
2105 tcg_gen_ext32u_i64(cpu_tmp1_i64, cpu_tmp1_i64);
2106 }
2107 tcg_gen_setcond_i64(cond, cpu_tmp1_i64, cpu_tmp1_i64, bndv);
2108 tcg_gen_extrl_i64_i32(cpu_tmp2_i32, cpu_tmp1_i64);
2109 gen_helper_bndck(cpu_env, cpu_tmp2_i32);
2110}
2111
664e0f19
FB
2112/* used for LEA and MOV AX, mem */
2113static void gen_add_A0_ds_seg(DisasContext *s)
2114{
6b672b5d 2115 gen_lea_v_seg(s, s->aflag, s->A0, R_DS, s->override);
664e0f19
FB
2116}
2117
222a3336 2118/* generate modrm memory load or store of 'reg'. TMP0 is used if reg ==
2c0262af 2119 OR_TMP0 */
0af10c86 2120static void gen_ldst_modrm(CPUX86State *env, DisasContext *s, int modrm,
d67dc9e6 2121 TCGMemOp ot, int reg, int is_store)
2c0262af 2122{
4eeb3939 2123 int mod, rm;
2c0262af
FB
2124
2125 mod = (modrm >> 6) & 3;
14ce26e7 2126 rm = (modrm & 7) | REX_B(s);
2c0262af
FB
2127 if (mod == 3) {
2128 if (is_store) {
2129 if (reg != OR_TMP0)
c66f9727
EC
2130 gen_op_mov_v_reg(ot, s->T0, reg);
2131 gen_op_mov_reg_v(ot, rm, s->T0);
2c0262af 2132 } else {
c66f9727 2133 gen_op_mov_v_reg(ot, s->T0, rm);
2c0262af 2134 if (reg != OR_TMP0)
c66f9727 2135 gen_op_mov_reg_v(ot, reg, s->T0);
2c0262af
FB
2136 }
2137 } else {
4eeb3939 2138 gen_lea_modrm(env, s, modrm);
2c0262af
FB
2139 if (is_store) {
2140 if (reg != OR_TMP0)
c66f9727
EC
2141 gen_op_mov_v_reg(ot, s->T0, reg);
2142 gen_op_st_v(s, ot, s->T0, s->A0);
2c0262af 2143 } else {
c66f9727 2144 gen_op_ld_v(s, ot, s->T0, s->A0);
2c0262af 2145 if (reg != OR_TMP0)
c66f9727 2146 gen_op_mov_reg_v(ot, reg, s->T0);
2c0262af
FB
2147 }
2148 }
2149}
2150
d67dc9e6 2151static inline uint32_t insn_get(CPUX86State *env, DisasContext *s, TCGMemOp ot)
2c0262af
FB
2152{
2153 uint32_t ret;
2154
d67dc9e6 2155 switch (ot) {
4ba9938c 2156 case MO_8:
e3af7c78 2157 ret = x86_ldub_code(env, s);
2c0262af 2158 break;
4ba9938c 2159 case MO_16:
e3af7c78 2160 ret = x86_lduw_code(env, s);
2c0262af 2161 break;
4ba9938c 2162 case MO_32:
d67dc9e6
RH
2163#ifdef TARGET_X86_64
2164 case MO_64:
2165#endif
e3af7c78 2166 ret = x86_ldl_code(env, s);
2c0262af 2167 break;
d67dc9e6
RH
2168 default:
2169 tcg_abort();
2c0262af
FB
2170 }
2171 return ret;
2172}
2173
d67dc9e6 2174static inline int insn_const_size(TCGMemOp ot)
14ce26e7 2175{
4ba9938c 2176 if (ot <= MO_32) {
14ce26e7 2177 return 1 << ot;
4ba9938c 2178 } else {
14ce26e7 2179 return 4;
4ba9938c 2180 }
14ce26e7
FB
2181}
2182
90aa39a1
SF
2183static inline bool use_goto_tb(DisasContext *s, target_ulong pc)
2184{
2185#ifndef CONFIG_USER_ONLY
6cf147aa 2186 return (pc & TARGET_PAGE_MASK) == (s->base.tb->pc & TARGET_PAGE_MASK) ||
90aa39a1
SF
2187 (pc & TARGET_PAGE_MASK) == (s->pc_start & TARGET_PAGE_MASK);
2188#else
2189 return true;
2190#endif
2191}
2192
6e256c93
FB
2193static inline void gen_goto_tb(DisasContext *s, int tb_num, target_ulong eip)
2194{
90aa39a1 2195 target_ulong pc = s->cs_base + eip;
6e256c93 2196
90aa39a1 2197 if (use_goto_tb(s, pc)) {
6e256c93 2198 /* jump to same page: we can use a direct jump */
57fec1fe 2199 tcg_gen_goto_tb(tb_num);
6e256c93 2200 gen_jmp_im(eip);
07ea28b4 2201 tcg_gen_exit_tb(s->base.tb, tb_num);
6cf147aa 2202 s->base.is_jmp = DISAS_NORETURN;
6e256c93 2203 } else {
fe620895 2204 /* jump to another page */
6e256c93 2205 gen_jmp_im(eip);
fe620895 2206 gen_jr(s, cpu_tmp0);
6e256c93
FB
2207 }
2208}
2209
5fafdf24 2210static inline void gen_jcc(DisasContext *s, int b,
14ce26e7 2211 target_ulong val, target_ulong next_eip)
2c0262af 2212{
42a268c2 2213 TCGLabel *l1, *l2;
3b46e624 2214
2c0262af 2215 if (s->jmp_opt) {
14ce26e7 2216 l1 = gen_new_label();
b27fc131 2217 gen_jcc1(s, b, l1);
dc259201 2218
6e256c93 2219 gen_goto_tb(s, 0, next_eip);
14ce26e7
FB
2220
2221 gen_set_label(l1);
6e256c93 2222 gen_goto_tb(s, 1, val);
2c0262af 2223 } else {
14ce26e7
FB
2224 l1 = gen_new_label();
2225 l2 = gen_new_label();
b27fc131 2226 gen_jcc1(s, b, l1);
8e1c85e3 2227
14ce26e7 2228 gen_jmp_im(next_eip);
8e1c85e3
FB
2229 tcg_gen_br(l2);
2230
14ce26e7
FB
2231 gen_set_label(l1);
2232 gen_jmp_im(val);
2233 gen_set_label(l2);
2c0262af
FB
2234 gen_eob(s);
2235 }
2236}
2237
d67dc9e6 2238static void gen_cmovcc1(CPUX86State *env, DisasContext *s, TCGMemOp ot, int b,
f32d3781
PB
2239 int modrm, int reg)
2240{
57eb0cc8 2241 CCPrepare cc;
f32d3781 2242
57eb0cc8 2243 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
f32d3781 2244
1d1cc4d0 2245 cc = gen_prepare_cc(s, b, cpu_T1);
57eb0cc8
RH
2246 if (cc.mask != -1) {
2247 TCGv t0 = tcg_temp_new();
2248 tcg_gen_andi_tl(t0, cc.reg, cc.mask);
2249 cc.reg = t0;
2250 }
2251 if (!cc.use_reg2) {
2252 cc.reg2 = tcg_const_tl(cc.imm);
f32d3781
PB
2253 }
2254
c66f9727
EC
2255 tcg_gen_movcond_tl(cc.cond, s->T0, cc.reg, cc.reg2,
2256 s->T0, cpu_regs[reg]);
2257 gen_op_mov_reg_v(ot, reg, s->T0);
57eb0cc8
RH
2258
2259 if (cc.mask != -1) {
2260 tcg_temp_free(cc.reg);
2261 }
2262 if (!cc.use_reg2) {
2263 tcg_temp_free(cc.reg2);
2264 }
f32d3781
PB
2265}
2266
c66f9727 2267static inline void gen_op_movl_T0_seg(DisasContext *s, int seg_reg)
3bd7da9e 2268{
c66f9727 2269 tcg_gen_ld32u_tl(s->T0, cpu_env,
3bd7da9e
FB
2270 offsetof(CPUX86State,segs[seg_reg].selector));
2271}
2272
c66f9727 2273static inline void gen_op_movl_seg_T0_vm(DisasContext *s, int seg_reg)
3bd7da9e 2274{
c66f9727
EC
2275 tcg_gen_ext16u_tl(s->T0, s->T0);
2276 tcg_gen_st32_tl(s->T0, cpu_env,
3bd7da9e 2277 offsetof(CPUX86State,segs[seg_reg].selector));
c66f9727 2278 tcg_gen_shli_tl(cpu_seg_base[seg_reg], s->T0, 4);
3bd7da9e
FB
2279}
2280
2c0262af
FB
2281/* move T0 to seg_reg and compute if the CPU state may change. Never
2282 call this function with seg_reg == R_CS */
100ec099 2283static void gen_movl_seg_T0(DisasContext *s, int seg_reg)
2c0262af 2284{
3415a4dd 2285 if (s->pe && !s->vm86) {
c66f9727 2286 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, s->T0);
2999a0b2 2287 gen_helper_load_seg(cpu_env, tcg_const_i32(seg_reg), cpu_tmp2_i32);
dc196a57
FB
2288 /* abort translation because the addseg value may change or
2289 because ss32 may change. For R_SS, translation must always
2290 stop as a special handling must be done to disable hardware
2291 interrupts for the next instruction */
1e39d97a 2292 if (seg_reg == R_SS || (s->code32 && seg_reg < R_FS)) {
6cf147aa 2293 s->base.is_jmp = DISAS_TOO_MANY;
1e39d97a 2294 }
3415a4dd 2295 } else {
c66f9727 2296 gen_op_movl_seg_T0_vm(s, seg_reg);
1e39d97a 2297 if (seg_reg == R_SS) {
6cf147aa 2298 s->base.is_jmp = DISAS_TOO_MANY;
1e39d97a 2299 }
3415a4dd 2300 }
2c0262af
FB
2301}
2302
0573fbfc
TS
2303static inline int svm_is_rep(int prefixes)
2304{
2305 return ((prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) ? 8 : 0);
2306}
2307
872929aa 2308static inline void
0573fbfc 2309gen_svm_check_intercept_param(DisasContext *s, target_ulong pc_start,
b8b6a50b 2310 uint32_t type, uint64_t param)
0573fbfc 2311{
872929aa
FB
2312 /* no SVM activated; fast case */
2313 if (likely(!(s->flags & HF_SVMI_MASK)))
2314 return;
773cdfcc 2315 gen_update_cc_op(s);
872929aa 2316 gen_jmp_im(pc_start - s->cs_base);
052e80d5 2317 gen_helper_svm_check_intercept_param(cpu_env, tcg_const_i32(type),
a7812ae4 2318 tcg_const_i64(param));
0573fbfc
TS
2319}
2320
872929aa 2321static inline void
0573fbfc
TS
2322gen_svm_check_intercept(DisasContext *s, target_ulong pc_start, uint64_t type)
2323{
872929aa 2324 gen_svm_check_intercept_param(s, pc_start, type, 0);
0573fbfc
TS
2325}
2326
4f31916f
FB
2327static inline void gen_stack_update(DisasContext *s, int addend)
2328{
64ae256c 2329 gen_op_add_reg_im(mo_stacksize(s), R_ESP, addend);
4f31916f
FB
2330}
2331
432baffe
RH
2332/* Generate a push. It depends on ss32, addseg and dflag. */
2333static void gen_push_v(DisasContext *s, TCGv val)
2c0262af 2334{
64ae256c
RH
2335 TCGMemOp d_ot = mo_pushpop(s, s->dflag);
2336 TCGMemOp a_ot = mo_stacksize(s);
432baffe 2337 int size = 1 << d_ot;
6b672b5d 2338 TCGv new_esp = s->A0;
432baffe 2339
6b672b5d 2340 tcg_gen_subi_tl(s->A0, cpu_regs[R_ESP], size);
2c0262af 2341
77ebcad0 2342 if (!CODE64(s)) {
432baffe
RH
2343 if (s->addseg) {
2344 new_esp = cpu_tmp4;
6b672b5d 2345 tcg_gen_mov_tl(new_esp, s->A0);
2c0262af 2346 }
6b672b5d 2347 gen_lea_v_seg(s, a_ot, s->A0, R_SS, -1);
2c0262af 2348 }
432baffe 2349
6b672b5d 2350 gen_op_st_v(s, d_ot, val, s->A0);
432baffe 2351 gen_op_mov_reg_v(a_ot, R_ESP, new_esp);
2c0262af
FB
2352}
2353
4f31916f 2354/* two step pop is necessary for precise exceptions */
8e31d234 2355static TCGMemOp gen_pop_T0(DisasContext *s)
2c0262af 2356{
8e31d234 2357 TCGMemOp d_ot = mo_pushpop(s, s->dflag);
8e31d234 2358
77ebcad0 2359 gen_lea_v_seg(s, mo_stacksize(s), cpu_regs[R_ESP], R_SS, -1);
c66f9727 2360 gen_op_ld_v(s, d_ot, s->T0, s->A0);
8e31d234 2361
8e31d234 2362 return d_ot;
2c0262af
FB
2363}
2364
77ebcad0 2365static inline void gen_pop_update(DisasContext *s, TCGMemOp ot)
2c0262af 2366{
8e31d234 2367 gen_stack_update(s, 1 << ot);
2c0262af
FB
2368}
2369
77ebcad0 2370static inline void gen_stack_A0(DisasContext *s)
2c0262af 2371{
77ebcad0 2372 gen_lea_v_seg(s, s->ss32 ? MO_32 : MO_16, cpu_regs[R_ESP], R_SS, -1);
2c0262af
FB
2373}
2374
2c0262af
FB
2375static void gen_pusha(DisasContext *s)
2376{
d37ea0c0
RH
2377 TCGMemOp s_ot = s->ss32 ? MO_32 : MO_16;
2378 TCGMemOp d_ot = s->dflag;
2379 int size = 1 << d_ot;
2c0262af 2380 int i;
d37ea0c0
RH
2381
2382 for (i = 0; i < 8; i++) {
6b672b5d
EC
2383 tcg_gen_addi_tl(s->A0, cpu_regs[R_ESP], (i - 8) * size);
2384 gen_lea_v_seg(s, s_ot, s->A0, R_SS, -1);
2385 gen_op_st_v(s, d_ot, cpu_regs[7 - i], s->A0);
d37ea0c0
RH
2386 }
2387
2388 gen_stack_update(s, -8 * size);
2389}
2390
2c0262af
FB
2391static void gen_popa(DisasContext *s)
2392{
d37ea0c0
RH
2393 TCGMemOp s_ot = s->ss32 ? MO_32 : MO_16;
2394 TCGMemOp d_ot = s->dflag;
2395 int size = 1 << d_ot;
2c0262af 2396 int i;
d37ea0c0
RH
2397
2398 for (i = 0; i < 8; i++) {
2c0262af 2399 /* ESP is not reloaded */
d37ea0c0
RH
2400 if (7 - i == R_ESP) {
2401 continue;
2c0262af 2402 }
6b672b5d
EC
2403 tcg_gen_addi_tl(s->A0, cpu_regs[R_ESP], i * size);
2404 gen_lea_v_seg(s, s_ot, s->A0, R_SS, -1);
c66f9727
EC
2405 gen_op_ld_v(s, d_ot, s->T0, s->A0);
2406 gen_op_mov_reg_v(d_ot, 7 - i, s->T0);
2c0262af 2407 }
d37ea0c0
RH
2408
2409 gen_stack_update(s, 8 * size);
2c0262af
FB
2410}
2411
2c0262af
FB
2412static void gen_enter(DisasContext *s, int esp_addend, int level)
2413{
743e398e
RH
2414 TCGMemOp d_ot = mo_pushpop(s, s->dflag);
2415 TCGMemOp a_ot = CODE64(s) ? MO_64 : s->ss32 ? MO_32 : MO_16;
2416 int size = 1 << d_ot;
2c0262af 2417
743e398e 2418 /* Push BP; compute FrameTemp into T1. */
1d1cc4d0
RH
2419 tcg_gen_subi_tl(cpu_T1, cpu_regs[R_ESP], size);
2420 gen_lea_v_seg(s, a_ot, cpu_T1, R_SS, -1);
6b672b5d 2421 gen_op_st_v(s, d_ot, cpu_regs[R_EBP], s->A0);
743e398e
RH
2422
2423 level &= 31;
2424 if (level != 0) {
2425 int i;
2426
2427 /* Copy level-1 pointers from the previous frame. */
2428 for (i = 1; i < level; ++i) {
6b672b5d
EC
2429 tcg_gen_subi_tl(s->A0, cpu_regs[R_EBP], size * i);
2430 gen_lea_v_seg(s, a_ot, s->A0, R_SS, -1);
2431 gen_op_ld_v(s, d_ot, cpu_tmp0, s->A0);
743e398e 2432
6b672b5d
EC
2433 tcg_gen_subi_tl(s->A0, cpu_T1, size * i);
2434 gen_lea_v_seg(s, a_ot, s->A0, R_SS, -1);
2435 gen_op_st_v(s, d_ot, cpu_tmp0, s->A0);
8f091a59 2436 }
743e398e
RH
2437
2438 /* Push the current FrameTemp as the last level. */
6b672b5d
EC
2439 tcg_gen_subi_tl(s->A0, cpu_T1, size * level);
2440 gen_lea_v_seg(s, a_ot, s->A0, R_SS, -1);
2441 gen_op_st_v(s, d_ot, cpu_T1, s->A0);
2c0262af 2442 }
743e398e
RH
2443
2444 /* Copy the FrameTemp value to EBP. */
1d1cc4d0 2445 gen_op_mov_reg_v(a_ot, R_EBP, cpu_T1);
743e398e
RH
2446
2447 /* Compute the final value of ESP. */
1d1cc4d0
RH
2448 tcg_gen_subi_tl(cpu_T1, cpu_T1, esp_addend + size * level);
2449 gen_op_mov_reg_v(a_ot, R_ESP, cpu_T1);
2c0262af
FB
2450}
2451
2045f04c
RH
2452static void gen_leave(DisasContext *s)
2453{
2454 TCGMemOp d_ot = mo_pushpop(s, s->dflag);
2455 TCGMemOp a_ot = mo_stacksize(s);
2456
2457 gen_lea_v_seg(s, a_ot, cpu_regs[R_EBP], R_SS, -1);
c66f9727 2458 gen_op_ld_v(s, d_ot, s->T0, s->A0);
2045f04c 2459
1d1cc4d0 2460 tcg_gen_addi_tl(cpu_T1, cpu_regs[R_EBP], 1 << d_ot);
2045f04c 2461
c66f9727 2462 gen_op_mov_reg_v(d_ot, R_EBP, s->T0);
1d1cc4d0 2463 gen_op_mov_reg_v(a_ot, R_ESP, cpu_T1);
2045f04c
RH
2464}
2465
14ce26e7 2466static void gen_exception(DisasContext *s, int trapno, target_ulong cur_eip)
2c0262af 2467{
773cdfcc 2468 gen_update_cc_op(s);
14ce26e7 2469 gen_jmp_im(cur_eip);
77b2bc2c 2470 gen_helper_raise_exception(cpu_env, tcg_const_i32(trapno));
6cf147aa 2471 s->base.is_jmp = DISAS_NORETURN;
2c0262af
FB
2472}
2473
b9f9c5b4
RH
2474/* Generate #UD for the current instruction. The assumption here is that
2475 the instruction is known, but it isn't allowed in the current cpu mode. */
2476static void gen_illegal_opcode(DisasContext *s)
2477{
2478 gen_exception(s, EXCP06_ILLOP, s->pc_start - s->cs_base);
2479}
2480
2481/* Similarly, except that the assumption here is that we don't decode
2482 the instruction at all -- either a missing opcode, an unimplemented
2483 feature, or just a bogus instruction stream. */
2484static void gen_unknown_opcode(CPUX86State *env, DisasContext *s)
2485{
2486 gen_illegal_opcode(s);
2487
2488 if (qemu_loglevel_mask(LOG_UNIMP)) {
2489 target_ulong pc = s->pc_start, end = s->pc;
1ee73216 2490 qemu_log_lock();
b9f9c5b4
RH
2491 qemu_log("ILLOPC: " TARGET_FMT_lx ":", pc);
2492 for (; pc < end; ++pc) {
2493 qemu_log(" %02x", cpu_ldub_code(env, pc));
2494 }
2495 qemu_log("\n");
1ee73216 2496 qemu_log_unlock();
b9f9c5b4
RH
2497 }
2498}
2499
2c0262af 2500/* an interrupt is different from an exception because of the
7f75ffd3 2501 privilege checks */
5fafdf24 2502static void gen_interrupt(DisasContext *s, int intno,
14ce26e7 2503 target_ulong cur_eip, target_ulong next_eip)
2c0262af 2504{
773cdfcc 2505 gen_update_cc_op(s);
14ce26e7 2506 gen_jmp_im(cur_eip);
77b2bc2c 2507 gen_helper_raise_interrupt(cpu_env, tcg_const_i32(intno),
a7812ae4 2508 tcg_const_i32(next_eip - cur_eip));
6cf147aa 2509 s->base.is_jmp = DISAS_NORETURN;
2c0262af
FB
2510}
2511
14ce26e7 2512static void gen_debug(DisasContext *s, target_ulong cur_eip)
2c0262af 2513{
773cdfcc 2514 gen_update_cc_op(s);
14ce26e7 2515 gen_jmp_im(cur_eip);
4a7443be 2516 gen_helper_debug(cpu_env);
6cf147aa 2517 s->base.is_jmp = DISAS_NORETURN;
2c0262af
FB
2518}
2519
7f0b7141
RH
2520static void gen_set_hflag(DisasContext *s, uint32_t mask)
2521{
2522 if ((s->flags & mask) == 0) {
2523 TCGv_i32 t = tcg_temp_new_i32();
2524 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUX86State, hflags));
2525 tcg_gen_ori_i32(t, t, mask);
2526 tcg_gen_st_i32(t, cpu_env, offsetof(CPUX86State, hflags));
2527 tcg_temp_free_i32(t);
2528 s->flags |= mask;
2529 }
2530}
2531
2532static void gen_reset_hflag(DisasContext *s, uint32_t mask)
2533{
2534 if (s->flags & mask) {
2535 TCGv_i32 t = tcg_temp_new_i32();
2536 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUX86State, hflags));
2537 tcg_gen_andi_i32(t, t, ~mask);
2538 tcg_gen_st_i32(t, cpu_env, offsetof(CPUX86State, hflags));
2539 tcg_temp_free_i32(t);
2540 s->flags &= ~mask;
2541 }
2542}
2543
7d117ce8
RH
2544/* Clear BND registers during legacy branches. */
2545static void gen_bnd_jmp(DisasContext *s)
2546{
8b33e82b
PB
2547 /* Clear the registers only if BND prefix is missing, MPX is enabled,
2548 and if the BNDREGs are known to be in use (non-zero) already.
2549 The helper itself will check BNDPRESERVE at runtime. */
7d117ce8 2550 if ((s->prefix & PREFIX_REPNZ) == 0
8b33e82b
PB
2551 && (s->flags & HF_MPX_EN_MASK) != 0
2552 && (s->flags & HF_MPX_IU_MASK) != 0) {
7d117ce8
RH
2553 gen_helper_bnd_jmp(cpu_env);
2554 }
2555}
2556
f083d92c 2557/* Generate an end of block. Trace exception is also generated if needed.
c52ab08a
DE
2558 If INHIBIT, set HF_INHIBIT_IRQ_MASK if it isn't already set.
2559 If RECHECK_TF, emit a rechecking helper for #DB, ignoring the state of
2560 S->TF. This is used by the syscall/sysret insns. */
1ebb1af1 2561static void
7f11636d 2562do_gen_eob_worker(DisasContext *s, bool inhibit, bool recheck_tf, bool jr)
2c0262af 2563{
773cdfcc 2564 gen_update_cc_op(s);
f083d92c
RH
2565
2566 /* If several instructions disable interrupts, only the first does it. */
2567 if (inhibit && !(s->flags & HF_INHIBIT_IRQ_MASK)) {
2568 gen_set_hflag(s, HF_INHIBIT_IRQ_MASK);
2569 } else {
2570 gen_reset_hflag(s, HF_INHIBIT_IRQ_MASK);
2571 }
2572
6cf147aa 2573 if (s->base.tb->flags & HF_RF_MASK) {
f0967a1a 2574 gen_helper_reset_rf(cpu_env);
a2397807 2575 }
6cf147aa 2576 if (s->base.singlestep_enabled) {
4a7443be 2577 gen_helper_debug(cpu_env);
c52ab08a
DE
2578 } else if (recheck_tf) {
2579 gen_helper_rechecking_single_step(cpu_env);
07ea28b4 2580 tcg_gen_exit_tb(NULL, 0);
34865134 2581 } else if (s->tf) {
4a7443be 2582 gen_helper_single_step(cpu_env);
7f11636d
EC
2583 } else if (jr) {
2584 tcg_gen_lookup_and_goto_ptr();
2c0262af 2585 } else {
07ea28b4 2586 tcg_gen_exit_tb(NULL, 0);
2c0262af 2587 }
6cf147aa 2588 s->base.is_jmp = DISAS_NORETURN;
2c0262af
FB
2589}
2590
1ebb1af1
EC
2591static inline void
2592gen_eob_worker(DisasContext *s, bool inhibit, bool recheck_tf)
2593{
7f11636d 2594 do_gen_eob_worker(s, inhibit, recheck_tf, false);
1ebb1af1
EC
2595}
2596
c52ab08a
DE
2597/* End of block.
2598 If INHIBIT, set HF_INHIBIT_IRQ_MASK if it isn't already set. */
2599static void gen_eob_inhibit_irq(DisasContext *s, bool inhibit)
2600{
2601 gen_eob_worker(s, inhibit, false);
2602}
2603
f083d92c
RH
2604/* End of block, resetting the inhibit irq flag. */
2605static void gen_eob(DisasContext *s)
2606{
c52ab08a 2607 gen_eob_worker(s, false, false);
f083d92c
RH
2608}
2609
1ebb1af1
EC
2610/* Jump to register */
2611static void gen_jr(DisasContext *s, TCGv dest)
2612{
7f11636d 2613 do_gen_eob_worker(s, false, false, true);
1ebb1af1
EC
2614}
2615
2c0262af
FB
2616/* generate a jump to eip. No segment change must happen before as a
2617 direct call to the next block may occur */
14ce26e7 2618static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num)
2c0262af 2619{
a3251186
RH
2620 gen_update_cc_op(s);
2621 set_cc_op(s, CC_OP_DYNAMIC);
2c0262af 2622 if (s->jmp_opt) {
6e256c93 2623 gen_goto_tb(s, tb_num, eip);
2c0262af 2624 } else {
14ce26e7 2625 gen_jmp_im(eip);
2c0262af
FB
2626 gen_eob(s);
2627 }
2628}
2629
14ce26e7
FB
2630static void gen_jmp(DisasContext *s, target_ulong eip)
2631{
2632 gen_jmp_tb(s, eip, 0);
2633}
2634
323d1876 2635static inline void gen_ldq_env_A0(DisasContext *s, int offset)
8686c490 2636{
6b672b5d 2637 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, s->A0, s->mem_index, MO_LEQ);
b6abf97d 2638 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, offset);
8686c490 2639}
664e0f19 2640
323d1876 2641static inline void gen_stq_env_A0(DisasContext *s, int offset)
8686c490 2642{
b6abf97d 2643 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, offset);
6b672b5d 2644 tcg_gen_qemu_st_i64(cpu_tmp1_i64, s->A0, s->mem_index, MO_LEQ);
8686c490 2645}
664e0f19 2646
323d1876 2647static inline void gen_ldo_env_A0(DisasContext *s, int offset)
8686c490 2648{
5c42a7cd 2649 int mem_index = s->mem_index;
6b672b5d 2650 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, s->A0, mem_index, MO_LEQ);
19cbd87c 2651 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(0)));
6b672b5d 2652 tcg_gen_addi_tl(cpu_tmp0, s->A0, 8);
3c5f4116 2653 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_tmp0, mem_index, MO_LEQ);
19cbd87c 2654 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(1)));
8686c490 2655}
14ce26e7 2656
323d1876 2657static inline void gen_sto_env_A0(DisasContext *s, int offset)
8686c490 2658{
5c42a7cd 2659 int mem_index = s->mem_index;
19cbd87c 2660 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(0)));
6b672b5d
EC
2661 tcg_gen_qemu_st_i64(cpu_tmp1_i64, s->A0, mem_index, MO_LEQ);
2662 tcg_gen_addi_tl(cpu_tmp0, s->A0, 8);
19cbd87c 2663 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(1)));
3523e4bd 2664 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_tmp0, mem_index, MO_LEQ);
8686c490 2665}
14ce26e7 2666
5af45186
FB
2667static inline void gen_op_movo(int d_offset, int s_offset)
2668{
19cbd87c
EH
2669 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset + offsetof(ZMMReg, ZMM_Q(0)));
2670 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset + offsetof(ZMMReg, ZMM_Q(0)));
2671 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset + offsetof(ZMMReg, ZMM_Q(1)));
2672 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset + offsetof(ZMMReg, ZMM_Q(1)));
5af45186
FB
2673}
2674
2675static inline void gen_op_movq(int d_offset, int s_offset)
2676{
b6abf97d
FB
2677 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset);
2678 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset);
5af45186
FB
2679}
2680
2681static inline void gen_op_movl(int d_offset, int s_offset)
2682{
b6abf97d
FB
2683 tcg_gen_ld_i32(cpu_tmp2_i32, cpu_env, s_offset);
2684 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, d_offset);
5af45186
FB
2685}
2686
2687static inline void gen_op_movq_env_0(int d_offset)
2688{
b6abf97d
FB
2689 tcg_gen_movi_i64(cpu_tmp1_i64, 0);
2690 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset);
5af45186 2691}
664e0f19 2692
d3eb5eae
BS
2693typedef void (*SSEFunc_i_ep)(TCGv_i32 val, TCGv_ptr env, TCGv_ptr reg);
2694typedef void (*SSEFunc_l_ep)(TCGv_i64 val, TCGv_ptr env, TCGv_ptr reg);
2695typedef void (*SSEFunc_0_epi)(TCGv_ptr env, TCGv_ptr reg, TCGv_i32 val);
2696typedef void (*SSEFunc_0_epl)(TCGv_ptr env, TCGv_ptr reg, TCGv_i64 val);
2697typedef void (*SSEFunc_0_epp)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b);
2698typedef void (*SSEFunc_0_eppi)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b,
2699 TCGv_i32 val);
c4baa050 2700typedef void (*SSEFunc_0_ppi)(TCGv_ptr reg_a, TCGv_ptr reg_b, TCGv_i32 val);
d3eb5eae
BS
2701typedef void (*SSEFunc_0_eppt)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b,
2702 TCGv val);
c4baa050 2703
5af45186
FB
2704#define SSE_SPECIAL ((void *)1)
2705#define SSE_DUMMY ((void *)2)
664e0f19 2706
a7812ae4
PB
2707#define MMX_OP2(x) { gen_helper_ ## x ## _mmx, gen_helper_ ## x ## _xmm }
2708#define SSE_FOP(x) { gen_helper_ ## x ## ps, gen_helper_ ## x ## pd, \
2709 gen_helper_ ## x ## ss, gen_helper_ ## x ## sd, }
5af45186 2710
d3eb5eae 2711static const SSEFunc_0_epp sse_op_table1[256][4] = {
a35f3ec7
AJ
2712 /* 3DNow! extensions */
2713 [0x0e] = { SSE_DUMMY }, /* femms */
2714 [0x0f] = { SSE_DUMMY }, /* pf... */
664e0f19
FB
2715 /* pure SSE operations */
2716 [0x10] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movups, movupd, movss, movsd */
2717 [0x11] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movups, movupd, movss, movsd */
465e9838 2718 [0x12] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movlps, movlpd, movsldup, movddup */
664e0f19 2719 [0x13] = { SSE_SPECIAL, SSE_SPECIAL }, /* movlps, movlpd */
a7812ae4
PB
2720 [0x14] = { gen_helper_punpckldq_xmm, gen_helper_punpcklqdq_xmm },
2721 [0x15] = { gen_helper_punpckhdq_xmm, gen_helper_punpckhqdq_xmm },
664e0f19
FB
2722 [0x16] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movhps, movhpd, movshdup */
2723 [0x17] = { SSE_SPECIAL, SSE_SPECIAL }, /* movhps, movhpd */
2724
2725 [0x28] = { SSE_SPECIAL, SSE_SPECIAL }, /* movaps, movapd */
2726 [0x29] = { SSE_SPECIAL, SSE_SPECIAL }, /* movaps, movapd */
2727 [0x2a] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvtpi2ps, cvtpi2pd, cvtsi2ss, cvtsi2sd */
d9f4bb27 2728 [0x2b] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movntps, movntpd, movntss, movntsd */
664e0f19
FB
2729 [0x2c] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvttps2pi, cvttpd2pi, cvttsd2si, cvttss2si */
2730 [0x2d] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvtps2pi, cvtpd2pi, cvtsd2si, cvtss2si */
a7812ae4
PB
2731 [0x2e] = { gen_helper_ucomiss, gen_helper_ucomisd },
2732 [0x2f] = { gen_helper_comiss, gen_helper_comisd },
664e0f19
FB
2733 [0x50] = { SSE_SPECIAL, SSE_SPECIAL }, /* movmskps, movmskpd */
2734 [0x51] = SSE_FOP(sqrt),
a7812ae4
PB
2735 [0x52] = { gen_helper_rsqrtps, NULL, gen_helper_rsqrtss, NULL },
2736 [0x53] = { gen_helper_rcpps, NULL, gen_helper_rcpss, NULL },
2737 [0x54] = { gen_helper_pand_xmm, gen_helper_pand_xmm }, /* andps, andpd */
2738 [0x55] = { gen_helper_pandn_xmm, gen_helper_pandn_xmm }, /* andnps, andnpd */
2739 [0x56] = { gen_helper_por_xmm, gen_helper_por_xmm }, /* orps, orpd */
2740 [0x57] = { gen_helper_pxor_xmm, gen_helper_pxor_xmm }, /* xorps, xorpd */
664e0f19
FB
2741 [0x58] = SSE_FOP(add),
2742 [0x59] = SSE_FOP(mul),
a7812ae4
PB
2743 [0x5a] = { gen_helper_cvtps2pd, gen_helper_cvtpd2ps,
2744 gen_helper_cvtss2sd, gen_helper_cvtsd2ss },
2745 [0x5b] = { gen_helper_cvtdq2ps, gen_helper_cvtps2dq, gen_helper_cvttps2dq },
664e0f19
FB
2746 [0x5c] = SSE_FOP(sub),
2747 [0x5d] = SSE_FOP(min),
2748 [0x5e] = SSE_FOP(div),
2749 [0x5f] = SSE_FOP(max),
2750
2751 [0xc2] = SSE_FOP(cmpeq),
d3eb5eae
BS
2752 [0xc6] = { (SSEFunc_0_epp)gen_helper_shufps,
2753 (SSEFunc_0_epp)gen_helper_shufpd }, /* XXX: casts */
664e0f19 2754
7073fbad
RH
2755 /* SSSE3, SSE4, MOVBE, CRC32, BMI1, BMI2, ADX. */
2756 [0x38] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
2757 [0x3a] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
4242b1bd 2758
664e0f19
FB
2759 /* MMX ops and their SSE extensions */
2760 [0x60] = MMX_OP2(punpcklbw),
2761 [0x61] = MMX_OP2(punpcklwd),
2762 [0x62] = MMX_OP2(punpckldq),
2763 [0x63] = MMX_OP2(packsswb),
2764 [0x64] = MMX_OP2(pcmpgtb),
2765 [0x65] = MMX_OP2(pcmpgtw),
2766 [0x66] = MMX_OP2(pcmpgtl),
2767 [0x67] = MMX_OP2(packuswb),
2768 [0x68] = MMX_OP2(punpckhbw),
2769 [0x69] = MMX_OP2(punpckhwd),
2770 [0x6a] = MMX_OP2(punpckhdq),
2771 [0x6b] = MMX_OP2(packssdw),
a7812ae4
PB
2772 [0x6c] = { NULL, gen_helper_punpcklqdq_xmm },
2773 [0x6d] = { NULL, gen_helper_punpckhqdq_xmm },
664e0f19
FB
2774 [0x6e] = { SSE_SPECIAL, SSE_SPECIAL }, /* movd mm, ea */
2775 [0x6f] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movq, movdqa, , movqdu */
d3eb5eae
BS
2776 [0x70] = { (SSEFunc_0_epp)gen_helper_pshufw_mmx,
2777 (SSEFunc_0_epp)gen_helper_pshufd_xmm,
2778 (SSEFunc_0_epp)gen_helper_pshufhw_xmm,
2779 (SSEFunc_0_epp)gen_helper_pshuflw_xmm }, /* XXX: casts */
664e0f19
FB
2780 [0x71] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftw */
2781 [0x72] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftd */
2782 [0x73] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftq */
2783 [0x74] = MMX_OP2(pcmpeqb),
2784 [0x75] = MMX_OP2(pcmpeqw),
2785 [0x76] = MMX_OP2(pcmpeql),
a35f3ec7 2786 [0x77] = { SSE_DUMMY }, /* emms */
d9f4bb27
AP
2787 [0x78] = { NULL, SSE_SPECIAL, NULL, SSE_SPECIAL }, /* extrq_i, insertq_i */
2788 [0x79] = { NULL, gen_helper_extrq_r, NULL, gen_helper_insertq_r },
a7812ae4
PB
2789 [0x7c] = { NULL, gen_helper_haddpd, NULL, gen_helper_haddps },
2790 [0x7d] = { NULL, gen_helper_hsubpd, NULL, gen_helper_hsubps },
664e0f19
FB
2791 [0x7e] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movd, movd, , movq */
2792 [0x7f] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movq, movdqa, movdqu */
2793 [0xc4] = { SSE_SPECIAL, SSE_SPECIAL }, /* pinsrw */
2794 [0xc5] = { SSE_SPECIAL, SSE_SPECIAL }, /* pextrw */
a7812ae4 2795 [0xd0] = { NULL, gen_helper_addsubpd, NULL, gen_helper_addsubps },
664e0f19
FB
2796 [0xd1] = MMX_OP2(psrlw),
2797 [0xd2] = MMX_OP2(psrld),
2798 [0xd3] = MMX_OP2(psrlq),
2799 [0xd4] = MMX_OP2(paddq),
2800 [0xd5] = MMX_OP2(pmullw),
2801 [0xd6] = { NULL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
2802 [0xd7] = { SSE_SPECIAL, SSE_SPECIAL }, /* pmovmskb */
2803 [0xd8] = MMX_OP2(psubusb),
2804 [0xd9] = MMX_OP2(psubusw),
2805 [0xda] = MMX_OP2(pminub),
2806 [0xdb] = MMX_OP2(pand),
2807 [0xdc] = MMX_OP2(paddusb),
2808 [0xdd] = MMX_OP2(paddusw),
2809 [0xde] = MMX_OP2(pmaxub),
2810 [0xdf] = MMX_OP2(pandn),
2811 [0xe0] = MMX_OP2(pavgb),
2812 [0xe1] = MMX_OP2(psraw),
2813 [0xe2] = MMX_OP2(psrad),
2814 [0xe3] = MMX_OP2(pavgw),
2815 [0xe4] = MMX_OP2(pmulhuw),
2816 [0xe5] = MMX_OP2(pmulhw),
a7812ae4 2817 [0xe6] = { NULL, gen_helper_cvttpd2dq, gen_helper_cvtdq2pd, gen_helper_cvtpd2dq },
664e0f19
FB
2818 [0xe7] = { SSE_SPECIAL , SSE_SPECIAL }, /* movntq, movntq */
2819 [0xe8] = MMX_OP2(psubsb),
2820 [0xe9] = MMX_OP2(psubsw),
2821 [0xea] = MMX_OP2(pminsw),
2822 [0xeb] = MMX_OP2(por),
2823 [0xec] = MMX_OP2(paddsb),
2824 [0xed] = MMX_OP2(paddsw),
2825 [0xee] = MMX_OP2(pmaxsw),
2826 [0xef] = MMX_OP2(pxor),
465e9838 2827 [0xf0] = { NULL, NULL, NULL, SSE_SPECIAL }, /* lddqu */
664e0f19
FB
2828 [0xf1] = MMX_OP2(psllw),
2829 [0xf2] = MMX_OP2(pslld),
2830 [0xf3] = MMX_OP2(psllq),
2831 [0xf4] = MMX_OP2(pmuludq),
2832 [0xf5] = MMX_OP2(pmaddwd),
2833 [0xf6] = MMX_OP2(psadbw),
d3eb5eae
BS
2834 [0xf7] = { (SSEFunc_0_epp)gen_helper_maskmov_mmx,
2835 (SSEFunc_0_epp)gen_helper_maskmov_xmm }, /* XXX: casts */
664e0f19
FB
2836 [0xf8] = MMX_OP2(psubb),
2837 [0xf9] = MMX_OP2(psubw),
2838 [0xfa] = MMX_OP2(psubl),
2839 [0xfb] = MMX_OP2(psubq),
2840 [0xfc] = MMX_OP2(paddb),
2841 [0xfd] = MMX_OP2(paddw),
2842 [0xfe] = MMX_OP2(paddl),
2843};
2844
d3eb5eae 2845static const SSEFunc_0_epp sse_op_table2[3 * 8][2] = {
664e0f19
FB
2846 [0 + 2] = MMX_OP2(psrlw),
2847 [0 + 4] = MMX_OP2(psraw),
2848 [0 + 6] = MMX_OP2(psllw),
2849 [8 + 2] = MMX_OP2(psrld),
2850 [8 + 4] = MMX_OP2(psrad),
2851 [8 + 6] = MMX_OP2(pslld),
2852 [16 + 2] = MMX_OP2(psrlq),
a7812ae4 2853 [16 + 3] = { NULL, gen_helper_psrldq_xmm },
664e0f19 2854 [16 + 6] = MMX_OP2(psllq),
a7812ae4 2855 [16 + 7] = { NULL, gen_helper_pslldq_xmm },
664e0f19
FB
2856};
2857
d3eb5eae 2858static const SSEFunc_0_epi sse_op_table3ai[] = {
a7812ae4 2859 gen_helper_cvtsi2ss,
11f8cdbc 2860 gen_helper_cvtsi2sd
c4baa050 2861};
a7812ae4 2862
11f8cdbc 2863#ifdef TARGET_X86_64
d3eb5eae 2864static const SSEFunc_0_epl sse_op_table3aq[] = {
11f8cdbc
SW
2865 gen_helper_cvtsq2ss,
2866 gen_helper_cvtsq2sd
2867};
2868#endif
2869
d3eb5eae 2870static const SSEFunc_i_ep sse_op_table3bi[] = {
a7812ae4 2871 gen_helper_cvttss2si,
a7812ae4 2872 gen_helper_cvtss2si,
bedc2ac1 2873 gen_helper_cvttsd2si,
11f8cdbc 2874 gen_helper_cvtsd2si
664e0f19 2875};
3b46e624 2876
11f8cdbc 2877#ifdef TARGET_X86_64
d3eb5eae 2878static const SSEFunc_l_ep sse_op_table3bq[] = {
11f8cdbc 2879 gen_helper_cvttss2sq,
11f8cdbc 2880 gen_helper_cvtss2sq,
bedc2ac1 2881 gen_helper_cvttsd2sq,
11f8cdbc
SW
2882 gen_helper_cvtsd2sq
2883};
2884#endif
2885
d3eb5eae 2886static const SSEFunc_0_epp sse_op_table4[8][4] = {
664e0f19
FB
2887 SSE_FOP(cmpeq),
2888 SSE_FOP(cmplt),
2889 SSE_FOP(cmple),
2890 SSE_FOP(cmpunord),
2891 SSE_FOP(cmpneq),
2892 SSE_FOP(cmpnlt),
2893 SSE_FOP(cmpnle),
2894 SSE_FOP(cmpord),
2895};
3b46e624 2896
d3eb5eae 2897static const SSEFunc_0_epp sse_op_table5[256] = {
a7812ae4
PB
2898 [0x0c] = gen_helper_pi2fw,
2899 [0x0d] = gen_helper_pi2fd,
2900 [0x1c] = gen_helper_pf2iw,
2901 [0x1d] = gen_helper_pf2id,
2902 [0x8a] = gen_helper_pfnacc,
2903 [0x8e] = gen_helper_pfpnacc,
2904 [0x90] = gen_helper_pfcmpge,
2905 [0x94] = gen_helper_pfmin,
2906 [0x96] = gen_helper_pfrcp,
2907 [0x97] = gen_helper_pfrsqrt,
2908 [0x9a] = gen_helper_pfsub,
2909 [0x9e] = gen_helper_pfadd,
2910 [0xa0] = gen_helper_pfcmpgt,
2911 [0xa4] = gen_helper_pfmax,
2912 [0xa6] = gen_helper_movq, /* pfrcpit1; no need to actually increase precision */
2913 [0xa7] = gen_helper_movq, /* pfrsqit1 */
2914 [0xaa] = gen_helper_pfsubr,
2915 [0xae] = gen_helper_pfacc,
2916 [0xb0] = gen_helper_pfcmpeq,
2917 [0xb4] = gen_helper_pfmul,
2918 [0xb6] = gen_helper_movq, /* pfrcpit2 */
2919 [0xb7] = gen_helper_pmulhrw_mmx,
2920 [0xbb] = gen_helper_pswapd,
2921 [0xbf] = gen_helper_pavgb_mmx /* pavgusb */
a35f3ec7
AJ
2922};
2923
d3eb5eae
BS
2924struct SSEOpHelper_epp {
2925 SSEFunc_0_epp op[2];
c4baa050
BS
2926 uint32_t ext_mask;
2927};
2928
d3eb5eae
BS
2929struct SSEOpHelper_eppi {
2930 SSEFunc_0_eppi op[2];
c4baa050 2931 uint32_t ext_mask;
222a3336 2932};
c4baa050 2933
222a3336 2934#define SSSE3_OP(x) { MMX_OP2(x), CPUID_EXT_SSSE3 }
a7812ae4
PB
2935#define SSE41_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, CPUID_EXT_SSE41 }
2936#define SSE42_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, CPUID_EXT_SSE42 }
222a3336 2937#define SSE41_SPECIAL { { NULL, SSE_SPECIAL }, CPUID_EXT_SSE41 }
e71827bc
AJ
2938#define PCLMULQDQ_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, \
2939 CPUID_EXT_PCLMULQDQ }
d640045a 2940#define AESNI_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, CPUID_EXT_AES }
c4baa050 2941
d3eb5eae 2942static const struct SSEOpHelper_epp sse_op_table6[256] = {
222a3336
AZ
2943 [0x00] = SSSE3_OP(pshufb),
2944 [0x01] = SSSE3_OP(phaddw),
2945 [0x02] = SSSE3_OP(phaddd),
2946 [0x03] = SSSE3_OP(phaddsw),
2947 [0x04] = SSSE3_OP(pmaddubsw),
2948 [0x05] = SSSE3_OP(phsubw),
2949 [0x06] = SSSE3_OP(phsubd),
2950 [0x07] = SSSE3_OP(phsubsw),
2951 [0x08] = SSSE3_OP(psignb),
2952 [0x09] = SSSE3_OP(psignw),
2953 [0x0a] = SSSE3_OP(psignd),
2954 [0x0b] = SSSE3_OP(pmulhrsw),
2955 [0x10] = SSE41_OP(pblendvb),
2956 [0x14] = SSE41_OP(blendvps),
2957 [0x15] = SSE41_OP(blendvpd),
2958 [0x17] = SSE41_OP(ptest),
2959 [0x1c] = SSSE3_OP(pabsb),
2960 [0x1d] = SSSE3_OP(pabsw),
2961 [0x1e] = SSSE3_OP(pabsd),
2962 [0x20] = SSE41_OP(pmovsxbw),
2963 [0x21] = SSE41_OP(pmovsxbd),
2964 [0x22] = SSE41_OP(pmovsxbq),
2965 [0x23] = SSE41_OP(pmovsxwd),
2966 [0x24] = SSE41_OP(pmovsxwq),
2967 [0x25] = SSE41_OP(pmovsxdq),
2968 [0x28] = SSE41_OP(pmuldq),
2969 [0x29] = SSE41_OP(pcmpeqq),
2970 [0x2a] = SSE41_SPECIAL, /* movntqda */
2971 [0x2b] = SSE41_OP(packusdw),
2972 [0x30] = SSE41_OP(pmovzxbw),
2973 [0x31] = SSE41_OP(pmovzxbd),
2974 [0x32] = SSE41_OP(pmovzxbq),
2975 [0x33] = SSE41_OP(pmovzxwd),
2976 [0x34] = SSE41_OP(pmovzxwq),
2977 [0x35] = SSE41_OP(pmovzxdq),
2978 [0x37] = SSE42_OP(pcmpgtq),
2979 [0x38] = SSE41_OP(pminsb),
2980 [0x39] = SSE41_OP(pminsd),
2981 [0x3a] = SSE41_OP(pminuw),
2982 [0x3b] = SSE41_OP(pminud),
2983 [0x3c] = SSE41_OP(pmaxsb),
2984 [0x3d] = SSE41_OP(pmaxsd),
2985 [0x3e] = SSE41_OP(pmaxuw),
2986 [0x3f] = SSE41_OP(pmaxud),
2987 [0x40] = SSE41_OP(pmulld),
2988 [0x41] = SSE41_OP(phminposuw),
d640045a
AJ
2989 [0xdb] = AESNI_OP(aesimc),
2990 [0xdc] = AESNI_OP(aesenc),
2991 [0xdd] = AESNI_OP(aesenclast),
2992 [0xde] = AESNI_OP(aesdec),
2993 [0xdf] = AESNI_OP(aesdeclast),
4242b1bd
AZ
2994};
2995
d3eb5eae 2996static const struct SSEOpHelper_eppi sse_op_table7[256] = {
222a3336
AZ
2997 [0x08] = SSE41_OP(roundps),
2998 [0x09] = SSE41_OP(roundpd),
2999 [0x0a] = SSE41_OP(roundss),
3000 [0x0b] = SSE41_OP(roundsd),
3001 [0x0c] = SSE41_OP(blendps),
3002 [0x0d] = SSE41_OP(blendpd),
3003 [0x0e] = SSE41_OP(pblendw),
3004 [0x0f] = SSSE3_OP(palignr),
3005 [0x14] = SSE41_SPECIAL, /* pextrb */
3006 [0x15] = SSE41_SPECIAL, /* pextrw */
3007 [0x16] = SSE41_SPECIAL, /* pextrd/pextrq */
3008 [0x17] = SSE41_SPECIAL, /* extractps */
3009 [0x20] = SSE41_SPECIAL, /* pinsrb */
3010 [0x21] = SSE41_SPECIAL, /* insertps */
3011 [0x22] = SSE41_SPECIAL, /* pinsrd/pinsrq */
3012 [0x40] = SSE41_OP(dpps),
3013 [0x41] = SSE41_OP(dppd),
3014 [0x42] = SSE41_OP(mpsadbw),
e71827bc 3015 [0x44] = PCLMULQDQ_OP(pclmulqdq),
222a3336
AZ
3016 [0x60] = SSE42_OP(pcmpestrm),
3017 [0x61] = SSE42_OP(pcmpestri),
3018 [0x62] = SSE42_OP(pcmpistrm),
3019 [0x63] = SSE42_OP(pcmpistri),
d640045a 3020 [0xdf] = AESNI_OP(aeskeygenassist),
4242b1bd
AZ
3021};
3022
0af10c86
BS
3023static void gen_sse(CPUX86State *env, DisasContext *s, int b,
3024 target_ulong pc_start, int rex_r)
664e0f19 3025{
d67dc9e6 3026 int b1, op1_offset, op2_offset, is_xmm, val;
4eeb3939 3027 int modrm, mod, rm, reg;
d3eb5eae
BS
3028 SSEFunc_0_epp sse_fn_epp;
3029 SSEFunc_0_eppi sse_fn_eppi;
c4baa050 3030 SSEFunc_0_ppi sse_fn_ppi;
d3eb5eae 3031 SSEFunc_0_eppt sse_fn_eppt;
d67dc9e6 3032 TCGMemOp ot;
664e0f19
FB
3033
3034 b &= 0xff;
5fafdf24 3035 if (s->prefix & PREFIX_DATA)
664e0f19 3036 b1 = 1;
5fafdf24 3037 else if (s->prefix & PREFIX_REPZ)
664e0f19 3038 b1 = 2;
5fafdf24 3039 else if (s->prefix & PREFIX_REPNZ)
664e0f19
FB
3040 b1 = 3;
3041 else
3042 b1 = 0;
d3eb5eae
BS
3043 sse_fn_epp = sse_op_table1[b][b1];
3044 if (!sse_fn_epp) {
b9f9c5b4 3045 goto unknown_op;
c4baa050 3046 }
a35f3ec7 3047 if ((b <= 0x5f && b >= 0x10) || b == 0xc6 || b == 0xc2) {
664e0f19
FB
3048 is_xmm = 1;
3049 } else {
3050 if (b1 == 0) {
3051 /* MMX case */
3052 is_xmm = 0;
3053 } else {
3054 is_xmm = 1;
3055 }
3056 }
3057 /* simple MMX/SSE operation */
3058 if (s->flags & HF_TS_MASK) {
3059 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
3060 return;
3061 }
3062 if (s->flags & HF_EM_MASK) {
3063 illegal_op:
b9f9c5b4 3064 gen_illegal_opcode(s);
664e0f19
FB
3065 return;
3066 }
b9f9c5b4
RH
3067 if (is_xmm
3068 && !(s->flags & HF_OSFXSR_MASK)
3069 && ((b != 0x38 && b != 0x3a) || (s->prefix & PREFIX_DATA))) {
3070 goto unknown_op;
3071 }
e771edab 3072 if (b == 0x0e) {
b9f9c5b4
RH
3073 if (!(s->cpuid_ext2_features & CPUID_EXT2_3DNOW)) {
3074 /* If we were fully decoding this we might use illegal_op. */
3075 goto unknown_op;
3076 }
e771edab 3077 /* femms */
d3eb5eae 3078 gen_helper_emms(cpu_env);
e771edab
AJ
3079 return;
3080 }
3081 if (b == 0x77) {
3082 /* emms */
d3eb5eae 3083 gen_helper_emms(cpu_env);
664e0f19
FB
3084 return;
3085 }
3086 /* prepare MMX state (XXX: optimize by storing fptt and fptags in
3087 the static cpu state) */
3088 if (!is_xmm) {
d3eb5eae 3089 gen_helper_enter_mmx(cpu_env);
664e0f19
FB
3090 }
3091
e3af7c78 3092 modrm = x86_ldub_code(env, s);
664e0f19
FB
3093 reg = ((modrm >> 3) & 7);
3094 if (is_xmm)
3095 reg |= rex_r;
3096 mod = (modrm >> 6) & 3;
d3eb5eae 3097 if (sse_fn_epp == SSE_SPECIAL) {
664e0f19
FB
3098 b |= (b1 << 8);
3099 switch(b) {
3100 case 0x0e7: /* movntq */
b9f9c5b4 3101 if (mod == 3) {
664e0f19 3102 goto illegal_op;
b9f9c5b4 3103 }
4eeb3939 3104 gen_lea_modrm(env, s, modrm);
323d1876 3105 gen_stq_env_A0(s, offsetof(CPUX86State, fpregs[reg].mmx));
664e0f19
FB
3106 break;
3107 case 0x1e7: /* movntdq */
3108 case 0x02b: /* movntps */
3109 case 0x12b: /* movntps */
2e21e749
T
3110 if (mod == 3)
3111 goto illegal_op;
4eeb3939 3112 gen_lea_modrm(env, s, modrm);
323d1876 3113 gen_sto_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
2e21e749 3114 break;
465e9838
FB
3115 case 0x3f0: /* lddqu */
3116 if (mod == 3)
664e0f19 3117 goto illegal_op;
4eeb3939 3118 gen_lea_modrm(env, s, modrm);
323d1876 3119 gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
664e0f19 3120 break;
d9f4bb27
AP
3121 case 0x22b: /* movntss */
3122 case 0x32b: /* movntsd */
3123 if (mod == 3)
3124 goto illegal_op;
4eeb3939 3125 gen_lea_modrm(env, s, modrm);
d9f4bb27 3126 if (b1 & 1) {
07958082 3127 gen_stq_env_A0(s, offsetof(CPUX86State,
19cbd87c 3128 xmm_regs[reg].ZMM_Q(0)));
d9f4bb27 3129 } else {
c66f9727 3130 tcg_gen_ld32u_tl(s->T0, cpu_env, offsetof(CPUX86State,
19cbd87c 3131 xmm_regs[reg].ZMM_L(0)));
c66f9727 3132 gen_op_st_v(s, MO_32, s->T0, s->A0);
d9f4bb27
AP
3133 }
3134 break;
664e0f19 3135 case 0x6e: /* movd mm, ea */
dabd98dd 3136#ifdef TARGET_X86_64
ab4e4aec 3137 if (s->dflag == MO_64) {
4ba9938c 3138 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 0);
c66f9727
EC
3139 tcg_gen_st_tl(s->T0, cpu_env,
3140 offsetof(CPUX86State, fpregs[reg].mmx));
5fafdf24 3141 } else
dabd98dd
FB
3142#endif
3143 {
4ba9938c 3144 gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 0);
5af45186
FB
3145 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3146 offsetof(CPUX86State,fpregs[reg].mmx));
c66f9727 3147 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, s->T0);
a7812ae4 3148 gen_helper_movl_mm_T0_mmx(cpu_ptr0, cpu_tmp2_i32);
dabd98dd 3149 }
664e0f19
FB
3150 break;
3151 case 0x16e: /* movd xmm, ea */
dabd98dd 3152#ifdef TARGET_X86_64
ab4e4aec 3153 if (s->dflag == MO_64) {
4ba9938c 3154 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 0);
5af45186
FB
3155 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3156 offsetof(CPUX86State,xmm_regs[reg]));
c66f9727 3157 gen_helper_movq_mm_T0_xmm(cpu_ptr0, s->T0);
5fafdf24 3158 } else
dabd98dd
FB
3159#endif
3160 {
4ba9938c 3161 gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 0);
5af45186
FB
3162 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3163 offsetof(CPUX86State,xmm_regs[reg]));
c66f9727 3164 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, s->T0);
a7812ae4 3165 gen_helper_movl_mm_T0_xmm(cpu_ptr0, cpu_tmp2_i32);
dabd98dd 3166 }
664e0f19
FB
3167 break;
3168 case 0x6f: /* movq mm, ea */
3169 if (mod != 3) {
4eeb3939 3170 gen_lea_modrm(env, s, modrm);
323d1876 3171 gen_ldq_env_A0(s, offsetof(CPUX86State, fpregs[reg].mmx));
664e0f19
FB
3172 } else {
3173 rm = (modrm & 7);
b6abf97d 3174 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env,
5af45186 3175 offsetof(CPUX86State,fpregs[rm].mmx));
b6abf97d 3176 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env,
5af45186 3177 offsetof(CPUX86State,fpregs[reg].mmx));
664e0f19
FB
3178 }
3179 break;
3180 case 0x010: /* movups */
3181 case 0x110: /* movupd */
3182 case 0x028: /* movaps */
3183 case 0x128: /* movapd */
3184 case 0x16f: /* movdqa xmm, ea */
3185 case 0x26f: /* movdqu xmm, ea */
3186 if (mod != 3) {
4eeb3939 3187 gen_lea_modrm(env, s, modrm);
323d1876 3188 gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
664e0f19
FB
3189 } else {
3190 rm = (modrm & 7) | REX_B(s);
3191 gen_op_movo(offsetof(CPUX86State,xmm_regs[reg]),
3192 offsetof(CPUX86State,xmm_regs[rm]));
3193 }
3194 break;
3195 case 0x210: /* movss xmm, ea */
3196 if (mod != 3) {
4eeb3939 3197 gen_lea_modrm(env, s, modrm);
c66f9727
EC
3198 gen_op_ld_v(s, MO_32, s->T0, s->A0);
3199 tcg_gen_st32_tl(s->T0, cpu_env,
3200 offsetof(CPUX86State, xmm_regs[reg].ZMM_L(0)));
3201 tcg_gen_movi_tl(s->T0, 0);
3202 tcg_gen_st32_tl(s->T0, cpu_env,
3203 offsetof(CPUX86State, xmm_regs[reg].ZMM_L(1)));
3204 tcg_gen_st32_tl(s->T0, cpu_env,
3205 offsetof(CPUX86State, xmm_regs[reg].ZMM_L(2)));
3206 tcg_gen_st32_tl(s->T0, cpu_env,
3207 offsetof(CPUX86State, xmm_regs[reg].ZMM_L(3)));
664e0f19
FB
3208 } else {
3209 rm = (modrm & 7) | REX_B(s);
19cbd87c
EH
3210 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0)),
3211 offsetof(CPUX86State,xmm_regs[rm].ZMM_L(0)));
664e0f19
FB
3212 }
3213 break;
3214 case 0x310: /* movsd xmm, ea */
3215 if (mod != 3) {
4eeb3939 3216 gen_lea_modrm(env, s, modrm);
323d1876 3217 gen_ldq_env_A0(s, offsetof(CPUX86State,
19cbd87c 3218 xmm_regs[reg].ZMM_Q(0)));
c66f9727
EC
3219 tcg_gen_movi_tl(s->T0, 0);
3220 tcg_gen_st32_tl(s->T0, cpu_env,
3221 offsetof(CPUX86State, xmm_regs[reg].ZMM_L(2)));
3222 tcg_gen_st32_tl(s->T0, cpu_env,
3223 offsetof(CPUX86State, xmm_regs[reg].ZMM_L(3)));
664e0f19
FB
3224 } else {
3225 rm = (modrm & 7) | REX_B(s);
19cbd87c
EH
3226 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)),
3227 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)));
664e0f19
FB
3228 }
3229 break;
3230 case 0x012: /* movlps */
3231 case 0x112: /* movlpd */
3232 if (mod != 3) {
4eeb3939 3233 gen_lea_modrm(env, s, modrm);
323d1876 3234 gen_ldq_env_A0(s, offsetof(CPUX86State,
19cbd87c 3235 xmm_regs[reg].ZMM_Q(0)));
664e0f19
FB
3236 } else {
3237 /* movhlps */
3238 rm = (modrm & 7) | REX_B(s);
19cbd87c
EH
3239 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)),
3240 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(1)));
664e0f19
FB
3241 }
3242 break;
465e9838
FB
3243 case 0x212: /* movsldup */
3244 if (mod != 3) {
4eeb3939 3245 gen_lea_modrm(env, s, modrm);
323d1876 3246 gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
465e9838
FB
3247 } else {
3248 rm = (modrm & 7) | REX_B(s);
19cbd87c
EH
3249 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0)),
3250 offsetof(CPUX86State,xmm_regs[rm].ZMM_L(0)));
3251 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].ZMM_L(2)),
3252 offsetof(CPUX86State,xmm_regs[rm].ZMM_L(2)));
465e9838 3253 }
19cbd87c
EH
3254 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].ZMM_L(1)),
3255 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0)));
3256 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].ZMM_L(3)),
3257 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(2)));
465e9838
FB
3258 break;
3259 case 0x312: /* movddup */
3260 if (mod != 3) {
4eeb3939 3261 gen_lea_modrm(env, s, modrm);
323d1876 3262 gen_ldq_env_A0(s, offsetof(CPUX86State,
19cbd87c 3263 xmm_regs[reg].ZMM_Q(0)));
465e9838
FB
3264 } else {
3265 rm = (modrm & 7) | REX_B(s);
19cbd87c
EH
3266 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)),
3267 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)));
465e9838 3268 }
19cbd87c
EH
3269 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(1)),
3270 offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)));
465e9838 3271 break;
664e0f19
FB
3272 case 0x016: /* movhps */
3273 case 0x116: /* movhpd */
3274 if (mod != 3) {
4eeb3939 3275 gen_lea_modrm(env, s, modrm);
323d1876 3276 gen_ldq_env_A0(s, offsetof(CPUX86State,
19cbd87c 3277 xmm_regs[reg].ZMM_Q(1)));
664e0f19
FB
3278 } else {
3279 /* movlhps */
3280 rm = (modrm & 7) | REX_B(s);
19cbd87c
EH
3281 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(1)),
3282 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)));
664e0f19
FB
3283 }
3284 break;
3285 case 0x216: /* movshdup */
3286 if (mod != 3) {
4eeb3939 3287 gen_lea_modrm(env, s, modrm);
323d1876 3288 gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
664e0f19
FB
3289 } else {
3290 rm = (modrm & 7) | REX_B(s);
19cbd87c
EH
3291 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].ZMM_L(1)),
3292 offsetof(CPUX86State,xmm_regs[rm].ZMM_L(1)));
3293 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].ZMM_L(3)),
3294 offsetof(CPUX86State,xmm_regs[rm].ZMM_L(3)));
664e0f19 3295 }
19cbd87c
EH
3296 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0)),
3297 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(1)));
3298 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].ZMM_L(2)),
3299 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(3)));
664e0f19 3300 break;
d9f4bb27
AP
3301 case 0x178:
3302 case 0x378:
3303 {
3304 int bit_index, field_length;
3305
3306 if (b1 == 1 && reg != 0)
3307 goto illegal_op;
e3af7c78
PB
3308 field_length = x86_ldub_code(env, s) & 0x3F;
3309 bit_index = x86_ldub_code(env, s) & 0x3F;
d9f4bb27
AP
3310 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3311 offsetof(CPUX86State,xmm_regs[reg]));
3312 if (b1 == 1)
d3eb5eae
BS
3313 gen_helper_extrq_i(cpu_env, cpu_ptr0,
3314 tcg_const_i32(bit_index),
3315 tcg_const_i32(field_length));
d9f4bb27 3316 else
d3eb5eae
BS
3317 gen_helper_insertq_i(cpu_env, cpu_ptr0,
3318 tcg_const_i32(bit_index),
3319 tcg_const_i32(field_length));
d9f4bb27
AP
3320 }
3321 break;
664e0f19 3322 case 0x7e: /* movd ea, mm */
dabd98dd 3323#ifdef TARGET_X86_64
ab4e4aec 3324 if (s->dflag == MO_64) {
c66f9727 3325 tcg_gen_ld_i64(s->T0, cpu_env,
5af45186 3326 offsetof(CPUX86State,fpregs[reg].mmx));
4ba9938c 3327 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 1);
5fafdf24 3328 } else
dabd98dd
FB
3329#endif
3330 {
c66f9727 3331 tcg_gen_ld32u_tl(s->T0, cpu_env,
5af45186 3332 offsetof(CPUX86State,fpregs[reg].mmx.MMX_L(0)));
4ba9938c 3333 gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 1);
dabd98dd 3334 }
664e0f19
FB
3335 break;
3336 case 0x17e: /* movd ea, xmm */
dabd98dd 3337#ifdef TARGET_X86_64
ab4e4aec 3338 if (s->dflag == MO_64) {
c66f9727 3339 tcg_gen_ld_i64(s->T0, cpu_env,
19cbd87c 3340 offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)));
4ba9938c 3341 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 1);
5fafdf24 3342 } else
dabd98dd
FB
3343#endif
3344 {
c66f9727 3345 tcg_gen_ld32u_tl(s->T0, cpu_env,
19cbd87c 3346 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0)));
4ba9938c 3347 gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 1);
dabd98dd 3348 }
664e0f19
FB
3349 break;
3350 case 0x27e: /* movq xmm, ea */
3351 if (mod != 3) {
4eeb3939 3352 gen_lea_modrm(env, s, modrm);
323d1876 3353 gen_ldq_env_A0(s, offsetof(CPUX86State,
19cbd87c 3354 xmm_regs[reg].ZMM_Q(0)));
664e0f19
FB
3355 } else {
3356 rm = (modrm & 7) | REX_B(s);
19cbd87c
EH
3357 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)),
3358 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)));
664e0f19 3359 }
19cbd87c 3360 gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(1)));
664e0f19
FB
3361 break;
3362 case 0x7f: /* movq ea, mm */
3363 if (mod != 3) {
4eeb3939 3364 gen_lea_modrm(env, s, modrm);
323d1876 3365 gen_stq_env_A0(s, offsetof(CPUX86State, fpregs[reg].mmx));
664e0f19
FB
3366 } else {
3367 rm = (modrm & 7);
3368 gen_op_movq(offsetof(CPUX86State,fpregs[rm].mmx),
3369 offsetof(CPUX86State,fpregs[reg].mmx));
3370 }
3371 break;
3372 case 0x011: /* movups */
3373 case 0x111: /* movupd */
3374 case 0x029: /* movaps */
3375 case 0x129: /* movapd */
3376 case 0x17f: /* movdqa ea, xmm */
3377 case 0x27f: /* movdqu ea, xmm */
3378 if (mod != 3) {
4eeb3939 3379 gen_lea_modrm(env, s, modrm);
323d1876 3380 gen_sto_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
664e0f19
FB
3381 } else {
3382 rm = (modrm & 7) | REX_B(s);
3383 gen_op_movo(offsetof(CPUX86State,xmm_regs[rm]),
3384 offsetof(CPUX86State,xmm_regs[reg]));
3385 }
3386 break;
3387 case 0x211: /* movss ea, xmm */
3388 if (mod != 3) {
4eeb3939 3389 gen_lea_modrm(env, s, modrm);
c66f9727
EC
3390 tcg_gen_ld32u_tl(s->T0, cpu_env,
3391 offsetof(CPUX86State, xmm_regs[reg].ZMM_L(0)));
3392 gen_op_st_v(s, MO_32, s->T0, s->A0);
664e0f19
FB
3393 } else {
3394 rm = (modrm & 7) | REX_B(s);
19cbd87c
EH
3395 gen_op_movl(offsetof(CPUX86State,xmm_regs[rm].ZMM_L(0)),
3396 offsetof(CPUX86State,xmm_regs[reg].ZMM_L(0)));
664e0f19
FB
3397 }
3398 break;
3399 case 0x311: /* movsd ea, xmm */
3400 if (mod != 3) {
4eeb3939 3401 gen_lea_modrm(env, s, modrm);
323d1876 3402 gen_stq_env_A0(s, offsetof(CPUX86State,
19cbd87c 3403 xmm_regs[reg].ZMM_Q(0)));
664e0f19
FB
3404 } else {
3405 rm = (modrm & 7) | REX_B(s);
19cbd87c
EH
3406 gen_op_movq(offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)),
3407 offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)));
664e0f19
FB
3408 }
3409 break;
3410 case 0x013: /* movlps */
3411 case 0x113: /* movlpd */
3412 if (mod != 3) {
4eeb3939 3413 gen_lea_modrm(env, s, modrm);
323d1876 3414 gen_stq_env_A0(s, offsetof(CPUX86State,
19cbd87c 3415 xmm_regs[reg].ZMM_Q(0)));
664e0f19
FB
3416 } else {
3417 goto illegal_op;
3418 }
3419 break;
3420 case 0x017: /* movhps */
3421 case 0x117: /* movhpd */
3422 if (mod != 3) {
4eeb3939 3423 gen_lea_modrm(env, s, modrm);
323d1876 3424 gen_stq_env_A0(s, offsetof(CPUX86State,
19cbd87c 3425 xmm_regs[reg].ZMM_Q(1)));
664e0f19
FB
3426 } else {
3427 goto illegal_op;
3428 }
3429 break;
3430 case 0x71: /* shift mm, im */
3431 case 0x72:
3432 case 0x73:
3433 case 0x171: /* shift xmm, im */
3434 case 0x172:
3435 case 0x173:
c045af25 3436 if (b1 >= 2) {
b9f9c5b4 3437 goto unknown_op;
c045af25 3438 }
e3af7c78 3439 val = x86_ldub_code(env, s);
664e0f19 3440 if (is_xmm) {
c66f9727
EC
3441 tcg_gen_movi_tl(s->T0, val);
3442 tcg_gen_st32_tl(s->T0, cpu_env,
3443 offsetof(CPUX86State, xmm_t0.ZMM_L(0)));
3444 tcg_gen_movi_tl(s->T0, 0);
3445 tcg_gen_st32_tl(s->T0, cpu_env,
3446 offsetof(CPUX86State, xmm_t0.ZMM_L(1)));
664e0f19
FB
3447 op1_offset = offsetof(CPUX86State,xmm_t0);
3448 } else {
c66f9727
EC
3449 tcg_gen_movi_tl(s->T0, val);
3450 tcg_gen_st32_tl(s->T0, cpu_env,
3451 offsetof(CPUX86State, mmx_t0.MMX_L(0)));
3452 tcg_gen_movi_tl(s->T0, 0);
3453 tcg_gen_st32_tl(s->T0, cpu_env,
3454 offsetof(CPUX86State, mmx_t0.MMX_L(1)));
664e0f19
FB
3455 op1_offset = offsetof(CPUX86State,mmx_t0);
3456 }
d3eb5eae
BS
3457 sse_fn_epp = sse_op_table2[((b - 1) & 3) * 8 +
3458 (((modrm >> 3)) & 7)][b1];
3459 if (!sse_fn_epp) {
b9f9c5b4 3460 goto unknown_op;
c4baa050 3461 }
664e0f19
FB
3462 if (is_xmm) {
3463 rm = (modrm & 7) | REX_B(s);
3464 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3465 } else {
3466 rm = (modrm & 7);
3467 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3468 }
5af45186
FB
3469 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op2_offset);
3470 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op1_offset);
d3eb5eae 3471 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
664e0f19
FB
3472 break;
3473 case 0x050: /* movmskps */
664e0f19 3474 rm = (modrm & 7) | REX_B(s);
5af45186
FB
3475 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3476 offsetof(CPUX86State,xmm_regs[rm]));
d3eb5eae 3477 gen_helper_movmskps(cpu_tmp2_i32, cpu_env, cpu_ptr0);
a7fbcbe5 3478 tcg_gen_extu_i32_tl(cpu_regs[reg], cpu_tmp2_i32);
664e0f19
FB
3479 break;
3480 case 0x150: /* movmskpd */
664e0f19 3481 rm = (modrm & 7) | REX_B(s);
5af45186
FB
3482 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3483 offsetof(CPUX86State,xmm_regs[rm]));
d3eb5eae 3484 gen_helper_movmskpd(cpu_tmp2_i32, cpu_env, cpu_ptr0);
a7fbcbe5 3485 tcg_gen_extu_i32_tl(cpu_regs[reg], cpu_tmp2_i32);
664e0f19
FB
3486 break;
3487 case 0x02a: /* cvtpi2ps */
3488 case 0x12a: /* cvtpi2pd */
d3eb5eae 3489 gen_helper_enter_mmx(cpu_env);
664e0f19 3490 if (mod != 3) {
4eeb3939 3491 gen_lea_modrm(env, s, modrm);
664e0f19 3492 op2_offset = offsetof(CPUX86State,mmx_t0);
323d1876 3493 gen_ldq_env_A0(s, op2_offset);
664e0f19
FB
3494 } else {
3495 rm = (modrm & 7);
3496 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3497 }
3498 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
5af45186
FB
3499 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
3500 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
664e0f19
FB
3501 switch(b >> 8) {
3502 case 0x0:
d3eb5eae 3503 gen_helper_cvtpi2ps(cpu_env, cpu_ptr0, cpu_ptr1);
664e0f19
FB
3504 break;
3505 default:
3506 case 0x1:
d3eb5eae 3507 gen_helper_cvtpi2pd(cpu_env, cpu_ptr0, cpu_ptr1);
664e0f19
FB
3508 break;
3509 }
3510 break;
3511 case 0x22a: /* cvtsi2ss */
3512 case 0x32a: /* cvtsi2sd */
ab4e4aec 3513 ot = mo_64_32(s->dflag);
0af10c86 3514 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
664e0f19 3515 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
5af45186 3516 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4ba9938c 3517 if (ot == MO_32) {
d3eb5eae 3518 SSEFunc_0_epi sse_fn_epi = sse_op_table3ai[(b >> 8) & 1];
c66f9727 3519 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, s->T0);
d3eb5eae 3520 sse_fn_epi(cpu_env, cpu_ptr0, cpu_tmp2_i32);
28e10711 3521 } else {
11f8cdbc 3522#ifdef TARGET_X86_64
d3eb5eae 3523 SSEFunc_0_epl sse_fn_epl = sse_op_table3aq[(b >> 8) & 1];
c66f9727 3524 sse_fn_epl(cpu_env, cpu_ptr0, s->T0);
11f8cdbc
SW
3525#else
3526 goto illegal_op;
3527#endif
28e10711 3528 }
664e0f19
FB
3529 break;
3530 case 0x02c: /* cvttps2pi */
3531 case 0x12c: /* cvttpd2pi */
3532 case 0x02d: /* cvtps2pi */
3533 case 0x12d: /* cvtpd2pi */
d3eb5eae 3534 gen_helper_enter_mmx(cpu_env);
664e0f19 3535 if (mod != 3) {
4eeb3939 3536 gen_lea_modrm(env, s, modrm);
664e0f19 3537 op2_offset = offsetof(CPUX86State,xmm_t0);
323d1876 3538 gen_ldo_env_A0(s, op2_offset);
664e0f19
FB
3539 } else {
3540 rm = (modrm & 7) | REX_B(s);
3541 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3542 }
3543 op1_offset = offsetof(CPUX86State,fpregs[reg & 7].mmx);
5af45186
FB
3544 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
3545 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
664e0f19
FB
3546 switch(b) {
3547 case 0x02c:
d3eb5eae 3548 gen_helper_cvttps2pi(cpu_env, cpu_ptr0, cpu_ptr1);
664e0f19
FB
3549 break;
3550 case 0x12c:
d3eb5eae 3551 gen_helper_cvttpd2pi(cpu_env, cpu_ptr0, cpu_ptr1);
664e0f19
FB
3552 break;
3553 case 0x02d:
d3eb5eae 3554 gen_helper_cvtps2pi(cpu_env, cpu_ptr0, cpu_ptr1);
664e0f19
FB
3555 break;
3556 case 0x12d:
d3eb5eae 3557 gen_helper_cvtpd2pi(cpu_env, cpu_ptr0, cpu_ptr1);
664e0f19
FB
3558 break;
3559 }
3560 break;
3561 case 0x22c: /* cvttss2si */
3562 case 0x32c: /* cvttsd2si */
3563 case 0x22d: /* cvtss2si */
3564 case 0x32d: /* cvtsd2si */
ab4e4aec 3565 ot = mo_64_32(s->dflag);
31313213 3566 if (mod != 3) {
4eeb3939 3567 gen_lea_modrm(env, s, modrm);
31313213 3568 if ((b >> 8) & 1) {
19cbd87c 3569 gen_ldq_env_A0(s, offsetof(CPUX86State, xmm_t0.ZMM_Q(0)));
31313213 3570 } else {
c66f9727
EC
3571 gen_op_ld_v(s, MO_32, s->T0, s->A0);
3572 tcg_gen_st32_tl(s->T0, cpu_env,
3573 offsetof(CPUX86State, xmm_t0.ZMM_L(0)));
31313213
FB
3574 }
3575 op2_offset = offsetof(CPUX86State,xmm_t0);
3576 } else {
3577 rm = (modrm & 7) | REX_B(s);
3578 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3579 }
5af45186 3580 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op2_offset);
4ba9938c 3581 if (ot == MO_32) {
d3eb5eae 3582 SSEFunc_i_ep sse_fn_i_ep =
bedc2ac1 3583 sse_op_table3bi[((b >> 7) & 2) | (b & 1)];
d3eb5eae 3584 sse_fn_i_ep(cpu_tmp2_i32, cpu_env, cpu_ptr0);
c66f9727 3585 tcg_gen_extu_i32_tl(s->T0, cpu_tmp2_i32);
5af45186 3586 } else {
11f8cdbc 3587#ifdef TARGET_X86_64
d3eb5eae 3588 SSEFunc_l_ep sse_fn_l_ep =
bedc2ac1 3589 sse_op_table3bq[((b >> 7) & 2) | (b & 1)];
c66f9727 3590 sse_fn_l_ep(s->T0, cpu_env, cpu_ptr0);
11f8cdbc
SW
3591#else
3592 goto illegal_op;
3593#endif
5af45186 3594 }
c66f9727 3595 gen_op_mov_reg_v(ot, reg, s->T0);
664e0f19
FB
3596 break;
3597 case 0xc4: /* pinsrw */
5fafdf24 3598 case 0x1c4:
d1e42c5c 3599 s->rip_offset = 1;
4ba9938c 3600 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
e3af7c78 3601 val = x86_ldub_code(env, s);
664e0f19
FB
3602 if (b1) {
3603 val &= 7;
c66f9727 3604 tcg_gen_st16_tl(s->T0, cpu_env,
19cbd87c 3605 offsetof(CPUX86State,xmm_regs[reg].ZMM_W(val)));
664e0f19
FB
3606 } else {
3607 val &= 3;
c66f9727 3608 tcg_gen_st16_tl(s->T0, cpu_env,
5af45186 3609 offsetof(CPUX86State,fpregs[reg].mmx.MMX_W(val)));
664e0f19
FB
3610 }
3611 break;
3612 case 0xc5: /* pextrw */
5fafdf24 3613 case 0x1c5:
664e0f19
FB
3614 if (mod != 3)
3615 goto illegal_op;
ab4e4aec 3616 ot = mo_64_32(s->dflag);
e3af7c78 3617 val = x86_ldub_code(env, s);
664e0f19
FB
3618 if (b1) {
3619 val &= 7;
3620 rm = (modrm & 7) | REX_B(s);
c66f9727 3621 tcg_gen_ld16u_tl(s->T0, cpu_env,
19cbd87c 3622 offsetof(CPUX86State,xmm_regs[rm].ZMM_W(val)));
664e0f19
FB
3623 } else {
3624 val &= 3;
3625 rm = (modrm & 7);
c66f9727 3626 tcg_gen_ld16u_tl(s->T0, cpu_env,
5af45186 3627 offsetof(CPUX86State,fpregs[rm].mmx.MMX_W(val)));
664e0f19
FB
3628 }
3629 reg = ((modrm >> 3) & 7) | rex_r;
c66f9727 3630 gen_op_mov_reg_v(ot, reg, s->T0);
664e0f19
FB
3631 break;
3632 case 0x1d6: /* movq ea, xmm */
3633 if (mod != 3) {
4eeb3939 3634 gen_lea_modrm(env, s, modrm);
323d1876 3635 gen_stq_env_A0(s, offsetof(CPUX86State,
19cbd87c 3636 xmm_regs[reg].ZMM_Q(0)));
664e0f19
FB
3637 } else {
3638 rm = (modrm & 7) | REX_B(s);
19cbd87c
EH
3639 gen_op_movq(offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)),
3640 offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)));
3641 gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(1)));
664e0f19
FB
3642 }
3643 break;
3644 case 0x2d6: /* movq2dq */
d3eb5eae 3645 gen_helper_enter_mmx(cpu_env);
480c1cdb 3646 rm = (modrm & 7);
19cbd87c 3647 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(0)),
480c1cdb 3648 offsetof(CPUX86State,fpregs[rm].mmx));
19cbd87c 3649 gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[reg].ZMM_Q(1)));
664e0f19
FB
3650 break;
3651 case 0x3d6: /* movdq2q */
d3eb5eae 3652 gen_helper_enter_mmx(cpu_env);
480c1cdb
FB
3653 rm = (modrm & 7) | REX_B(s);
3654 gen_op_movq(offsetof(CPUX86State,fpregs[reg & 7].mmx),
19cbd87c 3655 offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0)));
664e0f19
FB
3656 break;
3657 case 0xd7: /* pmovmskb */
3658 case 0x1d7:
3659 if (mod != 3)
3660 goto illegal_op;
3661 if (b1) {
3662 rm = (modrm & 7) | REX_B(s);
5af45186 3663 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, offsetof(CPUX86State,xmm_regs[rm]));
d3eb5eae 3664 gen_helper_pmovmskb_xmm(cpu_tmp2_i32, cpu_env, cpu_ptr0);
664e0f19
FB
3665 } else {
3666 rm = (modrm & 7);
5af45186 3667 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, offsetof(CPUX86State,fpregs[rm].mmx));
d3eb5eae 3668 gen_helper_pmovmskb_mmx(cpu_tmp2_i32, cpu_env, cpu_ptr0);
664e0f19
FB
3669 }
3670 reg = ((modrm >> 3) & 7) | rex_r;
a7fbcbe5 3671 tcg_gen_extu_i32_tl(cpu_regs[reg], cpu_tmp2_i32);
664e0f19 3672 break;
111994ee 3673
4242b1bd 3674 case 0x138:
000cacf6 3675 case 0x038:
4242b1bd 3676 b = modrm;
111994ee
RH
3677 if ((b & 0xf0) == 0xf0) {
3678 goto do_0f_38_fx;
3679 }
e3af7c78 3680 modrm = x86_ldub_code(env, s);
4242b1bd
AZ
3681 rm = modrm & 7;
3682 reg = ((modrm >> 3) & 7) | rex_r;
3683 mod = (modrm >> 6) & 3;
c045af25 3684 if (b1 >= 2) {
b9f9c5b4 3685 goto unknown_op;
c045af25 3686 }
4242b1bd 3687
d3eb5eae
BS
3688 sse_fn_epp = sse_op_table6[b].op[b1];
3689 if (!sse_fn_epp) {
b9f9c5b4 3690 goto unknown_op;
c4baa050 3691 }
222a3336
AZ
3692 if (!(s->cpuid_ext_features & sse_op_table6[b].ext_mask))
3693 goto illegal_op;
4242b1bd
AZ
3694
3695 if (b1) {
3696 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3697 if (mod == 3) {
3698 op2_offset = offsetof(CPUX86State,xmm_regs[rm | REX_B(s)]);
3699 } else {
3700 op2_offset = offsetof(CPUX86State,xmm_t0);
4eeb3939 3701 gen_lea_modrm(env, s, modrm);
222a3336
AZ
3702 switch (b) {
3703 case 0x20: case 0x30: /* pmovsxbw, pmovzxbw */
3704 case 0x23: case 0x33: /* pmovsxwd, pmovzxwd */
3705 case 0x25: case 0x35: /* pmovsxdq, pmovzxdq */
323d1876 3706 gen_ldq_env_A0(s, op2_offset +
19cbd87c 3707 offsetof(ZMMReg, ZMM_Q(0)));
222a3336
AZ
3708 break;
3709 case 0x21: case 0x31: /* pmovsxbd, pmovzxbd */
3710 case 0x24: case 0x34: /* pmovsxwq, pmovzxwq */
6b672b5d 3711 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, s->A0,
3c5f4116 3712 s->mem_index, MO_LEUL);
222a3336 3713 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, op2_offset +
19cbd87c 3714 offsetof(ZMMReg, ZMM_L(0)));
222a3336
AZ
3715 break;
3716 case 0x22: case 0x32: /* pmovsxbq, pmovzxbq */
6b672b5d 3717 tcg_gen_qemu_ld_tl(cpu_tmp0, s->A0,
3c5f4116 3718 s->mem_index, MO_LEUW);
222a3336 3719 tcg_gen_st16_tl(cpu_tmp0, cpu_env, op2_offset +
19cbd87c 3720 offsetof(ZMMReg, ZMM_W(0)));
222a3336
AZ
3721 break;
3722 case 0x2a: /* movntqda */
323d1876 3723 gen_ldo_env_A0(s, op1_offset);
222a3336
AZ
3724 return;
3725 default:
323d1876 3726 gen_ldo_env_A0(s, op2_offset);
222a3336 3727 }
4242b1bd
AZ
3728 }
3729 } else {
3730 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
3731 if (mod == 3) {
3732 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3733 } else {
3734 op2_offset = offsetof(CPUX86State,mmx_t0);
4eeb3939 3735 gen_lea_modrm(env, s, modrm);
323d1876 3736 gen_ldq_env_A0(s, op2_offset);
4242b1bd
AZ
3737 }
3738 }
d3eb5eae 3739 if (sse_fn_epp == SSE_SPECIAL) {
b9f9c5b4 3740 goto unknown_op;
c4baa050 3741 }
222a3336 3742
4242b1bd
AZ
3743 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
3744 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
d3eb5eae 3745 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
222a3336 3746
3ca51d07
RH
3747 if (b == 0x17) {
3748 set_cc_op(s, CC_OP_EFLAGS);
3749 }
4242b1bd 3750 break;
111994ee
RH
3751
3752 case 0x238:
3753 case 0x338:
3754 do_0f_38_fx:
3755 /* Various integer extensions at 0f 38 f[0-f]. */
3756 b = modrm | (b1 << 8);
e3af7c78 3757 modrm = x86_ldub_code(env, s);
222a3336
AZ
3758 reg = ((modrm >> 3) & 7) | rex_r;
3759
111994ee
RH
3760 switch (b) {
3761 case 0x3f0: /* crc32 Gd,Eb */
3762 case 0x3f1: /* crc32 Gd,Ey */
3763 do_crc32:
3764 if (!(s->cpuid_ext_features & CPUID_EXT_SSE42)) {
3765 goto illegal_op;
3766 }
3767 if ((b & 0xff) == 0xf0) {
4ba9938c 3768 ot = MO_8;
ab4e4aec 3769 } else if (s->dflag != MO_64) {
4ba9938c 3770 ot = (s->prefix & PREFIX_DATA ? MO_16 : MO_32);
111994ee 3771 } else {
4ba9938c 3772 ot = MO_64;
111994ee 3773 }
4242b1bd 3774
24b9c00f 3775 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[reg]);
111994ee 3776 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
c66f9727
EC
3777 gen_helper_crc32(s->T0, cpu_tmp2_i32,
3778 s->T0, tcg_const_i32(8 << ot));
222a3336 3779
ab4e4aec 3780 ot = mo_64_32(s->dflag);
c66f9727 3781 gen_op_mov_reg_v(ot, reg, s->T0);
111994ee 3782 break;
222a3336 3783
111994ee
RH
3784 case 0x1f0: /* crc32 or movbe */
3785 case 0x1f1:
3786 /* For these insns, the f3 prefix is supposed to have priority
3787 over the 66 prefix, but that's not what we implement above
3788 setting b1. */
3789 if (s->prefix & PREFIX_REPNZ) {
3790 goto do_crc32;
3791 }
3792 /* FALLTHRU */
3793 case 0x0f0: /* movbe Gy,My */
3794 case 0x0f1: /* movbe My,Gy */
3795 if (!(s->cpuid_ext_features & CPUID_EXT_MOVBE)) {
3796 goto illegal_op;
3797 }
ab4e4aec 3798 if (s->dflag != MO_64) {
4ba9938c 3799 ot = (s->prefix & PREFIX_DATA ? MO_16 : MO_32);
111994ee 3800 } else {
4ba9938c 3801 ot = MO_64;
111994ee
RH
3802 }
3803
3655a19f 3804 gen_lea_modrm(env, s, modrm);
111994ee 3805 if ((b & 1) == 0) {
c66f9727 3806 tcg_gen_qemu_ld_tl(s->T0, s->A0,
3655a19f 3807 s->mem_index, ot | MO_BE);
c66f9727 3808 gen_op_mov_reg_v(ot, reg, s->T0);
111994ee 3809 } else {
6b672b5d 3810 tcg_gen_qemu_st_tl(cpu_regs[reg], s->A0,
3655a19f 3811 s->mem_index, ot | MO_BE);
111994ee
RH
3812 }
3813 break;
3814
7073fbad
RH
3815 case 0x0f2: /* andn Gy, By, Ey */
3816 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)
3817 || !(s->prefix & PREFIX_VEX)
3818 || s->vex_l != 0) {
3819 goto illegal_op;
3820 }
ab4e4aec 3821 ot = mo_64_32(s->dflag);
7073fbad 3822 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
c66f9727
EC
3823 tcg_gen_andc_tl(s->T0, s->T0, cpu_regs[s->vex_v]);
3824 gen_op_mov_reg_v(ot, reg, s->T0);
3825 gen_op_update1_cc(s);
7073fbad
RH
3826 set_cc_op(s, CC_OP_LOGICB + ot);
3827 break;
3828
c7ab7565
RH
3829 case 0x0f7: /* bextr Gy, Ey, By */
3830 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)
3831 || !(s->prefix & PREFIX_VEX)
3832 || s->vex_l != 0) {
3833 goto illegal_op;
3834 }
ab4e4aec 3835 ot = mo_64_32(s->dflag);
c7ab7565
RH
3836 {
3837 TCGv bound, zero;
3838
3839 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3840 /* Extract START, and shift the operand.
3841 Shifts larger than operand size get zeros. */
6b672b5d 3842 tcg_gen_ext8u_tl(s->A0, cpu_regs[s->vex_v]);
c66f9727 3843 tcg_gen_shr_tl(s->T0, s->T0, s->A0);
c7ab7565 3844
4ba9938c 3845 bound = tcg_const_tl(ot == MO_64 ? 63 : 31);
c7ab7565 3846 zero = tcg_const_tl(0);
c66f9727
EC
3847 tcg_gen_movcond_tl(TCG_COND_LEU, s->T0, s->A0, bound,
3848 s->T0, zero);
c7ab7565
RH
3849 tcg_temp_free(zero);
3850
3851 /* Extract the LEN into a mask. Lengths larger than
3852 operand size get all ones. */
6b672b5d
EC
3853 tcg_gen_extract_tl(s->A0, cpu_regs[s->vex_v], 8, 8);
3854 tcg_gen_movcond_tl(TCG_COND_LEU, s->A0, s->A0, bound,
3855 s->A0, bound);
c7ab7565 3856 tcg_temp_free(bound);
1d1cc4d0 3857 tcg_gen_movi_tl(cpu_T1, 1);
6b672b5d 3858 tcg_gen_shl_tl(cpu_T1, cpu_T1, s->A0);
1d1cc4d0 3859 tcg_gen_subi_tl(cpu_T1, cpu_T1, 1);
c66f9727 3860 tcg_gen_and_tl(s->T0, s->T0, cpu_T1);
c7ab7565 3861
c66f9727
EC
3862 gen_op_mov_reg_v(ot, reg, s->T0);
3863 gen_op_update1_cc(s);
c7ab7565
RH
3864 set_cc_op(s, CC_OP_LOGICB + ot);
3865 }
3866 break;
3867
02ea1e6b
RH
3868 case 0x0f5: /* bzhi Gy, Ey, By */
3869 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
3870 || !(s->prefix & PREFIX_VEX)
3871 || s->vex_l != 0) {
3872 goto illegal_op;
3873 }
ab4e4aec 3874 ot = mo_64_32(s->dflag);
02ea1e6b 3875 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
1d1cc4d0 3876 tcg_gen_ext8u_tl(cpu_T1, cpu_regs[s->vex_v]);
02ea1e6b 3877 {
4ba9938c 3878 TCGv bound = tcg_const_tl(ot == MO_64 ? 63 : 31);
02ea1e6b
RH
3879 /* Note that since we're using BMILG (in order to get O
3880 cleared) we need to store the inverse into C. */
3881 tcg_gen_setcond_tl(TCG_COND_LT, cpu_cc_src,
1d1cc4d0
RH
3882 cpu_T1, bound);
3883 tcg_gen_movcond_tl(TCG_COND_GT, cpu_T1, cpu_T1,
3884 bound, bound, cpu_T1);
02ea1e6b
RH
3885 tcg_temp_free(bound);
3886 }
6b672b5d
EC
3887 tcg_gen_movi_tl(s->A0, -1);
3888 tcg_gen_shl_tl(s->A0, s->A0, cpu_T1);
c66f9727
EC
3889 tcg_gen_andc_tl(s->T0, s->T0, s->A0);
3890 gen_op_mov_reg_v(ot, reg, s->T0);
3891 gen_op_update1_cc(s);
02ea1e6b
RH
3892 set_cc_op(s, CC_OP_BMILGB + ot);
3893 break;
3894
5f1f4b17
RH
3895 case 0x3f6: /* mulx By, Gy, rdx, Ey */
3896 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
3897 || !(s->prefix & PREFIX_VEX)
3898 || s->vex_l != 0) {
3899 goto illegal_op;
3900 }
ab4e4aec 3901 ot = mo_64_32(s->dflag);
5f1f4b17
RH
3902 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3903 switch (ot) {
5f1f4b17 3904 default:
c66f9727 3905 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, s->T0);
a4bcea3d
RH
3906 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_regs[R_EDX]);
3907 tcg_gen_mulu2_i32(cpu_tmp2_i32, cpu_tmp3_i32,
3908 cpu_tmp2_i32, cpu_tmp3_i32);
3909 tcg_gen_extu_i32_tl(cpu_regs[s->vex_v], cpu_tmp2_i32);
3910 tcg_gen_extu_i32_tl(cpu_regs[reg], cpu_tmp3_i32);
5f1f4b17
RH
3911 break;
3912#ifdef TARGET_X86_64
4ba9938c 3913 case MO_64:
c66f9727
EC
3914 tcg_gen_mulu2_i64(s->T0, cpu_T1,
3915 s->T0, cpu_regs[R_EDX]);
3916 tcg_gen_mov_i64(cpu_regs[s->vex_v], s->T0);
1d1cc4d0 3917 tcg_gen_mov_i64(cpu_regs[reg], cpu_T1);
5f1f4b17
RH
3918 break;
3919#endif
3920 }
3921 break;
3922
0592f74a
RH
3923 case 0x3f5: /* pdep Gy, By, Ey */
3924 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
3925 || !(s->prefix & PREFIX_VEX)
3926 || s->vex_l != 0) {
3927 goto illegal_op;
3928 }
ab4e4aec 3929 ot = mo_64_32(s->dflag);
0592f74a
RH
3930 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3931 /* Note that by zero-extending the mask operand, we
3932 automatically handle zero-extending the result. */
ab4e4aec 3933 if (ot == MO_64) {
1d1cc4d0 3934 tcg_gen_mov_tl(cpu_T1, cpu_regs[s->vex_v]);
0592f74a 3935 } else {
1d1cc4d0 3936 tcg_gen_ext32u_tl(cpu_T1, cpu_regs[s->vex_v]);
0592f74a 3937 }
c66f9727 3938 gen_helper_pdep(cpu_regs[reg], s->T0, cpu_T1);
0592f74a
RH
3939 break;
3940
3941 case 0x2f5: /* pext Gy, By, Ey */
3942 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
3943 || !(s->prefix & PREFIX_VEX)
3944 || s->vex_l != 0) {
3945 goto illegal_op;
3946 }
ab4e4aec 3947 ot = mo_64_32(s->dflag);
0592f74a
RH
3948 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3949 /* Note that by zero-extending the mask operand, we
3950 automatically handle zero-extending the result. */
ab4e4aec 3951 if (ot == MO_64) {
1d1cc4d0 3952 tcg_gen_mov_tl(cpu_T1, cpu_regs[s->vex_v]);
0592f74a 3953 } else {
1d1cc4d0 3954 tcg_gen_ext32u_tl(cpu_T1, cpu_regs[s->vex_v]);
0592f74a 3955 }
c66f9727 3956 gen_helper_pext(cpu_regs[reg], s->T0, cpu_T1);
0592f74a
RH
3957 break;
3958
cd7f97ca
RH
3959 case 0x1f6: /* adcx Gy, Ey */
3960 case 0x2f6: /* adox Gy, Ey */
3961 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_ADX)) {
3962 goto illegal_op;
3963 } else {
76f13133 3964 TCGv carry_in, carry_out, zero;
cd7f97ca
RH
3965 int end_op;
3966
ab4e4aec 3967 ot = mo_64_32(s->dflag);
cd7f97ca
RH
3968 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3969
3970 /* Re-use the carry-out from a previous round. */
f764718d 3971 carry_in = NULL;
cd7f97ca
RH
3972 carry_out = (b == 0x1f6 ? cpu_cc_dst : cpu_cc_src2);
3973 switch (s->cc_op) {
3974 case CC_OP_ADCX:
3975 if (b == 0x1f6) {
3976 carry_in = cpu_cc_dst;
3977 end_op = CC_OP_ADCX;
3978 } else {
3979 end_op = CC_OP_ADCOX;
3980 }
3981 break;
3982 case CC_OP_ADOX:
3983 if (b == 0x1f6) {
3984 end_op = CC_OP_ADCOX;
3985 } else {
3986 carry_in = cpu_cc_src2;
3987 end_op = CC_OP_ADOX;
3988 }
3989 break;
3990 case CC_OP_ADCOX:
3991 end_op = CC_OP_ADCOX;
3992 carry_in = carry_out;
3993 break;
3994 default:
c53de1a2 3995 end_op = (b == 0x1f6 ? CC_OP_ADCX : CC_OP_ADOX);
cd7f97ca
RH
3996 break;
3997 }
3998 /* If we can't reuse carry-out, get it out of EFLAGS. */
f764718d 3999 if (!carry_in) {
cd7f97ca
RH
4000 if (s->cc_op != CC_OP_ADCX && s->cc_op != CC_OP_ADOX) {
4001 gen_compute_eflags(s);
4002 }
4003 carry_in = cpu_tmp0;
04fc2f1c
RH
4004 tcg_gen_extract_tl(carry_in, cpu_cc_src,
4005 ctz32(b == 0x1f6 ? CC_C : CC_O), 1);
cd7f97ca
RH
4006 }
4007
4008 switch (ot) {
4009#ifdef TARGET_X86_64
4ba9938c 4010 case MO_32:
cd7f97ca
RH
4011 /* If we know TL is 64-bit, and we want a 32-bit
4012 result, just do everything in 64-bit arithmetic. */
4013 tcg_gen_ext32u_i64(cpu_regs[reg], cpu_regs[reg]);
c66f9727
EC
4014 tcg_gen_ext32u_i64(s->T0, s->T0);
4015 tcg_gen_add_i64(s->T0, s->T0, cpu_regs[reg]);
4016 tcg_gen_add_i64(s->T0, s->T0, carry_in);
4017 tcg_gen_ext32u_i64(cpu_regs[reg], s->T0);
4018 tcg_gen_shri_i64(carry_out, s->T0, 32);
cd7f97ca
RH
4019 break;
4020#endif
4021 default:
4022 /* Otherwise compute the carry-out in two steps. */
76f13133 4023 zero = tcg_const_tl(0);
c66f9727
EC
4024 tcg_gen_add2_tl(s->T0, carry_out,
4025 s->T0, zero,
76f13133
RH
4026 carry_in, zero);
4027 tcg_gen_add2_tl(cpu_regs[reg], carry_out,
4028 cpu_regs[reg], carry_out,
c66f9727 4029 s->T0, zero);
76f13133 4030 tcg_temp_free(zero);
cd7f97ca
RH
4031 break;
4032 }
cd7f97ca
RH
4033 set_cc_op(s, end_op);
4034 }
4035 break;
4036
4a554890
RH
4037 case 0x1f7: /* shlx Gy, Ey, By */
4038 case 0x2f7: /* sarx Gy, Ey, By */
4039 case 0x3f7: /* shrx Gy, Ey, By */
4040 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
4041 || !(s->prefix & PREFIX_VEX)
4042 || s->vex_l != 0) {
4043 goto illegal_op;
4044 }
ab4e4aec 4045 ot = mo_64_32(s->dflag);
4a554890 4046 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4ba9938c 4047 if (ot == MO_64) {
1d1cc4d0 4048 tcg_gen_andi_tl(cpu_T1, cpu_regs[s->vex_v], 63);
4a554890 4049 } else {
1d1cc4d0 4050 tcg_gen_andi_tl(cpu_T1, cpu_regs[s->vex_v], 31);
4a554890
RH
4051 }
4052 if (b == 0x1f7) {
c66f9727 4053 tcg_gen_shl_tl(s->T0, s->T0, cpu_T1);
4a554890 4054 } else if (b == 0x2f7) {
4ba9938c 4055 if (ot != MO_64) {
c66f9727 4056 tcg_gen_ext32s_tl(s->T0, s->T0);
4a554890 4057 }
c66f9727 4058 tcg_gen_sar_tl(s->T0, s->T0, cpu_T1);
4a554890 4059 } else {
4ba9938c 4060 if (ot != MO_64) {
c66f9727 4061 tcg_gen_ext32u_tl(s->T0, s->T0);
4a554890 4062 }
c66f9727 4063 tcg_gen_shr_tl(s->T0, s->T0, cpu_T1);
4a554890 4064 }
c66f9727 4065 gen_op_mov_reg_v(ot, reg, s->T0);
4a554890
RH
4066 break;
4067
bc4b43dc
RH
4068 case 0x0f3:
4069 case 0x1f3:
4070 case 0x2f3:
4071 case 0x3f3: /* Group 17 */
4072 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)
4073 || !(s->prefix & PREFIX_VEX)
4074 || s->vex_l != 0) {
4075 goto illegal_op;
4076 }
ab4e4aec 4077 ot = mo_64_32(s->dflag);
bc4b43dc
RH
4078 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4079
c66f9727 4080 tcg_gen_mov_tl(cpu_cc_src, s->T0);
bc4b43dc
RH
4081 switch (reg & 7) {
4082 case 1: /* blsr By,Ey */
c66f9727
EC
4083 tcg_gen_subi_tl(cpu_T1, s->T0, 1);
4084 tcg_gen_and_tl(s->T0, s->T0, cpu_T1);
bc4b43dc 4085 break;
bc4b43dc 4086 case 2: /* blsmsk By,Ey */
c66f9727
EC
4087 tcg_gen_subi_tl(cpu_T1, s->T0, 1);
4088 tcg_gen_xor_tl(s->T0, s->T0, cpu_T1);
bc4b43dc 4089 break;
bc4b43dc 4090 case 3: /* blsi By, Ey */
c66f9727
EC
4091 tcg_gen_neg_tl(cpu_T1, s->T0);
4092 tcg_gen_and_tl(s->T0, s->T0, cpu_T1);
bc4b43dc 4093 break;
bc4b43dc 4094 default:
b9f9c5b4 4095 goto unknown_op;
bc4b43dc 4096 }
c66f9727
EC
4097 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
4098 gen_op_mov_reg_v(ot, s->vex_v, s->T0);
13672386 4099 set_cc_op(s, CC_OP_BMILGB + ot);
bc4b43dc
RH
4100 break;
4101
111994ee 4102 default:
b9f9c5b4 4103 goto unknown_op;
111994ee 4104 }
222a3336 4105 break;
111994ee 4106
222a3336
AZ
4107 case 0x03a:
4108 case 0x13a:
4242b1bd 4109 b = modrm;
e3af7c78 4110 modrm = x86_ldub_code(env, s);
4242b1bd
AZ
4111 rm = modrm & 7;
4112 reg = ((modrm >> 3) & 7) | rex_r;
4113 mod = (modrm >> 6) & 3;
c045af25 4114 if (b1 >= 2) {
b9f9c5b4 4115 goto unknown_op;
c045af25 4116 }
4242b1bd 4117
d3eb5eae
BS
4118 sse_fn_eppi = sse_op_table7[b].op[b1];
4119 if (!sse_fn_eppi) {
b9f9c5b4 4120 goto unknown_op;
c4baa050 4121 }
222a3336
AZ
4122 if (!(s->cpuid_ext_features & sse_op_table7[b].ext_mask))
4123 goto illegal_op;
4124
c6a82429
JM
4125 s->rip_offset = 1;
4126
d3eb5eae 4127 if (sse_fn_eppi == SSE_SPECIAL) {
ab4e4aec 4128 ot = mo_64_32(s->dflag);
222a3336
AZ
4129 rm = (modrm & 7) | REX_B(s);
4130 if (mod != 3)
4eeb3939 4131 gen_lea_modrm(env, s, modrm);
222a3336 4132 reg = ((modrm >> 3) & 7) | rex_r;
e3af7c78 4133 val = x86_ldub_code(env, s);
222a3336
AZ
4134 switch (b) {
4135 case 0x14: /* pextrb */
c66f9727 4136 tcg_gen_ld8u_tl(s->T0, cpu_env, offsetof(CPUX86State,
19cbd87c 4137 xmm_regs[reg].ZMM_B(val & 15)));
3523e4bd 4138 if (mod == 3) {
c66f9727 4139 gen_op_mov_reg_v(ot, rm, s->T0);
3523e4bd 4140 } else {
c66f9727 4141 tcg_gen_qemu_st_tl(s->T0, s->A0,
3523e4bd
RH
4142 s->mem_index, MO_UB);
4143 }
222a3336
AZ
4144 break;
4145 case 0x15: /* pextrw */
c66f9727 4146 tcg_gen_ld16u_tl(s->T0, cpu_env, offsetof(CPUX86State,
19cbd87c 4147 xmm_regs[reg].ZMM_W(val & 7)));
3523e4bd 4148 if (mod == 3) {
c66f9727 4149 gen_op_mov_reg_v(ot, rm, s->T0);
3523e4bd 4150 } else {
c66f9727 4151 tcg_gen_qemu_st_tl(s->T0, s->A0,
3523e4bd
RH
4152 s->mem_index, MO_LEUW);
4153 }
222a3336
AZ
4154 break;
4155 case 0x16:
4ba9938c 4156 if (ot == MO_32) { /* pextrd */
222a3336
AZ
4157 tcg_gen_ld_i32(cpu_tmp2_i32, cpu_env,
4158 offsetof(CPUX86State,
19cbd87c 4159 xmm_regs[reg].ZMM_L(val & 3)));
3523e4bd 4160 if (mod == 3) {
a7fbcbe5 4161 tcg_gen_extu_i32_tl(cpu_regs[rm], cpu_tmp2_i32);
3523e4bd 4162 } else {
6b672b5d 4163 tcg_gen_qemu_st_i32(cpu_tmp2_i32, s->A0,
d5601ad0 4164 s->mem_index, MO_LEUL);
3523e4bd 4165 }
222a3336 4166 } else { /* pextrq */
a7812ae4 4167#ifdef TARGET_X86_64
222a3336
AZ
4168 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env,
4169 offsetof(CPUX86State,
19cbd87c 4170 xmm_regs[reg].ZMM_Q(val & 1)));
3523e4bd 4171 if (mod == 3) {
a7fbcbe5 4172 tcg_gen_mov_i64(cpu_regs[rm], cpu_tmp1_i64);
3523e4bd 4173 } else {
6b672b5d 4174 tcg_gen_qemu_st_i64(cpu_tmp1_i64, s->A0,
3523e4bd
RH
4175 s->mem_index, MO_LEQ);
4176 }
a7812ae4
PB
4177#else
4178 goto illegal_op;
4179#endif
222a3336
AZ
4180 }
4181 break;
4182 case 0x17: /* extractps */
c66f9727 4183 tcg_gen_ld32u_tl(s->T0, cpu_env, offsetof(CPUX86State,
19cbd87c 4184 xmm_regs[reg].ZMM_L(val & 3)));
3523e4bd 4185 if (mod == 3) {
c66f9727 4186 gen_op_mov_reg_v(ot, rm, s->T0);
3523e4bd 4187 } else {
c66f9727 4188 tcg_gen_qemu_st_tl(s->T0, s->A0,
3523e4bd
RH
4189 s->mem_index, MO_LEUL);
4190 }
222a3336
AZ
4191 break;
4192 case 0x20: /* pinsrb */
3c5f4116 4193 if (mod == 3) {
c66f9727 4194 gen_op_mov_v_reg(MO_32, s->T0, rm);
3c5f4116 4195 } else {
c66f9727 4196 tcg_gen_qemu_ld_tl(s->T0, s->A0,
3c5f4116
RH
4197 s->mem_index, MO_UB);
4198 }
c66f9727 4199 tcg_gen_st8_tl(s->T0, cpu_env, offsetof(CPUX86State,
19cbd87c 4200 xmm_regs[reg].ZMM_B(val & 15)));
222a3336
AZ
4201 break;
4202 case 0x21: /* insertps */
a7812ae4 4203 if (mod == 3) {
222a3336
AZ
4204 tcg_gen_ld_i32(cpu_tmp2_i32, cpu_env,
4205 offsetof(CPUX86State,xmm_regs[rm]
19cbd87c 4206 .ZMM_L((val >> 6) & 3)));
a7812ae4 4207 } else {
6b672b5d 4208 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, s->A0,
3c5f4116 4209 s->mem_index, MO_LEUL);
a7812ae4 4210 }
222a3336
AZ
4211 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env,
4212 offsetof(CPUX86State,xmm_regs[reg]
19cbd87c 4213 .ZMM_L((val >> 4) & 3)));
222a3336
AZ
4214 if ((val >> 0) & 1)
4215 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4216 cpu_env, offsetof(CPUX86State,
19cbd87c 4217 xmm_regs[reg].ZMM_L(0)));
222a3336
AZ
4218 if ((val >> 1) & 1)
4219 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4220 cpu_env, offsetof(CPUX86State,
19cbd87c 4221 xmm_regs[reg].ZMM_L(1)));
222a3336
AZ
4222 if ((val >> 2) & 1)
4223 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4224 cpu_env, offsetof(CPUX86State,
19cbd87c 4225 xmm_regs[reg].ZMM_L(2)));
222a3336
AZ
4226 if ((val >> 3) & 1)
4227 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4228 cpu_env, offsetof(CPUX86State,
19cbd87c 4229 xmm_regs[reg].ZMM_L(3)));
222a3336
AZ
4230 break;
4231 case 0x22:
4ba9938c 4232 if (ot == MO_32) { /* pinsrd */
3c5f4116 4233 if (mod == 3) {
80b02013 4234 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[rm]);
3c5f4116 4235 } else {
6b672b5d 4236 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, s->A0,
80b02013 4237 s->mem_index, MO_LEUL);
3c5f4116 4238 }
222a3336
AZ
4239 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env,
4240 offsetof(CPUX86State,
19cbd87c 4241 xmm_regs[reg].ZMM_L(val & 3)));
222a3336 4242 } else { /* pinsrq */
a7812ae4 4243#ifdef TARGET_X86_64
3c5f4116 4244 if (mod == 3) {
222a3336 4245 gen_op_mov_v_reg(ot, cpu_tmp1_i64, rm);
3c5f4116 4246 } else {
6b672b5d 4247 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, s->A0,
3c5f4116
RH
4248 s->mem_index, MO_LEQ);
4249 }
222a3336
AZ
4250 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env,
4251 offsetof(CPUX86State,
19cbd87c 4252 xmm_regs[reg].ZMM_Q(val & 1)));
a7812ae4
PB
4253#else
4254 goto illegal_op;
4255#endif
222a3336
AZ
4256 }
4257 break;
4258 }
4259 return;
4260 }
4242b1bd
AZ
4261
4262 if (b1) {
4263 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
4264 if (mod == 3) {
4265 op2_offset = offsetof(CPUX86State,xmm_regs[rm | REX_B(s)]);
4266 } else {
4267 op2_offset = offsetof(CPUX86State,xmm_t0);
4eeb3939 4268 gen_lea_modrm(env, s, modrm);
323d1876 4269 gen_ldo_env_A0(s, op2_offset);
4242b1bd
AZ
4270 }
4271 } else {
4272 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
4273 if (mod == 3) {
4274 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
4275 } else {
4276 op2_offset = offsetof(CPUX86State,mmx_t0);
4eeb3939 4277 gen_lea_modrm(env, s, modrm);
323d1876 4278 gen_ldq_env_A0(s, op2_offset);
4242b1bd
AZ
4279 }
4280 }
e3af7c78 4281 val = x86_ldub_code(env, s);
4242b1bd 4282
222a3336 4283 if ((b & 0xfc) == 0x60) { /* pcmpXstrX */
3ca51d07 4284 set_cc_op(s, CC_OP_EFLAGS);
222a3336 4285
ab4e4aec 4286 if (s->dflag == MO_64) {
222a3336
AZ
4287 /* The helper must use entire 64-bit gp registers */
4288 val |= 1 << 8;
ab4e4aec 4289 }
222a3336
AZ
4290 }
4291
4242b1bd
AZ
4292 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4293 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
d3eb5eae 4294 sse_fn_eppi(cpu_env, cpu_ptr0, cpu_ptr1, tcg_const_i32(val));
4242b1bd 4295 break;
e2c3c2c5
RH
4296
4297 case 0x33a:
4298 /* Various integer extensions at 0f 3a f[0-f]. */
4299 b = modrm | (b1 << 8);
e3af7c78 4300 modrm = x86_ldub_code(env, s);
e2c3c2c5
RH
4301 reg = ((modrm >> 3) & 7) | rex_r;
4302
4303 switch (b) {
4304 case 0x3f0: /* rorx Gy,Ey, Ib */
4305 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
4306 || !(s->prefix & PREFIX_VEX)
4307 || s->vex_l != 0) {
4308 goto illegal_op;
4309 }
ab4e4aec 4310 ot = mo_64_32(s->dflag);
e2c3c2c5 4311 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
e3af7c78 4312 b = x86_ldub_code(env, s);
4ba9938c 4313 if (ot == MO_64) {
c66f9727 4314 tcg_gen_rotri_tl(s->T0, s->T0, b & 63);
e2c3c2c5 4315 } else {
c66f9727 4316 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, s->T0);
e2c3c2c5 4317 tcg_gen_rotri_i32(cpu_tmp2_i32, cpu_tmp2_i32, b & 31);
c66f9727 4318 tcg_gen_extu_i32_tl(s->T0, cpu_tmp2_i32);
e2c3c2c5 4319 }
c66f9727 4320 gen_op_mov_reg_v(ot, reg, s->T0);
e2c3c2c5
RH
4321 break;
4322
4323 default:
b9f9c5b4 4324 goto unknown_op;
e2c3c2c5
RH
4325 }
4326 break;
4327
664e0f19 4328 default:
b9f9c5b4
RH
4329 unknown_op:
4330 gen_unknown_opcode(env, s);
4331 return;
664e0f19
FB
4332 }
4333 } else {
4334 /* generic MMX or SSE operation */
d1e42c5c 4335 switch(b) {
d1e42c5c
FB
4336 case 0x70: /* pshufx insn */
4337 case 0xc6: /* pshufx insn */
4338 case 0xc2: /* compare insns */
4339 s->rip_offset = 1;
4340 break;
4341 default:
4342 break;
664e0f19
FB
4343 }
4344 if (is_xmm) {
4345 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
4346 if (mod != 3) {
cb48da7f
RH
4347 int sz = 4;
4348
4eeb3939 4349 gen_lea_modrm(env, s, modrm);
664e0f19 4350 op2_offset = offsetof(CPUX86State,xmm_t0);
cb48da7f
RH
4351
4352 switch (b) {
4353 case 0x50 ... 0x5a:
4354 case 0x5c ... 0x5f:
4355 case 0xc2:
4356 /* Most sse scalar operations. */
664e0f19 4357 if (b1 == 2) {
cb48da7f
RH
4358 sz = 2;
4359 } else if (b1 == 3) {
4360 sz = 3;
4361 }
4362 break;
4363
4364 case 0x2e: /* ucomis[sd] */
4365 case 0x2f: /* comis[sd] */
4366 if (b1 == 0) {
4367 sz = 2;
664e0f19 4368 } else {
cb48da7f 4369 sz = 3;
664e0f19 4370 }
cb48da7f
RH
4371 break;
4372 }
4373
4374 switch (sz) {
4375 case 2:
4376 /* 32 bit access */
c66f9727
EC
4377 gen_op_ld_v(s, MO_32, s->T0, s->A0);
4378 tcg_gen_st32_tl(s->T0, cpu_env,
19cbd87c 4379 offsetof(CPUX86State,xmm_t0.ZMM_L(0)));
cb48da7f
RH
4380 break;
4381 case 3:
4382 /* 64 bit access */
19cbd87c 4383 gen_ldq_env_A0(s, offsetof(CPUX86State, xmm_t0.ZMM_D(0)));
cb48da7f
RH
4384 break;
4385 default:
4386 /* 128 bit access */
323d1876 4387 gen_ldo_env_A0(s, op2_offset);
cb48da7f 4388 break;
664e0f19
FB
4389 }
4390 } else {
4391 rm = (modrm & 7) | REX_B(s);
4392 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
4393 }
4394 } else {
4395 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
4396 if (mod != 3) {
4eeb3939 4397 gen_lea_modrm(env, s, modrm);
664e0f19 4398 op2_offset = offsetof(CPUX86State,mmx_t0);
323d1876 4399 gen_ldq_env_A0(s, op2_offset);
664e0f19
FB
4400 } else {
4401 rm = (modrm & 7);
4402 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
4403 }
4404 }
4405 switch(b) {
a35f3ec7 4406 case 0x0f: /* 3DNow! data insns */
e3af7c78 4407 val = x86_ldub_code(env, s);
d3eb5eae
BS
4408 sse_fn_epp = sse_op_table5[val];
4409 if (!sse_fn_epp) {
b9f9c5b4
RH
4410 goto unknown_op;
4411 }
4412 if (!(s->cpuid_ext2_features & CPUID_EXT2_3DNOW)) {
a35f3ec7 4413 goto illegal_op;
c4baa050 4414 }
5af45186
FB
4415 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4416 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
d3eb5eae 4417 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
a35f3ec7 4418 break;
664e0f19
FB
4419 case 0x70: /* pshufx insn */
4420 case 0xc6: /* pshufx insn */
e3af7c78 4421 val = x86_ldub_code(env, s);
5af45186
FB
4422 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4423 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
c4baa050 4424 /* XXX: introduce a new table? */
d3eb5eae 4425 sse_fn_ppi = (SSEFunc_0_ppi)sse_fn_epp;
c4baa050 4426 sse_fn_ppi(cpu_ptr0, cpu_ptr1, tcg_const_i32(val));
664e0f19
FB
4427 break;
4428 case 0xc2:
4429 /* compare insns */
e3af7c78 4430 val = x86_ldub_code(env, s);
664e0f19 4431 if (val >= 8)
b9f9c5b4 4432 goto unknown_op;
d3eb5eae 4433 sse_fn_epp = sse_op_table4[val][b1];
c4baa050 4434
5af45186
FB
4435 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4436 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
d3eb5eae 4437 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
664e0f19 4438 break;
b8b6a50b
FB
4439 case 0xf7:
4440 /* maskmov : we must prepare A0 */
4441 if (mod != 3)
4442 goto illegal_op;
6b672b5d
EC
4443 tcg_gen_mov_tl(s->A0, cpu_regs[R_EDI]);
4444 gen_extu(s->aflag, s->A0);
b8b6a50b
FB
4445 gen_add_A0_ds_seg(s);
4446
4447 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4448 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
c4baa050 4449 /* XXX: introduce a new table? */
d3eb5eae 4450 sse_fn_eppt = (SSEFunc_0_eppt)sse_fn_epp;
6b672b5d 4451 sse_fn_eppt(cpu_env, cpu_ptr0, cpu_ptr1, s->A0);
b8b6a50b 4452 break;
664e0f19 4453 default:
5af45186
FB
4454 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4455 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
d3eb5eae 4456 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
664e0f19
FB
4457 break;
4458 }
4459 if (b == 0x2e || b == 0x2f) {
3ca51d07 4460 set_cc_op(s, CC_OP_EFLAGS);
664e0f19
FB
4461 }
4462 }
4463}
4464
6cf147aa 4465/* convert one instruction. s->base.is_jmp is set if the translation must
2c0262af 4466 be stopped. Return the next pc value */
2c2f8cac 4467static target_ulong disas_insn(DisasContext *s, CPUState *cpu)
2c0262af 4468{
2c2f8cac 4469 CPUX86State *env = cpu->env_ptr;
ab4e4aec 4470 int b, prefixes;
d67dc9e6 4471 int shift;
ab4e4aec 4472 TCGMemOp ot, aflag, dflag;
4eeb3939 4473 int modrm, reg, rm, mod, op, opreg, val;
14ce26e7
FB
4474 target_ulong next_eip, tval;
4475 int rex_w, rex_r;
2c2f8cac 4476 target_ulong pc_start = s->base.pc_next;
2c0262af 4477
b9f9c5b4 4478 s->pc_start = s->pc = pc_start;
2c0262af 4479 s->override = -1;
14ce26e7
FB
4480#ifdef TARGET_X86_64
4481 s->rex_x = 0;
4482 s->rex_b = 0;
5fafdf24 4483 x86_64_hregs = 0;
14ce26e7
FB
4484#endif
4485 s->rip_offset = 0; /* for relative ip address */
701ed211
RH
4486 s->vex_l = 0;
4487 s->vex_v = 0;
b066c537
PB
4488 if (sigsetjmp(s->jmpbuf, 0) != 0) {
4489 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
4490 return s->pc;
30663fd2 4491 }
b066c537 4492
a4926d99
SW
4493 prefixes = 0;
4494 rex_w = -1;
4495 rex_r = 0;
4496
b066c537 4497 next_byte:
e3af7c78 4498 b = x86_ldub_code(env, s);
4a6fd938
RH
4499 /* Collect prefixes. */
4500 switch (b) {
4501 case 0xf3:
4502 prefixes |= PREFIX_REPZ;
4503 goto next_byte;
4504 case 0xf2:
4505 prefixes |= PREFIX_REPNZ;
4506 goto next_byte;
4507 case 0xf0:
4508 prefixes |= PREFIX_LOCK;
4509 goto next_byte;
4510 case 0x2e:
4511 s->override = R_CS;
4512 goto next_byte;
4513 case 0x36:
4514 s->override = R_SS;
4515 goto next_byte;
4516 case 0x3e:
4517 s->override = R_DS;
4518 goto next_byte;
4519 case 0x26:
4520 s->override = R_ES;
4521 goto next_byte;
4522 case 0x64:
4523 s->override = R_FS;
4524 goto next_byte;
4525 case 0x65:
4526 s->override = R_GS;
4527 goto next_byte;
4528 case 0x66:
4529 prefixes |= PREFIX_DATA;
4530 goto next_byte;
4531 case 0x67:
4532 prefixes |= PREFIX_ADR;
4533 goto next_byte;
14ce26e7 4534#ifdef TARGET_X86_64
4a6fd938
RH
4535 case 0x40 ... 0x4f:
4536 if (CODE64(s)) {
14ce26e7
FB
4537 /* REX prefix */
4538 rex_w = (b >> 3) & 1;
4539 rex_r = (b & 0x4) << 1;
4540 s->rex_x = (b & 0x2) << 2;
4541 REX_B(s) = (b & 0x1) << 3;
4542 x86_64_hregs = 1; /* select uniform byte register addressing */
4543 goto next_byte;
4544 }
4a6fd938
RH
4545 break;
4546#endif
701ed211
RH
4547 case 0xc5: /* 2-byte VEX */
4548 case 0xc4: /* 3-byte VEX */
4549 /* VEX prefixes cannot be used except in 32-bit mode.
4550 Otherwise the instruction is LES or LDS. */
4551 if (s->code32 && !s->vm86) {
4552 static const int pp_prefix[4] = {
4553 0, PREFIX_DATA, PREFIX_REPZ, PREFIX_REPNZ
4554 };
e3af7c78 4555 int vex3, vex2 = x86_ldub_code(env, s);
701ed211
RH
4556
4557 if (!CODE64(s) && (vex2 & 0xc0) != 0xc0) {
4558 /* 4.1.4.6: In 32-bit mode, bits [7:6] must be 11b,
4559 otherwise the instruction is LES or LDS. */
cfcca361 4560 s->pc--; /* rewind the advance_pc() x86_ldub_code() did */
701ed211
RH
4561 break;
4562 }
701ed211 4563
085d8134 4564 /* 4.1.1-4.1.3: No preceding lock, 66, f2, f3, or rex prefixes. */
701ed211
RH
4565 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ
4566 | PREFIX_LOCK | PREFIX_DATA)) {
4567 goto illegal_op;
4568 }
4569#ifdef TARGET_X86_64
4570 if (x86_64_hregs) {
4571 goto illegal_op;
4572 }
4573#endif
4574 rex_r = (~vex2 >> 4) & 8;
4575 if (b == 0xc5) {
e0014d4b 4576 /* 2-byte VEX prefix: RVVVVlpp, implied 0f leading opcode byte */
701ed211 4577 vex3 = vex2;
e0014d4b 4578 b = x86_ldub_code(env, s) | 0x100;
701ed211 4579 } else {
e0014d4b 4580 /* 3-byte VEX prefix: RXBmmmmm wVVVVlpp */
701ed211
RH
4581#ifdef TARGET_X86_64
4582 s->rex_x = (~vex2 >> 3) & 8;
4583 s->rex_b = (~vex2 >> 2) & 8;
4584#endif
e3af7c78 4585 vex3 = x86_ldub_code(env, s);
701ed211
RH
4586 rex_w = (vex3 >> 7) & 1;
4587 switch (vex2 & 0x1f) {
4588 case 0x01: /* Implied 0f leading opcode bytes. */
e3af7c78 4589 b = x86_ldub_code(env, s) | 0x100;
701ed211
RH
4590 break;
4591 case 0x02: /* Implied 0f 38 leading opcode bytes. */
4592 b = 0x138;
4593 break;
4594 case 0x03: /* Implied 0f 3a leading opcode bytes. */
4595 b = 0x13a;
4596 break;
4597 default: /* Reserved for future use. */
b9f9c5b4 4598 goto unknown_op;
701ed211
RH
4599 }
4600 }
4601 s->vex_v = (~vex3 >> 3) & 0xf;
4602 s->vex_l = (vex3 >> 2) & 1;
4603 prefixes |= pp_prefix[vex3 & 3] | PREFIX_VEX;
4604 }
4605 break;
4a6fd938
RH
4606 }
4607
4608 /* Post-process prefixes. */
4a6fd938 4609 if (CODE64(s)) {
dec3fc96
RH
4610 /* In 64-bit mode, the default data size is 32-bit. Select 64-bit
4611 data with rex_w, and 16-bit data with 0x66; rex_w takes precedence
4612 over 0x66 if both are present. */
ab4e4aec 4613 dflag = (rex_w > 0 ? MO_64 : prefixes & PREFIX_DATA ? MO_16 : MO_32);
dec3fc96 4614 /* In 64-bit mode, 0x67 selects 32-bit addressing. */
1d71ddb1 4615 aflag = (prefixes & PREFIX_ADR ? MO_32 : MO_64);
dec3fc96
RH
4616 } else {
4617 /* In 16/32-bit mode, 0x66 selects the opposite data size. */
ab4e4aec
RH
4618 if (s->code32 ^ ((prefixes & PREFIX_DATA) != 0)) {
4619 dflag = MO_32;
4620 } else {
4621 dflag = MO_16;
14ce26e7 4622 }
dec3fc96 4623 /* In 16/32-bit mode, 0x67 selects the opposite addressing. */
1d71ddb1
RH
4624 if (s->code32 ^ ((prefixes & PREFIX_ADR) != 0)) {
4625 aflag = MO_32;
4626 } else {
4627 aflag = MO_16;
14ce26e7 4628 }
2c0262af
FB
4629 }
4630
2c0262af
FB
4631 s->prefix = prefixes;
4632 s->aflag = aflag;
4633 s->dflag = dflag;
4634
2c0262af
FB
4635 /* now check op code */
4636 reswitch:
4637 switch(b) {
4638 case 0x0f:
4639 /**************************/
4640 /* extended op code */
e3af7c78 4641 b = x86_ldub_code(env, s) | 0x100;
2c0262af 4642 goto reswitch;
3b46e624 4643
2c0262af
FB
4644 /**************************/
4645 /* arith & logic */
4646 case 0x00 ... 0x05:
4647 case 0x08 ... 0x0d:
4648 case 0x10 ... 0x15:
4649 case 0x18 ... 0x1d:
4650 case 0x20 ... 0x25:
4651 case 0x28 ... 0x2d:
4652 case 0x30 ... 0x35:
4653 case 0x38 ... 0x3d:
4654 {
4655 int op, f, val;
4656 op = (b >> 3) & 7;
4657 f = (b >> 1) & 3;
4658
ab4e4aec 4659 ot = mo_b_d(b, dflag);
3b46e624 4660
2c0262af
FB
4661 switch(f) {
4662 case 0: /* OP Ev, Gv */
e3af7c78 4663 modrm = x86_ldub_code(env, s);
14ce26e7 4664 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af 4665 mod = (modrm >> 6) & 3;
14ce26e7 4666 rm = (modrm & 7) | REX_B(s);
2c0262af 4667 if (mod != 3) {
4eeb3939 4668 gen_lea_modrm(env, s, modrm);
2c0262af
FB
4669 opreg = OR_TMP0;
4670 } else if (op == OP_XORL && rm == reg) {
4671 xor_zero:
4672 /* xor reg, reg optimisation */
436ff2d2 4673 set_cc_op(s, CC_OP_CLR);
c66f9727
EC
4674 tcg_gen_movi_tl(s->T0, 0);
4675 gen_op_mov_reg_v(ot, reg, s->T0);
2c0262af
FB
4676 break;
4677 } else {
4678 opreg = rm;
4679 }
1d1cc4d0 4680 gen_op_mov_v_reg(ot, cpu_T1, reg);
2c0262af
FB
4681 gen_op(s, op, ot, opreg);
4682 break;
4683 case 1: /* OP Gv, Ev */
e3af7c78 4684 modrm = x86_ldub_code(env, s);
2c0262af 4685 mod = (modrm >> 6) & 3;
14ce26e7
FB
4686 reg = ((modrm >> 3) & 7) | rex_r;
4687 rm = (modrm & 7) | REX_B(s);
2c0262af 4688 if (mod != 3) {
4eeb3939 4689 gen_lea_modrm(env, s, modrm);
6b672b5d 4690 gen_op_ld_v(s, ot, cpu_T1, s->A0);
2c0262af
FB
4691 } else if (op == OP_XORL && rm == reg) {
4692 goto xor_zero;
4693 } else {
1d1cc4d0 4694 gen_op_mov_v_reg(ot, cpu_T1, rm);
2c0262af
FB
4695 }
4696 gen_op(s, op, ot, reg);
4697 break;
4698 case 2: /* OP A, Iv */
0af10c86 4699 val = insn_get(env, s, ot);
1d1cc4d0 4700 tcg_gen_movi_tl(cpu_T1, val);
2c0262af
FB
4701 gen_op(s, op, ot, OR_EAX);
4702 break;
4703 }
4704 }
4705 break;
4706
ec9d6075
FB
4707 case 0x82:
4708 if (CODE64(s))
4709 goto illegal_op;
edd7541b 4710 /* fall through */
2c0262af
FB
4711 case 0x80: /* GRP1 */
4712 case 0x81:
4713 case 0x83:
4714 {
4715 int val;
4716
ab4e4aec 4717 ot = mo_b_d(b, dflag);
3b46e624 4718
e3af7c78 4719 modrm = x86_ldub_code(env, s);
2c0262af 4720 mod = (modrm >> 6) & 3;
14ce26e7 4721 rm = (modrm & 7) | REX_B(s);
2c0262af 4722 op = (modrm >> 3) & 7;
3b46e624 4723
2c0262af 4724 if (mod != 3) {
14ce26e7
FB
4725 if (b == 0x83)
4726 s->rip_offset = 1;
4727 else
4728 s->rip_offset = insn_const_size(ot);
4eeb3939 4729 gen_lea_modrm(env, s, modrm);
2c0262af
FB
4730 opreg = OR_TMP0;
4731 } else {
14ce26e7 4732 opreg = rm;
2c0262af
FB
4733 }
4734
4735 switch(b) {
4736 default:
4737 case 0x80:
4738 case 0x81:
d64477af 4739 case 0x82:
0af10c86 4740 val = insn_get(env, s, ot);
2c0262af
FB
4741 break;
4742 case 0x83:
4ba9938c 4743 val = (int8_t)insn_get(env, s, MO_8);
2c0262af
FB
4744 break;
4745 }
1d1cc4d0 4746 tcg_gen_movi_tl(cpu_T1, val);
2c0262af
FB
4747 gen_op(s, op, ot, opreg);
4748 }
4749 break;
4750
4751 /**************************/
4752 /* inc, dec, and other misc arith */
4753 case 0x40 ... 0x47: /* inc Gv */
ab4e4aec 4754 ot = dflag;
2c0262af
FB
4755 gen_inc(s, ot, OR_EAX + (b & 7), 1);
4756 break;
4757 case 0x48 ... 0x4f: /* dec Gv */
ab4e4aec 4758 ot = dflag;
2c0262af
FB
4759 gen_inc(s, ot, OR_EAX + (b & 7), -1);
4760 break;
4761 case 0xf6: /* GRP3 */
4762 case 0xf7:
ab4e4aec 4763 ot = mo_b_d(b, dflag);
2c0262af 4764
e3af7c78 4765 modrm = x86_ldub_code(env, s);
2c0262af 4766 mod = (modrm >> 6) & 3;
14ce26e7 4767 rm = (modrm & 7) | REX_B(s);
2c0262af
FB
4768 op = (modrm >> 3) & 7;
4769 if (mod != 3) {
2a5fe8ae 4770 if (op == 0) {
14ce26e7 4771 s->rip_offset = insn_const_size(ot);
2a5fe8ae 4772 }
4eeb3939 4773 gen_lea_modrm(env, s, modrm);
2a5fe8ae
EC
4774 /* For those below that handle locked memory, don't load here. */
4775 if (!(s->prefix & PREFIX_LOCK)
4776 || op != 2) {
c66f9727 4777 gen_op_ld_v(s, ot, s->T0, s->A0);
2a5fe8ae 4778 }
2c0262af 4779 } else {
c66f9727 4780 gen_op_mov_v_reg(ot, s->T0, rm);
2c0262af
FB
4781 }
4782
4783 switch(op) {
4784 case 0: /* test */
0af10c86 4785 val = insn_get(env, s, ot);
1d1cc4d0 4786 tcg_gen_movi_tl(cpu_T1, val);
c66f9727 4787 gen_op_testl_T0_T1_cc(s);
3ca51d07 4788 set_cc_op(s, CC_OP_LOGICB + ot);
2c0262af
FB
4789 break;
4790 case 2: /* not */
2a5fe8ae
EC
4791 if (s->prefix & PREFIX_LOCK) {
4792 if (mod == 3) {
4793 goto illegal_op;
4794 }
c66f9727
EC
4795 tcg_gen_movi_tl(s->T0, ~0);
4796 tcg_gen_atomic_xor_fetch_tl(s->T0, s->A0, s->T0,
2a5fe8ae 4797 s->mem_index, ot | MO_LE);
2c0262af 4798 } else {
c66f9727 4799 tcg_gen_not_tl(s->T0, s->T0);
2a5fe8ae 4800 if (mod != 3) {
c66f9727 4801 gen_op_st_v(s, ot, s->T0, s->A0);
2a5fe8ae 4802 } else {
c66f9727 4803 gen_op_mov_reg_v(ot, rm, s->T0);
2a5fe8ae 4804 }
2c0262af
FB
4805 }
4806 break;
4807 case 3: /* neg */
8eb8c738
EC
4808 if (s->prefix & PREFIX_LOCK) {
4809 TCGLabel *label1;
4810 TCGv a0, t0, t1, t2;
4811
4812 if (mod == 3) {
4813 goto illegal_op;
4814 }
4815 a0 = tcg_temp_local_new();
4816 t0 = tcg_temp_local_new();
4817 label1 = gen_new_label();
4818
6b672b5d 4819 tcg_gen_mov_tl(a0, s->A0);
c66f9727 4820 tcg_gen_mov_tl(t0, s->T0);
8eb8c738
EC
4821
4822 gen_set_label(label1);
4823 t1 = tcg_temp_new();
4824 t2 = tcg_temp_new();
4825 tcg_gen_mov_tl(t2, t0);
4826 tcg_gen_neg_tl(t1, t0);
4827 tcg_gen_atomic_cmpxchg_tl(t0, a0, t0, t1,
4828 s->mem_index, ot | MO_LE);
4829 tcg_temp_free(t1);
4830 tcg_gen_brcond_tl(TCG_COND_NE, t0, t2, label1);
4831
4832 tcg_temp_free(t2);
4833 tcg_temp_free(a0);
c66f9727 4834 tcg_gen_mov_tl(s->T0, t0);
8eb8c738 4835 tcg_temp_free(t0);
2c0262af 4836 } else {
c66f9727 4837 tcg_gen_neg_tl(s->T0, s->T0);
8eb8c738 4838 if (mod != 3) {
c66f9727 4839 gen_op_st_v(s, ot, s->T0, s->A0);
8eb8c738 4840 } else {
c66f9727 4841 gen_op_mov_reg_v(ot, rm, s->T0);
8eb8c738 4842 }
2c0262af 4843 }
93a3e108 4844 gen_op_update_neg_cc(s);
3ca51d07 4845 set_cc_op(s, CC_OP_SUBB + ot);
2c0262af
FB
4846 break;
4847 case 4: /* mul */
4848 switch(ot) {
4ba9938c 4849 case MO_8:
1d1cc4d0 4850 gen_op_mov_v_reg(MO_8, cpu_T1, R_EAX);
c66f9727 4851 tcg_gen_ext8u_tl(s->T0, s->T0);
1d1cc4d0 4852 tcg_gen_ext8u_tl(cpu_T1, cpu_T1);
0211e5af 4853 /* XXX: use 32 bit mul which could be faster */
c66f9727
EC
4854 tcg_gen_mul_tl(s->T0, s->T0, cpu_T1);
4855 gen_op_mov_reg_v(MO_16, R_EAX, s->T0);
4856 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
4857 tcg_gen_andi_tl(cpu_cc_src, s->T0, 0xff00);
3ca51d07 4858 set_cc_op(s, CC_OP_MULB);
2c0262af 4859 break;
4ba9938c 4860 case MO_16:
1d1cc4d0 4861 gen_op_mov_v_reg(MO_16, cpu_T1, R_EAX);
c66f9727 4862 tcg_gen_ext16u_tl(s->T0, s->T0);
1d1cc4d0 4863 tcg_gen_ext16u_tl(cpu_T1, cpu_T1);
0211e5af 4864 /* XXX: use 32 bit mul which could be faster */
c66f9727
EC
4865 tcg_gen_mul_tl(s->T0, s->T0, cpu_T1);
4866 gen_op_mov_reg_v(MO_16, R_EAX, s->T0);
4867 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
4868 tcg_gen_shri_tl(s->T0, s->T0, 16);
4869 gen_op_mov_reg_v(MO_16, R_EDX, s->T0);
4870 tcg_gen_mov_tl(cpu_cc_src, s->T0);
3ca51d07 4871 set_cc_op(s, CC_OP_MULW);
2c0262af
FB
4872 break;
4873 default:
4ba9938c 4874 case MO_32:
c66f9727 4875 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, s->T0);
a4bcea3d
RH
4876 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_regs[R_EAX]);
4877 tcg_gen_mulu2_i32(cpu_tmp2_i32, cpu_tmp3_i32,
4878 cpu_tmp2_i32, cpu_tmp3_i32);
4879 tcg_gen_extu_i32_tl(cpu_regs[R_EAX], cpu_tmp2_i32);
4880 tcg_gen_extu_i32_tl(cpu_regs[R_EDX], cpu_tmp3_i32);
4881 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
4882 tcg_gen_mov_tl(cpu_cc_src, cpu_regs[R_EDX]);
3ca51d07 4883 set_cc_op(s, CC_OP_MULL);
2c0262af 4884 break;
14ce26e7 4885#ifdef TARGET_X86_64
4ba9938c 4886 case MO_64:
a4bcea3d 4887 tcg_gen_mulu2_i64(cpu_regs[R_EAX], cpu_regs[R_EDX],
c66f9727 4888 s->T0, cpu_regs[R_EAX]);
a4bcea3d
RH
4889 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
4890 tcg_gen_mov_tl(cpu_cc_src, cpu_regs[R_EDX]);
3ca51d07 4891 set_cc_op(s, CC_OP_MULQ);
14ce26e7
FB
4892 break;
4893#endif
2c0262af 4894 }
2c0262af
FB
4895 break;
4896 case 5: /* imul */
4897 switch(ot) {
4ba9938c 4898 case MO_8:
1d1cc4d0 4899 gen_op_mov_v_reg(MO_8, cpu_T1, R_EAX);
c66f9727 4900 tcg_gen_ext8s_tl(s->T0, s->T0);
1d1cc4d0 4901 tcg_gen_ext8s_tl(cpu_T1, cpu_T1);
0211e5af 4902 /* XXX: use 32 bit mul which could be faster */
c66f9727
EC
4903 tcg_gen_mul_tl(s->T0, s->T0, cpu_T1);
4904 gen_op_mov_reg_v(MO_16, R_EAX, s->T0);
4905 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
4906 tcg_gen_ext8s_tl(cpu_tmp0, s->T0);
4907 tcg_gen_sub_tl(cpu_cc_src, s->T0, cpu_tmp0);
3ca51d07 4908 set_cc_op(s, CC_OP_MULB);
2c0262af 4909 break;
4ba9938c 4910 case MO_16:
1d1cc4d0 4911 gen_op_mov_v_reg(MO_16, cpu_T1, R_EAX);
c66f9727 4912 tcg_gen_ext16s_tl(s->T0, s->T0);
1d1cc4d0 4913 tcg_gen_ext16s_tl(cpu_T1, cpu_T1);
0211e5af 4914 /* XXX: use 32 bit mul which could be faster */
c66f9727
EC
4915 tcg_gen_mul_tl(s->T0, s->T0, cpu_T1);
4916 gen_op_mov_reg_v(MO_16, R_EAX, s->T0);
4917 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
4918 tcg_gen_ext16s_tl(cpu_tmp0, s->T0);
4919 tcg_gen_sub_tl(cpu_cc_src, s->T0, cpu_tmp0);
4920 tcg_gen_shri_tl(s->T0, s->T0, 16);
4921 gen_op_mov_reg_v(MO_16, R_EDX, s->T0);
3ca51d07 4922 set_cc_op(s, CC_OP_MULW);
2c0262af
FB
4923 break;
4924 default:
4ba9938c 4925 case MO_32:
c66f9727 4926 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, s->T0);
a4bcea3d
RH
4927 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_regs[R_EAX]);
4928 tcg_gen_muls2_i32(cpu_tmp2_i32, cpu_tmp3_i32,
4929 cpu_tmp2_i32, cpu_tmp3_i32);
4930 tcg_gen_extu_i32_tl(cpu_regs[R_EAX], cpu_tmp2_i32);
4931 tcg_gen_extu_i32_tl(cpu_regs[R_EDX], cpu_tmp3_i32);
4932 tcg_gen_sari_i32(cpu_tmp2_i32, cpu_tmp2_i32, 31);
4933 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
4934 tcg_gen_sub_i32(cpu_tmp2_i32, cpu_tmp2_i32, cpu_tmp3_i32);
4935 tcg_gen_extu_i32_tl(cpu_cc_src, cpu_tmp2_i32);
3ca51d07 4936 set_cc_op(s, CC_OP_MULL);
2c0262af 4937 break;
14ce26e7 4938#ifdef TARGET_X86_64
4ba9938c 4939 case MO_64:
a4bcea3d 4940 tcg_gen_muls2_i64(cpu_regs[R_EAX], cpu_regs[R_EDX],
c66f9727 4941 s->T0, cpu_regs[R_EAX]);
a4bcea3d
RH
4942 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
4943 tcg_gen_sari_tl(cpu_cc_src, cpu_regs[R_EAX], 63);
4944 tcg_gen_sub_tl(cpu_cc_src, cpu_cc_src, cpu_regs[R_EDX]);
3ca51d07 4945 set_cc_op(s, CC_OP_MULQ);
14ce26e7
FB
4946 break;
4947#endif
2c0262af 4948 }
2c0262af
FB
4949 break;
4950 case 6: /* div */
4951 switch(ot) {
4ba9938c 4952 case MO_8:
c66f9727 4953 gen_helper_divb_AL(cpu_env, s->T0);
2c0262af 4954 break;
4ba9938c 4955 case MO_16:
c66f9727 4956 gen_helper_divw_AX(cpu_env, s->T0);
2c0262af
FB
4957 break;
4958 default:
4ba9938c 4959 case MO_32:
c66f9727 4960 gen_helper_divl_EAX(cpu_env, s->T0);
14ce26e7
FB
4961 break;
4962#ifdef TARGET_X86_64
4ba9938c 4963 case MO_64:
c66f9727 4964 gen_helper_divq_EAX(cpu_env, s->T0);
2c0262af 4965 break;
14ce26e7 4966#endif
2c0262af
FB
4967 }
4968 break;
4969 case 7: /* idiv */
4970 switch(ot) {
4ba9938c 4971 case MO_8:
c66f9727 4972 gen_helper_idivb_AL(cpu_env, s->T0);
2c0262af 4973 break;
4ba9938c 4974 case MO_16:
c66f9727 4975 gen_helper_idivw_AX(cpu_env, s->T0);
2c0262af
FB
4976 break;
4977 default:
4ba9938c 4978 case MO_32:
c66f9727 4979 gen_helper_idivl_EAX(cpu_env, s->T0);
14ce26e7
FB
4980 break;
4981#ifdef TARGET_X86_64
4ba9938c 4982 case MO_64:
c66f9727 4983 gen_helper_idivq_EAX(cpu_env, s->T0);
2c0262af 4984 break;
14ce26e7 4985#endif
2c0262af
FB
4986 }
4987 break;
4988 default:
b9f9c5b4 4989 goto unknown_op;
2c0262af
FB
4990 }
4991 break;
4992
4993 case 0xfe: /* GRP4 */
4994 case 0xff: /* GRP5 */
ab4e4aec 4995 ot = mo_b_d(b, dflag);
2c0262af 4996
e3af7c78 4997 modrm = x86_ldub_code(env, s);
2c0262af 4998 mod = (modrm >> 6) & 3;
14ce26e7 4999 rm = (modrm & 7) | REX_B(s);
2c0262af
FB
5000 op = (modrm >> 3) & 7;
5001 if (op >= 2 && b == 0xfe) {
b9f9c5b4 5002 goto unknown_op;
2c0262af 5003 }
14ce26e7 5004 if (CODE64(s)) {
aba9d61e 5005 if (op == 2 || op == 4) {
14ce26e7 5006 /* operand size for jumps is 64 bit */
4ba9938c 5007 ot = MO_64;
aba9d61e 5008 } else if (op == 3 || op == 5) {
ab4e4aec 5009 ot = dflag != MO_16 ? MO_32 + (rex_w == 1) : MO_16;
14ce26e7
FB
5010 } else if (op == 6) {
5011 /* default push size is 64 bit */
ab4e4aec 5012 ot = mo_pushpop(s, dflag);
14ce26e7
FB
5013 }
5014 }
2c0262af 5015 if (mod != 3) {
4eeb3939 5016 gen_lea_modrm(env, s, modrm);
2c0262af 5017 if (op >= 2 && op != 3 && op != 5)
c66f9727 5018 gen_op_ld_v(s, ot, s->T0, s->A0);
2c0262af 5019 } else {
c66f9727 5020 gen_op_mov_v_reg(ot, s->T0, rm);
2c0262af
FB
5021 }
5022
5023 switch(op) {
5024 case 0: /* inc Ev */
5025 if (mod != 3)
5026 opreg = OR_TMP0;
5027 else
5028 opreg = rm;
5029 gen_inc(s, ot, opreg, 1);
5030 break;
5031 case 1: /* dec Ev */
5032 if (mod != 3)
5033 opreg = OR_TMP0;
5034 else
5035 opreg = rm;
5036 gen_inc(s, ot, opreg, -1);
5037 break;
5038 case 2: /* call Ev */
4f31916f 5039 /* XXX: optimize if memory (no 'and' is necessary) */
ab4e4aec 5040 if (dflag == MO_16) {
c66f9727 5041 tcg_gen_ext16u_tl(s->T0, s->T0);
40b90233 5042 }
2c0262af 5043 next_eip = s->pc - s->cs_base;
1d1cc4d0
RH
5044 tcg_gen_movi_tl(cpu_T1, next_eip);
5045 gen_push_v(s, cpu_T1);
c66f9727 5046 gen_op_jmp_v(s->T0);
7d117ce8 5047 gen_bnd_jmp(s);
c66f9727 5048 gen_jr(s, s->T0);
2c0262af 5049 break;
61382a50 5050 case 3: /* lcall Ev */
6b672b5d 5051 gen_op_ld_v(s, ot, cpu_T1, s->A0);
830a19a4 5052 gen_add_A0_im(s, 1 << ot);
c66f9727 5053 gen_op_ld_v(s, MO_16, s->T0, s->A0);
2c0262af
FB
5054 do_lcall:
5055 if (s->pe && !s->vm86) {
c66f9727 5056 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, s->T0);
1d1cc4d0 5057 gen_helper_lcall_protected(cpu_env, cpu_tmp2_i32, cpu_T1,
ab4e4aec 5058 tcg_const_i32(dflag - 1),
100ec099 5059 tcg_const_tl(s->pc - s->cs_base));
2c0262af 5060 } else {
c66f9727 5061 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, s->T0);
1d1cc4d0 5062 gen_helper_lcall_real(cpu_env, cpu_tmp2_i32, cpu_T1,
ab4e4aec 5063 tcg_const_i32(dflag - 1),
a7812ae4 5064 tcg_const_i32(s->pc - s->cs_base));
2c0262af 5065 }
b4aa2977
EC
5066 tcg_gen_ld_tl(cpu_tmp4, cpu_env, offsetof(CPUX86State, eip));
5067 gen_jr(s, cpu_tmp4);
2c0262af
FB
5068 break;
5069 case 4: /* jmp Ev */
ab4e4aec 5070 if (dflag == MO_16) {
c66f9727 5071 tcg_gen_ext16u_tl(s->T0, s->T0);
40b90233 5072 }
c66f9727 5073 gen_op_jmp_v(s->T0);
7d117ce8 5074 gen_bnd_jmp(s);
c66f9727 5075 gen_jr(s, s->T0);
2c0262af
FB
5076 break;
5077 case 5: /* ljmp Ev */
6b672b5d 5078 gen_op_ld_v(s, ot, cpu_T1, s->A0);
830a19a4 5079 gen_add_A0_im(s, 1 << ot);
c66f9727 5080 gen_op_ld_v(s, MO_16, s->T0, s->A0);
2c0262af
FB
5081 do_ljmp:
5082 if (s->pe && !s->vm86) {
c66f9727 5083 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, s->T0);
1d1cc4d0 5084 gen_helper_ljmp_protected(cpu_env, cpu_tmp2_i32, cpu_T1,
100ec099 5085 tcg_const_tl(s->pc - s->cs_base));
2c0262af 5086 } else {
c66f9727 5087 gen_op_movl_seg_T0_vm(s, R_CS);
1d1cc4d0 5088 gen_op_jmp_v(cpu_T1);
2c0262af 5089 }
b4aa2977
EC
5090 tcg_gen_ld_tl(cpu_tmp4, cpu_env, offsetof(CPUX86State, eip));
5091 gen_jr(s, cpu_tmp4);
2c0262af
FB
5092 break;
5093 case 6: /* push Ev */
c66f9727 5094 gen_push_v(s, s->T0);
2c0262af
FB
5095 break;
5096 default:
b9f9c5b4 5097 goto unknown_op;
2c0262af
FB
5098 }
5099 break;
5100
5101 case 0x84: /* test Ev, Gv */
5fafdf24 5102 case 0x85:
ab4e4aec 5103 ot = mo_b_d(b, dflag);
2c0262af 5104
e3af7c78 5105 modrm = x86_ldub_code(env, s);
14ce26e7 5106 reg = ((modrm >> 3) & 7) | rex_r;
3b46e624 5107
0af10c86 5108 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
1d1cc4d0 5109 gen_op_mov_v_reg(ot, cpu_T1, reg);
c66f9727 5110 gen_op_testl_T0_T1_cc(s);
3ca51d07 5111 set_cc_op(s, CC_OP_LOGICB + ot);
2c0262af 5112 break;
3b46e624 5113
2c0262af
FB
5114 case 0xa8: /* test eAX, Iv */
5115 case 0xa9:
ab4e4aec 5116 ot = mo_b_d(b, dflag);
0af10c86 5117 val = insn_get(env, s, ot);
2c0262af 5118
c66f9727 5119 gen_op_mov_v_reg(ot, s->T0, OR_EAX);
1d1cc4d0 5120 tcg_gen_movi_tl(cpu_T1, val);
c66f9727 5121 gen_op_testl_T0_T1_cc(s);
3ca51d07 5122 set_cc_op(s, CC_OP_LOGICB + ot);
2c0262af 5123 break;
3b46e624 5124
2c0262af 5125 case 0x98: /* CWDE/CBW */
ab4e4aec 5126 switch (dflag) {
14ce26e7 5127#ifdef TARGET_X86_64
ab4e4aec 5128 case MO_64:
c66f9727
EC
5129 gen_op_mov_v_reg(MO_32, s->T0, R_EAX);
5130 tcg_gen_ext32s_tl(s->T0, s->T0);
5131 gen_op_mov_reg_v(MO_64, R_EAX, s->T0);
ab4e4aec 5132 break;
14ce26e7 5133#endif
ab4e4aec 5134 case MO_32:
c66f9727
EC
5135 gen_op_mov_v_reg(MO_16, s->T0, R_EAX);
5136 tcg_gen_ext16s_tl(s->T0, s->T0);
5137 gen_op_mov_reg_v(MO_32, R_EAX, s->T0);
ab4e4aec
RH
5138 break;
5139 case MO_16:
c66f9727
EC
5140 gen_op_mov_v_reg(MO_8, s->T0, R_EAX);
5141 tcg_gen_ext8s_tl(s->T0, s->T0);
5142 gen_op_mov_reg_v(MO_16, R_EAX, s->T0);
ab4e4aec
RH
5143 break;
5144 default:
5145 tcg_abort();
e108dd01 5146 }
2c0262af
FB
5147 break;
5148 case 0x99: /* CDQ/CWD */
ab4e4aec 5149 switch (dflag) {
14ce26e7 5150#ifdef TARGET_X86_64
ab4e4aec 5151 case MO_64:
c66f9727
EC
5152 gen_op_mov_v_reg(MO_64, s->T0, R_EAX);
5153 tcg_gen_sari_tl(s->T0, s->T0, 63);
5154 gen_op_mov_reg_v(MO_64, R_EDX, s->T0);
ab4e4aec 5155 break;
14ce26e7 5156#endif
ab4e4aec 5157 case MO_32:
c66f9727
EC
5158 gen_op_mov_v_reg(MO_32, s->T0, R_EAX);
5159 tcg_gen_ext32s_tl(s->T0, s->T0);
5160 tcg_gen_sari_tl(s->T0, s->T0, 31);
5161 gen_op_mov_reg_v(MO_32, R_EDX, s->T0);
ab4e4aec
RH
5162 break;
5163 case MO_16:
c66f9727
EC
5164 gen_op_mov_v_reg(MO_16, s->T0, R_EAX);
5165 tcg_gen_ext16s_tl(s->T0, s->T0);
5166 tcg_gen_sari_tl(s->T0, s->T0, 15);
5167 gen_op_mov_reg_v(MO_16, R_EDX, s->T0);
ab4e4aec
RH
5168 break;
5169 default:
5170 tcg_abort();
e108dd01 5171 }
2c0262af
FB
5172 break;
5173 case 0x1af: /* imul Gv, Ev */
5174 case 0x69: /* imul Gv, Ev, I */
5175 case 0x6b:
ab4e4aec 5176 ot = dflag;
e3af7c78 5177 modrm = x86_ldub_code(env, s);
14ce26e7
FB
5178 reg = ((modrm >> 3) & 7) | rex_r;
5179 if (b == 0x69)
5180 s->rip_offset = insn_const_size(ot);
5181 else if (b == 0x6b)
5182 s->rip_offset = 1;
0af10c86 5183 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
2c0262af 5184 if (b == 0x69) {
0af10c86 5185 val = insn_get(env, s, ot);
1d1cc4d0 5186 tcg_gen_movi_tl(cpu_T1, val);
2c0262af 5187 } else if (b == 0x6b) {
4ba9938c 5188 val = (int8_t)insn_get(env, s, MO_8);
1d1cc4d0 5189 tcg_gen_movi_tl(cpu_T1, val);
2c0262af 5190 } else {
1d1cc4d0 5191 gen_op_mov_v_reg(ot, cpu_T1, reg);
2c0262af 5192 }
a4bcea3d 5193 switch (ot) {
0211e5af 5194#ifdef TARGET_X86_64
4ba9938c 5195 case MO_64:
c66f9727 5196 tcg_gen_muls2_i64(cpu_regs[reg], cpu_T1, s->T0, cpu_T1);
a4bcea3d
RH
5197 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[reg]);
5198 tcg_gen_sari_tl(cpu_cc_src, cpu_cc_dst, 63);
1d1cc4d0 5199 tcg_gen_sub_tl(cpu_cc_src, cpu_cc_src, cpu_T1);
a4bcea3d 5200 break;
0211e5af 5201#endif
4ba9938c 5202 case MO_32:
c66f9727 5203 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, s->T0);
1d1cc4d0 5204 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T1);
a4bcea3d
RH
5205 tcg_gen_muls2_i32(cpu_tmp2_i32, cpu_tmp3_i32,
5206 cpu_tmp2_i32, cpu_tmp3_i32);
5207 tcg_gen_extu_i32_tl(cpu_regs[reg], cpu_tmp2_i32);
5208 tcg_gen_sari_i32(cpu_tmp2_i32, cpu_tmp2_i32, 31);
5209 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[reg]);
5210 tcg_gen_sub_i32(cpu_tmp2_i32, cpu_tmp2_i32, cpu_tmp3_i32);
5211 tcg_gen_extu_i32_tl(cpu_cc_src, cpu_tmp2_i32);
5212 break;
5213 default:
c66f9727 5214 tcg_gen_ext16s_tl(s->T0, s->T0);
1d1cc4d0 5215 tcg_gen_ext16s_tl(cpu_T1, cpu_T1);
0211e5af 5216 /* XXX: use 32 bit mul which could be faster */
c66f9727
EC
5217 tcg_gen_mul_tl(s->T0, s->T0, cpu_T1);
5218 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
5219 tcg_gen_ext16s_tl(cpu_tmp0, s->T0);
5220 tcg_gen_sub_tl(cpu_cc_src, s->T0, cpu_tmp0);
5221 gen_op_mov_reg_v(ot, reg, s->T0);
a4bcea3d 5222 break;
2c0262af 5223 }
3ca51d07 5224 set_cc_op(s, CC_OP_MULB + ot);
2c0262af
FB
5225 break;
5226 case 0x1c0:
5227 case 0x1c1: /* xadd Ev, Gv */
ab4e4aec 5228 ot = mo_b_d(b, dflag);
e3af7c78 5229 modrm = x86_ldub_code(env, s);
14ce26e7 5230 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af 5231 mod = (modrm >> 6) & 3;
c66f9727 5232 gen_op_mov_v_reg(ot, s->T0, reg);
2c0262af 5233 if (mod == 3) {
14ce26e7 5234 rm = (modrm & 7) | REX_B(s);
1d1cc4d0 5235 gen_op_mov_v_reg(ot, cpu_T1, rm);
c66f9727 5236 tcg_gen_add_tl(s->T0, s->T0, cpu_T1);
1d1cc4d0 5237 gen_op_mov_reg_v(ot, reg, cpu_T1);
c66f9727 5238 gen_op_mov_reg_v(ot, rm, s->T0);
2c0262af 5239 } else {
4eeb3939 5240 gen_lea_modrm(env, s, modrm);
f53b0181 5241 if (s->prefix & PREFIX_LOCK) {
c66f9727 5242 tcg_gen_atomic_fetch_add_tl(cpu_T1, s->A0, s->T0,
f53b0181 5243 s->mem_index, ot | MO_LE);
c66f9727 5244 tcg_gen_add_tl(s->T0, s->T0, cpu_T1);
f53b0181 5245 } else {
6b672b5d 5246 gen_op_ld_v(s, ot, cpu_T1, s->A0);
c66f9727
EC
5247 tcg_gen_add_tl(s->T0, s->T0, cpu_T1);
5248 gen_op_st_v(s, ot, s->T0, s->A0);
f53b0181 5249 }
1d1cc4d0 5250 gen_op_mov_reg_v(ot, reg, cpu_T1);
2c0262af 5251 }
c66f9727 5252 gen_op_update2_cc(s);
3ca51d07 5253 set_cc_op(s, CC_OP_ADDB + ot);
2c0262af
FB
5254 break;
5255 case 0x1b0:
5256 case 0x1b1: /* cmpxchg Ev, Gv */
cad3a37d 5257 {
ae03f8de 5258 TCGv oldv, newv, cmpv;
cad3a37d 5259
ab4e4aec 5260 ot = mo_b_d(b, dflag);
e3af7c78 5261 modrm = x86_ldub_code(env, s);
cad3a37d
FB
5262 reg = ((modrm >> 3) & 7) | rex_r;
5263 mod = (modrm >> 6) & 3;
ae03f8de
EC
5264 oldv = tcg_temp_new();
5265 newv = tcg_temp_new();
5266 cmpv = tcg_temp_new();
5267 gen_op_mov_v_reg(ot, newv, reg);
5268 tcg_gen_mov_tl(cmpv, cpu_regs[R_EAX]);
5269
5270 if (s->prefix & PREFIX_LOCK) {
5271 if (mod == 3) {
5272 goto illegal_op;
5273 }
4eeb3939 5274 gen_lea_modrm(env, s, modrm);
6b672b5d 5275 tcg_gen_atomic_cmpxchg_tl(oldv, s->A0, cmpv, newv,
ae03f8de
EC
5276 s->mem_index, ot | MO_LE);
5277 gen_op_mov_reg_v(ot, R_EAX, oldv);
cad3a37d 5278 } else {
ae03f8de
EC
5279 if (mod == 3) {
5280 rm = (modrm & 7) | REX_B(s);
5281 gen_op_mov_v_reg(ot, oldv, rm);
5282 } else {
5283 gen_lea_modrm(env, s, modrm);
6b672b5d 5284 gen_op_ld_v(s, ot, oldv, s->A0);
ae03f8de
EC
5285 rm = 0; /* avoid warning */
5286 }
5287 gen_extu(ot, oldv);
5288 gen_extu(ot, cmpv);
5289 /* store value = (old == cmp ? new : old); */
5290 tcg_gen_movcond_tl(TCG_COND_EQ, newv, oldv, cmpv, newv, oldv);
5291 if (mod == 3) {
5292 gen_op_mov_reg_v(ot, R_EAX, oldv);
5293 gen_op_mov_reg_v(ot, rm, newv);
5294 } else {
5295 /* Perform an unconditional store cycle like physical cpu;
5296 must be before changing accumulator to ensure
5297 idempotency if the store faults and the instruction
5298 is restarted */
6b672b5d 5299 gen_op_st_v(s, ot, newv, s->A0);
ae03f8de
EC
5300 gen_op_mov_reg_v(ot, R_EAX, oldv);
5301 }
cad3a37d 5302 }
ae03f8de 5303 tcg_gen_mov_tl(cpu_cc_src, oldv);
93a3e108 5304 tcg_gen_mov_tl(s->cc_srcT, cmpv);
ae03f8de 5305 tcg_gen_sub_tl(cpu_cc_dst, cmpv, oldv);
3ca51d07 5306 set_cc_op(s, CC_OP_SUBB + ot);
ae03f8de
EC
5307 tcg_temp_free(oldv);
5308 tcg_temp_free(newv);
5309 tcg_temp_free(cmpv);
2c0262af 5310 }
2c0262af
FB
5311 break;
5312 case 0x1c7: /* cmpxchg8b */
e3af7c78 5313 modrm = x86_ldub_code(env, s);
2c0262af 5314 mod = (modrm >> 6) & 3;
71c3558e 5315 if ((mod == 3) || ((modrm & 0x38) != 0x8))
2c0262af 5316 goto illegal_op;
1b9d9ebb 5317#ifdef TARGET_X86_64
ab4e4aec 5318 if (dflag == MO_64) {
1b9d9ebb
FB
5319 if (!(s->cpuid_ext_features & CPUID_EXT_CX16))
5320 goto illegal_op;
4eeb3939 5321 gen_lea_modrm(env, s, modrm);
b5e3b4c2 5322 if ((s->prefix & PREFIX_LOCK) && (tb_cflags(s->base.tb) & CF_PARALLEL)) {
6b672b5d 5323 gen_helper_cmpxchg16b(cpu_env, s->A0);
ae03f8de 5324 } else {
6b672b5d 5325 gen_helper_cmpxchg16b_unlocked(cpu_env, s->A0);
ae03f8de 5326 }
1b9d9ebb
FB
5327 } else
5328#endif
5329 {
5330 if (!(s->cpuid_features & CPUID_CX8))
5331 goto illegal_op;
4eeb3939 5332 gen_lea_modrm(env, s, modrm);
b5e3b4c2 5333 if ((s->prefix & PREFIX_LOCK) && (tb_cflags(s->base.tb) & CF_PARALLEL)) {
6b672b5d 5334 gen_helper_cmpxchg8b(cpu_env, s->A0);
ae03f8de 5335 } else {
6b672b5d 5336 gen_helper_cmpxchg8b_unlocked(cpu_env, s->A0);
ae03f8de 5337 }
1b9d9ebb 5338 }
3ca51d07 5339 set_cc_op(s, CC_OP_EFLAGS);
2c0262af 5340 break;
3b46e624 5341
2c0262af
FB
5342 /**************************/
5343 /* push/pop */
5344 case 0x50 ... 0x57: /* push */
c66f9727
EC
5345 gen_op_mov_v_reg(MO_32, s->T0, (b & 7) | REX_B(s));
5346 gen_push_v(s, s->T0);
2c0262af
FB
5347 break;
5348 case 0x58 ... 0x5f: /* pop */
8e31d234 5349 ot = gen_pop_T0(s);
77729c24 5350 /* NOTE: order is important for pop %sp */
8e31d234 5351 gen_pop_update(s, ot);
c66f9727 5352 gen_op_mov_reg_v(ot, (b & 7) | REX_B(s), s->T0);
2c0262af
FB
5353 break;
5354 case 0x60: /* pusha */
14ce26e7
FB
5355 if (CODE64(s))
5356 goto illegal_op;
2c0262af
FB
5357 gen_pusha(s);
5358 break;
5359 case 0x61: /* popa */
14ce26e7
FB
5360 if (CODE64(s))
5361 goto illegal_op;
2c0262af
FB
5362 gen_popa(s);
5363 break;
5364 case 0x68: /* push Iv */
5365 case 0x6a:
ab4e4aec 5366 ot = mo_pushpop(s, dflag);
2c0262af 5367 if (b == 0x68)
0af10c86 5368 val = insn_get(env, s, ot);
2c0262af 5369 else
4ba9938c 5370 val = (int8_t)insn_get(env, s, MO_8);
c66f9727
EC
5371 tcg_gen_movi_tl(s->T0, val);
5372 gen_push_v(s, s->T0);
2c0262af
FB
5373 break;
5374 case 0x8f: /* pop Ev */
e3af7c78 5375 modrm = x86_ldub_code(env, s);
77729c24 5376 mod = (modrm >> 6) & 3;
8e31d234 5377 ot = gen_pop_T0(s);
77729c24
FB
5378 if (mod == 3) {
5379 /* NOTE: order is important for pop %sp */
8e31d234 5380 gen_pop_update(s, ot);
14ce26e7 5381 rm = (modrm & 7) | REX_B(s);
c66f9727 5382 gen_op_mov_reg_v(ot, rm, s->T0);
77729c24
FB
5383 } else {
5384 /* NOTE: order is important too for MMU exceptions */
14ce26e7 5385 s->popl_esp_hack = 1 << ot;
0af10c86 5386 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
77729c24 5387 s->popl_esp_hack = 0;
8e31d234 5388 gen_pop_update(s, ot);
77729c24 5389 }
2c0262af
FB
5390 break;
5391 case 0xc8: /* enter */
5392 {
5393 int level;
e3af7c78
PB
5394 val = x86_lduw_code(env, s);
5395 level = x86_ldub_code(env, s);
2c0262af
FB
5396 gen_enter(s, val, level);
5397 }
5398 break;
5399 case 0xc9: /* leave */
2045f04c 5400 gen_leave(s);
2c0262af
FB
5401 break;
5402 case 0x06: /* push es */
5403 case 0x0e: /* push cs */
5404 case 0x16: /* push ss */
5405 case 0x1e: /* push ds */
14ce26e7
FB
5406 if (CODE64(s))
5407 goto illegal_op;
c66f9727
EC
5408 gen_op_movl_T0_seg(s, b >> 3);
5409 gen_push_v(s, s->T0);
2c0262af
FB
5410 break;
5411 case 0x1a0: /* push fs */
5412 case 0x1a8: /* push gs */
c66f9727
EC
5413 gen_op_movl_T0_seg(s, (b >> 3) & 7);
5414 gen_push_v(s, s->T0);
2c0262af
FB
5415 break;
5416 case 0x07: /* pop es */
5417 case 0x17: /* pop ss */
5418 case 0x1f: /* pop ds */
14ce26e7
FB
5419 if (CODE64(s))
5420 goto illegal_op;
2c0262af 5421 reg = b >> 3;
8e31d234 5422 ot = gen_pop_T0(s);
100ec099 5423 gen_movl_seg_T0(s, reg);
8e31d234 5424 gen_pop_update(s, ot);
f083d92c 5425 /* Note that reg == R_SS in gen_movl_seg_T0 always sets is_jmp. */
6cf147aa 5426 if (s->base.is_jmp) {
14ce26e7 5427 gen_jmp_im(s->pc - s->cs_base);
f083d92c
RH
5428 if (reg == R_SS) {
5429 s->tf = 0;
5430 gen_eob_inhibit_irq(s, true);
5431 } else {
5432 gen_eob(s);
5433 }
2c0262af
FB
5434 }
5435 break;
5436 case 0x1a1: /* pop fs */
5437 case 0x1a9: /* pop gs */
8e31d234 5438 ot = gen_pop_T0(s);
100ec099 5439 gen_movl_seg_T0(s, (b >> 3) & 7);
8e31d234 5440 gen_pop_update(s, ot);
6cf147aa 5441 if (s->base.is_jmp) {
14ce26e7 5442 gen_jmp_im(s->pc - s->cs_base);
2c0262af
FB
5443 gen_eob(s);
5444 }
5445 break;
5446
5447 /**************************/
5448 /* mov */
5449 case 0x88:
5450 case 0x89: /* mov Gv, Ev */
ab4e4aec 5451 ot = mo_b_d(b, dflag);
e3af7c78 5452 modrm = x86_ldub_code(env, s);
14ce26e7 5453 reg = ((modrm >> 3) & 7) | rex_r;
3b46e624 5454
2c0262af 5455 /* generate a generic store */
0af10c86 5456 gen_ldst_modrm(env, s, modrm, ot, reg, 1);
2c0262af
FB
5457 break;
5458 case 0xc6:
5459 case 0xc7: /* mov Ev, Iv */
ab4e4aec 5460 ot = mo_b_d(b, dflag);
e3af7c78 5461 modrm = x86_ldub_code(env, s);
2c0262af 5462 mod = (modrm >> 6) & 3;
14ce26e7
FB
5463 if (mod != 3) {
5464 s->rip_offset = insn_const_size(ot);
4eeb3939 5465 gen_lea_modrm(env, s, modrm);
14ce26e7 5466 }
0af10c86 5467 val = insn_get(env, s, ot);
c66f9727 5468 tcg_gen_movi_tl(s->T0, val);
fd8ca9f6 5469 if (mod != 3) {
c66f9727 5470 gen_op_st_v(s, ot, s->T0, s->A0);
fd8ca9f6 5471 } else {
c66f9727 5472 gen_op_mov_reg_v(ot, (modrm & 7) | REX_B(s), s->T0);
fd8ca9f6 5473 }
2c0262af
FB
5474 break;
5475 case 0x8a:
5476 case 0x8b: /* mov Ev, Gv */
ab4e4aec 5477 ot = mo_b_d(b, dflag);
e3af7c78 5478 modrm = x86_ldub_code(env, s);
14ce26e7 5479 reg = ((modrm >> 3) & 7) | rex_r;
3b46e624 5480
0af10c86 5481 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
c66f9727 5482 gen_op_mov_reg_v(ot, reg, s->T0);
2c0262af
FB
5483 break;
5484 case 0x8e: /* mov seg, Gv */
e3af7c78 5485 modrm = x86_ldub_code(env, s);
2c0262af
FB
5486 reg = (modrm >> 3) & 7;
5487 if (reg >= 6 || reg == R_CS)
5488 goto illegal_op;
4ba9938c 5489 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
100ec099 5490 gen_movl_seg_T0(s, reg);
f083d92c 5491 /* Note that reg == R_SS in gen_movl_seg_T0 always sets is_jmp. */
6cf147aa 5492 if (s->base.is_jmp) {
14ce26e7 5493 gen_jmp_im(s->pc - s->cs_base);
f083d92c
RH
5494 if (reg == R_SS) {
5495 s->tf = 0;
5496 gen_eob_inhibit_irq(s, true);
5497 } else {
5498 gen_eob(s);
5499 }
2c0262af
FB
5500 }
5501 break;
5502 case 0x8c: /* mov Gv, seg */
e3af7c78 5503 modrm = x86_ldub_code(env, s);
2c0262af
FB
5504 reg = (modrm >> 3) & 7;
5505 mod = (modrm >> 6) & 3;
5506 if (reg >= 6)
5507 goto illegal_op;
c66f9727 5508 gen_op_movl_T0_seg(s, reg);
ab4e4aec 5509 ot = mod == 3 ? dflag : MO_16;
0af10c86 5510 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
2c0262af
FB
5511 break;
5512
5513 case 0x1b6: /* movzbS Gv, Eb */
5514 case 0x1b7: /* movzwS Gv, Eb */
5515 case 0x1be: /* movsbS Gv, Eb */
5516 case 0x1bf: /* movswS Gv, Eb */
5517 {
c8fbc479
RH
5518 TCGMemOp d_ot;
5519 TCGMemOp s_ot;
5520
2c0262af 5521 /* d_ot is the size of destination */
ab4e4aec 5522 d_ot = dflag;
2c0262af 5523 /* ot is the size of source */
4ba9938c 5524 ot = (b & 1) + MO_8;
c8fbc479
RH
5525 /* s_ot is the sign+size of source */
5526 s_ot = b & 8 ? MO_SIGN | ot : ot;
5527
e3af7c78 5528 modrm = x86_ldub_code(env, s);
14ce26e7 5529 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af 5530 mod = (modrm >> 6) & 3;
14ce26e7 5531 rm = (modrm & 7) | REX_B(s);
3b46e624 5532
2c0262af 5533 if (mod == 3) {
04fc2f1c 5534 if (s_ot == MO_SB && byte_reg_is_xH(rm)) {
c66f9727 5535 tcg_gen_sextract_tl(s->T0, cpu_regs[rm - 4], 8, 8);
04fc2f1c 5536 } else {
c66f9727 5537 gen_op_mov_v_reg(ot, s->T0, rm);
04fc2f1c
RH
5538 switch (s_ot) {
5539 case MO_UB:
c66f9727 5540 tcg_gen_ext8u_tl(s->T0, s->T0);
04fc2f1c
RH
5541 break;
5542 case MO_SB:
c66f9727 5543 tcg_gen_ext8s_tl(s->T0, s->T0);
04fc2f1c
RH
5544 break;
5545 case MO_UW:
c66f9727 5546 tcg_gen_ext16u_tl(s->T0, s->T0);
04fc2f1c
RH
5547 break;
5548 default:
5549 case MO_SW:
c66f9727 5550 tcg_gen_ext16s_tl(s->T0, s->T0);
04fc2f1c
RH
5551 break;
5552 }
2c0262af 5553 }
c66f9727 5554 gen_op_mov_reg_v(d_ot, reg, s->T0);
2c0262af 5555 } else {
4eeb3939 5556 gen_lea_modrm(env, s, modrm);
c66f9727
EC
5557 gen_op_ld_v(s, s_ot, s->T0, s->A0);
5558 gen_op_mov_reg_v(d_ot, reg, s->T0);
2c0262af
FB
5559 }
5560 }
5561 break;
5562
5563 case 0x8d: /* lea */
e3af7c78 5564 modrm = x86_ldub_code(env, s);
3a1d9b8b
FB
5565 mod = (modrm >> 6) & 3;
5566 if (mod == 3)
5567 goto illegal_op;
14ce26e7 5568 reg = ((modrm >> 3) & 7) | rex_r;
a074ce42
RH
5569 {
5570 AddressParts a = gen_lea_modrm_0(env, s, modrm);
6b672b5d 5571 TCGv ea = gen_lea_modrm_1(s, a);
620abfb0 5572 gen_lea_v_seg(s, s->aflag, ea, -1, -1);
6b672b5d 5573 gen_op_mov_reg_v(dflag, reg, s->A0);
a074ce42 5574 }
2c0262af 5575 break;
3b46e624 5576
2c0262af
FB
5577 case 0xa0: /* mov EAX, Ov */
5578 case 0xa1:
5579 case 0xa2: /* mov Ov, EAX */
5580 case 0xa3:
2c0262af 5581 {
14ce26e7
FB
5582 target_ulong offset_addr;
5583
ab4e4aec 5584 ot = mo_b_d(b, dflag);
1d71ddb1 5585 switch (s->aflag) {
14ce26e7 5586#ifdef TARGET_X86_64
1d71ddb1 5587 case MO_64:
e3af7c78 5588 offset_addr = x86_ldq_code(env, s);
1d71ddb1 5589 break;
14ce26e7 5590#endif
1d71ddb1
RH
5591 default:
5592 offset_addr = insn_get(env, s, s->aflag);
5593 break;
14ce26e7 5594 }
6b672b5d 5595 tcg_gen_movi_tl(s->A0, offset_addr);
664e0f19 5596 gen_add_A0_ds_seg(s);
14ce26e7 5597 if ((b & 2) == 0) {
c66f9727
EC
5598 gen_op_ld_v(s, ot, s->T0, s->A0);
5599 gen_op_mov_reg_v(ot, R_EAX, s->T0);
14ce26e7 5600 } else {
c66f9727
EC
5601 gen_op_mov_v_reg(ot, s->T0, R_EAX);
5602 gen_op_st_v(s, ot, s->T0, s->A0);
2c0262af
FB
5603 }
5604 }
2c0262af
FB
5605 break;
5606 case 0xd7: /* xlat */
6b672b5d 5607 tcg_gen_mov_tl(s->A0, cpu_regs[R_EBX]);
c66f9727
EC
5608 tcg_gen_ext8u_tl(s->T0, cpu_regs[R_EAX]);
5609 tcg_gen_add_tl(s->A0, s->A0, s->T0);
6b672b5d 5610 gen_extu(s->aflag, s->A0);
664e0f19 5611 gen_add_A0_ds_seg(s);
c66f9727
EC
5612 gen_op_ld_v(s, MO_8, s->T0, s->A0);
5613 gen_op_mov_reg_v(MO_8, R_EAX, s->T0);
2c0262af
FB
5614 break;
5615 case 0xb0 ... 0xb7: /* mov R, Ib */
4ba9938c 5616 val = insn_get(env, s, MO_8);
c66f9727
EC
5617 tcg_gen_movi_tl(s->T0, val);
5618 gen_op_mov_reg_v(MO_8, (b & 7) | REX_B(s), s->T0);
2c0262af
FB
5619 break;
5620 case 0xb8 ... 0xbf: /* mov R, Iv */
14ce26e7 5621#ifdef TARGET_X86_64
ab4e4aec 5622 if (dflag == MO_64) {
14ce26e7
FB
5623 uint64_t tmp;
5624 /* 64 bit case */
e3af7c78 5625 tmp = x86_ldq_code(env, s);
14ce26e7 5626 reg = (b & 7) | REX_B(s);
c66f9727
EC
5627 tcg_gen_movi_tl(s->T0, tmp);
5628 gen_op_mov_reg_v(MO_64, reg, s->T0);
5fafdf24 5629 } else
14ce26e7
FB
5630#endif
5631 {
ab4e4aec 5632 ot = dflag;
0af10c86 5633 val = insn_get(env, s, ot);
14ce26e7 5634 reg = (b & 7) | REX_B(s);
c66f9727
EC
5635 tcg_gen_movi_tl(s->T0, val);
5636 gen_op_mov_reg_v(ot, reg, s->T0);
14ce26e7 5637 }
2c0262af
FB
5638 break;
5639
5640 case 0x91 ... 0x97: /* xchg R, EAX */
7418027e 5641 do_xchg_reg_eax:
ab4e4aec 5642 ot = dflag;
14ce26e7 5643 reg = (b & 7) | REX_B(s);
2c0262af
FB
5644 rm = R_EAX;
5645 goto do_xchg_reg;
5646 case 0x86:
5647 case 0x87: /* xchg Ev, Gv */
ab4e4aec 5648 ot = mo_b_d(b, dflag);
e3af7c78 5649 modrm = x86_ldub_code(env, s);
14ce26e7 5650 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af
FB
5651 mod = (modrm >> 6) & 3;
5652 if (mod == 3) {
14ce26e7 5653 rm = (modrm & 7) | REX_B(s);
2c0262af 5654 do_xchg_reg:
c66f9727 5655 gen_op_mov_v_reg(ot, s->T0, reg);
1d1cc4d0 5656 gen_op_mov_v_reg(ot, cpu_T1, rm);
c66f9727 5657 gen_op_mov_reg_v(ot, rm, s->T0);
1d1cc4d0 5658 gen_op_mov_reg_v(ot, reg, cpu_T1);
2c0262af 5659 } else {
4eeb3939 5660 gen_lea_modrm(env, s, modrm);
c66f9727 5661 gen_op_mov_v_reg(ot, s->T0, reg);
2c0262af 5662 /* for xchg, lock is implicit */
c66f9727 5663 tcg_gen_atomic_xchg_tl(cpu_T1, s->A0, s->T0,
ea97ebe8 5664 s->mem_index, ot | MO_LE);
1d1cc4d0 5665 gen_op_mov_reg_v(ot, reg, cpu_T1);
2c0262af
FB
5666 }
5667 break;
5668 case 0xc4: /* les Gv */
701ed211 5669 /* In CODE64 this is VEX3; see above. */
2c0262af
FB
5670 op = R_ES;
5671 goto do_lxx;
5672 case 0xc5: /* lds Gv */
701ed211 5673 /* In CODE64 this is VEX2; see above. */
2c0262af
FB
5674 op = R_DS;
5675 goto do_lxx;
5676 case 0x1b2: /* lss Gv */
5677 op = R_SS;
5678 goto do_lxx;
5679 case 0x1b4: /* lfs Gv */
5680 op = R_FS;
5681 goto do_lxx;
5682 case 0x1b5: /* lgs Gv */
5683 op = R_GS;
5684 do_lxx:
ab4e4aec 5685 ot = dflag != MO_16 ? MO_32 : MO_16;
e3af7c78 5686 modrm = x86_ldub_code(env, s);
14ce26e7 5687 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af
FB
5688 mod = (modrm >> 6) & 3;
5689 if (mod == 3)
5690 goto illegal_op;
4eeb3939 5691 gen_lea_modrm(env, s, modrm);
6b672b5d 5692 gen_op_ld_v(s, ot, cpu_T1, s->A0);
830a19a4 5693 gen_add_A0_im(s, 1 << ot);
2c0262af 5694 /* load the segment first to handle exceptions properly */
c66f9727 5695 gen_op_ld_v(s, MO_16, s->T0, s->A0);
100ec099 5696 gen_movl_seg_T0(s, op);
2c0262af 5697 /* then put the data */
1d1cc4d0 5698 gen_op_mov_reg_v(ot, reg, cpu_T1);
6cf147aa 5699 if (s->base.is_jmp) {
14ce26e7 5700 gen_jmp_im(s->pc - s->cs_base);
2c0262af
FB
5701 gen_eob(s);
5702 }
5703 break;
3b46e624 5704
2c0262af
FB
5705 /************************/
5706 /* shifts */
5707 case 0xc0:
5708 case 0xc1:
5709 /* shift Ev,Ib */
5710 shift = 2;
5711 grp2:
5712 {
ab4e4aec 5713 ot = mo_b_d(b, dflag);
e3af7c78 5714 modrm = x86_ldub_code(env, s);
2c0262af 5715 mod = (modrm >> 6) & 3;
2c0262af 5716 op = (modrm >> 3) & 7;
3b46e624 5717
2c0262af 5718 if (mod != 3) {
14ce26e7
FB
5719 if (shift == 2) {
5720 s->rip_offset = 1;
5721 }
4eeb3939 5722 gen_lea_modrm(env, s, modrm);
2c0262af
FB
5723 opreg = OR_TMP0;
5724 } else {
14ce26e7 5725 opreg = (modrm & 7) | REX_B(s);
2c0262af
FB
5726 }
5727
5728 /* simpler op */
5729 if (shift == 0) {
5730 gen_shift(s, op, ot, opreg, OR_ECX);
5731 } else {
5732 if (shift == 2) {
e3af7c78 5733 shift = x86_ldub_code(env, s);
2c0262af
FB
5734 }
5735 gen_shifti(s, op, ot, opreg, shift);
5736 }
5737 }
5738 break;
5739 case 0xd0:
5740 case 0xd1:
5741 /* shift Ev,1 */
5742 shift = 1;
5743 goto grp2;
5744 case 0xd2:
5745 case 0xd3:
5746 /* shift Ev,cl */
5747 shift = 0;
5748 goto grp2;
5749
5750 case 0x1a4: /* shld imm */
5751 op = 0;
5752 shift = 1;
5753 goto do_shiftd;
5754 case 0x1a5: /* shld cl */
5755 op = 0;
5756 shift = 0;
5757 goto do_shiftd;
5758 case 0x1ac: /* shrd imm */
5759 op = 1;
5760 shift = 1;
5761 goto do_shiftd;
5762 case 0x1ad: /* shrd cl */
5763 op = 1;
5764 shift = 0;
5765 do_shiftd:
ab4e4aec 5766 ot = dflag;
e3af7c78 5767 modrm = x86_ldub_code(env, s);
2c0262af 5768 mod = (modrm >> 6) & 3;
14ce26e7
FB
5769 rm = (modrm & 7) | REX_B(s);
5770 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af 5771 if (mod != 3) {
4eeb3939 5772 gen_lea_modrm(env, s, modrm);
b6abf97d 5773 opreg = OR_TMP0;
2c0262af 5774 } else {
b6abf97d 5775 opreg = rm;
2c0262af 5776 }
1d1cc4d0 5777 gen_op_mov_v_reg(ot, cpu_T1, reg);
3b46e624 5778
2c0262af 5779 if (shift) {
e3af7c78 5780 TCGv imm = tcg_const_tl(x86_ldub_code(env, s));
3b9d3cf1
PB
5781 gen_shiftd_rm_T1(s, ot, opreg, op, imm);
5782 tcg_temp_free(imm);
2c0262af 5783 } else {
3b9d3cf1 5784 gen_shiftd_rm_T1(s, ot, opreg, op, cpu_regs[R_ECX]);
2c0262af
FB
5785 }
5786 break;
5787
5788 /************************/
5789 /* floats */
5fafdf24 5790 case 0xd8 ... 0xdf:
7eee2a50
FB
5791 if (s->flags & (HF_EM_MASK | HF_TS_MASK)) {
5792 /* if CR0.EM or CR0.TS are set, generate an FPU exception */
5793 /* XXX: what to do if illegal op ? */
5794 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
5795 break;
5796 }
e3af7c78 5797 modrm = x86_ldub_code(env, s);
2c0262af
FB
5798 mod = (modrm >> 6) & 3;
5799 rm = modrm & 7;
5800 op = ((b & 7) << 3) | ((modrm >> 3) & 7);
2c0262af
FB
5801 if (mod != 3) {
5802 /* memory op */
4eeb3939 5803 gen_lea_modrm(env, s, modrm);
2c0262af
FB
5804 switch(op) {
5805 case 0x00 ... 0x07: /* fxxxs */
5806 case 0x10 ... 0x17: /* fixxxl */
5807 case 0x20 ... 0x27: /* fxxxl */
5808 case 0x30 ... 0x37: /* fixxx */
5809 {
5810 int op1;
5811 op1 = op & 7;
5812
5813 switch(op >> 4) {
5814 case 0:
6b672b5d 5815 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, s->A0,
80b02013 5816 s->mem_index, MO_LEUL);
d3eb5eae 5817 gen_helper_flds_FT0(cpu_env, cpu_tmp2_i32);
2c0262af
FB
5818 break;
5819 case 1:
6b672b5d 5820 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, s->A0,
80b02013 5821 s->mem_index, MO_LEUL);
d3eb5eae 5822 gen_helper_fildl_FT0(cpu_env, cpu_tmp2_i32);
2c0262af
FB
5823 break;
5824 case 2:
6b672b5d 5825 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, s->A0,
3c5f4116 5826 s->mem_index, MO_LEQ);
d3eb5eae 5827 gen_helper_fldl_FT0(cpu_env, cpu_tmp1_i64);
2c0262af
FB
5828 break;
5829 case 3:
5830 default:
6b672b5d 5831 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, s->A0,
80b02013 5832 s->mem_index, MO_LESW);
d3eb5eae 5833 gen_helper_fildl_FT0(cpu_env, cpu_tmp2_i32);
2c0262af
FB
5834 break;
5835 }
3b46e624 5836
a7812ae4 5837 gen_helper_fp_arith_ST0_FT0(op1);
2c0262af
FB
5838 if (op1 == 3) {
5839 /* fcomp needs pop */
d3eb5eae 5840 gen_helper_fpop(cpu_env);
2c0262af
FB
5841 }
5842 }
5843 break;
5844 case 0x08: /* flds */
5845 case 0x0a: /* fsts */
5846 case 0x0b: /* fstps */
465e9838
FB
5847 case 0x18 ... 0x1b: /* fildl, fisttpl, fistl, fistpl */
5848 case 0x28 ... 0x2b: /* fldl, fisttpll, fstl, fstpl */
5849 case 0x38 ... 0x3b: /* filds, fisttps, fists, fistps */
2c0262af
FB
5850 switch(op & 7) {
5851 case 0:
5852 switch(op >> 4) {
5853 case 0:
6b672b5d 5854 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, s->A0,
80b02013 5855 s->mem_index, MO_LEUL);
d3eb5eae 5856 gen_helper_flds_ST0(cpu_env, cpu_tmp2_i32);
2c0262af
FB
5857 break;
5858 case 1:
6b672b5d 5859 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, s->A0,
80b02013 5860 s->mem_index, MO_LEUL);
d3eb5eae 5861 gen_helper_fildl_ST0(cpu_env, cpu_tmp2_i32);
2c0262af
FB
5862 break;
5863 case 2:
6b672b5d 5864 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, s->A0,
3c5f4116 5865 s->mem_index, MO_LEQ);
d3eb5eae 5866 gen_helper_fldl_ST0(cpu_env, cpu_tmp1_i64);
2c0262af
FB
5867 break;
5868 case 3:
5869 default:
6b672b5d 5870 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, s->A0,
80b02013 5871 s->mem_index, MO_LESW);
d3eb5eae 5872 gen_helper_fildl_ST0(cpu_env, cpu_tmp2_i32);
2c0262af
FB
5873 break;
5874 }
5875 break;
465e9838 5876 case 1:
19e6c4b8 5877 /* XXX: the corresponding CPUID bit must be tested ! */
465e9838
FB
5878 switch(op >> 4) {
5879 case 1:
d3eb5eae 5880 gen_helper_fisttl_ST0(cpu_tmp2_i32, cpu_env);
6b672b5d 5881 tcg_gen_qemu_st_i32(cpu_tmp2_i32, s->A0,
d5601ad0 5882 s->mem_index, MO_LEUL);
465e9838
FB
5883 break;
5884 case 2:
d3eb5eae 5885 gen_helper_fisttll_ST0(cpu_tmp1_i64, cpu_env);
6b672b5d 5886 tcg_gen_qemu_st_i64(cpu_tmp1_i64, s->A0,
3523e4bd 5887 s->mem_index, MO_LEQ);
465e9838
FB
5888 break;
5889 case 3:
5890 default:
d3eb5eae 5891 gen_helper_fistt_ST0(cpu_tmp2_i32, cpu_env);
6b672b5d 5892 tcg_gen_qemu_st_i32(cpu_tmp2_i32, s->A0,
d5601ad0 5893 s->mem_index, MO_LEUW);
19e6c4b8 5894 break;
465e9838 5895 }
d3eb5eae 5896 gen_helper_fpop(cpu_env);
465e9838 5897 break;
2c0262af
FB
5898 default:
5899 switch(op >> 4) {
5900 case 0:
d3eb5eae 5901 gen_helper_fsts_ST0(cpu_tmp2_i32, cpu_env);
6b672b5d 5902 tcg_gen_qemu_st_i32(cpu_tmp2_i32, s->A0,
d5601ad0 5903 s->mem_index, MO_LEUL);
2c0262af
FB
5904 break;
5905 case 1:
d3eb5eae 5906 gen_helper_fistl_ST0(cpu_tmp2_i32, cpu_env);
6b672b5d 5907 tcg_gen_qemu_st_i32(cpu_tmp2_i32, s->A0,
d5601ad0 5908 s->mem_index, MO_LEUL);
2c0262af
FB
5909 break;
5910 case 2:
d3eb5eae 5911 gen_helper_fstl_ST0(cpu_tmp1_i64, cpu_env);
6b672b5d 5912 tcg_gen_qemu_st_i64(cpu_tmp1_i64, s->A0,
3523e4bd 5913 s->mem_index, MO_LEQ);
2c0262af
FB
5914 break;
5915 case 3:
5916 default:
d3eb5eae 5917 gen_helper_fist_ST0(cpu_tmp2_i32, cpu_env);
6b672b5d 5918 tcg_gen_qemu_st_i32(cpu_tmp2_i32, s->A0,
d5601ad0 5919 s->mem_index, MO_LEUW);
2c0262af
FB
5920 break;
5921 }
5922 if ((op & 7) == 3)
d3eb5eae 5923 gen_helper_fpop(cpu_env);
2c0262af
FB
5924 break;
5925 }
5926 break;
5927 case 0x0c: /* fldenv mem */
6b672b5d 5928 gen_helper_fldenv(cpu_env, s->A0, tcg_const_i32(dflag - 1));
2c0262af
FB
5929 break;
5930 case 0x0d: /* fldcw mem */
6b672b5d 5931 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, s->A0,
80b02013 5932 s->mem_index, MO_LEUW);
d3eb5eae 5933 gen_helper_fldcw(cpu_env, cpu_tmp2_i32);
2c0262af
FB
5934 break;
5935 case 0x0e: /* fnstenv mem */
6b672b5d 5936 gen_helper_fstenv(cpu_env, s->A0, tcg_const_i32(dflag - 1));
2c0262af
FB
5937 break;
5938 case 0x0f: /* fnstcw mem */
d3eb5eae 5939 gen_helper_fnstcw(cpu_tmp2_i32, cpu_env);
6b672b5d 5940 tcg_gen_qemu_st_i32(cpu_tmp2_i32, s->A0,
d5601ad0 5941 s->mem_index, MO_LEUW);
2c0262af
FB
5942 break;
5943 case 0x1d: /* fldt mem */
6b672b5d 5944 gen_helper_fldt_ST0(cpu_env, s->A0);
2c0262af
FB
5945 break;
5946 case 0x1f: /* fstpt mem */
6b672b5d 5947 gen_helper_fstt_ST0(cpu_env, s->A0);
d3eb5eae 5948 gen_helper_fpop(cpu_env);
2c0262af
FB
5949 break;
5950 case 0x2c: /* frstor mem */
6b672b5d 5951 gen_helper_frstor(cpu_env, s->A0, tcg_const_i32(dflag - 1));
2c0262af
FB
5952 break;
5953 case 0x2e: /* fnsave mem */
6b672b5d 5954 gen_helper_fsave(cpu_env, s->A0, tcg_const_i32(dflag - 1));
2c0262af
FB
5955 break;
5956 case 0x2f: /* fnstsw mem */
d3eb5eae 5957 gen_helper_fnstsw(cpu_tmp2_i32, cpu_env);
6b672b5d 5958 tcg_gen_qemu_st_i32(cpu_tmp2_i32, s->A0,
d5601ad0 5959 s->mem_index, MO_LEUW);
2c0262af
FB
5960 break;
5961 case 0x3c: /* fbld */
6b672b5d 5962 gen_helper_fbld_ST0(cpu_env, s->A0);
2c0262af
FB
5963 break;
5964 case 0x3e: /* fbstp */
6b672b5d 5965 gen_helper_fbst_ST0(cpu_env, s->A0);
d3eb5eae 5966 gen_helper_fpop(cpu_env);
2c0262af
FB
5967 break;
5968 case 0x3d: /* fildll */
6b672b5d 5969 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, s->A0, s->mem_index, MO_LEQ);
d3eb5eae 5970 gen_helper_fildll_ST0(cpu_env, cpu_tmp1_i64);
2c0262af
FB
5971 break;
5972 case 0x3f: /* fistpll */
d3eb5eae 5973 gen_helper_fistll_ST0(cpu_tmp1_i64, cpu_env);
6b672b5d 5974 tcg_gen_qemu_st_i64(cpu_tmp1_i64, s->A0, s->mem_index, MO_LEQ);
d3eb5eae 5975 gen_helper_fpop(cpu_env);
2c0262af
FB
5976 break;
5977 default:
b9f9c5b4 5978 goto unknown_op;
2c0262af
FB
5979 }
5980 } else {
5981 /* register float ops */
5982 opreg = rm;
5983
5984 switch(op) {
5985 case 0x08: /* fld sti */
d3eb5eae
BS
5986 gen_helper_fpush(cpu_env);
5987 gen_helper_fmov_ST0_STN(cpu_env,
5988 tcg_const_i32((opreg + 1) & 7));
2c0262af
FB
5989 break;
5990 case 0x09: /* fxchg sti */
c169c906
FB
5991 case 0x29: /* fxchg4 sti, undocumented op */
5992 case 0x39: /* fxchg7 sti, undocumented op */
d3eb5eae 5993 gen_helper_fxchg_ST0_STN(cpu_env, tcg_const_i32(opreg));
2c0262af
FB
5994 break;
5995 case 0x0a: /* grp d9/2 */
5996 switch(rm) {
5997 case 0: /* fnop */
023fe10d 5998 /* check exceptions (FreeBSD FPU probe) */
d3eb5eae 5999 gen_helper_fwait(cpu_env);
2c0262af
FB
6000 break;
6001 default:
b9f9c5b4 6002 goto unknown_op;
2c0262af
FB
6003 }
6004 break;
6005 case 0x0c: /* grp d9/4 */
6006 switch(rm) {
6007 case 0: /* fchs */
d3eb5eae 6008 gen_helper_fchs_ST0(cpu_env);
2c0262af
FB
6009 break;
6010 case 1: /* fabs */
d3eb5eae 6011 gen_helper_fabs_ST0(cpu_env);
2c0262af
FB
6012 break;
6013 case 4: /* ftst */
d3eb5eae
BS
6014 gen_helper_fldz_FT0(cpu_env);
6015 gen_helper_fcom_ST0_FT0(cpu_env);
2c0262af
FB
6016 break;
6017 case 5: /* fxam */
d3eb5eae 6018 gen_helper_fxam_ST0(cpu_env);
2c0262af
FB
6019 break;
6020 default:
b9f9c5b4 6021 goto unknown_op;
2c0262af
FB
6022 }
6023 break;
6024 case 0x0d: /* grp d9/5 */
6025 {
6026 switch(rm) {
6027 case 0:
d3eb5eae
BS
6028 gen_helper_fpush(cpu_env);
6029 gen_helper_fld1_ST0(cpu_env);
2c0262af
FB
6030 break;
6031 case 1:
d3eb5eae
BS
6032 gen_helper_fpush(cpu_env);
6033 gen_helper_fldl2t_ST0(cpu_env);
2c0262af
FB
6034 break;
6035 case 2:
d3eb5eae
BS
6036 gen_helper_fpush(cpu_env);
6037 gen_helper_fldl2e_ST0(cpu_env);
2c0262af
FB
6038 break;
6039 case 3:
d3eb5eae
BS
6040 gen_helper_fpush(cpu_env);
6041 gen_helper_fldpi_ST0(cpu_env);
2c0262af
FB
6042 break;
6043 case 4:
d3eb5eae
BS
6044 gen_helper_fpush(cpu_env);
6045 gen_helper_fldlg2_ST0(cpu_env);
2c0262af
FB
6046 break;
6047 case 5:
d3eb5eae
BS
6048 gen_helper_fpush(cpu_env);
6049 gen_helper_fldln2_ST0(cpu_env);
2c0262af
FB
6050 break;
6051 case 6:
d3eb5eae
BS
6052 gen_helper_fpush(cpu_env);
6053 gen_helper_fldz_ST0(cpu_env);
2c0262af
FB
6054 break;
6055 default:
b9f9c5b4 6056 goto unknown_op;
2c0262af
FB
6057 }
6058 }
6059 break;
6060 case 0x0e: /* grp d9/6 */
6061 switch(rm) {
6062 case 0: /* f2xm1 */
d3eb5eae 6063 gen_helper_f2xm1(cpu_env);
2c0262af
FB
6064 break;
6065 case 1: /* fyl2x */
d3eb5eae 6066 gen_helper_fyl2x(cpu_env);
2c0262af
FB
6067 break;
6068 case 2: /* fptan */
d3eb5eae 6069 gen_helper_fptan(cpu_env);
2c0262af
FB
6070 break;
6071 case 3: /* fpatan */
d3eb5eae 6072 gen_helper_fpatan(cpu_env);
2c0262af
FB
6073 break;
6074 case 4: /* fxtract */
d3eb5eae 6075 gen_helper_fxtract(cpu_env);
2c0262af
FB
6076 break;
6077 case 5: /* fprem1 */
d3eb5eae 6078 gen_helper_fprem1(cpu_env);
2c0262af
FB
6079 break;
6080 case 6: /* fdecstp */
d3eb5eae 6081 gen_helper_fdecstp(cpu_env);
2c0262af
FB
6082 break;
6083 default:
6084 case 7: /* fincstp */
d3eb5eae 6085 gen_helper_fincstp(cpu_env);
2c0262af
FB
6086 break;
6087 }
6088 break;
6089 case 0x0f: /* grp d9/7 */
6090 switch(rm) {
6091 case 0: /* fprem */
d3eb5eae 6092 gen_helper_fprem(cpu_env);
2c0262af
FB
6093 break;
6094 case 1: /* fyl2xp1 */
d3eb5eae 6095 gen_helper_fyl2xp1(cpu_env);
2c0262af
FB
6096 break;
6097 case 2: /* fsqrt */
d3eb5eae 6098 gen_helper_fsqrt(cpu_env);
2c0262af
FB
6099 break;
6100 case 3: /* fsincos */
d3eb5eae 6101 gen_helper_fsincos(cpu_env);
2c0262af
FB
6102 break;
6103 case 5: /* fscale */
d3eb5eae 6104 gen_helper_fscale(cpu_env);
2c0262af
FB
6105 break;
6106 case 4: /* frndint */
d3eb5eae 6107 gen_helper_frndint(cpu_env);
2c0262af
FB
6108 break;
6109 case 6: /* fsin */
d3eb5eae 6110 gen_helper_fsin(cpu_env);
2c0262af
FB
6111 break;
6112 default:
6113 case 7: /* fcos */
d3eb5eae 6114 gen_helper_fcos(cpu_env);
2c0262af
FB
6115 break;
6116 }
6117 break;
6118 case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
6119 case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
6120 case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
6121 {
6122 int op1;
3b46e624 6123
2c0262af
FB
6124 op1 = op & 7;
6125 if (op >= 0x20) {
a7812ae4 6126 gen_helper_fp_arith_STN_ST0(op1, opreg);
2c0262af 6127 if (op >= 0x30)
d3eb5eae 6128 gen_helper_fpop(cpu_env);
2c0262af 6129 } else {
d3eb5eae 6130 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
a7812ae4 6131 gen_helper_fp_arith_ST0_FT0(op1);
2c0262af
FB
6132 }
6133 }
6134 break;
6135 case 0x02: /* fcom */
c169c906 6136 case 0x22: /* fcom2, undocumented op */
d3eb5eae
BS
6137 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6138 gen_helper_fcom_ST0_FT0(cpu_env);
2c0262af
FB
6139 break;
6140 case 0x03: /* fcomp */
c169c906
FB
6141 case 0x23: /* fcomp3, undocumented op */
6142 case 0x32: /* fcomp5, undocumented op */
d3eb5eae
BS
6143 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6144 gen_helper_fcom_ST0_FT0(cpu_env);
6145 gen_helper_fpop(cpu_env);
2c0262af
FB
6146 break;
6147 case 0x15: /* da/5 */
6148 switch(rm) {
6149 case 1: /* fucompp */
d3eb5eae
BS
6150 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(1));
6151 gen_helper_fucom_ST0_FT0(cpu_env);
6152 gen_helper_fpop(cpu_env);
6153 gen_helper_fpop(cpu_env);
2c0262af
FB
6154 break;
6155 default:
b9f9c5b4 6156 goto unknown_op;
2c0262af
FB
6157 }
6158 break;
6159 case 0x1c:
6160 switch(rm) {
6161 case 0: /* feni (287 only, just do nop here) */
6162 break;
6163 case 1: /* fdisi (287 only, just do nop here) */
6164 break;
6165 case 2: /* fclex */
d3eb5eae 6166 gen_helper_fclex(cpu_env);
2c0262af
FB
6167 break;
6168 case 3: /* fninit */
d3eb5eae 6169 gen_helper_fninit(cpu_env);
2c0262af
FB
6170 break;
6171 case 4: /* fsetpm (287 only, just do nop here) */
6172 break;
6173 default:
b9f9c5b4 6174 goto unknown_op;
2c0262af
FB
6175 }
6176 break;
6177 case 0x1d: /* fucomi */
bff93281
PM
6178 if (!(s->cpuid_features & CPUID_CMOV)) {
6179 goto illegal_op;
6180 }
773cdfcc 6181 gen_update_cc_op(s);
d3eb5eae
BS
6182 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6183 gen_helper_fucomi_ST0_FT0(cpu_env);
3ca51d07 6184 set_cc_op(s, CC_OP_EFLAGS);
2c0262af
FB
6185 break;
6186 case 0x1e: /* fcomi */
bff93281
PM
6187 if (!(s->cpuid_features & CPUID_CMOV)) {
6188 goto illegal_op;
6189 }
773cdfcc 6190 gen_update_cc_op(s);
d3eb5eae
BS
6191 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6192 gen_helper_fcomi_ST0_FT0(cpu_env);
3ca51d07 6193 set_cc_op(s, CC_OP_EFLAGS);
2c0262af 6194 break;
658c8bda 6195 case 0x28: /* ffree sti */
d3eb5eae 6196 gen_helper_ffree_STN(cpu_env, tcg_const_i32(opreg));
5fafdf24 6197 break;
2c0262af 6198 case 0x2a: /* fst sti */
d3eb5eae 6199 gen_helper_fmov_STN_ST0(cpu_env, tcg_const_i32(opreg));
2c0262af
FB
6200 break;
6201 case 0x2b: /* fstp sti */
c169c906
FB
6202 case 0x0b: /* fstp1 sti, undocumented op */
6203 case 0x3a: /* fstp8 sti, undocumented op */
6204 case 0x3b: /* fstp9 sti, undocumented op */
d3eb5eae
BS
6205 gen_helper_fmov_STN_ST0(cpu_env, tcg_const_i32(opreg));
6206 gen_helper_fpop(cpu_env);
2c0262af
FB
6207 break;
6208 case 0x2c: /* fucom st(i) */
d3eb5eae
BS
6209 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6210 gen_helper_fucom_ST0_FT0(cpu_env);
2c0262af
FB
6211 break;
6212 case 0x2d: /* fucomp st(i) */
d3eb5eae
BS
6213 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6214 gen_helper_fucom_ST0_FT0(cpu_env);
6215 gen_helper_fpop(cpu_env);
2c0262af
FB
6216 break;
6217 case 0x33: /* de/3 */
6218 switch(rm) {
6219 case 1: /* fcompp */
d3eb5eae
BS
6220 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(1));
6221 gen_helper_fcom_ST0_FT0(cpu_env);
6222 gen_helper_fpop(cpu_env);
6223 gen_helper_fpop(cpu_env);
2c0262af
FB
6224 break;
6225 default:
b9f9c5b4 6226 goto unknown_op;
2c0262af
FB
6227 }
6228 break;
c169c906 6229 case 0x38: /* ffreep sti, undocumented op */
d3eb5eae
BS
6230 gen_helper_ffree_STN(cpu_env, tcg_const_i32(opreg));
6231 gen_helper_fpop(cpu_env);
c169c906 6232 break;
2c0262af
FB
6233 case 0x3c: /* df/4 */
6234 switch(rm) {
6235 case 0:
d3eb5eae 6236 gen_helper_fnstsw(cpu_tmp2_i32, cpu_env);
c66f9727
EC
6237 tcg_gen_extu_i32_tl(s->T0, cpu_tmp2_i32);
6238 gen_op_mov_reg_v(MO_16, R_EAX, s->T0);
2c0262af
FB
6239 break;
6240 default:
b9f9c5b4 6241 goto unknown_op;
2c0262af
FB
6242 }
6243 break;
6244 case 0x3d: /* fucomip */
bff93281
PM
6245 if (!(s->cpuid_features & CPUID_CMOV)) {
6246 goto illegal_op;
6247 }
773cdfcc 6248 gen_update_cc_op(s);
d3eb5eae
BS
6249 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6250 gen_helper_fucomi_ST0_FT0(cpu_env);
6251 gen_helper_fpop(cpu_env);
3ca51d07 6252 set_cc_op(s, CC_OP_EFLAGS);
2c0262af
FB
6253 break;
6254 case 0x3e: /* fcomip */
bff93281
PM
6255 if (!(s->cpuid_features & CPUID_CMOV)) {
6256 goto illegal_op;
6257 }
773cdfcc 6258 gen_update_cc_op(s);
d3eb5eae
BS
6259 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6260 gen_helper_fcomi_ST0_FT0(cpu_env);
6261 gen_helper_fpop(cpu_env);
3ca51d07 6262 set_cc_op(s, CC_OP_EFLAGS);
2c0262af 6263 break;
a2cc3b24
FB
6264 case 0x10 ... 0x13: /* fcmovxx */
6265 case 0x18 ... 0x1b:
6266 {
42a268c2
RH
6267 int op1;
6268 TCGLabel *l1;
d70040bc 6269 static const uint8_t fcmov_cc[8] = {
a2cc3b24
FB
6270 (JCC_B << 1),
6271 (JCC_Z << 1),
6272 (JCC_BE << 1),
6273 (JCC_P << 1),
6274 };
bff93281
PM
6275
6276 if (!(s->cpuid_features & CPUID_CMOV)) {
6277 goto illegal_op;
6278 }
1e4840bf 6279 op1 = fcmov_cc[op & 3] | (((op >> 3) & 1) ^ 1);
19e6c4b8 6280 l1 = gen_new_label();
dc259201 6281 gen_jcc1_noeob(s, op1, l1);
d3eb5eae 6282 gen_helper_fmov_ST0_STN(cpu_env, tcg_const_i32(opreg));
19e6c4b8 6283 gen_set_label(l1);
a2cc3b24
FB
6284 }
6285 break;
2c0262af 6286 default:
b9f9c5b4 6287 goto unknown_op;
2c0262af
FB
6288 }
6289 }
6290 break;
6291 /************************/
6292 /* string ops */
6293
6294 case 0xa4: /* movsS */
6295 case 0xa5:
ab4e4aec 6296 ot = mo_b_d(b, dflag);
2c0262af
FB
6297 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6298 gen_repz_movs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6299 } else {
6300 gen_movs(s, ot);
6301 }
6302 break;
3b46e624 6303
2c0262af
FB
6304 case 0xaa: /* stosS */
6305 case 0xab:
ab4e4aec 6306 ot = mo_b_d(b, dflag);
2c0262af
FB
6307 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6308 gen_repz_stos(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6309 } else {
6310 gen_stos(s, ot);
6311 }
6312 break;
6313 case 0xac: /* lodsS */
6314 case 0xad:
ab4e4aec 6315 ot = mo_b_d(b, dflag);
2c0262af
FB
6316 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6317 gen_repz_lods(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6318 } else {
6319 gen_lods(s, ot);
6320 }
6321 break;
6322 case 0xae: /* scasS */
6323 case 0xaf:
ab4e4aec 6324 ot = mo_b_d(b, dflag);
2c0262af
FB
6325 if (prefixes & PREFIX_REPNZ) {
6326 gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
6327 } else if (prefixes & PREFIX_REPZ) {
6328 gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
6329 } else {
6330 gen_scas(s, ot);
2c0262af
FB
6331 }
6332 break;
6333
6334 case 0xa6: /* cmpsS */
6335 case 0xa7:
ab4e4aec 6336 ot = mo_b_d(b, dflag);
2c0262af
FB
6337 if (prefixes & PREFIX_REPNZ) {
6338 gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
6339 } else if (prefixes & PREFIX_REPZ) {
6340 gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
6341 } else {
6342 gen_cmps(s, ot);
2c0262af
FB
6343 }
6344 break;
6345 case 0x6c: /* insS */
6346 case 0x6d:
ab4e4aec 6347 ot = mo_b_d32(b, dflag);
c66f9727 6348 tcg_gen_ext16u_tl(s->T0, cpu_regs[R_EDX]);
b8b6a50b
FB
6349 gen_check_io(s, ot, pc_start - s->cs_base,
6350 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes) | 4);
f115e911
FB
6351 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6352 gen_repz_ins(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
2c0262af 6353 } else {
f115e911 6354 gen_ins(s, ot);
c5a49c63 6355 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
2e70f6ef
PB
6356 gen_jmp(s, s->pc - s->cs_base);
6357 }
2c0262af
FB
6358 }
6359 break;
6360 case 0x6e: /* outsS */
6361 case 0x6f:
ab4e4aec 6362 ot = mo_b_d32(b, dflag);
c66f9727 6363 tcg_gen_ext16u_tl(s->T0, cpu_regs[R_EDX]);
b8b6a50b
FB
6364 gen_check_io(s, ot, pc_start - s->cs_base,
6365 svm_is_rep(prefixes) | 4);
f115e911
FB
6366 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6367 gen_repz_outs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
2c0262af 6368 } else {
f115e911 6369 gen_outs(s, ot);
c5a49c63 6370 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
2e70f6ef
PB
6371 gen_jmp(s, s->pc - s->cs_base);
6372 }
2c0262af
FB
6373 }
6374 break;
6375
6376 /************************/
6377 /* port I/O */
0573fbfc 6378
2c0262af
FB
6379 case 0xe4:
6380 case 0xe5:
ab4e4aec 6381 ot = mo_b_d32(b, dflag);
e3af7c78 6382 val = x86_ldub_code(env, s);
c66f9727 6383 tcg_gen_movi_tl(s->T0, val);
b8b6a50b
FB
6384 gen_check_io(s, ot, pc_start - s->cs_base,
6385 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes));
c5a49c63 6386 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 6387 gen_io_start();
bd79255d 6388 }
1b90d56e 6389 tcg_gen_movi_i32(cpu_tmp2_i32, val);
1d1cc4d0
RH
6390 gen_helper_in_func(ot, cpu_T1, cpu_tmp2_i32);
6391 gen_op_mov_reg_v(ot, R_EAX, cpu_T1);
5223a942 6392 gen_bpt_io(s, cpu_tmp2_i32, ot);
c5a49c63 6393 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
2e70f6ef
PB
6394 gen_io_end();
6395 gen_jmp(s, s->pc - s->cs_base);
6396 }
2c0262af
FB
6397 break;
6398 case 0xe6:
6399 case 0xe7:
ab4e4aec 6400 ot = mo_b_d32(b, dflag);
e3af7c78 6401 val = x86_ldub_code(env, s);
c66f9727 6402 tcg_gen_movi_tl(s->T0, val);
b8b6a50b
FB
6403 gen_check_io(s, ot, pc_start - s->cs_base,
6404 svm_is_rep(prefixes));
1d1cc4d0 6405 gen_op_mov_v_reg(ot, cpu_T1, R_EAX);
b8b6a50b 6406
c5a49c63 6407 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 6408 gen_io_start();
bd79255d 6409 }
1b90d56e 6410 tcg_gen_movi_i32(cpu_tmp2_i32, val);
1d1cc4d0 6411 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T1);
a7812ae4 6412 gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32);
5223a942 6413 gen_bpt_io(s, cpu_tmp2_i32, ot);
c5a49c63 6414 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
2e70f6ef
PB
6415 gen_io_end();
6416 gen_jmp(s, s->pc - s->cs_base);
6417 }
2c0262af
FB
6418 break;
6419 case 0xec:
6420 case 0xed:
ab4e4aec 6421 ot = mo_b_d32(b, dflag);
c66f9727 6422 tcg_gen_ext16u_tl(s->T0, cpu_regs[R_EDX]);
b8b6a50b
FB
6423 gen_check_io(s, ot, pc_start - s->cs_base,
6424 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes));
c5a49c63 6425 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 6426 gen_io_start();
bd79255d 6427 }
c66f9727 6428 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, s->T0);
1d1cc4d0
RH
6429 gen_helper_in_func(ot, cpu_T1, cpu_tmp2_i32);
6430 gen_op_mov_reg_v(ot, R_EAX, cpu_T1);
5223a942 6431 gen_bpt_io(s, cpu_tmp2_i32, ot);
c5a49c63 6432 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
2e70f6ef
PB
6433 gen_io_end();
6434 gen_jmp(s, s->pc - s->cs_base);
6435 }
2c0262af
FB
6436 break;
6437 case 0xee:
6438 case 0xef:
ab4e4aec 6439 ot = mo_b_d32(b, dflag);
c66f9727 6440 tcg_gen_ext16u_tl(s->T0, cpu_regs[R_EDX]);
b8b6a50b
FB
6441 gen_check_io(s, ot, pc_start - s->cs_base,
6442 svm_is_rep(prefixes));
1d1cc4d0 6443 gen_op_mov_v_reg(ot, cpu_T1, R_EAX);
b8b6a50b 6444
c5a49c63 6445 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
2e70f6ef 6446 gen_io_start();
bd79255d 6447 }
c66f9727 6448 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, s->T0);
1d1cc4d0 6449 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T1);
a7812ae4 6450 gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32);
5223a942 6451 gen_bpt_io(s, cpu_tmp2_i32, ot);
c5a49c63 6452 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
2e70f6ef
PB
6453 gen_io_end();
6454 gen_jmp(s, s->pc - s->cs_base);
6455 }
2c0262af
FB
6456 break;
6457
6458 /************************/
6459 /* control */
6460 case 0xc2: /* ret im */
e3af7c78 6461 val = x86_ldsw_code(env, s);
8e31d234
RH
6462 ot = gen_pop_T0(s);
6463 gen_stack_update(s, val + (1 << ot));
6464 /* Note that gen_pop_T0 uses a zero-extending load. */
c66f9727 6465 gen_op_jmp_v(s->T0);
7d117ce8 6466 gen_bnd_jmp(s);
c66f9727 6467 gen_jr(s, s->T0);
2c0262af
FB
6468 break;
6469 case 0xc3: /* ret */
8e31d234
RH
6470 ot = gen_pop_T0(s);
6471 gen_pop_update(s, ot);
6472 /* Note that gen_pop_T0 uses a zero-extending load. */
c66f9727 6473 gen_op_jmp_v(s->T0);
7d117ce8 6474 gen_bnd_jmp(s);
c66f9727 6475 gen_jr(s, s->T0);
2c0262af
FB
6476 break;
6477 case 0xca: /* lret im */
e3af7c78 6478 val = x86_ldsw_code(env, s);
2c0262af
FB
6479 do_lret:
6480 if (s->pe && !s->vm86) {
773cdfcc 6481 gen_update_cc_op(s);
14ce26e7 6482 gen_jmp_im(pc_start - s->cs_base);
ab4e4aec 6483 gen_helper_lret_protected(cpu_env, tcg_const_i32(dflag - 1),
a7812ae4 6484 tcg_const_i32(val));
2c0262af
FB
6485 } else {
6486 gen_stack_A0(s);
6487 /* pop offset */
c66f9727 6488 gen_op_ld_v(s, dflag, s->T0, s->A0);
2c0262af
FB
6489 /* NOTE: keeping EIP updated is not a problem in case of
6490 exception */
c66f9727 6491 gen_op_jmp_v(s->T0);
2c0262af 6492 /* pop selector */
4e85057b 6493 gen_add_A0_im(s, 1 << dflag);
c66f9727
EC
6494 gen_op_ld_v(s, dflag, s->T0, s->A0);
6495 gen_op_movl_seg_T0_vm(s, R_CS);
2c0262af 6496 /* add stack offset */
ab4e4aec 6497 gen_stack_update(s, val + (2 << dflag));
2c0262af
FB
6498 }
6499 gen_eob(s);
6500 break;
6501 case 0xcb: /* lret */
6502 val = 0;
6503 goto do_lret;
6504 case 0xcf: /* iret */
872929aa 6505 gen_svm_check_intercept(s, pc_start, SVM_EXIT_IRET);
2c0262af
FB
6506 if (!s->pe) {
6507 /* real mode */
ab4e4aec 6508 gen_helper_iret_real(cpu_env, tcg_const_i32(dflag - 1));
3ca51d07 6509 set_cc_op(s, CC_OP_EFLAGS);
f115e911
FB
6510 } else if (s->vm86) {
6511 if (s->iopl != 3) {
6512 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6513 } else {
ab4e4aec 6514 gen_helper_iret_real(cpu_env, tcg_const_i32(dflag - 1));
3ca51d07 6515 set_cc_op(s, CC_OP_EFLAGS);
f115e911 6516 }
2c0262af 6517 } else {
ab4e4aec 6518 gen_helper_iret_protected(cpu_env, tcg_const_i32(dflag - 1),
a7812ae4 6519 tcg_const_i32(s->pc - s->cs_base));
3ca51d07 6520 set_cc_op(s, CC_OP_EFLAGS);
2c0262af 6521 }
410e9814 6522 gen_eob(s);
2c0262af
FB
6523 break;
6524 case 0xe8: /* call im */
6525 {
ab4e4aec 6526 if (dflag != MO_16) {
4ba9938c 6527 tval = (int32_t)insn_get(env, s, MO_32);
ab4e4aec 6528 } else {
4ba9938c 6529 tval = (int16_t)insn_get(env, s, MO_16);
ab4e4aec 6530 }
2c0262af 6531 next_eip = s->pc - s->cs_base;
14ce26e7 6532 tval += next_eip;
ab4e4aec 6533 if (dflag == MO_16) {
14ce26e7 6534 tval &= 0xffff;
ab4e4aec 6535 } else if (!CODE64(s)) {
99596385 6536 tval &= 0xffffffff;
ab4e4aec 6537 }
c66f9727
EC
6538 tcg_gen_movi_tl(s->T0, next_eip);
6539 gen_push_v(s, s->T0);
7d117ce8 6540 gen_bnd_jmp(s);
14ce26e7 6541 gen_jmp(s, tval);
2c0262af
FB
6542 }
6543 break;
6544 case 0x9a: /* lcall im */
6545 {
6546 unsigned int selector, offset;
3b46e624 6547
14ce26e7
FB
6548 if (CODE64(s))
6549 goto illegal_op;
ab4e4aec 6550 ot = dflag;
0af10c86 6551 offset = insn_get(env, s, ot);
4ba9938c 6552 selector = insn_get(env, s, MO_16);
3b46e624 6553
c66f9727 6554 tcg_gen_movi_tl(s->T0, selector);
1d1cc4d0 6555 tcg_gen_movi_tl(cpu_T1, offset);
2c0262af
FB
6556 }
6557 goto do_lcall;
ecada8a2 6558 case 0xe9: /* jmp im */
ab4e4aec 6559 if (dflag != MO_16) {
4ba9938c 6560 tval = (int32_t)insn_get(env, s, MO_32);
ab4e4aec 6561 } else {
4ba9938c 6562 tval = (int16_t)insn_get(env, s, MO_16);
ab4e4aec 6563 }
14ce26e7 6564 tval += s->pc - s->cs_base;
ab4e4aec 6565 if (dflag == MO_16) {
14ce26e7 6566 tval &= 0xffff;
ab4e4aec 6567 } else if (!CODE64(s)) {
32938e12 6568 tval &= 0xffffffff;
ab4e4aec 6569 }
7d117ce8 6570 gen_bnd_jmp(s);
14ce26e7 6571 gen_jmp(s, tval);
2c0262af
FB
6572 break;
6573 case 0xea: /* ljmp im */
6574 {
6575 unsigned int selector, offset;
6576
14ce26e7
FB
6577 if (CODE64(s))
6578 goto illegal_op;
ab4e4aec 6579 ot = dflag;
0af10c86 6580 offset = insn_get(env, s, ot);
4ba9938c 6581 selector = insn_get(env, s, MO_16);
3b46e624 6582
c66f9727 6583 tcg_gen_movi_tl(s->T0, selector);
1d1cc4d0 6584 tcg_gen_movi_tl(cpu_T1, offset);
2c0262af
FB
6585 }
6586 goto do_ljmp;
6587 case 0xeb: /* jmp Jb */
4ba9938c 6588 tval = (int8_t)insn_get(env, s, MO_8);
14ce26e7 6589 tval += s->pc - s->cs_base;
ab4e4aec 6590 if (dflag == MO_16) {
14ce26e7 6591 tval &= 0xffff;
ab4e4aec 6592 }
14ce26e7 6593 gen_jmp(s, tval);
2c0262af
FB
6594 break;
6595 case 0x70 ... 0x7f: /* jcc Jb */
4ba9938c 6596 tval = (int8_t)insn_get(env, s, MO_8);
2c0262af
FB
6597 goto do_jcc;
6598 case 0x180 ... 0x18f: /* jcc Jv */
ab4e4aec 6599 if (dflag != MO_16) {
4ba9938c 6600 tval = (int32_t)insn_get(env, s, MO_32);
2c0262af 6601 } else {
4ba9938c 6602 tval = (int16_t)insn_get(env, s, MO_16);
2c0262af
FB
6603 }
6604 do_jcc:
6605 next_eip = s->pc - s->cs_base;
14ce26e7 6606 tval += next_eip;
ab4e4aec 6607 if (dflag == MO_16) {
14ce26e7 6608 tval &= 0xffff;
ab4e4aec 6609 }
7d117ce8 6610 gen_bnd_jmp(s);
14ce26e7 6611 gen_jcc(s, b, tval, next_eip);
2c0262af
FB
6612 break;
6613
6614 case 0x190 ... 0x19f: /* setcc Gv */
e3af7c78 6615 modrm = x86_ldub_code(env, s);
c66f9727 6616 gen_setcc1(s, b, s->T0);
4ba9938c 6617 gen_ldst_modrm(env, s, modrm, MO_8, OR_TMP0, 1);
2c0262af
FB
6618 break;
6619 case 0x140 ... 0x14f: /* cmov Gv, Ev */
bff93281
PM
6620 if (!(s->cpuid_features & CPUID_CMOV)) {
6621 goto illegal_op;
6622 }
ab4e4aec 6623 ot = dflag;
e3af7c78 6624 modrm = x86_ldub_code(env, s);
f32d3781
PB
6625 reg = ((modrm >> 3) & 7) | rex_r;
6626 gen_cmovcc1(env, s, ot, b, modrm, reg);
2c0262af 6627 break;
3b46e624 6628
2c0262af
FB
6629 /************************/
6630 /* flags */
6631 case 0x9c: /* pushf */
872929aa 6632 gen_svm_check_intercept(s, pc_start, SVM_EXIT_PUSHF);
2c0262af
FB
6633 if (s->vm86 && s->iopl != 3) {
6634 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6635 } else {
773cdfcc 6636 gen_update_cc_op(s);
c66f9727
EC
6637 gen_helper_read_eflags(s->T0, cpu_env);
6638 gen_push_v(s, s->T0);
2c0262af
FB
6639 }
6640 break;
6641 case 0x9d: /* popf */
872929aa 6642 gen_svm_check_intercept(s, pc_start, SVM_EXIT_POPF);
2c0262af
FB
6643 if (s->vm86 && s->iopl != 3) {
6644 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6645 } else {
8e31d234 6646 ot = gen_pop_T0(s);
2c0262af 6647 if (s->cpl == 0) {
ab4e4aec 6648 if (dflag != MO_16) {
c66f9727 6649 gen_helper_write_eflags(cpu_env, s->T0,
f0967a1a
BS
6650 tcg_const_i32((TF_MASK | AC_MASK |
6651 ID_MASK | NT_MASK |
6652 IF_MASK |
6653 IOPL_MASK)));
2c0262af 6654 } else {
c66f9727 6655 gen_helper_write_eflags(cpu_env, s->T0,
f0967a1a
BS
6656 tcg_const_i32((TF_MASK | AC_MASK |
6657 ID_MASK | NT_MASK |
6658 IF_MASK | IOPL_MASK)
6659 & 0xffff));
2c0262af
FB
6660 }
6661 } else {
4136f33c 6662 if (s->cpl <= s->iopl) {
ab4e4aec 6663 if (dflag != MO_16) {
c66f9727 6664 gen_helper_write_eflags(cpu_env, s->T0,
f0967a1a
BS
6665 tcg_const_i32((TF_MASK |
6666 AC_MASK |
6667 ID_MASK |
6668 NT_MASK |
6669 IF_MASK)));
4136f33c 6670 } else {
c66f9727 6671 gen_helper_write_eflags(cpu_env, s->T0,
f0967a1a
BS
6672 tcg_const_i32((TF_MASK |
6673 AC_MASK |
6674 ID_MASK |
6675 NT_MASK |
6676 IF_MASK)
6677 & 0xffff));
4136f33c 6678 }
2c0262af 6679 } else {
ab4e4aec 6680 if (dflag != MO_16) {
c66f9727 6681 gen_helper_write_eflags(cpu_env, s->T0,
f0967a1a
BS
6682 tcg_const_i32((TF_MASK | AC_MASK |
6683 ID_MASK | NT_MASK)));
4136f33c 6684 } else {
c66f9727 6685 gen_helper_write_eflags(cpu_env, s->T0,
f0967a1a
BS
6686 tcg_const_i32((TF_MASK | AC_MASK |
6687 ID_MASK | NT_MASK)
6688 & 0xffff));
4136f33c 6689 }
2c0262af
FB
6690 }
6691 }
8e31d234 6692 gen_pop_update(s, ot);
3ca51d07 6693 set_cc_op(s, CC_OP_EFLAGS);
a9321a4d 6694 /* abort translation because TF/AC flag may change */
14ce26e7 6695 gen_jmp_im(s->pc - s->cs_base);
2c0262af
FB
6696 gen_eob(s);
6697 }
6698 break;
6699 case 0x9e: /* sahf */
12e26b75 6700 if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM))
14ce26e7 6701 goto illegal_op;
c66f9727 6702 gen_op_mov_v_reg(MO_8, s->T0, R_AH);
d229edce 6703 gen_compute_eflags(s);
bd7a7b33 6704 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, CC_O);
c66f9727
EC
6705 tcg_gen_andi_tl(s->T0, s->T0, CC_S | CC_Z | CC_A | CC_P | CC_C);
6706 tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, s->T0);
2c0262af
FB
6707 break;
6708 case 0x9f: /* lahf */
12e26b75 6709 if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM))
14ce26e7 6710 goto illegal_op;
d229edce 6711 gen_compute_eflags(s);
bd7a7b33 6712 /* Note: gen_compute_eflags() only gives the condition codes */
c66f9727
EC
6713 tcg_gen_ori_tl(s->T0, cpu_cc_src, 0x02);
6714 gen_op_mov_reg_v(MO_8, R_AH, s->T0);
2c0262af
FB
6715 break;
6716 case 0xf5: /* cmc */
d229edce 6717 gen_compute_eflags(s);
bd7a7b33 6718 tcg_gen_xori_tl(cpu_cc_src, cpu_cc_src, CC_C);
2c0262af
FB
6719 break;
6720 case 0xf8: /* clc */
d229edce 6721 gen_compute_eflags(s);
bd7a7b33 6722 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~CC_C);
2c0262af
FB
6723 break;
6724 case 0xf9: /* stc */
d229edce 6725 gen_compute_eflags(s);
bd7a7b33 6726 tcg_gen_ori_tl(cpu_cc_src, cpu_cc_src, CC_C);
2c0262af
FB
6727 break;
6728 case 0xfc: /* cld */
b6abf97d 6729 tcg_gen_movi_i32(cpu_tmp2_i32, 1);
317ac620 6730 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, offsetof(CPUX86State, df));
2c0262af
FB
6731 break;
6732 case 0xfd: /* std */
b6abf97d 6733 tcg_gen_movi_i32(cpu_tmp2_i32, -1);
317ac620 6734 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, offsetof(CPUX86State, df));
2c0262af
FB
6735 break;
6736
6737 /************************/
6738 /* bit operations */
6739 case 0x1ba: /* bt/bts/btr/btc Gv, im */
ab4e4aec 6740 ot = dflag;
e3af7c78 6741 modrm = x86_ldub_code(env, s);
33698e5f 6742 op = (modrm >> 3) & 7;
2c0262af 6743 mod = (modrm >> 6) & 3;
14ce26e7 6744 rm = (modrm & 7) | REX_B(s);
2c0262af 6745 if (mod != 3) {
14ce26e7 6746 s->rip_offset = 1;
4eeb3939 6747 gen_lea_modrm(env, s, modrm);
cfe819d3 6748 if (!(s->prefix & PREFIX_LOCK)) {
c66f9727 6749 gen_op_ld_v(s, ot, s->T0, s->A0);
cfe819d3 6750 }
2c0262af 6751 } else {
c66f9727 6752 gen_op_mov_v_reg(ot, s->T0, rm);
2c0262af
FB
6753 }
6754 /* load shift */
e3af7c78 6755 val = x86_ldub_code(env, s);
1d1cc4d0 6756 tcg_gen_movi_tl(cpu_T1, val);
2c0262af 6757 if (op < 4)
b9f9c5b4 6758 goto unknown_op;
2c0262af 6759 op -= 4;
f484d386 6760 goto bt_op;
2c0262af
FB
6761 case 0x1a3: /* bt Gv, Ev */
6762 op = 0;
6763 goto do_btx;
6764 case 0x1ab: /* bts */
6765 op = 1;
6766 goto do_btx;
6767 case 0x1b3: /* btr */
6768 op = 2;
6769 goto do_btx;
6770 case 0x1bb: /* btc */
6771 op = 3;
6772 do_btx:
ab4e4aec 6773 ot = dflag;
e3af7c78 6774 modrm = x86_ldub_code(env, s);
14ce26e7 6775 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af 6776 mod = (modrm >> 6) & 3;
14ce26e7 6777 rm = (modrm & 7) | REX_B(s);
1d1cc4d0 6778 gen_op_mov_v_reg(MO_32, cpu_T1, reg);
2c0262af 6779 if (mod != 3) {
cfe819d3 6780 AddressParts a = gen_lea_modrm_0(env, s, modrm);
2c0262af 6781 /* specific case: we need to add a displacement */
1d1cc4d0
RH
6782 gen_exts(ot, cpu_T1);
6783 tcg_gen_sari_tl(cpu_tmp0, cpu_T1, 3 + ot);
f484d386 6784 tcg_gen_shli_tl(cpu_tmp0, cpu_tmp0, ot);
6b672b5d
EC
6785 tcg_gen_add_tl(s->A0, gen_lea_modrm_1(s, a), cpu_tmp0);
6786 gen_lea_v_seg(s, s->aflag, s->A0, a.def_seg, s->override);
cfe819d3 6787 if (!(s->prefix & PREFIX_LOCK)) {
c66f9727 6788 gen_op_ld_v(s, ot, s->T0, s->A0);
cfe819d3 6789 }
2c0262af 6790 } else {
c66f9727 6791 gen_op_mov_v_reg(ot, s->T0, rm);
2c0262af 6792 }
f484d386 6793 bt_op:
1d1cc4d0 6794 tcg_gen_andi_tl(cpu_T1, cpu_T1, (1 << (3 + ot)) - 1);
cfe819d3
EC
6795 tcg_gen_movi_tl(cpu_tmp0, 1);
6796 tcg_gen_shl_tl(cpu_tmp0, cpu_tmp0, cpu_T1);
6797 if (s->prefix & PREFIX_LOCK) {
6798 switch (op) {
6799 case 0: /* bt */
6800 /* Needs no atomic ops; we surpressed the normal
6801 memory load for LOCK above so do it now. */
c66f9727 6802 gen_op_ld_v(s, ot, s->T0, s->A0);
cfe819d3
EC
6803 break;
6804 case 1: /* bts */
c66f9727 6805 tcg_gen_atomic_fetch_or_tl(s->T0, s->A0, cpu_tmp0,
cfe819d3
EC
6806 s->mem_index, ot | MO_LE);
6807 break;
6808 case 2: /* btr */
6809 tcg_gen_not_tl(cpu_tmp0, cpu_tmp0);
c66f9727 6810 tcg_gen_atomic_fetch_and_tl(s->T0, s->A0, cpu_tmp0,
cfe819d3
EC
6811 s->mem_index, ot | MO_LE);
6812 break;
6813 default:
6814 case 3: /* btc */
c66f9727 6815 tcg_gen_atomic_fetch_xor_tl(s->T0, s->A0, cpu_tmp0,
cfe819d3
EC
6816 s->mem_index, ot | MO_LE);
6817 break;
6818 }
c66f9727 6819 tcg_gen_shr_tl(cpu_tmp4, s->T0, cpu_T1);
cfe819d3 6820 } else {
c66f9727 6821 tcg_gen_shr_tl(cpu_tmp4, s->T0, cpu_T1);
cfe819d3
EC
6822 switch (op) {
6823 case 0: /* bt */
6824 /* Data already loaded; nothing to do. */
6825 break;
6826 case 1: /* bts */
c66f9727 6827 tcg_gen_or_tl(s->T0, s->T0, cpu_tmp0);
cfe819d3
EC
6828 break;
6829 case 2: /* btr */
c66f9727 6830 tcg_gen_andc_tl(s->T0, s->T0, cpu_tmp0);
cfe819d3
EC
6831 break;
6832 default:
6833 case 3: /* btc */
c66f9727 6834 tcg_gen_xor_tl(s->T0, s->T0, cpu_tmp0);
cfe819d3
EC
6835 break;
6836 }
6837 if (op != 0) {
6838 if (mod != 3) {
c66f9727 6839 gen_op_st_v(s, ot, s->T0, s->A0);
cfe819d3 6840 } else {
c66f9727 6841 gen_op_mov_reg_v(ot, rm, s->T0);
cfe819d3 6842 }
fd8ca9f6 6843 }
dc1823ce
RH
6844 }
6845
6846 /* Delay all CC updates until after the store above. Note that
6847 C is the result of the test, Z is unchanged, and the others
6848 are all undefined. */
6849 switch (s->cc_op) {
6850 case CC_OP_MULB ... CC_OP_MULQ:
6851 case CC_OP_ADDB ... CC_OP_ADDQ:
6852 case CC_OP_ADCB ... CC_OP_ADCQ:
6853 case CC_OP_SUBB ... CC_OP_SUBQ:
6854 case CC_OP_SBBB ... CC_OP_SBBQ:
6855 case CC_OP_LOGICB ... CC_OP_LOGICQ:
6856 case CC_OP_INCB ... CC_OP_INCQ:
6857 case CC_OP_DECB ... CC_OP_DECQ:
6858 case CC_OP_SHLB ... CC_OP_SHLQ:
6859 case CC_OP_SARB ... CC_OP_SARQ:
6860 case CC_OP_BMILGB ... CC_OP_BMILGQ:
6861 /* Z was going to be computed from the non-zero status of CC_DST.
6862 We can get that same Z value (and the new C value) by leaving
6863 CC_DST alone, setting CC_SRC, and using a CC_OP_SAR of the
6864 same width. */
f484d386 6865 tcg_gen_mov_tl(cpu_cc_src, cpu_tmp4);
dc1823ce
RH
6866 set_cc_op(s, ((s->cc_op - CC_OP_MULB) & 3) + CC_OP_SARB);
6867 break;
6868 default:
6869 /* Otherwise, generate EFLAGS and replace the C bit. */
6870 gen_compute_eflags(s);
6871 tcg_gen_deposit_tl(cpu_cc_src, cpu_cc_src, cpu_tmp4,
6872 ctz32(CC_C), 1);
6873 break;
2c0262af
FB
6874 }
6875 break;
321c5351
RH
6876 case 0x1bc: /* bsf / tzcnt */
6877 case 0x1bd: /* bsr / lzcnt */
ab4e4aec 6878 ot = dflag;
e3af7c78 6879 modrm = x86_ldub_code(env, s);
321c5351
RH
6880 reg = ((modrm >> 3) & 7) | rex_r;
6881 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
c66f9727 6882 gen_extu(ot, s->T0);
321c5351
RH
6883
6884 /* Note that lzcnt and tzcnt are in different extensions. */
6885 if ((prefixes & PREFIX_REPZ)
6886 && (b & 1
6887 ? s->cpuid_ext3_features & CPUID_EXT3_ABM
6888 : s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)) {
6889 int size = 8 << ot;
e5143c90 6890 /* For lzcnt/tzcnt, C bit is defined related to the input. */
c66f9727 6891 tcg_gen_mov_tl(cpu_cc_src, s->T0);
321c5351
RH
6892 if (b & 1) {
6893 /* For lzcnt, reduce the target_ulong result by the
6894 number of zeros that we expect to find at the top. */
c66f9727
EC
6895 tcg_gen_clzi_tl(s->T0, s->T0, TARGET_LONG_BITS);
6896 tcg_gen_subi_tl(s->T0, s->T0, TARGET_LONG_BITS - size);
6191b059 6897 } else {
e5143c90 6898 /* For tzcnt, a zero input must return the operand size. */
c66f9727 6899 tcg_gen_ctzi_tl(s->T0, s->T0, size);
6191b059 6900 }
e5143c90 6901 /* For lzcnt/tzcnt, Z bit is defined related to the result. */
c66f9727 6902 gen_op_update1_cc(s);
321c5351
RH
6903 set_cc_op(s, CC_OP_BMILGB + ot);
6904 } else {
6905 /* For bsr/bsf, only the Z bit is defined and it is related
6906 to the input and not the result. */
c66f9727 6907 tcg_gen_mov_tl(cpu_cc_dst, s->T0);
321c5351 6908 set_cc_op(s, CC_OP_LOGICB + ot);
e5143c90
RH
6909
6910 /* ??? The manual says that the output is undefined when the
6911 input is zero, but real hardware leaves it unchanged, and
6912 real programs appear to depend on that. Accomplish this
6913 by passing the output as the value to return upon zero. */
321c5351
RH
6914 if (b & 1) {
6915 /* For bsr, return the bit index of the first 1 bit,
6916 not the count of leading zeros. */
e5143c90 6917 tcg_gen_xori_tl(cpu_T1, cpu_regs[reg], TARGET_LONG_BITS - 1);
c66f9727
EC
6918 tcg_gen_clz_tl(s->T0, s->T0, cpu_T1);
6919 tcg_gen_xori_tl(s->T0, s->T0, TARGET_LONG_BITS - 1);
321c5351 6920 } else {
c66f9727 6921 tcg_gen_ctz_tl(s->T0, s->T0, cpu_regs[reg]);
321c5351 6922 }
6191b059 6923 }
c66f9727 6924 gen_op_mov_reg_v(ot, reg, s->T0);
2c0262af
FB
6925 break;
6926 /************************/
6927 /* bcd */
6928 case 0x27: /* daa */
14ce26e7
FB
6929 if (CODE64(s))
6930 goto illegal_op;
773cdfcc 6931 gen_update_cc_op(s);
7923057b 6932 gen_helper_daa(cpu_env);
3ca51d07 6933 set_cc_op(s, CC_OP_EFLAGS);
2c0262af
FB
6934 break;
6935 case 0x2f: /* das */
14ce26e7
FB
6936 if (CODE64(s))
6937 goto illegal_op;
773cdfcc 6938 gen_update_cc_op(s);
7923057b 6939 gen_helper_das(cpu_env);
3ca51d07 6940 set_cc_op(s, CC_OP_EFLAGS);
2c0262af
FB
6941 break;
6942 case 0x37: /* aaa */
14ce26e7
FB
6943 if (CODE64(s))
6944 goto illegal_op;
773cdfcc 6945 gen_update_cc_op(s);
7923057b 6946 gen_helper_aaa(cpu_env);
3ca51d07 6947 set_cc_op(s, CC_OP_EFLAGS);
2c0262af
FB
6948 break;
6949 case 0x3f: /* aas */
14ce26e7
FB
6950 if (CODE64(s))
6951 goto illegal_op;
773cdfcc 6952 gen_update_cc_op(s);
7923057b 6953 gen_helper_aas(cpu_env);
3ca51d07 6954 set_cc_op(s, CC_OP_EFLAGS);
2c0262af
FB
6955 break;
6956 case 0xd4: /* aam */
14ce26e7
FB
6957 if (CODE64(s))
6958 goto illegal_op;
e3af7c78 6959 val = x86_ldub_code(env, s);
b6d7c3db
TS
6960 if (val == 0) {
6961 gen_exception(s, EXCP00_DIVZ, pc_start - s->cs_base);
6962 } else {
7923057b 6963 gen_helper_aam(cpu_env, tcg_const_i32(val));
3ca51d07 6964 set_cc_op(s, CC_OP_LOGICB);
b6d7c3db 6965 }
2c0262af
FB
6966 break;
6967 case 0xd5: /* aad */
14ce26e7
FB
6968 if (CODE64(s))
6969 goto illegal_op;
e3af7c78 6970 val = x86_ldub_code(env, s);
7923057b 6971 gen_helper_aad(cpu_env, tcg_const_i32(val));
3ca51d07 6972 set_cc_op(s, CC_OP_LOGICB);
2c0262af
FB
6973 break;
6974 /************************/
6975 /* misc */
6976 case 0x90: /* nop */
ab1f142b 6977 /* XXX: correct lock test for all insn */
7418027e 6978 if (prefixes & PREFIX_LOCK) {
ab1f142b 6979 goto illegal_op;
7418027e
RH
6980 }
6981 /* If REX_B is set, then this is xchg eax, r8d, not a nop. */
6982 if (REX_B(s)) {
6983 goto do_xchg_reg_eax;
6984 }
0573fbfc 6985 if (prefixes & PREFIX_REPZ) {
81f3053b
PB
6986 gen_update_cc_op(s);
6987 gen_jmp_im(pc_start - s->cs_base);
6988 gen_helper_pause(cpu_env, tcg_const_i32(s->pc - pc_start));
6cf147aa 6989 s->base.is_jmp = DISAS_NORETURN;
0573fbfc 6990 }
2c0262af
FB
6991 break;
6992 case 0x9b: /* fwait */
5fafdf24 6993 if ((s->flags & (HF_MP_MASK | HF_TS_MASK)) ==
7eee2a50
FB
6994 (HF_MP_MASK | HF_TS_MASK)) {
6995 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
2ee73ac3 6996 } else {
d3eb5eae 6997 gen_helper_fwait(cpu_env);
7eee2a50 6998 }
2c0262af
FB
6999 break;
7000 case 0xcc: /* int3 */
7001 gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base);
7002 break;
7003 case 0xcd: /* int N */
e3af7c78 7004 val = x86_ldub_code(env, s);
f115e911 7005 if (s->vm86 && s->iopl != 3) {
5fafdf24 7006 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
f115e911
FB
7007 } else {
7008 gen_interrupt(s, val, pc_start - s->cs_base, s->pc - s->cs_base);
7009 }
2c0262af
FB
7010 break;
7011 case 0xce: /* into */
14ce26e7
FB
7012 if (CODE64(s))
7013 goto illegal_op;
773cdfcc 7014 gen_update_cc_op(s);
a8ede8ba 7015 gen_jmp_im(pc_start - s->cs_base);
4a7443be 7016 gen_helper_into(cpu_env, tcg_const_i32(s->pc - pc_start));
2c0262af 7017 break;
0b97134b 7018#ifdef WANT_ICEBP
2c0262af 7019 case 0xf1: /* icebp (undocumented, exits to external debugger) */
872929aa 7020 gen_svm_check_intercept(s, pc_start, SVM_EXIT_ICEBP);
aba9d61e 7021#if 1
2c0262af 7022 gen_debug(s, pc_start - s->cs_base);
aba9d61e
FB
7023#else
7024 /* start debug */
bbd77c18 7025 tb_flush(CPU(x86_env_get_cpu(env)));
24537a01 7026 qemu_set_log(CPU_LOG_INT | CPU_LOG_TB_IN_ASM);
aba9d61e 7027#endif
2c0262af 7028 break;
0b97134b 7029#endif
2c0262af
FB
7030 case 0xfa: /* cli */
7031 if (!s->vm86) {
7032 if (s->cpl <= s->iopl) {
f0967a1a 7033 gen_helper_cli(cpu_env);
2c0262af
FB
7034 } else {
7035 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7036 }
7037 } else {
7038 if (s->iopl == 3) {
f0967a1a 7039 gen_helper_cli(cpu_env);
2c0262af
FB
7040 } else {
7041 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7042 }
7043 }
7044 break;
7045 case 0xfb: /* sti */
f083d92c
RH
7046 if (s->vm86 ? s->iopl == 3 : s->cpl <= s->iopl) {
7047 gen_helper_sti(cpu_env);
7048 /* interruptions are enabled only the first insn after sti */
7049 gen_jmp_im(s->pc - s->cs_base);
7050 gen_eob_inhibit_irq(s, true);
2c0262af 7051 } else {
f083d92c 7052 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
2c0262af
FB
7053 }
7054 break;
7055 case 0x62: /* bound */
14ce26e7
FB
7056 if (CODE64(s))
7057 goto illegal_op;
ab4e4aec 7058 ot = dflag;
e3af7c78 7059 modrm = x86_ldub_code(env, s);
2c0262af
FB
7060 reg = (modrm >> 3) & 7;
7061 mod = (modrm >> 6) & 3;
7062 if (mod == 3)
7063 goto illegal_op;
c66f9727 7064 gen_op_mov_v_reg(ot, s->T0, reg);
4eeb3939 7065 gen_lea_modrm(env, s, modrm);
c66f9727 7066 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, s->T0);
4ba9938c 7067 if (ot == MO_16) {
6b672b5d 7068 gen_helper_boundw(cpu_env, s->A0, cpu_tmp2_i32);
92fc4b58 7069 } else {
6b672b5d 7070 gen_helper_boundl(cpu_env, s->A0, cpu_tmp2_i32);
92fc4b58 7071 }
2c0262af
FB
7072 break;
7073 case 0x1c8 ... 0x1cf: /* bswap reg */
14ce26e7
FB
7074 reg = (b & 7) | REX_B(s);
7075#ifdef TARGET_X86_64
ab4e4aec 7076 if (dflag == MO_64) {
c66f9727
EC
7077 gen_op_mov_v_reg(MO_64, s->T0, reg);
7078 tcg_gen_bswap64_i64(s->T0, s->T0);
7079 gen_op_mov_reg_v(MO_64, reg, s->T0);
5fafdf24 7080 } else
8777643e 7081#endif
57fec1fe 7082 {
c66f9727
EC
7083 gen_op_mov_v_reg(MO_32, s->T0, reg);
7084 tcg_gen_ext32u_tl(s->T0, s->T0);
7085 tcg_gen_bswap32_tl(s->T0, s->T0);
7086 gen_op_mov_reg_v(MO_32, reg, s->T0);
14ce26e7 7087 }
2c0262af
FB
7088 break;
7089 case 0xd6: /* salc */
14ce26e7
FB
7090 if (CODE64(s))
7091 goto illegal_op;
c66f9727
EC
7092 gen_compute_eflags_c(s, s->T0);
7093 tcg_gen_neg_tl(s->T0, s->T0);
7094 gen_op_mov_reg_v(MO_8, R_EAX, s->T0);
2c0262af
FB
7095 break;
7096 case 0xe0: /* loopnz */
7097 case 0xe1: /* loopz */
2c0262af
FB
7098 case 0xe2: /* loop */
7099 case 0xe3: /* jecxz */
14ce26e7 7100 {
42a268c2 7101 TCGLabel *l1, *l2, *l3;
14ce26e7 7102
4ba9938c 7103 tval = (int8_t)insn_get(env, s, MO_8);
14ce26e7
FB
7104 next_eip = s->pc - s->cs_base;
7105 tval += next_eip;
ab4e4aec 7106 if (dflag == MO_16) {
14ce26e7 7107 tval &= 0xffff;
ab4e4aec 7108 }
3b46e624 7109
14ce26e7
FB
7110 l1 = gen_new_label();
7111 l2 = gen_new_label();
6e0d8677 7112 l3 = gen_new_label();
14ce26e7 7113 b &= 3;
6e0d8677
FB
7114 switch(b) {
7115 case 0: /* loopnz */
7116 case 1: /* loopz */
1d71ddb1
RH
7117 gen_op_add_reg_im(s->aflag, R_ECX, -1);
7118 gen_op_jz_ecx(s->aflag, l3);
5bdb91b0 7119 gen_jcc1(s, (JCC_Z << 1) | (b ^ 1), l1);
6e0d8677
FB
7120 break;
7121 case 2: /* loop */
1d71ddb1
RH
7122 gen_op_add_reg_im(s->aflag, R_ECX, -1);
7123 gen_op_jnz_ecx(s->aflag, l1);
6e0d8677
FB
7124 break;
7125 default:
7126 case 3: /* jcxz */
1d71ddb1 7127 gen_op_jz_ecx(s->aflag, l1);
6e0d8677 7128 break;
14ce26e7
FB
7129 }
7130
6e0d8677 7131 gen_set_label(l3);
14ce26e7 7132 gen_jmp_im(next_eip);
8e1c85e3 7133 tcg_gen_br(l2);
6e0d8677 7134
14ce26e7
FB
7135 gen_set_label(l1);
7136 gen_jmp_im(tval);
7137 gen_set_label(l2);
7138 gen_eob(s);
7139 }
2c0262af
FB
7140 break;
7141 case 0x130: /* wrmsr */
7142 case 0x132: /* rdmsr */
7143 if (s->cpl != 0) {
7144 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7145 } else {
773cdfcc 7146 gen_update_cc_op(s);
872929aa 7147 gen_jmp_im(pc_start - s->cs_base);
0573fbfc 7148 if (b & 2) {
4a7443be 7149 gen_helper_rdmsr(cpu_env);
0573fbfc 7150 } else {
4a7443be 7151 gen_helper_wrmsr(cpu_env);
0573fbfc 7152 }
2c0262af
FB
7153 }
7154 break;
7155 case 0x131: /* rdtsc */
773cdfcc 7156 gen_update_cc_op(s);
ecada8a2 7157 gen_jmp_im(pc_start - s->cs_base);
c5a49c63 7158 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
efade670 7159 gen_io_start();
bd79255d 7160 }
4a7443be 7161 gen_helper_rdtsc(cpu_env);
c5a49c63 7162 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
efade670
PB
7163 gen_io_end();
7164 gen_jmp(s, s->pc - s->cs_base);
7165 }
2c0262af 7166 break;
df01e0fc 7167 case 0x133: /* rdpmc */
773cdfcc 7168 gen_update_cc_op(s);
df01e0fc 7169 gen_jmp_im(pc_start - s->cs_base);
4a7443be 7170 gen_helper_rdpmc(cpu_env);
df01e0fc 7171 break;
023fe10d 7172 case 0x134: /* sysenter */
2436b61a 7173 /* For Intel SYSENTER is valid on 64-bit */
0af10c86 7174 if (CODE64(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1)
14ce26e7 7175 goto illegal_op;
023fe10d
FB
7176 if (!s->pe) {
7177 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7178 } else {
2999a0b2 7179 gen_helper_sysenter(cpu_env);
023fe10d
FB
7180 gen_eob(s);
7181 }
7182 break;
7183 case 0x135: /* sysexit */
2436b61a 7184 /* For Intel SYSEXIT is valid on 64-bit */
0af10c86 7185 if (CODE64(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1)
14ce26e7 7186 goto illegal_op;
023fe10d
FB
7187 if (!s->pe) {
7188 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7189 } else {
ab4e4aec 7190 gen_helper_sysexit(cpu_env, tcg_const_i32(dflag - 1));
023fe10d
FB
7191 gen_eob(s);
7192 }
7193 break;
14ce26e7
FB
7194#ifdef TARGET_X86_64
7195 case 0x105: /* syscall */
7196 /* XXX: is it usable in real mode ? */
728d803b 7197 gen_update_cc_op(s);
14ce26e7 7198 gen_jmp_im(pc_start - s->cs_base);
2999a0b2 7199 gen_helper_syscall(cpu_env, tcg_const_i32(s->pc - pc_start));
410e9814
DE
7200 /* TF handling for the syscall insn is different. The TF bit is checked
7201 after the syscall insn completes. This allows #DB to not be
7202 generated after one has entered CPL0 if TF is set in FMASK. */
7203 gen_eob_worker(s, false, true);
14ce26e7
FB
7204 break;
7205 case 0x107: /* sysret */
7206 if (!s->pe) {
7207 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7208 } else {
ab4e4aec 7209 gen_helper_sysret(cpu_env, tcg_const_i32(dflag - 1));
aba9d61e 7210 /* condition codes are modified only in long mode */
3ca51d07
RH
7211 if (s->lma) {
7212 set_cc_op(s, CC_OP_EFLAGS);
7213 }
c52ab08a
DE
7214 /* TF handling for the sysret insn is different. The TF bit is
7215 checked after the sysret insn completes. This allows #DB to be
7216 generated "as if" the syscall insn in userspace has just
7217 completed. */
7218 gen_eob_worker(s, false, true);
14ce26e7
FB
7219 }
7220 break;
7221#endif
2c0262af 7222 case 0x1a2: /* cpuid */
773cdfcc 7223 gen_update_cc_op(s);
9575cb94 7224 gen_jmp_im(pc_start - s->cs_base);
4a7443be 7225 gen_helper_cpuid(cpu_env);
2c0262af
FB
7226 break;
7227 case 0xf4: /* hlt */
7228 if (s->cpl != 0) {
7229 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7230 } else {
773cdfcc 7231 gen_update_cc_op(s);
94451178 7232 gen_jmp_im(pc_start - s->cs_base);
4a7443be 7233 gen_helper_hlt(cpu_env, tcg_const_i32(s->pc - pc_start));
6cf147aa 7234 s->base.is_jmp = DISAS_NORETURN;
2c0262af
FB
7235 }
7236 break;
7237 case 0x100:
e3af7c78 7238 modrm = x86_ldub_code(env, s);
2c0262af
FB
7239 mod = (modrm >> 6) & 3;
7240 op = (modrm >> 3) & 7;
7241 switch(op) {
7242 case 0: /* sldt */
f115e911
FB
7243 if (!s->pe || s->vm86)
7244 goto illegal_op;
872929aa 7245 gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_READ);
c66f9727 7246 tcg_gen_ld32u_tl(s->T0, cpu_env,
1d1cc4d0 7247 offsetof(CPUX86State, ldt.selector));
ab4e4aec 7248 ot = mod == 3 ? dflag : MO_16;
0af10c86 7249 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
2c0262af
FB
7250 break;
7251 case 2: /* lldt */
f115e911
FB
7252 if (!s->pe || s->vm86)
7253 goto illegal_op;
2c0262af
FB
7254 if (s->cpl != 0) {
7255 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7256 } else {
872929aa 7257 gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_WRITE);
4ba9938c 7258 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
c66f9727 7259 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, s->T0);
2999a0b2 7260 gen_helper_lldt(cpu_env, cpu_tmp2_i32);
2c0262af
FB
7261 }
7262 break;
7263 case 1: /* str */
f115e911
FB
7264 if (!s->pe || s->vm86)
7265 goto illegal_op;
872929aa 7266 gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_READ);
c66f9727 7267 tcg_gen_ld32u_tl(s->T0, cpu_env,
1d1cc4d0 7268 offsetof(CPUX86State, tr.selector));
ab4e4aec 7269 ot = mod == 3 ? dflag : MO_16;
0af10c86 7270 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
2c0262af
FB
7271 break;
7272 case 3: /* ltr */
f115e911
FB
7273 if (!s->pe || s->vm86)
7274 goto illegal_op;
2c0262af
FB
7275 if (s->cpl != 0) {
7276 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7277 } else {
872929aa 7278 gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_WRITE);
4ba9938c 7279 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
c66f9727 7280 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, s->T0);
2999a0b2 7281 gen_helper_ltr(cpu_env, cpu_tmp2_i32);
2c0262af
FB
7282 }
7283 break;
7284 case 4: /* verr */
7285 case 5: /* verw */
f115e911
FB
7286 if (!s->pe || s->vm86)
7287 goto illegal_op;
4ba9938c 7288 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
773cdfcc 7289 gen_update_cc_op(s);
2999a0b2 7290 if (op == 4) {
c66f9727 7291 gen_helper_verr(cpu_env, s->T0);
2999a0b2 7292 } else {
c66f9727 7293 gen_helper_verw(cpu_env, s->T0);
2999a0b2 7294 }
3ca51d07 7295 set_cc_op(s, CC_OP_EFLAGS);
f115e911 7296 break;
2c0262af 7297 default:
b9f9c5b4 7298 goto unknown_op;
2c0262af
FB
7299 }
7300 break;
1906b2af 7301
2c0262af 7302 case 0x101:
e3af7c78 7303 modrm = x86_ldub_code(env, s);
1906b2af 7304 switch (modrm) {
880f8486 7305 CASE_MODRM_MEM_OP(0): /* sgdt */
872929aa 7306 gen_svm_check_intercept(s, pc_start, SVM_EXIT_GDTR_READ);
4eeb3939 7307 gen_lea_modrm(env, s, modrm);
c66f9727 7308 tcg_gen_ld32u_tl(s->T0,
1d1cc4d0 7309 cpu_env, offsetof(CPUX86State, gdt.limit));
c66f9727 7310 gen_op_st_v(s, MO_16, s->T0, s->A0);
aba9d61e 7311 gen_add_A0_im(s, 2);
c66f9727 7312 tcg_gen_ld_tl(s->T0, cpu_env, offsetof(CPUX86State, gdt.base));
ab4e4aec 7313 if (dflag == MO_16) {
c66f9727 7314 tcg_gen_andi_tl(s->T0, s->T0, 0xffffff);
f0706f0c 7315 }
c66f9727 7316 gen_op_st_v(s, CODE64(s) + MO_32, s->T0, s->A0);
2c0262af 7317 break;
1906b2af
RH
7318
7319 case 0xc8: /* monitor */
7320 if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) || s->cpl != 0) {
7321 goto illegal_op;
3d7374c5 7322 }
1906b2af
RH
7323 gen_update_cc_op(s);
7324 gen_jmp_im(pc_start - s->cs_base);
6b672b5d
EC
7325 tcg_gen_mov_tl(s->A0, cpu_regs[R_EAX]);
7326 gen_extu(s->aflag, s->A0);
1906b2af 7327 gen_add_A0_ds_seg(s);
6b672b5d 7328 gen_helper_monitor(cpu_env, s->A0);
3d7374c5 7329 break;
1906b2af
RH
7330
7331 case 0xc9: /* mwait */
7332 if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) || s->cpl != 0) {
7333 goto illegal_op;
7334 }
7335 gen_update_cc_op(s);
7336 gen_jmp_im(pc_start - s->cs_base);
7337 gen_helper_mwait(cpu_env, tcg_const_i32(s->pc - pc_start));
7338 gen_eob(s);
7339 break;
7340
7341 case 0xca: /* clac */
7342 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_SMAP)
7343 || s->cpl != 0) {
7344 goto illegal_op;
7345 }
7346 gen_helper_clac(cpu_env);
7347 gen_jmp_im(s->pc - s->cs_base);
7348 gen_eob(s);
7349 break;
7350
7351 case 0xcb: /* stac */
7352 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_SMAP)
7353 || s->cpl != 0) {
7354 goto illegal_op;
7355 }
7356 gen_helper_stac(cpu_env);
7357 gen_jmp_im(s->pc - s->cs_base);
7358 gen_eob(s);
7359 break;
7360
880f8486 7361 CASE_MODRM_MEM_OP(1): /* sidt */
1906b2af
RH
7362 gen_svm_check_intercept(s, pc_start, SVM_EXIT_IDTR_READ);
7363 gen_lea_modrm(env, s, modrm);
c66f9727
EC
7364 tcg_gen_ld32u_tl(s->T0, cpu_env, offsetof(CPUX86State, idt.limit));
7365 gen_op_st_v(s, MO_16, s->T0, s->A0);
1906b2af 7366 gen_add_A0_im(s, 2);
c66f9727 7367 tcg_gen_ld_tl(s->T0, cpu_env, offsetof(CPUX86State, idt.base));
1906b2af 7368 if (dflag == MO_16) {
c66f9727 7369 tcg_gen_andi_tl(s->T0, s->T0, 0xffffff);
1906b2af 7370 }
c66f9727 7371 gen_op_st_v(s, CODE64(s) + MO_32, s->T0, s->A0);
1906b2af
RH
7372 break;
7373
19dc85db
RH
7374 case 0xd0: /* xgetbv */
7375 if ((s->cpuid_ext_features & CPUID_EXT_XSAVE) == 0
7376 || (s->prefix & (PREFIX_LOCK | PREFIX_DATA
7377 | PREFIX_REPZ | PREFIX_REPNZ))) {
7378 goto illegal_op;
7379 }
7380 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[R_ECX]);
7381 gen_helper_xgetbv(cpu_tmp1_i64, cpu_env, cpu_tmp2_i32);
7382 tcg_gen_extr_i64_tl(cpu_regs[R_EAX], cpu_regs[R_EDX], cpu_tmp1_i64);
7383 break;
7384
7385 case 0xd1: /* xsetbv */
7386 if ((s->cpuid_ext_features & CPUID_EXT_XSAVE) == 0
7387 || (s->prefix & (PREFIX_LOCK | PREFIX_DATA
7388 | PREFIX_REPZ | PREFIX_REPNZ))) {
7389 goto illegal_op;
7390 }
7391 if (s->cpl != 0) {
7392 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7393 break;
7394 }
7395 tcg_gen_concat_tl_i64(cpu_tmp1_i64, cpu_regs[R_EAX],
7396 cpu_regs[R_EDX]);
7397 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[R_ECX]);
7398 gen_helper_xsetbv(cpu_env, cpu_tmp2_i32, cpu_tmp1_i64);
7399 /* End TB because translation flags may change. */
ba03584f 7400 gen_jmp_im(s->pc - s->cs_base);
19dc85db
RH
7401 gen_eob(s);
7402 break;
7403
1906b2af
RH
7404 case 0xd8: /* VMRUN */
7405 if (!(s->flags & HF_SVME_MASK) || !s->pe) {
7406 goto illegal_op;
7407 }
7408 if (s->cpl != 0) {
2c0262af 7409 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
1906b2af 7410 break;
2c0262af 7411 }
1906b2af
RH
7412 gen_update_cc_op(s);
7413 gen_jmp_im(pc_start - s->cs_base);
7414 gen_helper_vmrun(cpu_env, tcg_const_i32(s->aflag - 1),
7415 tcg_const_i32(s->pc - pc_start));
07ea28b4 7416 tcg_gen_exit_tb(NULL, 0);
6cf147aa 7417 s->base.is_jmp = DISAS_NORETURN;
2c0262af 7418 break;
1906b2af
RH
7419
7420 case 0xd9: /* VMMCALL */
7421 if (!(s->flags & HF_SVME_MASK)) {
7422 goto illegal_op;
7423 }
7424 gen_update_cc_op(s);
7425 gen_jmp_im(pc_start - s->cs_base);
7426 gen_helper_vmmcall(cpu_env);
7427 break;
7428
7429 case 0xda: /* VMLOAD */
7430 if (!(s->flags & HF_SVME_MASK) || !s->pe) {
7431 goto illegal_op;
7432 }
7433 if (s->cpl != 0) {
7434 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7435 break;
7436 }
7437 gen_update_cc_op(s);
7438 gen_jmp_im(pc_start - s->cs_base);
7439 gen_helper_vmload(cpu_env, tcg_const_i32(s->aflag - 1));
7440 break;
7441
7442 case 0xdb: /* VMSAVE */
7443 if (!(s->flags & HF_SVME_MASK) || !s->pe) {
7444 goto illegal_op;
7445 }
7446 if (s->cpl != 0) {
7447 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7448 break;
7449 }
7450 gen_update_cc_op(s);
7451 gen_jmp_im(pc_start - s->cs_base);
7452 gen_helper_vmsave(cpu_env, tcg_const_i32(s->aflag - 1));
7453 break;
7454
7455 case 0xdc: /* STGI */
7456 if ((!(s->flags & HF_SVME_MASK)
7457 && !(s->cpuid_ext3_features & CPUID_EXT3_SKINIT))
7458 || !s->pe) {
7459 goto illegal_op;
7460 }
7461 if (s->cpl != 0) {
7462 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7463 break;
7464 }
7465 gen_update_cc_op(s);
1906b2af 7466 gen_helper_stgi(cpu_env);
df2518aa
JK
7467 gen_jmp_im(s->pc - s->cs_base);
7468 gen_eob(s);
1906b2af
RH
7469 break;
7470
7471 case 0xdd: /* CLGI */
7472 if (!(s->flags & HF_SVME_MASK) || !s->pe) {
7473 goto illegal_op;
7474 }
7475 if (s->cpl != 0) {
7476 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7477 break;
7478 }
7479 gen_update_cc_op(s);
7480 gen_jmp_im(pc_start - s->cs_base);
7481 gen_helper_clgi(cpu_env);
7482 break;
7483
7484 case 0xde: /* SKINIT */
7485 if ((!(s->flags & HF_SVME_MASK)
7486 && !(s->cpuid_ext3_features & CPUID_EXT3_SKINIT))
7487 || !s->pe) {
7488 goto illegal_op;
7489 }
7490 gen_update_cc_op(s);
7491 gen_jmp_im(pc_start - s->cs_base);
7492 gen_helper_skinit(cpu_env);
7493 break;
7494
7495 case 0xdf: /* INVLPGA */
7496 if (!(s->flags & HF_SVME_MASK) || !s->pe) {
7497 goto illegal_op;
7498 }
7499 if (s->cpl != 0) {
7500 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7501 break;
7502 }
7503 gen_update_cc_op(s);
7504 gen_jmp_im(pc_start - s->cs_base);
7505 gen_helper_invlpga(cpu_env, tcg_const_i32(s->aflag - 1));
7506 break;
7507
880f8486 7508 CASE_MODRM_MEM_OP(2): /* lgdt */
1906b2af
RH
7509 if (s->cpl != 0) {
7510 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7511 break;
7512 }
7513 gen_svm_check_intercept(s, pc_start, SVM_EXIT_GDTR_WRITE);
7514 gen_lea_modrm(env, s, modrm);
6b672b5d 7515 gen_op_ld_v(s, MO_16, cpu_T1, s->A0);
1906b2af 7516 gen_add_A0_im(s, 2);
c66f9727 7517 gen_op_ld_v(s, CODE64(s) + MO_32, s->T0, s->A0);
1906b2af 7518 if (dflag == MO_16) {
c66f9727 7519 tcg_gen_andi_tl(s->T0, s->T0, 0xffffff);
1906b2af 7520 }
c66f9727 7521 tcg_gen_st_tl(s->T0, cpu_env, offsetof(CPUX86State, gdt.base));
1906b2af
RH
7522 tcg_gen_st32_tl(cpu_T1, cpu_env, offsetof(CPUX86State, gdt.limit));
7523 break;
7524
880f8486 7525 CASE_MODRM_MEM_OP(3): /* lidt */
1906b2af
RH
7526 if (s->cpl != 0) {
7527 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7528 break;
7529 }
7530 gen_svm_check_intercept(s, pc_start, SVM_EXIT_IDTR_WRITE);
7531 gen_lea_modrm(env, s, modrm);
6b672b5d 7532 gen_op_ld_v(s, MO_16, cpu_T1, s->A0);
1906b2af 7533 gen_add_A0_im(s, 2);
c66f9727 7534 gen_op_ld_v(s, CODE64(s) + MO_32, s->T0, s->A0);
1906b2af 7535 if (dflag == MO_16) {
c66f9727 7536 tcg_gen_andi_tl(s->T0, s->T0, 0xffffff);
1906b2af 7537 }
c66f9727 7538 tcg_gen_st_tl(s->T0, cpu_env, offsetof(CPUX86State, idt.base));
1906b2af
RH
7539 tcg_gen_st32_tl(cpu_T1, cpu_env, offsetof(CPUX86State, idt.limit));
7540 break;
7541
880f8486 7542 CASE_MODRM_OP(4): /* smsw */
872929aa 7543 gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_CR0);
c66f9727 7544 tcg_gen_ld_tl(s->T0, cpu_env, offsetof(CPUX86State, cr[0]));
a657f79e
RH
7545 if (CODE64(s)) {
7546 mod = (modrm >> 6) & 3;
7547 ot = (mod != 3 ? MO_16 : s->dflag);
7548 } else {
7549 ot = MO_16;
7550 }
7551 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
2c0262af 7552 break;
0f70ed47
PB
7553 case 0xee: /* rdpkru */
7554 if (prefixes & PREFIX_LOCK) {
7555 goto illegal_op;
7556 }
7557 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[R_ECX]);
7558 gen_helper_rdpkru(cpu_tmp1_i64, cpu_env, cpu_tmp2_i32);
7559 tcg_gen_extr_i64_tl(cpu_regs[R_EAX], cpu_regs[R_EDX], cpu_tmp1_i64);
7560 break;
7561 case 0xef: /* wrpkru */
7562 if (prefixes & PREFIX_LOCK) {
7563 goto illegal_op;
7564 }
7565 tcg_gen_concat_tl_i64(cpu_tmp1_i64, cpu_regs[R_EAX],
7566 cpu_regs[R_EDX]);
7567 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[R_ECX]);
7568 gen_helper_wrpkru(cpu_env, cpu_tmp2_i32, cpu_tmp1_i64);
7569 break;
880f8486 7570 CASE_MODRM_OP(6): /* lmsw */
2c0262af
FB
7571 if (s->cpl != 0) {
7572 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
1906b2af 7573 break;
2c0262af 7574 }
1906b2af
RH
7575 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0);
7576 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
c66f9727 7577 gen_helper_lmsw(cpu_env, s->T0);
1906b2af
RH
7578 gen_jmp_im(s->pc - s->cs_base);
7579 gen_eob(s);
2c0262af 7580 break;
1906b2af 7581
880f8486 7582 CASE_MODRM_MEM_OP(7): /* invlpg */
1906b2af
RH
7583 if (s->cpl != 0) {
7584 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7585 break;
7586 }
7587 gen_update_cc_op(s);
7588 gen_jmp_im(pc_start - s->cs_base);
7589 gen_lea_modrm(env, s, modrm);
6b672b5d 7590 gen_helper_invlpg(cpu_env, s->A0);
1906b2af
RH
7591 gen_jmp_im(s->pc - s->cs_base);
7592 gen_eob(s);
7593 break;
7594
7595 case 0xf8: /* swapgs */
7596#ifdef TARGET_X86_64
7597 if (CODE64(s)) {
1b050077
AP
7598 if (s->cpl != 0) {
7599 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7600 } else {
c66f9727 7601 tcg_gen_mov_tl(s->T0, cpu_seg_base[R_GS]);
1906b2af
RH
7602 tcg_gen_ld_tl(cpu_seg_base[R_GS], cpu_env,
7603 offsetof(CPUX86State, kernelgsbase));
c66f9727 7604 tcg_gen_st_tl(s->T0, cpu_env,
1906b2af 7605 offsetof(CPUX86State, kernelgsbase));
1b050077 7606 }
1906b2af
RH
7607 break;
7608 }
3558f805 7609#endif
1906b2af
RH
7610 goto illegal_op;
7611
7612 case 0xf9: /* rdtscp */
7613 if (!(s->cpuid_ext2_features & CPUID_EXT2_RDTSCP)) {
7614 goto illegal_op;
7615 }
7616 gen_update_cc_op(s);
7617 gen_jmp_im(pc_start - s->cs_base);
c5a49c63 7618 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
1906b2af
RH
7619 gen_io_start();
7620 }
7621 gen_helper_rdtscp(cpu_env);
c5a49c63 7622 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
1906b2af
RH
7623 gen_io_end();
7624 gen_jmp(s, s->pc - s->cs_base);
2c0262af
FB
7625 }
7626 break;
1906b2af 7627
2c0262af 7628 default:
b9f9c5b4 7629 goto unknown_op;
2c0262af
FB
7630 }
7631 break;
1906b2af 7632
3415a4dd
FB
7633 case 0x108: /* invd */
7634 case 0x109: /* wbinvd */
7635 if (s->cpl != 0) {
7636 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7637 } else {
872929aa 7638 gen_svm_check_intercept(s, pc_start, (b & 2) ? SVM_EXIT_INVD : SVM_EXIT_WBINVD);
3415a4dd
FB
7639 /* nothing to do */
7640 }
7641 break;
14ce26e7
FB
7642 case 0x63: /* arpl or movslS (x86_64) */
7643#ifdef TARGET_X86_64
7644 if (CODE64(s)) {
7645 int d_ot;
7646 /* d_ot is the size of destination */
ab4e4aec 7647 d_ot = dflag;
14ce26e7 7648
e3af7c78 7649 modrm = x86_ldub_code(env, s);
14ce26e7
FB
7650 reg = ((modrm >> 3) & 7) | rex_r;
7651 mod = (modrm >> 6) & 3;
7652 rm = (modrm & 7) | REX_B(s);
3b46e624 7653
14ce26e7 7654 if (mod == 3) {
c66f9727 7655 gen_op_mov_v_reg(MO_32, s->T0, rm);
14ce26e7 7656 /* sign extend */
4ba9938c 7657 if (d_ot == MO_64) {
c66f9727 7658 tcg_gen_ext32s_tl(s->T0, s->T0);
4ba9938c 7659 }
c66f9727 7660 gen_op_mov_reg_v(d_ot, reg, s->T0);
14ce26e7 7661 } else {
4eeb3939 7662 gen_lea_modrm(env, s, modrm);
c66f9727
EC
7663 gen_op_ld_v(s, MO_32 | MO_SIGN, s->T0, s->A0);
7664 gen_op_mov_reg_v(d_ot, reg, s->T0);
14ce26e7 7665 }
5fafdf24 7666 } else
14ce26e7
FB
7667#endif
7668 {
42a268c2 7669 TCGLabel *label1;
49d9fdcc 7670 TCGv t0, t1, t2, a0;
1e4840bf 7671
14ce26e7
FB
7672 if (!s->pe || s->vm86)
7673 goto illegal_op;
a7812ae4
PB
7674 t0 = tcg_temp_local_new();
7675 t1 = tcg_temp_local_new();
7676 t2 = tcg_temp_local_new();
4ba9938c 7677 ot = MO_16;
e3af7c78 7678 modrm = x86_ldub_code(env, s);
14ce26e7
FB
7679 reg = (modrm >> 3) & 7;
7680 mod = (modrm >> 6) & 3;
7681 rm = modrm & 7;
7682 if (mod != 3) {
4eeb3939 7683 gen_lea_modrm(env, s, modrm);
6b672b5d 7684 gen_op_ld_v(s, ot, t0, s->A0);
49d9fdcc 7685 a0 = tcg_temp_local_new();
6b672b5d 7686 tcg_gen_mov_tl(a0, s->A0);
14ce26e7 7687 } else {
1e4840bf 7688 gen_op_mov_v_reg(ot, t0, rm);
f764718d 7689 a0 = NULL;
14ce26e7 7690 }
1e4840bf
FB
7691 gen_op_mov_v_reg(ot, t1, reg);
7692 tcg_gen_andi_tl(cpu_tmp0, t0, 3);
7693 tcg_gen_andi_tl(t1, t1, 3);
7694 tcg_gen_movi_tl(t2, 0);
3bd7da9e 7695 label1 = gen_new_label();
1e4840bf
FB
7696 tcg_gen_brcond_tl(TCG_COND_GE, cpu_tmp0, t1, label1);
7697 tcg_gen_andi_tl(t0, t0, ~3);
7698 tcg_gen_or_tl(t0, t0, t1);
7699 tcg_gen_movi_tl(t2, CC_Z);
3bd7da9e 7700 gen_set_label(label1);
14ce26e7 7701 if (mod != 3) {
323d1876 7702 gen_op_st_v(s, ot, t0, a0);
49d9fdcc
LD
7703 tcg_temp_free(a0);
7704 } else {
1e4840bf 7705 gen_op_mov_reg_v(ot, rm, t0);
14ce26e7 7706 }
d229edce 7707 gen_compute_eflags(s);
3bd7da9e 7708 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~CC_Z);
1e4840bf 7709 tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, t2);
1e4840bf
FB
7710 tcg_temp_free(t0);
7711 tcg_temp_free(t1);
7712 tcg_temp_free(t2);
f115e911 7713 }
f115e911 7714 break;
2c0262af
FB
7715 case 0x102: /* lar */
7716 case 0x103: /* lsl */
cec6843e 7717 {
42a268c2 7718 TCGLabel *label1;
1e4840bf 7719 TCGv t0;
cec6843e
FB
7720 if (!s->pe || s->vm86)
7721 goto illegal_op;
ab4e4aec 7722 ot = dflag != MO_16 ? MO_32 : MO_16;
e3af7c78 7723 modrm = x86_ldub_code(env, s);
cec6843e 7724 reg = ((modrm >> 3) & 7) | rex_r;
4ba9938c 7725 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
a7812ae4 7726 t0 = tcg_temp_local_new();
773cdfcc 7727 gen_update_cc_op(s);
2999a0b2 7728 if (b == 0x102) {
c66f9727 7729 gen_helper_lar(t0, cpu_env, s->T0);
2999a0b2 7730 } else {
c66f9727 7731 gen_helper_lsl(t0, cpu_env, s->T0);
2999a0b2 7732 }
cec6843e
FB
7733 tcg_gen_andi_tl(cpu_tmp0, cpu_cc_src, CC_Z);
7734 label1 = gen_new_label();
cb63669a 7735 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_tmp0, 0, label1);
1e4840bf 7736 gen_op_mov_reg_v(ot, reg, t0);
cec6843e 7737 gen_set_label(label1);
3ca51d07 7738 set_cc_op(s, CC_OP_EFLAGS);
1e4840bf 7739 tcg_temp_free(t0);
cec6843e 7740 }
2c0262af
FB
7741 break;
7742 case 0x118:
e3af7c78 7743 modrm = x86_ldub_code(env, s);
2c0262af
FB
7744 mod = (modrm >> 6) & 3;
7745 op = (modrm >> 3) & 7;
7746 switch(op) {
7747 case 0: /* prefetchnta */
7748 case 1: /* prefetchnt0 */
7749 case 2: /* prefetchnt0 */
7750 case 3: /* prefetchnt0 */
7751 if (mod == 3)
7752 goto illegal_op;
26317698 7753 gen_nop_modrm(env, s, modrm);
2c0262af
FB
7754 /* nothing more to do */
7755 break;
e17a36ce 7756 default: /* nop (multi byte) */
0af10c86 7757 gen_nop_modrm(env, s, modrm);
e17a36ce 7758 break;
2c0262af
FB
7759 }
7760 break;
62b58ba5 7761 case 0x11a:
e3af7c78 7762 modrm = x86_ldub_code(env, s);
62b58ba5
RH
7763 if (s->flags & HF_MPX_EN_MASK) {
7764 mod = (modrm >> 6) & 3;
7765 reg = ((modrm >> 3) & 7) | rex_r;
523e28d7
RH
7766 if (prefixes & PREFIX_REPZ) {
7767 /* bndcl */
7768 if (reg >= 4
7769 || (prefixes & PREFIX_LOCK)
7770 || s->aflag == MO_16) {
7771 goto illegal_op;
7772 }
7773 gen_bndck(env, s, modrm, TCG_COND_LTU, cpu_bndl[reg]);
7774 } else if (prefixes & PREFIX_REPNZ) {
7775 /* bndcu */
7776 if (reg >= 4
7777 || (prefixes & PREFIX_LOCK)
7778 || s->aflag == MO_16) {
7779 goto illegal_op;
7780 }
7781 TCGv_i64 notu = tcg_temp_new_i64();
7782 tcg_gen_not_i64(notu, cpu_bndu[reg]);
7783 gen_bndck(env, s, modrm, TCG_COND_GTU, notu);
7784 tcg_temp_free_i64(notu);
7785 } else if (prefixes & PREFIX_DATA) {
62b58ba5
RH
7786 /* bndmov -- from reg/mem */
7787 if (reg >= 4 || s->aflag == MO_16) {
7788 goto illegal_op;
7789 }
7790 if (mod == 3) {
7791 int reg2 = (modrm & 7) | REX_B(s);
7792 if (reg2 >= 4 || (prefixes & PREFIX_LOCK)) {
7793 goto illegal_op;
7794 }
7795 if (s->flags & HF_MPX_IU_MASK) {
7796 tcg_gen_mov_i64(cpu_bndl[reg], cpu_bndl[reg2]);
7797 tcg_gen_mov_i64(cpu_bndu[reg], cpu_bndu[reg2]);
7798 }
7799 } else {
7800 gen_lea_modrm(env, s, modrm);
7801 if (CODE64(s)) {
6b672b5d 7802 tcg_gen_qemu_ld_i64(cpu_bndl[reg], s->A0,
62b58ba5 7803 s->mem_index, MO_LEQ);
6b672b5d
EC
7804 tcg_gen_addi_tl(s->A0, s->A0, 8);
7805 tcg_gen_qemu_ld_i64(cpu_bndu[reg], s->A0,
62b58ba5
RH
7806 s->mem_index, MO_LEQ);
7807 } else {
6b672b5d 7808 tcg_gen_qemu_ld_i64(cpu_bndl[reg], s->A0,
62b58ba5 7809 s->mem_index, MO_LEUL);
6b672b5d
EC
7810 tcg_gen_addi_tl(s->A0, s->A0, 4);
7811 tcg_gen_qemu_ld_i64(cpu_bndu[reg], s->A0,
62b58ba5
RH
7812 s->mem_index, MO_LEUL);
7813 }
7814 /* bnd registers are now in-use */
7815 gen_set_hflag(s, HF_MPX_IU_MASK);
7816 }
bdd87b3b
RH
7817 } else if (mod != 3) {
7818 /* bndldx */
7819 AddressParts a = gen_lea_modrm_0(env, s, modrm);
7820 if (reg >= 4
7821 || (prefixes & PREFIX_LOCK)
7822 || s->aflag == MO_16
7823 || a.base < -1) {
7824 goto illegal_op;
7825 }
7826 if (a.base >= 0) {
6b672b5d 7827 tcg_gen_addi_tl(s->A0, cpu_regs[a.base], a.disp);
bdd87b3b 7828 } else {
6b672b5d 7829 tcg_gen_movi_tl(s->A0, 0);
bdd87b3b 7830 }
6b672b5d 7831 gen_lea_v_seg(s, s->aflag, s->A0, a.def_seg, s->override);
bdd87b3b 7832 if (a.index >= 0) {
c66f9727 7833 tcg_gen_mov_tl(s->T0, cpu_regs[a.index]);
bdd87b3b 7834 } else {
c66f9727 7835 tcg_gen_movi_tl(s->T0, 0);
bdd87b3b
RH
7836 }
7837 if (CODE64(s)) {
c66f9727 7838 gen_helper_bndldx64(cpu_bndl[reg], cpu_env, s->A0, s->T0);
bdd87b3b
RH
7839 tcg_gen_ld_i64(cpu_bndu[reg], cpu_env,
7840 offsetof(CPUX86State, mmx_t0.MMX_Q(0)));
7841 } else {
c66f9727 7842 gen_helper_bndldx32(cpu_bndu[reg], cpu_env, s->A0, s->T0);
bdd87b3b
RH
7843 tcg_gen_ext32u_i64(cpu_bndl[reg], cpu_bndu[reg]);
7844 tcg_gen_shri_i64(cpu_bndu[reg], cpu_bndu[reg], 32);
7845 }
7846 gen_set_hflag(s, HF_MPX_IU_MASK);
62b58ba5
RH
7847 }
7848 }
7849 gen_nop_modrm(env, s, modrm);
7850 break;
149b427b 7851 case 0x11b:
e3af7c78 7852 modrm = x86_ldub_code(env, s);
149b427b
RH
7853 if (s->flags & HF_MPX_EN_MASK) {
7854 mod = (modrm >> 6) & 3;
7855 reg = ((modrm >> 3) & 7) | rex_r;
7856 if (mod != 3 && (prefixes & PREFIX_REPZ)) {
7857 /* bndmk */
7858 if (reg >= 4
7859 || (prefixes & PREFIX_LOCK)
7860 || s->aflag == MO_16) {
7861 goto illegal_op;
7862 }
7863 AddressParts a = gen_lea_modrm_0(env, s, modrm);
7864 if (a.base >= 0) {
7865 tcg_gen_extu_tl_i64(cpu_bndl[reg], cpu_regs[a.base]);
7866 if (!CODE64(s)) {
7867 tcg_gen_ext32u_i64(cpu_bndl[reg], cpu_bndl[reg]);
7868 }
7869 } else if (a.base == -1) {
7870 /* no base register has lower bound of 0 */
7871 tcg_gen_movi_i64(cpu_bndl[reg], 0);
7872 } else {
7873 /* rip-relative generates #ud */
7874 goto illegal_op;
7875 }
6b672b5d 7876 tcg_gen_not_tl(s->A0, gen_lea_modrm_1(s, a));
149b427b 7877 if (!CODE64(s)) {
6b672b5d 7878 tcg_gen_ext32u_tl(s->A0, s->A0);
149b427b 7879 }
6b672b5d 7880 tcg_gen_extu_tl_i64(cpu_bndu[reg], s->A0);
149b427b
RH
7881 /* bnd registers are now in-use */
7882 gen_set_hflag(s, HF_MPX_IU_MASK);
7883 break;
523e28d7
RH
7884 } else if (prefixes & PREFIX_REPNZ) {
7885 /* bndcn */
7886 if (reg >= 4
7887 || (prefixes & PREFIX_LOCK)
7888 || s->aflag == MO_16) {
7889 goto illegal_op;
7890 }
7891 gen_bndck(env, s, modrm, TCG_COND_GTU, cpu_bndu[reg]);
62b58ba5
RH
7892 } else if (prefixes & PREFIX_DATA) {
7893 /* bndmov -- to reg/mem */
7894 if (reg >= 4 || s->aflag == MO_16) {
7895 goto illegal_op;
7896 }
7897 if (mod == 3) {
7898 int reg2 = (modrm & 7) | REX_B(s);
7899 if (reg2 >= 4 || (prefixes & PREFIX_LOCK)) {
7900 goto illegal_op;
7901 }
7902 if (s->flags & HF_MPX_IU_MASK) {
7903 tcg_gen_mov_i64(cpu_bndl[reg2], cpu_bndl[reg]);
7904 tcg_gen_mov_i64(cpu_bndu[reg2], cpu_bndu[reg]);
7905 }
7906 } else {
7907 gen_lea_modrm(env, s, modrm);
7908 if (CODE64(s)) {
6b672b5d 7909 tcg_gen_qemu_st_i64(cpu_bndl[reg], s->A0,
62b58ba5 7910 s->mem_index, MO_LEQ);
6b672b5d
EC
7911 tcg_gen_addi_tl(s->A0, s->A0, 8);
7912 tcg_gen_qemu_st_i64(cpu_bndu[reg], s->A0,
62b58ba5
RH
7913 s->mem_index, MO_LEQ);
7914 } else {
6b672b5d 7915 tcg_gen_qemu_st_i64(cpu_bndl[reg], s->A0,
62b58ba5 7916 s->mem_index, MO_LEUL);
6b672b5d
EC
7917 tcg_gen_addi_tl(s->A0, s->A0, 4);
7918 tcg_gen_qemu_st_i64(cpu_bndu[reg], s->A0,
62b58ba5
RH
7919 s->mem_index, MO_LEUL);
7920 }
7921 }
bdd87b3b
RH
7922 } else if (mod != 3) {
7923 /* bndstx */
7924 AddressParts a = gen_lea_modrm_0(env, s, modrm);
7925 if (reg >= 4
7926 || (prefixes & PREFIX_LOCK)
7927 || s->aflag == MO_16
7928 || a.base < -1) {
7929 goto illegal_op;
7930 }
7931 if (a.base >= 0) {
6b672b5d 7932 tcg_gen_addi_tl(s->A0, cpu_regs[a.base], a.disp);
bdd87b3b 7933 } else {
6b672b5d 7934 tcg_gen_movi_tl(s->A0, 0);
bdd87b3b 7935 }
6b672b5d 7936 gen_lea_v_seg(s, s->aflag, s->A0, a.def_seg, s->override);
bdd87b3b 7937 if (a.index >= 0) {
c66f9727 7938 tcg_gen_mov_tl(s->T0, cpu_regs[a.index]);
bdd87b3b 7939 } else {
c66f9727 7940 tcg_gen_movi_tl(s->T0, 0);
bdd87b3b
RH
7941 }
7942 if (CODE64(s)) {
c66f9727 7943 gen_helper_bndstx64(cpu_env, s->A0, s->T0,
bdd87b3b
RH
7944 cpu_bndl[reg], cpu_bndu[reg]);
7945 } else {
c66f9727 7946 gen_helper_bndstx32(cpu_env, s->A0, s->T0,
bdd87b3b
RH
7947 cpu_bndl[reg], cpu_bndu[reg]);
7948 }
149b427b
RH
7949 }
7950 }
7951 gen_nop_modrm(env, s, modrm);
7952 break;
62b58ba5 7953 case 0x119: case 0x11c ... 0x11f: /* nop (multi byte) */
e3af7c78 7954 modrm = x86_ldub_code(env, s);
0af10c86 7955 gen_nop_modrm(env, s, modrm);
e17a36ce 7956 break;
2c0262af
FB
7957 case 0x120: /* mov reg, crN */
7958 case 0x122: /* mov crN, reg */
7959 if (s->cpl != 0) {
7960 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7961 } else {
e3af7c78 7962 modrm = x86_ldub_code(env, s);
5c73b757
MO
7963 /* Ignore the mod bits (assume (modrm&0xc0)==0xc0).
7964 * AMD documentation (24594.pdf) and testing of
7965 * intel 386 and 486 processors all show that the mod bits
7966 * are assumed to be 1's, regardless of actual values.
7967 */
14ce26e7
FB
7968 rm = (modrm & 7) | REX_B(s);
7969 reg = ((modrm >> 3) & 7) | rex_r;
7970 if (CODE64(s))
4ba9938c 7971 ot = MO_64;
14ce26e7 7972 else
4ba9938c 7973 ot = MO_32;
ccd59d09
AP
7974 if ((prefixes & PREFIX_LOCK) && (reg == 0) &&
7975 (s->cpuid_ext3_features & CPUID_EXT3_CR8LEG)) {
7976 reg = 8;
7977 }
2c0262af
FB
7978 switch(reg) {
7979 case 0:
7980 case 2:
7981 case 3:
7982 case 4:
9230e66e 7983 case 8:
773cdfcc 7984 gen_update_cc_op(s);
872929aa 7985 gen_jmp_im(pc_start - s->cs_base);
2c0262af 7986 if (b & 2) {
c5a49c63 7987 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
5b003a40
MA
7988 gen_io_start();
7989 }
c66f9727 7990 gen_op_mov_v_reg(ot, s->T0, rm);
4a7443be 7991 gen_helper_write_crN(cpu_env, tcg_const_i32(reg),
c66f9727 7992 s->T0);
c5a49c63 7993 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
5b003a40
MA
7994 gen_io_end();
7995 }
14ce26e7 7996 gen_jmp_im(s->pc - s->cs_base);
2c0262af
FB
7997 gen_eob(s);
7998 } else {
c5a49c63 7999 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
5b003a40
MA
8000 gen_io_start();
8001 }
c66f9727
EC
8002 gen_helper_read_crN(s->T0, cpu_env, tcg_const_i32(reg));
8003 gen_op_mov_reg_v(ot, rm, s->T0);
c5a49c63 8004 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
5b003a40
MA
8005 gen_io_end();
8006 }
2c0262af
FB
8007 }
8008 break;
8009 default:
b9f9c5b4 8010 goto unknown_op;
2c0262af
FB
8011 }
8012 }
8013 break;
8014 case 0x121: /* mov reg, drN */
8015 case 0x123: /* mov drN, reg */
8016 if (s->cpl != 0) {
8017 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
8018 } else {
e3af7c78 8019 modrm = x86_ldub_code(env, s);
5c73b757
MO
8020 /* Ignore the mod bits (assume (modrm&0xc0)==0xc0).
8021 * AMD documentation (24594.pdf) and testing of
8022 * intel 386 and 486 processors all show that the mod bits
8023 * are assumed to be 1's, regardless of actual values.
8024 */
14ce26e7
FB
8025 rm = (modrm & 7) | REX_B(s);
8026 reg = ((modrm >> 3) & 7) | rex_r;
8027 if (CODE64(s))
4ba9938c 8028 ot = MO_64;
14ce26e7 8029 else
4ba9938c 8030 ot = MO_32;
d0052339 8031 if (reg >= 8) {
2c0262af 8032 goto illegal_op;
d0052339 8033 }
2c0262af 8034 if (b & 2) {
0573fbfc 8035 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_DR0 + reg);
c66f9727 8036 gen_op_mov_v_reg(ot, s->T0, rm);
d0052339 8037 tcg_gen_movi_i32(cpu_tmp2_i32, reg);
c66f9727 8038 gen_helper_set_dr(cpu_env, cpu_tmp2_i32, s->T0);
14ce26e7 8039 gen_jmp_im(s->pc - s->cs_base);
2c0262af
FB
8040 gen_eob(s);
8041 } else {
0573fbfc 8042 gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_DR0 + reg);
d0052339 8043 tcg_gen_movi_i32(cpu_tmp2_i32, reg);
c66f9727
EC
8044 gen_helper_get_dr(s->T0, cpu_env, cpu_tmp2_i32);
8045 gen_op_mov_reg_v(ot, rm, s->T0);
2c0262af
FB
8046 }
8047 }
8048 break;
8049 case 0x106: /* clts */
8050 if (s->cpl != 0) {
8051 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
8052 } else {
0573fbfc 8053 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0);
f0967a1a 8054 gen_helper_clts(cpu_env);
7eee2a50 8055 /* abort block because static cpu state changed */
14ce26e7 8056 gen_jmp_im(s->pc - s->cs_base);
7eee2a50 8057 gen_eob(s);
2c0262af
FB
8058 }
8059 break;
222a3336 8060 /* MMX/3DNow!/SSE/SSE2/SSE3/SSSE3/SSE4 support */
664e0f19
FB
8061 case 0x1c3: /* MOVNTI reg, mem */
8062 if (!(s->cpuid_features & CPUID_SSE2))
14ce26e7 8063 goto illegal_op;
ab4e4aec 8064 ot = mo_64_32(dflag);
e3af7c78 8065 modrm = x86_ldub_code(env, s);
664e0f19
FB
8066 mod = (modrm >> 6) & 3;
8067 if (mod == 3)
8068 goto illegal_op;
8069 reg = ((modrm >> 3) & 7) | rex_r;
8070 /* generate a generic store */
0af10c86 8071 gen_ldst_modrm(env, s, modrm, ot, reg, 1);
14ce26e7 8072 break;
664e0f19 8073 case 0x1ae:
e3af7c78 8074 modrm = x86_ldub_code(env, s);
121f3157 8075 switch (modrm) {
880f8486 8076 CASE_MODRM_MEM_OP(0): /* fxsave */
121f3157
RH
8077 if (!(s->cpuid_features & CPUID_FXSR)
8078 || (prefixes & PREFIX_LOCK)) {
14ce26e7 8079 goto illegal_op;
121f3157 8080 }
09d85fb8 8081 if ((s->flags & HF_EM_MASK) || (s->flags & HF_TS_MASK)) {
0fd14b72
FB
8082 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
8083 break;
8084 }
4eeb3939 8085 gen_lea_modrm(env, s, modrm);
6b672b5d 8086 gen_helper_fxsave(cpu_env, s->A0);
664e0f19 8087 break;
121f3157 8088
880f8486 8089 CASE_MODRM_MEM_OP(1): /* fxrstor */
121f3157
RH
8090 if (!(s->cpuid_features & CPUID_FXSR)
8091 || (prefixes & PREFIX_LOCK)) {
14ce26e7 8092 goto illegal_op;
121f3157 8093 }
09d85fb8 8094 if ((s->flags & HF_EM_MASK) || (s->flags & HF_TS_MASK)) {
0fd14b72
FB
8095 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
8096 break;
8097 }
4eeb3939 8098 gen_lea_modrm(env, s, modrm);
6b672b5d 8099 gen_helper_fxrstor(cpu_env, s->A0);
664e0f19 8100 break;
121f3157 8101
880f8486 8102 CASE_MODRM_MEM_OP(2): /* ldmxcsr */
121f3157
RH
8103 if ((s->flags & HF_EM_MASK) || !(s->flags & HF_OSFXSR_MASK)) {
8104 goto illegal_op;
8105 }
664e0f19
FB
8106 if (s->flags & HF_TS_MASK) {
8107 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
8108 break;
14ce26e7 8109 }
4eeb3939 8110 gen_lea_modrm(env, s, modrm);
6b672b5d 8111 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, s->A0, s->mem_index, MO_LEUL);
121f3157 8112 gen_helper_ldmxcsr(cpu_env, cpu_tmp2_i32);
664e0f19 8113 break;
121f3157 8114
880f8486 8115 CASE_MODRM_MEM_OP(3): /* stmxcsr */
121f3157 8116 if ((s->flags & HF_EM_MASK) || !(s->flags & HF_OSFXSR_MASK)) {
664e0f19 8117 goto illegal_op;
121f3157
RH
8118 }
8119 if (s->flags & HF_TS_MASK) {
8120 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
8121 break;
8122 }
8123 gen_lea_modrm(env, s, modrm);
c66f9727
EC
8124 tcg_gen_ld32u_tl(s->T0, cpu_env, offsetof(CPUX86State, mxcsr));
8125 gen_op_st_v(s, MO_32, s->T0, s->A0);
664e0f19 8126 break;
121f3157 8127
880f8486 8128 CASE_MODRM_MEM_OP(4): /* xsave */
19dc85db
RH
8129 if ((s->cpuid_ext_features & CPUID_EXT_XSAVE) == 0
8130 || (prefixes & (PREFIX_LOCK | PREFIX_DATA
8131 | PREFIX_REPZ | PREFIX_REPNZ))) {
8132 goto illegal_op;
8133 }
8134 gen_lea_modrm(env, s, modrm);
8135 tcg_gen_concat_tl_i64(cpu_tmp1_i64, cpu_regs[R_EAX],
8136 cpu_regs[R_EDX]);
6b672b5d 8137 gen_helper_xsave(cpu_env, s->A0, cpu_tmp1_i64);
19dc85db
RH
8138 break;
8139
880f8486 8140 CASE_MODRM_MEM_OP(5): /* xrstor */
19dc85db
RH
8141 if ((s->cpuid_ext_features & CPUID_EXT_XSAVE) == 0
8142 || (prefixes & (PREFIX_LOCK | PREFIX_DATA
8143 | PREFIX_REPZ | PREFIX_REPNZ))) {
8144 goto illegal_op;
8145 }
8146 gen_lea_modrm(env, s, modrm);
8147 tcg_gen_concat_tl_i64(cpu_tmp1_i64, cpu_regs[R_EAX],
8148 cpu_regs[R_EDX]);
6b672b5d 8149 gen_helper_xrstor(cpu_env, s->A0, cpu_tmp1_i64);
f4f1110e
RH
8150 /* XRSTOR is how MPX is enabled, which changes how
8151 we translate. Thus we need to end the TB. */
8152 gen_update_cc_op(s);
8153 gen_jmp_im(s->pc - s->cs_base);
8154 gen_eob(s);
19dc85db
RH
8155 break;
8156
880f8486 8157 CASE_MODRM_MEM_OP(6): /* xsaveopt / clwb */
121f3157
RH
8158 if (prefixes & PREFIX_LOCK) {
8159 goto illegal_op;
8160 }
8161 if (prefixes & PREFIX_DATA) {
5e1fac2d 8162 /* clwb */
121f3157 8163 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_CLWB)) {
5e1fac2d 8164 goto illegal_op;
121f3157 8165 }
5e1fac2d 8166 gen_nop_modrm(env, s, modrm);
c9cfe8f9
RH
8167 } else {
8168 /* xsaveopt */
8169 if ((s->cpuid_ext_features & CPUID_EXT_XSAVE) == 0
8170 || (s->cpuid_xsave_features & CPUID_XSAVE_XSAVEOPT) == 0
8171 || (prefixes & (PREFIX_REPZ | PREFIX_REPNZ))) {
8172 goto illegal_op;
8173 }
8174 gen_lea_modrm(env, s, modrm);
8175 tcg_gen_concat_tl_i64(cpu_tmp1_i64, cpu_regs[R_EAX],
8176 cpu_regs[R_EDX]);
6b672b5d 8177 gen_helper_xsaveopt(cpu_env, s->A0, cpu_tmp1_i64);
121f3157 8178 }
c9cfe8f9 8179 break;
121f3157 8180
880f8486 8181 CASE_MODRM_MEM_OP(7): /* clflush / clflushopt */
121f3157
RH
8182 if (prefixes & PREFIX_LOCK) {
8183 goto illegal_op;
8184 }
8185 if (prefixes & PREFIX_DATA) {
8186 /* clflushopt */
8187 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_CLFLUSHOPT)) {
8188 goto illegal_op;
8189 }
5e1fac2d 8190 } else {
121f3157
RH
8191 /* clflush */
8192 if ((s->prefix & (PREFIX_REPZ | PREFIX_REPNZ))
8193 || !(s->cpuid_features & CPUID_CLFLUSH)) {
5e1fac2d 8194 goto illegal_op;
121f3157 8195 }
5e1fac2d 8196 }
121f3157 8197 gen_nop_modrm(env, s, modrm);
5e1fac2d 8198 break;
121f3157 8199
07929f2a 8200 case 0xc0 ... 0xc7: /* rdfsbase (f3 0f ae /0) */
e0dd5fd4 8201 case 0xc8 ... 0xcf: /* rdgsbase (f3 0f ae /1) */
07929f2a 8202 case 0xd0 ... 0xd7: /* wrfsbase (f3 0f ae /2) */
e0dd5fd4 8203 case 0xd8 ... 0xdf: /* wrgsbase (f3 0f ae /3) */
07929f2a
RH
8204 if (CODE64(s)
8205 && (prefixes & PREFIX_REPZ)
8206 && !(prefixes & PREFIX_LOCK)
8207 && (s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_FSGSBASE)) {
8208 TCGv base, treg, src, dst;
8209
8210 /* Preserve hflags bits by testing CR4 at runtime. */
8211 tcg_gen_movi_i32(cpu_tmp2_i32, CR4_FSGSBASE_MASK);
8212 gen_helper_cr4_testbit(cpu_env, cpu_tmp2_i32);
8213
8214 base = cpu_seg_base[modrm & 8 ? R_GS : R_FS];
8215 treg = cpu_regs[(modrm & 7) | REX_B(s)];
8216
8217 if (modrm & 0x10) {
8218 /* wr*base */
8219 dst = base, src = treg;
8220 } else {
8221 /* rd*base */
8222 dst = treg, src = base;
8223 }
8224
8225 if (s->dflag == MO_32) {
8226 tcg_gen_ext32u_tl(dst, src);
8227 } else {
8228 tcg_gen_mov_tl(dst, src);
8229 }
8230 break;
8231 }
b9f9c5b4 8232 goto unknown_op;
07929f2a 8233
121f3157
RH
8234 case 0xf8: /* sfence / pcommit */
8235 if (prefixes & PREFIX_DATA) {
8236 /* pcommit */
8237 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_PCOMMIT)
8238 || (prefixes & PREFIX_LOCK)) {
8239 goto illegal_op;
891bc821 8240 }
121f3157
RH
8241 break;
8242 }
8243 /* fallthru */
8244 case 0xf9 ... 0xff: /* sfence */
14cb949a
PB
8245 if (!(s->cpuid_features & CPUID_SSE)
8246 || (prefixes & PREFIX_LOCK)) {
8247 goto illegal_op;
8248 }
cc19e497 8249 tcg_gen_mb(TCG_MO_ST_ST | TCG_BAR_SC);
14cb949a 8250 break;
121f3157 8251 case 0xe8 ... 0xef: /* lfence */
cc19e497
PK
8252 if (!(s->cpuid_features & CPUID_SSE)
8253 || (prefixes & PREFIX_LOCK)) {
8254 goto illegal_op;
8255 }
8256 tcg_gen_mb(TCG_MO_LD_LD | TCG_BAR_SC);
8257 break;
121f3157
RH
8258 case 0xf0 ... 0xf7: /* mfence */
8259 if (!(s->cpuid_features & CPUID_SSE2)
8260 || (prefixes & PREFIX_LOCK)) {
8261 goto illegal_op;
8f091a59 8262 }
cc19e497 8263 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
8f091a59 8264 break;
121f3157 8265
664e0f19 8266 default:
b9f9c5b4 8267 goto unknown_op;
14ce26e7
FB
8268 }
8269 break;
121f3157 8270
a35f3ec7 8271 case 0x10d: /* 3DNow! prefetch(w) */
e3af7c78 8272 modrm = x86_ldub_code(env, s);
a35f3ec7
AJ
8273 mod = (modrm >> 6) & 3;
8274 if (mod == 3)
8275 goto illegal_op;
26317698 8276 gen_nop_modrm(env, s, modrm);
8f091a59 8277 break;
3b21e03e 8278 case 0x1aa: /* rsm */
872929aa 8279 gen_svm_check_intercept(s, pc_start, SVM_EXIT_RSM);
3b21e03e
FB
8280 if (!(s->flags & HF_SMM_MASK))
8281 goto illegal_op;
728d803b 8282 gen_update_cc_op(s);
3b21e03e 8283 gen_jmp_im(s->pc - s->cs_base);
608badfc 8284 gen_helper_rsm(cpu_env);
3b21e03e
FB
8285 gen_eob(s);
8286 break;
222a3336
AZ
8287 case 0x1b8: /* SSE4.2 popcnt */
8288 if ((prefixes & (PREFIX_REPZ | PREFIX_LOCK | PREFIX_REPNZ)) !=
8289 PREFIX_REPZ)
8290 goto illegal_op;
8291 if (!(s->cpuid_ext_features & CPUID_EXT_POPCNT))
8292 goto illegal_op;
8293
e3af7c78 8294 modrm = x86_ldub_code(env, s);
8b4a3df8 8295 reg = ((modrm >> 3) & 7) | rex_r;
222a3336 8296
ab4e4aec 8297 if (s->prefix & PREFIX_DATA) {
4ba9938c 8298 ot = MO_16;
ab4e4aec
RH
8299 } else {
8300 ot = mo_64_32(dflag);
8301 }
222a3336 8302
0af10c86 8303 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
c66f9727
EC
8304 gen_extu(ot, s->T0);
8305 tcg_gen_mov_tl(cpu_cc_src, s->T0);
8306 tcg_gen_ctpop_tl(s->T0, s->T0);
8307 gen_op_mov_reg_v(ot, reg, s->T0);
fdb0d09d 8308
4885c3c4 8309 set_cc_op(s, CC_OP_POPCNT);
222a3336 8310 break;
a35f3ec7
AJ
8311 case 0x10e ... 0x10f:
8312 /* 3DNow! instructions, ignore prefixes */
8313 s->prefix &= ~(PREFIX_REPZ | PREFIX_REPNZ | PREFIX_DATA);
edd7541b 8314 /* fall through */
664e0f19
FB
8315 case 0x110 ... 0x117:
8316 case 0x128 ... 0x12f:
4242b1bd 8317 case 0x138 ... 0x13a:
d9f4bb27 8318 case 0x150 ... 0x179:
664e0f19
FB
8319 case 0x17c ... 0x17f:
8320 case 0x1c2:
8321 case 0x1c4 ... 0x1c6:
8322 case 0x1d0 ... 0x1fe:
0af10c86 8323 gen_sse(env, s, b, pc_start, rex_r);
664e0f19 8324 break;
2c0262af 8325 default:
b9f9c5b4 8326 goto unknown_op;
2c0262af 8327 }
2c0262af
FB
8328 return s->pc;
8329 illegal_op:
b9f9c5b4
RH
8330 gen_illegal_opcode(s);
8331 return s->pc;
8332 unknown_op:
b9f9c5b4 8333 gen_unknown_opcode(env, s);
2c0262af
FB
8334 return s->pc;
8335}
8336
63618b4e 8337void tcg_x86_init(void)
2c0262af 8338{
fac0aff9
RH
8339 static const char reg_names[CPU_NB_REGS][4] = {
8340#ifdef TARGET_X86_64
8341 [R_EAX] = "rax",
8342 [R_EBX] = "rbx",
8343 [R_ECX] = "rcx",
8344 [R_EDX] = "rdx",
8345 [R_ESI] = "rsi",
8346 [R_EDI] = "rdi",
8347 [R_EBP] = "rbp",
8348 [R_ESP] = "rsp",
8349 [8] = "r8",
8350 [9] = "r9",
8351 [10] = "r10",
8352 [11] = "r11",
8353 [12] = "r12",
8354 [13] = "r13",
8355 [14] = "r14",
8356 [15] = "r15",
8357#else
8358 [R_EAX] = "eax",
8359 [R_EBX] = "ebx",
8360 [R_ECX] = "ecx",
8361 [R_EDX] = "edx",
8362 [R_ESI] = "esi",
8363 [R_EDI] = "edi",
8364 [R_EBP] = "ebp",
8365 [R_ESP] = "esp",
8366#endif
8367 };
3558f805
RH
8368 static const char seg_base_names[6][8] = {
8369 [R_CS] = "cs_base",
8370 [R_DS] = "ds_base",
8371 [R_ES] = "es_base",
8372 [R_FS] = "fs_base",
8373 [R_GS] = "gs_base",
8374 [R_SS] = "ss_base",
8375 };
149b427b
RH
8376 static const char bnd_regl_names[4][8] = {
8377 "bnd0_lb", "bnd1_lb", "bnd2_lb", "bnd3_lb"
8378 };
8379 static const char bnd_regu_names[4][8] = {
8380 "bnd0_ub", "bnd1_ub", "bnd2_ub", "bnd3_ub"
8381 };
fac0aff9
RH
8382 int i;
8383
e1ccc054 8384 cpu_cc_op = tcg_global_mem_new_i32(cpu_env,
317ac620 8385 offsetof(CPUX86State, cc_op), "cc_op");
e1ccc054 8386 cpu_cc_dst = tcg_global_mem_new(cpu_env, offsetof(CPUX86State, cc_dst),
a7812ae4 8387 "cc_dst");
e1ccc054 8388 cpu_cc_src = tcg_global_mem_new(cpu_env, offsetof(CPUX86State, cc_src),
a3251186 8389 "cc_src");
e1ccc054 8390 cpu_cc_src2 = tcg_global_mem_new(cpu_env, offsetof(CPUX86State, cc_src2),
988c3eb0 8391 "cc_src2");
437a88a5 8392
fac0aff9 8393 for (i = 0; i < CPU_NB_REGS; ++i) {
e1ccc054 8394 cpu_regs[i] = tcg_global_mem_new(cpu_env,
fac0aff9
RH
8395 offsetof(CPUX86State, regs[i]),
8396 reg_names[i]);
8397 }
677ef623 8398
3558f805
RH
8399 for (i = 0; i < 6; ++i) {
8400 cpu_seg_base[i]
8401 = tcg_global_mem_new(cpu_env,
8402 offsetof(CPUX86State, segs[i].base),
8403 seg_base_names[i]);
8404 }
8405
149b427b
RH
8406 for (i = 0; i < 4; ++i) {
8407 cpu_bndl[i]
8408 = tcg_global_mem_new_i64(cpu_env,
8409 offsetof(CPUX86State, bnd_regs[i].lb),
8410 bnd_regl_names[i]);
8411 cpu_bndu[i]
8412 = tcg_global_mem_new_i64(cpu_env,
8413 offsetof(CPUX86State, bnd_regs[i].ub),
8414 bnd_regu_names[i]);
8415 }
2c0262af
FB
8416}
8417
b542683d 8418static void i386_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cpu)
2c0262af 8419{
9761d39b
LV
8420 DisasContext *dc = container_of(dcbase, DisasContext, base);
8421 CPUX86State *env = cpu->env_ptr;
8422 uint32_t flags = dc->base.tb->flags;
8423 target_ulong cs_base = dc->base.tb->cs_base;
3a1d9b8b 8424
4f31916f 8425 dc->pe = (flags >> HF_PE_SHIFT) & 1;
2c0262af
FB
8426 dc->code32 = (flags >> HF_CS32_SHIFT) & 1;
8427 dc->ss32 = (flags >> HF_SS32_SHIFT) & 1;
8428 dc->addseg = (flags >> HF_ADDSEG_SHIFT) & 1;
8429 dc->f_st = 0;
8430 dc->vm86 = (flags >> VM_SHIFT) & 1;
8431 dc->cpl = (flags >> HF_CPL_SHIFT) & 3;
8432 dc->iopl = (flags >> IOPL_SHIFT) & 3;
8433 dc->tf = (flags >> TF_SHIFT) & 1;
8434 dc->cc_op = CC_OP_DYNAMIC;
e207582f 8435 dc->cc_op_dirty = false;
2c0262af 8436 dc->cs_base = cs_base;
2c0262af
FB
8437 dc->popl_esp_hack = 0;
8438 /* select memory access functions */
8439 dc->mem_index = 0;
da6d48e3
SF
8440#ifdef CONFIG_SOFTMMU
8441 dc->mem_index = cpu_mmu_index(env, false);
8442#endif
0514ef2f
EH
8443 dc->cpuid_features = env->features[FEAT_1_EDX];
8444 dc->cpuid_ext_features = env->features[FEAT_1_ECX];
8445 dc->cpuid_ext2_features = env->features[FEAT_8000_0001_EDX];
8446 dc->cpuid_ext3_features = env->features[FEAT_8000_0001_ECX];
8447 dc->cpuid_7_0_ebx_features = env->features[FEAT_7_0_EBX];
c9cfe8f9 8448 dc->cpuid_xsave_features = env->features[FEAT_XSAVE];
14ce26e7
FB
8449#ifdef TARGET_X86_64
8450 dc->lma = (flags >> HF_LMA_SHIFT) & 1;
8451 dc->code64 = (flags >> HF_CS64_SHIFT) & 1;
8452#endif
7eee2a50 8453 dc->flags = flags;
9761d39b 8454 dc->jmp_opt = !(dc->tf || dc->base.singlestep_enabled ||
da6d48e3 8455 (flags & HF_INHIBIT_IRQ_MASK));
c4d4525c
PD
8456 /* Do not optimize repz jumps at all in icount mode, because
8457 rep movsS instructions are execured with different paths
8458 in !repz_opt and repz_opt modes. The first one was used
8459 always except single step mode. And this setting
8460 disables jumps optimization and control paths become
8461 equivalent in run and single step modes.
8462 Now there will be no jump optimization for repz in
8463 record/replay modes and there will always be an
8464 additional step for ecx=0 when icount is enabled.
8465 */
c5a49c63 8466 dc->repz_opt = !dc->jmp_opt && !(tb_cflags(dc->base.tb) & CF_USE_ICOUNT);
4f31916f
FB
8467#if 0
8468 /* check addseg logic */
dc196a57 8469 if (!dc->addseg && (dc->vm86 || !dc->pe || !dc->code32))
4f31916f
FB
8470 printf("ERROR addseg\n");
8471#endif
8472
c66f9727 8473 dc->T0 = tcg_temp_new();
1d1cc4d0 8474 cpu_T1 = tcg_temp_new();
6b672b5d 8475 dc->A0 = tcg_temp_new();
a7812ae4
PB
8476
8477 cpu_tmp0 = tcg_temp_new();
8478 cpu_tmp1_i64 = tcg_temp_new_i64();
8479 cpu_tmp2_i32 = tcg_temp_new_i32();
8480 cpu_tmp3_i32 = tcg_temp_new_i32();
8481 cpu_tmp4 = tcg_temp_new();
a7812ae4
PB
8482 cpu_ptr0 = tcg_temp_new_ptr();
8483 cpu_ptr1 = tcg_temp_new_ptr();
93a3e108 8484 dc->cc_srcT = tcg_temp_local_new();
9761d39b
LV
8485}
8486
d2e6eedf
LV
8487static void i386_tr_tb_start(DisasContextBase *db, CPUState *cpu)
8488{
8489}
8490
9d75f52b
LV
8491static void i386_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
8492{
8493 DisasContext *dc = container_of(dcbase, DisasContext, base);
8494
8495 tcg_gen_insn_start(dc->base.pc_next, dc->cc_op);
8496}
8497
e6b41ec3
LV
8498static bool i386_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
8499 const CPUBreakpoint *bp)
8500{
8501 DisasContext *dc = container_of(dcbase, DisasContext, base);
8502 /* If RF is set, suppress an internally generated breakpoint. */
8503 int flags = dc->base.tb->flags & HF_RF_MASK ? BP_GDB : BP_ANY;
8504 if (bp->flags & flags) {
8505 gen_debug(dc, dc->base.pc_next - dc->cs_base);
8506 dc->base.is_jmp = DISAS_NORETURN;
8507 /* The address covered by the breakpoint must be included in
8508 [tb->pc, tb->pc + tb->size) in order to for it to be
8509 properly cleared -- thus we increment the PC here so that
d2e6eedf 8510 the generic logic setting tb->size later does the right thing. */
e6b41ec3
LV
8511 dc->base.pc_next += 1;
8512 return true;
8513 } else {
8514 return false;
8515 }
8516}
8517
2c2f8cac
LV
8518static void i386_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
8519{
8520 DisasContext *dc = container_of(dcbase, DisasContext, base);
8521 target_ulong pc_next = disas_insn(dc, cpu);
8522
8523 if (dc->tf || (dc->base.tb->flags & HF_INHIBIT_IRQ_MASK)) {
8524 /* if single step mode, we generate only one instruction and
8525 generate an exception */
8526 /* if irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear
8527 the flag and abort the translation to give the irqs a
8528 chance to happen */
2c2f8cac 8529 dc->base.is_jmp = DISAS_TOO_MANY;
c5a49c63 8530 } else if ((tb_cflags(dc->base.tb) & CF_USE_ICOUNT)
2c2f8cac
LV
8531 && ((dc->base.pc_next & TARGET_PAGE_MASK)
8532 != ((dc->base.pc_next + TARGET_MAX_INSN_SIZE - 1)
8533 & TARGET_PAGE_MASK)
8534 || (dc->base.pc_next & ~TARGET_PAGE_MASK) == 0)) {
8535 /* Do not cross the boundary of the pages in icount mode,
8536 it can cause an exception. Do it only when boundary is
8537 crossed by the first instruction in the block.
8538 If current instruction already crossed the bound - it's ok,
8539 because an exception hasn't stopped this code.
8540 */
2c2f8cac
LV
8541 dc->base.is_jmp = DISAS_TOO_MANY;
8542 } else if ((pc_next - dc->base.pc_first) >= (TARGET_PAGE_SIZE - 32)) {
2c2f8cac
LV
8543 dc->base.is_jmp = DISAS_TOO_MANY;
8544 }
8545
8546 dc->base.pc_next = pc_next;
8547}
8548
47e981b4
LV
8549static void i386_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
8550{
8551 DisasContext *dc = container_of(dcbase, DisasContext, base);
8552
8553 if (dc->base.is_jmp == DISAS_TOO_MANY) {
8554 gen_jmp_im(dc->base.pc_next - dc->cs_base);
8555 gen_eob(dc);
8556 }
8557}
8558
e0d110d9
LV
8559static void i386_tr_disas_log(const DisasContextBase *dcbase,
8560 CPUState *cpu)
8561{
8562 DisasContext *dc = container_of(dcbase, DisasContext, base);
e0d110d9
LV
8563
8564 qemu_log("IN: %s\n", lookup_symbol(dc->base.pc_first));
1d48474d 8565 log_target_disas(cpu, dc->base.pc_first, dc->base.tb->size);
e0d110d9
LV
8566}
8567
d2e6eedf
LV
8568static const TranslatorOps i386_tr_ops = {
8569 .init_disas_context = i386_tr_init_disas_context,
8570 .tb_start = i386_tr_tb_start,
8571 .insn_start = i386_tr_insn_start,
8572 .breakpoint_check = i386_tr_breakpoint_check,
8573 .translate_insn = i386_tr_translate_insn,
8574 .tb_stop = i386_tr_tb_stop,
8575 .disas_log = i386_tr_disas_log,
8576};
0a7df5da 8577
d2e6eedf
LV
8578/* generate intermediate code for basic block 'tb'. */
8579void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
8580{
8581 DisasContext dc;
e0d110d9 8582
d2e6eedf 8583 translator_loop(&i386_tr_ops, &dc.base, cpu, tb);
2c0262af
FB
8584}
8585
bad729e2
RH
8586void restore_state_to_opc(CPUX86State *env, TranslationBlock *tb,
8587 target_ulong *data)
d2856f1a 8588{
bad729e2
RH
8589 int cc_op = data[1];
8590 env->eip = data[0] - tb->cs_base;
8591 if (cc_op != CC_OP_DYNAMIC) {
d2856f1a 8592 env->cc_op = cc_op;
bad729e2 8593 }
d2856f1a 8594}
This page took 2.979681 seconds and 4 git commands to generate.