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