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