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