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