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