]> git.proxmox.com Git - mirror_qemu.git/blame - target-i386/translate.c
vl.c: fix regression when reading memory size from config file
[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
c92aa1ad 616static inline void gen_op_jnz_ecx(TCGMemOp size, int 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
c92aa1ad 623static inline void gen_op_jz_ecx(TCGMemOp size, int 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. */
dc259201
RH
1081static inline void gen_jcc1_noeob(DisasContext *s, int b, int l1)
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. */
b27fc131 1099static inline void gen_jcc1(DisasContext *s, int b, int 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 */
1118static int gen_jz_ecx_string(DisasContext *s, target_ulong next_eip)
2c0262af 1119{
14ce26e7
FB
1120 int l1, l2;
1121
1122 l1 = gen_new_label();
1123 l2 = gen_new_label();
1d71ddb1 1124 gen_op_jnz_ecx(s->aflag, l1);
14ce26e7
FB
1125 gen_set_label(l2);
1126 gen_jmp_tb(s, next_eip, 1);
1127 gen_set_label(l1);
1128 return l2;
2c0262af
FB
1129}
1130
d67dc9e6 1131static inline void gen_stos(DisasContext *s, TCGMemOp ot)
2c0262af 1132{
c56baccf 1133 gen_op_mov_v_reg(MO_32, cpu_T[0], R_EAX);
2c0262af 1134 gen_string_movl_A0_EDI(s);
fd8ca9f6 1135 gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
6e0d8677 1136 gen_op_movl_T0_Dshift(ot);
1d71ddb1 1137 gen_op_add_reg_T0(s->aflag, R_EDI);
2c0262af
FB
1138}
1139
d67dc9e6 1140static inline void gen_lods(DisasContext *s, TCGMemOp ot)
2c0262af
FB
1141{
1142 gen_string_movl_A0_ESI(s);
909be183 1143 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
480a762d 1144 gen_op_mov_reg_v(ot, R_EAX, cpu_T[0]);
6e0d8677 1145 gen_op_movl_T0_Dshift(ot);
1d71ddb1 1146 gen_op_add_reg_T0(s->aflag, R_ESI);
2c0262af
FB
1147}
1148
d67dc9e6 1149static inline void gen_scas(DisasContext *s, TCGMemOp ot)
2c0262af 1150{
2c0262af 1151 gen_string_movl_A0_EDI(s);
0f712e10 1152 gen_op_ld_v(s, ot, cpu_T[1], cpu_A0);
63633fe6 1153 gen_op(s, OP_CMPL, ot, R_EAX);
6e0d8677 1154 gen_op_movl_T0_Dshift(ot);
1d71ddb1 1155 gen_op_add_reg_T0(s->aflag, R_EDI);
2c0262af
FB
1156}
1157
d67dc9e6 1158static inline void gen_cmps(DisasContext *s, TCGMemOp ot)
2c0262af 1159{
2c0262af 1160 gen_string_movl_A0_EDI(s);
0f712e10 1161 gen_op_ld_v(s, ot, cpu_T[1], cpu_A0);
63633fe6
RH
1162 gen_string_movl_A0_ESI(s);
1163 gen_op(s, OP_CMPL, ot, OR_TMP0);
6e0d8677 1164 gen_op_movl_T0_Dshift(ot);
1d71ddb1
RH
1165 gen_op_add_reg_T0(s->aflag, R_ESI);
1166 gen_op_add_reg_T0(s->aflag, R_EDI);
2c0262af
FB
1167}
1168
d67dc9e6 1169static inline void gen_ins(DisasContext *s, TCGMemOp ot)
2c0262af 1170{
bd79255d 1171 if (s->tb->cflags & CF_USE_ICOUNT) {
2e70f6ef 1172 gen_io_start();
bd79255d 1173 }
2c0262af 1174 gen_string_movl_A0_EDI(s);
6e0d8677
FB
1175 /* Note: we must do this dummy write first to be restartable in
1176 case of page fault. */
97212c88 1177 tcg_gen_movi_tl(cpu_T[0], 0);
fd8ca9f6 1178 gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
24b9c00f 1179 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[R_EDX]);
b6abf97d 1180 tcg_gen_andi_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0xffff);
a7812ae4 1181 gen_helper_in_func(ot, cpu_T[0], cpu_tmp2_i32);
fd8ca9f6 1182 gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
6e0d8677 1183 gen_op_movl_T0_Dshift(ot);
1d71ddb1 1184 gen_op_add_reg_T0(s->aflag, R_EDI);
bd79255d 1185 if (s->tb->cflags & CF_USE_ICOUNT) {
2e70f6ef 1186 gen_io_end();
bd79255d 1187 }
2c0262af
FB
1188}
1189
d67dc9e6 1190static inline void gen_outs(DisasContext *s, TCGMemOp ot)
2c0262af 1191{
bd79255d 1192 if (s->tb->cflags & CF_USE_ICOUNT) {
2e70f6ef 1193 gen_io_start();
bd79255d 1194 }
2c0262af 1195 gen_string_movl_A0_ESI(s);
909be183 1196 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
b8b6a50b 1197
24b9c00f 1198 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[R_EDX]);
b6abf97d
FB
1199 tcg_gen_andi_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0xffff);
1200 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T[0]);
a7812ae4 1201 gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32);
b8b6a50b 1202
6e0d8677 1203 gen_op_movl_T0_Dshift(ot);
1d71ddb1 1204 gen_op_add_reg_T0(s->aflag, R_ESI);
bd79255d 1205 if (s->tb->cflags & CF_USE_ICOUNT) {
2e70f6ef 1206 gen_io_end();
bd79255d 1207 }
2c0262af
FB
1208}
1209
1210/* same method as Valgrind : we generate jumps to current or next
1211 instruction */
1212#define GEN_REPZ(op) \
d67dc9e6 1213static inline void gen_repz_ ## op(DisasContext *s, TCGMemOp ot, \
14ce26e7 1214 target_ulong cur_eip, target_ulong next_eip) \
2c0262af 1215{ \
14ce26e7 1216 int l2;\
2c0262af 1217 gen_update_cc_op(s); \
14ce26e7 1218 l2 = gen_jz_ecx_string(s, next_eip); \
2c0262af 1219 gen_ ## op(s, ot); \
1d71ddb1 1220 gen_op_add_reg_im(s->aflag, R_ECX, -1); \
2c0262af
FB
1221 /* a loop would cause two single step exceptions if ECX = 1 \
1222 before rep string_insn */ \
c4d4525c 1223 if (s->repz_opt) \
1d71ddb1 1224 gen_op_jz_ecx(s->aflag, l2); \
2c0262af
FB
1225 gen_jmp(s, cur_eip); \
1226}
1227
1228#define GEN_REPZ2(op) \
d67dc9e6 1229static inline void gen_repz_ ## op(DisasContext *s, TCGMemOp ot, \
14ce26e7
FB
1230 target_ulong cur_eip, \
1231 target_ulong next_eip, \
2c0262af
FB
1232 int nz) \
1233{ \
14ce26e7 1234 int l2;\
2c0262af 1235 gen_update_cc_op(s); \
14ce26e7 1236 l2 = gen_jz_ecx_string(s, next_eip); \
2c0262af 1237 gen_ ## op(s, ot); \
1d71ddb1 1238 gen_op_add_reg_im(s->aflag, R_ECX, -1); \
773cdfcc 1239 gen_update_cc_op(s); \
b27fc131 1240 gen_jcc1(s, (JCC_Z << 1) | (nz ^ 1), l2); \
c4d4525c 1241 if (s->repz_opt) \
1d71ddb1 1242 gen_op_jz_ecx(s->aflag, l2); \
2c0262af
FB
1243 gen_jmp(s, cur_eip); \
1244}
1245
1246GEN_REPZ(movs)
1247GEN_REPZ(stos)
1248GEN_REPZ(lods)
1249GEN_REPZ(ins)
1250GEN_REPZ(outs)
1251GEN_REPZ2(scas)
1252GEN_REPZ2(cmps)
1253
a7812ae4
PB
1254static void gen_helper_fp_arith_ST0_FT0(int op)
1255{
1256 switch (op) {
d3eb5eae
BS
1257 case 0:
1258 gen_helper_fadd_ST0_FT0(cpu_env);
1259 break;
1260 case 1:
1261 gen_helper_fmul_ST0_FT0(cpu_env);
1262 break;
1263 case 2:
1264 gen_helper_fcom_ST0_FT0(cpu_env);
1265 break;
1266 case 3:
1267 gen_helper_fcom_ST0_FT0(cpu_env);
1268 break;
1269 case 4:
1270 gen_helper_fsub_ST0_FT0(cpu_env);
1271 break;
1272 case 5:
1273 gen_helper_fsubr_ST0_FT0(cpu_env);
1274 break;
1275 case 6:
1276 gen_helper_fdiv_ST0_FT0(cpu_env);
1277 break;
1278 case 7:
1279 gen_helper_fdivr_ST0_FT0(cpu_env);
1280 break;
a7812ae4
PB
1281 }
1282}
2c0262af
FB
1283
1284/* NOTE the exception in "r" op ordering */
a7812ae4
PB
1285static void gen_helper_fp_arith_STN_ST0(int op, int opreg)
1286{
1287 TCGv_i32 tmp = tcg_const_i32(opreg);
1288 switch (op) {
d3eb5eae
BS
1289 case 0:
1290 gen_helper_fadd_STN_ST0(cpu_env, tmp);
1291 break;
1292 case 1:
1293 gen_helper_fmul_STN_ST0(cpu_env, tmp);
1294 break;
1295 case 4:
1296 gen_helper_fsubr_STN_ST0(cpu_env, tmp);
1297 break;
1298 case 5:
1299 gen_helper_fsub_STN_ST0(cpu_env, tmp);
1300 break;
1301 case 6:
1302 gen_helper_fdivr_STN_ST0(cpu_env, tmp);
1303 break;
1304 case 7:
1305 gen_helper_fdiv_STN_ST0(cpu_env, tmp);
1306 break;
a7812ae4
PB
1307 }
1308}
2c0262af
FB
1309
1310/* if d == OR_TMP0, it means memory operand (address in A0) */
d67dc9e6 1311static void gen_op(DisasContext *s1, int op, TCGMemOp ot, int d)
2c0262af 1312{
2c0262af 1313 if (d != OR_TMP0) {
c56baccf 1314 gen_op_mov_v_reg(ot, cpu_T[0], d);
2c0262af 1315 } else {
909be183 1316 gen_op_ld_v(s1, ot, cpu_T[0], cpu_A0);
2c0262af
FB
1317 }
1318 switch(op) {
1319 case OP_ADCL:
cc8b6f5b 1320 gen_compute_eflags_c(s1, cpu_tmp4);
cad3a37d
FB
1321 tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1322 tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_tmp4);
d4faa3e0 1323 gen_op_st_rm_T0_A0(s1, ot, d);
988c3eb0
RH
1324 gen_op_update3_cc(cpu_tmp4);
1325 set_cc_op(s1, CC_OP_ADCB + ot);
cad3a37d 1326 break;
2c0262af 1327 case OP_SBBL:
cc8b6f5b 1328 gen_compute_eflags_c(s1, cpu_tmp4);
cad3a37d
FB
1329 tcg_gen_sub_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1330 tcg_gen_sub_tl(cpu_T[0], cpu_T[0], cpu_tmp4);
d4faa3e0 1331 gen_op_st_rm_T0_A0(s1, ot, d);
988c3eb0
RH
1332 gen_op_update3_cc(cpu_tmp4);
1333 set_cc_op(s1, CC_OP_SBBB + ot);
cad3a37d 1334 break;
2c0262af 1335 case OP_ADDL:
fd5185ec 1336 tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
d4faa3e0 1337 gen_op_st_rm_T0_A0(s1, ot, d);
cad3a37d 1338 gen_op_update2_cc();
3ca51d07 1339 set_cc_op(s1, CC_OP_ADDB + ot);
2c0262af
FB
1340 break;
1341 case OP_SUBL:
a3251186 1342 tcg_gen_mov_tl(cpu_cc_srcT, cpu_T[0]);
57fec1fe 1343 tcg_gen_sub_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
d4faa3e0 1344 gen_op_st_rm_T0_A0(s1, ot, d);
cad3a37d 1345 gen_op_update2_cc();
3ca51d07 1346 set_cc_op(s1, CC_OP_SUBB + ot);
2c0262af
FB
1347 break;
1348 default:
1349 case OP_ANDL:
57fec1fe 1350 tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
d4faa3e0 1351 gen_op_st_rm_T0_A0(s1, ot, d);
cad3a37d 1352 gen_op_update1_cc();
3ca51d07 1353 set_cc_op(s1, CC_OP_LOGICB + ot);
57fec1fe 1354 break;
2c0262af 1355 case OP_ORL:
57fec1fe 1356 tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
d4faa3e0 1357 gen_op_st_rm_T0_A0(s1, ot, d);
cad3a37d 1358 gen_op_update1_cc();
3ca51d07 1359 set_cc_op(s1, CC_OP_LOGICB + ot);
57fec1fe 1360 break;
2c0262af 1361 case OP_XORL:
57fec1fe 1362 tcg_gen_xor_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
d4faa3e0 1363 gen_op_st_rm_T0_A0(s1, ot, d);
cad3a37d 1364 gen_op_update1_cc();
3ca51d07 1365 set_cc_op(s1, CC_OP_LOGICB + ot);
2c0262af
FB
1366 break;
1367 case OP_CMPL:
63633fe6 1368 tcg_gen_mov_tl(cpu_cc_src, cpu_T[1]);
a3251186 1369 tcg_gen_mov_tl(cpu_cc_srcT, cpu_T[0]);
63633fe6 1370 tcg_gen_sub_tl(cpu_cc_dst, cpu_T[0], cpu_T[1]);
3ca51d07 1371 set_cc_op(s1, CC_OP_SUBB + ot);
2c0262af
FB
1372 break;
1373 }
b6abf97d
FB
1374}
1375
2c0262af 1376/* if d == OR_TMP0, it means memory operand (address in A0) */
d67dc9e6 1377static void gen_inc(DisasContext *s1, TCGMemOp ot, int d, int c)
2c0262af 1378{
909be183 1379 if (d != OR_TMP0) {
c56baccf 1380 gen_op_mov_v_reg(ot, cpu_T[0], d);
909be183
RH
1381 } else {
1382 gen_op_ld_v(s1, ot, cpu_T[0], cpu_A0);
1383 }
cc8b6f5b 1384 gen_compute_eflags_c(s1, cpu_cc_src);
2c0262af 1385 if (c > 0) {
b6abf97d 1386 tcg_gen_addi_tl(cpu_T[0], cpu_T[0], 1);
3ca51d07 1387 set_cc_op(s1, CC_OP_INCB + ot);
2c0262af 1388 } else {
b6abf97d 1389 tcg_gen_addi_tl(cpu_T[0], cpu_T[0], -1);
3ca51d07 1390 set_cc_op(s1, CC_OP_DECB + ot);
2c0262af 1391 }
d4faa3e0 1392 gen_op_st_rm_T0_A0(s1, ot, d);
cd31fefa 1393 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
2c0262af
FB
1394}
1395
d67dc9e6
RH
1396static void gen_shift_flags(DisasContext *s, TCGMemOp ot, TCGv result,
1397 TCGv shm1, TCGv count, bool is_right)
f437d0a3
RH
1398{
1399 TCGv_i32 z32, s32, oldop;
1400 TCGv z_tl;
1401
1402 /* Store the results into the CC variables. If we know that the
1403 variable must be dead, store unconditionally. Otherwise we'll
1404 need to not disrupt the current contents. */
1405 z_tl = tcg_const_tl(0);
1406 if (cc_op_live[s->cc_op] & USES_CC_DST) {
1407 tcg_gen_movcond_tl(TCG_COND_NE, cpu_cc_dst, count, z_tl,
1408 result, cpu_cc_dst);
1409 } else {
1410 tcg_gen_mov_tl(cpu_cc_dst, result);
1411 }
1412 if (cc_op_live[s->cc_op] & USES_CC_SRC) {
1413 tcg_gen_movcond_tl(TCG_COND_NE, cpu_cc_src, count, z_tl,
1414 shm1, cpu_cc_src);
1415 } else {
1416 tcg_gen_mov_tl(cpu_cc_src, shm1);
1417 }
1418 tcg_temp_free(z_tl);
1419
1420 /* Get the two potential CC_OP values into temporaries. */
1421 tcg_gen_movi_i32(cpu_tmp2_i32, (is_right ? CC_OP_SARB : CC_OP_SHLB) + ot);
1422 if (s->cc_op == CC_OP_DYNAMIC) {
1423 oldop = cpu_cc_op;
1424 } else {
1425 tcg_gen_movi_i32(cpu_tmp3_i32, s->cc_op);
1426 oldop = cpu_tmp3_i32;
1427 }
1428
1429 /* Conditionally store the CC_OP value. */
1430 z32 = tcg_const_i32(0);
1431 s32 = tcg_temp_new_i32();
1432 tcg_gen_trunc_tl_i32(s32, count);
1433 tcg_gen_movcond_i32(TCG_COND_NE, cpu_cc_op, s32, z32, cpu_tmp2_i32, oldop);
1434 tcg_temp_free_i32(z32);
1435 tcg_temp_free_i32(s32);
1436
1437 /* The CC_OP value is no longer predictable. */
1438 set_cc_op(s, CC_OP_DYNAMIC);
1439}
1440
d67dc9e6 1441static void gen_shift_rm_T1(DisasContext *s, TCGMemOp ot, int op1,
b6abf97d 1442 int is_right, int is_arith)
2c0262af 1443{
4ba9938c 1444 target_ulong mask = (ot == MO_64 ? 0x3f : 0x1f);
3b46e624 1445
b6abf97d 1446 /* load */
82786041 1447 if (op1 == OR_TMP0) {
909be183 1448 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
82786041 1449 } else {
c56baccf 1450 gen_op_mov_v_reg(ot, cpu_T[0], op1);
82786041 1451 }
b6abf97d 1452
a41f62f5
RH
1453 tcg_gen_andi_tl(cpu_T[1], cpu_T[1], mask);
1454 tcg_gen_subi_tl(cpu_tmp0, cpu_T[1], 1);
b6abf97d
FB
1455
1456 if (is_right) {
1457 if (is_arith) {
f484d386 1458 gen_exts(ot, cpu_T[0]);
a41f62f5
RH
1459 tcg_gen_sar_tl(cpu_tmp0, cpu_T[0], cpu_tmp0);
1460 tcg_gen_sar_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
b6abf97d 1461 } else {
cad3a37d 1462 gen_extu(ot, cpu_T[0]);
a41f62f5
RH
1463 tcg_gen_shr_tl(cpu_tmp0, cpu_T[0], cpu_tmp0);
1464 tcg_gen_shr_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
b6abf97d
FB
1465 }
1466 } else {
a41f62f5
RH
1467 tcg_gen_shl_tl(cpu_tmp0, cpu_T[0], cpu_tmp0);
1468 tcg_gen_shl_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
b6abf97d
FB
1469 }
1470
1471 /* store */
d4faa3e0 1472 gen_op_st_rm_T0_A0(s, ot, op1);
82786041 1473
f437d0a3 1474 gen_shift_flags(s, ot, cpu_T[0], cpu_tmp0, cpu_T[1], is_right);
b6abf97d
FB
1475}
1476
d67dc9e6 1477static void gen_shift_rm_im(DisasContext *s, TCGMemOp ot, int op1, int op2,
c1c37968
FB
1478 int is_right, int is_arith)
1479{
4ba9938c 1480 int mask = (ot == MO_64 ? 0x3f : 0x1f);
c1c37968
FB
1481
1482 /* load */
1483 if (op1 == OR_TMP0)
909be183 1484 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
c1c37968 1485 else
c56baccf 1486 gen_op_mov_v_reg(ot, cpu_T[0], op1);
c1c37968
FB
1487
1488 op2 &= mask;
1489 if (op2 != 0) {
1490 if (is_right) {
1491 if (is_arith) {
1492 gen_exts(ot, cpu_T[0]);
2a449d14 1493 tcg_gen_sari_tl(cpu_tmp4, cpu_T[0], op2 - 1);
c1c37968
FB
1494 tcg_gen_sari_tl(cpu_T[0], cpu_T[0], op2);
1495 } else {
1496 gen_extu(ot, cpu_T[0]);
2a449d14 1497 tcg_gen_shri_tl(cpu_tmp4, cpu_T[0], op2 - 1);
c1c37968
FB
1498 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], op2);
1499 }
1500 } else {
2a449d14 1501 tcg_gen_shli_tl(cpu_tmp4, cpu_T[0], op2 - 1);
c1c37968
FB
1502 tcg_gen_shli_tl(cpu_T[0], cpu_T[0], op2);
1503 }
1504 }
1505
1506 /* store */
d4faa3e0
RH
1507 gen_op_st_rm_T0_A0(s, ot, op1);
1508
c1c37968
FB
1509 /* update eflags if non zero shift */
1510 if (op2 != 0) {
2a449d14 1511 tcg_gen_mov_tl(cpu_cc_src, cpu_tmp4);
c1c37968 1512 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
3ca51d07 1513 set_cc_op(s, (is_right ? CC_OP_SARB : CC_OP_SHLB) + ot);
c1c37968
FB
1514 }
1515}
1516
d67dc9e6 1517static void gen_rot_rm_T1(DisasContext *s, TCGMemOp ot, int op1, int is_right)
b6abf97d 1518{
4ba9938c 1519 target_ulong mask = (ot == MO_64 ? 0x3f : 0x1f);
34d80a55 1520 TCGv_i32 t0, t1;
b6abf97d
FB
1521
1522 /* load */
1e4840bf 1523 if (op1 == OR_TMP0) {
909be183 1524 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
1e4840bf 1525 } else {
c56baccf 1526 gen_op_mov_v_reg(ot, cpu_T[0], op1);
1e4840bf 1527 }
b6abf97d 1528
34d80a55 1529 tcg_gen_andi_tl(cpu_T[1], cpu_T[1], mask);
b6abf97d 1530
34d80a55 1531 switch (ot) {
4ba9938c 1532 case MO_8:
34d80a55
RH
1533 /* Replicate the 8-bit input so that a 32-bit rotate works. */
1534 tcg_gen_ext8u_tl(cpu_T[0], cpu_T[0]);
1535 tcg_gen_muli_tl(cpu_T[0], cpu_T[0], 0x01010101);
1536 goto do_long;
4ba9938c 1537 case MO_16:
34d80a55
RH
1538 /* Replicate the 16-bit input so that a 32-bit rotate works. */
1539 tcg_gen_deposit_tl(cpu_T[0], cpu_T[0], cpu_T[0], 16, 16);
1540 goto do_long;
1541 do_long:
1542#ifdef TARGET_X86_64
4ba9938c 1543 case MO_32:
34d80a55
RH
1544 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
1545 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T[1]);
1546 if (is_right) {
1547 tcg_gen_rotr_i32(cpu_tmp2_i32, cpu_tmp2_i32, cpu_tmp3_i32);
1548 } else {
1549 tcg_gen_rotl_i32(cpu_tmp2_i32, cpu_tmp2_i32, cpu_tmp3_i32);
1550 }
1551 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
1552 break;
1553#endif
1554 default:
1555 if (is_right) {
1556 tcg_gen_rotr_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1557 } else {
1558 tcg_gen_rotl_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1559 }
1560 break;
b6abf97d 1561 }
b6abf97d 1562
b6abf97d 1563 /* store */
d4faa3e0 1564 gen_op_st_rm_T0_A0(s, ot, op1);
b6abf97d 1565
34d80a55
RH
1566 /* We'll need the flags computed into CC_SRC. */
1567 gen_compute_eflags(s);
b6abf97d 1568
34d80a55
RH
1569 /* The value that was "rotated out" is now present at the other end
1570 of the word. Compute C into CC_DST and O into CC_SRC2. Note that
1571 since we've computed the flags into CC_SRC, these variables are
1572 currently dead. */
b6abf97d 1573 if (is_right) {
34d80a55
RH
1574 tcg_gen_shri_tl(cpu_cc_src2, cpu_T[0], mask - 1);
1575 tcg_gen_shri_tl(cpu_cc_dst, cpu_T[0], mask);
089305ac 1576 tcg_gen_andi_tl(cpu_cc_dst, cpu_cc_dst, 1);
34d80a55
RH
1577 } else {
1578 tcg_gen_shri_tl(cpu_cc_src2, cpu_T[0], mask);
1579 tcg_gen_andi_tl(cpu_cc_dst, cpu_T[0], 1);
b6abf97d 1580 }
34d80a55
RH
1581 tcg_gen_andi_tl(cpu_cc_src2, cpu_cc_src2, 1);
1582 tcg_gen_xor_tl(cpu_cc_src2, cpu_cc_src2, cpu_cc_dst);
1583
1584 /* Now conditionally store the new CC_OP value. If the shift count
1585 is 0 we keep the CC_OP_EFLAGS setting so that only CC_SRC is live.
1586 Otherwise reuse CC_OP_ADCOX which have the C and O flags split out
1587 exactly as we computed above. */
1588 t0 = tcg_const_i32(0);
1589 t1 = tcg_temp_new_i32();
1590 tcg_gen_trunc_tl_i32(t1, cpu_T[1]);
1591 tcg_gen_movi_i32(cpu_tmp2_i32, CC_OP_ADCOX);
1592 tcg_gen_movi_i32(cpu_tmp3_i32, CC_OP_EFLAGS);
1593 tcg_gen_movcond_i32(TCG_COND_NE, cpu_cc_op, t1, t0,
1594 cpu_tmp2_i32, cpu_tmp3_i32);
1595 tcg_temp_free_i32(t0);
1596 tcg_temp_free_i32(t1);
1597
1598 /* The CC_OP value is no longer predictable. */
1599 set_cc_op(s, CC_OP_DYNAMIC);
b6abf97d
FB
1600}
1601
d67dc9e6 1602static void gen_rot_rm_im(DisasContext *s, TCGMemOp ot, int op1, int op2,
8cd6345d 1603 int is_right)
1604{
4ba9938c 1605 int mask = (ot == MO_64 ? 0x3f : 0x1f);
34d80a55 1606 int shift;
8cd6345d 1607
1608 /* load */
1609 if (op1 == OR_TMP0) {
909be183 1610 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
8cd6345d 1611 } else {
c56baccf 1612 gen_op_mov_v_reg(ot, cpu_T[0], op1);
8cd6345d 1613 }
1614
8cd6345d 1615 op2 &= mask;
8cd6345d 1616 if (op2 != 0) {
34d80a55
RH
1617 switch (ot) {
1618#ifdef TARGET_X86_64
4ba9938c 1619 case MO_32:
34d80a55
RH
1620 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
1621 if (is_right) {
1622 tcg_gen_rotri_i32(cpu_tmp2_i32, cpu_tmp2_i32, op2);
1623 } else {
1624 tcg_gen_rotli_i32(cpu_tmp2_i32, cpu_tmp2_i32, op2);
1625 }
1626 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
1627 break;
1628#endif
1629 default:
1630 if (is_right) {
1631 tcg_gen_rotri_tl(cpu_T[0], cpu_T[0], op2);
1632 } else {
1633 tcg_gen_rotli_tl(cpu_T[0], cpu_T[0], op2);
1634 }
1635 break;
4ba9938c 1636 case MO_8:
34d80a55
RH
1637 mask = 7;
1638 goto do_shifts;
4ba9938c 1639 case MO_16:
34d80a55
RH
1640 mask = 15;
1641 do_shifts:
1642 shift = op2 & mask;
1643 if (is_right) {
1644 shift = mask + 1 - shift;
1645 }
1646 gen_extu(ot, cpu_T[0]);
1647 tcg_gen_shli_tl(cpu_tmp0, cpu_T[0], shift);
1648 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], mask + 1 - shift);
1649 tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_tmp0);
1650 break;
8cd6345d 1651 }
8cd6345d 1652 }
1653
1654 /* store */
d4faa3e0 1655 gen_op_st_rm_T0_A0(s, ot, op1);
8cd6345d 1656
1657 if (op2 != 0) {
34d80a55 1658 /* Compute the flags into CC_SRC. */
d229edce 1659 gen_compute_eflags(s);
0ff6addd 1660
34d80a55
RH
1661 /* The value that was "rotated out" is now present at the other end
1662 of the word. Compute C into CC_DST and O into CC_SRC2. Note that
1663 since we've computed the flags into CC_SRC, these variables are
1664 currently dead. */
8cd6345d 1665 if (is_right) {
34d80a55
RH
1666 tcg_gen_shri_tl(cpu_cc_src2, cpu_T[0], mask - 1);
1667 tcg_gen_shri_tl(cpu_cc_dst, cpu_T[0], mask);
38ebb396 1668 tcg_gen_andi_tl(cpu_cc_dst, cpu_cc_dst, 1);
34d80a55
RH
1669 } else {
1670 tcg_gen_shri_tl(cpu_cc_src2, cpu_T[0], mask);
1671 tcg_gen_andi_tl(cpu_cc_dst, cpu_T[0], 1);
8cd6345d 1672 }
34d80a55
RH
1673 tcg_gen_andi_tl(cpu_cc_src2, cpu_cc_src2, 1);
1674 tcg_gen_xor_tl(cpu_cc_src2, cpu_cc_src2, cpu_cc_dst);
1675 set_cc_op(s, CC_OP_ADCOX);
8cd6345d 1676 }
8cd6345d 1677}
1678
b6abf97d 1679/* XXX: add faster immediate = 1 case */
d67dc9e6 1680static void gen_rotc_rm_T1(DisasContext *s, TCGMemOp ot, int op1,
b6abf97d
FB
1681 int is_right)
1682{
d229edce 1683 gen_compute_eflags(s);
c7b3c873 1684 assert(s->cc_op == CC_OP_EFLAGS);
b6abf97d
FB
1685
1686 /* load */
1687 if (op1 == OR_TMP0)
909be183 1688 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
b6abf97d 1689 else
c56baccf 1690 gen_op_mov_v_reg(ot, cpu_T[0], op1);
b6abf97d 1691
a7812ae4
PB
1692 if (is_right) {
1693 switch (ot) {
4ba9938c 1694 case MO_8:
7923057b
BS
1695 gen_helper_rcrb(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
1696 break;
4ba9938c 1697 case MO_16:
7923057b
BS
1698 gen_helper_rcrw(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
1699 break;
4ba9938c 1700 case MO_32:
7923057b
BS
1701 gen_helper_rcrl(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
1702 break;
a7812ae4 1703#ifdef TARGET_X86_64
4ba9938c 1704 case MO_64:
7923057b
BS
1705 gen_helper_rcrq(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
1706 break;
a7812ae4 1707#endif
d67dc9e6
RH
1708 default:
1709 tcg_abort();
a7812ae4
PB
1710 }
1711 } else {
1712 switch (ot) {
4ba9938c 1713 case MO_8:
7923057b
BS
1714 gen_helper_rclb(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
1715 break;
4ba9938c 1716 case MO_16:
7923057b
BS
1717 gen_helper_rclw(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
1718 break;
4ba9938c 1719 case MO_32:
7923057b
BS
1720 gen_helper_rcll(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
1721 break;
a7812ae4 1722#ifdef TARGET_X86_64
4ba9938c 1723 case MO_64:
7923057b
BS
1724 gen_helper_rclq(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
1725 break;
a7812ae4 1726#endif
d67dc9e6
RH
1727 default:
1728 tcg_abort();
a7812ae4
PB
1729 }
1730 }
b6abf97d 1731 /* store */
d4faa3e0 1732 gen_op_st_rm_T0_A0(s, ot, op1);
b6abf97d
FB
1733}
1734
1735/* XXX: add faster immediate case */
d67dc9e6 1736static void gen_shiftd_rm_T1(DisasContext *s, TCGMemOp ot, int op1,
f437d0a3 1737 bool is_right, TCGv count_in)
b6abf97d 1738{
4ba9938c 1739 target_ulong mask = (ot == MO_64 ? 63 : 31);
f437d0a3 1740 TCGv count;
b6abf97d
FB
1741
1742 /* load */
1e4840bf 1743 if (op1 == OR_TMP0) {
909be183 1744 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
1e4840bf 1745 } else {
c56baccf 1746 gen_op_mov_v_reg(ot, cpu_T[0], op1);
1e4840bf 1747 }
b6abf97d 1748
f437d0a3
RH
1749 count = tcg_temp_new();
1750 tcg_gen_andi_tl(count, count_in, mask);
1e4840bf 1751
f437d0a3 1752 switch (ot) {
4ba9938c 1753 case MO_16:
f437d0a3
RH
1754 /* Note: we implement the Intel behaviour for shift count > 16.
1755 This means "shrdw C, B, A" shifts A:B:A >> C. Build the B:A
1756 portion by constructing it as a 32-bit value. */
b6abf97d 1757 if (is_right) {
f437d0a3
RH
1758 tcg_gen_deposit_tl(cpu_tmp0, cpu_T[0], cpu_T[1], 16, 16);
1759 tcg_gen_mov_tl(cpu_T[1], cpu_T[0]);
1760 tcg_gen_mov_tl(cpu_T[0], cpu_tmp0);
b6abf97d 1761 } else {
f437d0a3 1762 tcg_gen_deposit_tl(cpu_T[1], cpu_T[0], cpu_T[1], 16, 16);
b6abf97d 1763 }
f437d0a3
RH
1764 /* FALLTHRU */
1765#ifdef TARGET_X86_64
4ba9938c 1766 case MO_32:
f437d0a3
RH
1767 /* Concatenate the two 32-bit values and use a 64-bit shift. */
1768 tcg_gen_subi_tl(cpu_tmp0, count, 1);
b6abf97d 1769 if (is_right) {
f437d0a3
RH
1770 tcg_gen_concat_tl_i64(cpu_T[0], cpu_T[0], cpu_T[1]);
1771 tcg_gen_shr_i64(cpu_tmp0, cpu_T[0], cpu_tmp0);
1772 tcg_gen_shr_i64(cpu_T[0], cpu_T[0], count);
1773 } else {
1774 tcg_gen_concat_tl_i64(cpu_T[0], cpu_T[1], cpu_T[0]);
1775 tcg_gen_shl_i64(cpu_tmp0, cpu_T[0], cpu_tmp0);
1776 tcg_gen_shl_i64(cpu_T[0], cpu_T[0], count);
1777 tcg_gen_shri_i64(cpu_tmp0, cpu_tmp0, 32);
1778 tcg_gen_shri_i64(cpu_T[0], cpu_T[0], 32);
1779 }
1780 break;
1781#endif
1782 default:
1783 tcg_gen_subi_tl(cpu_tmp0, count, 1);
1784 if (is_right) {
1785 tcg_gen_shr_tl(cpu_tmp0, cpu_T[0], cpu_tmp0);
b6abf97d 1786
f437d0a3
RH
1787 tcg_gen_subfi_tl(cpu_tmp4, mask + 1, count);
1788 tcg_gen_shr_tl(cpu_T[0], cpu_T[0], count);
1789 tcg_gen_shl_tl(cpu_T[1], cpu_T[1], cpu_tmp4);
b6abf97d 1790 } else {
f437d0a3 1791 tcg_gen_shl_tl(cpu_tmp0, cpu_T[0], cpu_tmp0);
4ba9938c 1792 if (ot == MO_16) {
f437d0a3
RH
1793 /* Only needed if count > 16, for Intel behaviour. */
1794 tcg_gen_subfi_tl(cpu_tmp4, 33, count);
1795 tcg_gen_shr_tl(cpu_tmp4, cpu_T[1], cpu_tmp4);
1796 tcg_gen_or_tl(cpu_tmp0, cpu_tmp0, cpu_tmp4);
1797 }
1798
1799 tcg_gen_subfi_tl(cpu_tmp4, mask + 1, count);
1800 tcg_gen_shl_tl(cpu_T[0], cpu_T[0], count);
1801 tcg_gen_shr_tl(cpu_T[1], cpu_T[1], cpu_tmp4);
b6abf97d 1802 }
f437d0a3
RH
1803 tcg_gen_movi_tl(cpu_tmp4, 0);
1804 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_T[1], count, cpu_tmp4,
1805 cpu_tmp4, cpu_T[1]);
1806 tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
1807 break;
b6abf97d 1808 }
b6abf97d 1809
b6abf97d 1810 /* store */
d4faa3e0 1811 gen_op_st_rm_T0_A0(s, ot, op1);
1e4840bf 1812
f437d0a3
RH
1813 gen_shift_flags(s, ot, cpu_T[0], cpu_tmp0, count, is_right);
1814 tcg_temp_free(count);
b6abf97d
FB
1815}
1816
d67dc9e6 1817static void gen_shift(DisasContext *s1, int op, TCGMemOp ot, int d, int s)
b6abf97d
FB
1818{
1819 if (s != OR_TMP1)
c56baccf 1820 gen_op_mov_v_reg(ot, cpu_T[1], s);
b6abf97d
FB
1821 switch(op) {
1822 case OP_ROL:
1823 gen_rot_rm_T1(s1, ot, d, 0);
1824 break;
1825 case OP_ROR:
1826 gen_rot_rm_T1(s1, ot, d, 1);
1827 break;
1828 case OP_SHL:
1829 case OP_SHL1:
1830 gen_shift_rm_T1(s1, ot, d, 0, 0);
1831 break;
1832 case OP_SHR:
1833 gen_shift_rm_T1(s1, ot, d, 1, 0);
1834 break;
1835 case OP_SAR:
1836 gen_shift_rm_T1(s1, ot, d, 1, 1);
1837 break;
1838 case OP_RCL:
1839 gen_rotc_rm_T1(s1, ot, d, 0);
1840 break;
1841 case OP_RCR:
1842 gen_rotc_rm_T1(s1, ot, d, 1);
1843 break;
1844 }
2c0262af
FB
1845}
1846
d67dc9e6 1847static void gen_shifti(DisasContext *s1, int op, TCGMemOp ot, int d, int c)
2c0262af 1848{
c1c37968 1849 switch(op) {
8cd6345d 1850 case OP_ROL:
1851 gen_rot_rm_im(s1, ot, d, c, 0);
1852 break;
1853 case OP_ROR:
1854 gen_rot_rm_im(s1, ot, d, c, 1);
1855 break;
c1c37968
FB
1856 case OP_SHL:
1857 case OP_SHL1:
1858 gen_shift_rm_im(s1, ot, d, c, 0, 0);
1859 break;
1860 case OP_SHR:
1861 gen_shift_rm_im(s1, ot, d, c, 1, 0);
1862 break;
1863 case OP_SAR:
1864 gen_shift_rm_im(s1, ot, d, c, 1, 1);
1865 break;
1866 default:
1867 /* currently not optimized */
0ae657b1 1868 tcg_gen_movi_tl(cpu_T[1], c);
c1c37968
FB
1869 gen_shift(s1, op, ot, d, OR_TMP1);
1870 break;
1871 }
2c0262af
FB
1872}
1873
4eeb3939 1874static void gen_lea_modrm(CPUX86State *env, DisasContext *s, int modrm)
2c0262af 1875{
14ce26e7 1876 target_long disp;
2c0262af 1877 int havesib;
14ce26e7 1878 int base;
2c0262af
FB
1879 int index;
1880 int scale;
2c0262af 1881 int mod, rm, code, override, must_add_seg;
7865eec4 1882 TCGv sum;
2c0262af
FB
1883
1884 override = s->override;
1885 must_add_seg = s->addseg;
1886 if (override >= 0)
1887 must_add_seg = 1;
1888 mod = (modrm >> 6) & 3;
1889 rm = modrm & 7;
1890
1d71ddb1
RH
1891 switch (s->aflag) {
1892 case MO_64:
1893 case MO_32:
2c0262af
FB
1894 havesib = 0;
1895 base = rm;
7865eec4 1896 index = -1;
2c0262af 1897 scale = 0;
3b46e624 1898
2c0262af
FB
1899 if (base == 4) {
1900 havesib = 1;
0af10c86 1901 code = cpu_ldub_code(env, s->pc++);
2c0262af 1902 scale = (code >> 6) & 3;
14ce26e7 1903 index = ((code >> 3) & 7) | REX_X(s);
7865eec4
RH
1904 if (index == 4) {
1905 index = -1; /* no index */
1906 }
14ce26e7 1907 base = (code & 7);
2c0262af 1908 }
14ce26e7 1909 base |= REX_B(s);
2c0262af
FB
1910
1911 switch (mod) {
1912 case 0:
14ce26e7 1913 if ((base & 7) == 5) {
2c0262af 1914 base = -1;
0af10c86 1915 disp = (int32_t)cpu_ldl_code(env, s->pc);
2c0262af 1916 s->pc += 4;
14ce26e7
FB
1917 if (CODE64(s) && !havesib) {
1918 disp += s->pc + s->rip_offset;
1919 }
2c0262af
FB
1920 } else {
1921 disp = 0;
1922 }
1923 break;
1924 case 1:
0af10c86 1925 disp = (int8_t)cpu_ldub_code(env, s->pc++);
2c0262af
FB
1926 break;
1927 default:
1928 case 2:
0af10c86 1929 disp = (int32_t)cpu_ldl_code(env, s->pc);
2c0262af
FB
1930 s->pc += 4;
1931 break;
1932 }
3b46e624 1933
7865eec4
RH
1934 /* For correct popl handling with esp. */
1935 if (base == R_ESP && s->popl_esp_hack) {
1936 disp += s->popl_esp_hack;
1937 }
1938
1939 /* Compute the address, with a minimum number of TCG ops. */
1940 TCGV_UNUSED(sum);
1941 if (index >= 0) {
1942 if (scale == 0) {
1943 sum = cpu_regs[index];
1944 } else {
1945 tcg_gen_shli_tl(cpu_A0, cpu_regs[index], scale);
1946 sum = cpu_A0;
14ce26e7 1947 }
7865eec4
RH
1948 if (base >= 0) {
1949 tcg_gen_add_tl(cpu_A0, sum, cpu_regs[base]);
1950 sum = cpu_A0;
14ce26e7 1951 }
7865eec4
RH
1952 } else if (base >= 0) {
1953 sum = cpu_regs[base];
2c0262af 1954 }
7865eec4
RH
1955 if (TCGV_IS_UNUSED(sum)) {
1956 tcg_gen_movi_tl(cpu_A0, disp);
1957 } else {
1958 tcg_gen_addi_tl(cpu_A0, sum, disp);
2c0262af 1959 }
7865eec4 1960
2c0262af
FB
1961 if (must_add_seg) {
1962 if (override < 0) {
7865eec4 1963 if (base == R_EBP || base == R_ESP) {
2c0262af 1964 override = R_SS;
7865eec4 1965 } else {
2c0262af 1966 override = R_DS;
7865eec4 1967 }
2c0262af 1968 }
7865eec4
RH
1969
1970 tcg_gen_ld_tl(cpu_tmp0, cpu_env,
1971 offsetof(CPUX86State, segs[override].base));
1972 if (CODE64(s)) {
1d71ddb1 1973 if (s->aflag == MO_32) {
7865eec4
RH
1974 tcg_gen_ext32u_tl(cpu_A0, cpu_A0);
1975 }
1976 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
4eeb3939 1977 return;
14ce26e7 1978 }
7865eec4
RH
1979
1980 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
1981 }
1982
1d71ddb1 1983 if (s->aflag == MO_32) {
7865eec4 1984 tcg_gen_ext32u_tl(cpu_A0, cpu_A0);
2c0262af 1985 }
1d71ddb1
RH
1986 break;
1987
1988 case MO_16:
2c0262af
FB
1989 switch (mod) {
1990 case 0:
1991 if (rm == 6) {
0af10c86 1992 disp = cpu_lduw_code(env, s->pc);
2c0262af 1993 s->pc += 2;
3250cff8 1994 tcg_gen_movi_tl(cpu_A0, disp);
2c0262af
FB
1995 rm = 0; /* avoid SS override */
1996 goto no_rm;
1997 } else {
1998 disp = 0;
1999 }
2000 break;
2001 case 1:
0af10c86 2002 disp = (int8_t)cpu_ldub_code(env, s->pc++);
2c0262af
FB
2003 break;
2004 default:
2005 case 2:
7effd625 2006 disp = (int16_t)cpu_lduw_code(env, s->pc);
2c0262af
FB
2007 s->pc += 2;
2008 break;
2009 }
7effd625
RH
2010
2011 sum = cpu_A0;
2012 switch (rm) {
2c0262af 2013 case 0:
7effd625 2014 tcg_gen_add_tl(cpu_A0, cpu_regs[R_EBX], cpu_regs[R_ESI]);
2c0262af
FB
2015 break;
2016 case 1:
7effd625 2017 tcg_gen_add_tl(cpu_A0, cpu_regs[R_EBX], cpu_regs[R_EDI]);
2c0262af
FB
2018 break;
2019 case 2:
7effd625 2020 tcg_gen_add_tl(cpu_A0, cpu_regs[R_EBP], cpu_regs[R_ESI]);
2c0262af
FB
2021 break;
2022 case 3:
7effd625 2023 tcg_gen_add_tl(cpu_A0, cpu_regs[R_EBP], cpu_regs[R_EDI]);
2c0262af
FB
2024 break;
2025 case 4:
7effd625 2026 sum = cpu_regs[R_ESI];
2c0262af
FB
2027 break;
2028 case 5:
7effd625 2029 sum = cpu_regs[R_EDI];
2c0262af
FB
2030 break;
2031 case 6:
7effd625 2032 sum = cpu_regs[R_EBP];
2c0262af
FB
2033 break;
2034 default:
2035 case 7:
7effd625 2036 sum = cpu_regs[R_EBX];
2c0262af
FB
2037 break;
2038 }
7effd625 2039 tcg_gen_addi_tl(cpu_A0, sum, disp);
a7e5c7de 2040 tcg_gen_ext16u_tl(cpu_A0, cpu_A0);
2c0262af
FB
2041 no_rm:
2042 if (must_add_seg) {
2043 if (override < 0) {
7effd625 2044 if (rm == 2 || rm == 3 || rm == 6) {
2c0262af 2045 override = R_SS;
7effd625 2046 } else {
2c0262af 2047 override = R_DS;
7effd625 2048 }
2c0262af 2049 }
7162ab21 2050 gen_op_addl_A0_seg(s, override);
2c0262af 2051 }
1d71ddb1
RH
2052 break;
2053
2054 default:
2055 tcg_abort();
2c0262af 2056 }
2c0262af
FB
2057}
2058
0af10c86 2059static void gen_nop_modrm(CPUX86State *env, DisasContext *s, int modrm)
e17a36ce
FB
2060{
2061 int mod, rm, base, code;
2062
2063 mod = (modrm >> 6) & 3;
2064 if (mod == 3)
2065 return;
2066 rm = modrm & 7;
2067
1d71ddb1
RH
2068 switch (s->aflag) {
2069 case MO_64:
2070 case MO_32:
e17a36ce 2071 base = rm;
3b46e624 2072
e17a36ce 2073 if (base == 4) {
0af10c86 2074 code = cpu_ldub_code(env, s->pc++);
e17a36ce
FB
2075 base = (code & 7);
2076 }
3b46e624 2077
e17a36ce
FB
2078 switch (mod) {
2079 case 0:
2080 if (base == 5) {
2081 s->pc += 4;
2082 }
2083 break;
2084 case 1:
2085 s->pc++;
2086 break;
2087 default:
2088 case 2:
2089 s->pc += 4;
2090 break;
2091 }
1d71ddb1
RH
2092 break;
2093
2094 case MO_16:
e17a36ce
FB
2095 switch (mod) {
2096 case 0:
2097 if (rm == 6) {
2098 s->pc += 2;
2099 }
2100 break;
2101 case 1:
2102 s->pc++;
2103 break;
2104 default:
2105 case 2:
2106 s->pc += 2;
2107 break;
2108 }
1d71ddb1
RH
2109 break;
2110
2111 default:
2112 tcg_abort();
e17a36ce
FB
2113 }
2114}
2115
664e0f19
FB
2116/* used for LEA and MOV AX, mem */
2117static void gen_add_A0_ds_seg(DisasContext *s)
2118{
2119 int override, must_add_seg;
2120 must_add_seg = s->addseg;
2121 override = R_DS;
2122 if (s->override >= 0) {
2123 override = s->override;
2124 must_add_seg = 1;
664e0f19
FB
2125 }
2126 if (must_add_seg) {
8f091a59
FB
2127#ifdef TARGET_X86_64
2128 if (CODE64(s)) {
57fec1fe 2129 gen_op_addq_A0_seg(override);
5fafdf24 2130 } else
8f091a59
FB
2131#endif
2132 {
7162ab21 2133 gen_op_addl_A0_seg(s, override);
8f091a59 2134 }
664e0f19
FB
2135 }
2136}
2137
222a3336 2138/* generate modrm memory load or store of 'reg'. TMP0 is used if reg ==
2c0262af 2139 OR_TMP0 */
0af10c86 2140static void gen_ldst_modrm(CPUX86State *env, DisasContext *s, int modrm,
d67dc9e6 2141 TCGMemOp ot, int reg, int is_store)
2c0262af 2142{
4eeb3939 2143 int mod, rm;
2c0262af
FB
2144
2145 mod = (modrm >> 6) & 3;
14ce26e7 2146 rm = (modrm & 7) | REX_B(s);
2c0262af
FB
2147 if (mod == 3) {
2148 if (is_store) {
2149 if (reg != OR_TMP0)
c56baccf 2150 gen_op_mov_v_reg(ot, cpu_T[0], reg);
480a762d 2151 gen_op_mov_reg_v(ot, rm, cpu_T[0]);
2c0262af 2152 } else {
c56baccf 2153 gen_op_mov_v_reg(ot, cpu_T[0], rm);
2c0262af 2154 if (reg != OR_TMP0)
480a762d 2155 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
2c0262af
FB
2156 }
2157 } else {
4eeb3939 2158 gen_lea_modrm(env, s, modrm);
2c0262af
FB
2159 if (is_store) {
2160 if (reg != OR_TMP0)
c56baccf 2161 gen_op_mov_v_reg(ot, cpu_T[0], reg);
fd8ca9f6 2162 gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
2c0262af 2163 } else {
909be183 2164 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
2c0262af 2165 if (reg != OR_TMP0)
480a762d 2166 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
2c0262af
FB
2167 }
2168 }
2169}
2170
d67dc9e6 2171static inline uint32_t insn_get(CPUX86State *env, DisasContext *s, TCGMemOp ot)
2c0262af
FB
2172{
2173 uint32_t ret;
2174
d67dc9e6 2175 switch (ot) {
4ba9938c 2176 case MO_8:
0af10c86 2177 ret = cpu_ldub_code(env, s->pc);
2c0262af
FB
2178 s->pc++;
2179 break;
4ba9938c 2180 case MO_16:
0af10c86 2181 ret = cpu_lduw_code(env, s->pc);
2c0262af
FB
2182 s->pc += 2;
2183 break;
4ba9938c 2184 case MO_32:
d67dc9e6
RH
2185#ifdef TARGET_X86_64
2186 case MO_64:
2187#endif
0af10c86 2188 ret = cpu_ldl_code(env, s->pc);
2c0262af
FB
2189 s->pc += 4;
2190 break;
d67dc9e6
RH
2191 default:
2192 tcg_abort();
2c0262af
FB
2193 }
2194 return ret;
2195}
2196
d67dc9e6 2197static inline int insn_const_size(TCGMemOp ot)
14ce26e7 2198{
4ba9938c 2199 if (ot <= MO_32) {
14ce26e7 2200 return 1 << ot;
4ba9938c 2201 } else {
14ce26e7 2202 return 4;
4ba9938c 2203 }
14ce26e7
FB
2204}
2205
6e256c93
FB
2206static inline void gen_goto_tb(DisasContext *s, int tb_num, target_ulong eip)
2207{
2208 TranslationBlock *tb;
2209 target_ulong pc;
2210
2211 pc = s->cs_base + eip;
2212 tb = s->tb;
2213 /* NOTE: we handle the case where the TB spans two pages here */
2214 if ((pc & TARGET_PAGE_MASK) == (tb->pc & TARGET_PAGE_MASK) ||
2215 (pc & TARGET_PAGE_MASK) == ((s->pc - 1) & TARGET_PAGE_MASK)) {
2216 /* jump to same page: we can use a direct jump */
57fec1fe 2217 tcg_gen_goto_tb(tb_num);
6e256c93 2218 gen_jmp_im(eip);
8cfd0495 2219 tcg_gen_exit_tb((uintptr_t)tb + tb_num);
6e256c93
FB
2220 } else {
2221 /* jump to another page: currently not optimized */
2222 gen_jmp_im(eip);
2223 gen_eob(s);
2224 }
2225}
2226
5fafdf24 2227static inline void gen_jcc(DisasContext *s, int b,
14ce26e7 2228 target_ulong val, target_ulong next_eip)
2c0262af 2229{
b27fc131 2230 int l1, l2;
3b46e624 2231
2c0262af 2232 if (s->jmp_opt) {
14ce26e7 2233 l1 = gen_new_label();
b27fc131 2234 gen_jcc1(s, b, l1);
dc259201 2235
6e256c93 2236 gen_goto_tb(s, 0, next_eip);
14ce26e7
FB
2237
2238 gen_set_label(l1);
6e256c93 2239 gen_goto_tb(s, 1, val);
5779406a 2240 s->is_jmp = DISAS_TB_JUMP;
2c0262af 2241 } else {
14ce26e7
FB
2242 l1 = gen_new_label();
2243 l2 = gen_new_label();
b27fc131 2244 gen_jcc1(s, b, l1);
8e1c85e3 2245
14ce26e7 2246 gen_jmp_im(next_eip);
8e1c85e3
FB
2247 tcg_gen_br(l2);
2248
14ce26e7
FB
2249 gen_set_label(l1);
2250 gen_jmp_im(val);
2251 gen_set_label(l2);
2c0262af
FB
2252 gen_eob(s);
2253 }
2254}
2255
d67dc9e6 2256static void gen_cmovcc1(CPUX86State *env, DisasContext *s, TCGMemOp ot, int b,
f32d3781
PB
2257 int modrm, int reg)
2258{
57eb0cc8 2259 CCPrepare cc;
f32d3781 2260
57eb0cc8 2261 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
f32d3781 2262
57eb0cc8
RH
2263 cc = gen_prepare_cc(s, b, cpu_T[1]);
2264 if (cc.mask != -1) {
2265 TCGv t0 = tcg_temp_new();
2266 tcg_gen_andi_tl(t0, cc.reg, cc.mask);
2267 cc.reg = t0;
2268 }
2269 if (!cc.use_reg2) {
2270 cc.reg2 = tcg_const_tl(cc.imm);
f32d3781
PB
2271 }
2272
57eb0cc8
RH
2273 tcg_gen_movcond_tl(cc.cond, cpu_T[0], cc.reg, cc.reg2,
2274 cpu_T[0], cpu_regs[reg]);
480a762d 2275 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
57eb0cc8
RH
2276
2277 if (cc.mask != -1) {
2278 tcg_temp_free(cc.reg);
2279 }
2280 if (!cc.use_reg2) {
2281 tcg_temp_free(cc.reg2);
2282 }
f32d3781
PB
2283}
2284
3bd7da9e
FB
2285static inline void gen_op_movl_T0_seg(int seg_reg)
2286{
2287 tcg_gen_ld32u_tl(cpu_T[0], cpu_env,
2288 offsetof(CPUX86State,segs[seg_reg].selector));
2289}
2290
2291static inline void gen_op_movl_seg_T0_vm(int seg_reg)
2292{
2293 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xffff);
2294 tcg_gen_st32_tl(cpu_T[0], cpu_env,
2295 offsetof(CPUX86State,segs[seg_reg].selector));
2296 tcg_gen_shli_tl(cpu_T[0], cpu_T[0], 4);
2297 tcg_gen_st_tl(cpu_T[0], cpu_env,
2298 offsetof(CPUX86State,segs[seg_reg].base));
2299}
2300
2c0262af
FB
2301/* move T0 to seg_reg and compute if the CPU state may change. Never
2302 call this function with seg_reg == R_CS */
14ce26e7 2303static void gen_movl_seg_T0(DisasContext *s, int seg_reg, target_ulong cur_eip)
2c0262af 2304{
3415a4dd
FB
2305 if (s->pe && !s->vm86) {
2306 /* XXX: optimize by finding processor state dynamically */
773cdfcc 2307 gen_update_cc_op(s);
14ce26e7 2308 gen_jmp_im(cur_eip);
b6abf97d 2309 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
2999a0b2 2310 gen_helper_load_seg(cpu_env, tcg_const_i32(seg_reg), cpu_tmp2_i32);
dc196a57
FB
2311 /* abort translation because the addseg value may change or
2312 because ss32 may change. For R_SS, translation must always
2313 stop as a special handling must be done to disable hardware
2314 interrupts for the next instruction */
2315 if (seg_reg == R_SS || (s->code32 && seg_reg < R_FS))
5779406a 2316 s->is_jmp = DISAS_TB_JUMP;
3415a4dd 2317 } else {
3bd7da9e 2318 gen_op_movl_seg_T0_vm(seg_reg);
dc196a57 2319 if (seg_reg == R_SS)
5779406a 2320 s->is_jmp = DISAS_TB_JUMP;
3415a4dd 2321 }
2c0262af
FB
2322}
2323
0573fbfc
TS
2324static inline int svm_is_rep(int prefixes)
2325{
2326 return ((prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) ? 8 : 0);
2327}
2328
872929aa 2329static inline void
0573fbfc 2330gen_svm_check_intercept_param(DisasContext *s, target_ulong pc_start,
b8b6a50b 2331 uint32_t type, uint64_t param)
0573fbfc 2332{
872929aa
FB
2333 /* no SVM activated; fast case */
2334 if (likely(!(s->flags & HF_SVMI_MASK)))
2335 return;
773cdfcc 2336 gen_update_cc_op(s);
872929aa 2337 gen_jmp_im(pc_start - s->cs_base);
052e80d5 2338 gen_helper_svm_check_intercept_param(cpu_env, tcg_const_i32(type),
a7812ae4 2339 tcg_const_i64(param));
0573fbfc
TS
2340}
2341
872929aa 2342static inline void
0573fbfc
TS
2343gen_svm_check_intercept(DisasContext *s, target_ulong pc_start, uint64_t type)
2344{
872929aa 2345 gen_svm_check_intercept_param(s, pc_start, type, 0);
0573fbfc
TS
2346}
2347
4f31916f
FB
2348static inline void gen_stack_update(DisasContext *s, int addend)
2349{
14ce26e7
FB
2350#ifdef TARGET_X86_64
2351 if (CODE64(s)) {
d3f4bbe3 2352 gen_op_add_reg_im(MO_64, R_ESP, addend);
14ce26e7
FB
2353 } else
2354#endif
4f31916f 2355 if (s->ss32) {
d3f4bbe3 2356 gen_op_add_reg_im(MO_32, R_ESP, addend);
4f31916f 2357 } else {
d3f4bbe3 2358 gen_op_add_reg_im(MO_16, R_ESP, addend);
4f31916f
FB
2359 }
2360}
2361
432baffe
RH
2362/* Generate a push. It depends on ss32, addseg and dflag. */
2363static void gen_push_v(DisasContext *s, TCGv val)
2c0262af 2364{
432baffe
RH
2365 TCGMemOp a_ot, d_ot = mo_pushpop(s, s->dflag);
2366 int size = 1 << d_ot;
2367 TCGv new_esp = cpu_A0;
2368
2369 tcg_gen_subi_tl(cpu_A0, cpu_regs[R_ESP], size);
2c0262af 2370
14ce26e7 2371 if (CODE64(s)) {
432baffe
RH
2372 a_ot = MO_64;
2373 } else if (s->ss32) {
2374 a_ot = MO_32;
2375 if (s->addseg) {
2376 new_esp = cpu_tmp4;
2377 tcg_gen_mov_tl(new_esp, cpu_A0);
7162ab21 2378 gen_op_addl_A0_seg(s, R_SS);
432baffe
RH
2379 } else {
2380 tcg_gen_ext32u_tl(cpu_A0, cpu_A0);
2c0262af 2381 }
432baffe
RH
2382 } else {
2383 a_ot = MO_16;
2384 new_esp = cpu_tmp4;
2385 tcg_gen_ext16u_tl(cpu_A0, cpu_A0);
2386 tcg_gen_mov_tl(new_esp, cpu_A0);
2387 gen_op_addl_A0_seg(s, R_SS);
2c0262af 2388 }
432baffe
RH
2389
2390 gen_op_st_v(s, d_ot, val, cpu_A0);
2391 gen_op_mov_reg_v(a_ot, R_ESP, new_esp);
2c0262af
FB
2392}
2393
4f31916f 2394/* two step pop is necessary for precise exceptions */
8e31d234 2395static TCGMemOp gen_pop_T0(DisasContext *s)
2c0262af 2396{
8e31d234
RH
2397 TCGMemOp d_ot = mo_pushpop(s, s->dflag);
2398 TCGv addr = cpu_A0;
2399
14ce26e7 2400 if (CODE64(s)) {
8e31d234
RH
2401 addr = cpu_regs[R_ESP];
2402 } else if (!s->ss32) {
2403 tcg_gen_ext16u_tl(cpu_A0, cpu_regs[R_ESP]);
2404 gen_op_addl_A0_seg(s, R_SS);
2405 } else if (s->addseg) {
2406 tcg_gen_mov_tl(cpu_A0, cpu_regs[R_ESP]);
2407 gen_op_addl_A0_seg(s, R_SS);
2408 } else {
2409 tcg_gen_ext32u_tl(cpu_A0, cpu_regs[R_ESP]);
2c0262af 2410 }
8e31d234
RH
2411
2412 gen_op_ld_v(s, d_ot, cpu_T[0], addr);
2413 return d_ot;
2c0262af
FB
2414}
2415
8e31d234 2416static void gen_pop_update(DisasContext *s, TCGMemOp ot)
2c0262af 2417{
8e31d234 2418 gen_stack_update(s, 1 << ot);
2c0262af
FB
2419}
2420
2421static void gen_stack_A0(DisasContext *s)
2422{
57fec1fe 2423 gen_op_movl_A0_reg(R_ESP);
2c0262af 2424 if (!s->ss32)
a7e5c7de 2425 tcg_gen_ext16u_tl(cpu_A0, cpu_A0);
bbf662ee 2426 tcg_gen_mov_tl(cpu_T[1], cpu_A0);
2c0262af 2427 if (s->addseg)
7162ab21 2428 gen_op_addl_A0_seg(s, R_SS);
2c0262af
FB
2429}
2430
2431/* NOTE: wrap around in 16 bit not fully handled */
2432static void gen_pusha(DisasContext *s)
2433{
2434 int i;
57fec1fe 2435 gen_op_movl_A0_reg(R_ESP);
ab4e4aec 2436 gen_op_addl_A0_im(-8 << s->dflag);
2c0262af 2437 if (!s->ss32)
a7e5c7de 2438 tcg_gen_ext16u_tl(cpu_A0, cpu_A0);
bbf662ee 2439 tcg_gen_mov_tl(cpu_T[1], cpu_A0);
2c0262af 2440 if (s->addseg)
7162ab21 2441 gen_op_addl_A0_seg(s, R_SS);
2c0262af 2442 for(i = 0;i < 8; i++) {
c56baccf 2443 gen_op_mov_v_reg(MO_32, cpu_T[0], 7 - i);
ab4e4aec
RH
2444 gen_op_st_v(s, s->dflag, cpu_T[0], cpu_A0);
2445 gen_op_addl_A0_im(1 << s->dflag);
2c0262af 2446 }
68773f84 2447 gen_op_mov_reg_v(MO_16 + s->ss32, R_ESP, cpu_T[1]);
2c0262af
FB
2448}
2449
2450/* NOTE: wrap around in 16 bit not fully handled */
2451static void gen_popa(DisasContext *s)
2452{
2453 int i;
57fec1fe 2454 gen_op_movl_A0_reg(R_ESP);
2c0262af 2455 if (!s->ss32)
a7e5c7de 2456 tcg_gen_ext16u_tl(cpu_A0, cpu_A0);
bbf662ee 2457 tcg_gen_mov_tl(cpu_T[1], cpu_A0);
ab4e4aec 2458 tcg_gen_addi_tl(cpu_T[1], cpu_T[1], 8 << s->dflag);
2c0262af 2459 if (s->addseg)
7162ab21 2460 gen_op_addl_A0_seg(s, R_SS);
2c0262af
FB
2461 for(i = 0;i < 8; i++) {
2462 /* ESP is not reloaded */
2463 if (i != 3) {
ab4e4aec 2464 gen_op_ld_v(s, s->dflag, cpu_T[0], cpu_A0);
480a762d 2465 gen_op_mov_reg_v(s->dflag, 7 - i, cpu_T[0]);
2c0262af 2466 }
ab4e4aec 2467 gen_op_addl_A0_im(1 << s->dflag);
2c0262af 2468 }
68773f84 2469 gen_op_mov_reg_v(MO_16 + s->ss32, R_ESP, cpu_T[1]);
2c0262af
FB
2470}
2471
2c0262af
FB
2472static void gen_enter(DisasContext *s, int esp_addend, int level)
2473{
ab4e4aec
RH
2474 TCGMemOp ot = mo_pushpop(s, s->dflag);
2475 int opsize = 1 << ot;
2c0262af 2476
2c0262af 2477 level &= 0x1f;
8f091a59
FB
2478#ifdef TARGET_X86_64
2479 if (CODE64(s)) {
57fec1fe 2480 gen_op_movl_A0_reg(R_ESP);
8f091a59 2481 gen_op_addq_A0_im(-opsize);
bbf662ee 2482 tcg_gen_mov_tl(cpu_T[1], cpu_A0);
8f091a59
FB
2483
2484 /* push bp */
c56baccf 2485 gen_op_mov_v_reg(MO_32, cpu_T[0], R_EBP);
fd8ca9f6 2486 gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
8f091a59 2487 if (level) {
b5b38f61 2488 /* XXX: must save state */
2999a0b2 2489 gen_helper_enter64_level(cpu_env, tcg_const_i32(level),
4ba9938c 2490 tcg_const_i32((ot == MO_64)),
a7812ae4 2491 cpu_T[1]);
8f091a59 2492 }
68773f84 2493 gen_op_mov_reg_v(ot, R_EBP, cpu_T[1]);
bbf662ee 2494 tcg_gen_addi_tl(cpu_T[1], cpu_T[1], -esp_addend + (-opsize * level));
68773f84 2495 gen_op_mov_reg_v(MO_64, R_ESP, cpu_T[1]);
5fafdf24 2496 } else
8f091a59
FB
2497#endif
2498 {
57fec1fe 2499 gen_op_movl_A0_reg(R_ESP);
8f091a59
FB
2500 gen_op_addl_A0_im(-opsize);
2501 if (!s->ss32)
a7e5c7de 2502 tcg_gen_ext16u_tl(cpu_A0, cpu_A0);
bbf662ee 2503 tcg_gen_mov_tl(cpu_T[1], cpu_A0);
8f091a59 2504 if (s->addseg)
7162ab21 2505 gen_op_addl_A0_seg(s, R_SS);
8f091a59 2506 /* push bp */
c56baccf 2507 gen_op_mov_v_reg(MO_32, cpu_T[0], R_EBP);
fd8ca9f6 2508 gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
8f091a59 2509 if (level) {
b5b38f61 2510 /* XXX: must save state */
2999a0b2 2511 gen_helper_enter_level(cpu_env, tcg_const_i32(level),
ab4e4aec 2512 tcg_const_i32(s->dflag - 1),
a7812ae4 2513 cpu_T[1]);
8f091a59 2514 }
68773f84 2515 gen_op_mov_reg_v(ot, R_EBP, cpu_T[1]);
bbf662ee 2516 tcg_gen_addi_tl(cpu_T[1], cpu_T[1], -esp_addend + (-opsize * level));
68773f84 2517 gen_op_mov_reg_v(MO_16 + s->ss32, R_ESP, cpu_T[1]);
2c0262af 2518 }
2c0262af
FB
2519}
2520
14ce26e7 2521static void gen_exception(DisasContext *s, int trapno, target_ulong cur_eip)
2c0262af 2522{
773cdfcc 2523 gen_update_cc_op(s);
14ce26e7 2524 gen_jmp_im(cur_eip);
77b2bc2c 2525 gen_helper_raise_exception(cpu_env, tcg_const_i32(trapno));
5779406a 2526 s->is_jmp = DISAS_TB_JUMP;
2c0262af
FB
2527}
2528
2529/* an interrupt is different from an exception because of the
7f75ffd3 2530 privilege checks */
5fafdf24 2531static void gen_interrupt(DisasContext *s, int intno,
14ce26e7 2532 target_ulong cur_eip, target_ulong next_eip)
2c0262af 2533{
773cdfcc 2534 gen_update_cc_op(s);
14ce26e7 2535 gen_jmp_im(cur_eip);
77b2bc2c 2536 gen_helper_raise_interrupt(cpu_env, tcg_const_i32(intno),
a7812ae4 2537 tcg_const_i32(next_eip - cur_eip));
5779406a 2538 s->is_jmp = DISAS_TB_JUMP;
2c0262af
FB
2539}
2540
14ce26e7 2541static void gen_debug(DisasContext *s, target_ulong cur_eip)
2c0262af 2542{
773cdfcc 2543 gen_update_cc_op(s);
14ce26e7 2544 gen_jmp_im(cur_eip);
4a7443be 2545 gen_helper_debug(cpu_env);
5779406a 2546 s->is_jmp = DISAS_TB_JUMP;
2c0262af
FB
2547}
2548
2549/* generate a generic end of block. Trace exception is also generated
2550 if needed */
2551static void gen_eob(DisasContext *s)
2552{
773cdfcc 2553 gen_update_cc_op(s);
a2cc3b24 2554 if (s->tb->flags & HF_INHIBIT_IRQ_MASK) {
f0967a1a 2555 gen_helper_reset_inhibit_irq(cpu_env);
a2cc3b24 2556 }
a2397807 2557 if (s->tb->flags & HF_RF_MASK) {
f0967a1a 2558 gen_helper_reset_rf(cpu_env);
a2397807 2559 }
34865134 2560 if (s->singlestep_enabled) {
4a7443be 2561 gen_helper_debug(cpu_env);
34865134 2562 } else if (s->tf) {
4a7443be 2563 gen_helper_single_step(cpu_env);
2c0262af 2564 } else {
57fec1fe 2565 tcg_gen_exit_tb(0);
2c0262af 2566 }
5779406a 2567 s->is_jmp = DISAS_TB_JUMP;
2c0262af
FB
2568}
2569
2570/* generate a jump to eip. No segment change must happen before as a
2571 direct call to the next block may occur */
14ce26e7 2572static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num)
2c0262af 2573{
a3251186
RH
2574 gen_update_cc_op(s);
2575 set_cc_op(s, CC_OP_DYNAMIC);
2c0262af 2576 if (s->jmp_opt) {
6e256c93 2577 gen_goto_tb(s, tb_num, eip);
5779406a 2578 s->is_jmp = DISAS_TB_JUMP;
2c0262af 2579 } else {
14ce26e7 2580 gen_jmp_im(eip);
2c0262af
FB
2581 gen_eob(s);
2582 }
2583}
2584
14ce26e7
FB
2585static void gen_jmp(DisasContext *s, target_ulong eip)
2586{
2587 gen_jmp_tb(s, eip, 0);
2588}
2589
323d1876 2590static inline void gen_ldq_env_A0(DisasContext *s, int offset)
8686c490 2591{
3c5f4116 2592 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_A0, s->mem_index, MO_LEQ);
b6abf97d 2593 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, offset);
8686c490 2594}
664e0f19 2595
323d1876 2596static inline void gen_stq_env_A0(DisasContext *s, int offset)
8686c490 2597{
b6abf97d 2598 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, offset);
3523e4bd 2599 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0, s->mem_index, MO_LEQ);
8686c490 2600}
664e0f19 2601
323d1876 2602static inline void gen_ldo_env_A0(DisasContext *s, int offset)
8686c490 2603{
5c42a7cd 2604 int mem_index = s->mem_index;
3c5f4116 2605 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_A0, mem_index, MO_LEQ);
b6abf97d 2606 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(XMMReg, XMM_Q(0)));
8686c490 2607 tcg_gen_addi_tl(cpu_tmp0, cpu_A0, 8);
3c5f4116 2608 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_tmp0, mem_index, MO_LEQ);
b6abf97d 2609 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(XMMReg, XMM_Q(1)));
8686c490 2610}
14ce26e7 2611
323d1876 2612static inline void gen_sto_env_A0(DisasContext *s, int offset)
8686c490 2613{
5c42a7cd 2614 int mem_index = s->mem_index;
b6abf97d 2615 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(XMMReg, XMM_Q(0)));
3523e4bd 2616 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0, mem_index, MO_LEQ);
8686c490 2617 tcg_gen_addi_tl(cpu_tmp0, cpu_A0, 8);
b6abf97d 2618 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, offset + offsetof(XMMReg, XMM_Q(1)));
3523e4bd 2619 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_tmp0, mem_index, MO_LEQ);
8686c490 2620}
14ce26e7 2621
5af45186
FB
2622static inline void gen_op_movo(int d_offset, int s_offset)
2623{
b6abf97d
FB
2624 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset);
2625 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset);
2626 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset + 8);
2627 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset + 8);
5af45186
FB
2628}
2629
2630static inline void gen_op_movq(int d_offset, int s_offset)
2631{
b6abf97d
FB
2632 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset);
2633 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset);
5af45186
FB
2634}
2635
2636static inline void gen_op_movl(int d_offset, int s_offset)
2637{
b6abf97d
FB
2638 tcg_gen_ld_i32(cpu_tmp2_i32, cpu_env, s_offset);
2639 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, d_offset);
5af45186
FB
2640}
2641
2642static inline void gen_op_movq_env_0(int d_offset)
2643{
b6abf97d
FB
2644 tcg_gen_movi_i64(cpu_tmp1_i64, 0);
2645 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset);
5af45186 2646}
664e0f19 2647
d3eb5eae
BS
2648typedef void (*SSEFunc_i_ep)(TCGv_i32 val, TCGv_ptr env, TCGv_ptr reg);
2649typedef void (*SSEFunc_l_ep)(TCGv_i64 val, TCGv_ptr env, TCGv_ptr reg);
2650typedef void (*SSEFunc_0_epi)(TCGv_ptr env, TCGv_ptr reg, TCGv_i32 val);
2651typedef void (*SSEFunc_0_epl)(TCGv_ptr env, TCGv_ptr reg, TCGv_i64 val);
2652typedef void (*SSEFunc_0_epp)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b);
2653typedef void (*SSEFunc_0_eppi)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b,
2654 TCGv_i32 val);
c4baa050 2655typedef void (*SSEFunc_0_ppi)(TCGv_ptr reg_a, TCGv_ptr reg_b, TCGv_i32 val);
d3eb5eae
BS
2656typedef void (*SSEFunc_0_eppt)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b,
2657 TCGv val);
c4baa050 2658
5af45186
FB
2659#define SSE_SPECIAL ((void *)1)
2660#define SSE_DUMMY ((void *)2)
664e0f19 2661
a7812ae4
PB
2662#define MMX_OP2(x) { gen_helper_ ## x ## _mmx, gen_helper_ ## x ## _xmm }
2663#define SSE_FOP(x) { gen_helper_ ## x ## ps, gen_helper_ ## x ## pd, \
2664 gen_helper_ ## x ## ss, gen_helper_ ## x ## sd, }
5af45186 2665
d3eb5eae 2666static const SSEFunc_0_epp sse_op_table1[256][4] = {
a35f3ec7
AJ
2667 /* 3DNow! extensions */
2668 [0x0e] = { SSE_DUMMY }, /* femms */
2669 [0x0f] = { SSE_DUMMY }, /* pf... */
664e0f19
FB
2670 /* pure SSE operations */
2671 [0x10] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movups, movupd, movss, movsd */
2672 [0x11] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movups, movupd, movss, movsd */
465e9838 2673 [0x12] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movlps, movlpd, movsldup, movddup */
664e0f19 2674 [0x13] = { SSE_SPECIAL, SSE_SPECIAL }, /* movlps, movlpd */
a7812ae4
PB
2675 [0x14] = { gen_helper_punpckldq_xmm, gen_helper_punpcklqdq_xmm },
2676 [0x15] = { gen_helper_punpckhdq_xmm, gen_helper_punpckhqdq_xmm },
664e0f19
FB
2677 [0x16] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movhps, movhpd, movshdup */
2678 [0x17] = { SSE_SPECIAL, SSE_SPECIAL }, /* movhps, movhpd */
2679
2680 [0x28] = { SSE_SPECIAL, SSE_SPECIAL }, /* movaps, movapd */
2681 [0x29] = { SSE_SPECIAL, SSE_SPECIAL }, /* movaps, movapd */
2682 [0x2a] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvtpi2ps, cvtpi2pd, cvtsi2ss, cvtsi2sd */
d9f4bb27 2683 [0x2b] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movntps, movntpd, movntss, movntsd */
664e0f19
FB
2684 [0x2c] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvttps2pi, cvttpd2pi, cvttsd2si, cvttss2si */
2685 [0x2d] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvtps2pi, cvtpd2pi, cvtsd2si, cvtss2si */
a7812ae4
PB
2686 [0x2e] = { gen_helper_ucomiss, gen_helper_ucomisd },
2687 [0x2f] = { gen_helper_comiss, gen_helper_comisd },
664e0f19
FB
2688 [0x50] = { SSE_SPECIAL, SSE_SPECIAL }, /* movmskps, movmskpd */
2689 [0x51] = SSE_FOP(sqrt),
a7812ae4
PB
2690 [0x52] = { gen_helper_rsqrtps, NULL, gen_helper_rsqrtss, NULL },
2691 [0x53] = { gen_helper_rcpps, NULL, gen_helper_rcpss, NULL },
2692 [0x54] = { gen_helper_pand_xmm, gen_helper_pand_xmm }, /* andps, andpd */
2693 [0x55] = { gen_helper_pandn_xmm, gen_helper_pandn_xmm }, /* andnps, andnpd */
2694 [0x56] = { gen_helper_por_xmm, gen_helper_por_xmm }, /* orps, orpd */
2695 [0x57] = { gen_helper_pxor_xmm, gen_helper_pxor_xmm }, /* xorps, xorpd */
664e0f19
FB
2696 [0x58] = SSE_FOP(add),
2697 [0x59] = SSE_FOP(mul),
a7812ae4
PB
2698 [0x5a] = { gen_helper_cvtps2pd, gen_helper_cvtpd2ps,
2699 gen_helper_cvtss2sd, gen_helper_cvtsd2ss },
2700 [0x5b] = { gen_helper_cvtdq2ps, gen_helper_cvtps2dq, gen_helper_cvttps2dq },
664e0f19
FB
2701 [0x5c] = SSE_FOP(sub),
2702 [0x5d] = SSE_FOP(min),
2703 [0x5e] = SSE_FOP(div),
2704 [0x5f] = SSE_FOP(max),
2705
2706 [0xc2] = SSE_FOP(cmpeq),
d3eb5eae
BS
2707 [0xc6] = { (SSEFunc_0_epp)gen_helper_shufps,
2708 (SSEFunc_0_epp)gen_helper_shufpd }, /* XXX: casts */
664e0f19 2709
7073fbad
RH
2710 /* SSSE3, SSE4, MOVBE, CRC32, BMI1, BMI2, ADX. */
2711 [0x38] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
2712 [0x3a] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
4242b1bd 2713
664e0f19
FB
2714 /* MMX ops and their SSE extensions */
2715 [0x60] = MMX_OP2(punpcklbw),
2716 [0x61] = MMX_OP2(punpcklwd),
2717 [0x62] = MMX_OP2(punpckldq),
2718 [0x63] = MMX_OP2(packsswb),
2719 [0x64] = MMX_OP2(pcmpgtb),
2720 [0x65] = MMX_OP2(pcmpgtw),
2721 [0x66] = MMX_OP2(pcmpgtl),
2722 [0x67] = MMX_OP2(packuswb),
2723 [0x68] = MMX_OP2(punpckhbw),
2724 [0x69] = MMX_OP2(punpckhwd),
2725 [0x6a] = MMX_OP2(punpckhdq),
2726 [0x6b] = MMX_OP2(packssdw),
a7812ae4
PB
2727 [0x6c] = { NULL, gen_helper_punpcklqdq_xmm },
2728 [0x6d] = { NULL, gen_helper_punpckhqdq_xmm },
664e0f19
FB
2729 [0x6e] = { SSE_SPECIAL, SSE_SPECIAL }, /* movd mm, ea */
2730 [0x6f] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movq, movdqa, , movqdu */
d3eb5eae
BS
2731 [0x70] = { (SSEFunc_0_epp)gen_helper_pshufw_mmx,
2732 (SSEFunc_0_epp)gen_helper_pshufd_xmm,
2733 (SSEFunc_0_epp)gen_helper_pshufhw_xmm,
2734 (SSEFunc_0_epp)gen_helper_pshuflw_xmm }, /* XXX: casts */
664e0f19
FB
2735 [0x71] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftw */
2736 [0x72] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftd */
2737 [0x73] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftq */
2738 [0x74] = MMX_OP2(pcmpeqb),
2739 [0x75] = MMX_OP2(pcmpeqw),
2740 [0x76] = MMX_OP2(pcmpeql),
a35f3ec7 2741 [0x77] = { SSE_DUMMY }, /* emms */
d9f4bb27
AP
2742 [0x78] = { NULL, SSE_SPECIAL, NULL, SSE_SPECIAL }, /* extrq_i, insertq_i */
2743 [0x79] = { NULL, gen_helper_extrq_r, NULL, gen_helper_insertq_r },
a7812ae4
PB
2744 [0x7c] = { NULL, gen_helper_haddpd, NULL, gen_helper_haddps },
2745 [0x7d] = { NULL, gen_helper_hsubpd, NULL, gen_helper_hsubps },
664e0f19
FB
2746 [0x7e] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movd, movd, , movq */
2747 [0x7f] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movq, movdqa, movdqu */
2748 [0xc4] = { SSE_SPECIAL, SSE_SPECIAL }, /* pinsrw */
2749 [0xc5] = { SSE_SPECIAL, SSE_SPECIAL }, /* pextrw */
a7812ae4 2750 [0xd0] = { NULL, gen_helper_addsubpd, NULL, gen_helper_addsubps },
664e0f19
FB
2751 [0xd1] = MMX_OP2(psrlw),
2752 [0xd2] = MMX_OP2(psrld),
2753 [0xd3] = MMX_OP2(psrlq),
2754 [0xd4] = MMX_OP2(paddq),
2755 [0xd5] = MMX_OP2(pmullw),
2756 [0xd6] = { NULL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
2757 [0xd7] = { SSE_SPECIAL, SSE_SPECIAL }, /* pmovmskb */
2758 [0xd8] = MMX_OP2(psubusb),
2759 [0xd9] = MMX_OP2(psubusw),
2760 [0xda] = MMX_OP2(pminub),
2761 [0xdb] = MMX_OP2(pand),
2762 [0xdc] = MMX_OP2(paddusb),
2763 [0xdd] = MMX_OP2(paddusw),
2764 [0xde] = MMX_OP2(pmaxub),
2765 [0xdf] = MMX_OP2(pandn),
2766 [0xe0] = MMX_OP2(pavgb),
2767 [0xe1] = MMX_OP2(psraw),
2768 [0xe2] = MMX_OP2(psrad),
2769 [0xe3] = MMX_OP2(pavgw),
2770 [0xe4] = MMX_OP2(pmulhuw),
2771 [0xe5] = MMX_OP2(pmulhw),
a7812ae4 2772 [0xe6] = { NULL, gen_helper_cvttpd2dq, gen_helper_cvtdq2pd, gen_helper_cvtpd2dq },
664e0f19
FB
2773 [0xe7] = { SSE_SPECIAL , SSE_SPECIAL }, /* movntq, movntq */
2774 [0xe8] = MMX_OP2(psubsb),
2775 [0xe9] = MMX_OP2(psubsw),
2776 [0xea] = MMX_OP2(pminsw),
2777 [0xeb] = MMX_OP2(por),
2778 [0xec] = MMX_OP2(paddsb),
2779 [0xed] = MMX_OP2(paddsw),
2780 [0xee] = MMX_OP2(pmaxsw),
2781 [0xef] = MMX_OP2(pxor),
465e9838 2782 [0xf0] = { NULL, NULL, NULL, SSE_SPECIAL }, /* lddqu */
664e0f19
FB
2783 [0xf1] = MMX_OP2(psllw),
2784 [0xf2] = MMX_OP2(pslld),
2785 [0xf3] = MMX_OP2(psllq),
2786 [0xf4] = MMX_OP2(pmuludq),
2787 [0xf5] = MMX_OP2(pmaddwd),
2788 [0xf6] = MMX_OP2(psadbw),
d3eb5eae
BS
2789 [0xf7] = { (SSEFunc_0_epp)gen_helper_maskmov_mmx,
2790 (SSEFunc_0_epp)gen_helper_maskmov_xmm }, /* XXX: casts */
664e0f19
FB
2791 [0xf8] = MMX_OP2(psubb),
2792 [0xf9] = MMX_OP2(psubw),
2793 [0xfa] = MMX_OP2(psubl),
2794 [0xfb] = MMX_OP2(psubq),
2795 [0xfc] = MMX_OP2(paddb),
2796 [0xfd] = MMX_OP2(paddw),
2797 [0xfe] = MMX_OP2(paddl),
2798};
2799
d3eb5eae 2800static const SSEFunc_0_epp sse_op_table2[3 * 8][2] = {
664e0f19
FB
2801 [0 + 2] = MMX_OP2(psrlw),
2802 [0 + 4] = MMX_OP2(psraw),
2803 [0 + 6] = MMX_OP2(psllw),
2804 [8 + 2] = MMX_OP2(psrld),
2805 [8 + 4] = MMX_OP2(psrad),
2806 [8 + 6] = MMX_OP2(pslld),
2807 [16 + 2] = MMX_OP2(psrlq),
a7812ae4 2808 [16 + 3] = { NULL, gen_helper_psrldq_xmm },
664e0f19 2809 [16 + 6] = MMX_OP2(psllq),
a7812ae4 2810 [16 + 7] = { NULL, gen_helper_pslldq_xmm },
664e0f19
FB
2811};
2812
d3eb5eae 2813static const SSEFunc_0_epi sse_op_table3ai[] = {
a7812ae4 2814 gen_helper_cvtsi2ss,
11f8cdbc 2815 gen_helper_cvtsi2sd
c4baa050 2816};
a7812ae4 2817
11f8cdbc 2818#ifdef TARGET_X86_64
d3eb5eae 2819static const SSEFunc_0_epl sse_op_table3aq[] = {
11f8cdbc
SW
2820 gen_helper_cvtsq2ss,
2821 gen_helper_cvtsq2sd
2822};
2823#endif
2824
d3eb5eae 2825static const SSEFunc_i_ep sse_op_table3bi[] = {
a7812ae4 2826 gen_helper_cvttss2si,
a7812ae4 2827 gen_helper_cvtss2si,
bedc2ac1 2828 gen_helper_cvttsd2si,
11f8cdbc 2829 gen_helper_cvtsd2si
664e0f19 2830};
3b46e624 2831
11f8cdbc 2832#ifdef TARGET_X86_64
d3eb5eae 2833static const SSEFunc_l_ep sse_op_table3bq[] = {
11f8cdbc 2834 gen_helper_cvttss2sq,
11f8cdbc 2835 gen_helper_cvtss2sq,
bedc2ac1 2836 gen_helper_cvttsd2sq,
11f8cdbc
SW
2837 gen_helper_cvtsd2sq
2838};
2839#endif
2840
d3eb5eae 2841static const SSEFunc_0_epp sse_op_table4[8][4] = {
664e0f19
FB
2842 SSE_FOP(cmpeq),
2843 SSE_FOP(cmplt),
2844 SSE_FOP(cmple),
2845 SSE_FOP(cmpunord),
2846 SSE_FOP(cmpneq),
2847 SSE_FOP(cmpnlt),
2848 SSE_FOP(cmpnle),
2849 SSE_FOP(cmpord),
2850};
3b46e624 2851
d3eb5eae 2852static const SSEFunc_0_epp sse_op_table5[256] = {
a7812ae4
PB
2853 [0x0c] = gen_helper_pi2fw,
2854 [0x0d] = gen_helper_pi2fd,
2855 [0x1c] = gen_helper_pf2iw,
2856 [0x1d] = gen_helper_pf2id,
2857 [0x8a] = gen_helper_pfnacc,
2858 [0x8e] = gen_helper_pfpnacc,
2859 [0x90] = gen_helper_pfcmpge,
2860 [0x94] = gen_helper_pfmin,
2861 [0x96] = gen_helper_pfrcp,
2862 [0x97] = gen_helper_pfrsqrt,
2863 [0x9a] = gen_helper_pfsub,
2864 [0x9e] = gen_helper_pfadd,
2865 [0xa0] = gen_helper_pfcmpgt,
2866 [0xa4] = gen_helper_pfmax,
2867 [0xa6] = gen_helper_movq, /* pfrcpit1; no need to actually increase precision */
2868 [0xa7] = gen_helper_movq, /* pfrsqit1 */
2869 [0xaa] = gen_helper_pfsubr,
2870 [0xae] = gen_helper_pfacc,
2871 [0xb0] = gen_helper_pfcmpeq,
2872 [0xb4] = gen_helper_pfmul,
2873 [0xb6] = gen_helper_movq, /* pfrcpit2 */
2874 [0xb7] = gen_helper_pmulhrw_mmx,
2875 [0xbb] = gen_helper_pswapd,
2876 [0xbf] = gen_helper_pavgb_mmx /* pavgusb */
a35f3ec7
AJ
2877};
2878
d3eb5eae
BS
2879struct SSEOpHelper_epp {
2880 SSEFunc_0_epp op[2];
c4baa050
BS
2881 uint32_t ext_mask;
2882};
2883
d3eb5eae
BS
2884struct SSEOpHelper_eppi {
2885 SSEFunc_0_eppi op[2];
c4baa050 2886 uint32_t ext_mask;
222a3336 2887};
c4baa050 2888
222a3336 2889#define SSSE3_OP(x) { MMX_OP2(x), CPUID_EXT_SSSE3 }
a7812ae4
PB
2890#define SSE41_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, CPUID_EXT_SSE41 }
2891#define SSE42_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, CPUID_EXT_SSE42 }
222a3336 2892#define SSE41_SPECIAL { { NULL, SSE_SPECIAL }, CPUID_EXT_SSE41 }
e71827bc
AJ
2893#define PCLMULQDQ_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, \
2894 CPUID_EXT_PCLMULQDQ }
d640045a 2895#define AESNI_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, CPUID_EXT_AES }
c4baa050 2896
d3eb5eae 2897static const struct SSEOpHelper_epp sse_op_table6[256] = {
222a3336
AZ
2898 [0x00] = SSSE3_OP(pshufb),
2899 [0x01] = SSSE3_OP(phaddw),
2900 [0x02] = SSSE3_OP(phaddd),
2901 [0x03] = SSSE3_OP(phaddsw),
2902 [0x04] = SSSE3_OP(pmaddubsw),
2903 [0x05] = SSSE3_OP(phsubw),
2904 [0x06] = SSSE3_OP(phsubd),
2905 [0x07] = SSSE3_OP(phsubsw),
2906 [0x08] = SSSE3_OP(psignb),
2907 [0x09] = SSSE3_OP(psignw),
2908 [0x0a] = SSSE3_OP(psignd),
2909 [0x0b] = SSSE3_OP(pmulhrsw),
2910 [0x10] = SSE41_OP(pblendvb),
2911 [0x14] = SSE41_OP(blendvps),
2912 [0x15] = SSE41_OP(blendvpd),
2913 [0x17] = SSE41_OP(ptest),
2914 [0x1c] = SSSE3_OP(pabsb),
2915 [0x1d] = SSSE3_OP(pabsw),
2916 [0x1e] = SSSE3_OP(pabsd),
2917 [0x20] = SSE41_OP(pmovsxbw),
2918 [0x21] = SSE41_OP(pmovsxbd),
2919 [0x22] = SSE41_OP(pmovsxbq),
2920 [0x23] = SSE41_OP(pmovsxwd),
2921 [0x24] = SSE41_OP(pmovsxwq),
2922 [0x25] = SSE41_OP(pmovsxdq),
2923 [0x28] = SSE41_OP(pmuldq),
2924 [0x29] = SSE41_OP(pcmpeqq),
2925 [0x2a] = SSE41_SPECIAL, /* movntqda */
2926 [0x2b] = SSE41_OP(packusdw),
2927 [0x30] = SSE41_OP(pmovzxbw),
2928 [0x31] = SSE41_OP(pmovzxbd),
2929 [0x32] = SSE41_OP(pmovzxbq),
2930 [0x33] = SSE41_OP(pmovzxwd),
2931 [0x34] = SSE41_OP(pmovzxwq),
2932 [0x35] = SSE41_OP(pmovzxdq),
2933 [0x37] = SSE42_OP(pcmpgtq),
2934 [0x38] = SSE41_OP(pminsb),
2935 [0x39] = SSE41_OP(pminsd),
2936 [0x3a] = SSE41_OP(pminuw),
2937 [0x3b] = SSE41_OP(pminud),
2938 [0x3c] = SSE41_OP(pmaxsb),
2939 [0x3d] = SSE41_OP(pmaxsd),
2940 [0x3e] = SSE41_OP(pmaxuw),
2941 [0x3f] = SSE41_OP(pmaxud),
2942 [0x40] = SSE41_OP(pmulld),
2943 [0x41] = SSE41_OP(phminposuw),
d640045a
AJ
2944 [0xdb] = AESNI_OP(aesimc),
2945 [0xdc] = AESNI_OP(aesenc),
2946 [0xdd] = AESNI_OP(aesenclast),
2947 [0xde] = AESNI_OP(aesdec),
2948 [0xdf] = AESNI_OP(aesdeclast),
4242b1bd
AZ
2949};
2950
d3eb5eae 2951static const struct SSEOpHelper_eppi sse_op_table7[256] = {
222a3336
AZ
2952 [0x08] = SSE41_OP(roundps),
2953 [0x09] = SSE41_OP(roundpd),
2954 [0x0a] = SSE41_OP(roundss),
2955 [0x0b] = SSE41_OP(roundsd),
2956 [0x0c] = SSE41_OP(blendps),
2957 [0x0d] = SSE41_OP(blendpd),
2958 [0x0e] = SSE41_OP(pblendw),
2959 [0x0f] = SSSE3_OP(palignr),
2960 [0x14] = SSE41_SPECIAL, /* pextrb */
2961 [0x15] = SSE41_SPECIAL, /* pextrw */
2962 [0x16] = SSE41_SPECIAL, /* pextrd/pextrq */
2963 [0x17] = SSE41_SPECIAL, /* extractps */
2964 [0x20] = SSE41_SPECIAL, /* pinsrb */
2965 [0x21] = SSE41_SPECIAL, /* insertps */
2966 [0x22] = SSE41_SPECIAL, /* pinsrd/pinsrq */
2967 [0x40] = SSE41_OP(dpps),
2968 [0x41] = SSE41_OP(dppd),
2969 [0x42] = SSE41_OP(mpsadbw),
e71827bc 2970 [0x44] = PCLMULQDQ_OP(pclmulqdq),
222a3336
AZ
2971 [0x60] = SSE42_OP(pcmpestrm),
2972 [0x61] = SSE42_OP(pcmpestri),
2973 [0x62] = SSE42_OP(pcmpistrm),
2974 [0x63] = SSE42_OP(pcmpistri),
d640045a 2975 [0xdf] = AESNI_OP(aeskeygenassist),
4242b1bd
AZ
2976};
2977
0af10c86
BS
2978static void gen_sse(CPUX86State *env, DisasContext *s, int b,
2979 target_ulong pc_start, int rex_r)
664e0f19 2980{
d67dc9e6 2981 int b1, op1_offset, op2_offset, is_xmm, val;
4eeb3939 2982 int modrm, mod, rm, reg;
d3eb5eae
BS
2983 SSEFunc_0_epp sse_fn_epp;
2984 SSEFunc_0_eppi sse_fn_eppi;
c4baa050 2985 SSEFunc_0_ppi sse_fn_ppi;
d3eb5eae 2986 SSEFunc_0_eppt sse_fn_eppt;
d67dc9e6 2987 TCGMemOp ot;
664e0f19
FB
2988
2989 b &= 0xff;
5fafdf24 2990 if (s->prefix & PREFIX_DATA)
664e0f19 2991 b1 = 1;
5fafdf24 2992 else if (s->prefix & PREFIX_REPZ)
664e0f19 2993 b1 = 2;
5fafdf24 2994 else if (s->prefix & PREFIX_REPNZ)
664e0f19
FB
2995 b1 = 3;
2996 else
2997 b1 = 0;
d3eb5eae
BS
2998 sse_fn_epp = sse_op_table1[b][b1];
2999 if (!sse_fn_epp) {
664e0f19 3000 goto illegal_op;
c4baa050 3001 }
a35f3ec7 3002 if ((b <= 0x5f && b >= 0x10) || b == 0xc6 || b == 0xc2) {
664e0f19
FB
3003 is_xmm = 1;
3004 } else {
3005 if (b1 == 0) {
3006 /* MMX case */
3007 is_xmm = 0;
3008 } else {
3009 is_xmm = 1;
3010 }
3011 }
3012 /* simple MMX/SSE operation */
3013 if (s->flags & HF_TS_MASK) {
3014 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
3015 return;
3016 }
3017 if (s->flags & HF_EM_MASK) {
3018 illegal_op:
3019 gen_exception(s, EXCP06_ILLOP, pc_start - s->cs_base);
3020 return;
3021 }
3022 if (is_xmm && !(s->flags & HF_OSFXSR_MASK))
4242b1bd
AZ
3023 if ((b != 0x38 && b != 0x3a) || (s->prefix & PREFIX_DATA))
3024 goto illegal_op;
e771edab
AJ
3025 if (b == 0x0e) {
3026 if (!(s->cpuid_ext2_features & CPUID_EXT2_3DNOW))
3027 goto illegal_op;
3028 /* femms */
d3eb5eae 3029 gen_helper_emms(cpu_env);
e771edab
AJ
3030 return;
3031 }
3032 if (b == 0x77) {
3033 /* emms */
d3eb5eae 3034 gen_helper_emms(cpu_env);
664e0f19
FB
3035 return;
3036 }
3037 /* prepare MMX state (XXX: optimize by storing fptt and fptags in
3038 the static cpu state) */
3039 if (!is_xmm) {
d3eb5eae 3040 gen_helper_enter_mmx(cpu_env);
664e0f19
FB
3041 }
3042
0af10c86 3043 modrm = cpu_ldub_code(env, s->pc++);
664e0f19
FB
3044 reg = ((modrm >> 3) & 7);
3045 if (is_xmm)
3046 reg |= rex_r;
3047 mod = (modrm >> 6) & 3;
d3eb5eae 3048 if (sse_fn_epp == SSE_SPECIAL) {
664e0f19
FB
3049 b |= (b1 << 8);
3050 switch(b) {
3051 case 0x0e7: /* movntq */
5fafdf24 3052 if (mod == 3)
664e0f19 3053 goto illegal_op;
4eeb3939 3054 gen_lea_modrm(env, s, modrm);
323d1876 3055 gen_stq_env_A0(s, offsetof(CPUX86State, fpregs[reg].mmx));
664e0f19
FB
3056 break;
3057 case 0x1e7: /* movntdq */
3058 case 0x02b: /* movntps */
3059 case 0x12b: /* movntps */
2e21e749
T
3060 if (mod == 3)
3061 goto illegal_op;
4eeb3939 3062 gen_lea_modrm(env, s, modrm);
323d1876 3063 gen_sto_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
2e21e749 3064 break;
465e9838
FB
3065 case 0x3f0: /* lddqu */
3066 if (mod == 3)
664e0f19 3067 goto illegal_op;
4eeb3939 3068 gen_lea_modrm(env, s, modrm);
323d1876 3069 gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
664e0f19 3070 break;
d9f4bb27
AP
3071 case 0x22b: /* movntss */
3072 case 0x32b: /* movntsd */
3073 if (mod == 3)
3074 goto illegal_op;
4eeb3939 3075 gen_lea_modrm(env, s, modrm);
d9f4bb27 3076 if (b1 & 1) {
323d1876 3077 gen_stq_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
d9f4bb27
AP
3078 } else {
3079 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,
3080 xmm_regs[reg].XMM_L(0)));
fd8ca9f6 3081 gen_op_st_v(s, MO_32, cpu_T[0], cpu_A0);
d9f4bb27
AP
3082 }
3083 break;
664e0f19 3084 case 0x6e: /* movd mm, ea */
dabd98dd 3085#ifdef TARGET_X86_64
ab4e4aec 3086 if (s->dflag == MO_64) {
4ba9938c 3087 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 0);
5af45186 3088 tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,fpregs[reg].mmx));
5fafdf24 3089 } else
dabd98dd
FB
3090#endif
3091 {
4ba9938c 3092 gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 0);
5af45186
FB
3093 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3094 offsetof(CPUX86State,fpregs[reg].mmx));
a7812ae4
PB
3095 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
3096 gen_helper_movl_mm_T0_mmx(cpu_ptr0, cpu_tmp2_i32);
dabd98dd 3097 }
664e0f19
FB
3098 break;
3099 case 0x16e: /* movd xmm, ea */
dabd98dd 3100#ifdef TARGET_X86_64
ab4e4aec 3101 if (s->dflag == MO_64) {
4ba9938c 3102 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 0);
5af45186
FB
3103 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3104 offsetof(CPUX86State,xmm_regs[reg]));
a7812ae4 3105 gen_helper_movq_mm_T0_xmm(cpu_ptr0, cpu_T[0]);
5fafdf24 3106 } else
dabd98dd
FB
3107#endif
3108 {
4ba9938c 3109 gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 0);
5af45186
FB
3110 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3111 offsetof(CPUX86State,xmm_regs[reg]));
b6abf97d 3112 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
a7812ae4 3113 gen_helper_movl_mm_T0_xmm(cpu_ptr0, cpu_tmp2_i32);
dabd98dd 3114 }
664e0f19
FB
3115 break;
3116 case 0x6f: /* movq mm, ea */
3117 if (mod != 3) {
4eeb3939 3118 gen_lea_modrm(env, s, modrm);
323d1876 3119 gen_ldq_env_A0(s, offsetof(CPUX86State, fpregs[reg].mmx));
664e0f19
FB
3120 } else {
3121 rm = (modrm & 7);
b6abf97d 3122 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env,
5af45186 3123 offsetof(CPUX86State,fpregs[rm].mmx));
b6abf97d 3124 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env,
5af45186 3125 offsetof(CPUX86State,fpregs[reg].mmx));
664e0f19
FB
3126 }
3127 break;
3128 case 0x010: /* movups */
3129 case 0x110: /* movupd */
3130 case 0x028: /* movaps */
3131 case 0x128: /* movapd */
3132 case 0x16f: /* movdqa xmm, ea */
3133 case 0x26f: /* movdqu xmm, ea */
3134 if (mod != 3) {
4eeb3939 3135 gen_lea_modrm(env, s, modrm);
323d1876 3136 gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
664e0f19
FB
3137 } else {
3138 rm = (modrm & 7) | REX_B(s);
3139 gen_op_movo(offsetof(CPUX86State,xmm_regs[reg]),
3140 offsetof(CPUX86State,xmm_regs[rm]));
3141 }
3142 break;
3143 case 0x210: /* movss xmm, ea */
3144 if (mod != 3) {
4eeb3939 3145 gen_lea_modrm(env, s, modrm);
909be183 3146 gen_op_ld_v(s, MO_32, cpu_T[0], cpu_A0);
651ba608 3147 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
97212c88 3148 tcg_gen_movi_tl(cpu_T[0], 0);
651ba608
FB
3149 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)));
3150 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)));
3151 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)));
664e0f19
FB
3152 } else {
3153 rm = (modrm & 7) | REX_B(s);
3154 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)),
3155 offsetof(CPUX86State,xmm_regs[rm].XMM_L(0)));
3156 }
3157 break;
3158 case 0x310: /* movsd xmm, ea */
3159 if (mod != 3) {
4eeb3939 3160 gen_lea_modrm(env, s, modrm);
323d1876
RH
3161 gen_ldq_env_A0(s, offsetof(CPUX86State,
3162 xmm_regs[reg].XMM_Q(0)));
97212c88 3163 tcg_gen_movi_tl(cpu_T[0], 0);
651ba608
FB
3164 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)));
3165 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)));
664e0f19
FB
3166 } else {
3167 rm = (modrm & 7) | REX_B(s);
3168 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
3169 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
3170 }
3171 break;
3172 case 0x012: /* movlps */
3173 case 0x112: /* movlpd */
3174 if (mod != 3) {
4eeb3939 3175 gen_lea_modrm(env, s, modrm);
323d1876
RH
3176 gen_ldq_env_A0(s, offsetof(CPUX86State,
3177 xmm_regs[reg].XMM_Q(0)));
664e0f19
FB
3178 } else {
3179 /* movhlps */
3180 rm = (modrm & 7) | REX_B(s);
3181 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
3182 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(1)));
3183 }
3184 break;
465e9838
FB
3185 case 0x212: /* movsldup */
3186 if (mod != 3) {
4eeb3939 3187 gen_lea_modrm(env, s, modrm);
323d1876 3188 gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
465e9838
FB
3189 } else {
3190 rm = (modrm & 7) | REX_B(s);
3191 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)),
3192 offsetof(CPUX86State,xmm_regs[rm].XMM_L(0)));
3193 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)),
3194 offsetof(CPUX86State,xmm_regs[rm].XMM_L(2)));
3195 }
3196 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)),
3197 offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
3198 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)),
3199 offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)));
3200 break;
3201 case 0x312: /* movddup */
3202 if (mod != 3) {
4eeb3939 3203 gen_lea_modrm(env, s, modrm);
323d1876
RH
3204 gen_ldq_env_A0(s, offsetof(CPUX86State,
3205 xmm_regs[reg].XMM_Q(0)));
465e9838
FB
3206 } else {
3207 rm = (modrm & 7) | REX_B(s);
3208 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
3209 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
3210 }
3211 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)),
ba6526df 3212 offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
465e9838 3213 break;
664e0f19
FB
3214 case 0x016: /* movhps */
3215 case 0x116: /* movhpd */
3216 if (mod != 3) {
4eeb3939 3217 gen_lea_modrm(env, s, modrm);
323d1876
RH
3218 gen_ldq_env_A0(s, offsetof(CPUX86State,
3219 xmm_regs[reg].XMM_Q(1)));
664e0f19
FB
3220 } else {
3221 /* movlhps */
3222 rm = (modrm & 7) | REX_B(s);
3223 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)),
3224 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
3225 }
3226 break;
3227 case 0x216: /* movshdup */
3228 if (mod != 3) {
4eeb3939 3229 gen_lea_modrm(env, s, modrm);
323d1876 3230 gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
664e0f19
FB
3231 } else {
3232 rm = (modrm & 7) | REX_B(s);
3233 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)),
3234 offsetof(CPUX86State,xmm_regs[rm].XMM_L(1)));
3235 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)),
3236 offsetof(CPUX86State,xmm_regs[rm].XMM_L(3)));
3237 }
3238 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)),
3239 offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)));
3240 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)),
3241 offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)));
3242 break;
d9f4bb27
AP
3243 case 0x178:
3244 case 0x378:
3245 {
3246 int bit_index, field_length;
3247
3248 if (b1 == 1 && reg != 0)
3249 goto illegal_op;
0af10c86
BS
3250 field_length = cpu_ldub_code(env, s->pc++) & 0x3F;
3251 bit_index = cpu_ldub_code(env, s->pc++) & 0x3F;
d9f4bb27
AP
3252 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3253 offsetof(CPUX86State,xmm_regs[reg]));
3254 if (b1 == 1)
d3eb5eae
BS
3255 gen_helper_extrq_i(cpu_env, cpu_ptr0,
3256 tcg_const_i32(bit_index),
3257 tcg_const_i32(field_length));
d9f4bb27 3258 else
d3eb5eae
BS
3259 gen_helper_insertq_i(cpu_env, cpu_ptr0,
3260 tcg_const_i32(bit_index),
3261 tcg_const_i32(field_length));
d9f4bb27
AP
3262 }
3263 break;
664e0f19 3264 case 0x7e: /* movd ea, mm */
dabd98dd 3265#ifdef TARGET_X86_64
ab4e4aec 3266 if (s->dflag == MO_64) {
5af45186
FB
3267 tcg_gen_ld_i64(cpu_T[0], cpu_env,
3268 offsetof(CPUX86State,fpregs[reg].mmx));
4ba9938c 3269 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 1);
5fafdf24 3270 } else
dabd98dd
FB
3271#endif
3272 {
5af45186
FB
3273 tcg_gen_ld32u_tl(cpu_T[0], cpu_env,
3274 offsetof(CPUX86State,fpregs[reg].mmx.MMX_L(0)));
4ba9938c 3275 gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 1);
dabd98dd 3276 }
664e0f19
FB
3277 break;
3278 case 0x17e: /* movd ea, xmm */
dabd98dd 3279#ifdef TARGET_X86_64
ab4e4aec 3280 if (s->dflag == MO_64) {
5af45186
FB
3281 tcg_gen_ld_i64(cpu_T[0], cpu_env,
3282 offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
4ba9938c 3283 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 1);
5fafdf24 3284 } else
dabd98dd
FB
3285#endif
3286 {
5af45186
FB
3287 tcg_gen_ld32u_tl(cpu_T[0], cpu_env,
3288 offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
4ba9938c 3289 gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 1);
dabd98dd 3290 }
664e0f19
FB
3291 break;
3292 case 0x27e: /* movq xmm, ea */
3293 if (mod != 3) {
4eeb3939 3294 gen_lea_modrm(env, s, modrm);
323d1876
RH
3295 gen_ldq_env_A0(s, offsetof(CPUX86State,
3296 xmm_regs[reg].XMM_Q(0)));
664e0f19
FB
3297 } else {
3298 rm = (modrm & 7) | REX_B(s);
3299 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
3300 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
3301 }
3302 gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));
3303 break;
3304 case 0x7f: /* movq ea, mm */
3305 if (mod != 3) {
4eeb3939 3306 gen_lea_modrm(env, s, modrm);
323d1876 3307 gen_stq_env_A0(s, offsetof(CPUX86State, fpregs[reg].mmx));
664e0f19
FB
3308 } else {
3309 rm = (modrm & 7);
3310 gen_op_movq(offsetof(CPUX86State,fpregs[rm].mmx),
3311 offsetof(CPUX86State,fpregs[reg].mmx));
3312 }
3313 break;
3314 case 0x011: /* movups */
3315 case 0x111: /* movupd */
3316 case 0x029: /* movaps */
3317 case 0x129: /* movapd */
3318 case 0x17f: /* movdqa ea, xmm */
3319 case 0x27f: /* movdqu ea, xmm */
3320 if (mod != 3) {
4eeb3939 3321 gen_lea_modrm(env, s, modrm);
323d1876 3322 gen_sto_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
664e0f19
FB
3323 } else {
3324 rm = (modrm & 7) | REX_B(s);
3325 gen_op_movo(offsetof(CPUX86State,xmm_regs[rm]),
3326 offsetof(CPUX86State,xmm_regs[reg]));
3327 }
3328 break;
3329 case 0x211: /* movss ea, xmm */
3330 if (mod != 3) {
4eeb3939 3331 gen_lea_modrm(env, s, modrm);
651ba608 3332 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
fd8ca9f6 3333 gen_op_st_v(s, MO_32, cpu_T[0], cpu_A0);
664e0f19
FB
3334 } else {
3335 rm = (modrm & 7) | REX_B(s);
3336 gen_op_movl(offsetof(CPUX86State,xmm_regs[rm].XMM_L(0)),
3337 offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
3338 }
3339 break;
3340 case 0x311: /* movsd ea, xmm */
3341 if (mod != 3) {
4eeb3939 3342 gen_lea_modrm(env, s, modrm);
323d1876
RH
3343 gen_stq_env_A0(s, offsetof(CPUX86State,
3344 xmm_regs[reg].XMM_Q(0)));
664e0f19
FB
3345 } else {
3346 rm = (modrm & 7) | REX_B(s);
3347 gen_op_movq(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)),
3348 offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
3349 }
3350 break;
3351 case 0x013: /* movlps */
3352 case 0x113: /* movlpd */
3353 if (mod != 3) {
4eeb3939 3354 gen_lea_modrm(env, s, modrm);
323d1876
RH
3355 gen_stq_env_A0(s, offsetof(CPUX86State,
3356 xmm_regs[reg].XMM_Q(0)));
664e0f19
FB
3357 } else {
3358 goto illegal_op;
3359 }
3360 break;
3361 case 0x017: /* movhps */
3362 case 0x117: /* movhpd */
3363 if (mod != 3) {
4eeb3939 3364 gen_lea_modrm(env, s, modrm);
323d1876
RH
3365 gen_stq_env_A0(s, offsetof(CPUX86State,
3366 xmm_regs[reg].XMM_Q(1)));
664e0f19
FB
3367 } else {
3368 goto illegal_op;
3369 }
3370 break;
3371 case 0x71: /* shift mm, im */
3372 case 0x72:
3373 case 0x73:
3374 case 0x171: /* shift xmm, im */
3375 case 0x172:
3376 case 0x173:
c045af25
AK
3377 if (b1 >= 2) {
3378 goto illegal_op;
3379 }
0af10c86 3380 val = cpu_ldub_code(env, s->pc++);
664e0f19 3381 if (is_xmm) {
1b90d56e 3382 tcg_gen_movi_tl(cpu_T[0], val);
651ba608 3383 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_t0.XMM_L(0)));
97212c88 3384 tcg_gen_movi_tl(cpu_T[0], 0);
651ba608 3385 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_t0.XMM_L(1)));
664e0f19
FB
3386 op1_offset = offsetof(CPUX86State,xmm_t0);
3387 } else {
1b90d56e 3388 tcg_gen_movi_tl(cpu_T[0], val);
651ba608 3389 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,mmx_t0.MMX_L(0)));
97212c88 3390 tcg_gen_movi_tl(cpu_T[0], 0);
651ba608 3391 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,mmx_t0.MMX_L(1)));
664e0f19
FB
3392 op1_offset = offsetof(CPUX86State,mmx_t0);
3393 }
d3eb5eae
BS
3394 sse_fn_epp = sse_op_table2[((b - 1) & 3) * 8 +
3395 (((modrm >> 3)) & 7)][b1];
3396 if (!sse_fn_epp) {
664e0f19 3397 goto illegal_op;
c4baa050 3398 }
664e0f19
FB
3399 if (is_xmm) {
3400 rm = (modrm & 7) | REX_B(s);
3401 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3402 } else {
3403 rm = (modrm & 7);
3404 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3405 }
5af45186
FB
3406 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op2_offset);
3407 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op1_offset);
d3eb5eae 3408 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
664e0f19
FB
3409 break;
3410 case 0x050: /* movmskps */
664e0f19 3411 rm = (modrm & 7) | REX_B(s);
5af45186
FB
3412 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3413 offsetof(CPUX86State,xmm_regs[rm]));
d3eb5eae 3414 gen_helper_movmskps(cpu_tmp2_i32, cpu_env, cpu_ptr0);
a7fbcbe5 3415 tcg_gen_extu_i32_tl(cpu_regs[reg], cpu_tmp2_i32);
664e0f19
FB
3416 break;
3417 case 0x150: /* movmskpd */
664e0f19 3418 rm = (modrm & 7) | REX_B(s);
5af45186
FB
3419 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3420 offsetof(CPUX86State,xmm_regs[rm]));
d3eb5eae 3421 gen_helper_movmskpd(cpu_tmp2_i32, cpu_env, cpu_ptr0);
a7fbcbe5 3422 tcg_gen_extu_i32_tl(cpu_regs[reg], cpu_tmp2_i32);
664e0f19
FB
3423 break;
3424 case 0x02a: /* cvtpi2ps */
3425 case 0x12a: /* cvtpi2pd */
d3eb5eae 3426 gen_helper_enter_mmx(cpu_env);
664e0f19 3427 if (mod != 3) {
4eeb3939 3428 gen_lea_modrm(env, s, modrm);
664e0f19 3429 op2_offset = offsetof(CPUX86State,mmx_t0);
323d1876 3430 gen_ldq_env_A0(s, op2_offset);
664e0f19
FB
3431 } else {
3432 rm = (modrm & 7);
3433 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3434 }
3435 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
5af45186
FB
3436 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
3437 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
664e0f19
FB
3438 switch(b >> 8) {
3439 case 0x0:
d3eb5eae 3440 gen_helper_cvtpi2ps(cpu_env, cpu_ptr0, cpu_ptr1);
664e0f19
FB
3441 break;
3442 default:
3443 case 0x1:
d3eb5eae 3444 gen_helper_cvtpi2pd(cpu_env, cpu_ptr0, cpu_ptr1);
664e0f19
FB
3445 break;
3446 }
3447 break;
3448 case 0x22a: /* cvtsi2ss */
3449 case 0x32a: /* cvtsi2sd */
ab4e4aec 3450 ot = mo_64_32(s->dflag);
0af10c86 3451 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
664e0f19 3452 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
5af45186 3453 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4ba9938c 3454 if (ot == MO_32) {
d3eb5eae 3455 SSEFunc_0_epi sse_fn_epi = sse_op_table3ai[(b >> 8) & 1];
28e10711 3456 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
d3eb5eae 3457 sse_fn_epi(cpu_env, cpu_ptr0, cpu_tmp2_i32);
28e10711 3458 } else {
11f8cdbc 3459#ifdef TARGET_X86_64
d3eb5eae
BS
3460 SSEFunc_0_epl sse_fn_epl = sse_op_table3aq[(b >> 8) & 1];
3461 sse_fn_epl(cpu_env, cpu_ptr0, cpu_T[0]);
11f8cdbc
SW
3462#else
3463 goto illegal_op;
3464#endif
28e10711 3465 }
664e0f19
FB
3466 break;
3467 case 0x02c: /* cvttps2pi */
3468 case 0x12c: /* cvttpd2pi */
3469 case 0x02d: /* cvtps2pi */
3470 case 0x12d: /* cvtpd2pi */
d3eb5eae 3471 gen_helper_enter_mmx(cpu_env);
664e0f19 3472 if (mod != 3) {
4eeb3939 3473 gen_lea_modrm(env, s, modrm);
664e0f19 3474 op2_offset = offsetof(CPUX86State,xmm_t0);
323d1876 3475 gen_ldo_env_A0(s, op2_offset);
664e0f19
FB
3476 } else {
3477 rm = (modrm & 7) | REX_B(s);
3478 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3479 }
3480 op1_offset = offsetof(CPUX86State,fpregs[reg & 7].mmx);
5af45186
FB
3481 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
3482 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
664e0f19
FB
3483 switch(b) {
3484 case 0x02c:
d3eb5eae 3485 gen_helper_cvttps2pi(cpu_env, cpu_ptr0, cpu_ptr1);
664e0f19
FB
3486 break;
3487 case 0x12c:
d3eb5eae 3488 gen_helper_cvttpd2pi(cpu_env, cpu_ptr0, cpu_ptr1);
664e0f19
FB
3489 break;
3490 case 0x02d:
d3eb5eae 3491 gen_helper_cvtps2pi(cpu_env, cpu_ptr0, cpu_ptr1);
664e0f19
FB
3492 break;
3493 case 0x12d:
d3eb5eae 3494 gen_helper_cvtpd2pi(cpu_env, cpu_ptr0, cpu_ptr1);
664e0f19
FB
3495 break;
3496 }
3497 break;
3498 case 0x22c: /* cvttss2si */
3499 case 0x32c: /* cvttsd2si */
3500 case 0x22d: /* cvtss2si */
3501 case 0x32d: /* cvtsd2si */
ab4e4aec 3502 ot = mo_64_32(s->dflag);
31313213 3503 if (mod != 3) {
4eeb3939 3504 gen_lea_modrm(env, s, modrm);
31313213 3505 if ((b >> 8) & 1) {
323d1876 3506 gen_ldq_env_A0(s, offsetof(CPUX86State, xmm_t0.XMM_Q(0)));
31313213 3507 } else {
909be183 3508 gen_op_ld_v(s, MO_32, cpu_T[0], cpu_A0);
651ba608 3509 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_t0.XMM_L(0)));
31313213
FB
3510 }
3511 op2_offset = offsetof(CPUX86State,xmm_t0);
3512 } else {
3513 rm = (modrm & 7) | REX_B(s);
3514 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3515 }
5af45186 3516 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op2_offset);
4ba9938c 3517 if (ot == MO_32) {
d3eb5eae 3518 SSEFunc_i_ep sse_fn_i_ep =
bedc2ac1 3519 sse_op_table3bi[((b >> 7) & 2) | (b & 1)];
d3eb5eae 3520 sse_fn_i_ep(cpu_tmp2_i32, cpu_env, cpu_ptr0);
b6abf97d 3521 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
5af45186 3522 } else {
11f8cdbc 3523#ifdef TARGET_X86_64
d3eb5eae 3524 SSEFunc_l_ep sse_fn_l_ep =
bedc2ac1 3525 sse_op_table3bq[((b >> 7) & 2) | (b & 1)];
d3eb5eae 3526 sse_fn_l_ep(cpu_T[0], cpu_env, cpu_ptr0);
11f8cdbc
SW
3527#else
3528 goto illegal_op;
3529#endif
5af45186 3530 }
480a762d 3531 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
664e0f19
FB
3532 break;
3533 case 0xc4: /* pinsrw */
5fafdf24 3534 case 0x1c4:
d1e42c5c 3535 s->rip_offset = 1;
4ba9938c 3536 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
0af10c86 3537 val = cpu_ldub_code(env, s->pc++);
664e0f19
FB
3538 if (b1) {
3539 val &= 7;
5af45186
FB
3540 tcg_gen_st16_tl(cpu_T[0], cpu_env,
3541 offsetof(CPUX86State,xmm_regs[reg].XMM_W(val)));
664e0f19
FB
3542 } else {
3543 val &= 3;
5af45186
FB
3544 tcg_gen_st16_tl(cpu_T[0], cpu_env,
3545 offsetof(CPUX86State,fpregs[reg].mmx.MMX_W(val)));
664e0f19
FB
3546 }
3547 break;
3548 case 0xc5: /* pextrw */
5fafdf24 3549 case 0x1c5:
664e0f19
FB
3550 if (mod != 3)
3551 goto illegal_op;
ab4e4aec 3552 ot = mo_64_32(s->dflag);
0af10c86 3553 val = cpu_ldub_code(env, s->pc++);
664e0f19
FB
3554 if (b1) {
3555 val &= 7;
3556 rm = (modrm & 7) | REX_B(s);
5af45186
FB
3557 tcg_gen_ld16u_tl(cpu_T[0], cpu_env,
3558 offsetof(CPUX86State,xmm_regs[rm].XMM_W(val)));
664e0f19
FB
3559 } else {
3560 val &= 3;
3561 rm = (modrm & 7);
5af45186
FB
3562 tcg_gen_ld16u_tl(cpu_T[0], cpu_env,
3563 offsetof(CPUX86State,fpregs[rm].mmx.MMX_W(val)));
664e0f19
FB
3564 }
3565 reg = ((modrm >> 3) & 7) | rex_r;
480a762d 3566 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
664e0f19
FB
3567 break;
3568 case 0x1d6: /* movq ea, xmm */
3569 if (mod != 3) {
4eeb3939 3570 gen_lea_modrm(env, s, modrm);
323d1876
RH
3571 gen_stq_env_A0(s, offsetof(CPUX86State,
3572 xmm_regs[reg].XMM_Q(0)));
664e0f19
FB
3573 } else {
3574 rm = (modrm & 7) | REX_B(s);
3575 gen_op_movq(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)),
3576 offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
3577 gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(1)));
3578 }
3579 break;
3580 case 0x2d6: /* movq2dq */
d3eb5eae 3581 gen_helper_enter_mmx(cpu_env);
480c1cdb
FB
3582 rm = (modrm & 7);
3583 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
3584 offsetof(CPUX86State,fpregs[rm].mmx));
3585 gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));
664e0f19
FB
3586 break;
3587 case 0x3d6: /* movdq2q */
d3eb5eae 3588 gen_helper_enter_mmx(cpu_env);
480c1cdb
FB
3589 rm = (modrm & 7) | REX_B(s);
3590 gen_op_movq(offsetof(CPUX86State,fpregs[reg & 7].mmx),
3591 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
664e0f19
FB
3592 break;
3593 case 0xd7: /* pmovmskb */
3594 case 0x1d7:
3595 if (mod != 3)
3596 goto illegal_op;
3597 if (b1) {
3598 rm = (modrm & 7) | REX_B(s);
5af45186 3599 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, offsetof(CPUX86State,xmm_regs[rm]));
d3eb5eae 3600 gen_helper_pmovmskb_xmm(cpu_tmp2_i32, cpu_env, cpu_ptr0);
664e0f19
FB
3601 } else {
3602 rm = (modrm & 7);
5af45186 3603 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, offsetof(CPUX86State,fpregs[rm].mmx));
d3eb5eae 3604 gen_helper_pmovmskb_mmx(cpu_tmp2_i32, cpu_env, cpu_ptr0);
664e0f19
FB
3605 }
3606 reg = ((modrm >> 3) & 7) | rex_r;
a7fbcbe5 3607 tcg_gen_extu_i32_tl(cpu_regs[reg], cpu_tmp2_i32);
664e0f19 3608 break;
111994ee 3609
4242b1bd 3610 case 0x138:
000cacf6 3611 case 0x038:
4242b1bd 3612 b = modrm;
111994ee
RH
3613 if ((b & 0xf0) == 0xf0) {
3614 goto do_0f_38_fx;
3615 }
0af10c86 3616 modrm = cpu_ldub_code(env, s->pc++);
4242b1bd
AZ
3617 rm = modrm & 7;
3618 reg = ((modrm >> 3) & 7) | rex_r;
3619 mod = (modrm >> 6) & 3;
c045af25
AK
3620 if (b1 >= 2) {
3621 goto illegal_op;
3622 }
4242b1bd 3623
d3eb5eae
BS
3624 sse_fn_epp = sse_op_table6[b].op[b1];
3625 if (!sse_fn_epp) {
4242b1bd 3626 goto illegal_op;
c4baa050 3627 }
222a3336
AZ
3628 if (!(s->cpuid_ext_features & sse_op_table6[b].ext_mask))
3629 goto illegal_op;
4242b1bd
AZ
3630
3631 if (b1) {
3632 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3633 if (mod == 3) {
3634 op2_offset = offsetof(CPUX86State,xmm_regs[rm | REX_B(s)]);
3635 } else {
3636 op2_offset = offsetof(CPUX86State,xmm_t0);
4eeb3939 3637 gen_lea_modrm(env, s, modrm);
222a3336
AZ
3638 switch (b) {
3639 case 0x20: case 0x30: /* pmovsxbw, pmovzxbw */
3640 case 0x23: case 0x33: /* pmovsxwd, pmovzxwd */
3641 case 0x25: case 0x35: /* pmovsxdq, pmovzxdq */
323d1876 3642 gen_ldq_env_A0(s, op2_offset +
222a3336
AZ
3643 offsetof(XMMReg, XMM_Q(0)));
3644 break;
3645 case 0x21: case 0x31: /* pmovsxbd, pmovzxbd */
3646 case 0x24: case 0x34: /* pmovsxwq, pmovzxwq */
3c5f4116
RH
3647 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
3648 s->mem_index, MO_LEUL);
222a3336
AZ
3649 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, op2_offset +
3650 offsetof(XMMReg, XMM_L(0)));
3651 break;
3652 case 0x22: case 0x32: /* pmovsxbq, pmovzxbq */
3c5f4116
RH
3653 tcg_gen_qemu_ld_tl(cpu_tmp0, cpu_A0,
3654 s->mem_index, MO_LEUW);
222a3336
AZ
3655 tcg_gen_st16_tl(cpu_tmp0, cpu_env, op2_offset +
3656 offsetof(XMMReg, XMM_W(0)));
3657 break;
3658 case 0x2a: /* movntqda */
323d1876 3659 gen_ldo_env_A0(s, op1_offset);
222a3336
AZ
3660 return;
3661 default:
323d1876 3662 gen_ldo_env_A0(s, op2_offset);
222a3336 3663 }
4242b1bd
AZ
3664 }
3665 } else {
3666 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
3667 if (mod == 3) {
3668 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3669 } else {
3670 op2_offset = offsetof(CPUX86State,mmx_t0);
4eeb3939 3671 gen_lea_modrm(env, s, modrm);
323d1876 3672 gen_ldq_env_A0(s, op2_offset);
4242b1bd
AZ
3673 }
3674 }
d3eb5eae 3675 if (sse_fn_epp == SSE_SPECIAL) {
222a3336 3676 goto illegal_op;
c4baa050 3677 }
222a3336 3678
4242b1bd
AZ
3679 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
3680 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
d3eb5eae 3681 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
222a3336 3682
3ca51d07
RH
3683 if (b == 0x17) {
3684 set_cc_op(s, CC_OP_EFLAGS);
3685 }
4242b1bd 3686 break;
111994ee
RH
3687
3688 case 0x238:
3689 case 0x338:
3690 do_0f_38_fx:
3691 /* Various integer extensions at 0f 38 f[0-f]. */
3692 b = modrm | (b1 << 8);
0af10c86 3693 modrm = cpu_ldub_code(env, s->pc++);
222a3336
AZ
3694 reg = ((modrm >> 3) & 7) | rex_r;
3695
111994ee
RH
3696 switch (b) {
3697 case 0x3f0: /* crc32 Gd,Eb */
3698 case 0x3f1: /* crc32 Gd,Ey */
3699 do_crc32:
3700 if (!(s->cpuid_ext_features & CPUID_EXT_SSE42)) {
3701 goto illegal_op;
3702 }
3703 if ((b & 0xff) == 0xf0) {
4ba9938c 3704 ot = MO_8;
ab4e4aec 3705 } else if (s->dflag != MO_64) {
4ba9938c 3706 ot = (s->prefix & PREFIX_DATA ? MO_16 : MO_32);
111994ee 3707 } else {
4ba9938c 3708 ot = MO_64;
111994ee 3709 }
4242b1bd 3710
24b9c00f 3711 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[reg]);
111994ee
RH
3712 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3713 gen_helper_crc32(cpu_T[0], cpu_tmp2_i32,
3714 cpu_T[0], tcg_const_i32(8 << ot));
222a3336 3715
ab4e4aec 3716 ot = mo_64_32(s->dflag);
480a762d 3717 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
111994ee 3718 break;
222a3336 3719
111994ee
RH
3720 case 0x1f0: /* crc32 or movbe */
3721 case 0x1f1:
3722 /* For these insns, the f3 prefix is supposed to have priority
3723 over the 66 prefix, but that's not what we implement above
3724 setting b1. */
3725 if (s->prefix & PREFIX_REPNZ) {
3726 goto do_crc32;
3727 }
3728 /* FALLTHRU */
3729 case 0x0f0: /* movbe Gy,My */
3730 case 0x0f1: /* movbe My,Gy */
3731 if (!(s->cpuid_ext_features & CPUID_EXT_MOVBE)) {
3732 goto illegal_op;
3733 }
ab4e4aec 3734 if (s->dflag != MO_64) {
4ba9938c 3735 ot = (s->prefix & PREFIX_DATA ? MO_16 : MO_32);
111994ee 3736 } else {
4ba9938c 3737 ot = MO_64;
111994ee
RH
3738 }
3739
3655a19f 3740 gen_lea_modrm(env, s, modrm);
111994ee 3741 if ((b & 1) == 0) {
3655a19f
RH
3742 tcg_gen_qemu_ld_tl(cpu_T[0], cpu_A0,
3743 s->mem_index, ot | MO_BE);
480a762d 3744 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
111994ee 3745 } else {
3655a19f
RH
3746 tcg_gen_qemu_st_tl(cpu_regs[reg], cpu_A0,
3747 s->mem_index, ot | MO_BE);
111994ee
RH
3748 }
3749 break;
3750
7073fbad
RH
3751 case 0x0f2: /* andn Gy, By, Ey */
3752 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)
3753 || !(s->prefix & PREFIX_VEX)
3754 || s->vex_l != 0) {
3755 goto illegal_op;
3756 }
ab4e4aec 3757 ot = mo_64_32(s->dflag);
7073fbad
RH
3758 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3759 tcg_gen_andc_tl(cpu_T[0], cpu_regs[s->vex_v], cpu_T[0]);
480a762d 3760 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
7073fbad
RH
3761 gen_op_update1_cc();
3762 set_cc_op(s, CC_OP_LOGICB + ot);
3763 break;
3764
c7ab7565
RH
3765 case 0x0f7: /* bextr Gy, Ey, By */
3766 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)
3767 || !(s->prefix & PREFIX_VEX)
3768 || s->vex_l != 0) {
3769 goto illegal_op;
3770 }
ab4e4aec 3771 ot = mo_64_32(s->dflag);
c7ab7565
RH
3772 {
3773 TCGv bound, zero;
3774
3775 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3776 /* Extract START, and shift the operand.
3777 Shifts larger than operand size get zeros. */
3778 tcg_gen_ext8u_tl(cpu_A0, cpu_regs[s->vex_v]);
3779 tcg_gen_shr_tl(cpu_T[0], cpu_T[0], cpu_A0);
3780
4ba9938c 3781 bound = tcg_const_tl(ot == MO_64 ? 63 : 31);
c7ab7565
RH
3782 zero = tcg_const_tl(0);
3783 tcg_gen_movcond_tl(TCG_COND_LEU, cpu_T[0], cpu_A0, bound,
3784 cpu_T[0], zero);
3785 tcg_temp_free(zero);
3786
3787 /* Extract the LEN into a mask. Lengths larger than
3788 operand size get all ones. */
3789 tcg_gen_shri_tl(cpu_A0, cpu_regs[s->vex_v], 8);
3790 tcg_gen_ext8u_tl(cpu_A0, cpu_A0);
3791 tcg_gen_movcond_tl(TCG_COND_LEU, cpu_A0, cpu_A0, bound,
3792 cpu_A0, bound);
3793 tcg_temp_free(bound);
3794 tcg_gen_movi_tl(cpu_T[1], 1);
3795 tcg_gen_shl_tl(cpu_T[1], cpu_T[1], cpu_A0);
3796 tcg_gen_subi_tl(cpu_T[1], cpu_T[1], 1);
3797 tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
3798
480a762d 3799 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
c7ab7565
RH
3800 gen_op_update1_cc();
3801 set_cc_op(s, CC_OP_LOGICB + ot);
3802 }
3803 break;
3804
02ea1e6b
RH
3805 case 0x0f5: /* bzhi Gy, Ey, By */
3806 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
3807 || !(s->prefix & PREFIX_VEX)
3808 || s->vex_l != 0) {
3809 goto illegal_op;
3810 }
ab4e4aec 3811 ot = mo_64_32(s->dflag);
02ea1e6b
RH
3812 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3813 tcg_gen_ext8u_tl(cpu_T[1], cpu_regs[s->vex_v]);
3814 {
4ba9938c 3815 TCGv bound = tcg_const_tl(ot == MO_64 ? 63 : 31);
02ea1e6b
RH
3816 /* Note that since we're using BMILG (in order to get O
3817 cleared) we need to store the inverse into C. */
3818 tcg_gen_setcond_tl(TCG_COND_LT, cpu_cc_src,
3819 cpu_T[1], bound);
3820 tcg_gen_movcond_tl(TCG_COND_GT, cpu_T[1], cpu_T[1],
3821 bound, bound, cpu_T[1]);
3822 tcg_temp_free(bound);
3823 }
3824 tcg_gen_movi_tl(cpu_A0, -1);
3825 tcg_gen_shl_tl(cpu_A0, cpu_A0, cpu_T[1]);
3826 tcg_gen_andc_tl(cpu_T[0], cpu_T[0], cpu_A0);
480a762d 3827 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
02ea1e6b
RH
3828 gen_op_update1_cc();
3829 set_cc_op(s, CC_OP_BMILGB + ot);
3830 break;
3831
5f1f4b17
RH
3832 case 0x3f6: /* mulx By, Gy, rdx, Ey */
3833 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
3834 || !(s->prefix & PREFIX_VEX)
3835 || s->vex_l != 0) {
3836 goto illegal_op;
3837 }
ab4e4aec 3838 ot = mo_64_32(s->dflag);
5f1f4b17
RH
3839 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3840 switch (ot) {
5f1f4b17 3841 default:
a4bcea3d
RH
3842 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
3843 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_regs[R_EDX]);
3844 tcg_gen_mulu2_i32(cpu_tmp2_i32, cpu_tmp3_i32,
3845 cpu_tmp2_i32, cpu_tmp3_i32);
3846 tcg_gen_extu_i32_tl(cpu_regs[s->vex_v], cpu_tmp2_i32);
3847 tcg_gen_extu_i32_tl(cpu_regs[reg], cpu_tmp3_i32);
5f1f4b17
RH
3848 break;
3849#ifdef TARGET_X86_64
4ba9938c 3850 case MO_64:
a4bcea3d
RH
3851 tcg_gen_mulu2_i64(cpu_regs[s->vex_v], cpu_regs[reg],
3852 cpu_T[0], cpu_regs[R_EDX]);
5f1f4b17
RH
3853 break;
3854#endif
3855 }
3856 break;
3857
0592f74a
RH
3858 case 0x3f5: /* pdep Gy, By, Ey */
3859 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
3860 || !(s->prefix & PREFIX_VEX)
3861 || s->vex_l != 0) {
3862 goto illegal_op;
3863 }
ab4e4aec 3864 ot = mo_64_32(s->dflag);
0592f74a
RH
3865 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3866 /* Note that by zero-extending the mask operand, we
3867 automatically handle zero-extending the result. */
ab4e4aec 3868 if (ot == MO_64) {
0592f74a
RH
3869 tcg_gen_mov_tl(cpu_T[1], cpu_regs[s->vex_v]);
3870 } else {
3871 tcg_gen_ext32u_tl(cpu_T[1], cpu_regs[s->vex_v]);
3872 }
3873 gen_helper_pdep(cpu_regs[reg], cpu_T[0], cpu_T[1]);
3874 break;
3875
3876 case 0x2f5: /* pext Gy, By, Ey */
3877 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
3878 || !(s->prefix & PREFIX_VEX)
3879 || s->vex_l != 0) {
3880 goto illegal_op;
3881 }
ab4e4aec 3882 ot = mo_64_32(s->dflag);
0592f74a
RH
3883 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3884 /* Note that by zero-extending the mask operand, we
3885 automatically handle zero-extending the result. */
ab4e4aec 3886 if (ot == MO_64) {
0592f74a
RH
3887 tcg_gen_mov_tl(cpu_T[1], cpu_regs[s->vex_v]);
3888 } else {
3889 tcg_gen_ext32u_tl(cpu_T[1], cpu_regs[s->vex_v]);
3890 }
3891 gen_helper_pext(cpu_regs[reg], cpu_T[0], cpu_T[1]);
3892 break;
3893
cd7f97ca
RH
3894 case 0x1f6: /* adcx Gy, Ey */
3895 case 0x2f6: /* adox Gy, Ey */
3896 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_ADX)) {
3897 goto illegal_op;
3898 } else {
76f13133 3899 TCGv carry_in, carry_out, zero;
cd7f97ca
RH
3900 int end_op;
3901
ab4e4aec 3902 ot = mo_64_32(s->dflag);
cd7f97ca
RH
3903 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3904
3905 /* Re-use the carry-out from a previous round. */
3906 TCGV_UNUSED(carry_in);
3907 carry_out = (b == 0x1f6 ? cpu_cc_dst : cpu_cc_src2);
3908 switch (s->cc_op) {
3909 case CC_OP_ADCX:
3910 if (b == 0x1f6) {
3911 carry_in = cpu_cc_dst;
3912 end_op = CC_OP_ADCX;
3913 } else {
3914 end_op = CC_OP_ADCOX;
3915 }
3916 break;
3917 case CC_OP_ADOX:
3918 if (b == 0x1f6) {
3919 end_op = CC_OP_ADCOX;
3920 } else {
3921 carry_in = cpu_cc_src2;
3922 end_op = CC_OP_ADOX;
3923 }
3924 break;
3925 case CC_OP_ADCOX:
3926 end_op = CC_OP_ADCOX;
3927 carry_in = carry_out;
3928 break;
3929 default:
c53de1a2 3930 end_op = (b == 0x1f6 ? CC_OP_ADCX : CC_OP_ADOX);
cd7f97ca
RH
3931 break;
3932 }
3933 /* If we can't reuse carry-out, get it out of EFLAGS. */
3934 if (TCGV_IS_UNUSED(carry_in)) {
3935 if (s->cc_op != CC_OP_ADCX && s->cc_op != CC_OP_ADOX) {
3936 gen_compute_eflags(s);
3937 }
3938 carry_in = cpu_tmp0;
3939 tcg_gen_shri_tl(carry_in, cpu_cc_src,
3940 ctz32(b == 0x1f6 ? CC_C : CC_O));
3941 tcg_gen_andi_tl(carry_in, carry_in, 1);
3942 }
3943
3944 switch (ot) {
3945#ifdef TARGET_X86_64
4ba9938c 3946 case MO_32:
cd7f97ca
RH
3947 /* If we know TL is 64-bit, and we want a 32-bit
3948 result, just do everything in 64-bit arithmetic. */
3949 tcg_gen_ext32u_i64(cpu_regs[reg], cpu_regs[reg]);
3950 tcg_gen_ext32u_i64(cpu_T[0], cpu_T[0]);
3951 tcg_gen_add_i64(cpu_T[0], cpu_T[0], cpu_regs[reg]);
3952 tcg_gen_add_i64(cpu_T[0], cpu_T[0], carry_in);
3953 tcg_gen_ext32u_i64(cpu_regs[reg], cpu_T[0]);
3954 tcg_gen_shri_i64(carry_out, cpu_T[0], 32);
3955 break;
3956#endif
3957 default:
3958 /* Otherwise compute the carry-out in two steps. */
76f13133
RH
3959 zero = tcg_const_tl(0);
3960 tcg_gen_add2_tl(cpu_T[0], carry_out,
3961 cpu_T[0], zero,
3962 carry_in, zero);
3963 tcg_gen_add2_tl(cpu_regs[reg], carry_out,
3964 cpu_regs[reg], carry_out,
3965 cpu_T[0], zero);
3966 tcg_temp_free(zero);
cd7f97ca
RH
3967 break;
3968 }
cd7f97ca
RH
3969 set_cc_op(s, end_op);
3970 }
3971 break;
3972
4a554890
RH
3973 case 0x1f7: /* shlx Gy, Ey, By */
3974 case 0x2f7: /* sarx Gy, Ey, By */
3975 case 0x3f7: /* shrx Gy, Ey, By */
3976 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
3977 || !(s->prefix & PREFIX_VEX)
3978 || s->vex_l != 0) {
3979 goto illegal_op;
3980 }
ab4e4aec 3981 ot = mo_64_32(s->dflag);
4a554890 3982 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4ba9938c 3983 if (ot == MO_64) {
4a554890
RH
3984 tcg_gen_andi_tl(cpu_T[1], cpu_regs[s->vex_v], 63);
3985 } else {
3986 tcg_gen_andi_tl(cpu_T[1], cpu_regs[s->vex_v], 31);
3987 }
3988 if (b == 0x1f7) {
3989 tcg_gen_shl_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
3990 } else if (b == 0x2f7) {
4ba9938c 3991 if (ot != MO_64) {
4a554890
RH
3992 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
3993 }
3994 tcg_gen_sar_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
3995 } else {
4ba9938c 3996 if (ot != MO_64) {
4a554890
RH
3997 tcg_gen_ext32u_tl(cpu_T[0], cpu_T[0]);
3998 }
3999 tcg_gen_shr_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
4000 }
480a762d 4001 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
4a554890
RH
4002 break;
4003
bc4b43dc
RH
4004 case 0x0f3:
4005 case 0x1f3:
4006 case 0x2f3:
4007 case 0x3f3: /* Group 17 */
4008 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)
4009 || !(s->prefix & PREFIX_VEX)
4010 || s->vex_l != 0) {
4011 goto illegal_op;
4012 }
ab4e4aec 4013 ot = mo_64_32(s->dflag);
bc4b43dc
RH
4014 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4015
4016 switch (reg & 7) {
4017 case 1: /* blsr By,Ey */
4018 tcg_gen_neg_tl(cpu_T[1], cpu_T[0]);
4019 tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
480a762d 4020 gen_op_mov_reg_v(ot, s->vex_v, cpu_T[0]);
bc4b43dc
RH
4021 gen_op_update2_cc();
4022 set_cc_op(s, CC_OP_BMILGB + ot);
4023 break;
4024
4025 case 2: /* blsmsk By,Ey */
4026 tcg_gen_mov_tl(cpu_cc_src, cpu_T[0]);
4027 tcg_gen_subi_tl(cpu_T[0], cpu_T[0], 1);
4028 tcg_gen_xor_tl(cpu_T[0], cpu_T[0], cpu_cc_src);
4029 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4030 set_cc_op(s, CC_OP_BMILGB + ot);
4031 break;
4032
4033 case 3: /* blsi By, Ey */
4034 tcg_gen_mov_tl(cpu_cc_src, cpu_T[0]);
4035 tcg_gen_subi_tl(cpu_T[0], cpu_T[0], 1);
4036 tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_cc_src);
4037 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4038 set_cc_op(s, CC_OP_BMILGB + ot);
4039 break;
4040
4041 default:
4042 goto illegal_op;
4043 }
4044 break;
4045
111994ee
RH
4046 default:
4047 goto illegal_op;
4048 }
222a3336 4049 break;
111994ee 4050
222a3336
AZ
4051 case 0x03a:
4052 case 0x13a:
4242b1bd 4053 b = modrm;
0af10c86 4054 modrm = cpu_ldub_code(env, s->pc++);
4242b1bd
AZ
4055 rm = modrm & 7;
4056 reg = ((modrm >> 3) & 7) | rex_r;
4057 mod = (modrm >> 6) & 3;
c045af25
AK
4058 if (b1 >= 2) {
4059 goto illegal_op;
4060 }
4242b1bd 4061
d3eb5eae
BS
4062 sse_fn_eppi = sse_op_table7[b].op[b1];
4063 if (!sse_fn_eppi) {
4242b1bd 4064 goto illegal_op;
c4baa050 4065 }
222a3336
AZ
4066 if (!(s->cpuid_ext_features & sse_op_table7[b].ext_mask))
4067 goto illegal_op;
4068
d3eb5eae 4069 if (sse_fn_eppi == SSE_SPECIAL) {
ab4e4aec 4070 ot = mo_64_32(s->dflag);
222a3336
AZ
4071 rm = (modrm & 7) | REX_B(s);
4072 if (mod != 3)
4eeb3939 4073 gen_lea_modrm(env, s, modrm);
222a3336 4074 reg = ((modrm >> 3) & 7) | rex_r;
0af10c86 4075 val = cpu_ldub_code(env, s->pc++);
222a3336
AZ
4076 switch (b) {
4077 case 0x14: /* pextrb */
4078 tcg_gen_ld8u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,
4079 xmm_regs[reg].XMM_B(val & 15)));
3523e4bd 4080 if (mod == 3) {
480a762d 4081 gen_op_mov_reg_v(ot, rm, cpu_T[0]);
3523e4bd
RH
4082 } else {
4083 tcg_gen_qemu_st_tl(cpu_T[0], cpu_A0,
4084 s->mem_index, MO_UB);
4085 }
222a3336
AZ
4086 break;
4087 case 0x15: /* pextrw */
4088 tcg_gen_ld16u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,
4089 xmm_regs[reg].XMM_W(val & 7)));
3523e4bd 4090 if (mod == 3) {
480a762d 4091 gen_op_mov_reg_v(ot, rm, cpu_T[0]);
3523e4bd
RH
4092 } else {
4093 tcg_gen_qemu_st_tl(cpu_T[0], cpu_A0,
4094 s->mem_index, MO_LEUW);
4095 }
222a3336
AZ
4096 break;
4097 case 0x16:
4ba9938c 4098 if (ot == MO_32) { /* pextrd */
222a3336
AZ
4099 tcg_gen_ld_i32(cpu_tmp2_i32, cpu_env,
4100 offsetof(CPUX86State,
4101 xmm_regs[reg].XMM_L(val & 3)));
3523e4bd 4102 if (mod == 3) {
a7fbcbe5 4103 tcg_gen_extu_i32_tl(cpu_regs[rm], cpu_tmp2_i32);
3523e4bd 4104 } else {
d5601ad0
RH
4105 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
4106 s->mem_index, MO_LEUL);
3523e4bd 4107 }
222a3336 4108 } else { /* pextrq */
a7812ae4 4109#ifdef TARGET_X86_64
222a3336
AZ
4110 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env,
4111 offsetof(CPUX86State,
4112 xmm_regs[reg].XMM_Q(val & 1)));
3523e4bd 4113 if (mod == 3) {
a7fbcbe5 4114 tcg_gen_mov_i64(cpu_regs[rm], cpu_tmp1_i64);
3523e4bd
RH
4115 } else {
4116 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0,
4117 s->mem_index, MO_LEQ);
4118 }
a7812ae4
PB
4119#else
4120 goto illegal_op;
4121#endif
222a3336
AZ
4122 }
4123 break;
4124 case 0x17: /* extractps */
4125 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,
4126 xmm_regs[reg].XMM_L(val & 3)));
3523e4bd 4127 if (mod == 3) {
480a762d 4128 gen_op_mov_reg_v(ot, rm, cpu_T[0]);
3523e4bd
RH
4129 } else {
4130 tcg_gen_qemu_st_tl(cpu_T[0], cpu_A0,
4131 s->mem_index, MO_LEUL);
4132 }
222a3336
AZ
4133 break;
4134 case 0x20: /* pinsrb */
3c5f4116 4135 if (mod == 3) {
c56baccf 4136 gen_op_mov_v_reg(MO_32, cpu_T[0], rm);
3c5f4116
RH
4137 } else {
4138 tcg_gen_qemu_ld_tl(cpu_T[0], cpu_A0,
4139 s->mem_index, MO_UB);
4140 }
34c6addd 4141 tcg_gen_st8_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,
222a3336
AZ
4142 xmm_regs[reg].XMM_B(val & 15)));
4143 break;
4144 case 0x21: /* insertps */
a7812ae4 4145 if (mod == 3) {
222a3336
AZ
4146 tcg_gen_ld_i32(cpu_tmp2_i32, cpu_env,
4147 offsetof(CPUX86State,xmm_regs[rm]
4148 .XMM_L((val >> 6) & 3)));
a7812ae4 4149 } else {
3c5f4116
RH
4150 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
4151 s->mem_index, MO_LEUL);
a7812ae4 4152 }
222a3336
AZ
4153 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env,
4154 offsetof(CPUX86State,xmm_regs[reg]
4155 .XMM_L((val >> 4) & 3)));
4156 if ((val >> 0) & 1)
4157 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4158 cpu_env, offsetof(CPUX86State,
4159 xmm_regs[reg].XMM_L(0)));
4160 if ((val >> 1) & 1)
4161 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4162 cpu_env, offsetof(CPUX86State,
4163 xmm_regs[reg].XMM_L(1)));
4164 if ((val >> 2) & 1)
4165 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4166 cpu_env, offsetof(CPUX86State,
4167 xmm_regs[reg].XMM_L(2)));
4168 if ((val >> 3) & 1)
4169 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4170 cpu_env, offsetof(CPUX86State,
4171 xmm_regs[reg].XMM_L(3)));
4172 break;
4173 case 0x22:
4ba9938c 4174 if (ot == MO_32) { /* pinsrd */
3c5f4116 4175 if (mod == 3) {
80b02013 4176 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[rm]);
3c5f4116 4177 } else {
80b02013
RH
4178 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
4179 s->mem_index, MO_LEUL);
3c5f4116 4180 }
222a3336
AZ
4181 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env,
4182 offsetof(CPUX86State,
4183 xmm_regs[reg].XMM_L(val & 3)));
4184 } else { /* pinsrq */
a7812ae4 4185#ifdef TARGET_X86_64
3c5f4116 4186 if (mod == 3) {
222a3336 4187 gen_op_mov_v_reg(ot, cpu_tmp1_i64, rm);
3c5f4116
RH
4188 } else {
4189 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_A0,
4190 s->mem_index, MO_LEQ);
4191 }
222a3336
AZ
4192 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env,
4193 offsetof(CPUX86State,
4194 xmm_regs[reg].XMM_Q(val & 1)));
a7812ae4
PB
4195#else
4196 goto illegal_op;
4197#endif
222a3336
AZ
4198 }
4199 break;
4200 }
4201 return;
4202 }
4242b1bd
AZ
4203
4204 if (b1) {
4205 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
4206 if (mod == 3) {
4207 op2_offset = offsetof(CPUX86State,xmm_regs[rm | REX_B(s)]);
4208 } else {
4209 op2_offset = offsetof(CPUX86State,xmm_t0);
4eeb3939 4210 gen_lea_modrm(env, s, modrm);
323d1876 4211 gen_ldo_env_A0(s, op2_offset);
4242b1bd
AZ
4212 }
4213 } else {
4214 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
4215 if (mod == 3) {
4216 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
4217 } else {
4218 op2_offset = offsetof(CPUX86State,mmx_t0);
4eeb3939 4219 gen_lea_modrm(env, s, modrm);
323d1876 4220 gen_ldq_env_A0(s, op2_offset);
4242b1bd
AZ
4221 }
4222 }
0af10c86 4223 val = cpu_ldub_code(env, s->pc++);
4242b1bd 4224
222a3336 4225 if ((b & 0xfc) == 0x60) { /* pcmpXstrX */
3ca51d07 4226 set_cc_op(s, CC_OP_EFLAGS);
222a3336 4227
ab4e4aec 4228 if (s->dflag == MO_64) {
222a3336
AZ
4229 /* The helper must use entire 64-bit gp registers */
4230 val |= 1 << 8;
ab4e4aec 4231 }
222a3336
AZ
4232 }
4233
4242b1bd
AZ
4234 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4235 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
d3eb5eae 4236 sse_fn_eppi(cpu_env, cpu_ptr0, cpu_ptr1, tcg_const_i32(val));
4242b1bd 4237 break;
e2c3c2c5
RH
4238
4239 case 0x33a:
4240 /* Various integer extensions at 0f 3a f[0-f]. */
4241 b = modrm | (b1 << 8);
4242 modrm = cpu_ldub_code(env, s->pc++);
4243 reg = ((modrm >> 3) & 7) | rex_r;
4244
4245 switch (b) {
4246 case 0x3f0: /* rorx Gy,Ey, Ib */
4247 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
4248 || !(s->prefix & PREFIX_VEX)
4249 || s->vex_l != 0) {
4250 goto illegal_op;
4251 }
ab4e4aec 4252 ot = mo_64_32(s->dflag);
e2c3c2c5
RH
4253 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4254 b = cpu_ldub_code(env, s->pc++);
4ba9938c 4255 if (ot == MO_64) {
e2c3c2c5
RH
4256 tcg_gen_rotri_tl(cpu_T[0], cpu_T[0], b & 63);
4257 } else {
4258 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
4259 tcg_gen_rotri_i32(cpu_tmp2_i32, cpu_tmp2_i32, b & 31);
4260 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
4261 }
480a762d 4262 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
e2c3c2c5
RH
4263 break;
4264
4265 default:
4266 goto illegal_op;
4267 }
4268 break;
4269
664e0f19
FB
4270 default:
4271 goto illegal_op;
4272 }
4273 } else {
4274 /* generic MMX or SSE operation */
d1e42c5c 4275 switch(b) {
d1e42c5c
FB
4276 case 0x70: /* pshufx insn */
4277 case 0xc6: /* pshufx insn */
4278 case 0xc2: /* compare insns */
4279 s->rip_offset = 1;
4280 break;
4281 default:
4282 break;
664e0f19
FB
4283 }
4284 if (is_xmm) {
4285 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
4286 if (mod != 3) {
cb48da7f
RH
4287 int sz = 4;
4288
4eeb3939 4289 gen_lea_modrm(env, s, modrm);
664e0f19 4290 op2_offset = offsetof(CPUX86State,xmm_t0);
cb48da7f
RH
4291
4292 switch (b) {
4293 case 0x50 ... 0x5a:
4294 case 0x5c ... 0x5f:
4295 case 0xc2:
4296 /* Most sse scalar operations. */
664e0f19 4297 if (b1 == 2) {
cb48da7f
RH
4298 sz = 2;
4299 } else if (b1 == 3) {
4300 sz = 3;
4301 }
4302 break;
4303
4304 case 0x2e: /* ucomis[sd] */
4305 case 0x2f: /* comis[sd] */
4306 if (b1 == 0) {
4307 sz = 2;
664e0f19 4308 } else {
cb48da7f 4309 sz = 3;
664e0f19 4310 }
cb48da7f
RH
4311 break;
4312 }
4313
4314 switch (sz) {
4315 case 2:
4316 /* 32 bit access */
4317 gen_op_ld_v(s, MO_32, cpu_T[0], cpu_A0);
4318 tcg_gen_st32_tl(cpu_T[0], cpu_env,
4319 offsetof(CPUX86State,xmm_t0.XMM_L(0)));
4320 break;
4321 case 3:
4322 /* 64 bit access */
4323 gen_ldq_env_A0(s, offsetof(CPUX86State, xmm_t0.XMM_D(0)));
4324 break;
4325 default:
4326 /* 128 bit access */
323d1876 4327 gen_ldo_env_A0(s, op2_offset);
cb48da7f 4328 break;
664e0f19
FB
4329 }
4330 } else {
4331 rm = (modrm & 7) | REX_B(s);
4332 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
4333 }
4334 } else {
4335 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
4336 if (mod != 3) {
4eeb3939 4337 gen_lea_modrm(env, s, modrm);
664e0f19 4338 op2_offset = offsetof(CPUX86State,mmx_t0);
323d1876 4339 gen_ldq_env_A0(s, op2_offset);
664e0f19
FB
4340 } else {
4341 rm = (modrm & 7);
4342 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
4343 }
4344 }
4345 switch(b) {
a35f3ec7 4346 case 0x0f: /* 3DNow! data insns */
e771edab
AJ
4347 if (!(s->cpuid_ext2_features & CPUID_EXT2_3DNOW))
4348 goto illegal_op;
0af10c86 4349 val = cpu_ldub_code(env, s->pc++);
d3eb5eae
BS
4350 sse_fn_epp = sse_op_table5[val];
4351 if (!sse_fn_epp) {
a35f3ec7 4352 goto illegal_op;
c4baa050 4353 }
5af45186
FB
4354 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4355 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
d3eb5eae 4356 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
a35f3ec7 4357 break;
664e0f19
FB
4358 case 0x70: /* pshufx insn */
4359 case 0xc6: /* pshufx insn */
0af10c86 4360 val = cpu_ldub_code(env, s->pc++);
5af45186
FB
4361 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4362 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
c4baa050 4363 /* XXX: introduce a new table? */
d3eb5eae 4364 sse_fn_ppi = (SSEFunc_0_ppi)sse_fn_epp;
c4baa050 4365 sse_fn_ppi(cpu_ptr0, cpu_ptr1, tcg_const_i32(val));
664e0f19
FB
4366 break;
4367 case 0xc2:
4368 /* compare insns */
0af10c86 4369 val = cpu_ldub_code(env, s->pc++);
664e0f19
FB
4370 if (val >= 8)
4371 goto illegal_op;
d3eb5eae 4372 sse_fn_epp = sse_op_table4[val][b1];
c4baa050 4373
5af45186
FB
4374 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4375 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
d3eb5eae 4376 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
664e0f19 4377 break;
b8b6a50b
FB
4378 case 0xf7:
4379 /* maskmov : we must prepare A0 */
4380 if (mod != 3)
4381 goto illegal_op;
1d71ddb1
RH
4382 tcg_gen_mov_tl(cpu_A0, cpu_regs[R_EDI]);
4383 gen_extu(s->aflag, cpu_A0);
b8b6a50b
FB
4384 gen_add_A0_ds_seg(s);
4385
4386 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4387 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
c4baa050 4388 /* XXX: introduce a new table? */
d3eb5eae
BS
4389 sse_fn_eppt = (SSEFunc_0_eppt)sse_fn_epp;
4390 sse_fn_eppt(cpu_env, cpu_ptr0, cpu_ptr1, cpu_A0);
b8b6a50b 4391 break;
664e0f19 4392 default:
5af45186
FB
4393 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4394 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
d3eb5eae 4395 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
664e0f19
FB
4396 break;
4397 }
4398 if (b == 0x2e || b == 0x2f) {
3ca51d07 4399 set_cc_op(s, CC_OP_EFLAGS);
664e0f19
FB
4400 }
4401 }
4402}
4403
2c0262af
FB
4404/* convert one instruction. s->is_jmp is set if the translation must
4405 be stopped. Return the next pc value */
0af10c86
BS
4406static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
4407 target_ulong pc_start)
2c0262af 4408{
ab4e4aec 4409 int b, prefixes;
d67dc9e6 4410 int shift;
ab4e4aec 4411 TCGMemOp ot, aflag, dflag;
4eeb3939 4412 int modrm, reg, rm, mod, op, opreg, val;
14ce26e7
FB
4413 target_ulong next_eip, tval;
4414 int rex_w, rex_r;
2c0262af 4415
fdefe51c 4416 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
70cff25e 4417 tcg_gen_debug_insn_start(pc_start);
fdefe51c 4418 }
2c0262af
FB
4419 s->pc = pc_start;
4420 prefixes = 0;
2c0262af 4421 s->override = -1;
14ce26e7
FB
4422 rex_w = -1;
4423 rex_r = 0;
4424#ifdef TARGET_X86_64
4425 s->rex_x = 0;
4426 s->rex_b = 0;
5fafdf24 4427 x86_64_hregs = 0;
14ce26e7
FB
4428#endif
4429 s->rip_offset = 0; /* for relative ip address */
701ed211
RH
4430 s->vex_l = 0;
4431 s->vex_v = 0;
2c0262af 4432 next_byte:
0af10c86 4433 b = cpu_ldub_code(env, s->pc);
2c0262af 4434 s->pc++;
4a6fd938
RH
4435 /* Collect prefixes. */
4436 switch (b) {
4437 case 0xf3:
4438 prefixes |= PREFIX_REPZ;
4439 goto next_byte;
4440 case 0xf2:
4441 prefixes |= PREFIX_REPNZ;
4442 goto next_byte;
4443 case 0xf0:
4444 prefixes |= PREFIX_LOCK;
4445 goto next_byte;
4446 case 0x2e:
4447 s->override = R_CS;
4448 goto next_byte;
4449 case 0x36:
4450 s->override = R_SS;
4451 goto next_byte;
4452 case 0x3e:
4453 s->override = R_DS;
4454 goto next_byte;
4455 case 0x26:
4456 s->override = R_ES;
4457 goto next_byte;
4458 case 0x64:
4459 s->override = R_FS;
4460 goto next_byte;
4461 case 0x65:
4462 s->override = R_GS;
4463 goto next_byte;
4464 case 0x66:
4465 prefixes |= PREFIX_DATA;
4466 goto next_byte;
4467 case 0x67:
4468 prefixes |= PREFIX_ADR;
4469 goto next_byte;
14ce26e7 4470#ifdef TARGET_X86_64
4a6fd938
RH
4471 case 0x40 ... 0x4f:
4472 if (CODE64(s)) {
14ce26e7
FB
4473 /* REX prefix */
4474 rex_w = (b >> 3) & 1;
4475 rex_r = (b & 0x4) << 1;
4476 s->rex_x = (b & 0x2) << 2;
4477 REX_B(s) = (b & 0x1) << 3;
4478 x86_64_hregs = 1; /* select uniform byte register addressing */
4479 goto next_byte;
4480 }
4a6fd938
RH
4481 break;
4482#endif
701ed211
RH
4483 case 0xc5: /* 2-byte VEX */
4484 case 0xc4: /* 3-byte VEX */
4485 /* VEX prefixes cannot be used except in 32-bit mode.
4486 Otherwise the instruction is LES or LDS. */
4487 if (s->code32 && !s->vm86) {
4488 static const int pp_prefix[4] = {
4489 0, PREFIX_DATA, PREFIX_REPZ, PREFIX_REPNZ
4490 };
4491 int vex3, vex2 = cpu_ldub_code(env, s->pc);
4492
4493 if (!CODE64(s) && (vex2 & 0xc0) != 0xc0) {
4494 /* 4.1.4.6: In 32-bit mode, bits [7:6] must be 11b,
4495 otherwise the instruction is LES or LDS. */
4496 break;
4497 }
4498 s->pc++;
4499
085d8134 4500 /* 4.1.1-4.1.3: No preceding lock, 66, f2, f3, or rex prefixes. */
701ed211
RH
4501 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ
4502 | PREFIX_LOCK | PREFIX_DATA)) {
4503 goto illegal_op;
4504 }
4505#ifdef TARGET_X86_64
4506 if (x86_64_hregs) {
4507 goto illegal_op;
4508 }
4509#endif
4510 rex_r = (~vex2 >> 4) & 8;
4511 if (b == 0xc5) {
4512 vex3 = vex2;
4513 b = cpu_ldub_code(env, s->pc++);
4514 } else {
4515#ifdef TARGET_X86_64
4516 s->rex_x = (~vex2 >> 3) & 8;
4517 s->rex_b = (~vex2 >> 2) & 8;
4518#endif
4519 vex3 = cpu_ldub_code(env, s->pc++);
4520 rex_w = (vex3 >> 7) & 1;
4521 switch (vex2 & 0x1f) {
4522 case 0x01: /* Implied 0f leading opcode bytes. */
4523 b = cpu_ldub_code(env, s->pc++) | 0x100;
4524 break;
4525 case 0x02: /* Implied 0f 38 leading opcode bytes. */
4526 b = 0x138;
4527 break;
4528 case 0x03: /* Implied 0f 3a leading opcode bytes. */
4529 b = 0x13a;
4530 break;
4531 default: /* Reserved for future use. */
4532 goto illegal_op;
4533 }
4534 }
4535 s->vex_v = (~vex3 >> 3) & 0xf;
4536 s->vex_l = (vex3 >> 2) & 1;
4537 prefixes |= pp_prefix[vex3 & 3] | PREFIX_VEX;
4538 }
4539 break;
4a6fd938
RH
4540 }
4541
4542 /* Post-process prefixes. */
4a6fd938 4543 if (CODE64(s)) {
dec3fc96
RH
4544 /* In 64-bit mode, the default data size is 32-bit. Select 64-bit
4545 data with rex_w, and 16-bit data with 0x66; rex_w takes precedence
4546 over 0x66 if both are present. */
ab4e4aec 4547 dflag = (rex_w > 0 ? MO_64 : prefixes & PREFIX_DATA ? MO_16 : MO_32);
dec3fc96 4548 /* In 64-bit mode, 0x67 selects 32-bit addressing. */
1d71ddb1 4549 aflag = (prefixes & PREFIX_ADR ? MO_32 : MO_64);
dec3fc96
RH
4550 } else {
4551 /* In 16/32-bit mode, 0x66 selects the opposite data size. */
ab4e4aec
RH
4552 if (s->code32 ^ ((prefixes & PREFIX_DATA) != 0)) {
4553 dflag = MO_32;
4554 } else {
4555 dflag = MO_16;
14ce26e7 4556 }
dec3fc96 4557 /* In 16/32-bit mode, 0x67 selects the opposite addressing. */
1d71ddb1
RH
4558 if (s->code32 ^ ((prefixes & PREFIX_ADR) != 0)) {
4559 aflag = MO_32;
4560 } else {
4561 aflag = MO_16;
14ce26e7 4562 }
2c0262af
FB
4563 }
4564
2c0262af
FB
4565 s->prefix = prefixes;
4566 s->aflag = aflag;
4567 s->dflag = dflag;
4568
4569 /* lock generation */
4570 if (prefixes & PREFIX_LOCK)
a7812ae4 4571 gen_helper_lock();
2c0262af
FB
4572
4573 /* now check op code */
4574 reswitch:
4575 switch(b) {
4576 case 0x0f:
4577 /**************************/
4578 /* extended op code */
0af10c86 4579 b = cpu_ldub_code(env, s->pc++) | 0x100;
2c0262af 4580 goto reswitch;
3b46e624 4581
2c0262af
FB
4582 /**************************/
4583 /* arith & logic */
4584 case 0x00 ... 0x05:
4585 case 0x08 ... 0x0d:
4586 case 0x10 ... 0x15:
4587 case 0x18 ... 0x1d:
4588 case 0x20 ... 0x25:
4589 case 0x28 ... 0x2d:
4590 case 0x30 ... 0x35:
4591 case 0x38 ... 0x3d:
4592 {
4593 int op, f, val;
4594 op = (b >> 3) & 7;
4595 f = (b >> 1) & 3;
4596
ab4e4aec 4597 ot = mo_b_d(b, dflag);
3b46e624 4598
2c0262af
FB
4599 switch(f) {
4600 case 0: /* OP Ev, Gv */
0af10c86 4601 modrm = cpu_ldub_code(env, s->pc++);
14ce26e7 4602 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af 4603 mod = (modrm >> 6) & 3;
14ce26e7 4604 rm = (modrm & 7) | REX_B(s);
2c0262af 4605 if (mod != 3) {
4eeb3939 4606 gen_lea_modrm(env, s, modrm);
2c0262af
FB
4607 opreg = OR_TMP0;
4608 } else if (op == OP_XORL && rm == reg) {
4609 xor_zero:
4610 /* xor reg, reg optimisation */
436ff2d2 4611 set_cc_op(s, CC_OP_CLR);
97212c88 4612 tcg_gen_movi_tl(cpu_T[0], 0);
480a762d 4613 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
2c0262af
FB
4614 break;
4615 } else {
4616 opreg = rm;
4617 }
c56baccf 4618 gen_op_mov_v_reg(ot, cpu_T[1], reg);
2c0262af
FB
4619 gen_op(s, op, ot, opreg);
4620 break;
4621 case 1: /* OP Gv, Ev */
0af10c86 4622 modrm = cpu_ldub_code(env, s->pc++);
2c0262af 4623 mod = (modrm >> 6) & 3;
14ce26e7
FB
4624 reg = ((modrm >> 3) & 7) | rex_r;
4625 rm = (modrm & 7) | REX_B(s);
2c0262af 4626 if (mod != 3) {
4eeb3939 4627 gen_lea_modrm(env, s, modrm);
0f712e10 4628 gen_op_ld_v(s, ot, cpu_T[1], cpu_A0);
2c0262af
FB
4629 } else if (op == OP_XORL && rm == reg) {
4630 goto xor_zero;
4631 } else {
c56baccf 4632 gen_op_mov_v_reg(ot, cpu_T[1], rm);
2c0262af
FB
4633 }
4634 gen_op(s, op, ot, reg);
4635 break;
4636 case 2: /* OP A, Iv */
0af10c86 4637 val = insn_get(env, s, ot);
0ae657b1 4638 tcg_gen_movi_tl(cpu_T[1], val);
2c0262af
FB
4639 gen_op(s, op, ot, OR_EAX);
4640 break;
4641 }
4642 }
4643 break;
4644
ec9d6075
FB
4645 case 0x82:
4646 if (CODE64(s))
4647 goto illegal_op;
2c0262af
FB
4648 case 0x80: /* GRP1 */
4649 case 0x81:
4650 case 0x83:
4651 {
4652 int val;
4653
ab4e4aec 4654 ot = mo_b_d(b, dflag);
3b46e624 4655
0af10c86 4656 modrm = cpu_ldub_code(env, s->pc++);
2c0262af 4657 mod = (modrm >> 6) & 3;
14ce26e7 4658 rm = (modrm & 7) | REX_B(s);
2c0262af 4659 op = (modrm >> 3) & 7;
3b46e624 4660
2c0262af 4661 if (mod != 3) {
14ce26e7
FB
4662 if (b == 0x83)
4663 s->rip_offset = 1;
4664 else
4665 s->rip_offset = insn_const_size(ot);
4eeb3939 4666 gen_lea_modrm(env, s, modrm);
2c0262af
FB
4667 opreg = OR_TMP0;
4668 } else {
14ce26e7 4669 opreg = rm;
2c0262af
FB
4670 }
4671
4672 switch(b) {
4673 default:
4674 case 0x80:
4675 case 0x81:
d64477af 4676 case 0x82:
0af10c86 4677 val = insn_get(env, s, ot);
2c0262af
FB
4678 break;
4679 case 0x83:
4ba9938c 4680 val = (int8_t)insn_get(env, s, MO_8);
2c0262af
FB
4681 break;
4682 }
0ae657b1 4683 tcg_gen_movi_tl(cpu_T[1], val);
2c0262af
FB
4684 gen_op(s, op, ot, opreg);
4685 }
4686 break;
4687
4688 /**************************/
4689 /* inc, dec, and other misc arith */
4690 case 0x40 ... 0x47: /* inc Gv */
ab4e4aec 4691 ot = dflag;
2c0262af
FB
4692 gen_inc(s, ot, OR_EAX + (b & 7), 1);
4693 break;
4694 case 0x48 ... 0x4f: /* dec Gv */
ab4e4aec 4695 ot = dflag;
2c0262af
FB
4696 gen_inc(s, ot, OR_EAX + (b & 7), -1);
4697 break;
4698 case 0xf6: /* GRP3 */
4699 case 0xf7:
ab4e4aec 4700 ot = mo_b_d(b, dflag);
2c0262af 4701
0af10c86 4702 modrm = cpu_ldub_code(env, s->pc++);
2c0262af 4703 mod = (modrm >> 6) & 3;
14ce26e7 4704 rm = (modrm & 7) | REX_B(s);
2c0262af
FB
4705 op = (modrm >> 3) & 7;
4706 if (mod != 3) {
14ce26e7
FB
4707 if (op == 0)
4708 s->rip_offset = insn_const_size(ot);
4eeb3939 4709 gen_lea_modrm(env, s, modrm);
909be183 4710 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
2c0262af 4711 } else {
c56baccf 4712 gen_op_mov_v_reg(ot, cpu_T[0], rm);
2c0262af
FB
4713 }
4714
4715 switch(op) {
4716 case 0: /* test */
0af10c86 4717 val = insn_get(env, s, ot);
0ae657b1 4718 tcg_gen_movi_tl(cpu_T[1], val);
2c0262af 4719 gen_op_testl_T0_T1_cc();
3ca51d07 4720 set_cc_op(s, CC_OP_LOGICB + ot);
2c0262af
FB
4721 break;
4722 case 2: /* not */
b6abf97d 4723 tcg_gen_not_tl(cpu_T[0], cpu_T[0]);
2c0262af 4724 if (mod != 3) {
fd8ca9f6 4725 gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
2c0262af 4726 } else {
480a762d 4727 gen_op_mov_reg_v(ot, rm, cpu_T[0]);
2c0262af
FB
4728 }
4729 break;
4730 case 3: /* neg */
b6abf97d 4731 tcg_gen_neg_tl(cpu_T[0], cpu_T[0]);
2c0262af 4732 if (mod != 3) {
fd8ca9f6 4733 gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
2c0262af 4734 } else {
480a762d 4735 gen_op_mov_reg_v(ot, rm, cpu_T[0]);
2c0262af
FB
4736 }
4737 gen_op_update_neg_cc();
3ca51d07 4738 set_cc_op(s, CC_OP_SUBB + ot);
2c0262af
FB
4739 break;
4740 case 4: /* mul */
4741 switch(ot) {
4ba9938c 4742 case MO_8:
c56baccf 4743 gen_op_mov_v_reg(MO_8, cpu_T[1], R_EAX);
0211e5af
FB
4744 tcg_gen_ext8u_tl(cpu_T[0], cpu_T[0]);
4745 tcg_gen_ext8u_tl(cpu_T[1], cpu_T[1]);
4746 /* XXX: use 32 bit mul which could be faster */
4747 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
480a762d 4748 gen_op_mov_reg_v(MO_16, R_EAX, cpu_T[0]);
0211e5af
FB
4749 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4750 tcg_gen_andi_tl(cpu_cc_src, cpu_T[0], 0xff00);
3ca51d07 4751 set_cc_op(s, CC_OP_MULB);
2c0262af 4752 break;
4ba9938c 4753 case MO_16:
c56baccf 4754 gen_op_mov_v_reg(MO_16, cpu_T[1], R_EAX);
0211e5af
FB
4755 tcg_gen_ext16u_tl(cpu_T[0], cpu_T[0]);
4756 tcg_gen_ext16u_tl(cpu_T[1], cpu_T[1]);
4757 /* XXX: use 32 bit mul which could be faster */
4758 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
480a762d 4759 gen_op_mov_reg_v(MO_16, R_EAX, cpu_T[0]);
0211e5af
FB
4760 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4761 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 16);
480a762d 4762 gen_op_mov_reg_v(MO_16, R_EDX, cpu_T[0]);
0211e5af 4763 tcg_gen_mov_tl(cpu_cc_src, cpu_T[0]);
3ca51d07 4764 set_cc_op(s, CC_OP_MULW);
2c0262af
FB
4765 break;
4766 default:
4ba9938c 4767 case MO_32:
a4bcea3d
RH
4768 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
4769 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_regs[R_EAX]);
4770 tcg_gen_mulu2_i32(cpu_tmp2_i32, cpu_tmp3_i32,
4771 cpu_tmp2_i32, cpu_tmp3_i32);
4772 tcg_gen_extu_i32_tl(cpu_regs[R_EAX], cpu_tmp2_i32);
4773 tcg_gen_extu_i32_tl(cpu_regs[R_EDX], cpu_tmp3_i32);
4774 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
4775 tcg_gen_mov_tl(cpu_cc_src, cpu_regs[R_EDX]);
3ca51d07 4776 set_cc_op(s, CC_OP_MULL);
2c0262af 4777 break;
14ce26e7 4778#ifdef TARGET_X86_64
4ba9938c 4779 case MO_64:
a4bcea3d
RH
4780 tcg_gen_mulu2_i64(cpu_regs[R_EAX], cpu_regs[R_EDX],
4781 cpu_T[0], cpu_regs[R_EAX]);
4782 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
4783 tcg_gen_mov_tl(cpu_cc_src, cpu_regs[R_EDX]);
3ca51d07 4784 set_cc_op(s, CC_OP_MULQ);
14ce26e7
FB
4785 break;
4786#endif
2c0262af 4787 }
2c0262af
FB
4788 break;
4789 case 5: /* imul */
4790 switch(ot) {
4ba9938c 4791 case MO_8:
c56baccf 4792 gen_op_mov_v_reg(MO_8, cpu_T[1], R_EAX);
0211e5af
FB
4793 tcg_gen_ext8s_tl(cpu_T[0], cpu_T[0]);
4794 tcg_gen_ext8s_tl(cpu_T[1], cpu_T[1]);
4795 /* XXX: use 32 bit mul which could be faster */
4796 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
480a762d 4797 gen_op_mov_reg_v(MO_16, R_EAX, cpu_T[0]);
0211e5af
FB
4798 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4799 tcg_gen_ext8s_tl(cpu_tmp0, cpu_T[0]);
4800 tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0);
3ca51d07 4801 set_cc_op(s, CC_OP_MULB);
2c0262af 4802 break;
4ba9938c 4803 case MO_16:
c56baccf 4804 gen_op_mov_v_reg(MO_16, cpu_T[1], R_EAX);
0211e5af
FB
4805 tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
4806 tcg_gen_ext16s_tl(cpu_T[1], cpu_T[1]);
4807 /* XXX: use 32 bit mul which could be faster */
4808 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
480a762d 4809 gen_op_mov_reg_v(MO_16, R_EAX, cpu_T[0]);
0211e5af
FB
4810 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4811 tcg_gen_ext16s_tl(cpu_tmp0, cpu_T[0]);
4812 tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0);
4813 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 16);
480a762d 4814 gen_op_mov_reg_v(MO_16, R_EDX, cpu_T[0]);
3ca51d07 4815 set_cc_op(s, CC_OP_MULW);
2c0262af
FB
4816 break;
4817 default:
4ba9938c 4818 case MO_32:
a4bcea3d
RH
4819 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
4820 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_regs[R_EAX]);
4821 tcg_gen_muls2_i32(cpu_tmp2_i32, cpu_tmp3_i32,
4822 cpu_tmp2_i32, cpu_tmp3_i32);
4823 tcg_gen_extu_i32_tl(cpu_regs[R_EAX], cpu_tmp2_i32);
4824 tcg_gen_extu_i32_tl(cpu_regs[R_EDX], cpu_tmp3_i32);
4825 tcg_gen_sari_i32(cpu_tmp2_i32, cpu_tmp2_i32, 31);
4826 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
4827 tcg_gen_sub_i32(cpu_tmp2_i32, cpu_tmp2_i32, cpu_tmp3_i32);
4828 tcg_gen_extu_i32_tl(cpu_cc_src, cpu_tmp2_i32);
3ca51d07 4829 set_cc_op(s, CC_OP_MULL);
2c0262af 4830 break;
14ce26e7 4831#ifdef TARGET_X86_64
4ba9938c 4832 case MO_64:
a4bcea3d
RH
4833 tcg_gen_muls2_i64(cpu_regs[R_EAX], cpu_regs[R_EDX],
4834 cpu_T[0], cpu_regs[R_EAX]);
4835 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
4836 tcg_gen_sari_tl(cpu_cc_src, cpu_regs[R_EAX], 63);
4837 tcg_gen_sub_tl(cpu_cc_src, cpu_cc_src, cpu_regs[R_EDX]);
3ca51d07 4838 set_cc_op(s, CC_OP_MULQ);
14ce26e7
FB
4839 break;
4840#endif
2c0262af 4841 }
2c0262af
FB
4842 break;
4843 case 6: /* div */
4844 switch(ot) {
4ba9938c 4845 case MO_8:
14ce26e7 4846 gen_jmp_im(pc_start - s->cs_base);
7923057b 4847 gen_helper_divb_AL(cpu_env, cpu_T[0]);
2c0262af 4848 break;
4ba9938c 4849 case MO_16:
14ce26e7 4850 gen_jmp_im(pc_start - s->cs_base);
7923057b 4851 gen_helper_divw_AX(cpu_env, cpu_T[0]);
2c0262af
FB
4852 break;
4853 default:
4ba9938c 4854 case MO_32:
14ce26e7 4855 gen_jmp_im(pc_start - s->cs_base);
7923057b 4856 gen_helper_divl_EAX(cpu_env, cpu_T[0]);
14ce26e7
FB
4857 break;
4858#ifdef TARGET_X86_64
4ba9938c 4859 case MO_64:
14ce26e7 4860 gen_jmp_im(pc_start - s->cs_base);
7923057b 4861 gen_helper_divq_EAX(cpu_env, cpu_T[0]);
2c0262af 4862 break;
14ce26e7 4863#endif
2c0262af
FB
4864 }
4865 break;
4866 case 7: /* idiv */
4867 switch(ot) {
4ba9938c 4868 case MO_8:
14ce26e7 4869 gen_jmp_im(pc_start - s->cs_base);
7923057b 4870 gen_helper_idivb_AL(cpu_env, cpu_T[0]);
2c0262af 4871 break;
4ba9938c 4872 case MO_16:
14ce26e7 4873 gen_jmp_im(pc_start - s->cs_base);
7923057b 4874 gen_helper_idivw_AX(cpu_env, cpu_T[0]);
2c0262af
FB
4875 break;
4876 default:
4ba9938c 4877 case MO_32:
14ce26e7 4878 gen_jmp_im(pc_start - s->cs_base);
7923057b 4879 gen_helper_idivl_EAX(cpu_env, cpu_T[0]);
14ce26e7
FB
4880 break;
4881#ifdef TARGET_X86_64
4ba9938c 4882 case MO_64:
14ce26e7 4883 gen_jmp_im(pc_start - s->cs_base);
7923057b 4884 gen_helper_idivq_EAX(cpu_env, cpu_T[0]);
2c0262af 4885 break;
14ce26e7 4886#endif
2c0262af
FB
4887 }
4888 break;
4889 default:
4890 goto illegal_op;
4891 }
4892 break;
4893
4894 case 0xfe: /* GRP4 */
4895 case 0xff: /* GRP5 */
ab4e4aec 4896 ot = mo_b_d(b, dflag);
2c0262af 4897
0af10c86 4898 modrm = cpu_ldub_code(env, s->pc++);
2c0262af 4899 mod = (modrm >> 6) & 3;
14ce26e7 4900 rm = (modrm & 7) | REX_B(s);
2c0262af
FB
4901 op = (modrm >> 3) & 7;
4902 if (op >= 2 && b == 0xfe) {
4903 goto illegal_op;
4904 }
14ce26e7 4905 if (CODE64(s)) {
aba9d61e 4906 if (op == 2 || op == 4) {
14ce26e7 4907 /* operand size for jumps is 64 bit */
4ba9938c 4908 ot = MO_64;
aba9d61e 4909 } else if (op == 3 || op == 5) {
ab4e4aec 4910 ot = dflag != MO_16 ? MO_32 + (rex_w == 1) : MO_16;
14ce26e7
FB
4911 } else if (op == 6) {
4912 /* default push size is 64 bit */
ab4e4aec 4913 ot = mo_pushpop(s, dflag);
14ce26e7
FB
4914 }
4915 }
2c0262af 4916 if (mod != 3) {
4eeb3939 4917 gen_lea_modrm(env, s, modrm);
2c0262af 4918 if (op >= 2 && op != 3 && op != 5)
909be183 4919 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
2c0262af 4920 } else {
c56baccf 4921 gen_op_mov_v_reg(ot, cpu_T[0], rm);
2c0262af
FB
4922 }
4923
4924 switch(op) {
4925 case 0: /* inc Ev */
4926 if (mod != 3)
4927 opreg = OR_TMP0;
4928 else
4929 opreg = rm;
4930 gen_inc(s, ot, opreg, 1);
4931 break;
4932 case 1: /* dec Ev */
4933 if (mod != 3)
4934 opreg = OR_TMP0;
4935 else
4936 opreg = rm;
4937 gen_inc(s, ot, opreg, -1);
4938 break;
4939 case 2: /* call Ev */
4f31916f 4940 /* XXX: optimize if memory (no 'and' is necessary) */
ab4e4aec 4941 if (dflag == MO_16) {
40b90233
RH
4942 tcg_gen_ext16u_tl(cpu_T[0], cpu_T[0]);
4943 }
2c0262af 4944 next_eip = s->pc - s->cs_base;
cc0bce88 4945 tcg_gen_movi_tl(cpu_T[1], next_eip);
432baffe 4946 gen_push_v(s, cpu_T[1]);
74bdfbda 4947 gen_op_jmp_v(cpu_T[0]);
2c0262af
FB
4948 gen_eob(s);
4949 break;
61382a50 4950 case 3: /* lcall Ev */
0f712e10 4951 gen_op_ld_v(s, ot, cpu_T[1], cpu_A0);
830a19a4 4952 gen_add_A0_im(s, 1 << ot);
cc1a80df 4953 gen_op_ld_v(s, MO_16, cpu_T[0], cpu_A0);
2c0262af
FB
4954 do_lcall:
4955 if (s->pe && !s->vm86) {
773cdfcc 4956 gen_update_cc_op(s);
14ce26e7 4957 gen_jmp_im(pc_start - s->cs_base);
b6abf97d 4958 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
2999a0b2 4959 gen_helper_lcall_protected(cpu_env, cpu_tmp2_i32, cpu_T[1],
ab4e4aec 4960 tcg_const_i32(dflag - 1),
a7812ae4 4961 tcg_const_i32(s->pc - pc_start));
2c0262af 4962 } else {
b6abf97d 4963 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
2999a0b2 4964 gen_helper_lcall_real(cpu_env, cpu_tmp2_i32, cpu_T[1],
ab4e4aec 4965 tcg_const_i32(dflag - 1),
a7812ae4 4966 tcg_const_i32(s->pc - s->cs_base));
2c0262af
FB
4967 }
4968 gen_eob(s);
4969 break;
4970 case 4: /* jmp Ev */
ab4e4aec 4971 if (dflag == MO_16) {
40b90233
RH
4972 tcg_gen_ext16u_tl(cpu_T[0], cpu_T[0]);
4973 }
74bdfbda 4974 gen_op_jmp_v(cpu_T[0]);
2c0262af
FB
4975 gen_eob(s);
4976 break;
4977 case 5: /* ljmp Ev */
0f712e10 4978 gen_op_ld_v(s, ot, cpu_T[1], cpu_A0);
830a19a4 4979 gen_add_A0_im(s, 1 << ot);
cc1a80df 4980 gen_op_ld_v(s, MO_16, cpu_T[0], cpu_A0);
2c0262af
FB
4981 do_ljmp:
4982 if (s->pe && !s->vm86) {
773cdfcc 4983 gen_update_cc_op(s);
14ce26e7 4984 gen_jmp_im(pc_start - s->cs_base);
b6abf97d 4985 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
2999a0b2 4986 gen_helper_ljmp_protected(cpu_env, cpu_tmp2_i32, cpu_T[1],
a7812ae4 4987 tcg_const_i32(s->pc - pc_start));
2c0262af 4988 } else {
3bd7da9e 4989 gen_op_movl_seg_T0_vm(R_CS);
78261634 4990 gen_op_jmp_v(cpu_T[1]);
2c0262af
FB
4991 }
4992 gen_eob(s);
4993 break;
4994 case 6: /* push Ev */
432baffe 4995 gen_push_v(s, cpu_T[0]);
2c0262af
FB
4996 break;
4997 default:
4998 goto illegal_op;
4999 }
5000 break;
5001
5002 case 0x84: /* test Ev, Gv */
5fafdf24 5003 case 0x85:
ab4e4aec 5004 ot = mo_b_d(b, dflag);
2c0262af 5005
0af10c86 5006 modrm = cpu_ldub_code(env, s->pc++);
14ce26e7 5007 reg = ((modrm >> 3) & 7) | rex_r;
3b46e624 5008
0af10c86 5009 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
c56baccf 5010 gen_op_mov_v_reg(ot, cpu_T[1], reg);
2c0262af 5011 gen_op_testl_T0_T1_cc();
3ca51d07 5012 set_cc_op(s, CC_OP_LOGICB + ot);
2c0262af 5013 break;
3b46e624 5014
2c0262af
FB
5015 case 0xa8: /* test eAX, Iv */
5016 case 0xa9:
ab4e4aec 5017 ot = mo_b_d(b, dflag);
0af10c86 5018 val = insn_get(env, s, ot);
2c0262af 5019
c56baccf 5020 gen_op_mov_v_reg(ot, cpu_T[0], OR_EAX);
0ae657b1 5021 tcg_gen_movi_tl(cpu_T[1], val);
2c0262af 5022 gen_op_testl_T0_T1_cc();
3ca51d07 5023 set_cc_op(s, CC_OP_LOGICB + ot);
2c0262af 5024 break;
3b46e624 5025
2c0262af 5026 case 0x98: /* CWDE/CBW */
ab4e4aec 5027 switch (dflag) {
14ce26e7 5028#ifdef TARGET_X86_64
ab4e4aec 5029 case MO_64:
c56baccf 5030 gen_op_mov_v_reg(MO_32, cpu_T[0], R_EAX);
e108dd01 5031 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
480a762d 5032 gen_op_mov_reg_v(MO_64, R_EAX, cpu_T[0]);
ab4e4aec 5033 break;
14ce26e7 5034#endif
ab4e4aec 5035 case MO_32:
c56baccf 5036 gen_op_mov_v_reg(MO_16, cpu_T[0], R_EAX);
e108dd01 5037 tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
480a762d 5038 gen_op_mov_reg_v(MO_32, R_EAX, cpu_T[0]);
ab4e4aec
RH
5039 break;
5040 case MO_16:
c56baccf 5041 gen_op_mov_v_reg(MO_8, cpu_T[0], R_EAX);
e108dd01 5042 tcg_gen_ext8s_tl(cpu_T[0], cpu_T[0]);
480a762d 5043 gen_op_mov_reg_v(MO_16, R_EAX, cpu_T[0]);
ab4e4aec
RH
5044 break;
5045 default:
5046 tcg_abort();
e108dd01 5047 }
2c0262af
FB
5048 break;
5049 case 0x99: /* CDQ/CWD */
ab4e4aec 5050 switch (dflag) {
14ce26e7 5051#ifdef TARGET_X86_64
ab4e4aec 5052 case MO_64:
c56baccf 5053 gen_op_mov_v_reg(MO_64, cpu_T[0], R_EAX);
e108dd01 5054 tcg_gen_sari_tl(cpu_T[0], cpu_T[0], 63);
480a762d 5055 gen_op_mov_reg_v(MO_64, R_EDX, cpu_T[0]);
ab4e4aec 5056 break;
14ce26e7 5057#endif
ab4e4aec 5058 case MO_32:
c56baccf 5059 gen_op_mov_v_reg(MO_32, cpu_T[0], R_EAX);
e108dd01
FB
5060 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
5061 tcg_gen_sari_tl(cpu_T[0], cpu_T[0], 31);
480a762d 5062 gen_op_mov_reg_v(MO_32, R_EDX, cpu_T[0]);
ab4e4aec
RH
5063 break;
5064 case MO_16:
c56baccf 5065 gen_op_mov_v_reg(MO_16, cpu_T[0], R_EAX);
e108dd01
FB
5066 tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
5067 tcg_gen_sari_tl(cpu_T[0], cpu_T[0], 15);
480a762d 5068 gen_op_mov_reg_v(MO_16, R_EDX, cpu_T[0]);
ab4e4aec
RH
5069 break;
5070 default:
5071 tcg_abort();
e108dd01 5072 }
2c0262af
FB
5073 break;
5074 case 0x1af: /* imul Gv, Ev */
5075 case 0x69: /* imul Gv, Ev, I */
5076 case 0x6b:
ab4e4aec 5077 ot = dflag;
0af10c86 5078 modrm = cpu_ldub_code(env, s->pc++);
14ce26e7
FB
5079 reg = ((modrm >> 3) & 7) | rex_r;
5080 if (b == 0x69)
5081 s->rip_offset = insn_const_size(ot);
5082 else if (b == 0x6b)
5083 s->rip_offset = 1;
0af10c86 5084 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
2c0262af 5085 if (b == 0x69) {
0af10c86 5086 val = insn_get(env, s, ot);
0ae657b1 5087 tcg_gen_movi_tl(cpu_T[1], val);
2c0262af 5088 } else if (b == 0x6b) {
4ba9938c 5089 val = (int8_t)insn_get(env, s, MO_8);
0ae657b1 5090 tcg_gen_movi_tl(cpu_T[1], val);
2c0262af 5091 } else {
c56baccf 5092 gen_op_mov_v_reg(ot, cpu_T[1], reg);
2c0262af 5093 }
a4bcea3d 5094 switch (ot) {
0211e5af 5095#ifdef TARGET_X86_64
4ba9938c 5096 case MO_64:
a4bcea3d
RH
5097 tcg_gen_muls2_i64(cpu_regs[reg], cpu_T[1], cpu_T[0], cpu_T[1]);
5098 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[reg]);
5099 tcg_gen_sari_tl(cpu_cc_src, cpu_cc_dst, 63);
5100 tcg_gen_sub_tl(cpu_cc_src, cpu_cc_src, cpu_T[1]);
5101 break;
0211e5af 5102#endif
4ba9938c 5103 case MO_32:
a4bcea3d
RH
5104 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
5105 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T[1]);
5106 tcg_gen_muls2_i32(cpu_tmp2_i32, cpu_tmp3_i32,
5107 cpu_tmp2_i32, cpu_tmp3_i32);
5108 tcg_gen_extu_i32_tl(cpu_regs[reg], cpu_tmp2_i32);
5109 tcg_gen_sari_i32(cpu_tmp2_i32, cpu_tmp2_i32, 31);
5110 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[reg]);
5111 tcg_gen_sub_i32(cpu_tmp2_i32, cpu_tmp2_i32, cpu_tmp3_i32);
5112 tcg_gen_extu_i32_tl(cpu_cc_src, cpu_tmp2_i32);
5113 break;
5114 default:
0211e5af
FB
5115 tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
5116 tcg_gen_ext16s_tl(cpu_T[1], cpu_T[1]);
5117 /* XXX: use 32 bit mul which could be faster */
5118 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
5119 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
5120 tcg_gen_ext16s_tl(cpu_tmp0, cpu_T[0]);
5121 tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0);
480a762d 5122 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
a4bcea3d 5123 break;
2c0262af 5124 }
3ca51d07 5125 set_cc_op(s, CC_OP_MULB + ot);
2c0262af
FB
5126 break;
5127 case 0x1c0:
5128 case 0x1c1: /* xadd Ev, Gv */
ab4e4aec 5129 ot = mo_b_d(b, dflag);
0af10c86 5130 modrm = cpu_ldub_code(env, s->pc++);
14ce26e7 5131 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af
FB
5132 mod = (modrm >> 6) & 3;
5133 if (mod == 3) {
14ce26e7 5134 rm = (modrm & 7) | REX_B(s);
c56baccf
RH
5135 gen_op_mov_v_reg(ot, cpu_T[0], reg);
5136 gen_op_mov_v_reg(ot, cpu_T[1], rm);
fd5185ec 5137 tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
68773f84 5138 gen_op_mov_reg_v(ot, reg, cpu_T[1]);
480a762d 5139 gen_op_mov_reg_v(ot, rm, cpu_T[0]);
2c0262af 5140 } else {
4eeb3939 5141 gen_lea_modrm(env, s, modrm);
c56baccf 5142 gen_op_mov_v_reg(ot, cpu_T[0], reg);
0f712e10 5143 gen_op_ld_v(s, ot, cpu_T[1], cpu_A0);
fd5185ec 5144 tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
fd8ca9f6 5145 gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
68773f84 5146 gen_op_mov_reg_v(ot, reg, cpu_T[1]);
2c0262af
FB
5147 }
5148 gen_op_update2_cc();
3ca51d07 5149 set_cc_op(s, CC_OP_ADDB + ot);
2c0262af
FB
5150 break;
5151 case 0x1b0:
5152 case 0x1b1: /* cmpxchg Ev, Gv */
cad3a37d 5153 {
1130328e 5154 int label1, label2;
1e4840bf 5155 TCGv t0, t1, t2, a0;
cad3a37d 5156
ab4e4aec 5157 ot = mo_b_d(b, dflag);
0af10c86 5158 modrm = cpu_ldub_code(env, s->pc++);
cad3a37d
FB
5159 reg = ((modrm >> 3) & 7) | rex_r;
5160 mod = (modrm >> 6) & 3;
a7812ae4
PB
5161 t0 = tcg_temp_local_new();
5162 t1 = tcg_temp_local_new();
5163 t2 = tcg_temp_local_new();
5164 a0 = tcg_temp_local_new();
1e4840bf 5165 gen_op_mov_v_reg(ot, t1, reg);
cad3a37d
FB
5166 if (mod == 3) {
5167 rm = (modrm & 7) | REX_B(s);
1e4840bf 5168 gen_op_mov_v_reg(ot, t0, rm);
cad3a37d 5169 } else {
4eeb3939 5170 gen_lea_modrm(env, s, modrm);
1e4840bf 5171 tcg_gen_mov_tl(a0, cpu_A0);
323d1876 5172 gen_op_ld_v(s, ot, t0, a0);
cad3a37d
FB
5173 rm = 0; /* avoid warning */
5174 }
5175 label1 = gen_new_label();
a3251186
RH
5176 tcg_gen_mov_tl(t2, cpu_regs[R_EAX]);
5177 gen_extu(ot, t0);
1e4840bf 5178 gen_extu(ot, t2);
a3251186 5179 tcg_gen_brcond_tl(TCG_COND_EQ, t2, t0, label1);
f7e80adf 5180 label2 = gen_new_label();
cad3a37d 5181 if (mod == 3) {
1e4840bf 5182 gen_op_mov_reg_v(ot, R_EAX, t0);
1130328e
FB
5183 tcg_gen_br(label2);
5184 gen_set_label(label1);
1e4840bf 5185 gen_op_mov_reg_v(ot, rm, t1);
cad3a37d 5186 } else {
f7e80adf
AG
5187 /* perform no-op store cycle like physical cpu; must be
5188 before changing accumulator to ensure idempotency if
5189 the store faults and the instruction is restarted */
323d1876 5190 gen_op_st_v(s, ot, t0, a0);
1e4840bf 5191 gen_op_mov_reg_v(ot, R_EAX, t0);
f7e80adf 5192 tcg_gen_br(label2);
1130328e 5193 gen_set_label(label1);
323d1876 5194 gen_op_st_v(s, ot, t1, a0);
cad3a37d 5195 }
f7e80adf 5196 gen_set_label(label2);
1e4840bf 5197 tcg_gen_mov_tl(cpu_cc_src, t0);
a3251186
RH
5198 tcg_gen_mov_tl(cpu_cc_srcT, t2);
5199 tcg_gen_sub_tl(cpu_cc_dst, t2, t0);
3ca51d07 5200 set_cc_op(s, CC_OP_SUBB + ot);
1e4840bf
FB
5201 tcg_temp_free(t0);
5202 tcg_temp_free(t1);
5203 tcg_temp_free(t2);
5204 tcg_temp_free(a0);
2c0262af 5205 }
2c0262af
FB
5206 break;
5207 case 0x1c7: /* cmpxchg8b */
0af10c86 5208 modrm = cpu_ldub_code(env, s->pc++);
2c0262af 5209 mod = (modrm >> 6) & 3;
71c3558e 5210 if ((mod == 3) || ((modrm & 0x38) != 0x8))
2c0262af 5211 goto illegal_op;
1b9d9ebb 5212#ifdef TARGET_X86_64
ab4e4aec 5213 if (dflag == MO_64) {
1b9d9ebb
FB
5214 if (!(s->cpuid_ext_features & CPUID_EXT_CX16))
5215 goto illegal_op;
5216 gen_jmp_im(pc_start - s->cs_base);
773cdfcc 5217 gen_update_cc_op(s);
4eeb3939 5218 gen_lea_modrm(env, s, modrm);
92fc4b58 5219 gen_helper_cmpxchg16b(cpu_env, cpu_A0);
1b9d9ebb
FB
5220 } else
5221#endif
5222 {
5223 if (!(s->cpuid_features & CPUID_CX8))
5224 goto illegal_op;
5225 gen_jmp_im(pc_start - s->cs_base);
773cdfcc 5226 gen_update_cc_op(s);
4eeb3939 5227 gen_lea_modrm(env, s, modrm);
92fc4b58 5228 gen_helper_cmpxchg8b(cpu_env, cpu_A0);
1b9d9ebb 5229 }
3ca51d07 5230 set_cc_op(s, CC_OP_EFLAGS);
2c0262af 5231 break;
3b46e624 5232
2c0262af
FB
5233 /**************************/
5234 /* push/pop */
5235 case 0x50 ... 0x57: /* push */
c56baccf 5236 gen_op_mov_v_reg(MO_32, cpu_T[0], (b & 7) | REX_B(s));
432baffe 5237 gen_push_v(s, cpu_T[0]);
2c0262af
FB
5238 break;
5239 case 0x58 ... 0x5f: /* pop */
8e31d234 5240 ot = gen_pop_T0(s);
77729c24 5241 /* NOTE: order is important for pop %sp */
8e31d234 5242 gen_pop_update(s, ot);
480a762d 5243 gen_op_mov_reg_v(ot, (b & 7) | REX_B(s), cpu_T[0]);
2c0262af
FB
5244 break;
5245 case 0x60: /* pusha */
14ce26e7
FB
5246 if (CODE64(s))
5247 goto illegal_op;
2c0262af
FB
5248 gen_pusha(s);
5249 break;
5250 case 0x61: /* popa */
14ce26e7
FB
5251 if (CODE64(s))
5252 goto illegal_op;
2c0262af
FB
5253 gen_popa(s);
5254 break;
5255 case 0x68: /* push Iv */
5256 case 0x6a:
ab4e4aec 5257 ot = mo_pushpop(s, dflag);
2c0262af 5258 if (b == 0x68)
0af10c86 5259 val = insn_get(env, s, ot);
2c0262af 5260 else
4ba9938c 5261 val = (int8_t)insn_get(env, s, MO_8);
1b90d56e 5262 tcg_gen_movi_tl(cpu_T[0], val);
432baffe 5263 gen_push_v(s, cpu_T[0]);
2c0262af
FB
5264 break;
5265 case 0x8f: /* pop Ev */
0af10c86 5266 modrm = cpu_ldub_code(env, s->pc++);
77729c24 5267 mod = (modrm >> 6) & 3;
8e31d234 5268 ot = gen_pop_T0(s);
77729c24
FB
5269 if (mod == 3) {
5270 /* NOTE: order is important for pop %sp */
8e31d234 5271 gen_pop_update(s, ot);
14ce26e7 5272 rm = (modrm & 7) | REX_B(s);
480a762d 5273 gen_op_mov_reg_v(ot, rm, cpu_T[0]);
77729c24
FB
5274 } else {
5275 /* NOTE: order is important too for MMU exceptions */
14ce26e7 5276 s->popl_esp_hack = 1 << ot;
0af10c86 5277 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
77729c24 5278 s->popl_esp_hack = 0;
8e31d234 5279 gen_pop_update(s, ot);
77729c24 5280 }
2c0262af
FB
5281 break;
5282 case 0xc8: /* enter */
5283 {
5284 int level;
0af10c86 5285 val = cpu_lduw_code(env, s->pc);
2c0262af 5286 s->pc += 2;
0af10c86 5287 level = cpu_ldub_code(env, s->pc++);
2c0262af
FB
5288 gen_enter(s, val, level);
5289 }
5290 break;
5291 case 0xc9: /* leave */
5292 /* XXX: exception not precise (ESP is updated before potential exception) */
14ce26e7 5293 if (CODE64(s)) {
c56baccf 5294 gen_op_mov_v_reg(MO_64, cpu_T[0], R_EBP);
480a762d 5295 gen_op_mov_reg_v(MO_64, R_ESP, cpu_T[0]);
14ce26e7 5296 } else if (s->ss32) {
c56baccf 5297 gen_op_mov_v_reg(MO_32, cpu_T[0], R_EBP);
480a762d 5298 gen_op_mov_reg_v(MO_32, R_ESP, cpu_T[0]);
2c0262af 5299 } else {
c56baccf 5300 gen_op_mov_v_reg(MO_16, cpu_T[0], R_EBP);
480a762d 5301 gen_op_mov_reg_v(MO_16, R_ESP, cpu_T[0]);
2c0262af 5302 }
8e31d234 5303 ot = gen_pop_T0(s);
480a762d 5304 gen_op_mov_reg_v(ot, R_EBP, cpu_T[0]);
8e31d234 5305 gen_pop_update(s, ot);
2c0262af
FB
5306 break;
5307 case 0x06: /* push es */
5308 case 0x0e: /* push cs */
5309 case 0x16: /* push ss */
5310 case 0x1e: /* push ds */
14ce26e7
FB
5311 if (CODE64(s))
5312 goto illegal_op;
2c0262af 5313 gen_op_movl_T0_seg(b >> 3);
432baffe 5314 gen_push_v(s, cpu_T[0]);
2c0262af
FB
5315 break;
5316 case 0x1a0: /* push fs */
5317 case 0x1a8: /* push gs */
5318 gen_op_movl_T0_seg((b >> 3) & 7);
432baffe 5319 gen_push_v(s, cpu_T[0]);
2c0262af
FB
5320 break;
5321 case 0x07: /* pop es */
5322 case 0x17: /* pop ss */
5323 case 0x1f: /* pop ds */
14ce26e7
FB
5324 if (CODE64(s))
5325 goto illegal_op;
2c0262af 5326 reg = b >> 3;
8e31d234 5327 ot = gen_pop_T0(s);
2c0262af 5328 gen_movl_seg_T0(s, reg, pc_start - s->cs_base);
8e31d234 5329 gen_pop_update(s, ot);
2c0262af 5330 if (reg == R_SS) {
a2cc3b24
FB
5331 /* if reg == SS, inhibit interrupts/trace. */
5332 /* If several instructions disable interrupts, only the
5333 _first_ does it */
5334 if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
f0967a1a 5335 gen_helper_set_inhibit_irq(cpu_env);
2c0262af
FB
5336 s->tf = 0;
5337 }
5338 if (s->is_jmp) {
14ce26e7 5339 gen_jmp_im(s->pc - s->cs_base);
2c0262af
FB
5340 gen_eob(s);
5341 }
5342 break;
5343 case 0x1a1: /* pop fs */
5344 case 0x1a9: /* pop gs */
8e31d234 5345 ot = gen_pop_T0(s);
2c0262af 5346 gen_movl_seg_T0(s, (b >> 3) & 7, pc_start - s->cs_base);
8e31d234 5347 gen_pop_update(s, ot);
2c0262af 5348 if (s->is_jmp) {
14ce26e7 5349 gen_jmp_im(s->pc - s->cs_base);
2c0262af
FB
5350 gen_eob(s);
5351 }
5352 break;
5353
5354 /**************************/
5355 /* mov */
5356 case 0x88:
5357 case 0x89: /* mov Gv, Ev */
ab4e4aec 5358 ot = mo_b_d(b, dflag);
0af10c86 5359 modrm = cpu_ldub_code(env, s->pc++);
14ce26e7 5360 reg = ((modrm >> 3) & 7) | rex_r;
3b46e624 5361
2c0262af 5362 /* generate a generic store */
0af10c86 5363 gen_ldst_modrm(env, s, modrm, ot, reg, 1);
2c0262af
FB
5364 break;
5365 case 0xc6:
5366 case 0xc7: /* mov Ev, Iv */
ab4e4aec 5367 ot = mo_b_d(b, dflag);
0af10c86 5368 modrm = cpu_ldub_code(env, s->pc++);
2c0262af 5369 mod = (modrm >> 6) & 3;
14ce26e7
FB
5370 if (mod != 3) {
5371 s->rip_offset = insn_const_size(ot);
4eeb3939 5372 gen_lea_modrm(env, s, modrm);
14ce26e7 5373 }
0af10c86 5374 val = insn_get(env, s, ot);
1b90d56e 5375 tcg_gen_movi_tl(cpu_T[0], val);
fd8ca9f6
RH
5376 if (mod != 3) {
5377 gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
5378 } else {
480a762d 5379 gen_op_mov_reg_v(ot, (modrm & 7) | REX_B(s), cpu_T[0]);
fd8ca9f6 5380 }
2c0262af
FB
5381 break;
5382 case 0x8a:
5383 case 0x8b: /* mov Ev, Gv */
ab4e4aec 5384 ot = mo_b_d(b, dflag);
0af10c86 5385 modrm = cpu_ldub_code(env, s->pc++);
14ce26e7 5386 reg = ((modrm >> 3) & 7) | rex_r;
3b46e624 5387
0af10c86 5388 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
480a762d 5389 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
2c0262af
FB
5390 break;
5391 case 0x8e: /* mov seg, Gv */
0af10c86 5392 modrm = cpu_ldub_code(env, s->pc++);
2c0262af
FB
5393 reg = (modrm >> 3) & 7;
5394 if (reg >= 6 || reg == R_CS)
5395 goto illegal_op;
4ba9938c 5396 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
2c0262af
FB
5397 gen_movl_seg_T0(s, reg, pc_start - s->cs_base);
5398 if (reg == R_SS) {
5399 /* if reg == SS, inhibit interrupts/trace */
a2cc3b24
FB
5400 /* If several instructions disable interrupts, only the
5401 _first_ does it */
5402 if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
f0967a1a 5403 gen_helper_set_inhibit_irq(cpu_env);
2c0262af
FB
5404 s->tf = 0;
5405 }
5406 if (s->is_jmp) {
14ce26e7 5407 gen_jmp_im(s->pc - s->cs_base);
2c0262af
FB
5408 gen_eob(s);
5409 }
5410 break;
5411 case 0x8c: /* mov Gv, seg */
0af10c86 5412 modrm = cpu_ldub_code(env, s->pc++);
2c0262af
FB
5413 reg = (modrm >> 3) & 7;
5414 mod = (modrm >> 6) & 3;
5415 if (reg >= 6)
5416 goto illegal_op;
5417 gen_op_movl_T0_seg(reg);
ab4e4aec 5418 ot = mod == 3 ? dflag : MO_16;
0af10c86 5419 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
2c0262af
FB
5420 break;
5421
5422 case 0x1b6: /* movzbS Gv, Eb */
5423 case 0x1b7: /* movzwS Gv, Eb */
5424 case 0x1be: /* movsbS Gv, Eb */
5425 case 0x1bf: /* movswS Gv, Eb */
5426 {
c8fbc479
RH
5427 TCGMemOp d_ot;
5428 TCGMemOp s_ot;
5429
2c0262af 5430 /* d_ot is the size of destination */
ab4e4aec 5431 d_ot = dflag;
2c0262af 5432 /* ot is the size of source */
4ba9938c 5433 ot = (b & 1) + MO_8;
c8fbc479
RH
5434 /* s_ot is the sign+size of source */
5435 s_ot = b & 8 ? MO_SIGN | ot : ot;
5436
0af10c86 5437 modrm = cpu_ldub_code(env, s->pc++);
14ce26e7 5438 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af 5439 mod = (modrm >> 6) & 3;
14ce26e7 5440 rm = (modrm & 7) | REX_B(s);
3b46e624 5441
2c0262af 5442 if (mod == 3) {
c56baccf 5443 gen_op_mov_v_reg(ot, cpu_T[0], rm);
c8fbc479
RH
5444 switch (s_ot) {
5445 case MO_UB:
e108dd01 5446 tcg_gen_ext8u_tl(cpu_T[0], cpu_T[0]);
2c0262af 5447 break;
c8fbc479 5448 case MO_SB:
e108dd01 5449 tcg_gen_ext8s_tl(cpu_T[0], cpu_T[0]);
2c0262af 5450 break;
c8fbc479 5451 case MO_UW:
e108dd01 5452 tcg_gen_ext16u_tl(cpu_T[0], cpu_T[0]);
2c0262af
FB
5453 break;
5454 default:
c8fbc479 5455 case MO_SW:
e108dd01 5456 tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
2c0262af
FB
5457 break;
5458 }
480a762d 5459 gen_op_mov_reg_v(d_ot, reg, cpu_T[0]);
2c0262af 5460 } else {
4eeb3939 5461 gen_lea_modrm(env, s, modrm);
c8fbc479 5462 gen_op_ld_v(s, s_ot, cpu_T[0], cpu_A0);
480a762d 5463 gen_op_mov_reg_v(d_ot, reg, cpu_T[0]);
2c0262af
FB
5464 }
5465 }
5466 break;
5467
5468 case 0x8d: /* lea */
ab4e4aec 5469 ot = dflag;
0af10c86 5470 modrm = cpu_ldub_code(env, s->pc++);
3a1d9b8b
FB
5471 mod = (modrm >> 6) & 3;
5472 if (mod == 3)
5473 goto illegal_op;
14ce26e7 5474 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af
FB
5475 /* we must ensure that no segment is added */
5476 s->override = -1;
5477 val = s->addseg;
5478 s->addseg = 0;
4eeb3939 5479 gen_lea_modrm(env, s, modrm);
2c0262af 5480 s->addseg = val;
33b7891b 5481 gen_op_mov_reg_v(ot, reg, cpu_A0);
2c0262af 5482 break;
3b46e624 5483
2c0262af
FB
5484 case 0xa0: /* mov EAX, Ov */
5485 case 0xa1:
5486 case 0xa2: /* mov Ov, EAX */
5487 case 0xa3:
2c0262af 5488 {
14ce26e7
FB
5489 target_ulong offset_addr;
5490
ab4e4aec 5491 ot = mo_b_d(b, dflag);
1d71ddb1 5492 switch (s->aflag) {
14ce26e7 5493#ifdef TARGET_X86_64
1d71ddb1 5494 case MO_64:
0af10c86 5495 offset_addr = cpu_ldq_code(env, s->pc);
14ce26e7 5496 s->pc += 8;
1d71ddb1 5497 break;
14ce26e7 5498#endif
1d71ddb1
RH
5499 default:
5500 offset_addr = insn_get(env, s, s->aflag);
5501 break;
14ce26e7 5502 }
3250cff8 5503 tcg_gen_movi_tl(cpu_A0, offset_addr);
664e0f19 5504 gen_add_A0_ds_seg(s);
14ce26e7 5505 if ((b & 2) == 0) {
909be183 5506 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
480a762d 5507 gen_op_mov_reg_v(ot, R_EAX, cpu_T[0]);
14ce26e7 5508 } else {
c56baccf 5509 gen_op_mov_v_reg(ot, cpu_T[0], R_EAX);
fd8ca9f6 5510 gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
2c0262af
FB
5511 }
5512 }
2c0262af
FB
5513 break;
5514 case 0xd7: /* xlat */
1d71ddb1
RH
5515 tcg_gen_mov_tl(cpu_A0, cpu_regs[R_EBX]);
5516 tcg_gen_ext8u_tl(cpu_T[0], cpu_regs[R_EAX]);
5517 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_T[0]);
5518 gen_extu(s->aflag, cpu_A0);
664e0f19 5519 gen_add_A0_ds_seg(s);
cc1a80df 5520 gen_op_ld_v(s, MO_8, cpu_T[0], cpu_A0);
480a762d 5521 gen_op_mov_reg_v(MO_8, R_EAX, cpu_T[0]);
2c0262af
FB
5522 break;
5523 case 0xb0 ... 0xb7: /* mov R, Ib */
4ba9938c 5524 val = insn_get(env, s, MO_8);
1b90d56e 5525 tcg_gen_movi_tl(cpu_T[0], val);
480a762d 5526 gen_op_mov_reg_v(MO_8, (b & 7) | REX_B(s), cpu_T[0]);
2c0262af
FB
5527 break;
5528 case 0xb8 ... 0xbf: /* mov R, Iv */
14ce26e7 5529#ifdef TARGET_X86_64
ab4e4aec 5530 if (dflag == MO_64) {
14ce26e7
FB
5531 uint64_t tmp;
5532 /* 64 bit case */
0af10c86 5533 tmp = cpu_ldq_code(env, s->pc);
14ce26e7
FB
5534 s->pc += 8;
5535 reg = (b & 7) | REX_B(s);
cc0bce88 5536 tcg_gen_movi_tl(cpu_T[0], tmp);
480a762d 5537 gen_op_mov_reg_v(MO_64, reg, cpu_T[0]);
5fafdf24 5538 } else
14ce26e7
FB
5539#endif
5540 {
ab4e4aec 5541 ot = dflag;
0af10c86 5542 val = insn_get(env, s, ot);
14ce26e7 5543 reg = (b & 7) | REX_B(s);
1b90d56e 5544 tcg_gen_movi_tl(cpu_T[0], val);
480a762d 5545 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
14ce26e7 5546 }
2c0262af
FB
5547 break;
5548
5549 case 0x91 ... 0x97: /* xchg R, EAX */
7418027e 5550 do_xchg_reg_eax:
ab4e4aec 5551 ot = dflag;
14ce26e7 5552 reg = (b & 7) | REX_B(s);
2c0262af
FB
5553 rm = R_EAX;
5554 goto do_xchg_reg;
5555 case 0x86:
5556 case 0x87: /* xchg Ev, Gv */
ab4e4aec 5557 ot = mo_b_d(b, dflag);
0af10c86 5558 modrm = cpu_ldub_code(env, s->pc++);
14ce26e7 5559 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af
FB
5560 mod = (modrm >> 6) & 3;
5561 if (mod == 3) {
14ce26e7 5562 rm = (modrm & 7) | REX_B(s);
2c0262af 5563 do_xchg_reg:
c56baccf
RH
5564 gen_op_mov_v_reg(ot, cpu_T[0], reg);
5565 gen_op_mov_v_reg(ot, cpu_T[1], rm);
480a762d 5566 gen_op_mov_reg_v(ot, rm, cpu_T[0]);
68773f84 5567 gen_op_mov_reg_v(ot, reg, cpu_T[1]);
2c0262af 5568 } else {
4eeb3939 5569 gen_lea_modrm(env, s, modrm);
c56baccf 5570 gen_op_mov_v_reg(ot, cpu_T[0], reg);
2c0262af
FB
5571 /* for xchg, lock is implicit */
5572 if (!(prefixes & PREFIX_LOCK))
a7812ae4 5573 gen_helper_lock();
0f712e10 5574 gen_op_ld_v(s, ot, cpu_T[1], cpu_A0);
fd8ca9f6 5575 gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
2c0262af 5576 if (!(prefixes & PREFIX_LOCK))
a7812ae4 5577 gen_helper_unlock();
68773f84 5578 gen_op_mov_reg_v(ot, reg, cpu_T[1]);
2c0262af
FB
5579 }
5580 break;
5581 case 0xc4: /* les Gv */
701ed211 5582 /* In CODE64 this is VEX3; see above. */
2c0262af
FB
5583 op = R_ES;
5584 goto do_lxx;
5585 case 0xc5: /* lds Gv */
701ed211 5586 /* In CODE64 this is VEX2; see above. */
2c0262af
FB
5587 op = R_DS;
5588 goto do_lxx;
5589 case 0x1b2: /* lss Gv */
5590 op = R_SS;
5591 goto do_lxx;
5592 case 0x1b4: /* lfs Gv */
5593 op = R_FS;
5594 goto do_lxx;
5595 case 0x1b5: /* lgs Gv */
5596 op = R_GS;
5597 do_lxx:
ab4e4aec 5598 ot = dflag != MO_16 ? MO_32 : MO_16;
0af10c86 5599 modrm = cpu_ldub_code(env, s->pc++);
14ce26e7 5600 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af
FB
5601 mod = (modrm >> 6) & 3;
5602 if (mod == 3)
5603 goto illegal_op;
4eeb3939 5604 gen_lea_modrm(env, s, modrm);
0f712e10 5605 gen_op_ld_v(s, ot, cpu_T[1], cpu_A0);
830a19a4 5606 gen_add_A0_im(s, 1 << ot);
2c0262af 5607 /* load the segment first to handle exceptions properly */
cc1a80df 5608 gen_op_ld_v(s, MO_16, cpu_T[0], cpu_A0);
2c0262af
FB
5609 gen_movl_seg_T0(s, op, pc_start - s->cs_base);
5610 /* then put the data */
68773f84 5611 gen_op_mov_reg_v(ot, reg, cpu_T[1]);
2c0262af 5612 if (s->is_jmp) {
14ce26e7 5613 gen_jmp_im(s->pc - s->cs_base);
2c0262af
FB
5614 gen_eob(s);
5615 }
5616 break;
3b46e624 5617
2c0262af
FB
5618 /************************/
5619 /* shifts */
5620 case 0xc0:
5621 case 0xc1:
5622 /* shift Ev,Ib */
5623 shift = 2;
5624 grp2:
5625 {
ab4e4aec 5626 ot = mo_b_d(b, dflag);
0af10c86 5627 modrm = cpu_ldub_code(env, s->pc++);
2c0262af 5628 mod = (modrm >> 6) & 3;
2c0262af 5629 op = (modrm >> 3) & 7;
3b46e624 5630
2c0262af 5631 if (mod != 3) {
14ce26e7
FB
5632 if (shift == 2) {
5633 s->rip_offset = 1;
5634 }
4eeb3939 5635 gen_lea_modrm(env, s, modrm);
2c0262af
FB
5636 opreg = OR_TMP0;
5637 } else {
14ce26e7 5638 opreg = (modrm & 7) | REX_B(s);
2c0262af
FB
5639 }
5640
5641 /* simpler op */
5642 if (shift == 0) {
5643 gen_shift(s, op, ot, opreg, OR_ECX);
5644 } else {
5645 if (shift == 2) {
0af10c86 5646 shift = cpu_ldub_code(env, s->pc++);
2c0262af
FB
5647 }
5648 gen_shifti(s, op, ot, opreg, shift);
5649 }
5650 }
5651 break;
5652 case 0xd0:
5653 case 0xd1:
5654 /* shift Ev,1 */
5655 shift = 1;
5656 goto grp2;
5657 case 0xd2:
5658 case 0xd3:
5659 /* shift Ev,cl */
5660 shift = 0;
5661 goto grp2;
5662
5663 case 0x1a4: /* shld imm */
5664 op = 0;
5665 shift = 1;
5666 goto do_shiftd;
5667 case 0x1a5: /* shld cl */
5668 op = 0;
5669 shift = 0;
5670 goto do_shiftd;
5671 case 0x1ac: /* shrd imm */
5672 op = 1;
5673 shift = 1;
5674 goto do_shiftd;
5675 case 0x1ad: /* shrd cl */
5676 op = 1;
5677 shift = 0;
5678 do_shiftd:
ab4e4aec 5679 ot = dflag;
0af10c86 5680 modrm = cpu_ldub_code(env, s->pc++);
2c0262af 5681 mod = (modrm >> 6) & 3;
14ce26e7
FB
5682 rm = (modrm & 7) | REX_B(s);
5683 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af 5684 if (mod != 3) {
4eeb3939 5685 gen_lea_modrm(env, s, modrm);
b6abf97d 5686 opreg = OR_TMP0;
2c0262af 5687 } else {
b6abf97d 5688 opreg = rm;
2c0262af 5689 }
c56baccf 5690 gen_op_mov_v_reg(ot, cpu_T[1], reg);
3b46e624 5691
2c0262af 5692 if (shift) {
3b9d3cf1
PB
5693 TCGv imm = tcg_const_tl(cpu_ldub_code(env, s->pc++));
5694 gen_shiftd_rm_T1(s, ot, opreg, op, imm);
5695 tcg_temp_free(imm);
2c0262af 5696 } else {
3b9d3cf1 5697 gen_shiftd_rm_T1(s, ot, opreg, op, cpu_regs[R_ECX]);
2c0262af
FB
5698 }
5699 break;
5700
5701 /************************/
5702 /* floats */
5fafdf24 5703 case 0xd8 ... 0xdf:
7eee2a50
FB
5704 if (s->flags & (HF_EM_MASK | HF_TS_MASK)) {
5705 /* if CR0.EM or CR0.TS are set, generate an FPU exception */
5706 /* XXX: what to do if illegal op ? */
5707 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
5708 break;
5709 }
0af10c86 5710 modrm = cpu_ldub_code(env, s->pc++);
2c0262af
FB
5711 mod = (modrm >> 6) & 3;
5712 rm = modrm & 7;
5713 op = ((b & 7) << 3) | ((modrm >> 3) & 7);
2c0262af
FB
5714 if (mod != 3) {
5715 /* memory op */
4eeb3939 5716 gen_lea_modrm(env, s, modrm);
2c0262af
FB
5717 switch(op) {
5718 case 0x00 ... 0x07: /* fxxxs */
5719 case 0x10 ... 0x17: /* fixxxl */
5720 case 0x20 ... 0x27: /* fxxxl */
5721 case 0x30 ... 0x37: /* fixxx */
5722 {
5723 int op1;
5724 op1 = op & 7;
5725
5726 switch(op >> 4) {
5727 case 0:
80b02013
RH
5728 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5729 s->mem_index, MO_LEUL);
d3eb5eae 5730 gen_helper_flds_FT0(cpu_env, cpu_tmp2_i32);
2c0262af
FB
5731 break;
5732 case 1:
80b02013
RH
5733 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5734 s->mem_index, MO_LEUL);
d3eb5eae 5735 gen_helper_fildl_FT0(cpu_env, cpu_tmp2_i32);
2c0262af
FB
5736 break;
5737 case 2:
3c5f4116
RH
5738 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_A0,
5739 s->mem_index, MO_LEQ);
d3eb5eae 5740 gen_helper_fldl_FT0(cpu_env, cpu_tmp1_i64);
2c0262af
FB
5741 break;
5742 case 3:
5743 default:
80b02013
RH
5744 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5745 s->mem_index, MO_LESW);
d3eb5eae 5746 gen_helper_fildl_FT0(cpu_env, cpu_tmp2_i32);
2c0262af
FB
5747 break;
5748 }
3b46e624 5749
a7812ae4 5750 gen_helper_fp_arith_ST0_FT0(op1);
2c0262af
FB
5751 if (op1 == 3) {
5752 /* fcomp needs pop */
d3eb5eae 5753 gen_helper_fpop(cpu_env);
2c0262af
FB
5754 }
5755 }
5756 break;
5757 case 0x08: /* flds */
5758 case 0x0a: /* fsts */
5759 case 0x0b: /* fstps */
465e9838
FB
5760 case 0x18 ... 0x1b: /* fildl, fisttpl, fistl, fistpl */
5761 case 0x28 ... 0x2b: /* fldl, fisttpll, fstl, fstpl */
5762 case 0x38 ... 0x3b: /* filds, fisttps, fists, fistps */
2c0262af
FB
5763 switch(op & 7) {
5764 case 0:
5765 switch(op >> 4) {
5766 case 0:
80b02013
RH
5767 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5768 s->mem_index, MO_LEUL);
d3eb5eae 5769 gen_helper_flds_ST0(cpu_env, cpu_tmp2_i32);
2c0262af
FB
5770 break;
5771 case 1:
80b02013
RH
5772 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5773 s->mem_index, MO_LEUL);
d3eb5eae 5774 gen_helper_fildl_ST0(cpu_env, cpu_tmp2_i32);
2c0262af
FB
5775 break;
5776 case 2:
3c5f4116
RH
5777 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_A0,
5778 s->mem_index, MO_LEQ);
d3eb5eae 5779 gen_helper_fldl_ST0(cpu_env, cpu_tmp1_i64);
2c0262af
FB
5780 break;
5781 case 3:
5782 default:
80b02013
RH
5783 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5784 s->mem_index, MO_LESW);
d3eb5eae 5785 gen_helper_fildl_ST0(cpu_env, cpu_tmp2_i32);
2c0262af
FB
5786 break;
5787 }
5788 break;
465e9838 5789 case 1:
19e6c4b8 5790 /* XXX: the corresponding CPUID bit must be tested ! */
465e9838
FB
5791 switch(op >> 4) {
5792 case 1:
d3eb5eae 5793 gen_helper_fisttl_ST0(cpu_tmp2_i32, cpu_env);
d5601ad0
RH
5794 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5795 s->mem_index, MO_LEUL);
465e9838
FB
5796 break;
5797 case 2:
d3eb5eae 5798 gen_helper_fisttll_ST0(cpu_tmp1_i64, cpu_env);
3523e4bd
RH
5799 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0,
5800 s->mem_index, MO_LEQ);
465e9838
FB
5801 break;
5802 case 3:
5803 default:
d3eb5eae 5804 gen_helper_fistt_ST0(cpu_tmp2_i32, cpu_env);
d5601ad0
RH
5805 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5806 s->mem_index, MO_LEUW);
19e6c4b8 5807 break;
465e9838 5808 }
d3eb5eae 5809 gen_helper_fpop(cpu_env);
465e9838 5810 break;
2c0262af
FB
5811 default:
5812 switch(op >> 4) {
5813 case 0:
d3eb5eae 5814 gen_helper_fsts_ST0(cpu_tmp2_i32, cpu_env);
d5601ad0
RH
5815 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5816 s->mem_index, MO_LEUL);
2c0262af
FB
5817 break;
5818 case 1:
d3eb5eae 5819 gen_helper_fistl_ST0(cpu_tmp2_i32, cpu_env);
d5601ad0
RH
5820 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5821 s->mem_index, MO_LEUL);
2c0262af
FB
5822 break;
5823 case 2:
d3eb5eae 5824 gen_helper_fstl_ST0(cpu_tmp1_i64, cpu_env);
3523e4bd
RH
5825 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0,
5826 s->mem_index, MO_LEQ);
2c0262af
FB
5827 break;
5828 case 3:
5829 default:
d3eb5eae 5830 gen_helper_fist_ST0(cpu_tmp2_i32, cpu_env);
d5601ad0
RH
5831 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5832 s->mem_index, MO_LEUW);
2c0262af
FB
5833 break;
5834 }
5835 if ((op & 7) == 3)
d3eb5eae 5836 gen_helper_fpop(cpu_env);
2c0262af
FB
5837 break;
5838 }
5839 break;
5840 case 0x0c: /* fldenv mem */
773cdfcc 5841 gen_update_cc_op(s);
19e6c4b8 5842 gen_jmp_im(pc_start - s->cs_base);
ab4e4aec 5843 gen_helper_fldenv(cpu_env, cpu_A0, tcg_const_i32(dflag - 1));
2c0262af
FB
5844 break;
5845 case 0x0d: /* fldcw mem */
80b02013
RH
5846 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5847 s->mem_index, MO_LEUW);
d3eb5eae 5848 gen_helper_fldcw(cpu_env, cpu_tmp2_i32);
2c0262af
FB
5849 break;
5850 case 0x0e: /* fnstenv mem */
773cdfcc 5851 gen_update_cc_op(s);
19e6c4b8 5852 gen_jmp_im(pc_start - s->cs_base);
ab4e4aec 5853 gen_helper_fstenv(cpu_env, cpu_A0, tcg_const_i32(dflag - 1));
2c0262af
FB
5854 break;
5855 case 0x0f: /* fnstcw mem */
d3eb5eae 5856 gen_helper_fnstcw(cpu_tmp2_i32, cpu_env);
d5601ad0
RH
5857 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5858 s->mem_index, MO_LEUW);
2c0262af
FB
5859 break;
5860 case 0x1d: /* fldt mem */
773cdfcc 5861 gen_update_cc_op(s);
19e6c4b8 5862 gen_jmp_im(pc_start - s->cs_base);
d3eb5eae 5863 gen_helper_fldt_ST0(cpu_env, cpu_A0);
2c0262af
FB
5864 break;
5865 case 0x1f: /* fstpt mem */
773cdfcc 5866 gen_update_cc_op(s);
19e6c4b8 5867 gen_jmp_im(pc_start - s->cs_base);
d3eb5eae
BS
5868 gen_helper_fstt_ST0(cpu_env, cpu_A0);
5869 gen_helper_fpop(cpu_env);
2c0262af
FB
5870 break;
5871 case 0x2c: /* frstor mem */
773cdfcc 5872 gen_update_cc_op(s);
19e6c4b8 5873 gen_jmp_im(pc_start - s->cs_base);
ab4e4aec 5874 gen_helper_frstor(cpu_env, cpu_A0, tcg_const_i32(dflag - 1));
2c0262af
FB
5875 break;
5876 case 0x2e: /* fnsave mem */
773cdfcc 5877 gen_update_cc_op(s);
19e6c4b8 5878 gen_jmp_im(pc_start - s->cs_base);
ab4e4aec 5879 gen_helper_fsave(cpu_env, cpu_A0, tcg_const_i32(dflag - 1));
2c0262af
FB
5880 break;
5881 case 0x2f: /* fnstsw mem */
d3eb5eae 5882 gen_helper_fnstsw(cpu_tmp2_i32, cpu_env);
d5601ad0
RH
5883 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5884 s->mem_index, MO_LEUW);
2c0262af
FB
5885 break;
5886 case 0x3c: /* fbld */
773cdfcc 5887 gen_update_cc_op(s);
19e6c4b8 5888 gen_jmp_im(pc_start - s->cs_base);
d3eb5eae 5889 gen_helper_fbld_ST0(cpu_env, cpu_A0);
2c0262af
FB
5890 break;
5891 case 0x3e: /* fbstp */
773cdfcc 5892 gen_update_cc_op(s);
19e6c4b8 5893 gen_jmp_im(pc_start - s->cs_base);
d3eb5eae
BS
5894 gen_helper_fbst_ST0(cpu_env, cpu_A0);
5895 gen_helper_fpop(cpu_env);
2c0262af
FB
5896 break;
5897 case 0x3d: /* fildll */
3c5f4116 5898 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_A0, s->mem_index, MO_LEQ);
d3eb5eae 5899 gen_helper_fildll_ST0(cpu_env, cpu_tmp1_i64);
2c0262af
FB
5900 break;
5901 case 0x3f: /* fistpll */
d3eb5eae 5902 gen_helper_fistll_ST0(cpu_tmp1_i64, cpu_env);
3523e4bd 5903 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0, s->mem_index, MO_LEQ);
d3eb5eae 5904 gen_helper_fpop(cpu_env);
2c0262af
FB
5905 break;
5906 default:
5907 goto illegal_op;
5908 }
5909 } else {
5910 /* register float ops */
5911 opreg = rm;
5912
5913 switch(op) {
5914 case 0x08: /* fld sti */
d3eb5eae
BS
5915 gen_helper_fpush(cpu_env);
5916 gen_helper_fmov_ST0_STN(cpu_env,
5917 tcg_const_i32((opreg + 1) & 7));
2c0262af
FB
5918 break;
5919 case 0x09: /* fxchg sti */
c169c906
FB
5920 case 0x29: /* fxchg4 sti, undocumented op */
5921 case 0x39: /* fxchg7 sti, undocumented op */
d3eb5eae 5922 gen_helper_fxchg_ST0_STN(cpu_env, tcg_const_i32(opreg));
2c0262af
FB
5923 break;
5924 case 0x0a: /* grp d9/2 */
5925 switch(rm) {
5926 case 0: /* fnop */
023fe10d 5927 /* check exceptions (FreeBSD FPU probe) */
773cdfcc 5928 gen_update_cc_op(s);
14ce26e7 5929 gen_jmp_im(pc_start - s->cs_base);
d3eb5eae 5930 gen_helper_fwait(cpu_env);
2c0262af
FB
5931 break;
5932 default:
5933 goto illegal_op;
5934 }
5935 break;
5936 case 0x0c: /* grp d9/4 */
5937 switch(rm) {
5938 case 0: /* fchs */
d3eb5eae 5939 gen_helper_fchs_ST0(cpu_env);
2c0262af
FB
5940 break;
5941 case 1: /* fabs */
d3eb5eae 5942 gen_helper_fabs_ST0(cpu_env);
2c0262af
FB
5943 break;
5944 case 4: /* ftst */
d3eb5eae
BS
5945 gen_helper_fldz_FT0(cpu_env);
5946 gen_helper_fcom_ST0_FT0(cpu_env);
2c0262af
FB
5947 break;
5948 case 5: /* fxam */
d3eb5eae 5949 gen_helper_fxam_ST0(cpu_env);
2c0262af
FB
5950 break;
5951 default:
5952 goto illegal_op;
5953 }
5954 break;
5955 case 0x0d: /* grp d9/5 */
5956 {
5957 switch(rm) {
5958 case 0:
d3eb5eae
BS
5959 gen_helper_fpush(cpu_env);
5960 gen_helper_fld1_ST0(cpu_env);
2c0262af
FB
5961 break;
5962 case 1:
d3eb5eae
BS
5963 gen_helper_fpush(cpu_env);
5964 gen_helper_fldl2t_ST0(cpu_env);
2c0262af
FB
5965 break;
5966 case 2:
d3eb5eae
BS
5967 gen_helper_fpush(cpu_env);
5968 gen_helper_fldl2e_ST0(cpu_env);
2c0262af
FB
5969 break;
5970 case 3:
d3eb5eae
BS
5971 gen_helper_fpush(cpu_env);
5972 gen_helper_fldpi_ST0(cpu_env);
2c0262af
FB
5973 break;
5974 case 4:
d3eb5eae
BS
5975 gen_helper_fpush(cpu_env);
5976 gen_helper_fldlg2_ST0(cpu_env);
2c0262af
FB
5977 break;
5978 case 5:
d3eb5eae
BS
5979 gen_helper_fpush(cpu_env);
5980 gen_helper_fldln2_ST0(cpu_env);
2c0262af
FB
5981 break;
5982 case 6:
d3eb5eae
BS
5983 gen_helper_fpush(cpu_env);
5984 gen_helper_fldz_ST0(cpu_env);
2c0262af
FB
5985 break;
5986 default:
5987 goto illegal_op;
5988 }
5989 }
5990 break;
5991 case 0x0e: /* grp d9/6 */
5992 switch(rm) {
5993 case 0: /* f2xm1 */
d3eb5eae 5994 gen_helper_f2xm1(cpu_env);
2c0262af
FB
5995 break;
5996 case 1: /* fyl2x */
d3eb5eae 5997 gen_helper_fyl2x(cpu_env);
2c0262af
FB
5998 break;
5999 case 2: /* fptan */
d3eb5eae 6000 gen_helper_fptan(cpu_env);
2c0262af
FB
6001 break;
6002 case 3: /* fpatan */
d3eb5eae 6003 gen_helper_fpatan(cpu_env);
2c0262af
FB
6004 break;
6005 case 4: /* fxtract */
d3eb5eae 6006 gen_helper_fxtract(cpu_env);
2c0262af
FB
6007 break;
6008 case 5: /* fprem1 */
d3eb5eae 6009 gen_helper_fprem1(cpu_env);
2c0262af
FB
6010 break;
6011 case 6: /* fdecstp */
d3eb5eae 6012 gen_helper_fdecstp(cpu_env);
2c0262af
FB
6013 break;
6014 default:
6015 case 7: /* fincstp */
d3eb5eae 6016 gen_helper_fincstp(cpu_env);
2c0262af
FB
6017 break;
6018 }
6019 break;
6020 case 0x0f: /* grp d9/7 */
6021 switch(rm) {
6022 case 0: /* fprem */
d3eb5eae 6023 gen_helper_fprem(cpu_env);
2c0262af
FB
6024 break;
6025 case 1: /* fyl2xp1 */
d3eb5eae 6026 gen_helper_fyl2xp1(cpu_env);
2c0262af
FB
6027 break;
6028 case 2: /* fsqrt */
d3eb5eae 6029 gen_helper_fsqrt(cpu_env);
2c0262af
FB
6030 break;
6031 case 3: /* fsincos */
d3eb5eae 6032 gen_helper_fsincos(cpu_env);
2c0262af
FB
6033 break;
6034 case 5: /* fscale */
d3eb5eae 6035 gen_helper_fscale(cpu_env);
2c0262af
FB
6036 break;
6037 case 4: /* frndint */
d3eb5eae 6038 gen_helper_frndint(cpu_env);
2c0262af
FB
6039 break;
6040 case 6: /* fsin */
d3eb5eae 6041 gen_helper_fsin(cpu_env);
2c0262af
FB
6042 break;
6043 default:
6044 case 7: /* fcos */
d3eb5eae 6045 gen_helper_fcos(cpu_env);
2c0262af
FB
6046 break;
6047 }
6048 break;
6049 case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
6050 case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
6051 case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
6052 {
6053 int op1;
3b46e624 6054
2c0262af
FB
6055 op1 = op & 7;
6056 if (op >= 0x20) {
a7812ae4 6057 gen_helper_fp_arith_STN_ST0(op1, opreg);
2c0262af 6058 if (op >= 0x30)
d3eb5eae 6059 gen_helper_fpop(cpu_env);
2c0262af 6060 } else {
d3eb5eae 6061 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
a7812ae4 6062 gen_helper_fp_arith_ST0_FT0(op1);
2c0262af
FB
6063 }
6064 }
6065 break;
6066 case 0x02: /* fcom */
c169c906 6067 case 0x22: /* fcom2, undocumented op */
d3eb5eae
BS
6068 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6069 gen_helper_fcom_ST0_FT0(cpu_env);
2c0262af
FB
6070 break;
6071 case 0x03: /* fcomp */
c169c906
FB
6072 case 0x23: /* fcomp3, undocumented op */
6073 case 0x32: /* fcomp5, undocumented op */
d3eb5eae
BS
6074 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6075 gen_helper_fcom_ST0_FT0(cpu_env);
6076 gen_helper_fpop(cpu_env);
2c0262af
FB
6077 break;
6078 case 0x15: /* da/5 */
6079 switch(rm) {
6080 case 1: /* fucompp */
d3eb5eae
BS
6081 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(1));
6082 gen_helper_fucom_ST0_FT0(cpu_env);
6083 gen_helper_fpop(cpu_env);
6084 gen_helper_fpop(cpu_env);
2c0262af
FB
6085 break;
6086 default:
6087 goto illegal_op;
6088 }
6089 break;
6090 case 0x1c:
6091 switch(rm) {
6092 case 0: /* feni (287 only, just do nop here) */
6093 break;
6094 case 1: /* fdisi (287 only, just do nop here) */
6095 break;
6096 case 2: /* fclex */
d3eb5eae 6097 gen_helper_fclex(cpu_env);
2c0262af
FB
6098 break;
6099 case 3: /* fninit */
d3eb5eae 6100 gen_helper_fninit(cpu_env);
2c0262af
FB
6101 break;
6102 case 4: /* fsetpm (287 only, just do nop here) */
6103 break;
6104 default:
6105 goto illegal_op;
6106 }
6107 break;
6108 case 0x1d: /* fucomi */
bff93281
PM
6109 if (!(s->cpuid_features & CPUID_CMOV)) {
6110 goto illegal_op;
6111 }
773cdfcc 6112 gen_update_cc_op(s);
d3eb5eae
BS
6113 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6114 gen_helper_fucomi_ST0_FT0(cpu_env);
3ca51d07 6115 set_cc_op(s, CC_OP_EFLAGS);
2c0262af
FB
6116 break;
6117 case 0x1e: /* fcomi */
bff93281
PM
6118 if (!(s->cpuid_features & CPUID_CMOV)) {
6119 goto illegal_op;
6120 }
773cdfcc 6121 gen_update_cc_op(s);
d3eb5eae
BS
6122 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6123 gen_helper_fcomi_ST0_FT0(cpu_env);
3ca51d07 6124 set_cc_op(s, CC_OP_EFLAGS);
2c0262af 6125 break;
658c8bda 6126 case 0x28: /* ffree sti */
d3eb5eae 6127 gen_helper_ffree_STN(cpu_env, tcg_const_i32(opreg));
5fafdf24 6128 break;
2c0262af 6129 case 0x2a: /* fst sti */
d3eb5eae 6130 gen_helper_fmov_STN_ST0(cpu_env, tcg_const_i32(opreg));
2c0262af
FB
6131 break;
6132 case 0x2b: /* fstp sti */
c169c906
FB
6133 case 0x0b: /* fstp1 sti, undocumented op */
6134 case 0x3a: /* fstp8 sti, undocumented op */
6135 case 0x3b: /* fstp9 sti, undocumented op */
d3eb5eae
BS
6136 gen_helper_fmov_STN_ST0(cpu_env, tcg_const_i32(opreg));
6137 gen_helper_fpop(cpu_env);
2c0262af
FB
6138 break;
6139 case 0x2c: /* fucom st(i) */
d3eb5eae
BS
6140 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6141 gen_helper_fucom_ST0_FT0(cpu_env);
2c0262af
FB
6142 break;
6143 case 0x2d: /* fucomp st(i) */
d3eb5eae
BS
6144 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6145 gen_helper_fucom_ST0_FT0(cpu_env);
6146 gen_helper_fpop(cpu_env);
2c0262af
FB
6147 break;
6148 case 0x33: /* de/3 */
6149 switch(rm) {
6150 case 1: /* fcompp */
d3eb5eae
BS
6151 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(1));
6152 gen_helper_fcom_ST0_FT0(cpu_env);
6153 gen_helper_fpop(cpu_env);
6154 gen_helper_fpop(cpu_env);
2c0262af
FB
6155 break;
6156 default:
6157 goto illegal_op;
6158 }
6159 break;
c169c906 6160 case 0x38: /* ffreep sti, undocumented op */
d3eb5eae
BS
6161 gen_helper_ffree_STN(cpu_env, tcg_const_i32(opreg));
6162 gen_helper_fpop(cpu_env);
c169c906 6163 break;
2c0262af
FB
6164 case 0x3c: /* df/4 */
6165 switch(rm) {
6166 case 0:
d3eb5eae 6167 gen_helper_fnstsw(cpu_tmp2_i32, cpu_env);
b6abf97d 6168 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
480a762d 6169 gen_op_mov_reg_v(MO_16, R_EAX, cpu_T[0]);
2c0262af
FB
6170 break;
6171 default:
6172 goto illegal_op;
6173 }
6174 break;
6175 case 0x3d: /* fucomip */
bff93281
PM
6176 if (!(s->cpuid_features & CPUID_CMOV)) {
6177 goto illegal_op;
6178 }
773cdfcc 6179 gen_update_cc_op(s);
d3eb5eae
BS
6180 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6181 gen_helper_fucomi_ST0_FT0(cpu_env);
6182 gen_helper_fpop(cpu_env);
3ca51d07 6183 set_cc_op(s, CC_OP_EFLAGS);
2c0262af
FB
6184 break;
6185 case 0x3e: /* fcomip */
bff93281
PM
6186 if (!(s->cpuid_features & CPUID_CMOV)) {
6187 goto illegal_op;
6188 }
773cdfcc 6189 gen_update_cc_op(s);
d3eb5eae
BS
6190 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6191 gen_helper_fcomi_ST0_FT0(cpu_env);
6192 gen_helper_fpop(cpu_env);
3ca51d07 6193 set_cc_op(s, CC_OP_EFLAGS);
2c0262af 6194 break;
a2cc3b24
FB
6195 case 0x10 ... 0x13: /* fcmovxx */
6196 case 0x18 ... 0x1b:
6197 {
19e6c4b8 6198 int op1, 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 {
6e0d8677 7019 int 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 {
3bd7da9e 7517 int 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
FB
7565 {
7566 int 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;
2c0262af 7915 uint16_t *gen_opc_end;
a1d1bb31 7916 CPUBreakpoint *bp;
7f5b7d3e 7917 int j, lj;
c068688b 7918 uint64_t flags;
14ce26e7
FB
7919 target_ulong pc_start;
7920 target_ulong cs_base;
2e70f6ef
PB
7921 int num_insns;
7922 int max_insns;
3b46e624 7923
2c0262af 7924 /* generate intermediate code */
14ce26e7
FB
7925 pc_start = tb->pc;
7926 cs_base = tb->cs_base;
2c0262af 7927 flags = tb->flags;
3a1d9b8b 7928
4f31916f 7929 dc->pe = (flags >> HF_PE_SHIFT) & 1;
2c0262af
FB
7930 dc->code32 = (flags >> HF_CS32_SHIFT) & 1;
7931 dc->ss32 = (flags >> HF_SS32_SHIFT) & 1;
7932 dc->addseg = (flags >> HF_ADDSEG_SHIFT) & 1;
7933 dc->f_st = 0;
7934 dc->vm86 = (flags >> VM_SHIFT) & 1;
7935 dc->cpl = (flags >> HF_CPL_SHIFT) & 3;
7936 dc->iopl = (flags >> IOPL_SHIFT) & 3;
7937 dc->tf = (flags >> TF_SHIFT) & 1;
ed2803da 7938 dc->singlestep_enabled = cs->singlestep_enabled;
2c0262af 7939 dc->cc_op = CC_OP_DYNAMIC;
e207582f 7940 dc->cc_op_dirty = false;
2c0262af
FB
7941 dc->cs_base = cs_base;
7942 dc->tb = tb;
7943 dc->popl_esp_hack = 0;
7944 /* select memory access functions */
7945 dc->mem_index = 0;
7946 if (flags & HF_SOFTMMU_MASK) {
5c42a7cd 7947 dc->mem_index = cpu_mmu_index(env);
2c0262af 7948 }
0514ef2f
EH
7949 dc->cpuid_features = env->features[FEAT_1_EDX];
7950 dc->cpuid_ext_features = env->features[FEAT_1_ECX];
7951 dc->cpuid_ext2_features = env->features[FEAT_8000_0001_EDX];
7952 dc->cpuid_ext3_features = env->features[FEAT_8000_0001_ECX];
7953 dc->cpuid_7_0_ebx_features = env->features[FEAT_7_0_EBX];
14ce26e7
FB
7954#ifdef TARGET_X86_64
7955 dc->lma = (flags >> HF_LMA_SHIFT) & 1;
7956 dc->code64 = (flags >> HF_CS64_SHIFT) & 1;
7957#endif
7eee2a50 7958 dc->flags = flags;
ed2803da 7959 dc->jmp_opt = !(dc->tf || cs->singlestep_enabled ||
a2cc3b24 7960 (flags & HF_INHIBIT_IRQ_MASK)
415fa2ea 7961#ifndef CONFIG_SOFTMMU
2c0262af
FB
7962 || (flags & HF_SOFTMMU_MASK)
7963#endif
7964 );
c4d4525c
PD
7965 /* Do not optimize repz jumps at all in icount mode, because
7966 rep movsS instructions are execured with different paths
7967 in !repz_opt and repz_opt modes. The first one was used
7968 always except single step mode. And this setting
7969 disables jumps optimization and control paths become
7970 equivalent in run and single step modes.
7971 Now there will be no jump optimization for repz in
7972 record/replay modes and there will always be an
7973 additional step for ecx=0 when icount is enabled.
7974 */
bd79255d 7975 dc->repz_opt = !dc->jmp_opt && !(tb->cflags & CF_USE_ICOUNT);
4f31916f
FB
7976#if 0
7977 /* check addseg logic */
dc196a57 7978 if (!dc->addseg && (dc->vm86 || !dc->pe || !dc->code32))
4f31916f
FB
7979 printf("ERROR addseg\n");
7980#endif
7981
a7812ae4
PB
7982 cpu_T[0] = tcg_temp_new();
7983 cpu_T[1] = tcg_temp_new();
7984 cpu_A0 = tcg_temp_new();
a7812ae4
PB
7985
7986 cpu_tmp0 = tcg_temp_new();
7987 cpu_tmp1_i64 = tcg_temp_new_i64();
7988 cpu_tmp2_i32 = tcg_temp_new_i32();
7989 cpu_tmp3_i32 = tcg_temp_new_i32();
7990 cpu_tmp4 = tcg_temp_new();
a7812ae4
PB
7991 cpu_ptr0 = tcg_temp_new_ptr();
7992 cpu_ptr1 = tcg_temp_new_ptr();
a3251186 7993 cpu_cc_srcT = tcg_temp_local_new();
57fec1fe 7994
92414b31 7995 gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
2c0262af
FB
7996
7997 dc->is_jmp = DISAS_NEXT;
7998 pc_ptr = pc_start;
7999 lj = -1;
2e70f6ef
PB
8000 num_insns = 0;
8001 max_insns = tb->cflags & CF_COUNT_MASK;
8002 if (max_insns == 0)
8003 max_insns = CF_COUNT_MASK;
2c0262af 8004
cd42d5b2 8005 gen_tb_start(tb);
2c0262af 8006 for(;;) {
f0c3c505
AF
8007 if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
8008 QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
a2397807
JK
8009 if (bp->pc == pc_ptr &&
8010 !((bp->flags & BP_CPU) && (tb->flags & HF_RF_MASK))) {
2c0262af 8011 gen_debug(dc, pc_ptr - dc->cs_base);
e64e3535 8012 goto done_generating;
2c0262af
FB
8013 }
8014 }
8015 }
8016 if (search_pc) {
92414b31 8017 j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
2c0262af
FB
8018 if (lj < j) {
8019 lj++;
8020 while (lj < j)
ab1103de 8021 tcg_ctx.gen_opc_instr_start[lj++] = 0;
2c0262af 8022 }
25983cad 8023 tcg_ctx.gen_opc_pc[lj] = pc_ptr;
2c0262af 8024 gen_opc_cc_op[lj] = dc->cc_op;
ab1103de 8025 tcg_ctx.gen_opc_instr_start[lj] = 1;
c9c99c22 8026 tcg_ctx.gen_opc_icount[lj] = num_insns;
2c0262af 8027 }
2e70f6ef
PB
8028 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
8029 gen_io_start();
8030
0af10c86 8031 pc_ptr = disas_insn(env, dc, pc_ptr);
2e70f6ef 8032 num_insns++;
2c0262af
FB
8033 /* stop translation if indicated */
8034 if (dc->is_jmp)
8035 break;
8036 /* if single step mode, we generate only one instruction and
8037 generate an exception */
a2cc3b24
FB
8038 /* if irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear
8039 the flag and abort the translation to give the irqs a
8040 change to be happen */
5fafdf24 8041 if (dc->tf || dc->singlestep_enabled ||
2e70f6ef 8042 (flags & HF_INHIBIT_IRQ_MASK)) {
14ce26e7 8043 gen_jmp_im(pc_ptr - dc->cs_base);
2c0262af
FB
8044 gen_eob(dc);
8045 break;
8046 }
5b9efc39
PD
8047 /* Do not cross the boundary of the pages in icount mode,
8048 it can cause an exception. Do it only when boundary is
8049 crossed by the first instruction in the block.
8050 If current instruction already crossed the bound - it's ok,
8051 because an exception hasn't stopped this code.
8052 */
bd79255d 8053 if ((tb->cflags & CF_USE_ICOUNT)
5b9efc39
PD
8054 && ((pc_ptr & TARGET_PAGE_MASK)
8055 != ((pc_ptr + TARGET_MAX_INSN_SIZE - 1) & TARGET_PAGE_MASK)
8056 || (pc_ptr & ~TARGET_PAGE_MASK) == 0)) {
8057 gen_jmp_im(pc_ptr - dc->cs_base);
8058 gen_eob(dc);
8059 break;
8060 }
2c0262af 8061 /* if too long translation, stop generation too */
efd7f486 8062 if (tcg_ctx.gen_opc_ptr >= gen_opc_end ||
2e70f6ef
PB
8063 (pc_ptr - pc_start) >= (TARGET_PAGE_SIZE - 32) ||
8064 num_insns >= max_insns) {
14ce26e7 8065 gen_jmp_im(pc_ptr - dc->cs_base);
2c0262af
FB
8066 gen_eob(dc);
8067 break;
8068 }
1b530a6d
AJ
8069 if (singlestep) {
8070 gen_jmp_im(pc_ptr - dc->cs_base);
8071 gen_eob(dc);
8072 break;
8073 }
2c0262af 8074 }
2e70f6ef
PB
8075 if (tb->cflags & CF_LAST_IO)
8076 gen_io_end();
e64e3535 8077done_generating:
806f352d 8078 gen_tb_end(tb, num_insns);
efd7f486 8079 *tcg_ctx.gen_opc_ptr = INDEX_op_end;
2c0262af
FB
8080 /* we don't forget to fill the last values */
8081 if (search_pc) {
92414b31 8082 j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
2c0262af
FB
8083 lj++;
8084 while (lj <= j)
ab1103de 8085 tcg_ctx.gen_opc_instr_start[lj++] = 0;
2c0262af 8086 }
3b46e624 8087
2c0262af 8088#ifdef DEBUG_DISAS
8fec2b8c 8089 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
14ce26e7 8090 int disas_flags;
93fcfe39
AL
8091 qemu_log("----------------\n");
8092 qemu_log("IN: %s\n", lookup_symbol(pc_start));
14ce26e7
FB
8093#ifdef TARGET_X86_64
8094 if (dc->code64)
8095 disas_flags = 2;
8096 else
8097#endif
8098 disas_flags = !dc->code32;
f4359b9f 8099 log_target_disas(env, pc_start, pc_ptr - pc_start, disas_flags);
93fcfe39 8100 qemu_log("\n");
2c0262af
FB
8101 }
8102#endif
8103
2e70f6ef 8104 if (!search_pc) {
2c0262af 8105 tb->size = pc_ptr - pc_start;
2e70f6ef
PB
8106 tb->icount = num_insns;
8107 }
2c0262af
FB
8108}
8109
317ac620 8110void gen_intermediate_code(CPUX86State *env, TranslationBlock *tb)
2c0262af 8111{
467215c2 8112 gen_intermediate_code_internal(x86_env_get_cpu(env), tb, false);
2c0262af
FB
8113}
8114
317ac620 8115void gen_intermediate_code_pc(CPUX86State *env, TranslationBlock *tb)
2c0262af 8116{
467215c2 8117 gen_intermediate_code_internal(x86_env_get_cpu(env), tb, true);
2c0262af
FB
8118}
8119
317ac620 8120void restore_state_to_opc(CPUX86State *env, TranslationBlock *tb, int pc_pos)
d2856f1a
AJ
8121{
8122 int cc_op;
8123#ifdef DEBUG_DISAS
8fec2b8c 8124 if (qemu_loglevel_mask(CPU_LOG_TB_OP)) {
d2856f1a 8125 int i;
93fcfe39 8126 qemu_log("RESTORE:\n");
d2856f1a 8127 for(i = 0;i <= pc_pos; i++) {
ab1103de 8128 if (tcg_ctx.gen_opc_instr_start[i]) {
25983cad
EV
8129 qemu_log("0x%04x: " TARGET_FMT_lx "\n", i,
8130 tcg_ctx.gen_opc_pc[i]);
d2856f1a
AJ
8131 }
8132 }
e87b7cb0 8133 qemu_log("pc_pos=0x%x eip=" TARGET_FMT_lx " cs_base=%x\n",
25983cad 8134 pc_pos, tcg_ctx.gen_opc_pc[pc_pos] - tb->cs_base,
d2856f1a
AJ
8135 (uint32_t)tb->cs_base);
8136 }
8137#endif
25983cad 8138 env->eip = tcg_ctx.gen_opc_pc[pc_pos] - tb->cs_base;
d2856f1a
AJ
8139 cc_op = gen_opc_cc_op[pc_pos];
8140 if (cc_op != CC_OP_DYNAMIC)
8141 env->cc_op = cc_op;
8142}