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