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