]> git.proxmox.com Git - mirror_qemu.git/blame - target-i386/translate.c
target-i386: Implement BEXTR
[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
c7ab7565
RH
4029 case 0x0f7: /* bextr Gy, Ey, By */
4030 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_BMI1)
4031 || !(s->prefix & PREFIX_VEX)
4032 || s->vex_l != 0) {
4033 goto illegal_op;
4034 }
4035 ot = s->dflag == 2 ? OT_QUAD : OT_LONG;
4036 {
4037 TCGv bound, zero;
4038
4039 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
4040 /* Extract START, and shift the operand.
4041 Shifts larger than operand size get zeros. */
4042 tcg_gen_ext8u_tl(cpu_A0, cpu_regs[s->vex_v]);
4043 tcg_gen_shr_tl(cpu_T[0], cpu_T[0], cpu_A0);
4044
4045 bound = tcg_const_tl(ot == OT_QUAD ? 63 : 31);
4046 zero = tcg_const_tl(0);
4047 tcg_gen_movcond_tl(TCG_COND_LEU, cpu_T[0], cpu_A0, bound,
4048 cpu_T[0], zero);
4049 tcg_temp_free(zero);
4050
4051 /* Extract the LEN into a mask. Lengths larger than
4052 operand size get all ones. */
4053 tcg_gen_shri_tl(cpu_A0, cpu_regs[s->vex_v], 8);
4054 tcg_gen_ext8u_tl(cpu_A0, cpu_A0);
4055 tcg_gen_movcond_tl(TCG_COND_LEU, cpu_A0, cpu_A0, bound,
4056 cpu_A0, bound);
4057 tcg_temp_free(bound);
4058 tcg_gen_movi_tl(cpu_T[1], 1);
4059 tcg_gen_shl_tl(cpu_T[1], cpu_T[1], cpu_A0);
4060 tcg_gen_subi_tl(cpu_T[1], cpu_T[1], 1);
4061 tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
4062
4063 gen_op_mov_reg_T0(ot, reg);
4064 gen_op_update1_cc();
4065 set_cc_op(s, CC_OP_LOGICB + ot);
4066 }
4067 break;
4068
111994ee
RH
4069 default:
4070 goto illegal_op;
4071 }
222a3336 4072 break;
111994ee 4073
222a3336
AZ
4074 case 0x03a:
4075 case 0x13a:
4242b1bd 4076 b = modrm;
0af10c86 4077 modrm = cpu_ldub_code(env, s->pc++);
4242b1bd
AZ
4078 rm = modrm & 7;
4079 reg = ((modrm >> 3) & 7) | rex_r;
4080 mod = (modrm >> 6) & 3;
c045af25
AK
4081 if (b1 >= 2) {
4082 goto illegal_op;
4083 }
4242b1bd 4084
d3eb5eae
BS
4085 sse_fn_eppi = sse_op_table7[b].op[b1];
4086 if (!sse_fn_eppi) {
4242b1bd 4087 goto illegal_op;
c4baa050 4088 }
222a3336
AZ
4089 if (!(s->cpuid_ext_features & sse_op_table7[b].ext_mask))
4090 goto illegal_op;
4091
d3eb5eae 4092 if (sse_fn_eppi == SSE_SPECIAL) {
222a3336
AZ
4093 ot = (s->dflag == 2) ? OT_QUAD : OT_LONG;
4094 rm = (modrm & 7) | REX_B(s);
4095 if (mod != 3)
0af10c86 4096 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
222a3336 4097 reg = ((modrm >> 3) & 7) | rex_r;
0af10c86 4098 val = cpu_ldub_code(env, s->pc++);
222a3336
AZ
4099 switch (b) {
4100 case 0x14: /* pextrb */
4101 tcg_gen_ld8u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,
4102 xmm_regs[reg].XMM_B(val & 15)));
4103 if (mod == 3)
4104 gen_op_mov_reg_T0(ot, rm);
4105 else
4106 tcg_gen_qemu_st8(cpu_T[0], cpu_A0,
4107 (s->mem_index >> 2) - 1);
4108 break;
4109 case 0x15: /* pextrw */
4110 tcg_gen_ld16u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,
4111 xmm_regs[reg].XMM_W(val & 7)));
4112 if (mod == 3)
4113 gen_op_mov_reg_T0(ot, rm);
4114 else
4115 tcg_gen_qemu_st16(cpu_T[0], cpu_A0,
4116 (s->mem_index >> 2) - 1);
4117 break;
4118 case 0x16:
4119 if (ot == OT_LONG) { /* pextrd */
4120 tcg_gen_ld_i32(cpu_tmp2_i32, cpu_env,
4121 offsetof(CPUX86State,
4122 xmm_regs[reg].XMM_L(val & 3)));
a7812ae4 4123 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
222a3336 4124 if (mod == 3)
a7812ae4 4125 gen_op_mov_reg_v(ot, rm, cpu_T[0]);
222a3336 4126 else
a7812ae4 4127 tcg_gen_qemu_st32(cpu_T[0], cpu_A0,
222a3336
AZ
4128 (s->mem_index >> 2) - 1);
4129 } else { /* pextrq */
a7812ae4 4130#ifdef TARGET_X86_64
222a3336
AZ
4131 tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env,
4132 offsetof(CPUX86State,
4133 xmm_regs[reg].XMM_Q(val & 1)));
4134 if (mod == 3)
4135 gen_op_mov_reg_v(ot, rm, cpu_tmp1_i64);
4136 else
4137 tcg_gen_qemu_st64(cpu_tmp1_i64, cpu_A0,
4138 (s->mem_index >> 2) - 1);
a7812ae4
PB
4139#else
4140 goto illegal_op;
4141#endif
222a3336
AZ
4142 }
4143 break;
4144 case 0x17: /* extractps */
4145 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,
4146 xmm_regs[reg].XMM_L(val & 3)));
4147 if (mod == 3)
4148 gen_op_mov_reg_T0(ot, rm);
4149 else
4150 tcg_gen_qemu_st32(cpu_T[0], cpu_A0,
4151 (s->mem_index >> 2) - 1);
4152 break;
4153 case 0x20: /* pinsrb */
4154 if (mod == 3)
4155 gen_op_mov_TN_reg(OT_LONG, 0, rm);
4156 else
a7812ae4 4157 tcg_gen_qemu_ld8u(cpu_tmp0, cpu_A0,
222a3336 4158 (s->mem_index >> 2) - 1);
a7812ae4 4159 tcg_gen_st8_tl(cpu_tmp0, cpu_env, offsetof(CPUX86State,
222a3336
AZ
4160 xmm_regs[reg].XMM_B(val & 15)));
4161 break;
4162 case 0x21: /* insertps */
a7812ae4 4163 if (mod == 3) {
222a3336
AZ
4164 tcg_gen_ld_i32(cpu_tmp2_i32, cpu_env,
4165 offsetof(CPUX86State,xmm_regs[rm]
4166 .XMM_L((val >> 6) & 3)));
a7812ae4
PB
4167 } else {
4168 tcg_gen_qemu_ld32u(cpu_tmp0, cpu_A0,
222a3336 4169 (s->mem_index >> 2) - 1);
a7812ae4
PB
4170 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_tmp0);
4171 }
222a3336
AZ
4172 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env,
4173 offsetof(CPUX86State,xmm_regs[reg]
4174 .XMM_L((val >> 4) & 3)));
4175 if ((val >> 0) & 1)
4176 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4177 cpu_env, offsetof(CPUX86State,
4178 xmm_regs[reg].XMM_L(0)));
4179 if ((val >> 1) & 1)
4180 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4181 cpu_env, offsetof(CPUX86State,
4182 xmm_regs[reg].XMM_L(1)));
4183 if ((val >> 2) & 1)
4184 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4185 cpu_env, offsetof(CPUX86State,
4186 xmm_regs[reg].XMM_L(2)));
4187 if ((val >> 3) & 1)
4188 tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
4189 cpu_env, offsetof(CPUX86State,
4190 xmm_regs[reg].XMM_L(3)));
4191 break;
4192 case 0x22:
4193 if (ot == OT_LONG) { /* pinsrd */
4194 if (mod == 3)
a7812ae4 4195 gen_op_mov_v_reg(ot, cpu_tmp0, rm);
222a3336 4196 else
a7812ae4 4197 tcg_gen_qemu_ld32u(cpu_tmp0, cpu_A0,
222a3336 4198 (s->mem_index >> 2) - 1);
a7812ae4 4199 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_tmp0);
222a3336
AZ
4200 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env,
4201 offsetof(CPUX86State,
4202 xmm_regs[reg].XMM_L(val & 3)));
4203 } else { /* pinsrq */
a7812ae4 4204#ifdef TARGET_X86_64
222a3336
AZ
4205 if (mod == 3)
4206 gen_op_mov_v_reg(ot, cpu_tmp1_i64, rm);
4207 else
4208 tcg_gen_qemu_ld64(cpu_tmp1_i64, cpu_A0,
4209 (s->mem_index >> 2) - 1);
4210 tcg_gen_st_i64(cpu_tmp1_i64, cpu_env,
4211 offsetof(CPUX86State,
4212 xmm_regs[reg].XMM_Q(val & 1)));
a7812ae4
PB
4213#else
4214 goto illegal_op;
4215#endif
222a3336
AZ
4216 }
4217 break;
4218 }
4219 return;
4220 }
4242b1bd
AZ
4221
4222 if (b1) {
4223 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
4224 if (mod == 3) {
4225 op2_offset = offsetof(CPUX86State,xmm_regs[rm | REX_B(s)]);
4226 } else {
4227 op2_offset = offsetof(CPUX86State,xmm_t0);
0af10c86 4228 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
4242b1bd
AZ
4229 gen_ldo_env_A0(s->mem_index, op2_offset);
4230 }
4231 } else {
4232 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
4233 if (mod == 3) {
4234 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
4235 } else {
4236 op2_offset = offsetof(CPUX86State,mmx_t0);
0af10c86 4237 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
4242b1bd
AZ
4238 gen_ldq_env_A0(s->mem_index, op2_offset);
4239 }
4240 }
0af10c86 4241 val = cpu_ldub_code(env, s->pc++);
4242b1bd 4242
222a3336 4243 if ((b & 0xfc) == 0x60) { /* pcmpXstrX */
3ca51d07 4244 set_cc_op(s, CC_OP_EFLAGS);
222a3336
AZ
4245
4246 if (s->dflag == 2)
4247 /* The helper must use entire 64-bit gp registers */
4248 val |= 1 << 8;
4249 }
4250
4242b1bd
AZ
4251 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4252 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
d3eb5eae 4253 sse_fn_eppi(cpu_env, cpu_ptr0, cpu_ptr1, tcg_const_i32(val));
4242b1bd 4254 break;
664e0f19
FB
4255 default:
4256 goto illegal_op;
4257 }
4258 } else {
4259 /* generic MMX or SSE operation */
d1e42c5c 4260 switch(b) {
d1e42c5c
FB
4261 case 0x70: /* pshufx insn */
4262 case 0xc6: /* pshufx insn */
4263 case 0xc2: /* compare insns */
4264 s->rip_offset = 1;
4265 break;
4266 default:
4267 break;
664e0f19
FB
4268 }
4269 if (is_xmm) {
4270 op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
4271 if (mod != 3) {
0af10c86 4272 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
664e0f19 4273 op2_offset = offsetof(CPUX86State,xmm_t0);
480c1cdb 4274 if (b1 >= 2 && ((b >= 0x50 && b <= 0x5f && b != 0x5b) ||
664e0f19
FB
4275 b == 0xc2)) {
4276 /* specific case for SSE single instructions */
4277 if (b1 == 2) {
4278 /* 32 bit access */
57fec1fe 4279 gen_op_ld_T0_A0(OT_LONG + s->mem_index);
651ba608 4280 tcg_gen_st32_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,xmm_t0.XMM_L(0)));
664e0f19
FB
4281 } else {
4282 /* 64 bit access */
8686c490 4283 gen_ldq_env_A0(s->mem_index, offsetof(CPUX86State,xmm_t0.XMM_D(0)));
664e0f19
FB
4284 }
4285 } else {
8686c490 4286 gen_ldo_env_A0(s->mem_index, op2_offset);
664e0f19
FB
4287 }
4288 } else {
4289 rm = (modrm & 7) | REX_B(s);
4290 op2_offset = offsetof(CPUX86State,xmm_regs[rm]);
4291 }
4292 } else {
4293 op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
4294 if (mod != 3) {
0af10c86 4295 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
664e0f19 4296 op2_offset = offsetof(CPUX86State,mmx_t0);
8686c490 4297 gen_ldq_env_A0(s->mem_index, op2_offset);
664e0f19
FB
4298 } else {
4299 rm = (modrm & 7);
4300 op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
4301 }
4302 }
4303 switch(b) {
a35f3ec7 4304 case 0x0f: /* 3DNow! data insns */
e771edab
AJ
4305 if (!(s->cpuid_ext2_features & CPUID_EXT2_3DNOW))
4306 goto illegal_op;
0af10c86 4307 val = cpu_ldub_code(env, s->pc++);
d3eb5eae
BS
4308 sse_fn_epp = sse_op_table5[val];
4309 if (!sse_fn_epp) {
a35f3ec7 4310 goto illegal_op;
c4baa050 4311 }
5af45186
FB
4312 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4313 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
d3eb5eae 4314 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
a35f3ec7 4315 break;
664e0f19
FB
4316 case 0x70: /* pshufx insn */
4317 case 0xc6: /* pshufx insn */
0af10c86 4318 val = cpu_ldub_code(env, s->pc++);
5af45186
FB
4319 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4320 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
c4baa050 4321 /* XXX: introduce a new table? */
d3eb5eae 4322 sse_fn_ppi = (SSEFunc_0_ppi)sse_fn_epp;
c4baa050 4323 sse_fn_ppi(cpu_ptr0, cpu_ptr1, tcg_const_i32(val));
664e0f19
FB
4324 break;
4325 case 0xc2:
4326 /* compare insns */
0af10c86 4327 val = cpu_ldub_code(env, s->pc++);
664e0f19
FB
4328 if (val >= 8)
4329 goto illegal_op;
d3eb5eae 4330 sse_fn_epp = sse_op_table4[val][b1];
c4baa050 4331
5af45186
FB
4332 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4333 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
d3eb5eae 4334 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
664e0f19 4335 break;
b8b6a50b
FB
4336 case 0xf7:
4337 /* maskmov : we must prepare A0 */
4338 if (mod != 3)
4339 goto illegal_op;
4340#ifdef TARGET_X86_64
4341 if (s->aflag == 2) {
4342 gen_op_movq_A0_reg(R_EDI);
4343 } else
4344#endif
4345 {
4346 gen_op_movl_A0_reg(R_EDI);
4347 if (s->aflag == 0)
4348 gen_op_andl_A0_ffff();
4349 }
4350 gen_add_A0_ds_seg(s);
4351
4352 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4353 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
c4baa050 4354 /* XXX: introduce a new table? */
d3eb5eae
BS
4355 sse_fn_eppt = (SSEFunc_0_eppt)sse_fn_epp;
4356 sse_fn_eppt(cpu_env, cpu_ptr0, cpu_ptr1, cpu_A0);
b8b6a50b 4357 break;
664e0f19 4358 default:
5af45186
FB
4359 tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
4360 tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
d3eb5eae 4361 sse_fn_epp(cpu_env, cpu_ptr0, cpu_ptr1);
664e0f19
FB
4362 break;
4363 }
4364 if (b == 0x2e || b == 0x2f) {
3ca51d07 4365 set_cc_op(s, CC_OP_EFLAGS);
664e0f19
FB
4366 }
4367 }
4368}
4369
2c0262af
FB
4370/* convert one instruction. s->is_jmp is set if the translation must
4371 be stopped. Return the next pc value */
0af10c86
BS
4372static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
4373 target_ulong pc_start)
2c0262af
FB
4374{
4375 int b, prefixes, aflag, dflag;
4376 int shift, ot;
4377 int modrm, reg, rm, mod, reg_addr, op, opreg, offset_addr, val;
14ce26e7
FB
4378 target_ulong next_eip, tval;
4379 int rex_w, rex_r;
2c0262af 4380
fdefe51c 4381 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
70cff25e 4382 tcg_gen_debug_insn_start(pc_start);
fdefe51c 4383 }
2c0262af
FB
4384 s->pc = pc_start;
4385 prefixes = 0;
4386 aflag = s->code32;
4387 dflag = s->code32;
4388 s->override = -1;
14ce26e7
FB
4389 rex_w = -1;
4390 rex_r = 0;
4391#ifdef TARGET_X86_64
4392 s->rex_x = 0;
4393 s->rex_b = 0;
5fafdf24 4394 x86_64_hregs = 0;
14ce26e7
FB
4395#endif
4396 s->rip_offset = 0; /* for relative ip address */
701ed211
RH
4397 s->vex_l = 0;
4398 s->vex_v = 0;
2c0262af 4399 next_byte:
0af10c86 4400 b = cpu_ldub_code(env, s->pc);
2c0262af 4401 s->pc++;
4a6fd938
RH
4402 /* Collect prefixes. */
4403 switch (b) {
4404 case 0xf3:
4405 prefixes |= PREFIX_REPZ;
4406 goto next_byte;
4407 case 0xf2:
4408 prefixes |= PREFIX_REPNZ;
4409 goto next_byte;
4410 case 0xf0:
4411 prefixes |= PREFIX_LOCK;
4412 goto next_byte;
4413 case 0x2e:
4414 s->override = R_CS;
4415 goto next_byte;
4416 case 0x36:
4417 s->override = R_SS;
4418 goto next_byte;
4419 case 0x3e:
4420 s->override = R_DS;
4421 goto next_byte;
4422 case 0x26:
4423 s->override = R_ES;
4424 goto next_byte;
4425 case 0x64:
4426 s->override = R_FS;
4427 goto next_byte;
4428 case 0x65:
4429 s->override = R_GS;
4430 goto next_byte;
4431 case 0x66:
4432 prefixes |= PREFIX_DATA;
4433 goto next_byte;
4434 case 0x67:
4435 prefixes |= PREFIX_ADR;
4436 goto next_byte;
14ce26e7 4437#ifdef TARGET_X86_64
4a6fd938
RH
4438 case 0x40 ... 0x4f:
4439 if (CODE64(s)) {
14ce26e7
FB
4440 /* REX prefix */
4441 rex_w = (b >> 3) & 1;
4442 rex_r = (b & 0x4) << 1;
4443 s->rex_x = (b & 0x2) << 2;
4444 REX_B(s) = (b & 0x1) << 3;
4445 x86_64_hregs = 1; /* select uniform byte register addressing */
4446 goto next_byte;
4447 }
4a6fd938
RH
4448 break;
4449#endif
701ed211
RH
4450 case 0xc5: /* 2-byte VEX */
4451 case 0xc4: /* 3-byte VEX */
4452 /* VEX prefixes cannot be used except in 32-bit mode.
4453 Otherwise the instruction is LES or LDS. */
4454 if (s->code32 && !s->vm86) {
4455 static const int pp_prefix[4] = {
4456 0, PREFIX_DATA, PREFIX_REPZ, PREFIX_REPNZ
4457 };
4458 int vex3, vex2 = cpu_ldub_code(env, s->pc);
4459
4460 if (!CODE64(s) && (vex2 & 0xc0) != 0xc0) {
4461 /* 4.1.4.6: In 32-bit mode, bits [7:6] must be 11b,
4462 otherwise the instruction is LES or LDS. */
4463 break;
4464 }
4465 s->pc++;
4466
4467 /* 4.1.1-4.1.3: No preceeding lock, 66, f2, f3, or rex prefixes. */
4468 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ
4469 | PREFIX_LOCK | PREFIX_DATA)) {
4470 goto illegal_op;
4471 }
4472#ifdef TARGET_X86_64
4473 if (x86_64_hregs) {
4474 goto illegal_op;
4475 }
4476#endif
4477 rex_r = (~vex2 >> 4) & 8;
4478 if (b == 0xc5) {
4479 vex3 = vex2;
4480 b = cpu_ldub_code(env, s->pc++);
4481 } else {
4482#ifdef TARGET_X86_64
4483 s->rex_x = (~vex2 >> 3) & 8;
4484 s->rex_b = (~vex2 >> 2) & 8;
4485#endif
4486 vex3 = cpu_ldub_code(env, s->pc++);
4487 rex_w = (vex3 >> 7) & 1;
4488 switch (vex2 & 0x1f) {
4489 case 0x01: /* Implied 0f leading opcode bytes. */
4490 b = cpu_ldub_code(env, s->pc++) | 0x100;
4491 break;
4492 case 0x02: /* Implied 0f 38 leading opcode bytes. */
4493 b = 0x138;
4494 break;
4495 case 0x03: /* Implied 0f 3a leading opcode bytes. */
4496 b = 0x13a;
4497 break;
4498 default: /* Reserved for future use. */
4499 goto illegal_op;
4500 }
4501 }
4502 s->vex_v = (~vex3 >> 3) & 0xf;
4503 s->vex_l = (vex3 >> 2) & 1;
4504 prefixes |= pp_prefix[vex3 & 3] | PREFIX_VEX;
4505 }
4506 break;
4a6fd938
RH
4507 }
4508
4509 /* Post-process prefixes. */
4510 if (prefixes & PREFIX_DATA) {
4511 dflag ^= 1;
4512 }
4513 if (prefixes & PREFIX_ADR) {
4514 aflag ^= 1;
4515 }
4516#ifdef TARGET_X86_64
4517 if (CODE64(s)) {
14ce26e7
FB
4518 if (rex_w == 1) {
4519 /* 0x66 is ignored if rex.w is set */
4520 dflag = 2;
14ce26e7 4521 }
4a6fd938 4522 if (!(prefixes & PREFIX_ADR)) {
14ce26e7 4523 aflag = 2;
14ce26e7 4524 }
2c0262af 4525 }
4a6fd938 4526#endif
2c0262af 4527
2c0262af
FB
4528 s->prefix = prefixes;
4529 s->aflag = aflag;
4530 s->dflag = dflag;
4531
4532 /* lock generation */
4533 if (prefixes & PREFIX_LOCK)
a7812ae4 4534 gen_helper_lock();
2c0262af
FB
4535
4536 /* now check op code */
4537 reswitch:
4538 switch(b) {
4539 case 0x0f:
4540 /**************************/
4541 /* extended op code */
0af10c86 4542 b = cpu_ldub_code(env, s->pc++) | 0x100;
2c0262af 4543 goto reswitch;
3b46e624 4544
2c0262af
FB
4545 /**************************/
4546 /* arith & logic */
4547 case 0x00 ... 0x05:
4548 case 0x08 ... 0x0d:
4549 case 0x10 ... 0x15:
4550 case 0x18 ... 0x1d:
4551 case 0x20 ... 0x25:
4552 case 0x28 ... 0x2d:
4553 case 0x30 ... 0x35:
4554 case 0x38 ... 0x3d:
4555 {
4556 int op, f, val;
4557 op = (b >> 3) & 7;
4558 f = (b >> 1) & 3;
4559
4560 if ((b & 1) == 0)
4561 ot = OT_BYTE;
4562 else
14ce26e7 4563 ot = dflag + OT_WORD;
3b46e624 4564
2c0262af
FB
4565 switch(f) {
4566 case 0: /* OP Ev, Gv */
0af10c86 4567 modrm = cpu_ldub_code(env, s->pc++);
14ce26e7 4568 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af 4569 mod = (modrm >> 6) & 3;
14ce26e7 4570 rm = (modrm & 7) | REX_B(s);
2c0262af 4571 if (mod != 3) {
0af10c86 4572 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
2c0262af
FB
4573 opreg = OR_TMP0;
4574 } else if (op == OP_XORL && rm == reg) {
4575 xor_zero:
4576 /* xor reg, reg optimisation */
4577 gen_op_movl_T0_0();
3ca51d07 4578 set_cc_op(s, CC_OP_LOGICB + ot);
57fec1fe 4579 gen_op_mov_reg_T0(ot, reg);
2c0262af
FB
4580 gen_op_update1_cc();
4581 break;
4582 } else {
4583 opreg = rm;
4584 }
57fec1fe 4585 gen_op_mov_TN_reg(ot, 1, reg);
2c0262af
FB
4586 gen_op(s, op, ot, opreg);
4587 break;
4588 case 1: /* OP Gv, Ev */
0af10c86 4589 modrm = cpu_ldub_code(env, s->pc++);
2c0262af 4590 mod = (modrm >> 6) & 3;
14ce26e7
FB
4591 reg = ((modrm >> 3) & 7) | rex_r;
4592 rm = (modrm & 7) | REX_B(s);
2c0262af 4593 if (mod != 3) {
0af10c86 4594 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
57fec1fe 4595 gen_op_ld_T1_A0(ot + s->mem_index);
2c0262af
FB
4596 } else if (op == OP_XORL && rm == reg) {
4597 goto xor_zero;
4598 } else {
57fec1fe 4599 gen_op_mov_TN_reg(ot, 1, rm);
2c0262af
FB
4600 }
4601 gen_op(s, op, ot, reg);
4602 break;
4603 case 2: /* OP A, Iv */
0af10c86 4604 val = insn_get(env, s, ot);
2c0262af
FB
4605 gen_op_movl_T1_im(val);
4606 gen_op(s, op, ot, OR_EAX);
4607 break;
4608 }
4609 }
4610 break;
4611
ec9d6075
FB
4612 case 0x82:
4613 if (CODE64(s))
4614 goto illegal_op;
2c0262af
FB
4615 case 0x80: /* GRP1 */
4616 case 0x81:
4617 case 0x83:
4618 {
4619 int val;
4620
4621 if ((b & 1) == 0)
4622 ot = OT_BYTE;
4623 else
14ce26e7 4624 ot = dflag + OT_WORD;
3b46e624 4625
0af10c86 4626 modrm = cpu_ldub_code(env, s->pc++);
2c0262af 4627 mod = (modrm >> 6) & 3;
14ce26e7 4628 rm = (modrm & 7) | REX_B(s);
2c0262af 4629 op = (modrm >> 3) & 7;
3b46e624 4630
2c0262af 4631 if (mod != 3) {
14ce26e7
FB
4632 if (b == 0x83)
4633 s->rip_offset = 1;
4634 else
4635 s->rip_offset = insn_const_size(ot);
0af10c86 4636 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
2c0262af
FB
4637 opreg = OR_TMP0;
4638 } else {
14ce26e7 4639 opreg = rm;
2c0262af
FB
4640 }
4641
4642 switch(b) {
4643 default:
4644 case 0x80:
4645 case 0x81:
d64477af 4646 case 0x82:
0af10c86 4647 val = insn_get(env, s, ot);
2c0262af
FB
4648 break;
4649 case 0x83:
0af10c86 4650 val = (int8_t)insn_get(env, s, OT_BYTE);
2c0262af
FB
4651 break;
4652 }
4653 gen_op_movl_T1_im(val);
4654 gen_op(s, op, ot, opreg);
4655 }
4656 break;
4657
4658 /**************************/
4659 /* inc, dec, and other misc arith */
4660 case 0x40 ... 0x47: /* inc Gv */
4661 ot = dflag ? OT_LONG : OT_WORD;
4662 gen_inc(s, ot, OR_EAX + (b & 7), 1);
4663 break;
4664 case 0x48 ... 0x4f: /* dec Gv */
4665 ot = dflag ? OT_LONG : OT_WORD;
4666 gen_inc(s, ot, OR_EAX + (b & 7), -1);
4667 break;
4668 case 0xf6: /* GRP3 */
4669 case 0xf7:
4670 if ((b & 1) == 0)
4671 ot = OT_BYTE;
4672 else
14ce26e7 4673 ot = dflag + OT_WORD;
2c0262af 4674
0af10c86 4675 modrm = cpu_ldub_code(env, s->pc++);
2c0262af 4676 mod = (modrm >> 6) & 3;
14ce26e7 4677 rm = (modrm & 7) | REX_B(s);
2c0262af
FB
4678 op = (modrm >> 3) & 7;
4679 if (mod != 3) {
14ce26e7
FB
4680 if (op == 0)
4681 s->rip_offset = insn_const_size(ot);
0af10c86 4682 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
57fec1fe 4683 gen_op_ld_T0_A0(ot + s->mem_index);
2c0262af 4684 } else {
57fec1fe 4685 gen_op_mov_TN_reg(ot, 0, rm);
2c0262af
FB
4686 }
4687
4688 switch(op) {
4689 case 0: /* test */
0af10c86 4690 val = insn_get(env, s, ot);
2c0262af
FB
4691 gen_op_movl_T1_im(val);
4692 gen_op_testl_T0_T1_cc();
3ca51d07 4693 set_cc_op(s, CC_OP_LOGICB + ot);
2c0262af
FB
4694 break;
4695 case 2: /* not */
b6abf97d 4696 tcg_gen_not_tl(cpu_T[0], cpu_T[0]);
2c0262af 4697 if (mod != 3) {
57fec1fe 4698 gen_op_st_T0_A0(ot + s->mem_index);
2c0262af 4699 } else {
57fec1fe 4700 gen_op_mov_reg_T0(ot, rm);
2c0262af
FB
4701 }
4702 break;
4703 case 3: /* neg */
b6abf97d 4704 tcg_gen_neg_tl(cpu_T[0], cpu_T[0]);
2c0262af 4705 if (mod != 3) {
57fec1fe 4706 gen_op_st_T0_A0(ot + s->mem_index);
2c0262af 4707 } else {
57fec1fe 4708 gen_op_mov_reg_T0(ot, rm);
2c0262af
FB
4709 }
4710 gen_op_update_neg_cc();
3ca51d07 4711 set_cc_op(s, CC_OP_SUBB + ot);
2c0262af
FB
4712 break;
4713 case 4: /* mul */
4714 switch(ot) {
4715 case OT_BYTE:
0211e5af
FB
4716 gen_op_mov_TN_reg(OT_BYTE, 1, R_EAX);
4717 tcg_gen_ext8u_tl(cpu_T[0], cpu_T[0]);
4718 tcg_gen_ext8u_tl(cpu_T[1], cpu_T[1]);
4719 /* XXX: use 32 bit mul which could be faster */
4720 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
4721 gen_op_mov_reg_T0(OT_WORD, R_EAX);
4722 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4723 tcg_gen_andi_tl(cpu_cc_src, cpu_T[0], 0xff00);
3ca51d07 4724 set_cc_op(s, CC_OP_MULB);
2c0262af
FB
4725 break;
4726 case OT_WORD:
0211e5af
FB
4727 gen_op_mov_TN_reg(OT_WORD, 1, R_EAX);
4728 tcg_gen_ext16u_tl(cpu_T[0], cpu_T[0]);
4729 tcg_gen_ext16u_tl(cpu_T[1], cpu_T[1]);
4730 /* XXX: use 32 bit mul which could be faster */
4731 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
4732 gen_op_mov_reg_T0(OT_WORD, R_EAX);
4733 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4734 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 16);
4735 gen_op_mov_reg_T0(OT_WORD, R_EDX);
4736 tcg_gen_mov_tl(cpu_cc_src, cpu_T[0]);
3ca51d07 4737 set_cc_op(s, CC_OP_MULW);
2c0262af
FB
4738 break;
4739 default:
4740 case OT_LONG:
0211e5af
FB
4741#ifdef TARGET_X86_64
4742 gen_op_mov_TN_reg(OT_LONG, 1, R_EAX);
4743 tcg_gen_ext32u_tl(cpu_T[0], cpu_T[0]);
4744 tcg_gen_ext32u_tl(cpu_T[1], cpu_T[1]);
4745 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
4746 gen_op_mov_reg_T0(OT_LONG, R_EAX);
4747 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4748 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 32);
4749 gen_op_mov_reg_T0(OT_LONG, R_EDX);
4750 tcg_gen_mov_tl(cpu_cc_src, cpu_T[0]);
4751#else
4752 {
a7812ae4
PB
4753 TCGv_i64 t0, t1;
4754 t0 = tcg_temp_new_i64();
4755 t1 = tcg_temp_new_i64();
0211e5af
FB
4756 gen_op_mov_TN_reg(OT_LONG, 1, R_EAX);
4757 tcg_gen_extu_i32_i64(t0, cpu_T[0]);
4758 tcg_gen_extu_i32_i64(t1, cpu_T[1]);
4759 tcg_gen_mul_i64(t0, t0, t1);
4760 tcg_gen_trunc_i64_i32(cpu_T[0], t0);
4761 gen_op_mov_reg_T0(OT_LONG, R_EAX);
4762 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4763 tcg_gen_shri_i64(t0, t0, 32);
4764 tcg_gen_trunc_i64_i32(cpu_T[0], t0);
4765 gen_op_mov_reg_T0(OT_LONG, R_EDX);
4766 tcg_gen_mov_tl(cpu_cc_src, cpu_T[0]);
4767 }
4768#endif
3ca51d07 4769 set_cc_op(s, CC_OP_MULL);
2c0262af 4770 break;
14ce26e7
FB
4771#ifdef TARGET_X86_64
4772 case OT_QUAD:
7923057b 4773 gen_helper_mulq_EAX_T0(cpu_env, cpu_T[0]);
3ca51d07 4774 set_cc_op(s, CC_OP_MULQ);
14ce26e7
FB
4775 break;
4776#endif
2c0262af 4777 }
2c0262af
FB
4778 break;
4779 case 5: /* imul */
4780 switch(ot) {
4781 case OT_BYTE:
0211e5af
FB
4782 gen_op_mov_TN_reg(OT_BYTE, 1, R_EAX);
4783 tcg_gen_ext8s_tl(cpu_T[0], cpu_T[0]);
4784 tcg_gen_ext8s_tl(cpu_T[1], cpu_T[1]);
4785 /* XXX: use 32 bit mul which could be faster */
4786 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
4787 gen_op_mov_reg_T0(OT_WORD, R_EAX);
4788 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4789 tcg_gen_ext8s_tl(cpu_tmp0, cpu_T[0]);
4790 tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0);
3ca51d07 4791 set_cc_op(s, CC_OP_MULB);
2c0262af
FB
4792 break;
4793 case OT_WORD:
0211e5af
FB
4794 gen_op_mov_TN_reg(OT_WORD, 1, R_EAX);
4795 tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
4796 tcg_gen_ext16s_tl(cpu_T[1], cpu_T[1]);
4797 /* XXX: use 32 bit mul which could be faster */
4798 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
4799 gen_op_mov_reg_T0(OT_WORD, R_EAX);
4800 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4801 tcg_gen_ext16s_tl(cpu_tmp0, cpu_T[0]);
4802 tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0);
4803 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 16);
4804 gen_op_mov_reg_T0(OT_WORD, R_EDX);
3ca51d07 4805 set_cc_op(s, CC_OP_MULW);
2c0262af
FB
4806 break;
4807 default:
4808 case OT_LONG:
0211e5af
FB
4809#ifdef TARGET_X86_64
4810 gen_op_mov_TN_reg(OT_LONG, 1, R_EAX);
4811 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
4812 tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]);
4813 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
4814 gen_op_mov_reg_T0(OT_LONG, R_EAX);
4815 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4816 tcg_gen_ext32s_tl(cpu_tmp0, cpu_T[0]);
4817 tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0);
4818 tcg_gen_shri_tl(cpu_T[0], cpu_T[0], 32);
4819 gen_op_mov_reg_T0(OT_LONG, R_EDX);
4820#else
4821 {
a7812ae4
PB
4822 TCGv_i64 t0, t1;
4823 t0 = tcg_temp_new_i64();
4824 t1 = tcg_temp_new_i64();
0211e5af
FB
4825 gen_op_mov_TN_reg(OT_LONG, 1, R_EAX);
4826 tcg_gen_ext_i32_i64(t0, cpu_T[0]);
4827 tcg_gen_ext_i32_i64(t1, cpu_T[1]);
4828 tcg_gen_mul_i64(t0, t0, t1);
4829 tcg_gen_trunc_i64_i32(cpu_T[0], t0);
4830 gen_op_mov_reg_T0(OT_LONG, R_EAX);
4831 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
4832 tcg_gen_sari_tl(cpu_tmp0, cpu_T[0], 31);
4833 tcg_gen_shri_i64(t0, t0, 32);
4834 tcg_gen_trunc_i64_i32(cpu_T[0], t0);
4835 gen_op_mov_reg_T0(OT_LONG, R_EDX);
4836 tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0);
4837 }
4838#endif
3ca51d07 4839 set_cc_op(s, CC_OP_MULL);
2c0262af 4840 break;
14ce26e7
FB
4841#ifdef TARGET_X86_64
4842 case OT_QUAD:
7923057b 4843 gen_helper_imulq_EAX_T0(cpu_env, cpu_T[0]);
3ca51d07 4844 set_cc_op(s, CC_OP_MULQ);
14ce26e7
FB
4845 break;
4846#endif
2c0262af 4847 }
2c0262af
FB
4848 break;
4849 case 6: /* div */
4850 switch(ot) {
4851 case OT_BYTE:
14ce26e7 4852 gen_jmp_im(pc_start - s->cs_base);
7923057b 4853 gen_helper_divb_AL(cpu_env, cpu_T[0]);
2c0262af
FB
4854 break;
4855 case OT_WORD:
14ce26e7 4856 gen_jmp_im(pc_start - s->cs_base);
7923057b 4857 gen_helper_divw_AX(cpu_env, cpu_T[0]);
2c0262af
FB
4858 break;
4859 default:
4860 case OT_LONG:
14ce26e7 4861 gen_jmp_im(pc_start - s->cs_base);
7923057b 4862 gen_helper_divl_EAX(cpu_env, cpu_T[0]);
14ce26e7
FB
4863 break;
4864#ifdef TARGET_X86_64
4865 case OT_QUAD:
4866 gen_jmp_im(pc_start - s->cs_base);
7923057b 4867 gen_helper_divq_EAX(cpu_env, cpu_T[0]);
2c0262af 4868 break;
14ce26e7 4869#endif
2c0262af
FB
4870 }
4871 break;
4872 case 7: /* idiv */
4873 switch(ot) {
4874 case OT_BYTE:
14ce26e7 4875 gen_jmp_im(pc_start - s->cs_base);
7923057b 4876 gen_helper_idivb_AL(cpu_env, cpu_T[0]);
2c0262af
FB
4877 break;
4878 case OT_WORD:
14ce26e7 4879 gen_jmp_im(pc_start - s->cs_base);
7923057b 4880 gen_helper_idivw_AX(cpu_env, cpu_T[0]);
2c0262af
FB
4881 break;
4882 default:
4883 case OT_LONG:
14ce26e7 4884 gen_jmp_im(pc_start - s->cs_base);
7923057b 4885 gen_helper_idivl_EAX(cpu_env, cpu_T[0]);
14ce26e7
FB
4886 break;
4887#ifdef TARGET_X86_64
4888 case OT_QUAD:
4889 gen_jmp_im(pc_start - s->cs_base);
7923057b 4890 gen_helper_idivq_EAX(cpu_env, cpu_T[0]);
2c0262af 4891 break;
14ce26e7 4892#endif
2c0262af
FB
4893 }
4894 break;
4895 default:
4896 goto illegal_op;
4897 }
4898 break;
4899
4900 case 0xfe: /* GRP4 */
4901 case 0xff: /* GRP5 */
4902 if ((b & 1) == 0)
4903 ot = OT_BYTE;
4904 else
14ce26e7 4905 ot = dflag + OT_WORD;
2c0262af 4906
0af10c86 4907 modrm = cpu_ldub_code(env, s->pc++);
2c0262af 4908 mod = (modrm >> 6) & 3;
14ce26e7 4909 rm = (modrm & 7) | REX_B(s);
2c0262af
FB
4910 op = (modrm >> 3) & 7;
4911 if (op >= 2 && b == 0xfe) {
4912 goto illegal_op;
4913 }
14ce26e7 4914 if (CODE64(s)) {
aba9d61e 4915 if (op == 2 || op == 4) {
14ce26e7
FB
4916 /* operand size for jumps is 64 bit */
4917 ot = OT_QUAD;
aba9d61e 4918 } else if (op == 3 || op == 5) {
41b1e61f 4919 ot = dflag ? OT_LONG + (rex_w == 1) : OT_WORD;
14ce26e7
FB
4920 } else if (op == 6) {
4921 /* default push size is 64 bit */
4922 ot = dflag ? OT_QUAD : OT_WORD;
4923 }
4924 }
2c0262af 4925 if (mod != 3) {
0af10c86 4926 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
2c0262af 4927 if (op >= 2 && op != 3 && op != 5)
57fec1fe 4928 gen_op_ld_T0_A0(ot + s->mem_index);
2c0262af 4929 } else {
57fec1fe 4930 gen_op_mov_TN_reg(ot, 0, rm);
2c0262af
FB
4931 }
4932
4933 switch(op) {
4934 case 0: /* inc Ev */
4935 if (mod != 3)
4936 opreg = OR_TMP0;
4937 else
4938 opreg = rm;
4939 gen_inc(s, ot, opreg, 1);
4940 break;
4941 case 1: /* dec Ev */
4942 if (mod != 3)
4943 opreg = OR_TMP0;
4944 else
4945 opreg = rm;
4946 gen_inc(s, ot, opreg, -1);
4947 break;
4948 case 2: /* call Ev */
4f31916f 4949 /* XXX: optimize if memory (no 'and' is necessary) */
2c0262af
FB
4950 if (s->dflag == 0)
4951 gen_op_andl_T0_ffff();
2c0262af 4952 next_eip = s->pc - s->cs_base;
1ef38687 4953 gen_movtl_T1_im(next_eip);
4f31916f
FB
4954 gen_push_T1(s);
4955 gen_op_jmp_T0();
2c0262af
FB
4956 gen_eob(s);
4957 break;
61382a50 4958 case 3: /* lcall Ev */
57fec1fe 4959 gen_op_ld_T1_A0(ot + s->mem_index);
aba9d61e 4960 gen_add_A0_im(s, 1 << (ot - OT_WORD + 1));
57fec1fe 4961 gen_op_ldu_T0_A0(OT_WORD + s->mem_index);
2c0262af
FB
4962 do_lcall:
4963 if (s->pe && !s->vm86) {
773cdfcc 4964 gen_update_cc_op(s);
14ce26e7 4965 gen_jmp_im(pc_start - s->cs_base);
b6abf97d 4966 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
2999a0b2
BS
4967 gen_helper_lcall_protected(cpu_env, cpu_tmp2_i32, cpu_T[1],
4968 tcg_const_i32(dflag),
a7812ae4 4969 tcg_const_i32(s->pc - pc_start));
2c0262af 4970 } else {
b6abf97d 4971 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
2999a0b2
BS
4972 gen_helper_lcall_real(cpu_env, cpu_tmp2_i32, cpu_T[1],
4973 tcg_const_i32(dflag),
a7812ae4 4974 tcg_const_i32(s->pc - s->cs_base));
2c0262af
FB
4975 }
4976 gen_eob(s);
4977 break;
4978 case 4: /* jmp Ev */
4979 if (s->dflag == 0)
4980 gen_op_andl_T0_ffff();
4981 gen_op_jmp_T0();
4982 gen_eob(s);
4983 break;
4984 case 5: /* ljmp Ev */
57fec1fe 4985 gen_op_ld_T1_A0(ot + s->mem_index);
aba9d61e 4986 gen_add_A0_im(s, 1 << (ot - OT_WORD + 1));
57fec1fe 4987 gen_op_ldu_T0_A0(OT_WORD + s->mem_index);
2c0262af
FB
4988 do_ljmp:
4989 if (s->pe && !s->vm86) {
773cdfcc 4990 gen_update_cc_op(s);
14ce26e7 4991 gen_jmp_im(pc_start - s->cs_base);
b6abf97d 4992 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
2999a0b2 4993 gen_helper_ljmp_protected(cpu_env, cpu_tmp2_i32, cpu_T[1],
a7812ae4 4994 tcg_const_i32(s->pc - pc_start));
2c0262af 4995 } else {
3bd7da9e 4996 gen_op_movl_seg_T0_vm(R_CS);
2c0262af
FB
4997 gen_op_movl_T0_T1();
4998 gen_op_jmp_T0();
4999 }
5000 gen_eob(s);
5001 break;
5002 case 6: /* push Ev */
5003 gen_push_T0(s);
5004 break;
5005 default:
5006 goto illegal_op;
5007 }
5008 break;
5009
5010 case 0x84: /* test Ev, Gv */
5fafdf24 5011 case 0x85:
2c0262af
FB
5012 if ((b & 1) == 0)
5013 ot = OT_BYTE;
5014 else
14ce26e7 5015 ot = dflag + OT_WORD;
2c0262af 5016
0af10c86 5017 modrm = cpu_ldub_code(env, s->pc++);
14ce26e7 5018 reg = ((modrm >> 3) & 7) | rex_r;
3b46e624 5019
0af10c86 5020 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
57fec1fe 5021 gen_op_mov_TN_reg(ot, 1, reg);
2c0262af 5022 gen_op_testl_T0_T1_cc();
3ca51d07 5023 set_cc_op(s, CC_OP_LOGICB + ot);
2c0262af 5024 break;
3b46e624 5025
2c0262af
FB
5026 case 0xa8: /* test eAX, Iv */
5027 case 0xa9:
5028 if ((b & 1) == 0)
5029 ot = OT_BYTE;
5030 else
14ce26e7 5031 ot = dflag + OT_WORD;
0af10c86 5032 val = insn_get(env, s, ot);
2c0262af 5033
57fec1fe 5034 gen_op_mov_TN_reg(ot, 0, OR_EAX);
2c0262af
FB
5035 gen_op_movl_T1_im(val);
5036 gen_op_testl_T0_T1_cc();
3ca51d07 5037 set_cc_op(s, CC_OP_LOGICB + ot);
2c0262af 5038 break;
3b46e624 5039
2c0262af 5040 case 0x98: /* CWDE/CBW */
14ce26e7
FB
5041#ifdef TARGET_X86_64
5042 if (dflag == 2) {
e108dd01
FB
5043 gen_op_mov_TN_reg(OT_LONG, 0, R_EAX);
5044 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
5045 gen_op_mov_reg_T0(OT_QUAD, R_EAX);
14ce26e7
FB
5046 } else
5047#endif
e108dd01
FB
5048 if (dflag == 1) {
5049 gen_op_mov_TN_reg(OT_WORD, 0, R_EAX);
5050 tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
5051 gen_op_mov_reg_T0(OT_LONG, R_EAX);
5052 } else {
5053 gen_op_mov_TN_reg(OT_BYTE, 0, R_EAX);
5054 tcg_gen_ext8s_tl(cpu_T[0], cpu_T[0]);
5055 gen_op_mov_reg_T0(OT_WORD, R_EAX);
5056 }
2c0262af
FB
5057 break;
5058 case 0x99: /* CDQ/CWD */
14ce26e7
FB
5059#ifdef TARGET_X86_64
5060 if (dflag == 2) {
e108dd01
FB
5061 gen_op_mov_TN_reg(OT_QUAD, 0, R_EAX);
5062 tcg_gen_sari_tl(cpu_T[0], cpu_T[0], 63);
5063 gen_op_mov_reg_T0(OT_QUAD, R_EDX);
14ce26e7
FB
5064 } else
5065#endif
e108dd01
FB
5066 if (dflag == 1) {
5067 gen_op_mov_TN_reg(OT_LONG, 0, R_EAX);
5068 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
5069 tcg_gen_sari_tl(cpu_T[0], cpu_T[0], 31);
5070 gen_op_mov_reg_T0(OT_LONG, R_EDX);
5071 } else {
5072 gen_op_mov_TN_reg(OT_WORD, 0, R_EAX);
5073 tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
5074 tcg_gen_sari_tl(cpu_T[0], cpu_T[0], 15);
5075 gen_op_mov_reg_T0(OT_WORD, R_EDX);
5076 }
2c0262af
FB
5077 break;
5078 case 0x1af: /* imul Gv, Ev */
5079 case 0x69: /* imul Gv, Ev, I */
5080 case 0x6b:
14ce26e7 5081 ot = dflag + OT_WORD;
0af10c86 5082 modrm = cpu_ldub_code(env, s->pc++);
14ce26e7
FB
5083 reg = ((modrm >> 3) & 7) | rex_r;
5084 if (b == 0x69)
5085 s->rip_offset = insn_const_size(ot);
5086 else if (b == 0x6b)
5087 s->rip_offset = 1;
0af10c86 5088 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
2c0262af 5089 if (b == 0x69) {
0af10c86 5090 val = insn_get(env, s, ot);
2c0262af
FB
5091 gen_op_movl_T1_im(val);
5092 } else if (b == 0x6b) {
0af10c86 5093 val = (int8_t)insn_get(env, s, OT_BYTE);
2c0262af
FB
5094 gen_op_movl_T1_im(val);
5095 } else {
57fec1fe 5096 gen_op_mov_TN_reg(ot, 1, reg);
2c0262af
FB
5097 }
5098
14ce26e7
FB
5099#ifdef TARGET_X86_64
5100 if (ot == OT_QUAD) {
7923057b 5101 gen_helper_imulq_T0_T1(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]);
14ce26e7
FB
5102 } else
5103#endif
2c0262af 5104 if (ot == OT_LONG) {
0211e5af
FB
5105#ifdef TARGET_X86_64
5106 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
5107 tcg_gen_ext32s_tl(cpu_T[1], cpu_T[1]);
5108 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
5109 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
5110 tcg_gen_ext32s_tl(cpu_tmp0, cpu_T[0]);
5111 tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0);
5112#else
5113 {
a7812ae4
PB
5114 TCGv_i64 t0, t1;
5115 t0 = tcg_temp_new_i64();
5116 t1 = tcg_temp_new_i64();
0211e5af
FB
5117 tcg_gen_ext_i32_i64(t0, cpu_T[0]);
5118 tcg_gen_ext_i32_i64(t1, cpu_T[1]);
5119 tcg_gen_mul_i64(t0, t0, t1);
5120 tcg_gen_trunc_i64_i32(cpu_T[0], t0);
5121 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
5122 tcg_gen_sari_tl(cpu_tmp0, cpu_T[0], 31);
5123 tcg_gen_shri_i64(t0, t0, 32);
5124 tcg_gen_trunc_i64_i32(cpu_T[1], t0);
5125 tcg_gen_sub_tl(cpu_cc_src, cpu_T[1], cpu_tmp0);
5126 }
5127#endif
2c0262af 5128 } else {
0211e5af
FB
5129 tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
5130 tcg_gen_ext16s_tl(cpu_T[1], cpu_T[1]);
5131 /* XXX: use 32 bit mul which could be faster */
5132 tcg_gen_mul_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
5133 tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]);
5134 tcg_gen_ext16s_tl(cpu_tmp0, cpu_T[0]);
5135 tcg_gen_sub_tl(cpu_cc_src, cpu_T[0], cpu_tmp0);
2c0262af 5136 }
57fec1fe 5137 gen_op_mov_reg_T0(ot, reg);
3ca51d07 5138 set_cc_op(s, CC_OP_MULB + ot);
2c0262af
FB
5139 break;
5140 case 0x1c0:
5141 case 0x1c1: /* xadd Ev, Gv */
5142 if ((b & 1) == 0)
5143 ot = OT_BYTE;
5144 else
14ce26e7 5145 ot = dflag + OT_WORD;
0af10c86 5146 modrm = cpu_ldub_code(env, s->pc++);
14ce26e7 5147 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af
FB
5148 mod = (modrm >> 6) & 3;
5149 if (mod == 3) {
14ce26e7 5150 rm = (modrm & 7) | REX_B(s);
57fec1fe
FB
5151 gen_op_mov_TN_reg(ot, 0, reg);
5152 gen_op_mov_TN_reg(ot, 1, rm);
2c0262af 5153 gen_op_addl_T0_T1();
57fec1fe
FB
5154 gen_op_mov_reg_T1(ot, reg);
5155 gen_op_mov_reg_T0(ot, rm);
2c0262af 5156 } else {
0af10c86 5157 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
57fec1fe
FB
5158 gen_op_mov_TN_reg(ot, 0, reg);
5159 gen_op_ld_T1_A0(ot + s->mem_index);
2c0262af 5160 gen_op_addl_T0_T1();
57fec1fe
FB
5161 gen_op_st_T0_A0(ot + s->mem_index);
5162 gen_op_mov_reg_T1(ot, reg);
2c0262af
FB
5163 }
5164 gen_op_update2_cc();
3ca51d07 5165 set_cc_op(s, CC_OP_ADDB + ot);
2c0262af
FB
5166 break;
5167 case 0x1b0:
5168 case 0x1b1: /* cmpxchg Ev, Gv */
cad3a37d 5169 {
1130328e 5170 int label1, label2;
1e4840bf 5171 TCGv t0, t1, t2, a0;
cad3a37d
FB
5172
5173 if ((b & 1) == 0)
5174 ot = OT_BYTE;
5175 else
5176 ot = dflag + OT_WORD;
0af10c86 5177 modrm = cpu_ldub_code(env, s->pc++);
cad3a37d
FB
5178 reg = ((modrm >> 3) & 7) | rex_r;
5179 mod = (modrm >> 6) & 3;
a7812ae4
PB
5180 t0 = tcg_temp_local_new();
5181 t1 = tcg_temp_local_new();
5182 t2 = tcg_temp_local_new();
5183 a0 = tcg_temp_local_new();
1e4840bf 5184 gen_op_mov_v_reg(ot, t1, reg);
cad3a37d
FB
5185 if (mod == 3) {
5186 rm = (modrm & 7) | REX_B(s);
1e4840bf 5187 gen_op_mov_v_reg(ot, t0, rm);
cad3a37d 5188 } else {
0af10c86 5189 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
1e4840bf
FB
5190 tcg_gen_mov_tl(a0, cpu_A0);
5191 gen_op_ld_v(ot + s->mem_index, t0, a0);
cad3a37d
FB
5192 rm = 0; /* avoid warning */
5193 }
5194 label1 = gen_new_label();
a3251186
RH
5195 tcg_gen_mov_tl(t2, cpu_regs[R_EAX]);
5196 gen_extu(ot, t0);
1e4840bf 5197 gen_extu(ot, t2);
a3251186 5198 tcg_gen_brcond_tl(TCG_COND_EQ, t2, t0, label1);
f7e80adf 5199 label2 = gen_new_label();
cad3a37d 5200 if (mod == 3) {
1e4840bf 5201 gen_op_mov_reg_v(ot, R_EAX, t0);
1130328e
FB
5202 tcg_gen_br(label2);
5203 gen_set_label(label1);
1e4840bf 5204 gen_op_mov_reg_v(ot, rm, t1);
cad3a37d 5205 } else {
f7e80adf
AG
5206 /* perform no-op store cycle like physical cpu; must be
5207 before changing accumulator to ensure idempotency if
5208 the store faults and the instruction is restarted */
5209 gen_op_st_v(ot + s->mem_index, t0, a0);
1e4840bf 5210 gen_op_mov_reg_v(ot, R_EAX, t0);
f7e80adf 5211 tcg_gen_br(label2);
1130328e 5212 gen_set_label(label1);
1e4840bf 5213 gen_op_st_v(ot + s->mem_index, t1, a0);
cad3a37d 5214 }
f7e80adf 5215 gen_set_label(label2);
1e4840bf 5216 tcg_gen_mov_tl(cpu_cc_src, t0);
a3251186
RH
5217 tcg_gen_mov_tl(cpu_cc_srcT, t2);
5218 tcg_gen_sub_tl(cpu_cc_dst, t2, t0);
3ca51d07 5219 set_cc_op(s, CC_OP_SUBB + ot);
1e4840bf
FB
5220 tcg_temp_free(t0);
5221 tcg_temp_free(t1);
5222 tcg_temp_free(t2);
5223 tcg_temp_free(a0);
2c0262af 5224 }
2c0262af
FB
5225 break;
5226 case 0x1c7: /* cmpxchg8b */
0af10c86 5227 modrm = cpu_ldub_code(env, s->pc++);
2c0262af 5228 mod = (modrm >> 6) & 3;
71c3558e 5229 if ((mod == 3) || ((modrm & 0x38) != 0x8))
2c0262af 5230 goto illegal_op;
1b9d9ebb
FB
5231#ifdef TARGET_X86_64
5232 if (dflag == 2) {
5233 if (!(s->cpuid_ext_features & CPUID_EXT_CX16))
5234 goto illegal_op;
5235 gen_jmp_im(pc_start - s->cs_base);
773cdfcc 5236 gen_update_cc_op(s);
0af10c86 5237 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
92fc4b58 5238 gen_helper_cmpxchg16b(cpu_env, cpu_A0);
1b9d9ebb
FB
5239 } else
5240#endif
5241 {
5242 if (!(s->cpuid_features & CPUID_CX8))
5243 goto illegal_op;
5244 gen_jmp_im(pc_start - s->cs_base);
773cdfcc 5245 gen_update_cc_op(s);
0af10c86 5246 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
92fc4b58 5247 gen_helper_cmpxchg8b(cpu_env, cpu_A0);
1b9d9ebb 5248 }
3ca51d07 5249 set_cc_op(s, CC_OP_EFLAGS);
2c0262af 5250 break;
3b46e624 5251
2c0262af
FB
5252 /**************************/
5253 /* push/pop */
5254 case 0x50 ... 0x57: /* push */
57fec1fe 5255 gen_op_mov_TN_reg(OT_LONG, 0, (b & 7) | REX_B(s));
2c0262af
FB
5256 gen_push_T0(s);
5257 break;
5258 case 0x58 ... 0x5f: /* pop */
14ce26e7
FB
5259 if (CODE64(s)) {
5260 ot = dflag ? OT_QUAD : OT_WORD;
5261 } else {
5262 ot = dflag + OT_WORD;
5263 }
2c0262af 5264 gen_pop_T0(s);
77729c24 5265 /* NOTE: order is important for pop %sp */
2c0262af 5266 gen_pop_update(s);
57fec1fe 5267 gen_op_mov_reg_T0(ot, (b & 7) | REX_B(s));
2c0262af
FB
5268 break;
5269 case 0x60: /* pusha */
14ce26e7
FB
5270 if (CODE64(s))
5271 goto illegal_op;
2c0262af
FB
5272 gen_pusha(s);
5273 break;
5274 case 0x61: /* popa */
14ce26e7
FB
5275 if (CODE64(s))
5276 goto illegal_op;
2c0262af
FB
5277 gen_popa(s);
5278 break;
5279 case 0x68: /* push Iv */
5280 case 0x6a:
14ce26e7
FB
5281 if (CODE64(s)) {
5282 ot = dflag ? OT_QUAD : OT_WORD;
5283 } else {
5284 ot = dflag + OT_WORD;
5285 }
2c0262af 5286 if (b == 0x68)
0af10c86 5287 val = insn_get(env, s, ot);
2c0262af 5288 else
0af10c86 5289 val = (int8_t)insn_get(env, s, OT_BYTE);
2c0262af
FB
5290 gen_op_movl_T0_im(val);
5291 gen_push_T0(s);
5292 break;
5293 case 0x8f: /* pop Ev */
14ce26e7
FB
5294 if (CODE64(s)) {
5295 ot = dflag ? OT_QUAD : OT_WORD;
5296 } else {
5297 ot = dflag + OT_WORD;
5298 }
0af10c86 5299 modrm = cpu_ldub_code(env, s->pc++);
77729c24 5300 mod = (modrm >> 6) & 3;
2c0262af 5301 gen_pop_T0(s);
77729c24
FB
5302 if (mod == 3) {
5303 /* NOTE: order is important for pop %sp */
5304 gen_pop_update(s);
14ce26e7 5305 rm = (modrm & 7) | REX_B(s);
57fec1fe 5306 gen_op_mov_reg_T0(ot, rm);
77729c24
FB
5307 } else {
5308 /* NOTE: order is important too for MMU exceptions */
14ce26e7 5309 s->popl_esp_hack = 1 << ot;
0af10c86 5310 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
77729c24
FB
5311 s->popl_esp_hack = 0;
5312 gen_pop_update(s);
5313 }
2c0262af
FB
5314 break;
5315 case 0xc8: /* enter */
5316 {
5317 int level;
0af10c86 5318 val = cpu_lduw_code(env, s->pc);
2c0262af 5319 s->pc += 2;
0af10c86 5320 level = cpu_ldub_code(env, s->pc++);
2c0262af
FB
5321 gen_enter(s, val, level);
5322 }
5323 break;
5324 case 0xc9: /* leave */
5325 /* XXX: exception not precise (ESP is updated before potential exception) */
14ce26e7 5326 if (CODE64(s)) {
57fec1fe
FB
5327 gen_op_mov_TN_reg(OT_QUAD, 0, R_EBP);
5328 gen_op_mov_reg_T0(OT_QUAD, R_ESP);
14ce26e7 5329 } else if (s->ss32) {
57fec1fe
FB
5330 gen_op_mov_TN_reg(OT_LONG, 0, R_EBP);
5331 gen_op_mov_reg_T0(OT_LONG, R_ESP);
2c0262af 5332 } else {
57fec1fe
FB
5333 gen_op_mov_TN_reg(OT_WORD, 0, R_EBP);
5334 gen_op_mov_reg_T0(OT_WORD, R_ESP);
2c0262af
FB
5335 }
5336 gen_pop_T0(s);
14ce26e7
FB
5337 if (CODE64(s)) {
5338 ot = dflag ? OT_QUAD : OT_WORD;
5339 } else {
5340 ot = dflag + OT_WORD;
5341 }
57fec1fe 5342 gen_op_mov_reg_T0(ot, R_EBP);
2c0262af
FB
5343 gen_pop_update(s);
5344 break;
5345 case 0x06: /* push es */
5346 case 0x0e: /* push cs */
5347 case 0x16: /* push ss */
5348 case 0x1e: /* push ds */
14ce26e7
FB
5349 if (CODE64(s))
5350 goto illegal_op;
2c0262af
FB
5351 gen_op_movl_T0_seg(b >> 3);
5352 gen_push_T0(s);
5353 break;
5354 case 0x1a0: /* push fs */
5355 case 0x1a8: /* push gs */
5356 gen_op_movl_T0_seg((b >> 3) & 7);
5357 gen_push_T0(s);
5358 break;
5359 case 0x07: /* pop es */
5360 case 0x17: /* pop ss */
5361 case 0x1f: /* pop ds */
14ce26e7
FB
5362 if (CODE64(s))
5363 goto illegal_op;
2c0262af
FB
5364 reg = b >> 3;
5365 gen_pop_T0(s);
5366 gen_movl_seg_T0(s, reg, pc_start - s->cs_base);
5367 gen_pop_update(s);
5368 if (reg == R_SS) {
a2cc3b24
FB
5369 /* if reg == SS, inhibit interrupts/trace. */
5370 /* If several instructions disable interrupts, only the
5371 _first_ does it */
5372 if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
f0967a1a 5373 gen_helper_set_inhibit_irq(cpu_env);
2c0262af
FB
5374 s->tf = 0;
5375 }
5376 if (s->is_jmp) {
14ce26e7 5377 gen_jmp_im(s->pc - s->cs_base);
2c0262af
FB
5378 gen_eob(s);
5379 }
5380 break;
5381 case 0x1a1: /* pop fs */
5382 case 0x1a9: /* pop gs */
5383 gen_pop_T0(s);
5384 gen_movl_seg_T0(s, (b >> 3) & 7, pc_start - s->cs_base);
5385 gen_pop_update(s);
5386 if (s->is_jmp) {
14ce26e7 5387 gen_jmp_im(s->pc - s->cs_base);
2c0262af
FB
5388 gen_eob(s);
5389 }
5390 break;
5391
5392 /**************************/
5393 /* mov */
5394 case 0x88:
5395 case 0x89: /* mov Gv, Ev */
5396 if ((b & 1) == 0)
5397 ot = OT_BYTE;
5398 else
14ce26e7 5399 ot = dflag + OT_WORD;
0af10c86 5400 modrm = cpu_ldub_code(env, s->pc++);
14ce26e7 5401 reg = ((modrm >> 3) & 7) | rex_r;
3b46e624 5402
2c0262af 5403 /* generate a generic store */
0af10c86 5404 gen_ldst_modrm(env, s, modrm, ot, reg, 1);
2c0262af
FB
5405 break;
5406 case 0xc6:
5407 case 0xc7: /* mov Ev, Iv */
5408 if ((b & 1) == 0)
5409 ot = OT_BYTE;
5410 else
14ce26e7 5411 ot = dflag + OT_WORD;
0af10c86 5412 modrm = cpu_ldub_code(env, s->pc++);
2c0262af 5413 mod = (modrm >> 6) & 3;
14ce26e7
FB
5414 if (mod != 3) {
5415 s->rip_offset = insn_const_size(ot);
0af10c86 5416 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
14ce26e7 5417 }
0af10c86 5418 val = insn_get(env, s, ot);
2c0262af
FB
5419 gen_op_movl_T0_im(val);
5420 if (mod != 3)
57fec1fe 5421 gen_op_st_T0_A0(ot + s->mem_index);
2c0262af 5422 else
57fec1fe 5423 gen_op_mov_reg_T0(ot, (modrm & 7) | REX_B(s));
2c0262af
FB
5424 break;
5425 case 0x8a:
5426 case 0x8b: /* mov Ev, Gv */
5427 if ((b & 1) == 0)
5428 ot = OT_BYTE;
5429 else
14ce26e7 5430 ot = OT_WORD + dflag;
0af10c86 5431 modrm = cpu_ldub_code(env, s->pc++);
14ce26e7 5432 reg = ((modrm >> 3) & 7) | rex_r;
3b46e624 5433
0af10c86 5434 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
57fec1fe 5435 gen_op_mov_reg_T0(ot, reg);
2c0262af
FB
5436 break;
5437 case 0x8e: /* mov seg, Gv */
0af10c86 5438 modrm = cpu_ldub_code(env, s->pc++);
2c0262af
FB
5439 reg = (modrm >> 3) & 7;
5440 if (reg >= 6 || reg == R_CS)
5441 goto illegal_op;
0af10c86 5442 gen_ldst_modrm(env, s, modrm, OT_WORD, OR_TMP0, 0);
2c0262af
FB
5443 gen_movl_seg_T0(s, reg, pc_start - s->cs_base);
5444 if (reg == R_SS) {
5445 /* if reg == SS, inhibit interrupts/trace */
a2cc3b24
FB
5446 /* If several instructions disable interrupts, only the
5447 _first_ does it */
5448 if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
f0967a1a 5449 gen_helper_set_inhibit_irq(cpu_env);
2c0262af
FB
5450 s->tf = 0;
5451 }
5452 if (s->is_jmp) {
14ce26e7 5453 gen_jmp_im(s->pc - s->cs_base);
2c0262af
FB
5454 gen_eob(s);
5455 }
5456 break;
5457 case 0x8c: /* mov Gv, seg */
0af10c86 5458 modrm = cpu_ldub_code(env, s->pc++);
2c0262af
FB
5459 reg = (modrm >> 3) & 7;
5460 mod = (modrm >> 6) & 3;
5461 if (reg >= 6)
5462 goto illegal_op;
5463 gen_op_movl_T0_seg(reg);
14ce26e7
FB
5464 if (mod == 3)
5465 ot = OT_WORD + dflag;
5466 else
5467 ot = OT_WORD;
0af10c86 5468 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
2c0262af
FB
5469 break;
5470
5471 case 0x1b6: /* movzbS Gv, Eb */
5472 case 0x1b7: /* movzwS Gv, Eb */
5473 case 0x1be: /* movsbS Gv, Eb */
5474 case 0x1bf: /* movswS Gv, Eb */
5475 {
5476 int d_ot;
5477 /* d_ot is the size of destination */
5478 d_ot = dflag + OT_WORD;
5479 /* ot is the size of source */
5480 ot = (b & 1) + OT_BYTE;
0af10c86 5481 modrm = cpu_ldub_code(env, s->pc++);
14ce26e7 5482 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af 5483 mod = (modrm >> 6) & 3;
14ce26e7 5484 rm = (modrm & 7) | REX_B(s);
3b46e624 5485
2c0262af 5486 if (mod == 3) {
57fec1fe 5487 gen_op_mov_TN_reg(ot, 0, rm);
2c0262af
FB
5488 switch(ot | (b & 8)) {
5489 case OT_BYTE:
e108dd01 5490 tcg_gen_ext8u_tl(cpu_T[0], cpu_T[0]);
2c0262af
FB
5491 break;
5492 case OT_BYTE | 8:
e108dd01 5493 tcg_gen_ext8s_tl(cpu_T[0], cpu_T[0]);
2c0262af
FB
5494 break;
5495 case OT_WORD:
e108dd01 5496 tcg_gen_ext16u_tl(cpu_T[0], cpu_T[0]);
2c0262af
FB
5497 break;
5498 default:
5499 case OT_WORD | 8:
e108dd01 5500 tcg_gen_ext16s_tl(cpu_T[0], cpu_T[0]);
2c0262af
FB
5501 break;
5502 }
57fec1fe 5503 gen_op_mov_reg_T0(d_ot, reg);
2c0262af 5504 } else {
0af10c86 5505 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
2c0262af 5506 if (b & 8) {
57fec1fe 5507 gen_op_lds_T0_A0(ot + s->mem_index);
2c0262af 5508 } else {
57fec1fe 5509 gen_op_ldu_T0_A0(ot + s->mem_index);
2c0262af 5510 }
57fec1fe 5511 gen_op_mov_reg_T0(d_ot, reg);
2c0262af
FB
5512 }
5513 }
5514 break;
5515
5516 case 0x8d: /* lea */
14ce26e7 5517 ot = dflag + OT_WORD;
0af10c86 5518 modrm = cpu_ldub_code(env, s->pc++);
3a1d9b8b
FB
5519 mod = (modrm >> 6) & 3;
5520 if (mod == 3)
5521 goto illegal_op;
14ce26e7 5522 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af
FB
5523 /* we must ensure that no segment is added */
5524 s->override = -1;
5525 val = s->addseg;
5526 s->addseg = 0;
0af10c86 5527 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
2c0262af 5528 s->addseg = val;
57fec1fe 5529 gen_op_mov_reg_A0(ot - OT_WORD, reg);
2c0262af 5530 break;
3b46e624 5531
2c0262af
FB
5532 case 0xa0: /* mov EAX, Ov */
5533 case 0xa1:
5534 case 0xa2: /* mov Ov, EAX */
5535 case 0xa3:
2c0262af 5536 {
14ce26e7
FB
5537 target_ulong offset_addr;
5538
5539 if ((b & 1) == 0)
5540 ot = OT_BYTE;
5541 else
5542 ot = dflag + OT_WORD;
5543#ifdef TARGET_X86_64
8f091a59 5544 if (s->aflag == 2) {
0af10c86 5545 offset_addr = cpu_ldq_code(env, s->pc);
14ce26e7 5546 s->pc += 8;
57fec1fe 5547 gen_op_movq_A0_im(offset_addr);
5fafdf24 5548 } else
14ce26e7
FB
5549#endif
5550 {
5551 if (s->aflag) {
0af10c86 5552 offset_addr = insn_get(env, s, OT_LONG);
14ce26e7 5553 } else {
0af10c86 5554 offset_addr = insn_get(env, s, OT_WORD);
14ce26e7
FB
5555 }
5556 gen_op_movl_A0_im(offset_addr);
5557 }
664e0f19 5558 gen_add_A0_ds_seg(s);
14ce26e7 5559 if ((b & 2) == 0) {
57fec1fe
FB
5560 gen_op_ld_T0_A0(ot + s->mem_index);
5561 gen_op_mov_reg_T0(ot, R_EAX);
14ce26e7 5562 } else {
57fec1fe
FB
5563 gen_op_mov_TN_reg(ot, 0, R_EAX);
5564 gen_op_st_T0_A0(ot + s->mem_index);
2c0262af
FB
5565 }
5566 }
2c0262af
FB
5567 break;
5568 case 0xd7: /* xlat */
14ce26e7 5569#ifdef TARGET_X86_64
8f091a59 5570 if (s->aflag == 2) {
57fec1fe 5571 gen_op_movq_A0_reg(R_EBX);
bbf662ee
FB
5572 gen_op_mov_TN_reg(OT_QUAD, 0, R_EAX);
5573 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xff);
5574 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_T[0]);
5fafdf24 5575 } else
14ce26e7
FB
5576#endif
5577 {
57fec1fe 5578 gen_op_movl_A0_reg(R_EBX);
bbf662ee
FB
5579 gen_op_mov_TN_reg(OT_LONG, 0, R_EAX);
5580 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xff);
5581 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_T[0]);
14ce26e7
FB
5582 if (s->aflag == 0)
5583 gen_op_andl_A0_ffff();
bbf662ee
FB
5584 else
5585 tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffffffff);
14ce26e7 5586 }
664e0f19 5587 gen_add_A0_ds_seg(s);
57fec1fe
FB
5588 gen_op_ldu_T0_A0(OT_BYTE + s->mem_index);
5589 gen_op_mov_reg_T0(OT_BYTE, R_EAX);
2c0262af
FB
5590 break;
5591 case 0xb0 ... 0xb7: /* mov R, Ib */
0af10c86 5592 val = insn_get(env, s, OT_BYTE);
2c0262af 5593 gen_op_movl_T0_im(val);
57fec1fe 5594 gen_op_mov_reg_T0(OT_BYTE, (b & 7) | REX_B(s));
2c0262af
FB
5595 break;
5596 case 0xb8 ... 0xbf: /* mov R, Iv */
14ce26e7
FB
5597#ifdef TARGET_X86_64
5598 if (dflag == 2) {
5599 uint64_t tmp;
5600 /* 64 bit case */
0af10c86 5601 tmp = cpu_ldq_code(env, s->pc);
14ce26e7
FB
5602 s->pc += 8;
5603 reg = (b & 7) | REX_B(s);
5604 gen_movtl_T0_im(tmp);
57fec1fe 5605 gen_op_mov_reg_T0(OT_QUAD, reg);
5fafdf24 5606 } else
14ce26e7
FB
5607#endif
5608 {
5609 ot = dflag ? OT_LONG : OT_WORD;
0af10c86 5610 val = insn_get(env, s, ot);
14ce26e7
FB
5611 reg = (b & 7) | REX_B(s);
5612 gen_op_movl_T0_im(val);
57fec1fe 5613 gen_op_mov_reg_T0(ot, reg);
14ce26e7 5614 }
2c0262af
FB
5615 break;
5616
5617 case 0x91 ... 0x97: /* xchg R, EAX */
7418027e 5618 do_xchg_reg_eax:
14ce26e7
FB
5619 ot = dflag + OT_WORD;
5620 reg = (b & 7) | REX_B(s);
2c0262af
FB
5621 rm = R_EAX;
5622 goto do_xchg_reg;
5623 case 0x86:
5624 case 0x87: /* xchg Ev, Gv */
5625 if ((b & 1) == 0)
5626 ot = OT_BYTE;
5627 else
14ce26e7 5628 ot = dflag + OT_WORD;
0af10c86 5629 modrm = cpu_ldub_code(env, s->pc++);
14ce26e7 5630 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af
FB
5631 mod = (modrm >> 6) & 3;
5632 if (mod == 3) {
14ce26e7 5633 rm = (modrm & 7) | REX_B(s);
2c0262af 5634 do_xchg_reg:
57fec1fe
FB
5635 gen_op_mov_TN_reg(ot, 0, reg);
5636 gen_op_mov_TN_reg(ot, 1, rm);
5637 gen_op_mov_reg_T0(ot, rm);
5638 gen_op_mov_reg_T1(ot, reg);
2c0262af 5639 } else {
0af10c86 5640 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
57fec1fe 5641 gen_op_mov_TN_reg(ot, 0, reg);
2c0262af
FB
5642 /* for xchg, lock is implicit */
5643 if (!(prefixes & PREFIX_LOCK))
a7812ae4 5644 gen_helper_lock();
57fec1fe
FB
5645 gen_op_ld_T1_A0(ot + s->mem_index);
5646 gen_op_st_T0_A0(ot + s->mem_index);
2c0262af 5647 if (!(prefixes & PREFIX_LOCK))
a7812ae4 5648 gen_helper_unlock();
57fec1fe 5649 gen_op_mov_reg_T1(ot, reg);
2c0262af
FB
5650 }
5651 break;
5652 case 0xc4: /* les Gv */
701ed211 5653 /* In CODE64 this is VEX3; see above. */
2c0262af
FB
5654 op = R_ES;
5655 goto do_lxx;
5656 case 0xc5: /* lds Gv */
701ed211 5657 /* In CODE64 this is VEX2; see above. */
2c0262af
FB
5658 op = R_DS;
5659 goto do_lxx;
5660 case 0x1b2: /* lss Gv */
5661 op = R_SS;
5662 goto do_lxx;
5663 case 0x1b4: /* lfs Gv */
5664 op = R_FS;
5665 goto do_lxx;
5666 case 0x1b5: /* lgs Gv */
5667 op = R_GS;
5668 do_lxx:
5669 ot = dflag ? OT_LONG : OT_WORD;
0af10c86 5670 modrm = cpu_ldub_code(env, s->pc++);
14ce26e7 5671 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af
FB
5672 mod = (modrm >> 6) & 3;
5673 if (mod == 3)
5674 goto illegal_op;
0af10c86 5675 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
57fec1fe 5676 gen_op_ld_T1_A0(ot + s->mem_index);
aba9d61e 5677 gen_add_A0_im(s, 1 << (ot - OT_WORD + 1));
2c0262af 5678 /* load the segment first to handle exceptions properly */
57fec1fe 5679 gen_op_ldu_T0_A0(OT_WORD + s->mem_index);
2c0262af
FB
5680 gen_movl_seg_T0(s, op, pc_start - s->cs_base);
5681 /* then put the data */
57fec1fe 5682 gen_op_mov_reg_T1(ot, reg);
2c0262af 5683 if (s->is_jmp) {
14ce26e7 5684 gen_jmp_im(s->pc - s->cs_base);
2c0262af
FB
5685 gen_eob(s);
5686 }
5687 break;
3b46e624 5688
2c0262af
FB
5689 /************************/
5690 /* shifts */
5691 case 0xc0:
5692 case 0xc1:
5693 /* shift Ev,Ib */
5694 shift = 2;
5695 grp2:
5696 {
5697 if ((b & 1) == 0)
5698 ot = OT_BYTE;
5699 else
14ce26e7 5700 ot = dflag + OT_WORD;
3b46e624 5701
0af10c86 5702 modrm = cpu_ldub_code(env, s->pc++);
2c0262af 5703 mod = (modrm >> 6) & 3;
2c0262af 5704 op = (modrm >> 3) & 7;
3b46e624 5705
2c0262af 5706 if (mod != 3) {
14ce26e7
FB
5707 if (shift == 2) {
5708 s->rip_offset = 1;
5709 }
0af10c86 5710 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
2c0262af
FB
5711 opreg = OR_TMP0;
5712 } else {
14ce26e7 5713 opreg = (modrm & 7) | REX_B(s);
2c0262af
FB
5714 }
5715
5716 /* simpler op */
5717 if (shift == 0) {
5718 gen_shift(s, op, ot, opreg, OR_ECX);
5719 } else {
5720 if (shift == 2) {
0af10c86 5721 shift = cpu_ldub_code(env, s->pc++);
2c0262af
FB
5722 }
5723 gen_shifti(s, op, ot, opreg, shift);
5724 }
5725 }
5726 break;
5727 case 0xd0:
5728 case 0xd1:
5729 /* shift Ev,1 */
5730 shift = 1;
5731 goto grp2;
5732 case 0xd2:
5733 case 0xd3:
5734 /* shift Ev,cl */
5735 shift = 0;
5736 goto grp2;
5737
5738 case 0x1a4: /* shld imm */
5739 op = 0;
5740 shift = 1;
5741 goto do_shiftd;
5742 case 0x1a5: /* shld cl */
5743 op = 0;
5744 shift = 0;
5745 goto do_shiftd;
5746 case 0x1ac: /* shrd imm */
5747 op = 1;
5748 shift = 1;
5749 goto do_shiftd;
5750 case 0x1ad: /* shrd cl */
5751 op = 1;
5752 shift = 0;
5753 do_shiftd:
14ce26e7 5754 ot = dflag + OT_WORD;
0af10c86 5755 modrm = cpu_ldub_code(env, s->pc++);
2c0262af 5756 mod = (modrm >> 6) & 3;
14ce26e7
FB
5757 rm = (modrm & 7) | REX_B(s);
5758 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af 5759 if (mod != 3) {
0af10c86 5760 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
b6abf97d 5761 opreg = OR_TMP0;
2c0262af 5762 } else {
b6abf97d 5763 opreg = rm;
2c0262af 5764 }
57fec1fe 5765 gen_op_mov_TN_reg(ot, 1, reg);
3b46e624 5766
2c0262af 5767 if (shift) {
3b9d3cf1
PB
5768 TCGv imm = tcg_const_tl(cpu_ldub_code(env, s->pc++));
5769 gen_shiftd_rm_T1(s, ot, opreg, op, imm);
5770 tcg_temp_free(imm);
2c0262af 5771 } else {
3b9d3cf1 5772 gen_shiftd_rm_T1(s, ot, opreg, op, cpu_regs[R_ECX]);
2c0262af
FB
5773 }
5774 break;
5775
5776 /************************/
5777 /* floats */
5fafdf24 5778 case 0xd8 ... 0xdf:
7eee2a50
FB
5779 if (s->flags & (HF_EM_MASK | HF_TS_MASK)) {
5780 /* if CR0.EM or CR0.TS are set, generate an FPU exception */
5781 /* XXX: what to do if illegal op ? */
5782 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
5783 break;
5784 }
0af10c86 5785 modrm = cpu_ldub_code(env, s->pc++);
2c0262af
FB
5786 mod = (modrm >> 6) & 3;
5787 rm = modrm & 7;
5788 op = ((b & 7) << 3) | ((modrm >> 3) & 7);
2c0262af
FB
5789 if (mod != 3) {
5790 /* memory op */
0af10c86 5791 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
2c0262af
FB
5792 switch(op) {
5793 case 0x00 ... 0x07: /* fxxxs */
5794 case 0x10 ... 0x17: /* fixxxl */
5795 case 0x20 ... 0x27: /* fxxxl */
5796 case 0x30 ... 0x37: /* fixxx */
5797 {
5798 int op1;
5799 op1 = op & 7;
5800
5801 switch(op >> 4) {
5802 case 0:
ba7cd150 5803 gen_op_ld_T0_A0(OT_LONG + s->mem_index);
b6abf97d 5804 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
d3eb5eae 5805 gen_helper_flds_FT0(cpu_env, cpu_tmp2_i32);
2c0262af
FB
5806 break;
5807 case 1:
ba7cd150 5808 gen_op_ld_T0_A0(OT_LONG + s->mem_index);
b6abf97d 5809 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
d3eb5eae 5810 gen_helper_fildl_FT0(cpu_env, cpu_tmp2_i32);
2c0262af
FB
5811 break;
5812 case 2:
b6abf97d 5813 tcg_gen_qemu_ld64(cpu_tmp1_i64, cpu_A0,
19e6c4b8 5814 (s->mem_index >> 2) - 1);
d3eb5eae 5815 gen_helper_fldl_FT0(cpu_env, cpu_tmp1_i64);
2c0262af
FB
5816 break;
5817 case 3:
5818 default:
ba7cd150 5819 gen_op_lds_T0_A0(OT_WORD + s->mem_index);
b6abf97d 5820 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
d3eb5eae 5821 gen_helper_fildl_FT0(cpu_env, cpu_tmp2_i32);
2c0262af
FB
5822 break;
5823 }
3b46e624 5824
a7812ae4 5825 gen_helper_fp_arith_ST0_FT0(op1);
2c0262af
FB
5826 if (op1 == 3) {
5827 /* fcomp needs pop */
d3eb5eae 5828 gen_helper_fpop(cpu_env);
2c0262af
FB
5829 }
5830 }
5831 break;
5832 case 0x08: /* flds */
5833 case 0x0a: /* fsts */
5834 case 0x0b: /* fstps */
465e9838
FB
5835 case 0x18 ... 0x1b: /* fildl, fisttpl, fistl, fistpl */
5836 case 0x28 ... 0x2b: /* fldl, fisttpll, fstl, fstpl */
5837 case 0x38 ... 0x3b: /* filds, fisttps, fists, fistps */
2c0262af
FB
5838 switch(op & 7) {
5839 case 0:
5840 switch(op >> 4) {
5841 case 0:
ba7cd150 5842 gen_op_ld_T0_A0(OT_LONG + s->mem_index);
b6abf97d 5843 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
d3eb5eae 5844 gen_helper_flds_ST0(cpu_env, cpu_tmp2_i32);
2c0262af
FB
5845 break;
5846 case 1:
ba7cd150 5847 gen_op_ld_T0_A0(OT_LONG + s->mem_index);
b6abf97d 5848 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
d3eb5eae 5849 gen_helper_fildl_ST0(cpu_env, cpu_tmp2_i32);
2c0262af
FB
5850 break;
5851 case 2:
b6abf97d 5852 tcg_gen_qemu_ld64(cpu_tmp1_i64, cpu_A0,
19e6c4b8 5853 (s->mem_index >> 2) - 1);
d3eb5eae 5854 gen_helper_fldl_ST0(cpu_env, cpu_tmp1_i64);
2c0262af
FB
5855 break;
5856 case 3:
5857 default:
ba7cd150 5858 gen_op_lds_T0_A0(OT_WORD + s->mem_index);
b6abf97d 5859 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
d3eb5eae 5860 gen_helper_fildl_ST0(cpu_env, cpu_tmp2_i32);
2c0262af
FB
5861 break;
5862 }
5863 break;
465e9838 5864 case 1:
19e6c4b8 5865 /* XXX: the corresponding CPUID bit must be tested ! */
465e9838
FB
5866 switch(op >> 4) {
5867 case 1:
d3eb5eae 5868 gen_helper_fisttl_ST0(cpu_tmp2_i32, cpu_env);
b6abf97d 5869 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
ba7cd150 5870 gen_op_st_T0_A0(OT_LONG + s->mem_index);
465e9838
FB
5871 break;
5872 case 2:
d3eb5eae 5873 gen_helper_fisttll_ST0(cpu_tmp1_i64, cpu_env);
b6abf97d 5874 tcg_gen_qemu_st64(cpu_tmp1_i64, cpu_A0,
19e6c4b8 5875 (s->mem_index >> 2) - 1);
465e9838
FB
5876 break;
5877 case 3:
5878 default:
d3eb5eae 5879 gen_helper_fistt_ST0(cpu_tmp2_i32, cpu_env);
b6abf97d 5880 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
ba7cd150 5881 gen_op_st_T0_A0(OT_WORD + s->mem_index);
19e6c4b8 5882 break;
465e9838 5883 }
d3eb5eae 5884 gen_helper_fpop(cpu_env);
465e9838 5885 break;
2c0262af
FB
5886 default:
5887 switch(op >> 4) {
5888 case 0:
d3eb5eae 5889 gen_helper_fsts_ST0(cpu_tmp2_i32, cpu_env);
b6abf97d 5890 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
ba7cd150 5891 gen_op_st_T0_A0(OT_LONG + s->mem_index);
2c0262af
FB
5892 break;
5893 case 1:
d3eb5eae 5894 gen_helper_fistl_ST0(cpu_tmp2_i32, cpu_env);
b6abf97d 5895 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
ba7cd150 5896 gen_op_st_T0_A0(OT_LONG + s->mem_index);
2c0262af
FB
5897 break;
5898 case 2:
d3eb5eae 5899 gen_helper_fstl_ST0(cpu_tmp1_i64, cpu_env);
b6abf97d 5900 tcg_gen_qemu_st64(cpu_tmp1_i64, cpu_A0,
19e6c4b8 5901 (s->mem_index >> 2) - 1);
2c0262af
FB
5902 break;
5903 case 3:
5904 default:
d3eb5eae 5905 gen_helper_fist_ST0(cpu_tmp2_i32, cpu_env);
b6abf97d 5906 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
ba7cd150 5907 gen_op_st_T0_A0(OT_WORD + s->mem_index);
2c0262af
FB
5908 break;
5909 }
5910 if ((op & 7) == 3)
d3eb5eae 5911 gen_helper_fpop(cpu_env);
2c0262af
FB
5912 break;
5913 }
5914 break;
5915 case 0x0c: /* fldenv mem */
773cdfcc 5916 gen_update_cc_op(s);
19e6c4b8 5917 gen_jmp_im(pc_start - s->cs_base);
d3eb5eae 5918 gen_helper_fldenv(cpu_env, cpu_A0, tcg_const_i32(s->dflag));
2c0262af
FB
5919 break;
5920 case 0x0d: /* fldcw mem */
19e6c4b8 5921 gen_op_ld_T0_A0(OT_WORD + s->mem_index);
b6abf97d 5922 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
d3eb5eae 5923 gen_helper_fldcw(cpu_env, cpu_tmp2_i32);
2c0262af
FB
5924 break;
5925 case 0x0e: /* fnstenv mem */
773cdfcc 5926 gen_update_cc_op(s);
19e6c4b8 5927 gen_jmp_im(pc_start - s->cs_base);
d3eb5eae 5928 gen_helper_fstenv(cpu_env, cpu_A0, tcg_const_i32(s->dflag));
2c0262af
FB
5929 break;
5930 case 0x0f: /* fnstcw mem */
d3eb5eae 5931 gen_helper_fnstcw(cpu_tmp2_i32, cpu_env);
b6abf97d 5932 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
19e6c4b8 5933 gen_op_st_T0_A0(OT_WORD + s->mem_index);
2c0262af
FB
5934 break;
5935 case 0x1d: /* fldt mem */
773cdfcc 5936 gen_update_cc_op(s);
19e6c4b8 5937 gen_jmp_im(pc_start - s->cs_base);
d3eb5eae 5938 gen_helper_fldt_ST0(cpu_env, cpu_A0);
2c0262af
FB
5939 break;
5940 case 0x1f: /* fstpt mem */
773cdfcc 5941 gen_update_cc_op(s);
19e6c4b8 5942 gen_jmp_im(pc_start - s->cs_base);
d3eb5eae
BS
5943 gen_helper_fstt_ST0(cpu_env, cpu_A0);
5944 gen_helper_fpop(cpu_env);
2c0262af
FB
5945 break;
5946 case 0x2c: /* frstor mem */
773cdfcc 5947 gen_update_cc_op(s);
19e6c4b8 5948 gen_jmp_im(pc_start - s->cs_base);
d3eb5eae 5949 gen_helper_frstor(cpu_env, cpu_A0, tcg_const_i32(s->dflag));
2c0262af
FB
5950 break;
5951 case 0x2e: /* fnsave mem */
773cdfcc 5952 gen_update_cc_op(s);
19e6c4b8 5953 gen_jmp_im(pc_start - s->cs_base);
d3eb5eae 5954 gen_helper_fsave(cpu_env, cpu_A0, tcg_const_i32(s->dflag));
2c0262af
FB
5955 break;
5956 case 0x2f: /* fnstsw mem */
d3eb5eae 5957 gen_helper_fnstsw(cpu_tmp2_i32, cpu_env);
b6abf97d 5958 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
19e6c4b8 5959 gen_op_st_T0_A0(OT_WORD + s->mem_index);
2c0262af
FB
5960 break;
5961 case 0x3c: /* fbld */
773cdfcc 5962 gen_update_cc_op(s);
19e6c4b8 5963 gen_jmp_im(pc_start - s->cs_base);
d3eb5eae 5964 gen_helper_fbld_ST0(cpu_env, cpu_A0);
2c0262af
FB
5965 break;
5966 case 0x3e: /* fbstp */
773cdfcc 5967 gen_update_cc_op(s);
19e6c4b8 5968 gen_jmp_im(pc_start - s->cs_base);
d3eb5eae
BS
5969 gen_helper_fbst_ST0(cpu_env, cpu_A0);
5970 gen_helper_fpop(cpu_env);
2c0262af
FB
5971 break;
5972 case 0x3d: /* fildll */
b6abf97d 5973 tcg_gen_qemu_ld64(cpu_tmp1_i64, cpu_A0,
19e6c4b8 5974 (s->mem_index >> 2) - 1);
d3eb5eae 5975 gen_helper_fildll_ST0(cpu_env, cpu_tmp1_i64);
2c0262af
FB
5976 break;
5977 case 0x3f: /* fistpll */
d3eb5eae 5978 gen_helper_fistll_ST0(cpu_tmp1_i64, cpu_env);
b6abf97d 5979 tcg_gen_qemu_st64(cpu_tmp1_i64, cpu_A0,
19e6c4b8 5980 (s->mem_index >> 2) - 1);
d3eb5eae 5981 gen_helper_fpop(cpu_env);
2c0262af
FB
5982 break;
5983 default:
5984 goto illegal_op;
5985 }
5986 } else {
5987 /* register float ops */
5988 opreg = rm;
5989
5990 switch(op) {
5991 case 0x08: /* fld sti */
d3eb5eae
BS
5992 gen_helper_fpush(cpu_env);
5993 gen_helper_fmov_ST0_STN(cpu_env,
5994 tcg_const_i32((opreg + 1) & 7));
2c0262af
FB
5995 break;
5996 case 0x09: /* fxchg sti */
c169c906
FB
5997 case 0x29: /* fxchg4 sti, undocumented op */
5998 case 0x39: /* fxchg7 sti, undocumented op */
d3eb5eae 5999 gen_helper_fxchg_ST0_STN(cpu_env, tcg_const_i32(opreg));
2c0262af
FB
6000 break;
6001 case 0x0a: /* grp d9/2 */
6002 switch(rm) {
6003 case 0: /* fnop */
023fe10d 6004 /* check exceptions (FreeBSD FPU probe) */
773cdfcc 6005 gen_update_cc_op(s);
14ce26e7 6006 gen_jmp_im(pc_start - s->cs_base);
d3eb5eae 6007 gen_helper_fwait(cpu_env);
2c0262af
FB
6008 break;
6009 default:
6010 goto illegal_op;
6011 }
6012 break;
6013 case 0x0c: /* grp d9/4 */
6014 switch(rm) {
6015 case 0: /* fchs */
d3eb5eae 6016 gen_helper_fchs_ST0(cpu_env);
2c0262af
FB
6017 break;
6018 case 1: /* fabs */
d3eb5eae 6019 gen_helper_fabs_ST0(cpu_env);
2c0262af
FB
6020 break;
6021 case 4: /* ftst */
d3eb5eae
BS
6022 gen_helper_fldz_FT0(cpu_env);
6023 gen_helper_fcom_ST0_FT0(cpu_env);
2c0262af
FB
6024 break;
6025 case 5: /* fxam */
d3eb5eae 6026 gen_helper_fxam_ST0(cpu_env);
2c0262af
FB
6027 break;
6028 default:
6029 goto illegal_op;
6030 }
6031 break;
6032 case 0x0d: /* grp d9/5 */
6033 {
6034 switch(rm) {
6035 case 0:
d3eb5eae
BS
6036 gen_helper_fpush(cpu_env);
6037 gen_helper_fld1_ST0(cpu_env);
2c0262af
FB
6038 break;
6039 case 1:
d3eb5eae
BS
6040 gen_helper_fpush(cpu_env);
6041 gen_helper_fldl2t_ST0(cpu_env);
2c0262af
FB
6042 break;
6043 case 2:
d3eb5eae
BS
6044 gen_helper_fpush(cpu_env);
6045 gen_helper_fldl2e_ST0(cpu_env);
2c0262af
FB
6046 break;
6047 case 3:
d3eb5eae
BS
6048 gen_helper_fpush(cpu_env);
6049 gen_helper_fldpi_ST0(cpu_env);
2c0262af
FB
6050 break;
6051 case 4:
d3eb5eae
BS
6052 gen_helper_fpush(cpu_env);
6053 gen_helper_fldlg2_ST0(cpu_env);
2c0262af
FB
6054 break;
6055 case 5:
d3eb5eae
BS
6056 gen_helper_fpush(cpu_env);
6057 gen_helper_fldln2_ST0(cpu_env);
2c0262af
FB
6058 break;
6059 case 6:
d3eb5eae
BS
6060 gen_helper_fpush(cpu_env);
6061 gen_helper_fldz_ST0(cpu_env);
2c0262af
FB
6062 break;
6063 default:
6064 goto illegal_op;
6065 }
6066 }
6067 break;
6068 case 0x0e: /* grp d9/6 */
6069 switch(rm) {
6070 case 0: /* f2xm1 */
d3eb5eae 6071 gen_helper_f2xm1(cpu_env);
2c0262af
FB
6072 break;
6073 case 1: /* fyl2x */
d3eb5eae 6074 gen_helper_fyl2x(cpu_env);
2c0262af
FB
6075 break;
6076 case 2: /* fptan */
d3eb5eae 6077 gen_helper_fptan(cpu_env);
2c0262af
FB
6078 break;
6079 case 3: /* fpatan */
d3eb5eae 6080 gen_helper_fpatan(cpu_env);
2c0262af
FB
6081 break;
6082 case 4: /* fxtract */
d3eb5eae 6083 gen_helper_fxtract(cpu_env);
2c0262af
FB
6084 break;
6085 case 5: /* fprem1 */
d3eb5eae 6086 gen_helper_fprem1(cpu_env);
2c0262af
FB
6087 break;
6088 case 6: /* fdecstp */
d3eb5eae 6089 gen_helper_fdecstp(cpu_env);
2c0262af
FB
6090 break;
6091 default:
6092 case 7: /* fincstp */
d3eb5eae 6093 gen_helper_fincstp(cpu_env);
2c0262af
FB
6094 break;
6095 }
6096 break;
6097 case 0x0f: /* grp d9/7 */
6098 switch(rm) {
6099 case 0: /* fprem */
d3eb5eae 6100 gen_helper_fprem(cpu_env);
2c0262af
FB
6101 break;
6102 case 1: /* fyl2xp1 */
d3eb5eae 6103 gen_helper_fyl2xp1(cpu_env);
2c0262af
FB
6104 break;
6105 case 2: /* fsqrt */
d3eb5eae 6106 gen_helper_fsqrt(cpu_env);
2c0262af
FB
6107 break;
6108 case 3: /* fsincos */
d3eb5eae 6109 gen_helper_fsincos(cpu_env);
2c0262af
FB
6110 break;
6111 case 5: /* fscale */
d3eb5eae 6112 gen_helper_fscale(cpu_env);
2c0262af
FB
6113 break;
6114 case 4: /* frndint */
d3eb5eae 6115 gen_helper_frndint(cpu_env);
2c0262af
FB
6116 break;
6117 case 6: /* fsin */
d3eb5eae 6118 gen_helper_fsin(cpu_env);
2c0262af
FB
6119 break;
6120 default:
6121 case 7: /* fcos */
d3eb5eae 6122 gen_helper_fcos(cpu_env);
2c0262af
FB
6123 break;
6124 }
6125 break;
6126 case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
6127 case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
6128 case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
6129 {
6130 int op1;
3b46e624 6131
2c0262af
FB
6132 op1 = op & 7;
6133 if (op >= 0x20) {
a7812ae4 6134 gen_helper_fp_arith_STN_ST0(op1, opreg);
2c0262af 6135 if (op >= 0x30)
d3eb5eae 6136 gen_helper_fpop(cpu_env);
2c0262af 6137 } else {
d3eb5eae 6138 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
a7812ae4 6139 gen_helper_fp_arith_ST0_FT0(op1);
2c0262af
FB
6140 }
6141 }
6142 break;
6143 case 0x02: /* fcom */
c169c906 6144 case 0x22: /* fcom2, undocumented op */
d3eb5eae
BS
6145 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6146 gen_helper_fcom_ST0_FT0(cpu_env);
2c0262af
FB
6147 break;
6148 case 0x03: /* fcomp */
c169c906
FB
6149 case 0x23: /* fcomp3, undocumented op */
6150 case 0x32: /* fcomp5, undocumented op */
d3eb5eae
BS
6151 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6152 gen_helper_fcom_ST0_FT0(cpu_env);
6153 gen_helper_fpop(cpu_env);
2c0262af
FB
6154 break;
6155 case 0x15: /* da/5 */
6156 switch(rm) {
6157 case 1: /* fucompp */
d3eb5eae
BS
6158 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(1));
6159 gen_helper_fucom_ST0_FT0(cpu_env);
6160 gen_helper_fpop(cpu_env);
6161 gen_helper_fpop(cpu_env);
2c0262af
FB
6162 break;
6163 default:
6164 goto illegal_op;
6165 }
6166 break;
6167 case 0x1c:
6168 switch(rm) {
6169 case 0: /* feni (287 only, just do nop here) */
6170 break;
6171 case 1: /* fdisi (287 only, just do nop here) */
6172 break;
6173 case 2: /* fclex */
d3eb5eae 6174 gen_helper_fclex(cpu_env);
2c0262af
FB
6175 break;
6176 case 3: /* fninit */
d3eb5eae 6177 gen_helper_fninit(cpu_env);
2c0262af
FB
6178 break;
6179 case 4: /* fsetpm (287 only, just do nop here) */
6180 break;
6181 default:
6182 goto illegal_op;
6183 }
6184 break;
6185 case 0x1d: /* fucomi */
773cdfcc 6186 gen_update_cc_op(s);
d3eb5eae
BS
6187 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6188 gen_helper_fucomi_ST0_FT0(cpu_env);
3ca51d07 6189 set_cc_op(s, CC_OP_EFLAGS);
2c0262af
FB
6190 break;
6191 case 0x1e: /* fcomi */
773cdfcc 6192 gen_update_cc_op(s);
d3eb5eae
BS
6193 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6194 gen_helper_fcomi_ST0_FT0(cpu_env);
3ca51d07 6195 set_cc_op(s, CC_OP_EFLAGS);
2c0262af 6196 break;
658c8bda 6197 case 0x28: /* ffree sti */
d3eb5eae 6198 gen_helper_ffree_STN(cpu_env, tcg_const_i32(opreg));
5fafdf24 6199 break;
2c0262af 6200 case 0x2a: /* fst sti */
d3eb5eae 6201 gen_helper_fmov_STN_ST0(cpu_env, tcg_const_i32(opreg));
2c0262af
FB
6202 break;
6203 case 0x2b: /* fstp sti */
c169c906
FB
6204 case 0x0b: /* fstp1 sti, undocumented op */
6205 case 0x3a: /* fstp8 sti, undocumented op */
6206 case 0x3b: /* fstp9 sti, undocumented op */
d3eb5eae
BS
6207 gen_helper_fmov_STN_ST0(cpu_env, tcg_const_i32(opreg));
6208 gen_helper_fpop(cpu_env);
2c0262af
FB
6209 break;
6210 case 0x2c: /* fucom st(i) */
d3eb5eae
BS
6211 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6212 gen_helper_fucom_ST0_FT0(cpu_env);
2c0262af
FB
6213 break;
6214 case 0x2d: /* fucomp st(i) */
d3eb5eae
BS
6215 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6216 gen_helper_fucom_ST0_FT0(cpu_env);
6217 gen_helper_fpop(cpu_env);
2c0262af
FB
6218 break;
6219 case 0x33: /* de/3 */
6220 switch(rm) {
6221 case 1: /* fcompp */
d3eb5eae
BS
6222 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(1));
6223 gen_helper_fcom_ST0_FT0(cpu_env);
6224 gen_helper_fpop(cpu_env);
6225 gen_helper_fpop(cpu_env);
2c0262af
FB
6226 break;
6227 default:
6228 goto illegal_op;
6229 }
6230 break;
c169c906 6231 case 0x38: /* ffreep sti, undocumented op */
d3eb5eae
BS
6232 gen_helper_ffree_STN(cpu_env, tcg_const_i32(opreg));
6233 gen_helper_fpop(cpu_env);
c169c906 6234 break;
2c0262af
FB
6235 case 0x3c: /* df/4 */
6236 switch(rm) {
6237 case 0:
d3eb5eae 6238 gen_helper_fnstsw(cpu_tmp2_i32, cpu_env);
b6abf97d 6239 tcg_gen_extu_i32_tl(cpu_T[0], cpu_tmp2_i32);
19e6c4b8 6240 gen_op_mov_reg_T0(OT_WORD, R_EAX);
2c0262af
FB
6241 break;
6242 default:
6243 goto illegal_op;
6244 }
6245 break;
6246 case 0x3d: /* fucomip */
773cdfcc 6247 gen_update_cc_op(s);
d3eb5eae
BS
6248 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6249 gen_helper_fucomi_ST0_FT0(cpu_env);
6250 gen_helper_fpop(cpu_env);
3ca51d07 6251 set_cc_op(s, CC_OP_EFLAGS);
2c0262af
FB
6252 break;
6253 case 0x3e: /* fcomip */
773cdfcc 6254 gen_update_cc_op(s);
d3eb5eae
BS
6255 gen_helper_fmov_FT0_STN(cpu_env, tcg_const_i32(opreg));
6256 gen_helper_fcomi_ST0_FT0(cpu_env);
6257 gen_helper_fpop(cpu_env);
3ca51d07 6258 set_cc_op(s, CC_OP_EFLAGS);
2c0262af 6259 break;
a2cc3b24
FB
6260 case 0x10 ... 0x13: /* fcmovxx */
6261 case 0x18 ... 0x1b:
6262 {
19e6c4b8 6263 int op1, l1;
d70040bc 6264 static const uint8_t fcmov_cc[8] = {
a2cc3b24
FB
6265 (JCC_B << 1),
6266 (JCC_Z << 1),
6267 (JCC_BE << 1),
6268 (JCC_P << 1),
6269 };
1e4840bf 6270 op1 = fcmov_cc[op & 3] | (((op >> 3) & 1) ^ 1);
19e6c4b8 6271 l1 = gen_new_label();
dc259201 6272 gen_jcc1_noeob(s, op1, l1);
d3eb5eae 6273 gen_helper_fmov_ST0_STN(cpu_env, tcg_const_i32(opreg));
19e6c4b8 6274 gen_set_label(l1);
a2cc3b24
FB
6275 }
6276 break;
2c0262af
FB
6277 default:
6278 goto illegal_op;
6279 }
6280 }
6281 break;
6282 /************************/
6283 /* string ops */
6284
6285 case 0xa4: /* movsS */
6286 case 0xa5:
6287 if ((b & 1) == 0)
6288 ot = OT_BYTE;
6289 else
14ce26e7 6290 ot = dflag + OT_WORD;
2c0262af
FB
6291
6292 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6293 gen_repz_movs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6294 } else {
6295 gen_movs(s, ot);
6296 }
6297 break;
3b46e624 6298
2c0262af
FB
6299 case 0xaa: /* stosS */
6300 case 0xab:
6301 if ((b & 1) == 0)
6302 ot = OT_BYTE;
6303 else
14ce26e7 6304 ot = dflag + OT_WORD;
2c0262af
FB
6305
6306 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6307 gen_repz_stos(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6308 } else {
6309 gen_stos(s, ot);
6310 }
6311 break;
6312 case 0xac: /* lodsS */
6313 case 0xad:
6314 if ((b & 1) == 0)
6315 ot = OT_BYTE;
6316 else
14ce26e7 6317 ot = dflag + OT_WORD;
2c0262af
FB
6318 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6319 gen_repz_lods(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
6320 } else {
6321 gen_lods(s, ot);
6322 }
6323 break;
6324 case 0xae: /* scasS */
6325 case 0xaf:
6326 if ((b & 1) == 0)
6327 ot = OT_BYTE;
6328 else
14ce26e7 6329 ot = dflag + OT_WORD;
2c0262af
FB
6330 if (prefixes & PREFIX_REPNZ) {
6331 gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
6332 } else if (prefixes & PREFIX_REPZ) {
6333 gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
6334 } else {
6335 gen_scas(s, ot);
2c0262af
FB
6336 }
6337 break;
6338
6339 case 0xa6: /* cmpsS */
6340 case 0xa7:
6341 if ((b & 1) == 0)
6342 ot = OT_BYTE;
6343 else
14ce26e7 6344 ot = dflag + OT_WORD;
2c0262af
FB
6345 if (prefixes & PREFIX_REPNZ) {
6346 gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
6347 } else if (prefixes & PREFIX_REPZ) {
6348 gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
6349 } else {
6350 gen_cmps(s, ot);
2c0262af
FB
6351 }
6352 break;
6353 case 0x6c: /* insS */
6354 case 0x6d:
f115e911
FB
6355 if ((b & 1) == 0)
6356 ot = OT_BYTE;
6357 else
6358 ot = dflag ? OT_LONG : OT_WORD;
57fec1fe 6359 gen_op_mov_TN_reg(OT_WORD, 0, R_EDX);
0573fbfc 6360 gen_op_andl_T0_ffff();
b8b6a50b
FB
6361 gen_check_io(s, ot, pc_start - s->cs_base,
6362 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes) | 4);
f115e911
FB
6363 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6364 gen_repz_ins(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
2c0262af 6365 } else {
f115e911 6366 gen_ins(s, ot);
2e70f6ef
PB
6367 if (use_icount) {
6368 gen_jmp(s, s->pc - s->cs_base);
6369 }
2c0262af
FB
6370 }
6371 break;
6372 case 0x6e: /* outsS */
6373 case 0x6f:
f115e911
FB
6374 if ((b & 1) == 0)
6375 ot = OT_BYTE;
6376 else
6377 ot = dflag ? OT_LONG : OT_WORD;
57fec1fe 6378 gen_op_mov_TN_reg(OT_WORD, 0, R_EDX);
0573fbfc 6379 gen_op_andl_T0_ffff();
b8b6a50b
FB
6380 gen_check_io(s, ot, pc_start - s->cs_base,
6381 svm_is_rep(prefixes) | 4);
f115e911
FB
6382 if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
6383 gen_repz_outs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
2c0262af 6384 } else {
f115e911 6385 gen_outs(s, ot);
2e70f6ef
PB
6386 if (use_icount) {
6387 gen_jmp(s, s->pc - s->cs_base);
6388 }
2c0262af
FB
6389 }
6390 break;
6391
6392 /************************/
6393 /* port I/O */
0573fbfc 6394
2c0262af
FB
6395 case 0xe4:
6396 case 0xe5:
f115e911
FB
6397 if ((b & 1) == 0)
6398 ot = OT_BYTE;
6399 else
6400 ot = dflag ? OT_LONG : OT_WORD;
0af10c86 6401 val = cpu_ldub_code(env, s->pc++);
f115e911 6402 gen_op_movl_T0_im(val);
b8b6a50b
FB
6403 gen_check_io(s, ot, pc_start - s->cs_base,
6404 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes));
2e70f6ef
PB
6405 if (use_icount)
6406 gen_io_start();
b6abf97d 6407 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
a7812ae4 6408 gen_helper_in_func(ot, cpu_T[1], cpu_tmp2_i32);
57fec1fe 6409 gen_op_mov_reg_T1(ot, R_EAX);
2e70f6ef
PB
6410 if (use_icount) {
6411 gen_io_end();
6412 gen_jmp(s, s->pc - s->cs_base);
6413 }
2c0262af
FB
6414 break;
6415 case 0xe6:
6416 case 0xe7:
f115e911
FB
6417 if ((b & 1) == 0)
6418 ot = OT_BYTE;
6419 else
6420 ot = dflag ? OT_LONG : OT_WORD;
0af10c86 6421 val = cpu_ldub_code(env, s->pc++);
f115e911 6422 gen_op_movl_T0_im(val);
b8b6a50b
FB
6423 gen_check_io(s, ot, pc_start - s->cs_base,
6424 svm_is_rep(prefixes));
57fec1fe 6425 gen_op_mov_TN_reg(ot, 1, R_EAX);
b8b6a50b 6426
2e70f6ef
PB
6427 if (use_icount)
6428 gen_io_start();
b6abf97d 6429 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
b6abf97d 6430 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T[1]);
a7812ae4 6431 gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32);
2e70f6ef
PB
6432 if (use_icount) {
6433 gen_io_end();
6434 gen_jmp(s, s->pc - s->cs_base);
6435 }
2c0262af
FB
6436 break;
6437 case 0xec:
6438 case 0xed:
f115e911
FB
6439 if ((b & 1) == 0)
6440 ot = OT_BYTE;
6441 else
6442 ot = dflag ? OT_LONG : OT_WORD;
57fec1fe 6443 gen_op_mov_TN_reg(OT_WORD, 0, R_EDX);
4f31916f 6444 gen_op_andl_T0_ffff();
b8b6a50b
FB
6445 gen_check_io(s, ot, pc_start - s->cs_base,
6446 SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes));
2e70f6ef
PB
6447 if (use_icount)
6448 gen_io_start();
b6abf97d 6449 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
a7812ae4 6450 gen_helper_in_func(ot, cpu_T[1], cpu_tmp2_i32);
57fec1fe 6451 gen_op_mov_reg_T1(ot, R_EAX);
2e70f6ef
PB
6452 if (use_icount) {
6453 gen_io_end();
6454 gen_jmp(s, s->pc - s->cs_base);
6455 }
2c0262af
FB
6456 break;
6457 case 0xee:
6458 case 0xef:
f115e911
FB
6459 if ((b & 1) == 0)
6460 ot = OT_BYTE;
6461 else
6462 ot = dflag ? OT_LONG : OT_WORD;
57fec1fe 6463 gen_op_mov_TN_reg(OT_WORD, 0, R_EDX);
4f31916f 6464 gen_op_andl_T0_ffff();
b8b6a50b
FB
6465 gen_check_io(s, ot, pc_start - s->cs_base,
6466 svm_is_rep(prefixes));
57fec1fe 6467 gen_op_mov_TN_reg(ot, 1, R_EAX);
b8b6a50b 6468
2e70f6ef
PB
6469 if (use_icount)
6470 gen_io_start();
b6abf97d 6471 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
b6abf97d 6472 tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T[1]);
a7812ae4 6473 gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32);
2e70f6ef
PB
6474 if (use_icount) {
6475 gen_io_end();
6476 gen_jmp(s, s->pc - s->cs_base);
6477 }
2c0262af
FB
6478 break;
6479
6480 /************************/
6481 /* control */
6482 case 0xc2: /* ret im */
0af10c86 6483 val = cpu_ldsw_code(env, s->pc);
2c0262af
FB
6484 s->pc += 2;
6485 gen_pop_T0(s);
8f091a59
FB
6486 if (CODE64(s) && s->dflag)
6487 s->dflag = 2;
2c0262af
FB
6488 gen_stack_update(s, val + (2 << s->dflag));
6489 if (s->dflag == 0)
6490 gen_op_andl_T0_ffff();
6491 gen_op_jmp_T0();
6492 gen_eob(s);
6493 break;
6494 case 0xc3: /* ret */
6495 gen_pop_T0(s);
6496 gen_pop_update(s);
6497 if (s->dflag == 0)
6498 gen_op_andl_T0_ffff();
6499 gen_op_jmp_T0();
6500 gen_eob(s);
6501 break;
6502 case 0xca: /* lret im */
0af10c86 6503 val = cpu_ldsw_code(env, s->pc);
2c0262af
FB
6504 s->pc += 2;
6505 do_lret:
6506 if (s->pe && !s->vm86) {
773cdfcc 6507 gen_update_cc_op(s);
14ce26e7 6508 gen_jmp_im(pc_start - s->cs_base);
2999a0b2 6509 gen_helper_lret_protected(cpu_env, tcg_const_i32(s->dflag),
a7812ae4 6510 tcg_const_i32(val));
2c0262af
FB
6511 } else {
6512 gen_stack_A0(s);
6513 /* pop offset */
57fec1fe 6514 gen_op_ld_T0_A0(1 + s->dflag + s->mem_index);
2c0262af
FB
6515 if (s->dflag == 0)
6516 gen_op_andl_T0_ffff();
6517 /* NOTE: keeping EIP updated is not a problem in case of
6518 exception */
6519 gen_op_jmp_T0();
6520 /* pop selector */
6521 gen_op_addl_A0_im(2 << s->dflag);
57fec1fe 6522 gen_op_ld_T0_A0(1 + s->dflag + s->mem_index);
3bd7da9e 6523 gen_op_movl_seg_T0_vm(R_CS);
2c0262af
FB
6524 /* add stack offset */
6525 gen_stack_update(s, val + (4 << s->dflag));
6526 }
6527 gen_eob(s);
6528 break;
6529 case 0xcb: /* lret */
6530 val = 0;
6531 goto do_lret;
6532 case 0xcf: /* iret */
872929aa 6533 gen_svm_check_intercept(s, pc_start, SVM_EXIT_IRET);
2c0262af
FB
6534 if (!s->pe) {
6535 /* real mode */
2999a0b2 6536 gen_helper_iret_real(cpu_env, tcg_const_i32(s->dflag));
3ca51d07 6537 set_cc_op(s, CC_OP_EFLAGS);
f115e911
FB
6538 } else if (s->vm86) {
6539 if (s->iopl != 3) {
6540 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6541 } else {
2999a0b2 6542 gen_helper_iret_real(cpu_env, tcg_const_i32(s->dflag));
3ca51d07 6543 set_cc_op(s, CC_OP_EFLAGS);
f115e911 6544 }
2c0262af 6545 } else {
773cdfcc 6546 gen_update_cc_op(s);
14ce26e7 6547 gen_jmp_im(pc_start - s->cs_base);
2999a0b2 6548 gen_helper_iret_protected(cpu_env, tcg_const_i32(s->dflag),
a7812ae4 6549 tcg_const_i32(s->pc - s->cs_base));
3ca51d07 6550 set_cc_op(s, CC_OP_EFLAGS);
2c0262af
FB
6551 }
6552 gen_eob(s);
6553 break;
6554 case 0xe8: /* call im */
6555 {
14ce26e7 6556 if (dflag)
0af10c86 6557 tval = (int32_t)insn_get(env, s, OT_LONG);
14ce26e7 6558 else
0af10c86 6559 tval = (int16_t)insn_get(env, s, OT_WORD);
2c0262af 6560 next_eip = s->pc - s->cs_base;
14ce26e7 6561 tval += next_eip;
2c0262af 6562 if (s->dflag == 0)
14ce26e7 6563 tval &= 0xffff;
99596385
AJ
6564 else if(!CODE64(s))
6565 tval &= 0xffffffff;
14ce26e7 6566 gen_movtl_T0_im(next_eip);
2c0262af 6567 gen_push_T0(s);
14ce26e7 6568 gen_jmp(s, tval);
2c0262af
FB
6569 }
6570 break;
6571 case 0x9a: /* lcall im */
6572 {
6573 unsigned int selector, offset;
3b46e624 6574
14ce26e7
FB
6575 if (CODE64(s))
6576 goto illegal_op;
2c0262af 6577 ot = dflag ? OT_LONG : OT_WORD;
0af10c86
BS
6578 offset = insn_get(env, s, ot);
6579 selector = insn_get(env, s, OT_WORD);
3b46e624 6580
2c0262af 6581 gen_op_movl_T0_im(selector);
14ce26e7 6582 gen_op_movl_T1_imu(offset);
2c0262af
FB
6583 }
6584 goto do_lcall;
ecada8a2 6585 case 0xe9: /* jmp im */
14ce26e7 6586 if (dflag)
0af10c86 6587 tval = (int32_t)insn_get(env, s, OT_LONG);
14ce26e7 6588 else
0af10c86 6589 tval = (int16_t)insn_get(env, s, OT_WORD);
14ce26e7 6590 tval += s->pc - s->cs_base;
2c0262af 6591 if (s->dflag == 0)
14ce26e7 6592 tval &= 0xffff;
32938e12
AJ
6593 else if(!CODE64(s))
6594 tval &= 0xffffffff;
14ce26e7 6595 gen_jmp(s, tval);
2c0262af
FB
6596 break;
6597 case 0xea: /* ljmp im */
6598 {
6599 unsigned int selector, offset;
6600
14ce26e7
FB
6601 if (CODE64(s))
6602 goto illegal_op;
2c0262af 6603 ot = dflag ? OT_LONG : OT_WORD;
0af10c86
BS
6604 offset = insn_get(env, s, ot);
6605 selector = insn_get(env, s, OT_WORD);
3b46e624 6606
2c0262af 6607 gen_op_movl_T0_im(selector);
14ce26e7 6608 gen_op_movl_T1_imu(offset);
2c0262af
FB
6609 }
6610 goto do_ljmp;
6611 case 0xeb: /* jmp Jb */
0af10c86 6612 tval = (int8_t)insn_get(env, s, OT_BYTE);
14ce26e7 6613 tval += s->pc - s->cs_base;
2c0262af 6614 if (s->dflag == 0)
14ce26e7
FB
6615 tval &= 0xffff;
6616 gen_jmp(s, tval);
2c0262af
FB
6617 break;
6618 case 0x70 ... 0x7f: /* jcc Jb */
0af10c86 6619 tval = (int8_t)insn_get(env, s, OT_BYTE);
2c0262af
FB
6620 goto do_jcc;
6621 case 0x180 ... 0x18f: /* jcc Jv */
6622 if (dflag) {
0af10c86 6623 tval = (int32_t)insn_get(env, s, OT_LONG);
2c0262af 6624 } else {
0af10c86 6625 tval = (int16_t)insn_get(env, s, OT_WORD);
2c0262af
FB
6626 }
6627 do_jcc:
6628 next_eip = s->pc - s->cs_base;
14ce26e7 6629 tval += next_eip;
2c0262af 6630 if (s->dflag == 0)
14ce26e7
FB
6631 tval &= 0xffff;
6632 gen_jcc(s, b, tval, next_eip);
2c0262af
FB
6633 break;
6634
6635 case 0x190 ... 0x19f: /* setcc Gv */
0af10c86 6636 modrm = cpu_ldub_code(env, s->pc++);
cc8b6f5b 6637 gen_setcc1(s, b, cpu_T[0]);
0af10c86 6638 gen_ldst_modrm(env, s, modrm, OT_BYTE, OR_TMP0, 1);
2c0262af
FB
6639 break;
6640 case 0x140 ... 0x14f: /* cmov Gv, Ev */
f32d3781
PB
6641 ot = dflag + OT_WORD;
6642 modrm = cpu_ldub_code(env, s->pc++);
6643 reg = ((modrm >> 3) & 7) | rex_r;
6644 gen_cmovcc1(env, s, ot, b, modrm, reg);
2c0262af 6645 break;
3b46e624 6646
2c0262af
FB
6647 /************************/
6648 /* flags */
6649 case 0x9c: /* pushf */
872929aa 6650 gen_svm_check_intercept(s, pc_start, SVM_EXIT_PUSHF);
2c0262af
FB
6651 if (s->vm86 && s->iopl != 3) {
6652 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6653 } else {
773cdfcc 6654 gen_update_cc_op(s);
f0967a1a 6655 gen_helper_read_eflags(cpu_T[0], cpu_env);
2c0262af
FB
6656 gen_push_T0(s);
6657 }
6658 break;
6659 case 0x9d: /* popf */
872929aa 6660 gen_svm_check_intercept(s, pc_start, SVM_EXIT_POPF);
2c0262af
FB
6661 if (s->vm86 && s->iopl != 3) {
6662 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6663 } else {
6664 gen_pop_T0(s);
6665 if (s->cpl == 0) {
6666 if (s->dflag) {
f0967a1a
BS
6667 gen_helper_write_eflags(cpu_env, cpu_T[0],
6668 tcg_const_i32((TF_MASK | AC_MASK |
6669 ID_MASK | NT_MASK |
6670 IF_MASK |
6671 IOPL_MASK)));
2c0262af 6672 } else {
f0967a1a
BS
6673 gen_helper_write_eflags(cpu_env, cpu_T[0],
6674 tcg_const_i32((TF_MASK | AC_MASK |
6675 ID_MASK | NT_MASK |
6676 IF_MASK | IOPL_MASK)
6677 & 0xffff));
2c0262af
FB
6678 }
6679 } else {
4136f33c
FB
6680 if (s->cpl <= s->iopl) {
6681 if (s->dflag) {
f0967a1a
BS
6682 gen_helper_write_eflags(cpu_env, cpu_T[0],
6683 tcg_const_i32((TF_MASK |
6684 AC_MASK |
6685 ID_MASK |
6686 NT_MASK |
6687 IF_MASK)));
4136f33c 6688 } else {
f0967a1a
BS
6689 gen_helper_write_eflags(cpu_env, cpu_T[0],
6690 tcg_const_i32((TF_MASK |
6691 AC_MASK |
6692 ID_MASK |
6693 NT_MASK |
6694 IF_MASK)
6695 & 0xffff));
4136f33c 6696 }
2c0262af 6697 } else {
4136f33c 6698 if (s->dflag) {
f0967a1a
BS
6699 gen_helper_write_eflags(cpu_env, cpu_T[0],
6700 tcg_const_i32((TF_MASK | AC_MASK |
6701 ID_MASK | NT_MASK)));
4136f33c 6702 } else {
f0967a1a
BS
6703 gen_helper_write_eflags(cpu_env, cpu_T[0],
6704 tcg_const_i32((TF_MASK | AC_MASK |
6705 ID_MASK | NT_MASK)
6706 & 0xffff));
4136f33c 6707 }
2c0262af
FB
6708 }
6709 }
6710 gen_pop_update(s);
3ca51d07 6711 set_cc_op(s, CC_OP_EFLAGS);
a9321a4d 6712 /* abort translation because TF/AC flag may change */
14ce26e7 6713 gen_jmp_im(s->pc - s->cs_base);
2c0262af
FB
6714 gen_eob(s);
6715 }
6716 break;
6717 case 0x9e: /* sahf */
12e26b75 6718 if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM))
14ce26e7 6719 goto illegal_op;
57fec1fe 6720 gen_op_mov_TN_reg(OT_BYTE, 0, R_AH);
d229edce 6721 gen_compute_eflags(s);
bd7a7b33
FB
6722 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, CC_O);
6723 tcg_gen_andi_tl(cpu_T[0], cpu_T[0], CC_S | CC_Z | CC_A | CC_P | CC_C);
6724 tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, cpu_T[0]);
2c0262af
FB
6725 break;
6726 case 0x9f: /* lahf */
12e26b75 6727 if (CODE64(s) && !(s->cpuid_ext3_features & CPUID_EXT3_LAHF_LM))
14ce26e7 6728 goto illegal_op;
d229edce 6729 gen_compute_eflags(s);
bd7a7b33 6730 /* Note: gen_compute_eflags() only gives the condition codes */
d229edce 6731 tcg_gen_ori_tl(cpu_T[0], cpu_cc_src, 0x02);
57fec1fe 6732 gen_op_mov_reg_T0(OT_BYTE, R_AH);
2c0262af
FB
6733 break;
6734 case 0xf5: /* cmc */
d229edce 6735 gen_compute_eflags(s);
bd7a7b33 6736 tcg_gen_xori_tl(cpu_cc_src, cpu_cc_src, CC_C);
2c0262af
FB
6737 break;
6738 case 0xf8: /* clc */
d229edce 6739 gen_compute_eflags(s);
bd7a7b33 6740 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~CC_C);
2c0262af
FB
6741 break;
6742 case 0xf9: /* stc */
d229edce 6743 gen_compute_eflags(s);
bd7a7b33 6744 tcg_gen_ori_tl(cpu_cc_src, cpu_cc_src, CC_C);
2c0262af
FB
6745 break;
6746 case 0xfc: /* cld */
b6abf97d 6747 tcg_gen_movi_i32(cpu_tmp2_i32, 1);
317ac620 6748 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, offsetof(CPUX86State, df));
2c0262af
FB
6749 break;
6750 case 0xfd: /* std */
b6abf97d 6751 tcg_gen_movi_i32(cpu_tmp2_i32, -1);
317ac620 6752 tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, offsetof(CPUX86State, df));
2c0262af
FB
6753 break;
6754
6755 /************************/
6756 /* bit operations */
6757 case 0x1ba: /* bt/bts/btr/btc Gv, im */
14ce26e7 6758 ot = dflag + OT_WORD;
0af10c86 6759 modrm = cpu_ldub_code(env, s->pc++);
33698e5f 6760 op = (modrm >> 3) & 7;
2c0262af 6761 mod = (modrm >> 6) & 3;
14ce26e7 6762 rm = (modrm & 7) | REX_B(s);
2c0262af 6763 if (mod != 3) {
14ce26e7 6764 s->rip_offset = 1;
0af10c86 6765 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
57fec1fe 6766 gen_op_ld_T0_A0(ot + s->mem_index);
2c0262af 6767 } else {
57fec1fe 6768 gen_op_mov_TN_reg(ot, 0, rm);
2c0262af
FB
6769 }
6770 /* load shift */
0af10c86 6771 val = cpu_ldub_code(env, s->pc++);
2c0262af
FB
6772 gen_op_movl_T1_im(val);
6773 if (op < 4)
6774 goto illegal_op;
6775 op -= 4;
f484d386 6776 goto bt_op;
2c0262af
FB
6777 case 0x1a3: /* bt Gv, Ev */
6778 op = 0;
6779 goto do_btx;
6780 case 0x1ab: /* bts */
6781 op = 1;
6782 goto do_btx;
6783 case 0x1b3: /* btr */
6784 op = 2;
6785 goto do_btx;
6786 case 0x1bb: /* btc */
6787 op = 3;
6788 do_btx:
14ce26e7 6789 ot = dflag + OT_WORD;
0af10c86 6790 modrm = cpu_ldub_code(env, s->pc++);
14ce26e7 6791 reg = ((modrm >> 3) & 7) | rex_r;
2c0262af 6792 mod = (modrm >> 6) & 3;
14ce26e7 6793 rm = (modrm & 7) | REX_B(s);
57fec1fe 6794 gen_op_mov_TN_reg(OT_LONG, 1, reg);
2c0262af 6795 if (mod != 3) {
0af10c86 6796 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
2c0262af 6797 /* specific case: we need to add a displacement */
f484d386
FB
6798 gen_exts(ot, cpu_T[1]);
6799 tcg_gen_sari_tl(cpu_tmp0, cpu_T[1], 3 + ot);
6800 tcg_gen_shli_tl(cpu_tmp0, cpu_tmp0, ot);
6801 tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
57fec1fe 6802 gen_op_ld_T0_A0(ot + s->mem_index);
2c0262af 6803 } else {
57fec1fe 6804 gen_op_mov_TN_reg(ot, 0, rm);
2c0262af 6805 }
f484d386
FB
6806 bt_op:
6807 tcg_gen_andi_tl(cpu_T[1], cpu_T[1], (1 << (3 + ot)) - 1);
6808 switch(op) {
6809 case 0:
6810 tcg_gen_shr_tl(cpu_cc_src, cpu_T[0], cpu_T[1]);
6811 tcg_gen_movi_tl(cpu_cc_dst, 0);
6812 break;
6813 case 1:
6814 tcg_gen_shr_tl(cpu_tmp4, cpu_T[0], cpu_T[1]);
6815 tcg_gen_movi_tl(cpu_tmp0, 1);
6816 tcg_gen_shl_tl(cpu_tmp0, cpu_tmp0, cpu_T[1]);
6817 tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_tmp0);
6818 break;
6819 case 2:
6820 tcg_gen_shr_tl(cpu_tmp4, cpu_T[0], cpu_T[1]);
6821 tcg_gen_movi_tl(cpu_tmp0, 1);
6822 tcg_gen_shl_tl(cpu_tmp0, cpu_tmp0, cpu_T[1]);
6823 tcg_gen_not_tl(cpu_tmp0, cpu_tmp0);
6824 tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_tmp0);
6825 break;
6826 default:
6827 case 3:
6828 tcg_gen_shr_tl(cpu_tmp4, cpu_T[0], cpu_T[1]);
6829 tcg_gen_movi_tl(cpu_tmp0, 1);
6830 tcg_gen_shl_tl(cpu_tmp0, cpu_tmp0, cpu_T[1]);
6831 tcg_gen_xor_tl(cpu_T[0], cpu_T[0], cpu_tmp0);
6832 break;
6833 }
3ca51d07 6834 set_cc_op(s, CC_OP_SARB + ot);
2c0262af
FB
6835 if (op != 0) {
6836 if (mod != 3)
57fec1fe 6837 gen_op_st_T0_A0(ot + s->mem_index);
2c0262af 6838 else
57fec1fe 6839 gen_op_mov_reg_T0(ot, rm);
f484d386
FB
6840 tcg_gen_mov_tl(cpu_cc_src, cpu_tmp4);
6841 tcg_gen_movi_tl(cpu_cc_dst, 0);
2c0262af
FB
6842 }
6843 break;
6844 case 0x1bc: /* bsf */
6845 case 0x1bd: /* bsr */
6191b059
FB
6846 {
6847 int label1;
1e4840bf
FB
6848 TCGv t0;
6849
6191b059 6850 ot = dflag + OT_WORD;
0af10c86 6851 modrm = cpu_ldub_code(env, s->pc++);
6191b059 6852 reg = ((modrm >> 3) & 7) | rex_r;
0af10c86 6853 gen_ldst_modrm(env, s,modrm, ot, OR_TMP0, 0);
6191b059 6854 gen_extu(ot, cpu_T[0]);
a7812ae4 6855 t0 = tcg_temp_local_new();
1e4840bf 6856 tcg_gen_mov_tl(t0, cpu_T[0]);
31501a71
AP
6857 if ((b & 1) && (prefixes & PREFIX_REPZ) &&
6858 (s->cpuid_ext3_features & CPUID_EXT3_ABM)) {
6859 switch(ot) {
6860 case OT_WORD: gen_helper_lzcnt(cpu_T[0], t0,
6861 tcg_const_i32(16)); break;
6862 case OT_LONG: gen_helper_lzcnt(cpu_T[0], t0,
6863 tcg_const_i32(32)); break;
6864 case OT_QUAD: gen_helper_lzcnt(cpu_T[0], t0,
6865 tcg_const_i32(64)); break;
6866 }
6867 gen_op_mov_reg_T0(ot, reg);
6191b059 6868 } else {
31501a71
AP
6869 label1 = gen_new_label();
6870 tcg_gen_movi_tl(cpu_cc_dst, 0);
6871 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, label1);
6872 if (b & 1) {
6873 gen_helper_bsr(cpu_T[0], t0);
6874 } else {
6875 gen_helper_bsf(cpu_T[0], t0);
6876 }
6877 gen_op_mov_reg_T0(ot, reg);
6878 tcg_gen_movi_tl(cpu_cc_dst, 1);
6879 gen_set_label(label1);
3ca51d07 6880 set_cc_op(s, CC_OP_LOGICB + ot);
6191b059 6881 }
1e4840bf 6882 tcg_temp_free(t0);
6191b059 6883 }
2c0262af
FB
6884 break;
6885 /************************/
6886 /* bcd */
6887 case 0x27: /* daa */
14ce26e7
FB
6888 if (CODE64(s))
6889 goto illegal_op;
773cdfcc 6890 gen_update_cc_op(s);
7923057b 6891 gen_helper_daa(cpu_env);
3ca51d07 6892 set_cc_op(s, CC_OP_EFLAGS);
2c0262af
FB
6893 break;
6894 case 0x2f: /* das */
14ce26e7
FB
6895 if (CODE64(s))
6896 goto illegal_op;
773cdfcc 6897 gen_update_cc_op(s);
7923057b 6898 gen_helper_das(cpu_env);
3ca51d07 6899 set_cc_op(s, CC_OP_EFLAGS);
2c0262af
FB
6900 break;
6901 case 0x37: /* aaa */
14ce26e7
FB
6902 if (CODE64(s))
6903 goto illegal_op;
773cdfcc 6904 gen_update_cc_op(s);
7923057b 6905 gen_helper_aaa(cpu_env);
3ca51d07 6906 set_cc_op(s, CC_OP_EFLAGS);
2c0262af
FB
6907 break;
6908 case 0x3f: /* aas */
14ce26e7
FB
6909 if (CODE64(s))
6910 goto illegal_op;
773cdfcc 6911 gen_update_cc_op(s);
7923057b 6912 gen_helper_aas(cpu_env);
3ca51d07 6913 set_cc_op(s, CC_OP_EFLAGS);
2c0262af
FB
6914 break;
6915 case 0xd4: /* aam */
14ce26e7
FB
6916 if (CODE64(s))
6917 goto illegal_op;
0af10c86 6918 val = cpu_ldub_code(env, s->pc++);
b6d7c3db
TS
6919 if (val == 0) {
6920 gen_exception(s, EXCP00_DIVZ, pc_start - s->cs_base);
6921 } else {
7923057b 6922 gen_helper_aam(cpu_env, tcg_const_i32(val));
3ca51d07 6923 set_cc_op(s, CC_OP_LOGICB);
b6d7c3db 6924 }
2c0262af
FB
6925 break;
6926 case 0xd5: /* aad */
14ce26e7
FB
6927 if (CODE64(s))
6928 goto illegal_op;
0af10c86 6929 val = cpu_ldub_code(env, s->pc++);
7923057b 6930 gen_helper_aad(cpu_env, tcg_const_i32(val));
3ca51d07 6931 set_cc_op(s, CC_OP_LOGICB);
2c0262af
FB
6932 break;
6933 /************************/
6934 /* misc */
6935 case 0x90: /* nop */
ab1f142b 6936 /* XXX: correct lock test for all insn */
7418027e 6937 if (prefixes & PREFIX_LOCK) {
ab1f142b 6938 goto illegal_op;
7418027e
RH
6939 }
6940 /* If REX_B is set, then this is xchg eax, r8d, not a nop. */
6941 if (REX_B(s)) {
6942 goto do_xchg_reg_eax;
6943 }
0573fbfc
TS
6944 if (prefixes & PREFIX_REPZ) {
6945 gen_svm_check_intercept(s, pc_start, SVM_EXIT_PAUSE);
6946 }
2c0262af
FB
6947 break;
6948 case 0x9b: /* fwait */
5fafdf24 6949 if ((s->flags & (HF_MP_MASK | HF_TS_MASK)) ==
7eee2a50
FB
6950 (HF_MP_MASK | HF_TS_MASK)) {
6951 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
2ee73ac3 6952 } else {
773cdfcc 6953 gen_update_cc_op(s);
14ce26e7 6954 gen_jmp_im(pc_start - s->cs_base);
d3eb5eae 6955 gen_helper_fwait(cpu_env);
7eee2a50 6956 }
2c0262af
FB
6957 break;
6958 case 0xcc: /* int3 */
6959 gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base);
6960 break;
6961 case 0xcd: /* int N */
0af10c86 6962 val = cpu_ldub_code(env, s->pc++);
f115e911 6963 if (s->vm86 && s->iopl != 3) {
5fafdf24 6964 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
f115e911
FB
6965 } else {
6966 gen_interrupt(s, val, pc_start - s->cs_base, s->pc - s->cs_base);
6967 }
2c0262af
FB
6968 break;
6969 case 0xce: /* into */
14ce26e7
FB
6970 if (CODE64(s))
6971 goto illegal_op;
773cdfcc 6972 gen_update_cc_op(s);
a8ede8ba 6973 gen_jmp_im(pc_start - s->cs_base);
4a7443be 6974 gen_helper_into(cpu_env, tcg_const_i32(s->pc - pc_start));
2c0262af 6975 break;
0b97134b 6976#ifdef WANT_ICEBP
2c0262af 6977 case 0xf1: /* icebp (undocumented, exits to external debugger) */
872929aa 6978 gen_svm_check_intercept(s, pc_start, SVM_EXIT_ICEBP);
aba9d61e 6979#if 1
2c0262af 6980 gen_debug(s, pc_start - s->cs_base);
aba9d61e
FB
6981#else
6982 /* start debug */
0af10c86 6983 tb_flush(env);
24537a01 6984 qemu_set_log(CPU_LOG_INT | CPU_LOG_TB_IN_ASM);
aba9d61e 6985#endif
2c0262af 6986 break;
0b97134b 6987#endif
2c0262af
FB
6988 case 0xfa: /* cli */
6989 if (!s->vm86) {
6990 if (s->cpl <= s->iopl) {
f0967a1a 6991 gen_helper_cli(cpu_env);
2c0262af
FB
6992 } else {
6993 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
6994 }
6995 } else {
6996 if (s->iopl == 3) {
f0967a1a 6997 gen_helper_cli(cpu_env);
2c0262af
FB
6998 } else {
6999 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7000 }
7001 }
7002 break;
7003 case 0xfb: /* sti */
7004 if (!s->vm86) {
7005 if (s->cpl <= s->iopl) {
7006 gen_sti:
f0967a1a 7007 gen_helper_sti(cpu_env);
2c0262af 7008 /* interruptions are enabled only the first insn after sti */
a2cc3b24
FB
7009 /* If several instructions disable interrupts, only the
7010 _first_ does it */
7011 if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
f0967a1a 7012 gen_helper_set_inhibit_irq(cpu_env);
2c0262af 7013 /* give a chance to handle pending irqs */
14ce26e7 7014 gen_jmp_im(s->pc - s->cs_base);
2c0262af
FB
7015 gen_eob(s);
7016 } else {
7017 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7018 }
7019 } else {
7020 if (s->iopl == 3) {
7021 goto gen_sti;
7022 } else {
7023 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7024 }
7025 }
7026 break;
7027 case 0x62: /* bound */
14ce26e7
FB
7028 if (CODE64(s))
7029 goto illegal_op;
2c0262af 7030 ot = dflag ? OT_LONG : OT_WORD;
0af10c86 7031 modrm = cpu_ldub_code(env, s->pc++);
2c0262af
FB
7032 reg = (modrm >> 3) & 7;
7033 mod = (modrm >> 6) & 3;
7034 if (mod == 3)
7035 goto illegal_op;
57fec1fe 7036 gen_op_mov_TN_reg(ot, 0, reg);
0af10c86 7037 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
14ce26e7 7038 gen_jmp_im(pc_start - s->cs_base);
b6abf97d 7039 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
92fc4b58
BS
7040 if (ot == OT_WORD) {
7041 gen_helper_boundw(cpu_env, cpu_A0, cpu_tmp2_i32);
7042 } else {
7043 gen_helper_boundl(cpu_env, cpu_A0, cpu_tmp2_i32);
7044 }
2c0262af
FB
7045 break;
7046 case 0x1c8 ... 0x1cf: /* bswap reg */
14ce26e7
FB
7047 reg = (b & 7) | REX_B(s);
7048#ifdef TARGET_X86_64
7049 if (dflag == 2) {
57fec1fe 7050 gen_op_mov_TN_reg(OT_QUAD, 0, reg);
66896cb8 7051 tcg_gen_bswap64_i64(cpu_T[0], cpu_T[0]);
57fec1fe 7052 gen_op_mov_reg_T0(OT_QUAD, reg);
5fafdf24 7053 } else
8777643e 7054#endif
57fec1fe
FB
7055 {
7056 gen_op_mov_TN_reg(OT_LONG, 0, reg);
8777643e
AJ
7057 tcg_gen_ext32u_tl(cpu_T[0], cpu_T[0]);
7058 tcg_gen_bswap32_tl(cpu_T[0], cpu_T[0]);
57fec1fe 7059 gen_op_mov_reg_T0(OT_LONG, reg);
14ce26e7 7060 }
2c0262af
FB
7061 break;
7062 case 0xd6: /* salc */
14ce26e7
FB
7063 if (CODE64(s))
7064 goto illegal_op;
cc8b6f5b 7065 gen_compute_eflags_c(s, cpu_T[0]);
bd7a7b33
FB
7066 tcg_gen_neg_tl(cpu_T[0], cpu_T[0]);
7067 gen_op_mov_reg_T0(OT_BYTE, R_EAX);
2c0262af
FB
7068 break;
7069 case 0xe0: /* loopnz */
7070 case 0xe1: /* loopz */
2c0262af
FB
7071 case 0xe2: /* loop */
7072 case 0xe3: /* jecxz */
14ce26e7 7073 {
6e0d8677 7074 int l1, l2, l3;
14ce26e7 7075
0af10c86 7076 tval = (int8_t)insn_get(env, s, OT_BYTE);
14ce26e7
FB
7077 next_eip = s->pc - s->cs_base;
7078 tval += next_eip;
7079 if (s->dflag == 0)
7080 tval &= 0xffff;
3b46e624 7081
14ce26e7
FB
7082 l1 = gen_new_label();
7083 l2 = gen_new_label();
6e0d8677 7084 l3 = gen_new_label();
14ce26e7 7085 b &= 3;
6e0d8677
FB
7086 switch(b) {
7087 case 0: /* loopnz */
7088 case 1: /* loopz */
6e0d8677
FB
7089 gen_op_add_reg_im(s->aflag, R_ECX, -1);
7090 gen_op_jz_ecx(s->aflag, l3);
5bdb91b0 7091 gen_jcc1(s, (JCC_Z << 1) | (b ^ 1), l1);
6e0d8677
FB
7092 break;
7093 case 2: /* loop */
7094 gen_op_add_reg_im(s->aflag, R_ECX, -1);
7095 gen_op_jnz_ecx(s->aflag, l1);
7096 break;
7097 default:
7098 case 3: /* jcxz */
7099 gen_op_jz_ecx(s->aflag, l1);
7100 break;
14ce26e7
FB
7101 }
7102
6e0d8677 7103 gen_set_label(l3);
14ce26e7 7104 gen_jmp_im(next_eip);
8e1c85e3 7105 tcg_gen_br(l2);
6e0d8677 7106
14ce26e7
FB
7107 gen_set_label(l1);
7108 gen_jmp_im(tval);
7109 gen_set_label(l2);
7110 gen_eob(s);
7111 }
2c0262af
FB
7112 break;
7113 case 0x130: /* wrmsr */
7114 case 0x132: /* rdmsr */
7115 if (s->cpl != 0) {
7116 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7117 } else {
773cdfcc 7118 gen_update_cc_op(s);
872929aa 7119 gen_jmp_im(pc_start - s->cs_base);
0573fbfc 7120 if (b & 2) {
4a7443be 7121 gen_helper_rdmsr(cpu_env);
0573fbfc 7122 } else {
4a7443be 7123 gen_helper_wrmsr(cpu_env);
0573fbfc 7124 }
2c0262af
FB
7125 }
7126 break;
7127 case 0x131: /* rdtsc */
773cdfcc 7128 gen_update_cc_op(s);
ecada8a2 7129 gen_jmp_im(pc_start - s->cs_base);
efade670
PB
7130 if (use_icount)
7131 gen_io_start();
4a7443be 7132 gen_helper_rdtsc(cpu_env);
efade670
PB
7133 if (use_icount) {
7134 gen_io_end();
7135 gen_jmp(s, s->pc - s->cs_base);
7136 }
2c0262af 7137 break;
df01e0fc 7138 case 0x133: /* rdpmc */
773cdfcc 7139 gen_update_cc_op(s);
df01e0fc 7140 gen_jmp_im(pc_start - s->cs_base);
4a7443be 7141 gen_helper_rdpmc(cpu_env);
df01e0fc 7142 break;
023fe10d 7143 case 0x134: /* sysenter */
2436b61a 7144 /* For Intel SYSENTER is valid on 64-bit */
0af10c86 7145 if (CODE64(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1)
14ce26e7 7146 goto illegal_op;
023fe10d
FB
7147 if (!s->pe) {
7148 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7149 } else {
728d803b 7150 gen_update_cc_op(s);
14ce26e7 7151 gen_jmp_im(pc_start - s->cs_base);
2999a0b2 7152 gen_helper_sysenter(cpu_env);
023fe10d
FB
7153 gen_eob(s);
7154 }
7155 break;
7156 case 0x135: /* sysexit */
2436b61a 7157 /* For Intel SYSEXIT is valid on 64-bit */
0af10c86 7158 if (CODE64(s) && env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1)
14ce26e7 7159 goto illegal_op;
023fe10d
FB
7160 if (!s->pe) {
7161 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7162 } else {
728d803b 7163 gen_update_cc_op(s);
14ce26e7 7164 gen_jmp_im(pc_start - s->cs_base);
2999a0b2 7165 gen_helper_sysexit(cpu_env, tcg_const_i32(dflag));
023fe10d
FB
7166 gen_eob(s);
7167 }
7168 break;
14ce26e7
FB
7169#ifdef TARGET_X86_64
7170 case 0x105: /* syscall */
7171 /* XXX: is it usable in real mode ? */
728d803b 7172 gen_update_cc_op(s);
14ce26e7 7173 gen_jmp_im(pc_start - s->cs_base);
2999a0b2 7174 gen_helper_syscall(cpu_env, tcg_const_i32(s->pc - pc_start));
14ce26e7
FB
7175 gen_eob(s);
7176 break;
7177 case 0x107: /* sysret */
7178 if (!s->pe) {
7179 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7180 } else {
728d803b 7181 gen_update_cc_op(s);
14ce26e7 7182 gen_jmp_im(pc_start - s->cs_base);
2999a0b2 7183 gen_helper_sysret(cpu_env, tcg_const_i32(s->dflag));
aba9d61e 7184 /* condition codes are modified only in long mode */
3ca51d07
RH
7185 if (s->lma) {
7186 set_cc_op(s, CC_OP_EFLAGS);
7187 }
14ce26e7
FB
7188 gen_eob(s);
7189 }
7190 break;
7191#endif
2c0262af 7192 case 0x1a2: /* cpuid */
773cdfcc 7193 gen_update_cc_op(s);
9575cb94 7194 gen_jmp_im(pc_start - s->cs_base);
4a7443be 7195 gen_helper_cpuid(cpu_env);
2c0262af
FB
7196 break;
7197 case 0xf4: /* hlt */
7198 if (s->cpl != 0) {
7199 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7200 } else {
773cdfcc 7201 gen_update_cc_op(s);
94451178 7202 gen_jmp_im(pc_start - s->cs_base);
4a7443be 7203 gen_helper_hlt(cpu_env, tcg_const_i32(s->pc - pc_start));
5779406a 7204 s->is_jmp = DISAS_TB_JUMP;
2c0262af
FB
7205 }
7206 break;
7207 case 0x100:
0af10c86 7208 modrm = cpu_ldub_code(env, s->pc++);
2c0262af
FB
7209 mod = (modrm >> 6) & 3;
7210 op = (modrm >> 3) & 7;
7211 switch(op) {
7212 case 0: /* sldt */
f115e911
FB
7213 if (!s->pe || s->vm86)
7214 goto illegal_op;
872929aa 7215 gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_READ);
651ba608 7216 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,ldt.selector));
2c0262af
FB
7217 ot = OT_WORD;
7218 if (mod == 3)
7219 ot += s->dflag;
0af10c86 7220 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
2c0262af
FB
7221 break;
7222 case 2: /* lldt */
f115e911
FB
7223 if (!s->pe || s->vm86)
7224 goto illegal_op;
2c0262af
FB
7225 if (s->cpl != 0) {
7226 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7227 } else {
872929aa 7228 gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_WRITE);
0af10c86 7229 gen_ldst_modrm(env, s, modrm, OT_WORD, OR_TMP0, 0);
14ce26e7 7230 gen_jmp_im(pc_start - s->cs_base);
b6abf97d 7231 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
2999a0b2 7232 gen_helper_lldt(cpu_env, cpu_tmp2_i32);
2c0262af
FB
7233 }
7234 break;
7235 case 1: /* str */
f115e911
FB
7236 if (!s->pe || s->vm86)
7237 goto illegal_op;
872929aa 7238 gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_READ);
651ba608 7239 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,tr.selector));
2c0262af
FB
7240 ot = OT_WORD;
7241 if (mod == 3)
7242 ot += s->dflag;
0af10c86 7243 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 1);
2c0262af
FB
7244 break;
7245 case 3: /* ltr */
f115e911
FB
7246 if (!s->pe || s->vm86)
7247 goto illegal_op;
2c0262af
FB
7248 if (s->cpl != 0) {
7249 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7250 } else {
872929aa 7251 gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_WRITE);
0af10c86 7252 gen_ldst_modrm(env, s, modrm, OT_WORD, OR_TMP0, 0);
14ce26e7 7253 gen_jmp_im(pc_start - s->cs_base);
b6abf97d 7254 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
2999a0b2 7255 gen_helper_ltr(cpu_env, cpu_tmp2_i32);
2c0262af
FB
7256 }
7257 break;
7258 case 4: /* verr */
7259 case 5: /* verw */
f115e911
FB
7260 if (!s->pe || s->vm86)
7261 goto illegal_op;
0af10c86 7262 gen_ldst_modrm(env, s, modrm, OT_WORD, OR_TMP0, 0);
773cdfcc 7263 gen_update_cc_op(s);
2999a0b2
BS
7264 if (op == 4) {
7265 gen_helper_verr(cpu_env, cpu_T[0]);
7266 } else {
7267 gen_helper_verw(cpu_env, cpu_T[0]);
7268 }
3ca51d07 7269 set_cc_op(s, CC_OP_EFLAGS);
f115e911 7270 break;
2c0262af
FB
7271 default:
7272 goto illegal_op;
7273 }
7274 break;
7275 case 0x101:
0af10c86 7276 modrm = cpu_ldub_code(env, s->pc++);
2c0262af
FB
7277 mod = (modrm >> 6) & 3;
7278 op = (modrm >> 3) & 7;
3d7374c5 7279 rm = modrm & 7;
2c0262af
FB
7280 switch(op) {
7281 case 0: /* sgdt */
2c0262af
FB
7282 if (mod == 3)
7283 goto illegal_op;
872929aa 7284 gen_svm_check_intercept(s, pc_start, SVM_EXIT_GDTR_READ);
0af10c86 7285 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
651ba608 7286 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, gdt.limit));
57fec1fe 7287 gen_op_st_T0_A0(OT_WORD + s->mem_index);
aba9d61e 7288 gen_add_A0_im(s, 2);
651ba608 7289 tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, gdt.base));
2c0262af
FB
7290 if (!s->dflag)
7291 gen_op_andl_T0_im(0xffffff);
57fec1fe 7292 gen_op_st_T0_A0(CODE64(s) + OT_LONG + s->mem_index);
2c0262af 7293 break;
3d7374c5
FB
7294 case 1:
7295 if (mod == 3) {
7296 switch (rm) {
7297 case 0: /* monitor */
7298 if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) ||
7299 s->cpl != 0)
7300 goto illegal_op;
773cdfcc 7301 gen_update_cc_op(s);
3d7374c5
FB
7302 gen_jmp_im(pc_start - s->cs_base);
7303#ifdef TARGET_X86_64
7304 if (s->aflag == 2) {
bbf662ee 7305 gen_op_movq_A0_reg(R_EAX);
5fafdf24 7306 } else
3d7374c5
FB
7307#endif
7308 {
bbf662ee 7309 gen_op_movl_A0_reg(R_EAX);
3d7374c5
FB
7310 if (s->aflag == 0)
7311 gen_op_andl_A0_ffff();
7312 }
7313 gen_add_A0_ds_seg(s);
4a7443be 7314 gen_helper_monitor(cpu_env, cpu_A0);
3d7374c5
FB
7315 break;
7316 case 1: /* mwait */
7317 if (!(s->cpuid_ext_features & CPUID_EXT_MONITOR) ||
7318 s->cpl != 0)
7319 goto illegal_op;
728d803b 7320 gen_update_cc_op(s);
94451178 7321 gen_jmp_im(pc_start - s->cs_base);
4a7443be 7322 gen_helper_mwait(cpu_env, tcg_const_i32(s->pc - pc_start));
3d7374c5
FB
7323 gen_eob(s);
7324 break;
a9321a4d
PA
7325 case 2: /* clac */
7326 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_SMAP) ||
7327 s->cpl != 0) {
7328 goto illegal_op;
7329 }
7330 gen_helper_clac(cpu_env);
7331 gen_jmp_im(s->pc - s->cs_base);
7332 gen_eob(s);
7333 break;
7334 case 3: /* stac */
7335 if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_SMAP) ||
7336 s->cpl != 0) {
7337 goto illegal_op;
7338 }
7339 gen_helper_stac(cpu_env);
7340 gen_jmp_im(s->pc - s->cs_base);
7341 gen_eob(s);
7342 break;
3d7374c5
FB
7343 default:
7344 goto illegal_op;
7345 }
7346 } else { /* sidt */
872929aa 7347 gen_svm_check_intercept(s, pc_start, SVM_EXIT_IDTR_READ);
0af10c86 7348 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
651ba608 7349 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, idt.limit));
57fec1fe 7350 gen_op_st_T0_A0(OT_WORD + s->mem_index);
3d7374c5 7351 gen_add_A0_im(s, 2);
651ba608 7352 tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, idt.base));
3d7374c5
FB
7353 if (!s->dflag)
7354 gen_op_andl_T0_im(0xffffff);
57fec1fe 7355 gen_op_st_T0_A0(CODE64(s) + OT_LONG + s->mem_index);
3d7374c5
FB
7356 }
7357 break;
2c0262af
FB
7358 case 2: /* lgdt */
7359 case 3: /* lidt */
0573fbfc 7360 if (mod == 3) {
773cdfcc 7361 gen_update_cc_op(s);
872929aa 7362 gen_jmp_im(pc_start - s->cs_base);
0573fbfc
TS
7363 switch(rm) {
7364 case 0: /* VMRUN */
872929aa
FB
7365 if (!(s->flags & HF_SVME_MASK) || !s->pe)
7366 goto illegal_op;
7367 if (s->cpl != 0) {
7368 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
0573fbfc 7369 break;
872929aa 7370 } else {
052e80d5 7371 gen_helper_vmrun(cpu_env, tcg_const_i32(s->aflag),
a7812ae4 7372 tcg_const_i32(s->pc - pc_start));
db620f46 7373 tcg_gen_exit_tb(0);
5779406a 7374 s->is_jmp = DISAS_TB_JUMP;
872929aa 7375 }
0573fbfc
TS
7376 break;
7377 case 1: /* VMMCALL */
872929aa
FB
7378 if (!(s->flags & HF_SVME_MASK))
7379 goto illegal_op;
052e80d5 7380 gen_helper_vmmcall(cpu_env);
0573fbfc
TS
7381 break;
7382 case 2: /* VMLOAD */
872929aa
FB
7383 if (!(s->flags & HF_SVME_MASK) || !s->pe)
7384 goto illegal_op;
7385 if (s->cpl != 0) {
7386 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7387 break;
7388 } else {
052e80d5 7389 gen_helper_vmload(cpu_env, tcg_const_i32(s->aflag));
872929aa 7390 }
0573fbfc
TS
7391 break;
7392 case 3: /* VMSAVE */
872929aa
FB
7393 if (!(s->flags & HF_SVME_MASK) || !s->pe)
7394 goto illegal_op;
7395 if (s->cpl != 0) {
7396 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7397 break;
7398 } else {
052e80d5 7399 gen_helper_vmsave(cpu_env, tcg_const_i32(s->aflag));
872929aa 7400 }
0573fbfc
TS
7401 break;
7402 case 4: /* STGI */
872929aa
FB
7403 if ((!(s->flags & HF_SVME_MASK) &&
7404 !(s->cpuid_ext3_features & CPUID_EXT3_SKINIT)) ||
7405 !s->pe)
7406 goto illegal_op;
7407 if (s->cpl != 0) {
7408 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7409 break;
7410 } else {
052e80d5 7411 gen_helper_stgi(cpu_env);
872929aa 7412 }
0573fbfc
TS
7413 break;
7414 case 5: /* CLGI */
872929aa
FB
7415 if (!(s->flags & HF_SVME_MASK) || !s->pe)
7416 goto illegal_op;
7417 if (s->cpl != 0) {
7418 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7419 break;
7420 } else {
052e80d5 7421 gen_helper_clgi(cpu_env);
872929aa 7422 }
0573fbfc
TS
7423 break;
7424 case 6: /* SKINIT */
872929aa
FB
7425 if ((!(s->flags & HF_SVME_MASK) &&
7426 !(s->cpuid_ext3_features & CPUID_EXT3_SKINIT)) ||
7427 !s->pe)
7428 goto illegal_op;
052e80d5 7429 gen_helper_skinit(cpu_env);
0573fbfc
TS
7430 break;
7431 case 7: /* INVLPGA */
872929aa
FB
7432 if (!(s->flags & HF_SVME_MASK) || !s->pe)
7433 goto illegal_op;
7434 if (s->cpl != 0) {
7435 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7436 break;
7437 } else {
052e80d5 7438 gen_helper_invlpga(cpu_env, tcg_const_i32(s->aflag));
872929aa 7439 }
0573fbfc
TS
7440 break;
7441 default:
7442 goto illegal_op;
7443 }
7444 } else if (s->cpl != 0) {
2c0262af
FB
7445 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7446 } else {
872929aa
FB
7447 gen_svm_check_intercept(s, pc_start,
7448 op==2 ? SVM_EXIT_GDTR_WRITE : SVM_EXIT_IDTR_WRITE);
0af10c86 7449 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
57fec1fe 7450 gen_op_ld_T1_A0(OT_WORD + s->mem_index);
aba9d61e 7451 gen_add_A0_im(s, 2);
57fec1fe 7452 gen_op_ld_T0_A0(CODE64(s) + OT_LONG + s->mem_index);
2c0262af
FB
7453 if (!s->dflag)
7454 gen_op_andl_T0_im(0xffffff);
7455 if (op == 2) {
651ba608
FB
7456 tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,gdt.base));
7457 tcg_gen_st32_tl(cpu_T[1], cpu_env, offsetof(CPUX86State,gdt.limit));
2c0262af 7458 } else {
651ba608
FB
7459 tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,idt.base));
7460 tcg_gen_st32_tl(cpu_T[1], cpu_env, offsetof(CPUX86State,idt.limit));
2c0262af
FB
7461 }
7462 }
7463 break;
7464 case 4: /* smsw */
872929aa 7465 gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_CR0);
e2542fe2 7466#if defined TARGET_X86_64 && defined HOST_WORDS_BIGENDIAN
f60d2728 7467 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,cr[0]) + 4);
7468#else
651ba608 7469 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,cr[0]));
f60d2728 7470#endif
0af10c86 7471 gen_ldst_modrm(env, s, modrm, OT_WORD, OR_TMP0, 1);
2c0262af
FB
7472 break;
7473 case 6: /* lmsw */
7474 if (s->cpl != 0) {
7475 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7476 } else {
872929aa 7477 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0);
0af10c86 7478 gen_ldst_modrm(env, s, modrm, OT_WORD, OR_TMP0, 0);
4a7443be 7479 gen_helper_lmsw(cpu_env, cpu_T[0]);
14ce26e7 7480 gen_jmp_im(s->pc - s->cs_base);
d71b9a8b 7481 gen_eob(s);
2c0262af
FB
7482 }
7483 break;
1b050077
AP
7484 case 7:
7485 if (mod != 3) { /* invlpg */
7486 if (s->cpl != 0) {
7487 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7488 } else {
773cdfcc 7489 gen_update_cc_op(s);
1b050077 7490 gen_jmp_im(pc_start - s->cs_base);
0af10c86 7491 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
4a7443be 7492 gen_helper_invlpg(cpu_env, cpu_A0);
1b050077
AP
7493 gen_jmp_im(s->pc - s->cs_base);
7494 gen_eob(s);
7495 }
2c0262af 7496 } else {
1b050077
AP
7497 switch (rm) {
7498 case 0: /* swapgs */
14ce26e7 7499#ifdef TARGET_X86_64
1b050077
AP
7500 if (CODE64(s)) {
7501 if (s->cpl != 0) {
7502 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7503 } else {
7504 tcg_gen_ld_tl(cpu_T[0], cpu_env,
7505 offsetof(CPUX86State,segs[R_GS].base));
7506 tcg_gen_ld_tl(cpu_T[1], cpu_env,
7507 offsetof(CPUX86State,kernelgsbase));
7508 tcg_gen_st_tl(cpu_T[1], cpu_env,
7509 offsetof(CPUX86State,segs[R_GS].base));
7510 tcg_gen_st_tl(cpu_T[0], cpu_env,
7511 offsetof(CPUX86State,kernelgsbase));
7512 }
5fafdf24 7513 } else
14ce26e7
FB
7514#endif
7515 {
7516 goto illegal_op;
7517 }
1b050077
AP
7518 break;
7519 case 1: /* rdtscp */
7520 if (!(s->cpuid_ext2_features & CPUID_EXT2_RDTSCP))
7521 goto illegal_op;
773cdfcc 7522 gen_update_cc_op(s);
9575cb94 7523 gen_jmp_im(pc_start - s->cs_base);
1b050077
AP
7524 if (use_icount)
7525 gen_io_start();
4a7443be 7526 gen_helper_rdtscp(cpu_env);
1b050077
AP
7527 if (use_icount) {
7528 gen_io_end();
7529 gen_jmp(s, s->pc - s->cs_base);
7530 }
7531 break;
7532 default:
7533 goto illegal_op;
14ce26e7 7534 }
2c0262af
FB
7535 }
7536 break;
7537 default:
7538 goto illegal_op;
7539 }
7540 break;
3415a4dd
FB
7541 case 0x108: /* invd */
7542 case 0x109: /* wbinvd */
7543 if (s->cpl != 0) {
7544 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7545 } else {
872929aa 7546 gen_svm_check_intercept(s, pc_start, (b & 2) ? SVM_EXIT_INVD : SVM_EXIT_WBINVD);
3415a4dd
FB
7547 /* nothing to do */
7548 }
7549 break;
14ce26e7
FB
7550 case 0x63: /* arpl or movslS (x86_64) */
7551#ifdef TARGET_X86_64
7552 if (CODE64(s)) {
7553 int d_ot;
7554 /* d_ot is the size of destination */
7555 d_ot = dflag + OT_WORD;
7556
0af10c86 7557 modrm = cpu_ldub_code(env, s->pc++);
14ce26e7
FB
7558 reg = ((modrm >> 3) & 7) | rex_r;
7559 mod = (modrm >> 6) & 3;
7560 rm = (modrm & 7) | REX_B(s);
3b46e624 7561
14ce26e7 7562 if (mod == 3) {
57fec1fe 7563 gen_op_mov_TN_reg(OT_LONG, 0, rm);
14ce26e7
FB
7564 /* sign extend */
7565 if (d_ot == OT_QUAD)
e108dd01 7566 tcg_gen_ext32s_tl(cpu_T[0], cpu_T[0]);
57fec1fe 7567 gen_op_mov_reg_T0(d_ot, reg);
14ce26e7 7568 } else {
0af10c86 7569 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
14ce26e7 7570 if (d_ot == OT_QUAD) {
57fec1fe 7571 gen_op_lds_T0_A0(OT_LONG + s->mem_index);
14ce26e7 7572 } else {
57fec1fe 7573 gen_op_ld_T0_A0(OT_LONG + s->mem_index);
14ce26e7 7574 }
57fec1fe 7575 gen_op_mov_reg_T0(d_ot, reg);
14ce26e7 7576 }
5fafdf24 7577 } else
14ce26e7
FB
7578#endif
7579 {
3bd7da9e 7580 int label1;
49d9fdcc 7581 TCGv t0, t1, t2, a0;
1e4840bf 7582
14ce26e7
FB
7583 if (!s->pe || s->vm86)
7584 goto illegal_op;
a7812ae4
PB
7585 t0 = tcg_temp_local_new();
7586 t1 = tcg_temp_local_new();
7587 t2 = tcg_temp_local_new();
3bd7da9e 7588 ot = OT_WORD;
0af10c86 7589 modrm = cpu_ldub_code(env, s->pc++);
14ce26e7
FB
7590 reg = (modrm >> 3) & 7;
7591 mod = (modrm >> 6) & 3;
7592 rm = modrm & 7;
7593 if (mod != 3) {
0af10c86 7594 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
1e4840bf 7595 gen_op_ld_v(ot + s->mem_index, t0, cpu_A0);
49d9fdcc
LD
7596 a0 = tcg_temp_local_new();
7597 tcg_gen_mov_tl(a0, cpu_A0);
14ce26e7 7598 } else {
1e4840bf 7599 gen_op_mov_v_reg(ot, t0, rm);
49d9fdcc 7600 TCGV_UNUSED(a0);
14ce26e7 7601 }
1e4840bf
FB
7602 gen_op_mov_v_reg(ot, t1, reg);
7603 tcg_gen_andi_tl(cpu_tmp0, t0, 3);
7604 tcg_gen_andi_tl(t1, t1, 3);
7605 tcg_gen_movi_tl(t2, 0);
3bd7da9e 7606 label1 = gen_new_label();
1e4840bf
FB
7607 tcg_gen_brcond_tl(TCG_COND_GE, cpu_tmp0, t1, label1);
7608 tcg_gen_andi_tl(t0, t0, ~3);
7609 tcg_gen_or_tl(t0, t0, t1);
7610 tcg_gen_movi_tl(t2, CC_Z);
3bd7da9e 7611 gen_set_label(label1);
14ce26e7 7612 if (mod != 3) {
49d9fdcc
LD
7613 gen_op_st_v(ot + s->mem_index, t0, a0);
7614 tcg_temp_free(a0);
7615 } else {
1e4840bf 7616 gen_op_mov_reg_v(ot, rm, t0);
14ce26e7 7617 }
d229edce 7618 gen_compute_eflags(s);
3bd7da9e 7619 tcg_gen_andi_tl(cpu_cc_src, cpu_cc_src, ~CC_Z);
1e4840bf 7620 tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, t2);
1e4840bf
FB
7621 tcg_temp_free(t0);
7622 tcg_temp_free(t1);
7623 tcg_temp_free(t2);
f115e911 7624 }
f115e911 7625 break;
2c0262af
FB
7626 case 0x102: /* lar */
7627 case 0x103: /* lsl */
cec6843e
FB
7628 {
7629 int label1;
1e4840bf 7630 TCGv t0;
cec6843e
FB
7631 if (!s->pe || s->vm86)
7632 goto illegal_op;
7633 ot = dflag ? OT_LONG : OT_WORD;
0af10c86 7634 modrm = cpu_ldub_code(env, s->pc++);
cec6843e 7635 reg = ((modrm >> 3) & 7) | rex_r;
0af10c86 7636 gen_ldst_modrm(env, s, modrm, OT_WORD, OR_TMP0, 0);
a7812ae4 7637 t0 = tcg_temp_local_new();
773cdfcc 7638 gen_update_cc_op(s);
2999a0b2
BS
7639 if (b == 0x102) {
7640 gen_helper_lar(t0, cpu_env, cpu_T[0]);
7641 } else {
7642 gen_helper_lsl(t0, cpu_env, cpu_T[0]);
7643 }
cec6843e
FB
7644 tcg_gen_andi_tl(cpu_tmp0, cpu_cc_src, CC_Z);
7645 label1 = gen_new_label();
cb63669a 7646 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_tmp0, 0, label1);
1e4840bf 7647 gen_op_mov_reg_v(ot, reg, t0);
cec6843e 7648 gen_set_label(label1);
3ca51d07 7649 set_cc_op(s, CC_OP_EFLAGS);
1e4840bf 7650 tcg_temp_free(t0);
cec6843e 7651 }
2c0262af
FB
7652 break;
7653 case 0x118:
0af10c86 7654 modrm = cpu_ldub_code(env, s->pc++);
2c0262af
FB
7655 mod = (modrm >> 6) & 3;
7656 op = (modrm >> 3) & 7;
7657 switch(op) {
7658 case 0: /* prefetchnta */
7659 case 1: /* prefetchnt0 */
7660 case 2: /* prefetchnt0 */
7661 case 3: /* prefetchnt0 */
7662 if (mod == 3)
7663 goto illegal_op;
0af10c86 7664 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
2c0262af
FB
7665 /* nothing more to do */
7666 break;
e17a36ce 7667 default: /* nop (multi byte) */
0af10c86 7668 gen_nop_modrm(env, s, modrm);
e17a36ce 7669 break;
2c0262af
FB
7670 }
7671 break;
e17a36ce 7672 case 0x119 ... 0x11f: /* nop (multi byte) */
0af10c86
BS
7673 modrm = cpu_ldub_code(env, s->pc++);
7674 gen_nop_modrm(env, s, modrm);
e17a36ce 7675 break;
2c0262af
FB
7676 case 0x120: /* mov reg, crN */
7677 case 0x122: /* mov crN, reg */
7678 if (s->cpl != 0) {
7679 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7680 } else {
0af10c86 7681 modrm = cpu_ldub_code(env, s->pc++);
5c73b757
MO
7682 /* Ignore the mod bits (assume (modrm&0xc0)==0xc0).
7683 * AMD documentation (24594.pdf) and testing of
7684 * intel 386 and 486 processors all show that the mod bits
7685 * are assumed to be 1's, regardless of actual values.
7686 */
14ce26e7
FB
7687 rm = (modrm & 7) | REX_B(s);
7688 reg = ((modrm >> 3) & 7) | rex_r;
7689 if (CODE64(s))
7690 ot = OT_QUAD;
7691 else
7692 ot = OT_LONG;
ccd59d09
AP
7693 if ((prefixes & PREFIX_LOCK) && (reg == 0) &&
7694 (s->cpuid_ext3_features & CPUID_EXT3_CR8LEG)) {
7695 reg = 8;
7696 }
2c0262af
FB
7697 switch(reg) {
7698 case 0:
7699 case 2:
7700 case 3:
7701 case 4:
9230e66e 7702 case 8:
773cdfcc 7703 gen_update_cc_op(s);
872929aa 7704 gen_jmp_im(pc_start - s->cs_base);
2c0262af 7705 if (b & 2) {
57fec1fe 7706 gen_op_mov_TN_reg(ot, 0, rm);
4a7443be
BS
7707 gen_helper_write_crN(cpu_env, tcg_const_i32(reg),
7708 cpu_T[0]);
14ce26e7 7709 gen_jmp_im(s->pc - s->cs_base);
2c0262af
FB
7710 gen_eob(s);
7711 } else {
4a7443be 7712 gen_helper_read_crN(cpu_T[0], cpu_env, tcg_const_i32(reg));
57fec1fe 7713 gen_op_mov_reg_T0(ot, rm);
2c0262af
FB
7714 }
7715 break;
7716 default:
7717 goto illegal_op;
7718 }
7719 }
7720 break;
7721 case 0x121: /* mov reg, drN */
7722 case 0x123: /* mov drN, reg */
7723 if (s->cpl != 0) {
7724 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7725 } else {
0af10c86 7726 modrm = cpu_ldub_code(env, s->pc++);
5c73b757
MO
7727 /* Ignore the mod bits (assume (modrm&0xc0)==0xc0).
7728 * AMD documentation (24594.pdf) and testing of
7729 * intel 386 and 486 processors all show that the mod bits
7730 * are assumed to be 1's, regardless of actual values.
7731 */
14ce26e7
FB
7732 rm = (modrm & 7) | REX_B(s);
7733 reg = ((modrm >> 3) & 7) | rex_r;
7734 if (CODE64(s))
7735 ot = OT_QUAD;
7736 else
7737 ot = OT_LONG;
2c0262af 7738 /* XXX: do it dynamically with CR4.DE bit */
14ce26e7 7739 if (reg == 4 || reg == 5 || reg >= 8)
2c0262af
FB
7740 goto illegal_op;
7741 if (b & 2) {
0573fbfc 7742 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_DR0 + reg);
57fec1fe 7743 gen_op_mov_TN_reg(ot, 0, rm);
4a7443be 7744 gen_helper_movl_drN_T0(cpu_env, tcg_const_i32(reg), cpu_T[0]);
14ce26e7 7745 gen_jmp_im(s->pc - s->cs_base);
2c0262af
FB
7746 gen_eob(s);
7747 } else {
0573fbfc 7748 gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_DR0 + reg);
651ba608 7749 tcg_gen_ld_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,dr[reg]));
57fec1fe 7750 gen_op_mov_reg_T0(ot, rm);
2c0262af
FB
7751 }
7752 }
7753 break;
7754 case 0x106: /* clts */
7755 if (s->cpl != 0) {
7756 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
7757 } else {
0573fbfc 7758 gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0);
f0967a1a 7759 gen_helper_clts(cpu_env);
7eee2a50 7760 /* abort block because static cpu state changed */
14ce26e7 7761 gen_jmp_im(s->pc - s->cs_base);
7eee2a50 7762 gen_eob(s);
2c0262af
FB
7763 }
7764 break;
222a3336 7765 /* MMX/3DNow!/SSE/SSE2/SSE3/SSSE3/SSE4 support */
664e0f19
FB
7766 case 0x1c3: /* MOVNTI reg, mem */
7767 if (!(s->cpuid_features & CPUID_SSE2))
14ce26e7 7768 goto illegal_op;
664e0f19 7769 ot = s->dflag == 2 ? OT_QUAD : OT_LONG;
0af10c86 7770 modrm = cpu_ldub_code(env, s->pc++);
664e0f19
FB
7771 mod = (modrm >> 6) & 3;
7772 if (mod == 3)
7773 goto illegal_op;
7774 reg = ((modrm >> 3) & 7) | rex_r;
7775 /* generate a generic store */
0af10c86 7776 gen_ldst_modrm(env, s, modrm, ot, reg, 1);
14ce26e7 7777 break;
664e0f19 7778 case 0x1ae:
0af10c86 7779 modrm = cpu_ldub_code(env, s->pc++);
664e0f19
FB
7780 mod = (modrm >> 6) & 3;
7781 op = (modrm >> 3) & 7;
7782 switch(op) {
7783 case 0: /* fxsave */
5fafdf24 7784 if (mod == 3 || !(s->cpuid_features & CPUID_FXSR) ||
09d85fb8 7785 (s->prefix & PREFIX_LOCK))
14ce26e7 7786 goto illegal_op;
09d85fb8 7787 if ((s->flags & HF_EM_MASK) || (s->flags & HF_TS_MASK)) {
0fd14b72
FB
7788 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
7789 break;
7790 }
0af10c86 7791 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
773cdfcc 7792 gen_update_cc_op(s);
19e6c4b8 7793 gen_jmp_im(pc_start - s->cs_base);
d3eb5eae 7794 gen_helper_fxsave(cpu_env, cpu_A0, tcg_const_i32((s->dflag == 2)));
664e0f19
FB
7795 break;
7796 case 1: /* fxrstor */
5fafdf24 7797 if (mod == 3 || !(s->cpuid_features & CPUID_FXSR) ||
09d85fb8 7798 (s->prefix & PREFIX_LOCK))
14ce26e7 7799 goto illegal_op;
09d85fb8 7800 if ((s->flags & HF_EM_MASK) || (s->flags & HF_TS_MASK)) {
0fd14b72
FB
7801 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
7802 break;
7803 }
0af10c86 7804 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
773cdfcc 7805 gen_update_cc_op(s);
19e6c4b8 7806 gen_jmp_im(pc_start - s->cs_base);
d3eb5eae
BS
7807 gen_helper_fxrstor(cpu_env, cpu_A0,
7808 tcg_const_i32((s->dflag == 2)));
664e0f19
FB
7809 break;
7810 case 2: /* ldmxcsr */
7811 case 3: /* stmxcsr */
7812 if (s->flags & HF_TS_MASK) {
7813 gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
7814 break;
14ce26e7 7815 }
664e0f19
FB
7816 if ((s->flags & HF_EM_MASK) || !(s->flags & HF_OSFXSR_MASK) ||
7817 mod == 3)
14ce26e7 7818 goto illegal_op;
0af10c86 7819 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
664e0f19 7820 if (op == 2) {
57fec1fe 7821 gen_op_ld_T0_A0(OT_LONG + s->mem_index);
20f8bd48 7822 tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
d3eb5eae 7823 gen_helper_ldmxcsr(cpu_env, cpu_tmp2_i32);
14ce26e7 7824 } else {
651ba608 7825 tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, mxcsr));
57fec1fe 7826 gen_op_st_T0_A0(OT_LONG + s->mem_index);
14ce26e7 7827 }
664e0f19
FB
7828 break;
7829 case 5: /* lfence */
7830 case 6: /* mfence */
8001c294 7831 if ((modrm & 0xc7) != 0xc0 || !(s->cpuid_features & CPUID_SSE2))
664e0f19
FB
7832 goto illegal_op;
7833 break;
8f091a59
FB
7834 case 7: /* sfence / clflush */
7835 if ((modrm & 0xc7) == 0xc0) {
7836 /* sfence */
a35f3ec7 7837 /* XXX: also check for cpuid_ext2_features & CPUID_EXT2_EMMX */
8f091a59
FB
7838 if (!(s->cpuid_features & CPUID_SSE))
7839 goto illegal_op;
7840 } else {
7841 /* clflush */
7842 if (!(s->cpuid_features & CPUID_CLFLUSH))
7843 goto illegal_op;
0af10c86 7844 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
8f091a59
FB
7845 }
7846 break;
664e0f19 7847 default:
14ce26e7
FB
7848 goto illegal_op;
7849 }
7850 break;
a35f3ec7 7851 case 0x10d: /* 3DNow! prefetch(w) */
0af10c86 7852 modrm = cpu_ldub_code(env, s->pc++);
a35f3ec7
AJ
7853 mod = (modrm >> 6) & 3;
7854 if (mod == 3)
7855 goto illegal_op;
0af10c86 7856 gen_lea_modrm(env, s, modrm, &reg_addr, &offset_addr);
8f091a59
FB
7857 /* ignore for now */
7858 break;
3b21e03e 7859 case 0x1aa: /* rsm */
872929aa 7860 gen_svm_check_intercept(s, pc_start, SVM_EXIT_RSM);
3b21e03e
FB
7861 if (!(s->flags & HF_SMM_MASK))
7862 goto illegal_op;
728d803b 7863 gen_update_cc_op(s);
3b21e03e 7864 gen_jmp_im(s->pc - s->cs_base);
608badfc 7865 gen_helper_rsm(cpu_env);
3b21e03e
FB
7866 gen_eob(s);
7867 break;
222a3336
AZ
7868 case 0x1b8: /* SSE4.2 popcnt */
7869 if ((prefixes & (PREFIX_REPZ | PREFIX_LOCK | PREFIX_REPNZ)) !=
7870 PREFIX_REPZ)
7871 goto illegal_op;
7872 if (!(s->cpuid_ext_features & CPUID_EXT_POPCNT))
7873 goto illegal_op;
7874
0af10c86 7875 modrm = cpu_ldub_code(env, s->pc++);
8b4a3df8 7876 reg = ((modrm >> 3) & 7) | rex_r;
222a3336
AZ
7877
7878 if (s->prefix & PREFIX_DATA)
7879 ot = OT_WORD;
7880 else if (s->dflag != 2)
7881 ot = OT_LONG;
7882 else
7883 ot = OT_QUAD;
7884
0af10c86 7885 gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0);
d3eb5eae 7886 gen_helper_popcnt(cpu_T[0], cpu_env, cpu_T[0], tcg_const_i32(ot));
222a3336 7887 gen_op_mov_reg_T0(ot, reg);
fdb0d09d 7888
3ca51d07 7889 set_cc_op(s, CC_OP_EFLAGS);
222a3336 7890 break;
a35f3ec7
AJ
7891 case 0x10e ... 0x10f:
7892 /* 3DNow! instructions, ignore prefixes */
7893 s->prefix &= ~(PREFIX_REPZ | PREFIX_REPNZ | PREFIX_DATA);
664e0f19
FB
7894 case 0x110 ... 0x117:
7895 case 0x128 ... 0x12f:
4242b1bd 7896 case 0x138 ... 0x13a:
d9f4bb27 7897 case 0x150 ... 0x179:
664e0f19
FB
7898 case 0x17c ... 0x17f:
7899 case 0x1c2:
7900 case 0x1c4 ... 0x1c6:
7901 case 0x1d0 ... 0x1fe:
0af10c86 7902 gen_sse(env, s, b, pc_start, rex_r);
664e0f19 7903 break;
2c0262af
FB
7904 default:
7905 goto illegal_op;
7906 }
7907 /* lock generation */
7908 if (s->prefix & PREFIX_LOCK)
a7812ae4 7909 gen_helper_unlock();
2c0262af
FB
7910 return s->pc;
7911 illegal_op:
ab1f142b 7912 if (s->prefix & PREFIX_LOCK)
a7812ae4 7913 gen_helper_unlock();
2c0262af
FB
7914 /* XXX: ensure that no lock was generated */
7915 gen_exception(s, EXCP06_ILLOP, pc_start - s->cs_base);
7916 return s->pc;
7917}
7918
2c0262af
FB
7919void optimize_flags_init(void)
7920{
a7812ae4
PB
7921 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
7922 cpu_cc_op = tcg_global_mem_new_i32(TCG_AREG0,
317ac620 7923 offsetof(CPUX86State, cc_op), "cc_op");
317ac620 7924 cpu_cc_dst = tcg_global_mem_new(TCG_AREG0, offsetof(CPUX86State, cc_dst),
a7812ae4 7925 "cc_dst");
a3251186
RH
7926 cpu_cc_src = tcg_global_mem_new(TCG_AREG0, offsetof(CPUX86State, cc_src),
7927 "cc_src");
988c3eb0
RH
7928 cpu_cc_src2 = tcg_global_mem_new(TCG_AREG0, offsetof(CPUX86State, cc_src2),
7929 "cc_src2");
437a88a5 7930
cc739bb0
LD
7931#ifdef TARGET_X86_64
7932 cpu_regs[R_EAX] = tcg_global_mem_new_i64(TCG_AREG0,
317ac620 7933 offsetof(CPUX86State, regs[R_EAX]), "rax");
cc739bb0 7934 cpu_regs[R_ECX] = tcg_global_mem_new_i64(TCG_AREG0,
317ac620 7935 offsetof(CPUX86State, regs[R_ECX]), "rcx");
cc739bb0 7936 cpu_regs[R_EDX] = tcg_global_mem_new_i64(TCG_AREG0,
317ac620 7937 offsetof(CPUX86State, regs[R_EDX]), "rdx");
cc739bb0 7938 cpu_regs[R_EBX] = tcg_global_mem_new_i64(TCG_AREG0,
317ac620 7939 offsetof(CPUX86State, regs[R_EBX]), "rbx");
cc739bb0 7940 cpu_regs[R_ESP] = tcg_global_mem_new_i64(TCG_AREG0,
317ac620 7941 offsetof(CPUX86State, regs[R_ESP]), "rsp");
cc739bb0 7942 cpu_regs[R_EBP] = tcg_global_mem_new_i64(TCG_AREG0,
317ac620 7943 offsetof(CPUX86State, regs[R_EBP]), "rbp");
cc739bb0 7944 cpu_regs[R_ESI] = tcg_global_mem_new_i64(TCG_AREG0,
317ac620 7945 offsetof(CPUX86State, regs[R_ESI]), "rsi");
cc739bb0 7946 cpu_regs[R_EDI] = tcg_global_mem_new_i64(TCG_AREG0,
317ac620 7947 offsetof(CPUX86State, regs[R_EDI]), "rdi");
cc739bb0 7948 cpu_regs[8] = tcg_global_mem_new_i64(TCG_AREG0,
317ac620 7949 offsetof(CPUX86State, regs[8]), "r8");
cc739bb0 7950 cpu_regs[9] = tcg_global_mem_new_i64(TCG_AREG0,
317ac620 7951 offsetof(CPUX86State, regs[9]), "r9");
cc739bb0 7952 cpu_regs[10] = tcg_global_mem_new_i64(TCG_AREG0,
317ac620 7953 offsetof(CPUX86State, regs[10]), "r10");
cc739bb0 7954 cpu_regs[11] = tcg_global_mem_new_i64(TCG_AREG0,
317ac620 7955 offsetof(CPUX86State, regs[11]), "r11");
cc739bb0 7956 cpu_regs[12] = tcg_global_mem_new_i64(TCG_AREG0,
317ac620 7957 offsetof(CPUX86State, regs[12]), "r12");
cc739bb0 7958 cpu_regs[13] = tcg_global_mem_new_i64(TCG_AREG0,
317ac620 7959 offsetof(CPUX86State, regs[13]), "r13");
cc739bb0 7960 cpu_regs[14] = tcg_global_mem_new_i64(TCG_AREG0,
317ac620 7961 offsetof(CPUX86State, regs[14]), "r14");
cc739bb0 7962 cpu_regs[15] = tcg_global_mem_new_i64(TCG_AREG0,
317ac620 7963 offsetof(CPUX86State, regs[15]), "r15");
cc739bb0
LD
7964#else
7965 cpu_regs[R_EAX] = tcg_global_mem_new_i32(TCG_AREG0,
317ac620 7966 offsetof(CPUX86State, regs[R_EAX]), "eax");
cc739bb0 7967 cpu_regs[R_ECX] = tcg_global_mem_new_i32(TCG_AREG0,
317ac620 7968 offsetof(CPUX86State, regs[R_ECX]), "ecx");
cc739bb0 7969 cpu_regs[R_EDX] = tcg_global_mem_new_i32(TCG_AREG0,
317ac620 7970 offsetof(CPUX86State, regs[R_EDX]), "edx");
cc739bb0 7971 cpu_regs[R_EBX] = tcg_global_mem_new_i32(TCG_AREG0,
317ac620 7972 offsetof(CPUX86State, regs[R_EBX]), "ebx");
cc739bb0 7973 cpu_regs[R_ESP] = tcg_global_mem_new_i32(TCG_AREG0,
317ac620 7974 offsetof(CPUX86State, regs[R_ESP]), "esp");
cc739bb0 7975 cpu_regs[R_EBP] = tcg_global_mem_new_i32(TCG_AREG0,
317ac620 7976 offsetof(CPUX86State, regs[R_EBP]), "ebp");
cc739bb0 7977 cpu_regs[R_ESI] = tcg_global_mem_new_i32(TCG_AREG0,
317ac620 7978 offsetof(CPUX86State, regs[R_ESI]), "esi");
cc739bb0 7979 cpu_regs[R_EDI] = tcg_global_mem_new_i32(TCG_AREG0,
317ac620 7980 offsetof(CPUX86State, regs[R_EDI]), "edi");
cc739bb0
LD
7981#endif
7982
437a88a5 7983 /* register helpers */
a7812ae4 7984#define GEN_HELPER 2
437a88a5 7985#include "helper.h"
2c0262af
FB
7986}
7987
7988/* generate intermediate code in gen_opc_buf and gen_opparam_buf for
7989 basic block 'tb'. If search_pc is TRUE, also generate PC
7990 information for each intermediate instruction. */
317ac620 7991static inline void gen_intermediate_code_internal(CPUX86State *env,
2cfc5f17
TS
7992 TranslationBlock *tb,
7993 int search_pc)
2c0262af
FB
7994{
7995 DisasContext dc1, *dc = &dc1;
14ce26e7 7996 target_ulong pc_ptr;
2c0262af 7997 uint16_t *gen_opc_end;
a1d1bb31 7998 CPUBreakpoint *bp;
7f5b7d3e 7999 int j, lj;
c068688b 8000 uint64_t flags;
14ce26e7
FB
8001 target_ulong pc_start;
8002 target_ulong cs_base;
2e70f6ef
PB
8003 int num_insns;
8004 int max_insns;
3b46e624 8005
2c0262af 8006 /* generate intermediate code */
14ce26e7
FB
8007 pc_start = tb->pc;
8008 cs_base = tb->cs_base;
2c0262af 8009 flags = tb->flags;
3a1d9b8b 8010
4f31916f 8011 dc->pe = (flags >> HF_PE_SHIFT) & 1;
2c0262af
FB
8012 dc->code32 = (flags >> HF_CS32_SHIFT) & 1;
8013 dc->ss32 = (flags >> HF_SS32_SHIFT) & 1;
8014 dc->addseg = (flags >> HF_ADDSEG_SHIFT) & 1;
8015 dc->f_st = 0;
8016 dc->vm86 = (flags >> VM_SHIFT) & 1;
8017 dc->cpl = (flags >> HF_CPL_SHIFT) & 3;
8018 dc->iopl = (flags >> IOPL_SHIFT) & 3;
8019 dc->tf = (flags >> TF_SHIFT) & 1;
34865134 8020 dc->singlestep_enabled = env->singlestep_enabled;
2c0262af 8021 dc->cc_op = CC_OP_DYNAMIC;
e207582f 8022 dc->cc_op_dirty = false;
2c0262af
FB
8023 dc->cs_base = cs_base;
8024 dc->tb = tb;
8025 dc->popl_esp_hack = 0;
8026 /* select memory access functions */
8027 dc->mem_index = 0;
8028 if (flags & HF_SOFTMMU_MASK) {
a9321a4d 8029 dc->mem_index = (cpu_mmu_index(env) + 1) << 2;
2c0262af 8030 }
14ce26e7 8031 dc->cpuid_features = env->cpuid_features;
3d7374c5 8032 dc->cpuid_ext_features = env->cpuid_ext_features;
e771edab 8033 dc->cpuid_ext2_features = env->cpuid_ext2_features;
12e26b75 8034 dc->cpuid_ext3_features = env->cpuid_ext3_features;
a9321a4d 8035 dc->cpuid_7_0_ebx_features = env->cpuid_7_0_ebx_features;
14ce26e7
FB
8036#ifdef TARGET_X86_64
8037 dc->lma = (flags >> HF_LMA_SHIFT) & 1;
8038 dc->code64 = (flags >> HF_CS64_SHIFT) & 1;
8039#endif
7eee2a50 8040 dc->flags = flags;
a2cc3b24
FB
8041 dc->jmp_opt = !(dc->tf || env->singlestep_enabled ||
8042 (flags & HF_INHIBIT_IRQ_MASK)
415fa2ea 8043#ifndef CONFIG_SOFTMMU
2c0262af
FB
8044 || (flags & HF_SOFTMMU_MASK)
8045#endif
8046 );
4f31916f
FB
8047#if 0
8048 /* check addseg logic */
dc196a57 8049 if (!dc->addseg && (dc->vm86 || !dc->pe || !dc->code32))
4f31916f
FB
8050 printf("ERROR addseg\n");
8051#endif
8052
a7812ae4
PB
8053 cpu_T[0] = tcg_temp_new();
8054 cpu_T[1] = tcg_temp_new();
8055 cpu_A0 = tcg_temp_new();
a7812ae4
PB
8056
8057 cpu_tmp0 = tcg_temp_new();
8058 cpu_tmp1_i64 = tcg_temp_new_i64();
8059 cpu_tmp2_i32 = tcg_temp_new_i32();
8060 cpu_tmp3_i32 = tcg_temp_new_i32();
8061 cpu_tmp4 = tcg_temp_new();
8062 cpu_tmp5 = tcg_temp_new();
a7812ae4
PB
8063 cpu_ptr0 = tcg_temp_new_ptr();
8064 cpu_ptr1 = tcg_temp_new_ptr();
a3251186 8065 cpu_cc_srcT = tcg_temp_local_new();
57fec1fe 8066
92414b31 8067 gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
2c0262af
FB
8068
8069 dc->is_jmp = DISAS_NEXT;
8070 pc_ptr = pc_start;
8071 lj = -1;
2e70f6ef
PB
8072 num_insns = 0;
8073 max_insns = tb->cflags & CF_COUNT_MASK;
8074 if (max_insns == 0)
8075 max_insns = CF_COUNT_MASK;
2c0262af 8076
2e70f6ef 8077 gen_icount_start();
2c0262af 8078 for(;;) {
72cf2d4f
BS
8079 if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
8080 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
a2397807
JK
8081 if (bp->pc == pc_ptr &&
8082 !((bp->flags & BP_CPU) && (tb->flags & HF_RF_MASK))) {
2c0262af
FB
8083 gen_debug(dc, pc_ptr - dc->cs_base);
8084 break;
8085 }
8086 }
8087 }
8088 if (search_pc) {
92414b31 8089 j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
2c0262af
FB
8090 if (lj < j) {
8091 lj++;
8092 while (lj < j)
ab1103de 8093 tcg_ctx.gen_opc_instr_start[lj++] = 0;
2c0262af 8094 }
25983cad 8095 tcg_ctx.gen_opc_pc[lj] = pc_ptr;
2c0262af 8096 gen_opc_cc_op[lj] = dc->cc_op;
ab1103de 8097 tcg_ctx.gen_opc_instr_start[lj] = 1;
c9c99c22 8098 tcg_ctx.gen_opc_icount[lj] = num_insns;
2c0262af 8099 }
2e70f6ef
PB
8100 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
8101 gen_io_start();
8102
0af10c86 8103 pc_ptr = disas_insn(env, dc, pc_ptr);
2e70f6ef 8104 num_insns++;
2c0262af
FB
8105 /* stop translation if indicated */
8106 if (dc->is_jmp)
8107 break;
8108 /* if single step mode, we generate only one instruction and
8109 generate an exception */
a2cc3b24
FB
8110 /* if irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear
8111 the flag and abort the translation to give the irqs a
8112 change to be happen */
5fafdf24 8113 if (dc->tf || dc->singlestep_enabled ||
2e70f6ef 8114 (flags & HF_INHIBIT_IRQ_MASK)) {
14ce26e7 8115 gen_jmp_im(pc_ptr - dc->cs_base);
2c0262af
FB
8116 gen_eob(dc);
8117 break;
8118 }
8119 /* if too long translation, stop generation too */
efd7f486 8120 if (tcg_ctx.gen_opc_ptr >= gen_opc_end ||
2e70f6ef
PB
8121 (pc_ptr - pc_start) >= (TARGET_PAGE_SIZE - 32) ||
8122 num_insns >= max_insns) {
14ce26e7 8123 gen_jmp_im(pc_ptr - dc->cs_base);
2c0262af
FB
8124 gen_eob(dc);
8125 break;
8126 }
1b530a6d
AJ
8127 if (singlestep) {
8128 gen_jmp_im(pc_ptr - dc->cs_base);
8129 gen_eob(dc);
8130 break;
8131 }
2c0262af 8132 }
2e70f6ef
PB
8133 if (tb->cflags & CF_LAST_IO)
8134 gen_io_end();
8135 gen_icount_end(tb, num_insns);
efd7f486 8136 *tcg_ctx.gen_opc_ptr = INDEX_op_end;
2c0262af
FB
8137 /* we don't forget to fill the last values */
8138 if (search_pc) {
92414b31 8139 j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
2c0262af
FB
8140 lj++;
8141 while (lj <= j)
ab1103de 8142 tcg_ctx.gen_opc_instr_start[lj++] = 0;
2c0262af 8143 }
3b46e624 8144
2c0262af 8145#ifdef DEBUG_DISAS
8fec2b8c 8146 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
14ce26e7 8147 int disas_flags;
93fcfe39
AL
8148 qemu_log("----------------\n");
8149 qemu_log("IN: %s\n", lookup_symbol(pc_start));
14ce26e7
FB
8150#ifdef TARGET_X86_64
8151 if (dc->code64)
8152 disas_flags = 2;
8153 else
8154#endif
8155 disas_flags = !dc->code32;
f4359b9f 8156 log_target_disas(env, pc_start, pc_ptr - pc_start, disas_flags);
93fcfe39 8157 qemu_log("\n");
2c0262af
FB
8158 }
8159#endif
8160
2e70f6ef 8161 if (!search_pc) {
2c0262af 8162 tb->size = pc_ptr - pc_start;
2e70f6ef
PB
8163 tb->icount = num_insns;
8164 }
2c0262af
FB
8165}
8166
317ac620 8167void gen_intermediate_code(CPUX86State *env, TranslationBlock *tb)
2c0262af 8168{
2cfc5f17 8169 gen_intermediate_code_internal(env, tb, 0);
2c0262af
FB
8170}
8171
317ac620 8172void gen_intermediate_code_pc(CPUX86State *env, TranslationBlock *tb)
2c0262af 8173{
2cfc5f17 8174 gen_intermediate_code_internal(env, tb, 1);
2c0262af
FB
8175}
8176
317ac620 8177void restore_state_to_opc(CPUX86State *env, TranslationBlock *tb, int pc_pos)
d2856f1a
AJ
8178{
8179 int cc_op;
8180#ifdef DEBUG_DISAS
8fec2b8c 8181 if (qemu_loglevel_mask(CPU_LOG_TB_OP)) {
d2856f1a 8182 int i;
93fcfe39 8183 qemu_log("RESTORE:\n");
d2856f1a 8184 for(i = 0;i <= pc_pos; i++) {
ab1103de 8185 if (tcg_ctx.gen_opc_instr_start[i]) {
25983cad
EV
8186 qemu_log("0x%04x: " TARGET_FMT_lx "\n", i,
8187 tcg_ctx.gen_opc_pc[i]);
d2856f1a
AJ
8188 }
8189 }
e87b7cb0 8190 qemu_log("pc_pos=0x%x eip=" TARGET_FMT_lx " cs_base=%x\n",
25983cad 8191 pc_pos, tcg_ctx.gen_opc_pc[pc_pos] - tb->cs_base,
d2856f1a
AJ
8192 (uint32_t)tb->cs_base);
8193 }
8194#endif
25983cad 8195 env->eip = tcg_ctx.gen_opc_pc[pc_pos] - tb->cs_base;
d2856f1a
AJ
8196 cc_op = gen_opc_cc_op[pc_pos];
8197 if (cc_op != CC_OP_DYNAMIC)
8198 env->cc_op = cc_op;
8199}