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