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