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 ****************************************************************************/
75 /*----------------------------- Implementation ----------------------------*/
77 /* constant arrays to do several instructions in just one function */
80 static const 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 const 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 static void x86emuOp_illegal_op(
178 if (M.x86.R_SP != 0) {
179 DECODE_PRINTF("ILLEGAL X86 OPCODE\n");
181 DB( printf("%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 static 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);
223 store_data_byte(destoffset, destval);
226 { /* register to register */
227 destreg = DECODE_RM_BYTE_REGISTER(rl);
229 srcreg = DECODE_RM_BYTE_REGISTER(rh);
232 *destreg = genop_byte_operation[op1](*destreg, *srcreg);
234 DECODE_CLEAR_SEGOVR();
238 /****************************************************************************
240 Handles opcodes 0x01, 0x09, 0x11, 0x19, 0x21, 0x29, 0x31, 0x39
241 ****************************************************************************/
242 static void x86emuOp_genop_word_RM_R(u8 op1)
247 op1 = (op1 >> 3) & 0x7;
250 DECODE_PRINTF(x86emu_GenOpName[op1]);
252 FETCH_DECODE_MODRM(mod, rh, rl);
255 destoffset = decode_rmXX_address(mod,rl);
256 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
261 destval = fetch_data_long(destoffset);
262 srcreg = DECODE_RM_LONG_REGISTER(rh);
265 destval = genop_long_operation[op1](destval, *srcreg);
267 store_data_long(destoffset, destval);
273 destval = fetch_data_word(destoffset);
274 srcreg = DECODE_RM_WORD_REGISTER(rh);
277 destval = genop_word_operation[op1](destval, *srcreg);
279 store_data_word(destoffset, destval);
281 } else { /* register to register */
282 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
283 u32 *destreg, *srcreg;
285 destreg = DECODE_RM_LONG_REGISTER(rl);
287 srcreg = DECODE_RM_LONG_REGISTER(rh);
290 *destreg = genop_long_operation[op1](*destreg, *srcreg);
292 u16 *destreg, *srcreg;
294 destreg = DECODE_RM_WORD_REGISTER(rl);
296 srcreg = DECODE_RM_WORD_REGISTER(rh);
299 *destreg = genop_word_operation[op1](*destreg, *srcreg);
302 DECODE_CLEAR_SEGOVR();
306 /****************************************************************************
308 Handles opcodes 0x02, 0x0a, 0x12, 0x1a, 0x22, 0x2a, 0x32, 0x3a
309 ****************************************************************************/
310 static void x86emuOp_genop_byte_R_RM(u8 op1)
313 u8 *destreg, *srcreg;
317 op1 = (op1 >> 3) & 0x7;
320 DECODE_PRINTF(x86emu_GenOpName[op1]);
322 FETCH_DECODE_MODRM(mod, rh, rl);
324 destreg = DECODE_RM_BYTE_REGISTER(rh);
326 srcoffset = decode_rmXX_address(mod,rl);
327 srcval = fetch_data_byte(srcoffset);
328 } else { /* register to register */
329 destreg = DECODE_RM_BYTE_REGISTER(rh);
331 srcreg = DECODE_RM_BYTE_REGISTER(rl);
336 *destreg = genop_byte_operation[op1](*destreg, srcval);
338 DECODE_CLEAR_SEGOVR();
342 /****************************************************************************
344 Handles opcodes 0x03, 0x0b, 0x13, 0x1b, 0x23, 0x2b, 0x33, 0x3b
345 ****************************************************************************/
346 static void x86emuOp_genop_word_R_RM(u8 op1)
350 u32 *destreg32, srcval;
353 op1 = (op1 >> 3) & 0x7;
356 DECODE_PRINTF(x86emu_GenOpName[op1]);
358 FETCH_DECODE_MODRM(mod, rh, rl);
360 srcoffset = decode_rmXX_address(mod,rl);
361 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
362 destreg32 = DECODE_RM_LONG_REGISTER(rh);
364 srcval = fetch_data_long(srcoffset);
367 *destreg32 = genop_long_operation[op1](*destreg32, srcval);
369 destreg = DECODE_RM_WORD_REGISTER(rh);
371 srcval = fetch_data_word(srcoffset);
374 *destreg = genop_word_operation[op1](*destreg, srcval);
376 } else { /* register to register */
377 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
379 destreg32 = DECODE_RM_LONG_REGISTER(rh);
381 srcreg = DECODE_RM_LONG_REGISTER(rl);
384 *destreg32 = genop_long_operation[op1](*destreg32, *srcreg);
387 destreg = DECODE_RM_WORD_REGISTER(rh);
389 srcreg = DECODE_RM_WORD_REGISTER(rl);
392 *destreg = genop_word_operation[op1](*destreg, *srcreg);
395 DECODE_CLEAR_SEGOVR();
399 /****************************************************************************
401 Handles opcodes 0x04, 0x0c, 0x14, 0x1c, 0x24, 0x2c, 0x34, 0x3c
402 ****************************************************************************/
403 static void x86emuOp_genop_byte_AL_IMM(u8 op1)
407 op1 = (op1 >> 3) & 0x7;
410 DECODE_PRINTF(x86emu_GenOpName[op1]);
411 DECODE_PRINTF("\tAL,");
412 srcval = fetch_byte_imm();
413 DECODE_PRINTF2("%x\n", srcval);
415 M.x86.R_AL = genop_byte_operation[op1](M.x86.R_AL, srcval);
416 DECODE_CLEAR_SEGOVR();
420 /****************************************************************************
422 Handles opcodes 0x05, 0x0d, 0x15, 0x1d, 0x25, 0x2d, 0x35, 0x3d
423 ****************************************************************************/
424 static void x86emuOp_genop_word_AX_IMM(u8 op1)
428 op1 = (op1 >> 3) & 0x7;
431 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
432 DECODE_PRINTF(x86emu_GenOpName[op1]);
433 DECODE_PRINTF("\tEAX,");
434 srcval = fetch_long_imm();
436 DECODE_PRINTF(x86emu_GenOpName[op1]);
437 DECODE_PRINTF("\tAX,");
438 srcval = fetch_word_imm();
440 DECODE_PRINTF2("%x\n", srcval);
442 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
443 M.x86.R_EAX = genop_long_operation[op1](M.x86.R_EAX, srcval);
445 M.x86.R_AX = genop_word_operation[op1](M.x86.R_AX, (u16)srcval);
447 DECODE_CLEAR_SEGOVR();
451 /****************************************************************************
454 ****************************************************************************/
455 static void x86emuOp_push_ES(u8 X86EMU_UNUSED(op1))
458 DECODE_PRINTF("PUSH\tES\n");
460 push_word(M.x86.R_ES);
461 DECODE_CLEAR_SEGOVR();
465 /****************************************************************************
468 ****************************************************************************/
469 static void x86emuOp_pop_ES(u8 X86EMU_UNUSED(op1))
472 DECODE_PRINTF("POP\tES\n");
474 M.x86.R_ES = pop_word();
475 DECODE_CLEAR_SEGOVR();
479 /****************************************************************************
482 ****************************************************************************/
483 static void x86emuOp_push_CS(u8 X86EMU_UNUSED(op1))
486 DECODE_PRINTF("PUSH\tCS\n");
488 push_word(M.x86.R_CS);
489 DECODE_CLEAR_SEGOVR();
493 /****************************************************************************
495 Handles opcode 0x0f. Escape for two-byte opcode (286 or better)
496 ****************************************************************************/
497 static void x86emuOp_two_byte(u8 X86EMU_UNUSED(op1))
499 u8 op2 = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++));
500 INC_DECODED_INST_LEN(1);
501 (*x86emu_optab2[op2])(op2);
504 /****************************************************************************
507 ****************************************************************************/
508 static void x86emuOp_push_SS(u8 X86EMU_UNUSED(op1))
511 DECODE_PRINTF("PUSH\tSS\n");
513 push_word(M.x86.R_SS);
514 DECODE_CLEAR_SEGOVR();
518 /****************************************************************************
521 ****************************************************************************/
522 static void x86emuOp_pop_SS(u8 X86EMU_UNUSED(op1))
525 DECODE_PRINTF("POP\tSS\n");
527 M.x86.R_SS = pop_word();
528 DECODE_CLEAR_SEGOVR();
532 /****************************************************************************
535 ****************************************************************************/
536 static void x86emuOp_push_DS(u8 X86EMU_UNUSED(op1))
539 DECODE_PRINTF("PUSH\tDS\n");
541 push_word(M.x86.R_DS);
542 DECODE_CLEAR_SEGOVR();
546 /****************************************************************************
549 ****************************************************************************/
550 static void x86emuOp_pop_DS(u8 X86EMU_UNUSED(op1))
553 DECODE_PRINTF("POP\tDS\n");
555 M.x86.R_DS = pop_word();
556 DECODE_CLEAR_SEGOVR();
560 /****************************************************************************
563 ****************************************************************************/
564 static void x86emuOp_segovr_ES(u8 X86EMU_UNUSED(op1))
567 DECODE_PRINTF("ES:\n");
569 M.x86.mode |= SYSMODE_SEGOVR_ES;
571 * note the lack of DECODE_CLEAR_SEGOVR(r) since, here is one of 4
572 * opcode subroutines we do not want to do this.
577 /****************************************************************************
580 ****************************************************************************/
581 static void x86emuOp_daa(u8 X86EMU_UNUSED(op1))
584 DECODE_PRINTF("DAA\n");
586 M.x86.R_AL = daa_byte(M.x86.R_AL);
587 DECODE_CLEAR_SEGOVR();
591 /****************************************************************************
594 ****************************************************************************/
595 static void x86emuOp_segovr_CS(u8 X86EMU_UNUSED(op1))
598 DECODE_PRINTF("CS:\n");
600 M.x86.mode |= SYSMODE_SEGOVR_CS;
601 /* note no DECODE_CLEAR_SEGOVR here. */
605 /****************************************************************************
608 ****************************************************************************/
609 static void x86emuOp_das(u8 X86EMU_UNUSED(op1))
612 DECODE_PRINTF("DAS\n");
614 M.x86.R_AL = das_byte(M.x86.R_AL);
615 DECODE_CLEAR_SEGOVR();
619 /****************************************************************************
622 ****************************************************************************/
623 static void x86emuOp_segovr_SS(u8 X86EMU_UNUSED(op1))
626 DECODE_PRINTF("SS:\n");
628 M.x86.mode |= SYSMODE_SEGOVR_SS;
629 /* no DECODE_CLEAR_SEGOVR ! */
633 /****************************************************************************
636 ****************************************************************************/
637 static void x86emuOp_aaa(u8 X86EMU_UNUSED(op1))
640 DECODE_PRINTF("AAA\n");
642 M.x86.R_AX = aaa_word(M.x86.R_AX);
643 DECODE_CLEAR_SEGOVR();
647 /****************************************************************************
650 ****************************************************************************/
651 static void x86emuOp_segovr_DS(u8 X86EMU_UNUSED(op1))
654 DECODE_PRINTF("DS:\n");
656 M.x86.mode |= SYSMODE_SEGOVR_DS;
657 /* NO DECODE_CLEAR_SEGOVR! */
661 /****************************************************************************
664 ****************************************************************************/
665 static void x86emuOp_aas(u8 X86EMU_UNUSED(op1))
668 DECODE_PRINTF("AAS\n");
670 M.x86.R_AX = aas_word(M.x86.R_AX);
671 DECODE_CLEAR_SEGOVR();
675 /****************************************************************************
677 Handles opcode 0x40 - 0x47
678 ****************************************************************************/
679 static void x86emuOp_inc_register(u8 op1)
683 DECODE_PRINTF("INC\t");
684 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
686 reg = DECODE_RM_LONG_REGISTER(op1);
689 *reg = inc_long(*reg);
692 reg = DECODE_RM_WORD_REGISTER(op1);
695 *reg = inc_word(*reg);
697 DECODE_CLEAR_SEGOVR();
701 /****************************************************************************
703 Handles opcode 0x48 - 0x4F
704 ****************************************************************************/
705 static void x86emuOp_dec_register(u8 op1)
709 DECODE_PRINTF("DEC\t");
710 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
712 reg = DECODE_RM_LONG_REGISTER(op1);
715 *reg = dec_long(*reg);
718 reg = DECODE_RM_WORD_REGISTER(op1);
721 *reg = dec_word(*reg);
723 DECODE_CLEAR_SEGOVR();
727 /****************************************************************************
729 Handles opcode 0x50 - 0x57
730 ****************************************************************************/
731 static void x86emuOp_push_register(u8 op1)
735 DECODE_PRINTF("PUSH\t");
736 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
738 reg = DECODE_RM_LONG_REGISTER(op1);
744 reg = DECODE_RM_WORD_REGISTER(op1);
749 DECODE_CLEAR_SEGOVR();
753 /****************************************************************************
755 Handles opcode 0x58 - 0x5F
756 ****************************************************************************/
757 static void x86emuOp_pop_register(u8 op1)
761 DECODE_PRINTF("POP\t");
762 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
764 reg = DECODE_RM_LONG_REGISTER(op1);
770 reg = DECODE_RM_WORD_REGISTER(op1);
775 DECODE_CLEAR_SEGOVR();
779 /****************************************************************************
782 ****************************************************************************/
783 static void x86emuOp_push_all(u8 X86EMU_UNUSED(op1))
786 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
787 DECODE_PRINTF("PUSHAD\n");
789 DECODE_PRINTF("PUSHA\n");
792 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
793 u32 old_sp = M.x86.R_ESP;
795 push_long(M.x86.R_EAX);
796 push_long(M.x86.R_ECX);
797 push_long(M.x86.R_EDX);
798 push_long(M.x86.R_EBX);
800 push_long(M.x86.R_EBP);
801 push_long(M.x86.R_ESI);
802 push_long(M.x86.R_EDI);
804 u16 old_sp = M.x86.R_SP;
806 push_word(M.x86.R_AX);
807 push_word(M.x86.R_CX);
808 push_word(M.x86.R_DX);
809 push_word(M.x86.R_BX);
811 push_word(M.x86.R_BP);
812 push_word(M.x86.R_SI);
813 push_word(M.x86.R_DI);
815 DECODE_CLEAR_SEGOVR();
819 /****************************************************************************
822 ****************************************************************************/
823 static void x86emuOp_pop_all(u8 X86EMU_UNUSED(op1))
826 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
827 DECODE_PRINTF("POPAD\n");
829 DECODE_PRINTF("POPA\n");
832 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
833 M.x86.R_EDI = pop_long();
834 M.x86.R_ESI = pop_long();
835 M.x86.R_EBP = pop_long();
836 M.x86.R_ESP += 4; /* skip ESP */
837 M.x86.R_EBX = pop_long();
838 M.x86.R_EDX = pop_long();
839 M.x86.R_ECX = pop_long();
840 M.x86.R_EAX = pop_long();
842 M.x86.R_DI = pop_word();
843 M.x86.R_SI = pop_word();
844 M.x86.R_BP = pop_word();
845 M.x86.R_SP += 2; /* skip SP */
846 M.x86.R_BX = pop_word();
847 M.x86.R_DX = pop_word();
848 M.x86.R_CX = pop_word();
849 M.x86.R_AX = pop_word();
851 DECODE_CLEAR_SEGOVR();
855 /*opcode 0x62 ILLEGAL OP, calls x86emuOp_illegal_op() */
856 /*opcode 0x63 ILLEGAL OP, calls x86emuOp_illegal_op() */
858 /****************************************************************************
861 ****************************************************************************/
862 static void x86emuOp_segovr_FS(u8 X86EMU_UNUSED(op1))
865 DECODE_PRINTF("FS:\n");
867 M.x86.mode |= SYSMODE_SEGOVR_FS;
869 * note the lack of DECODE_CLEAR_SEGOVR(r) since, here is one of 4
870 * opcode subroutines we do not want to do this.
875 /****************************************************************************
878 ****************************************************************************/
879 static void x86emuOp_segovr_GS(u8 X86EMU_UNUSED(op1))
882 DECODE_PRINTF("GS:\n");
884 M.x86.mode |= SYSMODE_SEGOVR_GS;
886 * note the lack of DECODE_CLEAR_SEGOVR(r) since, here is one of 4
887 * opcode subroutines we do not want to do this.
892 /****************************************************************************
894 Handles opcode 0x66 - prefix for 32-bit register
895 ****************************************************************************/
896 static void x86emuOp_prefix_data(u8 X86EMU_UNUSED(op1))
899 DECODE_PRINTF("DATA:\n");
901 M.x86.mode |= SYSMODE_PREFIX_DATA;
902 /* note no DECODE_CLEAR_SEGOVR here. */
906 /****************************************************************************
908 Handles opcode 0x67 - prefix for 32-bit address
909 ****************************************************************************/
910 static void x86emuOp_prefix_addr(u8 X86EMU_UNUSED(op1))
913 DECODE_PRINTF("ADDR:\n");
915 M.x86.mode |= SYSMODE_PREFIX_ADDR;
916 /* note no DECODE_CLEAR_SEGOVR here. */
920 /****************************************************************************
923 ****************************************************************************/
924 static void x86emuOp_push_word_IMM(u8 X86EMU_UNUSED(op1))
929 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
930 imm = fetch_long_imm();
932 imm = fetch_word_imm();
934 DECODE_PRINTF2("PUSH\t%x\n", imm);
936 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
941 DECODE_CLEAR_SEGOVR();
945 /****************************************************************************
948 ****************************************************************************/
949 static void x86emuOp_imul_word_IMM(u8 X86EMU_UNUSED(op1))
955 DECODE_PRINTF("IMUL\t");
956 FETCH_DECODE_MODRM(mod, rh, rl);
958 srcoffset = decode_rmXX_address(mod, rl);
959 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
965 destreg = DECODE_RM_LONG_REGISTER(rh);
967 srcval = fetch_data_long(srcoffset);
968 imm = fetch_long_imm();
969 DECODE_PRINTF2(",%d\n", (s32)imm);
971 imul_long_direct(&res_lo,&res_hi,(s32)srcval,(s32)imm);
972 if ((((res_lo & 0x80000000) == 0) && (res_hi == 0x00000000)) ||
973 (((res_lo & 0x80000000) != 0) && (res_hi == 0xFFFFFFFF))) {
980 *destreg = (u32)res_lo;
987 destreg = DECODE_RM_WORD_REGISTER(rh);
989 srcval = fetch_data_word(srcoffset);
990 imm = fetch_word_imm();
991 DECODE_PRINTF2(",%d\n", (s32)imm);
993 res = (s16)srcval * (s16)imm;
994 if ((((res & 0x8000) == 0) && ((res >> 16) == 0x0000)) ||
995 (((res & 0x8000) != 0) && ((res >> 16) == 0xFFFF))) {
1002 *destreg = (u16)res;
1004 } else { /* register to register */
1005 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1006 u32 *destreg,*srcreg;
1010 destreg = DECODE_RM_LONG_REGISTER(rh);
1012 srcreg = DECODE_RM_LONG_REGISTER(rl);
1013 imm = fetch_long_imm();
1014 DECODE_PRINTF2(",%d\n", (s32)imm);
1016 imul_long_direct(&res_lo,&res_hi,(s32)*srcreg,(s32)imm);
1017 if ((((res_lo & 0x80000000) == 0) && (res_hi == 0x00000000)) ||
1018 (((res_lo & 0x80000000) != 0) && (res_hi == 0xFFFFFFFF))) {
1025 *destreg = (u32)res_lo;
1027 u16 *destreg,*srcreg;
1031 destreg = DECODE_RM_WORD_REGISTER(rh);
1033 srcreg = DECODE_RM_WORD_REGISTER(rl);
1034 imm = fetch_word_imm();
1035 DECODE_PRINTF2(",%d\n", (s32)imm);
1036 res = (s16)*srcreg * (s16)imm;
1037 if ((((res & 0x8000) == 0) && ((res >> 16) == 0x0000)) ||
1038 (((res & 0x8000) != 0) && ((res >> 16) == 0xFFFF))) {
1045 *destreg = (u16)res;
1048 DECODE_CLEAR_SEGOVR();
1052 /****************************************************************************
1055 ****************************************************************************/
1056 static void x86emuOp_push_byte_IMM(u8 X86EMU_UNUSED(op1))
1061 imm = (s8)fetch_byte_imm();
1062 DECODE_PRINTF2("PUSH\t%d\n", imm);
1064 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1069 DECODE_CLEAR_SEGOVR();
1073 /****************************************************************************
1076 ****************************************************************************/
1077 static void x86emuOp_imul_byte_IMM(u8 X86EMU_UNUSED(op1))
1084 DECODE_PRINTF("IMUL\t");
1085 FETCH_DECODE_MODRM(mod, rh, rl);
1087 srcoffset = decode_rmXX_address(mod, rl);
1088 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1093 destreg = DECODE_RM_LONG_REGISTER(rh);
1095 srcval = fetch_data_long(srcoffset);
1096 imm = fetch_byte_imm();
1097 DECODE_PRINTF2(",%d\n", (s32)imm);
1099 imul_long_direct(&res_lo,&res_hi,(s32)srcval,(s32)imm);
1100 if ((((res_lo & 0x80000000) == 0) && (res_hi == 0x00000000)) ||
1101 (((res_lo & 0x80000000) != 0) && (res_hi == 0xFFFFFFFF))) {
1108 *destreg = (u32)res_lo;
1114 destreg = DECODE_RM_WORD_REGISTER(rh);
1116 srcval = fetch_data_word(srcoffset);
1117 imm = fetch_byte_imm();
1118 DECODE_PRINTF2(",%d\n", (s32)imm);
1120 res = (s16)srcval * (s16)imm;
1121 if ((((res & 0x8000) == 0) && ((res >> 16) == 0x0000)) ||
1122 (((res & 0x8000) != 0) && ((res >> 16) == 0xFFFF))) {
1129 *destreg = (u16)res;
1131 } else { /* register to register */
1132 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1133 u32 *destreg,*srcreg;
1136 destreg = DECODE_RM_LONG_REGISTER(rh);
1138 srcreg = DECODE_RM_LONG_REGISTER(rl);
1139 imm = fetch_byte_imm();
1140 DECODE_PRINTF2(",%d\n", (s32)imm);
1142 imul_long_direct(&res_lo,&res_hi,(s32)*srcreg,(s32)imm);
1143 if ((((res_lo & 0x80000000) == 0) && (res_hi == 0x00000000)) ||
1144 (((res_lo & 0x80000000) != 0) && (res_hi == 0xFFFFFFFF))) {
1151 *destreg = (u32)res_lo;
1153 u16 *destreg,*srcreg;
1156 destreg = DECODE_RM_WORD_REGISTER(rh);
1158 srcreg = DECODE_RM_WORD_REGISTER(rl);
1159 imm = fetch_byte_imm();
1160 DECODE_PRINTF2(",%d\n", (s32)imm);
1162 res = (s16)*srcreg * (s16)imm;
1163 if ((((res & 0x8000) == 0) && ((res >> 16) == 0x0000)) ||
1164 (((res & 0x8000) != 0) && ((res >> 16) == 0xFFFF))) {
1171 *destreg = (u16)res;
1174 DECODE_CLEAR_SEGOVR();
1178 /****************************************************************************
1181 ****************************************************************************/
1182 static void x86emuOp_ins_byte(u8 X86EMU_UNUSED(op1))
1185 DECODE_PRINTF("INSB\n");
1188 DECODE_CLEAR_SEGOVR();
1192 /****************************************************************************
1195 ****************************************************************************/
1196 static void x86emuOp_ins_word(u8 X86EMU_UNUSED(op1))
1199 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1200 DECODE_PRINTF("INSD\n");
1203 DECODE_PRINTF("INSW\n");
1207 DECODE_CLEAR_SEGOVR();
1211 /****************************************************************************
1214 ****************************************************************************/
1215 static void x86emuOp_outs_byte(u8 X86EMU_UNUSED(op1))
1218 DECODE_PRINTF("OUTSB\n");
1221 DECODE_CLEAR_SEGOVR();
1225 /****************************************************************************
1228 ****************************************************************************/
1229 static void x86emuOp_outs_word(u8 X86EMU_UNUSED(op1))
1232 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1233 DECODE_PRINTF("OUTSD\n");
1236 DECODE_PRINTF("OUTSW\n");
1240 DECODE_CLEAR_SEGOVR();
1244 /****************************************************************************
1246 Handles opcode 0x70 - 0x7F
1247 ****************************************************************************/
1248 static void x86emuOp_jump_near_cond(u8 op1)
1254 /* jump to byte offset if overflow flag is set */
1256 cond = x86emu_check_jump_condition(op1 & 0xF);
1257 offset = (s8)fetch_byte_imm();
1258 target = (u16)(M.x86.R_IP + (s16)offset);
1259 DECODE_PRINTF2("%x\n", target);
1262 M.x86.R_IP = target;
1263 JMP_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, M.x86.R_IP, " NEAR COND ");
1265 DECODE_CLEAR_SEGOVR();
1269 /****************************************************************************
1272 ****************************************************************************/
1273 static void x86emuOp_opc80_byte_RM_IMM(u8 X86EMU_UNUSED(op1))
1282 * Weirdo special case instruction format. Part of the opcode
1283 * held below in "RH". Doubly nested case would result, except
1284 * that the decoded instruction
1287 FETCH_DECODE_MODRM(mod, rh, rl);
1289 if (DEBUG_DECODE()) {
1290 /* XXX DECODE_PRINTF may be changed to something more
1291 general, so that it is important to leave the strings
1292 in the same format, even though the result is that the
1293 above test is done twice. */
1297 DECODE_PRINTF("ADD\t");
1300 DECODE_PRINTF("OR\t");
1303 DECODE_PRINTF("ADC\t");
1306 DECODE_PRINTF("SBB\t");
1309 DECODE_PRINTF("AND\t");
1312 DECODE_PRINTF("SUB\t");
1315 DECODE_PRINTF("XOR\t");
1318 DECODE_PRINTF("CMP\t");
1323 /* know operation, decode the mod byte to find the addressing
1326 DECODE_PRINTF("BYTE PTR ");
1327 destoffset = decode_rmXX_address(mod, rl);
1329 destval = fetch_data_byte(destoffset);
1330 imm = fetch_byte_imm();
1331 DECODE_PRINTF2("%x\n", imm);
1333 destval = (*genop_byte_operation[rh]) (destval, imm);
1335 store_data_byte(destoffset, destval);
1336 } else { /* register to register */
1337 destreg = DECODE_RM_BYTE_REGISTER(rl);
1339 imm = fetch_byte_imm();
1340 DECODE_PRINTF2("%x\n", imm);
1342 *destreg = (*genop_byte_operation[rh]) (*destreg, imm);
1344 DECODE_CLEAR_SEGOVR();
1348 /****************************************************************************
1351 ****************************************************************************/
1352 static void x86emuOp_opc81_word_RM_IMM(u8 X86EMU_UNUSED(op1))
1358 * Weirdo special case instruction format. Part of the opcode
1359 * held below in "RH". Doubly nested case would result, except
1360 * that the decoded instruction
1363 FETCH_DECODE_MODRM(mod, rh, rl);
1365 if (DEBUG_DECODE()) {
1366 /* XXX DECODE_PRINTF may be changed to something more
1367 general, so that it is important to leave the strings
1368 in the same format, even though the result is that the
1369 above test is done twice. */
1373 DECODE_PRINTF("ADD\t");
1376 DECODE_PRINTF("OR\t");
1379 DECODE_PRINTF("ADC\t");
1382 DECODE_PRINTF("SBB\t");
1385 DECODE_PRINTF("AND\t");
1388 DECODE_PRINTF("SUB\t");
1391 DECODE_PRINTF("XOR\t");
1394 DECODE_PRINTF("CMP\t");
1400 * Know operation, decode the mod byte to find the addressing
1404 DECODE_PRINTF("DWORD PTR ");
1405 destoffset = decode_rmXX_address(mod, rl);
1406 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1410 destval = fetch_data_long(destoffset);
1411 imm = fetch_long_imm();
1412 DECODE_PRINTF2("%x\n", imm);
1414 destval = (*genop_long_operation[rh]) (destval, imm);
1416 store_data_long(destoffset, destval);
1421 destval = fetch_data_word(destoffset);
1422 imm = fetch_word_imm();
1423 DECODE_PRINTF2("%x\n", imm);
1425 destval = (*genop_word_operation[rh]) (destval, imm);
1427 store_data_word(destoffset, destval);
1429 } else { /* register to register */
1430 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1433 destreg = DECODE_RM_LONG_REGISTER(rl);
1435 imm = fetch_long_imm();
1436 DECODE_PRINTF2("%x\n", imm);
1438 *destreg = (*genop_long_operation[rh]) (*destreg, imm);
1442 destreg = DECODE_RM_WORD_REGISTER(rl);
1444 imm = fetch_word_imm();
1445 DECODE_PRINTF2("%x\n", imm);
1447 *destreg = (*genop_word_operation[rh]) (*destreg, imm);
1450 DECODE_CLEAR_SEGOVR();
1454 /****************************************************************************
1457 ****************************************************************************/
1458 static void x86emuOp_opc82_byte_RM_IMM(u8 X86EMU_UNUSED(op1))
1467 * Weirdo special case instruction format. Part of the opcode
1468 * held below in "RH". Doubly nested case would result, except
1469 * that the decoded instruction Similar to opcode 81, except that
1470 * the immediate byte is sign extended to a word length.
1473 FETCH_DECODE_MODRM(mod, rh, rl);
1475 if (DEBUG_DECODE()) {
1476 /* XXX DECODE_PRINTF may be changed to something more
1477 general, so that it is important to leave the strings
1478 in the same format, even though the result is that the
1479 above test is done twice. */
1482 DECODE_PRINTF("ADD\t");
1485 DECODE_PRINTF("OR\t");
1488 DECODE_PRINTF("ADC\t");
1491 DECODE_PRINTF("SBB\t");
1494 DECODE_PRINTF("AND\t");
1497 DECODE_PRINTF("SUB\t");
1500 DECODE_PRINTF("XOR\t");
1503 DECODE_PRINTF("CMP\t");
1508 /* know operation, decode the mod byte to find the addressing
1511 DECODE_PRINTF("BYTE PTR ");
1512 destoffset = decode_rmXX_address(mod, rl);
1513 destval = fetch_data_byte(destoffset);
1514 imm = fetch_byte_imm();
1515 DECODE_PRINTF2(",%x\n", imm);
1517 destval = (*genop_byte_operation[rh]) (destval, imm);
1519 store_data_byte(destoffset, destval);
1520 } else { /* register to register */
1521 destreg = DECODE_RM_BYTE_REGISTER(rl);
1522 imm = fetch_byte_imm();
1523 DECODE_PRINTF2(",%x\n", imm);
1525 *destreg = (*genop_byte_operation[rh]) (*destreg, imm);
1527 DECODE_CLEAR_SEGOVR();
1531 /****************************************************************************
1534 ****************************************************************************/
1535 static void x86emuOp_opc83_word_RM_IMM(u8 X86EMU_UNUSED(op1))
1541 * Weirdo special case instruction format. Part of the opcode
1542 * held below in "RH". Doubly nested case would result, except
1543 * that the decoded instruction Similar to opcode 81, except that
1544 * the immediate byte is sign extended to a word length.
1547 FETCH_DECODE_MODRM(mod, rh, rl);
1549 if (DEBUG_DECODE()) {
1550 /* XXX DECODE_PRINTF may be changed to something more
1551 general, so that it is important to leave the strings
1552 in the same format, even though the result is that the
1553 above test is done twice. */
1556 DECODE_PRINTF("ADD\t");
1559 DECODE_PRINTF("OR\t");
1562 DECODE_PRINTF("ADC\t");
1565 DECODE_PRINTF("SBB\t");
1568 DECODE_PRINTF("AND\t");
1571 DECODE_PRINTF("SUB\t");
1574 DECODE_PRINTF("XOR\t");
1577 DECODE_PRINTF("CMP\t");
1582 /* know operation, decode the mod byte to find the addressing
1585 DECODE_PRINTF("DWORD PTR ");
1586 destoffset = decode_rmXX_address(mod,rl);
1588 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1591 destval = fetch_data_long(destoffset);
1592 imm = (s8) fetch_byte_imm();
1593 DECODE_PRINTF2(",%x\n", imm);
1595 destval = (*genop_long_operation[rh]) (destval, imm);
1597 store_data_long(destoffset, destval);
1601 destval = fetch_data_word(destoffset);
1602 imm = (s8) fetch_byte_imm();
1603 DECODE_PRINTF2(",%x\n", imm);
1605 destval = (*genop_word_operation[rh]) (destval, imm);
1607 store_data_word(destoffset, destval);
1609 } else { /* register to register */
1610 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1613 destreg = DECODE_RM_LONG_REGISTER(rl);
1614 imm = (s8) fetch_byte_imm();
1615 DECODE_PRINTF2(",%x\n", imm);
1617 *destreg = (*genop_long_operation[rh]) (*destreg, imm);
1621 destreg = DECODE_RM_WORD_REGISTER(rl);
1622 imm = (s8) fetch_byte_imm();
1623 DECODE_PRINTF2(",%x\n", imm);
1625 *destreg = (*genop_word_operation[rh]) (*destreg, imm);
1628 DECODE_CLEAR_SEGOVR();
1632 /****************************************************************************
1635 ****************************************************************************/
1636 static void x86emuOp_test_byte_RM_R(u8 X86EMU_UNUSED(op1))
1639 u8 *destreg, *srcreg;
1644 DECODE_PRINTF("TEST\t");
1645 FETCH_DECODE_MODRM(mod, rh, rl);
1647 destoffset = decode_rmXX_address(mod, rl);
1649 destval = fetch_data_byte(destoffset);
1650 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1651 DECODE_PRINTF("\n");
1653 test_byte(destval, *srcreg);
1654 } else { /* register to register */
1655 destreg = DECODE_RM_BYTE_REGISTER(rl);
1657 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1658 DECODE_PRINTF("\n");
1660 test_byte(*destreg, *srcreg);
1662 DECODE_CLEAR_SEGOVR();
1666 /****************************************************************************
1669 ****************************************************************************/
1670 static void x86emuOp_test_word_RM_R(u8 X86EMU_UNUSED(op1))
1676 DECODE_PRINTF("TEST\t");
1677 FETCH_DECODE_MODRM(mod, rh, rl);
1679 destoffset = decode_rmXX_address(mod, rl);
1680 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1685 destval = fetch_data_long(destoffset);
1686 srcreg = DECODE_RM_LONG_REGISTER(rh);
1687 DECODE_PRINTF("\n");
1689 test_long(destval, *srcreg);
1695 destval = fetch_data_word(destoffset);
1696 srcreg = DECODE_RM_WORD_REGISTER(rh);
1697 DECODE_PRINTF("\n");
1699 test_word(destval, *srcreg);
1701 } else { /* register to register */
1702 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1703 u32 *destreg,*srcreg;
1705 destreg = DECODE_RM_LONG_REGISTER(rl);
1707 srcreg = DECODE_RM_LONG_REGISTER(rh);
1708 DECODE_PRINTF("\n");
1710 test_long(*destreg, *srcreg);
1712 u16 *destreg,*srcreg;
1714 destreg = DECODE_RM_WORD_REGISTER(rl);
1716 srcreg = DECODE_RM_WORD_REGISTER(rh);
1717 DECODE_PRINTF("\n");
1719 test_word(*destreg, *srcreg);
1722 DECODE_CLEAR_SEGOVR();
1726 /****************************************************************************
1729 ****************************************************************************/
1730 static void x86emuOp_xchg_byte_RM_R(u8 X86EMU_UNUSED(op1))
1733 u8 *destreg, *srcreg;
1739 DECODE_PRINTF("XCHG\t");
1740 FETCH_DECODE_MODRM(mod, rh, rl);
1742 destoffset = decode_rmXX_address(mod, rl);
1744 destval = fetch_data_byte(destoffset);
1745 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1746 DECODE_PRINTF("\n");
1751 store_data_byte(destoffset, destval);
1752 } else { /* register to register */
1753 destreg = DECODE_RM_BYTE_REGISTER(rl);
1755 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1756 DECODE_PRINTF("\n");
1762 DECODE_CLEAR_SEGOVR();
1766 /****************************************************************************
1769 ****************************************************************************/
1770 static void x86emuOp_xchg_word_RM_R(u8 X86EMU_UNUSED(op1))
1776 DECODE_PRINTF("XCHG\t");
1777 FETCH_DECODE_MODRM(mod, rh, rl);
1779 destoffset = decode_rmXX_address(mod, rl);
1781 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1785 destval = fetch_data_long(destoffset);
1786 srcreg = DECODE_RM_LONG_REGISTER(rh);
1787 DECODE_PRINTF("\n");
1792 store_data_long(destoffset, destval);
1797 destval = fetch_data_word(destoffset);
1798 srcreg = DECODE_RM_WORD_REGISTER(rh);
1799 DECODE_PRINTF("\n");
1804 store_data_word(destoffset, destval);
1806 } else { /* register to register */
1807 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1808 u32 *destreg,*srcreg;
1811 destreg = DECODE_RM_LONG_REGISTER(rl);
1813 srcreg = DECODE_RM_LONG_REGISTER(rh);
1814 DECODE_PRINTF("\n");
1820 u16 *destreg,*srcreg;
1823 destreg = DECODE_RM_WORD_REGISTER(rl);
1825 srcreg = DECODE_RM_WORD_REGISTER(rh);
1826 DECODE_PRINTF("\n");
1833 DECODE_CLEAR_SEGOVR();
1837 /****************************************************************************
1840 ****************************************************************************/
1841 static void x86emuOp_mov_byte_RM_R(u8 X86EMU_UNUSED(op1))
1844 u8 *destreg, *srcreg;
1848 DECODE_PRINTF("MOV\t");
1849 FETCH_DECODE_MODRM(mod, rh, rl);
1851 destoffset = decode_rmXX_address(mod, rl);
1853 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1854 DECODE_PRINTF("\n");
1856 store_data_byte(destoffset, *srcreg);
1857 } else { /* register to register */
1858 destreg = DECODE_RM_BYTE_REGISTER(rl);
1860 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1861 DECODE_PRINTF("\n");
1865 DECODE_CLEAR_SEGOVR();
1869 /****************************************************************************
1872 ****************************************************************************/
1873 static void x86emuOp_mov_word_RM_R(u8 X86EMU_UNUSED(op1))
1879 DECODE_PRINTF("MOV\t");
1880 FETCH_DECODE_MODRM(mod, rh, rl);
1882 destoffset = decode_rmXX_address(mod, rl);
1883 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1887 srcreg = DECODE_RM_LONG_REGISTER(rh);
1888 DECODE_PRINTF("\n");
1890 store_data_long(destoffset, *srcreg);
1895 srcreg = DECODE_RM_WORD_REGISTER(rh);
1896 DECODE_PRINTF("\n");
1898 store_data_word(destoffset, *srcreg);
1900 } else { /* register to register */
1901 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1902 u32 *destreg,*srcreg;
1904 destreg = DECODE_RM_LONG_REGISTER(rl);
1906 srcreg = DECODE_RM_LONG_REGISTER(rh);
1907 DECODE_PRINTF("\n");
1911 u16 *destreg,*srcreg;
1913 destreg = DECODE_RM_WORD_REGISTER(rl);
1915 srcreg = DECODE_RM_WORD_REGISTER(rh);
1916 DECODE_PRINTF("\n");
1921 DECODE_CLEAR_SEGOVR();
1925 /****************************************************************************
1928 ****************************************************************************/
1929 static void x86emuOp_mov_byte_R_RM(u8 X86EMU_UNUSED(op1))
1932 u8 *destreg, *srcreg;
1937 DECODE_PRINTF("MOV\t");
1938 FETCH_DECODE_MODRM(mod, rh, rl);
1940 destreg = DECODE_RM_BYTE_REGISTER(rh);
1942 srcoffset = decode_rmXX_address(mod, rl);
1943 srcval = fetch_data_byte(srcoffset);
1944 DECODE_PRINTF("\n");
1947 } else { /* register to register */
1948 destreg = DECODE_RM_BYTE_REGISTER(rh);
1950 srcreg = DECODE_RM_BYTE_REGISTER(rl);
1951 DECODE_PRINTF("\n");
1955 DECODE_CLEAR_SEGOVR();
1959 /****************************************************************************
1962 ****************************************************************************/
1963 static void x86emuOp_mov_word_R_RM(u8 X86EMU_UNUSED(op1))
1969 DECODE_PRINTF("MOV\t");
1970 FETCH_DECODE_MODRM(mod, rh, rl);
1972 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1976 destreg = DECODE_RM_LONG_REGISTER(rh);
1978 srcoffset = decode_rmXX_address(mod, rl);
1979 srcval = fetch_data_long(srcoffset);
1980 DECODE_PRINTF("\n");
1987 destreg = DECODE_RM_WORD_REGISTER(rh);
1989 srcoffset = decode_rmXX_address(mod, rl);
1990 srcval = fetch_data_word(srcoffset);
1991 DECODE_PRINTF("\n");
1995 } else { /* register to register */
1996 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1997 u32 *destreg, *srcreg;
1999 destreg = DECODE_RM_LONG_REGISTER(rh);
2001 srcreg = DECODE_RM_LONG_REGISTER(rl);
2002 DECODE_PRINTF("\n");
2006 u16 *destreg, *srcreg;
2008 destreg = DECODE_RM_WORD_REGISTER(rh);
2010 srcreg = DECODE_RM_WORD_REGISTER(rl);
2011 DECODE_PRINTF("\n");
2016 DECODE_CLEAR_SEGOVR();
2020 /****************************************************************************
2023 ****************************************************************************/
2024 static void x86emuOp_mov_word_RM_SR(u8 X86EMU_UNUSED(op1))
2027 u16 *destreg, *srcreg;
2032 DECODE_PRINTF("MOV\t");
2033 FETCH_DECODE_MODRM(mod, rh, rl);
2035 destoffset = decode_rmXX_address(mod, rl);
2037 srcreg = decode_rm_seg_register(rh);
2038 DECODE_PRINTF("\n");
2041 store_data_word(destoffset, destval);
2042 } else { /* register to register */
2043 destreg = DECODE_RM_WORD_REGISTER(rl);
2045 srcreg = decode_rm_seg_register(rh);
2046 DECODE_PRINTF("\n");
2050 DECODE_CLEAR_SEGOVR();
2054 /****************************************************************************
2057 ****************************************************************************/
2058 static void x86emuOp_lea_word_R_M(u8 X86EMU_UNUSED(op1))
2065 * TODO: Need to handle address size prefix!
2067 * lea eax,[eax+ebx*2] ??
2071 DECODE_PRINTF("LEA\t");
2072 FETCH_DECODE_MODRM(mod, rh, rl);
2074 srcreg = DECODE_RM_WORD_REGISTER(rh);
2076 destoffset = decode_rmXX_address(mod, rl);
2077 DECODE_PRINTF("\n");
2079 *srcreg = (u16)destoffset;
2081 /* } else { undefined. Do nothing. } */
2082 DECODE_CLEAR_SEGOVR();
2086 /****************************************************************************
2089 ****************************************************************************/
2090 static void x86emuOp_mov_word_SR_RM(u8 X86EMU_UNUSED(op1))
2093 u16 *destreg, *srcreg;
2098 DECODE_PRINTF("MOV\t");
2099 FETCH_DECODE_MODRM(mod, rh, rl);
2101 destreg = decode_rm_seg_register(rh);
2103 srcoffset = decode_rmXX_address(mod, rl);
2104 srcval = fetch_data_word(srcoffset);
2105 DECODE_PRINTF("\n");
2108 } else { /* register to register */
2109 destreg = decode_rm_seg_register(rh);
2111 srcreg = DECODE_RM_WORD_REGISTER(rl);
2112 DECODE_PRINTF("\n");
2117 * Clean up, and reset all the R_xSP pointers to the correct
2118 * locations. This is about 3x too much overhead (doing all the
2119 * segreg ptrs when only one is needed, but this instruction
2120 * *cannot* be that common, and this isn't too much work anyway.
2122 DECODE_CLEAR_SEGOVR();
2126 /****************************************************************************
2129 ****************************************************************************/
2130 static void x86emuOp_pop_RM(u8 X86EMU_UNUSED(op1))
2136 DECODE_PRINTF("POP\t");
2137 FETCH_DECODE_MODRM(mod, rh, rl);
2139 DECODE_PRINTF("ILLEGAL DECODE OF OPCODE 8F\n");
2143 destoffset = decode_rmXX_address(mod, rl);
2144 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2147 DECODE_PRINTF("\n");
2149 destval = pop_long();
2150 store_data_long(destoffset, destval);
2154 DECODE_PRINTF("\n");
2156 destval = pop_word();
2157 store_data_word(destoffset, destval);
2159 } else { /* register to register */
2160 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2163 destreg = DECODE_RM_LONG_REGISTER(rl);
2164 DECODE_PRINTF("\n");
2166 *destreg = pop_long();
2170 destreg = DECODE_RM_WORD_REGISTER(rl);
2171 DECODE_PRINTF("\n");
2173 *destreg = pop_word();
2176 DECODE_CLEAR_SEGOVR();
2180 /****************************************************************************
2183 ****************************************************************************/
2184 static void x86emuOp_nop(u8 X86EMU_UNUSED(op1))
2187 DECODE_PRINTF("NOP\n");
2189 DECODE_CLEAR_SEGOVR();
2193 /****************************************************************************
2195 Handles opcode 0x91-0x97
2196 ****************************************************************************/
2197 static void x86emuOp_xchg_word_AX_register(u8 X86EMU_UNUSED(op1))
2205 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2207 DECODE_PRINTF("XCHG\tEAX,");
2208 reg32 = DECODE_RM_LONG_REGISTER(op1);
2209 DECODE_PRINTF("\n");
2212 M.x86.R_EAX = *reg32;
2216 DECODE_PRINTF("XCHG\tAX,");
2217 reg16 = DECODE_RM_WORD_REGISTER(op1);
2218 DECODE_PRINTF("\n");
2221 M.x86.R_AX = *reg16;
2224 DECODE_CLEAR_SEGOVR();
2228 /****************************************************************************
2231 ****************************************************************************/
2232 static void x86emuOp_cbw(u8 X86EMU_UNUSED(op1))
2235 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2236 DECODE_PRINTF("CWDE\n");
2238 DECODE_PRINTF("CBW\n");
2241 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2242 if (M.x86.R_AX & 0x8000) {
2243 M.x86.R_EAX |= 0xffff0000;
2245 M.x86.R_EAX &= 0x0000ffff;
2248 if (M.x86.R_AL & 0x80) {
2254 DECODE_CLEAR_SEGOVR();
2258 /****************************************************************************
2261 ****************************************************************************/
2262 static void x86emuOp_cwd(u8 X86EMU_UNUSED(op1))
2265 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2266 DECODE_PRINTF("CDQ\n");
2268 DECODE_PRINTF("CWD\n");
2270 DECODE_PRINTF("CWD\n");
2272 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2273 if (M.x86.R_EAX & 0x80000000) {
2274 M.x86.R_EDX = 0xffffffff;
2279 if (M.x86.R_AX & 0x8000) {
2280 M.x86.R_DX = 0xffff;
2285 DECODE_CLEAR_SEGOVR();
2289 /****************************************************************************
2292 ****************************************************************************/
2293 static void x86emuOp_call_far_IMM(u8 X86EMU_UNUSED(op1))
2298 DECODE_PRINTF("CALL\t");
2299 faroff = fetch_word_imm();
2300 farseg = fetch_word_imm();
2301 DECODE_PRINTF2("%04x:", farseg);
2302 DECODE_PRINTF2("%04x\n", faroff);
2303 CALL_TRACE(M.x86.saved_cs, M.x86.saved_ip, farseg, faroff, "FAR ");
2307 * Hooked interrupt vectors calling into our "BIOS" will cause
2308 * problems unless all intersegment stuff is checked for BIOS
2309 * access. Check needed here. For moment, let it alone.
2312 push_word(M.x86.R_CS);
2313 M.x86.R_CS = farseg;
2314 push_word(M.x86.R_IP);
2315 M.x86.R_IP = faroff;
2316 DECODE_CLEAR_SEGOVR();
2320 /****************************************************************************
2323 ****************************************************************************/
2324 static void x86emuOp_wait(u8 X86EMU_UNUSED(op1))
2327 DECODE_PRINTF("WAIT");
2330 DECODE_CLEAR_SEGOVR();
2334 /****************************************************************************
2337 ****************************************************************************/
2338 static void x86emuOp_pushf_word(u8 X86EMU_UNUSED(op1))
2343 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2344 DECODE_PRINTF("PUSHFD\n");
2346 DECODE_PRINTF("PUSHF\n");
2350 /* clear out *all* bits not representing flags, and turn on real bits */
2351 flags = (M.x86.R_EFLG & F_MSK) | F_ALWAYS_ON;
2352 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2355 push_word((u16)flags);
2357 DECODE_CLEAR_SEGOVR();
2361 /****************************************************************************
2364 ****************************************************************************/
2365 static void x86emuOp_popf_word(u8 X86EMU_UNUSED(op1))
2368 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2369 DECODE_PRINTF("POPFD\n");
2371 DECODE_PRINTF("POPF\n");
2374 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2375 M.x86.R_EFLG = pop_long();
2377 M.x86.R_FLG = pop_word();
2379 DECODE_CLEAR_SEGOVR();
2383 /****************************************************************************
2386 ****************************************************************************/
2387 static void x86emuOp_sahf(u8 X86EMU_UNUSED(op1))
2390 DECODE_PRINTF("SAHF\n");
2392 /* clear the lower bits of the flag register */
2393 M.x86.R_FLG &= 0xffffff00;
2394 /* or in the AH register into the flags register */
2395 M.x86.R_FLG |= M.x86.R_AH;
2396 DECODE_CLEAR_SEGOVR();
2400 /****************************************************************************
2403 ****************************************************************************/
2404 static void x86emuOp_lahf(u8 X86EMU_UNUSED(op1))
2407 DECODE_PRINTF("LAHF\n");
2409 M.x86.R_AH = (u8)(M.x86.R_FLG & 0xff);
2410 /*undocumented TC++ behavior??? Nope. It's documented, but
2411 you have too look real hard to notice it. */
2413 DECODE_CLEAR_SEGOVR();
2417 /****************************************************************************
2420 ****************************************************************************/
2421 static void x86emuOp_mov_AL_M_IMM(u8 X86EMU_UNUSED(op1))
2426 DECODE_PRINTF("MOV\tAL,");
2427 offset = fetch_word_imm();
2428 DECODE_PRINTF2("[%04x]\n", offset);
2430 M.x86.R_AL = fetch_data_byte(offset);
2431 DECODE_CLEAR_SEGOVR();
2435 /****************************************************************************
2438 ****************************************************************************/
2439 static void x86emuOp_mov_AX_M_IMM(u8 X86EMU_UNUSED(op1))
2444 offset = fetch_word_imm();
2445 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2446 DECODE_PRINTF2("MOV\tEAX,[%04x]\n", offset);
2448 DECODE_PRINTF2("MOV\tAX,[%04x]\n", offset);
2451 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2452 M.x86.R_EAX = fetch_data_long(offset);
2454 M.x86.R_AX = fetch_data_word(offset);
2456 DECODE_CLEAR_SEGOVR();
2460 /****************************************************************************
2463 ****************************************************************************/
2464 static void x86emuOp_mov_M_AL_IMM(u8 X86EMU_UNUSED(op1))
2469 DECODE_PRINTF("MOV\t");
2470 offset = fetch_word_imm();
2471 DECODE_PRINTF2("[%04x],AL\n", offset);
2473 store_data_byte(offset, M.x86.R_AL);
2474 DECODE_CLEAR_SEGOVR();
2478 /****************************************************************************
2481 ****************************************************************************/
2482 static void x86emuOp_mov_M_AX_IMM(u8 X86EMU_UNUSED(op1))
2487 offset = fetch_word_imm();
2488 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2489 DECODE_PRINTF2("MOV\t[%04x],EAX\n", offset);
2491 DECODE_PRINTF2("MOV\t[%04x],AX\n", offset);
2494 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2495 store_data_long(offset, M.x86.R_EAX);
2497 store_data_word(offset, M.x86.R_AX);
2499 DECODE_CLEAR_SEGOVR();
2503 /****************************************************************************
2506 ****************************************************************************/
2507 static void x86emuOp_movs_byte(u8 X86EMU_UNUSED(op1))
2514 DECODE_PRINTF("MOVS\tBYTE\n");
2515 if (ACCESS_FLAG(F_DF)) /* down */
2521 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2522 /* dont care whether REPE or REPNE */
2523 /* move them until (E)CX is ZERO. */
2524 count = (M.x86.mode & SYSMODE_32BIT_REP) ? M.x86.R_ECX : M.x86.R_CX;
2526 if (M.x86.mode & SYSMODE_32BIT_REP)
2528 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2531 val = fetch_data_byte(M.x86.R_SI);
2532 store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, val);
2535 if (M.x86.intr & INTR_HALTED)
2538 DECODE_CLEAR_SEGOVR();
2542 /****************************************************************************
2545 ****************************************************************************/
2546 static void x86emuOp_movs_word(u8 X86EMU_UNUSED(op1))
2553 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2554 DECODE_PRINTF("MOVS\tDWORD\n");
2555 if (ACCESS_FLAG(F_DF)) /* down */
2560 DECODE_PRINTF("MOVS\tWORD\n");
2561 if (ACCESS_FLAG(F_DF)) /* down */
2568 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2569 /* dont care whether REPE or REPNE */
2570 /* move them until (E)CX is ZERO. */
2571 count = (M.x86.mode & SYSMODE_32BIT_REP) ? M.x86.R_ECX : M.x86.R_CX;
2573 if (M.x86.mode & SYSMODE_32BIT_REP)
2575 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2578 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2579 val = fetch_data_long(M.x86.R_SI);
2580 store_data_long_abs(M.x86.R_ES, M.x86.R_DI, val);
2582 val = fetch_data_word(M.x86.R_SI);
2583 store_data_word_abs(M.x86.R_ES, M.x86.R_DI, (u16)val);
2587 if (M.x86.intr & INTR_HALTED)
2590 DECODE_CLEAR_SEGOVR();
2594 /****************************************************************************
2597 ****************************************************************************/
2598 static void x86emuOp_cmps_byte(u8 X86EMU_UNUSED(op1))
2604 DECODE_PRINTF("CMPS\tBYTE\n");
2606 if (ACCESS_FLAG(F_DF)) /* down */
2611 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2613 /* move them until (E)CX is ZERO. */
2614 while (((M.x86.mode & SYSMODE_32BIT_REP) ? M.x86.R_ECX : M.x86.R_CX) != 0) {
2615 val1 = fetch_data_byte(M.x86.R_SI);
2616 val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2617 cmp_byte(val1, val2);
2618 if (M.x86.mode & SYSMODE_32BIT_REP)
2624 if ( (M.x86.mode & SYSMODE_PREFIX_REPE) && (ACCESS_FLAG(F_ZF) == 0) ) break;
2625 if ( (M.x86.mode & SYSMODE_PREFIX_REPNE) && ACCESS_FLAG(F_ZF) ) break;
2626 if (M.x86.intr & INTR_HALTED)
2629 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2631 val1 = fetch_data_byte(M.x86.R_SI);
2632 val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2633 cmp_byte(val1, val2);
2637 DECODE_CLEAR_SEGOVR();
2641 /****************************************************************************
2644 ****************************************************************************/
2645 static void x86emuOp_cmps_word(u8 X86EMU_UNUSED(op1))
2651 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2652 DECODE_PRINTF("CMPS\tDWORD\n");
2655 DECODE_PRINTF("CMPS\tWORD\n");
2658 if (ACCESS_FLAG(F_DF)) /* down */
2662 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2664 /* move them until (E)CX is ZERO. */
2665 while (((M.x86.mode & SYSMODE_32BIT_REP) ? M.x86.R_ECX : M.x86.R_CX) != 0) {
2666 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2667 val1 = fetch_data_long(M.x86.R_SI);
2668 val2 = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
2669 cmp_long(val1, val2);
2671 val1 = fetch_data_word(M.x86.R_SI);
2672 val2 = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
2673 cmp_word((u16)val1, (u16)val2);
2675 if (M.x86.mode & SYSMODE_32BIT_REP)
2681 if ( (M.x86.mode & SYSMODE_PREFIX_REPE) && ACCESS_FLAG(F_ZF) == 0 ) break;
2682 if ( (M.x86.mode & SYSMODE_PREFIX_REPNE) && ACCESS_FLAG(F_ZF) ) break;
2683 if (M.x86.intr & INTR_HALTED)
2686 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2688 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2689 val1 = fetch_data_long(M.x86.R_SI);
2690 val2 = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
2691 cmp_long(val1, val2);
2693 val1 = fetch_data_word(M.x86.R_SI);
2694 val2 = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
2695 cmp_word((u16)val1, (u16)val2);
2700 DECODE_CLEAR_SEGOVR();
2704 /****************************************************************************
2707 ****************************************************************************/
2708 static void x86emuOp_test_AL_IMM(u8 X86EMU_UNUSED(op1))
2713 DECODE_PRINTF("TEST\tAL,");
2714 imm = fetch_byte_imm();
2715 DECODE_PRINTF2("%04x\n", imm);
2717 test_byte(M.x86.R_AL, (u8)imm);
2718 DECODE_CLEAR_SEGOVR();
2722 /****************************************************************************
2725 ****************************************************************************/
2726 static void x86emuOp_test_AX_IMM(u8 X86EMU_UNUSED(op1))
2731 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2732 DECODE_PRINTF("TEST\tEAX,");
2733 srcval = fetch_long_imm();
2735 DECODE_PRINTF("TEST\tAX,");
2736 srcval = fetch_word_imm();
2738 DECODE_PRINTF2("%x\n", srcval);
2740 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2741 test_long(M.x86.R_EAX, srcval);
2743 test_word(M.x86.R_AX, (u16)srcval);
2745 DECODE_CLEAR_SEGOVR();
2749 /****************************************************************************
2752 ****************************************************************************/
2753 static void x86emuOp_stos_byte(u8 X86EMU_UNUSED(op1))
2758 DECODE_PRINTF("STOS\tBYTE\n");
2759 if (ACCESS_FLAG(F_DF)) /* down */
2764 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2765 /* dont care whether REPE or REPNE */
2766 /* move them until (E)CX is ZERO. */
2767 while (((M.x86.mode & SYSMODE_32BIT_REP) ? M.x86.R_ECX : M.x86.R_CX) != 0) {
2768 store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AL);
2769 if (M.x86.mode & SYSMODE_32BIT_REP)
2774 if (M.x86.intr & INTR_HALTED)
2777 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2779 store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AL);
2782 DECODE_CLEAR_SEGOVR();
2786 /****************************************************************************
2789 ****************************************************************************/
2790 static void x86emuOp_stos_word(u8 X86EMU_UNUSED(op1))
2796 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2797 DECODE_PRINTF("STOS\tDWORD\n");
2798 if (ACCESS_FLAG(F_DF)) /* down */
2803 DECODE_PRINTF("STOS\tWORD\n");
2804 if (ACCESS_FLAG(F_DF)) /* down */
2811 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2812 /* dont care whether REPE or REPNE */
2813 /* move them until (E)CX is ZERO. */
2814 count = (M.x86.mode & SYSMODE_32BIT_REP) ? M.x86.R_ECX : M.x86.R_CX;
2816 if (M.x86.mode & SYSMODE_32BIT_REP)
2818 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2821 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2822 store_data_long_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_EAX);
2824 store_data_word_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AX);
2827 if (M.x86.intr & INTR_HALTED)
2830 DECODE_CLEAR_SEGOVR();
2834 /****************************************************************************
2837 ****************************************************************************/
2838 static void x86emuOp_lods_byte(u8 X86EMU_UNUSED(op1))
2843 DECODE_PRINTF("LODS\tBYTE\n");
2845 if (ACCESS_FLAG(F_DF)) /* down */
2849 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2850 /* dont care whether REPE or REPNE */
2851 /* move them until (E)CX is ZERO. */
2852 while (((M.x86.mode & SYSMODE_32BIT_REP) ? M.x86.R_ECX : M.x86.R_CX) != 0) {
2853 M.x86.R_AL = fetch_data_byte(M.x86.R_SI);
2854 if (M.x86.mode & SYSMODE_32BIT_REP)
2859 if (M.x86.intr & INTR_HALTED)
2862 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2864 M.x86.R_AL = fetch_data_byte(M.x86.R_SI);
2867 DECODE_CLEAR_SEGOVR();
2871 /****************************************************************************
2874 ****************************************************************************/
2875 static void x86emuOp_lods_word(u8 X86EMU_UNUSED(op1))
2881 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2882 DECODE_PRINTF("LODS\tDWORD\n");
2883 if (ACCESS_FLAG(F_DF)) /* down */
2888 DECODE_PRINTF("LODS\tWORD\n");
2889 if (ACCESS_FLAG(F_DF)) /* down */
2896 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2897 /* dont care whether REPE or REPNE */
2898 /* move them until (E)CX is ZERO. */
2899 count = (M.x86.mode & SYSMODE_32BIT_REP) ? M.x86.R_ECX : M.x86.R_CX;
2901 if (M.x86.mode & SYSMODE_32BIT_REP)
2903 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2906 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2907 M.x86.R_EAX = fetch_data_long(M.x86.R_SI);
2909 M.x86.R_AX = fetch_data_word(M.x86.R_SI);
2912 if (M.x86.intr & INTR_HALTED)
2915 DECODE_CLEAR_SEGOVR();
2919 /****************************************************************************
2922 ****************************************************************************/
2923 static void x86emuOp_scas_byte(u8 X86EMU_UNUSED(op1))
2929 DECODE_PRINTF("SCAS\tBYTE\n");
2931 if (ACCESS_FLAG(F_DF)) /* down */
2935 if (M.x86.mode & SYSMODE_PREFIX_REPE) {
2937 /* move them until (E)CX is ZERO. */
2938 while (((M.x86.mode & SYSMODE_32BIT_REP) ? M.x86.R_ECX : M.x86.R_CX) != 0) {
2939 val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2940 cmp_byte(M.x86.R_AL, val2);
2941 if (M.x86.mode & SYSMODE_32BIT_REP)
2946 if (ACCESS_FLAG(F_ZF) == 0)
2948 if (M.x86.intr & INTR_HALTED)
2951 M.x86.mode &= ~SYSMODE_PREFIX_REPE;
2952 } else if (M.x86.mode & SYSMODE_PREFIX_REPNE) {
2954 /* move them until (E)CX is ZERO. */
2955 while (((M.x86.mode & SYSMODE_32BIT_REP) ? M.x86.R_ECX : M.x86.R_CX) != 0) {
2956 val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2957 cmp_byte(M.x86.R_AL, val2);
2958 if (M.x86.mode & SYSMODE_32BIT_REP)
2963 if (ACCESS_FLAG(F_ZF))
2964 break; /* zero flag set means equal */
2965 if (M.x86.intr & INTR_HALTED)
2968 M.x86.mode &= ~SYSMODE_PREFIX_REPNE;
2970 val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2971 cmp_byte(M.x86.R_AL, val2);
2974 DECODE_CLEAR_SEGOVR();
2978 /****************************************************************************
2981 ****************************************************************************/
2982 static void x86emuOp_scas_word(u8 X86EMU_UNUSED(op1))
2988 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2989 DECODE_PRINTF("SCAS\tDWORD\n");
2990 if (ACCESS_FLAG(F_DF)) /* down */
2995 DECODE_PRINTF("SCAS\tWORD\n");
2996 if (ACCESS_FLAG(F_DF)) /* down */
3002 if (M.x86.mode & SYSMODE_PREFIX_REPE) {
3004 /* move them until (E)CX is ZERO. */
3005 while (((M.x86.mode & SYSMODE_32BIT_REP) ? M.x86.R_ECX : M.x86.R_CX) != 0) {
3006 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3007 val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
3008 cmp_long(M.x86.R_EAX, val);
3010 val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
3011 cmp_word(M.x86.R_AX, (u16)val);
3013 if (M.x86.mode & SYSMODE_32BIT_REP)
3018 if (ACCESS_FLAG(F_ZF) == 0)
3020 if (M.x86.intr & INTR_HALTED)
3023 M.x86.mode &= ~SYSMODE_PREFIX_REPE;
3024 } else if (M.x86.mode & SYSMODE_PREFIX_REPNE) {
3026 /* move them until (E)CX is ZERO. */
3027 while (((M.x86.mode & SYSMODE_32BIT_REP) ? M.x86.R_ECX : M.x86.R_CX) != 0) {
3028 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3029 val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
3030 cmp_long(M.x86.R_EAX, val);
3032 val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
3033 cmp_word(M.x86.R_AX, (u16)val);
3035 if (M.x86.mode & SYSMODE_32BIT_REP)
3040 if (ACCESS_FLAG(F_ZF))
3041 break; /* zero flag set means equal */
3042 if (M.x86.intr & INTR_HALTED)
3045 M.x86.mode &= ~SYSMODE_PREFIX_REPNE;
3047 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3048 val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
3049 cmp_long(M.x86.R_EAX, val);
3051 val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
3052 cmp_word(M.x86.R_AX, (u16)val);
3056 DECODE_CLEAR_SEGOVR();
3060 /****************************************************************************
3062 Handles opcode 0xb0 - 0xb7
3063 ****************************************************************************/
3064 static void x86emuOp_mov_byte_register_IMM(u8 op1)
3069 DECODE_PRINTF("MOV\t");
3070 ptr = DECODE_RM_BYTE_REGISTER(op1 & 0x7);
3072 imm = fetch_byte_imm();
3073 DECODE_PRINTF2("%x\n", imm);
3076 DECODE_CLEAR_SEGOVR();
3080 /****************************************************************************
3082 Handles opcode 0xb8 - 0xbf
3083 ****************************************************************************/
3084 static void x86emuOp_mov_word_register_IMM(u8 X86EMU_UNUSED(op1))
3091 DECODE_PRINTF("MOV\t");
3092 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3094 reg32 = DECODE_RM_LONG_REGISTER(op1);
3095 srcval = fetch_long_imm();
3096 DECODE_PRINTF2(",%x\n", srcval);
3101 reg16 = DECODE_RM_WORD_REGISTER(op1);
3102 srcval = fetch_word_imm();
3103 DECODE_PRINTF2(",%x\n", srcval);
3105 *reg16 = (u16)srcval;
3107 DECODE_CLEAR_SEGOVR();
3111 /****************************************************************************
3114 ****************************************************************************/
3115 static void x86emuOp_opcC0_byte_RM_MEM(u8 X86EMU_UNUSED(op1))
3124 * Yet another weirdo special case instruction format. Part of
3125 * the opcode held below in "RH". Doubly nested case would
3126 * result, except that the decoded instruction
3129 FETCH_DECODE_MODRM(mod, rh, rl);
3131 if (DEBUG_DECODE()) {
3132 /* XXX DECODE_PRINTF may be changed to something more
3133 general, so that it is important to leave the strings
3134 in the same format, even though the result is that the
3135 above test is done twice. */
3139 DECODE_PRINTF("ROL\t");
3142 DECODE_PRINTF("ROR\t");
3145 DECODE_PRINTF("RCL\t");
3148 DECODE_PRINTF("RCR\t");
3151 DECODE_PRINTF("SHL\t");
3154 DECODE_PRINTF("SHR\t");
3157 DECODE_PRINTF("SAL\t");
3160 DECODE_PRINTF("SAR\t");
3165 /* know operation, decode the mod byte to find the addressing
3168 DECODE_PRINTF("BYTE PTR ");
3169 destoffset = decode_rmXX_address(mod, rl);
3170 amt = fetch_byte_imm();
3171 DECODE_PRINTF2(",%x\n", amt);
3172 destval = fetch_data_byte(destoffset);
3174 destval = (*opcD0_byte_operation[rh]) (destval, amt);
3175 store_data_byte(destoffset, destval);
3176 } else { /* register to register */
3177 destreg = DECODE_RM_BYTE_REGISTER(rl);
3178 amt = fetch_byte_imm();
3179 DECODE_PRINTF2(",%x\n", amt);
3181 destval = (*opcD0_byte_operation[rh]) (*destreg, amt);
3184 DECODE_CLEAR_SEGOVR();
3188 /****************************************************************************
3191 ****************************************************************************/
3192 static void x86emuOp_opcC1_word_RM_MEM(u8 X86EMU_UNUSED(op1))
3199 * Yet another weirdo special case instruction format. Part of
3200 * the opcode held below in "RH". Doubly nested case would
3201 * result, except that the decoded instruction
3204 FETCH_DECODE_MODRM(mod, rh, rl);
3206 if (DEBUG_DECODE()) {
3207 /* XXX DECODE_PRINTF may be changed to something more
3208 general, so that it is important to leave the strings
3209 in the same format, even though the result is that the
3210 above test is done twice. */
3214 DECODE_PRINTF("ROL\t");
3217 DECODE_PRINTF("ROR\t");
3220 DECODE_PRINTF("RCL\t");
3223 DECODE_PRINTF("RCR\t");
3226 DECODE_PRINTF("SHL\t");
3229 DECODE_PRINTF("SHR\t");
3232 DECODE_PRINTF("SAL\t");
3235 DECODE_PRINTF("SAR\t");
3240 /* know operation, decode the mod byte to find the addressing
3243 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3246 DECODE_PRINTF("DWORD PTR ");
3247 destoffset = decode_rmXX_address(mod, rl);
3248 amt = fetch_byte_imm();
3249 DECODE_PRINTF2(",%x\n", amt);
3250 destval = fetch_data_long(destoffset);
3252 destval = (*opcD1_long_operation[rh]) (destval, amt);
3253 store_data_long(destoffset, destval);
3257 DECODE_PRINTF("WORD PTR ");
3258 destoffset = decode_rmXX_address(mod, rl);
3259 amt = fetch_byte_imm();
3260 DECODE_PRINTF2(",%x\n", amt);
3261 destval = fetch_data_word(destoffset);
3263 destval = (*opcD1_word_operation[rh]) (destval, amt);
3264 store_data_word(destoffset, destval);
3266 } else { /* register to register */
3267 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3270 destreg = DECODE_RM_LONG_REGISTER(rl);
3271 amt = fetch_byte_imm();
3272 DECODE_PRINTF2(",%x\n", amt);
3274 *destreg = (*opcD1_long_operation[rh]) (*destreg, amt);
3278 destreg = DECODE_RM_WORD_REGISTER(rl);
3279 amt = fetch_byte_imm();
3280 DECODE_PRINTF2(",%x\n", amt);
3282 *destreg = (*opcD1_word_operation[rh]) (*destreg, amt);
3285 DECODE_CLEAR_SEGOVR();
3289 /****************************************************************************
3292 ****************************************************************************/
3293 static void x86emuOp_ret_near_IMM(u8 X86EMU_UNUSED(op1))
3298 DECODE_PRINTF("RET\t");
3299 imm = fetch_word_imm();
3300 DECODE_PRINTF2("%x\n", imm);
3302 M.x86.R_IP = pop_word();
3303 RETURN_TRACE(M.x86.saved_cs,M.x86.saved_ip, M.x86.R_CS, M.x86.R_IP, "NEAR");
3305 DECODE_CLEAR_SEGOVR();
3309 /****************************************************************************
3312 ****************************************************************************/
3313 static void x86emuOp_ret_near(u8 X86EMU_UNUSED(op1))
3316 DECODE_PRINTF("RET\n");
3318 M.x86.R_IP = pop_word();
3319 RETURN_TRACE(M.x86.saved_cs,M.x86.saved_ip, M.x86.R_CS, M.x86.R_IP, "NEAR");
3320 DECODE_CLEAR_SEGOVR();
3324 /****************************************************************************
3327 ****************************************************************************/
3328 static void x86emuOp_les_R_IMM(u8 X86EMU_UNUSED(op1))
3335 DECODE_PRINTF("LES\t");
3336 FETCH_DECODE_MODRM(mod, rh, rl);
3338 dstreg = DECODE_RM_WORD_REGISTER(rh);
3340 srcoffset = decode_rmXX_address(mod, rl);
3341 DECODE_PRINTF("\n");
3343 *dstreg = fetch_data_word(srcoffset);
3344 M.x86.R_ES = fetch_data_word(srcoffset + 2);
3346 /* else UNDEFINED! register to register */
3348 DECODE_CLEAR_SEGOVR();
3352 /****************************************************************************
3355 ****************************************************************************/
3356 static void x86emuOp_lds_R_IMM(u8 X86EMU_UNUSED(op1))
3363 DECODE_PRINTF("LDS\t");
3364 FETCH_DECODE_MODRM(mod, rh, rl);
3366 dstreg = DECODE_RM_WORD_REGISTER(rh);
3368 srcoffset = decode_rmXX_address(mod, rl);
3369 DECODE_PRINTF("\n");
3371 *dstreg = fetch_data_word(srcoffset);
3372 M.x86.R_DS = fetch_data_word(srcoffset + 2);
3374 /* else UNDEFINED! */
3375 DECODE_CLEAR_SEGOVR();
3379 /****************************************************************************
3382 ****************************************************************************/
3383 static void x86emuOp_mov_byte_RM_IMM(u8 X86EMU_UNUSED(op1))
3391 DECODE_PRINTF("MOV\t");
3392 FETCH_DECODE_MODRM(mod, rh, rl);
3394 DECODE_PRINTF("ILLEGAL DECODE OF OPCODE c6\n");
3398 DECODE_PRINTF("BYTE PTR ");
3399 destoffset = decode_rmXX_address(mod, rl);
3400 imm = fetch_byte_imm();
3401 DECODE_PRINTF2(",%2x\n", imm);
3403 store_data_byte(destoffset, imm);
3404 } else { /* register to register */
3405 destreg = DECODE_RM_BYTE_REGISTER(rl);
3406 imm = fetch_byte_imm();
3407 DECODE_PRINTF2(",%2x\n", imm);
3411 DECODE_CLEAR_SEGOVR();
3415 /****************************************************************************
3418 ****************************************************************************/
3419 static void x86emuOp_mov_word_RM_IMM(u8 X86EMU_UNUSED(op1))
3425 DECODE_PRINTF("MOV\t");
3426 FETCH_DECODE_MODRM(mod, rh, rl);
3428 DECODE_PRINTF("ILLEGAL DECODE OF OPCODE 8F\n");
3432 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3435 DECODE_PRINTF("DWORD PTR ");
3436 destoffset = decode_rmXX_address(mod, rl);
3437 imm = fetch_long_imm();
3438 DECODE_PRINTF2(",%x\n", imm);
3440 store_data_long(destoffset, imm);
3444 DECODE_PRINTF("WORD PTR ");
3445 destoffset = decode_rmXX_address(mod, rl);
3446 imm = fetch_word_imm();
3447 DECODE_PRINTF2(",%x\n", imm);
3449 store_data_word(destoffset, imm);
3451 } else { /* register to register */
3452 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3456 destreg = DECODE_RM_LONG_REGISTER(rl);
3457 imm = fetch_long_imm();
3458 DECODE_PRINTF2(",%x\n", imm);
3465 destreg = DECODE_RM_WORD_REGISTER(rl);
3466 imm = fetch_word_imm();
3467 DECODE_PRINTF2(",%x\n", imm);
3472 DECODE_CLEAR_SEGOVR();
3476 /****************************************************************************
3479 ****************************************************************************/
3480 static void x86emuOp_enter(u8 X86EMU_UNUSED(op1))
3482 u16 local,frame_pointer;
3487 local = fetch_word_imm();
3488 nesting = fetch_byte_imm();
3489 DECODE_PRINTF2("ENTER %x\n", local);
3490 DECODE_PRINTF2(",%x\n", nesting);
3492 push_word(M.x86.R_BP);
3493 frame_pointer = M.x86.R_SP;
3495 for (i = 1; i < nesting; i++) {
3497 push_word(fetch_data_word_abs(M.x86.R_SS, M.x86.R_BP));
3499 push_word(frame_pointer);
3501 M.x86.R_BP = frame_pointer;
3502 M.x86.R_SP = (u16)(M.x86.R_SP - local);
3503 DECODE_CLEAR_SEGOVR();
3507 /****************************************************************************
3510 ****************************************************************************/
3511 static void x86emuOp_leave(u8 X86EMU_UNUSED(op1))
3514 DECODE_PRINTF("LEAVE\n");
3516 M.x86.R_SP = M.x86.R_BP;
3517 M.x86.R_BP = pop_word();
3518 DECODE_CLEAR_SEGOVR();
3522 /****************************************************************************
3525 ****************************************************************************/
3526 static void x86emuOp_ret_far_IMM(u8 X86EMU_UNUSED(op1))
3531 DECODE_PRINTF("RETF\t");
3532 imm = fetch_word_imm();
3533 DECODE_PRINTF2("%x\n", imm);
3535 M.x86.R_IP = pop_word();
3536 M.x86.R_CS = pop_word();
3537 RETURN_TRACE(M.x86.saved_cs,M.x86.saved_ip, M.x86.R_CS, M.x86.R_IP, "FAR");
3539 DECODE_CLEAR_SEGOVR();
3543 /****************************************************************************
3546 ****************************************************************************/
3547 static void x86emuOp_ret_far(u8 X86EMU_UNUSED(op1))
3550 DECODE_PRINTF("RETF\n");
3552 M.x86.R_IP = pop_word();
3553 M.x86.R_CS = pop_word();
3554 RETURN_TRACE(M.x86.saved_cs,M.x86.saved_ip, M.x86.R_CS, M.x86.R_IP, "FAR");
3555 DECODE_CLEAR_SEGOVR();
3559 /****************************************************************************
3562 ****************************************************************************/
3563 static void x86emuOp_int3(u8 X86EMU_UNUSED(op1))
3568 DECODE_PRINTF("INT 3\n");
3569 tmp = (u16) mem_access_word(3 * 4 + 2);
3570 /* access the segment register */
3572 if (_X86EMU_intrTab[3]) {
3573 (*_X86EMU_intrTab[3])(3);
3575 push_word((u16)M.x86.R_FLG);
3578 push_word(M.x86.R_CS);
3579 M.x86.R_CS = mem_access_word(3 * 4 + 2);
3580 push_word(M.x86.R_IP);
3581 M.x86.R_IP = mem_access_word(3 * 4);
3583 DECODE_CLEAR_SEGOVR();
3587 /****************************************************************************
3590 ****************************************************************************/
3591 static void x86emuOp_int_IMM(u8 X86EMU_UNUSED(op1))
3597 DECODE_PRINTF("INT\t");
3598 intnum = fetch_byte_imm();
3599 DECODE_PRINTF2("%x\n", intnum);
3600 tmp = mem_access_word(intnum * 4 + 2);
3602 if (_X86EMU_intrTab[intnum]) {
3603 (*_X86EMU_intrTab[intnum])(intnum);
3605 push_word((u16)M.x86.R_FLG);
3608 push_word(M.x86.R_CS);
3609 M.x86.R_CS = mem_access_word(intnum * 4 + 2);
3610 push_word(M.x86.R_IP);
3611 M.x86.R_IP = mem_access_word(intnum * 4);
3613 DECODE_CLEAR_SEGOVR();
3617 /****************************************************************************
3620 ****************************************************************************/
3621 static void x86emuOp_into(u8 X86EMU_UNUSED(op1))
3626 DECODE_PRINTF("INTO\n");
3628 if (ACCESS_FLAG(F_OF)) {
3629 tmp = mem_access_word(4 * 4 + 2);
3630 if (_X86EMU_intrTab[4]) {
3631 (*_X86EMU_intrTab[4])(4);
3633 push_word((u16)M.x86.R_FLG);
3636 push_word(M.x86.R_CS);
3637 M.x86.R_CS = mem_access_word(4 * 4 + 2);
3638 push_word(M.x86.R_IP);
3639 M.x86.R_IP = mem_access_word(4 * 4);
3642 DECODE_CLEAR_SEGOVR();
3646 /****************************************************************************
3649 ****************************************************************************/
3650 static void x86emuOp_iret(u8 X86EMU_UNUSED(op1))
3653 DECODE_PRINTF("IRET\n");
3657 M.x86.R_IP = pop_word();
3658 M.x86.R_CS = pop_word();
3659 M.x86.R_FLG = pop_word();
3660 DECODE_CLEAR_SEGOVR();
3664 /****************************************************************************
3667 ****************************************************************************/
3668 static void x86emuOp_opcD0_byte_RM_1(u8 X86EMU_UNUSED(op1))
3676 * Yet another weirdo special case instruction format. Part of
3677 * the opcode held below in "RH". Doubly nested case would
3678 * result, except that the decoded instruction
3681 FETCH_DECODE_MODRM(mod, rh, rl);
3683 if (DEBUG_DECODE()) {
3684 /* XXX DECODE_PRINTF may be changed to something more
3685 general, so that it is important to leave the strings
3686 in the same format, even though the result is that the
3687 above test is done twice. */
3690 DECODE_PRINTF("ROL\t");
3693 DECODE_PRINTF("ROR\t");
3696 DECODE_PRINTF("RCL\t");
3699 DECODE_PRINTF("RCR\t");
3702 DECODE_PRINTF("SHL\t");
3705 DECODE_PRINTF("SHR\t");
3708 DECODE_PRINTF("SAL\t");
3711 DECODE_PRINTF("SAR\t");
3716 /* know operation, decode the mod byte to find the addressing
3719 DECODE_PRINTF("BYTE PTR ");
3720 destoffset = decode_rmXX_address(mod, rl);
3721 DECODE_PRINTF(",1\n");
3722 destval = fetch_data_byte(destoffset);
3724 destval = (*opcD0_byte_operation[rh]) (destval, 1);
3725 store_data_byte(destoffset, destval);
3726 } else { /* register to register */
3727 destreg = DECODE_RM_BYTE_REGISTER(rl);
3728 DECODE_PRINTF(",1\n");
3730 destval = (*opcD0_byte_operation[rh]) (*destreg, 1);
3733 DECODE_CLEAR_SEGOVR();
3737 /****************************************************************************
3740 ****************************************************************************/
3741 static void x86emuOp_opcD1_word_RM_1(u8 X86EMU_UNUSED(op1))
3747 * Yet another weirdo special case instruction format. Part of
3748 * the opcode held below in "RH". Doubly nested case would
3749 * result, except that the decoded instruction
3752 FETCH_DECODE_MODRM(mod, rh, rl);
3754 if (DEBUG_DECODE()) {
3755 /* XXX DECODE_PRINTF may be changed to something more
3756 general, so that it is important to leave the strings
3757 in the same format, even though the result is that the
3758 above test is done twice. */
3761 DECODE_PRINTF("ROL\t");
3764 DECODE_PRINTF("ROR\t");
3767 DECODE_PRINTF("RCL\t");
3770 DECODE_PRINTF("RCR\t");
3773 DECODE_PRINTF("SHL\t");
3776 DECODE_PRINTF("SHR\t");
3779 DECODE_PRINTF("SAL\t");
3782 DECODE_PRINTF("SAR\t");
3787 /* know operation, decode the mod byte to find the addressing
3790 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3793 DECODE_PRINTF("DWORD PTR ");
3794 destoffset = decode_rmXX_address(mod, rl);
3795 DECODE_PRINTF(",1\n");
3796 destval = fetch_data_long(destoffset);
3798 destval = (*opcD1_long_operation[rh]) (destval, 1);
3799 store_data_long(destoffset, destval);
3803 DECODE_PRINTF("WORD PTR ");
3804 destoffset = decode_rmXX_address(mod, rl);
3805 DECODE_PRINTF(",1\n");
3806 destval = fetch_data_word(destoffset);
3808 destval = (*opcD1_word_operation[rh]) (destval, 1);
3809 store_data_word(destoffset, destval);
3811 } else { /* register to register */
3812 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3816 destreg = DECODE_RM_LONG_REGISTER(rl);
3817 DECODE_PRINTF(",1\n");
3819 destval = (*opcD1_long_operation[rh]) (*destreg, 1);
3825 destreg = DECODE_RM_WORD_REGISTER(rl);
3826 DECODE_PRINTF(",1\n");
3828 destval = (*opcD1_word_operation[rh]) (*destreg, 1);
3832 DECODE_CLEAR_SEGOVR();
3836 /****************************************************************************
3839 ****************************************************************************/
3840 static void x86emuOp_opcD2_byte_RM_CL(u8 X86EMU_UNUSED(op1))
3849 * Yet another weirdo special case instruction format. Part of
3850 * the opcode held below in "RH". Doubly nested case would
3851 * result, except that the decoded instruction
3854 FETCH_DECODE_MODRM(mod, rh, rl);
3856 if (DEBUG_DECODE()) {
3857 /* XXX DECODE_PRINTF may be changed to something more
3858 general, so that it is important to leave the strings
3859 in the same format, even though the result is that the
3860 above test is done twice. */
3863 DECODE_PRINTF("ROL\t");
3866 DECODE_PRINTF("ROR\t");
3869 DECODE_PRINTF("RCL\t");
3872 DECODE_PRINTF("RCR\t");
3875 DECODE_PRINTF("SHL\t");
3878 DECODE_PRINTF("SHR\t");
3881 DECODE_PRINTF("SAL\t");
3884 DECODE_PRINTF("SAR\t");
3889 /* know operation, decode the mod byte to find the addressing
3893 DECODE_PRINTF("BYTE PTR ");
3894 destoffset = decode_rmXX_address(mod, rl);
3895 DECODE_PRINTF(",CL\n");
3896 destval = fetch_data_byte(destoffset);
3898 destval = (*opcD0_byte_operation[rh]) (destval, amt);
3899 store_data_byte(destoffset, destval);
3900 } else { /* register to register */
3901 destreg = DECODE_RM_BYTE_REGISTER(rl);
3902 DECODE_PRINTF(",CL\n");
3904 destval = (*opcD0_byte_operation[rh]) (*destreg, amt);
3907 DECODE_CLEAR_SEGOVR();
3911 /****************************************************************************
3914 ****************************************************************************/
3915 static void x86emuOp_opcD3_word_RM_CL(u8 X86EMU_UNUSED(op1))
3922 * Yet another weirdo special case instruction format. Part of
3923 * the opcode held below in "RH". Doubly nested case would
3924 * result, except that the decoded instruction
3927 FETCH_DECODE_MODRM(mod, rh, rl);
3929 if (DEBUG_DECODE()) {
3930 /* XXX DECODE_PRINTF may be changed to something more
3931 general, so that it is important to leave the strings
3932 in the same format, even though the result is that the
3933 above test is done twice. */
3936 DECODE_PRINTF("ROL\t");
3939 DECODE_PRINTF("ROR\t");
3942 DECODE_PRINTF("RCL\t");
3945 DECODE_PRINTF("RCR\t");
3948 DECODE_PRINTF("SHL\t");
3951 DECODE_PRINTF("SHR\t");
3954 DECODE_PRINTF("SAL\t");
3957 DECODE_PRINTF("SAR\t");
3962 /* know operation, decode the mod byte to find the addressing
3966 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3969 DECODE_PRINTF("DWORD PTR ");
3970 destoffset = decode_rmXX_address(mod, rl);
3971 DECODE_PRINTF(",CL\n");
3972 destval = fetch_data_long(destoffset);
3974 destval = (*opcD1_long_operation[rh]) (destval, amt);
3975 store_data_long(destoffset, destval);
3979 DECODE_PRINTF("WORD PTR ");
3980 destoffset = decode_rmXX_address(mod, rl);
3981 DECODE_PRINTF(",CL\n");
3982 destval = fetch_data_word(destoffset);
3984 destval = (*opcD1_word_operation[rh]) (destval, amt);
3985 store_data_word(destoffset, destval);
3987 } else { /* register to register */
3988 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3991 destreg = DECODE_RM_LONG_REGISTER(rl);
3992 DECODE_PRINTF(",CL\n");
3994 *destreg = (*opcD1_long_operation[rh]) (*destreg, amt);
3998 destreg = DECODE_RM_WORD_REGISTER(rl);
3999 DECODE_PRINTF(",CL\n");
4001 *destreg = (*opcD1_word_operation[rh]) (*destreg, amt);
4004 DECODE_CLEAR_SEGOVR();
4008 /****************************************************************************
4011 ****************************************************************************/
4012 static void x86emuOp_aam(u8 X86EMU_UNUSED(op1))
4017 DECODE_PRINTF("AAM\n");
4018 a = fetch_byte_imm(); /* this is a stupid encoding. */
4020 DECODE_PRINTF("ERROR DECODING AAM\n");
4025 /* note the type change here --- returning AL and AH in AX. */
4026 M.x86.R_AX = aam_word(M.x86.R_AL);
4027 DECODE_CLEAR_SEGOVR();
4031 /****************************************************************************
4034 ****************************************************************************/
4035 static void x86emuOp_aad(u8 X86EMU_UNUSED(op1))
4040 DECODE_PRINTF("AAD\n");
4041 a = fetch_byte_imm();
4043 M.x86.R_AX = aad_word(M.x86.R_AX);
4044 DECODE_CLEAR_SEGOVR();
4048 /* opcode 0xd6 ILLEGAL OPCODE */
4050 /****************************************************************************
4053 ****************************************************************************/
4054 static void x86emuOp_xlat(u8 X86EMU_UNUSED(op1))
4059 DECODE_PRINTF("XLAT\n");
4061 addr = (u16)(M.x86.R_BX + (u8)M.x86.R_AL);
4062 M.x86.R_AL = fetch_data_byte(addr);
4063 DECODE_CLEAR_SEGOVR();
4067 /* instuctions D8 .. DF are in i87_ops.c */
4069 /****************************************************************************
4072 ****************************************************************************/
4073 static void x86emuOp_loopne(u8 X86EMU_UNUSED(op1))
4078 DECODE_PRINTF("LOOPNE\t");
4079 ip = (s8) fetch_byte_imm();
4080 ip += (s16) M.x86.R_IP;
4081 DECODE_PRINTF2("%04x\n", ip);
4083 if (M.x86.mode & SYSMODE_PREFIX_ADDR)
4087 if (((M.x86.mode & SYSMODE_PREFIX_ADDR) ? M.x86.R_ECX : M.x86.R_CX) != 0 && !ACCESS_FLAG(F_ZF)) /* (E)CX != 0 and !ZF */
4089 DECODE_CLEAR_SEGOVR();
4093 /****************************************************************************
4096 ****************************************************************************/
4097 static void x86emuOp_loope(u8 X86EMU_UNUSED(op1))
4102 DECODE_PRINTF("LOOPE\t");
4103 ip = (s8) fetch_byte_imm();
4104 ip += (s16) M.x86.R_IP;
4105 DECODE_PRINTF2("%04x\n", ip);
4107 if (M.x86.mode & SYSMODE_PREFIX_ADDR)
4111 if (((M.x86.mode & SYSMODE_PREFIX_ADDR) ? M.x86.R_ECX : M.x86.R_CX) != 0 && ACCESS_FLAG(F_ZF)) /* (E)CX != 0 and ZF */
4113 DECODE_CLEAR_SEGOVR();
4117 /****************************************************************************
4120 ****************************************************************************/
4121 static void x86emuOp_loop(u8 X86EMU_UNUSED(op1))
4126 DECODE_PRINTF("LOOP\t");
4127 ip = (s8) fetch_byte_imm();
4128 ip += (s16) M.x86.R_IP;
4129 DECODE_PRINTF2("%04x\n", ip);
4131 if (M.x86.mode & SYSMODE_PREFIX_ADDR)
4135 if (((M.x86.mode & SYSMODE_PREFIX_ADDR) ? M.x86.R_ECX : M.x86.R_CX) != 0) /* (E)CX != 0 */
4137 DECODE_CLEAR_SEGOVR();
4141 /****************************************************************************
4144 ****************************************************************************/
4145 static void x86emuOp_jcxz(u8 X86EMU_UNUSED(op1))
4150 /* jump to byte offset if overflow flag is set */
4152 DECODE_PRINTF("JCXZ\t");
4153 offset = (s8)fetch_byte_imm();
4154 target = (u16)(M.x86.R_IP + offset);
4155 DECODE_PRINTF2("%x\n", target);
4157 if (M.x86.R_CX == 0) {
4158 M.x86.R_IP = target;
4159 JMP_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, M.x86.R_IP, " CXZ ");
4161 DECODE_CLEAR_SEGOVR();
4165 /****************************************************************************
4168 ****************************************************************************/
4169 static void x86emuOp_in_byte_AL_IMM(u8 X86EMU_UNUSED(op1))
4174 DECODE_PRINTF("IN\t");
4175 port = (u8) fetch_byte_imm();
4176 DECODE_PRINTF2("%x,AL\n", port);
4178 M.x86.R_AL = (*sys_inb)(port);
4179 DECODE_CLEAR_SEGOVR();
4183 /****************************************************************************
4186 ****************************************************************************/
4187 static void x86emuOp_in_word_AX_IMM(u8 X86EMU_UNUSED(op1))
4192 DECODE_PRINTF("IN\t");
4193 port = (u8) fetch_byte_imm();
4194 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4195 DECODE_PRINTF2("EAX,%x\n", port);
4197 DECODE_PRINTF2("AX,%x\n", port);
4200 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4201 M.x86.R_EAX = (*sys_inl)(port);
4203 M.x86.R_AX = (*sys_inw)(port);
4205 DECODE_CLEAR_SEGOVR();
4209 /****************************************************************************
4212 ****************************************************************************/
4213 static void x86emuOp_out_byte_IMM_AL(u8 X86EMU_UNUSED(op1))
4218 DECODE_PRINTF("OUT\t");
4219 port = (u8) fetch_byte_imm();
4220 DECODE_PRINTF2("%x,AL\n", port);
4222 (*sys_outb)(port, M.x86.R_AL);
4223 DECODE_CLEAR_SEGOVR();
4227 /****************************************************************************
4230 ****************************************************************************/
4231 static void x86emuOp_out_word_IMM_AX(u8 X86EMU_UNUSED(op1))
4236 DECODE_PRINTF("OUT\t");
4237 port = (u8) fetch_byte_imm();
4238 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4239 DECODE_PRINTF2("%x,EAX\n", port);
4241 DECODE_PRINTF2("%x,AX\n", port);
4244 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4245 (*sys_outl)(port, M.x86.R_EAX);
4247 (*sys_outw)(port, M.x86.R_AX);
4249 DECODE_CLEAR_SEGOVR();
4253 /****************************************************************************
4256 ****************************************************************************/
4257 static void x86emuOp_call_near_IMM(u8 X86EMU_UNUSED(op1))
4262 DECODE_PRINTF("CALL\t");
4263 ip = (s16) fetch_word_imm();
4264 ip += (s16) M.x86.R_IP; /* CHECK SIGN */
4265 DECODE_PRINTF2("%04x\n", ip);
4266 CALL_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, ip, "");
4268 push_word(M.x86.R_IP);
4270 DECODE_CLEAR_SEGOVR();
4274 /****************************************************************************
4277 ****************************************************************************/
4278 static void x86emuOp_jump_near_IMM(u8 X86EMU_UNUSED(op1))
4283 DECODE_PRINTF("JMP\t");
4284 ip = (s16)fetch_word_imm();
4285 ip += (s16)M.x86.R_IP;
4286 DECODE_PRINTF2("%04x\n", ip);
4287 JMP_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, ip, " NEAR ");
4289 M.x86.R_IP = (u16)ip;
4290 DECODE_CLEAR_SEGOVR();
4294 /****************************************************************************
4297 ****************************************************************************/
4298 static void x86emuOp_jump_far_IMM(u8 X86EMU_UNUSED(op1))
4303 DECODE_PRINTF("JMP\tFAR ");
4304 ip = fetch_word_imm();
4305 cs = fetch_word_imm();
4306 DECODE_PRINTF2("%04x:", cs);
4307 DECODE_PRINTF2("%04x\n", ip);
4308 JMP_TRACE(M.x86.saved_cs, M.x86.saved_ip, cs, ip, " FAR ");
4312 DECODE_CLEAR_SEGOVR();
4316 /****************************************************************************
4319 ****************************************************************************/
4320 static void x86emuOp_jump_byte_IMM(u8 X86EMU_UNUSED(op1))
4326 DECODE_PRINTF("JMP\t");
4327 offset = (s8)fetch_byte_imm();
4328 target = (u16)(M.x86.R_IP + offset);
4329 DECODE_PRINTF2("%x\n", target);
4330 JMP_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, target, " BYTE ");
4332 M.x86.R_IP = target;
4333 DECODE_CLEAR_SEGOVR();
4337 /****************************************************************************
4340 ****************************************************************************/
4341 static void x86emuOp_in_byte_AL_DX(u8 X86EMU_UNUSED(op1))
4344 DECODE_PRINTF("IN\tAL,DX\n");
4346 M.x86.R_AL = (*sys_inb)(M.x86.R_DX);
4347 DECODE_CLEAR_SEGOVR();
4351 /****************************************************************************
4354 ****************************************************************************/
4355 static void x86emuOp_in_word_AX_DX(u8 X86EMU_UNUSED(op1))
4358 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4359 DECODE_PRINTF("IN\tEAX,DX\n");
4361 DECODE_PRINTF("IN\tAX,DX\n");
4364 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4365 M.x86.R_EAX = (*sys_inl)(M.x86.R_DX);
4367 M.x86.R_AX = (*sys_inw)(M.x86.R_DX);
4369 DECODE_CLEAR_SEGOVR();
4373 /****************************************************************************
4376 ****************************************************************************/
4377 static void x86emuOp_out_byte_DX_AL(u8 X86EMU_UNUSED(op1))
4380 DECODE_PRINTF("OUT\tDX,AL\n");
4382 (*sys_outb)(M.x86.R_DX, M.x86.R_AL);
4383 DECODE_CLEAR_SEGOVR();
4387 /****************************************************************************
4390 ****************************************************************************/
4391 static void x86emuOp_out_word_DX_AX(u8 X86EMU_UNUSED(op1))
4394 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4395 DECODE_PRINTF("OUT\tDX,EAX\n");
4397 DECODE_PRINTF("OUT\tDX,AX\n");
4400 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4401 (*sys_outl)(M.x86.R_DX, M.x86.R_EAX);
4403 (*sys_outw)(M.x86.R_DX, M.x86.R_AX);
4405 DECODE_CLEAR_SEGOVR();
4409 /****************************************************************************
4412 ****************************************************************************/
4413 static void x86emuOp_lock(u8 X86EMU_UNUSED(op1))
4416 DECODE_PRINTF("LOCK:\n");
4418 DECODE_CLEAR_SEGOVR();
4422 /*opcode 0xf1 ILLEGAL OPERATION */
4424 /****************************************************************************
4427 ****************************************************************************/
4428 static void x86emuOp_repne(u8 X86EMU_UNUSED(op1))
4431 DECODE_PRINTF("REPNE\n");
4433 M.x86.mode |= SYSMODE_PREFIX_REPNE;
4434 if (M.x86.mode & SYSMODE_PREFIX_ADDR)
4435 M.x86.mode |= SYSMODE_32BIT_REP;
4436 DECODE_CLEAR_SEGOVR();
4440 /****************************************************************************
4443 ****************************************************************************/
4444 static void x86emuOp_repe(u8 X86EMU_UNUSED(op1))
4447 DECODE_PRINTF("REPE\n");
4449 M.x86.mode |= SYSMODE_PREFIX_REPE;
4450 if (M.x86.mode & SYSMODE_PREFIX_ADDR)
4451 M.x86.mode |= SYSMODE_32BIT_REP;
4452 DECODE_CLEAR_SEGOVR();
4456 /****************************************************************************
4459 ****************************************************************************/
4460 static void x86emuOp_halt(u8 X86EMU_UNUSED(op1))
4463 DECODE_PRINTF("HALT\n");
4466 DECODE_CLEAR_SEGOVR();
4470 /****************************************************************************
4473 ****************************************************************************/
4474 static void x86emuOp_cmc(u8 X86EMU_UNUSED(op1))
4476 /* complement the carry flag. */
4478 DECODE_PRINTF("CMC\n");
4481 DECODE_CLEAR_SEGOVR();
4485 /****************************************************************************
4488 ****************************************************************************/
4489 static void x86emuOp_opcF6_byte_RM(u8 X86EMU_UNUSED(op1))
4496 /* long, drawn out code follows. Double switch for a total
4499 FETCH_DECODE_MODRM(mod, rh, rl);
4500 DECODE_PRINTF(opF6_names[rh]);
4502 DECODE_PRINTF("BYTE PTR ");
4503 destoffset = decode_rmXX_address(mod, rl);
4504 destval = fetch_data_byte(destoffset);
4507 case 0: /* test byte imm */
4509 srcval = fetch_byte_imm();
4510 DECODE_PRINTF2("%02x\n", srcval);
4512 test_byte(destval, srcval);
4515 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4519 DECODE_PRINTF("\n");
4521 destval = not_byte(destval);
4522 store_data_byte(destoffset, destval);
4525 DECODE_PRINTF("\n");
4527 destval = neg_byte(destval);
4528 store_data_byte(destoffset, destval);
4531 DECODE_PRINTF("\n");
4536 DECODE_PRINTF("\n");
4541 DECODE_PRINTF("\n");
4546 DECODE_PRINTF("\n");
4551 } else { /* mod=11 */
4552 destreg = DECODE_RM_BYTE_REGISTER(rl);
4554 case 0: /* test byte imm */
4556 srcval = fetch_byte_imm();
4557 DECODE_PRINTF2("%02x\n", srcval);
4559 test_byte(*destreg, srcval);
4562 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4566 DECODE_PRINTF("\n");
4568 *destreg = not_byte(*destreg);
4571 DECODE_PRINTF("\n");
4573 *destreg = neg_byte(*destreg);
4576 DECODE_PRINTF("\n");
4578 mul_byte(*destreg); /*!!! */
4581 DECODE_PRINTF("\n");
4583 imul_byte(*destreg);
4586 DECODE_PRINTF("\n");
4591 DECODE_PRINTF("\n");
4593 idiv_byte(*destreg);
4597 DECODE_CLEAR_SEGOVR();
4601 /****************************************************************************
4604 ****************************************************************************/
4605 static void x86emuOp_opcF7_word_RM(u8 X86EMU_UNUSED(op1))
4611 FETCH_DECODE_MODRM(mod, rh, rl);
4612 DECODE_PRINTF(opF6_names[rh]);
4615 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4616 u32 destval, srcval;
4618 DECODE_PRINTF("DWORD PTR ");
4619 destoffset = decode_rmXX_address(mod, rl);
4620 destval = fetch_data_long(destoffset);
4625 srcval = fetch_long_imm();
4626 DECODE_PRINTF2("%x\n", srcval);
4628 test_long(destval, srcval);
4631 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F7\n");
4635 DECODE_PRINTF("\n");
4637 destval = not_long(destval);
4638 store_data_long(destoffset, destval);
4641 DECODE_PRINTF("\n");
4643 destval = neg_long(destval);
4644 store_data_long(destoffset, destval);
4647 DECODE_PRINTF("\n");
4652 DECODE_PRINTF("\n");
4657 DECODE_PRINTF("\n");
4662 DECODE_PRINTF("\n");
4668 u16 destval, srcval;
4670 DECODE_PRINTF("WORD PTR ");
4671 destoffset = decode_rmXX_address(mod, rl);
4672 destval = fetch_data_word(destoffset);
4675 case 0: /* test word imm */
4677 srcval = fetch_word_imm();
4678 DECODE_PRINTF2("%x\n", srcval);
4680 test_word(destval, srcval);
4683 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F7\n");
4687 DECODE_PRINTF("\n");
4689 destval = not_word(destval);
4690 store_data_word(destoffset, destval);
4693 DECODE_PRINTF("\n");
4695 destval = neg_word(destval);
4696 store_data_word(destoffset, destval);
4699 DECODE_PRINTF("\n");
4704 DECODE_PRINTF("\n");
4709 DECODE_PRINTF("\n");
4714 DECODE_PRINTF("\n");
4721 } else { /* mod=11 */
4723 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4727 destreg = DECODE_RM_LONG_REGISTER(rl);
4730 case 0: /* test word imm */
4732 srcval = fetch_long_imm();
4733 DECODE_PRINTF2("%x\n", srcval);
4735 test_long(*destreg, srcval);
4738 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4742 DECODE_PRINTF("\n");
4744 *destreg = not_long(*destreg);
4747 DECODE_PRINTF("\n");
4749 *destreg = neg_long(*destreg);
4752 DECODE_PRINTF("\n");
4754 mul_long(*destreg); /*!!! */
4757 DECODE_PRINTF("\n");
4759 imul_long(*destreg);
4762 DECODE_PRINTF("\n");
4767 DECODE_PRINTF("\n");
4769 idiv_long(*destreg);
4776 destreg = DECODE_RM_WORD_REGISTER(rl);
4779 case 0: /* test word imm */
4781 srcval = fetch_word_imm();
4782 DECODE_PRINTF2("%x\n", srcval);
4784 test_word(*destreg, srcval);
4787 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4791 DECODE_PRINTF("\n");
4793 *destreg = not_word(*destreg);
4796 DECODE_PRINTF("\n");
4798 *destreg = neg_word(*destreg);
4801 DECODE_PRINTF("\n");
4803 mul_word(*destreg); /*!!! */
4806 DECODE_PRINTF("\n");
4808 imul_word(*destreg);
4811 DECODE_PRINTF("\n");
4816 DECODE_PRINTF("\n");
4818 idiv_word(*destreg);
4823 DECODE_CLEAR_SEGOVR();
4827 /****************************************************************************
4830 ****************************************************************************/
4831 static void x86emuOp_clc(u8 X86EMU_UNUSED(op1))
4833 /* clear the carry flag. */
4835 DECODE_PRINTF("CLC\n");
4838 DECODE_CLEAR_SEGOVR();
4842 /****************************************************************************
4845 ****************************************************************************/
4846 static void x86emuOp_stc(u8 X86EMU_UNUSED(op1))
4848 /* set the carry flag. */
4850 DECODE_PRINTF("STC\n");
4853 DECODE_CLEAR_SEGOVR();
4857 /****************************************************************************
4860 ****************************************************************************/
4861 static void x86emuOp_cli(u8 X86EMU_UNUSED(op1))
4863 /* clear interrupts. */
4865 DECODE_PRINTF("CLI\n");
4868 DECODE_CLEAR_SEGOVR();
4872 /****************************************************************************
4875 ****************************************************************************/
4876 static void x86emuOp_sti(u8 X86EMU_UNUSED(op1))
4878 /* enable interrupts. */
4880 DECODE_PRINTF("STI\n");
4883 DECODE_CLEAR_SEGOVR();
4887 /****************************************************************************
4890 ****************************************************************************/
4891 static void x86emuOp_cld(u8 X86EMU_UNUSED(op1))
4893 /* clear interrupts. */
4895 DECODE_PRINTF("CLD\n");
4898 DECODE_CLEAR_SEGOVR();
4902 /****************************************************************************
4905 ****************************************************************************/
4906 static void x86emuOp_std(u8 X86EMU_UNUSED(op1))
4908 /* clear interrupts. */
4910 DECODE_PRINTF("STD\n");
4913 DECODE_CLEAR_SEGOVR();
4917 /****************************************************************************
4920 ****************************************************************************/
4921 static void x86emuOp_opcFE_byte_RM(u8 X86EMU_UNUSED(op1))
4928 /* Yet another special case instruction. */
4930 FETCH_DECODE_MODRM(mod, rh, rl);
4932 if (DEBUG_DECODE()) {
4933 /* XXX DECODE_PRINTF may be changed to something more
4934 general, so that it is important to leave the strings
4935 in the same format, even though the result is that the
4936 above test is done twice. */
4940 DECODE_PRINTF("INC\t");
4943 DECODE_PRINTF("DEC\t");
4951 DECODE_PRINTF2("ILLEGAL OP MAJOR OP 0xFE MINOR OP %x \n", mod);
4958 DECODE_PRINTF("BYTE PTR ");
4959 destoffset = decode_rmXX_address(mod, rl);
4960 DECODE_PRINTF("\n");
4961 destval = fetch_data_byte(destoffset);
4964 destval = inc_byte(destval);
4966 destval = dec_byte(destval);
4967 store_data_byte(destoffset, destval);
4969 destreg = DECODE_RM_BYTE_REGISTER(rl);
4970 DECODE_PRINTF("\n");
4973 *destreg = inc_byte(*destreg);
4975 *destreg = dec_byte(*destreg);
4977 DECODE_CLEAR_SEGOVR();
4981 /****************************************************************************
4984 ****************************************************************************/
4985 static void x86emuOp_opcFF_word_RM(u8 X86EMU_UNUSED(op1))
4988 uint destoffset = 0;
4991 u16 destval,destval2;
4994 /* Yet another special case instruction. */
4996 FETCH_DECODE_MODRM(mod, rh, rl);
4998 if (DEBUG_DECODE()) {
4999 /* XXX DECODE_PRINTF may be changed to something more
5000 general, so that it is important to leave the strings
5001 in the same format, even though the result is that the
5002 above test is done twice. */
5006 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5007 DECODE_PRINTF("INC\tDWORD PTR ");
5009 DECODE_PRINTF("INC\tWORD PTR ");
5013 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5014 DECODE_PRINTF("DEC\tDWORD PTR ");
5016 DECODE_PRINTF("DEC\tWORD PTR ");
5020 DECODE_PRINTF("CALL\t ");
5023 DECODE_PRINTF("CALL\tFAR ");
5026 DECODE_PRINTF("JMP\t");
5029 DECODE_PRINTF("JMP\tFAR ");
5032 DECODE_PRINTF("PUSH\t");
5035 DECODE_PRINTF("ILLEGAL DECODING OF OPCODE FF\t");
5042 destoffset = decode_rmXX_address(mod, rl);
5043 DECODE_PRINTF("\n");
5045 case 0: /* inc word ptr ... */
5046 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5047 destval32 = fetch_data_long(destoffset);
5049 destval32 = inc_long(destval32);
5050 store_data_long(destoffset, destval32);
5052 destval = fetch_data_word(destoffset);
5054 destval = inc_word(destval);
5055 store_data_word(destoffset, destval);
5058 case 1: /* dec word ptr ... */
5059 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5060 destval32 = fetch_data_long(destoffset);
5062 destval32 = dec_long(destval32);
5063 store_data_long(destoffset, destval32);
5065 destval = fetch_data_word(destoffset);
5067 destval = dec_word(destval);
5068 store_data_word(destoffset, destval);
5071 case 2: /* call word ptr ... */
5072 destval = fetch_data_word(destoffset);
5074 push_word(M.x86.R_IP);
5075 M.x86.R_IP = destval;
5077 case 3: /* call far ptr ... */
5078 destval = fetch_data_word(destoffset);
5079 destval2 = fetch_data_word(destoffset + 2);
5081 push_word(M.x86.R_CS);
5082 M.x86.R_CS = destval2;
5083 push_word(M.x86.R_IP);
5084 M.x86.R_IP = destval;
5086 case 4: /* jmp word ptr ... */
5087 destval = fetch_data_word(destoffset);
5088 JMP_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, destval, " WORD ");
5090 M.x86.R_IP = destval;
5092 case 5: /* jmp far ptr ... */
5093 destval = fetch_data_word(destoffset);
5094 destval2 = fetch_data_word(destoffset + 2);
5095 JMP_TRACE(M.x86.saved_cs, M.x86.saved_ip, destval2, destval, " FAR ");
5097 M.x86.R_IP = destval;
5098 M.x86.R_CS = destval2;
5100 case 6: /* push word ptr ... */
5101 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5102 destval32 = fetch_data_long(destoffset);
5104 push_long(destval32);
5106 destval = fetch_data_word(destoffset);
5115 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5116 destreg32 = DECODE_RM_LONG_REGISTER(rl);
5117 DECODE_PRINTF("\n");
5119 *destreg32 = inc_long(*destreg32);
5121 destreg = DECODE_RM_WORD_REGISTER(rl);
5122 DECODE_PRINTF("\n");
5124 *destreg = inc_word(*destreg);
5128 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5129 destreg32 = DECODE_RM_LONG_REGISTER(rl);
5130 DECODE_PRINTF("\n");
5132 *destreg32 = dec_long(*destreg32);
5134 destreg = DECODE_RM_WORD_REGISTER(rl);
5135 DECODE_PRINTF("\n");
5137 *destreg = dec_word(*destreg);
5140 case 2: /* call word ptr ... */
5141 destreg = DECODE_RM_WORD_REGISTER(rl);
5142 DECODE_PRINTF("\n");
5144 push_word(M.x86.R_IP);
5145 M.x86.R_IP = *destreg;
5147 case 3: /* jmp far ptr ... */
5148 DECODE_PRINTF("OPERATION UNDEFINED 0XFF \n");
5153 case 4: /* jmp ... */
5154 destreg = DECODE_RM_WORD_REGISTER(rl);
5155 DECODE_PRINTF("\n");
5157 M.x86.R_IP = (u16) (*destreg);
5159 case 5: /* jmp far ptr ... */
5160 DECODE_PRINTF("OPERATION UNDEFINED 0XFF \n");
5165 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5166 destreg32 = DECODE_RM_LONG_REGISTER(rl);
5167 DECODE_PRINTF("\n");
5169 push_long(*destreg32);
5171 destreg = DECODE_RM_WORD_REGISTER(rl);
5172 DECODE_PRINTF("\n");
5174 push_word(*destreg);
5179 DECODE_CLEAR_SEGOVR();
5183 /***************************************************************************
5184 * Single byte operation code table:
5185 **************************************************************************/
5186 void (*x86emu_optab[256])(u8) =
5188 /* 0x00 */ x86emuOp_genop_byte_RM_R,
5189 /* 0x01 */ x86emuOp_genop_word_RM_R,
5190 /* 0x02 */ x86emuOp_genop_byte_R_RM,
5191 /* 0x03 */ x86emuOp_genop_word_R_RM,
5192 /* 0x04 */ x86emuOp_genop_byte_AL_IMM,
5193 /* 0x05 */ x86emuOp_genop_word_AX_IMM,
5194 /* 0x06 */ x86emuOp_push_ES,
5195 /* 0x07 */ x86emuOp_pop_ES,
5197 /* 0x08 */ x86emuOp_genop_byte_RM_R,
5198 /* 0x09 */ x86emuOp_genop_word_RM_R,
5199 /* 0x0a */ x86emuOp_genop_byte_R_RM,
5200 /* 0x0b */ x86emuOp_genop_word_R_RM,
5201 /* 0x0c */ x86emuOp_genop_byte_AL_IMM,
5202 /* 0x0d */ x86emuOp_genop_word_AX_IMM,
5203 /* 0x0e */ x86emuOp_push_CS,
5204 /* 0x0f */ x86emuOp_two_byte,
5206 /* 0x10 */ x86emuOp_genop_byte_RM_R,
5207 /* 0x11 */ x86emuOp_genop_word_RM_R,
5208 /* 0x12 */ x86emuOp_genop_byte_R_RM,
5209 /* 0x13 */ x86emuOp_genop_word_R_RM,
5210 /* 0x14 */ x86emuOp_genop_byte_AL_IMM,
5211 /* 0x15 */ x86emuOp_genop_word_AX_IMM,
5212 /* 0x16 */ x86emuOp_push_SS,
5213 /* 0x17 */ x86emuOp_pop_SS,
5215 /* 0x18 */ x86emuOp_genop_byte_RM_R,
5216 /* 0x19 */ x86emuOp_genop_word_RM_R,
5217 /* 0x1a */ x86emuOp_genop_byte_R_RM,
5218 /* 0x1b */ x86emuOp_genop_word_R_RM,
5219 /* 0x1c */ x86emuOp_genop_byte_AL_IMM,
5220 /* 0x1d */ x86emuOp_genop_word_AX_IMM,
5221 /* 0x1e */ x86emuOp_push_DS,
5222 /* 0x1f */ x86emuOp_pop_DS,
5224 /* 0x20 */ x86emuOp_genop_byte_RM_R,
5225 /* 0x21 */ x86emuOp_genop_word_RM_R,
5226 /* 0x22 */ x86emuOp_genop_byte_R_RM,
5227 /* 0x23 */ x86emuOp_genop_word_R_RM,
5228 /* 0x24 */ x86emuOp_genop_byte_AL_IMM,
5229 /* 0x25 */ x86emuOp_genop_word_AX_IMM,
5230 /* 0x26 */ x86emuOp_segovr_ES,
5231 /* 0x27 */ x86emuOp_daa,
5233 /* 0x28 */ x86emuOp_genop_byte_RM_R,
5234 /* 0x29 */ x86emuOp_genop_word_RM_R,
5235 /* 0x2a */ x86emuOp_genop_byte_R_RM,
5236 /* 0x2b */ x86emuOp_genop_word_R_RM,
5237 /* 0x2c */ x86emuOp_genop_byte_AL_IMM,
5238 /* 0x2d */ x86emuOp_genop_word_AX_IMM,
5239 /* 0x2e */ x86emuOp_segovr_CS,
5240 /* 0x2f */ x86emuOp_das,
5242 /* 0x30 */ x86emuOp_genop_byte_RM_R,
5243 /* 0x31 */ x86emuOp_genop_word_RM_R,
5244 /* 0x32 */ x86emuOp_genop_byte_R_RM,
5245 /* 0x33 */ x86emuOp_genop_word_R_RM,
5246 /* 0x34 */ x86emuOp_genop_byte_AL_IMM,
5247 /* 0x35 */ x86emuOp_genop_word_AX_IMM,
5248 /* 0x36 */ x86emuOp_segovr_SS,
5249 /* 0x37 */ x86emuOp_aaa,
5251 /* 0x38 */ x86emuOp_genop_byte_RM_R,
5252 /* 0x39 */ x86emuOp_genop_word_RM_R,
5253 /* 0x3a */ x86emuOp_genop_byte_R_RM,
5254 /* 0x3b */ x86emuOp_genop_word_R_RM,
5255 /* 0x3c */ x86emuOp_genop_byte_AL_IMM,
5256 /* 0x3d */ x86emuOp_genop_word_AX_IMM,
5257 /* 0x3e */ x86emuOp_segovr_DS,
5258 /* 0x3f */ x86emuOp_aas,
5260 /* 0x40 */ x86emuOp_inc_register,
5261 /* 0x41 */ x86emuOp_inc_register,
5262 /* 0x42 */ x86emuOp_inc_register,
5263 /* 0x43 */ x86emuOp_inc_register,
5264 /* 0x44 */ x86emuOp_inc_register,
5265 /* 0x45 */ x86emuOp_inc_register,
5266 /* 0x46 */ x86emuOp_inc_register,
5267 /* 0x47 */ x86emuOp_inc_register,
5269 /* 0x48 */ x86emuOp_dec_register,
5270 /* 0x49 */ x86emuOp_dec_register,
5271 /* 0x4a */ x86emuOp_dec_register,
5272 /* 0x4b */ x86emuOp_dec_register,
5273 /* 0x4c */ x86emuOp_dec_register,
5274 /* 0x4d */ x86emuOp_dec_register,
5275 /* 0x4e */ x86emuOp_dec_register,
5276 /* 0x4f */ x86emuOp_dec_register,
5278 /* 0x50 */ x86emuOp_push_register,
5279 /* 0x51 */ x86emuOp_push_register,
5280 /* 0x52 */ x86emuOp_push_register,
5281 /* 0x53 */ x86emuOp_push_register,
5282 /* 0x54 */ x86emuOp_push_register,
5283 /* 0x55 */ x86emuOp_push_register,
5284 /* 0x56 */ x86emuOp_push_register,
5285 /* 0x57 */ x86emuOp_push_register,
5287 /* 0x58 */ x86emuOp_pop_register,
5288 /* 0x59 */ x86emuOp_pop_register,
5289 /* 0x5a */ x86emuOp_pop_register,
5290 /* 0x5b */ x86emuOp_pop_register,
5291 /* 0x5c */ x86emuOp_pop_register,
5292 /* 0x5d */ x86emuOp_pop_register,
5293 /* 0x5e */ x86emuOp_pop_register,
5294 /* 0x5f */ x86emuOp_pop_register,
5296 /* 0x60 */ x86emuOp_push_all,
5297 /* 0x61 */ x86emuOp_pop_all,
5298 /* 0x62 */ x86emuOp_illegal_op, /* bound */
5299 /* 0x63 */ x86emuOp_illegal_op, /* arpl */
5300 /* 0x64 */ x86emuOp_segovr_FS,
5301 /* 0x65 */ x86emuOp_segovr_GS,
5302 /* 0x66 */ x86emuOp_prefix_data,
5303 /* 0x67 */ x86emuOp_prefix_addr,
5305 /* 0x68 */ x86emuOp_push_word_IMM,
5306 /* 0x69 */ x86emuOp_imul_word_IMM,
5307 /* 0x6a */ x86emuOp_push_byte_IMM,
5308 /* 0x6b */ x86emuOp_imul_byte_IMM,
5309 /* 0x6c */ x86emuOp_ins_byte,
5310 /* 0x6d */ x86emuOp_ins_word,
5311 /* 0x6e */ x86emuOp_outs_byte,
5312 /* 0x6f */ x86emuOp_outs_word,
5314 /* 0x70 */ x86emuOp_jump_near_cond,
5315 /* 0x71 */ x86emuOp_jump_near_cond,
5316 /* 0x72 */ x86emuOp_jump_near_cond,
5317 /* 0x73 */ x86emuOp_jump_near_cond,
5318 /* 0x74 */ x86emuOp_jump_near_cond,
5319 /* 0x75 */ x86emuOp_jump_near_cond,
5320 /* 0x76 */ x86emuOp_jump_near_cond,
5321 /* 0x77 */ x86emuOp_jump_near_cond,
5323 /* 0x78 */ x86emuOp_jump_near_cond,
5324 /* 0x79 */ x86emuOp_jump_near_cond,
5325 /* 0x7a */ x86emuOp_jump_near_cond,
5326 /* 0x7b */ x86emuOp_jump_near_cond,
5327 /* 0x7c */ x86emuOp_jump_near_cond,
5328 /* 0x7d */ x86emuOp_jump_near_cond,
5329 /* 0x7e */ x86emuOp_jump_near_cond,
5330 /* 0x7f */ x86emuOp_jump_near_cond,
5332 /* 0x80 */ x86emuOp_opc80_byte_RM_IMM,
5333 /* 0x81 */ x86emuOp_opc81_word_RM_IMM,
5334 /* 0x82 */ x86emuOp_opc82_byte_RM_IMM,
5335 /* 0x83 */ x86emuOp_opc83_word_RM_IMM,
5336 /* 0x84 */ x86emuOp_test_byte_RM_R,
5337 /* 0x85 */ x86emuOp_test_word_RM_R,
5338 /* 0x86 */ x86emuOp_xchg_byte_RM_R,
5339 /* 0x87 */ x86emuOp_xchg_word_RM_R,
5341 /* 0x88 */ x86emuOp_mov_byte_RM_R,
5342 /* 0x89 */ x86emuOp_mov_word_RM_R,
5343 /* 0x8a */ x86emuOp_mov_byte_R_RM,
5344 /* 0x8b */ x86emuOp_mov_word_R_RM,
5345 /* 0x8c */ x86emuOp_mov_word_RM_SR,
5346 /* 0x8d */ x86emuOp_lea_word_R_M,
5347 /* 0x8e */ x86emuOp_mov_word_SR_RM,
5348 /* 0x8f */ x86emuOp_pop_RM,
5350 /* 0x90 */ x86emuOp_nop,
5351 /* 0x91 */ x86emuOp_xchg_word_AX_register,
5352 /* 0x92 */ x86emuOp_xchg_word_AX_register,
5353 /* 0x93 */ x86emuOp_xchg_word_AX_register,
5354 /* 0x94 */ x86emuOp_xchg_word_AX_register,
5355 /* 0x95 */ x86emuOp_xchg_word_AX_register,
5356 /* 0x96 */ x86emuOp_xchg_word_AX_register,
5357 /* 0x97 */ x86emuOp_xchg_word_AX_register,
5359 /* 0x98 */ x86emuOp_cbw,
5360 /* 0x99 */ x86emuOp_cwd,
5361 /* 0x9a */ x86emuOp_call_far_IMM,
5362 /* 0x9b */ x86emuOp_wait,
5363 /* 0x9c */ x86emuOp_pushf_word,
5364 /* 0x9d */ x86emuOp_popf_word,
5365 /* 0x9e */ x86emuOp_sahf,
5366 /* 0x9f */ x86emuOp_lahf,
5368 /* 0xa0 */ x86emuOp_mov_AL_M_IMM,
5369 /* 0xa1 */ x86emuOp_mov_AX_M_IMM,
5370 /* 0xa2 */ x86emuOp_mov_M_AL_IMM,
5371 /* 0xa3 */ x86emuOp_mov_M_AX_IMM,
5372 /* 0xa4 */ x86emuOp_movs_byte,
5373 /* 0xa5 */ x86emuOp_movs_word,
5374 /* 0xa6 */ x86emuOp_cmps_byte,
5375 /* 0xa7 */ x86emuOp_cmps_word,
5376 /* 0xa8 */ x86emuOp_test_AL_IMM,
5377 /* 0xa9 */ x86emuOp_test_AX_IMM,
5378 /* 0xaa */ x86emuOp_stos_byte,
5379 /* 0xab */ x86emuOp_stos_word,
5380 /* 0xac */ x86emuOp_lods_byte,
5381 /* 0xad */ x86emuOp_lods_word,
5382 /* 0xac */ x86emuOp_scas_byte,
5383 /* 0xad */ x86emuOp_scas_word,
5385 /* 0xb0 */ x86emuOp_mov_byte_register_IMM,
5386 /* 0xb1 */ x86emuOp_mov_byte_register_IMM,
5387 /* 0xb2 */ x86emuOp_mov_byte_register_IMM,
5388 /* 0xb3 */ x86emuOp_mov_byte_register_IMM,
5389 /* 0xb4 */ x86emuOp_mov_byte_register_IMM,
5390 /* 0xb5 */ x86emuOp_mov_byte_register_IMM,
5391 /* 0xb6 */ x86emuOp_mov_byte_register_IMM,
5392 /* 0xb7 */ x86emuOp_mov_byte_register_IMM,
5394 /* 0xb8 */ x86emuOp_mov_word_register_IMM,
5395 /* 0xb9 */ x86emuOp_mov_word_register_IMM,
5396 /* 0xba */ x86emuOp_mov_word_register_IMM,
5397 /* 0xbb */ x86emuOp_mov_word_register_IMM,
5398 /* 0xbc */ x86emuOp_mov_word_register_IMM,
5399 /* 0xbd */ x86emuOp_mov_word_register_IMM,
5400 /* 0xbe */ x86emuOp_mov_word_register_IMM,
5401 /* 0xbf */ x86emuOp_mov_word_register_IMM,
5403 /* 0xc0 */ x86emuOp_opcC0_byte_RM_MEM,
5404 /* 0xc1 */ x86emuOp_opcC1_word_RM_MEM,
5405 /* 0xc2 */ x86emuOp_ret_near_IMM,
5406 /* 0xc3 */ x86emuOp_ret_near,
5407 /* 0xc4 */ x86emuOp_les_R_IMM,
5408 /* 0xc5 */ x86emuOp_lds_R_IMM,
5409 /* 0xc6 */ x86emuOp_mov_byte_RM_IMM,
5410 /* 0xc7 */ x86emuOp_mov_word_RM_IMM,
5411 /* 0xc8 */ x86emuOp_enter,
5412 /* 0xc9 */ x86emuOp_leave,
5413 /* 0xca */ x86emuOp_ret_far_IMM,
5414 /* 0xcb */ x86emuOp_ret_far,
5415 /* 0xcc */ x86emuOp_int3,
5416 /* 0xcd */ x86emuOp_int_IMM,
5417 /* 0xce */ x86emuOp_into,
5418 /* 0xcf */ x86emuOp_iret,
5420 /* 0xd0 */ x86emuOp_opcD0_byte_RM_1,
5421 /* 0xd1 */ x86emuOp_opcD1_word_RM_1,
5422 /* 0xd2 */ x86emuOp_opcD2_byte_RM_CL,
5423 /* 0xd3 */ x86emuOp_opcD3_word_RM_CL,
5424 /* 0xd4 */ x86emuOp_aam,
5425 /* 0xd5 */ x86emuOp_aad,
5426 /* 0xd6 */ x86emuOp_illegal_op, /* Undocumented SETALC instruction */
5427 /* 0xd7 */ x86emuOp_xlat,
5428 /* 0xd8 */ x86emuOp_esc_coprocess_d8,
5429 /* 0xd9 */ x86emuOp_esc_coprocess_d9,
5430 /* 0xda */ x86emuOp_esc_coprocess_da,
5431 /* 0xdb */ x86emuOp_esc_coprocess_db,
5432 /* 0xdc */ x86emuOp_esc_coprocess_dc,
5433 /* 0xdd */ x86emuOp_esc_coprocess_dd,
5434 /* 0xde */ x86emuOp_esc_coprocess_de,
5435 /* 0xdf */ x86emuOp_esc_coprocess_df,
5437 /* 0xe0 */ x86emuOp_loopne,
5438 /* 0xe1 */ x86emuOp_loope,
5439 /* 0xe2 */ x86emuOp_loop,
5440 /* 0xe3 */ x86emuOp_jcxz,
5441 /* 0xe4 */ x86emuOp_in_byte_AL_IMM,
5442 /* 0xe5 */ x86emuOp_in_word_AX_IMM,
5443 /* 0xe6 */ x86emuOp_out_byte_IMM_AL,
5444 /* 0xe7 */ x86emuOp_out_word_IMM_AX,
5446 /* 0xe8 */ x86emuOp_call_near_IMM,
5447 /* 0xe9 */ x86emuOp_jump_near_IMM,
5448 /* 0xea */ x86emuOp_jump_far_IMM,
5449 /* 0xeb */ x86emuOp_jump_byte_IMM,
5450 /* 0xec */ x86emuOp_in_byte_AL_DX,
5451 /* 0xed */ x86emuOp_in_word_AX_DX,
5452 /* 0xee */ x86emuOp_out_byte_DX_AL,
5453 /* 0xef */ x86emuOp_out_word_DX_AX,
5455 /* 0xf0 */ x86emuOp_lock,
5456 /* 0xf1 */ x86emuOp_illegal_op,
5457 /* 0xf2 */ x86emuOp_repne,
5458 /* 0xf3 */ x86emuOp_repe,
5459 /* 0xf4 */ x86emuOp_halt,
5460 /* 0xf5 */ x86emuOp_cmc,
5461 /* 0xf6 */ x86emuOp_opcF6_byte_RM,
5462 /* 0xf7 */ x86emuOp_opcF7_word_RM,
5464 /* 0xf8 */ x86emuOp_clc,
5465 /* 0xf9 */ x86emuOp_stc,
5466 /* 0xfa */ x86emuOp_cli,
5467 /* 0xfb */ x86emuOp_sti,
5468 /* 0xfc */ x86emuOp_cld,
5469 /* 0xfd */ x86emuOp_std,
5470 /* 0xfe */ x86emuOp_opcFE_byte_RM,
5471 /* 0xff */ x86emuOp_opcFF_word_RM,