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