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