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