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