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