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