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