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