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 processor instructions.
38 * There are approximately 250 subroutines in here, which correspond
39 * to the 256 byte-"opcodes" found on the 8086. The table which
40 * dispatches this is found in the files optab.[ch].
42 * Each opcode proc has a comment preceeding it which gives it's table
43 * address. Several opcodes are missing (undefined) in the table.
45 * Each proc includes information for decoding (DECODE_PRINTF and
46 * DECODE_PRINTF2), debugging (TRACE_REGS, SINGLE_STEP), and misc
47 * functions (START_OF_INSTR, END_OF_INSTR).
49 * Many of the procedures are *VERY* similar in coding. This has
50 * allowed for a very large amount of code to be generated in a fairly
51 * short amount of time (i.e. cut, paste, and modify). The result is
52 * that much of the code below could have been folded into subroutines
53 * for a large reduction in size of this file. The downside would be
54 * that there would be a penalty in execution speed. The file could
55 * also have been *MUCH* larger by inlining certain functions which
56 * were called. This could have resulted even faster execution. The
57 * prime directive I used to decide whether to inline the code or to
58 * modularize it, was basically: 1) no unnecessary subroutine calls,
59 * 2) no routines more than about 200 lines in size, and 3) modularize
60 * any code that I might not get right the first time. The fetch_*
61 * subroutines fall into the latter category. The The decode_* fall
62 * into the second category. The coding of the "switch(mod){ .... }"
63 * in many of the subroutines below falls into the first category.
64 * Especially, the coding of {add,and,or,sub,...}_{byte,word}
65 * subroutines are an especially glaring case of the third guideline.
66 * Since so much of the code is cloned from other modules (compare
67 * opcode #00 to opcode #01), making the basic operations subroutine
68 * calls is especially important; otherwise mistakes in coding an
69 * "add" would represent a nightmare in maintenance.
71 ****************************************************************************/
73 #include "x86emu/x86emui.h"
75 /*----------------------------- Implementation ----------------------------*/
77 /* constant arrays to do several instructions in just one function */
80 static char *x86emu_GenOpName[8] = {
81 "ADD", "OR", "ADC", "SBB", "AND", "SUB", "XOR", "CMP"};
84 /* used by several opcodes */
85 static u8 (*genop_byte_operation[])(u8 d, u8 s) =
97 static u16 (*genop_word_operation[])(u16 d, u16 s) =
109 static u32 (*genop_long_operation[])(u32 d, u32 s) =
121 /* used by opcodes 80, c0, d0, and d2. */
122 static u8(*opcD0_byte_operation[])(u8 d, u8 s) =
130 shl_byte, /* sal_byte === shl_byte by definition */
134 /* used by opcodes c1, d1, and d3. */
135 static u16(*opcD1_word_operation[])(u16 s, u8 d) =
143 shl_word, /* sal_byte === shl_byte by definition */
147 /* used by opcodes c1, d1, and d3. */
148 static u32 (*opcD1_long_operation[])(u32 s, u8 d) =
156 shl_long, /* sal_byte === shl_byte by definition */
162 static char *opF6_names[8] =
163 { "TEST\t", "", "NOT\t", "NEG\t", "MUL\t", "IMUL\t", "DIV\t", "IDIV\t" };
167 /****************************************************************************
169 op1 - Instruction op code
172 Handles illegal opcodes.
173 ****************************************************************************/
174 void x86emuOp_illegal_op(
178 if (M.x86.R_SP != 0) {
179 DECODE_PRINTF("ILLEGAL X86 OPCODE\n");
181 DB( printk("%04x:%04x: %02X ILLEGAL X86 OPCODE!\n",
182 M.x86.R_CS, M.x86.R_IP-1,op1));
186 /* If we get here, it means the stack pointer is back to zero
187 * so we are just returning from an emulator service call
188 * so therte is no need to display an error message. We trap
189 * the emulator with an 0xF1 opcode to finish the service
197 /****************************************************************************
199 Handles opcodes 0x00, 0x08, 0x10, 0x18, 0x20, 0x28, 0x30, 0x38
200 ****************************************************************************/
201 void x86emuOp_genop_byte_RM_R(u8 op1)
205 u8 *destreg, *srcreg;
208 op1 = (op1 >> 3) & 0x7;
211 DECODE_PRINTF(x86emu_GenOpName[op1]);
213 FETCH_DECODE_MODRM(mod, rh, rl);
215 { destoffset = decode_rmXX_address(mod,rl);
217 destval = fetch_data_byte(destoffset);
218 srcreg = DECODE_RM_BYTE_REGISTER(rh);
221 destval = genop_byte_operation[op1](destval, *srcreg);
222 store_data_byte(destoffset, destval);
225 { /* register to register */
226 destreg = DECODE_RM_BYTE_REGISTER(rl);
228 srcreg = DECODE_RM_BYTE_REGISTER(rh);
231 *destreg = genop_byte_operation[op1](*destreg, *srcreg);
233 DECODE_CLEAR_SEGOVR();
237 /****************************************************************************
239 Handles opcodes 0x01, 0x09, 0x11, 0x19, 0x21, 0x29, 0x31, 0x39
240 ****************************************************************************/
241 void x86emuOp_genop_word_RM_R(u8 op1)
246 op1 = (op1 >> 3) & 0x7;
249 DECODE_PRINTF(x86emu_GenOpName[op1]);
251 FETCH_DECODE_MODRM(mod, rh, rl);
254 destoffset = decode_rmXX_address(mod,rl);
255 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
260 destval = fetch_data_long(destoffset);
261 srcreg = DECODE_RM_LONG_REGISTER(rh);
264 destval = genop_long_operation[op1](destval, *srcreg);
265 store_data_long(destoffset, destval);
271 destval = fetch_data_word(destoffset);
272 srcreg = DECODE_RM_WORD_REGISTER(rh);
275 destval = genop_word_operation[op1](destval, *srcreg);
276 store_data_word(destoffset, destval);
278 } else { /* register to register */
279 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
280 u32 *destreg,*srcreg;
282 destreg = DECODE_RM_LONG_REGISTER(rl);
284 srcreg = DECODE_RM_LONG_REGISTER(rh);
287 *destreg = genop_long_operation[op1](*destreg, *srcreg);
289 u16 *destreg,*srcreg;
291 destreg = DECODE_RM_WORD_REGISTER(rl);
293 srcreg = DECODE_RM_WORD_REGISTER(rh);
296 *destreg = genop_word_operation[op1](*destreg, *srcreg);
299 DECODE_CLEAR_SEGOVR();
303 /****************************************************************************
305 Handles opcodes 0x02, 0x0a, 0x12, 0x1a, 0x22, 0x2a, 0x32, 0x3a
306 ****************************************************************************/
307 void x86emuOp_genop_byte_R_RM(u8 op1)
310 u8 *destreg, *srcreg;
314 op1 = (op1 >> 3) & 0x7;
317 DECODE_PRINTF(x86emu_GenOpName[op1]);
319 FETCH_DECODE_MODRM(mod, rh, rl);
321 destreg = DECODE_RM_BYTE_REGISTER(rh);
323 srcoffset = decode_rmXX_address(mod,rl);
324 srcval = fetch_data_byte(srcoffset);
325 } else { /* register to register */
326 destreg = DECODE_RM_BYTE_REGISTER(rh);
328 srcreg = DECODE_RM_BYTE_REGISTER(rl);
333 *destreg = genop_byte_operation[op1](*destreg, srcval);
335 DECODE_CLEAR_SEGOVR();
339 /****************************************************************************
341 Handles opcodes 0x03, 0x0b, 0x13, 0x1b, 0x23, 0x2b, 0x33, 0x3b
342 ****************************************************************************/
343 void x86emuOp_genop_word_R_RM(u8 op1)
347 u32 *destreg32, srcval;
350 op1 = (op1 >> 3) & 0x7;
353 DECODE_PRINTF(x86emu_GenOpName[op1]);
355 FETCH_DECODE_MODRM(mod, rh, rl);
357 srcoffset = decode_rmXX_address(mod,rl);
358 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
359 destreg32 = DECODE_RM_LONG_REGISTER(rh);
361 srcval = fetch_data_long(srcoffset);
364 *destreg32 = genop_long_operation[op1](*destreg32, srcval);
366 destreg = DECODE_RM_WORD_REGISTER(rh);
368 srcval = fetch_data_word(srcoffset);
371 *destreg = genop_word_operation[op1](*destreg, srcval);
373 } else { /* register to register */
374 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
376 destreg32 = DECODE_RM_LONG_REGISTER(rh);
378 srcreg = DECODE_RM_LONG_REGISTER(rl);
381 *destreg32 = genop_long_operation[op1](*destreg32, *srcreg);
384 destreg = DECODE_RM_WORD_REGISTER(rh);
386 srcreg = DECODE_RM_WORD_REGISTER(rl);
389 *destreg = genop_word_operation[op1](*destreg, *srcreg);
392 DECODE_CLEAR_SEGOVR();
396 /****************************************************************************
398 Handles opcodes 0x04, 0x0c, 0x14, 0x1c, 0x24, 0x2c, 0x34, 0x3c
399 ****************************************************************************/
400 void x86emuOp_genop_byte_AL_IMM(u8 op1)
404 op1 = (op1 >> 3) & 0x7;
407 DECODE_PRINTF(x86emu_GenOpName[op1]);
408 DECODE_PRINTF("\tAL,");
409 srcval = fetch_byte_imm();
410 DECODE_PRINTF2("%x\n", srcval);
412 M.x86.R_AL = genop_byte_operation[op1](M.x86.R_AL, srcval);
413 DECODE_CLEAR_SEGOVR();
417 /****************************************************************************
419 Handles opcodes 0x05, 0x0d, 0x15, 0x1d, 0x25, 0x2d, 0x35, 0x3d
420 ****************************************************************************/
421 void x86emuOp_genop_word_AX_IMM(u8 op1)
425 op1 = (op1 >> 3) & 0x7;
428 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
429 DECODE_PRINTF(x86emu_GenOpName[op1]);
430 DECODE_PRINTF("\tEAX,");
431 srcval = fetch_long_imm();
433 DECODE_PRINTF(x86emu_GenOpName[op1]);
434 DECODE_PRINTF("\tAX,");
435 srcval = fetch_word_imm();
437 DECODE_PRINTF2("%x\n", srcval);
439 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
440 M.x86.R_EAX = genop_long_operation[op1](M.x86.R_EAX, srcval);
442 M.x86.R_AX = genop_word_operation[op1](M.x86.R_AX, (u16)srcval);
444 DECODE_CLEAR_SEGOVR();
448 /****************************************************************************
451 ****************************************************************************/
452 void x86emuOp_push_ES(u8 X86EMU_UNUSED(op1))
455 DECODE_PRINTF("PUSH\tES\n");
457 push_word(M.x86.R_ES);
458 DECODE_CLEAR_SEGOVR();
462 /****************************************************************************
465 ****************************************************************************/
466 void x86emuOp_pop_ES(u8 X86EMU_UNUSED(op1))
469 DECODE_PRINTF("POP\tES\n");
471 M.x86.R_ES = pop_word();
472 DECODE_CLEAR_SEGOVR();
476 /****************************************************************************
479 ****************************************************************************/
480 void x86emuOp_push_CS(u8 X86EMU_UNUSED(op1))
483 DECODE_PRINTF("PUSH\tCS\n");
485 push_word(M.x86.R_CS);
486 DECODE_CLEAR_SEGOVR();
490 /****************************************************************************
492 Handles opcode 0x0f. Escape for two-byte opcode (286 or better)
493 ****************************************************************************/
494 void x86emuOp_two_byte(u8 X86EMU_UNUSED(op1))
496 u8 op2 = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++));
497 INC_DECODED_INST_LEN(1);
498 (*x86emu_optab2[op2])(op2);
501 /****************************************************************************
504 ****************************************************************************/
505 void x86emuOp_push_SS(u8 X86EMU_UNUSED(op1))
508 DECODE_PRINTF("PUSH\tSS\n");
510 push_word(M.x86.R_SS);
511 DECODE_CLEAR_SEGOVR();
515 /****************************************************************************
518 ****************************************************************************/
519 void x86emuOp_pop_SS(u8 X86EMU_UNUSED(op1))
522 DECODE_PRINTF("POP\tSS\n");
524 M.x86.R_SS = pop_word();
525 DECODE_CLEAR_SEGOVR();
529 /****************************************************************************
532 ****************************************************************************/
533 void x86emuOp_push_DS(u8 X86EMU_UNUSED(op1))
536 DECODE_PRINTF("PUSH\tDS\n");
538 push_word(M.x86.R_DS);
539 DECODE_CLEAR_SEGOVR();
543 /****************************************************************************
546 ****************************************************************************/
547 void x86emuOp_pop_DS(u8 X86EMU_UNUSED(op1))
550 DECODE_PRINTF("POP\tDS\n");
552 M.x86.R_DS = pop_word();
553 DECODE_CLEAR_SEGOVR();
557 /****************************************************************************
560 ****************************************************************************/
561 void x86emuOp_segovr_ES(u8 X86EMU_UNUSED(op1))
564 DECODE_PRINTF("ES:\n");
566 M.x86.mode |= SYSMODE_SEGOVR_ES;
568 * note the lack of DECODE_CLEAR_SEGOVR(r) since, here is one of 4
569 * opcode subroutines we do not want to do this.
574 /****************************************************************************
577 ****************************************************************************/
578 void x86emuOp_daa(u8 X86EMU_UNUSED(op1))
581 DECODE_PRINTF("DAA\n");
583 M.x86.R_AL = daa_byte(M.x86.R_AL);
584 DECODE_CLEAR_SEGOVR();
588 /****************************************************************************
591 ****************************************************************************/
592 void x86emuOp_segovr_CS(u8 X86EMU_UNUSED(op1))
595 DECODE_PRINTF("CS:\n");
597 M.x86.mode |= SYSMODE_SEGOVR_CS;
598 /* note no DECODE_CLEAR_SEGOVR here. */
602 /****************************************************************************
605 ****************************************************************************/
606 void x86emuOp_das(u8 X86EMU_UNUSED(op1))
609 DECODE_PRINTF("DAS\n");
611 M.x86.R_AL = das_byte(M.x86.R_AL);
612 DECODE_CLEAR_SEGOVR();
616 /****************************************************************************
619 ****************************************************************************/
620 void x86emuOp_segovr_SS(u8 X86EMU_UNUSED(op1))
623 DECODE_PRINTF("SS:\n");
625 M.x86.mode |= SYSMODE_SEGOVR_SS;
626 /* no DECODE_CLEAR_SEGOVR ! */
630 /****************************************************************************
633 ****************************************************************************/
634 void x86emuOp_aaa(u8 X86EMU_UNUSED(op1))
637 DECODE_PRINTF("AAA\n");
639 M.x86.R_AX = aaa_word(M.x86.R_AX);
640 DECODE_CLEAR_SEGOVR();
644 /****************************************************************************
647 ****************************************************************************/
648 void x86emuOp_segovr_DS(u8 X86EMU_UNUSED(op1))
651 DECODE_PRINTF("DS:\n");
653 M.x86.mode |= SYSMODE_SEGOVR_DS;
654 /* NO DECODE_CLEAR_SEGOVR! */
658 /****************************************************************************
661 ****************************************************************************/
662 void x86emuOp_aas(u8 X86EMU_UNUSED(op1))
665 DECODE_PRINTF("AAS\n");
667 M.x86.R_AX = aas_word(M.x86.R_AX);
668 DECODE_CLEAR_SEGOVR();
672 /****************************************************************************
674 Handles opcode 0x40 - 0x47
675 ****************************************************************************/
676 void x86emuOp_inc_register(u8 op1)
680 DECODE_PRINTF("INC\t");
681 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
683 reg = DECODE_RM_LONG_REGISTER(op1);
686 *reg = inc_long(*reg);
689 reg = DECODE_RM_WORD_REGISTER(op1);
692 *reg = inc_word(*reg);
694 DECODE_CLEAR_SEGOVR();
698 /****************************************************************************
700 Handles opcode 0x48 - 0x4F
701 ****************************************************************************/
702 void x86emuOp_dec_register(u8 op1)
706 DECODE_PRINTF("DEC\t");
707 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
709 reg = DECODE_RM_LONG_REGISTER(op1);
712 *reg = dec_long(*reg);
715 reg = DECODE_RM_WORD_REGISTER(op1);
718 *reg = dec_word(*reg);
720 DECODE_CLEAR_SEGOVR();
724 /****************************************************************************
726 Handles opcode 0x50 - 0x57
727 ****************************************************************************/
728 void x86emuOp_push_register(u8 op1)
732 DECODE_PRINTF("PUSH\t");
733 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
735 reg = DECODE_RM_LONG_REGISTER(op1);
741 reg = DECODE_RM_WORD_REGISTER(op1);
746 DECODE_CLEAR_SEGOVR();
750 /****************************************************************************
752 Handles opcode 0x58 - 0x5F
753 ****************************************************************************/
754 void x86emuOp_pop_register(u8 op1)
758 DECODE_PRINTF("POP\t");
759 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
761 reg = DECODE_RM_LONG_REGISTER(op1);
767 reg = DECODE_RM_WORD_REGISTER(op1);
772 DECODE_CLEAR_SEGOVR();
776 /****************************************************************************
779 ****************************************************************************/
780 void x86emuOp_push_all(u8 X86EMU_UNUSED(op1))
783 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
784 DECODE_PRINTF("PUSHAD\n");
786 DECODE_PRINTF("PUSHA\n");
789 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
790 u32 old_sp = M.x86.R_ESP;
792 push_long(M.x86.R_EAX);
793 push_long(M.x86.R_ECX);
794 push_long(M.x86.R_EDX);
795 push_long(M.x86.R_EBX);
797 push_long(M.x86.R_EBP);
798 push_long(M.x86.R_ESI);
799 push_long(M.x86.R_EDI);
801 u16 old_sp = M.x86.R_SP;
803 push_word(M.x86.R_AX);
804 push_word(M.x86.R_CX);
805 push_word(M.x86.R_DX);
806 push_word(M.x86.R_BX);
808 push_word(M.x86.R_BP);
809 push_word(M.x86.R_SI);
810 push_word(M.x86.R_DI);
812 DECODE_CLEAR_SEGOVR();
816 /****************************************************************************
819 ****************************************************************************/
820 void x86emuOp_pop_all(u8 X86EMU_UNUSED(op1))
823 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
824 DECODE_PRINTF("POPAD\n");
826 DECODE_PRINTF("POPA\n");
829 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
830 M.x86.R_EDI = pop_long();
831 M.x86.R_ESI = pop_long();
832 M.x86.R_EBP = pop_long();
833 M.x86.R_ESP += 4; /* skip ESP */
834 M.x86.R_EBX = pop_long();
835 M.x86.R_EDX = pop_long();
836 M.x86.R_ECX = pop_long();
837 M.x86.R_EAX = pop_long();
839 M.x86.R_DI = pop_word();
840 M.x86.R_SI = pop_word();
841 M.x86.R_BP = pop_word();
842 M.x86.R_SP += 2; /* skip SP */
843 M.x86.R_BX = pop_word();
844 M.x86.R_DX = pop_word();
845 M.x86.R_CX = pop_word();
846 M.x86.R_AX = pop_word();
848 DECODE_CLEAR_SEGOVR();
852 /*opcode 0x62 ILLEGAL OP, calls x86emuOp_illegal_op() */
853 /*opcode 0x63 ILLEGAL OP, calls x86emuOp_illegal_op() */
855 /****************************************************************************
858 ****************************************************************************/
859 void x86emuOp_segovr_FS(u8 X86EMU_UNUSED(op1))
862 DECODE_PRINTF("FS:\n");
864 M.x86.mode |= SYSMODE_SEGOVR_FS;
866 * note the lack of DECODE_CLEAR_SEGOVR(r) since, here is one of 4
867 * opcode subroutines we do not want to do this.
872 /****************************************************************************
875 ****************************************************************************/
876 void x86emuOp_segovr_GS(u8 X86EMU_UNUSED(op1))
879 DECODE_PRINTF("GS:\n");
881 M.x86.mode |= SYSMODE_SEGOVR_GS;
883 * note the lack of DECODE_CLEAR_SEGOVR(r) since, here is one of 4
884 * opcode subroutines we do not want to do this.
889 /****************************************************************************
891 Handles opcode 0x66 - prefix for 32-bit register
892 ****************************************************************************/
893 void x86emuOp_prefix_data(u8 X86EMU_UNUSED(op1))
896 DECODE_PRINTF("DATA:\n");
898 M.x86.mode |= SYSMODE_PREFIX_DATA;
899 /* note no DECODE_CLEAR_SEGOVR here. */
903 /****************************************************************************
905 Handles opcode 0x67 - prefix for 32-bit address
906 ****************************************************************************/
907 void x86emuOp_prefix_addr(u8 X86EMU_UNUSED(op1))
910 DECODE_PRINTF("ADDR:\n");
912 M.x86.mode |= SYSMODE_PREFIX_ADDR;
913 /* note no DECODE_CLEAR_SEGOVR here. */
917 /****************************************************************************
920 ****************************************************************************/
921 void x86emuOp_push_word_IMM(u8 X86EMU_UNUSED(op1))
926 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
927 imm = fetch_long_imm();
929 imm = fetch_word_imm();
931 DECODE_PRINTF2("PUSH\t%x\n", imm);
933 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
938 DECODE_CLEAR_SEGOVR();
942 /****************************************************************************
945 ****************************************************************************/
946 void x86emuOp_imul_word_IMM(u8 X86EMU_UNUSED(op1))
952 DECODE_PRINTF("IMUL\t");
953 FETCH_DECODE_MODRM(mod, rh, rl);
955 srcoffset = decode_rmXX_address(mod, rl);
956 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
962 destreg = DECODE_RM_LONG_REGISTER(rh);
964 srcval = fetch_data_long(srcoffset);
965 imm = fetch_long_imm();
966 DECODE_PRINTF2(",%d\n", (s32)imm);
968 imul_long_direct(&res_lo,&res_hi,(s32)srcval,(s32)imm);
969 if ((((res_lo & 0x80000000) == 0) && (res_hi == 0x00000000)) ||
970 (((res_lo & 0x80000000) != 0) && (res_hi == 0xFFFFFFFF))) {
977 *destreg = (u32)res_lo;
984 destreg = DECODE_RM_WORD_REGISTER(rh);
986 srcval = fetch_data_word(srcoffset);
987 imm = fetch_word_imm();
988 DECODE_PRINTF2(",%d\n", (s32)imm);
990 res = (s16)srcval * (s16)imm;
991 if ((((res & 0x8000) == 0) && ((res >> 16) == 0x0000)) ||
992 (((res & 0x8000) != 0) && ((res >> 16) == 0xFFFF))) {
1001 } else { /* register to register */
1002 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1003 u32 *destreg,*srcreg;
1007 destreg = DECODE_RM_LONG_REGISTER(rh);
1009 srcreg = DECODE_RM_LONG_REGISTER(rl);
1010 imm = fetch_long_imm();
1011 DECODE_PRINTF2(",%d\n", (s32)imm);
1013 imul_long_direct(&res_lo,&res_hi,(s32)*srcreg,(s32)imm);
1014 if ((((res_lo & 0x80000000) == 0) && (res_hi == 0x00000000)) ||
1015 (((res_lo & 0x80000000) != 0) && (res_hi == 0xFFFFFFFF))) {
1022 *destreg = (u32)res_lo;
1024 u16 *destreg,*srcreg;
1028 destreg = DECODE_RM_WORD_REGISTER(rh);
1030 srcreg = DECODE_RM_WORD_REGISTER(rl);
1031 imm = fetch_word_imm();
1032 DECODE_PRINTF2(",%d\n", (s32)imm);
1033 res = (s16)*srcreg * (s16)imm;
1034 if ((((res & 0x8000) == 0) && ((res >> 16) == 0x0000)) ||
1035 (((res & 0x8000) != 0) && ((res >> 16) == 0xFFFF))) {
1042 *destreg = (u16)res;
1045 DECODE_CLEAR_SEGOVR();
1049 /****************************************************************************
1052 ****************************************************************************/
1053 void x86emuOp_push_byte_IMM(u8 X86EMU_UNUSED(op1))
1058 imm = (s8)fetch_byte_imm();
1059 DECODE_PRINTF2("PUSH\t%d\n", imm);
1062 DECODE_CLEAR_SEGOVR();
1066 /****************************************************************************
1069 ****************************************************************************/
1070 void x86emuOp_imul_byte_IMM(u8 X86EMU_UNUSED(op1))
1077 DECODE_PRINTF("IMUL\t");
1078 FETCH_DECODE_MODRM(mod, rh, rl);
1080 srcoffset = decode_rmXX_address(mod, rl);
1081 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1086 destreg = DECODE_RM_LONG_REGISTER(rh);
1088 srcval = fetch_data_long(srcoffset);
1089 imm = fetch_byte_imm();
1090 DECODE_PRINTF2(",%d\n", (s32)imm);
1092 imul_long_direct(&res_lo,&res_hi,(s32)srcval,(s32)imm);
1093 if ((((res_lo & 0x80000000) == 0) && (res_hi == 0x00000000)) ||
1094 (((res_lo & 0x80000000) != 0) && (res_hi == 0xFFFFFFFF))) {
1101 *destreg = (u32)res_lo;
1107 destreg = DECODE_RM_WORD_REGISTER(rh);
1109 srcval = fetch_data_word(srcoffset);
1110 imm = fetch_byte_imm();
1111 DECODE_PRINTF2(",%d\n", (s32)imm);
1113 res = (s16)srcval * (s16)imm;
1114 if ((((res & 0x8000) == 0) && ((res >> 16) == 0x0000)) ||
1115 (((res & 0x8000) != 0) && ((res >> 16) == 0xFFFF))) {
1122 *destreg = (u16)res;
1124 } else { /* register to register */
1125 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1126 u32 *destreg,*srcreg;
1129 destreg = DECODE_RM_LONG_REGISTER(rh);
1131 srcreg = DECODE_RM_LONG_REGISTER(rl);
1132 imm = fetch_byte_imm();
1133 DECODE_PRINTF2(",%d\n", (s32)imm);
1135 imul_long_direct(&res_lo,&res_hi,(s32)*srcreg,(s32)imm);
1136 if ((((res_lo & 0x80000000) == 0) && (res_hi == 0x00000000)) ||
1137 (((res_lo & 0x80000000) != 0) && (res_hi == 0xFFFFFFFF))) {
1144 *destreg = (u32)res_lo;
1146 u16 *destreg,*srcreg;
1149 destreg = DECODE_RM_WORD_REGISTER(rh);
1151 srcreg = DECODE_RM_WORD_REGISTER(rl);
1152 imm = fetch_byte_imm();
1153 DECODE_PRINTF2(",%d\n", (s32)imm);
1155 res = (s16)*srcreg * (s16)imm;
1156 if ((((res & 0x8000) == 0) && ((res >> 16) == 0x0000)) ||
1157 (((res & 0x8000) != 0) && ((res >> 16) == 0xFFFF))) {
1164 *destreg = (u16)res;
1167 DECODE_CLEAR_SEGOVR();
1171 /****************************************************************************
1174 ****************************************************************************/
1175 void x86emuOp_ins_byte(u8 X86EMU_UNUSED(op1))
1178 DECODE_PRINTF("INSB\n");
1181 DECODE_CLEAR_SEGOVR();
1185 /****************************************************************************
1188 ****************************************************************************/
1189 void x86emuOp_ins_word(u8 X86EMU_UNUSED(op1))
1192 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1193 DECODE_PRINTF("INSD\n");
1196 DECODE_PRINTF("INSW\n");
1200 DECODE_CLEAR_SEGOVR();
1204 /****************************************************************************
1207 ****************************************************************************/
1208 void x86emuOp_outs_byte(u8 X86EMU_UNUSED(op1))
1211 DECODE_PRINTF("OUTSB\n");
1214 DECODE_CLEAR_SEGOVR();
1218 /****************************************************************************
1221 ****************************************************************************/
1222 void x86emuOp_outs_word(u8 X86EMU_UNUSED(op1))
1225 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1226 DECODE_PRINTF("OUTSD\n");
1229 DECODE_PRINTF("OUTSW\n");
1233 DECODE_CLEAR_SEGOVR();
1237 /****************************************************************************
1239 Handles opcode 0x70 - 0x7F
1240 ****************************************************************************/
1241 int x86emu_check_jump_condition(u8 op);
1243 void x86emuOp_jump_near_cond(u8 op1)
1249 /* jump to byte offset if overflow flag is set */
1251 cond = x86emu_check_jump_condition(op1 & 0xF);
1252 offset = (s8)fetch_byte_imm();
1253 target = (u16)(M.x86.R_IP + (s16)offset);
1254 DECODE_PRINTF2("%x\n", target);
1257 M.x86.R_IP = target;
1258 DECODE_CLEAR_SEGOVR();
1262 /****************************************************************************
1265 ****************************************************************************/
1266 void x86emuOp_opc80_byte_RM_IMM(u8 X86EMU_UNUSED(op1))
1275 * Weirdo special case instruction format. Part of the opcode
1276 * held below in "RH". Doubly nested case would result, except
1277 * that the decoded instruction
1280 FETCH_DECODE_MODRM(mod, rh, rl);
1282 if (DEBUG_DECODE()) {
1283 /* XXX DECODE_PRINTF may be changed to something more
1284 general, so that it is important to leave the strings
1285 in the same format, even though the result is that the
1286 above test is done twice. */
1290 DECODE_PRINTF("ADD\t");
1293 DECODE_PRINTF("OR\t");
1296 DECODE_PRINTF("ADC\t");
1299 DECODE_PRINTF("SBB\t");
1302 DECODE_PRINTF("AND\t");
1305 DECODE_PRINTF("SUB\t");
1308 DECODE_PRINTF("XOR\t");
1311 DECODE_PRINTF("CMP\t");
1316 /* know operation, decode the mod byte to find the addressing
1319 DECODE_PRINTF("BYTE PTR ");
1320 destoffset = decode_rmXX_address(mod, rl);
1322 destval = fetch_data_byte(destoffset);
1323 imm = fetch_byte_imm();
1324 DECODE_PRINTF2("%x\n", imm);
1326 destval = (*genop_byte_operation[rh]) (destval, imm);
1328 store_data_byte(destoffset, destval);
1329 } else { /* register to register */
1330 destreg = DECODE_RM_BYTE_REGISTER(rl);
1332 imm = fetch_byte_imm();
1333 DECODE_PRINTF2("%x\n", imm);
1335 destval = (*genop_byte_operation[rh]) (*destreg, imm);
1339 DECODE_CLEAR_SEGOVR();
1343 /****************************************************************************
1346 ****************************************************************************/
1347 void x86emuOp_opc81_word_RM_IMM(u8 X86EMU_UNUSED(op1))
1353 * Weirdo special case instruction format. Part of the opcode
1354 * held below in "RH". Doubly nested case would result, except
1355 * that the decoded instruction
1358 FETCH_DECODE_MODRM(mod, rh, rl);
1360 if (DEBUG_DECODE()) {
1361 /* XXX DECODE_PRINTF may be changed to something more
1362 general, so that it is important to leave the strings
1363 in the same format, even though the result is that the
1364 above test is done twice. */
1368 DECODE_PRINTF("ADD\t");
1371 DECODE_PRINTF("OR\t");
1374 DECODE_PRINTF("ADC\t");
1377 DECODE_PRINTF("SBB\t");
1380 DECODE_PRINTF("AND\t");
1383 DECODE_PRINTF("SUB\t");
1386 DECODE_PRINTF("XOR\t");
1389 DECODE_PRINTF("CMP\t");
1395 * Know operation, decode the mod byte to find the addressing
1399 DECODE_PRINTF("DWORD PTR ");
1400 destoffset = decode_rmXX_address(mod, rl);
1401 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1405 destval = fetch_data_long(destoffset);
1406 imm = fetch_long_imm();
1407 DECODE_PRINTF2("%x\n", imm);
1409 destval = (*genop_long_operation[rh]) (destval, imm);
1411 store_data_long(destoffset, destval);
1416 destval = fetch_data_word(destoffset);
1417 imm = fetch_word_imm();
1418 DECODE_PRINTF2("%x\n", imm);
1420 destval = (*genop_word_operation[rh]) (destval, imm);
1422 store_data_word(destoffset, destval);
1424 } else { /* register to register */
1425 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1429 destreg = DECODE_RM_LONG_REGISTER(rl);
1431 imm = fetch_long_imm();
1432 DECODE_PRINTF2("%x\n", imm);
1434 destval = (*genop_long_operation[rh]) (*destreg, imm);
1441 destreg = DECODE_RM_WORD_REGISTER(rl);
1443 imm = fetch_word_imm();
1444 DECODE_PRINTF2("%x\n", imm);
1446 destval = (*genop_word_operation[rh]) (*destreg, imm);
1451 DECODE_CLEAR_SEGOVR();
1455 /****************************************************************************
1458 ****************************************************************************/
1459 void x86emuOp_opc82_byte_RM_IMM(u8 X86EMU_UNUSED(op1))
1468 * Weirdo special case instruction format. Part of the opcode
1469 * held below in "RH". Doubly nested case would result, except
1470 * that the decoded instruction Similar to opcode 81, except that
1471 * the immediate byte is sign extended to a word length.
1474 FETCH_DECODE_MODRM(mod, rh, rl);
1476 if (DEBUG_DECODE()) {
1477 /* XXX DECODE_PRINTF may be changed to something more
1478 general, so that it is important to leave the strings
1479 in the same format, even though the result is that the
1480 above test is done twice. */
1483 DECODE_PRINTF("ADD\t");
1486 DECODE_PRINTF("OR\t");
1489 DECODE_PRINTF("ADC\t");
1492 DECODE_PRINTF("SBB\t");
1495 DECODE_PRINTF("AND\t");
1498 DECODE_PRINTF("SUB\t");
1501 DECODE_PRINTF("XOR\t");
1504 DECODE_PRINTF("CMP\t");
1509 /* know operation, decode the mod byte to find the addressing
1512 DECODE_PRINTF("BYTE PTR ");
1513 destoffset = decode_rmXX_address(mod, rl);
1514 destval = fetch_data_byte(destoffset);
1515 imm = fetch_byte_imm();
1516 DECODE_PRINTF2(",%x\n", imm);
1518 destval = (*genop_byte_operation[rh]) (destval, imm);
1520 store_data_byte(destoffset, destval);
1521 } else { /* register to register */
1522 destreg = DECODE_RM_BYTE_REGISTER(rl);
1523 imm = fetch_byte_imm();
1524 DECODE_PRINTF2(",%x\n", imm);
1526 destval = (*genop_byte_operation[rh]) (*destreg, imm);
1530 DECODE_CLEAR_SEGOVR();
1534 /****************************************************************************
1537 ****************************************************************************/
1538 void x86emuOp_opc83_word_RM_IMM(u8 X86EMU_UNUSED(op1))
1544 * Weirdo special case instruction format. Part of the opcode
1545 * held below in "RH". Doubly nested case would result, except
1546 * that the decoded instruction Similar to opcode 81, except that
1547 * the immediate byte is sign extended to a word length.
1550 FETCH_DECODE_MODRM(mod, rh, rl);
1552 if (DEBUG_DECODE()) {
1553 /* XXX DECODE_PRINTF may be changed to something more
1554 general, so that it is important to leave the strings
1555 in the same format, even though the result is that the
1556 above test is done twice. */
1559 DECODE_PRINTF("ADD\t");
1562 DECODE_PRINTF("OR\t");
1565 DECODE_PRINTF("ADC\t");
1568 DECODE_PRINTF("SBB\t");
1571 DECODE_PRINTF("AND\t");
1574 DECODE_PRINTF("SUB\t");
1577 DECODE_PRINTF("XOR\t");
1580 DECODE_PRINTF("CMP\t");
1585 /* know operation, decode the mod byte to find the addressing
1588 DECODE_PRINTF("DWORD PTR ");
1589 destoffset = decode_rmXX_address(mod,rl);
1591 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1594 destval = fetch_data_long(destoffset);
1595 imm = (s8) fetch_byte_imm();
1596 DECODE_PRINTF2(",%x\n", imm);
1598 destval = (*genop_long_operation[rh]) (destval, imm);
1600 store_data_long(destoffset, destval);
1604 destval = fetch_data_word(destoffset);
1605 imm = (s8) fetch_byte_imm();
1606 DECODE_PRINTF2(",%x\n", imm);
1608 destval = (*genop_word_operation[rh]) (destval, imm);
1610 store_data_word(destoffset, destval);
1612 } else { /* register to register */
1613 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1617 destreg = DECODE_RM_LONG_REGISTER(rl);
1618 imm = (s8) fetch_byte_imm();
1619 DECODE_PRINTF2(",%x\n", imm);
1621 destval = (*genop_long_operation[rh]) (*destreg, imm);
1628 destreg = DECODE_RM_WORD_REGISTER(rl);
1629 imm = (s8) fetch_byte_imm();
1630 DECODE_PRINTF2(",%x\n", imm);
1632 destval = (*genop_word_operation[rh]) (*destreg, imm);
1637 DECODE_CLEAR_SEGOVR();
1641 /****************************************************************************
1644 ****************************************************************************/
1645 void x86emuOp_test_byte_RM_R(u8 X86EMU_UNUSED(op1))
1648 u8 *destreg, *srcreg;
1653 DECODE_PRINTF("TEST\t");
1654 FETCH_DECODE_MODRM(mod, rh, rl);
1656 destoffset = decode_rmXX_address(mod, rl);
1658 destval = fetch_data_byte(destoffset);
1659 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1660 DECODE_PRINTF("\n");
1662 test_byte(destval, *srcreg);
1663 } else { /* register to register */
1664 destreg = DECODE_RM_BYTE_REGISTER(rl);
1666 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1667 DECODE_PRINTF("\n");
1669 test_byte(*destreg, *srcreg);
1671 DECODE_CLEAR_SEGOVR();
1675 /****************************************************************************
1678 ****************************************************************************/
1679 void x86emuOp_test_word_RM_R(u8 X86EMU_UNUSED(op1))
1685 DECODE_PRINTF("TEST\t");
1686 FETCH_DECODE_MODRM(mod, rh, rl);
1688 destoffset = decode_rmXX_address(mod, rl);
1689 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1694 destval = fetch_data_long(destoffset);
1695 srcreg = DECODE_RM_LONG_REGISTER(rh);
1696 DECODE_PRINTF("\n");
1698 test_long(destval, *srcreg);
1704 destval = fetch_data_word(destoffset);
1705 srcreg = DECODE_RM_WORD_REGISTER(rh);
1706 DECODE_PRINTF("\n");
1708 test_word(destval, *srcreg);
1710 } else { /* register to register */
1711 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1712 u32 *destreg,*srcreg;
1714 destreg = DECODE_RM_LONG_REGISTER(rl);
1716 srcreg = DECODE_RM_LONG_REGISTER(rh);
1717 DECODE_PRINTF("\n");
1719 test_long(*destreg, *srcreg);
1721 u16 *destreg,*srcreg;
1723 destreg = DECODE_RM_WORD_REGISTER(rl);
1725 srcreg = DECODE_RM_WORD_REGISTER(rh);
1726 DECODE_PRINTF("\n");
1728 test_word(*destreg, *srcreg);
1731 DECODE_CLEAR_SEGOVR();
1735 /****************************************************************************
1738 ****************************************************************************/
1739 void x86emuOp_xchg_byte_RM_R(u8 X86EMU_UNUSED(op1))
1742 u8 *destreg, *srcreg;
1748 DECODE_PRINTF("XCHG\t");
1749 FETCH_DECODE_MODRM(mod, rh, rl);
1751 destoffset = decode_rmXX_address(mod, rl);
1753 destval = fetch_data_byte(destoffset);
1754 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1755 DECODE_PRINTF("\n");
1760 store_data_byte(destoffset, destval);
1761 } else { /* register to register */
1762 destreg = DECODE_RM_BYTE_REGISTER(rl);
1764 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1765 DECODE_PRINTF("\n");
1771 DECODE_CLEAR_SEGOVR();
1775 /****************************************************************************
1778 ****************************************************************************/
1779 void x86emuOp_xchg_word_RM_R(u8 X86EMU_UNUSED(op1))
1785 DECODE_PRINTF("XCHG\t");
1786 FETCH_DECODE_MODRM(mod, rh, rl);
1788 destoffset = decode_rmXX_address(mod, rl);
1790 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1794 destval = fetch_data_long(destoffset);
1795 srcreg = DECODE_RM_LONG_REGISTER(rh);
1796 DECODE_PRINTF("\n");
1801 store_data_long(destoffset, destval);
1806 destval = fetch_data_word(destoffset);
1807 srcreg = DECODE_RM_WORD_REGISTER(rh);
1808 DECODE_PRINTF("\n");
1813 store_data_word(destoffset, destval);
1815 } else { /* register to register */
1816 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1817 u32 *destreg,*srcreg;
1820 destreg = DECODE_RM_LONG_REGISTER(rl);
1822 srcreg = DECODE_RM_LONG_REGISTER(rh);
1823 DECODE_PRINTF("\n");
1829 u16 *destreg,*srcreg;
1832 destreg = DECODE_RM_WORD_REGISTER(rl);
1834 srcreg = DECODE_RM_WORD_REGISTER(rh);
1835 DECODE_PRINTF("\n");
1842 DECODE_CLEAR_SEGOVR();
1846 /****************************************************************************
1849 ****************************************************************************/
1850 void x86emuOp_mov_byte_RM_R(u8 X86EMU_UNUSED(op1))
1853 u8 *destreg, *srcreg;
1857 DECODE_PRINTF("MOV\t");
1858 FETCH_DECODE_MODRM(mod, rh, rl);
1860 destoffset = decode_rmXX_address(mod, rl);
1862 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1863 DECODE_PRINTF("\n");
1865 store_data_byte(destoffset, *srcreg);
1866 } else { /* register to register */
1867 destreg = DECODE_RM_BYTE_REGISTER(rl);
1869 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1870 DECODE_PRINTF("\n");
1874 DECODE_CLEAR_SEGOVR();
1878 /****************************************************************************
1881 ****************************************************************************/
1882 void x86emuOp_mov_word_RM_R(u8 X86EMU_UNUSED(op1))
1888 DECODE_PRINTF("MOV\t");
1889 FETCH_DECODE_MODRM(mod, rh, rl);
1891 destoffset = decode_rmXX_address(mod, rl);
1892 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1896 srcreg = DECODE_RM_LONG_REGISTER(rh);
1897 DECODE_PRINTF("\n");
1899 store_data_long(destoffset, *srcreg);
1904 srcreg = DECODE_RM_WORD_REGISTER(rh);
1905 DECODE_PRINTF("\n");
1907 store_data_word(destoffset, *srcreg);
1909 } else { /* register to register */
1910 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1911 u32 *destreg,*srcreg;
1913 destreg = DECODE_RM_LONG_REGISTER(rl);
1915 srcreg = DECODE_RM_LONG_REGISTER(rh);
1916 DECODE_PRINTF("\n");
1920 u16 *destreg,*srcreg;
1922 destreg = DECODE_RM_WORD_REGISTER(rl);
1924 srcreg = DECODE_RM_WORD_REGISTER(rh);
1925 DECODE_PRINTF("\n");
1930 DECODE_CLEAR_SEGOVR();
1934 /****************************************************************************
1937 ****************************************************************************/
1938 void x86emuOp_mov_byte_R_RM(u8 X86EMU_UNUSED(op1))
1941 u8 *destreg, *srcreg;
1946 DECODE_PRINTF("MOV\t");
1947 FETCH_DECODE_MODRM(mod, rh, rl);
1949 destreg = DECODE_RM_BYTE_REGISTER(rh);
1951 srcoffset = decode_rmXX_address(mod, rl);
1952 srcval = fetch_data_byte(srcoffset);
1953 DECODE_PRINTF("\n");
1956 } else { /* register to register */
1957 destreg = DECODE_RM_BYTE_REGISTER(rh);
1959 srcreg = DECODE_RM_BYTE_REGISTER(rl);
1960 DECODE_PRINTF("\n");
1964 DECODE_CLEAR_SEGOVR();
1968 /****************************************************************************
1971 ****************************************************************************/
1972 void x86emuOp_mov_word_R_RM(u8 X86EMU_UNUSED(op1))
1978 DECODE_PRINTF("MOV\t");
1979 FETCH_DECODE_MODRM(mod, rh, rl);
1981 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1985 destreg = DECODE_RM_LONG_REGISTER(rh);
1987 srcoffset = decode_rmXX_address(mod, rl);
1988 srcval = fetch_data_long(srcoffset);
1989 DECODE_PRINTF("\n");
1996 destreg = DECODE_RM_WORD_REGISTER(rh);
1998 srcoffset = decode_rmXX_address(mod, rl);
1999 srcval = fetch_data_word(srcoffset);
2000 DECODE_PRINTF("\n");
2004 } else { /* register to register */
2005 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2006 u32 *destreg, *srcreg;
2008 destreg = DECODE_RM_LONG_REGISTER(rh);
2010 srcreg = DECODE_RM_LONG_REGISTER(rl);
2011 DECODE_PRINTF("\n");
2015 u16 *destreg, *srcreg;
2017 destreg = DECODE_RM_WORD_REGISTER(rh);
2019 srcreg = DECODE_RM_WORD_REGISTER(rl);
2020 DECODE_PRINTF("\n");
2025 DECODE_CLEAR_SEGOVR();
2029 /****************************************************************************
2032 ****************************************************************************/
2033 void x86emuOp_mov_word_RM_SR(u8 X86EMU_UNUSED(op1))
2036 u16 *destreg, *srcreg;
2041 DECODE_PRINTF("MOV\t");
2042 FETCH_DECODE_MODRM(mod, rh, rl);
2044 destoffset = decode_rmXX_address(mod, rl);
2046 srcreg = decode_rm_seg_register(rh);
2047 DECODE_PRINTF("\n");
2050 store_data_word(destoffset, destval);
2051 } else { /* register to register */
2052 destreg = DECODE_RM_WORD_REGISTER(rl);
2054 srcreg = decode_rm_seg_register(rh);
2055 DECODE_PRINTF("\n");
2059 DECODE_CLEAR_SEGOVR();
2063 /****************************************************************************
2066 ****************************************************************************/
2067 void x86emuOp_lea_word_R_M(u8 X86EMU_UNUSED(op1))
2074 * TODO: Need to handle address size prefix!
2076 * lea eax,[eax+ebx*2] ??
2080 DECODE_PRINTF("LEA\t");
2081 FETCH_DECODE_MODRM(mod, rh, rl);
2083 srcreg = DECODE_RM_WORD_REGISTER(rh);
2085 destoffset = decode_rmXX_address(mod, rl);
2086 DECODE_PRINTF("\n");
2088 *srcreg = (u16)destoffset;
2090 /* } else { undefined. Do nothing. } */
2091 DECODE_CLEAR_SEGOVR();
2095 /****************************************************************************
2098 ****************************************************************************/
2099 void x86emuOp_mov_word_SR_RM(u8 X86EMU_UNUSED(op1))
2102 u16 *destreg, *srcreg;
2107 DECODE_PRINTF("MOV\t");
2108 FETCH_DECODE_MODRM(mod, rh, rl);
2110 destreg = decode_rm_seg_register(rh);
2112 srcoffset = decode_rmXX_address(mod, rl);
2113 srcval = fetch_data_word(srcoffset);
2114 DECODE_PRINTF("\n");
2117 } else { /* register to register */
2118 destreg = decode_rm_seg_register(rh);
2120 srcreg = DECODE_RM_WORD_REGISTER(rl);
2121 DECODE_PRINTF("\n");
2126 * Clean up, and reset all the R_xSP pointers to the correct
2127 * locations. This is about 3x too much overhead (doing all the
2128 * segreg ptrs when only one is needed, but this instruction
2129 * *cannot* be that common, and this isn't too much work anyway.
2131 DECODE_CLEAR_SEGOVR();
2135 /****************************************************************************
2138 ****************************************************************************/
2139 void x86emuOp_pop_RM(u8 X86EMU_UNUSED(op1))
2145 DECODE_PRINTF("POP\t");
2146 FETCH_DECODE_MODRM(mod, rh, rl);
2148 DECODE_PRINTF("ILLEGAL DECODE OF OPCODE 8F\n");
2152 destoffset = decode_rmXX_address(mod, rl);
2153 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2156 DECODE_PRINTF("\n");
2158 destval = pop_long();
2159 store_data_long(destoffset, destval);
2163 DECODE_PRINTF("\n");
2165 destval = pop_word();
2166 store_data_word(destoffset, destval);
2168 } else { /* register to register */
2169 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2172 destreg = DECODE_RM_LONG_REGISTER(rl);
2173 DECODE_PRINTF("\n");
2175 *destreg = pop_long();
2179 destreg = DECODE_RM_WORD_REGISTER(rl);
2180 DECODE_PRINTF("\n");
2182 *destreg = pop_word();
2185 DECODE_CLEAR_SEGOVR();
2189 /****************************************************************************
2192 ****************************************************************************/
2193 void x86emuOp_nop(u8 X86EMU_UNUSED(op1))
2196 DECODE_PRINTF("NOP\n");
2198 DECODE_CLEAR_SEGOVR();
2202 /****************************************************************************
2204 Handles opcode 0x91-0x97
2205 ****************************************************************************/
2206 void x86emuOp_xchg_word_AX_register(u8 X86EMU_UNUSED(op1))
2214 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2216 DECODE_PRINTF("XCHG\tEAX,");
2217 reg32 = DECODE_RM_LONG_REGISTER(op1);
2218 DECODE_PRINTF("\n");
2221 M.x86.R_EAX = *reg32;
2225 DECODE_PRINTF("XCHG\tAX,");
2226 reg16 = DECODE_RM_WORD_REGISTER(op1);
2227 DECODE_PRINTF("\n");
2230 M.x86.R_EAX = *reg16;
2233 DECODE_CLEAR_SEGOVR();
2237 /****************************************************************************
2240 ****************************************************************************/
2241 void x86emuOp_cbw(u8 X86EMU_UNUSED(op1))
2244 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2245 DECODE_PRINTF("CWDE\n");
2247 DECODE_PRINTF("CBW\n");
2250 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2251 if (M.x86.R_AX & 0x8000) {
2252 M.x86.R_EAX |= 0xffff0000;
2254 M.x86.R_EAX &= 0x0000ffff;
2257 if (M.x86.R_AL & 0x80) {
2263 DECODE_CLEAR_SEGOVR();
2267 /****************************************************************************
2270 ****************************************************************************/
2271 void x86emuOp_cwd(u8 X86EMU_UNUSED(op1))
2274 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2275 DECODE_PRINTF("CDQ\n");
2277 DECODE_PRINTF("CWD\n");
2279 DECODE_PRINTF("CWD\n");
2281 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2282 if (M.x86.R_EAX & 0x80000000) {
2283 M.x86.R_EDX = 0xffffffff;
2288 if (M.x86.R_AX & 0x8000) {
2289 M.x86.R_DX = 0xffff;
2294 DECODE_CLEAR_SEGOVR();
2298 /****************************************************************************
2301 ****************************************************************************/
2302 void x86emuOp_call_far_IMM(u8 X86EMU_UNUSED(op1))
2307 DECODE_PRINTF("CALL\t");
2308 faroff = fetch_word_imm();
2309 farseg = fetch_word_imm();
2310 DECODE_PRINTF2("%04x:", farseg);
2311 DECODE_PRINTF2("%04x\n", faroff);
2312 CALL_TRACE(M.x86.saved_cs, M.x86.saved_ip, farseg, faroff, "FAR ");
2316 * Hooked interrupt vectors calling into our "BIOS" will cause
2317 * problems unless all intersegment stuff is checked for BIOS
2318 * access. Check needed here. For moment, let it alone.
2321 push_word(M.x86.R_CS);
2322 M.x86.R_CS = farseg;
2323 push_word(M.x86.R_IP);
2324 M.x86.R_IP = faroff;
2325 DECODE_CLEAR_SEGOVR();
2329 /****************************************************************************
2332 ****************************************************************************/
2333 void x86emuOp_wait(u8 X86EMU_UNUSED(op1))
2336 DECODE_PRINTF("WAIT");
2339 DECODE_CLEAR_SEGOVR();
2343 /****************************************************************************
2346 ****************************************************************************/
2347 void x86emuOp_pushf_word(u8 X86EMU_UNUSED(op1))
2352 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2353 DECODE_PRINTF("PUSHFD\n");
2355 DECODE_PRINTF("PUSHF\n");
2359 /* clear out *all* bits not representing flags, and turn on real bits */
2360 flags = (M.x86.R_EFLG & F_MSK) | F_ALWAYS_ON;
2361 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2364 push_word((u16)flags);
2366 DECODE_CLEAR_SEGOVR();
2370 /****************************************************************************
2373 ****************************************************************************/
2374 void x86emuOp_popf_word(u8 X86EMU_UNUSED(op1))
2377 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2378 DECODE_PRINTF("POPFD\n");
2380 DECODE_PRINTF("POPF\n");
2383 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2384 M.x86.R_EFLG = pop_long();
2386 M.x86.R_FLG = pop_word();
2388 DECODE_CLEAR_SEGOVR();
2392 /****************************************************************************
2395 ****************************************************************************/
2396 void x86emuOp_sahf(u8 X86EMU_UNUSED(op1))
2399 DECODE_PRINTF("SAHF\n");
2401 /* clear the lower bits of the flag register */
2402 M.x86.R_FLG &= 0xffffff00;
2403 /* or in the AH register into the flags register */
2404 M.x86.R_FLG |= M.x86.R_AH;
2405 DECODE_CLEAR_SEGOVR();
2409 /****************************************************************************
2412 ****************************************************************************/
2413 void x86emuOp_lahf(u8 X86EMU_UNUSED(op1))
2416 DECODE_PRINTF("LAHF\n");
2418 M.x86.R_AH = (u8)(M.x86.R_FLG & 0xff);
2419 /*undocumented TC++ behavior??? Nope. It's documented, but
2420 you have too look real hard to notice it. */
2422 DECODE_CLEAR_SEGOVR();
2426 /****************************************************************************
2429 ****************************************************************************/
2430 void x86emuOp_mov_AL_M_IMM(u8 X86EMU_UNUSED(op1))
2435 DECODE_PRINTF("MOV\tAL,");
2436 offset = fetch_word_imm();
2437 DECODE_PRINTF2("[%04x]\n", offset);
2439 M.x86.R_AL = fetch_data_byte(offset);
2440 DECODE_CLEAR_SEGOVR();
2444 /****************************************************************************
2447 ****************************************************************************/
2448 void x86emuOp_mov_AX_M_IMM(u8 X86EMU_UNUSED(op1))
2453 offset = fetch_word_imm();
2454 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2455 DECODE_PRINTF2("MOV\tEAX,[%04x]\n", offset);
2457 DECODE_PRINTF2("MOV\tAX,[%04x]\n", offset);
2460 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2461 M.x86.R_EAX = fetch_data_long(offset);
2463 M.x86.R_AX = fetch_data_word(offset);
2465 DECODE_CLEAR_SEGOVR();
2469 /****************************************************************************
2472 ****************************************************************************/
2473 void x86emuOp_mov_M_AL_IMM(u8 X86EMU_UNUSED(op1))
2478 DECODE_PRINTF("MOV\t");
2479 offset = fetch_word_imm();
2480 DECODE_PRINTF2("[%04x],AL\n", offset);
2482 store_data_byte(offset, M.x86.R_AL);
2483 DECODE_CLEAR_SEGOVR();
2487 /****************************************************************************
2490 ****************************************************************************/
2491 void x86emuOp_mov_M_AX_IMM(u8 X86EMU_UNUSED(op1))
2496 offset = fetch_word_imm();
2497 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2498 DECODE_PRINTF2("MOV\t[%04x],EAX\n", offset);
2500 DECODE_PRINTF2("MOV\t[%04x],AX\n", offset);
2503 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2504 store_data_long(offset, M.x86.R_EAX);
2506 store_data_word(offset, M.x86.R_AX);
2508 DECODE_CLEAR_SEGOVR();
2512 /****************************************************************************
2515 ****************************************************************************/
2516 void x86emuOp_movs_byte(u8 X86EMU_UNUSED(op1))
2523 DECODE_PRINTF("MOVS\tBYTE\n");
2524 if (ACCESS_FLAG(F_DF)) /* down */
2530 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2531 /* dont care whether REPE or REPNE */
2532 /* move them until CX is ZERO. */
2535 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2538 val = fetch_data_byte(M.x86.R_SI);
2539 store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, val);
2543 DECODE_CLEAR_SEGOVR();
2547 /****************************************************************************
2550 ****************************************************************************/
2551 void x86emuOp_movs_word(u8 X86EMU_UNUSED(op1))
2558 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2559 DECODE_PRINTF("MOVS\tDWORD\n");
2560 if (ACCESS_FLAG(F_DF)) /* down */
2565 DECODE_PRINTF("MOVS\tWORD\n");
2566 if (ACCESS_FLAG(F_DF)) /* down */
2573 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2574 /* dont care whether REPE or REPNE */
2575 /* move them until CX is ZERO. */
2578 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2581 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2582 val = fetch_data_long(M.x86.R_SI);
2583 store_data_long_abs(M.x86.R_ES, M.x86.R_DI, val);
2585 val = fetch_data_word(M.x86.R_SI);
2586 store_data_word_abs(M.x86.R_ES, M.x86.R_DI, (u16)val);
2591 DECODE_CLEAR_SEGOVR();
2595 /****************************************************************************
2598 ****************************************************************************/
2599 void x86emuOp_cmps_byte(u8 X86EMU_UNUSED(op1))
2605 DECODE_PRINTF("CMPS\tBYTE\n");
2607 if (ACCESS_FLAG(F_DF)) /* down */
2612 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2614 /* move them until CX is ZERO. */
2615 while (M.x86.R_CX != 0) {
2616 val1 = fetch_data_byte(M.x86.R_SI);
2617 val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2618 cmp_byte(val1, val2);
2622 if ( (M.x86.mode & SYSMODE_PREFIX_REPE) && (ACCESS_FLAG(F_ZF) == 0) ) break;
2623 if ( (M.x86.mode & SYSMODE_PREFIX_REPNE) && ACCESS_FLAG(F_ZF) ) break;
2625 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2627 val1 = fetch_data_byte(M.x86.R_SI);
2628 val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2629 cmp_byte(val1, val2);
2633 DECODE_CLEAR_SEGOVR();
2637 /****************************************************************************
2640 ****************************************************************************/
2641 void x86emuOp_cmps_word(u8 X86EMU_UNUSED(op1))
2647 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2648 DECODE_PRINTF("CMPS\tDWORD\n");
2651 DECODE_PRINTF("CMPS\tWORD\n");
2654 if (ACCESS_FLAG(F_DF)) /* down */
2658 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2660 /* move them until CX is ZERO. */
2661 while (M.x86.R_CX != 0) {
2662 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2663 val1 = fetch_data_long(M.x86.R_SI);
2664 val2 = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
2665 cmp_long(val1, val2);
2667 val1 = fetch_data_word(M.x86.R_SI);
2668 val2 = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
2669 cmp_word((u16)val1, (u16)val2);
2674 if ( (M.x86.mode & SYSMODE_PREFIX_REPE) && ACCESS_FLAG(F_ZF) == 0 ) break;
2675 if ( (M.x86.mode & SYSMODE_PREFIX_REPNE) && ACCESS_FLAG(F_ZF) ) break;
2677 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2679 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2680 val1 = fetch_data_long(M.x86.R_SI);
2681 val2 = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
2682 cmp_long(val1, val2);
2684 val1 = fetch_data_word(M.x86.R_SI);
2685 val2 = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
2686 cmp_word((u16)val1, (u16)val2);
2691 DECODE_CLEAR_SEGOVR();
2695 /****************************************************************************
2698 ****************************************************************************/
2699 void x86emuOp_test_AL_IMM(u8 X86EMU_UNUSED(op1))
2704 DECODE_PRINTF("TEST\tAL,");
2705 imm = fetch_byte_imm();
2706 DECODE_PRINTF2("%04x\n", imm);
2708 test_byte(M.x86.R_AL, (u8)imm);
2709 DECODE_CLEAR_SEGOVR();
2713 /****************************************************************************
2716 ****************************************************************************/
2717 void x86emuOp_test_AX_IMM(u8 X86EMU_UNUSED(op1))
2722 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2723 DECODE_PRINTF("TEST\tEAX,");
2724 srcval = fetch_long_imm();
2726 DECODE_PRINTF("TEST\tAX,");
2727 srcval = fetch_word_imm();
2729 DECODE_PRINTF2("%x\n", srcval);
2731 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2732 test_long(M.x86.R_EAX, srcval);
2734 test_word(M.x86.R_AX, (u16)srcval);
2736 DECODE_CLEAR_SEGOVR();
2740 /****************************************************************************
2743 ****************************************************************************/
2744 void x86emuOp_stos_byte(u8 X86EMU_UNUSED(op1))
2749 DECODE_PRINTF("STOS\tBYTE\n");
2750 if (ACCESS_FLAG(F_DF)) /* down */
2755 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2756 /* dont care whether REPE or REPNE */
2757 /* move them until CX is ZERO. */
2758 while (M.x86.R_CX != 0) {
2759 store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AL);
2763 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2765 store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AL);
2768 DECODE_CLEAR_SEGOVR();
2772 /****************************************************************************
2775 ****************************************************************************/
2776 void x86emuOp_stos_word(u8 X86EMU_UNUSED(op1))
2782 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2783 DECODE_PRINTF("STOS\tDWORD\n");
2784 if (ACCESS_FLAG(F_DF)) /* down */
2789 DECODE_PRINTF("STOS\tWORD\n");
2790 if (ACCESS_FLAG(F_DF)) /* down */
2797 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2798 /* dont care whether REPE or REPNE */
2799 /* move them until CX is ZERO. */
2802 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2805 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2806 store_data_long_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_EAX);
2808 store_data_word_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AX);
2812 DECODE_CLEAR_SEGOVR();
2816 /****************************************************************************
2819 ****************************************************************************/
2820 void x86emuOp_lods_byte(u8 X86EMU_UNUSED(op1))
2825 DECODE_PRINTF("LODS\tBYTE\n");
2827 if (ACCESS_FLAG(F_DF)) /* down */
2831 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2832 /* dont care whether REPE or REPNE */
2833 /* move them until CX is ZERO. */
2834 while (M.x86.R_CX != 0) {
2835 M.x86.R_AL = fetch_data_byte(M.x86.R_SI);
2839 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2841 M.x86.R_AL = fetch_data_byte(M.x86.R_SI);
2844 DECODE_CLEAR_SEGOVR();
2848 /****************************************************************************
2851 ****************************************************************************/
2852 void x86emuOp_lods_word(u8 X86EMU_UNUSED(op1))
2858 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2859 DECODE_PRINTF("LODS\tDWORD\n");
2860 if (ACCESS_FLAG(F_DF)) /* down */
2865 DECODE_PRINTF("LODS\tWORD\n");
2866 if (ACCESS_FLAG(F_DF)) /* down */
2873 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2874 /* dont care whether REPE or REPNE */
2875 /* move them until CX is ZERO. */
2878 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2881 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2882 M.x86.R_EAX = fetch_data_long(M.x86.R_SI);
2884 M.x86.R_AX = fetch_data_word(M.x86.R_SI);
2888 DECODE_CLEAR_SEGOVR();
2892 /****************************************************************************
2895 ****************************************************************************/
2896 void x86emuOp_scas_byte(u8 X86EMU_UNUSED(op1))
2902 DECODE_PRINTF("SCAS\tBYTE\n");
2904 if (ACCESS_FLAG(F_DF)) /* down */
2908 if (M.x86.mode & SYSMODE_PREFIX_REPE) {
2910 /* move them until CX is ZERO. */
2911 while (M.x86.R_CX != 0) {
2912 val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2913 cmp_byte(M.x86.R_AL, val2);
2916 if (ACCESS_FLAG(F_ZF) == 0)
2919 M.x86.mode &= ~SYSMODE_PREFIX_REPE;
2920 } else if (M.x86.mode & SYSMODE_PREFIX_REPNE) {
2922 /* move them until CX is ZERO. */
2923 while (M.x86.R_CX != 0) {
2924 val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2925 cmp_byte(M.x86.R_AL, val2);
2928 if (ACCESS_FLAG(F_ZF))
2929 break; /* zero flag set means equal */
2931 M.x86.mode &= ~SYSMODE_PREFIX_REPNE;
2933 val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2934 cmp_byte(M.x86.R_AL, val2);
2937 DECODE_CLEAR_SEGOVR();
2941 /****************************************************************************
2944 ****************************************************************************/
2945 void x86emuOp_scas_word(u8 X86EMU_UNUSED(op1))
2951 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2952 DECODE_PRINTF("SCAS\tDWORD\n");
2953 if (ACCESS_FLAG(F_DF)) /* down */
2958 DECODE_PRINTF("SCAS\tWORD\n");
2959 if (ACCESS_FLAG(F_DF)) /* down */
2965 if (M.x86.mode & SYSMODE_PREFIX_REPE) {
2967 /* move them until CX is ZERO. */
2968 while (M.x86.R_CX != 0) {
2969 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2970 val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
2971 cmp_long(M.x86.R_EAX, val);
2973 val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
2974 cmp_word(M.x86.R_AX, (u16)val);
2978 if (ACCESS_FLAG(F_ZF) == 0)
2981 M.x86.mode &= ~SYSMODE_PREFIX_REPE;
2982 } else if (M.x86.mode & SYSMODE_PREFIX_REPNE) {
2984 /* move them until CX is ZERO. */
2985 while (M.x86.R_CX != 0) {
2986 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2987 val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
2988 cmp_long(M.x86.R_EAX, val);
2990 val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
2991 cmp_word(M.x86.R_AX, (u16)val);
2995 if (ACCESS_FLAG(F_ZF))
2996 break; /* zero flag set means equal */
2998 M.x86.mode &= ~SYSMODE_PREFIX_REPNE;
3000 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3001 val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
3002 cmp_long(M.x86.R_EAX, val);
3004 val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
3005 cmp_word(M.x86.R_AX, (u16)val);
3009 DECODE_CLEAR_SEGOVR();
3013 /****************************************************************************
3015 Handles opcode 0xb0 - 0xb7
3016 ****************************************************************************/
3017 void x86emuOp_mov_byte_register_IMM(u8 op1)
3022 DECODE_PRINTF("MOV\t");
3023 ptr = DECODE_RM_BYTE_REGISTER(op1 & 0x7);
3025 imm = fetch_byte_imm();
3026 DECODE_PRINTF2("%x\n", imm);
3029 DECODE_CLEAR_SEGOVR();
3033 /****************************************************************************
3035 Handles opcode 0xb8 - 0xbf
3036 ****************************************************************************/
3037 void x86emuOp_mov_word_register_IMM(u8 X86EMU_UNUSED(op1))
3044 DECODE_PRINTF("MOV\t");
3045 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3047 reg32 = DECODE_RM_LONG_REGISTER(op1);
3048 srcval = fetch_long_imm();
3049 DECODE_PRINTF2(",%x\n", srcval);
3054 reg16 = DECODE_RM_WORD_REGISTER(op1);
3055 srcval = fetch_word_imm();
3056 DECODE_PRINTF2(",%x\n", srcval);
3058 *reg16 = (u16)srcval;
3060 DECODE_CLEAR_SEGOVR();
3064 /****************************************************************************
3067 ****************************************************************************/
3068 void x86emuOp_opcC0_byte_RM_MEM(u8 X86EMU_UNUSED(op1))
3077 * Yet another weirdo special case instruction format. Part of
3078 * the opcode held below in "RH". Doubly nested case would
3079 * result, except that the decoded instruction
3082 FETCH_DECODE_MODRM(mod, rh, rl);
3084 if (DEBUG_DECODE()) {
3085 /* XXX DECODE_PRINTF may be changed to something more
3086 general, so that it is important to leave the strings
3087 in the same format, even though the result is that the
3088 above test is done twice. */
3092 DECODE_PRINTF("ROL\t");
3095 DECODE_PRINTF("ROR\t");
3098 DECODE_PRINTF("RCL\t");
3101 DECODE_PRINTF("RCR\t");
3104 DECODE_PRINTF("SHL\t");
3107 DECODE_PRINTF("SHR\t");
3110 DECODE_PRINTF("SAL\t");
3113 DECODE_PRINTF("SAR\t");
3118 /* know operation, decode the mod byte to find the addressing
3121 DECODE_PRINTF("BYTE PTR ");
3122 destoffset = decode_rmXX_address(mod, rl);
3123 amt = fetch_byte_imm();
3124 DECODE_PRINTF2(",%x\n", amt);
3125 destval = fetch_data_byte(destoffset);
3127 destval = (*opcD0_byte_operation[rh]) (destval, amt);
3128 store_data_byte(destoffset, destval);
3129 } else { /* register to register */
3130 destreg = DECODE_RM_BYTE_REGISTER(rl);
3131 amt = fetch_byte_imm();
3132 DECODE_PRINTF2(",%x\n", amt);
3134 destval = (*opcD0_byte_operation[rh]) (*destreg, amt);
3137 DECODE_CLEAR_SEGOVR();
3141 /****************************************************************************
3144 ****************************************************************************/
3145 void x86emuOp_opcC1_word_RM_MEM(u8 X86EMU_UNUSED(op1))
3152 * Yet another weirdo special case instruction format. Part of
3153 * the opcode held below in "RH". Doubly nested case would
3154 * result, except that the decoded instruction
3157 FETCH_DECODE_MODRM(mod, rh, rl);
3159 if (DEBUG_DECODE()) {
3160 /* XXX DECODE_PRINTF may be changed to something more
3161 general, so that it is important to leave the strings
3162 in the same format, even though the result is that the
3163 above test is done twice. */
3167 DECODE_PRINTF("ROL\t");
3170 DECODE_PRINTF("ROR\t");
3173 DECODE_PRINTF("RCL\t");
3176 DECODE_PRINTF("RCR\t");
3179 DECODE_PRINTF("SHL\t");
3182 DECODE_PRINTF("SHR\t");
3185 DECODE_PRINTF("SAL\t");
3188 DECODE_PRINTF("SAR\t");
3193 /* know operation, decode the mod byte to find the addressing
3196 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3199 DECODE_PRINTF("DWORD PTR ");
3200 destoffset = decode_rmXX_address(mod, rl);
3201 amt = fetch_byte_imm();
3202 DECODE_PRINTF2(",%x\n", amt);
3203 destval = fetch_data_long(destoffset);
3205 destval = (*opcD1_long_operation[rh]) (destval, amt);
3206 store_data_long(destoffset, destval);
3210 DECODE_PRINTF("WORD PTR ");
3211 destoffset = decode_rmXX_address(mod, rl);
3212 amt = fetch_byte_imm();
3213 DECODE_PRINTF2(",%x\n", amt);
3214 destval = fetch_data_word(destoffset);
3216 destval = (*opcD1_word_operation[rh]) (destval, amt);
3217 store_data_word(destoffset, destval);
3219 } else { /* register to register */
3220 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3223 destreg = DECODE_RM_LONG_REGISTER(rl);
3224 amt = fetch_byte_imm();
3225 DECODE_PRINTF2(",%x\n", amt);
3227 *destreg = (*opcD1_long_operation[rh]) (*destreg, amt);
3231 destreg = DECODE_RM_WORD_REGISTER(rl);
3232 amt = fetch_byte_imm();
3233 DECODE_PRINTF2(",%x\n", amt);
3235 *destreg = (*opcD1_word_operation[rh]) (*destreg, amt);
3238 DECODE_CLEAR_SEGOVR();
3242 /****************************************************************************
3245 ****************************************************************************/
3246 void x86emuOp_ret_near_IMM(u8 X86EMU_UNUSED(op1))
3251 DECODE_PRINTF("RET\t");
3252 imm = fetch_word_imm();
3253 DECODE_PRINTF2("%x\n", imm);
3254 RETURN_TRACE("RET",M.x86.saved_cs,M.x86.saved_ip);
3256 M.x86.R_IP = pop_word();
3258 DECODE_CLEAR_SEGOVR();
3262 /****************************************************************************
3265 ****************************************************************************/
3266 void x86emuOp_ret_near(u8 X86EMU_UNUSED(op1))
3269 DECODE_PRINTF("RET\n");
3270 RETURN_TRACE("RET",M.x86.saved_cs,M.x86.saved_ip);
3272 M.x86.R_IP = pop_word();
3273 DECODE_CLEAR_SEGOVR();
3277 /****************************************************************************
3280 ****************************************************************************/
3281 void x86emuOp_les_R_IMM(u8 X86EMU_UNUSED(op1))
3288 DECODE_PRINTF("LES\t");
3289 FETCH_DECODE_MODRM(mod, rh, rl);
3291 dstreg = DECODE_RM_WORD_REGISTER(rh);
3293 srcoffset = decode_rmXX_address(mod, rl);
3294 DECODE_PRINTF("\n");
3296 *dstreg = fetch_data_word(srcoffset);
3297 M.x86.R_ES = fetch_data_word(srcoffset + 2);
3299 /* else UNDEFINED! register to register */
3301 DECODE_CLEAR_SEGOVR();
3305 /****************************************************************************
3308 ****************************************************************************/
3309 void x86emuOp_lds_R_IMM(u8 X86EMU_UNUSED(op1))
3316 DECODE_PRINTF("LDS\t");
3317 FETCH_DECODE_MODRM(mod, rh, rl);
3319 dstreg = DECODE_RM_WORD_REGISTER(rh);
3321 srcoffset = decode_rmXX_address(mod, rl);
3322 DECODE_PRINTF("\n");
3324 *dstreg = fetch_data_word(srcoffset);
3325 M.x86.R_DS = fetch_data_word(srcoffset + 2);
3327 /* else UNDEFINED! */
3328 DECODE_CLEAR_SEGOVR();
3332 /****************************************************************************
3335 ****************************************************************************/
3336 void x86emuOp_mov_byte_RM_IMM(u8 X86EMU_UNUSED(op1))
3344 DECODE_PRINTF("MOV\t");
3345 FETCH_DECODE_MODRM(mod, rh, rl);
3347 DECODE_PRINTF("ILLEGAL DECODE OF OPCODE c6\n");
3351 DECODE_PRINTF("BYTE PTR ");
3352 destoffset = decode_rmXX_address(mod, rl);
3353 imm = fetch_byte_imm();
3354 DECODE_PRINTF2(",%2x\n", imm);
3356 store_data_byte(destoffset, imm);
3357 } else { /* register to register */
3358 destreg = DECODE_RM_BYTE_REGISTER(rl);
3359 imm = fetch_byte_imm();
3360 DECODE_PRINTF2(",%2x\n", imm);
3364 DECODE_CLEAR_SEGOVR();
3368 /****************************************************************************
3371 ****************************************************************************/
3372 void x86emuOp_mov_word_RM_IMM(u8 X86EMU_UNUSED(op1))
3378 DECODE_PRINTF("MOV\t");
3379 FETCH_DECODE_MODRM(mod, rh, rl);
3381 DECODE_PRINTF("ILLEGAL DECODE OF OPCODE 8F\n");
3385 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3388 DECODE_PRINTF("DWORD PTR ");
3389 destoffset = decode_rmXX_address(mod, rl);
3390 imm = fetch_long_imm();
3391 DECODE_PRINTF2(",%x\n", imm);
3393 store_data_long(destoffset, imm);
3397 DECODE_PRINTF("WORD PTR ");
3398 destoffset = decode_rmXX_address(mod, rl);
3399 imm = fetch_word_imm();
3400 DECODE_PRINTF2(",%x\n", imm);
3402 store_data_word(destoffset, imm);
3404 } else { /* register to register */
3405 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3409 destreg = DECODE_RM_LONG_REGISTER(rl);
3410 imm = fetch_long_imm();
3411 DECODE_PRINTF2(",%x\n", imm);
3418 destreg = DECODE_RM_WORD_REGISTER(rl);
3419 imm = fetch_word_imm();
3420 DECODE_PRINTF2(",%x\n", imm);
3425 DECODE_CLEAR_SEGOVR();
3429 /****************************************************************************
3432 ****************************************************************************/
3433 void x86emuOp_enter(u8 X86EMU_UNUSED(op1))
3435 u16 local,frame_pointer;
3440 local = fetch_word_imm();
3441 nesting = fetch_byte_imm();
3442 DECODE_PRINTF2("ENTER %x\n", local);
3443 DECODE_PRINTF2(",%x\n", nesting);
3445 push_word(M.x86.R_BP);
3446 frame_pointer = M.x86.R_SP;
3448 for (i = 1; i < nesting; i++) {
3450 push_word(fetch_data_word_abs(M.x86.R_SS, M.x86.R_BP));
3452 push_word(frame_pointer);
3454 M.x86.R_BP = frame_pointer;
3455 M.x86.R_SP = (u16)(M.x86.R_SP - local);
3456 DECODE_CLEAR_SEGOVR();
3460 /****************************************************************************
3463 ****************************************************************************/
3464 void x86emuOp_leave(u8 X86EMU_UNUSED(op1))
3467 DECODE_PRINTF("LEAVE\n");
3469 M.x86.R_SP = M.x86.R_BP;
3470 M.x86.R_BP = pop_word();
3471 DECODE_CLEAR_SEGOVR();
3475 /****************************************************************************
3478 ****************************************************************************/
3479 void x86emuOp_ret_far_IMM(u8 X86EMU_UNUSED(op1))
3484 DECODE_PRINTF("RETF\t");
3485 imm = fetch_word_imm();
3486 DECODE_PRINTF2("%x\n", imm);
3487 RETURN_TRACE("RETF",M.x86.saved_cs,M.x86.saved_ip);
3489 M.x86.R_IP = pop_word();
3490 M.x86.R_CS = pop_word();
3492 DECODE_CLEAR_SEGOVR();
3496 /****************************************************************************
3499 ****************************************************************************/
3500 void x86emuOp_ret_far(u8 X86EMU_UNUSED(op1))
3503 DECODE_PRINTF("RETF\n");
3504 RETURN_TRACE("RETF",M.x86.saved_cs,M.x86.saved_ip);
3506 M.x86.R_IP = pop_word();
3507 M.x86.R_CS = pop_word();
3508 DECODE_CLEAR_SEGOVR();
3512 /****************************************************************************
3515 ****************************************************************************/
3516 void x86emuOp_int3(u8 X86EMU_UNUSED(op1))
3521 DECODE_PRINTF("INT 3\n");
3522 tmp = (u16) mem_access_word(3 * 4 + 2);
3523 /* access the segment register */
3525 if (_X86EMU_intrTab[3]) {
3526 (*_X86EMU_intrTab[3])(3);
3528 push_word((u16)M.x86.R_FLG);
3531 push_word(M.x86.R_CS);
3532 M.x86.R_CS = mem_access_word(3 * 4 + 2);
3533 push_word(M.x86.R_IP);
3534 M.x86.R_IP = mem_access_word(3 * 4);
3536 DECODE_CLEAR_SEGOVR();
3540 /****************************************************************************
3543 ****************************************************************************/
3544 void x86emuOp_int_IMM(u8 X86EMU_UNUSED(op1))
3550 DECODE_PRINTF("INT\t");
3551 intnum = fetch_byte_imm();
3552 DECODE_PRINTF2("%x\n", intnum);
3553 tmp = mem_access_word(intnum * 4 + 2);
3555 if (_X86EMU_intrTab[intnum]) {
3556 (*_X86EMU_intrTab[intnum])(intnum);
3558 push_word((u16)M.x86.R_FLG);
3561 push_word(M.x86.R_CS);
3562 M.x86.R_CS = mem_access_word(intnum * 4 + 2);
3563 push_word(M.x86.R_IP);
3564 M.x86.R_IP = mem_access_word(intnum * 4);
3566 DECODE_CLEAR_SEGOVR();
3570 /****************************************************************************
3573 ****************************************************************************/
3574 void x86emuOp_into(u8 X86EMU_UNUSED(op1))
3579 DECODE_PRINTF("INTO\n");
3581 if (ACCESS_FLAG(F_OF)) {
3582 tmp = mem_access_word(4 * 4 + 2);
3583 if (_X86EMU_intrTab[4]) {
3584 (*_X86EMU_intrTab[4])(4);
3586 push_word((u16)M.x86.R_FLG);
3589 push_word(M.x86.R_CS);
3590 M.x86.R_CS = mem_access_word(4 * 4 + 2);
3591 push_word(M.x86.R_IP);
3592 M.x86.R_IP = mem_access_word(4 * 4);
3595 DECODE_CLEAR_SEGOVR();
3599 /****************************************************************************
3602 ****************************************************************************/
3603 void x86emuOp_iret(u8 X86EMU_UNUSED(op1))
3606 DECODE_PRINTF("IRET\n");
3610 M.x86.R_IP = pop_word();
3611 M.x86.R_CS = pop_word();
3612 M.x86.R_FLG = pop_word();
3613 DECODE_CLEAR_SEGOVR();
3617 /****************************************************************************
3620 ****************************************************************************/
3621 void x86emuOp_opcD0_byte_RM_1(u8 X86EMU_UNUSED(op1))
3629 * Yet another weirdo special case instruction format. Part of
3630 * the opcode held below in "RH". Doubly nested case would
3631 * result, except that the decoded instruction
3634 FETCH_DECODE_MODRM(mod, rh, rl);
3636 if (DEBUG_DECODE()) {
3637 /* XXX DECODE_PRINTF may be changed to something more
3638 general, so that it is important to leave the strings
3639 in the same format, even though the result is that the
3640 above test is done twice. */
3643 DECODE_PRINTF("ROL\t");
3646 DECODE_PRINTF("ROR\t");
3649 DECODE_PRINTF("RCL\t");
3652 DECODE_PRINTF("RCR\t");
3655 DECODE_PRINTF("SHL\t");
3658 DECODE_PRINTF("SHR\t");
3661 DECODE_PRINTF("SAL\t");
3664 DECODE_PRINTF("SAR\t");
3669 /* know operation, decode the mod byte to find the addressing
3672 DECODE_PRINTF("BYTE PTR ");
3673 destoffset = decode_rmXX_address(mod, rl);
3674 DECODE_PRINTF(",1\n");
3675 destval = fetch_data_byte(destoffset);
3677 destval = (*opcD0_byte_operation[rh]) (destval, 1);
3678 store_data_byte(destoffset, destval);
3679 } else { /* register to register */
3680 destreg = DECODE_RM_BYTE_REGISTER(rl);
3681 DECODE_PRINTF(",1\n");
3683 destval = (*opcD0_byte_operation[rh]) (*destreg, 1);
3686 DECODE_CLEAR_SEGOVR();
3690 /****************************************************************************
3693 ****************************************************************************/
3694 void x86emuOp_opcD1_word_RM_1(u8 X86EMU_UNUSED(op1))
3700 * Yet another weirdo special case instruction format. Part of
3701 * the opcode held below in "RH". Doubly nested case would
3702 * result, except that the decoded instruction
3705 FETCH_DECODE_MODRM(mod, rh, rl);
3707 if (DEBUG_DECODE()) {
3708 /* XXX DECODE_PRINTF may be changed to something more
3709 general, so that it is important to leave the strings
3710 in the same format, even though the result is that the
3711 above test is done twice. */
3714 DECODE_PRINTF("ROL\t");
3717 DECODE_PRINTF("ROR\t");
3720 DECODE_PRINTF("RCL\t");
3723 DECODE_PRINTF("RCR\t");
3726 DECODE_PRINTF("SHL\t");
3729 DECODE_PRINTF("SHR\t");
3732 DECODE_PRINTF("SAL\t");
3735 DECODE_PRINTF("SAR\t");
3740 /* know operation, decode the mod byte to find the addressing
3743 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3746 DECODE_PRINTF("DWORD PTR ");
3747 destoffset = decode_rmXX_address(mod, rl);
3748 DECODE_PRINTF(",1\n");
3749 destval = fetch_data_long(destoffset);
3751 destval = (*opcD1_long_operation[rh]) (destval, 1);
3752 store_data_long(destoffset, destval);
3756 DECODE_PRINTF("WORD PTR ");
3757 destoffset = decode_rmXX_address(mod, rl);
3758 DECODE_PRINTF(",1\n");
3759 destval = fetch_data_word(destoffset);
3761 destval = (*opcD1_word_operation[rh]) (destval, 1);
3762 store_data_word(destoffset, destval);
3764 } else { /* register to register */
3765 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3769 destreg = DECODE_RM_LONG_REGISTER(rl);
3770 DECODE_PRINTF(",1\n");
3772 destval = (*opcD1_long_operation[rh]) (*destreg, 1);
3778 destreg = DECODE_RM_WORD_REGISTER(rl);
3779 DECODE_PRINTF(",1\n");
3781 destval = (*opcD1_word_operation[rh]) (*destreg, 1);
3785 DECODE_CLEAR_SEGOVR();
3789 /****************************************************************************
3792 ****************************************************************************/
3793 void x86emuOp_opcD2_byte_RM_CL(u8 X86EMU_UNUSED(op1))
3802 * Yet another weirdo special case instruction format. Part of
3803 * the opcode held below in "RH". Doubly nested case would
3804 * result, except that the decoded instruction
3807 FETCH_DECODE_MODRM(mod, rh, rl);
3809 if (DEBUG_DECODE()) {
3810 /* XXX DECODE_PRINTF may be changed to something more
3811 general, so that it is important to leave the strings
3812 in the same format, even though the result is that the
3813 above test is done twice. */
3816 DECODE_PRINTF("ROL\t");
3819 DECODE_PRINTF("ROR\t");
3822 DECODE_PRINTF("RCL\t");
3825 DECODE_PRINTF("RCR\t");
3828 DECODE_PRINTF("SHL\t");
3831 DECODE_PRINTF("SHR\t");
3834 DECODE_PRINTF("SAL\t");
3837 DECODE_PRINTF("SAR\t");
3842 /* know operation, decode the mod byte to find the addressing
3846 DECODE_PRINTF("BYTE PTR ");
3847 destoffset = decode_rmXX_address(mod, rl);
3848 DECODE_PRINTF(",CL\n");
3849 destval = fetch_data_byte(destoffset);
3851 destval = (*opcD0_byte_operation[rh]) (destval, amt);
3852 store_data_byte(destoffset, destval);
3853 } else { /* register to register */
3854 destreg = DECODE_RM_BYTE_REGISTER(rl);
3855 DECODE_PRINTF(",CL\n");
3857 destval = (*opcD0_byte_operation[rh]) (*destreg, amt);
3860 DECODE_CLEAR_SEGOVR();
3864 /****************************************************************************
3867 ****************************************************************************/
3868 void x86emuOp_opcD3_word_RM_CL(u8 X86EMU_UNUSED(op1))
3875 * Yet another weirdo special case instruction format. Part of
3876 * the opcode held below in "RH". Doubly nested case would
3877 * result, except that the decoded instruction
3880 FETCH_DECODE_MODRM(mod, rh, rl);
3882 if (DEBUG_DECODE()) {
3883 /* XXX DECODE_PRINTF may be changed to something more
3884 general, so that it is important to leave the strings
3885 in the same format, even though the result is that the
3886 above test is done twice. */
3889 DECODE_PRINTF("ROL\t");
3892 DECODE_PRINTF("ROR\t");
3895 DECODE_PRINTF("RCL\t");
3898 DECODE_PRINTF("RCR\t");
3901 DECODE_PRINTF("SHL\t");
3904 DECODE_PRINTF("SHR\t");
3907 DECODE_PRINTF("SAL\t");
3910 DECODE_PRINTF("SAR\t");
3915 /* know operation, decode the mod byte to find the addressing
3919 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3922 DECODE_PRINTF("DWORD PTR ");
3923 destoffset = decode_rmXX_address(mod, rl);
3924 DECODE_PRINTF(",CL\n");
3925 destval = fetch_data_long(destoffset);
3927 destval = (*opcD1_long_operation[rh]) (destval, amt);
3928 store_data_long(destoffset, destval);
3932 DECODE_PRINTF("WORD PTR ");
3933 destoffset = decode_rmXX_address(mod, rl);
3934 DECODE_PRINTF(",CL\n");
3935 destval = fetch_data_word(destoffset);
3937 destval = (*opcD1_word_operation[rh]) (destval, amt);
3938 store_data_word(destoffset, destval);
3940 } else { /* register to register */
3941 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3944 destreg = DECODE_RM_LONG_REGISTER(rl);
3945 DECODE_PRINTF(",CL\n");
3947 *destreg = (*opcD1_long_operation[rh]) (*destreg, amt);
3951 destreg = DECODE_RM_WORD_REGISTER(rl);
3952 DECODE_PRINTF(",CL\n");
3954 *destreg = (*opcD1_word_operation[rh]) (*destreg, amt);
3957 DECODE_CLEAR_SEGOVR();
3961 /****************************************************************************
3964 ****************************************************************************/
3965 void x86emuOp_aam(u8 X86EMU_UNUSED(op1))
3970 DECODE_PRINTF("AAM\n");
3971 a = fetch_byte_imm(); /* this is a stupid encoding. */
3973 DECODE_PRINTF("ERROR DECODING AAM\n");
3978 /* note the type change here --- returning AL and AH in AX. */
3979 M.x86.R_AX = aam_word(M.x86.R_AL);
3980 DECODE_CLEAR_SEGOVR();
3984 /****************************************************************************
3987 ****************************************************************************/
3988 void x86emuOp_aad(u8 X86EMU_UNUSED(op1))
3993 DECODE_PRINTF("AAD\n");
3994 a = fetch_byte_imm();
3996 M.x86.R_AX = aad_word(M.x86.R_AX);
3997 DECODE_CLEAR_SEGOVR();
4001 /* opcode 0xd6 ILLEGAL OPCODE */
4003 /****************************************************************************
4006 ****************************************************************************/
4007 void x86emuOp_xlat(u8 X86EMU_UNUSED(op1))
4012 DECODE_PRINTF("XLAT\n");
4014 addr = (u16)(M.x86.R_BX + (u8)M.x86.R_AL);
4015 M.x86.R_AL = fetch_data_byte(addr);
4016 DECODE_CLEAR_SEGOVR();
4020 /* instuctions D8 .. DF are in i87_ops.c */
4022 /****************************************************************************
4025 ****************************************************************************/
4026 void x86emuOp_loopne(u8 X86EMU_UNUSED(op1))
4031 DECODE_PRINTF("LOOPNE\t");
4032 ip = (s8) fetch_byte_imm();
4033 ip += (s16) M.x86.R_IP;
4034 DECODE_PRINTF2("%04x\n", ip);
4037 if (M.x86.R_CX != 0 && !ACCESS_FLAG(F_ZF)) /* CX != 0 and !ZF */
4039 DECODE_CLEAR_SEGOVR();
4043 /****************************************************************************
4046 ****************************************************************************/
4047 void x86emuOp_loope(u8 X86EMU_UNUSED(op1))
4052 DECODE_PRINTF("LOOPE\t");
4053 ip = (s8) fetch_byte_imm();
4054 ip += (s16) M.x86.R_IP;
4055 DECODE_PRINTF2("%04x\n", ip);
4058 if (M.x86.R_CX != 0 && ACCESS_FLAG(F_ZF)) /* CX != 0 and ZF */
4060 DECODE_CLEAR_SEGOVR();
4064 /****************************************************************************
4067 ****************************************************************************/
4068 void x86emuOp_loop(u8 X86EMU_UNUSED(op1))
4073 DECODE_PRINTF("LOOP\t");
4074 ip = (s8) fetch_byte_imm();
4075 ip += (s16) M.x86.R_IP;
4076 DECODE_PRINTF2("%04x\n", ip);
4079 if (M.x86.R_CX != 0)
4081 DECODE_CLEAR_SEGOVR();
4085 /****************************************************************************
4088 ****************************************************************************/
4089 void x86emuOp_jcxz(u8 X86EMU_UNUSED(op1))
4094 /* jump to byte offset if overflow flag is set */
4096 DECODE_PRINTF("JCXZ\t");
4097 offset = (s8)fetch_byte_imm();
4098 target = (u16)(M.x86.R_IP + offset);
4099 DECODE_PRINTF2("%x\n", target);
4101 if (M.x86.R_CX == 0)
4102 M.x86.R_IP = target;
4103 DECODE_CLEAR_SEGOVR();
4107 /****************************************************************************
4110 ****************************************************************************/
4111 void x86emuOp_in_byte_AL_IMM(u8 X86EMU_UNUSED(op1))
4116 DECODE_PRINTF("IN\t");
4117 port = (u8) fetch_byte_imm();
4118 DECODE_PRINTF2("%x,AL\n", port);
4120 M.x86.R_AL = (*sys_inb)(port);
4121 DECODE_CLEAR_SEGOVR();
4125 /****************************************************************************
4128 ****************************************************************************/
4129 void x86emuOp_in_word_AX_IMM(u8 X86EMU_UNUSED(op1))
4134 DECODE_PRINTF("IN\t");
4135 port = (u8) fetch_byte_imm();
4136 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4137 DECODE_PRINTF2("EAX,%x\n", port);
4139 DECODE_PRINTF2("AX,%x\n", port);
4142 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4143 M.x86.R_EAX = (*sys_inl)(port);
4145 M.x86.R_AX = (*sys_inw)(port);
4147 DECODE_CLEAR_SEGOVR();
4151 /****************************************************************************
4154 ****************************************************************************/
4155 void x86emuOp_out_byte_IMM_AL(u8 X86EMU_UNUSED(op1))
4160 DECODE_PRINTF("OUT\t");
4161 port = (u8) fetch_byte_imm();
4162 DECODE_PRINTF2("%x,AL\n", port);
4164 (*sys_outb)(port, M.x86.R_AL);
4165 DECODE_CLEAR_SEGOVR();
4169 /****************************************************************************
4172 ****************************************************************************/
4173 void x86emuOp_out_word_IMM_AX(u8 X86EMU_UNUSED(op1))
4178 DECODE_PRINTF("OUT\t");
4179 port = (u8) fetch_byte_imm();
4180 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4181 DECODE_PRINTF2("%x,EAX\n", port);
4183 DECODE_PRINTF2("%x,AX\n", port);
4186 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4187 (*sys_outl)(port, M.x86.R_EAX);
4189 (*sys_outw)(port, M.x86.R_AX);
4191 DECODE_CLEAR_SEGOVR();
4195 /****************************************************************************
4198 ****************************************************************************/
4199 void x86emuOp_call_near_IMM(u8 X86EMU_UNUSED(op1))
4204 DECODE_PRINTF("CALL\t");
4205 ip = (s16) fetch_word_imm();
4206 ip += (s16) M.x86.R_IP; /* CHECK SIGN */
4207 DECODE_PRINTF2("%04x\n", ip);
4208 CALL_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, ip, "");
4210 push_word(M.x86.R_IP);
4212 DECODE_CLEAR_SEGOVR();
4216 /****************************************************************************
4219 ****************************************************************************/
4220 void x86emuOp_jump_near_IMM(u8 X86EMU_UNUSED(op1))
4225 DECODE_PRINTF("JMP\t");
4226 ip = (s16)fetch_word_imm();
4227 ip += (s16)M.x86.R_IP;
4228 DECODE_PRINTF2("%04x\n", ip);
4230 M.x86.R_IP = (u16)ip;
4231 DECODE_CLEAR_SEGOVR();
4235 /****************************************************************************
4238 ****************************************************************************/
4239 void x86emuOp_jump_far_IMM(u8 X86EMU_UNUSED(op1))
4244 DECODE_PRINTF("JMP\tFAR ");
4245 ip = fetch_word_imm();
4246 cs = fetch_word_imm();
4247 DECODE_PRINTF2("%04x:", cs);
4248 DECODE_PRINTF2("%04x\n", ip);
4252 DECODE_CLEAR_SEGOVR();
4256 /****************************************************************************
4259 ****************************************************************************/
4260 void x86emuOp_jump_byte_IMM(u8 X86EMU_UNUSED(op1))
4266 DECODE_PRINTF("JMP\t");
4267 offset = (s8)fetch_byte_imm();
4268 target = (u16)(M.x86.R_IP + offset);
4269 DECODE_PRINTF2("%x\n", target);
4271 M.x86.R_IP = target;
4272 DECODE_CLEAR_SEGOVR();
4276 /****************************************************************************
4279 ****************************************************************************/
4280 void x86emuOp_in_byte_AL_DX(u8 X86EMU_UNUSED(op1))
4283 DECODE_PRINTF("IN\tAL,DX\n");
4285 M.x86.R_AL = (*sys_inb)(M.x86.R_DX);
4286 DECODE_CLEAR_SEGOVR();
4290 /****************************************************************************
4293 ****************************************************************************/
4294 void x86emuOp_in_word_AX_DX(u8 X86EMU_UNUSED(op1))
4297 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4298 DECODE_PRINTF("IN\tEAX,DX\n");
4300 DECODE_PRINTF("IN\tAX,DX\n");
4303 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4304 M.x86.R_EAX = (*sys_inl)(M.x86.R_DX);
4306 M.x86.R_AX = (*sys_inw)(M.x86.R_DX);
4308 DECODE_CLEAR_SEGOVR();
4312 /****************************************************************************
4315 ****************************************************************************/
4316 void x86emuOp_out_byte_DX_AL(u8 X86EMU_UNUSED(op1))
4319 DECODE_PRINTF("OUT\tDX,AL\n");
4321 (*sys_outb)(M.x86.R_DX, M.x86.R_AL);
4322 DECODE_CLEAR_SEGOVR();
4326 /****************************************************************************
4329 ****************************************************************************/
4330 void x86emuOp_out_word_DX_AX(u8 X86EMU_UNUSED(op1))
4333 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4334 DECODE_PRINTF("OUT\tDX,EAX\n");
4336 DECODE_PRINTF("OUT\tDX,AX\n");
4339 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4340 (*sys_outl)(M.x86.R_DX, M.x86.R_EAX);
4342 (*sys_outw)(M.x86.R_DX, M.x86.R_AX);
4344 DECODE_CLEAR_SEGOVR();
4348 /****************************************************************************
4351 ****************************************************************************/
4352 void x86emuOp_lock(u8 X86EMU_UNUSED(op1))
4355 DECODE_PRINTF("LOCK:\n");
4357 DECODE_CLEAR_SEGOVR();
4361 /*opcode 0xf1 ILLEGAL OPERATION */
4363 /****************************************************************************
4366 ****************************************************************************/
4367 void x86emuOp_repne(u8 X86EMU_UNUSED(op1))
4370 DECODE_PRINTF("REPNE\n");
4372 M.x86.mode |= SYSMODE_PREFIX_REPNE;
4373 DECODE_CLEAR_SEGOVR();
4377 /****************************************************************************
4380 ****************************************************************************/
4381 void x86emuOp_repe(u8 X86EMU_UNUSED(op1))
4384 DECODE_PRINTF("REPE\n");
4386 M.x86.mode |= SYSMODE_PREFIX_REPE;
4387 DECODE_CLEAR_SEGOVR();
4391 /****************************************************************************
4394 ****************************************************************************/
4395 void x86emuOp_halt(u8 X86EMU_UNUSED(op1))
4398 DECODE_PRINTF("HALT\n");
4401 DECODE_CLEAR_SEGOVR();
4405 /****************************************************************************
4408 ****************************************************************************/
4409 void x86emuOp_cmc(u8 X86EMU_UNUSED(op1))
4411 /* complement the carry flag. */
4413 DECODE_PRINTF("CMC\n");
4416 DECODE_CLEAR_SEGOVR();
4420 /****************************************************************************
4423 ****************************************************************************/
4424 void x86emuOp_opcF6_byte_RM(u8 X86EMU_UNUSED(op1))
4431 /* long, drawn out code follows. Double switch for a total
4434 FETCH_DECODE_MODRM(mod, rh, rl);
4435 DECODE_PRINTF(opF6_names[rh]);
4437 DECODE_PRINTF("BYTE PTR ");
4438 destoffset = decode_rmXX_address(mod, rl);
4439 destval = fetch_data_byte(destoffset);
4442 case 0: /* test byte imm */
4444 srcval = fetch_byte_imm();
4445 DECODE_PRINTF2("%02x\n", srcval);
4447 test_byte(destval, srcval);
4450 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4454 DECODE_PRINTF("\n");
4456 destval = not_byte(destval);
4457 store_data_byte(destoffset, destval);
4460 DECODE_PRINTF("\n");
4462 destval = neg_byte(destval);
4463 store_data_byte(destoffset, destval);
4466 DECODE_PRINTF("\n");
4471 DECODE_PRINTF("\n");
4476 DECODE_PRINTF("\n");
4481 DECODE_PRINTF("\n");
4486 } else { /* mod=11 */
4487 destreg = DECODE_RM_BYTE_REGISTER(rl);
4489 case 0: /* test byte imm */
4491 srcval = fetch_byte_imm();
4492 DECODE_PRINTF2("%02x\n", srcval);
4494 test_byte(*destreg, srcval);
4497 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4501 DECODE_PRINTF("\n");
4503 *destreg = not_byte(*destreg);
4506 DECODE_PRINTF("\n");
4508 *destreg = neg_byte(*destreg);
4511 DECODE_PRINTF("\n");
4513 mul_byte(*destreg); /*!!! */
4516 DECODE_PRINTF("\n");
4518 imul_byte(*destreg);
4521 DECODE_PRINTF("\n");
4526 DECODE_PRINTF("\n");
4528 idiv_byte(*destreg);
4532 DECODE_CLEAR_SEGOVR();
4536 /****************************************************************************
4539 ****************************************************************************/
4540 void x86emuOp_opcF7_word_RM(u8 X86EMU_UNUSED(op1))
4546 FETCH_DECODE_MODRM(mod, rh, rl);
4547 DECODE_PRINTF(opF6_names[rh]);
4550 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4551 u32 destval, srcval;
4553 DECODE_PRINTF("DWORD PTR ");
4554 destoffset = decode_rmXX_address(mod, rl);
4555 destval = fetch_data_long(destoffset);
4560 srcval = fetch_long_imm();
4561 DECODE_PRINTF2("%x\n", srcval);
4563 test_long(destval, srcval);
4566 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F7\n");
4570 DECODE_PRINTF("\n");
4572 destval = not_long(destval);
4573 store_data_long(destoffset, destval);
4576 DECODE_PRINTF("\n");
4578 destval = neg_long(destval);
4579 store_data_long(destoffset, destval);
4582 DECODE_PRINTF("\n");
4587 DECODE_PRINTF("\n");
4592 DECODE_PRINTF("\n");
4597 DECODE_PRINTF("\n");
4603 u16 destval, srcval;
4605 DECODE_PRINTF("WORD PTR ");
4606 destoffset = decode_rmXX_address(mod, rl);
4607 destval = fetch_data_word(destoffset);
4610 case 0: /* test word imm */
4612 srcval = fetch_word_imm();
4613 DECODE_PRINTF2("%x\n", srcval);
4615 test_word(destval, srcval);
4618 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F7\n");
4622 DECODE_PRINTF("\n");
4624 destval = not_word(destval);
4625 store_data_word(destoffset, destval);
4628 DECODE_PRINTF("\n");
4630 destval = neg_word(destval);
4631 store_data_word(destoffset, destval);
4634 DECODE_PRINTF("\n");
4639 DECODE_PRINTF("\n");
4644 DECODE_PRINTF("\n");
4649 DECODE_PRINTF("\n");
4656 } else { /* mod=11 */
4658 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4662 destreg = DECODE_RM_LONG_REGISTER(rl);
4665 case 0: /* test word imm */
4667 srcval = fetch_long_imm();
4668 DECODE_PRINTF2("%x\n", srcval);
4670 test_long(*destreg, srcval);
4673 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4677 DECODE_PRINTF("\n");
4679 *destreg = not_long(*destreg);
4682 DECODE_PRINTF("\n");
4684 *destreg = neg_long(*destreg);
4687 DECODE_PRINTF("\n");
4689 mul_long(*destreg); /*!!! */
4692 DECODE_PRINTF("\n");
4694 imul_long(*destreg);
4697 DECODE_PRINTF("\n");
4702 DECODE_PRINTF("\n");
4704 idiv_long(*destreg);
4711 destreg = DECODE_RM_WORD_REGISTER(rl);
4714 case 0: /* test word imm */
4716 srcval = fetch_word_imm();
4717 DECODE_PRINTF2("%x\n", srcval);
4719 test_word(*destreg, srcval);
4722 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4726 DECODE_PRINTF("\n");
4728 *destreg = not_word(*destreg);
4731 DECODE_PRINTF("\n");
4733 *destreg = neg_word(*destreg);
4736 DECODE_PRINTF("\n");
4738 mul_word(*destreg); /*!!! */
4741 DECODE_PRINTF("\n");
4743 imul_word(*destreg);
4746 DECODE_PRINTF("\n");
4751 DECODE_PRINTF("\n");
4753 idiv_word(*destreg);
4758 DECODE_CLEAR_SEGOVR();
4762 /****************************************************************************
4765 ****************************************************************************/
4766 void x86emuOp_clc(u8 X86EMU_UNUSED(op1))
4768 /* clear the carry flag. */
4770 DECODE_PRINTF("CLC\n");
4773 DECODE_CLEAR_SEGOVR();
4777 /****************************************************************************
4780 ****************************************************************************/
4781 void x86emuOp_stc(u8 X86EMU_UNUSED(op1))
4783 /* set the carry flag. */
4785 DECODE_PRINTF("STC\n");
4788 DECODE_CLEAR_SEGOVR();
4792 /****************************************************************************
4795 ****************************************************************************/
4796 void x86emuOp_cli(u8 X86EMU_UNUSED(op1))
4798 /* clear interrupts. */
4800 DECODE_PRINTF("CLI\n");
4803 DECODE_CLEAR_SEGOVR();
4807 /****************************************************************************
4810 ****************************************************************************/
4811 void x86emuOp_sti(u8 X86EMU_UNUSED(op1))
4813 /* enable interrupts. */
4815 DECODE_PRINTF("STI\n");
4818 DECODE_CLEAR_SEGOVR();
4822 /****************************************************************************
4825 ****************************************************************************/
4826 void x86emuOp_cld(u8 X86EMU_UNUSED(op1))
4828 /* clear interrupts. */
4830 DECODE_PRINTF("CLD\n");
4833 DECODE_CLEAR_SEGOVR();
4837 /****************************************************************************
4840 ****************************************************************************/
4841 void x86emuOp_std(u8 X86EMU_UNUSED(op1))
4843 /* clear interrupts. */
4845 DECODE_PRINTF("STD\n");
4848 DECODE_CLEAR_SEGOVR();
4852 /****************************************************************************
4855 ****************************************************************************/
4856 void x86emuOp_opcFE_byte_RM(u8 X86EMU_UNUSED(op1))
4863 /* Yet another special case instruction. */
4865 FETCH_DECODE_MODRM(mod, rh, rl);
4867 if (DEBUG_DECODE()) {
4868 /* XXX DECODE_PRINTF may be changed to something more
4869 general, so that it is important to leave the strings
4870 in the same format, even though the result is that the
4871 above test is done twice. */
4875 DECODE_PRINTF("INC\t");
4878 DECODE_PRINTF("DEC\t");
4886 DECODE_PRINTF2("ILLEGAL OP MAJOR OP 0xFE MINOR OP %x \n", mod);
4893 DECODE_PRINTF("BYTE PTR ");
4894 destoffset = decode_rmXX_address(mod, rl);
4895 DECODE_PRINTF("\n");
4896 destval = fetch_data_byte(destoffset);
4899 destval = inc_byte(destval);
4901 destval = dec_byte(destval);
4902 store_data_byte(destoffset, destval);
4904 destreg = DECODE_RM_BYTE_REGISTER(rl);
4905 DECODE_PRINTF("\n");
4908 *destreg = inc_byte(*destreg);
4910 *destreg = dec_byte(*destreg);
4912 DECODE_CLEAR_SEGOVR();
4916 /****************************************************************************
4919 ****************************************************************************/
4920 void x86emuOp_opcFF_word_RM(u8 X86EMU_UNUSED(op1))
4923 uint destoffset = 0;
4925 u16 destval,destval2;
4927 /* Yet another special case instruction. */
4929 FETCH_DECODE_MODRM(mod, rh, rl);
4931 if (DEBUG_DECODE()) {
4932 /* XXX DECODE_PRINTF may be changed to something more
4933 general, so that it is important to leave the strings
4934 in the same format, even though the result is that the
4935 above test is done twice. */
4939 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4940 DECODE_PRINTF("INC\tDWORD PTR ");
4942 DECODE_PRINTF("INC\tWORD PTR ");
4946 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4947 DECODE_PRINTF("DEC\tDWORD PTR ");
4949 DECODE_PRINTF("DEC\tWORD PTR ");
4953 DECODE_PRINTF("CALL\t ");
4956 DECODE_PRINTF("CALL\tFAR ");
4959 DECODE_PRINTF("JMP\t");
4962 DECODE_PRINTF("JMP\tFAR ");
4965 DECODE_PRINTF("PUSH\t");
4968 DECODE_PRINTF("ILLEGAL DECODING OF OPCODE FF\t");
4975 destoffset = decode_rmXX_address(mod, rl);
4976 DECODE_PRINTF("\n");
4978 case 0: /* inc word ptr ... */
4979 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4982 destval = fetch_data_long(destoffset);
4984 destval = inc_long(destval);
4985 store_data_long(destoffset, destval);
4989 destval = fetch_data_word(destoffset);
4991 destval = inc_word(destval);
4992 store_data_word(destoffset, destval);
4995 case 1: /* dec word ptr ... */
4996 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4999 destval = fetch_data_long(destoffset);
5001 destval = dec_long(destval);
5002 store_data_long(destoffset, destval);
5006 destval = fetch_data_word(destoffset);
5008 destval = dec_word(destval);
5009 store_data_word(destoffset, destval);
5012 case 2: /* call word ptr ... */
5013 destval = fetch_data_word(destoffset);
5015 push_word(M.x86.R_IP);
5016 M.x86.R_IP = destval;
5018 case 3: /* call far ptr ... */
5019 destval = fetch_data_word(destoffset);
5020 destval2 = fetch_data_word(destoffset + 2);
5022 push_word(M.x86.R_CS);
5023 M.x86.R_CS = destval2;
5024 push_word(M.x86.R_IP);
5025 M.x86.R_IP = destval;
5027 case 4: /* jmp word ptr ... */
5028 destval = fetch_data_word(destoffset);
5030 M.x86.R_IP = destval;
5032 case 5: /* jmp far ptr ... */
5033 destval = fetch_data_word(destoffset);
5034 destval2 = fetch_data_word(destoffset + 2);
5036 M.x86.R_IP = destval;
5037 M.x86.R_CS = destval2;
5039 case 6: /* push word ptr ... */
5040 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5043 destval = fetch_data_long(destoffset);
5049 destval = fetch_data_word(destoffset);
5058 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5061 destreg = DECODE_RM_LONG_REGISTER(rl);
5062 DECODE_PRINTF("\n");
5064 *destreg = inc_long(*destreg);
5068 destreg = DECODE_RM_WORD_REGISTER(rl);
5069 DECODE_PRINTF("\n");
5071 *destreg = inc_word(*destreg);
5075 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5078 destreg = DECODE_RM_LONG_REGISTER(rl);
5079 DECODE_PRINTF("\n");
5081 *destreg = dec_long(*destreg);
5085 destreg = DECODE_RM_WORD_REGISTER(rl);
5086 DECODE_PRINTF("\n");
5088 *destreg = dec_word(*destreg);
5091 case 2: /* call word ptr ... */
5092 destreg = DECODE_RM_WORD_REGISTER(rl);
5093 DECODE_PRINTF("\n");
5095 push_word(M.x86.R_IP);
5096 M.x86.R_IP = *destreg;
5098 case 3: /* jmp far ptr ... */
5099 DECODE_PRINTF("OPERATION UNDEFINED 0XFF \n");
5104 case 4: /* jmp ... */
5105 destreg = DECODE_RM_WORD_REGISTER(rl);
5106 DECODE_PRINTF("\n");
5108 M.x86.R_IP = (u16) (*destreg);
5110 case 5: /* jmp far ptr ... */
5111 DECODE_PRINTF("OPERATION UNDEFINED 0XFF \n");
5116 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5119 destreg = DECODE_RM_LONG_REGISTER(rl);
5120 DECODE_PRINTF("\n");
5122 push_long(*destreg);
5126 destreg = DECODE_RM_WORD_REGISTER(rl);
5127 DECODE_PRINTF("\n");
5129 push_word(*destreg);
5134 DECODE_CLEAR_SEGOVR();
5138 /***************************************************************************
5139 * Single byte operation code table:
5140 **************************************************************************/
5141 void (*x86emu_optab[256])(u8) =
5143 /* 0x00 */ x86emuOp_genop_byte_RM_R,
5144 /* 0x01 */ x86emuOp_genop_word_RM_R,
5145 /* 0x02 */ x86emuOp_genop_byte_R_RM,
5146 /* 0x03 */ x86emuOp_genop_word_R_RM,
5147 /* 0x04 */ x86emuOp_genop_byte_AL_IMM,
5148 /* 0x05 */ x86emuOp_genop_word_AX_IMM,
5149 /* 0x06 */ x86emuOp_push_ES,
5150 /* 0x07 */ x86emuOp_pop_ES,
5152 /* 0x08 */ x86emuOp_genop_byte_RM_R,
5153 /* 0x09 */ x86emuOp_genop_word_RM_R,
5154 /* 0x0a */ x86emuOp_genop_byte_R_RM,
5155 /* 0x0b */ x86emuOp_genop_word_R_RM,
5156 /* 0x0c */ x86emuOp_genop_byte_AL_IMM,
5157 /* 0x0d */ x86emuOp_genop_word_AX_IMM,
5158 /* 0x0e */ x86emuOp_push_CS,
5159 /* 0x0f */ x86emuOp_two_byte,
5161 /* 0x10 */ x86emuOp_genop_byte_RM_R,
5162 /* 0x11 */ x86emuOp_genop_word_RM_R,
5163 /* 0x12 */ x86emuOp_genop_byte_R_RM,
5164 /* 0x13 */ x86emuOp_genop_word_R_RM,
5165 /* 0x14 */ x86emuOp_genop_byte_AL_IMM,
5166 /* 0x15 */ x86emuOp_genop_word_AX_IMM,
5167 /* 0x16 */ x86emuOp_push_SS,
5168 /* 0x17 */ x86emuOp_pop_SS,
5170 /* 0x18 */ x86emuOp_genop_byte_RM_R,
5171 /* 0x19 */ x86emuOp_genop_word_RM_R,
5172 /* 0x1a */ x86emuOp_genop_byte_R_RM,
5173 /* 0x1b */ x86emuOp_genop_word_R_RM,
5174 /* 0x1c */ x86emuOp_genop_byte_AL_IMM,
5175 /* 0x1d */ x86emuOp_genop_word_AX_IMM,
5176 /* 0x1e */ x86emuOp_push_DS,
5177 /* 0x1f */ x86emuOp_pop_DS,
5179 /* 0x20 */ x86emuOp_genop_byte_RM_R,
5180 /* 0x21 */ x86emuOp_genop_word_RM_R,
5181 /* 0x22 */ x86emuOp_genop_byte_R_RM,
5182 /* 0x23 */ x86emuOp_genop_word_R_RM,
5183 /* 0x24 */ x86emuOp_genop_byte_AL_IMM,
5184 /* 0x25 */ x86emuOp_genop_word_AX_IMM,
5185 /* 0x26 */ x86emuOp_segovr_ES,
5186 /* 0x27 */ x86emuOp_daa,
5188 /* 0x28 */ x86emuOp_genop_byte_RM_R,
5189 /* 0x29 */ x86emuOp_genop_word_RM_R,
5190 /* 0x2a */ x86emuOp_genop_byte_R_RM,
5191 /* 0x2b */ x86emuOp_genop_word_R_RM,
5192 /* 0x2c */ x86emuOp_genop_byte_AL_IMM,
5193 /* 0x2d */ x86emuOp_genop_word_AX_IMM,
5194 /* 0x2e */ x86emuOp_segovr_CS,
5195 /* 0x2f */ x86emuOp_das,
5197 /* 0x30 */ x86emuOp_genop_byte_RM_R,
5198 /* 0x31 */ x86emuOp_genop_word_RM_R,
5199 /* 0x32 */ x86emuOp_genop_byte_R_RM,
5200 /* 0x33 */ x86emuOp_genop_word_R_RM,
5201 /* 0x34 */ x86emuOp_genop_byte_AL_IMM,
5202 /* 0x35 */ x86emuOp_genop_word_AX_IMM,
5203 /* 0x36 */ x86emuOp_segovr_SS,
5204 /* 0x37 */ x86emuOp_aaa,
5206 /* 0x38 */ x86emuOp_genop_byte_RM_R,
5207 /* 0x39 */ x86emuOp_genop_word_RM_R,
5208 /* 0x3a */ x86emuOp_genop_byte_R_RM,
5209 /* 0x3b */ x86emuOp_genop_word_R_RM,
5210 /* 0x3c */ x86emuOp_genop_byte_AL_IMM,
5211 /* 0x3d */ x86emuOp_genop_word_AX_IMM,
5212 /* 0x3e */ x86emuOp_segovr_DS,
5213 /* 0x3f */ x86emuOp_aas,
5215 /* 0x40 */ x86emuOp_inc_register,
5216 /* 0x41 */ x86emuOp_inc_register,
5217 /* 0x42 */ x86emuOp_inc_register,
5218 /* 0x43 */ x86emuOp_inc_register,
5219 /* 0x44 */ x86emuOp_inc_register,
5220 /* 0x45 */ x86emuOp_inc_register,
5221 /* 0x46 */ x86emuOp_inc_register,
5222 /* 0x47 */ x86emuOp_inc_register,
5224 /* 0x48 */ x86emuOp_dec_register,
5225 /* 0x49 */ x86emuOp_dec_register,
5226 /* 0x4a */ x86emuOp_dec_register,
5227 /* 0x4b */ x86emuOp_dec_register,
5228 /* 0x4c */ x86emuOp_dec_register,
5229 /* 0x4d */ x86emuOp_dec_register,
5230 /* 0x4e */ x86emuOp_dec_register,
5231 /* 0x4f */ x86emuOp_dec_register,
5233 /* 0x50 */ x86emuOp_push_register,
5234 /* 0x51 */ x86emuOp_push_register,
5235 /* 0x52 */ x86emuOp_push_register,
5236 /* 0x53 */ x86emuOp_push_register,
5237 /* 0x54 */ x86emuOp_push_register,
5238 /* 0x55 */ x86emuOp_push_register,
5239 /* 0x56 */ x86emuOp_push_register,
5240 /* 0x57 */ x86emuOp_push_register,
5242 /* 0x58 */ x86emuOp_pop_register,
5243 /* 0x59 */ x86emuOp_pop_register,
5244 /* 0x5a */ x86emuOp_pop_register,
5245 /* 0x5b */ x86emuOp_pop_register,
5246 /* 0x5c */ x86emuOp_pop_register,
5247 /* 0x5d */ x86emuOp_pop_register,
5248 /* 0x5e */ x86emuOp_pop_register,
5249 /* 0x5f */ x86emuOp_pop_register,
5251 /* 0x60 */ x86emuOp_push_all,
5252 /* 0x61 */ x86emuOp_pop_all,
5253 /* 0x62 */ x86emuOp_illegal_op, /* bound */
5254 /* 0x63 */ x86emuOp_illegal_op, /* arpl */
5255 /* 0x64 */ x86emuOp_segovr_FS,
5256 /* 0x65 */ x86emuOp_segovr_GS,
5257 /* 0x66 */ x86emuOp_prefix_data,
5258 /* 0x67 */ x86emuOp_prefix_addr,
5260 /* 0x68 */ x86emuOp_push_word_IMM,
5261 /* 0x69 */ x86emuOp_imul_word_IMM,
5262 /* 0x6a */ x86emuOp_push_byte_IMM,
5263 /* 0x6b */ x86emuOp_imul_byte_IMM,
5264 /* 0x6c */ x86emuOp_ins_byte,
5265 /* 0x6d */ x86emuOp_ins_word,
5266 /* 0x6e */ x86emuOp_outs_byte,
5267 /* 0x6f */ x86emuOp_outs_word,
5269 /* 0x70 */ x86emuOp_jump_near_cond,
5270 /* 0x71 */ x86emuOp_jump_near_cond,
5271 /* 0x72 */ x86emuOp_jump_near_cond,
5272 /* 0x73 */ x86emuOp_jump_near_cond,
5273 /* 0x74 */ x86emuOp_jump_near_cond,
5274 /* 0x75 */ x86emuOp_jump_near_cond,
5275 /* 0x76 */ x86emuOp_jump_near_cond,
5276 /* 0x77 */ x86emuOp_jump_near_cond,
5278 /* 0x78 */ x86emuOp_jump_near_cond,
5279 /* 0x79 */ x86emuOp_jump_near_cond,
5280 /* 0x7a */ x86emuOp_jump_near_cond,
5281 /* 0x7b */ x86emuOp_jump_near_cond,
5282 /* 0x7c */ x86emuOp_jump_near_cond,
5283 /* 0x7d */ x86emuOp_jump_near_cond,
5284 /* 0x7e */ x86emuOp_jump_near_cond,
5285 /* 0x7f */ x86emuOp_jump_near_cond,
5287 /* 0x80 */ x86emuOp_opc80_byte_RM_IMM,
5288 /* 0x81 */ x86emuOp_opc81_word_RM_IMM,
5289 /* 0x82 */ x86emuOp_opc82_byte_RM_IMM,
5290 /* 0x83 */ x86emuOp_opc83_word_RM_IMM,
5291 /* 0x84 */ x86emuOp_test_byte_RM_R,
5292 /* 0x85 */ x86emuOp_test_word_RM_R,
5293 /* 0x86 */ x86emuOp_xchg_byte_RM_R,
5294 /* 0x87 */ x86emuOp_xchg_word_RM_R,
5296 /* 0x88 */ x86emuOp_mov_byte_RM_R,
5297 /* 0x89 */ x86emuOp_mov_word_RM_R,
5298 /* 0x8a */ x86emuOp_mov_byte_R_RM,
5299 /* 0x8b */ x86emuOp_mov_word_R_RM,
5300 /* 0x8c */ x86emuOp_mov_word_RM_SR,
5301 /* 0x8d */ x86emuOp_lea_word_R_M,
5302 /* 0x8e */ x86emuOp_mov_word_SR_RM,
5303 /* 0x8f */ x86emuOp_pop_RM,
5305 /* 0x90 */ x86emuOp_nop,
5306 /* 0x91 */ x86emuOp_xchg_word_AX_register,
5307 /* 0x92 */ x86emuOp_xchg_word_AX_register,
5308 /* 0x93 */ x86emuOp_xchg_word_AX_register,
5309 /* 0x94 */ x86emuOp_xchg_word_AX_register,
5310 /* 0x95 */ x86emuOp_xchg_word_AX_register,
5311 /* 0x96 */ x86emuOp_xchg_word_AX_register,
5312 /* 0x97 */ x86emuOp_xchg_word_AX_register,
5314 /* 0x98 */ x86emuOp_cbw,
5315 /* 0x99 */ x86emuOp_cwd,
5316 /* 0x9a */ x86emuOp_call_far_IMM,
5317 /* 0x9b */ x86emuOp_wait,
5318 /* 0x9c */ x86emuOp_pushf_word,
5319 /* 0x9d */ x86emuOp_popf_word,
5320 /* 0x9e */ x86emuOp_sahf,
5321 /* 0x9f */ x86emuOp_lahf,
5323 /* 0xa0 */ x86emuOp_mov_AL_M_IMM,
5324 /* 0xa1 */ x86emuOp_mov_AX_M_IMM,
5325 /* 0xa2 */ x86emuOp_mov_M_AL_IMM,
5326 /* 0xa3 */ x86emuOp_mov_M_AX_IMM,
5327 /* 0xa4 */ x86emuOp_movs_byte,
5328 /* 0xa5 */ x86emuOp_movs_word,
5329 /* 0xa6 */ x86emuOp_cmps_byte,
5330 /* 0xa7 */ x86emuOp_cmps_word,
5331 /* 0xa8 */ x86emuOp_test_AL_IMM,
5332 /* 0xa9 */ x86emuOp_test_AX_IMM,
5333 /* 0xaa */ x86emuOp_stos_byte,
5334 /* 0xab */ x86emuOp_stos_word,
5335 /* 0xac */ x86emuOp_lods_byte,
5336 /* 0xad */ x86emuOp_lods_word,
5337 /* 0xac */ x86emuOp_scas_byte,
5338 /* 0xad */ x86emuOp_scas_word,
5340 /* 0xb0 */ x86emuOp_mov_byte_register_IMM,
5341 /* 0xb1 */ x86emuOp_mov_byte_register_IMM,
5342 /* 0xb2 */ x86emuOp_mov_byte_register_IMM,
5343 /* 0xb3 */ x86emuOp_mov_byte_register_IMM,
5344 /* 0xb4 */ x86emuOp_mov_byte_register_IMM,
5345 /* 0xb5 */ x86emuOp_mov_byte_register_IMM,
5346 /* 0xb6 */ x86emuOp_mov_byte_register_IMM,
5347 /* 0xb7 */ x86emuOp_mov_byte_register_IMM,
5349 /* 0xb8 */ x86emuOp_mov_word_register_IMM,
5350 /* 0xb9 */ x86emuOp_mov_word_register_IMM,
5351 /* 0xba */ x86emuOp_mov_word_register_IMM,
5352 /* 0xbb */ x86emuOp_mov_word_register_IMM,
5353 /* 0xbc */ x86emuOp_mov_word_register_IMM,
5354 /* 0xbd */ x86emuOp_mov_word_register_IMM,
5355 /* 0xbe */ x86emuOp_mov_word_register_IMM,
5356 /* 0xbf */ x86emuOp_mov_word_register_IMM,
5358 /* 0xc0 */ x86emuOp_opcC0_byte_RM_MEM,
5359 /* 0xc1 */ x86emuOp_opcC1_word_RM_MEM,
5360 /* 0xc2 */ x86emuOp_ret_near_IMM,
5361 /* 0xc3 */ x86emuOp_ret_near,
5362 /* 0xc4 */ x86emuOp_les_R_IMM,
5363 /* 0xc5 */ x86emuOp_lds_R_IMM,
5364 /* 0xc6 */ x86emuOp_mov_byte_RM_IMM,
5365 /* 0xc7 */ x86emuOp_mov_word_RM_IMM,
5366 /* 0xc8 */ x86emuOp_enter,
5367 /* 0xc9 */ x86emuOp_leave,
5368 /* 0xca */ x86emuOp_ret_far_IMM,
5369 /* 0xcb */ x86emuOp_ret_far,
5370 /* 0xcc */ x86emuOp_int3,
5371 /* 0xcd */ x86emuOp_int_IMM,
5372 /* 0xce */ x86emuOp_into,
5373 /* 0xcf */ x86emuOp_iret,
5375 /* 0xd0 */ x86emuOp_opcD0_byte_RM_1,
5376 /* 0xd1 */ x86emuOp_opcD1_word_RM_1,
5377 /* 0xd2 */ x86emuOp_opcD2_byte_RM_CL,
5378 /* 0xd3 */ x86emuOp_opcD3_word_RM_CL,
5379 /* 0xd4 */ x86emuOp_aam,
5380 /* 0xd5 */ x86emuOp_aad,
5381 /* 0xd6 */ x86emuOp_illegal_op, /* Undocumented SETALC instruction */
5382 /* 0xd7 */ x86emuOp_xlat,
5383 /* 0xd8 */ x86emuOp_esc_coprocess_d8,
5384 /* 0xd9 */ x86emuOp_esc_coprocess_d9,
5385 /* 0xda */ x86emuOp_esc_coprocess_da,
5386 /* 0xdb */ x86emuOp_esc_coprocess_db,
5387 /* 0xdc */ x86emuOp_esc_coprocess_dc,
5388 /* 0xdd */ x86emuOp_esc_coprocess_dd,
5389 /* 0xde */ x86emuOp_esc_coprocess_de,
5390 /* 0xdf */ x86emuOp_esc_coprocess_df,
5392 /* 0xe0 */ x86emuOp_loopne,
5393 /* 0xe1 */ x86emuOp_loope,
5394 /* 0xe2 */ x86emuOp_loop,
5395 /* 0xe3 */ x86emuOp_jcxz,
5396 /* 0xe4 */ x86emuOp_in_byte_AL_IMM,
5397 /* 0xe5 */ x86emuOp_in_word_AX_IMM,
5398 /* 0xe6 */ x86emuOp_out_byte_IMM_AL,
5399 /* 0xe7 */ x86emuOp_out_word_IMM_AX,
5401 /* 0xe8 */ x86emuOp_call_near_IMM,
5402 /* 0xe9 */ x86emuOp_jump_near_IMM,
5403 /* 0xea */ x86emuOp_jump_far_IMM,
5404 /* 0xeb */ x86emuOp_jump_byte_IMM,
5405 /* 0xec */ x86emuOp_in_byte_AL_DX,
5406 /* 0xed */ x86emuOp_in_word_AX_DX,
5407 /* 0xee */ x86emuOp_out_byte_DX_AL,
5408 /* 0xef */ x86emuOp_out_word_DX_AX,
5410 /* 0xf0 */ x86emuOp_lock,
5411 /* 0xf1 */ x86emuOp_illegal_op,
5412 /* 0xf2 */ x86emuOp_repne,
5413 /* 0xf3 */ x86emuOp_repe,
5414 /* 0xf4 */ x86emuOp_halt,
5415 /* 0xf5 */ x86emuOp_cmc,
5416 /* 0xf6 */ x86emuOp_opcF6_byte_RM,
5417 /* 0xf7 */ x86emuOp_opcF7_word_RM,
5419 /* 0xf8 */ x86emuOp_clc,
5420 /* 0xf9 */ x86emuOp_stc,
5421 /* 0xfa */ x86emuOp_cli,
5422 /* 0xfb */ x86emuOp_sti,
5423 /* 0xfc */ x86emuOp_cld,
5424 /* 0xfd */ x86emuOp_std,
5425 /* 0xfe */ x86emuOp_opcFE_byte_RM,
5426 /* 0xff */ x86emuOp_opcFF_word_RM,