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