]> git.proxmox.com Git - mirror_qemu.git/blame - target-i386/translate.c
tcg: Move emit of INDEX_op_end into gen_tb_end
[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{
bee81887
PB
2624 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset + offsetof(XMMReg, XMM_Q(0)));
2625 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset + offsetof(XMMReg, XMM_Q(0)));
2626 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset + offsetof(XMMReg, XMM_Q(1)));
2627 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset + offsetof(XMMReg, XMM_Q(1)));
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) {
07958082
PB
3077 gen_stq_env_A0(s, offsetof(CPUX86State,
3078 xmm_regs[reg].XMM_Q(0)));
d9f4bb27
AP
3079 } else {
3080 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,
3081 xmm_regs[reg].XMM_L(0)));
fd8ca9f6 3082 gen_op_st_v(s, MO_32, cpu_T[0], cpu_A0);
d9f4bb27
AP
3083 }
3084 break;
664e0f19 3085 case 0x6e: /* movd mm, ea */
dabd98dd 3086#ifdef TARGET_X86_64
ab4e4aec 3087 if (s->dflag == MO_64) {
4ba9938c 3088 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 0);
5af45186 3089 tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,fpregs[reg].mmx));
5fafdf24 3090 } else
dabd98dd
FB
3091#endif
3092 {
4ba9938c 3093 gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 0);
5af45186
FB
3094 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3095 offsetof(CPUX86State,fpregs[reg].mmx));
a7812ae4
PB
3096 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
3097 gen_helper_movl_mm_T0_mmx(cpu_ptr0, cpu_tmp2_i32);
dabd98dd 3098 }
664e0f19
FB
3099 break;
3100 case 0x16e: /* movd xmm, ea */
dabd98dd 3101#ifdef TARGET_X86_64
ab4e4aec 3102 if (s->dflag == MO_64) {
4ba9938c 3103 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 0);
5af45186
FB
3104 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3105 offsetof(CPUX86State,xmm_regs[reg]));
a7812ae4 3106 gen_helper_movq_mm_T0_xmm(cpu_ptr0, cpu_T[0]);
5fafdf24 3107 } else
dabd98dd
FB
3108#endif
3109 {
4ba9938c 3110 gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 0);
5af45186
FB
3111 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3112 offsetof(CPUX86State,xmm_regs[reg]));
b6abf97d 3113 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
a7812ae4 3114 gen_helper_movl_mm_T0_xmm(cpu_ptr0, cpu_tmp2_i32);
dabd98dd 3115 }
664e0f19
FB
3116 break;
3117 case 0x6f: /* movq mm, ea */
3118 if (mod != 3) {
4eeb3939 3119 gen_lea_modrm(env, s, modrm);
323d1876 3120 gen_ldq_env_A0(s, offsetof(CPUX86State, fpregs[reg].mmx));
664e0f19
FB
3121 } else {
3122 rm = (modrm & 7);
b6abf97d 3123 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env,
5af45186 3124 offsetof(CPUX86State,fpregs[rm].mmx));
b6abf97d 3125 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env,
5af45186 3126 offsetof(CPUX86State,fpregs[reg].mmx));
664e0f19
FB
3127 }
3128 break;
3129 case 0x010: /* movups */
3130 case 0x110: /* movupd */
3131 case 0x028: /* movaps */
3132 case 0x128: /* movapd */
3133 case 0x16f: /* movdqa xmm, ea */
3134 case 0x26f: /* movdqu xmm, ea */
3135 if (mod != 3) {
4eeb3939 3136 gen_lea_modrm(env, s, modrm);
323d1876 3137 gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
664e0f19
FB
3138 } else {
3139 rm = (modrm & 7) | REX_B(s);
3140 gen_op_movo(offsetof(CPUX86State,xmm_regs[reg]),
3141 offsetof(CPUX86State,xmm_regs[rm]));
3142 }
3143 break;
3144 case 0x210: /* movss xmm, ea */
3145 if (mod != 3) {
4eeb3939 3146 gen_lea_modrm(env, s, modrm);
909be183 3147 gen_op_ld_v(s, MO_32, cpu_T[0], cpu_A0);
651ba608 3148 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
97212c88 3149 tcg_gen_movi_tl(cpu_T[0], 0);
651ba608
FB
3150 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)));
3151 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)));
3152 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)));
664e0f19
FB
3153 } else {
3154 rm = (modrm & 7) | REX_B(s);
3155 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)),
3156 offsetof(CPUX86State,xmm_regs[rm].XMM_L(0)));
3157 }
3158 break;
3159 case 0x310: /* movsd xmm, ea */
3160 if (mod != 3) {
4eeb3939 3161 gen_lea_modrm(env, s, modrm);
323d1876
RH
3162 gen_ldq_env_A0(s, offsetof(CPUX86State,
3163 xmm_regs[reg].XMM_Q(0)));
97212c88 3164 tcg_gen_movi_tl(cpu_T[0], 0);
651ba608
FB
3165 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)));
3166 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)));
664e0f19
FB
3167 } else {
3168 rm = (modrm & 7) | REX_B(s);
3169 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
3170 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
3171 }
3172 break;
3173 case 0x012: /* movlps */
3174 case 0x112: /* movlpd */
3175 if (mod != 3) {
4eeb3939 3176 gen_lea_modrm(env, s, modrm);
323d1876
RH
3177 gen_ldq_env_A0(s, offsetof(CPUX86State,
3178 xmm_regs[reg].XMM_Q(0)));
664e0f19
FB
3179 } else {
3180 /* movhlps */
3181 rm = (modrm & 7) | REX_B(s);
3182 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
3183 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(1)));
3184 }
3185 break;
465e9838
FB
3186 case 0x212: /* movsldup */
3187 if (mod != 3) {
4eeb3939 3188 gen_lea_modrm(env, s, modrm);
323d1876 3189 gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
465e9838
FB
3190 } else {
3191 rm = (modrm & 7) | REX_B(s);
3192 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)),
3193 offsetof(CPUX86State,xmm_regs[rm].XMM_L(0)));
3194 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)),
3195 offsetof(CPUX86State,xmm_regs[rm].XMM_L(2)));
3196 }
3197 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)),
3198 offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
3199 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)),
3200 offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)));
3201 break;
3202 case 0x312: /* movddup */
3203 if (mod != 3) {
4eeb3939 3204 gen_lea_modrm(env, s, modrm);
323d1876
RH
3205 gen_ldq_env_A0(s, offsetof(CPUX86State,
3206 xmm_regs[reg].XMM_Q(0)));
465e9838
FB
3207 } else {
3208 rm = (modrm & 7) | REX_B(s);
3209 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
3210 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
3211 }
3212 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)),
ba6526df 3213 offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
465e9838 3214 break;
664e0f19
FB
3215 case 0x016: /* movhps */
3216 case 0x116: /* movhpd */
3217 if (mod != 3) {
4eeb3939 3218 gen_lea_modrm(env, s, modrm);
323d1876
RH
3219 gen_ldq_env_A0(s, offsetof(CPUX86State,
3220 xmm_regs[reg].XMM_Q(1)));
664e0f19
FB
3221 } else {
3222 /* movlhps */
3223 rm = (modrm & 7) | REX_B(s);
3224 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)),
3225 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
3226 }
3227 break;
3228 case 0x216: /* movshdup */
3229 if (mod != 3) {
4eeb3939 3230 gen_lea_modrm(env, s, modrm);
323d1876 3231 gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
664e0f19
FB
3232 } else {
3233 rm = (modrm & 7) | REX_B(s);
3234 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)),
3235 offsetof(CPUX86State,xmm_regs[rm].XMM_L(1)));
3236 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)),
3237 offsetof(CPUX86State,xmm_regs[rm].XMM_L(3)));
3238 }
3239 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)),
3240 offsetof(CPUX86State,xmm_regs[reg].XMM_L(1)));
3241 gen_op_movl(offsetof(CPUX86State,xmm_regs[reg].XMM_L(2)),
3242 offsetof(CPUX86State,xmm_regs[reg].XMM_L(3)));
3243 break;
d9f4bb27
AP
3244 case 0x178:
3245 case 0x378:
3246 {
3247 int bit_index, field_length;
3248
3249 if (b1 == 1 && reg != 0)
3250 goto illegal_op;
0af10c86
BS
3251 field_length = cpu_ldub_code(env, s->pc++) & 0x3F;
3252 bit_index = cpu_ldub_code(env, s->pc++) & 0x3F;
d9f4bb27
AP
3253 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3254 offsetof(CPUX86State,xmm_regs[reg]));
3255 if (b1 == 1)
d3eb5eae
BS
3256 gen_helper_extrq_i(cpu_env, cpu_ptr0,
3257 tcg_const_i32(bit_index),
3258 tcg_const_i32(field_length));
d9f4bb27 3259 else
d3eb5eae
BS
3260 gen_helper_insertq_i(cpu_env, cpu_ptr0,
3261 tcg_const_i32(bit_index),
3262 tcg_const_i32(field_length));
d9f4bb27
AP
3263 }
3264 break;
664e0f19 3265 case 0x7e: /* movd ea, mm */
dabd98dd 3266#ifdef TARGET_X86_64
ab4e4aec 3267 if (s->dflag == MO_64) {
5af45186
FB
3268 tcg_gen_ld_i64(cpu_T[0], cpu_env,
3269 offsetof(CPUX86State,fpregs[reg].mmx));
4ba9938c 3270 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 1);
5fafdf24 3271 } else
dabd98dd
FB
3272#endif
3273 {
5af45186
FB
3274 tcg_gen_ld32u_tl(cpu_T[0], cpu_env,
3275 offsetof(CPUX86State,fpregs[reg].mmx.MMX_L(0)));
4ba9938c 3276 gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 1);
dabd98dd 3277 }
664e0f19
FB
3278 break;
3279 case 0x17e: /* movd ea, xmm */
dabd98dd 3280#ifdef TARGET_X86_64
ab4e4aec 3281 if (s->dflag == MO_64) {
5af45186
FB
3282 tcg_gen_ld_i64(cpu_T[0], cpu_env,
3283 offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
4ba9938c 3284 gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 1);
5fafdf24 3285 } else
dabd98dd
FB
3286#endif
3287 {
5af45186
FB
3288 tcg_gen_ld32u_tl(cpu_T[0], cpu_env,
3289 offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
4ba9938c 3290 gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 1);
dabd98dd 3291 }
664e0f19
FB
3292 break;
3293 case 0x27e: /* movq xmm, ea */
3294 if (mod != 3) {
4eeb3939 3295 gen_lea_modrm(env, s, modrm);
323d1876
RH
3296 gen_ldq_env_A0(s, offsetof(CPUX86State,
3297 xmm_regs[reg].XMM_Q(0)));
664e0f19
FB
3298 } else {
3299 rm = (modrm & 7) | REX_B(s);
3300 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
3301 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
3302 }
3303 gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));
3304 break;
3305 case 0x7f: /* movq ea, mm */
3306 if (mod != 3) {
4eeb3939 3307 gen_lea_modrm(env, s, modrm);
323d1876 3308 gen_stq_env_A0(s, offsetof(CPUX86State, fpregs[reg].mmx));
664e0f19
FB
3309 } else {
3310 rm = (modrm & 7);
3311 gen_op_movq(offsetof(CPUX86State,fpregs[rm].mmx),
3312 offsetof(CPUX86State,fpregs[reg].mmx));
3313 }
3314 break;
3315 case 0x011: /* movups */
3316 case 0x111: /* movupd */
3317 case 0x029: /* movaps */
3318 case 0x129: /* movapd */
3319 case 0x17f: /* movdqa ea, xmm */
3320 case 0x27f: /* movdqu ea, xmm */
3321 if (mod != 3) {
4eeb3939 3322 gen_lea_modrm(env, s, modrm);
323d1876 3323 gen_sto_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
664e0f19
FB
3324 } else {
3325 rm = (modrm & 7) | REX_B(s);
3326 gen_op_movo(offsetof(CPUX86State,xmm_regs[rm]),
3327 offsetof(CPUX86State,xmm_regs[reg]));
3328 }
3329 break;
3330 case 0x211: /* movss ea, xmm */
3331 if (mod != 3) {
4eeb3939 3332 gen_lea_modrm(env, s, modrm);
651ba608 3333 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
fd8ca9f6 3334 gen_op_st_v(s, MO_32, cpu_T[0], cpu_A0);
664e0f19
FB
3335 } else {
3336 rm = (modrm & 7) | REX_B(s);
3337 gen_op_movl(offsetof(CPUX86State,xmm_regs[rm].XMM_L(0)),
3338 offsetof(CPUX86State,xmm_regs[reg].XMM_L(0)));
3339 }
3340 break;
3341 case 0x311: /* movsd ea, xmm */
3342 if (mod != 3) {
4eeb3939 3343 gen_lea_modrm(env, s, modrm);
323d1876
RH
3344 gen_stq_env_A0(s, offsetof(CPUX86State,
3345 xmm_regs[reg].XMM_Q(0)));
664e0f19
FB
3346 } else {
3347 rm = (modrm & 7) | REX_B(s);
3348 gen_op_movq(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)),
3349 offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
3350 }
3351 break;
3352 case 0x013: /* movlps */
3353 case 0x113: /* movlpd */
3354 if (mod != 3) {
4eeb3939 3355 gen_lea_modrm(env, s, modrm);
323d1876
RH
3356 gen_stq_env_A0(s, offsetof(CPUX86State,
3357 xmm_regs[reg].XMM_Q(0)));
664e0f19
FB
3358 } else {
3359 goto illegal_op;
3360 }
3361 break;
3362 case 0x017: /* movhps */
3363 case 0x117: /* movhpd */
3364 if (mod != 3) {
4eeb3939 3365 gen_lea_modrm(env, s, modrm);
323d1876
RH
3366 gen_stq_env_A0(s, offsetof(CPUX86State,
3367 xmm_regs[reg].XMM_Q(1)));
664e0f19
FB
3368 } else {
3369 goto illegal_op;
3370 }
3371 break;
3372 case 0x71: /* shift mm, im */
3373 case 0x72:
3374 case 0x73:
3375 case 0x171: /* shift xmm, im */
3376 case 0x172:
3377 case 0x173:
c045af25
AK
3378 if (b1 >= 2) {
3379 goto illegal_op;
3380 }
0af10c86 3381 val = cpu_ldub_code(env, s->pc++);
664e0f19 3382 if (is_xmm) {
1b90d56e 3383 tcg_gen_movi_tl(cpu_T[0], val);
651ba608 3384 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_t0.XMM_L(0)));
97212c88 3385 tcg_gen_movi_tl(cpu_T[0], 0);
651ba608 3386 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_t0.XMM_L(1)));
664e0f19
FB
3387 op1_offset = offsetof(CPUX86State,xmm_t0);
3388 } else {
1b90d56e 3389 tcg_gen_movi_tl(cpu_T[0], val);
651ba608 3390 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,mmx_t0.MMX_L(0)));
97212c88 3391 tcg_gen_movi_tl(cpu_T[0], 0);
651ba608 3392 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,mmx_t0.MMX_L(1)));
664e0f19
FB
3393 op1_offset = offsetof(CPUX86State,mmx_t0);
3394 }
d3eb5eae
BS
3395 sse_fn_epp = sse_op_table2[((b - 1) & 3) * 8 +
3396 (((modrm >> 3)) & 7)][b1];
3397 if (!sse_fn_epp) {
664e0f19 3398 goto illegal_op;
c4baa050 3399 }
664e0f19
FB
3400 if (is_xmm) {
3401 rm = (modrm & 7) | REX_B(s);
3402 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3403 } else {
3404 rm = (modrm & 7);
3405 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3406 }
5af45186
FB
3407 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op2_offset);
3408 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op1_offset);
d3eb5eae 3409 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
664e0f19
FB
3410 break;
3411 case 0x050: /* movmskps */
664e0f19 3412 rm = (modrm & 7) | REX_B(s);
5af45186
FB
3413 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3414 offsetof(CPUX86State,xmm_regs[rm]));
d3eb5eae 3415 gen_helper_movmskps(cpu_tmp2_i32, cpu_env, cpu_ptr0);
a7fbcbe5 3416 tcg_gen_extu_i32_tl(cpu_regs[reg], cpu_tmp2_i32);
664e0f19
FB
3417 break;
3418 case 0x150: /* movmskpd */
664e0f19 3419 rm = (modrm & 7) | REX_B(s);
5af45186
FB
3420 tcg_gen_addi_ptr(cpu_ptr0, cpu_env,
3421 offsetof(CPUX86State,xmm_regs[rm]));
d3eb5eae 3422 gen_helper_movmskpd(cpu_tmp2_i32, cpu_env, cpu_ptr0);
a7fbcbe5 3423 tcg_gen_extu_i32_tl(cpu_regs[reg], cpu_tmp2_i32);
664e0f19
FB
3424 break;
3425 case 0x02a: /* cvtpi2ps */
3426 case 0x12a: /* cvtpi2pd */
d3eb5eae 3427 gen_helper_enter_mmx(cpu_env);
664e0f19 3428 if (mod != 3) {
4eeb3939 3429 gen_lea_modrm(env, s, modrm);
664e0f19 3430 op2_offset = offsetof(CPUX86State,mmx_t0);
323d1876 3431 gen_ldq_env_A0(s, op2_offset);
664e0f19
FB
3432 } else {
3433 rm = (modrm & 7);
3434 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3435 }
3436 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
5af45186
FB
3437 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
3438 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
664e0f19
FB
3439 switch(b >> 8) {
3440 case 0x0:
d3eb5eae 3441 gen_helper_cvtpi2ps(cpu_env, cpu_ptr0, cpu_ptr1);
664e0f19
FB
3442 break;
3443 default:
3444 case 0x1:
d3eb5eae 3445 gen_helper_cvtpi2pd(cpu_env, cpu_ptr0, cpu_ptr1);
664e0f19
FB
3446 break;
3447 }
3448 break;
3449 case 0x22a: /* cvtsi2ss */
3450 case 0x32a: /* cvtsi2sd */
ab4e4aec 3451 ot = mo_64_32(s->dflag);
0af10c86 3452 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
664e0f19 3453 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
5af45186 3454 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4ba9938c 3455 if (ot == MO_32) {
d3eb5eae 3456 SSEFunc_0_epi sse_fn_epi = sse_op_table3ai[(b >> 8) & 1];
28e10711 3457 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
d3eb5eae 3458 sse_fn_epi(cpu_env, cpu_ptr0, cpu_tmp2_i32);
28e10711 3459 } else {
11f8cdbc 3460#ifdef TARGET_X86_64
d3eb5eae
BS
3461 SSEFunc_0_epl sse_fn_epl = sse_op_table3aq[(b >> 8) & 1];
3462 sse_fn_epl(cpu_env, cpu_ptr0, cpu_T[0]);
11f8cdbc
SW
3463#else
3464 goto illegal_op;
3465#endif
28e10711 3466 }
664e0f19
FB
3467 break;
3468 case 0x02c: /* cvttps2pi */
3469 case 0x12c: /* cvttpd2pi */
3470 case 0x02d: /* cvtps2pi */
3471 case 0x12d: /* cvtpd2pi */
d3eb5eae 3472 gen_helper_enter_mmx(cpu_env);
664e0f19 3473 if (mod != 3) {
4eeb3939 3474 gen_lea_modrm(env, s, modrm);
664e0f19 3475 op2_offset = offsetof(CPUX86State,xmm_t0);
323d1876 3476 gen_ldo_env_A0(s, op2_offset);
664e0f19
FB
3477 } else {
3478 rm = (modrm & 7) | REX_B(s);
3479 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3480 }
3481 op1_offset = offsetof(CPUX86State,fpregs[reg & 7].mmx);
5af45186
FB
3482 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
3483 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
664e0f19
FB
3484 switch(b) {
3485 case 0x02c:
d3eb5eae 3486 gen_helper_cvttps2pi(cpu_env, cpu_ptr0, cpu_ptr1);
664e0f19
FB
3487 break;
3488 case 0x12c:
d3eb5eae 3489 gen_helper_cvttpd2pi(cpu_env, cpu_ptr0, cpu_ptr1);
664e0f19
FB
3490 break;
3491 case 0x02d:
d3eb5eae 3492 gen_helper_cvtps2pi(cpu_env, cpu_ptr0, cpu_ptr1);
664e0f19
FB
3493 break;
3494 case 0x12d:
d3eb5eae 3495 gen_helper_cvtpd2pi(cpu_env, cpu_ptr0, cpu_ptr1);
664e0f19
FB
3496 break;
3497 }
3498 break;
3499 case 0x22c: /* cvttss2si */
3500 case 0x32c: /* cvttsd2si */
3501 case 0x22d: /* cvtss2si */
3502 case 0x32d: /* cvtsd2si */
ab4e4aec 3503 ot = mo_64_32(s->dflag);
31313213 3504 if (mod != 3) {
4eeb3939 3505 gen_lea_modrm(env, s, modrm);
31313213 3506 if ((b >> 8) & 1) {
323d1876 3507 gen_ldq_env_A0(s, offsetof(CPUX86State, xmm_t0.XMM_Q(0)));
31313213 3508 } else {
909be183 3509 gen_op_ld_v(s, MO_32, cpu_T[0], cpu_A0);
651ba608 3510 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_t0.XMM_L(0)));
31313213
FB
3511 }
3512 op2_offset = offsetof(CPUX86State,xmm_t0);
3513 } else {
3514 rm = (modrm & 7) | REX_B(s);
3515 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
3516 }
5af45186 3517 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op2_offset);
4ba9938c 3518 if (ot == MO_32) {
d3eb5eae 3519 SSEFunc_i_ep sse_fn_i_ep =
bedc2ac1 3520 sse_op_table3bi[((b >> 7) & 2) | (b & 1)];
d3eb5eae 3521 sse_fn_i_ep(cpu_tmp2_i32, cpu_env, cpu_ptr0);
b6abf97d 3522 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
5af45186 3523 } else {
11f8cdbc 3524#ifdef TARGET_X86_64
d3eb5eae 3525 SSEFunc_l_ep sse_fn_l_ep =
bedc2ac1 3526 sse_op_table3bq[((b >> 7) & 2) | (b & 1)];
d3eb5eae 3527 sse_fn_l_ep(cpu_T[0], cpu_env, cpu_ptr0);
11f8cdbc
SW
3528#else
3529 goto illegal_op;
3530#endif
5af45186 3531 }
480a762d 3532 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
664e0f19
FB
3533 break;
3534 case 0xc4: /* pinsrw */
5fafdf24 3535 case 0x1c4:
d1e42c5c 3536 s->rip_offset = 1;
4ba9938c 3537 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
0af10c86 3538 val = cpu_ldub_code(env, s->pc++);
664e0f19
FB
3539 if (b1) {
3540 val &= 7;
5af45186
FB
3541 tcg_gen_st16_tl(cpu_T[0], cpu_env,
3542 offsetof(CPUX86State,xmm_regs[reg].XMM_W(val)));
664e0f19
FB
3543 } else {
3544 val &= 3;
5af45186
FB
3545 tcg_gen_st16_tl(cpu_T[0], cpu_env,
3546 offsetof(CPUX86State,fpregs[reg].mmx.MMX_W(val)));
664e0f19
FB
3547 }
3548 break;
3549 case 0xc5: /* pextrw */
5fafdf24 3550 case 0x1c5:
664e0f19
FB
3551 if (mod != 3)
3552 goto illegal_op;
ab4e4aec 3553 ot = mo_64_32(s->dflag);
0af10c86 3554 val = cpu_ldub_code(env, s->pc++);
664e0f19
FB
3555 if (b1) {
3556 val &= 7;
3557 rm = (modrm & 7) | REX_B(s);
5af45186
FB
3558 tcg_gen_ld16u_tl(cpu_T[0], cpu_env,
3559 offsetof(CPUX86State,xmm_regs[rm].XMM_W(val)));
664e0f19
FB
3560 } else {
3561 val &= 3;
3562 rm = (modrm & 7);
5af45186
FB
3563 tcg_gen_ld16u_tl(cpu_T[0], cpu_env,
3564 offsetof(CPUX86State,fpregs[rm].mmx.MMX_W(val)));
664e0f19
FB
3565 }
3566 reg = ((modrm >> 3) & 7) | rex_r;
480a762d 3567 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
664e0f19
FB
3568 break;
3569 case 0x1d6: /* movq ea, xmm */
3570 if (mod != 3) {
4eeb3939 3571 gen_lea_modrm(env, s, modrm);
323d1876
RH
3572 gen_stq_env_A0(s, offsetof(CPUX86State,
3573 xmm_regs[reg].XMM_Q(0)));
664e0f19
FB
3574 } else {
3575 rm = (modrm & 7) | REX_B(s);
3576 gen_op_movq(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)),
3577 offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)));
3578 gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[rm].XMM_Q(1)));
3579 }
3580 break;
3581 case 0x2d6: /* movq2dq */
d3eb5eae 3582 gen_helper_enter_mmx(cpu_env);
480c1cdb
FB
3583 rm = (modrm & 7);
3584 gen_op_movq(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(0)),
3585 offsetof(CPUX86State,fpregs[rm].mmx));
3586 gen_op_movq_env_0(offsetof(CPUX86State,xmm_regs[reg].XMM_Q(1)));
664e0f19
FB
3587 break;
3588 case 0x3d6: /* movdq2q */
d3eb5eae 3589 gen_helper_enter_mmx(cpu_env);
480c1cdb
FB
3590 rm = (modrm & 7) | REX_B(s);
3591 gen_op_movq(offsetof(CPUX86State,fpregs[reg & 7].mmx),
3592 offsetof(CPUX86State,xmm_regs[rm].XMM_Q(0)));
664e0f19
FB
3593 break;
3594 case 0xd7: /* pmovmskb */
3595 case 0x1d7:
3596 if (mod != 3)
3597 goto illegal_op;
3598 if (b1) {
3599 rm = (modrm & 7) | REX_B(s);
5af45186 3600 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, offsetof(CPUX86State,xmm_regs[rm]));
d3eb5eae 3601 gen_helper_pmovmskb_xmm(cpu_tmp2_i32, cpu_env, cpu_ptr0);
664e0f19
FB
3602 } else {
3603 rm = (modrm & 7);
5af45186 3604 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, offsetof(CPUX86State,fpregs[rm].mmx));
d3eb5eae 3605 gen_helper_pmovmskb_mmx(cpu_tmp2_i32, cpu_env, cpu_ptr0);
664e0f19
FB
3606 }
3607 reg = ((modrm >> 3) & 7) | rex_r;
a7fbcbe5 3608 tcg_gen_extu_i32_tl(cpu_regs[reg], cpu_tmp2_i32);
664e0f19 3609 break;
111994ee 3610
4242b1bd 3611 case 0x138:
000cacf6 3612 case 0x038:
4242b1bd 3613 b = modrm;
111994ee
RH
3614 if ((b & 0xf0) == 0xf0) {
3615 goto do_0f_38_fx;
3616 }
0af10c86 3617 modrm = cpu_ldub_code(env, s->pc++);
4242b1bd
AZ
3618 rm = modrm & 7;
3619 reg = ((modrm >> 3) & 7) | rex_r;
3620 mod = (modrm >> 6) & 3;
c045af25
AK
3621 if (b1 >= 2) {
3622 goto illegal_op;
3623 }
4242b1bd 3624
d3eb5eae
BS
3625 sse_fn_epp = sse_op_table6[b].op[b1];
3626 if (!sse_fn_epp) {
4242b1bd 3627 goto illegal_op;
c4baa050 3628 }
222a3336
AZ
3629 if (!(s->cpuid_ext_features & sse_op_table6[b].ext_mask))
3630 goto illegal_op;
4242b1bd
AZ
3631
3632 if (b1) {
3633 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
3634 if (mod == 3) {
3635 op2_offset = offsetof(CPUX86State,xmm_regs[rm | REX_B(s)]);
3636 } else {
3637 op2_offset = offsetof(CPUX86State,xmm_t0);
4eeb3939 3638 gen_lea_modrm(env, s, modrm);
222a3336
AZ
3639 switch (b) {
3640 case 0x20: case 0x30: /* pmovsxbw, pmovzxbw */
3641 case 0x23: case 0x33: /* pmovsxwd, pmovzxwd */
3642 case 0x25: case 0x35: /* pmovsxdq, pmovzxdq */
323d1876 3643 gen_ldq_env_A0(s, op2_offset +
222a3336
AZ
3644 offsetof(XMMReg, XMM_Q(0)));
3645 break;
3646 case 0x21: case 0x31: /* pmovsxbd, pmovzxbd */
3647 case 0x24: case 0x34: /* pmovsxwq, pmovzxwq */
3c5f4116
RH
3648 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
3649 s->mem_index, MO_LEUL);
222a3336
AZ
3650 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, op2_offset +
3651 offsetof(XMMReg, XMM_L(0)));
3652 break;
3653 case 0x22: case 0x32: /* pmovsxbq, pmovzxbq */
3c5f4116
RH
3654 tcg_gen_qemu_ld_tl(cpu_tmp0, cpu_A0,
3655 s->mem_index, MO_LEUW);
222a3336
AZ
3656 tcg_gen_st16_tl(cpu_tmp0, cpu_env, op2_offset +
3657 offsetof(XMMReg, XMM_W(0)));
3658 break;
3659 case 0x2a: /* movntqda */
323d1876 3660 gen_ldo_env_A0(s, op1_offset);
222a3336
AZ
3661 return;
3662 default:
323d1876 3663 gen_ldo_env_A0(s, op2_offset);
222a3336 3664 }
4242b1bd
AZ
3665 }
3666 } else {
3667 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
3668 if (mod == 3) {
3669 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
3670 } else {
3671 op2_offset = offsetof(CPUX86State,mmx_t0);
4eeb3939 3672 gen_lea_modrm(env, s, modrm);
323d1876 3673 gen_ldq_env_A0(s, op2_offset);
4242b1bd
AZ
3674 }
3675 }
d3eb5eae 3676 if (sse_fn_epp == SSE_SPECIAL) {
222a3336 3677 goto illegal_op;
c4baa050 3678 }
222a3336 3679
4242b1bd
AZ
3680 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
3681 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
d3eb5eae 3682 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
222a3336 3683
3ca51d07
RH
3684 if (b == 0x17) {
3685 set_cc_op(s, CC_OP_EFLAGS);
3686 }
4242b1bd 3687 break;
111994ee
RH
3688
3689 case 0x238:
3690 case 0x338:
3691 do_0f_38_fx:
3692 /* Various integer extensions at 0f 38 f[0-f]. */
3693 b = modrm | (b1 << 8);
0af10c86 3694 modrm = cpu_ldub_code(env, s->pc++);
222a3336
AZ
3695 reg = ((modrm >> 3) & 7) | rex_r;
3696
111994ee
RH
3697 switch (b) {
3698 case 0x3f0: /* crc32 Gd,Eb */
3699 case 0x3f1: /* crc32 Gd,Ey */
3700 do_crc32:
3701 if (!(s->cpuid_ext_features & CPUID_EXT_SSE42)) {
3702 goto illegal_op;
3703 }
3704 if ((b & 0xff) == 0xf0) {
4ba9938c 3705 ot = MO_8;
ab4e4aec 3706 } else if (s->dflag != MO_64) {
4ba9938c 3707 ot = (s->prefix & PREFIX_DATA ? MO_16 : MO_32);
111994ee 3708 } else {
4ba9938c 3709 ot = MO_64;
111994ee 3710 }
4242b1bd 3711
24b9c00f 3712 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[reg]);
111994ee
RH
3713 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3714 gen_helper_crc32(cpu_T[0], cpu_tmp2_i32,
3715 cpu_T[0], tcg_const_i32(8 << ot));
222a3336 3716
ab4e4aec 3717 ot = mo_64_32(s->dflag);
480a762d 3718 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
111994ee 3719 break;
222a3336 3720
111994ee
RH
3721 case 0x1f0: /* crc32 or movbe */
3722 case 0x1f1:
3723 /* For these insns, the f3 prefix is supposed to have priority
3724 over the 66 prefix, but that's not what we implement above
3725 setting b1. */
3726 if (s->prefix & PREFIX_REPNZ) {
3727 goto do_crc32;
3728 }
3729 /* FALLTHRU */
3730 case 0x0f0: /* movbe Gy,My */
3731 case 0x0f1: /* movbe My,Gy */
3732 if (!(s->cpuid_ext_features & CPUID_EXT_MOVBE)) {
3733 goto illegal_op;
3734 }
ab4e4aec 3735 if (s->dflag != MO_64) {
4ba9938c 3736 ot = (s->prefix & PREFIX_DATA ? MO_16 : MO_32);
111994ee 3737 } else {
4ba9938c 3738 ot = MO_64;
111994ee
RH
3739 }
3740
3655a19f 3741 gen_lea_modrm(env, s, modrm);
111994ee 3742 if ((b & 1) == 0) {
3655a19f
RH
3743 tcg_gen_qemu_ld_tl(cpu_T[0], cpu_A0,
3744 s->mem_index, ot | MO_BE);
480a762d 3745 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
111994ee 3746 } else {
3655a19f
RH
3747 tcg_gen_qemu_st_tl(cpu_regs[reg], cpu_A0,
3748 s->mem_index, ot | MO_BE);
111994ee
RH
3749 }
3750 break;
3751
7073fbad
RH
3752 case 0x0f2: /* andn Gy, By, Ey */
3753 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)
3754 || !(s->prefix & PREFIX_VEX)
3755 || s->vex_l != 0) {
3756 goto illegal_op;
3757 }
ab4e4aec 3758 ot = mo_64_32(s->dflag);
7073fbad
RH
3759 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3760 tcg_gen_andc_tl(cpu_T[0], cpu_regs[s->vex_v], cpu_T[0]);
480a762d 3761 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
7073fbad
RH
3762 gen_op_update1_cc();
3763 set_cc_op(s, CC_OP_LOGICB + ot);
3764 break;
3765
c7ab7565
RH
3766 case 0x0f7: /* bextr Gy, Ey, By */
3767 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)
3768 || !(s->prefix & PREFIX_VEX)
3769 || s->vex_l != 0) {
3770 goto illegal_op;
3771 }
ab4e4aec 3772 ot = mo_64_32(s->dflag);
c7ab7565
RH
3773 {
3774 TCGv bound, zero;
3775
3776 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3777 /* Extract START, and shift the operand.
3778 Shifts larger than operand size get zeros. */
3779 tcg_gen_ext8u_tl(cpu_A0, cpu_regs[s->vex_v]);
3780 tcg_gen_shr_tl(cpu_T[0], cpu_T[0], cpu_A0);
3781
4ba9938c 3782 bound = tcg_const_tl(ot == MO_64 ? 63 : 31);
c7ab7565
RH
3783 zero = tcg_const_tl(0);
3784 tcg_gen_movcond_tl(TCG_COND_LEU, cpu_T[0], cpu_A0, bound,
3785 cpu_T[0], zero);
3786 tcg_temp_free(zero);
3787
3788 /* Extract the LEN into a mask. Lengths larger than
3789 operand size get all ones. */
3790 tcg_gen_shri_tl(cpu_A0, cpu_regs[s->vex_v], 8);
3791 tcg_gen_ext8u_tl(cpu_A0, cpu_A0);
3792 tcg_gen_movcond_tl(TCG_COND_LEU, cpu_A0, cpu_A0, bound,
3793 cpu_A0, bound);
3794 tcg_temp_free(bound);
3795 tcg_gen_movi_tl(cpu_T[1], 1);
3796 tcg_gen_shl_tl(cpu_T[1], cpu_T[1], cpu_A0);
3797 tcg_gen_subi_tl(cpu_T[1], cpu_T[1], 1);
3798 tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
3799
480a762d 3800 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
c7ab7565
RH
3801 gen_op_update1_cc();
3802 set_cc_op(s, CC_OP_LOGICB + ot);
3803 }
3804 break;
3805
02ea1e6b
RH
3806 case 0x0f5: /* bzhi Gy, Ey, By */
3807 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
3808 || !(s->prefix & PREFIX_VEX)
3809 || s->vex_l != 0) {
3810 goto illegal_op;
3811 }
ab4e4aec 3812 ot = mo_64_32(s->dflag);
02ea1e6b
RH
3813 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3814 tcg_gen_ext8u_tl(cpu_T[1], cpu_regs[s->vex_v]);
3815 {
4ba9938c 3816 TCGv bound = tcg_const_tl(ot == MO_64 ? 63 : 31);
02ea1e6b
RH
3817 /* Note that since we're using BMILG (in order to get O
3818 cleared) we need to store the inverse into C. */
3819 tcg_gen_setcond_tl(TCG_COND_LT, cpu_cc_src,
3820 cpu_T[1], bound);
3821 tcg_gen_movcond_tl(TCG_COND_GT, cpu_T[1], cpu_T[1],
3822 bound, bound, cpu_T[1]);
3823 tcg_temp_free(bound);
3824 }
3825 tcg_gen_movi_tl(cpu_A0, -1);
3826 tcg_gen_shl_tl(cpu_A0, cpu_A0, cpu_T[1]);
3827 tcg_gen_andc_tl(cpu_T[0], cpu_T[0], cpu_A0);
480a762d 3828 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
02ea1e6b
RH
3829 gen_op_update1_cc();
3830 set_cc_op(s, CC_OP_BMILGB + ot);
3831 break;
3832
5f1f4b17
RH
3833 case 0x3f6: /* mulx By, Gy, rdx, Ey */
3834 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
3835 || !(s->prefix & PREFIX_VEX)
3836 || s->vex_l != 0) {
3837 goto illegal_op;
3838 }
ab4e4aec 3839 ot = mo_64_32(s->dflag);
5f1f4b17
RH
3840 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3841 switch (ot) {
5f1f4b17 3842 default:
a4bcea3d
RH
3843 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
3844 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_regs[R_EDX]);
3845 tcg_gen_mulu2_i32(cpu_tmp2_i32, cpu_tmp3_i32,
3846 cpu_tmp2_i32, cpu_tmp3_i32);
3847 tcg_gen_extu_i32_tl(cpu_regs[s->vex_v], cpu_tmp2_i32);
3848 tcg_gen_extu_i32_tl(cpu_regs[reg], cpu_tmp3_i32);
5f1f4b17
RH
3849 break;
3850#ifdef TARGET_X86_64
4ba9938c 3851 case MO_64:
a4bcea3d
RH
3852 tcg_gen_mulu2_i64(cpu_regs[s->vex_v], cpu_regs[reg],
3853 cpu_T[0], cpu_regs[R_EDX]);
5f1f4b17
RH
3854 break;
3855#endif
3856 }
3857 break;
3858
0592f74a
RH
3859 case 0x3f5: /* pdep Gy, By, Ey */
3860 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
3861 || !(s->prefix & PREFIX_VEX)
3862 || s->vex_l != 0) {
3863 goto illegal_op;
3864 }
ab4e4aec 3865 ot = mo_64_32(s->dflag);
0592f74a
RH
3866 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3867 /* Note that by zero-extending the mask operand, we
3868 automatically handle zero-extending the result. */
ab4e4aec 3869 if (ot == MO_64) {
0592f74a
RH
3870 tcg_gen_mov_tl(cpu_T[1], cpu_regs[s->vex_v]);
3871 } else {
3872 tcg_gen_ext32u_tl(cpu_T[1], cpu_regs[s->vex_v]);
3873 }
3874 gen_helper_pdep(cpu_regs[reg], cpu_T[0], cpu_T[1]);
3875 break;
3876
3877 case 0x2f5: /* pext Gy, By, Ey */
3878 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
3879 || !(s->prefix & PREFIX_VEX)
3880 || s->vex_l != 0) {
3881 goto illegal_op;
3882 }
ab4e4aec 3883 ot = mo_64_32(s->dflag);
0592f74a
RH
3884 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3885 /* Note that by zero-extending the mask operand, we
3886 automatically handle zero-extending the result. */
ab4e4aec 3887 if (ot == MO_64) {
0592f74a
RH
3888 tcg_gen_mov_tl(cpu_T[1], cpu_regs[s->vex_v]);
3889 } else {
3890 tcg_gen_ext32u_tl(cpu_T[1], cpu_regs[s->vex_v]);
3891 }
3892 gen_helper_pext(cpu_regs[reg], cpu_T[0], cpu_T[1]);
3893 break;
3894
cd7f97ca
RH
3895 case 0x1f6: /* adcx Gy, Ey */
3896 case 0x2f6: /* adox Gy, Ey */
3897 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_ADX)) {
3898 goto illegal_op;
3899 } else {
76f13133 3900 TCGv carry_in, carry_out, zero;
cd7f97ca
RH
3901 int end_op;
3902
ab4e4aec 3903 ot = mo_64_32(s->dflag);
cd7f97ca
RH
3904 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
3905
3906 /* Re-use the carry-out from a previous round. */
3907 TCGV_UNUSED(carry_in);
3908 carry_out = (b == 0x1f6 ? cpu_cc_dst : cpu_cc_src2);
3909 switch (s->cc_op) {
3910 case CC_OP_ADCX:
3911 if (b == 0x1f6) {
3912 carry_in = cpu_cc_dst;
3913 end_op = CC_OP_ADCX;
3914 } else {
3915 end_op = CC_OP_ADCOX;
3916 }
3917 break;
3918 case CC_OP_ADOX:
3919 if (b == 0x1f6) {
3920 end_op = CC_OP_ADCOX;
3921 } else {
3922 carry_in = cpu_cc_src2;
3923 end_op = CC_OP_ADOX;
3924 }
3925 break;
3926 case CC_OP_ADCOX:
3927 end_op = CC_OP_ADCOX;
3928 carry_in = carry_out;
3929 break;
3930 default:
c53de1a2 3931 end_op = (b == 0x1f6 ? CC_OP_ADCX : CC_OP_ADOX);
cd7f97ca
RH
3932 break;
3933 }
3934 /* If we can't reuse carry-out, get it out of EFLAGS. */
3935 if (TCGV_IS_UNUSED(carry_in)) {
3936 if (s->cc_op != CC_OP_ADCX && s->cc_op != CC_OP_ADOX) {
3937 gen_compute_eflags(s);
3938 }
3939 carry_in = cpu_tmp0;
3940 tcg_gen_shri_tl(carry_in, cpu_cc_src,
3941 ctz32(b == 0x1f6 ? CC_C : CC_O));
3942 tcg_gen_andi_tl(carry_in, carry_in, 1);
3943 }
3944
3945 switch (ot) {
3946#ifdef TARGET_X86_64
4ba9938c 3947 case MO_32:
cd7f97ca
RH
3948 /* If we know TL is 64-bit, and we want a 32-bit
3949 result, just do everything in 64-bit arithmetic. */
3950 tcg_gen_ext32u_i64(cpu_regs[reg], cpu_regs[reg]);
3951 tcg_gen_ext32u_i64(cpu_T[0], cpu_T[0]);
3952 tcg_gen_add_i64(cpu_T[0], cpu_T[0], cpu_regs[reg]);
3953 tcg_gen_add_i64(cpu_T[0], cpu_T[0], carry_in);
3954 tcg_gen_ext32u_i64(cpu_regs[reg], cpu_T[0]);
3955 tcg_gen_shri_i64(carry_out, cpu_T[0], 32);
3956 break;
3957#endif
3958 default:
3959 /* Otherwise compute the carry-out in two steps. */
76f13133
RH
3960 zero = tcg_const_tl(0);
3961 tcg_gen_add2_tl(cpu_T[0], carry_out,
3962 cpu_T[0], zero,
3963 carry_in, zero);
3964 tcg_gen_add2_tl(cpu_regs[reg], carry_out,
3965 cpu_regs[reg], carry_out,
3966 cpu_T[0], zero);
3967 tcg_temp_free(zero);
cd7f97ca
RH
3968 break;
3969 }
cd7f97ca
RH
3970 set_cc_op(s, end_op);
3971 }
3972 break;
3973
4a554890
RH
3974 case 0x1f7: /* shlx Gy, Ey, By */
3975 case 0x2f7: /* sarx Gy, Ey, By */
3976 case 0x3f7: /* shrx Gy, Ey, By */
3977 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
3978 || !(s->prefix & PREFIX_VEX)
3979 || s->vex_l != 0) {
3980 goto illegal_op;
3981 }
ab4e4aec 3982 ot = mo_64_32(s->dflag);
4a554890 3983 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4ba9938c 3984 if (ot == MO_64) {
4a554890
RH
3985 tcg_gen_andi_tl(cpu_T[1], cpu_regs[s->vex_v], 63);
3986 } else {
3987 tcg_gen_andi_tl(cpu_T[1], cpu_regs[s->vex_v], 31);
3988 }
3989 if (b == 0x1f7) {
3990 tcg_gen_shl_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
3991 } else if (b == 0x2f7) {
4ba9938c 3992 if (ot != MO_64) {
4a554890
RH
3993 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
3994 }
3995 tcg_gen_sar_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
3996 } else {
4ba9938c 3997 if (ot != MO_64) {
4a554890
RH
3998 tcg_gen_ext32u_tl(cpu_T[0], cpu_T[0]);
3999 }
4000 tcg_gen_shr_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
4001 }
480a762d 4002 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
4a554890
RH
4003 break;
4004
bc4b43dc
RH
4005 case 0x0f3:
4006 case 0x1f3:
4007 case 0x2f3:
4008 case 0x3f3: /* Group 17 */
4009 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)
4010 || !(s->prefix & PREFIX_VEX)
4011 || s->vex_l != 0) {
4012 goto illegal_op;
4013 }
ab4e4aec 4014 ot = mo_64_32(s->dflag);
bc4b43dc
RH
4015 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4016
4017 switch (reg & 7) {
4018 case 1: /* blsr By,Ey */
4019 tcg_gen_neg_tl(cpu_T[1], cpu_T[0]);
4020 tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
480a762d 4021 gen_op_mov_reg_v(ot, s->vex_v, cpu_T[0]);
bc4b43dc
RH
4022 gen_op_update2_cc();
4023 set_cc_op(s, CC_OP_BMILGB + ot);
4024 break;
4025
4026 case 2: /* blsmsk By,Ey */
4027 tcg_gen_mov_tl(cpu_cc_src, cpu_T[0]);
4028 tcg_gen_subi_tl(cpu_T[0], cpu_T[0], 1);
4029 tcg_gen_xor_tl(cpu_T[0], cpu_T[0], cpu_cc_src);
4030 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4031 set_cc_op(s, CC_OP_BMILGB + ot);
4032 break;
4033
4034 case 3: /* blsi By, Ey */
4035 tcg_gen_mov_tl(cpu_cc_src, cpu_T[0]);
4036 tcg_gen_subi_tl(cpu_T[0], cpu_T[0], 1);
4037 tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_cc_src);
4038 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4039 set_cc_op(s, CC_OP_BMILGB + ot);
4040 break;
4041
4042 default:
4043 goto illegal_op;
4044 }
4045 break;
4046
111994ee
RH
4047 default:
4048 goto illegal_op;
4049 }
222a3336 4050 break;
111994ee 4051
222a3336
AZ
4052 case 0x03a:
4053 case 0x13a:
4242b1bd 4054 b = modrm;
0af10c86 4055 modrm = cpu_ldub_code(env, s->pc++);
4242b1bd
AZ
4056 rm = modrm & 7;
4057 reg = ((modrm >> 3) & 7) | rex_r;
4058 mod = (modrm >> 6) & 3;
c045af25
AK
4059 if (b1 >= 2) {
4060 goto illegal_op;
4061 }
4242b1bd 4062
d3eb5eae
BS
4063 sse_fn_eppi = sse_op_table7[b].op[b1];
4064 if (!sse_fn_eppi) {
4242b1bd 4065 goto illegal_op;
c4baa050 4066 }
222a3336
AZ
4067 if (!(s->cpuid_ext_features & sse_op_table7[b].ext_mask))
4068 goto illegal_op;
4069
d3eb5eae 4070 if (sse_fn_eppi == SSE_SPECIAL) {
ab4e4aec 4071 ot = mo_64_32(s->dflag);
222a3336
AZ
4072 rm = (modrm & 7) | REX_B(s);
4073 if (mod != 3)
4eeb3939 4074 gen_lea_modrm(env, s, modrm);
222a3336 4075 reg = ((modrm >> 3) & 7) | rex_r;
0af10c86 4076 val = cpu_ldub_code(env, s->pc++);
222a3336
AZ
4077 switch (b) {
4078 case 0x14: /* pextrb */
4079 tcg_gen_ld8u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,
4080 xmm_regs[reg].XMM_B(val & 15)));
3523e4bd 4081 if (mod == 3) {
480a762d 4082 gen_op_mov_reg_v(ot, rm, cpu_T[0]);
3523e4bd
RH
4083 } else {
4084 tcg_gen_qemu_st_tl(cpu_T[0], cpu_A0,
4085 s->mem_index, MO_UB);
4086 }
222a3336
AZ
4087 break;
4088 case 0x15: /* pextrw */
4089 tcg_gen_ld16u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,
4090 xmm_regs[reg].XMM_W(val & 7)));
3523e4bd 4091 if (mod == 3) {
480a762d 4092 gen_op_mov_reg_v(ot, rm, cpu_T[0]);
3523e4bd
RH
4093 } else {
4094 tcg_gen_qemu_st_tl(cpu_T[0], cpu_A0,
4095 s->mem_index, MO_LEUW);
4096 }
222a3336
AZ
4097 break;
4098 case 0x16:
4ba9938c 4099 if (ot == MO_32) { /* pextrd */
222a3336
AZ
4100 tcg_gen_ld_i32(cpu_tmp2_i32, cpu_env,
4101 offsetof(CPUX86State,
4102 xmm_regs[reg].XMM_L(val & 3)));
3523e4bd 4103 if (mod == 3) {
a7fbcbe5 4104 tcg_gen_extu_i32_tl(cpu_regs[rm], cpu_tmp2_i32);
3523e4bd 4105 } else {
d5601ad0
RH
4106 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
4107 s->mem_index, MO_LEUL);
3523e4bd 4108 }
222a3336 4109 } else { /* pextrq */
a7812ae4 4110#ifdef TARGET_X86_64
222a3336
AZ
4111 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env,
4112 offsetof(CPUX86State,
4113 xmm_regs[reg].XMM_Q(val & 1)));
3523e4bd 4114 if (mod == 3) {
a7fbcbe5 4115 tcg_gen_mov_i64(cpu_regs[rm], cpu_tmp1_i64);
3523e4bd
RH
4116 } else {
4117 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0,
4118 s->mem_index, MO_LEQ);
4119 }
a7812ae4
PB
4120#else
4121 goto illegal_op;
4122#endif
222a3336
AZ
4123 }
4124 break;
4125 case 0x17: /* extractps */
4126 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,
4127 xmm_regs[reg].XMM_L(val & 3)));
3523e4bd 4128 if (mod == 3) {
480a762d 4129 gen_op_mov_reg_v(ot, rm, cpu_T[0]);
3523e4bd
RH
4130 } else {
4131 tcg_gen_qemu_st_tl(cpu_T[0], cpu_A0,
4132 s->mem_index, MO_LEUL);
4133 }
222a3336
AZ
4134 break;
4135 case 0x20: /* pinsrb */
3c5f4116 4136 if (mod == 3) {
c56baccf 4137 gen_op_mov_v_reg(MO_32, cpu_T[0], rm);
3c5f4116
RH
4138 } else {
4139 tcg_gen_qemu_ld_tl(cpu_T[0], cpu_A0,
4140 s->mem_index, MO_UB);
4141 }
34c6addd 4142 tcg_gen_st8_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,
222a3336
AZ
4143 xmm_regs[reg].XMM_B(val & 15)));
4144 break;
4145 case 0x21: /* insertps */
a7812ae4 4146 if (mod == 3) {
222a3336
AZ
4147 tcg_gen_ld_i32(cpu_tmp2_i32, cpu_env,
4148 offsetof(CPUX86State,xmm_regs[rm]
4149 .XMM_L((val >> 6) & 3)));
a7812ae4 4150 } else {
3c5f4116
RH
4151 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
4152 s->mem_index, MO_LEUL);
a7812ae4 4153 }
222a3336
AZ
4154 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env,
4155 offsetof(CPUX86State,xmm_regs[reg]
4156 .XMM_L((val >> 4) & 3)));
4157 if ((val >> 0) & 1)
4158 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4159 cpu_env, offsetof(CPUX86State,
4160 xmm_regs[reg].XMM_L(0)));
4161 if ((val >> 1) & 1)
4162 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4163 cpu_env, offsetof(CPUX86State,
4164 xmm_regs[reg].XMM_L(1)));
4165 if ((val >> 2) & 1)
4166 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4167 cpu_env, offsetof(CPUX86State,
4168 xmm_regs[reg].XMM_L(2)));
4169 if ((val >> 3) & 1)
4170 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4171 cpu_env, offsetof(CPUX86State,
4172 xmm_regs[reg].XMM_L(3)));
4173 break;
4174 case 0x22:
4ba9938c 4175 if (ot == MO_32) { /* pinsrd */
3c5f4116 4176 if (mod == 3) {
80b02013 4177 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_regs[rm]);
3c5f4116 4178 } else {
80b02013
RH
4179 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
4180 s->mem_index, MO_LEUL);
3c5f4116 4181 }
222a3336
AZ
4182 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env,
4183 offsetof(CPUX86State,
4184 xmm_regs[reg].XMM_L(val & 3)));
4185 } else { /* pinsrq */
a7812ae4 4186#ifdef TARGET_X86_64
3c5f4116 4187 if (mod == 3) {
222a3336 4188 gen_op_mov_v_reg(ot, cpu_tmp1_i64, rm);
3c5f4116
RH
4189 } else {
4190 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_A0,
4191 s->mem_index, MO_LEQ);
4192 }
222a3336
AZ
4193 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env,
4194 offsetof(CPUX86State,
4195 xmm_regs[reg].XMM_Q(val & 1)));
a7812ae4
PB
4196#else
4197 goto illegal_op;
4198#endif
222a3336
AZ
4199 }
4200 break;
4201 }
4202 return;
4203 }
4242b1bd
AZ
4204
4205 if (b1) {
4206 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
4207 if (mod == 3) {
4208 op2_offset = offsetof(CPUX86State,xmm_regs[rm | REX_B(s)]);
4209 } else {
4210 op2_offset = offsetof(CPUX86State,xmm_t0);
4eeb3939 4211 gen_lea_modrm(env, s, modrm);
323d1876 4212 gen_ldo_env_A0(s, op2_offset);
4242b1bd
AZ
4213 }
4214 } else {
4215 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
4216 if (mod == 3) {
4217 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
4218 } else {
4219 op2_offset = offsetof(CPUX86State,mmx_t0);
4eeb3939 4220 gen_lea_modrm(env, s, modrm);
323d1876 4221 gen_ldq_env_A0(s, op2_offset);
4242b1bd
AZ
4222 }
4223 }
0af10c86 4224 val = cpu_ldub_code(env, s->pc++);
4242b1bd 4225
222a3336 4226 if ((b & 0xfc) == 0x60) { /* pcmpXstrX */
3ca51d07 4227 set_cc_op(s, CC_OP_EFLAGS);
222a3336 4228
ab4e4aec 4229 if (s->dflag == MO_64) {
222a3336
AZ
4230 /* The helper must use entire 64-bit gp registers */
4231 val |= 1 << 8;
ab4e4aec 4232 }
222a3336
AZ
4233 }
4234
4242b1bd
AZ
4235 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4236 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
d3eb5eae 4237 sse_fn_eppi(cpu_env, cpu_ptr0, cpu_ptr1, tcg_const_i32(val));
4242b1bd 4238 break;
e2c3c2c5
RH
4239
4240 case 0x33a:
4241 /* Various integer extensions at 0f 3a f[0-f]. */
4242 b = modrm | (b1 << 8);
4243 modrm = cpu_ldub_code(env, s->pc++);
4244 reg = ((modrm >> 3) & 7) | rex_r;
4245
4246 switch (b) {
4247 case 0x3f0: /* rorx Gy,Ey, Ib */
4248 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI2)
4249 || !(s->prefix & PREFIX_VEX)
4250 || s->vex_l != 0) {
4251 goto illegal_op;
4252 }
ab4e4aec 4253 ot = mo_64_32(s->dflag);
e2c3c2c5
RH
4254 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4255 b = cpu_ldub_code(env, s->pc++);
4ba9938c 4256 if (ot == MO_64) {
e2c3c2c5
RH
4257 tcg_gen_rotri_tl(cpu_T[0], cpu_T[0], b & 63);
4258 } else {
4259 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
4260 tcg_gen_rotri_i32(cpu_tmp2_i32, cpu_tmp2_i32, b & 31);
4261 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
4262 }
480a762d 4263 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
e2c3c2c5
RH
4264 break;
4265
4266 default:
4267 goto illegal_op;
4268 }
4269 break;
4270
664e0f19
FB
4271 default:
4272 goto illegal_op;
4273 }
4274 } else {
4275 /* generic MMX or SSE operation */
d1e42c5c 4276 switch(b) {
d1e42c5c
FB
4277 case 0x70: /* pshufx insn */
4278 case 0xc6: /* pshufx insn */
4279 case 0xc2: /* compare insns */
4280 s->rip_offset = 1;
4281 break;
4282 default:
4283 break;
664e0f19
FB
4284 }
4285 if (is_xmm) {
4286 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
4287 if (mod != 3) {
cb48da7f
RH
4288 int sz = 4;
4289
4eeb3939 4290 gen_lea_modrm(env, s, modrm);
664e0f19 4291 op2_offset = offsetof(CPUX86State,xmm_t0);
cb48da7f
RH
4292
4293 switch (b) {
4294 case 0x50 ... 0x5a:
4295 case 0x5c ... 0x5f:
4296 case 0xc2:
4297 /* Most sse scalar operations. */
664e0f19 4298 if (b1 == 2) {
cb48da7f
RH
4299 sz = 2;
4300 } else if (b1 == 3) {
4301 sz = 3;
4302 }
4303 break;
4304
4305 case 0x2e: /* ucomis[sd] */
4306 case 0x2f: /* comis[sd] */
4307 if (b1 == 0) {
4308 sz = 2;
664e0f19 4309 } else {
cb48da7f 4310 sz = 3;
664e0f19 4311 }
cb48da7f
RH
4312 break;
4313 }
4314
4315 switch (sz) {
4316 case 2:
4317 /* 32 bit access */
4318 gen_op_ld_v(s, MO_32, cpu_T[0], cpu_A0);
4319 tcg_gen_st32_tl(cpu_T[0], cpu_env,
4320 offsetof(CPUX86State,xmm_t0.XMM_L(0)));
4321 break;
4322 case 3:
4323 /* 64 bit access */
4324 gen_ldq_env_A0(s, offsetof(CPUX86State, xmm_t0.XMM_D(0)));
4325 break;
4326 default:
4327 /* 128 bit access */
323d1876 4328 gen_ldo_env_A0(s, op2_offset);
cb48da7f 4329 break;
664e0f19
FB
4330 }
4331 } else {
4332 rm = (modrm & 7) | REX_B(s);
4333 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
4334 }
4335 } else {
4336 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
4337 if (mod != 3) {
4eeb3939 4338 gen_lea_modrm(env, s, modrm);
664e0f19 4339 op2_offset = offsetof(CPUX86State,mmx_t0);
323d1876 4340 gen_ldq_env_A0(s, op2_offset);
664e0f19
FB
4341 } else {
4342 rm = (modrm & 7);
4343 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
4344 }
4345 }
4346 switch(b) {
a35f3ec7 4347 case 0x0f: /* 3DNow! data insns */
e771edab
AJ
4348 if (!(s->cpuid_ext2_features & CPUID_EXT2_3DNOW))
4349 goto illegal_op;
0af10c86 4350 val = cpu_ldub_code(env, s->pc++);
d3eb5eae
BS
4351 sse_fn_epp = sse_op_table5[val];
4352 if (!sse_fn_epp) {
a35f3ec7 4353 goto illegal_op;
c4baa050 4354 }
5af45186
FB
4355 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4356 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
d3eb5eae 4357 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
a35f3ec7 4358 break;
664e0f19
FB
4359 case 0x70: /* pshufx insn */
4360 case 0xc6: /* pshufx insn */
0af10c86 4361 val = cpu_ldub_code(env, s->pc++);
5af45186
FB
4362 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4363 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
c4baa050 4364 /* XXX: introduce a new table? */
d3eb5eae 4365 sse_fn_ppi = (SSEFunc_0_ppi)sse_fn_epp;
c4baa050 4366 sse_fn_ppi(cpu_ptr0, cpu_ptr1, tcg_const_i32(val));
664e0f19
FB
4367 break;
4368 case 0xc2:
4369 /* compare insns */
0af10c86 4370 val = cpu_ldub_code(env, s->pc++);
664e0f19
FB
4371 if (val >= 8)
4372 goto illegal_op;
d3eb5eae 4373 sse_fn_epp = sse_op_table4[val][b1];
c4baa050 4374
5af45186
FB
4375 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4376 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
d3eb5eae 4377 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
664e0f19 4378 break;
b8b6a50b
FB
4379 case 0xf7:
4380 /* maskmov : we must prepare A0 */
4381 if (mod != 3)
4382 goto illegal_op;
1d71ddb1
RH
4383 tcg_gen_mov_tl(cpu_A0, cpu_regs[R_EDI]);
4384 gen_extu(s->aflag, cpu_A0);
b8b6a50b
FB
4385 gen_add_A0_ds_seg(s);
4386
4387 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4388 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
c4baa050 4389 /* XXX: introduce a new table? */
d3eb5eae
BS
4390 sse_fn_eppt = (SSEFunc_0_eppt)sse_fn_epp;
4391 sse_fn_eppt(cpu_env, cpu_ptr0, cpu_ptr1, cpu_A0);
b8b6a50b 4392 break;
664e0f19 4393 default:
5af45186
FB
4394 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4395 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
d3eb5eae 4396 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
664e0f19
FB
4397 break;
4398 }
4399 if (b == 0x2e || b == 0x2f) {
3ca51d07 4400 set_cc_op(s, CC_OP_EFLAGS);
664e0f19
FB
4401 }
4402 }
4403}
4404
2c0262af
FB
4405/* convert one instruction. s->is_jmp is set if the translation must
4406 be stopped. Return the next pc value */
0af10c86
BS
4407static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
4408 target_ulong pc_start)
2c0262af 4409{
ab4e4aec 4410 int b, prefixes;
d67dc9e6 4411 int shift;
ab4e4aec 4412 TCGMemOp ot, aflag, dflag;
4eeb3939 4413 int modrm, reg, rm, mod, op, opreg, val;
14ce26e7
FB
4414 target_ulong next_eip, tval;
4415 int rex_w, rex_r;
2c0262af 4416
fdefe51c 4417 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
70cff25e 4418 tcg_gen_debug_insn_start(pc_start);
fdefe51c 4419 }
2c0262af
FB
4420 s->pc = pc_start;
4421 prefixes = 0;
2c0262af 4422 s->override = -1;
14ce26e7
FB
4423 rex_w = -1;
4424 rex_r = 0;
4425#ifdef TARGET_X86_64
4426 s->rex_x = 0;
4427 s->rex_b = 0;
5fafdf24 4428 x86_64_hregs = 0;
14ce26e7
FB
4429#endif
4430 s->rip_offset = 0; /* for relative ip address */
701ed211
RH
4431 s->vex_l = 0;
4432 s->vex_v = 0;
2c0262af 4433 next_byte:
0af10c86 4434 b = cpu_ldub_code(env, s->pc);
2c0262af 4435 s->pc++;
4a6fd938
RH
4436 /* Collect prefixes. */
4437 switch (b) {
4438 case 0xf3:
4439 prefixes |= PREFIX_REPZ;
4440 goto next_byte;
4441 case 0xf2:
4442 prefixes |= PREFIX_REPNZ;
4443 goto next_byte;
4444 case 0xf0:
4445 prefixes |= PREFIX_LOCK;
4446 goto next_byte;
4447 case 0x2e:
4448 s->override = R_CS;
4449 goto next_byte;
4450 case 0x36:
4451 s->override = R_SS;
4452 goto next_byte;
4453 case 0x3e:
4454 s->override = R_DS;
4455 goto next_byte;
4456 case 0x26:
4457 s->override = R_ES;
4458 goto next_byte;
4459 case 0x64:
4460 s->override = R_FS;
4461 goto next_byte;
4462 case 0x65:
4463 s->override = R_GS;
4464 goto next_byte;
4465 case 0x66:
4466 prefixes |= PREFIX_DATA;
4467 goto next_byte;
4468 case 0x67:
4469 prefixes |= PREFIX_ADR;
4470 goto next_byte;
14ce26e7 4471#ifdef TARGET_X86_64
4a6fd938
RH
4472 case 0x40 ... 0x4f:
4473 if (CODE64(s)) {
14ce26e7
FB
4474 /* REX prefix */
4475 rex_w = (b >> 3) & 1;
4476 rex_r = (b & 0x4) << 1;
4477 s->rex_x = (b & 0x2) << 2;
4478 REX_B(s) = (b & 0x1) << 3;
4479 x86_64_hregs = 1; /* select uniform byte register addressing */
4480 goto next_byte;
4481 }
4a6fd938
RH
4482 break;
4483#endif
701ed211
RH
4484 case 0xc5: /* 2-byte VEX */
4485 case 0xc4: /* 3-byte VEX */
4486 /* VEX prefixes cannot be used except in 32-bit mode.
4487 Otherwise the instruction is LES or LDS. */
4488 if (s->code32 && !s->vm86) {
4489 static const int pp_prefix[4] = {
4490 0, PREFIX_DATA, PREFIX_REPZ, PREFIX_REPNZ
4491 };
4492 int vex3, vex2 = cpu_ldub_code(env, s->pc);
4493
4494 if (!CODE64(s) && (vex2 & 0xc0) != 0xc0) {
4495 /* 4.1.4.6: In 32-bit mode, bits [7:6] must be 11b,
4496 otherwise the instruction is LES or LDS. */
4497 break;
4498 }
4499 s->pc++;
4500
085d8134 4501 /* 4.1.1-4.1.3: No preceding lock, 66, f2, f3, or rex prefixes. */
701ed211
RH
4502 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ
4503 | PREFIX_LOCK | PREFIX_DATA)) {
4504 goto illegal_op;
4505 }
4506#ifdef TARGET_X86_64
4507 if (x86_64_hregs) {
4508 goto illegal_op;
4509 }
4510#endif
4511 rex_r = (~vex2 >> 4) & 8;
4512 if (b == 0xc5) {
4513 vex3 = vex2;
4514 b = cpu_ldub_code(env, s->pc++);
4515 } else {
4516#ifdef TARGET_X86_64
4517 s->rex_x = (~vex2 >> 3) & 8;
4518 s->rex_b = (~vex2 >> 2) & 8;
4519#endif
4520 vex3 = cpu_ldub_code(env, s->pc++);
4521 rex_w = (vex3 >> 7) & 1;
4522 switch (vex2 & 0x1f) {
4523 case 0x01: /* Implied 0f leading opcode bytes. */
4524 b = cpu_ldub_code(env, s->pc++) | 0x100;
4525 break;
4526 case 0x02: /* Implied 0f 38 leading opcode bytes. */
4527 b = 0x138;
4528 break;
4529 case 0x03: /* Implied 0f 3a leading opcode bytes. */
4530 b = 0x13a;
4531 break;
4532 default: /* Reserved for future use. */
4533 goto illegal_op;
4534 }
4535 }
4536 s->vex_v = (~vex3 >> 3) & 0xf;
4537 s->vex_l = (vex3 >> 2) & 1;
4538 prefixes |= pp_prefix[vex3 & 3] | PREFIX_VEX;
4539 }
4540 break;
4a6fd938
RH
4541 }
4542
4543 /* Post-process prefixes. */
4a6fd938 4544 if (CODE64(s)) {
dec3fc96
RH
4545 /* In 64-bit mode, the default data size is 32-bit. Select 64-bit
4546 data with rex_w, and 16-bit data with 0x66; rex_w takes precedence
4547 over 0x66 if both are present. */
ab4e4aec 4548 dflag = (rex_w > 0 ? MO_64 : prefixes & PREFIX_DATA ? MO_16 : MO_32);
dec3fc96 4549 /* In 64-bit mode, 0x67 selects 32-bit addressing. */
1d71ddb1 4550 aflag = (prefixes & PREFIX_ADR ? MO_32 : MO_64);
dec3fc96
RH
4551 } else {
4552 /* In 16/32-bit mode, 0x66 selects the opposite data size. */
ab4e4aec
RH
4553 if (s->code32 ^ ((prefixes & PREFIX_DATA) != 0)) {
4554 dflag = MO_32;
4555 } else {
4556 dflag = MO_16;
14ce26e7 4557 }
dec3fc96 4558 /* In 16/32-bit mode, 0x67 selects the opposite addressing. */
1d71ddb1
RH
4559 if (s->code32 ^ ((prefixes & PREFIX_ADR) != 0)) {
4560 aflag = MO_32;
4561 } else {
4562 aflag = MO_16;
14ce26e7 4563 }
2c0262af
FB
4564 }
4565
2c0262af
FB
4566 s->prefix = prefixes;
4567 s->aflag = aflag;
4568 s->dflag = dflag;
4569
4570 /* lock generation */
4571 if (prefixes & PREFIX_LOCK)
a7812ae4 4572 gen_helper_lock();
2c0262af
FB
4573
4574 /* now check op code */
4575 reswitch:
4576 switch(b) {
4577 case 0x0f:
4578 /**************************/
4579 /* extended op code */
0af10c86 4580 b = cpu_ldub_code(env, s->pc++) | 0x100;
2c0262af 4581 goto reswitch;
3b46e624 4582
2c0262af
FB
4583 /**************************/
4584 /* arith & logic */
4585 case 0x00 ... 0x05:
4586 case 0x08 ... 0x0d:
4587 case 0x10 ... 0x15:
4588 case 0x18 ... 0x1d:
4589 case 0x20 ... 0x25:
4590 case 0x28 ... 0x2d:
4591 case 0x30 ... 0x35:
4592 case 0x38 ... 0x3d:
4593 {
4594 int op, f, val;
4595 op = (b >> 3) & 7;
4596 f = (b >> 1) & 3;
4597
ab4e4aec 4598 ot = mo_b_d(b, dflag);
3b46e624 4599
2c0262af
FB
4600 switch(f) {
4601 case 0: /* OP Ev, Gv */
0af10c86 4602 modrm = cpu_ldub_code(env, s->pc++);
14ce26e7 4603 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af 4604 mod = (modrm >> 6) & 3;
14ce26e7 4605 rm = (modrm & 7) | REX_B(s);
2c0262af 4606 if (mod != 3) {
4eeb3939 4607 gen_lea_modrm(env, s, modrm);
2c0262af
FB
4608 opreg = OR_TMP0;
4609 } else if (op == OP_XORL && rm == reg) {
4610 xor_zero:
4611 /* xor reg, reg optimisation */
436ff2d2 4612 set_cc_op(s, CC_OP_CLR);
97212c88 4613 tcg_gen_movi_tl(cpu_T[0], 0);
480a762d 4614 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
2c0262af
FB
4615 break;
4616 } else {
4617 opreg = rm;
4618 }
c56baccf 4619 gen_op_mov_v_reg(ot, cpu_T[1], reg);
2c0262af
FB
4620 gen_op(s, op, ot, opreg);
4621 break;
4622 case 1: /* OP Gv, Ev */
0af10c86 4623 modrm = cpu_ldub_code(env, s->pc++);
2c0262af 4624 mod = (modrm >> 6) & 3;
14ce26e7
FB
4625 reg = ((modrm >> 3) & 7) | rex_r;
4626 rm = (modrm & 7) | REX_B(s);
2c0262af 4627 if (mod != 3) {
4eeb3939 4628 gen_lea_modrm(env, s, modrm);
0f712e10 4629 gen_op_ld_v(s, ot, cpu_T[1], cpu_A0);
2c0262af
FB
4630 } else if (op == OP_XORL && rm == reg) {
4631 goto xor_zero;
4632 } else {
c56baccf 4633 gen_op_mov_v_reg(ot, cpu_T[1], rm);
2c0262af
FB
4634 }
4635 gen_op(s, op, ot, reg);
4636 break;
4637 case 2: /* OP A, Iv */
0af10c86 4638 val = insn_get(env, s, ot);
0ae657b1 4639 tcg_gen_movi_tl(cpu_T[1], val);
2c0262af
FB
4640 gen_op(s, op, ot, OR_EAX);
4641 break;
4642 }
4643 }
4644 break;
4645
ec9d6075
FB
4646 case 0x82:
4647 if (CODE64(s))
4648 goto illegal_op;
2c0262af
FB
4649 case 0x80: /* GRP1 */
4650 case 0x81:
4651 case 0x83:
4652 {
4653 int val;
4654
ab4e4aec 4655 ot = mo_b_d(b, dflag);
3b46e624 4656
0af10c86 4657 modrm = cpu_ldub_code(env, s->pc++);
2c0262af 4658 mod = (modrm >> 6) & 3;
14ce26e7 4659 rm = (modrm & 7) | REX_B(s);
2c0262af 4660 op = (modrm >> 3) & 7;
3b46e624 4661
2c0262af 4662 if (mod != 3) {
14ce26e7
FB
4663 if (b == 0x83)
4664 s->rip_offset = 1;
4665 else
4666 s->rip_offset = insn_const_size(ot);
4eeb3939 4667 gen_lea_modrm(env, s, modrm);
2c0262af
FB
4668 opreg = OR_TMP0;
4669 } else {
14ce26e7 4670 opreg = rm;
2c0262af
FB
4671 }
4672
4673 switch(b) {
4674 default:
4675 case 0x80:
4676 case 0x81:
d64477af 4677 case 0x82:
0af10c86 4678 val = insn_get(env, s, ot);
2c0262af
FB
4679 break;
4680 case 0x83:
4ba9938c 4681 val = (int8_t)insn_get(env, s, MO_8);
2c0262af
FB
4682 break;
4683 }
0ae657b1 4684 tcg_gen_movi_tl(cpu_T[1], val);
2c0262af
FB
4685 gen_op(s, op, ot, opreg);
4686 }
4687 break;
4688
4689 /**************************/
4690 /* inc, dec, and other misc arith */
4691 case 0x40 ... 0x47: /* inc Gv */
ab4e4aec 4692 ot = dflag;
2c0262af
FB
4693 gen_inc(s, ot, OR_EAX + (b & 7), 1);
4694 break;
4695 case 0x48 ... 0x4f: /* dec Gv */
ab4e4aec 4696 ot = dflag;
2c0262af
FB
4697 gen_inc(s, ot, OR_EAX + (b & 7), -1);
4698 break;
4699 case 0xf6: /* GRP3 */
4700 case 0xf7:
ab4e4aec 4701 ot = mo_b_d(b, dflag);
2c0262af 4702
0af10c86 4703 modrm = cpu_ldub_code(env, s->pc++);
2c0262af 4704 mod = (modrm >> 6) & 3;
14ce26e7 4705 rm = (modrm & 7) | REX_B(s);
2c0262af
FB
4706 op = (modrm >> 3) & 7;
4707 if (mod != 3) {
14ce26e7
FB
4708 if (op == 0)
4709 s->rip_offset = insn_const_size(ot);
4eeb3939 4710 gen_lea_modrm(env, s, modrm);
909be183 4711 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
2c0262af 4712 } else {
c56baccf 4713 gen_op_mov_v_reg(ot, cpu_T[0], rm);
2c0262af
FB
4714 }
4715
4716 switch(op) {
4717 case 0: /* test */
0af10c86 4718 val = insn_get(env, s, ot);
0ae657b1 4719 tcg_gen_movi_tl(cpu_T[1], val);
2c0262af 4720 gen_op_testl_T0_T1_cc();
3ca51d07 4721 set_cc_op(s, CC_OP_LOGICB + ot);
2c0262af
FB
4722 break;
4723 case 2: /* not */
b6abf97d 4724 tcg_gen_not_tl(cpu_T[0], cpu_T[0]);
2c0262af 4725 if (mod != 3) {
fd8ca9f6 4726 gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
2c0262af 4727 } else {
480a762d 4728 gen_op_mov_reg_v(ot, rm, cpu_T[0]);
2c0262af
FB
4729 }
4730 break;
4731 case 3: /* neg */
b6abf97d 4732 tcg_gen_neg_tl(cpu_T[0], cpu_T[0]);
2c0262af 4733 if (mod != 3) {
fd8ca9f6 4734 gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
2c0262af 4735 } else {
480a762d 4736 gen_op_mov_reg_v(ot, rm, cpu_T[0]);
2c0262af
FB
4737 }
4738 gen_op_update_neg_cc();
3ca51d07 4739 set_cc_op(s, CC_OP_SUBB + ot);
2c0262af
FB
4740 break;
4741 case 4: /* mul */
4742 switch(ot) {
4ba9938c 4743 case MO_8:
c56baccf 4744 gen_op_mov_v_reg(MO_8, cpu_T[1], R_EAX);
0211e5af
FB
4745 tcg_gen_ext8u_tl(cpu_T[0], cpu_T[0]);
4746 tcg_gen_ext8u_tl(cpu_T[1], cpu_T[1]);
4747 /* XXX: use 32 bit mul which could be faster */
4748 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
480a762d 4749 gen_op_mov_reg_v(MO_16, R_EAX, cpu_T[0]);
0211e5af
FB
4750 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4751 tcg_gen_andi_tl(cpu_cc_src, cpu_T[0], 0xff00);
3ca51d07 4752 set_cc_op(s, CC_OP_MULB);
2c0262af 4753 break;
4ba9938c 4754 case MO_16:
c56baccf 4755 gen_op_mov_v_reg(MO_16, cpu_T[1], R_EAX);
0211e5af
FB
4756 tcg_gen_ext16u_tl(cpu_T[0], cpu_T[0]);
4757 tcg_gen_ext16u_tl(cpu_T[1], cpu_T[1]);
4758 /* XXX: use 32 bit mul which could be faster */
4759 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
480a762d 4760 gen_op_mov_reg_v(MO_16, R_EAX, cpu_T[0]);
0211e5af
FB
4761 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4762 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 16);
480a762d 4763 gen_op_mov_reg_v(MO_16, R_EDX, cpu_T[0]);
0211e5af 4764 tcg_gen_mov_tl(cpu_cc_src, cpu_T[0]);
3ca51d07 4765 set_cc_op(s, CC_OP_MULW);
2c0262af
FB
4766 break;
4767 default:
4ba9938c 4768 case MO_32:
a4bcea3d
RH
4769 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
4770 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_regs[R_EAX]);
4771 tcg_gen_mulu2_i32(cpu_tmp2_i32, cpu_tmp3_i32,
4772 cpu_tmp2_i32, cpu_tmp3_i32);
4773 tcg_gen_extu_i32_tl(cpu_regs[R_EAX], cpu_tmp2_i32);
4774 tcg_gen_extu_i32_tl(cpu_regs[R_EDX], cpu_tmp3_i32);
4775 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
4776 tcg_gen_mov_tl(cpu_cc_src, cpu_regs[R_EDX]);
3ca51d07 4777 set_cc_op(s, CC_OP_MULL);
2c0262af 4778 break;
14ce26e7 4779#ifdef TARGET_X86_64
4ba9938c 4780 case MO_64:
a4bcea3d
RH
4781 tcg_gen_mulu2_i64(cpu_regs[R_EAX], cpu_regs[R_EDX],
4782 cpu_T[0], cpu_regs[R_EAX]);
4783 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
4784 tcg_gen_mov_tl(cpu_cc_src, cpu_regs[R_EDX]);
3ca51d07 4785 set_cc_op(s, CC_OP_MULQ);
14ce26e7
FB
4786 break;
4787#endif
2c0262af 4788 }
2c0262af
FB
4789 break;
4790 case 5: /* imul */
4791 switch(ot) {
4ba9938c 4792 case MO_8:
c56baccf 4793 gen_op_mov_v_reg(MO_8, cpu_T[1], R_EAX);
0211e5af
FB
4794 tcg_gen_ext8s_tl(cpu_T[0], cpu_T[0]);
4795 tcg_gen_ext8s_tl(cpu_T[1], cpu_T[1]);
4796 /* XXX: use 32 bit mul which could be faster */
4797 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
480a762d 4798 gen_op_mov_reg_v(MO_16, R_EAX, cpu_T[0]);
0211e5af
FB
4799 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4800 tcg_gen_ext8s_tl(cpu_tmp0, cpu_T[0]);
4801 tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0);
3ca51d07 4802 set_cc_op(s, CC_OP_MULB);
2c0262af 4803 break;
4ba9938c 4804 case MO_16:
c56baccf 4805 gen_op_mov_v_reg(MO_16, cpu_T[1], R_EAX);
0211e5af
FB
4806 tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
4807 tcg_gen_ext16s_tl(cpu_T[1], cpu_T[1]);
4808 /* XXX: use 32 bit mul which could be faster */
4809 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
480a762d 4810 gen_op_mov_reg_v(MO_16, R_EAX, cpu_T[0]);
0211e5af
FB
4811 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4812 tcg_gen_ext16s_tl(cpu_tmp0, cpu_T[0]);
4813 tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0);
4814 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 16);
480a762d 4815 gen_op_mov_reg_v(MO_16, R_EDX, cpu_T[0]);
3ca51d07 4816 set_cc_op(s, CC_OP_MULW);
2c0262af
FB
4817 break;
4818 default:
4ba9938c 4819 case MO_32:
a4bcea3d
RH
4820 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
4821 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_regs[R_EAX]);
4822 tcg_gen_muls2_i32(cpu_tmp2_i32, cpu_tmp3_i32,
4823 cpu_tmp2_i32, cpu_tmp3_i32);
4824 tcg_gen_extu_i32_tl(cpu_regs[R_EAX], cpu_tmp2_i32);
4825 tcg_gen_extu_i32_tl(cpu_regs[R_EDX], cpu_tmp3_i32);
4826 tcg_gen_sari_i32(cpu_tmp2_i32, cpu_tmp2_i32, 31);
4827 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
4828 tcg_gen_sub_i32(cpu_tmp2_i32, cpu_tmp2_i32, cpu_tmp3_i32);
4829 tcg_gen_extu_i32_tl(cpu_cc_src, cpu_tmp2_i32);
3ca51d07 4830 set_cc_op(s, CC_OP_MULL);
2c0262af 4831 break;
14ce26e7 4832#ifdef TARGET_X86_64
4ba9938c 4833 case MO_64:
a4bcea3d
RH
4834 tcg_gen_muls2_i64(cpu_regs[R_EAX], cpu_regs[R_EDX],
4835 cpu_T[0], cpu_regs[R_EAX]);
4836 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[R_EAX]);
4837 tcg_gen_sari_tl(cpu_cc_src, cpu_regs[R_EAX], 63);
4838 tcg_gen_sub_tl(cpu_cc_src, cpu_cc_src, cpu_regs[R_EDX]);
3ca51d07 4839 set_cc_op(s, CC_OP_MULQ);
14ce26e7
FB
4840 break;
4841#endif
2c0262af 4842 }
2c0262af
FB
4843 break;
4844 case 6: /* div */
4845 switch(ot) {
4ba9938c 4846 case MO_8:
14ce26e7 4847 gen_jmp_im(pc_start - s->cs_base);
7923057b 4848 gen_helper_divb_AL(cpu_env, cpu_T[0]);
2c0262af 4849 break;
4ba9938c 4850 case MO_16:
14ce26e7 4851 gen_jmp_im(pc_start - s->cs_base);
7923057b 4852 gen_helper_divw_AX(cpu_env, cpu_T[0]);
2c0262af
FB
4853 break;
4854 default:
4ba9938c 4855 case MO_32:
14ce26e7 4856 gen_jmp_im(pc_start - s->cs_base);
7923057b 4857 gen_helper_divl_EAX(cpu_env, cpu_T[0]);
14ce26e7
FB
4858 break;
4859#ifdef TARGET_X86_64
4ba9938c 4860 case MO_64:
14ce26e7 4861 gen_jmp_im(pc_start - s->cs_base);
7923057b 4862 gen_helper_divq_EAX(cpu_env, cpu_T[0]);
2c0262af 4863 break;
14ce26e7 4864#endif
2c0262af
FB
4865 }
4866 break;
4867 case 7: /* idiv */
4868 switch(ot) {
4ba9938c 4869 case MO_8:
14ce26e7 4870 gen_jmp_im(pc_start - s->cs_base);
7923057b 4871 gen_helper_idivb_AL(cpu_env, cpu_T[0]);
2c0262af 4872 break;
4ba9938c 4873 case MO_16:
14ce26e7 4874 gen_jmp_im(pc_start - s->cs_base);
7923057b 4875 gen_helper_idivw_AX(cpu_env, cpu_T[0]);
2c0262af
FB
4876 break;
4877 default:
4ba9938c 4878 case MO_32:
14ce26e7 4879 gen_jmp_im(pc_start - s->cs_base);
7923057b 4880 gen_helper_idivl_EAX(cpu_env, cpu_T[0]);
14ce26e7
FB
4881 break;
4882#ifdef TARGET_X86_64
4ba9938c 4883 case MO_64:
14ce26e7 4884 gen_jmp_im(pc_start - s->cs_base);
7923057b 4885 gen_helper_idivq_EAX(cpu_env, cpu_T[0]);
2c0262af 4886 break;
14ce26e7 4887#endif
2c0262af
FB
4888 }
4889 break;
4890 default:
4891 goto illegal_op;
4892 }
4893 break;
4894
4895 case 0xfe: /* GRP4 */
4896 case 0xff: /* GRP5 */
ab4e4aec 4897 ot = mo_b_d(b, dflag);
2c0262af 4898
0af10c86 4899 modrm = cpu_ldub_code(env, s->pc++);
2c0262af 4900 mod = (modrm >> 6) & 3;
14ce26e7 4901 rm = (modrm & 7) | REX_B(s);
2c0262af
FB
4902 op = (modrm >> 3) & 7;
4903 if (op >= 2 && b == 0xfe) {
4904 goto illegal_op;
4905 }
14ce26e7 4906 if (CODE64(s)) {
aba9d61e 4907 if (op == 2 || op == 4) {
14ce26e7 4908 /* operand size for jumps is 64 bit */
4ba9938c 4909 ot = MO_64;
aba9d61e 4910 } else if (op == 3 || op == 5) {
ab4e4aec 4911 ot = dflag != MO_16 ? MO_32 + (rex_w == 1) : MO_16;
14ce26e7
FB
4912 } else if (op == 6) {
4913 /* default push size is 64 bit */
ab4e4aec 4914 ot = mo_pushpop(s, dflag);
14ce26e7
FB
4915 }
4916 }
2c0262af 4917 if (mod != 3) {
4eeb3939 4918 gen_lea_modrm(env, s, modrm);
2c0262af 4919 if (op >= 2 && op != 3 && op != 5)
909be183 4920 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
2c0262af 4921 } else {
c56baccf 4922 gen_op_mov_v_reg(ot, cpu_T[0], rm);
2c0262af
FB
4923 }
4924
4925 switch(op) {
4926 case 0: /* inc Ev */
4927 if (mod != 3)
4928 opreg = OR_TMP0;
4929 else
4930 opreg = rm;
4931 gen_inc(s, ot, opreg, 1);
4932 break;
4933 case 1: /* dec Ev */
4934 if (mod != 3)
4935 opreg = OR_TMP0;
4936 else
4937 opreg = rm;
4938 gen_inc(s, ot, opreg, -1);
4939 break;
4940 case 2: /* call Ev */
4f31916f 4941 /* XXX: optimize if memory (no 'and' is necessary) */
ab4e4aec 4942 if (dflag == MO_16) {
40b90233
RH
4943 tcg_gen_ext16u_tl(cpu_T[0], cpu_T[0]);
4944 }
2c0262af 4945 next_eip = s->pc - s->cs_base;
cc0bce88 4946 tcg_gen_movi_tl(cpu_T[1], next_eip);
432baffe 4947 gen_push_v(s, cpu_T[1]);
74bdfbda 4948 gen_op_jmp_v(cpu_T[0]);
2c0262af
FB
4949 gen_eob(s);
4950 break;
61382a50 4951 case 3: /* lcall Ev */
0f712e10 4952 gen_op_ld_v(s, ot, cpu_T[1], cpu_A0);
830a19a4 4953 gen_add_A0_im(s, 1 << ot);
cc1a80df 4954 gen_op_ld_v(s, MO_16, cpu_T[0], cpu_A0);
2c0262af
FB
4955 do_lcall:
4956 if (s->pe && !s->vm86) {
773cdfcc 4957 gen_update_cc_op(s);
14ce26e7 4958 gen_jmp_im(pc_start - s->cs_base);
b6abf97d 4959 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
2999a0b2 4960 gen_helper_lcall_protected(cpu_env, cpu_tmp2_i32, cpu_T[1],
ab4e4aec 4961 tcg_const_i32(dflag - 1),
a7812ae4 4962 tcg_const_i32(s->pc - pc_start));
2c0262af 4963 } else {
b6abf97d 4964 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
2999a0b2 4965 gen_helper_lcall_real(cpu_env, cpu_tmp2_i32, cpu_T[1],
ab4e4aec 4966 tcg_const_i32(dflag - 1),
a7812ae4 4967 tcg_const_i32(s->pc - s->cs_base));
2c0262af
FB
4968 }
4969 gen_eob(s);
4970 break;
4971 case 4: /* jmp Ev */
ab4e4aec 4972 if (dflag == MO_16) {
40b90233
RH
4973 tcg_gen_ext16u_tl(cpu_T[0], cpu_T[0]);
4974 }
74bdfbda 4975 gen_op_jmp_v(cpu_T[0]);
2c0262af
FB
4976 gen_eob(s);
4977 break;
4978 case 5: /* ljmp Ev */
0f712e10 4979 gen_op_ld_v(s, ot, cpu_T[1], cpu_A0);
830a19a4 4980 gen_add_A0_im(s, 1 << ot);
cc1a80df 4981 gen_op_ld_v(s, MO_16, cpu_T[0], cpu_A0);
2c0262af
FB
4982 do_ljmp:
4983 if (s->pe && !s->vm86) {
773cdfcc 4984 gen_update_cc_op(s);
14ce26e7 4985 gen_jmp_im(pc_start - s->cs_base);
b6abf97d 4986 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
2999a0b2 4987 gen_helper_ljmp_protected(cpu_env, cpu_tmp2_i32, cpu_T[1],
a7812ae4 4988 tcg_const_i32(s->pc - pc_start));
2c0262af 4989 } else {
3bd7da9e 4990 gen_op_movl_seg_T0_vm(R_CS);
78261634 4991 gen_op_jmp_v(cpu_T[1]);
2c0262af
FB
4992 }
4993 gen_eob(s);
4994 break;
4995 case 6: /* push Ev */
432baffe 4996 gen_push_v(s, cpu_T[0]);
2c0262af
FB
4997 break;
4998 default:
4999 goto illegal_op;
5000 }
5001 break;
5002
5003 case 0x84: /* test Ev, Gv */
5fafdf24 5004 case 0x85:
ab4e4aec 5005 ot = mo_b_d(b, dflag);
2c0262af 5006
0af10c86 5007 modrm = cpu_ldub_code(env, s->pc++);
14ce26e7 5008 reg = ((modrm >> 3) & 7) | rex_r;
3b46e624 5009
0af10c86 5010 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
c56baccf 5011 gen_op_mov_v_reg(ot, cpu_T[1], reg);
2c0262af 5012 gen_op_testl_T0_T1_cc();
3ca51d07 5013 set_cc_op(s, CC_OP_LOGICB + ot);
2c0262af 5014 break;
3b46e624 5015
2c0262af
FB
5016 case 0xa8: /* test eAX, Iv */
5017 case 0xa9:
ab4e4aec 5018 ot = mo_b_d(b, dflag);
0af10c86 5019 val = insn_get(env, s, ot);
2c0262af 5020
c56baccf 5021 gen_op_mov_v_reg(ot, cpu_T[0], OR_EAX);
0ae657b1 5022 tcg_gen_movi_tl(cpu_T[1], val);
2c0262af 5023 gen_op_testl_T0_T1_cc();
3ca51d07 5024 set_cc_op(s, CC_OP_LOGICB + ot);
2c0262af 5025 break;
3b46e624 5026
2c0262af 5027 case 0x98: /* CWDE/CBW */
ab4e4aec 5028 switch (dflag) {
14ce26e7 5029#ifdef TARGET_X86_64
ab4e4aec 5030 case MO_64:
c56baccf 5031 gen_op_mov_v_reg(MO_32, cpu_T[0], R_EAX);
e108dd01 5032 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
480a762d 5033 gen_op_mov_reg_v(MO_64, R_EAX, cpu_T[0]);
ab4e4aec 5034 break;
14ce26e7 5035#endif
ab4e4aec 5036 case MO_32:
c56baccf 5037 gen_op_mov_v_reg(MO_16, cpu_T[0], R_EAX);
e108dd01 5038 tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
480a762d 5039 gen_op_mov_reg_v(MO_32, R_EAX, cpu_T[0]);
ab4e4aec
RH
5040 break;
5041 case MO_16:
c56baccf 5042 gen_op_mov_v_reg(MO_8, cpu_T[0], R_EAX);
e108dd01 5043 tcg_gen_ext8s_tl(cpu_T[0], cpu_T[0]);
480a762d 5044 gen_op_mov_reg_v(MO_16, R_EAX, cpu_T[0]);
ab4e4aec
RH
5045 break;
5046 default:
5047 tcg_abort();
e108dd01 5048 }
2c0262af
FB
5049 break;
5050 case 0x99: /* CDQ/CWD */
ab4e4aec 5051 switch (dflag) {
14ce26e7 5052#ifdef TARGET_X86_64
ab4e4aec 5053 case MO_64:
c56baccf 5054 gen_op_mov_v_reg(MO_64, cpu_T[0], R_EAX);
e108dd01 5055 tcg_gen_sari_tl(cpu_T[0], cpu_T[0], 63);
480a762d 5056 gen_op_mov_reg_v(MO_64, R_EDX, cpu_T[0]);
ab4e4aec 5057 break;
14ce26e7 5058#endif
ab4e4aec 5059 case MO_32:
c56baccf 5060 gen_op_mov_v_reg(MO_32, cpu_T[0], R_EAX);
e108dd01
FB
5061 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
5062 tcg_gen_sari_tl(cpu_T[0], cpu_T[0], 31);
480a762d 5063 gen_op_mov_reg_v(MO_32, R_EDX, cpu_T[0]);
ab4e4aec
RH
5064 break;
5065 case MO_16:
c56baccf 5066 gen_op_mov_v_reg(MO_16, cpu_T[0], R_EAX);
e108dd01
FB
5067 tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
5068 tcg_gen_sari_tl(cpu_T[0], cpu_T[0], 15);
480a762d 5069 gen_op_mov_reg_v(MO_16, R_EDX, cpu_T[0]);
ab4e4aec
RH
5070 break;
5071 default:
5072 tcg_abort();
e108dd01 5073 }
2c0262af
FB
5074 break;
5075 case 0x1af: /* imul Gv, Ev */
5076 case 0x69: /* imul Gv, Ev, I */
5077 case 0x6b:
ab4e4aec 5078 ot = dflag;
0af10c86 5079 modrm = cpu_ldub_code(env, s->pc++);
14ce26e7
FB
5080 reg = ((modrm >> 3) & 7) | rex_r;
5081 if (b == 0x69)
5082 s->rip_offset = insn_const_size(ot);
5083 else if (b == 0x6b)
5084 s->rip_offset = 1;
0af10c86 5085 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
2c0262af 5086 if (b == 0x69) {
0af10c86 5087 val = insn_get(env, s, ot);
0ae657b1 5088 tcg_gen_movi_tl(cpu_T[1], val);
2c0262af 5089 } else if (b == 0x6b) {
4ba9938c 5090 val = (int8_t)insn_get(env, s, MO_8);
0ae657b1 5091 tcg_gen_movi_tl(cpu_T[1], val);
2c0262af 5092 } else {
c56baccf 5093 gen_op_mov_v_reg(ot, cpu_T[1], reg);
2c0262af 5094 }
a4bcea3d 5095 switch (ot) {
0211e5af 5096#ifdef TARGET_X86_64
4ba9938c 5097 case MO_64:
a4bcea3d
RH
5098 tcg_gen_muls2_i64(cpu_regs[reg], cpu_T[1], cpu_T[0], cpu_T[1]);
5099 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[reg]);
5100 tcg_gen_sari_tl(cpu_cc_src, cpu_cc_dst, 63);
5101 tcg_gen_sub_tl(cpu_cc_src, cpu_cc_src, cpu_T[1]);
5102 break;
0211e5af 5103#endif
4ba9938c 5104 case MO_32:
a4bcea3d
RH
5105 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
5106 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T[1]);
5107 tcg_gen_muls2_i32(cpu_tmp2_i32, cpu_tmp3_i32,
5108 cpu_tmp2_i32, cpu_tmp3_i32);
5109 tcg_gen_extu_i32_tl(cpu_regs[reg], cpu_tmp2_i32);
5110 tcg_gen_sari_i32(cpu_tmp2_i32, cpu_tmp2_i32, 31);
5111 tcg_gen_mov_tl(cpu_cc_dst, cpu_regs[reg]);
5112 tcg_gen_sub_i32(cpu_tmp2_i32, cpu_tmp2_i32, cpu_tmp3_i32);
5113 tcg_gen_extu_i32_tl(cpu_cc_src, cpu_tmp2_i32);
5114 break;
5115 default:
0211e5af
FB
5116 tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
5117 tcg_gen_ext16s_tl(cpu_T[1], cpu_T[1]);
5118 /* XXX: use 32 bit mul which could be faster */
5119 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
5120 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
5121 tcg_gen_ext16s_tl(cpu_tmp0, cpu_T[0]);
5122 tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0);
480a762d 5123 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
a4bcea3d 5124 break;
2c0262af 5125 }
3ca51d07 5126 set_cc_op(s, CC_OP_MULB + ot);
2c0262af
FB
5127 break;
5128 case 0x1c0:
5129 case 0x1c1: /* xadd Ev, Gv */
ab4e4aec 5130 ot = mo_b_d(b, dflag);
0af10c86 5131 modrm = cpu_ldub_code(env, s->pc++);
14ce26e7 5132 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af
FB
5133 mod = (modrm >> 6) & 3;
5134 if (mod == 3) {
14ce26e7 5135 rm = (modrm & 7) | REX_B(s);
c56baccf
RH
5136 gen_op_mov_v_reg(ot, cpu_T[0], reg);
5137 gen_op_mov_v_reg(ot, cpu_T[1], rm);
fd5185ec 5138 tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
68773f84 5139 gen_op_mov_reg_v(ot, reg, cpu_T[1]);
480a762d 5140 gen_op_mov_reg_v(ot, rm, cpu_T[0]);
2c0262af 5141 } else {
4eeb3939 5142 gen_lea_modrm(env, s, modrm);
c56baccf 5143 gen_op_mov_v_reg(ot, cpu_T[0], reg);
0f712e10 5144 gen_op_ld_v(s, ot, cpu_T[1], cpu_A0);
fd5185ec 5145 tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
fd8ca9f6 5146 gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
68773f84 5147 gen_op_mov_reg_v(ot, reg, cpu_T[1]);
2c0262af
FB
5148 }
5149 gen_op_update2_cc();
3ca51d07 5150 set_cc_op(s, CC_OP_ADDB + ot);
2c0262af
FB
5151 break;
5152 case 0x1b0:
5153 case 0x1b1: /* cmpxchg Ev, Gv */
cad3a37d 5154 {
1130328e 5155 int label1, label2;
1e4840bf 5156 TCGv t0, t1, t2, a0;
cad3a37d 5157
ab4e4aec 5158 ot = mo_b_d(b, dflag);
0af10c86 5159 modrm = cpu_ldub_code(env, s->pc++);
cad3a37d
FB
5160 reg = ((modrm >> 3) & 7) | rex_r;
5161 mod = (modrm >> 6) & 3;
a7812ae4
PB
5162 t0 = tcg_temp_local_new();
5163 t1 = tcg_temp_local_new();
5164 t2 = tcg_temp_local_new();
5165 a0 = tcg_temp_local_new();
1e4840bf 5166 gen_op_mov_v_reg(ot, t1, reg);
cad3a37d
FB
5167 if (mod == 3) {
5168 rm = (modrm & 7) | REX_B(s);
1e4840bf 5169 gen_op_mov_v_reg(ot, t0, rm);
cad3a37d 5170 } else {
4eeb3939 5171 gen_lea_modrm(env, s, modrm);
1e4840bf 5172 tcg_gen_mov_tl(a0, cpu_A0);
323d1876 5173 gen_op_ld_v(s, ot, t0, a0);
cad3a37d
FB
5174 rm = 0; /* avoid warning */
5175 }
5176 label1 = gen_new_label();
a3251186
RH
5177 tcg_gen_mov_tl(t2, cpu_regs[R_EAX]);
5178 gen_extu(ot, t0);
1e4840bf 5179 gen_extu(ot, t2);
a3251186 5180 tcg_gen_brcond_tl(TCG_COND_EQ, t2, t0, label1);
f7e80adf 5181 label2 = gen_new_label();
cad3a37d 5182 if (mod == 3) {
1e4840bf 5183 gen_op_mov_reg_v(ot, R_EAX, t0);
1130328e
FB
5184 tcg_gen_br(label2);
5185 gen_set_label(label1);
1e4840bf 5186 gen_op_mov_reg_v(ot, rm, t1);
cad3a37d 5187 } else {
f7e80adf
AG
5188 /* perform no-op store cycle like physical cpu; must be
5189 before changing accumulator to ensure idempotency if
5190 the store faults and the instruction is restarted */
323d1876 5191 gen_op_st_v(s, ot, t0, a0);
1e4840bf 5192 gen_op_mov_reg_v(ot, R_EAX, t0);
f7e80adf 5193 tcg_gen_br(label2);
1130328e 5194 gen_set_label(label1);
323d1876 5195 gen_op_st_v(s, ot, t1, a0);
cad3a37d 5196 }
f7e80adf 5197 gen_set_label(label2);
1e4840bf 5198 tcg_gen_mov_tl(cpu_cc_src, t0);
a3251186
RH
5199 tcg_gen_mov_tl(cpu_cc_srcT, t2);
5200 tcg_gen_sub_tl(cpu_cc_dst, t2, t0);
3ca51d07 5201 set_cc_op(s, CC_OP_SUBB + ot);
1e4840bf
FB
5202 tcg_temp_free(t0);
5203 tcg_temp_free(t1);
5204 tcg_temp_free(t2);
5205 tcg_temp_free(a0);
2c0262af 5206 }
2c0262af
FB
5207 break;
5208 case 0x1c7: /* cmpxchg8b */
0af10c86 5209 modrm = cpu_ldub_code(env, s->pc++);
2c0262af 5210 mod = (modrm >> 6) & 3;
71c3558e 5211 if ((mod == 3) || ((modrm & 0x38) != 0x8))
2c0262af 5212 goto illegal_op;
1b9d9ebb 5213#ifdef TARGET_X86_64
ab4e4aec 5214 if (dflag == MO_64) {
1b9d9ebb
FB
5215 if (!(s->cpuid_ext_features & CPUID_EXT_CX16))
5216 goto illegal_op;
5217 gen_jmp_im(pc_start - s->cs_base);
773cdfcc 5218 gen_update_cc_op(s);
4eeb3939 5219 gen_lea_modrm(env, s, modrm);
92fc4b58 5220 gen_helper_cmpxchg16b(cpu_env, cpu_A0);
1b9d9ebb
FB
5221 } else
5222#endif
5223 {
5224 if (!(s->cpuid_features & CPUID_CX8))
5225 goto illegal_op;
5226 gen_jmp_im(pc_start - s->cs_base);
773cdfcc 5227 gen_update_cc_op(s);
4eeb3939 5228 gen_lea_modrm(env, s, modrm);
92fc4b58 5229 gen_helper_cmpxchg8b(cpu_env, cpu_A0);
1b9d9ebb 5230 }
3ca51d07 5231 set_cc_op(s, CC_OP_EFLAGS);
2c0262af 5232 break;
3b46e624 5233
2c0262af
FB
5234 /**************************/
5235 /* push/pop */
5236 case 0x50 ... 0x57: /* push */
c56baccf 5237 gen_op_mov_v_reg(MO_32, cpu_T[0], (b & 7) | REX_B(s));
432baffe 5238 gen_push_v(s, cpu_T[0]);
2c0262af
FB
5239 break;
5240 case 0x58 ... 0x5f: /* pop */
8e31d234 5241 ot = gen_pop_T0(s);
77729c24 5242 /* NOTE: order is important for pop %sp */
8e31d234 5243 gen_pop_update(s, ot);
480a762d 5244 gen_op_mov_reg_v(ot, (b & 7) | REX_B(s), cpu_T[0]);
2c0262af
FB
5245 break;
5246 case 0x60: /* pusha */
14ce26e7
FB
5247 if (CODE64(s))
5248 goto illegal_op;
2c0262af
FB
5249 gen_pusha(s);
5250 break;
5251 case 0x61: /* popa */
14ce26e7
FB
5252 if (CODE64(s))
5253 goto illegal_op;
2c0262af
FB
5254 gen_popa(s);
5255 break;
5256 case 0x68: /* push Iv */
5257 case 0x6a:
ab4e4aec 5258 ot = mo_pushpop(s, dflag);
2c0262af 5259 if (b == 0x68)
0af10c86 5260 val = insn_get(env, s, ot);
2c0262af 5261 else
4ba9938c 5262 val = (int8_t)insn_get(env, s, MO_8);
1b90d56e 5263 tcg_gen_movi_tl(cpu_T[0], val);
432baffe 5264 gen_push_v(s, cpu_T[0]);
2c0262af
FB
5265 break;
5266 case 0x8f: /* pop Ev */
0af10c86 5267 modrm = cpu_ldub_code(env, s->pc++);
77729c24 5268 mod = (modrm >> 6) & 3;
8e31d234 5269 ot = gen_pop_T0(s);
77729c24
FB
5270 if (mod == 3) {
5271 /* NOTE: order is important for pop %sp */
8e31d234 5272 gen_pop_update(s, ot);
14ce26e7 5273 rm = (modrm & 7) | REX_B(s);
480a762d 5274 gen_op_mov_reg_v(ot, rm, cpu_T[0]);
77729c24
FB
5275 } else {
5276 /* NOTE: order is important too for MMU exceptions */
14ce26e7 5277 s->popl_esp_hack = 1 << ot;
0af10c86 5278 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
77729c24 5279 s->popl_esp_hack = 0;
8e31d234 5280 gen_pop_update(s, ot);
77729c24 5281 }
2c0262af
FB
5282 break;
5283 case 0xc8: /* enter */
5284 {
5285 int level;
0af10c86 5286 val = cpu_lduw_code(env, s->pc);
2c0262af 5287 s->pc += 2;
0af10c86 5288 level = cpu_ldub_code(env, s->pc++);
2c0262af
FB
5289 gen_enter(s, val, level);
5290 }
5291 break;
5292 case 0xc9: /* leave */
5293 /* XXX: exception not precise (ESP is updated before potential exception) */
14ce26e7 5294 if (CODE64(s)) {
c56baccf 5295 gen_op_mov_v_reg(MO_64, cpu_T[0], R_EBP);
480a762d 5296 gen_op_mov_reg_v(MO_64, R_ESP, cpu_T[0]);
14ce26e7 5297 } else if (s->ss32) {
c56baccf 5298 gen_op_mov_v_reg(MO_32, cpu_T[0], R_EBP);
480a762d 5299 gen_op_mov_reg_v(MO_32, R_ESP, cpu_T[0]);
2c0262af 5300 } else {
c56baccf 5301 gen_op_mov_v_reg(MO_16, cpu_T[0], R_EBP);
480a762d 5302 gen_op_mov_reg_v(MO_16, R_ESP, cpu_T[0]);
2c0262af 5303 }
8e31d234 5304 ot = gen_pop_T0(s);
480a762d 5305 gen_op_mov_reg_v(ot, R_EBP, cpu_T[0]);
8e31d234 5306 gen_pop_update(s, ot);
2c0262af
FB
5307 break;
5308 case 0x06: /* push es */
5309 case 0x0e: /* push cs */
5310 case 0x16: /* push ss */
5311 case 0x1e: /* push ds */
14ce26e7
FB
5312 if (CODE64(s))
5313 goto illegal_op;
2c0262af 5314 gen_op_movl_T0_seg(b >> 3);
432baffe 5315 gen_push_v(s, cpu_T[0]);
2c0262af
FB
5316 break;
5317 case 0x1a0: /* push fs */
5318 case 0x1a8: /* push gs */
5319 gen_op_movl_T0_seg((b >> 3) & 7);
432baffe 5320 gen_push_v(s, cpu_T[0]);
2c0262af
FB
5321 break;
5322 case 0x07: /* pop es */
5323 case 0x17: /* pop ss */
5324 case 0x1f: /* pop ds */
14ce26e7
FB
5325 if (CODE64(s))
5326 goto illegal_op;
2c0262af 5327 reg = b >> 3;
8e31d234 5328 ot = gen_pop_T0(s);
2c0262af 5329 gen_movl_seg_T0(s, reg, pc_start - s->cs_base);
8e31d234 5330 gen_pop_update(s, ot);
2c0262af 5331 if (reg == R_SS) {
a2cc3b24
FB
5332 /* if reg == SS, inhibit interrupts/trace. */
5333 /* If several instructions disable interrupts, only the
5334 _first_ does it */
5335 if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
f0967a1a 5336 gen_helper_set_inhibit_irq(cpu_env);
2c0262af
FB
5337 s->tf = 0;
5338 }
5339 if (s->is_jmp) {
14ce26e7 5340 gen_jmp_im(s->pc - s->cs_base);
2c0262af
FB
5341 gen_eob(s);
5342 }
5343 break;
5344 case 0x1a1: /* pop fs */
5345 case 0x1a9: /* pop gs */
8e31d234 5346 ot = gen_pop_T0(s);
2c0262af 5347 gen_movl_seg_T0(s, (b >> 3) & 7, pc_start - s->cs_base);
8e31d234 5348 gen_pop_update(s, ot);
2c0262af 5349 if (s->is_jmp) {
14ce26e7 5350 gen_jmp_im(s->pc - s->cs_base);
2c0262af
FB
5351 gen_eob(s);
5352 }
5353 break;
5354
5355 /**************************/
5356 /* mov */
5357 case 0x88:
5358 case 0x89: /* mov Gv, Ev */
ab4e4aec 5359 ot = mo_b_d(b, dflag);
0af10c86 5360 modrm = cpu_ldub_code(env, s->pc++);
14ce26e7 5361 reg = ((modrm >> 3) & 7) | rex_r;
3b46e624 5362
2c0262af 5363 /* generate a generic store */
0af10c86 5364 gen_ldst_modrm(env, s, modrm, ot, reg, 1);
2c0262af
FB
5365 break;
5366 case 0xc6:
5367 case 0xc7: /* mov Ev, Iv */
ab4e4aec 5368 ot = mo_b_d(b, dflag);
0af10c86 5369 modrm = cpu_ldub_code(env, s->pc++);
2c0262af 5370 mod = (modrm >> 6) & 3;
14ce26e7
FB
5371 if (mod != 3) {
5372 s->rip_offset = insn_const_size(ot);
4eeb3939 5373 gen_lea_modrm(env, s, modrm);
14ce26e7 5374 }
0af10c86 5375 val = insn_get(env, s, ot);
1b90d56e 5376 tcg_gen_movi_tl(cpu_T[0], val);
fd8ca9f6
RH
5377 if (mod != 3) {
5378 gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
5379 } else {
480a762d 5380 gen_op_mov_reg_v(ot, (modrm & 7) | REX_B(s), cpu_T[0]);
fd8ca9f6 5381 }
2c0262af
FB
5382 break;
5383 case 0x8a:
5384 case 0x8b: /* mov Ev, Gv */
ab4e4aec 5385 ot = mo_b_d(b, dflag);
0af10c86 5386 modrm = cpu_ldub_code(env, s->pc++);
14ce26e7 5387 reg = ((modrm >> 3) & 7) | rex_r;
3b46e624 5388
0af10c86 5389 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
480a762d 5390 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
2c0262af
FB
5391 break;
5392 case 0x8e: /* mov seg, Gv */
0af10c86 5393 modrm = cpu_ldub_code(env, s->pc++);
2c0262af
FB
5394 reg = (modrm >> 3) & 7;
5395 if (reg >= 6 || reg == R_CS)
5396 goto illegal_op;
4ba9938c 5397 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
2c0262af
FB
5398 gen_movl_seg_T0(s, reg, pc_start - s->cs_base);
5399 if (reg == R_SS) {
5400 /* if reg == SS, inhibit interrupts/trace */
a2cc3b24
FB
5401 /* If several instructions disable interrupts, only the
5402 _first_ does it */
5403 if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
f0967a1a 5404 gen_helper_set_inhibit_irq(cpu_env);
2c0262af
FB
5405 s->tf = 0;
5406 }
5407 if (s->is_jmp) {
14ce26e7 5408 gen_jmp_im(s->pc - s->cs_base);
2c0262af
FB
5409 gen_eob(s);
5410 }
5411 break;
5412 case 0x8c: /* mov Gv, seg */
0af10c86 5413 modrm = cpu_ldub_code(env, s->pc++);
2c0262af
FB
5414 reg = (modrm >> 3) & 7;
5415 mod = (modrm >> 6) & 3;
5416 if (reg >= 6)
5417 goto illegal_op;
5418 gen_op_movl_T0_seg(reg);
ab4e4aec 5419 ot = mod == 3 ? dflag : MO_16;
0af10c86 5420 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
2c0262af
FB
5421 break;
5422
5423 case 0x1b6: /* movzbS Gv, Eb */
5424 case 0x1b7: /* movzwS Gv, Eb */
5425 case 0x1be: /* movsbS Gv, Eb */
5426 case 0x1bf: /* movswS Gv, Eb */
5427 {
c8fbc479
RH
5428 TCGMemOp d_ot;
5429 TCGMemOp s_ot;
5430
2c0262af 5431 /* d_ot is the size of destination */
ab4e4aec 5432 d_ot = dflag;
2c0262af 5433 /* ot is the size of source */
4ba9938c 5434 ot = (b & 1) + MO_8;
c8fbc479
RH
5435 /* s_ot is the sign+size of source */
5436 s_ot = b & 8 ? MO_SIGN | ot : ot;
5437
0af10c86 5438 modrm = cpu_ldub_code(env, s->pc++);
14ce26e7 5439 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af 5440 mod = (modrm >> 6) & 3;
14ce26e7 5441 rm = (modrm & 7) | REX_B(s);
3b46e624 5442
2c0262af 5443 if (mod == 3) {
c56baccf 5444 gen_op_mov_v_reg(ot, cpu_T[0], rm);
c8fbc479
RH
5445 switch (s_ot) {
5446 case MO_UB:
e108dd01 5447 tcg_gen_ext8u_tl(cpu_T[0], cpu_T[0]);
2c0262af 5448 break;
c8fbc479 5449 case MO_SB:
e108dd01 5450 tcg_gen_ext8s_tl(cpu_T[0], cpu_T[0]);
2c0262af 5451 break;
c8fbc479 5452 case MO_UW:
e108dd01 5453 tcg_gen_ext16u_tl(cpu_T[0], cpu_T[0]);
2c0262af
FB
5454 break;
5455 default:
c8fbc479 5456 case MO_SW:
e108dd01 5457 tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
2c0262af
FB
5458 break;
5459 }
480a762d 5460 gen_op_mov_reg_v(d_ot, reg, cpu_T[0]);
2c0262af 5461 } else {
4eeb3939 5462 gen_lea_modrm(env, s, modrm);
c8fbc479 5463 gen_op_ld_v(s, s_ot, cpu_T[0], cpu_A0);
480a762d 5464 gen_op_mov_reg_v(d_ot, reg, cpu_T[0]);
2c0262af
FB
5465 }
5466 }
5467 break;
5468
5469 case 0x8d: /* lea */
ab4e4aec 5470 ot = dflag;
0af10c86 5471 modrm = cpu_ldub_code(env, s->pc++);
3a1d9b8b
FB
5472 mod = (modrm >> 6) & 3;
5473 if (mod == 3)
5474 goto illegal_op;
14ce26e7 5475 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af
FB
5476 /* we must ensure that no segment is added */
5477 s->override = -1;
5478 val = s->addseg;
5479 s->addseg = 0;
4eeb3939 5480 gen_lea_modrm(env, s, modrm);
2c0262af 5481 s->addseg = val;
33b7891b 5482 gen_op_mov_reg_v(ot, reg, cpu_A0);
2c0262af 5483 break;
3b46e624 5484
2c0262af
FB
5485 case 0xa0: /* mov EAX, Ov */
5486 case 0xa1:
5487 case 0xa2: /* mov Ov, EAX */
5488 case 0xa3:
2c0262af 5489 {
14ce26e7
FB
5490 target_ulong offset_addr;
5491
ab4e4aec 5492 ot = mo_b_d(b, dflag);
1d71ddb1 5493 switch (s->aflag) {
14ce26e7 5494#ifdef TARGET_X86_64
1d71ddb1 5495 case MO_64:
0af10c86 5496 offset_addr = cpu_ldq_code(env, s->pc);
14ce26e7 5497 s->pc += 8;
1d71ddb1 5498 break;
14ce26e7 5499#endif
1d71ddb1
RH
5500 default:
5501 offset_addr = insn_get(env, s, s->aflag);
5502 break;
14ce26e7 5503 }
3250cff8 5504 tcg_gen_movi_tl(cpu_A0, offset_addr);
664e0f19 5505 gen_add_A0_ds_seg(s);
14ce26e7 5506 if ((b & 2) == 0) {
909be183 5507 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
480a762d 5508 gen_op_mov_reg_v(ot, R_EAX, cpu_T[0]);
14ce26e7 5509 } else {
c56baccf 5510 gen_op_mov_v_reg(ot, cpu_T[0], R_EAX);
fd8ca9f6 5511 gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
2c0262af
FB
5512 }
5513 }
2c0262af
FB
5514 break;
5515 case 0xd7: /* xlat */
1d71ddb1
RH
5516 tcg_gen_mov_tl(cpu_A0, cpu_regs[R_EBX]);
5517 tcg_gen_ext8u_tl(cpu_T[0], cpu_regs[R_EAX]);
5518 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_T[0]);
5519 gen_extu(s->aflag, cpu_A0);
664e0f19 5520 gen_add_A0_ds_seg(s);
cc1a80df 5521 gen_op_ld_v(s, MO_8, cpu_T[0], cpu_A0);
480a762d 5522 gen_op_mov_reg_v(MO_8, R_EAX, cpu_T[0]);
2c0262af
FB
5523 break;
5524 case 0xb0 ... 0xb7: /* mov R, Ib */
4ba9938c 5525 val = insn_get(env, s, MO_8);
1b90d56e 5526 tcg_gen_movi_tl(cpu_T[0], val);
480a762d 5527 gen_op_mov_reg_v(MO_8, (b & 7) | REX_B(s), cpu_T[0]);
2c0262af
FB
5528 break;
5529 case 0xb8 ... 0xbf: /* mov R, Iv */
14ce26e7 5530#ifdef TARGET_X86_64
ab4e4aec 5531 if (dflag == MO_64) {
14ce26e7
FB
5532 uint64_t tmp;
5533 /* 64 bit case */
0af10c86 5534 tmp = cpu_ldq_code(env, s->pc);
14ce26e7
FB
5535 s->pc += 8;
5536 reg = (b & 7) | REX_B(s);
cc0bce88 5537 tcg_gen_movi_tl(cpu_T[0], tmp);
480a762d 5538 gen_op_mov_reg_v(MO_64, reg, cpu_T[0]);
5fafdf24 5539 } else
14ce26e7
FB
5540#endif
5541 {
ab4e4aec 5542 ot = dflag;
0af10c86 5543 val = insn_get(env, s, ot);
14ce26e7 5544 reg = (b & 7) | REX_B(s);
1b90d56e 5545 tcg_gen_movi_tl(cpu_T[0], val);
480a762d 5546 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
14ce26e7 5547 }
2c0262af
FB
5548 break;
5549
5550 case 0x91 ... 0x97: /* xchg R, EAX */
7418027e 5551 do_xchg_reg_eax:
ab4e4aec 5552 ot = dflag;
14ce26e7 5553 reg = (b & 7) | REX_B(s);
2c0262af
FB
5554 rm = R_EAX;
5555 goto do_xchg_reg;
5556 case 0x86:
5557 case 0x87: /* xchg Ev, Gv */
ab4e4aec 5558 ot = mo_b_d(b, dflag);
0af10c86 5559 modrm = cpu_ldub_code(env, s->pc++);
14ce26e7 5560 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af
FB
5561 mod = (modrm >> 6) & 3;
5562 if (mod == 3) {
14ce26e7 5563 rm = (modrm & 7) | REX_B(s);
2c0262af 5564 do_xchg_reg:
c56baccf
RH
5565 gen_op_mov_v_reg(ot, cpu_T[0], reg);
5566 gen_op_mov_v_reg(ot, cpu_T[1], rm);
480a762d 5567 gen_op_mov_reg_v(ot, rm, cpu_T[0]);
68773f84 5568 gen_op_mov_reg_v(ot, reg, cpu_T[1]);
2c0262af 5569 } else {
4eeb3939 5570 gen_lea_modrm(env, s, modrm);
c56baccf 5571 gen_op_mov_v_reg(ot, cpu_T[0], reg);
2c0262af
FB
5572 /* for xchg, lock is implicit */
5573 if (!(prefixes & PREFIX_LOCK))
a7812ae4 5574 gen_helper_lock();
0f712e10 5575 gen_op_ld_v(s, ot, cpu_T[1], cpu_A0);
fd8ca9f6 5576 gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
2c0262af 5577 if (!(prefixes & PREFIX_LOCK))
a7812ae4 5578 gen_helper_unlock();
68773f84 5579 gen_op_mov_reg_v(ot, reg, cpu_T[1]);
2c0262af
FB
5580 }
5581 break;
5582 case 0xc4: /* les Gv */
701ed211 5583 /* In CODE64 this is VEX3; see above. */
2c0262af
FB
5584 op = R_ES;
5585 goto do_lxx;
5586 case 0xc5: /* lds Gv */
701ed211 5587 /* In CODE64 this is VEX2; see above. */
2c0262af
FB
5588 op = R_DS;
5589 goto do_lxx;
5590 case 0x1b2: /* lss Gv */
5591 op = R_SS;
5592 goto do_lxx;
5593 case 0x1b4: /* lfs Gv */
5594 op = R_FS;
5595 goto do_lxx;
5596 case 0x1b5: /* lgs Gv */
5597 op = R_GS;
5598 do_lxx:
ab4e4aec 5599 ot = dflag != MO_16 ? MO_32 : MO_16;
0af10c86 5600 modrm = cpu_ldub_code(env, s->pc++);
14ce26e7 5601 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af
FB
5602 mod = (modrm >> 6) & 3;
5603 if (mod == 3)
5604 goto illegal_op;
4eeb3939 5605 gen_lea_modrm(env, s, modrm);
0f712e10 5606 gen_op_ld_v(s, ot, cpu_T[1], cpu_A0);
830a19a4 5607 gen_add_A0_im(s, 1 << ot);
2c0262af 5608 /* load the segment first to handle exceptions properly */
cc1a80df 5609 gen_op_ld_v(s, MO_16, cpu_T[0], cpu_A0);
2c0262af
FB
5610 gen_movl_seg_T0(s, op, pc_start - s->cs_base);
5611 /* then put the data */
68773f84 5612 gen_op_mov_reg_v(ot, reg, cpu_T[1]);
2c0262af 5613 if (s->is_jmp) {
14ce26e7 5614 gen_jmp_im(s->pc - s->cs_base);
2c0262af
FB
5615 gen_eob(s);
5616 }
5617 break;
3b46e624 5618
2c0262af
FB
5619 /************************/
5620 /* shifts */
5621 case 0xc0:
5622 case 0xc1:
5623 /* shift Ev,Ib */
5624 shift = 2;
5625 grp2:
5626 {
ab4e4aec 5627 ot = mo_b_d(b, dflag);
0af10c86 5628 modrm = cpu_ldub_code(env, s->pc++);
2c0262af 5629 mod = (modrm >> 6) & 3;
2c0262af 5630 op = (modrm >> 3) & 7;
3b46e624 5631
2c0262af 5632 if (mod != 3) {
14ce26e7
FB
5633 if (shift == 2) {
5634 s->rip_offset = 1;
5635 }
4eeb3939 5636 gen_lea_modrm(env, s, modrm);
2c0262af
FB
5637 opreg = OR_TMP0;
5638 } else {
14ce26e7 5639 opreg = (modrm & 7) | REX_B(s);
2c0262af
FB
5640 }
5641
5642 /* simpler op */
5643 if (shift == 0) {
5644 gen_shift(s, op, ot, opreg, OR_ECX);
5645 } else {
5646 if (shift == 2) {
0af10c86 5647 shift = cpu_ldub_code(env, s->pc++);
2c0262af
FB
5648 }
5649 gen_shifti(s, op, ot, opreg, shift);
5650 }
5651 }
5652 break;
5653 case 0xd0:
5654 case 0xd1:
5655 /* shift Ev,1 */
5656 shift = 1;
5657 goto grp2;
5658 case 0xd2:
5659 case 0xd3:
5660 /* shift Ev,cl */
5661 shift = 0;
5662 goto grp2;
5663
5664 case 0x1a4: /* shld imm */
5665 op = 0;
5666 shift = 1;
5667 goto do_shiftd;
5668 case 0x1a5: /* shld cl */
5669 op = 0;
5670 shift = 0;
5671 goto do_shiftd;
5672 case 0x1ac: /* shrd imm */
5673 op = 1;
5674 shift = 1;
5675 goto do_shiftd;
5676 case 0x1ad: /* shrd cl */
5677 op = 1;
5678 shift = 0;
5679 do_shiftd:
ab4e4aec 5680 ot = dflag;
0af10c86 5681 modrm = cpu_ldub_code(env, s->pc++);
2c0262af 5682 mod = (modrm >> 6) & 3;
14ce26e7
FB
5683 rm = (modrm & 7) | REX_B(s);
5684 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af 5685 if (mod != 3) {
4eeb3939 5686 gen_lea_modrm(env, s, modrm);
b6abf97d 5687 opreg = OR_TMP0;
2c0262af 5688 } else {
b6abf97d 5689 opreg = rm;
2c0262af 5690 }
c56baccf 5691 gen_op_mov_v_reg(ot, cpu_T[1], reg);
3b46e624 5692
2c0262af 5693 if (shift) {
3b9d3cf1
PB
5694 TCGv imm = tcg_const_tl(cpu_ldub_code(env, s->pc++));
5695 gen_shiftd_rm_T1(s, ot, opreg, op, imm);
5696 tcg_temp_free(imm);
2c0262af 5697 } else {
3b9d3cf1 5698 gen_shiftd_rm_T1(s, ot, opreg, op, cpu_regs[R_ECX]);
2c0262af
FB
5699 }
5700 break;
5701
5702 /************************/
5703 /* floats */
5fafdf24 5704 case 0xd8 ... 0xdf:
7eee2a50
FB
5705 if (s->flags & (HF_EM_MASK | HF_TS_MASK)) {
5706 /* if CR0.EM or CR0.TS are set, generate an FPU exception */
5707 /* XXX: what to do if illegal op ? */
5708 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
5709 break;
5710 }
0af10c86 5711 modrm = cpu_ldub_code(env, s->pc++);
2c0262af
FB
5712 mod = (modrm >> 6) & 3;
5713 rm = modrm & 7;
5714 op = ((b & 7) << 3) | ((modrm >> 3) & 7);
2c0262af
FB
5715 if (mod != 3) {
5716 /* memory op */
4eeb3939 5717 gen_lea_modrm(env, s, modrm);
2c0262af
FB
5718 switch(op) {
5719 case 0x00 ... 0x07: /* fxxxs */
5720 case 0x10 ... 0x17: /* fixxxl */
5721 case 0x20 ... 0x27: /* fxxxl */
5722 case 0x30 ... 0x37: /* fixxx */
5723 {
5724 int op1;
5725 op1 = op & 7;
5726
5727 switch(op >> 4) {
5728 case 0:
80b02013
RH
5729 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5730 s->mem_index, MO_LEUL);
d3eb5eae 5731 gen_helper_flds_FT0(cpu_env, cpu_tmp2_i32);
2c0262af
FB
5732 break;
5733 case 1:
80b02013
RH
5734 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5735 s->mem_index, MO_LEUL);
d3eb5eae 5736 gen_helper_fildl_FT0(cpu_env, cpu_tmp2_i32);
2c0262af
FB
5737 break;
5738 case 2:
3c5f4116
RH
5739 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_A0,
5740 s->mem_index, MO_LEQ);
d3eb5eae 5741 gen_helper_fldl_FT0(cpu_env, cpu_tmp1_i64);
2c0262af
FB
5742 break;
5743 case 3:
5744 default:
80b02013
RH
5745 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5746 s->mem_index, MO_LESW);
d3eb5eae 5747 gen_helper_fildl_FT0(cpu_env, cpu_tmp2_i32);
2c0262af
FB
5748 break;
5749 }
3b46e624 5750
a7812ae4 5751 gen_helper_fp_arith_ST0_FT0(op1);
2c0262af
FB
5752 if (op1 == 3) {
5753 /* fcomp needs pop */
d3eb5eae 5754 gen_helper_fpop(cpu_env);
2c0262af
FB
5755 }
5756 }
5757 break;
5758 case 0x08: /* flds */
5759 case 0x0a: /* fsts */
5760 case 0x0b: /* fstps */
465e9838
FB
5761 case 0x18 ... 0x1b: /* fildl, fisttpl, fistl, fistpl */
5762 case 0x28 ... 0x2b: /* fldl, fisttpll, fstl, fstpl */
5763 case 0x38 ... 0x3b: /* filds, fisttps, fists, fistps */
2c0262af
FB
5764 switch(op & 7) {
5765 case 0:
5766 switch(op >> 4) {
5767 case 0:
80b02013
RH
5768 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5769 s->mem_index, MO_LEUL);
d3eb5eae 5770 gen_helper_flds_ST0(cpu_env, cpu_tmp2_i32);
2c0262af
FB
5771 break;
5772 case 1:
80b02013
RH
5773 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5774 s->mem_index, MO_LEUL);
d3eb5eae 5775 gen_helper_fildl_ST0(cpu_env, cpu_tmp2_i32);
2c0262af
FB
5776 break;
5777 case 2:
3c5f4116
RH
5778 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_A0,
5779 s->mem_index, MO_LEQ);
d3eb5eae 5780 gen_helper_fldl_ST0(cpu_env, cpu_tmp1_i64);
2c0262af
FB
5781 break;
5782 case 3:
5783 default:
80b02013
RH
5784 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5785 s->mem_index, MO_LESW);
d3eb5eae 5786 gen_helper_fildl_ST0(cpu_env, cpu_tmp2_i32);
2c0262af
FB
5787 break;
5788 }
5789 break;
465e9838 5790 case 1:
19e6c4b8 5791 /* XXX: the corresponding CPUID bit must be tested ! */
465e9838
FB
5792 switch(op >> 4) {
5793 case 1:
d3eb5eae 5794 gen_helper_fisttl_ST0(cpu_tmp2_i32, cpu_env);
d5601ad0
RH
5795 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5796 s->mem_index, MO_LEUL);
465e9838
FB
5797 break;
5798 case 2:
d3eb5eae 5799 gen_helper_fisttll_ST0(cpu_tmp1_i64, cpu_env);
3523e4bd
RH
5800 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0,
5801 s->mem_index, MO_LEQ);
465e9838
FB
5802 break;
5803 case 3:
5804 default:
d3eb5eae 5805 gen_helper_fistt_ST0(cpu_tmp2_i32, cpu_env);
d5601ad0
RH
5806 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5807 s->mem_index, MO_LEUW);
19e6c4b8 5808 break;
465e9838 5809 }
d3eb5eae 5810 gen_helper_fpop(cpu_env);
465e9838 5811 break;
2c0262af
FB
5812 default:
5813 switch(op >> 4) {
5814 case 0:
d3eb5eae 5815 gen_helper_fsts_ST0(cpu_tmp2_i32, cpu_env);
d5601ad0
RH
5816 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5817 s->mem_index, MO_LEUL);
2c0262af
FB
5818 break;
5819 case 1:
d3eb5eae 5820 gen_helper_fistl_ST0(cpu_tmp2_i32, cpu_env);
d5601ad0
RH
5821 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5822 s->mem_index, MO_LEUL);
2c0262af
FB
5823 break;
5824 case 2:
d3eb5eae 5825 gen_helper_fstl_ST0(cpu_tmp1_i64, cpu_env);
3523e4bd
RH
5826 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0,
5827 s->mem_index, MO_LEQ);
2c0262af
FB
5828 break;
5829 case 3:
5830 default:
d3eb5eae 5831 gen_helper_fist_ST0(cpu_tmp2_i32, cpu_env);
d5601ad0
RH
5832 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5833 s->mem_index, MO_LEUW);
2c0262af
FB
5834 break;
5835 }
5836 if ((op & 7) == 3)
d3eb5eae 5837 gen_helper_fpop(cpu_env);
2c0262af
FB
5838 break;
5839 }
5840 break;
5841 case 0x0c: /* fldenv mem */
773cdfcc 5842 gen_update_cc_op(s);
19e6c4b8 5843 gen_jmp_im(pc_start - s->cs_base);
ab4e4aec 5844 gen_helper_fldenv(cpu_env, cpu_A0, tcg_const_i32(dflag - 1));
2c0262af
FB
5845 break;
5846 case 0x0d: /* fldcw mem */
80b02013
RH
5847 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
5848 s->mem_index, MO_LEUW);
d3eb5eae 5849 gen_helper_fldcw(cpu_env, cpu_tmp2_i32);
2c0262af
FB
5850 break;
5851 case 0x0e: /* fnstenv mem */
773cdfcc 5852 gen_update_cc_op(s);
19e6c4b8 5853 gen_jmp_im(pc_start - s->cs_base);
ab4e4aec 5854 gen_helper_fstenv(cpu_env, cpu_A0, tcg_const_i32(dflag - 1));
2c0262af
FB
5855 break;
5856 case 0x0f: /* fnstcw mem */
d3eb5eae 5857 gen_helper_fnstcw(cpu_tmp2_i32, cpu_env);
d5601ad0
RH
5858 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5859 s->mem_index, MO_LEUW);
2c0262af
FB
5860 break;
5861 case 0x1d: /* fldt mem */
773cdfcc 5862 gen_update_cc_op(s);
19e6c4b8 5863 gen_jmp_im(pc_start - s->cs_base);
d3eb5eae 5864 gen_helper_fldt_ST0(cpu_env, cpu_A0);
2c0262af
FB
5865 break;
5866 case 0x1f: /* fstpt mem */
773cdfcc 5867 gen_update_cc_op(s);
19e6c4b8 5868 gen_jmp_im(pc_start - s->cs_base);
d3eb5eae
BS
5869 gen_helper_fstt_ST0(cpu_env, cpu_A0);
5870 gen_helper_fpop(cpu_env);
2c0262af
FB
5871 break;
5872 case 0x2c: /* frstor mem */
773cdfcc 5873 gen_update_cc_op(s);
19e6c4b8 5874 gen_jmp_im(pc_start - s->cs_base);
ab4e4aec 5875 gen_helper_frstor(cpu_env, cpu_A0, tcg_const_i32(dflag - 1));
2c0262af
FB
5876 break;
5877 case 0x2e: /* fnsave mem */
773cdfcc 5878 gen_update_cc_op(s);
19e6c4b8 5879 gen_jmp_im(pc_start - s->cs_base);
ab4e4aec 5880 gen_helper_fsave(cpu_env, cpu_A0, tcg_const_i32(dflag - 1));
2c0262af
FB
5881 break;
5882 case 0x2f: /* fnstsw mem */
d3eb5eae 5883 gen_helper_fnstsw(cpu_tmp2_i32, cpu_env);
d5601ad0
RH
5884 tcg_gen_qemu_st_i32(cpu_tmp2_i32, cpu_A0,
5885 s->mem_index, MO_LEUW);
2c0262af
FB
5886 break;
5887 case 0x3c: /* fbld */
773cdfcc 5888 gen_update_cc_op(s);
19e6c4b8 5889 gen_jmp_im(pc_start - s->cs_base);
d3eb5eae 5890 gen_helper_fbld_ST0(cpu_env, cpu_A0);
2c0262af
FB
5891 break;
5892 case 0x3e: /* fbstp */
773cdfcc 5893 gen_update_cc_op(s);
19e6c4b8 5894 gen_jmp_im(pc_start - s->cs_base);
d3eb5eae
BS
5895 gen_helper_fbst_ST0(cpu_env, cpu_A0);
5896 gen_helper_fpop(cpu_env);
2c0262af
FB
5897 break;
5898 case 0x3d: /* fildll */
3c5f4116 5899 tcg_gen_qemu_ld_i64(cpu_tmp1_i64, cpu_A0, s->mem_index, MO_LEQ);
d3eb5eae 5900 gen_helper_fildll_ST0(cpu_env, cpu_tmp1_i64);
2c0262af
FB
5901 break;
5902 case 0x3f: /* fistpll */
d3eb5eae 5903 gen_helper_fistll_ST0(cpu_tmp1_i64, cpu_env);
3523e4bd 5904 tcg_gen_qemu_st_i64(cpu_tmp1_i64, cpu_A0, s->mem_index, MO_LEQ);
d3eb5eae 5905 gen_helper_fpop(cpu_env);
2c0262af
FB
5906 break;
5907 default:
5908 goto illegal_op;
5909 }
5910 } else {
5911 /* register float ops */
5912 opreg = rm;
5913
5914 switch(op) {
5915 case 0x08: /* fld sti */
d3eb5eae
BS
5916 gen_helper_fpush(cpu_env);
5917 gen_helper_fmov_ST0_STN(cpu_env,
5918 tcg_const_i32((opreg + 1) & 7));
2c0262af
FB
5919 break;
5920 case 0x09: /* fxchg sti */
c169c906
FB
5921 case 0x29: /* fxchg4 sti, undocumented op */
5922 case 0x39: /* fxchg7 sti, undocumented op */
d3eb5eae 5923 gen_helper_fxchg_ST0_STN(cpu_env, tcg_const_i32(opreg));
2c0262af
FB
5924 break;
5925 case 0x0a: /* grp d9/2 */
5926 switch(rm) {
5927 case 0: /* fnop */
023fe10d 5928 /* check exceptions (FreeBSD FPU probe) */
773cdfcc 5929 gen_update_cc_op(s);
14ce26e7 5930 gen_jmp_im(pc_start - s->cs_base);
d3eb5eae 5931 gen_helper_fwait(cpu_env);
2c0262af
FB
5932 break;
5933 default:
5934 goto illegal_op;
5935 }
5936 break;
5937 case 0x0c: /* grp d9/4 */
5938 switch(rm) {
5939 case 0: /* fchs */
d3eb5eae 5940 gen_helper_fchs_ST0(cpu_env);
2c0262af
FB
5941 break;
5942 case 1: /* fabs */
d3eb5eae 5943 gen_helper_fabs_ST0(cpu_env);
2c0262af
FB
5944 break;
5945 case 4: /* ftst */
d3eb5eae
BS
5946 gen_helper_fldz_FT0(cpu_env);
5947 gen_helper_fcom_ST0_FT0(cpu_env);
2c0262af
FB
5948 break;
5949 case 5: /* fxam */
d3eb5eae 5950 gen_helper_fxam_ST0(cpu_env);
2c0262af
FB
5951 break;
5952 default:
5953 goto illegal_op;
5954 }
5955 break;
5956 case 0x0d: /* grp d9/5 */
5957 {
5958 switch(rm) {
5959 case 0:
d3eb5eae
BS
5960 gen_helper_fpush(cpu_env);
5961 gen_helper_fld1_ST0(cpu_env);
2c0262af
FB
5962 break;
5963 case 1:
d3eb5eae
BS
5964 gen_helper_fpush(cpu_env);
5965 gen_helper_fldl2t_ST0(cpu_env);
2c0262af
FB
5966 break;
5967 case 2:
d3eb5eae
BS
5968 gen_helper_fpush(cpu_env);
5969 gen_helper_fldl2e_ST0(cpu_env);
2c0262af
FB
5970 break;
5971 case 3:
d3eb5eae
BS
5972 gen_helper_fpush(cpu_env);
5973 gen_helper_fldpi_ST0(cpu_env);
2c0262af
FB
5974 break;
5975 case 4:
d3eb5eae
BS
5976 gen_helper_fpush(cpu_env);
5977 gen_helper_fldlg2_ST0(cpu_env);
2c0262af
FB
5978 break;
5979 case 5:
d3eb5eae
BS
5980 gen_helper_fpush(cpu_env);
5981 gen_helper_fldln2_ST0(cpu_env);
2c0262af
FB
5982 break;
5983 case 6:
d3eb5eae
BS
5984 gen_helper_fpush(cpu_env);
5985 gen_helper_fldz_ST0(cpu_env);
2c0262af
FB
5986 break;
5987 default:
5988 goto illegal_op;
5989 }
5990 }
5991 break;
5992 case 0x0e: /* grp d9/6 */
5993 switch(rm) {
5994 case 0: /* f2xm1 */
d3eb5eae 5995 gen_helper_f2xm1(cpu_env);
2c0262af
FB
5996 break;
5997 case 1: /* fyl2x */
d3eb5eae 5998 gen_helper_fyl2x(cpu_env);
2c0262af
FB
5999 break;
6000 case 2: /* fptan */
d3eb5eae 6001 gen_helper_fptan(cpu_env);
2c0262af
FB
6002 break;
6003 case 3: /* fpatan */
d3eb5eae 6004 gen_helper_fpatan(cpu_env);
2c0262af
FB
6005 break;
6006 case 4: /* fxtract */
d3eb5eae 6007 gen_helper_fxtract(cpu_env);
2c0262af
FB
6008 break;
6009 case 5: /* fprem1 */
d3eb5eae 6010 gen_helper_fprem1(cpu_env);
2c0262af
FB
6011 break;
6012 case 6: /* fdecstp */
d3eb5eae 6013 gen_helper_fdecstp(cpu_env);
2c0262af
FB
6014 break;
6015 default:
6016 case 7: /* fincstp */
d3eb5eae 6017 gen_helper_fincstp(cpu_env);
2c0262af
FB
6018 break;
6019 }
6020 break;
6021 case 0x0f: /* grp d9/7 */
6022 switch(rm) {
6023 case 0: /* fprem */
d3eb5eae 6024 gen_helper_fprem(cpu_env);
2c0262af
FB
6025 break;
6026 case 1: /* fyl2xp1 */
d3eb5eae 6027 gen_helper_fyl2xp1(cpu_env);
2c0262af
FB
6028 break;
6029 case 2: /* fsqrt */
d3eb5eae 6030 gen_helper_fsqrt(cpu_env);
2c0262af
FB
6031 break;
6032 case 3: /* fsincos */
d3eb5eae 6033 gen_helper_fsincos(cpu_env);
2c0262af
FB
6034 break;
6035 case 5: /* fscale */
d3eb5eae 6036 gen_helper_fscale(cpu_env);
2c0262af
FB
6037 break;
6038 case 4: /* frndint */
d3eb5eae 6039 gen_helper_frndint(cpu_env);
2c0262af
FB
6040 break;
6041 case 6: /* fsin */
d3eb5eae 6042 gen_helper_fsin(cpu_env);
2c0262af
FB
6043 break;
6044 default:
6045 case 7: /* fcos */
d3eb5eae 6046 gen_helper_fcos(cpu_env);
2c0262af
FB
6047 break;
6048 }
6049 break;
6050 case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
6051 case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
6052 case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
6053 {
6054 int op1;
3b46e624 6055
2c0262af
FB
6056 op1 = op & 7;
6057 if (op >= 0x20) {
a7812ae4 6058 gen_helper_fp_arith_STN_ST0(op1, opreg);
2c0262af 6059 if (op >= 0x30)
d3eb5eae 6060 gen_helper_fpop(cpu_env);
2c0262af 6061 } else {
d3eb5eae 6062 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
a7812ae4 6063 gen_helper_fp_arith_ST0_FT0(op1);
2c0262af
FB
6064 }
6065 }
6066 break;
6067 case 0x02: /* fcom */
c169c906 6068 case 0x22: /* fcom2, undocumented op */
d3eb5eae
BS
6069 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6070 gen_helper_fcom_ST0_FT0(cpu_env);
2c0262af
FB
6071 break;
6072 case 0x03: /* fcomp */
c169c906
FB
6073 case 0x23: /* fcomp3, undocumented op */
6074 case 0x32: /* fcomp5, undocumented op */
d3eb5eae
BS
6075 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6076 gen_helper_fcom_ST0_FT0(cpu_env);
6077 gen_helper_fpop(cpu_env);
2c0262af
FB
6078 break;
6079 case 0x15: /* da/5 */
6080 switch(rm) {
6081 case 1: /* fucompp */
d3eb5eae
BS
6082 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(1));
6083 gen_helper_fucom_ST0_FT0(cpu_env);
6084 gen_helper_fpop(cpu_env);
6085 gen_helper_fpop(cpu_env);
2c0262af
FB
6086 break;
6087 default:
6088 goto illegal_op;
6089 }
6090 break;
6091 case 0x1c:
6092 switch(rm) {
6093 case 0: /* feni (287 only, just do nop here) */
6094 break;
6095 case 1: /* fdisi (287 only, just do nop here) */
6096 break;
6097 case 2: /* fclex */
d3eb5eae 6098 gen_helper_fclex(cpu_env);
2c0262af
FB
6099 break;
6100 case 3: /* fninit */
d3eb5eae 6101 gen_helper_fninit(cpu_env);
2c0262af
FB
6102 break;
6103 case 4: /* fsetpm (287 only, just do nop here) */
6104 break;
6105 default:
6106 goto illegal_op;
6107 }
6108 break;
6109 case 0x1d: /* fucomi */
bff93281
PM
6110 if (!(s->cpuid_features & CPUID_CMOV)) {
6111 goto illegal_op;
6112 }
773cdfcc 6113 gen_update_cc_op(s);
d3eb5eae
BS
6114 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6115 gen_helper_fucomi_ST0_FT0(cpu_env);
3ca51d07 6116 set_cc_op(s, CC_OP_EFLAGS);
2c0262af
FB
6117 break;
6118 case 0x1e: /* fcomi */
bff93281
PM
6119 if (!(s->cpuid_features & CPUID_CMOV)) {
6120 goto illegal_op;
6121 }
773cdfcc 6122 gen_update_cc_op(s);
d3eb5eae
BS
6123 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6124 gen_helper_fcomi_ST0_FT0(cpu_env);
3ca51d07 6125 set_cc_op(s, CC_OP_EFLAGS);
2c0262af 6126 break;
658c8bda 6127 case 0x28: /* ffree sti */
d3eb5eae 6128 gen_helper_ffree_STN(cpu_env, tcg_const_i32(opreg));
5fafdf24 6129 break;
2c0262af 6130 case 0x2a: /* fst sti */
d3eb5eae 6131 gen_helper_fmov_STN_ST0(cpu_env, tcg_const_i32(opreg));
2c0262af
FB
6132 break;
6133 case 0x2b: /* fstp sti */
c169c906
FB
6134 case 0x0b: /* fstp1 sti, undocumented op */
6135 case 0x3a: /* fstp8 sti, undocumented op */
6136 case 0x3b: /* fstp9 sti, undocumented op */
d3eb5eae
BS
6137 gen_helper_fmov_STN_ST0(cpu_env, tcg_const_i32(opreg));
6138 gen_helper_fpop(cpu_env);
2c0262af
FB
6139 break;
6140 case 0x2c: /* fucom st(i) */
d3eb5eae
BS
6141 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6142 gen_helper_fucom_ST0_FT0(cpu_env);
2c0262af
FB
6143 break;
6144 case 0x2d: /* fucomp st(i) */
d3eb5eae
BS
6145 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6146 gen_helper_fucom_ST0_FT0(cpu_env);
6147 gen_helper_fpop(cpu_env);
2c0262af
FB
6148 break;
6149 case 0x33: /* de/3 */
6150 switch(rm) {
6151 case 1: /* fcompp */
d3eb5eae
BS
6152 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(1));
6153 gen_helper_fcom_ST0_FT0(cpu_env);
6154 gen_helper_fpop(cpu_env);
6155 gen_helper_fpop(cpu_env);
2c0262af
FB
6156 break;
6157 default:
6158 goto illegal_op;
6159 }
6160 break;
c169c906 6161 case 0x38: /* ffreep sti, undocumented op */
d3eb5eae
BS
6162 gen_helper_ffree_STN(cpu_env, tcg_const_i32(opreg));
6163 gen_helper_fpop(cpu_env);
c169c906 6164 break;
2c0262af
FB
6165 case 0x3c: /* df/4 */
6166 switch(rm) {
6167 case 0:
d3eb5eae 6168 gen_helper_fnstsw(cpu_tmp2_i32, cpu_env);
b6abf97d 6169 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
480a762d 6170 gen_op_mov_reg_v(MO_16, R_EAX, cpu_T[0]);
2c0262af
FB
6171 break;
6172 default:
6173 goto illegal_op;
6174 }
6175 break;
6176 case 0x3d: /* fucomip */
bff93281
PM
6177 if (!(s->cpuid_features & CPUID_CMOV)) {
6178 goto illegal_op;
6179 }
773cdfcc 6180 gen_update_cc_op(s);
d3eb5eae
BS
6181 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6182 gen_helper_fucomi_ST0_FT0(cpu_env);
6183 gen_helper_fpop(cpu_env);
3ca51d07 6184 set_cc_op(s, CC_OP_EFLAGS);
2c0262af
FB
6185 break;
6186 case 0x3e: /* fcomip */
bff93281
PM
6187 if (!(s->cpuid_features & CPUID_CMOV)) {
6188 goto illegal_op;
6189 }
773cdfcc 6190 gen_update_cc_op(s);
d3eb5eae
BS
6191 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6192 gen_helper_fcomi_ST0_FT0(cpu_env);
6193 gen_helper_fpop(cpu_env);
3ca51d07 6194 set_cc_op(s, CC_OP_EFLAGS);
2c0262af 6195 break;
a2cc3b24
FB
6196 case 0x10 ... 0x13: /* fcmovxx */
6197 case 0x18 ... 0x1b:
6198 {
19e6c4b8 6199 int op1, l1;
d70040bc 6200 static const uint8_t fcmov_cc[8] = {
a2cc3b24
FB
6201 (JCC_B << 1),
6202 (JCC_Z << 1),
6203 (JCC_BE << 1),
6204 (JCC_P << 1),
6205 };
bff93281
PM
6206
6207 if (!(s->cpuid_features & CPUID_CMOV)) {
6208 goto illegal_op;
6209 }
1e4840bf 6210 op1 = fcmov_cc[op & 3] | (((op >> 3) & 1) ^ 1);
19e6c4b8 6211 l1 = gen_new_label();
dc259201 6212 gen_jcc1_noeob(s, op1, l1);
d3eb5eae 6213 gen_helper_fmov_ST0_STN(cpu_env, tcg_const_i32(opreg));
19e6c4b8 6214 gen_set_label(l1);
a2cc3b24
FB
6215 }
6216 break;
2c0262af
FB
6217 default:
6218 goto illegal_op;
6219 }
6220 }
6221 break;
6222 /************************/
6223 /* string ops */
6224
6225 case 0xa4: /* movsS */
6226 case 0xa5:
ab4e4aec 6227 ot = mo_b_d(b, dflag);
2c0262af
FB
6228 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6229 gen_repz_movs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6230 } else {
6231 gen_movs(s, ot);
6232 }
6233 break;
3b46e624 6234
2c0262af
FB
6235 case 0xaa: /* stosS */
6236 case 0xab:
ab4e4aec 6237 ot = mo_b_d(b, dflag);
2c0262af
FB
6238 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6239 gen_repz_stos(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6240 } else {
6241 gen_stos(s, ot);
6242 }
6243 break;
6244 case 0xac: /* lodsS */
6245 case 0xad:
ab4e4aec 6246 ot = mo_b_d(b, dflag);
2c0262af
FB
6247 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6248 gen_repz_lods(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6249 } else {
6250 gen_lods(s, ot);
6251 }
6252 break;
6253 case 0xae: /* scasS */
6254 case 0xaf:
ab4e4aec 6255 ot = mo_b_d(b, dflag);
2c0262af
FB
6256 if (prefixes & PREFIX_REPNZ) {
6257 gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
6258 } else if (prefixes & PREFIX_REPZ) {
6259 gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
6260 } else {
6261 gen_scas(s, ot);
2c0262af
FB
6262 }
6263 break;
6264
6265 case 0xa6: /* cmpsS */
6266 case 0xa7:
ab4e4aec 6267 ot = mo_b_d(b, dflag);
2c0262af
FB
6268 if (prefixes & PREFIX_REPNZ) {
6269 gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
6270 } else if (prefixes & PREFIX_REPZ) {
6271 gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
6272 } else {
6273 gen_cmps(s, ot);
2c0262af
FB
6274 }
6275 break;
6276 case 0x6c: /* insS */
6277 case 0x6d:
ab4e4aec 6278 ot = mo_b_d32(b, dflag);
40b90233 6279 tcg_gen_ext16u_tl(cpu_T[0], cpu_regs[R_EDX]);
b8b6a50b
FB
6280 gen_check_io(s, ot, pc_start - s->cs_base,
6281 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes) | 4);
f115e911
FB
6282 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6283 gen_repz_ins(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
2c0262af 6284 } else {
f115e911 6285 gen_ins(s, ot);
bd79255d 6286 if (s->tb->cflags & CF_USE_ICOUNT) {
2e70f6ef
PB
6287 gen_jmp(s, s->pc - s->cs_base);
6288 }
2c0262af
FB
6289 }
6290 break;
6291 case 0x6e: /* outsS */
6292 case 0x6f:
ab4e4aec 6293 ot = mo_b_d32(b, dflag);
40b90233 6294 tcg_gen_ext16u_tl(cpu_T[0], cpu_regs[R_EDX]);
b8b6a50b
FB
6295 gen_check_io(s, ot, pc_start - s->cs_base,
6296 svm_is_rep(prefixes) | 4);
f115e911
FB
6297 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6298 gen_repz_outs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
2c0262af 6299 } else {
f115e911 6300 gen_outs(s, ot);
bd79255d 6301 if (s->tb->cflags & CF_USE_ICOUNT) {
2e70f6ef
PB
6302 gen_jmp(s, s->pc - s->cs_base);
6303 }
2c0262af
FB
6304 }
6305 break;
6306
6307 /************************/
6308 /* port I/O */
0573fbfc 6309
2c0262af
FB
6310 case 0xe4:
6311 case 0xe5:
ab4e4aec 6312 ot = mo_b_d32(b, dflag);
0af10c86 6313 val = cpu_ldub_code(env, s->pc++);
6d093a4f 6314 tcg_gen_movi_tl(cpu_T[0], val);
b8b6a50b
FB
6315 gen_check_io(s, ot, pc_start - s->cs_base,
6316 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes));
bd79255d 6317 if (s->tb->cflags & CF_USE_ICOUNT) {
2e70f6ef 6318 gen_io_start();
bd79255d 6319 }
1b90d56e 6320 tcg_gen_movi_i32(cpu_tmp2_i32, val);
a7812ae4 6321 gen_helper_in_func(ot, cpu_T[1], cpu_tmp2_i32);
68773f84 6322 gen_op_mov_reg_v(ot, R_EAX, cpu_T[1]);
bd79255d 6323 if (s->tb->cflags & CF_USE_ICOUNT) {
2e70f6ef
PB
6324 gen_io_end();
6325 gen_jmp(s, s->pc - s->cs_base);
6326 }
2c0262af
FB
6327 break;
6328 case 0xe6:
6329 case 0xe7:
ab4e4aec 6330 ot = mo_b_d32(b, dflag);
0af10c86 6331 val = cpu_ldub_code(env, s->pc++);
6d093a4f 6332 tcg_gen_movi_tl(cpu_T[0], val);
b8b6a50b
FB
6333 gen_check_io(s, ot, pc_start - s->cs_base,
6334 svm_is_rep(prefixes));
c56baccf 6335 gen_op_mov_v_reg(ot, cpu_T[1], R_EAX);
b8b6a50b 6336
bd79255d 6337 if (s->tb->cflags & CF_USE_ICOUNT) {
2e70f6ef 6338 gen_io_start();
bd79255d 6339 }
1b90d56e 6340 tcg_gen_movi_i32(cpu_tmp2_i32, val);
b6abf97d 6341 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T[1]);
a7812ae4 6342 gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32);
bd79255d 6343 if (s->tb->cflags & CF_USE_ICOUNT) {
2e70f6ef
PB
6344 gen_io_end();
6345 gen_jmp(s, s->pc - s->cs_base);
6346 }
2c0262af
FB
6347 break;
6348 case 0xec:
6349 case 0xed:
ab4e4aec 6350 ot = mo_b_d32(b, dflag);
40b90233 6351 tcg_gen_ext16u_tl(cpu_T[0], cpu_regs[R_EDX]);
b8b6a50b
FB
6352 gen_check_io(s, ot, pc_start - s->cs_base,
6353 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes));
bd79255d 6354 if (s->tb->cflags & CF_USE_ICOUNT) {
2e70f6ef 6355 gen_io_start();
bd79255d 6356 }
b6abf97d 6357 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
a7812ae4 6358 gen_helper_in_func(ot, cpu_T[1], cpu_tmp2_i32);
68773f84 6359 gen_op_mov_reg_v(ot, R_EAX, cpu_T[1]);
bd79255d 6360 if (s->tb->cflags & CF_USE_ICOUNT) {
2e70f6ef
PB
6361 gen_io_end();
6362 gen_jmp(s, s->pc - s->cs_base);
6363 }
2c0262af
FB
6364 break;
6365 case 0xee:
6366 case 0xef:
ab4e4aec 6367 ot = mo_b_d32(b, dflag);
40b90233 6368 tcg_gen_ext16u_tl(cpu_T[0], cpu_regs[R_EDX]);
b8b6a50b
FB
6369 gen_check_io(s, ot, pc_start - s->cs_base,
6370 svm_is_rep(prefixes));
c56baccf 6371 gen_op_mov_v_reg(ot, cpu_T[1], R_EAX);
b8b6a50b 6372
bd79255d 6373 if (s->tb->cflags & CF_USE_ICOUNT) {
2e70f6ef 6374 gen_io_start();
bd79255d 6375 }
b6abf97d 6376 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
b6abf97d 6377 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T[1]);
a7812ae4 6378 gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32);
bd79255d 6379 if (s->tb->cflags & CF_USE_ICOUNT) {
2e70f6ef
PB
6380 gen_io_end();
6381 gen_jmp(s, s->pc - s->cs_base);
6382 }
2c0262af
FB
6383 break;
6384
6385 /************************/
6386 /* control */
6387 case 0xc2: /* ret im */
0af10c86 6388 val = cpu_ldsw_code(env, s->pc);
2c0262af 6389 s->pc += 2;
8e31d234
RH
6390 ot = gen_pop_T0(s);
6391 gen_stack_update(s, val + (1 << ot));
6392 /* Note that gen_pop_T0 uses a zero-extending load. */
74bdfbda 6393 gen_op_jmp_v(cpu_T[0]);
2c0262af
FB
6394 gen_eob(s);
6395 break;
6396 case 0xc3: /* ret */
8e31d234
RH
6397 ot = gen_pop_T0(s);
6398 gen_pop_update(s, ot);
6399 /* Note that gen_pop_T0 uses a zero-extending load. */
74bdfbda 6400 gen_op_jmp_v(cpu_T[0]);
2c0262af
FB
6401 gen_eob(s);
6402 break;
6403 case 0xca: /* lret im */
0af10c86 6404 val = cpu_ldsw_code(env, s->pc);
2c0262af
FB
6405 s->pc += 2;
6406 do_lret:
6407 if (s->pe && !s->vm86) {
773cdfcc 6408 gen_update_cc_op(s);
14ce26e7 6409 gen_jmp_im(pc_start - s->cs_base);
ab4e4aec 6410 gen_helper_lret_protected(cpu_env, tcg_const_i32(dflag - 1),
a7812ae4 6411 tcg_const_i32(val));
2c0262af
FB
6412 } else {
6413 gen_stack_A0(s);
6414 /* pop offset */
ab4e4aec 6415 gen_op_ld_v(s, dflag, cpu_T[0], cpu_A0);
2c0262af
FB
6416 /* NOTE: keeping EIP updated is not a problem in case of
6417 exception */
74bdfbda 6418 gen_op_jmp_v(cpu_T[0]);
2c0262af 6419 /* pop selector */
ab4e4aec
RH
6420 gen_op_addl_A0_im(1 << dflag);
6421 gen_op_ld_v(s, dflag, cpu_T[0], cpu_A0);
3bd7da9e 6422 gen_op_movl_seg_T0_vm(R_CS);
2c0262af 6423 /* add stack offset */
ab4e4aec 6424 gen_stack_update(s, val + (2 << dflag));
2c0262af
FB
6425 }
6426 gen_eob(s);
6427 break;
6428 case 0xcb: /* lret */
6429 val = 0;
6430 goto do_lret;
6431 case 0xcf: /* iret */
872929aa 6432 gen_svm_check_intercept(s, pc_start, SVM_EXIT_IRET);
2c0262af
FB
6433 if (!s->pe) {
6434 /* real mode */
ab4e4aec 6435 gen_helper_iret_real(cpu_env, tcg_const_i32(dflag - 1));
3ca51d07 6436 set_cc_op(s, CC_OP_EFLAGS);
f115e911
FB
6437 } else if (s->vm86) {
6438 if (s->iopl != 3) {
6439 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6440 } else {
ab4e4aec 6441 gen_helper_iret_real(cpu_env, tcg_const_i32(dflag - 1));
3ca51d07 6442 set_cc_op(s, CC_OP_EFLAGS);
f115e911 6443 }
2c0262af 6444 } else {
773cdfcc 6445 gen_update_cc_op(s);
14ce26e7 6446 gen_jmp_im(pc_start - s->cs_base);
ab4e4aec 6447 gen_helper_iret_protected(cpu_env, tcg_const_i32(dflag - 1),
a7812ae4 6448 tcg_const_i32(s->pc - s->cs_base));
3ca51d07 6449 set_cc_op(s, CC_OP_EFLAGS);
2c0262af
FB
6450 }
6451 gen_eob(s);
6452 break;
6453 case 0xe8: /* call im */
6454 {
ab4e4aec 6455 if (dflag != MO_16) {
4ba9938c 6456 tval = (int32_t)insn_get(env, s, MO_32);
ab4e4aec 6457 } else {
4ba9938c 6458 tval = (int16_t)insn_get(env, s, MO_16);
ab4e4aec 6459 }
2c0262af 6460 next_eip = s->pc - s->cs_base;
14ce26e7 6461 tval += next_eip;
ab4e4aec 6462 if (dflag == MO_16) {
14ce26e7 6463 tval &= 0xffff;
ab4e4aec 6464 } else if (!CODE64(s)) {
99596385 6465 tval &= 0xffffffff;
ab4e4aec 6466 }
cc0bce88 6467 tcg_gen_movi_tl(cpu_T[0], next_eip);
432baffe 6468 gen_push_v(s, cpu_T[0]);
14ce26e7 6469 gen_jmp(s, tval);
2c0262af
FB
6470 }
6471 break;
6472 case 0x9a: /* lcall im */
6473 {
6474 unsigned int selector, offset;
3b46e624 6475
14ce26e7
FB
6476 if (CODE64(s))
6477 goto illegal_op;
ab4e4aec 6478 ot = dflag;
0af10c86 6479 offset = insn_get(env, s, ot);
4ba9938c 6480 selector = insn_get(env, s, MO_16);
3b46e624 6481
1b90d56e 6482 tcg_gen_movi_tl(cpu_T[0], selector);
0ae657b1 6483 tcg_gen_movi_tl(cpu_T[1], offset);
2c0262af
FB
6484 }
6485 goto do_lcall;
ecada8a2 6486 case 0xe9: /* jmp im */
ab4e4aec 6487 if (dflag != MO_16) {
4ba9938c 6488 tval = (int32_t)insn_get(env, s, MO_32);
ab4e4aec 6489 } else {
4ba9938c 6490 tval = (int16_t)insn_get(env, s, MO_16);
ab4e4aec 6491 }
14ce26e7 6492 tval += s->pc - s->cs_base;
ab4e4aec 6493 if (dflag == MO_16) {
14ce26e7 6494 tval &= 0xffff;
ab4e4aec 6495 } else if (!CODE64(s)) {
32938e12 6496 tval &= 0xffffffff;
ab4e4aec 6497 }
14ce26e7 6498 gen_jmp(s, tval);
2c0262af
FB
6499 break;
6500 case 0xea: /* ljmp im */
6501 {
6502 unsigned int selector, offset;
6503
14ce26e7
FB
6504 if (CODE64(s))
6505 goto illegal_op;
ab4e4aec 6506 ot = dflag;
0af10c86 6507 offset = insn_get(env, s, ot);
4ba9938c 6508 selector = insn_get(env, s, MO_16);
3b46e624 6509
1b90d56e 6510 tcg_gen_movi_tl(cpu_T[0], selector);
0ae657b1 6511 tcg_gen_movi_tl(cpu_T[1], offset);
2c0262af
FB
6512 }
6513 goto do_ljmp;
6514 case 0xeb: /* jmp Jb */
4ba9938c 6515 tval = (int8_t)insn_get(env, s, MO_8);
14ce26e7 6516 tval += s->pc - s->cs_base;
ab4e4aec 6517 if (dflag == MO_16) {
14ce26e7 6518 tval &= 0xffff;
ab4e4aec 6519 }
14ce26e7 6520 gen_jmp(s, tval);
2c0262af
FB
6521 break;
6522 case 0x70 ... 0x7f: /* jcc Jb */
4ba9938c 6523 tval = (int8_t)insn_get(env, s, MO_8);
2c0262af
FB
6524 goto do_jcc;
6525 case 0x180 ... 0x18f: /* jcc Jv */
ab4e4aec 6526 if (dflag != MO_16) {
4ba9938c 6527 tval = (int32_t)insn_get(env, s, MO_32);
2c0262af 6528 } else {
4ba9938c 6529 tval = (int16_t)insn_get(env, s, MO_16);
2c0262af
FB
6530 }
6531 do_jcc:
6532 next_eip = s->pc - s->cs_base;
14ce26e7 6533 tval += next_eip;
ab4e4aec 6534 if (dflag == MO_16) {
14ce26e7 6535 tval &= 0xffff;
ab4e4aec 6536 }
14ce26e7 6537 gen_jcc(s, b, tval, next_eip);
2c0262af
FB
6538 break;
6539
6540 case 0x190 ... 0x19f: /* setcc Gv */
0af10c86 6541 modrm = cpu_ldub_code(env, s->pc++);
cc8b6f5b 6542 gen_setcc1(s, b, cpu_T[0]);
4ba9938c 6543 gen_ldst_modrm(env, s, modrm, MO_8, OR_TMP0, 1);
2c0262af
FB
6544 break;
6545 case 0x140 ... 0x14f: /* cmov Gv, Ev */
bff93281
PM
6546 if (!(s->cpuid_features & CPUID_CMOV)) {
6547 goto illegal_op;
6548 }
ab4e4aec 6549 ot = dflag;
f32d3781
PB
6550 modrm = cpu_ldub_code(env, s->pc++);
6551 reg = ((modrm >> 3) & 7) | rex_r;
6552 gen_cmovcc1(env, s, ot, b, modrm, reg);
2c0262af 6553 break;
3b46e624 6554
2c0262af
FB
6555 /************************/
6556 /* flags */
6557 case 0x9c: /* pushf */
872929aa 6558 gen_svm_check_intercept(s, pc_start, SVM_EXIT_PUSHF);
2c0262af
FB
6559 if (s->vm86 && s->iopl != 3) {
6560 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6561 } else {
773cdfcc 6562 gen_update_cc_op(s);
f0967a1a 6563 gen_helper_read_eflags(cpu_T[0], cpu_env);
432baffe 6564 gen_push_v(s, cpu_T[0]);
2c0262af
FB
6565 }
6566 break;
6567 case 0x9d: /* popf */
872929aa 6568 gen_svm_check_intercept(s, pc_start, SVM_EXIT_POPF);
2c0262af
FB
6569 if (s->vm86 && s->iopl != 3) {
6570 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6571 } else {
8e31d234 6572 ot = gen_pop_T0(s);
2c0262af 6573 if (s->cpl == 0) {
ab4e4aec 6574 if (dflag != MO_16) {
f0967a1a
BS
6575 gen_helper_write_eflags(cpu_env, cpu_T[0],
6576 tcg_const_i32((TF_MASK | AC_MASK |
6577 ID_MASK | NT_MASK |
6578 IF_MASK |
6579 IOPL_MASK)));
2c0262af 6580 } else {
f0967a1a
BS
6581 gen_helper_write_eflags(cpu_env, cpu_T[0],
6582 tcg_const_i32((TF_MASK | AC_MASK |
6583 ID_MASK | NT_MASK |
6584 IF_MASK | IOPL_MASK)
6585 & 0xffff));
2c0262af
FB
6586 }
6587 } else {
4136f33c 6588 if (s->cpl <= s->iopl) {
ab4e4aec 6589 if (dflag != MO_16) {
f0967a1a
BS
6590 gen_helper_write_eflags(cpu_env, cpu_T[0],
6591 tcg_const_i32((TF_MASK |
6592 AC_MASK |
6593 ID_MASK |
6594 NT_MASK |
6595 IF_MASK)));
4136f33c 6596 } else {
f0967a1a
BS
6597 gen_helper_write_eflags(cpu_env, cpu_T[0],
6598 tcg_const_i32((TF_MASK |
6599 AC_MASK |
6600 ID_MASK |
6601 NT_MASK |
6602 IF_MASK)
6603 & 0xffff));
4136f33c 6604 }
2c0262af 6605 } else {
ab4e4aec 6606 if (dflag != MO_16) {
f0967a1a
BS
6607 gen_helper_write_eflags(cpu_env, cpu_T[0],
6608 tcg_const_i32((TF_MASK | AC_MASK |
6609 ID_MASK | NT_MASK)));
4136f33c 6610 } else {
f0967a1a
BS
6611 gen_helper_write_eflags(cpu_env, cpu_T[0],
6612 tcg_const_i32((TF_MASK | AC_MASK |
6613 ID_MASK | NT_MASK)
6614 & 0xffff));
4136f33c 6615 }
2c0262af
FB
6616 }
6617 }
8e31d234 6618 gen_pop_update(s, ot);
3ca51d07 6619 set_cc_op(s, CC_OP_EFLAGS);
a9321a4d 6620 /* abort translation because TF/AC flag may change */
14ce26e7 6621 gen_jmp_im(s->pc - s->cs_base);
2c0262af
FB
6622 gen_eob(s);
6623 }
6624 break;
6625 case 0x9e: /* sahf */
12e26b75 6626 if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM))
14ce26e7 6627 goto illegal_op;
c56baccf 6628 gen_op_mov_v_reg(MO_8, cpu_T[0], R_AH);
d229edce 6629 gen_compute_eflags(s);
bd7a7b33
FB
6630 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, CC_O);
6631 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], CC_S | CC_Z | CC_A | CC_P | CC_C);
6632 tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, cpu_T[0]);
2c0262af
FB
6633 break;
6634 case 0x9f: /* lahf */
12e26b75 6635 if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM))
14ce26e7 6636 goto illegal_op;
d229edce 6637 gen_compute_eflags(s);
bd7a7b33 6638 /* Note: gen_compute_eflags() only gives the condition codes */
d229edce 6639 tcg_gen_ori_tl(cpu_T[0], cpu_cc_src, 0x02);
480a762d 6640 gen_op_mov_reg_v(MO_8, R_AH, cpu_T[0]);
2c0262af
FB
6641 break;
6642 case 0xf5: /* cmc */
d229edce 6643 gen_compute_eflags(s);
bd7a7b33 6644 tcg_gen_xori_tl(cpu_cc_src, cpu_cc_src, CC_C);
2c0262af
FB
6645 break;
6646 case 0xf8: /* clc */
d229edce 6647 gen_compute_eflags(s);
bd7a7b33 6648 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~CC_C);
2c0262af
FB
6649 break;
6650 case 0xf9: /* stc */
d229edce 6651 gen_compute_eflags(s);
bd7a7b33 6652 tcg_gen_ori_tl(cpu_cc_src, cpu_cc_src, CC_C);
2c0262af
FB
6653 break;
6654 case 0xfc: /* cld */
b6abf97d 6655 tcg_gen_movi_i32(cpu_tmp2_i32, 1);
317ac620 6656 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, offsetof(CPUX86State, df));
2c0262af
FB
6657 break;
6658 case 0xfd: /* std */
b6abf97d 6659 tcg_gen_movi_i32(cpu_tmp2_i32, -1);
317ac620 6660 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, offsetof(CPUX86State, df));
2c0262af
FB
6661 break;
6662
6663 /************************/
6664 /* bit operations */
6665 case 0x1ba: /* bt/bts/btr/btc Gv, im */
ab4e4aec 6666 ot = dflag;
0af10c86 6667 modrm = cpu_ldub_code(env, s->pc++);
33698e5f 6668 op = (modrm >> 3) & 7;
2c0262af 6669 mod = (modrm >> 6) & 3;
14ce26e7 6670 rm = (modrm & 7) | REX_B(s);
2c0262af 6671 if (mod != 3) {
14ce26e7 6672 s->rip_offset = 1;
4eeb3939 6673 gen_lea_modrm(env, s, modrm);
909be183 6674 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
2c0262af 6675 } else {
c56baccf 6676 gen_op_mov_v_reg(ot, cpu_T[0], rm);
2c0262af
FB
6677 }
6678 /* load shift */
0af10c86 6679 val = cpu_ldub_code(env, s->pc++);
0ae657b1 6680 tcg_gen_movi_tl(cpu_T[1], val);
2c0262af
FB
6681 if (op < 4)
6682 goto illegal_op;
6683 op -= 4;
f484d386 6684 goto bt_op;
2c0262af
FB
6685 case 0x1a3: /* bt Gv, Ev */
6686 op = 0;
6687 goto do_btx;
6688 case 0x1ab: /* bts */
6689 op = 1;
6690 goto do_btx;
6691 case 0x1b3: /* btr */
6692 op = 2;
6693 goto do_btx;
6694 case 0x1bb: /* btc */
6695 op = 3;
6696 do_btx:
ab4e4aec 6697 ot = dflag;
0af10c86 6698 modrm = cpu_ldub_code(env, s->pc++);
14ce26e7 6699 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af 6700 mod = (modrm >> 6) & 3;
14ce26e7 6701 rm = (modrm & 7) | REX_B(s);
c56baccf 6702 gen_op_mov_v_reg(MO_32, cpu_T[1], reg);
2c0262af 6703 if (mod != 3) {
4eeb3939 6704 gen_lea_modrm(env, s, modrm);
2c0262af 6705 /* specific case: we need to add a displacement */
f484d386
FB
6706 gen_exts(ot, cpu_T[1]);
6707 tcg_gen_sari_tl(cpu_tmp0, cpu_T[1], 3 + ot);
6708 tcg_gen_shli_tl(cpu_tmp0, cpu_tmp0, ot);
6709 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
909be183 6710 gen_op_ld_v(s, ot, cpu_T[0], cpu_A0);
2c0262af 6711 } else {
c56baccf 6712 gen_op_mov_v_reg(ot, cpu_T[0], rm);
2c0262af 6713 }
f484d386
FB
6714 bt_op:
6715 tcg_gen_andi_tl(cpu_T[1], cpu_T[1], (1 << (3 + ot)) - 1);
dc1823ce 6716 tcg_gen_shr_tl(cpu_tmp4, cpu_T[0], cpu_T[1]);
f484d386
FB
6717 switch(op) {
6718 case 0:
f484d386
FB
6719 break;
6720 case 1:
f484d386
FB
6721 tcg_gen_movi_tl(cpu_tmp0, 1);
6722 tcg_gen_shl_tl(cpu_tmp0, cpu_tmp0, cpu_T[1]);
6723 tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_tmp0);
6724 break;
6725 case 2:
f484d386
FB
6726 tcg_gen_movi_tl(cpu_tmp0, 1);
6727 tcg_gen_shl_tl(cpu_tmp0, cpu_tmp0, cpu_T[1]);
dc1823ce 6728 tcg_gen_andc_tl(cpu_T[0], cpu_T[0], cpu_tmp0);
f484d386
FB
6729 break;
6730 default:
6731 case 3:
f484d386
FB
6732 tcg_gen_movi_tl(cpu_tmp0, 1);
6733 tcg_gen_shl_tl(cpu_tmp0, cpu_tmp0, cpu_T[1]);
6734 tcg_gen_xor_tl(cpu_T[0], cpu_T[0], cpu_tmp0);
6735 break;
6736 }
2c0262af 6737 if (op != 0) {
fd8ca9f6
RH
6738 if (mod != 3) {
6739 gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
6740 } else {
480a762d 6741 gen_op_mov_reg_v(ot, rm, cpu_T[0]);
fd8ca9f6 6742 }
dc1823ce
RH
6743 }
6744
6745 /* Delay all CC updates until after the store above. Note that
6746 C is the result of the test, Z is unchanged, and the others
6747 are all undefined. */
6748 switch (s->cc_op) {
6749 case CC_OP_MULB ... CC_OP_MULQ:
6750 case CC_OP_ADDB ... CC_OP_ADDQ:
6751 case CC_OP_ADCB ... CC_OP_ADCQ:
6752 case CC_OP_SUBB ... CC_OP_SUBQ:
6753 case CC_OP_SBBB ... CC_OP_SBBQ:
6754 case CC_OP_LOGICB ... CC_OP_LOGICQ:
6755 case CC_OP_INCB ... CC_OP_INCQ:
6756 case CC_OP_DECB ... CC_OP_DECQ:
6757 case CC_OP_SHLB ... CC_OP_SHLQ:
6758 case CC_OP_SARB ... CC_OP_SARQ:
6759 case CC_OP_BMILGB ... CC_OP_BMILGQ:
6760 /* Z was going to be computed from the non-zero status of CC_DST.
6761 We can get that same Z value (and the new C value) by leaving
6762 CC_DST alone, setting CC_SRC, and using a CC_OP_SAR of the
6763 same width. */
f484d386 6764 tcg_gen_mov_tl(cpu_cc_src, cpu_tmp4);
dc1823ce
RH
6765 set_cc_op(s, ((s->cc_op - CC_OP_MULB) & 3) + CC_OP_SARB);
6766 break;
6767 default:
6768 /* Otherwise, generate EFLAGS and replace the C bit. */
6769 gen_compute_eflags(s);
6770 tcg_gen_deposit_tl(cpu_cc_src, cpu_cc_src, cpu_tmp4,
6771 ctz32(CC_C), 1);
6772 break;
2c0262af
FB
6773 }
6774 break;
321c5351
RH
6775 case 0x1bc: /* bsf / tzcnt */
6776 case 0x1bd: /* bsr / lzcnt */
ab4e4aec 6777 ot = dflag;
321c5351
RH
6778 modrm = cpu_ldub_code(env, s->pc++);
6779 reg = ((modrm >> 3) & 7) | rex_r;
6780 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
6781 gen_extu(ot, cpu_T[0]);
6782
6783 /* Note that lzcnt and tzcnt are in different extensions. */
6784 if ((prefixes & PREFIX_REPZ)
6785 && (b & 1
6786 ? s->cpuid_ext3_features & CPUID_EXT3_ABM
6787 : s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)) {
6788 int size = 8 << ot;
6789 tcg_gen_mov_tl(cpu_cc_src, cpu_T[0]);
6790 if (b & 1) {
6791 /* For lzcnt, reduce the target_ulong result by the
6792 number of zeros that we expect to find at the top. */
6793 gen_helper_clz(cpu_T[0], cpu_T[0]);
6794 tcg_gen_subi_tl(cpu_T[0], cpu_T[0], TARGET_LONG_BITS - size);
6191b059 6795 } else {
321c5351
RH
6796 /* For tzcnt, a zero input must return the operand size:
6797 force all bits outside the operand size to 1. */
6798 target_ulong mask = (target_ulong)-2 << (size - 1);
6799 tcg_gen_ori_tl(cpu_T[0], cpu_T[0], mask);
6800 gen_helper_ctz(cpu_T[0], cpu_T[0]);
6191b059 6801 }
321c5351
RH
6802 /* For lzcnt/tzcnt, C and Z bits are defined and are
6803 related to the result. */
6804 gen_op_update1_cc();
6805 set_cc_op(s, CC_OP_BMILGB + ot);
6806 } else {
6807 /* For bsr/bsf, only the Z bit is defined and it is related
6808 to the input and not the result. */
6809 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
6810 set_cc_op(s, CC_OP_LOGICB + ot);
6811 if (b & 1) {
6812 /* For bsr, return the bit index of the first 1 bit,
6813 not the count of leading zeros. */
6814 gen_helper_clz(cpu_T[0], cpu_T[0]);
6815 tcg_gen_xori_tl(cpu_T[0], cpu_T[0], TARGET_LONG_BITS - 1);
6816 } else {
6817 gen_helper_ctz(cpu_T[0], cpu_T[0]);
6818 }
6819 /* ??? The manual says that the output is undefined when the
6820 input is zero, but real hardware leaves it unchanged, and
6821 real programs appear to depend on that. */
6822 tcg_gen_movi_tl(cpu_tmp0, 0);
6823 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_T[0], cpu_cc_dst, cpu_tmp0,
6824 cpu_regs[reg], cpu_T[0]);
6191b059 6825 }
480a762d 6826 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
2c0262af
FB
6827 break;
6828 /************************/
6829 /* bcd */
6830 case 0x27: /* daa */
14ce26e7
FB
6831 if (CODE64(s))
6832 goto illegal_op;
773cdfcc 6833 gen_update_cc_op(s);
7923057b 6834 gen_helper_daa(cpu_env);
3ca51d07 6835 set_cc_op(s, CC_OP_EFLAGS);
2c0262af
FB
6836 break;
6837 case 0x2f: /* das */
14ce26e7
FB
6838 if (CODE64(s))
6839 goto illegal_op;
773cdfcc 6840 gen_update_cc_op(s);
7923057b 6841 gen_helper_das(cpu_env);
3ca51d07 6842 set_cc_op(s, CC_OP_EFLAGS);
2c0262af
FB
6843 break;
6844 case 0x37: /* aaa */
14ce26e7
FB
6845 if (CODE64(s))
6846 goto illegal_op;
773cdfcc 6847 gen_update_cc_op(s);
7923057b 6848 gen_helper_aaa(cpu_env);
3ca51d07 6849 set_cc_op(s, CC_OP_EFLAGS);
2c0262af
FB
6850 break;
6851 case 0x3f: /* aas */
14ce26e7
FB
6852 if (CODE64(s))
6853 goto illegal_op;
773cdfcc 6854 gen_update_cc_op(s);
7923057b 6855 gen_helper_aas(cpu_env);
3ca51d07 6856 set_cc_op(s, CC_OP_EFLAGS);
2c0262af
FB
6857 break;
6858 case 0xd4: /* aam */
14ce26e7
FB
6859 if (CODE64(s))
6860 goto illegal_op;
0af10c86 6861 val = cpu_ldub_code(env, s->pc++);
b6d7c3db
TS
6862 if (val == 0) {
6863 gen_exception(s, EXCP00_DIVZ, pc_start - s->cs_base);
6864 } else {
7923057b 6865 gen_helper_aam(cpu_env, tcg_const_i32(val));
3ca51d07 6866 set_cc_op(s, CC_OP_LOGICB);
b6d7c3db 6867 }
2c0262af
FB
6868 break;
6869 case 0xd5: /* aad */
14ce26e7
FB
6870 if (CODE64(s))
6871 goto illegal_op;
0af10c86 6872 val = cpu_ldub_code(env, s->pc++);
7923057b 6873 gen_helper_aad(cpu_env, tcg_const_i32(val));
3ca51d07 6874 set_cc_op(s, CC_OP_LOGICB);
2c0262af
FB
6875 break;
6876 /************************/
6877 /* misc */
6878 case 0x90: /* nop */
ab1f142b 6879 /* XXX: correct lock test for all insn */
7418027e 6880 if (prefixes & PREFIX_LOCK) {
ab1f142b 6881 goto illegal_op;
7418027e
RH
6882 }
6883 /* If REX_B is set, then this is xchg eax, r8d, not a nop. */
6884 if (REX_B(s)) {
6885 goto do_xchg_reg_eax;
6886 }
0573fbfc 6887 if (prefixes & PREFIX_REPZ) {
81f3053b
PB
6888 gen_update_cc_op(s);
6889 gen_jmp_im(pc_start - s->cs_base);
6890 gen_helper_pause(cpu_env, tcg_const_i32(s->pc - pc_start));
6891 s->is_jmp = DISAS_TB_JUMP;
0573fbfc 6892 }
2c0262af
FB
6893 break;
6894 case 0x9b: /* fwait */
5fafdf24 6895 if ((s->flags & (HF_MP_MASK | HF_TS_MASK)) ==
7eee2a50
FB
6896 (HF_MP_MASK | HF_TS_MASK)) {
6897 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
2ee73ac3 6898 } else {
773cdfcc 6899 gen_update_cc_op(s);
14ce26e7 6900 gen_jmp_im(pc_start - s->cs_base);
d3eb5eae 6901 gen_helper_fwait(cpu_env);
7eee2a50 6902 }
2c0262af
FB
6903 break;
6904 case 0xcc: /* int3 */
6905 gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base);
6906 break;
6907 case 0xcd: /* int N */
0af10c86 6908 val = cpu_ldub_code(env, s->pc++);
f115e911 6909 if (s->vm86 && s->iopl != 3) {
5fafdf24 6910 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
f115e911
FB
6911 } else {
6912 gen_interrupt(s, val, pc_start - s->cs_base, s->pc - s->cs_base);
6913 }
2c0262af
FB
6914 break;
6915 case 0xce: /* into */
14ce26e7
FB
6916 if (CODE64(s))
6917 goto illegal_op;
773cdfcc 6918 gen_update_cc_op(s);
a8ede8ba 6919 gen_jmp_im(pc_start - s->cs_base);
4a7443be 6920 gen_helper_into(cpu_env, tcg_const_i32(s->pc - pc_start));
2c0262af 6921 break;
0b97134b 6922#ifdef WANT_ICEBP
2c0262af 6923 case 0xf1: /* icebp (undocumented, exits to external debugger) */
872929aa 6924 gen_svm_check_intercept(s, pc_start, SVM_EXIT_ICEBP);
aba9d61e 6925#if 1
2c0262af 6926 gen_debug(s, pc_start - s->cs_base);
aba9d61e
FB
6927#else
6928 /* start debug */
0af10c86 6929 tb_flush(env);
24537a01 6930 qemu_set_log(CPU_LOG_INT | CPU_LOG_TB_IN_ASM);
aba9d61e 6931#endif
2c0262af 6932 break;
0b97134b 6933#endif
2c0262af
FB
6934 case 0xfa: /* cli */
6935 if (!s->vm86) {
6936 if (s->cpl <= s->iopl) {
f0967a1a 6937 gen_helper_cli(cpu_env);
2c0262af
FB
6938 } else {
6939 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6940 }
6941 } else {
6942 if (s->iopl == 3) {
f0967a1a 6943 gen_helper_cli(cpu_env);
2c0262af
FB
6944 } else {
6945 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6946 }
6947 }
6948 break;
6949 case 0xfb: /* sti */
6950 if (!s->vm86) {
6951 if (s->cpl <= s->iopl) {
6952 gen_sti:
f0967a1a 6953 gen_helper_sti(cpu_env);
2c0262af 6954 /* interruptions are enabled only the first insn after sti */
a2cc3b24
FB
6955 /* If several instructions disable interrupts, only the
6956 _first_ does it */
6957 if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
f0967a1a 6958 gen_helper_set_inhibit_irq(cpu_env);
2c0262af 6959 /* give a chance to handle pending irqs */
14ce26e7 6960 gen_jmp_im(s->pc - s->cs_base);
2c0262af
FB
6961 gen_eob(s);
6962 } else {
6963 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6964 }
6965 } else {
6966 if (s->iopl == 3) {
6967 goto gen_sti;
6968 } else {
6969 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6970 }
6971 }
6972 break;
6973 case 0x62: /* bound */
14ce26e7
FB
6974 if (CODE64(s))
6975 goto illegal_op;
ab4e4aec 6976 ot = dflag;
0af10c86 6977 modrm = cpu_ldub_code(env, s->pc++);
2c0262af
FB
6978 reg = (modrm >> 3) & 7;
6979 mod = (modrm >> 6) & 3;
6980 if (mod == 3)
6981 goto illegal_op;
c56baccf 6982 gen_op_mov_v_reg(ot, cpu_T[0], reg);
4eeb3939 6983 gen_lea_modrm(env, s, modrm);
14ce26e7 6984 gen_jmp_im(pc_start - s->cs_base);
b6abf97d 6985 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
4ba9938c 6986 if (ot == MO_16) {
92fc4b58
BS
6987 gen_helper_boundw(cpu_env, cpu_A0, cpu_tmp2_i32);
6988 } else {
6989 gen_helper_boundl(cpu_env, cpu_A0, cpu_tmp2_i32);
6990 }
2c0262af
FB
6991 break;
6992 case 0x1c8 ... 0x1cf: /* bswap reg */
14ce26e7
FB
6993 reg = (b & 7) | REX_B(s);
6994#ifdef TARGET_X86_64
ab4e4aec 6995 if (dflag == MO_64) {
c56baccf 6996 gen_op_mov_v_reg(MO_64, cpu_T[0], reg);
66896cb8 6997 tcg_gen_bswap64_i64(cpu_T[0], cpu_T[0]);
480a762d 6998 gen_op_mov_reg_v(MO_64, reg, cpu_T[0]);
5fafdf24 6999 } else
8777643e 7000#endif
57fec1fe 7001 {
c56baccf 7002 gen_op_mov_v_reg(MO_32, cpu_T[0], reg);
8777643e
AJ
7003 tcg_gen_ext32u_tl(cpu_T[0], cpu_T[0]);
7004 tcg_gen_bswap32_tl(cpu_T[0], cpu_T[0]);
480a762d 7005 gen_op_mov_reg_v(MO_32, reg, cpu_T[0]);
14ce26e7 7006 }
2c0262af
FB
7007 break;
7008 case 0xd6: /* salc */
14ce26e7
FB
7009 if (CODE64(s))
7010 goto illegal_op;
cc8b6f5b 7011 gen_compute_eflags_c(s, cpu_T[0]);
bd7a7b33 7012 tcg_gen_neg_tl(cpu_T[0], cpu_T[0]);
480a762d 7013 gen_op_mov_reg_v(MO_8, R_EAX, cpu_T[0]);
2c0262af
FB
7014 break;
7015 case 0xe0: /* loopnz */
7016 case 0xe1: /* loopz */
2c0262af
FB
7017 case 0xe2: /* loop */
7018 case 0xe3: /* jecxz */
14ce26e7 7019 {
6e0d8677 7020 int l1, l2, l3;
14ce26e7 7021
4ba9938c 7022 tval = (int8_t)insn_get(env, s, MO_8);
14ce26e7
FB
7023 next_eip = s->pc - s->cs_base;
7024 tval += next_eip;
ab4e4aec 7025 if (dflag == MO_16) {
14ce26e7 7026 tval &= 0xffff;
ab4e4aec 7027 }
3b46e624 7028
14ce26e7
FB
7029 l1 = gen_new_label();
7030 l2 = gen_new_label();
6e0d8677 7031 l3 = gen_new_label();
14ce26e7 7032 b &= 3;
6e0d8677
FB
7033 switch(b) {
7034 case 0: /* loopnz */
7035 case 1: /* loopz */
1d71ddb1
RH
7036 gen_op_add_reg_im(s->aflag, R_ECX, -1);
7037 gen_op_jz_ecx(s->aflag, l3);
5bdb91b0 7038 gen_jcc1(s, (JCC_Z << 1) | (b ^ 1), l1);
6e0d8677
FB
7039 break;
7040 case 2: /* loop */
1d71ddb1
RH
7041 gen_op_add_reg_im(s->aflag, R_ECX, -1);
7042 gen_op_jnz_ecx(s->aflag, l1);
6e0d8677
FB
7043 break;
7044 default:
7045 case 3: /* jcxz */
1d71ddb1 7046 gen_op_jz_ecx(s->aflag, l1);
6e0d8677 7047 break;
14ce26e7
FB
7048 }
7049
6e0d8677 7050 gen_set_label(l3);
14ce26e7 7051 gen_jmp_im(next_eip);
8e1c85e3 7052 tcg_gen_br(l2);
6e0d8677 7053
14ce26e7
FB
7054 gen_set_label(l1);
7055 gen_jmp_im(tval);
7056 gen_set_label(l2);
7057 gen_eob(s);
7058 }
2c0262af
FB
7059 break;
7060 case 0x130: /* wrmsr */
7061 case 0x132: /* rdmsr */
7062 if (s->cpl != 0) {
7063 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7064 } else {
773cdfcc 7065 gen_update_cc_op(s);
872929aa 7066 gen_jmp_im(pc_start - s->cs_base);
0573fbfc 7067 if (b & 2) {
4a7443be 7068 gen_helper_rdmsr(cpu_env);
0573fbfc 7069 } else {
4a7443be 7070 gen_helper_wrmsr(cpu_env);
0573fbfc 7071 }
2c0262af
FB
7072 }
7073 break;
7074 case 0x131: /* rdtsc */
773cdfcc 7075 gen_update_cc_op(s);
ecada8a2 7076 gen_jmp_im(pc_start - s->cs_base);
bd79255d 7077 if (s->tb->cflags & CF_USE_ICOUNT) {
efade670 7078 gen_io_start();
bd79255d 7079 }
4a7443be 7080 gen_helper_rdtsc(cpu_env);
bd79255d 7081 if (s->tb->cflags & CF_USE_ICOUNT) {
efade670
PB
7082 gen_io_end();
7083 gen_jmp(s, s->pc - s->cs_base);
7084 }
2c0262af 7085 break;
df01e0fc 7086 case 0x133: /* rdpmc */
773cdfcc 7087 gen_update_cc_op(s);
df01e0fc 7088 gen_jmp_im(pc_start - s->cs_base);
4a7443be 7089 gen_helper_rdpmc(cpu_env);
df01e0fc 7090 break;
023fe10d 7091 case 0x134: /* sysenter */
2436b61a 7092 /* For Intel SYSENTER is valid on 64-bit */
0af10c86 7093 if (CODE64(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1)
14ce26e7 7094 goto illegal_op;
023fe10d
FB
7095 if (!s->pe) {
7096 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7097 } else {
728d803b 7098 gen_update_cc_op(s);
14ce26e7 7099 gen_jmp_im(pc_start - s->cs_base);
2999a0b2 7100 gen_helper_sysenter(cpu_env);
023fe10d
FB
7101 gen_eob(s);
7102 }
7103 break;
7104 case 0x135: /* sysexit */
2436b61a 7105 /* For Intel SYSEXIT is valid on 64-bit */
0af10c86 7106 if (CODE64(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1)
14ce26e7 7107 goto illegal_op;
023fe10d
FB
7108 if (!s->pe) {
7109 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7110 } else {
728d803b 7111 gen_update_cc_op(s);
14ce26e7 7112 gen_jmp_im(pc_start - s->cs_base);
ab4e4aec 7113 gen_helper_sysexit(cpu_env, tcg_const_i32(dflag - 1));
023fe10d
FB
7114 gen_eob(s);
7115 }
7116 break;
14ce26e7
FB
7117#ifdef TARGET_X86_64
7118 case 0x105: /* syscall */
7119 /* XXX: is it usable in real mode ? */
728d803b 7120 gen_update_cc_op(s);
14ce26e7 7121 gen_jmp_im(pc_start - s->cs_base);
2999a0b2 7122 gen_helper_syscall(cpu_env, tcg_const_i32(s->pc - pc_start));
14ce26e7
FB
7123 gen_eob(s);
7124 break;
7125 case 0x107: /* sysret */
7126 if (!s->pe) {
7127 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7128 } else {
728d803b 7129 gen_update_cc_op(s);
14ce26e7 7130 gen_jmp_im(pc_start - s->cs_base);
ab4e4aec 7131 gen_helper_sysret(cpu_env, tcg_const_i32(dflag - 1));
aba9d61e 7132 /* condition codes are modified only in long mode */
3ca51d07
RH
7133 if (s->lma) {
7134 set_cc_op(s, CC_OP_EFLAGS);
7135 }
14ce26e7
FB
7136 gen_eob(s);
7137 }
7138 break;
7139#endif
2c0262af 7140 case 0x1a2: /* cpuid */
773cdfcc 7141 gen_update_cc_op(s);
9575cb94 7142 gen_jmp_im(pc_start - s->cs_base);
4a7443be 7143 gen_helper_cpuid(cpu_env);
2c0262af
FB
7144 break;
7145 case 0xf4: /* hlt */
7146 if (s->cpl != 0) {
7147 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7148 } else {
773cdfcc 7149 gen_update_cc_op(s);
94451178 7150 gen_jmp_im(pc_start - s->cs_base);
4a7443be 7151 gen_helper_hlt(cpu_env, tcg_const_i32(s->pc - pc_start));
5779406a 7152 s->is_jmp = DISAS_TB_JUMP;
2c0262af
FB
7153 }
7154 break;
7155 case 0x100:
0af10c86 7156 modrm = cpu_ldub_code(env, s->pc++);
2c0262af
FB
7157 mod = (modrm >> 6) & 3;
7158 op = (modrm >> 3) & 7;
7159 switch(op) {
7160 case 0: /* sldt */
f115e911
FB
7161 if (!s->pe || s->vm86)
7162 goto illegal_op;
872929aa 7163 gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_READ);
651ba608 7164 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,ldt.selector));
ab4e4aec 7165 ot = mod == 3 ? dflag : MO_16;
0af10c86 7166 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
2c0262af
FB
7167 break;
7168 case 2: /* lldt */
f115e911
FB
7169 if (!s->pe || s->vm86)
7170 goto illegal_op;
2c0262af
FB
7171 if (s->cpl != 0) {
7172 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7173 } else {
872929aa 7174 gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_WRITE);
4ba9938c 7175 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
14ce26e7 7176 gen_jmp_im(pc_start - s->cs_base);
b6abf97d 7177 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
2999a0b2 7178 gen_helper_lldt(cpu_env, cpu_tmp2_i32);
2c0262af
FB
7179 }
7180 break;
7181 case 1: /* str */
f115e911
FB
7182 if (!s->pe || s->vm86)
7183 goto illegal_op;
872929aa 7184 gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_READ);
651ba608 7185 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,tr.selector));
ab4e4aec 7186 ot = mod == 3 ? dflag : MO_16;
0af10c86 7187 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
2c0262af
FB
7188 break;
7189 case 3: /* ltr */
f115e911
FB
7190 if (!s->pe || s->vm86)
7191 goto illegal_op;
2c0262af
FB
7192 if (s->cpl != 0) {
7193 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7194 } else {
872929aa 7195 gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_WRITE);
4ba9938c 7196 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
14ce26e7 7197 gen_jmp_im(pc_start - s->cs_base);
b6abf97d 7198 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
2999a0b2 7199 gen_helper_ltr(cpu_env, cpu_tmp2_i32);
2c0262af
FB
7200 }
7201 break;
7202 case 4: /* verr */
7203 case 5: /* verw */
f115e911
FB
7204 if (!s->pe || s->vm86)
7205 goto illegal_op;
4ba9938c 7206 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
773cdfcc 7207 gen_update_cc_op(s);
2999a0b2
BS
7208 if (op == 4) {
7209 gen_helper_verr(cpu_env, cpu_T[0]);
7210 } else {
7211 gen_helper_verw(cpu_env, cpu_T[0]);
7212 }
3ca51d07 7213 set_cc_op(s, CC_OP_EFLAGS);
f115e911 7214 break;
2c0262af
FB
7215 default:
7216 goto illegal_op;
7217 }
7218 break;
7219 case 0x101:
0af10c86 7220 modrm = cpu_ldub_code(env, s->pc++);
2c0262af
FB
7221 mod = (modrm >> 6) & 3;
7222 op = (modrm >> 3) & 7;
3d7374c5 7223 rm = modrm & 7;
2c0262af
FB
7224 switch(op) {
7225 case 0: /* sgdt */
2c0262af
FB
7226 if (mod == 3)
7227 goto illegal_op;
872929aa 7228 gen_svm_check_intercept(s, pc_start, SVM_EXIT_GDTR_READ);
4eeb3939 7229 gen_lea_modrm(env, s, modrm);
651ba608 7230 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, gdt.limit));
fd8ca9f6 7231 gen_op_st_v(s, MO_16, cpu_T[0], cpu_A0);
aba9d61e 7232 gen_add_A0_im(s, 2);
651ba608 7233 tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, gdt.base));
ab4e4aec 7234 if (dflag == MO_16) {
f0706f0c
RH
7235 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xffffff);
7236 }
fd8ca9f6 7237 gen_op_st_v(s, CODE64(s) + MO_32, cpu_T[0], cpu_A0);
2c0262af 7238 break;
3d7374c5
FB
7239 case 1:
7240 if (mod == 3) {
7241 switch (rm) {
7242 case 0: /* monitor */
7243 if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) ||
7244 s->cpl != 0)
7245 goto illegal_op;
773cdfcc 7246 gen_update_cc_op(s);
3d7374c5 7247 gen_jmp_im(pc_start - s->cs_base);
1d71ddb1
RH
7248 tcg_gen_mov_tl(cpu_A0, cpu_regs[R_EAX]);
7249 gen_extu(s->aflag, cpu_A0);
3d7374c5 7250 gen_add_A0_ds_seg(s);
4a7443be 7251 gen_helper_monitor(cpu_env, cpu_A0);
3d7374c5
FB
7252 break;
7253 case 1: /* mwait */
7254 if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) ||
7255 s->cpl != 0)
7256 goto illegal_op;
728d803b 7257 gen_update_cc_op(s);
94451178 7258 gen_jmp_im(pc_start - s->cs_base);
4a7443be 7259 gen_helper_mwait(cpu_env, tcg_const_i32(s->pc - pc_start));
3d7374c5
FB
7260 gen_eob(s);
7261 break;
a9321a4d
PA
7262 case 2: /* clac */
7263 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_SMAP) ||
7264 s->cpl != 0) {
7265 goto illegal_op;
7266 }
7267 gen_helper_clac(cpu_env);
7268 gen_jmp_im(s->pc - s->cs_base);
7269 gen_eob(s);
7270 break;
7271 case 3: /* stac */
7272 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_SMAP) ||
7273 s->cpl != 0) {
7274 goto illegal_op;
7275 }
7276 gen_helper_stac(cpu_env);
7277 gen_jmp_im(s->pc - s->cs_base);
7278 gen_eob(s);
7279 break;
3d7374c5
FB
7280 default:
7281 goto illegal_op;
7282 }
7283 } else { /* sidt */
872929aa 7284 gen_svm_check_intercept(s, pc_start, SVM_EXIT_IDTR_READ);
4eeb3939 7285 gen_lea_modrm(env, s, modrm);
651ba608 7286 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, idt.limit));
fd8ca9f6 7287 gen_op_st_v(s, MO_16, cpu_T[0], cpu_A0);
3d7374c5 7288 gen_add_A0_im(s, 2);
651ba608 7289 tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, idt.base));
ab4e4aec 7290 if (dflag == MO_16) {
f0706f0c
RH
7291 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xffffff);
7292 }
fd8ca9f6 7293 gen_op_st_v(s, CODE64(s) + MO_32, cpu_T[0], cpu_A0);
3d7374c5
FB
7294 }
7295 break;
2c0262af
FB
7296 case 2: /* lgdt */
7297 case 3: /* lidt */
0573fbfc 7298 if (mod == 3) {
773cdfcc 7299 gen_update_cc_op(s);
872929aa 7300 gen_jmp_im(pc_start - s->cs_base);
0573fbfc
TS
7301 switch(rm) {
7302 case 0: /* VMRUN */
872929aa
FB
7303 if (!(s->flags & HF_SVME_MASK) || !s->pe)
7304 goto illegal_op;
7305 if (s->cpl != 0) {
7306 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
0573fbfc 7307 break;
872929aa 7308 } else {
1d71ddb1 7309 gen_helper_vmrun(cpu_env, tcg_const_i32(s->aflag - 1),
a7812ae4 7310 tcg_const_i32(s->pc - pc_start));
db620f46 7311 tcg_gen_exit_tb(0);
5779406a 7312 s->is_jmp = DISAS_TB_JUMP;
872929aa 7313 }
0573fbfc
TS
7314 break;
7315 case 1: /* VMMCALL */
872929aa
FB
7316 if (!(s->flags & HF_SVME_MASK))
7317 goto illegal_op;
052e80d5 7318 gen_helper_vmmcall(cpu_env);
0573fbfc
TS
7319 break;
7320 case 2: /* VMLOAD */
872929aa
FB
7321 if (!(s->flags & HF_SVME_MASK) || !s->pe)
7322 goto illegal_op;
7323 if (s->cpl != 0) {
7324 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7325 break;
7326 } else {
1d71ddb1 7327 gen_helper_vmload(cpu_env, tcg_const_i32(s->aflag - 1));
872929aa 7328 }
0573fbfc
TS
7329 break;
7330 case 3: /* VMSAVE */
872929aa
FB
7331 if (!(s->flags & HF_SVME_MASK) || !s->pe)
7332 goto illegal_op;
7333 if (s->cpl != 0) {
7334 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7335 break;
7336 } else {
1d71ddb1 7337 gen_helper_vmsave(cpu_env, tcg_const_i32(s->aflag - 1));
872929aa 7338 }
0573fbfc
TS
7339 break;
7340 case 4: /* STGI */
872929aa
FB
7341 if ((!(s->flags & HF_SVME_MASK) &&
7342 !(s->cpuid_ext3_features & CPUID_EXT3_SKINIT)) ||
7343 !s->pe)
7344 goto illegal_op;
7345 if (s->cpl != 0) {
7346 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7347 break;
7348 } else {
052e80d5 7349 gen_helper_stgi(cpu_env);
872929aa 7350 }
0573fbfc
TS
7351 break;
7352 case 5: /* CLGI */
872929aa
FB
7353 if (!(s->flags & HF_SVME_MASK) || !s->pe)
7354 goto illegal_op;
7355 if (s->cpl != 0) {
7356 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7357 break;
7358 } else {
052e80d5 7359 gen_helper_clgi(cpu_env);
872929aa 7360 }
0573fbfc
TS
7361 break;
7362 case 6: /* SKINIT */
872929aa
FB
7363 if ((!(s->flags & HF_SVME_MASK) &&
7364 !(s->cpuid_ext3_features & CPUID_EXT3_SKINIT)) ||
7365 !s->pe)
7366 goto illegal_op;
052e80d5 7367 gen_helper_skinit(cpu_env);
0573fbfc
TS
7368 break;
7369 case 7: /* INVLPGA */
872929aa
FB
7370 if (!(s->flags & HF_SVME_MASK) || !s->pe)
7371 goto illegal_op;
7372 if (s->cpl != 0) {
7373 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7374 break;
7375 } else {
1d71ddb1
RH
7376 gen_helper_invlpga(cpu_env,
7377 tcg_const_i32(s->aflag - 1));
872929aa 7378 }
0573fbfc
TS
7379 break;
7380 default:
7381 goto illegal_op;
7382 }
7383 } else if (s->cpl != 0) {
2c0262af
FB
7384 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7385 } else {
872929aa
FB
7386 gen_svm_check_intercept(s, pc_start,
7387 op==2 ? SVM_EXIT_GDTR_WRITE : SVM_EXIT_IDTR_WRITE);
4eeb3939 7388 gen_lea_modrm(env, s, modrm);
0f712e10 7389 gen_op_ld_v(s, MO_16, cpu_T[1], cpu_A0);
aba9d61e 7390 gen_add_A0_im(s, 2);
909be183 7391 gen_op_ld_v(s, CODE64(s) + MO_32, cpu_T[0], cpu_A0);
ab4e4aec 7392 if (dflag == MO_16) {
f0706f0c
RH
7393 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xffffff);
7394 }
2c0262af 7395 if (op == 2) {
651ba608
FB
7396 tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,gdt.base));
7397 tcg_gen_st32_tl(cpu_T[1], cpu_env, offsetof(CPUX86State,gdt.limit));
2c0262af 7398 } else {
651ba608
FB
7399 tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,idt.base));
7400 tcg_gen_st32_tl(cpu_T[1], cpu_env, offsetof(CPUX86State,idt.limit));
2c0262af
FB
7401 }
7402 }
7403 break;
7404 case 4: /* smsw */
872929aa 7405 gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_CR0);
e2542fe2 7406#if defined TARGET_X86_64 && defined HOST_WORDS_BIGENDIAN
f60d2728 7407 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,cr[0]) + 4);
7408#else
651ba608 7409 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,cr[0]));
f60d2728 7410#endif
4ba9938c 7411 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 1);
2c0262af
FB
7412 break;
7413 case 6: /* lmsw */
7414 if (s->cpl != 0) {
7415 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7416 } else {
872929aa 7417 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0);
4ba9938c 7418 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
4a7443be 7419 gen_helper_lmsw(cpu_env, cpu_T[0]);
14ce26e7 7420 gen_jmp_im(s->pc - s->cs_base);
d71b9a8b 7421 gen_eob(s);
2c0262af
FB
7422 }
7423 break;
1b050077
AP
7424 case 7:
7425 if (mod != 3) { /* invlpg */
7426 if (s->cpl != 0) {
7427 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7428 } else {
773cdfcc 7429 gen_update_cc_op(s);
1b050077 7430 gen_jmp_im(pc_start - s->cs_base);
4eeb3939 7431 gen_lea_modrm(env, s, modrm);
4a7443be 7432 gen_helper_invlpg(cpu_env, cpu_A0);
1b050077
AP
7433 gen_jmp_im(s->pc - s->cs_base);
7434 gen_eob(s);
7435 }
2c0262af 7436 } else {
1b050077
AP
7437 switch (rm) {
7438 case 0: /* swapgs */
14ce26e7 7439#ifdef TARGET_X86_64
1b050077
AP
7440 if (CODE64(s)) {
7441 if (s->cpl != 0) {
7442 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7443 } else {
7444 tcg_gen_ld_tl(cpu_T[0], cpu_env,
7445 offsetof(CPUX86State,segs[R_GS].base));
7446 tcg_gen_ld_tl(cpu_T[1], cpu_env,
7447 offsetof(CPUX86State,kernelgsbase));
7448 tcg_gen_st_tl(cpu_T[1], cpu_env,
7449 offsetof(CPUX86State,segs[R_GS].base));
7450 tcg_gen_st_tl(cpu_T[0], cpu_env,
7451 offsetof(CPUX86State,kernelgsbase));
7452 }
5fafdf24 7453 } else
14ce26e7
FB
7454#endif
7455 {
7456 goto illegal_op;
7457 }
1b050077
AP
7458 break;
7459 case 1: /* rdtscp */
7460 if (!(s->cpuid_ext2_features & CPUID_EXT2_RDTSCP))
7461 goto illegal_op;
773cdfcc 7462 gen_update_cc_op(s);
9575cb94 7463 gen_jmp_im(pc_start - s->cs_base);
bd79255d 7464 if (s->tb->cflags & CF_USE_ICOUNT) {
1b050077 7465 gen_io_start();
bd79255d 7466 }
4a7443be 7467 gen_helper_rdtscp(cpu_env);
bd79255d 7468 if (s->tb->cflags & CF_USE_ICOUNT) {
1b050077
AP
7469 gen_io_end();
7470 gen_jmp(s, s->pc - s->cs_base);
7471 }
7472 break;
7473 default:
7474 goto illegal_op;
14ce26e7 7475 }
2c0262af
FB
7476 }
7477 break;
7478 default:
7479 goto illegal_op;
7480 }
7481 break;
3415a4dd
FB
7482 case 0x108: /* invd */
7483 case 0x109: /* wbinvd */
7484 if (s->cpl != 0) {
7485 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7486 } else {
872929aa 7487 gen_svm_check_intercept(s, pc_start, (b & 2) ? SVM_EXIT_INVD : SVM_EXIT_WBINVD);
3415a4dd
FB
7488 /* nothing to do */
7489 }
7490 break;
14ce26e7
FB
7491 case 0x63: /* arpl or movslS (x86_64) */
7492#ifdef TARGET_X86_64
7493 if (CODE64(s)) {
7494 int d_ot;
7495 /* d_ot is the size of destination */
ab4e4aec 7496 d_ot = dflag;
14ce26e7 7497
0af10c86 7498 modrm = cpu_ldub_code(env, s->pc++);
14ce26e7
FB
7499 reg = ((modrm >> 3) & 7) | rex_r;
7500 mod = (modrm >> 6) & 3;
7501 rm = (modrm & 7) | REX_B(s);
3b46e624 7502
14ce26e7 7503 if (mod == 3) {
c56baccf 7504 gen_op_mov_v_reg(MO_32, cpu_T[0], rm);
14ce26e7 7505 /* sign extend */
4ba9938c 7506 if (d_ot == MO_64) {
e108dd01 7507 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
4ba9938c 7508 }
480a762d 7509 gen_op_mov_reg_v(d_ot, reg, cpu_T[0]);
14ce26e7 7510 } else {
4eeb3939 7511 gen_lea_modrm(env, s, modrm);
4b1fe067 7512 gen_op_ld_v(s, MO_32 | MO_SIGN, cpu_T[0], cpu_A0);
480a762d 7513 gen_op_mov_reg_v(d_ot, reg, cpu_T[0]);
14ce26e7 7514 }
5fafdf24 7515 } else
14ce26e7
FB
7516#endif
7517 {
3bd7da9e 7518 int label1;
49d9fdcc 7519 TCGv t0, t1, t2, a0;
1e4840bf 7520
14ce26e7
FB
7521 if (!s->pe || s->vm86)
7522 goto illegal_op;
a7812ae4
PB
7523 t0 = tcg_temp_local_new();
7524 t1 = tcg_temp_local_new();
7525 t2 = tcg_temp_local_new();
4ba9938c 7526 ot = MO_16;
0af10c86 7527 modrm = cpu_ldub_code(env, s->pc++);
14ce26e7
FB
7528 reg = (modrm >> 3) & 7;
7529 mod = (modrm >> 6) & 3;
7530 rm = modrm & 7;
7531 if (mod != 3) {
4eeb3939 7532 gen_lea_modrm(env, s, modrm);
323d1876 7533 gen_op_ld_v(s, ot, t0, cpu_A0);
49d9fdcc
LD
7534 a0 = tcg_temp_local_new();
7535 tcg_gen_mov_tl(a0, cpu_A0);
14ce26e7 7536 } else {
1e4840bf 7537 gen_op_mov_v_reg(ot, t0, rm);
49d9fdcc 7538 TCGV_UNUSED(a0);
14ce26e7 7539 }
1e4840bf
FB
7540 gen_op_mov_v_reg(ot, t1, reg);
7541 tcg_gen_andi_tl(cpu_tmp0, t0, 3);
7542 tcg_gen_andi_tl(t1, t1, 3);
7543 tcg_gen_movi_tl(t2, 0);
3bd7da9e 7544 label1 = gen_new_label();
1e4840bf
FB
7545 tcg_gen_brcond_tl(TCG_COND_GE, cpu_tmp0, t1, label1);
7546 tcg_gen_andi_tl(t0, t0, ~3);
7547 tcg_gen_or_tl(t0, t0, t1);
7548 tcg_gen_movi_tl(t2, CC_Z);
3bd7da9e 7549 gen_set_label(label1);
14ce26e7 7550 if (mod != 3) {
323d1876 7551 gen_op_st_v(s, ot, t0, a0);
49d9fdcc
LD
7552 tcg_temp_free(a0);
7553 } else {
1e4840bf 7554 gen_op_mov_reg_v(ot, rm, t0);
14ce26e7 7555 }
d229edce 7556 gen_compute_eflags(s);
3bd7da9e 7557 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~CC_Z);
1e4840bf 7558 tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, t2);
1e4840bf
FB
7559 tcg_temp_free(t0);
7560 tcg_temp_free(t1);
7561 tcg_temp_free(t2);
f115e911 7562 }
f115e911 7563 break;
2c0262af
FB
7564 case 0x102: /* lar */
7565 case 0x103: /* lsl */
cec6843e
FB
7566 {
7567 int label1;
1e4840bf 7568 TCGv t0;
cec6843e
FB
7569 if (!s->pe || s->vm86)
7570 goto illegal_op;
ab4e4aec 7571 ot = dflag != MO_16 ? MO_32 : MO_16;
0af10c86 7572 modrm = cpu_ldub_code(env, s->pc++);
cec6843e 7573 reg = ((modrm >> 3) & 7) | rex_r;
4ba9938c 7574 gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
a7812ae4 7575 t0 = tcg_temp_local_new();
773cdfcc 7576 gen_update_cc_op(s);
2999a0b2
BS
7577 if (b == 0x102) {
7578 gen_helper_lar(t0, cpu_env, cpu_T[0]);
7579 } else {
7580 gen_helper_lsl(t0, cpu_env, cpu_T[0]);
7581 }
cec6843e
FB
7582 tcg_gen_andi_tl(cpu_tmp0, cpu_cc_src, CC_Z);
7583 label1 = gen_new_label();
cb63669a 7584 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_tmp0, 0, label1);
1e4840bf 7585 gen_op_mov_reg_v(ot, reg, t0);
cec6843e 7586 gen_set_label(label1);
3ca51d07 7587 set_cc_op(s, CC_OP_EFLAGS);
1e4840bf 7588 tcg_temp_free(t0);
cec6843e 7589 }
2c0262af
FB
7590 break;
7591 case 0x118:
0af10c86 7592 modrm = cpu_ldub_code(env, s->pc++);
2c0262af
FB
7593 mod = (modrm >> 6) & 3;
7594 op = (modrm >> 3) & 7;
7595 switch(op) {
7596 case 0: /* prefetchnta */
7597 case 1: /* prefetchnt0 */
7598 case 2: /* prefetchnt0 */
7599 case 3: /* prefetchnt0 */
7600 if (mod == 3)
7601 goto illegal_op;
4eeb3939 7602 gen_lea_modrm(env, s, modrm);
2c0262af
FB
7603 /* nothing more to do */
7604 break;
e17a36ce 7605 default: /* nop (multi byte) */
0af10c86 7606 gen_nop_modrm(env, s, modrm);
e17a36ce 7607 break;
2c0262af
FB
7608 }
7609 break;
e17a36ce 7610 case 0x119 ... 0x11f: /* nop (multi byte) */
0af10c86
BS
7611 modrm = cpu_ldub_code(env, s->pc++);
7612 gen_nop_modrm(env, s, modrm);
e17a36ce 7613 break;
2c0262af
FB
7614 case 0x120: /* mov reg, crN */
7615 case 0x122: /* mov crN, reg */
7616 if (s->cpl != 0) {
7617 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7618 } else {
0af10c86 7619 modrm = cpu_ldub_code(env, s->pc++);
5c73b757
MO
7620 /* Ignore the mod bits (assume (modrm&0xc0)==0xc0).
7621 * AMD documentation (24594.pdf) and testing of
7622 * intel 386 and 486 processors all show that the mod bits
7623 * are assumed to be 1's, regardless of actual values.
7624 */
14ce26e7
FB
7625 rm = (modrm & 7) | REX_B(s);
7626 reg = ((modrm >> 3) & 7) | rex_r;
7627 if (CODE64(s))
4ba9938c 7628 ot = MO_64;
14ce26e7 7629 else
4ba9938c 7630 ot = MO_32;
ccd59d09
AP
7631 if ((prefixes & PREFIX_LOCK) && (reg == 0) &&
7632 (s->cpuid_ext3_features & CPUID_EXT3_CR8LEG)) {
7633 reg = 8;
7634 }
2c0262af
FB
7635 switch(reg) {
7636 case 0:
7637 case 2:
7638 case 3:
7639 case 4:
9230e66e 7640 case 8:
773cdfcc 7641 gen_update_cc_op(s);
872929aa 7642 gen_jmp_im(pc_start - s->cs_base);
2c0262af 7643 if (b & 2) {
c56baccf 7644 gen_op_mov_v_reg(ot, cpu_T[0], rm);
4a7443be
BS
7645 gen_helper_write_crN(cpu_env, tcg_const_i32(reg),
7646 cpu_T[0]);
14ce26e7 7647 gen_jmp_im(s->pc - s->cs_base);
2c0262af
FB
7648 gen_eob(s);
7649 } else {
4a7443be 7650 gen_helper_read_crN(cpu_T[0], cpu_env, tcg_const_i32(reg));
480a762d 7651 gen_op_mov_reg_v(ot, rm, cpu_T[0]);
2c0262af
FB
7652 }
7653 break;
7654 default:
7655 goto illegal_op;
7656 }
7657 }
7658 break;
7659 case 0x121: /* mov reg, drN */
7660 case 0x123: /* mov drN, reg */
7661 if (s->cpl != 0) {
7662 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7663 } else {
0af10c86 7664 modrm = cpu_ldub_code(env, s->pc++);
5c73b757
MO
7665 /* Ignore the mod bits (assume (modrm&0xc0)==0xc0).
7666 * AMD documentation (24594.pdf) and testing of
7667 * intel 386 and 486 processors all show that the mod bits
7668 * are assumed to be 1's, regardless of actual values.
7669 */
14ce26e7
FB
7670 rm = (modrm & 7) | REX_B(s);
7671 reg = ((modrm >> 3) & 7) | rex_r;
7672 if (CODE64(s))
4ba9938c 7673 ot = MO_64;
14ce26e7 7674 else
4ba9938c 7675 ot = MO_32;
2c0262af 7676 /* XXX: do it dynamically with CR4.DE bit */
14ce26e7 7677 if (reg == 4 || reg == 5 || reg >= 8)
2c0262af
FB
7678 goto illegal_op;
7679 if (b & 2) {
0573fbfc 7680 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_DR0 + reg);
c56baccf 7681 gen_op_mov_v_reg(ot, cpu_T[0], rm);
4a7443be 7682 gen_helper_movl_drN_T0(cpu_env, tcg_const_i32(reg), cpu_T[0]);
14ce26e7 7683 gen_jmp_im(s->pc - s->cs_base);
2c0262af
FB
7684 gen_eob(s);
7685 } else {
0573fbfc 7686 gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_DR0 + reg);
651ba608 7687 tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,dr[reg]));
480a762d 7688 gen_op_mov_reg_v(ot, rm, cpu_T[0]);
2c0262af
FB
7689 }
7690 }
7691 break;
7692 case 0x106: /* clts */
7693 if (s->cpl != 0) {
7694 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7695 } else {
0573fbfc 7696 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0);
f0967a1a 7697 gen_helper_clts(cpu_env);
7eee2a50 7698 /* abort block because static cpu state changed */
14ce26e7 7699 gen_jmp_im(s->pc - s->cs_base);
7eee2a50 7700 gen_eob(s);
2c0262af
FB
7701 }
7702 break;
222a3336 7703 /* MMX/3DNow!/SSE/SSE2/SSE3/SSSE3/SSE4 support */
664e0f19
FB
7704 case 0x1c3: /* MOVNTI reg, mem */
7705 if (!(s->cpuid_features & CPUID_SSE2))
14ce26e7 7706 goto illegal_op;
ab4e4aec 7707 ot = mo_64_32(dflag);
0af10c86 7708 modrm = cpu_ldub_code(env, s->pc++);
664e0f19
FB
7709 mod = (modrm >> 6) & 3;
7710 if (mod == 3)
7711 goto illegal_op;
7712 reg = ((modrm >> 3) & 7) | rex_r;
7713 /* generate a generic store */
0af10c86 7714 gen_ldst_modrm(env, s, modrm, ot, reg, 1);
14ce26e7 7715 break;
664e0f19 7716 case 0x1ae:
0af10c86 7717 modrm = cpu_ldub_code(env, s->pc++);
664e0f19
FB
7718 mod = (modrm >> 6) & 3;
7719 op = (modrm >> 3) & 7;
7720 switch(op) {
7721 case 0: /* fxsave */
5fafdf24 7722 if (mod == 3 || !(s->cpuid_features & CPUID_FXSR) ||
09d85fb8 7723 (s->prefix & PREFIX_LOCK))
14ce26e7 7724 goto illegal_op;
09d85fb8 7725 if ((s->flags & HF_EM_MASK) || (s->flags & HF_TS_MASK)) {
0fd14b72
FB
7726 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
7727 break;
7728 }
4eeb3939 7729 gen_lea_modrm(env, s, modrm);
773cdfcc 7730 gen_update_cc_op(s);
19e6c4b8 7731 gen_jmp_im(pc_start - s->cs_base);
ab4e4aec 7732 gen_helper_fxsave(cpu_env, cpu_A0, tcg_const_i32(dflag == MO_64));
664e0f19
FB
7733 break;
7734 case 1: /* fxrstor */
5fafdf24 7735 if (mod == 3 || !(s->cpuid_features & CPUID_FXSR) ||
09d85fb8 7736 (s->prefix & PREFIX_LOCK))
14ce26e7 7737 goto illegal_op;
09d85fb8 7738 if ((s->flags & HF_EM_MASK) || (s->flags & HF_TS_MASK)) {
0fd14b72
FB
7739 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
7740 break;
7741 }
4eeb3939 7742 gen_lea_modrm(env, s, modrm);
773cdfcc 7743 gen_update_cc_op(s);
19e6c4b8 7744 gen_jmp_im(pc_start - s->cs_base);
ab4e4aec 7745 gen_helper_fxrstor(cpu_env, cpu_A0, tcg_const_i32(dflag == MO_64));
664e0f19
FB
7746 break;
7747 case 2: /* ldmxcsr */
7748 case 3: /* stmxcsr */
7749 if (s->flags & HF_TS_MASK) {
7750 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
7751 break;
14ce26e7 7752 }
664e0f19
FB
7753 if ((s->flags & HF_EM_MASK) || !(s->flags & HF_OSFXSR_MASK) ||
7754 mod == 3)
14ce26e7 7755 goto illegal_op;
4eeb3939 7756 gen_lea_modrm(env, s, modrm);
664e0f19 7757 if (op == 2) {
80b02013
RH
7758 tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
7759 s->mem_index, MO_LEUL);
d3eb5eae 7760 gen_helper_ldmxcsr(cpu_env, cpu_tmp2_i32);
14ce26e7 7761 } else {
651ba608 7762 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, mxcsr));
fd8ca9f6 7763 gen_op_st_v(s, MO_32, cpu_T[0], cpu_A0);
14ce26e7 7764 }
664e0f19
FB
7765 break;
7766 case 5: /* lfence */
7767 case 6: /* mfence */
8001c294 7768 if ((modrm & 0xc7) != 0xc0 || !(s->cpuid_features & CPUID_SSE2))
664e0f19
FB
7769 goto illegal_op;
7770 break;
8f091a59
FB
7771 case 7: /* sfence / clflush */
7772 if ((modrm & 0xc7) == 0xc0) {
7773 /* sfence */
a35f3ec7 7774 /* XXX: also check for cpuid_ext2_features & CPUID_EXT2_EMMX */
8f091a59
FB
7775 if (!(s->cpuid_features & CPUID_SSE))
7776 goto illegal_op;
7777 } else {
7778 /* clflush */
7779 if (!(s->cpuid_features & CPUID_CLFLUSH))
7780 goto illegal_op;
4eeb3939 7781 gen_lea_modrm(env, s, modrm);
8f091a59
FB
7782 }
7783 break;
664e0f19 7784 default:
14ce26e7
FB
7785 goto illegal_op;
7786 }
7787 break;
a35f3ec7 7788 case 0x10d: /* 3DNow! prefetch(w) */
0af10c86 7789 modrm = cpu_ldub_code(env, s->pc++);
a35f3ec7
AJ
7790 mod = (modrm >> 6) & 3;
7791 if (mod == 3)
7792 goto illegal_op;
4eeb3939 7793 gen_lea_modrm(env, s, modrm);
8f091a59
FB
7794 /* ignore for now */
7795 break;
3b21e03e 7796 case 0x1aa: /* rsm */
872929aa 7797 gen_svm_check_intercept(s, pc_start, SVM_EXIT_RSM);
3b21e03e
FB
7798 if (!(s->flags & HF_SMM_MASK))
7799 goto illegal_op;
728d803b 7800 gen_update_cc_op(s);
3b21e03e 7801 gen_jmp_im(s->pc - s->cs_base);
608badfc 7802 gen_helper_rsm(cpu_env);
3b21e03e
FB
7803 gen_eob(s);
7804 break;
222a3336
AZ
7805 case 0x1b8: /* SSE4.2 popcnt */
7806 if ((prefixes & (PREFIX_REPZ | PREFIX_LOCK | PREFIX_REPNZ)) !=
7807 PREFIX_REPZ)
7808 goto illegal_op;
7809 if (!(s->cpuid_ext_features & CPUID_EXT_POPCNT))
7810 goto illegal_op;
7811
0af10c86 7812 modrm = cpu_ldub_code(env, s->pc++);
8b4a3df8 7813 reg = ((modrm >> 3) & 7) | rex_r;
222a3336 7814
ab4e4aec 7815 if (s->prefix & PREFIX_DATA) {
4ba9938c 7816 ot = MO_16;
ab4e4aec
RH
7817 } else {
7818 ot = mo_64_32(dflag);
7819 }
222a3336 7820
0af10c86 7821 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
d3eb5eae 7822 gen_helper_popcnt(cpu_T[0], cpu_env, cpu_T[0], tcg_const_i32(ot));
480a762d 7823 gen_op_mov_reg_v(ot, reg, cpu_T[0]);
fdb0d09d 7824
3ca51d07 7825 set_cc_op(s, CC_OP_EFLAGS);
222a3336 7826 break;
a35f3ec7
AJ
7827 case 0x10e ... 0x10f:
7828 /* 3DNow! instructions, ignore prefixes */
7829 s->prefix &= ~(PREFIX_REPZ | PREFIX_REPNZ | PREFIX_DATA);
664e0f19
FB
7830 case 0x110 ... 0x117:
7831 case 0x128 ... 0x12f:
4242b1bd 7832 case 0x138 ... 0x13a:
d9f4bb27 7833 case 0x150 ... 0x179:
664e0f19
FB
7834 case 0x17c ... 0x17f:
7835 case 0x1c2:
7836 case 0x1c4 ... 0x1c6:
7837 case 0x1d0 ... 0x1fe:
0af10c86 7838 gen_sse(env, s, b, pc_start, rex_r);
664e0f19 7839 break;
2c0262af
FB
7840 default:
7841 goto illegal_op;
7842 }
7843 /* lock generation */
7844 if (s->prefix & PREFIX_LOCK)
a7812ae4 7845 gen_helper_unlock();
2c0262af
FB
7846 return s->pc;
7847 illegal_op:
ab1f142b 7848 if (s->prefix & PREFIX_LOCK)
a7812ae4 7849 gen_helper_unlock();
2c0262af
FB
7850 /* XXX: ensure that no lock was generated */
7851 gen_exception(s, EXCP06_ILLOP, pc_start - s->cs_base);
7852 return s->pc;
7853}
7854
2c0262af
FB
7855void optimize_flags_init(void)
7856{
fac0aff9
RH
7857 static const char reg_names[CPU_NB_REGS][4] = {
7858#ifdef TARGET_X86_64
7859 [R_EAX] = "rax",
7860 [R_EBX] = "rbx",
7861 [R_ECX] = "rcx",
7862 [R_EDX] = "rdx",
7863 [R_ESI] = "rsi",
7864 [R_EDI] = "rdi",
7865 [R_EBP] = "rbp",
7866 [R_ESP] = "rsp",
7867 [8] = "r8",
7868 [9] = "r9",
7869 [10] = "r10",
7870 [11] = "r11",
7871 [12] = "r12",
7872 [13] = "r13",
7873 [14] = "r14",
7874 [15] = "r15",
7875#else
7876 [R_EAX] = "eax",
7877 [R_EBX] = "ebx",
7878 [R_ECX] = "ecx",
7879 [R_EDX] = "edx",
7880 [R_ESI] = "esi",
7881 [R_EDI] = "edi",
7882 [R_EBP] = "ebp",
7883 [R_ESP] = "esp",
7884#endif
7885 };
7886 int i;
7887
a7812ae4
PB
7888 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
7889 cpu_cc_op = tcg_global_mem_new_i32(TCG_AREG0,
317ac620 7890 offsetof(CPUX86State, cc_op), "cc_op");
317ac620 7891 cpu_cc_dst = tcg_global_mem_new(TCG_AREG0, offsetof(CPUX86State, cc_dst),
a7812ae4 7892 "cc_dst");
a3251186
RH
7893 cpu_cc_src = tcg_global_mem_new(TCG_AREG0, offsetof(CPUX86State, cc_src),
7894 "cc_src");
988c3eb0
RH
7895 cpu_cc_src2 = tcg_global_mem_new(TCG_AREG0, offsetof(CPUX86State, cc_src2),
7896 "cc_src2");
437a88a5 7897
fac0aff9
RH
7898 for (i = 0; i < CPU_NB_REGS; ++i) {
7899 cpu_regs[i] = tcg_global_mem_new(TCG_AREG0,
7900 offsetof(CPUX86State, regs[i]),
7901 reg_names[i]);
7902 }
2c0262af
FB
7903}
7904
7905/* generate intermediate code in gen_opc_buf and gen_opparam_buf for
7906 basic block 'tb'. If search_pc is TRUE, also generate PC
7907 information for each intermediate instruction. */
467215c2 7908static inline void gen_intermediate_code_internal(X86CPU *cpu,
2cfc5f17 7909 TranslationBlock *tb,
467215c2 7910 bool search_pc)
2c0262af 7911{
ed2803da 7912 CPUState *cs = CPU(cpu);
467215c2 7913 CPUX86State *env = &cpu->env;
2c0262af 7914 DisasContext dc1, *dc = &dc1;
14ce26e7 7915 target_ulong pc_ptr;
2c0262af 7916 uint16_t *gen_opc_end;
a1d1bb31 7917 CPUBreakpoint *bp;
7f5b7d3e 7918 int j, lj;
c068688b 7919 uint64_t flags;
14ce26e7
FB
7920 target_ulong pc_start;
7921 target_ulong cs_base;
2e70f6ef
PB
7922 int num_insns;
7923 int max_insns;
3b46e624 7924
2c0262af 7925 /* generate intermediate code */
14ce26e7
FB
7926 pc_start = tb->pc;
7927 cs_base = tb->cs_base;
2c0262af 7928 flags = tb->flags;
3a1d9b8b 7929
4f31916f 7930 dc->pe = (flags >> HF_PE_SHIFT) & 1;
2c0262af
FB
7931 dc->code32 = (flags >> HF_CS32_SHIFT) & 1;
7932 dc->ss32 = (flags >> HF_SS32_SHIFT) & 1;
7933 dc->addseg = (flags >> HF_ADDSEG_SHIFT) & 1;
7934 dc->f_st = 0;
7935 dc->vm86 = (flags >> VM_SHIFT) & 1;
7936 dc->cpl = (flags >> HF_CPL_SHIFT) & 3;
7937 dc->iopl = (flags >> IOPL_SHIFT) & 3;
7938 dc->tf = (flags >> TF_SHIFT) & 1;
ed2803da 7939 dc->singlestep_enabled = cs->singlestep_enabled;
2c0262af 7940 dc->cc_op = CC_OP_DYNAMIC;
e207582f 7941 dc->cc_op_dirty = false;
2c0262af
FB
7942 dc->cs_base = cs_base;
7943 dc->tb = tb;
7944 dc->popl_esp_hack = 0;
7945 /* select memory access functions */
7946 dc->mem_index = 0;
7947 if (flags & HF_SOFTMMU_MASK) {
5c42a7cd 7948 dc->mem_index = cpu_mmu_index(env);
2c0262af 7949 }
0514ef2f
EH
7950 dc->cpuid_features = env->features[FEAT_1_EDX];
7951 dc->cpuid_ext_features = env->features[FEAT_1_ECX];
7952 dc->cpuid_ext2_features = env->features[FEAT_8000_0001_EDX];
7953 dc->cpuid_ext3_features = env->features[FEAT_8000_0001_ECX];
7954 dc->cpuid_7_0_ebx_features = env->features[FEAT_7_0_EBX];
14ce26e7
FB
7955#ifdef TARGET_X86_64
7956 dc->lma = (flags >> HF_LMA_SHIFT) & 1;
7957 dc->code64 = (flags >> HF_CS64_SHIFT) & 1;
7958#endif
7eee2a50 7959 dc->flags = flags;
ed2803da 7960 dc->jmp_opt = !(dc->tf || cs->singlestep_enabled ||
a2cc3b24 7961 (flags & HF_INHIBIT_IRQ_MASK)
415fa2ea 7962#ifndef CONFIG_SOFTMMU
2c0262af
FB
7963 || (flags & HF_SOFTMMU_MASK)
7964#endif
7965 );
c4d4525c
PD
7966 /* Do not optimize repz jumps at all in icount mode, because
7967 rep movsS instructions are execured with different paths
7968 in !repz_opt and repz_opt modes. The first one was used
7969 always except single step mode. And this setting
7970 disables jumps optimization and control paths become
7971 equivalent in run and single step modes.
7972 Now there will be no jump optimization for repz in
7973 record/replay modes and there will always be an
7974 additional step for ecx=0 when icount is enabled.
7975 */
bd79255d 7976 dc->repz_opt = !dc->jmp_opt && !(tb->cflags & CF_USE_ICOUNT);
4f31916f
FB
7977#if 0
7978 /* check addseg logic */
dc196a57 7979 if (!dc->addseg && (dc->vm86 || !dc->pe || !dc->code32))
4f31916f
FB
7980 printf("ERROR addseg\n");
7981#endif
7982
a7812ae4
PB
7983 cpu_T[0] = tcg_temp_new();
7984 cpu_T[1] = tcg_temp_new();
7985 cpu_A0 = tcg_temp_new();
a7812ae4
PB
7986
7987 cpu_tmp0 = tcg_temp_new();
7988 cpu_tmp1_i64 = tcg_temp_new_i64();
7989 cpu_tmp2_i32 = tcg_temp_new_i32();
7990 cpu_tmp3_i32 = tcg_temp_new_i32();
7991 cpu_tmp4 = tcg_temp_new();
a7812ae4
PB
7992 cpu_ptr0 = tcg_temp_new_ptr();
7993 cpu_ptr1 = tcg_temp_new_ptr();
a3251186 7994 cpu_cc_srcT = tcg_temp_local_new();
57fec1fe 7995
92414b31 7996 gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
2c0262af
FB
7997
7998 dc->is_jmp = DISAS_NEXT;
7999 pc_ptr = pc_start;
8000 lj = -1;
2e70f6ef
PB
8001 num_insns = 0;
8002 max_insns = tb->cflags & CF_COUNT_MASK;
8003 if (max_insns == 0)
8004 max_insns = CF_COUNT_MASK;
2c0262af 8005
cd42d5b2 8006 gen_tb_start(tb);
2c0262af 8007 for(;;) {
f0c3c505
AF
8008 if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
8009 QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
a2397807
JK
8010 if (bp->pc == pc_ptr &&
8011 !((bp->flags & BP_CPU) && (tb->flags & HF_RF_MASK))) {
2c0262af 8012 gen_debug(dc, pc_ptr - dc->cs_base);
e64e3535 8013 goto done_generating;
2c0262af
FB
8014 }
8015 }
8016 }
8017 if (search_pc) {
92414b31 8018 j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
2c0262af
FB
8019 if (lj < j) {
8020 lj++;
8021 while (lj < j)
ab1103de 8022 tcg_ctx.gen_opc_instr_start[lj++] = 0;
2c0262af 8023 }
25983cad 8024 tcg_ctx.gen_opc_pc[lj] = pc_ptr;
2c0262af 8025 gen_opc_cc_op[lj] = dc->cc_op;
ab1103de 8026 tcg_ctx.gen_opc_instr_start[lj] = 1;
c9c99c22 8027 tcg_ctx.gen_opc_icount[lj] = num_insns;
2c0262af 8028 }
2e70f6ef
PB
8029 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
8030 gen_io_start();
8031
0af10c86 8032 pc_ptr = disas_insn(env, dc, pc_ptr);
2e70f6ef 8033 num_insns++;
2c0262af
FB
8034 /* stop translation if indicated */
8035 if (dc->is_jmp)
8036 break;
8037 /* if single step mode, we generate only one instruction and
8038 generate an exception */
a2cc3b24
FB
8039 /* if irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear
8040 the flag and abort the translation to give the irqs a
8041 change to be happen */
5fafdf24 8042 if (dc->tf || dc->singlestep_enabled ||
2e70f6ef 8043 (flags & HF_INHIBIT_IRQ_MASK)) {
14ce26e7 8044 gen_jmp_im(pc_ptr - dc->cs_base);
2c0262af
FB
8045 gen_eob(dc);
8046 break;
8047 }
5b9efc39
PD
8048 /* Do not cross the boundary of the pages in icount mode,
8049 it can cause an exception. Do it only when boundary is
8050 crossed by the first instruction in the block.
8051 If current instruction already crossed the bound - it's ok,
8052 because an exception hasn't stopped this code.
8053 */
bd79255d 8054 if ((tb->cflags & CF_USE_ICOUNT)
5b9efc39
PD
8055 && ((pc_ptr & TARGET_PAGE_MASK)
8056 != ((pc_ptr + TARGET_MAX_INSN_SIZE - 1) & TARGET_PAGE_MASK)
8057 || (pc_ptr & ~TARGET_PAGE_MASK) == 0)) {
8058 gen_jmp_im(pc_ptr - dc->cs_base);
8059 gen_eob(dc);
8060 break;
8061 }
2c0262af 8062 /* if too long translation, stop generation too */
efd7f486 8063 if (tcg_ctx.gen_opc_ptr >= gen_opc_end ||
2e70f6ef
PB
8064 (pc_ptr - pc_start) >= (TARGET_PAGE_SIZE - 32) ||
8065 num_insns >= max_insns) {
14ce26e7 8066 gen_jmp_im(pc_ptr - dc->cs_base);
2c0262af
FB
8067 gen_eob(dc);
8068 break;
8069 }
1b530a6d
AJ
8070 if (singlestep) {
8071 gen_jmp_im(pc_ptr - dc->cs_base);
8072 gen_eob(dc);
8073 break;
8074 }
2c0262af 8075 }
2e70f6ef
PB
8076 if (tb->cflags & CF_LAST_IO)
8077 gen_io_end();
e64e3535 8078done_generating:
806f352d 8079 gen_tb_end(tb, num_insns);
0a7df5da 8080
2c0262af
FB
8081 /* we don't forget to fill the last values */
8082 if (search_pc) {
92414b31 8083 j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
2c0262af
FB
8084 lj++;
8085 while (lj <= j)
ab1103de 8086 tcg_ctx.gen_opc_instr_start[lj++] = 0;
2c0262af 8087 }
3b46e624 8088
2c0262af 8089#ifdef DEBUG_DISAS
8fec2b8c 8090 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
14ce26e7 8091 int disas_flags;
93fcfe39
AL
8092 qemu_log("----------------\n");
8093 qemu_log("IN: %s\n", lookup_symbol(pc_start));
14ce26e7
FB
8094#ifdef TARGET_X86_64
8095 if (dc->code64)
8096 disas_flags = 2;
8097 else
8098#endif
8099 disas_flags = !dc->code32;
f4359b9f 8100 log_target_disas(env, pc_start, pc_ptr - pc_start, disas_flags);
93fcfe39 8101 qemu_log("\n");
2c0262af
FB
8102 }
8103#endif
8104
2e70f6ef 8105 if (!search_pc) {
2c0262af 8106 tb->size = pc_ptr - pc_start;
2e70f6ef
PB
8107 tb->icount = num_insns;
8108 }
2c0262af
FB
8109}
8110
317ac620 8111void gen_intermediate_code(CPUX86State *env, TranslationBlock *tb)
2c0262af 8112{
467215c2 8113 gen_intermediate_code_internal(x86_env_get_cpu(env), tb, false);
2c0262af
FB
8114}
8115
317ac620 8116void gen_intermediate_code_pc(CPUX86State *env, TranslationBlock *tb)
2c0262af 8117{
467215c2 8118 gen_intermediate_code_internal(x86_env_get_cpu(env), tb, true);
2c0262af
FB
8119}
8120
317ac620 8121void restore_state_to_opc(CPUX86State *env, TranslationBlock *tb, int pc_pos)
d2856f1a
AJ
8122{
8123 int cc_op;
8124#ifdef DEBUG_DISAS
8fec2b8c 8125 if (qemu_loglevel_mask(CPU_LOG_TB_OP)) {
d2856f1a 8126 int i;
93fcfe39 8127 qemu_log("RESTORE:\n");
d2856f1a 8128 for(i = 0;i <= pc_pos; i++) {
ab1103de 8129 if (tcg_ctx.gen_opc_instr_start[i]) {
25983cad
EV
8130 qemu_log("0x%04x: " TARGET_FMT_lx "\n", i,
8131 tcg_ctx.gen_opc_pc[i]);
d2856f1a
AJ
8132 }
8133 }
e87b7cb0 8134 qemu_log("pc_pos=0x%x eip=" TARGET_FMT_lx " cs_base=%x\n",
25983cad 8135 pc_pos, tcg_ctx.gen_opc_pc[pc_pos] - tb->cs_base,
d2856f1a
AJ
8136 (uint32_t)tb->cs_base);
8137 }
8138#endif
25983cad 8139 env->eip = tcg_ctx.gen_opc_pc[pc_pos] - tb->cs_base;
d2856f1a
AJ
8140 cc_op = gen_opc_cc_op[pc_pos];
8141 if (cc_op != CC_OP_DYNAMIC)
8142 env->cc_op = cc_op;
8143}