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