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