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