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