4 * Copyright (c) 2003 Fabrice Bellard
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.
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.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
33 /* XXX: move that elsewhere */
34 static uint16_t *gen_opc_ptr
;
35 static uint32_t *gen_opparam_ptr
;
37 #define PREFIX_REPZ 0x01
38 #define PREFIX_REPNZ 0x02
39 #define PREFIX_LOCK 0x04
40 #define PREFIX_DATA 0x08
41 #define PREFIX_ADR 0x10
43 typedef struct DisasContext
{
44 /* current insn context */
45 int override
; /* -1 if no override */
48 uint8_t *pc
; /* pc = eip + cs_base */
49 int is_jmp
; /* 1 = means jump (stop translation), 2 means CPU
50 static state change (stop translation) */
51 /* current block context */
52 uint8_t *cs_base
; /* base of CS segment */
53 int pe
; /* protected mode */
54 int code32
; /* 32 bit code segment */
55 int ss32
; /* 32 bit stack segment */
56 int cc_op
; /* current CC operation */
57 int addseg
; /* non zero if either DS/ES/SS have a non zero base */
58 int f_st
; /* currently unused */
59 int vm86
; /* vm86 mode */
62 int tf
; /* TF cpu flag */
63 int mem_index
; /* select memory access functions */
64 struct TranslationBlock
*tb
;
65 int popl_esp_hack
; /* for correct popl with esp base handling */
68 /* i386 arith/logic operations */
88 OP_SHL1
, /* undocumented */
93 #define DEF(s, n, copy_size) INDEX_op_ ## s,
99 #include "gen-op-i386.h"
110 /* I386 int registers */
111 OR_EAX
, /* MUST be even numbered */
119 OR_TMP0
, /* temporary operand register */
121 OR_A0
, /* temporary register used when doing address evaluation */
122 OR_ZERO
, /* fixed zero register */
126 typedef void (GenOpFunc
)(void);
127 typedef void (GenOpFunc1
)(long);
128 typedef void (GenOpFunc2
)(long, long);
129 typedef void (GenOpFunc3
)(long, long, long);
131 static GenOpFunc
*gen_op_mov_reg_T0
[3][8] = {
164 static GenOpFunc
*gen_op_mov_reg_T1
[3][8] = {
197 static GenOpFunc
*gen_op_mov_reg_A0
[2][8] = {
220 static GenOpFunc
*gen_op_mov_TN_reg
[3][2][8] =
290 static GenOpFunc
*gen_op_movl_A0_reg
[8] = {
301 static GenOpFunc
*gen_op_addl_A0_reg_sN
[4][8] = {
313 gen_op_addl_A0_EAX_s1
,
314 gen_op_addl_A0_ECX_s1
,
315 gen_op_addl_A0_EDX_s1
,
316 gen_op_addl_A0_EBX_s1
,
317 gen_op_addl_A0_ESP_s1
,
318 gen_op_addl_A0_EBP_s1
,
319 gen_op_addl_A0_ESI_s1
,
320 gen_op_addl_A0_EDI_s1
,
323 gen_op_addl_A0_EAX_s2
,
324 gen_op_addl_A0_ECX_s2
,
325 gen_op_addl_A0_EDX_s2
,
326 gen_op_addl_A0_EBX_s2
,
327 gen_op_addl_A0_ESP_s2
,
328 gen_op_addl_A0_EBP_s2
,
329 gen_op_addl_A0_ESI_s2
,
330 gen_op_addl_A0_EDI_s2
,
333 gen_op_addl_A0_EAX_s3
,
334 gen_op_addl_A0_ECX_s3
,
335 gen_op_addl_A0_EDX_s3
,
336 gen_op_addl_A0_EBX_s3
,
337 gen_op_addl_A0_ESP_s3
,
338 gen_op_addl_A0_EBP_s3
,
339 gen_op_addl_A0_ESI_s3
,
340 gen_op_addl_A0_EDI_s3
,
344 static GenOpFunc
*gen_op_cmov_reg_T1_T0
[2][8] = {
346 gen_op_cmovw_EAX_T1_T0
,
347 gen_op_cmovw_ECX_T1_T0
,
348 gen_op_cmovw_EDX_T1_T0
,
349 gen_op_cmovw_EBX_T1_T0
,
350 gen_op_cmovw_ESP_T1_T0
,
351 gen_op_cmovw_EBP_T1_T0
,
352 gen_op_cmovw_ESI_T1_T0
,
353 gen_op_cmovw_EDI_T1_T0
,
356 gen_op_cmovl_EAX_T1_T0
,
357 gen_op_cmovl_ECX_T1_T0
,
358 gen_op_cmovl_EDX_T1_T0
,
359 gen_op_cmovl_EBX_T1_T0
,
360 gen_op_cmovl_ESP_T1_T0
,
361 gen_op_cmovl_EBP_T1_T0
,
362 gen_op_cmovl_ESI_T1_T0
,
363 gen_op_cmovl_EDI_T1_T0
,
367 static GenOpFunc
*gen_op_arith_T0_T1_cc
[8] = {
378 static GenOpFunc
*gen_op_arithc_T0_T1_cc
[3][2] = {
380 gen_op_adcb_T0_T1_cc
,
381 gen_op_sbbb_T0_T1_cc
,
384 gen_op_adcw_T0_T1_cc
,
385 gen_op_sbbw_T0_T1_cc
,
388 gen_op_adcl_T0_T1_cc
,
389 gen_op_sbbl_T0_T1_cc
,
393 static GenOpFunc
*gen_op_arithc_mem_T0_T1_cc
[3][2] = {
395 gen_op_adcb_mem_T0_T1_cc
,
396 gen_op_sbbb_mem_T0_T1_cc
,
399 gen_op_adcw_mem_T0_T1_cc
,
400 gen_op_sbbw_mem_T0_T1_cc
,
403 gen_op_adcl_mem_T0_T1_cc
,
404 gen_op_sbbl_mem_T0_T1_cc
,
408 static const int cc_op_arithb
[8] = {
419 static GenOpFunc
*gen_op_cmpxchg_T0_T1_EAX_cc
[3] = {
420 gen_op_cmpxchgb_T0_T1_EAX_cc
,
421 gen_op_cmpxchgw_T0_T1_EAX_cc
,
422 gen_op_cmpxchgl_T0_T1_EAX_cc
,
425 static GenOpFunc
*gen_op_cmpxchg_mem_T0_T1_EAX_cc
[3] = {
426 gen_op_cmpxchgb_mem_T0_T1_EAX_cc
,
427 gen_op_cmpxchgw_mem_T0_T1_EAX_cc
,
428 gen_op_cmpxchgl_mem_T0_T1_EAX_cc
,
431 static GenOpFunc
*gen_op_shift_T0_T1_cc
[3][8] = {
433 gen_op_rolb_T0_T1_cc
,
434 gen_op_rorb_T0_T1_cc
,
435 gen_op_rclb_T0_T1_cc
,
436 gen_op_rcrb_T0_T1_cc
,
437 gen_op_shlb_T0_T1_cc
,
438 gen_op_shrb_T0_T1_cc
,
439 gen_op_shlb_T0_T1_cc
,
440 gen_op_sarb_T0_T1_cc
,
443 gen_op_rolw_T0_T1_cc
,
444 gen_op_rorw_T0_T1_cc
,
445 gen_op_rclw_T0_T1_cc
,
446 gen_op_rcrw_T0_T1_cc
,
447 gen_op_shlw_T0_T1_cc
,
448 gen_op_shrw_T0_T1_cc
,
449 gen_op_shlw_T0_T1_cc
,
450 gen_op_sarw_T0_T1_cc
,
453 gen_op_roll_T0_T1_cc
,
454 gen_op_rorl_T0_T1_cc
,
455 gen_op_rcll_T0_T1_cc
,
456 gen_op_rcrl_T0_T1_cc
,
457 gen_op_shll_T0_T1_cc
,
458 gen_op_shrl_T0_T1_cc
,
459 gen_op_shll_T0_T1_cc
,
460 gen_op_sarl_T0_T1_cc
,
464 static GenOpFunc
*gen_op_shift_mem_T0_T1_cc
[3][8] = {
466 gen_op_rolb_mem_T0_T1_cc
,
467 gen_op_rorb_mem_T0_T1_cc
,
468 gen_op_rclb_mem_T0_T1_cc
,
469 gen_op_rcrb_mem_T0_T1_cc
,
470 gen_op_shlb_mem_T0_T1_cc
,
471 gen_op_shrb_mem_T0_T1_cc
,
472 gen_op_shlb_mem_T0_T1_cc
,
473 gen_op_sarb_mem_T0_T1_cc
,
476 gen_op_rolw_mem_T0_T1_cc
,
477 gen_op_rorw_mem_T0_T1_cc
,
478 gen_op_rclw_mem_T0_T1_cc
,
479 gen_op_rcrw_mem_T0_T1_cc
,
480 gen_op_shlw_mem_T0_T1_cc
,
481 gen_op_shrw_mem_T0_T1_cc
,
482 gen_op_shlw_mem_T0_T1_cc
,
483 gen_op_sarw_mem_T0_T1_cc
,
486 gen_op_roll_mem_T0_T1_cc
,
487 gen_op_rorl_mem_T0_T1_cc
,
488 gen_op_rcll_mem_T0_T1_cc
,
489 gen_op_rcrl_mem_T0_T1_cc
,
490 gen_op_shll_mem_T0_T1_cc
,
491 gen_op_shrl_mem_T0_T1_cc
,
492 gen_op_shll_mem_T0_T1_cc
,
493 gen_op_sarl_mem_T0_T1_cc
,
497 static GenOpFunc1
*gen_op_shiftd_T0_T1_im_cc
[2][2] = {
499 gen_op_shldw_T0_T1_im_cc
,
500 gen_op_shrdw_T0_T1_im_cc
,
503 gen_op_shldl_T0_T1_im_cc
,
504 gen_op_shrdl_T0_T1_im_cc
,
508 static GenOpFunc
*gen_op_shiftd_T0_T1_ECX_cc
[2][2] = {
510 gen_op_shldw_T0_T1_ECX_cc
,
511 gen_op_shrdw_T0_T1_ECX_cc
,
514 gen_op_shldl_T0_T1_ECX_cc
,
515 gen_op_shrdl_T0_T1_ECX_cc
,
519 static GenOpFunc1
*gen_op_shiftd_mem_T0_T1_im_cc
[2][2] = {
521 gen_op_shldw_mem_T0_T1_im_cc
,
522 gen_op_shrdw_mem_T0_T1_im_cc
,
525 gen_op_shldl_mem_T0_T1_im_cc
,
526 gen_op_shrdl_mem_T0_T1_im_cc
,
530 static GenOpFunc
*gen_op_shiftd_mem_T0_T1_ECX_cc
[2][2] = {
532 gen_op_shldw_mem_T0_T1_ECX_cc
,
533 gen_op_shrdw_mem_T0_T1_ECX_cc
,
536 gen_op_shldl_mem_T0_T1_ECX_cc
,
537 gen_op_shrdl_mem_T0_T1_ECX_cc
,
541 static GenOpFunc
*gen_op_btx_T0_T1_cc
[2][4] = {
544 gen_op_btsw_T0_T1_cc
,
545 gen_op_btrw_T0_T1_cc
,
546 gen_op_btcw_T0_T1_cc
,
550 gen_op_btsl_T0_T1_cc
,
551 gen_op_btrl_T0_T1_cc
,
552 gen_op_btcl_T0_T1_cc
,
556 static GenOpFunc
*gen_op_bsx_T0_cc
[2][2] = {
567 static GenOpFunc
*gen_op_lds_T0_A0
[3 * 3] = {
572 gen_op_ldsb_kernel_T0_A0
,
573 gen_op_ldsw_kernel_T0_A0
,
576 gen_op_ldsb_user_T0_A0
,
577 gen_op_ldsw_user_T0_A0
,
581 static GenOpFunc
*gen_op_ldu_T0_A0
[3 * 3] = {
586 gen_op_ldub_kernel_T0_A0
,
587 gen_op_lduw_kernel_T0_A0
,
590 gen_op_ldub_user_T0_A0
,
591 gen_op_lduw_user_T0_A0
,
595 /* sign does not matter, except for lidt/lgdt call (TODO: fix it) */
596 static GenOpFunc
*gen_op_ld_T0_A0
[3 * 3] = {
601 gen_op_ldub_kernel_T0_A0
,
602 gen_op_lduw_kernel_T0_A0
,
603 gen_op_ldl_kernel_T0_A0
,
605 gen_op_ldub_user_T0_A0
,
606 gen_op_lduw_user_T0_A0
,
607 gen_op_ldl_user_T0_A0
,
610 static GenOpFunc
*gen_op_ld_T1_A0
[3 * 3] = {
615 gen_op_ldub_kernel_T1_A0
,
616 gen_op_lduw_kernel_T1_A0
,
617 gen_op_ldl_kernel_T1_A0
,
619 gen_op_ldub_user_T1_A0
,
620 gen_op_lduw_user_T1_A0
,
621 gen_op_ldl_user_T1_A0
,
624 static GenOpFunc
*gen_op_st_T0_A0
[3 * 3] = {
629 gen_op_stb_kernel_T0_A0
,
630 gen_op_stw_kernel_T0_A0
,
631 gen_op_stl_kernel_T0_A0
,
633 gen_op_stb_user_T0_A0
,
634 gen_op_stw_user_T0_A0
,
635 gen_op_stl_user_T0_A0
,
638 /* the _a32 and _a16 string operations use A0 as the base register. */
640 #define STRINGOP_NB 9
642 #define STRINGOP(x) \
643 gen_op_ ## x ## b_fast, \
644 gen_op_ ## x ## w_fast, \
645 gen_op_ ## x ## l_fast, \
646 gen_op_ ## x ## b_a32, \
647 gen_op_ ## x ## w_a32, \
648 gen_op_ ## x ## l_a32, \
649 gen_op_ ## x ## b_a16, \
650 gen_op_ ## x ## w_a16, \
651 gen_op_ ## x ## l_a16,
653 static GenOpFunc
*gen_op_scas
[STRINGOP_NB
* 3] = {
658 static GenOpFunc
*gen_op_cmps
[STRINGOP_NB
* 3] = {
663 static inline void gen_string_movl_A0_ESI(DisasContext
*s
)
667 override
= s
->override
;
670 if (s
->addseg
&& override
< 0)
673 gen_op_movl_A0_seg(offsetof(CPUX86State
,segs
[override
].base
));
674 gen_op_addl_A0_reg_sN
[0][R_ESI
]();
676 gen_op_movl_A0_reg
[R_ESI
]();
679 /* 16 address, always override */
682 gen_op_movl_A0_reg
[R_ESI
]();
683 gen_op_andl_A0_ffff();
684 gen_op_addl_A0_seg(offsetof(CPUX86State
,segs
[override
].base
));
688 static inline void gen_string_movl_A0_EDI(DisasContext
*s
)
692 gen_op_movl_A0_seg(offsetof(CPUX86State
,segs
[R_ES
].base
));
693 gen_op_addl_A0_reg_sN
[0][R_EDI
]();
695 gen_op_movl_A0_reg
[R_EDI
]();
698 gen_op_movl_A0_reg
[R_EDI
]();
699 gen_op_andl_A0_ffff();
700 gen_op_addl_A0_seg(offsetof(CPUX86State
,segs
[R_ES
].base
));
704 static GenOpFunc
*gen_op_movl_T0_Dshift
[3] = {
705 gen_op_movl_T0_Dshiftb
,
706 gen_op_movl_T0_Dshiftw
,
707 gen_op_movl_T0_Dshiftl
,
710 static GenOpFunc2
*gen_op_jz_ecx
[2] = {
715 static GenOpFunc
*gen_op_dec_ECX
[2] = {
720 static GenOpFunc2
*gen_op_string_jnz_sub
[2][3] = {
722 gen_op_string_jnz_subb
,
723 gen_op_string_jnz_subw
,
724 gen_op_string_jnz_subl
,
727 gen_op_string_jz_subb
,
728 gen_op_string_jz_subw
,
729 gen_op_string_jz_subl
,
733 static GenOpFunc
*gen_op_in_DX_T0
[3] = {
739 static GenOpFunc
*gen_op_out_DX_T0
[3] = {
745 static inline void gen_movs(DisasContext
*s
, int ot
)
747 gen_string_movl_A0_ESI(s
);
748 gen_op_ld_T0_A0
[ot
+ s
->mem_index
]();
749 gen_string_movl_A0_EDI(s
);
750 gen_op_st_T0_A0
[ot
+ s
->mem_index
]();
751 gen_op_movl_T0_Dshift
[ot
]();
753 gen_op_addl_ESI_T0();
754 gen_op_addl_EDI_T0();
756 gen_op_addw_ESI_T0();
757 gen_op_addw_EDI_T0();
761 /* same method as Valgrind : we generate jumps to current or next
763 static inline void gen_repz_movs(DisasContext
*s
, int ot
,
764 unsigned int cur_eip
, unsigned int next_eip
)
766 if (s
->cc_op
!= CC_OP_DYNAMIC
)
767 gen_op_set_cc_op(s
->cc_op
);
768 gen_op_jz_ecx
[s
->aflag
]((long)s
->tb
, next_eip
);
770 gen_op_dec_ECX
[s
->aflag
]();
771 gen_op_jmp_tb_next((long)s
->tb
, cur_eip
);
775 static inline void gen_stos(DisasContext
*s
, int ot
)
777 gen_op_mov_TN_reg
[OT_LONG
][0][R_EAX
]();
778 gen_string_movl_A0_EDI(s
);
779 gen_op_st_T0_A0
[ot
+ s
->mem_index
]();
780 gen_op_movl_T0_Dshift
[ot
]();
782 gen_op_addl_EDI_T0();
784 gen_op_addw_EDI_T0();
788 static inline void gen_repz_stos(DisasContext
*s
, int ot
,
789 unsigned int cur_eip
, unsigned int next_eip
)
791 if (s
->cc_op
!= CC_OP_DYNAMIC
)
792 gen_op_set_cc_op(s
->cc_op
);
793 gen_op_jz_ecx
[s
->aflag
]((long)s
->tb
, next_eip
);
795 gen_op_dec_ECX
[s
->aflag
]();
796 gen_op_jmp_tb_next((long)s
->tb
, cur_eip
);
800 static inline void gen_lods(DisasContext
*s
, int ot
)
802 gen_string_movl_A0_ESI(s
);
803 gen_op_ld_T0_A0
[ot
+ s
->mem_index
]();
804 gen_op_mov_reg_T0
[ot
][R_EAX
]();
805 gen_op_movl_T0_Dshift
[ot
]();
807 gen_op_addl_ESI_T0();
809 gen_op_addw_ESI_T0();
813 static inline void gen_repz_lods(DisasContext
*s
, int ot
,
814 unsigned int cur_eip
, unsigned int next_eip
)
816 if (s
->cc_op
!= CC_OP_DYNAMIC
)
817 gen_op_set_cc_op(s
->cc_op
);
818 gen_op_jz_ecx
[s
->aflag
]((long)s
->tb
, next_eip
);
820 gen_op_dec_ECX
[s
->aflag
]();
821 gen_op_jmp_tb_next((long)s
->tb
, cur_eip
);
825 static inline void gen_scas(DisasContext
*s
, int ot
)
827 gen_op_mov_TN_reg
[OT_LONG
][0][R_EAX
]();
828 gen_string_movl_A0_EDI(s
);
829 gen_op_ld_T1_A0
[ot
+ s
->mem_index
]();
830 gen_op_cmpl_T0_T1_cc();
831 gen_op_movl_T0_Dshift
[ot
]();
833 gen_op_addl_EDI_T0();
835 gen_op_addw_EDI_T0();
840 static inline void gen_repz_scas(DisasContext
*s
, int ot
,
841 unsigned int cur_eip
, unsigned int next_eip
,
844 if (s
->cc_op
!= CC_OP_DYNAMIC
)
845 gen_op_set_cc_op(s
->cc_op
);
846 gen_op_jz_ecx
[s
->aflag
]((long)s
->tb
, next_eip
);
848 gen_op_set_cc_op(CC_OP_SUBB
+ ot
);
849 gen_op_string_jnz_sub
[nz
][ot
]((long)s
->tb
, next_eip
);
850 gen_op_dec_ECX
[s
->aflag
]();
851 gen_op_jmp_tb_next((long)s
->tb
, cur_eip
);
856 static inline void gen_cmps(DisasContext
*s
, int ot
)
858 gen_string_movl_A0_ESI(s
);
859 gen_op_ld_T0_A0
[ot
+ s
->mem_index
]();
860 gen_string_movl_A0_EDI(s
);
861 gen_op_ld_T1_A0
[ot
+ s
->mem_index
]();
862 gen_op_cmpl_T0_T1_cc();
863 gen_op_movl_T0_Dshift
[ot
]();
865 gen_op_addl_ESI_T0();
866 gen_op_addl_EDI_T0();
868 gen_op_addw_ESI_T0();
869 gen_op_addw_EDI_T0();
873 static inline void gen_ins(DisasContext
*s
, int ot
)
875 gen_op_in_DX_T0
[ot
]();
876 gen_string_movl_A0_EDI(s
);
877 gen_op_st_T0_A0
[ot
+ s
->mem_index
]();
878 gen_op_movl_T0_Dshift
[ot
]();
880 gen_op_addl_EDI_T0();
882 gen_op_addw_EDI_T0();
886 static inline void gen_repz_ins(DisasContext
*s
, int ot
,
887 unsigned int cur_eip
, unsigned int next_eip
)
889 if (s
->cc_op
!= CC_OP_DYNAMIC
)
890 gen_op_set_cc_op(s
->cc_op
);
891 gen_op_jz_ecx
[s
->aflag
]((long)s
->tb
, next_eip
);
893 gen_op_dec_ECX
[s
->aflag
]();
894 gen_op_jmp_tb_next((long)s
->tb
, cur_eip
);
898 static inline void gen_outs(DisasContext
*s
, int ot
)
900 gen_string_movl_A0_ESI(s
);
901 gen_op_ld_T0_A0
[ot
+ s
->mem_index
]();
902 gen_op_out_DX_T0
[ot
]();
903 gen_op_movl_T0_Dshift
[ot
]();
905 gen_op_addl_ESI_T0();
907 gen_op_addw_ESI_T0();
911 static inline void gen_repz_outs(DisasContext
*s
, int ot
,
912 unsigned int cur_eip
, unsigned int next_eip
)
914 if (s
->cc_op
!= CC_OP_DYNAMIC
)
915 gen_op_set_cc_op(s
->cc_op
);
916 gen_op_jz_ecx
[s
->aflag
]((long)s
->tb
, next_eip
);
918 gen_op_dec_ECX
[s
->aflag
]();
919 gen_op_jmp_tb_next((long)s
->tb
, cur_eip
);
923 static inline void gen_string_ds(DisasContext
*s
, int ot
, GenOpFunc
**func
)
927 override
= s
->override
;
930 if (s
->addseg
&& override
< 0)
933 gen_op_movl_A0_seg(offsetof(CPUX86State
,segs
[override
].base
));
941 gen_op_movl_A0_seg(offsetof(CPUX86State
,segs
[override
].base
));
942 /* 16 address, always override */
948 static inline void gen_string_es(DisasContext
*s
, int ot
, GenOpFunc
**func
)
965 static GenOpFunc
*gen_op_in
[3] = {
971 static GenOpFunc
*gen_op_out
[3] = {
988 static GenOpFunc3
*gen_jcc_sub
[3][8] = {
1020 static GenOpFunc2
*gen_op_loop
[2][4] = {
1035 static GenOpFunc
*gen_setcc_slow
[8] = {
1046 static GenOpFunc
*gen_setcc_sub
[3][8] = {
1049 gen_op_setb_T0_subb
,
1050 gen_op_setz_T0_subb
,
1051 gen_op_setbe_T0_subb
,
1052 gen_op_sets_T0_subb
,
1054 gen_op_setl_T0_subb
,
1055 gen_op_setle_T0_subb
,
1059 gen_op_setb_T0_subw
,
1060 gen_op_setz_T0_subw
,
1061 gen_op_setbe_T0_subw
,
1062 gen_op_sets_T0_subw
,
1064 gen_op_setl_T0_subw
,
1065 gen_op_setle_T0_subw
,
1069 gen_op_setb_T0_subl
,
1070 gen_op_setz_T0_subl
,
1071 gen_op_setbe_T0_subl
,
1072 gen_op_sets_T0_subl
,
1074 gen_op_setl_T0_subl
,
1075 gen_op_setle_T0_subl
,
1079 static GenOpFunc
*gen_op_fp_arith_ST0_FT0
[8] = {
1080 gen_op_fadd_ST0_FT0
,
1081 gen_op_fmul_ST0_FT0
,
1082 gen_op_fcom_ST0_FT0
,
1083 gen_op_fcom_ST0_FT0
,
1084 gen_op_fsub_ST0_FT0
,
1085 gen_op_fsubr_ST0_FT0
,
1086 gen_op_fdiv_ST0_FT0
,
1087 gen_op_fdivr_ST0_FT0
,
1090 /* NOTE the exception in "r" op ordering */
1091 static GenOpFunc1
*gen_op_fp_arith_STN_ST0
[8] = {
1092 gen_op_fadd_STN_ST0
,
1093 gen_op_fmul_STN_ST0
,
1096 gen_op_fsubr_STN_ST0
,
1097 gen_op_fsub_STN_ST0
,
1098 gen_op_fdivr_STN_ST0
,
1099 gen_op_fdiv_STN_ST0
,
1102 /* if d == OR_TMP0, it means memory operand (address in A0) */
1103 static void gen_op(DisasContext
*s1
, int op
, int ot
, int d
)
1105 GenOpFunc
*gen_update_cc
;
1108 gen_op_mov_TN_reg
[ot
][0][d
]();
1110 gen_op_ld_T0_A0
[ot
+ s1
->mem_index
]();
1115 if (s1
->cc_op
!= CC_OP_DYNAMIC
)
1116 gen_op_set_cc_op(s1
->cc_op
);
1118 gen_op_arithc_T0_T1_cc
[ot
][op
- OP_ADCL
]();
1119 gen_op_mov_reg_T0
[ot
][d
]();
1121 gen_op_arithc_mem_T0_T1_cc
[ot
][op
- OP_ADCL
]();
1123 s1
->cc_op
= CC_OP_DYNAMIC
;
1126 gen_op_addl_T0_T1();
1127 s1
->cc_op
= CC_OP_ADDB
+ ot
;
1128 gen_update_cc
= gen_op_update2_cc
;
1131 gen_op_subl_T0_T1();
1132 s1
->cc_op
= CC_OP_SUBB
+ ot
;
1133 gen_update_cc
= gen_op_update2_cc
;
1139 gen_op_arith_T0_T1_cc
[op
]();
1140 s1
->cc_op
= CC_OP_LOGICB
+ ot
;
1141 gen_update_cc
= gen_op_update1_cc
;
1144 gen_op_cmpl_T0_T1_cc();
1145 s1
->cc_op
= CC_OP_SUBB
+ ot
;
1146 gen_update_cc
= NULL
;
1149 if (op
!= OP_CMPL
) {
1151 gen_op_mov_reg_T0
[ot
][d
]();
1153 gen_op_st_T0_A0
[ot
+ s1
->mem_index
]();
1155 /* the flags update must happen after the memory write (precise
1156 exception support) */
1162 /* if d == OR_TMP0, it means memory operand (address in A0) */
1163 static void gen_inc(DisasContext
*s1
, int ot
, int d
, int c
)
1166 gen_op_mov_TN_reg
[ot
][0][d
]();
1168 gen_op_ld_T0_A0
[ot
+ s1
->mem_index
]();
1169 if (s1
->cc_op
!= CC_OP_DYNAMIC
)
1170 gen_op_set_cc_op(s1
->cc_op
);
1173 s1
->cc_op
= CC_OP_INCB
+ ot
;
1176 s1
->cc_op
= CC_OP_DECB
+ ot
;
1179 gen_op_mov_reg_T0
[ot
][d
]();
1181 gen_op_st_T0_A0
[ot
+ s1
->mem_index
]();
1182 gen_op_update_inc_cc();
1185 static void gen_shift(DisasContext
*s1
, int op
, int ot
, int d
, int s
)
1188 gen_op_mov_TN_reg
[ot
][0][d
]();
1190 gen_op_ld_T0_A0
[ot
+ s1
->mem_index
]();
1192 gen_op_mov_TN_reg
[ot
][1][s
]();
1193 /* for zero counts, flags are not updated, so must do it dynamically */
1194 if (s1
->cc_op
!= CC_OP_DYNAMIC
)
1195 gen_op_set_cc_op(s1
->cc_op
);
1198 gen_op_shift_T0_T1_cc
[ot
][op
]();
1200 gen_op_shift_mem_T0_T1_cc
[ot
][op
]();
1202 gen_op_mov_reg_T0
[ot
][d
]();
1203 s1
->cc_op
= CC_OP_DYNAMIC
; /* cannot predict flags after */
1206 static void gen_shifti(DisasContext
*s1
, int op
, int ot
, int d
, int c
)
1208 /* currently not optimized */
1209 gen_op_movl_T1_im(c
);
1210 gen_shift(s1
, op
, ot
, d
, OR_TMP1
);
1213 static void gen_lea_modrm(DisasContext
*s
, int modrm
, int *reg_ptr
, int *offset_ptr
)
1220 int mod
, rm
, code
, override
, must_add_seg
;
1222 override
= s
->override
;
1223 must_add_seg
= s
->addseg
;
1226 mod
= (modrm
>> 6) & 3;
1238 code
= ldub(s
->pc
++);
1239 scale
= (code
>> 6) & 3;
1240 index
= (code
>> 3) & 7;
1255 disp
= (int8_t)ldub(s
->pc
++);
1265 /* for correct popl handling with esp */
1266 if (base
== 4 && s
->popl_esp_hack
)
1267 disp
+= s
->popl_esp_hack
;
1268 gen_op_movl_A0_reg
[base
]();
1270 gen_op_addl_A0_im(disp
);
1272 gen_op_movl_A0_im(disp
);
1274 /* XXX: index == 4 is always invalid */
1275 if (havesib
&& (index
!= 4 || scale
!= 0)) {
1276 gen_op_addl_A0_reg_sN
[scale
][index
]();
1280 if (base
== R_EBP
|| base
== R_ESP
)
1285 gen_op_addl_A0_seg(offsetof(CPUX86State
,segs
[override
].base
));
1293 gen_op_movl_A0_im(disp
);
1294 rm
= 0; /* avoid SS override */
1301 disp
= (int8_t)ldub(s
->pc
++);
1311 gen_op_movl_A0_reg
[R_EBX
]();
1312 gen_op_addl_A0_reg_sN
[0][R_ESI
]();
1315 gen_op_movl_A0_reg
[R_EBX
]();
1316 gen_op_addl_A0_reg_sN
[0][R_EDI
]();
1319 gen_op_movl_A0_reg
[R_EBP
]();
1320 gen_op_addl_A0_reg_sN
[0][R_ESI
]();
1323 gen_op_movl_A0_reg
[R_EBP
]();
1324 gen_op_addl_A0_reg_sN
[0][R_EDI
]();
1327 gen_op_movl_A0_reg
[R_ESI
]();
1330 gen_op_movl_A0_reg
[R_EDI
]();
1333 gen_op_movl_A0_reg
[R_EBP
]();
1337 gen_op_movl_A0_reg
[R_EBX
]();
1341 gen_op_addl_A0_im(disp
);
1342 gen_op_andl_A0_ffff();
1346 if (rm
== 2 || rm
== 3 || rm
== 6)
1351 gen_op_addl_A0_seg(offsetof(CPUX86State
,segs
[override
].base
));
1361 /* generate modrm memory load or store of 'reg'. TMP0 is used if reg !=
1363 static void gen_ldst_modrm(DisasContext
*s
, int modrm
, int ot
, int reg
, int is_store
)
1365 int mod
, rm
, opreg
, disp
;
1367 mod
= (modrm
>> 6) & 3;
1372 gen_op_mov_TN_reg
[ot
][0][reg
]();
1373 gen_op_mov_reg_T0
[ot
][rm
]();
1375 gen_op_mov_TN_reg
[ot
][0][rm
]();
1377 gen_op_mov_reg_T0
[ot
][reg
]();
1380 gen_lea_modrm(s
, modrm
, &opreg
, &disp
);
1383 gen_op_mov_TN_reg
[ot
][0][reg
]();
1384 gen_op_st_T0_A0
[ot
+ s
->mem_index
]();
1386 gen_op_ld_T0_A0
[ot
+ s
->mem_index
]();
1388 gen_op_mov_reg_T0
[ot
][reg
]();
1393 static inline uint32_t insn_get(DisasContext
*s
, int ot
)
1415 static inline void gen_jcc(DisasContext
*s
, int b
, int val
, int next_eip
)
1417 TranslationBlock
*tb
;
1422 jcc_op
= (b
>> 1) & 7;
1424 /* we optimize the cmp/jcc case */
1428 func
= gen_jcc_sub
[s
->cc_op
- CC_OP_SUBB
][jcc_op
];
1431 /* some jumps are easy to compute */
1458 func
= gen_jcc_sub
[(s
->cc_op
- CC_OP_ADDB
) % 3][jcc_op
];
1461 func
= gen_jcc_sub
[(s
->cc_op
- CC_OP_ADDB
) % 3][jcc_op
];
1473 if (s
->cc_op
!= CC_OP_DYNAMIC
)
1474 gen_op_set_cc_op(s
->cc_op
);
1477 gen_setcc_slow
[jcc_op
]();
1483 func((long)tb
, val
, next_eip
);
1485 func((long)tb
, next_eip
, val
);
1490 static void gen_setcc(DisasContext
*s
, int b
)
1496 jcc_op
= (b
>> 1) & 7;
1498 /* we optimize the cmp/jcc case */
1502 func
= gen_setcc_sub
[s
->cc_op
- CC_OP_SUBB
][jcc_op
];
1507 /* some jumps are easy to compute */
1525 func
= gen_setcc_sub
[(s
->cc_op
- CC_OP_ADDB
) % 3][jcc_op
];
1528 func
= gen_setcc_sub
[(s
->cc_op
- CC_OP_ADDB
) % 3][jcc_op
];
1536 if (s
->cc_op
!= CC_OP_DYNAMIC
)
1537 gen_op_set_cc_op(s
->cc_op
);
1538 func
= gen_setcc_slow
[jcc_op
];
1547 /* move T0 to seg_reg and compute if the CPU state may change */
1548 static void gen_movl_seg_T0(DisasContext
*s
, int seg_reg
, unsigned int cur_eip
)
1550 if (s
->pe
&& !s
->vm86
)
1551 gen_op_movl_seg_T0(seg_reg
, cur_eip
);
1553 gen_op_movl_seg_T0_vm(offsetof(CPUX86State
,segs
[seg_reg
]));
1554 /* abort translation because the register may have a non zero base
1555 or because ss32 may change. For R_SS, translation must always
1556 stop as a special handling must be done to disable hardware
1557 interrupts for the next instruction */
1558 if (seg_reg
== R_SS
|| (!s
->addseg
&& seg_reg
< R_FS
))
1562 /* generate a push. It depends on ss32, addseg and dflag */
1563 static void gen_push_T0(DisasContext
*s
)
1573 gen_op_pushl_ss32_T0();
1575 gen_op_pushw_ss32_T0();
1579 gen_op_pushl_ss16_T0();
1581 gen_op_pushw_ss16_T0();
1585 /* two step pop is necessary for precise exceptions */
1586 static void gen_pop_T0(DisasContext
*s
)
1596 gen_op_popl_ss32_T0();
1598 gen_op_popw_ss32_T0();
1602 gen_op_popl_ss16_T0();
1604 gen_op_popw_ss16_T0();
1608 static inline void gen_stack_update(DisasContext
*s
, int addend
)
1612 gen_op_addl_ESP_2();
1613 else if (addend
== 4)
1614 gen_op_addl_ESP_4();
1616 gen_op_addl_ESP_im(addend
);
1619 gen_op_addw_ESP_2();
1620 else if (addend
== 4)
1621 gen_op_addw_ESP_4();
1623 gen_op_addw_ESP_im(addend
);
1627 static void gen_pop_update(DisasContext
*s
)
1629 gen_stack_update(s
, 2 << s
->dflag
);
1632 static void gen_stack_A0(DisasContext
*s
)
1634 gen_op_movl_A0_ESP();
1636 gen_op_andl_A0_ffff();
1637 gen_op_movl_T1_A0();
1639 gen_op_addl_A0_seg(offsetof(CPUX86State
,segs
[R_SS
].base
));
1642 /* NOTE: wrap around in 16 bit not fully handled */
1643 static void gen_pusha(DisasContext
*s
)
1646 gen_op_movl_A0_ESP();
1647 gen_op_addl_A0_im(-16 << s
->dflag
);
1649 gen_op_andl_A0_ffff();
1650 gen_op_movl_T1_A0();
1652 gen_op_addl_A0_seg(offsetof(CPUX86State
,segs
[R_SS
].base
));
1653 for(i
= 0;i
< 8; i
++) {
1654 gen_op_mov_TN_reg
[OT_LONG
][0][7 - i
]();
1655 gen_op_st_T0_A0
[OT_WORD
+ s
->dflag
+ s
->mem_index
]();
1656 gen_op_addl_A0_im(2 << s
->dflag
);
1658 gen_op_mov_reg_T1
[OT_WORD
+ s
->dflag
][R_ESP
]();
1661 /* NOTE: wrap around in 16 bit not fully handled */
1662 static void gen_popa(DisasContext
*s
)
1665 gen_op_movl_A0_ESP();
1667 gen_op_andl_A0_ffff();
1668 gen_op_movl_T1_A0();
1669 gen_op_addl_T1_im(16 << s
->dflag
);
1671 gen_op_addl_A0_seg(offsetof(CPUX86State
,segs
[R_SS
].base
));
1672 for(i
= 0;i
< 8; i
++) {
1673 /* ESP is not reloaded */
1675 gen_op_ld_T0_A0
[OT_WORD
+ s
->dflag
+ s
->mem_index
]();
1676 gen_op_mov_reg_T0
[OT_WORD
+ s
->dflag
][7 - i
]();
1678 gen_op_addl_A0_im(2 << s
->dflag
);
1680 gen_op_mov_reg_T1
[OT_WORD
+ s
->dflag
][R_ESP
]();
1683 /* NOTE: wrap around in 16 bit not fully handled */
1684 /* XXX: check this */
1685 static void gen_enter(DisasContext
*s
, int esp_addend
, int level
)
1687 int ot
, level1
, addend
, opsize
;
1689 ot
= s
->dflag
+ OT_WORD
;
1692 opsize
= 2 << s
->dflag
;
1694 gen_op_movl_A0_ESP();
1695 gen_op_addl_A0_im(-opsize
);
1697 gen_op_andl_A0_ffff();
1698 gen_op_movl_T1_A0();
1700 gen_op_addl_A0_seg(offsetof(CPUX86State
,segs
[R_SS
].base
));
1702 gen_op_mov_TN_reg
[OT_LONG
][0][R_EBP
]();
1703 gen_op_st_T0_A0
[ot
+ s
->mem_index
]();
1706 gen_op_addl_A0_im(-opsize
);
1707 gen_op_addl_T0_im(-opsize
);
1708 gen_op_st_T0_A0
[ot
+ s
->mem_index
]();
1710 gen_op_addl_A0_im(-opsize
);
1711 /* XXX: add st_T1_A0 ? */
1712 gen_op_movl_T0_T1();
1713 gen_op_st_T0_A0
[ot
+ s
->mem_index
]();
1715 gen_op_mov_reg_T1
[ot
][R_EBP
]();
1716 addend
= -esp_addend
;
1718 addend
-= opsize
* (level1
+ 1);
1719 gen_op_addl_T1_im(addend
);
1720 gen_op_mov_reg_T1
[ot
][R_ESP
]();
1723 static void gen_exception(DisasContext
*s
, int trapno
, unsigned int cur_eip
)
1725 if (s
->cc_op
!= CC_OP_DYNAMIC
)
1726 gen_op_set_cc_op(s
->cc_op
);
1727 gen_op_jmp_im(cur_eip
);
1728 gen_op_raise_exception(trapno
);
1732 /* an interrupt is different from an exception because of the
1733 priviledge checks */
1734 static void gen_interrupt(DisasContext
*s
, int intno
,
1735 unsigned int cur_eip
, unsigned int next_eip
)
1737 if (s
->cc_op
!= CC_OP_DYNAMIC
)
1738 gen_op_set_cc_op(s
->cc_op
);
1739 gen_op_jmp_im(cur_eip
);
1740 gen_op_raise_interrupt(intno
, next_eip
);
1744 static void gen_debug(DisasContext
*s
, unsigned int cur_eip
)
1746 if (s
->cc_op
!= CC_OP_DYNAMIC
)
1747 gen_op_set_cc_op(s
->cc_op
);
1748 gen_op_jmp_im(cur_eip
);
1753 /* generate a jump to eip. No segment change must happen before as a
1754 direct call to the next block may occur */
1755 static void gen_jmp(DisasContext
*s
, unsigned int eip
)
1757 TranslationBlock
*tb
= s
->tb
;
1759 if (s
->cc_op
!= CC_OP_DYNAMIC
)
1760 gen_op_set_cc_op(s
->cc_op
);
1761 gen_op_jmp_tb_next((long)tb
, eip
);
1765 /* return the next pc address. Return -1 if no insn found. *is_jmp_ptr
1766 is set to true if the instruction sets the PC (last instruction of
1768 long disas_insn(DisasContext
*s
, uint8_t *pc_start
)
1770 int b
, prefixes
, aflag
, dflag
;
1772 int modrm
, reg
, rm
, mod
, reg_addr
, op
, opreg
, offset_addr
, val
;
1773 unsigned int next_eip
;
1783 /* check prefixes */
1786 prefixes
|= PREFIX_REPZ
;
1789 prefixes
|= PREFIX_REPNZ
;
1792 prefixes
|= PREFIX_LOCK
;
1813 prefixes
|= PREFIX_DATA
;
1816 prefixes
|= PREFIX_ADR
;
1820 if (prefixes
& PREFIX_DATA
)
1822 if (prefixes
& PREFIX_ADR
)
1825 s
->prefix
= prefixes
;
1829 /* lock generation */
1830 if (prefixes
& PREFIX_LOCK
)
1833 /* now check op code */
1837 /**************************/
1838 /* extended op code */
1839 b
= ldub(s
->pc
++) | 0x100;
1842 /**************************/
1860 ot
= dflag
? OT_LONG
: OT_WORD
;
1863 case 0: /* OP Ev, Gv */
1864 modrm
= ldub(s
->pc
++);
1865 reg
= ((modrm
>> 3) & 7);
1866 mod
= (modrm
>> 6) & 3;
1869 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1871 } else if (op
== OP_XORL
&& rm
== reg
) {
1873 /* xor reg, reg optimisation */
1875 s
->cc_op
= CC_OP_LOGICB
+ ot
;
1876 gen_op_mov_reg_T0
[ot
][reg
]();
1877 gen_op_update1_cc();
1882 gen_op_mov_TN_reg
[ot
][1][reg
]();
1883 gen_op(s
, op
, ot
, opreg
);
1885 case 1: /* OP Gv, Ev */
1886 modrm
= ldub(s
->pc
++);
1887 mod
= (modrm
>> 6) & 3;
1888 reg
= ((modrm
>> 3) & 7);
1891 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1892 gen_op_ld_T1_A0
[ot
+ s
->mem_index
]();
1893 } else if (op
== OP_XORL
&& rm
== reg
) {
1896 gen_op_mov_TN_reg
[ot
][1][rm
]();
1898 gen_op(s
, op
, ot
, reg
);
1900 case 2: /* OP A, Iv */
1901 val
= insn_get(s
, ot
);
1902 gen_op_movl_T1_im(val
);
1903 gen_op(s
, op
, ot
, OR_EAX
);
1909 case 0x80: /* GRP1 */
1918 ot
= dflag
? OT_LONG
: OT_WORD
;
1920 modrm
= ldub(s
->pc
++);
1921 mod
= (modrm
>> 6) & 3;
1923 op
= (modrm
>> 3) & 7;
1926 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1929 opreg
= rm
+ OR_EAX
;
1936 val
= insn_get(s
, ot
);
1939 val
= (int8_t)insn_get(s
, OT_BYTE
);
1942 gen_op_movl_T1_im(val
);
1943 gen_op(s
, op
, ot
, opreg
);
1947 /**************************/
1948 /* inc, dec, and other misc arith */
1949 case 0x40 ... 0x47: /* inc Gv */
1950 ot
= dflag
? OT_LONG
: OT_WORD
;
1951 gen_inc(s
, ot
, OR_EAX
+ (b
& 7), 1);
1953 case 0x48 ... 0x4f: /* dec Gv */
1954 ot
= dflag
? OT_LONG
: OT_WORD
;
1955 gen_inc(s
, ot
, OR_EAX
+ (b
& 7), -1);
1957 case 0xf6: /* GRP3 */
1962 ot
= dflag
? OT_LONG
: OT_WORD
;
1964 modrm
= ldub(s
->pc
++);
1965 mod
= (modrm
>> 6) & 3;
1967 op
= (modrm
>> 3) & 7;
1969 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
1970 gen_op_ld_T0_A0
[ot
+ s
->mem_index
]();
1972 gen_op_mov_TN_reg
[ot
][0][rm
]();
1977 val
= insn_get(s
, ot
);
1978 gen_op_movl_T1_im(val
);
1979 gen_op_testl_T0_T1_cc();
1980 s
->cc_op
= CC_OP_LOGICB
+ ot
;
1985 gen_op_st_T0_A0
[ot
+ s
->mem_index
]();
1987 gen_op_mov_reg_T0
[ot
][rm
]();
1993 gen_op_st_T0_A0
[ot
+ s
->mem_index
]();
1995 gen_op_mov_reg_T0
[ot
][rm
]();
1997 gen_op_update_neg_cc();
1998 s
->cc_op
= CC_OP_SUBB
+ ot
;
2003 gen_op_mulb_AL_T0();
2006 gen_op_mulw_AX_T0();
2010 gen_op_mull_EAX_T0();
2013 s
->cc_op
= CC_OP_MUL
;
2018 gen_op_imulb_AL_T0();
2021 gen_op_imulw_AX_T0();
2025 gen_op_imull_EAX_T0();
2028 s
->cc_op
= CC_OP_MUL
;
2033 gen_op_divb_AL_T0(pc_start
- s
->cs_base
);
2036 gen_op_divw_AX_T0(pc_start
- s
->cs_base
);
2040 gen_op_divl_EAX_T0(pc_start
- s
->cs_base
);
2047 gen_op_idivb_AL_T0(pc_start
- s
->cs_base
);
2050 gen_op_idivw_AX_T0(pc_start
- s
->cs_base
);
2054 gen_op_idivl_EAX_T0(pc_start
- s
->cs_base
);
2063 case 0xfe: /* GRP4 */
2064 case 0xff: /* GRP5 */
2068 ot
= dflag
? OT_LONG
: OT_WORD
;
2070 modrm
= ldub(s
->pc
++);
2071 mod
= (modrm
>> 6) & 3;
2073 op
= (modrm
>> 3) & 7;
2074 if (op
>= 2 && b
== 0xfe) {
2078 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2079 if (op
>= 2 && op
!= 3 && op
!= 5)
2080 gen_op_ld_T0_A0
[ot
+ s
->mem_index
]();
2082 gen_op_mov_TN_reg
[ot
][0][rm
]();
2086 case 0: /* inc Ev */
2091 gen_inc(s
, ot
, opreg
, 1);
2093 case 1: /* dec Ev */
2098 gen_inc(s
, ot
, opreg
, -1);
2100 case 2: /* call Ev */
2101 /* XXX: optimize if memory (no and is necessary) */
2103 gen_op_andl_T0_ffff();
2105 next_eip
= s
->pc
- s
->cs_base
;
2106 gen_op_movl_T0_im(next_eip
);
2110 case 3: /* lcall Ev */
2111 gen_op_ld_T1_A0
[ot
+ s
->mem_index
]();
2112 gen_op_addl_A0_im(1 << (ot
- OT_WORD
+ 1));
2113 gen_op_ld_T0_A0
[OT_WORD
+ s
->mem_index
]();
2115 if (s
->pe
&& !s
->vm86
) {
2116 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2117 gen_op_set_cc_op(s
->cc_op
);
2118 gen_op_jmp_im(pc_start
- s
->cs_base
);
2119 gen_op_lcall_protected_T0_T1(dflag
, s
->pc
- s
->cs_base
);
2121 gen_op_lcall_real_T0_T1(dflag
, s
->pc
- s
->cs_base
);
2125 case 4: /* jmp Ev */
2127 gen_op_andl_T0_ffff();
2131 case 5: /* ljmp Ev */
2132 gen_op_ld_T1_A0
[ot
+ s
->mem_index
]();
2133 gen_op_addl_A0_im(1 << (ot
- OT_WORD
+ 1));
2134 gen_op_lduw_T0_A0();
2136 if (s
->pe
&& !s
->vm86
) {
2137 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2138 gen_op_set_cc_op(s
->cc_op
);
2139 gen_op_jmp_im(pc_start
- s
->cs_base
);
2140 gen_op_ljmp_protected_T0_T1();
2142 gen_op_movl_seg_T0_vm(offsetof(CPUX86State
,segs
[R_CS
]));
2143 gen_op_movl_T0_T1();
2148 case 6: /* push Ev */
2156 case 0x84: /* test Ev, Gv */
2161 ot
= dflag
? OT_LONG
: OT_WORD
;
2163 modrm
= ldub(s
->pc
++);
2164 mod
= (modrm
>> 6) & 3;
2166 reg
= (modrm
>> 3) & 7;
2168 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 0);
2169 gen_op_mov_TN_reg
[ot
][1][reg
+ OR_EAX
]();
2170 gen_op_testl_T0_T1_cc();
2171 s
->cc_op
= CC_OP_LOGICB
+ ot
;
2174 case 0xa8: /* test eAX, Iv */
2179 ot
= dflag
? OT_LONG
: OT_WORD
;
2180 val
= insn_get(s
, ot
);
2182 gen_op_mov_TN_reg
[ot
][0][OR_EAX
]();
2183 gen_op_movl_T1_im(val
);
2184 gen_op_testl_T0_T1_cc();
2185 s
->cc_op
= CC_OP_LOGICB
+ ot
;
2188 case 0x98: /* CWDE/CBW */
2190 gen_op_movswl_EAX_AX();
2192 gen_op_movsbw_AX_AL();
2194 case 0x99: /* CDQ/CWD */
2196 gen_op_movslq_EDX_EAX();
2198 gen_op_movswl_DX_AX();
2200 case 0x1af: /* imul Gv, Ev */
2201 case 0x69: /* imul Gv, Ev, I */
2203 ot
= dflag
? OT_LONG
: OT_WORD
;
2204 modrm
= ldub(s
->pc
++);
2205 reg
= ((modrm
>> 3) & 7) + OR_EAX
;
2206 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 0);
2208 val
= insn_get(s
, ot
);
2209 gen_op_movl_T1_im(val
);
2210 } else if (b
== 0x6b) {
2211 val
= insn_get(s
, OT_BYTE
);
2212 gen_op_movl_T1_im(val
);
2214 gen_op_mov_TN_reg
[ot
][1][reg
]();
2217 if (ot
== OT_LONG
) {
2218 gen_op_imull_T0_T1();
2220 gen_op_imulw_T0_T1();
2222 gen_op_mov_reg_T0
[ot
][reg
]();
2223 s
->cc_op
= CC_OP_MUL
;
2226 case 0x1c1: /* xadd Ev, Gv */
2230 ot
= dflag
? OT_LONG
: OT_WORD
;
2231 modrm
= ldub(s
->pc
++);
2232 reg
= (modrm
>> 3) & 7;
2233 mod
= (modrm
>> 6) & 3;
2236 gen_op_mov_TN_reg
[ot
][0][reg
]();
2237 gen_op_mov_TN_reg
[ot
][1][rm
]();
2238 gen_op_addl_T0_T1();
2239 gen_op_mov_reg_T0
[ot
][rm
]();
2240 gen_op_mov_reg_T1
[ot
][reg
]();
2242 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2243 gen_op_mov_TN_reg
[ot
][0][reg
]();
2244 gen_op_ld_T1_A0
[ot
+ s
->mem_index
]();
2245 gen_op_addl_T0_T1();
2246 gen_op_st_T0_A0
[ot
+ s
->mem_index
]();
2247 gen_op_mov_reg_T1
[ot
][reg
]();
2249 gen_op_update2_cc();
2250 s
->cc_op
= CC_OP_ADDB
+ ot
;
2253 case 0x1b1: /* cmpxchg Ev, Gv */
2257 ot
= dflag
? OT_LONG
: OT_WORD
;
2258 modrm
= ldub(s
->pc
++);
2259 reg
= (modrm
>> 3) & 7;
2260 mod
= (modrm
>> 6) & 3;
2261 gen_op_mov_TN_reg
[ot
][1][reg
]();
2264 gen_op_mov_TN_reg
[ot
][0][rm
]();
2265 gen_op_cmpxchg_T0_T1_EAX_cc
[ot
]();
2266 gen_op_mov_reg_T0
[ot
][rm
]();
2268 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2269 gen_op_ld_T0_A0
[ot
+ s
->mem_index
]();
2270 gen_op_cmpxchg_mem_T0_T1_EAX_cc
[ot
]();
2272 s
->cc_op
= CC_OP_SUBB
+ ot
;
2274 case 0x1c7: /* cmpxchg8b */
2275 modrm
= ldub(s
->pc
++);
2276 mod
= (modrm
>> 6) & 3;
2279 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2280 gen_op_set_cc_op(s
->cc_op
);
2281 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2283 s
->cc_op
= CC_OP_EFLAGS
;
2286 /**************************/
2288 case 0x50 ... 0x57: /* push */
2289 gen_op_mov_TN_reg
[OT_LONG
][0][b
& 7]();
2292 case 0x58 ... 0x5f: /* pop */
2293 ot
= dflag
? OT_LONG
: OT_WORD
;
2295 gen_op_mov_reg_T0
[ot
][b
& 7]();
2298 case 0x60: /* pusha */
2301 case 0x61: /* popa */
2304 case 0x68: /* push Iv */
2306 ot
= dflag
? OT_LONG
: OT_WORD
;
2308 val
= insn_get(s
, ot
);
2310 val
= (int8_t)insn_get(s
, OT_BYTE
);
2311 gen_op_movl_T0_im(val
);
2314 case 0x8f: /* pop Ev */
2315 ot
= dflag
? OT_LONG
: OT_WORD
;
2316 modrm
= ldub(s
->pc
++);
2318 s
->popl_esp_hack
= 2 << dflag
;
2319 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 1);
2320 s
->popl_esp_hack
= 0;
2323 case 0xc8: /* enter */
2328 level
= ldub(s
->pc
++);
2329 gen_enter(s
, val
, level
);
2332 case 0xc9: /* leave */
2333 /* XXX: exception not precise (ESP is updated before potential exception) */
2335 gen_op_mov_TN_reg
[OT_LONG
][0][R_EBP
]();
2336 gen_op_mov_reg_T0
[OT_LONG
][R_ESP
]();
2338 gen_op_mov_TN_reg
[OT_WORD
][0][R_EBP
]();
2339 gen_op_mov_reg_T0
[OT_WORD
][R_ESP
]();
2342 ot
= dflag
? OT_LONG
: OT_WORD
;
2343 gen_op_mov_reg_T0
[ot
][R_EBP
]();
2346 case 0x06: /* push es */
2347 case 0x0e: /* push cs */
2348 case 0x16: /* push ss */
2349 case 0x1e: /* push ds */
2350 gen_op_movl_T0_seg(b
>> 3);
2353 case 0x1a0: /* push fs */
2354 case 0x1a8: /* push gs */
2355 gen_op_movl_T0_seg((b
>> 3) & 7);
2358 case 0x07: /* pop es */
2359 case 0x17: /* pop ss */
2360 case 0x1f: /* pop ds */
2363 gen_movl_seg_T0(s
, reg
, pc_start
- s
->cs_base
);
2366 /* if reg == SS, inhibit interrupts/trace */
2367 gen_op_set_inhibit_irq();
2370 case 0x1a1: /* pop fs */
2371 case 0x1a9: /* pop gs */
2373 gen_movl_seg_T0(s
, (b
>> 3) & 7, pc_start
- s
->cs_base
);
2377 /**************************/
2380 case 0x89: /* mov Gv, Ev */
2384 ot
= dflag
? OT_LONG
: OT_WORD
;
2385 modrm
= ldub(s
->pc
++);
2386 reg
= (modrm
>> 3) & 7;
2388 /* generate a generic store */
2389 gen_ldst_modrm(s
, modrm
, ot
, OR_EAX
+ reg
, 1);
2392 case 0xc7: /* mov Ev, Iv */
2396 ot
= dflag
? OT_LONG
: OT_WORD
;
2397 modrm
= ldub(s
->pc
++);
2398 mod
= (modrm
>> 6) & 3;
2400 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2401 val
= insn_get(s
, ot
);
2402 gen_op_movl_T0_im(val
);
2404 gen_op_st_T0_A0
[ot
+ s
->mem_index
]();
2406 gen_op_mov_reg_T0
[ot
][modrm
& 7]();
2409 case 0x8b: /* mov Ev, Gv */
2413 ot
= dflag
? OT_LONG
: OT_WORD
;
2414 modrm
= ldub(s
->pc
++);
2415 reg
= (modrm
>> 3) & 7;
2417 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 0);
2418 gen_op_mov_reg_T0
[ot
][reg
]();
2420 case 0x8e: /* mov seg, Gv */
2421 modrm
= ldub(s
->pc
++);
2422 reg
= (modrm
>> 3) & 7;
2423 if (reg
>= 6 || reg
== R_CS
)
2425 gen_ldst_modrm(s
, modrm
, OT_WORD
, OR_TMP0
, 0);
2426 gen_movl_seg_T0(s
, reg
, pc_start
- s
->cs_base
);
2428 /* if reg == SS, inhibit interrupts/trace */
2429 gen_op_set_inhibit_irq();
2432 case 0x8c: /* mov Gv, seg */
2433 modrm
= ldub(s
->pc
++);
2434 reg
= (modrm
>> 3) & 7;
2435 mod
= (modrm
>> 6) & 3;
2438 gen_op_movl_T0_seg(reg
);
2440 if (mod
== 3 && dflag
)
2442 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 1);
2445 case 0x1b6: /* movzbS Gv, Eb */
2446 case 0x1b7: /* movzwS Gv, Eb */
2447 case 0x1be: /* movsbS Gv, Eb */
2448 case 0x1bf: /* movswS Gv, Eb */
2451 /* d_ot is the size of destination */
2452 d_ot
= dflag
+ OT_WORD
;
2453 /* ot is the size of source */
2454 ot
= (b
& 1) + OT_BYTE
;
2455 modrm
= ldub(s
->pc
++);
2456 reg
= ((modrm
>> 3) & 7) + OR_EAX
;
2457 mod
= (modrm
>> 6) & 3;
2461 gen_op_mov_TN_reg
[ot
][0][rm
]();
2462 switch(ot
| (b
& 8)) {
2464 gen_op_movzbl_T0_T0();
2467 gen_op_movsbl_T0_T0();
2470 gen_op_movzwl_T0_T0();
2474 gen_op_movswl_T0_T0();
2477 gen_op_mov_reg_T0
[d_ot
][reg
]();
2479 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2481 gen_op_lds_T0_A0
[ot
+ s
->mem_index
]();
2483 gen_op_ldu_T0_A0
[ot
+ s
->mem_index
]();
2485 gen_op_mov_reg_T0
[d_ot
][reg
]();
2490 case 0x8d: /* lea */
2491 ot
= dflag
? OT_LONG
: OT_WORD
;
2492 modrm
= ldub(s
->pc
++);
2493 reg
= (modrm
>> 3) & 7;
2494 /* we must ensure that no segment is added */
2498 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2500 gen_op_mov_reg_A0
[ot
- OT_WORD
][reg
]();
2503 case 0xa0: /* mov EAX, Ov */
2505 case 0xa2: /* mov Ov, EAX */
2510 ot
= dflag
? OT_LONG
: OT_WORD
;
2512 offset_addr
= insn_get(s
, OT_LONG
);
2514 offset_addr
= insn_get(s
, OT_WORD
);
2515 gen_op_movl_A0_im(offset_addr
);
2516 /* handle override */
2518 int override
, must_add_seg
;
2519 must_add_seg
= s
->addseg
;
2520 if (s
->override
>= 0) {
2521 override
= s
->override
;
2527 gen_op_addl_A0_seg(offsetof(CPUX86State
,segs
[override
].base
));
2531 gen_op_ld_T0_A0
[ot
+ s
->mem_index
]();
2532 gen_op_mov_reg_T0
[ot
][R_EAX
]();
2534 gen_op_mov_TN_reg
[ot
][0][R_EAX
]();
2535 gen_op_st_T0_A0
[ot
+ s
->mem_index
]();
2538 case 0xd7: /* xlat */
2539 gen_op_movl_A0_reg
[R_EBX
]();
2540 gen_op_addl_A0_AL();
2542 gen_op_andl_A0_ffff();
2543 /* handle override */
2545 int override
, must_add_seg
;
2546 must_add_seg
= s
->addseg
;
2548 if (s
->override
>= 0) {
2549 override
= s
->override
;
2555 gen_op_addl_A0_seg(offsetof(CPUX86State
,segs
[override
].base
));
2558 gen_op_ldu_T0_A0
[OT_BYTE
+ s
->mem_index
]();
2559 gen_op_mov_reg_T0
[OT_BYTE
][R_EAX
]();
2561 case 0xb0 ... 0xb7: /* mov R, Ib */
2562 val
= insn_get(s
, OT_BYTE
);
2563 gen_op_movl_T0_im(val
);
2564 gen_op_mov_reg_T0
[OT_BYTE
][b
& 7]();
2566 case 0xb8 ... 0xbf: /* mov R, Iv */
2567 ot
= dflag
? OT_LONG
: OT_WORD
;
2568 val
= insn_get(s
, ot
);
2569 reg
= OR_EAX
+ (b
& 7);
2570 gen_op_movl_T0_im(val
);
2571 gen_op_mov_reg_T0
[ot
][reg
]();
2574 case 0x91 ... 0x97: /* xchg R, EAX */
2575 ot
= dflag
? OT_LONG
: OT_WORD
;
2580 case 0x87: /* xchg Ev, Gv */
2584 ot
= dflag
? OT_LONG
: OT_WORD
;
2585 modrm
= ldub(s
->pc
++);
2586 reg
= (modrm
>> 3) & 7;
2587 mod
= (modrm
>> 6) & 3;
2591 gen_op_mov_TN_reg
[ot
][0][reg
]();
2592 gen_op_mov_TN_reg
[ot
][1][rm
]();
2593 gen_op_mov_reg_T0
[ot
][rm
]();
2594 gen_op_mov_reg_T1
[ot
][reg
]();
2596 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2597 gen_op_mov_TN_reg
[ot
][0][reg
]();
2598 /* for xchg, lock is implicit */
2599 if (!(prefixes
& PREFIX_LOCK
))
2601 gen_op_ld_T1_A0
[ot
+ s
->mem_index
]();
2602 gen_op_st_T0_A0
[ot
+ s
->mem_index
]();
2603 if (!(prefixes
& PREFIX_LOCK
))
2605 gen_op_mov_reg_T1
[ot
][reg
]();
2608 case 0xc4: /* les Gv */
2611 case 0xc5: /* lds Gv */
2614 case 0x1b2: /* lss Gv */
2617 case 0x1b4: /* lfs Gv */
2620 case 0x1b5: /* lgs Gv */
2623 ot
= dflag
? OT_LONG
: OT_WORD
;
2624 modrm
= ldub(s
->pc
++);
2625 reg
= (modrm
>> 3) & 7;
2626 mod
= (modrm
>> 6) & 3;
2629 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2630 gen_op_ld_T1_A0
[ot
+ s
->mem_index
]();
2631 gen_op_addl_A0_im(1 << (ot
- OT_WORD
+ 1));
2632 /* load the segment first to handle exceptions properly */
2633 gen_op_lduw_T0_A0();
2634 gen_movl_seg_T0(s
, op
, pc_start
- s
->cs_base
);
2635 /* then put the data */
2636 gen_op_mov_reg_T1
[ot
][reg
]();
2639 /************************/
2650 ot
= dflag
? OT_LONG
: OT_WORD
;
2652 modrm
= ldub(s
->pc
++);
2653 mod
= (modrm
>> 6) & 3;
2655 op
= (modrm
>> 3) & 7;
2658 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2661 opreg
= rm
+ OR_EAX
;
2666 gen_shift(s
, op
, ot
, opreg
, OR_ECX
);
2669 shift
= ldub(s
->pc
++);
2671 gen_shifti(s
, op
, ot
, opreg
, shift
);
2686 case 0x1a4: /* shld imm */
2690 case 0x1a5: /* shld cl */
2694 case 0x1ac: /* shrd imm */
2698 case 0x1ad: /* shrd cl */
2702 ot
= dflag
? OT_LONG
: OT_WORD
;
2703 modrm
= ldub(s
->pc
++);
2704 mod
= (modrm
>> 6) & 3;
2706 reg
= (modrm
>> 3) & 7;
2709 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2710 gen_op_ld_T0_A0
[ot
+ s
->mem_index
]();
2712 gen_op_mov_TN_reg
[ot
][0][rm
]();
2714 gen_op_mov_TN_reg
[ot
][1][reg
]();
2717 val
= ldub(s
->pc
++);
2721 gen_op_shiftd_T0_T1_im_cc
[ot
- OT_WORD
][op
](val
);
2723 gen_op_shiftd_mem_T0_T1_im_cc
[ot
- OT_WORD
][op
](val
);
2724 if (op
== 0 && ot
!= OT_WORD
)
2725 s
->cc_op
= CC_OP_SHLB
+ ot
;
2727 s
->cc_op
= CC_OP_SARB
+ ot
;
2730 if (s
->cc_op
!= CC_OP_DYNAMIC
)
2731 gen_op_set_cc_op(s
->cc_op
);
2733 gen_op_shiftd_T0_T1_ECX_cc
[ot
- OT_WORD
][op
]();
2735 gen_op_shiftd_mem_T0_T1_ECX_cc
[ot
- OT_WORD
][op
]();
2736 s
->cc_op
= CC_OP_DYNAMIC
; /* cannot predict flags after */
2739 gen_op_mov_reg_T0
[ot
][rm
]();
2743 /************************/
2746 modrm
= ldub(s
->pc
++);
2747 mod
= (modrm
>> 6) & 3;
2749 op
= ((b
& 7) << 3) | ((modrm
>> 3) & 7);
2753 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
2755 case 0x00 ... 0x07: /* fxxxs */
2756 case 0x10 ... 0x17: /* fixxxl */
2757 case 0x20 ... 0x27: /* fxxxl */
2758 case 0x30 ... 0x37: /* fixxx */
2765 gen_op_flds_FT0_A0();
2768 gen_op_fildl_FT0_A0();
2771 gen_op_fldl_FT0_A0();
2775 gen_op_fild_FT0_A0();
2779 gen_op_fp_arith_ST0_FT0
[op1
]();
2781 /* fcomp needs pop */
2786 case 0x08: /* flds */
2787 case 0x0a: /* fsts */
2788 case 0x0b: /* fstps */
2789 case 0x18: /* fildl */
2790 case 0x1a: /* fistl */
2791 case 0x1b: /* fistpl */
2792 case 0x28: /* fldl */
2793 case 0x2a: /* fstl */
2794 case 0x2b: /* fstpl */
2795 case 0x38: /* filds */
2796 case 0x3a: /* fists */
2797 case 0x3b: /* fistps */
2803 gen_op_flds_ST0_A0();
2806 gen_op_fildl_ST0_A0();
2809 gen_op_fldl_ST0_A0();
2813 gen_op_fild_ST0_A0();
2820 gen_op_fsts_ST0_A0();
2823 gen_op_fistl_ST0_A0();
2826 gen_op_fstl_ST0_A0();
2830 gen_op_fist_ST0_A0();
2838 case 0x0c: /* fldenv mem */
2839 gen_op_fldenv_A0(s
->dflag
);
2841 case 0x0d: /* fldcw mem */
2844 case 0x0e: /* fnstenv mem */
2845 gen_op_fnstenv_A0(s
->dflag
);
2847 case 0x0f: /* fnstcw mem */
2850 case 0x1d: /* fldt mem */
2851 gen_op_fldt_ST0_A0();
2853 case 0x1f: /* fstpt mem */
2854 gen_op_fstt_ST0_A0();
2857 case 0x2c: /* frstor mem */
2858 gen_op_frstor_A0(s
->dflag
);
2860 case 0x2e: /* fnsave mem */
2861 gen_op_fnsave_A0(s
->dflag
);
2863 case 0x2f: /* fnstsw mem */
2866 case 0x3c: /* fbld */
2867 gen_op_fbld_ST0_A0();
2869 case 0x3e: /* fbstp */
2870 gen_op_fbst_ST0_A0();
2873 case 0x3d: /* fildll */
2874 gen_op_fildll_ST0_A0();
2876 case 0x3f: /* fistpll */
2877 gen_op_fistll_ST0_A0();
2884 /* register float ops */
2888 case 0x08: /* fld sti */
2890 gen_op_fmov_ST0_STN((opreg
+ 1) & 7);
2892 case 0x09: /* fxchg sti */
2893 gen_op_fxchg_ST0_STN(opreg
);
2895 case 0x0a: /* grp d9/2 */
2903 case 0x0c: /* grp d9/4 */
2913 gen_op_fcom_ST0_FT0();
2922 case 0x0d: /* grp d9/5 */
2931 gen_op_fldl2t_ST0();
2935 gen_op_fldl2e_ST0();
2943 gen_op_fldlg2_ST0();
2947 gen_op_fldln2_ST0();
2958 case 0x0e: /* grp d9/6 */
2969 case 3: /* fpatan */
2972 case 4: /* fxtract */
2975 case 5: /* fprem1 */
2978 case 6: /* fdecstp */
2982 case 7: /* fincstp */
2987 case 0x0f: /* grp d9/7 */
2992 case 1: /* fyl2xp1 */
2998 case 3: /* fsincos */
3001 case 5: /* fscale */
3004 case 4: /* frndint */
3016 case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
3017 case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
3018 case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
3024 gen_op_fp_arith_STN_ST0
[op1
](opreg
);
3028 gen_op_fmov_FT0_STN(opreg
);
3029 gen_op_fp_arith_ST0_FT0
[op1
]();
3033 case 0x02: /* fcom */
3034 gen_op_fmov_FT0_STN(opreg
);
3035 gen_op_fcom_ST0_FT0();
3037 case 0x03: /* fcomp */
3038 gen_op_fmov_FT0_STN(opreg
);
3039 gen_op_fcom_ST0_FT0();
3042 case 0x15: /* da/5 */
3044 case 1: /* fucompp */
3045 gen_op_fmov_FT0_STN(1);
3046 gen_op_fucom_ST0_FT0();
3056 case 0: /* feni (287 only, just do nop here) */
3058 case 1: /* fdisi (287 only, just do nop here) */
3063 case 3: /* fninit */
3066 case 4: /* fsetpm (287 only, just do nop here) */
3072 case 0x1d: /* fucomi */
3073 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3074 gen_op_set_cc_op(s
->cc_op
);
3075 gen_op_fmov_FT0_STN(opreg
);
3076 gen_op_fucomi_ST0_FT0();
3077 s
->cc_op
= CC_OP_EFLAGS
;
3079 case 0x1e: /* fcomi */
3080 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3081 gen_op_set_cc_op(s
->cc_op
);
3082 gen_op_fmov_FT0_STN(opreg
);
3083 gen_op_fcomi_ST0_FT0();
3084 s
->cc_op
= CC_OP_EFLAGS
;
3086 case 0x2a: /* fst sti */
3087 gen_op_fmov_STN_ST0(opreg
);
3089 case 0x2b: /* fstp sti */
3090 gen_op_fmov_STN_ST0(opreg
);
3093 case 0x2c: /* fucom st(i) */
3094 gen_op_fmov_FT0_STN(opreg
);
3095 gen_op_fucom_ST0_FT0();
3097 case 0x2d: /* fucomp st(i) */
3098 gen_op_fmov_FT0_STN(opreg
);
3099 gen_op_fucom_ST0_FT0();
3102 case 0x33: /* de/3 */
3104 case 1: /* fcompp */
3105 gen_op_fmov_FT0_STN(1);
3106 gen_op_fcom_ST0_FT0();
3114 case 0x3c: /* df/4 */
3117 gen_op_fnstsw_EAX();
3123 case 0x3d: /* fucomip */
3124 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3125 gen_op_set_cc_op(s
->cc_op
);
3126 gen_op_fmov_FT0_STN(opreg
);
3127 gen_op_fucomi_ST0_FT0();
3129 s
->cc_op
= CC_OP_EFLAGS
;
3131 case 0x3e: /* fcomip */
3132 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3133 gen_op_set_cc_op(s
->cc_op
);
3134 gen_op_fmov_FT0_STN(opreg
);
3135 gen_op_fcomi_ST0_FT0();
3137 s
->cc_op
= CC_OP_EFLAGS
;
3144 /************************/
3147 case 0xa4: /* movsS */
3152 ot
= dflag
? OT_LONG
: OT_WORD
;
3154 if (prefixes
& (PREFIX_REPZ
| PREFIX_REPNZ
)) {
3155 gen_repz_movs(s
, ot
, pc_start
- s
->cs_base
, s
->pc
- s
->cs_base
);
3161 case 0xaa: /* stosS */
3166 ot
= dflag
? OT_LONG
: OT_WORD
;
3168 if (prefixes
& (PREFIX_REPZ
| PREFIX_REPNZ
)) {
3169 gen_repz_stos(s
, ot
, pc_start
- s
->cs_base
, s
->pc
- s
->cs_base
);
3174 case 0xac: /* lodsS */
3179 ot
= dflag
? OT_LONG
: OT_WORD
;
3180 if (prefixes
& (PREFIX_REPZ
| PREFIX_REPNZ
)) {
3181 gen_repz_lods(s
, ot
, pc_start
- s
->cs_base
, s
->pc
- s
->cs_base
);
3186 case 0xae: /* scasS */
3191 ot
= dflag
? OT_LONG
: OT_WORD
;
3192 if (prefixes
& PREFIX_REPNZ
) {
3193 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3194 gen_op_set_cc_op(s
->cc_op
);
3195 gen_string_es(s
, ot
, gen_op_scas
+ STRINGOP_NB
);
3196 s
->cc_op
= CC_OP_DYNAMIC
; /* cannot predict flags after */
3197 } else if (prefixes
& PREFIX_REPZ
) {
3198 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3199 gen_op_set_cc_op(s
->cc_op
);
3200 gen_string_es(s
, ot
, gen_op_scas
);
3201 s
->cc_op
= CC_OP_DYNAMIC
; /* cannot predict flags after */
3204 s
->cc_op
= CC_OP_SUBB
+ ot
;
3208 case 0xa6: /* cmpsS */
3213 ot
= dflag
? OT_LONG
: OT_WORD
;
3214 if (prefixes
& PREFIX_REPNZ
) {
3215 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3216 gen_op_set_cc_op(s
->cc_op
);
3217 gen_string_ds(s
, ot
, gen_op_cmps
+ STRINGOP_NB
);
3218 s
->cc_op
= CC_OP_DYNAMIC
; /* cannot predict flags after */
3219 } else if (prefixes
& PREFIX_REPZ
) {
3220 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3221 gen_op_set_cc_op(s
->cc_op
);
3222 gen_string_ds(s
, ot
, gen_op_cmps
);
3223 s
->cc_op
= CC_OP_DYNAMIC
; /* cannot predict flags after */
3226 s
->cc_op
= CC_OP_SUBB
+ ot
;
3229 case 0x6c: /* insS */
3231 if (s
->pe
&& (s
->cpl
> s
->iopl
|| s
->vm86
)) {
3232 /* NOTE: even for (E)CX = 0 the exception is raised */
3233 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
3238 ot
= dflag
? OT_LONG
: OT_WORD
;
3239 if (prefixes
& (PREFIX_REPZ
| PREFIX_REPNZ
)) {
3240 gen_repz_ins(s
, ot
, pc_start
- s
->cs_base
, s
->pc
- s
->cs_base
);
3246 case 0x6e: /* outsS */
3248 if (s
->pe
&& (s
->cpl
> s
->iopl
|| s
->vm86
)) {
3249 /* NOTE: even for (E)CX = 0 the exception is raised */
3250 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
3255 ot
= dflag
? OT_LONG
: OT_WORD
;
3256 if (prefixes
& (PREFIX_REPZ
| PREFIX_REPNZ
)) {
3257 gen_repz_outs(s
, ot
, pc_start
- s
->cs_base
, s
->pc
- s
->cs_base
);
3264 /************************/
3268 if (s
->pe
&& (s
->cpl
> s
->iopl
|| s
->vm86
)) {
3269 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
3274 ot
= dflag
? OT_LONG
: OT_WORD
;
3275 val
= ldub(s
->pc
++);
3276 gen_op_movl_T0_im(val
);
3278 gen_op_mov_reg_T1
[ot
][R_EAX
]();
3283 if (s
->pe
&& (s
->cpl
> s
->iopl
|| s
->vm86
)) {
3284 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
3289 ot
= dflag
? OT_LONG
: OT_WORD
;
3290 val
= ldub(s
->pc
++);
3291 gen_op_movl_T0_im(val
);
3292 gen_op_mov_TN_reg
[ot
][1][R_EAX
]();
3298 if (s
->pe
&& (s
->cpl
> s
->iopl
|| s
->vm86
)) {
3299 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
3304 ot
= dflag
? OT_LONG
: OT_WORD
;
3305 gen_op_mov_TN_reg
[OT_WORD
][0][R_EDX
]();
3307 gen_op_mov_reg_T1
[ot
][R_EAX
]();
3312 if (s
->pe
&& (s
->cpl
> s
->iopl
|| s
->vm86
)) {
3313 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
3318 ot
= dflag
? OT_LONG
: OT_WORD
;
3319 gen_op_mov_TN_reg
[OT_WORD
][0][R_EDX
]();
3320 gen_op_mov_TN_reg
[ot
][1][R_EAX
]();
3325 /************************/
3327 case 0xc2: /* ret im */
3331 gen_stack_update(s
, val
+ (2 << s
->dflag
));
3333 gen_op_andl_T0_ffff();
3337 case 0xc3: /* ret */
3341 gen_op_andl_T0_ffff();
3345 case 0xca: /* lret im */
3349 if (s
->pe
&& !s
->vm86
) {
3350 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3351 gen_op_set_cc_op(s
->cc_op
);
3352 gen_op_jmp_im(pc_start
- s
->cs_base
);
3353 gen_op_lret_protected(s
->dflag
, val
);
3357 gen_op_ld_T0_A0
[1 + s
->dflag
+ s
->mem_index
]();
3359 gen_op_andl_T0_ffff();
3360 /* NOTE: keeping EIP updated is not a problem in case of
3364 gen_op_addl_A0_im(2 << s
->dflag
);
3365 gen_op_ld_T0_A0
[1 + s
->dflag
+ s
->mem_index
]();
3366 gen_op_movl_seg_T0_vm(offsetof(CPUX86State
,segs
[R_CS
]));
3367 /* add stack offset */
3368 gen_stack_update(s
, val
+ (4 << s
->dflag
));
3372 case 0xcb: /* lret */
3375 case 0xcf: /* iret */
3378 gen_op_iret_real(s
->dflag
);
3379 s
->cc_op
= CC_OP_EFLAGS
;
3380 } else if (s
->vm86
&& s
->iopl
!= 3) {
3381 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
3383 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3384 gen_op_set_cc_op(s
->cc_op
);
3385 gen_op_jmp_im(pc_start
- s
->cs_base
);
3386 gen_op_iret_protected(s
->dflag
);
3387 s
->cc_op
= CC_OP_EFLAGS
;
3391 case 0xe8: /* call im */
3393 unsigned int next_eip
;
3394 ot
= dflag
? OT_LONG
: OT_WORD
;
3395 val
= insn_get(s
, ot
);
3396 next_eip
= s
->pc
- s
->cs_base
;
3400 gen_op_movl_T0_im(next_eip
);
3405 case 0x9a: /* lcall im */
3407 unsigned int selector
, offset
;
3409 ot
= dflag
? OT_LONG
: OT_WORD
;
3410 offset
= insn_get(s
, ot
);
3411 selector
= insn_get(s
, OT_WORD
);
3413 gen_op_movl_T0_im(selector
);
3414 gen_op_movl_T1_im(offset
);
3417 case 0xe9: /* jmp */
3418 ot
= dflag
? OT_LONG
: OT_WORD
;
3419 val
= insn_get(s
, ot
);
3420 val
+= s
->pc
- s
->cs_base
;
3425 case 0xea: /* ljmp im */
3427 unsigned int selector
, offset
;
3429 ot
= dflag
? OT_LONG
: OT_WORD
;
3430 offset
= insn_get(s
, ot
);
3431 selector
= insn_get(s
, OT_WORD
);
3433 gen_op_movl_T0_im(selector
);
3434 gen_op_movl_T1_im(offset
);
3437 case 0xeb: /* jmp Jb */
3438 val
= (int8_t)insn_get(s
, OT_BYTE
);
3439 val
+= s
->pc
- s
->cs_base
;
3444 case 0x70 ... 0x7f: /* jcc Jb */
3445 val
= (int8_t)insn_get(s
, OT_BYTE
);
3447 case 0x180 ... 0x18f: /* jcc Jv */
3449 val
= insn_get(s
, OT_LONG
);
3451 val
= (int16_t)insn_get(s
, OT_WORD
);
3454 next_eip
= s
->pc
- s
->cs_base
;
3458 gen_jcc(s
, b
, val
, next_eip
);
3461 case 0x190 ... 0x19f: /* setcc Gv */
3462 modrm
= ldub(s
->pc
++);
3464 gen_ldst_modrm(s
, modrm
, OT_BYTE
, OR_TMP0
, 1);
3466 case 0x140 ... 0x14f: /* cmov Gv, Ev */
3467 ot
= dflag
? OT_LONG
: OT_WORD
;
3468 modrm
= ldub(s
->pc
++);
3469 reg
= (modrm
>> 3) & 7;
3470 mod
= (modrm
>> 6) & 3;
3473 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
3474 gen_op_ld_T1_A0
[ot
+ s
->mem_index
]();
3477 gen_op_mov_TN_reg
[ot
][1][rm
]();
3479 gen_op_cmov_reg_T1_T0
[ot
- OT_WORD
][reg
]();
3482 /************************/
3484 case 0x9c: /* pushf */
3485 if (s
->vm86
&& s
->iopl
!= 3) {
3486 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
3488 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3489 gen_op_set_cc_op(s
->cc_op
);
3490 gen_op_movl_T0_eflags();
3494 case 0x9d: /* popf */
3495 if (s
->vm86
&& s
->iopl
!= 3) {
3496 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
3501 gen_op_movl_eflags_T0_cpl0();
3503 gen_op_movw_eflags_T0_cpl0();
3507 gen_op_movl_eflags_T0();
3509 gen_op_movw_eflags_T0();
3513 s
->cc_op
= CC_OP_EFLAGS
;
3514 s
->is_jmp
= 2; /* abort translation because TF flag may change */
3517 case 0x9e: /* sahf */
3518 gen_op_mov_TN_reg
[OT_BYTE
][0][R_AH
]();
3519 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3520 gen_op_set_cc_op(s
->cc_op
);
3521 gen_op_movb_eflags_T0();
3522 s
->cc_op
= CC_OP_EFLAGS
;
3524 case 0x9f: /* lahf */
3525 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3526 gen_op_set_cc_op(s
->cc_op
);
3527 gen_op_movl_T0_eflags();
3528 gen_op_mov_reg_T0
[OT_BYTE
][R_AH
]();
3530 case 0xf5: /* cmc */
3531 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3532 gen_op_set_cc_op(s
->cc_op
);
3534 s
->cc_op
= CC_OP_EFLAGS
;
3536 case 0xf8: /* clc */
3537 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3538 gen_op_set_cc_op(s
->cc_op
);
3540 s
->cc_op
= CC_OP_EFLAGS
;
3542 case 0xf9: /* stc */
3543 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3544 gen_op_set_cc_op(s
->cc_op
);
3546 s
->cc_op
= CC_OP_EFLAGS
;
3548 case 0xfc: /* cld */
3551 case 0xfd: /* std */
3555 /************************/
3556 /* bit operations */
3557 case 0x1ba: /* bt/bts/btr/btc Gv, im */
3558 ot
= dflag
? OT_LONG
: OT_WORD
;
3559 modrm
= ldub(s
->pc
++);
3560 op
= (modrm
>> 3) & 7;
3561 mod
= (modrm
>> 6) & 3;
3564 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
3565 gen_op_ld_T0_A0
[ot
+ s
->mem_index
]();
3567 gen_op_mov_TN_reg
[ot
][0][rm
]();
3570 val
= ldub(s
->pc
++);
3571 gen_op_movl_T1_im(val
);
3575 gen_op_btx_T0_T1_cc
[ot
- OT_WORD
][op
]();
3576 s
->cc_op
= CC_OP_SARB
+ ot
;
3579 gen_op_st_T0_A0
[ot
+ s
->mem_index
]();
3581 gen_op_mov_reg_T0
[ot
][rm
]();
3582 gen_op_update_bt_cc();
3585 case 0x1a3: /* bt Gv, Ev */
3588 case 0x1ab: /* bts */
3591 case 0x1b3: /* btr */
3594 case 0x1bb: /* btc */
3597 ot
= dflag
? OT_LONG
: OT_WORD
;
3598 modrm
= ldub(s
->pc
++);
3599 reg
= (modrm
>> 3) & 7;
3600 mod
= (modrm
>> 6) & 3;
3602 gen_op_mov_TN_reg
[OT_LONG
][1][reg
]();
3604 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
3605 /* specific case: we need to add a displacement */
3607 gen_op_add_bitw_A0_T1();
3609 gen_op_add_bitl_A0_T1();
3610 gen_op_ld_T0_A0
[ot
+ s
->mem_index
]();
3612 gen_op_mov_TN_reg
[ot
][0][rm
]();
3614 gen_op_btx_T0_T1_cc
[ot
- OT_WORD
][op
]();
3615 s
->cc_op
= CC_OP_SARB
+ ot
;
3618 gen_op_st_T0_A0
[ot
+ s
->mem_index
]();
3620 gen_op_mov_reg_T0
[ot
][rm
]();
3621 gen_op_update_bt_cc();
3624 case 0x1bc: /* bsf */
3625 case 0x1bd: /* bsr */
3626 ot
= dflag
? OT_LONG
: OT_WORD
;
3627 modrm
= ldub(s
->pc
++);
3628 reg
= (modrm
>> 3) & 7;
3629 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 0);
3630 gen_op_bsx_T0_cc
[ot
- OT_WORD
][b
& 1]();
3631 /* NOTE: we always write back the result. Intel doc says it is
3632 undefined if T0 == 0 */
3633 gen_op_mov_reg_T0
[ot
][reg
]();
3634 s
->cc_op
= CC_OP_LOGICB
+ ot
;
3636 /************************/
3638 case 0x27: /* daa */
3639 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3640 gen_op_set_cc_op(s
->cc_op
);
3642 s
->cc_op
= CC_OP_EFLAGS
;
3644 case 0x2f: /* das */
3645 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3646 gen_op_set_cc_op(s
->cc_op
);
3648 s
->cc_op
= CC_OP_EFLAGS
;
3650 case 0x37: /* aaa */
3651 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3652 gen_op_set_cc_op(s
->cc_op
);
3654 s
->cc_op
= CC_OP_EFLAGS
;
3656 case 0x3f: /* aas */
3657 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3658 gen_op_set_cc_op(s
->cc_op
);
3660 s
->cc_op
= CC_OP_EFLAGS
;
3662 case 0xd4: /* aam */
3663 val
= ldub(s
->pc
++);
3665 s
->cc_op
= CC_OP_LOGICB
;
3667 case 0xd5: /* aad */
3668 val
= ldub(s
->pc
++);
3670 s
->cc_op
= CC_OP_LOGICB
;
3672 /************************/
3674 case 0x90: /* nop */
3676 case 0x9b: /* fwait */
3678 case 0xcc: /* int3 */
3679 gen_interrupt(s
, EXCP03_INT3
, pc_start
- s
->cs_base
, s
->pc
- s
->cs_base
);
3681 case 0xcd: /* int N */
3682 val
= ldub(s
->pc
++);
3683 /* XXX: add error code for vm86 GPF */
3685 gen_interrupt(s
, val
, pc_start
- s
->cs_base
, s
->pc
- s
->cs_base
);
3687 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
3689 case 0xce: /* into */
3690 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3691 gen_op_set_cc_op(s
->cc_op
);
3692 gen_op_into(s
->pc
- s
->cs_base
);
3694 case 0xf1: /* icebp (undocumented, exits to external debugger) */
3695 gen_debug(s
, pc_start
- s
->cs_base
);
3697 case 0xfa: /* cli */
3699 if (s
->cpl
<= s
->iopl
) {
3702 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
3708 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
3712 case 0xfb: /* sti */
3714 if (s
->cpl
<= s
->iopl
) {
3716 /* interruptions are enabled only the first insn after sti */
3717 gen_op_set_inhibit_irq();
3718 s
->is_jmp
= 2; /* give a chance to handle pending irqs */
3720 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
3725 /* interruptions are enabled only the first insn after sti */
3726 gen_op_set_inhibit_irq();
3727 s
->is_jmp
= 2; /* give a chance to handle pending irqs */
3729 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
3733 case 0x62: /* bound */
3734 ot
= dflag
? OT_LONG
: OT_WORD
;
3735 modrm
= ldub(s
->pc
++);
3736 reg
= (modrm
>> 3) & 7;
3737 mod
= (modrm
>> 6) & 3;
3740 gen_op_mov_reg_T0
[ot
][reg
]();
3741 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
3743 gen_op_boundw(pc_start
- s
->cs_base
);
3745 gen_op_boundl(pc_start
- s
->cs_base
);
3747 case 0x1c8 ... 0x1cf: /* bswap reg */
3749 gen_op_mov_TN_reg
[OT_LONG
][0][reg
]();
3751 gen_op_mov_reg_T0
[OT_LONG
][reg
]();
3753 case 0xd6: /* salc */
3754 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3755 gen_op_set_cc_op(s
->cc_op
);
3758 case 0xe0: /* loopnz */
3759 case 0xe1: /* loopz */
3760 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3761 gen_op_set_cc_op(s
->cc_op
);
3763 case 0xe2: /* loop */
3764 case 0xe3: /* jecxz */
3765 val
= (int8_t)insn_get(s
, OT_BYTE
);
3766 next_eip
= s
->pc
- s
->cs_base
;
3770 gen_op_loop
[s
->aflag
][b
& 3](val
, next_eip
);
3773 case 0x130: /* wrmsr */
3774 case 0x132: /* rdmsr */
3776 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
3784 case 0x131: /* rdtsc */
3787 case 0x1a2: /* cpuid */
3790 case 0xf4: /* hlt */
3792 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
3794 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3795 gen_op_set_cc_op(s
->cc_op
);
3796 gen_op_jmp_im(s
->pc
- s
->cs_base
);
3802 modrm
= ldub(s
->pc
++);
3803 mod
= (modrm
>> 6) & 3;
3804 op
= (modrm
>> 3) & 7;
3807 gen_op_movl_T0_env(offsetof(CPUX86State
,ldt
.selector
));
3811 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 1);
3815 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
3817 gen_ldst_modrm(s
, modrm
, OT_WORD
, OR_TMP0
, 0);
3818 gen_op_jmp_im(pc_start
- s
->cs_base
);
3823 gen_op_movl_T0_env(offsetof(CPUX86State
,tr
.selector
));
3827 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 1);
3831 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
3833 gen_ldst_modrm(s
, modrm
, OT_WORD
, OR_TMP0
, 0);
3834 gen_op_jmp_im(pc_start
- s
->cs_base
);
3845 modrm
= ldub(s
->pc
++);
3846 mod
= (modrm
>> 6) & 3;
3847 op
= (modrm
>> 3) & 7;
3853 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
3855 gen_op_movl_T0_env(offsetof(CPUX86State
,gdt
.limit
));
3857 gen_op_movl_T0_env(offsetof(CPUX86State
,idt
.limit
));
3858 gen_op_st_T0_A0
[OT_WORD
+ s
->mem_index
]();
3859 gen_op_addl_A0_im(2);
3861 gen_op_movl_T0_env(offsetof(CPUX86State
,gdt
.base
));
3863 gen_op_movl_T0_env(offsetof(CPUX86State
,idt
.base
));
3865 gen_op_andl_T0_im(0xffffff);
3866 gen_op_st_T0_A0
[OT_LONG
+ s
->mem_index
]();
3873 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
3875 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
3876 gen_op_ld_T1_A0
[OT_WORD
+ s
->mem_index
]();
3877 gen_op_addl_A0_im(2);
3878 gen_op_ld_T0_A0
[OT_LONG
+ s
->mem_index
]();
3880 gen_op_andl_T0_im(0xffffff);
3882 gen_op_movl_env_T0(offsetof(CPUX86State
,gdt
.base
));
3883 gen_op_movl_env_T1(offsetof(CPUX86State
,gdt
.limit
));
3885 gen_op_movl_env_T0(offsetof(CPUX86State
,idt
.base
));
3886 gen_op_movl_env_T1(offsetof(CPUX86State
,idt
.limit
));
3891 gen_op_movl_T0_env(offsetof(CPUX86State
,cr
[0]));
3892 gen_ldst_modrm(s
, modrm
, OT_WORD
, OR_TMP0
, 1);
3896 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
3898 gen_ldst_modrm(s
, modrm
, OT_WORD
, OR_TMP0
, 0);
3902 case 7: /* invlpg */
3904 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
3908 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
3916 case 0x102: /* lar */
3917 case 0x103: /* lsl */
3918 if (!s
->pe
|| s
->vm86
)
3920 ot
= dflag
? OT_LONG
: OT_WORD
;
3921 modrm
= ldub(s
->pc
++);
3922 reg
= (modrm
>> 3) & 7;
3923 gen_ldst_modrm(s
, modrm
, ot
, OR_TMP0
, 0);
3924 gen_op_mov_TN_reg
[ot
][1][reg
]();
3925 if (s
->cc_op
!= CC_OP_DYNAMIC
)
3926 gen_op_set_cc_op(s
->cc_op
);
3931 s
->cc_op
= CC_OP_EFLAGS
;
3932 gen_op_mov_reg_T1
[ot
][reg
]();
3935 modrm
= ldub(s
->pc
++);
3936 mod
= (modrm
>> 6) & 3;
3937 op
= (modrm
>> 3) & 7;
3939 case 0: /* prefetchnta */
3940 case 1: /* prefetchnt0 */
3941 case 2: /* prefetchnt0 */
3942 case 3: /* prefetchnt0 */
3945 gen_lea_modrm(s
, modrm
, ®_addr
, &offset_addr
);
3946 /* nothing more to do */
3952 case 0x120: /* mov reg, crN */
3953 case 0x122: /* mov crN, reg */
3955 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
3957 modrm
= ldub(s
->pc
++);
3958 if ((modrm
& 0xc0) != 0xc0)
3961 reg
= (modrm
>> 3) & 7;
3968 gen_op_mov_TN_reg
[OT_LONG
][0][rm
]();
3969 gen_op_movl_crN_T0(reg
);
3972 gen_op_movl_T0_env(offsetof(CPUX86State
,cr
[reg
]));
3973 gen_op_mov_reg_T0
[OT_LONG
][rm
]();
3981 case 0x121: /* mov reg, drN */
3982 case 0x123: /* mov drN, reg */
3984 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
3986 modrm
= ldub(s
->pc
++);
3987 if ((modrm
& 0xc0) != 0xc0)
3990 reg
= (modrm
>> 3) & 7;
3991 /* XXX: do it dynamically with CR4.DE bit */
3992 if (reg
== 4 || reg
== 5)
3995 gen_op_mov_TN_reg
[OT_LONG
][0][rm
]();
3996 gen_op_movl_drN_T0(reg
);
3999 gen_op_movl_T0_env(offsetof(CPUX86State
,dr
[reg
]));
4000 gen_op_mov_reg_T0
[OT_LONG
][rm
]();
4004 case 0x106: /* clts */
4006 gen_exception(s
, EXCP0D_GPF
, pc_start
- s
->cs_base
);
4014 /* lock generation */
4015 if (s
->prefix
& PREFIX_LOCK
)
4019 /* XXX: ensure that no lock was generated */
4023 #define CC_OSZAPC (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C)
4024 #define CC_OSZAP (CC_O | CC_S | CC_Z | CC_A | CC_P)
4026 /* flags read by an operation */
4027 static uint16_t opc_read_flags
[NB_OPS
] = {
4028 [INDEX_op_aas
] = CC_A
,
4029 [INDEX_op_aaa
] = CC_A
,
4030 [INDEX_op_das
] = CC_A
| CC_C
,
4031 [INDEX_op_daa
] = CC_A
| CC_C
,
4033 [INDEX_op_adcb_T0_T1_cc
] = CC_C
,
4034 [INDEX_op_adcw_T0_T1_cc
] = CC_C
,
4035 [INDEX_op_adcl_T0_T1_cc
] = CC_C
,
4036 [INDEX_op_sbbb_T0_T1_cc
] = CC_C
,
4037 [INDEX_op_sbbw_T0_T1_cc
] = CC_C
,
4038 [INDEX_op_sbbl_T0_T1_cc
] = CC_C
,
4040 [INDEX_op_adcb_mem_T0_T1_cc
] = CC_C
,
4041 [INDEX_op_adcw_mem_T0_T1_cc
] = CC_C
,
4042 [INDEX_op_adcl_mem_T0_T1_cc
] = CC_C
,
4043 [INDEX_op_sbbb_mem_T0_T1_cc
] = CC_C
,
4044 [INDEX_op_sbbw_mem_T0_T1_cc
] = CC_C
,
4045 [INDEX_op_sbbl_mem_T0_T1_cc
] = CC_C
,
4047 /* subtle: due to the incl/decl implementation, C is used */
4048 [INDEX_op_update_inc_cc
] = CC_C
,
4050 [INDEX_op_into
] = CC_O
,
4052 [INDEX_op_jb_subb
] = CC_C
,
4053 [INDEX_op_jb_subw
] = CC_C
,
4054 [INDEX_op_jb_subl
] = CC_C
,
4056 [INDEX_op_jz_subb
] = CC_Z
,
4057 [INDEX_op_jz_subw
] = CC_Z
,
4058 [INDEX_op_jz_subl
] = CC_Z
,
4060 [INDEX_op_jbe_subb
] = CC_Z
| CC_C
,
4061 [INDEX_op_jbe_subw
] = CC_Z
| CC_C
,
4062 [INDEX_op_jbe_subl
] = CC_Z
| CC_C
,
4064 [INDEX_op_js_subb
] = CC_S
,
4065 [INDEX_op_js_subw
] = CC_S
,
4066 [INDEX_op_js_subl
] = CC_S
,
4068 [INDEX_op_jl_subb
] = CC_O
| CC_S
,
4069 [INDEX_op_jl_subw
] = CC_O
| CC_S
,
4070 [INDEX_op_jl_subl
] = CC_O
| CC_S
,
4072 [INDEX_op_jle_subb
] = CC_O
| CC_S
| CC_Z
,
4073 [INDEX_op_jle_subw
] = CC_O
| CC_S
| CC_Z
,
4074 [INDEX_op_jle_subl
] = CC_O
| CC_S
| CC_Z
,
4076 [INDEX_op_loopnzw
] = CC_Z
,
4077 [INDEX_op_loopnzl
] = CC_Z
,
4078 [INDEX_op_loopzw
] = CC_Z
,
4079 [INDEX_op_loopzl
] = CC_Z
,
4081 [INDEX_op_seto_T0_cc
] = CC_O
,
4082 [INDEX_op_setb_T0_cc
] = CC_C
,
4083 [INDEX_op_setz_T0_cc
] = CC_Z
,
4084 [INDEX_op_setbe_T0_cc
] = CC_Z
| CC_C
,
4085 [INDEX_op_sets_T0_cc
] = CC_S
,
4086 [INDEX_op_setp_T0_cc
] = CC_P
,
4087 [INDEX_op_setl_T0_cc
] = CC_O
| CC_S
,
4088 [INDEX_op_setle_T0_cc
] = CC_O
| CC_S
| CC_Z
,
4090 [INDEX_op_setb_T0_subb
] = CC_C
,
4091 [INDEX_op_setb_T0_subw
] = CC_C
,
4092 [INDEX_op_setb_T0_subl
] = CC_C
,
4094 [INDEX_op_setz_T0_subb
] = CC_Z
,
4095 [INDEX_op_setz_T0_subw
] = CC_Z
,
4096 [INDEX_op_setz_T0_subl
] = CC_Z
,
4098 [INDEX_op_setbe_T0_subb
] = CC_Z
| CC_C
,
4099 [INDEX_op_setbe_T0_subw
] = CC_Z
| CC_C
,
4100 [INDEX_op_setbe_T0_subl
] = CC_Z
| CC_C
,
4102 [INDEX_op_sets_T0_subb
] = CC_S
,
4103 [INDEX_op_sets_T0_subw
] = CC_S
,
4104 [INDEX_op_sets_T0_subl
] = CC_S
,
4106 [INDEX_op_setl_T0_subb
] = CC_O
| CC_S
,
4107 [INDEX_op_setl_T0_subw
] = CC_O
| CC_S
,
4108 [INDEX_op_setl_T0_subl
] = CC_O
| CC_S
,
4110 [INDEX_op_setle_T0_subb
] = CC_O
| CC_S
| CC_Z
,
4111 [INDEX_op_setle_T0_subw
] = CC_O
| CC_S
| CC_Z
,
4112 [INDEX_op_setle_T0_subl
] = CC_O
| CC_S
| CC_Z
,
4114 [INDEX_op_movl_T0_eflags
] = CC_OSZAPC
,
4115 [INDEX_op_cmc
] = CC_C
,
4116 [INDEX_op_salc
] = CC_C
,
4118 [INDEX_op_rclb_T0_T1_cc
] = CC_C
,
4119 [INDEX_op_rclw_T0_T1_cc
] = CC_C
,
4120 [INDEX_op_rcll_T0_T1_cc
] = CC_C
,
4121 [INDEX_op_rcrb_T0_T1_cc
] = CC_C
,
4122 [INDEX_op_rcrw_T0_T1_cc
] = CC_C
,
4123 [INDEX_op_rcrl_T0_T1_cc
] = CC_C
,
4125 [INDEX_op_rclb_mem_T0_T1_cc
] = CC_C
,
4126 [INDEX_op_rclw_mem_T0_T1_cc
] = CC_C
,
4127 [INDEX_op_rcll_mem_T0_T1_cc
] = CC_C
,
4128 [INDEX_op_rcrb_mem_T0_T1_cc
] = CC_C
,
4129 [INDEX_op_rcrw_mem_T0_T1_cc
] = CC_C
,
4130 [INDEX_op_rcrl_mem_T0_T1_cc
] = CC_C
,
4133 /* flags written by an operation */
4134 static uint16_t opc_write_flags
[NB_OPS
] = {
4135 [INDEX_op_update2_cc
] = CC_OSZAPC
,
4136 [INDEX_op_update1_cc
] = CC_OSZAPC
,
4137 [INDEX_op_cmpl_T0_T1_cc
] = CC_OSZAPC
,
4138 [INDEX_op_update_neg_cc
] = CC_OSZAPC
,
4139 /* subtle: due to the incl/decl implementation, C is used */
4140 [INDEX_op_update_inc_cc
] = CC_OSZAPC
,
4141 [INDEX_op_testl_T0_T1_cc
] = CC_OSZAPC
,
4143 [INDEX_op_adcb_T0_T1_cc
] = CC_OSZAPC
,
4144 [INDEX_op_adcw_T0_T1_cc
] = CC_OSZAPC
,
4145 [INDEX_op_adcl_T0_T1_cc
] = CC_OSZAPC
,
4146 [INDEX_op_sbbb_T0_T1_cc
] = CC_OSZAPC
,
4147 [INDEX_op_sbbw_T0_T1_cc
] = CC_OSZAPC
,
4148 [INDEX_op_sbbl_T0_T1_cc
] = CC_OSZAPC
,
4150 [INDEX_op_adcb_mem_T0_T1_cc
] = CC_OSZAPC
,
4151 [INDEX_op_adcw_mem_T0_T1_cc
] = CC_OSZAPC
,
4152 [INDEX_op_adcl_mem_T0_T1_cc
] = CC_OSZAPC
,
4153 [INDEX_op_sbbb_mem_T0_T1_cc
] = CC_OSZAPC
,
4154 [INDEX_op_sbbw_mem_T0_T1_cc
] = CC_OSZAPC
,
4155 [INDEX_op_sbbl_mem_T0_T1_cc
] = CC_OSZAPC
,
4157 [INDEX_op_mulb_AL_T0
] = CC_OSZAPC
,
4158 [INDEX_op_imulb_AL_T0
] = CC_OSZAPC
,
4159 [INDEX_op_mulw_AX_T0
] = CC_OSZAPC
,
4160 [INDEX_op_imulw_AX_T0
] = CC_OSZAPC
,
4161 [INDEX_op_mull_EAX_T0
] = CC_OSZAPC
,
4162 [INDEX_op_imull_EAX_T0
] = CC_OSZAPC
,
4163 [INDEX_op_imulw_T0_T1
] = CC_OSZAPC
,
4164 [INDEX_op_imull_T0_T1
] = CC_OSZAPC
,
4167 [INDEX_op_aam
] = CC_OSZAPC
,
4168 [INDEX_op_aad
] = CC_OSZAPC
,
4169 [INDEX_op_aas
] = CC_OSZAPC
,
4170 [INDEX_op_aaa
] = CC_OSZAPC
,
4171 [INDEX_op_das
] = CC_OSZAPC
,
4172 [INDEX_op_daa
] = CC_OSZAPC
,
4174 [INDEX_op_movb_eflags_T0
] = CC_S
| CC_Z
| CC_A
| CC_P
| CC_C
,
4175 [INDEX_op_movw_eflags_T0
] = CC_OSZAPC
,
4176 [INDEX_op_movl_eflags_T0
] = CC_OSZAPC
,
4177 [INDEX_op_clc
] = CC_C
,
4178 [INDEX_op_stc
] = CC_C
,
4179 [INDEX_op_cmc
] = CC_C
,
4181 [INDEX_op_rolb_T0_T1_cc
] = CC_O
| CC_C
,
4182 [INDEX_op_rolw_T0_T1_cc
] = CC_O
| CC_C
,
4183 [INDEX_op_roll_T0_T1_cc
] = CC_O
| CC_C
,
4184 [INDEX_op_rorb_T0_T1_cc
] = CC_O
| CC_C
,
4185 [INDEX_op_rorw_T0_T1_cc
] = CC_O
| CC_C
,
4186 [INDEX_op_rorl_T0_T1_cc
] = CC_O
| CC_C
,
4188 [INDEX_op_rclb_T0_T1_cc
] = CC_O
| CC_C
,
4189 [INDEX_op_rclw_T0_T1_cc
] = CC_O
| CC_C
,
4190 [INDEX_op_rcll_T0_T1_cc
] = CC_O
| CC_C
,
4191 [INDEX_op_rcrb_T0_T1_cc
] = CC_O
| CC_C
,
4192 [INDEX_op_rcrw_T0_T1_cc
] = CC_O
| CC_C
,
4193 [INDEX_op_rcrl_T0_T1_cc
] = CC_O
| CC_C
,
4195 [INDEX_op_shlb_T0_T1_cc
] = CC_OSZAPC
,
4196 [INDEX_op_shlw_T0_T1_cc
] = CC_OSZAPC
,
4197 [INDEX_op_shll_T0_T1_cc
] = CC_OSZAPC
,
4199 [INDEX_op_shrb_T0_T1_cc
] = CC_OSZAPC
,
4200 [INDEX_op_shrw_T0_T1_cc
] = CC_OSZAPC
,
4201 [INDEX_op_shrl_T0_T1_cc
] = CC_OSZAPC
,
4203 [INDEX_op_sarb_T0_T1_cc
] = CC_OSZAPC
,
4204 [INDEX_op_sarw_T0_T1_cc
] = CC_OSZAPC
,
4205 [INDEX_op_sarl_T0_T1_cc
] = CC_OSZAPC
,
4207 [INDEX_op_shldw_T0_T1_ECX_cc
] = CC_OSZAPC
,
4208 [INDEX_op_shldl_T0_T1_ECX_cc
] = CC_OSZAPC
,
4209 [INDEX_op_shldw_T0_T1_im_cc
] = CC_OSZAPC
,
4210 [INDEX_op_shldl_T0_T1_im_cc
] = CC_OSZAPC
,
4212 [INDEX_op_shrdw_T0_T1_ECX_cc
] = CC_OSZAPC
,
4213 [INDEX_op_shrdl_T0_T1_ECX_cc
] = CC_OSZAPC
,
4214 [INDEX_op_shrdw_T0_T1_im_cc
] = CC_OSZAPC
,
4215 [INDEX_op_shrdl_T0_T1_im_cc
] = CC_OSZAPC
,
4217 [INDEX_op_rolb_mem_T0_T1_cc
] = CC_O
| CC_C
,
4218 [INDEX_op_rolw_mem_T0_T1_cc
] = CC_O
| CC_C
,
4219 [INDEX_op_roll_mem_T0_T1_cc
] = CC_O
| CC_C
,
4220 [INDEX_op_rorb_mem_T0_T1_cc
] = CC_O
| CC_C
,
4221 [INDEX_op_rorw_mem_T0_T1_cc
] = CC_O
| CC_C
,
4222 [INDEX_op_rorl_mem_T0_T1_cc
] = CC_O
| CC_C
,
4224 [INDEX_op_rclb_mem_T0_T1_cc
] = CC_O
| CC_C
,
4225 [INDEX_op_rclw_mem_T0_T1_cc
] = CC_O
| CC_C
,
4226 [INDEX_op_rcll_mem_T0_T1_cc
] = CC_O
| CC_C
,
4227 [INDEX_op_rcrb_mem_T0_T1_cc
] = CC_O
| CC_C
,
4228 [INDEX_op_rcrw_mem_T0_T1_cc
] = CC_O
| CC_C
,
4229 [INDEX_op_rcrl_mem_T0_T1_cc
] = CC_O
| CC_C
,
4231 [INDEX_op_shlb_mem_T0_T1_cc
] = CC_OSZAPC
,
4232 [INDEX_op_shlw_mem_T0_T1_cc
] = CC_OSZAPC
,
4233 [INDEX_op_shll_mem_T0_T1_cc
] = CC_OSZAPC
,
4235 [INDEX_op_shrb_mem_T0_T1_cc
] = CC_OSZAPC
,
4236 [INDEX_op_shrw_mem_T0_T1_cc
] = CC_OSZAPC
,
4237 [INDEX_op_shrl_mem_T0_T1_cc
] = CC_OSZAPC
,
4239 [INDEX_op_sarb_mem_T0_T1_cc
] = CC_OSZAPC
,
4240 [INDEX_op_sarw_mem_T0_T1_cc
] = CC_OSZAPC
,
4241 [INDEX_op_sarl_mem_T0_T1_cc
] = CC_OSZAPC
,
4243 [INDEX_op_shldw_mem_T0_T1_ECX_cc
] = CC_OSZAPC
,
4244 [INDEX_op_shldl_mem_T0_T1_ECX_cc
] = CC_OSZAPC
,
4245 [INDEX_op_shldw_mem_T0_T1_im_cc
] = CC_OSZAPC
,
4246 [INDEX_op_shldl_mem_T0_T1_im_cc
] = CC_OSZAPC
,
4248 [INDEX_op_shrdw_mem_T0_T1_ECX_cc
] = CC_OSZAPC
,
4249 [INDEX_op_shrdl_mem_T0_T1_ECX_cc
] = CC_OSZAPC
,
4250 [INDEX_op_shrdw_mem_T0_T1_im_cc
] = CC_OSZAPC
,
4251 [INDEX_op_shrdl_mem_T0_T1_im_cc
] = CC_OSZAPC
,
4253 [INDEX_op_btw_T0_T1_cc
] = CC_OSZAPC
,
4254 [INDEX_op_btl_T0_T1_cc
] = CC_OSZAPC
,
4255 [INDEX_op_btsw_T0_T1_cc
] = CC_OSZAPC
,
4256 [INDEX_op_btsl_T0_T1_cc
] = CC_OSZAPC
,
4257 [INDEX_op_btrw_T0_T1_cc
] = CC_OSZAPC
,
4258 [INDEX_op_btrl_T0_T1_cc
] = CC_OSZAPC
,
4259 [INDEX_op_btcw_T0_T1_cc
] = CC_OSZAPC
,
4260 [INDEX_op_btcl_T0_T1_cc
] = CC_OSZAPC
,
4262 [INDEX_op_bsfw_T0_cc
] = CC_OSZAPC
,
4263 [INDEX_op_bsfl_T0_cc
] = CC_OSZAPC
,
4264 [INDEX_op_bsrw_T0_cc
] = CC_OSZAPC
,
4265 [INDEX_op_bsrl_T0_cc
] = CC_OSZAPC
,
4268 #define STRINGOP(x) \
4269 [INDEX_op_ ## x ## b_fast] = CC_OSZAPC, \
4270 [INDEX_op_ ## x ## w_fast] = CC_OSZAPC, \
4271 [INDEX_op_ ## x ## l_fast] = CC_OSZAPC, \
4272 [INDEX_op_ ## x ## b_a32] = CC_OSZAPC, \
4273 [INDEX_op_ ## x ## w_a32] = CC_OSZAPC, \
4274 [INDEX_op_ ## x ## l_a32] = CC_OSZAPC, \
4275 [INDEX_op_ ## x ## b_a16] = CC_OSZAPC, \
4276 [INDEX_op_ ## x ## w_a16] = CC_OSZAPC, \
4277 [INDEX_op_ ## x ## l_a16] = CC_OSZAPC,
4280 STRINGOP(repnz_scas
)
4282 STRINGOP(repnz_cmps
)
4284 [INDEX_op_cmpxchgb_T0_T1_EAX_cc
] = CC_OSZAPC
,
4285 [INDEX_op_cmpxchgw_T0_T1_EAX_cc
] = CC_OSZAPC
,
4286 [INDEX_op_cmpxchgl_T0_T1_EAX_cc
] = CC_OSZAPC
,
4288 [INDEX_op_cmpxchgb_mem_T0_T1_EAX_cc
] = CC_OSZAPC
,
4289 [INDEX_op_cmpxchgw_mem_T0_T1_EAX_cc
] = CC_OSZAPC
,
4290 [INDEX_op_cmpxchgl_mem_T0_T1_EAX_cc
] = CC_OSZAPC
,
4292 [INDEX_op_cmpxchg8b
] = CC_Z
,
4293 [INDEX_op_lar
] = CC_Z
,
4294 [INDEX_op_lsl
] = CC_Z
,
4295 [INDEX_op_fcomi_ST0_FT0
] = CC_Z
| CC_P
| CC_C
,
4296 [INDEX_op_fucomi_ST0_FT0
] = CC_Z
| CC_P
| CC_C
,
4299 /* simpler form of an operation if no flags need to be generated */
4300 static uint16_t opc_simpler
[NB_OPS
] = {
4301 [INDEX_op_update2_cc
] = INDEX_op_nop
,
4302 [INDEX_op_update1_cc
] = INDEX_op_nop
,
4303 [INDEX_op_update_neg_cc
] = INDEX_op_nop
,
4305 /* broken: CC_OP logic must be rewritten */
4306 [INDEX_op_update_inc_cc
] = INDEX_op_nop
,
4308 [INDEX_op_rolb_T0_T1_cc
] = INDEX_op_rolb_T0_T1
,
4309 [INDEX_op_rolw_T0_T1_cc
] = INDEX_op_rolw_T0_T1
,
4310 [INDEX_op_roll_T0_T1_cc
] = INDEX_op_roll_T0_T1
,
4312 [INDEX_op_rorb_T0_T1_cc
] = INDEX_op_rorb_T0_T1
,
4313 [INDEX_op_rorw_T0_T1_cc
] = INDEX_op_rorw_T0_T1
,
4314 [INDEX_op_rorl_T0_T1_cc
] = INDEX_op_rorl_T0_T1
,
4316 [INDEX_op_rolb_mem_T0_T1_cc
] = INDEX_op_rolb_mem_T0_T1
,
4317 [INDEX_op_rolw_mem_T0_T1_cc
] = INDEX_op_rolw_mem_T0_T1
,
4318 [INDEX_op_roll_mem_T0_T1_cc
] = INDEX_op_roll_mem_T0_T1
,
4320 [INDEX_op_rorb_mem_T0_T1_cc
] = INDEX_op_rorb_mem_T0_T1
,
4321 [INDEX_op_rorw_mem_T0_T1_cc
] = INDEX_op_rorw_mem_T0_T1
,
4322 [INDEX_op_rorl_mem_T0_T1_cc
] = INDEX_op_rorl_mem_T0_T1
,
4324 [INDEX_op_shlb_T0_T1_cc
] = INDEX_op_shlb_T0_T1
,
4325 [INDEX_op_shlw_T0_T1_cc
] = INDEX_op_shlw_T0_T1
,
4326 [INDEX_op_shll_T0_T1_cc
] = INDEX_op_shll_T0_T1
,
4328 [INDEX_op_shrb_T0_T1_cc
] = INDEX_op_shrb_T0_T1
,
4329 [INDEX_op_shrw_T0_T1_cc
] = INDEX_op_shrw_T0_T1
,
4330 [INDEX_op_shrl_T0_T1_cc
] = INDEX_op_shrl_T0_T1
,
4332 [INDEX_op_sarb_T0_T1_cc
] = INDEX_op_sarb_T0_T1
,
4333 [INDEX_op_sarw_T0_T1_cc
] = INDEX_op_sarw_T0_T1
,
4334 [INDEX_op_sarl_T0_T1_cc
] = INDEX_op_sarl_T0_T1
,
4337 void optimize_flags_init(void)
4340 /* put default values in arrays */
4341 for(i
= 0; i
< NB_OPS
; i
++) {
4342 if (opc_simpler
[i
] == 0)
4347 /* CPU flags computation optimization: we move backward thru the
4348 generated code to see which flags are needed. The operation is
4349 modified if suitable */
4350 static void optimize_flags(uint16_t *opc_buf
, int opc_buf_len
)
4353 int live_flags
, write_flags
, op
;
4355 opc_ptr
= opc_buf
+ opc_buf_len
;
4356 /* live_flags contains the flags needed by the next instructions
4357 in the code. At the end of the bloc, we consider that all the
4359 live_flags
= CC_OSZAPC
;
4360 while (opc_ptr
> opc_buf
) {
4362 /* if none of the flags written by the instruction is used,
4363 then we can try to find a simpler instruction */
4364 write_flags
= opc_write_flags
[op
];
4365 if ((live_flags
& write_flags
) == 0) {
4366 *opc_ptr
= opc_simpler
[op
];
4368 /* compute the live flags before the instruction */
4369 live_flags
&= ~write_flags
;
4370 live_flags
|= opc_read_flags
[op
];
4374 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
4375 basic block 'tb'. If search_pc is TRUE, also generate PC
4376 information for each intermediate instruction. */
4377 static inline int gen_intermediate_code_internal(CPUState
*env
,
4378 TranslationBlock
*tb
,
4381 DisasContext dc1
, *dc
= &dc1
;
4383 uint16_t *gen_opc_end
;
4389 /* generate intermediate code */
4390 pc_start
= (uint8_t *)tb
->pc
;
4391 cs_base
= (uint8_t *)tb
->cs_base
;
4394 dc
->pe
= env
->cr
[0] & CR0_PE_MASK
;
4395 dc
->code32
= (flags
>> HF_CS32_SHIFT
) & 1;
4396 dc
->ss32
= (flags
>> HF_SS32_SHIFT
) & 1;
4397 dc
->addseg
= (flags
>> HF_ADDSEG_SHIFT
) & 1;
4399 dc
->vm86
= (flags
>> VM_SHIFT
) & 1;
4400 dc
->cpl
= (flags
>> HF_CPL_SHIFT
) & 3;
4401 dc
->iopl
= (flags
>> IOPL_SHIFT
) & 3;
4402 dc
->tf
= (flags
>> TF_SHIFT
) & 1;
4403 dc
->cc_op
= CC_OP_DYNAMIC
;
4404 dc
->cs_base
= cs_base
;
4406 dc
->popl_esp_hack
= 0;
4407 /* select memory access functions */
4409 if (flags
& HF_SOFTMMU_MASK
) {
4416 gen_opc_ptr
= gen_opc_buf
;
4417 gen_opc_end
= gen_opc_buf
+ OPC_MAX_SIZE
;
4418 gen_opparam_ptr
= gen_opparam_buf
;
4420 dc
->is_jmp
= DISAS_NEXT
;
4424 /* if irq were inhibited for the next instruction, we can disable
4425 them here as it is simpler (otherwise jumps would have to
4426 handled as special case) */
4427 if (flags
& HF_INHIBIT_IRQ_MASK
) {
4428 gen_op_reset_inhibit_irq();
4431 if (env
->nb_breakpoints
> 0) {
4432 for(j
= 0; j
< env
->nb_breakpoints
; j
++) {
4433 if (env
->breakpoints
[j
] == (unsigned long)pc_ptr
) {
4434 gen_debug(dc
, pc_ptr
- dc
->cs_base
);
4440 j
= gen_opc_ptr
- gen_opc_buf
;
4444 gen_opc_instr_start
[lj
++] = 0;
4446 gen_opc_pc
[lj
] = (uint32_t)pc_ptr
;
4447 gen_opc_cc_op
[lj
] = dc
->cc_op
;
4448 gen_opc_instr_start
[lj
] = 1;
4450 ret
= disas_insn(dc
, pc_ptr
);
4452 /* we trigger an illegal instruction operation only if it
4453 is the first instruction. Otherwise, we simply stop
4454 generating the code just before it */
4455 if (pc_ptr
== pc_start
)
4460 pc_ptr
= (void *)ret
;
4461 /* if single step mode, we generate only one instruction and
4462 generate an exception */
4465 } while (!dc
->is_jmp
&& gen_opc_ptr
< gen_opc_end
&&
4466 (pc_ptr
- pc_start
) < (TARGET_PAGE_SIZE
- 32));
4467 if (!dc
->tf
&& dc
->is_jmp
== DISAS_NEXT
) {
4468 gen_jmp(dc
, ret
- (unsigned long)dc
->cs_base
);
4471 /* we must store the eflags state if it is not already done */
4472 if (dc
->is_jmp
!= DISAS_TB_JUMP
) {
4473 if (dc
->cc_op
!= CC_OP_DYNAMIC
)
4474 gen_op_set_cc_op(dc
->cc_op
);
4475 if (dc
->is_jmp
!= DISAS_JUMP
) {
4476 /* we add an additionnal jmp to update the simulated PC */
4477 gen_op_jmp_im(ret
- (unsigned long)dc
->cs_base
);
4481 gen_op_raise_exception(EXCP01_SSTP
);
4484 if (dc
->is_jmp
!= DISAS_TB_JUMP
) {
4485 /* indicate that the hash table must be used to find the next TB */
4489 *gen_opc_ptr
= INDEX_op_end
;
4490 /* we don't forget to fill the last values */
4492 j
= gen_opc_ptr
- gen_opc_buf
;
4495 gen_opc_instr_start
[lj
++] = 0;
4500 fprintf(logfile
, "----------------\n");
4501 fprintf(logfile
, "IN: %s\n", lookup_symbol(pc_start
));
4502 disas(logfile
, pc_start
, pc_ptr
- pc_start
, 0, !dc
->code32
);
4503 fprintf(logfile
, "\n");
4505 fprintf(logfile
, "OP:\n");
4506 dump_ops(gen_opc_buf
, gen_opparam_buf
);
4507 fprintf(logfile
, "\n");
4511 /* optimize flag computations */
4512 optimize_flags(gen_opc_buf
, gen_opc_ptr
- gen_opc_buf
);
4516 fprintf(logfile
, "AFTER FLAGS OPT:\n");
4517 dump_ops(gen_opc_buf
, gen_opparam_buf
);
4518 fprintf(logfile
, "\n");
4522 tb
->size
= pc_ptr
- pc_start
;
4526 int gen_intermediate_code(CPUState
*env
, TranslationBlock
*tb
)
4528 return gen_intermediate_code_internal(env
, tb
, 0);
4531 int gen_intermediate_code_pc(CPUState
*env
, TranslationBlock
*tb
)
4533 return gen_intermediate_code_internal(env
, tb
, 1);