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