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