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