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