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