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