1 /****************************************************************************
3 * Realmode X86 Emulator Library
5 * Copyright (C) 1991-2004 SciTech Software, Inc.
6 * Copyright (C) David Mosberger-Tang
7 * Copyright (C) 1999 Egbert Eich
9 * ========================================================================
11 * Permission to use, copy, modify, distribute, and sell this software and
12 * its documentation for any purpose is hereby granted without fee,
13 * provided that the above copyright notice appear in all copies and that
14 * both that copyright notice and this permission notice appear in
15 * supporting documentation, and that the name of the authors not be used
16 * in advertising or publicity pertaining to distribution of the software
17 * without specific, written prior permission. The authors makes no
18 * representations about the suitability of this software for any purpose.
19 * It is provided "as is" without express or implied warranty.
21 * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
22 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
23 * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
24 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
25 * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
26 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
27 * PERFORMANCE OF THIS SOFTWARE.
29 * ========================================================================
33 * Developer: Kendall Bennett
35 * Description: This file includes subroutines to implement the decoding
36 * and emulation of all the x86 extended two-byte processor
39 ****************************************************************************/
43 /*----------------------------- Implementation ----------------------------*/
45 /****************************************************************************
47 op1 - Instruction op code
50 Handles illegal opcodes.
51 ****************************************************************************/
52 static void x86emuOp2_illegal_op(u8 op2
)
55 DECODE_PRINTF("ILLEGAL EXTENDED X86 OPCODE\n");
57 printf("%04x:%04x: %02X ILLEGAL EXTENDED X86 OPCODE!\n",
58 M
.x86
.R_CS
, M
.x86
.R_IP
-2, op2
);
63 /****************************************************************************
65 * Handles opcode 0x0f,0x01
66 * ****************************************************************************/
68 static void x86emuOp2_opc_01(u8 op2
)
75 FETCH_DECODE_MODRM(mod
, rh
, rl
);
78 case 4: // SMSW (Store Machine Status Word)
79 // Decode the mod byte to find the addressing
80 // Dummy implementation: Always returns 0x10 (initial value as per intel manual volume 3, figure 8-1)
81 #define SMSW_INITIAL_VALUE 0x10
82 DECODE_PRINTF("SMSW\t");
85 destoffset
= decode_rm00_address(rl
);
86 store_data_word(destoffset
, SMSW_INITIAL_VALUE
);
89 destoffset
= decode_rm01_address(rl
);
90 store_data_word(destoffset
, SMSW_INITIAL_VALUE
);
93 destoffset
= decode_rm10_address(rl
);
94 store_data_word(destoffset
, SMSW_INITIAL_VALUE
);
97 destreg
= DECODE_RM_WORD_REGISTER(rl
);
98 *destreg
= SMSW_INITIAL_VALUE
;
102 DECODE_CLEAR_SEGOVR();
106 DECODE_PRINTF("ILLEGAL EXTENDED X86 OPCODE IN 0F 01\n");
108 printf("%04x:%04x: %02X ILLEGAL EXTENDED X86 OPCODE!\n",
109 M
.x86
.R_CS
, M
.x86
.R_IP
-2, op2
);
117 /****************************************************************************
119 * Handles opcode 0x0f,0x08
120 * ****************************************************************************/
121 static void x86emuOp2_invd(u8 op2
)
124 DECODE_PRINTF("INVD\n");
126 DECODE_CLEAR_SEGOVR();
130 /****************************************************************************
132 * Handles opcode 0x0f,0x09
133 * ****************************************************************************/
134 static void x86emuOp2_wbinvd(u8 op2
)
137 DECODE_PRINTF("WBINVD\n");
139 DECODE_CLEAR_SEGOVR();
143 /****************************************************************************
145 * Handles opcode 0x0f,0x30
146 * ****************************************************************************/
147 static void x86emuOp2_wrmsr(u8 op2
)
149 /* dummy implementation, does nothing */
152 DECODE_PRINTF("WRMSR\n");
154 DECODE_CLEAR_SEGOVR();
158 /****************************************************************************
160 Handles opcode 0x0f,0x31
161 ****************************************************************************/
162 static void x86emuOp2_rdtsc(u8
X86EMU_UNUSED(op2
))
164 #ifdef __HAS_LONG_LONG__
165 static u64 counter
= 0;
167 static u32 counter
= 0;
172 /* read timestamp counter */
174 * Note that instead of actually trying to accurately measure this, we just
175 * increase the counter by a fixed amount every time we hit one of these
176 * instructions. Feel free to come up with a better method.
179 DECODE_PRINTF("RDTSC\n");
181 #ifdef __HAS_LONG_LONG__
182 M
.x86
.R_EAX
= counter
& 0xffffffff;
183 M
.x86
.R_EDX
= counter
>> 32;
185 M
.x86
.R_EAX
= counter
;
188 DECODE_CLEAR_SEGOVR();
192 /****************************************************************************
194 * Handles opcode 0x0f,0x32
195 * ****************************************************************************/
196 static void x86emuOp2_rdmsr(u8 op2
)
198 /* dummy implementation, always return 0 */
201 DECODE_PRINTF("RDMSR\n");
205 DECODE_CLEAR_SEGOVR();
209 #define xorl(a,b) (((a) && !(b)) || (!(a) && (b)))
211 /****************************************************************************
213 Handles opcode 0x0f,0x80-0x8F
214 ****************************************************************************/
215 int x86emu_check_jump_condition(u8 op
)
219 DECODE_PRINTF("JO\t");
220 return ACCESS_FLAG(F_OF
);
222 DECODE_PRINTF("JNO\t");
223 return !ACCESS_FLAG(F_OF
);
226 DECODE_PRINTF("JB\t");
227 return ACCESS_FLAG(F_CF
);
230 DECODE_PRINTF("JNB\t");
231 return !ACCESS_FLAG(F_CF
);
234 DECODE_PRINTF("JZ\t");
235 return ACCESS_FLAG(F_ZF
);
238 DECODE_PRINTF("JNZ\t");
239 return !ACCESS_FLAG(F_ZF
);
242 DECODE_PRINTF("JBE\t");
243 return ACCESS_FLAG(F_CF
) || ACCESS_FLAG(F_ZF
);
246 DECODE_PRINTF("JNBE\t");
247 return !(ACCESS_FLAG(F_CF
) || ACCESS_FLAG(F_ZF
));
250 DECODE_PRINTF("JS\t");
251 return ACCESS_FLAG(F_SF
);
254 DECODE_PRINTF("JNS\t");
255 return !ACCESS_FLAG(F_SF
);
258 DECODE_PRINTF("JP\t");
259 return ACCESS_FLAG(F_PF
);
262 DECODE_PRINTF("JNP\t");
263 return !ACCESS_FLAG(F_PF
);
266 DECODE_PRINTF("JL\t");
267 return xorl(ACCESS_FLAG(F_SF
), ACCESS_FLAG(F_OF
));
270 DECODE_PRINTF("JNL\t");
271 return !xorl(ACCESS_FLAG(F_SF
), ACCESS_FLAG(F_OF
));
274 DECODE_PRINTF("JLE\t");
275 return (xorl(ACCESS_FLAG(F_SF
), ACCESS_FLAG(F_OF
)) ||
279 DECODE_PRINTF("JNLE\t");
280 return !(xorl(ACCESS_FLAG(F_SF
), ACCESS_FLAG(F_OF
)) ||
285 static void x86emuOp2_long_jump(u8 op2
)
290 /* conditional jump to word offset. */
292 cond
= x86emu_check_jump_condition(op2
& 0xF);
293 target
= (s16
) fetch_word_imm();
294 target
+= (s16
) M
.x86
.R_IP
;
295 DECODE_PRINTF2("%04x\n", target
);
298 M
.x86
.R_IP
= (u16
)target
;
299 JMP_TRACE(M
.x86
.saved_cs
, M
.x86
.saved_ip
, M
.x86
.R_CS
, M
.x86
.R_IP
, " LONG COND ");
301 DECODE_CLEAR_SEGOVR();
305 /****************************************************************************
307 Handles opcode 0x0f,0xC8-0xCF
308 ****************************************************************************/
309 static s32
x86emu_bswap(s32 reg
)
311 // perform the byte swap
313 reg
= (temp
& 0xFF000000) >> 24 |
314 (temp
& 0xFF0000) >> 8 |
315 (temp
& 0xFF00) << 8 |
320 static void x86emuOp2_bswap(u8 op2
)
322 /* byte swap 32 bit register */
324 DECODE_PRINTF("BSWAP\t");
327 DECODE_PRINTF("EAX\n");
328 M
.x86
.R_EAX
= x86emu_bswap(M
.x86
.R_EAX
);
331 DECODE_PRINTF("ECX\n");
332 M
.x86
.R_ECX
= x86emu_bswap(M
.x86
.R_ECX
);
335 DECODE_PRINTF("EDX\n");
336 M
.x86
.R_EDX
= x86emu_bswap(M
.x86
.R_EDX
);
339 DECODE_PRINTF("EBX\n");
340 M
.x86
.R_EBX
= x86emu_bswap(M
.x86
.R_EBX
);
343 DECODE_PRINTF("ESP\n");
344 M
.x86
.R_ESP
= x86emu_bswap(M
.x86
.R_ESP
);
347 DECODE_PRINTF("EBP\n");
348 M
.x86
.R_EBP
= x86emu_bswap(M
.x86
.R_EBP
);
351 DECODE_PRINTF("ESI\n");
352 M
.x86
.R_ESI
= x86emu_bswap(M
.x86
.R_ESI
);
355 DECODE_PRINTF("EDI\n");
356 M
.x86
.R_EDI
= x86emu_bswap(M
.x86
.R_EDI
);
360 DECODE_CLEAR_SEGOVR();
364 /****************************************************************************
366 Handles opcode 0x0f,0x90-0x9F
367 ****************************************************************************/
368 static void x86emuOp2_set_byte(u8 op2
)
373 const char *X86EMU_DEBUG_ONLY(name
) = NULL
;
380 cond
= ACCESS_FLAG(F_OF
);
384 cond
= !ACCESS_FLAG(F_OF
);
388 cond
= ACCESS_FLAG(F_CF
);
392 cond
= !ACCESS_FLAG(F_CF
);
396 cond
= ACCESS_FLAG(F_ZF
);
400 cond
= !ACCESS_FLAG(F_ZF
);
404 cond
= ACCESS_FLAG(F_CF
) || ACCESS_FLAG(F_ZF
);
408 cond
= !(ACCESS_FLAG(F_CF
) || ACCESS_FLAG(F_ZF
));
412 cond
= ACCESS_FLAG(F_SF
);
416 cond
= !ACCESS_FLAG(F_SF
);
420 cond
= ACCESS_FLAG(F_PF
);
424 cond
= !ACCESS_FLAG(F_PF
);
428 cond
= xorl(ACCESS_FLAG(F_SF
), ACCESS_FLAG(F_OF
));
432 cond
= !xorl(ACCESS_FLAG(F_SF
), ACCESS_FLAG(F_OF
));
436 cond
= (xorl(ACCESS_FLAG(F_SF
), ACCESS_FLAG(F_OF
)) ||
441 cond
= !(xorl(ACCESS_FLAG(F_SF
), ACCESS_FLAG(F_OF
)) ||
446 FETCH_DECODE_MODRM(mod
, rh
, rl
);
448 destoffset
= decode_rmXX_address(mod
, rl
);
450 store_data_byte(destoffset
, cond
? 0x01 : 0x00);
451 } else { /* register to register */
452 destreg
= DECODE_RM_BYTE_REGISTER(rl
);
454 *destreg
= cond
? 0x01 : 0x00;
456 DECODE_CLEAR_SEGOVR();
460 /****************************************************************************
462 Handles opcode 0x0f,0xa0
463 ****************************************************************************/
464 static void x86emuOp2_push_FS(u8
X86EMU_UNUSED(op2
))
467 DECODE_PRINTF("PUSH\tFS\n");
469 push_word(M
.x86
.R_FS
);
470 DECODE_CLEAR_SEGOVR();
474 /****************************************************************************
476 Handles opcode 0x0f,0xa1
477 ****************************************************************************/
478 static void x86emuOp2_pop_FS(u8
X86EMU_UNUSED(op2
))
481 DECODE_PRINTF("POP\tFS\n");
483 M
.x86
.R_FS
= pop_word();
484 DECODE_CLEAR_SEGOVR();
488 /****************************************************************************
489 REMARKS: CPUID takes EAX/ECX as inputs, writes EAX/EBX/ECX/EDX as output
490 Handles opcode 0x0f,0xa2
491 ****************************************************************************/
492 static void x86emuOp2_cpuid(u8
X86EMU_UNUSED(op2
))
495 DECODE_PRINTF("CPUID\n");
498 DECODE_CLEAR_SEGOVR();
502 /****************************************************************************
504 Handles opcode 0x0f,0xa3
505 ****************************************************************************/
506 static void x86emuOp2_bt_R(u8
X86EMU_UNUSED(op2
))
513 DECODE_PRINTF("BT\t");
514 FETCH_DECODE_MODRM(mod
, rh
, rl
);
516 srcoffset
= decode_rmXX_address(mod
, rl
);
517 if (M
.x86
.mode
& SYSMODE_PREFIX_DATA
) {
522 shiftreg
= DECODE_RM_LONG_REGISTER(rh
);
524 bit
= *shiftreg
& 0x1F;
525 disp
= (s16
)*shiftreg
>> 5;
526 srcval
= fetch_data_long(srcoffset
+disp
);
527 CONDITIONAL_SET_FLAG(srcval
& (0x1 << bit
),F_CF
);
533 shiftreg
= DECODE_RM_WORD_REGISTER(rh
);
535 bit
= *shiftreg
& 0xF;
536 disp
= (s16
)*shiftreg
>> 4;
537 srcval
= fetch_data_word(srcoffset
+disp
);
538 CONDITIONAL_SET_FLAG(srcval
& (0x1 << bit
),F_CF
);
540 } else { /* register to register */
541 if (M
.x86
.mode
& SYSMODE_PREFIX_DATA
) {
542 u32
*srcreg
,*shiftreg
;
544 srcreg
= DECODE_RM_LONG_REGISTER(rl
);
546 shiftreg
= DECODE_RM_LONG_REGISTER(rh
);
548 bit
= *shiftreg
& 0x1F;
549 CONDITIONAL_SET_FLAG(*srcreg
& (0x1 << bit
),F_CF
);
551 u16
*srcreg
,*shiftreg
;
553 srcreg
= DECODE_RM_WORD_REGISTER(rl
);
555 shiftreg
= DECODE_RM_WORD_REGISTER(rh
);
557 bit
= *shiftreg
& 0xF;
558 CONDITIONAL_SET_FLAG(*srcreg
& (0x1 << bit
),F_CF
);
561 DECODE_CLEAR_SEGOVR();
565 /****************************************************************************
567 Handles opcode 0x0f,0xa4
568 ****************************************************************************/
569 static void x86emuOp2_shld_IMM(u8
X86EMU_UNUSED(op2
))
576 DECODE_PRINTF("SHLD\t");
577 FETCH_DECODE_MODRM(mod
, rh
, rl
);
579 destoffset
= decode_rmXX_address(mod
, rl
);
580 if (M
.x86
.mode
& SYSMODE_PREFIX_DATA
) {
585 shiftreg
= DECODE_RM_LONG_REGISTER(rh
);
587 shift
= fetch_byte_imm();
588 DECODE_PRINTF2("%d\n", shift
);
590 destval
= fetch_data_long(destoffset
);
591 destval
= shld_long(destval
,*shiftreg
,shift
);
592 store_data_long(destoffset
, destval
);
598 shiftreg
= DECODE_RM_WORD_REGISTER(rh
);
600 shift
= fetch_byte_imm();
601 DECODE_PRINTF2("%d\n", shift
);
603 destval
= fetch_data_word(destoffset
);
604 destval
= shld_word(destval
,*shiftreg
,shift
);
605 store_data_word(destoffset
, destval
);
607 } else { /* register to register */
608 if (M
.x86
.mode
& SYSMODE_PREFIX_DATA
) {
609 u32
*destreg
,*shiftreg
;
611 destreg
= DECODE_RM_LONG_REGISTER(rl
);
613 shiftreg
= DECODE_RM_LONG_REGISTER(rh
);
615 shift
= fetch_byte_imm();
616 DECODE_PRINTF2("%d\n", shift
);
618 *destreg
= shld_long(*destreg
,*shiftreg
,shift
);
620 u16
*destreg
,*shiftreg
;
622 destreg
= DECODE_RM_WORD_REGISTER(rl
);
624 shiftreg
= DECODE_RM_WORD_REGISTER(rh
);
626 shift
= fetch_byte_imm();
627 DECODE_PRINTF2("%d\n", shift
);
629 *destreg
= shld_word(*destreg
,*shiftreg
,shift
);
632 DECODE_CLEAR_SEGOVR();
636 /****************************************************************************
638 Handles opcode 0x0f,0xa5
639 ****************************************************************************/
640 static void x86emuOp2_shld_CL(u8
X86EMU_UNUSED(op2
))
646 DECODE_PRINTF("SHLD\t");
647 FETCH_DECODE_MODRM(mod
, rh
, rl
);
649 destoffset
= decode_rmXX_address(mod
, rl
);
650 if (M
.x86
.mode
& SYSMODE_PREFIX_DATA
) {
655 shiftreg
= DECODE_RM_LONG_REGISTER(rh
);
656 DECODE_PRINTF(",CL\n");
658 destval
= fetch_data_long(destoffset
);
659 destval
= shld_long(destval
,*shiftreg
,M
.x86
.R_CL
);
660 store_data_long(destoffset
, destval
);
666 shiftreg
= DECODE_RM_WORD_REGISTER(rh
);
667 DECODE_PRINTF(",CL\n");
669 destval
= fetch_data_word(destoffset
);
670 destval
= shld_word(destval
,*shiftreg
,M
.x86
.R_CL
);
671 store_data_word(destoffset
, destval
);
673 } else { /* register to register */
674 if (M
.x86
.mode
& SYSMODE_PREFIX_DATA
) {
675 u32
*destreg
,*shiftreg
;
677 destreg
= DECODE_RM_LONG_REGISTER(rl
);
679 shiftreg
= DECODE_RM_LONG_REGISTER(rh
);
680 DECODE_PRINTF(",CL\n");
682 *destreg
= shld_long(*destreg
,*shiftreg
,M
.x86
.R_CL
);
684 u16
*destreg
,*shiftreg
;
686 destreg
= DECODE_RM_WORD_REGISTER(rl
);
688 shiftreg
= DECODE_RM_WORD_REGISTER(rh
);
689 DECODE_PRINTF(",CL\n");
691 *destreg
= shld_word(*destreg
,*shiftreg
,M
.x86
.R_CL
);
694 DECODE_CLEAR_SEGOVR();
698 /****************************************************************************
700 Handles opcode 0x0f,0xa8
701 ****************************************************************************/
702 static void x86emuOp2_push_GS(u8
X86EMU_UNUSED(op2
))
705 DECODE_PRINTF("PUSH\tGS\n");
707 push_word(M
.x86
.R_GS
);
708 DECODE_CLEAR_SEGOVR();
712 /****************************************************************************
714 Handles opcode 0x0f,0xa9
715 ****************************************************************************/
716 static void x86emuOp2_pop_GS(u8
X86EMU_UNUSED(op2
))
719 DECODE_PRINTF("POP\tGS\n");
721 M
.x86
.R_GS
= pop_word();
722 DECODE_CLEAR_SEGOVR();
726 /****************************************************************************
728 Handles opcode 0x0f,0xab
729 ****************************************************************************/
730 static void x86emuOp2_bts_R(u8
X86EMU_UNUSED(op2
))
737 DECODE_PRINTF("BTS\t");
738 FETCH_DECODE_MODRM(mod
, rh
, rl
);
740 srcoffset
= decode_rmXX_address(mod
, rl
);
741 if (M
.x86
.mode
& SYSMODE_PREFIX_DATA
) {
746 shiftreg
= DECODE_RM_LONG_REGISTER(rh
);
748 bit
= *shiftreg
& 0x1F;
749 disp
= (s16
)*shiftreg
>> 5;
750 srcval
= fetch_data_long(srcoffset
+disp
);
752 CONDITIONAL_SET_FLAG(srcval
& mask
,F_CF
);
753 store_data_long(srcoffset
+disp
, srcval
| mask
);
759 shiftreg
= DECODE_RM_WORD_REGISTER(rh
);
761 bit
= *shiftreg
& 0xF;
762 disp
= (s16
)*shiftreg
>> 4;
763 srcval
= fetch_data_word(srcoffset
+disp
);
764 mask
= (u16
)(0x1 << bit
);
765 CONDITIONAL_SET_FLAG(srcval
& mask
,F_CF
);
766 store_data_word(srcoffset
+disp
, srcval
| mask
);
768 } else { /* register to register */
769 if (M
.x86
.mode
& SYSMODE_PREFIX_DATA
) {
770 u32
*srcreg
,*shiftreg
;
773 srcreg
= DECODE_RM_LONG_REGISTER(rl
);
775 shiftreg
= DECODE_RM_LONG_REGISTER(rh
);
777 bit
= *shiftreg
& 0x1F;
779 CONDITIONAL_SET_FLAG(*srcreg
& mask
,F_CF
);
782 u16
*srcreg
,*shiftreg
;
785 srcreg
= DECODE_RM_WORD_REGISTER(rl
);
787 shiftreg
= DECODE_RM_WORD_REGISTER(rh
);
789 bit
= *shiftreg
& 0xF;
790 mask
= (u16
)(0x1 << bit
);
791 CONDITIONAL_SET_FLAG(*srcreg
& mask
,F_CF
);
795 DECODE_CLEAR_SEGOVR();
799 /****************************************************************************
801 Handles opcode 0x0f,0xac
802 ****************************************************************************/
803 static void x86emuOp2_shrd_IMM(u8
X86EMU_UNUSED(op2
))
810 DECODE_PRINTF("SHLD\t");
811 FETCH_DECODE_MODRM(mod
, rh
, rl
);
813 destoffset
= decode_rmXX_address(mod
, rl
);
814 if (M
.x86
.mode
& SYSMODE_PREFIX_DATA
) {
819 shiftreg
= DECODE_RM_LONG_REGISTER(rh
);
821 shift
= fetch_byte_imm();
822 DECODE_PRINTF2("%d\n", shift
);
824 destval
= fetch_data_long(destoffset
);
825 destval
= shrd_long(destval
,*shiftreg
,shift
);
826 store_data_long(destoffset
, destval
);
832 shiftreg
= DECODE_RM_WORD_REGISTER(rh
);
834 shift
= fetch_byte_imm();
835 DECODE_PRINTF2("%d\n", shift
);
837 destval
= fetch_data_word(destoffset
);
838 destval
= shrd_word(destval
,*shiftreg
,shift
);
839 store_data_word(destoffset
, destval
);
841 } else { /* register to register */
842 if (M
.x86
.mode
& SYSMODE_PREFIX_DATA
) {
843 u32
*destreg
,*shiftreg
;
845 destreg
= DECODE_RM_LONG_REGISTER(rl
);
847 shiftreg
= DECODE_RM_LONG_REGISTER(rh
);
849 shift
= fetch_byte_imm();
850 DECODE_PRINTF2("%d\n", shift
);
852 *destreg
= shrd_long(*destreg
,*shiftreg
,shift
);
854 u16
*destreg
,*shiftreg
;
856 destreg
= DECODE_RM_WORD_REGISTER(rl
);
858 shiftreg
= DECODE_RM_WORD_REGISTER(rh
);
860 shift
= fetch_byte_imm();
861 DECODE_PRINTF2("%d\n", shift
);
863 *destreg
= shrd_word(*destreg
,*shiftreg
,shift
);
866 DECODE_CLEAR_SEGOVR();
870 /****************************************************************************
872 Handles opcode 0x0f,0xad
873 ****************************************************************************/
874 static void x86emuOp2_shrd_CL(u8
X86EMU_UNUSED(op2
))
880 DECODE_PRINTF("SHLD\t");
881 FETCH_DECODE_MODRM(mod
, rh
, rl
);
883 destoffset
= decode_rmXX_address(mod
, rl
);
885 if (M
.x86
.mode
& SYSMODE_PREFIX_DATA
) {
889 shiftreg
= DECODE_RM_LONG_REGISTER(rh
);
890 DECODE_PRINTF(",CL\n");
892 destval
= fetch_data_long(destoffset
);
893 destval
= shrd_long(destval
,*shiftreg
,M
.x86
.R_CL
);
894 store_data_long(destoffset
, destval
);
899 shiftreg
= DECODE_RM_WORD_REGISTER(rh
);
900 DECODE_PRINTF(",CL\n");
902 destval
= fetch_data_word(destoffset
);
903 destval
= shrd_word(destval
,*shiftreg
,M
.x86
.R_CL
);
904 store_data_word(destoffset
, destval
);
906 } else { /* register to register */
907 if (M
.x86
.mode
& SYSMODE_PREFIX_DATA
) {
908 u32
*destreg
,*shiftreg
;
910 destreg
= DECODE_RM_LONG_REGISTER(rl
);
912 shiftreg
= DECODE_RM_LONG_REGISTER(rh
);
913 DECODE_PRINTF(",CL\n");
915 *destreg
= shrd_long(*destreg
,*shiftreg
,M
.x86
.R_CL
);
917 u16
*destreg
,*shiftreg
;
919 destreg
= DECODE_RM_WORD_REGISTER(rl
);
921 shiftreg
= DECODE_RM_WORD_REGISTER(rh
);
922 DECODE_PRINTF(",CL\n");
924 *destreg
= shrd_word(*destreg
,*shiftreg
,M
.x86
.R_CL
);
927 DECODE_CLEAR_SEGOVR();
931 /****************************************************************************
933 Handles opcode 0x0f,0xaf
934 ****************************************************************************/
935 static void x86emuOp2_imul_R_RM(u8
X86EMU_UNUSED(op2
))
941 DECODE_PRINTF("IMUL\t");
942 FETCH_DECODE_MODRM(mod
, rh
, rl
);
944 if (M
.x86
.mode
& SYSMODE_PREFIX_DATA
) {
949 destreg
= DECODE_RM_LONG_REGISTER(rh
);
951 srcoffset
= decode_rmXX_address(mod
, rl
);
952 srcval
= fetch_data_long(srcoffset
);
954 imul_long_direct(&res_lo
,&res_hi
,(s32
)*destreg
,(s32
)srcval
);
962 *destreg
= (u32
)res_lo
;
968 destreg
= DECODE_RM_WORD_REGISTER(rh
);
970 srcoffset
= decode_rmXX_address(mod
, rl
);
971 srcval
= fetch_data_word(srcoffset
);
973 res
= (s16
)*destreg
* (s16
)srcval
;
983 } else { /* register to register */
984 if (M
.x86
.mode
& SYSMODE_PREFIX_DATA
) {
985 u32
*destreg
,*srcreg
;
988 destreg
= DECODE_RM_LONG_REGISTER(rh
);
990 srcreg
= DECODE_RM_LONG_REGISTER(rl
);
992 imul_long_direct(&res_lo
,&res_hi
,(s32
)*destreg
,(s32
)*srcreg
);
1000 *destreg
= (u32
)res_lo
;
1002 u16
*destreg
,*srcreg
;
1005 destreg
= DECODE_RM_WORD_REGISTER(rh
);
1007 srcreg
= DECODE_RM_WORD_REGISTER(rl
);
1008 res
= (s16
)*destreg
* (s16
)*srcreg
;
1016 *destreg
= (u16
)res
;
1019 DECODE_CLEAR_SEGOVR();
1023 /****************************************************************************
1025 Handles opcode 0x0f,0xb2
1026 ****************************************************************************/
1027 static void x86emuOp2_lss_R_IMM(u8
X86EMU_UNUSED(op2
))
1034 DECODE_PRINTF("LSS\t");
1035 FETCH_DECODE_MODRM(mod
, rh
, rl
);
1037 dstreg
= DECODE_RM_WORD_REGISTER(rh
);
1039 srcoffset
= decode_rmXX_address(mod
, rl
);
1040 DECODE_PRINTF("\n");
1042 *dstreg
= fetch_data_word(srcoffset
);
1043 M
.x86
.R_SS
= fetch_data_word(srcoffset
+ 2);
1044 } else { /* register to register */
1048 DECODE_CLEAR_SEGOVR();
1052 /****************************************************************************
1054 Handles opcode 0x0f,0xb3
1055 ****************************************************************************/
1056 static void x86emuOp2_btr_R(u8
X86EMU_UNUSED(op2
))
1063 DECODE_PRINTF("BTR\t");
1064 FETCH_DECODE_MODRM(mod
, rh
, rl
);
1066 srcoffset
= decode_rmXX_address(mod
, rl
);
1068 if (M
.x86
.mode
& SYSMODE_PREFIX_DATA
) {
1072 shiftreg
= DECODE_RM_LONG_REGISTER(rh
);
1074 bit
= *shiftreg
& 0x1F;
1075 disp
= (s16
)*shiftreg
>> 5;
1076 srcval
= fetch_data_long(srcoffset
+disp
);
1077 mask
= (0x1 << bit
);
1078 CONDITIONAL_SET_FLAG(srcval
& mask
,F_CF
);
1079 store_data_long(srcoffset
+disp
, srcval
& ~mask
);
1084 shiftreg
= DECODE_RM_WORD_REGISTER(rh
);
1086 bit
= *shiftreg
& 0xF;
1087 disp
= (s16
)*shiftreg
>> 4;
1088 srcval
= fetch_data_word(srcoffset
+disp
);
1089 mask
= (u16
)(0x1 << bit
);
1090 CONDITIONAL_SET_FLAG(srcval
& mask
,F_CF
);
1091 store_data_word(srcoffset
+disp
, (u16
)(srcval
& ~mask
));
1093 } else { /* register to register */
1094 if (M
.x86
.mode
& SYSMODE_PREFIX_DATA
) {
1095 u32
*srcreg
,*shiftreg
;
1098 srcreg
= DECODE_RM_LONG_REGISTER(rl
);
1100 shiftreg
= DECODE_RM_LONG_REGISTER(rh
);
1102 bit
= *shiftreg
& 0x1F;
1103 mask
= (0x1 << bit
);
1104 CONDITIONAL_SET_FLAG(*srcreg
& mask
,F_CF
);
1107 u16
*srcreg
,*shiftreg
;
1110 srcreg
= DECODE_RM_WORD_REGISTER(rl
);
1112 shiftreg
= DECODE_RM_WORD_REGISTER(rh
);
1114 bit
= *shiftreg
& 0xF;
1115 mask
= (u16
)(0x1 << bit
);
1116 CONDITIONAL_SET_FLAG(*srcreg
& mask
,F_CF
);
1120 DECODE_CLEAR_SEGOVR();
1124 /****************************************************************************
1126 Handles opcode 0x0f,0xb4
1127 ****************************************************************************/
1128 static void x86emuOp2_lfs_R_IMM(u8
X86EMU_UNUSED(op2
))
1135 DECODE_PRINTF("LFS\t");
1136 FETCH_DECODE_MODRM(mod
, rh
, rl
);
1138 dstreg
= DECODE_RM_WORD_REGISTER(rh
);
1140 srcoffset
= decode_rmXX_address(mod
, rl
);
1141 DECODE_PRINTF("\n");
1143 *dstreg
= fetch_data_word(srcoffset
);
1144 M
.x86
.R_FS
= fetch_data_word(srcoffset
+ 2);
1145 } else { /* register to register */
1149 DECODE_CLEAR_SEGOVR();
1153 /****************************************************************************
1155 Handles opcode 0x0f,0xb5
1156 ****************************************************************************/
1157 static void x86emuOp2_lgs_R_IMM(u8
X86EMU_UNUSED(op2
))
1164 DECODE_PRINTF("LGS\t");
1165 FETCH_DECODE_MODRM(mod
, rh
, rl
);
1167 dstreg
= DECODE_RM_WORD_REGISTER(rh
);
1169 srcoffset
= decode_rmXX_address(mod
, rl
);
1170 DECODE_PRINTF("\n");
1172 *dstreg
= fetch_data_word(srcoffset
);
1173 M
.x86
.R_GS
= fetch_data_word(srcoffset
+ 2);
1174 } else { /* register to register */
1178 DECODE_CLEAR_SEGOVR();
1182 /****************************************************************************
1184 Handles opcode 0x0f,0xb6
1185 ****************************************************************************/
1186 static void x86emuOp2_movzx_byte_R_RM(u8
X86EMU_UNUSED(op2
))
1192 DECODE_PRINTF("MOVZX\t");
1193 FETCH_DECODE_MODRM(mod
, rh
, rl
);
1195 if (M
.x86
.mode
& SYSMODE_PREFIX_DATA
) {
1199 destreg
= DECODE_RM_LONG_REGISTER(rh
);
1201 srcoffset
= decode_rmXX_address(mod
, rl
);
1202 srcval
= fetch_data_byte(srcoffset
);
1203 DECODE_PRINTF("\n");
1210 destreg
= DECODE_RM_WORD_REGISTER(rh
);
1212 srcoffset
= decode_rmXX_address(mod
, rl
);
1213 srcval
= fetch_data_byte(srcoffset
);
1214 DECODE_PRINTF("\n");
1218 } else { /* register to register */
1219 if (M
.x86
.mode
& SYSMODE_PREFIX_DATA
) {
1223 destreg
= DECODE_RM_LONG_REGISTER(rh
);
1225 srcreg
= DECODE_RM_BYTE_REGISTER(rl
);
1226 DECODE_PRINTF("\n");
1233 destreg
= DECODE_RM_WORD_REGISTER(rh
);
1235 srcreg
= DECODE_RM_BYTE_REGISTER(rl
);
1236 DECODE_PRINTF("\n");
1241 DECODE_CLEAR_SEGOVR();
1245 /****************************************************************************
1247 Handles opcode 0x0f,0xb7
1248 ****************************************************************************/
1249 static void x86emuOp2_movzx_word_R_RM(u8
X86EMU_UNUSED(op2
))
1258 DECODE_PRINTF("MOVZX\t");
1259 FETCH_DECODE_MODRM(mod
, rh
, rl
);
1261 destreg
= DECODE_RM_LONG_REGISTER(rh
);
1263 srcoffset
= decode_rmXX_address(mod
, rl
);
1264 srcval
= fetch_data_word(srcoffset
);
1265 DECODE_PRINTF("\n");
1268 } else { /* register to register */
1269 destreg
= DECODE_RM_LONG_REGISTER(rh
);
1271 srcreg
= DECODE_RM_WORD_REGISTER(rl
);
1272 DECODE_PRINTF("\n");
1276 DECODE_CLEAR_SEGOVR();
1280 /****************************************************************************
1282 Handles opcode 0x0f,0xba
1283 ****************************************************************************/
1284 static void x86emuOp2_btX_I(u8
X86EMU_UNUSED(op2
))
1292 FETCH_DECODE_MODRM(mod
, rh
, rl
);
1295 DECODE_PRINTF("BT\t");
1298 DECODE_PRINTF("BTS\t");
1301 DECODE_PRINTF("BTR\t");
1304 DECODE_PRINTF("BTC\t");
1307 DECODE_PRINTF("ILLEGAL EXTENDED X86 OPCODE\n");
1309 printf("%04x:%04x: %02X%02X ILLEGAL EXTENDED X86 OPCODE EXTENSION!\n",
1310 M
.x86
.R_CS
, M
.x86
.R_IP
-3,op2
, (mod
<<6)|(rh
<<3)|rl
);
1315 srcoffset
= decode_rmXX_address(mod
, rl
);
1316 shift
= fetch_byte_imm();
1317 DECODE_PRINTF2(",%d\n", shift
);
1320 if (M
.x86
.mode
& SYSMODE_PREFIX_DATA
) {
1324 srcval
= fetch_data_long(srcoffset
);
1325 mask
= (0x1 << bit
);
1326 CONDITIONAL_SET_FLAG(srcval
& mask
,F_CF
);
1329 store_data_long(srcoffset
, srcval
| mask
);
1332 store_data_long(srcoffset
, srcval
& ~mask
);
1335 store_data_long(srcoffset
, srcval
^ mask
);
1344 srcval
= fetch_data_word(srcoffset
);
1345 mask
= (0x1 << bit
);
1346 CONDITIONAL_SET_FLAG(srcval
& mask
,F_CF
);
1349 store_data_word(srcoffset
, srcval
| mask
);
1352 store_data_word(srcoffset
, srcval
& ~mask
);
1355 store_data_word(srcoffset
, srcval
^ mask
);
1361 } else { /* register to register */
1362 if (M
.x86
.mode
& SYSMODE_PREFIX_DATA
) {
1366 srcreg
= DECODE_RM_LONG_REGISTER(rl
);
1367 shift
= fetch_byte_imm();
1368 DECODE_PRINTF2(",%d\n", shift
);
1371 mask
= (0x1 << bit
);
1372 CONDITIONAL_SET_FLAG(*srcreg
& mask
,F_CF
);
1390 srcreg
= DECODE_RM_WORD_REGISTER(rl
);
1391 shift
= fetch_byte_imm();
1392 DECODE_PRINTF2(",%d\n", shift
);
1395 mask
= (0x1 << bit
);
1396 CONDITIONAL_SET_FLAG(*srcreg
& mask
,F_CF
);
1412 DECODE_CLEAR_SEGOVR();
1416 /****************************************************************************
1418 Handles opcode 0x0f,0xbb
1419 ****************************************************************************/
1420 static void x86emuOp2_btc_R(u8
X86EMU_UNUSED(op2
))
1427 DECODE_PRINTF("BTC\t");
1428 FETCH_DECODE_MODRM(mod
, rh
, rl
);
1430 srcoffset
= decode_rmXX_address(mod
, rl
);
1432 if (M
.x86
.mode
& SYSMODE_PREFIX_DATA
) {
1436 shiftreg
= DECODE_RM_LONG_REGISTER(rh
);
1438 bit
= *shiftreg
& 0x1F;
1439 disp
= (s16
)*shiftreg
>> 5;
1440 srcval
= fetch_data_long(srcoffset
+disp
);
1441 mask
= (0x1 << bit
);
1442 CONDITIONAL_SET_FLAG(srcval
& mask
,F_CF
);
1443 store_data_long(srcoffset
+disp
, srcval
^ mask
);
1448 shiftreg
= DECODE_RM_WORD_REGISTER(rh
);
1450 bit
= *shiftreg
& 0xF;
1451 disp
= (s16
)*shiftreg
>> 4;
1452 srcval
= fetch_data_word(srcoffset
+disp
);
1453 mask
= (u16
)(0x1 << bit
);
1454 CONDITIONAL_SET_FLAG(srcval
& mask
,F_CF
);
1455 store_data_word(srcoffset
+disp
, (u16
)(srcval
^ mask
));
1457 } else { /* register to register */
1458 if (M
.x86
.mode
& SYSMODE_PREFIX_DATA
) {
1459 u32
*srcreg
,*shiftreg
;
1462 srcreg
= DECODE_RM_LONG_REGISTER(rl
);
1464 shiftreg
= DECODE_RM_LONG_REGISTER(rh
);
1466 bit
= *shiftreg
& 0x1F;
1467 mask
= (0x1 << bit
);
1468 CONDITIONAL_SET_FLAG(*srcreg
& mask
,F_CF
);
1471 u16
*srcreg
,*shiftreg
;
1474 srcreg
= DECODE_RM_WORD_REGISTER(rl
);
1476 shiftreg
= DECODE_RM_WORD_REGISTER(rh
);
1478 bit
= *shiftreg
& 0xF;
1479 mask
= (u16
)(0x1 << bit
);
1480 CONDITIONAL_SET_FLAG(*srcreg
& mask
,F_CF
);
1484 DECODE_CLEAR_SEGOVR();
1488 /****************************************************************************
1490 Handles opcode 0x0f,0xbc
1491 ****************************************************************************/
1492 static void x86emuOp2_bsf(u8
X86EMU_UNUSED(op2
))
1498 DECODE_PRINTF("BSF\t");
1499 FETCH_DECODE_MODRM(mod
, rh
, rl
);
1501 srcoffset
= decode_rmXX_address(mod
, rl
);
1503 if (M
.x86
.mode
& SYSMODE_PREFIX_DATA
) {
1504 u32 srcval
, *dstreg
;
1506 dstreg
= DECODE_RM_LONG_REGISTER(rh
);
1508 srcval
= fetch_data_long(srcoffset
);
1509 CONDITIONAL_SET_FLAG(srcval
== 0, F_ZF
);
1510 for (*dstreg
= 0; *dstreg
< 32; (*dstreg
)++)
1511 if ((srcval
>> *dstreg
) & 1) break;
1513 u16 srcval
, *dstreg
;
1515 dstreg
= DECODE_RM_WORD_REGISTER(rh
);
1517 srcval
= fetch_data_word(srcoffset
);
1518 CONDITIONAL_SET_FLAG(srcval
== 0, F_ZF
);
1519 for (*dstreg
= 0; *dstreg
< 16; (*dstreg
)++)
1520 if ((srcval
>> *dstreg
) & 1) break;
1522 } else { /* register to register */
1523 if (M
.x86
.mode
& SYSMODE_PREFIX_DATA
) {
1524 u32 srcval
, *dstreg
;
1526 srcval
= *DECODE_RM_LONG_REGISTER(rl
);
1528 dstreg
= DECODE_RM_LONG_REGISTER(rh
);
1530 CONDITIONAL_SET_FLAG(srcval
== 0, F_ZF
);
1531 for (*dstreg
= 0; *dstreg
< 32; (*dstreg
)++)
1532 if ((srcval
>> *dstreg
) & 1) break;
1534 u16 srcval
, *dstreg
;
1536 srcval
= *DECODE_RM_WORD_REGISTER(rl
);
1538 dstreg
= DECODE_RM_WORD_REGISTER(rh
);
1540 CONDITIONAL_SET_FLAG(srcval
== 0, F_ZF
);
1541 for (*dstreg
= 0; *dstreg
< 16; (*dstreg
)++)
1542 if ((srcval
>> *dstreg
) & 1) break;
1545 DECODE_CLEAR_SEGOVR();
1549 /****************************************************************************
1551 Handles opcode 0x0f,0xbd
1552 ****************************************************************************/
1553 static void x86emuOp2_bsr(u8
X86EMU_UNUSED(op2
))
1559 DECODE_PRINTF("BSR\t");
1560 FETCH_DECODE_MODRM(mod
, rh
, rl
);
1562 srcoffset
= decode_rmXX_address(mod
, rl
);
1564 if (M
.x86
.mode
& SYSMODE_PREFIX_DATA
) {
1565 u32 srcval
, *dstreg
;
1567 dstreg
= DECODE_RM_LONG_REGISTER(rh
);
1569 srcval
= fetch_data_long(srcoffset
);
1570 CONDITIONAL_SET_FLAG(srcval
== 0, F_ZF
);
1571 for (*dstreg
= 31; *dstreg
> 0; (*dstreg
)--)
1572 if ((srcval
>> *dstreg
) & 1) break;
1574 u16 srcval
, *dstreg
;
1576 dstreg
= DECODE_RM_WORD_REGISTER(rh
);
1578 srcval
= fetch_data_word(srcoffset
);
1579 CONDITIONAL_SET_FLAG(srcval
== 0, F_ZF
);
1580 for (*dstreg
= 15; *dstreg
> 0; (*dstreg
)--)
1581 if ((srcval
>> *dstreg
) & 1) break;
1583 } else { /* register to register */
1584 if (M
.x86
.mode
& SYSMODE_PREFIX_DATA
) {
1585 u32 srcval
, *dstreg
;
1587 srcval
= *DECODE_RM_LONG_REGISTER(rl
);
1589 dstreg
= DECODE_RM_LONG_REGISTER(rh
);
1591 CONDITIONAL_SET_FLAG(srcval
== 0, F_ZF
);
1592 for (*dstreg
= 31; *dstreg
> 0; (*dstreg
)--)
1593 if ((srcval
>> *dstreg
) & 1) break;
1595 u16 srcval
, *dstreg
;
1597 srcval
= *DECODE_RM_WORD_REGISTER(rl
);
1599 dstreg
= DECODE_RM_WORD_REGISTER(rh
);
1601 CONDITIONAL_SET_FLAG(srcval
== 0, F_ZF
);
1602 for (*dstreg
= 15; *dstreg
> 0; (*dstreg
)--)
1603 if ((srcval
>> *dstreg
) & 1) break;
1606 DECODE_CLEAR_SEGOVR();
1610 /****************************************************************************
1612 Handles opcode 0x0f,0xbe
1613 ****************************************************************************/
1614 static void x86emuOp2_movsx_byte_R_RM(u8
X86EMU_UNUSED(op2
))
1620 DECODE_PRINTF("MOVSX\t");
1621 FETCH_DECODE_MODRM(mod
, rh
, rl
);
1623 if (M
.x86
.mode
& SYSMODE_PREFIX_DATA
) {
1627 destreg
= DECODE_RM_LONG_REGISTER(rh
);
1629 srcoffset
= decode_rmXX_address(mod
, rl
);
1630 srcval
= (s32
)((s8
)fetch_data_byte(srcoffset
));
1631 DECODE_PRINTF("\n");
1638 destreg
= DECODE_RM_WORD_REGISTER(rh
);
1640 srcoffset
= decode_rmXX_address(mod
, rl
);
1641 srcval
= (s16
)((s8
)fetch_data_byte(srcoffset
));
1642 DECODE_PRINTF("\n");
1646 } else { /* register to register */
1647 if (M
.x86
.mode
& SYSMODE_PREFIX_DATA
) {
1651 destreg
= DECODE_RM_LONG_REGISTER(rh
);
1653 srcreg
= DECODE_RM_BYTE_REGISTER(rl
);
1654 DECODE_PRINTF("\n");
1656 *destreg
= (s32
)((s8
)*srcreg
);
1661 destreg
= DECODE_RM_WORD_REGISTER(rh
);
1663 srcreg
= DECODE_RM_BYTE_REGISTER(rl
);
1664 DECODE_PRINTF("\n");
1666 *destreg
= (s16
)((s8
)*srcreg
);
1669 DECODE_CLEAR_SEGOVR();
1673 /****************************************************************************
1675 Handles opcode 0x0f,0xbf
1676 ****************************************************************************/
1677 static void x86emuOp2_movsx_word_R_RM(u8
X86EMU_UNUSED(op2
))
1686 DECODE_PRINTF("MOVSX\t");
1687 FETCH_DECODE_MODRM(mod
, rh
, rl
);
1689 destreg
= DECODE_RM_LONG_REGISTER(rh
);
1691 srcoffset
= decode_rmXX_address(mod
, rl
);
1692 srcval
= (s32
)((s16
)fetch_data_word(srcoffset
));
1693 DECODE_PRINTF("\n");
1696 } else { /* register to register */
1697 destreg
= DECODE_RM_LONG_REGISTER(rh
);
1699 srcreg
= DECODE_RM_WORD_REGISTER(rl
);
1700 DECODE_PRINTF("\n");
1702 *destreg
= (s32
)((s16
)*srcreg
);
1704 DECODE_CLEAR_SEGOVR();
1708 /***************************************************************************
1709 * Double byte operation code table:
1710 **************************************************************************/
1711 void (*x86emu_optab2
[256])(u8
) =
1713 /* 0x00 */ x86emuOp2_illegal_op
, /* Group F (ring 0 PM) */
1714 /* 0x01 */ x86emuOp2_opc_01
, /* Group G (ring 0 PM) */
1715 /* 0x02 */ x86emuOp2_illegal_op
, /* lar (ring 0 PM) */
1716 /* 0x03 */ x86emuOp2_illegal_op
, /* lsl (ring 0 PM) */
1717 /* 0x04 */ x86emuOp2_illegal_op
,
1718 /* 0x05 */ x86emuOp2_illegal_op
, /* loadall (undocumented) */
1719 /* 0x06 */ x86emuOp2_illegal_op
, /* clts (ring 0 PM) */
1720 /* 0x07 */ x86emuOp2_illegal_op
, /* loadall (undocumented) */
1721 /* 0x08 */ x86emuOp2_invd
, /* invd (ring 0 PM) */
1722 /* 0x09 */ x86emuOp2_wbinvd
, /* wbinvd (ring 0 PM) */
1723 /* 0x0a */ x86emuOp2_illegal_op
,
1724 /* 0x0b */ x86emuOp2_illegal_op
,
1725 /* 0x0c */ x86emuOp2_illegal_op
,
1726 /* 0x0d */ x86emuOp2_illegal_op
,
1727 /* 0x0e */ x86emuOp2_illegal_op
,
1728 /* 0x0f */ x86emuOp2_illegal_op
,
1730 /* 0x10 */ x86emuOp2_illegal_op
,
1731 /* 0x11 */ x86emuOp2_illegal_op
,
1732 /* 0x12 */ x86emuOp2_illegal_op
,
1733 /* 0x13 */ x86emuOp2_illegal_op
,
1734 /* 0x14 */ x86emuOp2_illegal_op
,
1735 /* 0x15 */ x86emuOp2_illegal_op
,
1736 /* 0x16 */ x86emuOp2_illegal_op
,
1737 /* 0x17 */ x86emuOp2_illegal_op
,
1738 /* 0x18 */ x86emuOp2_illegal_op
,
1739 /* 0x19 */ x86emuOp2_illegal_op
,
1740 /* 0x1a */ x86emuOp2_illegal_op
,
1741 /* 0x1b */ x86emuOp2_illegal_op
,
1742 /* 0x1c */ x86emuOp2_illegal_op
,
1743 /* 0x1d */ x86emuOp2_illegal_op
,
1744 /* 0x1e */ x86emuOp2_illegal_op
,
1745 /* 0x1f */ x86emuOp2_illegal_op
,
1747 /* 0x20 */ x86emuOp2_illegal_op
, /* mov reg32,creg (ring 0 PM) */
1748 /* 0x21 */ x86emuOp2_illegal_op
, /* mov reg32,dreg (ring 0 PM) */
1749 /* 0x22 */ x86emuOp2_illegal_op
, /* mov creg,reg32 (ring 0 PM) */
1750 /* 0x23 */ x86emuOp2_illegal_op
, /* mov dreg,reg32 (ring 0 PM) */
1751 /* 0x24 */ x86emuOp2_illegal_op
, /* mov reg32,treg (ring 0 PM) */
1752 /* 0x25 */ x86emuOp2_illegal_op
,
1753 /* 0x26 */ x86emuOp2_illegal_op
, /* mov treg,reg32 (ring 0 PM) */
1754 /* 0x27 */ x86emuOp2_illegal_op
,
1755 /* 0x28 */ x86emuOp2_illegal_op
,
1756 /* 0x29 */ x86emuOp2_illegal_op
,
1757 /* 0x2a */ x86emuOp2_illegal_op
,
1758 /* 0x2b */ x86emuOp2_illegal_op
,
1759 /* 0x2c */ x86emuOp2_illegal_op
,
1760 /* 0x2d */ x86emuOp2_illegal_op
,
1761 /* 0x2e */ x86emuOp2_illegal_op
,
1762 /* 0x2f */ x86emuOp2_illegal_op
,
1764 /* 0x30 */ x86emuOp2_wrmsr
,
1765 /* 0x31 */ x86emuOp2_rdtsc
,
1766 /* 0x32 */ x86emuOp2_rdmsr
,
1767 /* 0x33 */ x86emuOp2_illegal_op
,
1768 /* 0x34 */ x86emuOp2_illegal_op
,
1769 /* 0x35 */ x86emuOp2_illegal_op
,
1770 /* 0x36 */ x86emuOp2_illegal_op
,
1771 /* 0x37 */ x86emuOp2_illegal_op
,
1772 /* 0x38 */ x86emuOp2_illegal_op
,
1773 /* 0x39 */ x86emuOp2_illegal_op
,
1774 /* 0x3a */ x86emuOp2_illegal_op
,
1775 /* 0x3b */ x86emuOp2_illegal_op
,
1776 /* 0x3c */ x86emuOp2_illegal_op
,
1777 /* 0x3d */ x86emuOp2_illegal_op
,
1778 /* 0x3e */ x86emuOp2_illegal_op
,
1779 /* 0x3f */ x86emuOp2_illegal_op
,
1781 /* 0x40 */ x86emuOp2_illegal_op
,
1782 /* 0x41 */ x86emuOp2_illegal_op
,
1783 /* 0x42 */ x86emuOp2_illegal_op
,
1784 /* 0x43 */ x86emuOp2_illegal_op
,
1785 /* 0x44 */ x86emuOp2_illegal_op
,
1786 /* 0x45 */ x86emuOp2_illegal_op
,
1787 /* 0x46 */ x86emuOp2_illegal_op
,
1788 /* 0x47 */ x86emuOp2_illegal_op
,
1789 /* 0x48 */ x86emuOp2_illegal_op
,
1790 /* 0x49 */ x86emuOp2_illegal_op
,
1791 /* 0x4a */ x86emuOp2_illegal_op
,
1792 /* 0x4b */ x86emuOp2_illegal_op
,
1793 /* 0x4c */ x86emuOp2_illegal_op
,
1794 /* 0x4d */ x86emuOp2_illegal_op
,
1795 /* 0x4e */ x86emuOp2_illegal_op
,
1796 /* 0x4f */ x86emuOp2_illegal_op
,
1798 /* 0x50 */ x86emuOp2_illegal_op
,
1799 /* 0x51 */ x86emuOp2_illegal_op
,
1800 /* 0x52 */ x86emuOp2_illegal_op
,
1801 /* 0x53 */ x86emuOp2_illegal_op
,
1802 /* 0x54 */ x86emuOp2_illegal_op
,
1803 /* 0x55 */ x86emuOp2_illegal_op
,
1804 /* 0x56 */ x86emuOp2_illegal_op
,
1805 /* 0x57 */ x86emuOp2_illegal_op
,
1806 /* 0x58 */ x86emuOp2_illegal_op
,
1807 /* 0x59 */ x86emuOp2_illegal_op
,
1808 /* 0x5a */ x86emuOp2_illegal_op
,
1809 /* 0x5b */ x86emuOp2_illegal_op
,
1810 /* 0x5c */ x86emuOp2_illegal_op
,
1811 /* 0x5d */ x86emuOp2_illegal_op
,
1812 /* 0x5e */ x86emuOp2_illegal_op
,
1813 /* 0x5f */ x86emuOp2_illegal_op
,
1815 /* 0x60 */ x86emuOp2_illegal_op
,
1816 /* 0x61 */ x86emuOp2_illegal_op
,
1817 /* 0x62 */ x86emuOp2_illegal_op
,
1818 /* 0x63 */ x86emuOp2_illegal_op
,
1819 /* 0x64 */ x86emuOp2_illegal_op
,
1820 /* 0x65 */ x86emuOp2_illegal_op
,
1821 /* 0x66 */ x86emuOp2_illegal_op
,
1822 /* 0x67 */ x86emuOp2_illegal_op
,
1823 /* 0x68 */ x86emuOp2_illegal_op
,
1824 /* 0x69 */ x86emuOp2_illegal_op
,
1825 /* 0x6a */ x86emuOp2_illegal_op
,
1826 /* 0x6b */ x86emuOp2_illegal_op
,
1827 /* 0x6c */ x86emuOp2_illegal_op
,
1828 /* 0x6d */ x86emuOp2_illegal_op
,
1829 /* 0x6e */ x86emuOp2_illegal_op
,
1830 /* 0x6f */ x86emuOp2_illegal_op
,
1832 /* 0x70 */ x86emuOp2_illegal_op
,
1833 /* 0x71 */ x86emuOp2_illegal_op
,
1834 /* 0x72 */ x86emuOp2_illegal_op
,
1835 /* 0x73 */ x86emuOp2_illegal_op
,
1836 /* 0x74 */ x86emuOp2_illegal_op
,
1837 /* 0x75 */ x86emuOp2_illegal_op
,
1838 /* 0x76 */ x86emuOp2_illegal_op
,
1839 /* 0x77 */ x86emuOp2_illegal_op
,
1840 /* 0x78 */ x86emuOp2_illegal_op
,
1841 /* 0x79 */ x86emuOp2_illegal_op
,
1842 /* 0x7a */ x86emuOp2_illegal_op
,
1843 /* 0x7b */ x86emuOp2_illegal_op
,
1844 /* 0x7c */ x86emuOp2_illegal_op
,
1845 /* 0x7d */ x86emuOp2_illegal_op
,
1846 /* 0x7e */ x86emuOp2_illegal_op
,
1847 /* 0x7f */ x86emuOp2_illegal_op
,
1849 /* 0x80 */ x86emuOp2_long_jump
,
1850 /* 0x81 */ x86emuOp2_long_jump
,
1851 /* 0x82 */ x86emuOp2_long_jump
,
1852 /* 0x83 */ x86emuOp2_long_jump
,
1853 /* 0x84 */ x86emuOp2_long_jump
,
1854 /* 0x85 */ x86emuOp2_long_jump
,
1855 /* 0x86 */ x86emuOp2_long_jump
,
1856 /* 0x87 */ x86emuOp2_long_jump
,
1857 /* 0x88 */ x86emuOp2_long_jump
,
1858 /* 0x89 */ x86emuOp2_long_jump
,
1859 /* 0x8a */ x86emuOp2_long_jump
,
1860 /* 0x8b */ x86emuOp2_long_jump
,
1861 /* 0x8c */ x86emuOp2_long_jump
,
1862 /* 0x8d */ x86emuOp2_long_jump
,
1863 /* 0x8e */ x86emuOp2_long_jump
,
1864 /* 0x8f */ x86emuOp2_long_jump
,
1866 /* 0x90 */ x86emuOp2_set_byte
,
1867 /* 0x91 */ x86emuOp2_set_byte
,
1868 /* 0x92 */ x86emuOp2_set_byte
,
1869 /* 0x93 */ x86emuOp2_set_byte
,
1870 /* 0x94 */ x86emuOp2_set_byte
,
1871 /* 0x95 */ x86emuOp2_set_byte
,
1872 /* 0x96 */ x86emuOp2_set_byte
,
1873 /* 0x97 */ x86emuOp2_set_byte
,
1874 /* 0x98 */ x86emuOp2_set_byte
,
1875 /* 0x99 */ x86emuOp2_set_byte
,
1876 /* 0x9a */ x86emuOp2_set_byte
,
1877 /* 0x9b */ x86emuOp2_set_byte
,
1878 /* 0x9c */ x86emuOp2_set_byte
,
1879 /* 0x9d */ x86emuOp2_set_byte
,
1880 /* 0x9e */ x86emuOp2_set_byte
,
1881 /* 0x9f */ x86emuOp2_set_byte
,
1883 /* 0xa0 */ x86emuOp2_push_FS
,
1884 /* 0xa1 */ x86emuOp2_pop_FS
,
1885 /* 0xa2 */ x86emuOp2_cpuid
,
1886 /* 0xa3 */ x86emuOp2_bt_R
,
1887 /* 0xa4 */ x86emuOp2_shld_IMM
,
1888 /* 0xa5 */ x86emuOp2_shld_CL
,
1889 /* 0xa6 */ x86emuOp2_illegal_op
,
1890 /* 0xa7 */ x86emuOp2_illegal_op
,
1891 /* 0xa8 */ x86emuOp2_push_GS
,
1892 /* 0xa9 */ x86emuOp2_pop_GS
,
1893 /* 0xaa */ x86emuOp2_illegal_op
,
1894 /* 0xab */ x86emuOp2_bts_R
,
1895 /* 0xac */ x86emuOp2_shrd_IMM
,
1896 /* 0xad */ x86emuOp2_shrd_CL
,
1897 /* 0xae */ x86emuOp2_illegal_op
,
1898 /* 0xaf */ x86emuOp2_imul_R_RM
,
1900 /* 0xb0 */ x86emuOp2_illegal_op
, /* TODO: cmpxchg */
1901 /* 0xb1 */ x86emuOp2_illegal_op
, /* TODO: cmpxchg */
1902 /* 0xb2 */ x86emuOp2_lss_R_IMM
,
1903 /* 0xb3 */ x86emuOp2_btr_R
,
1904 /* 0xb4 */ x86emuOp2_lfs_R_IMM
,
1905 /* 0xb5 */ x86emuOp2_lgs_R_IMM
,
1906 /* 0xb6 */ x86emuOp2_movzx_byte_R_RM
,
1907 /* 0xb7 */ x86emuOp2_movzx_word_R_RM
,
1908 /* 0xb8 */ x86emuOp2_illegal_op
,
1909 /* 0xb9 */ x86emuOp2_illegal_op
,
1910 /* 0xba */ x86emuOp2_btX_I
,
1911 /* 0xbb */ x86emuOp2_btc_R
,
1912 /* 0xbc */ x86emuOp2_bsf
,
1913 /* 0xbd */ x86emuOp2_bsr
,
1914 /* 0xbe */ x86emuOp2_movsx_byte_R_RM
,
1915 /* 0xbf */ x86emuOp2_movsx_word_R_RM
,
1917 /* 0xc0 */ x86emuOp2_illegal_op
, /* TODO: xadd */
1918 /* 0xc1 */ x86emuOp2_illegal_op
, /* TODO: xadd */
1919 /* 0xc2 */ x86emuOp2_illegal_op
,
1920 /* 0xc3 */ x86emuOp2_illegal_op
,
1921 /* 0xc4 */ x86emuOp2_illegal_op
,
1922 /* 0xc5 */ x86emuOp2_illegal_op
,
1923 /* 0xc6 */ x86emuOp2_illegal_op
,
1924 /* 0xc7 */ x86emuOp2_illegal_op
,
1925 /* 0xc8 */ x86emuOp2_bswap
,
1926 /* 0xc9 */ x86emuOp2_bswap
,
1927 /* 0xca */ x86emuOp2_bswap
,
1928 /* 0xcb */ x86emuOp2_bswap
,
1929 /* 0xcc */ x86emuOp2_bswap
,
1930 /* 0xcd */ x86emuOp2_bswap
,
1931 /* 0xce */ x86emuOp2_bswap
,
1932 /* 0xcf */ x86emuOp2_bswap
,
1934 /* 0xd0 */ x86emuOp2_illegal_op
,
1935 /* 0xd1 */ x86emuOp2_illegal_op
,
1936 /* 0xd2 */ x86emuOp2_illegal_op
,
1937 /* 0xd3 */ x86emuOp2_illegal_op
,
1938 /* 0xd4 */ x86emuOp2_illegal_op
,
1939 /* 0xd5 */ x86emuOp2_illegal_op
,
1940 /* 0xd6 */ x86emuOp2_illegal_op
,
1941 /* 0xd7 */ x86emuOp2_illegal_op
,
1942 /* 0xd8 */ x86emuOp2_illegal_op
,
1943 /* 0xd9 */ x86emuOp2_illegal_op
,
1944 /* 0xda */ x86emuOp2_illegal_op
,
1945 /* 0xdb */ x86emuOp2_illegal_op
,
1946 /* 0xdc */ x86emuOp2_illegal_op
,
1947 /* 0xdd */ x86emuOp2_illegal_op
,
1948 /* 0xde */ x86emuOp2_illegal_op
,
1949 /* 0xdf */ x86emuOp2_illegal_op
,
1951 /* 0xe0 */ x86emuOp2_illegal_op
,
1952 /* 0xe1 */ x86emuOp2_illegal_op
,
1953 /* 0xe2 */ x86emuOp2_illegal_op
,
1954 /* 0xe3 */ x86emuOp2_illegal_op
,
1955 /* 0xe4 */ x86emuOp2_illegal_op
,
1956 /* 0xe5 */ x86emuOp2_illegal_op
,
1957 /* 0xe6 */ x86emuOp2_illegal_op
,
1958 /* 0xe7 */ x86emuOp2_illegal_op
,
1959 /* 0xe8 */ x86emuOp2_illegal_op
,
1960 /* 0xe9 */ x86emuOp2_illegal_op
,
1961 /* 0xea */ x86emuOp2_illegal_op
,
1962 /* 0xeb */ x86emuOp2_illegal_op
,
1963 /* 0xec */ x86emuOp2_illegal_op
,
1964 /* 0xed */ x86emuOp2_illegal_op
,
1965 /* 0xee */ x86emuOp2_illegal_op
,
1966 /* 0xef */ x86emuOp2_illegal_op
,
1968 /* 0xf0 */ x86emuOp2_illegal_op
,
1969 /* 0xf1 */ x86emuOp2_illegal_op
,
1970 /* 0xf2 */ x86emuOp2_illegal_op
,
1971 /* 0xf3 */ x86emuOp2_illegal_op
,
1972 /* 0xf4 */ x86emuOp2_illegal_op
,
1973 /* 0xf5 */ x86emuOp2_illegal_op
,
1974 /* 0xf6 */ x86emuOp2_illegal_op
,
1975 /* 0xf7 */ x86emuOp2_illegal_op
,
1976 /* 0xf8 */ x86emuOp2_illegal_op
,
1977 /* 0xf9 */ x86emuOp2_illegal_op
,
1978 /* 0xfa */ x86emuOp2_illegal_op
,
1979 /* 0xfb */ x86emuOp2_illegal_op
,
1980 /* 0xfc */ x86emuOp2_illegal_op
,
1981 /* 0xfd */ x86emuOp2_illegal_op
,
1982 /* 0xfe */ x86emuOp2_illegal_op
,
1983 /* 0xff */ x86emuOp2_illegal_op
,