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