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