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