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 char *x86emu_GenOpName[8] = {
81 "ADD", "OR", "ADC", "SBB", "AND", "SUB", "XOR", "CMP"};
84 /* used by several opcodes */
85 static u8 (*genop_byte_operation[])(u8 d, u8 s) =
97 static u16 (*genop_word_operation[])(u16 d, u16 s) =
109 static u32 (*genop_long_operation[])(u32 d, u32 s) =
121 /* used by opcodes 80, c0, d0, and d2. */
122 static u8(*opcD0_byte_operation[])(u8 d, u8 s) =
130 shl_byte, /* sal_byte === shl_byte by definition */
134 /* used by opcodes c1, d1, and d3. */
135 static u16(*opcD1_word_operation[])(u16 s, u8 d) =
143 shl_word, /* sal_byte === shl_byte by definition */
147 /* used by opcodes c1, d1, and d3. */
148 static u32 (*opcD1_long_operation[])(u32 s, u8 d) =
156 shl_long, /* sal_byte === shl_byte by definition */
162 static char *opF6_names[8] =
163 { "TEST\t", "", "NOT\t", "NEG\t", "MUL\t", "IMUL\t", "DIV\t", "IDIV\t" };
167 /****************************************************************************
169 op1 - Instruction op code
172 Handles illegal opcodes.
173 ****************************************************************************/
174 void x86emuOp_illegal_op(
178 if (M.x86.R_SP != 0) {
179 DECODE_PRINTF("ILLEGAL X86 OPCODE\n");
181 DB( printk("%04x:%04x: %02X ILLEGAL X86 OPCODE!\n",
182 M.x86.R_CS, M.x86.R_IP-1,op1));
186 /* If we get here, it means the stack pointer is back to zero
187 * so we are just returning from an emulator service call
188 * so therte is no need to display an error message. We trap
189 * the emulator with an 0xF1 opcode to finish the service
197 /****************************************************************************
199 Handles opcodes 0x00, 0x08, 0x10, 0x18, 0x20, 0x28, 0x30, 0x38
200 ****************************************************************************/
201 void x86emuOp_genop_byte_RM_R(u8 op1)
205 u8 *destreg, *srcreg;
208 op1 = (op1 >> 3) & 0x7;
211 DECODE_PRINTF(x86emu_GenOpName[op1]);
213 FETCH_DECODE_MODRM(mod, rh, rl);
215 { destoffset = decode_rmXX_address(mod,rl);
217 destval = fetch_data_byte(destoffset);
218 srcreg = DECODE_RM_BYTE_REGISTER(rh);
221 destval = genop_byte_operation[op1](destval, *srcreg);
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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 void x86emuOp_ins_byte(u8 X86EMU_UNUSED(op1))
1185 DECODE_PRINTF("INSB\n");
1188 DECODE_CLEAR_SEGOVR();
1192 /****************************************************************************
1195 ****************************************************************************/
1196 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 void x86emuOp_outs_byte(u8 X86EMU_UNUSED(op1))
1218 DECODE_PRINTF("OUTSB\n");
1221 DECODE_CLEAR_SEGOVR();
1225 /****************************************************************************
1228 ****************************************************************************/
1229 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 int x86emu_check_jump_condition(u8 op);
1250 void x86emuOp_jump_near_cond(u8 op1)
1256 /* jump to byte offset if overflow flag is set */
1258 cond = x86emu_check_jump_condition(op1 & 0xF);
1259 offset = (s8)fetch_byte_imm();
1260 target = (u16)(M.x86.R_IP + (s16)offset);
1261 DECODE_PRINTF2("%x\n", target);
1264 M.x86.R_IP = target;
1265 JMP_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, M.x86.R_IP, " NEAR COND ");
1267 DECODE_CLEAR_SEGOVR();
1271 /****************************************************************************
1274 ****************************************************************************/
1275 void x86emuOp_opc80_byte_RM_IMM(u8 X86EMU_UNUSED(op1))
1284 * Weirdo special case instruction format. Part of the opcode
1285 * held below in "RH". Doubly nested case would result, except
1286 * that the decoded instruction
1289 FETCH_DECODE_MODRM(mod, rh, rl);
1291 if (DEBUG_DECODE()) {
1292 /* XXX DECODE_PRINTF may be changed to something more
1293 general, so that it is important to leave the strings
1294 in the same format, even though the result is that the
1295 above test is done twice. */
1299 DECODE_PRINTF("ADD\t");
1302 DECODE_PRINTF("OR\t");
1305 DECODE_PRINTF("ADC\t");
1308 DECODE_PRINTF("SBB\t");
1311 DECODE_PRINTF("AND\t");
1314 DECODE_PRINTF("SUB\t");
1317 DECODE_PRINTF("XOR\t");
1320 DECODE_PRINTF("CMP\t");
1325 /* know operation, decode the mod byte to find the addressing
1328 DECODE_PRINTF("BYTE PTR ");
1329 destoffset = decode_rmXX_address(mod, rl);
1331 destval = fetch_data_byte(destoffset);
1332 imm = fetch_byte_imm();
1333 DECODE_PRINTF2("%x\n", imm);
1335 destval = (*genop_byte_operation[rh]) (destval, imm);
1337 store_data_byte(destoffset, destval);
1338 } else { /* register to register */
1339 destreg = DECODE_RM_BYTE_REGISTER(rl);
1341 imm = fetch_byte_imm();
1342 DECODE_PRINTF2("%x\n", imm);
1344 *destreg = (*genop_byte_operation[rh]) (*destreg, imm);
1346 DECODE_CLEAR_SEGOVR();
1350 /****************************************************************************
1353 ****************************************************************************/
1354 void x86emuOp_opc81_word_RM_IMM(u8 X86EMU_UNUSED(op1))
1360 * Weirdo special case instruction format. Part of the opcode
1361 * held below in "RH". Doubly nested case would result, except
1362 * that the decoded instruction
1365 FETCH_DECODE_MODRM(mod, rh, rl);
1367 if (DEBUG_DECODE()) {
1368 /* XXX DECODE_PRINTF may be changed to something more
1369 general, so that it is important to leave the strings
1370 in the same format, even though the result is that the
1371 above test is done twice. */
1375 DECODE_PRINTF("ADD\t");
1378 DECODE_PRINTF("OR\t");
1381 DECODE_PRINTF("ADC\t");
1384 DECODE_PRINTF("SBB\t");
1387 DECODE_PRINTF("AND\t");
1390 DECODE_PRINTF("SUB\t");
1393 DECODE_PRINTF("XOR\t");
1396 DECODE_PRINTF("CMP\t");
1402 * Know operation, decode the mod byte to find the addressing
1406 DECODE_PRINTF("DWORD PTR ");
1407 destoffset = decode_rmXX_address(mod, rl);
1408 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1412 destval = fetch_data_long(destoffset);
1413 imm = fetch_long_imm();
1414 DECODE_PRINTF2("%x\n", imm);
1416 destval = (*genop_long_operation[rh]) (destval, imm);
1418 store_data_long(destoffset, destval);
1423 destval = fetch_data_word(destoffset);
1424 imm = fetch_word_imm();
1425 DECODE_PRINTF2("%x\n", imm);
1427 destval = (*genop_word_operation[rh]) (destval, imm);
1429 store_data_word(destoffset, destval);
1431 } else { /* register to register */
1432 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1435 destreg = DECODE_RM_LONG_REGISTER(rl);
1437 imm = fetch_long_imm();
1438 DECODE_PRINTF2("%x\n", imm);
1440 *destreg = (*genop_long_operation[rh]) (*destreg, imm);
1444 destreg = DECODE_RM_WORD_REGISTER(rl);
1446 imm = fetch_word_imm();
1447 DECODE_PRINTF2("%x\n", imm);
1449 *destreg = (*genop_word_operation[rh]) (*destreg, imm);
1452 DECODE_CLEAR_SEGOVR();
1456 /****************************************************************************
1459 ****************************************************************************/
1460 void x86emuOp_opc82_byte_RM_IMM(u8 X86EMU_UNUSED(op1))
1469 * Weirdo special case instruction format. Part of the opcode
1470 * held below in "RH". Doubly nested case would result, except
1471 * that the decoded instruction Similar to opcode 81, except that
1472 * the immediate byte is sign extended to a word length.
1475 FETCH_DECODE_MODRM(mod, rh, rl);
1477 if (DEBUG_DECODE()) {
1478 /* XXX DECODE_PRINTF may be changed to something more
1479 general, so that it is important to leave the strings
1480 in the same format, even though the result is that the
1481 above test is done twice. */
1484 DECODE_PRINTF("ADD\t");
1487 DECODE_PRINTF("OR\t");
1490 DECODE_PRINTF("ADC\t");
1493 DECODE_PRINTF("SBB\t");
1496 DECODE_PRINTF("AND\t");
1499 DECODE_PRINTF("SUB\t");
1502 DECODE_PRINTF("XOR\t");
1505 DECODE_PRINTF("CMP\t");
1510 /* know operation, decode the mod byte to find the addressing
1513 DECODE_PRINTF("BYTE PTR ");
1514 destoffset = decode_rmXX_address(mod, rl);
1515 destval = fetch_data_byte(destoffset);
1516 imm = fetch_byte_imm();
1517 DECODE_PRINTF2(",%x\n", imm);
1519 destval = (*genop_byte_operation[rh]) (destval, imm);
1521 store_data_byte(destoffset, destval);
1522 } else { /* register to register */
1523 destreg = DECODE_RM_BYTE_REGISTER(rl);
1524 imm = fetch_byte_imm();
1525 DECODE_PRINTF2(",%x\n", imm);
1527 *destreg = (*genop_byte_operation[rh]) (*destreg, imm);
1529 DECODE_CLEAR_SEGOVR();
1533 /****************************************************************************
1536 ****************************************************************************/
1537 void x86emuOp_opc83_word_RM_IMM(u8 X86EMU_UNUSED(op1))
1543 * Weirdo special case instruction format. Part of the opcode
1544 * held below in "RH". Doubly nested case would result, except
1545 * that the decoded instruction Similar to opcode 81, except that
1546 * the immediate byte is sign extended to a word length.
1549 FETCH_DECODE_MODRM(mod, rh, rl);
1551 if (DEBUG_DECODE()) {
1552 /* XXX DECODE_PRINTF may be changed to something more
1553 general, so that it is important to leave the strings
1554 in the same format, even though the result is that the
1555 above test is done twice. */
1558 DECODE_PRINTF("ADD\t");
1561 DECODE_PRINTF("OR\t");
1564 DECODE_PRINTF("ADC\t");
1567 DECODE_PRINTF("SBB\t");
1570 DECODE_PRINTF("AND\t");
1573 DECODE_PRINTF("SUB\t");
1576 DECODE_PRINTF("XOR\t");
1579 DECODE_PRINTF("CMP\t");
1584 /* know operation, decode the mod byte to find the addressing
1587 DECODE_PRINTF("DWORD PTR ");
1588 destoffset = decode_rmXX_address(mod,rl);
1590 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1593 destval = fetch_data_long(destoffset);
1594 imm = (s8) fetch_byte_imm();
1595 DECODE_PRINTF2(",%x\n", imm);
1597 destval = (*genop_long_operation[rh]) (destval, imm);
1599 store_data_long(destoffset, destval);
1603 destval = fetch_data_word(destoffset);
1604 imm = (s8) fetch_byte_imm();
1605 DECODE_PRINTF2(",%x\n", imm);
1607 destval = (*genop_word_operation[rh]) (destval, imm);
1609 store_data_word(destoffset, destval);
1611 } else { /* register to register */
1612 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1615 destreg = DECODE_RM_LONG_REGISTER(rl);
1616 imm = (s8) fetch_byte_imm();
1617 DECODE_PRINTF2(",%x\n", imm);
1619 *destreg = (*genop_long_operation[rh]) (*destreg, imm);
1623 destreg = DECODE_RM_WORD_REGISTER(rl);
1624 imm = (s8) fetch_byte_imm();
1625 DECODE_PRINTF2(",%x\n", imm);
1627 *destreg = (*genop_word_operation[rh]) (*destreg, imm);
1630 DECODE_CLEAR_SEGOVR();
1634 /****************************************************************************
1637 ****************************************************************************/
1638 void x86emuOp_test_byte_RM_R(u8 X86EMU_UNUSED(op1))
1641 u8 *destreg, *srcreg;
1646 DECODE_PRINTF("TEST\t");
1647 FETCH_DECODE_MODRM(mod, rh, rl);
1649 destoffset = decode_rmXX_address(mod, rl);
1651 destval = fetch_data_byte(destoffset);
1652 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1653 DECODE_PRINTF("\n");
1655 test_byte(destval, *srcreg);
1656 } else { /* register to register */
1657 destreg = DECODE_RM_BYTE_REGISTER(rl);
1659 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1660 DECODE_PRINTF("\n");
1662 test_byte(*destreg, *srcreg);
1664 DECODE_CLEAR_SEGOVR();
1668 /****************************************************************************
1671 ****************************************************************************/
1672 void x86emuOp_test_word_RM_R(u8 X86EMU_UNUSED(op1))
1678 DECODE_PRINTF("TEST\t");
1679 FETCH_DECODE_MODRM(mod, rh, rl);
1681 destoffset = decode_rmXX_address(mod, rl);
1682 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1687 destval = fetch_data_long(destoffset);
1688 srcreg = DECODE_RM_LONG_REGISTER(rh);
1689 DECODE_PRINTF("\n");
1691 test_long(destval, *srcreg);
1697 destval = fetch_data_word(destoffset);
1698 srcreg = DECODE_RM_WORD_REGISTER(rh);
1699 DECODE_PRINTF("\n");
1701 test_word(destval, *srcreg);
1703 } else { /* register to register */
1704 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1705 u32 *destreg,*srcreg;
1707 destreg = DECODE_RM_LONG_REGISTER(rl);
1709 srcreg = DECODE_RM_LONG_REGISTER(rh);
1710 DECODE_PRINTF("\n");
1712 test_long(*destreg, *srcreg);
1714 u16 *destreg,*srcreg;
1716 destreg = DECODE_RM_WORD_REGISTER(rl);
1718 srcreg = DECODE_RM_WORD_REGISTER(rh);
1719 DECODE_PRINTF("\n");
1721 test_word(*destreg, *srcreg);
1724 DECODE_CLEAR_SEGOVR();
1728 /****************************************************************************
1731 ****************************************************************************/
1732 void x86emuOp_xchg_byte_RM_R(u8 X86EMU_UNUSED(op1))
1735 u8 *destreg, *srcreg;
1741 DECODE_PRINTF("XCHG\t");
1742 FETCH_DECODE_MODRM(mod, rh, rl);
1744 destoffset = decode_rmXX_address(mod, rl);
1746 destval = fetch_data_byte(destoffset);
1747 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1748 DECODE_PRINTF("\n");
1753 store_data_byte(destoffset, destval);
1754 } else { /* register to register */
1755 destreg = DECODE_RM_BYTE_REGISTER(rl);
1757 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1758 DECODE_PRINTF("\n");
1764 DECODE_CLEAR_SEGOVR();
1768 /****************************************************************************
1771 ****************************************************************************/
1772 void x86emuOp_xchg_word_RM_R(u8 X86EMU_UNUSED(op1))
1778 DECODE_PRINTF("XCHG\t");
1779 FETCH_DECODE_MODRM(mod, rh, rl);
1781 destoffset = decode_rmXX_address(mod, rl);
1783 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1787 destval = fetch_data_long(destoffset);
1788 srcreg = DECODE_RM_LONG_REGISTER(rh);
1789 DECODE_PRINTF("\n");
1794 store_data_long(destoffset, destval);
1799 destval = fetch_data_word(destoffset);
1800 srcreg = DECODE_RM_WORD_REGISTER(rh);
1801 DECODE_PRINTF("\n");
1806 store_data_word(destoffset, destval);
1808 } else { /* register to register */
1809 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1810 u32 *destreg,*srcreg;
1813 destreg = DECODE_RM_LONG_REGISTER(rl);
1815 srcreg = DECODE_RM_LONG_REGISTER(rh);
1816 DECODE_PRINTF("\n");
1822 u16 *destreg,*srcreg;
1825 destreg = DECODE_RM_WORD_REGISTER(rl);
1827 srcreg = DECODE_RM_WORD_REGISTER(rh);
1828 DECODE_PRINTF("\n");
1835 DECODE_CLEAR_SEGOVR();
1839 /****************************************************************************
1842 ****************************************************************************/
1843 void x86emuOp_mov_byte_RM_R(u8 X86EMU_UNUSED(op1))
1846 u8 *destreg, *srcreg;
1850 DECODE_PRINTF("MOV\t");
1851 FETCH_DECODE_MODRM(mod, rh, rl);
1853 destoffset = decode_rmXX_address(mod, rl);
1855 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1856 DECODE_PRINTF("\n");
1858 store_data_byte(destoffset, *srcreg);
1859 } else { /* register to register */
1860 destreg = DECODE_RM_BYTE_REGISTER(rl);
1862 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1863 DECODE_PRINTF("\n");
1867 DECODE_CLEAR_SEGOVR();
1871 /****************************************************************************
1874 ****************************************************************************/
1875 void x86emuOp_mov_word_RM_R(u8 X86EMU_UNUSED(op1))
1881 DECODE_PRINTF("MOV\t");
1882 FETCH_DECODE_MODRM(mod, rh, rl);
1884 destoffset = decode_rmXX_address(mod, rl);
1885 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1889 srcreg = DECODE_RM_LONG_REGISTER(rh);
1890 DECODE_PRINTF("\n");
1892 store_data_long(destoffset, *srcreg);
1897 srcreg = DECODE_RM_WORD_REGISTER(rh);
1898 DECODE_PRINTF("\n");
1900 store_data_word(destoffset, *srcreg);
1902 } else { /* register to register */
1903 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1904 u32 *destreg,*srcreg;
1906 destreg = DECODE_RM_LONG_REGISTER(rl);
1908 srcreg = DECODE_RM_LONG_REGISTER(rh);
1909 DECODE_PRINTF("\n");
1913 u16 *destreg,*srcreg;
1915 destreg = DECODE_RM_WORD_REGISTER(rl);
1917 srcreg = DECODE_RM_WORD_REGISTER(rh);
1918 DECODE_PRINTF("\n");
1923 DECODE_CLEAR_SEGOVR();
1927 /****************************************************************************
1930 ****************************************************************************/
1931 void x86emuOp_mov_byte_R_RM(u8 X86EMU_UNUSED(op1))
1934 u8 *destreg, *srcreg;
1939 DECODE_PRINTF("MOV\t");
1940 FETCH_DECODE_MODRM(mod, rh, rl);
1942 destreg = DECODE_RM_BYTE_REGISTER(rh);
1944 srcoffset = decode_rmXX_address(mod, rl);
1945 srcval = fetch_data_byte(srcoffset);
1946 DECODE_PRINTF("\n");
1949 } else { /* register to register */
1950 destreg = DECODE_RM_BYTE_REGISTER(rh);
1952 srcreg = DECODE_RM_BYTE_REGISTER(rl);
1953 DECODE_PRINTF("\n");
1957 DECODE_CLEAR_SEGOVR();
1961 /****************************************************************************
1964 ****************************************************************************/
1965 void x86emuOp_mov_word_R_RM(u8 X86EMU_UNUSED(op1))
1971 DECODE_PRINTF("MOV\t");
1972 FETCH_DECODE_MODRM(mod, rh, rl);
1974 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1978 destreg = DECODE_RM_LONG_REGISTER(rh);
1980 srcoffset = decode_rmXX_address(mod, rl);
1981 srcval = fetch_data_long(srcoffset);
1982 DECODE_PRINTF("\n");
1989 destreg = DECODE_RM_WORD_REGISTER(rh);
1991 srcoffset = decode_rmXX_address(mod, rl);
1992 srcval = fetch_data_word(srcoffset);
1993 DECODE_PRINTF("\n");
1997 } else { /* register to register */
1998 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1999 u32 *destreg, *srcreg;
2001 destreg = DECODE_RM_LONG_REGISTER(rh);
2003 srcreg = DECODE_RM_LONG_REGISTER(rl);
2004 DECODE_PRINTF("\n");
2008 u16 *destreg, *srcreg;
2010 destreg = DECODE_RM_WORD_REGISTER(rh);
2012 srcreg = DECODE_RM_WORD_REGISTER(rl);
2013 DECODE_PRINTF("\n");
2018 DECODE_CLEAR_SEGOVR();
2022 /****************************************************************************
2025 ****************************************************************************/
2026 void x86emuOp_mov_word_RM_SR(u8 X86EMU_UNUSED(op1))
2029 u16 *destreg, *srcreg;
2034 DECODE_PRINTF("MOV\t");
2035 FETCH_DECODE_MODRM(mod, rh, rl);
2037 destoffset = decode_rmXX_address(mod, rl);
2039 srcreg = decode_rm_seg_register(rh);
2040 DECODE_PRINTF("\n");
2043 store_data_word(destoffset, destval);
2044 } else { /* register to register */
2045 destreg = DECODE_RM_WORD_REGISTER(rl);
2047 srcreg = decode_rm_seg_register(rh);
2048 DECODE_PRINTF("\n");
2052 DECODE_CLEAR_SEGOVR();
2056 /****************************************************************************
2059 ****************************************************************************/
2060 void x86emuOp_lea_word_R_M(u8 X86EMU_UNUSED(op1))
2067 * TODO: Need to handle address size prefix!
2069 * lea eax,[eax+ebx*2] ??
2073 DECODE_PRINTF("LEA\t");
2074 FETCH_DECODE_MODRM(mod, rh, rl);
2076 srcreg = DECODE_RM_WORD_REGISTER(rh);
2078 destoffset = decode_rmXX_address(mod, rl);
2079 DECODE_PRINTF("\n");
2081 *srcreg = (u16)destoffset;
2083 /* } else { undefined. Do nothing. } */
2084 DECODE_CLEAR_SEGOVR();
2088 /****************************************************************************
2091 ****************************************************************************/
2092 void x86emuOp_mov_word_SR_RM(u8 X86EMU_UNUSED(op1))
2095 u16 *destreg, *srcreg;
2100 DECODE_PRINTF("MOV\t");
2101 FETCH_DECODE_MODRM(mod, rh, rl);
2103 destreg = decode_rm_seg_register(rh);
2105 srcoffset = decode_rmXX_address(mod, rl);
2106 srcval = fetch_data_word(srcoffset);
2107 DECODE_PRINTF("\n");
2110 } else { /* register to register */
2111 destreg = decode_rm_seg_register(rh);
2113 srcreg = DECODE_RM_WORD_REGISTER(rl);
2114 DECODE_PRINTF("\n");
2119 * Clean up, and reset all the R_xSP pointers to the correct
2120 * locations. This is about 3x too much overhead (doing all the
2121 * segreg ptrs when only one is needed, but this instruction
2122 * *cannot* be that common, and this isn't too much work anyway.
2124 DECODE_CLEAR_SEGOVR();
2128 /****************************************************************************
2131 ****************************************************************************/
2132 void x86emuOp_pop_RM(u8 X86EMU_UNUSED(op1))
2138 DECODE_PRINTF("POP\t");
2139 FETCH_DECODE_MODRM(mod, rh, rl);
2141 DECODE_PRINTF("ILLEGAL DECODE OF OPCODE 8F\n");
2145 destoffset = decode_rmXX_address(mod, rl);
2146 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2149 DECODE_PRINTF("\n");
2151 destval = pop_long();
2152 store_data_long(destoffset, destval);
2156 DECODE_PRINTF("\n");
2158 destval = pop_word();
2159 store_data_word(destoffset, destval);
2161 } else { /* register to register */
2162 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2165 destreg = DECODE_RM_LONG_REGISTER(rl);
2166 DECODE_PRINTF("\n");
2168 *destreg = pop_long();
2172 destreg = DECODE_RM_WORD_REGISTER(rl);
2173 DECODE_PRINTF("\n");
2175 *destreg = pop_word();
2178 DECODE_CLEAR_SEGOVR();
2182 /****************************************************************************
2185 ****************************************************************************/
2186 void x86emuOp_nop(u8 X86EMU_UNUSED(op1))
2189 DECODE_PRINTF("NOP\n");
2191 DECODE_CLEAR_SEGOVR();
2195 /****************************************************************************
2197 Handles opcode 0x91-0x97
2198 ****************************************************************************/
2199 void x86emuOp_xchg_word_AX_register(u8 X86EMU_UNUSED(op1))
2207 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2209 DECODE_PRINTF("XCHG\tEAX,");
2210 reg32 = DECODE_RM_LONG_REGISTER(op1);
2211 DECODE_PRINTF("\n");
2214 M.x86.R_EAX = *reg32;
2218 DECODE_PRINTF("XCHG\tAX,");
2219 reg16 = DECODE_RM_WORD_REGISTER(op1);
2220 DECODE_PRINTF("\n");
2223 M.x86.R_AX = *reg16;
2226 DECODE_CLEAR_SEGOVR();
2230 /****************************************************************************
2233 ****************************************************************************/
2234 void x86emuOp_cbw(u8 X86EMU_UNUSED(op1))
2237 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2238 DECODE_PRINTF("CWDE\n");
2240 DECODE_PRINTF("CBW\n");
2243 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2244 if (M.x86.R_AX & 0x8000) {
2245 M.x86.R_EAX |= 0xffff0000;
2247 M.x86.R_EAX &= 0x0000ffff;
2250 if (M.x86.R_AL & 0x80) {
2256 DECODE_CLEAR_SEGOVR();
2260 /****************************************************************************
2263 ****************************************************************************/
2264 void x86emuOp_cwd(u8 X86EMU_UNUSED(op1))
2267 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2268 DECODE_PRINTF("CDQ\n");
2270 DECODE_PRINTF("CWD\n");
2272 DECODE_PRINTF("CWD\n");
2274 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2275 if (M.x86.R_EAX & 0x80000000) {
2276 M.x86.R_EDX = 0xffffffff;
2281 if (M.x86.R_AX & 0x8000) {
2282 M.x86.R_DX = 0xffff;
2287 DECODE_CLEAR_SEGOVR();
2291 /****************************************************************************
2294 ****************************************************************************/
2295 void x86emuOp_call_far_IMM(u8 X86EMU_UNUSED(op1))
2300 DECODE_PRINTF("CALL\t");
2301 faroff = fetch_word_imm();
2302 farseg = fetch_word_imm();
2303 DECODE_PRINTF2("%04x:", farseg);
2304 DECODE_PRINTF2("%04x\n", faroff);
2305 CALL_TRACE(M.x86.saved_cs, M.x86.saved_ip, farseg, faroff, "FAR ");
2309 * Hooked interrupt vectors calling into our "BIOS" will cause
2310 * problems unless all intersegment stuff is checked for BIOS
2311 * access. Check needed here. For moment, let it alone.
2314 push_word(M.x86.R_CS);
2315 M.x86.R_CS = farseg;
2316 push_word(M.x86.R_IP);
2317 M.x86.R_IP = faroff;
2318 DECODE_CLEAR_SEGOVR();
2322 /****************************************************************************
2325 ****************************************************************************/
2326 void x86emuOp_wait(u8 X86EMU_UNUSED(op1))
2329 DECODE_PRINTF("WAIT");
2332 DECODE_CLEAR_SEGOVR();
2336 /****************************************************************************
2339 ****************************************************************************/
2340 void x86emuOp_pushf_word(u8 X86EMU_UNUSED(op1))
2345 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2346 DECODE_PRINTF("PUSHFD\n");
2348 DECODE_PRINTF("PUSHF\n");
2352 /* clear out *all* bits not representing flags, and turn on real bits */
2353 flags = (M.x86.R_EFLG & F_MSK) | F_ALWAYS_ON;
2354 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2357 push_word((u16)flags);
2359 DECODE_CLEAR_SEGOVR();
2363 /****************************************************************************
2366 ****************************************************************************/
2367 void x86emuOp_popf_word(u8 X86EMU_UNUSED(op1))
2370 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2371 DECODE_PRINTF("POPFD\n");
2373 DECODE_PRINTF("POPF\n");
2376 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2377 M.x86.R_EFLG = pop_long();
2379 M.x86.R_FLG = pop_word();
2381 DECODE_CLEAR_SEGOVR();
2385 /****************************************************************************
2388 ****************************************************************************/
2389 void x86emuOp_sahf(u8 X86EMU_UNUSED(op1))
2392 DECODE_PRINTF("SAHF\n");
2394 /* clear the lower bits of the flag register */
2395 M.x86.R_FLG &= 0xffffff00;
2396 /* or in the AH register into the flags register */
2397 M.x86.R_FLG |= M.x86.R_AH;
2398 DECODE_CLEAR_SEGOVR();
2402 /****************************************************************************
2405 ****************************************************************************/
2406 void x86emuOp_lahf(u8 X86EMU_UNUSED(op1))
2409 DECODE_PRINTF("LAHF\n");
2411 M.x86.R_AH = (u8)(M.x86.R_FLG & 0xff);
2412 /*undocumented TC++ behavior??? Nope. It's documented, but
2413 you have too look real hard to notice it. */
2415 DECODE_CLEAR_SEGOVR();
2419 /****************************************************************************
2422 ****************************************************************************/
2423 void x86emuOp_mov_AL_M_IMM(u8 X86EMU_UNUSED(op1))
2428 DECODE_PRINTF("MOV\tAL,");
2429 offset = fetch_word_imm();
2430 DECODE_PRINTF2("[%04x]\n", offset);
2432 M.x86.R_AL = fetch_data_byte(offset);
2433 DECODE_CLEAR_SEGOVR();
2437 /****************************************************************************
2440 ****************************************************************************/
2441 void x86emuOp_mov_AX_M_IMM(u8 X86EMU_UNUSED(op1))
2446 offset = fetch_word_imm();
2447 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2448 DECODE_PRINTF2("MOV\tEAX,[%04x]\n", offset);
2450 DECODE_PRINTF2("MOV\tAX,[%04x]\n", offset);
2453 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2454 M.x86.R_EAX = fetch_data_long(offset);
2456 M.x86.R_AX = fetch_data_word(offset);
2458 DECODE_CLEAR_SEGOVR();
2462 /****************************************************************************
2465 ****************************************************************************/
2466 void x86emuOp_mov_M_AL_IMM(u8 X86EMU_UNUSED(op1))
2471 DECODE_PRINTF("MOV\t");
2472 offset = fetch_word_imm();
2473 DECODE_PRINTF2("[%04x],AL\n", offset);
2475 store_data_byte(offset, M.x86.R_AL);
2476 DECODE_CLEAR_SEGOVR();
2480 /****************************************************************************
2483 ****************************************************************************/
2484 void x86emuOp_mov_M_AX_IMM(u8 X86EMU_UNUSED(op1))
2489 offset = fetch_word_imm();
2490 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2491 DECODE_PRINTF2("MOV\t[%04x],EAX\n", offset);
2493 DECODE_PRINTF2("MOV\t[%04x],AX\n", offset);
2496 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2497 store_data_long(offset, M.x86.R_EAX);
2499 store_data_word(offset, M.x86.R_AX);
2501 DECODE_CLEAR_SEGOVR();
2505 /****************************************************************************
2508 ****************************************************************************/
2509 void x86emuOp_movs_byte(u8 X86EMU_UNUSED(op1))
2516 DECODE_PRINTF("MOVS\tBYTE\n");
2517 if (ACCESS_FLAG(F_DF)) /* down */
2523 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2524 /* dont care whether REPE or REPNE */
2525 /* move them until (E)CX is ZERO. */
2526 count = (M.x86.mode & SYSMODE_32BIT_REP) ? M.x86.R_ECX : M.x86.R_CX;
2528 if (M.x86.mode & SYSMODE_32BIT_REP)
2530 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2533 val = fetch_data_byte(M.x86.R_SI);
2534 store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, val);
2537 if (M.x86.intr & INTR_HALTED)
2540 DECODE_CLEAR_SEGOVR();
2544 /****************************************************************************
2547 ****************************************************************************/
2548 void x86emuOp_movs_word(u8 X86EMU_UNUSED(op1))
2555 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2556 DECODE_PRINTF("MOVS\tDWORD\n");
2557 if (ACCESS_FLAG(F_DF)) /* down */
2562 DECODE_PRINTF("MOVS\tWORD\n");
2563 if (ACCESS_FLAG(F_DF)) /* down */
2570 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2571 /* dont care whether REPE or REPNE */
2572 /* move them until (E)CX is ZERO. */
2573 count = (M.x86.mode & SYSMODE_32BIT_REP) ? M.x86.R_ECX : M.x86.R_CX;
2575 if (M.x86.mode & SYSMODE_32BIT_REP)
2577 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2580 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2581 val = fetch_data_long(M.x86.R_SI);
2582 store_data_long_abs(M.x86.R_ES, M.x86.R_DI, val);
2584 val = fetch_data_word(M.x86.R_SI);
2585 store_data_word_abs(M.x86.R_ES, M.x86.R_DI, (u16)val);
2589 if (M.x86.intr & INTR_HALTED)
2592 DECODE_CLEAR_SEGOVR();
2596 /****************************************************************************
2599 ****************************************************************************/
2600 void x86emuOp_cmps_byte(u8 X86EMU_UNUSED(op1))
2606 DECODE_PRINTF("CMPS\tBYTE\n");
2608 if (ACCESS_FLAG(F_DF)) /* down */
2613 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2615 /* move them until (E)CX is ZERO. */
2616 while (((M.x86.mode & SYSMODE_32BIT_REP) ? M.x86.R_ECX : M.x86.R_CX) != 0) {
2617 val1 = fetch_data_byte(M.x86.R_SI);
2618 val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2619 cmp_byte(val1, val2);
2620 if (M.x86.mode & SYSMODE_32BIT_REP)
2626 if ( (M.x86.mode & SYSMODE_PREFIX_REPE) && (ACCESS_FLAG(F_ZF) == 0) ) break;
2627 if ( (M.x86.mode & SYSMODE_PREFIX_REPNE) && ACCESS_FLAG(F_ZF) ) break;
2628 if (M.x86.intr & INTR_HALTED)
2631 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2633 val1 = fetch_data_byte(M.x86.R_SI);
2634 val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2635 cmp_byte(val1, val2);
2639 DECODE_CLEAR_SEGOVR();
2643 /****************************************************************************
2646 ****************************************************************************/
2647 void x86emuOp_cmps_word(u8 X86EMU_UNUSED(op1))
2653 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2654 DECODE_PRINTF("CMPS\tDWORD\n");
2657 DECODE_PRINTF("CMPS\tWORD\n");
2660 if (ACCESS_FLAG(F_DF)) /* down */
2664 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2666 /* move them until (E)CX is ZERO. */
2667 while (((M.x86.mode & SYSMODE_32BIT_REP) ? M.x86.R_ECX : M.x86.R_CX) != 0) {
2668 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2669 val1 = fetch_data_long(M.x86.R_SI);
2670 val2 = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
2671 cmp_long(val1, val2);
2673 val1 = fetch_data_word(M.x86.R_SI);
2674 val2 = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
2675 cmp_word((u16)val1, (u16)val2);
2677 if (M.x86.mode & SYSMODE_32BIT_REP)
2683 if ( (M.x86.mode & SYSMODE_PREFIX_REPE) && ACCESS_FLAG(F_ZF) == 0 ) break;
2684 if ( (M.x86.mode & SYSMODE_PREFIX_REPNE) && ACCESS_FLAG(F_ZF) ) break;
2685 if (M.x86.intr & INTR_HALTED)
2688 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2690 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2691 val1 = fetch_data_long(M.x86.R_SI);
2692 val2 = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
2693 cmp_long(val1, val2);
2695 val1 = fetch_data_word(M.x86.R_SI);
2696 val2 = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
2697 cmp_word((u16)val1, (u16)val2);
2702 DECODE_CLEAR_SEGOVR();
2706 /****************************************************************************
2709 ****************************************************************************/
2710 void x86emuOp_test_AL_IMM(u8 X86EMU_UNUSED(op1))
2715 DECODE_PRINTF("TEST\tAL,");
2716 imm = fetch_byte_imm();
2717 DECODE_PRINTF2("%04x\n", imm);
2719 test_byte(M.x86.R_AL, (u8)imm);
2720 DECODE_CLEAR_SEGOVR();
2724 /****************************************************************************
2727 ****************************************************************************/
2728 void x86emuOp_test_AX_IMM(u8 X86EMU_UNUSED(op1))
2733 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2734 DECODE_PRINTF("TEST\tEAX,");
2735 srcval = fetch_long_imm();
2737 DECODE_PRINTF("TEST\tAX,");
2738 srcval = fetch_word_imm();
2740 DECODE_PRINTF2("%x\n", srcval);
2742 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2743 test_long(M.x86.R_EAX, srcval);
2745 test_word(M.x86.R_AX, (u16)srcval);
2747 DECODE_CLEAR_SEGOVR();
2751 /****************************************************************************
2754 ****************************************************************************/
2755 void x86emuOp_stos_byte(u8 X86EMU_UNUSED(op1))
2760 DECODE_PRINTF("STOS\tBYTE\n");
2761 if (ACCESS_FLAG(F_DF)) /* down */
2766 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2767 /* dont care whether REPE or REPNE */
2768 /* move them until (E)CX is ZERO. */
2769 while (((M.x86.mode & SYSMODE_32BIT_REP) ? M.x86.R_ECX : M.x86.R_CX) != 0) {
2770 store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AL);
2771 if (M.x86.mode & SYSMODE_32BIT_REP)
2776 if (M.x86.intr & INTR_HALTED)
2779 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2781 store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AL);
2784 DECODE_CLEAR_SEGOVR();
2788 /****************************************************************************
2791 ****************************************************************************/
2792 void x86emuOp_stos_word(u8 X86EMU_UNUSED(op1))
2798 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2799 DECODE_PRINTF("STOS\tDWORD\n");
2800 if (ACCESS_FLAG(F_DF)) /* down */
2805 DECODE_PRINTF("STOS\tWORD\n");
2806 if (ACCESS_FLAG(F_DF)) /* down */
2813 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2814 /* dont care whether REPE or REPNE */
2815 /* move them until (E)CX is ZERO. */
2816 count = (M.x86.mode & SYSMODE_32BIT_REP) ? M.x86.R_ECX : M.x86.R_CX;
2818 if (M.x86.mode & SYSMODE_32BIT_REP)
2820 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2823 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2824 store_data_long_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_EAX);
2826 store_data_word_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AX);
2829 if (M.x86.intr & INTR_HALTED)
2832 DECODE_CLEAR_SEGOVR();
2836 /****************************************************************************
2839 ****************************************************************************/
2840 void x86emuOp_lods_byte(u8 X86EMU_UNUSED(op1))
2845 DECODE_PRINTF("LODS\tBYTE\n");
2847 if (ACCESS_FLAG(F_DF)) /* down */
2851 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2852 /* dont care whether REPE or REPNE */
2853 /* move them until (E)CX is ZERO. */
2854 while (((M.x86.mode & SYSMODE_32BIT_REP) ? M.x86.R_ECX : M.x86.R_CX) != 0) {
2855 M.x86.R_AL = fetch_data_byte(M.x86.R_SI);
2856 if (M.x86.mode & SYSMODE_32BIT_REP)
2861 if (M.x86.intr & INTR_HALTED)
2864 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2866 M.x86.R_AL = fetch_data_byte(M.x86.R_SI);
2869 DECODE_CLEAR_SEGOVR();
2873 /****************************************************************************
2876 ****************************************************************************/
2877 void x86emuOp_lods_word(u8 X86EMU_UNUSED(op1))
2883 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2884 DECODE_PRINTF("LODS\tDWORD\n");
2885 if (ACCESS_FLAG(F_DF)) /* down */
2890 DECODE_PRINTF("LODS\tWORD\n");
2891 if (ACCESS_FLAG(F_DF)) /* down */
2898 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2899 /* dont care whether REPE or REPNE */
2900 /* move them until (E)CX is ZERO. */
2901 count = (M.x86.mode & SYSMODE_32BIT_REP) ? M.x86.R_ECX : M.x86.R_CX;
2903 if (M.x86.mode & SYSMODE_32BIT_REP)
2905 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2908 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2909 M.x86.R_EAX = fetch_data_long(M.x86.R_SI);
2911 M.x86.R_AX = fetch_data_word(M.x86.R_SI);
2914 if (M.x86.intr & INTR_HALTED)
2917 DECODE_CLEAR_SEGOVR();
2921 /****************************************************************************
2924 ****************************************************************************/
2925 void x86emuOp_scas_byte(u8 X86EMU_UNUSED(op1))
2931 DECODE_PRINTF("SCAS\tBYTE\n");
2933 if (ACCESS_FLAG(F_DF)) /* down */
2937 if (M.x86.mode & SYSMODE_PREFIX_REPE) {
2939 /* move them until (E)CX is ZERO. */
2940 while (((M.x86.mode & SYSMODE_32BIT_REP) ? M.x86.R_ECX : M.x86.R_CX) != 0) {
2941 val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2942 cmp_byte(M.x86.R_AL, val2);
2943 if (M.x86.mode & SYSMODE_32BIT_REP)
2948 if (ACCESS_FLAG(F_ZF) == 0)
2950 if (M.x86.intr & INTR_HALTED)
2953 M.x86.mode &= ~SYSMODE_PREFIX_REPE;
2954 } else if (M.x86.mode & SYSMODE_PREFIX_REPNE) {
2956 /* move them until (E)CX is ZERO. */
2957 while (((M.x86.mode & SYSMODE_32BIT_REP) ? M.x86.R_ECX : M.x86.R_CX) != 0) {
2958 val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2959 cmp_byte(M.x86.R_AL, val2);
2960 if (M.x86.mode & SYSMODE_32BIT_REP)
2965 if (ACCESS_FLAG(F_ZF))
2966 break; /* zero flag set means equal */
2967 if (M.x86.intr & INTR_HALTED)
2970 M.x86.mode &= ~SYSMODE_PREFIX_REPNE;
2972 val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2973 cmp_byte(M.x86.R_AL, val2);
2976 DECODE_CLEAR_SEGOVR();
2980 /****************************************************************************
2983 ****************************************************************************/
2984 void x86emuOp_scas_word(u8 X86EMU_UNUSED(op1))
2990 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2991 DECODE_PRINTF("SCAS\tDWORD\n");
2992 if (ACCESS_FLAG(F_DF)) /* down */
2997 DECODE_PRINTF("SCAS\tWORD\n");
2998 if (ACCESS_FLAG(F_DF)) /* down */
3004 if (M.x86.mode & SYSMODE_PREFIX_REPE) {
3006 /* move them until (E)CX is ZERO. */
3007 while (((M.x86.mode & SYSMODE_32BIT_REP) ? M.x86.R_ECX : M.x86.R_CX) != 0) {
3008 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3009 val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
3010 cmp_long(M.x86.R_EAX, val);
3012 val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
3013 cmp_word(M.x86.R_AX, (u16)val);
3015 if (M.x86.mode & SYSMODE_32BIT_REP)
3020 if (ACCESS_FLAG(F_ZF) == 0)
3022 if (M.x86.intr & INTR_HALTED)
3025 M.x86.mode &= ~SYSMODE_PREFIX_REPE;
3026 } else if (M.x86.mode & SYSMODE_PREFIX_REPNE) {
3028 /* move them until (E)CX is ZERO. */
3029 while (((M.x86.mode & SYSMODE_32BIT_REP) ? M.x86.R_ECX : M.x86.R_CX) != 0) {
3030 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3031 val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
3032 cmp_long(M.x86.R_EAX, val);
3034 val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
3035 cmp_word(M.x86.R_AX, (u16)val);
3037 if (M.x86.mode & SYSMODE_32BIT_REP)
3042 if (ACCESS_FLAG(F_ZF))
3043 break; /* zero flag set means equal */
3044 if (M.x86.intr & INTR_HALTED)
3047 M.x86.mode &= ~SYSMODE_PREFIX_REPNE;
3049 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3050 val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
3051 cmp_long(M.x86.R_EAX, val);
3053 val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
3054 cmp_word(M.x86.R_AX, (u16)val);
3058 DECODE_CLEAR_SEGOVR();
3062 /****************************************************************************
3064 Handles opcode 0xb0 - 0xb7
3065 ****************************************************************************/
3066 void x86emuOp_mov_byte_register_IMM(u8 op1)
3071 DECODE_PRINTF("MOV\t");
3072 ptr = DECODE_RM_BYTE_REGISTER(op1 & 0x7);
3074 imm = fetch_byte_imm();
3075 DECODE_PRINTF2("%x\n", imm);
3078 DECODE_CLEAR_SEGOVR();
3082 /****************************************************************************
3084 Handles opcode 0xb8 - 0xbf
3085 ****************************************************************************/
3086 void x86emuOp_mov_word_register_IMM(u8 X86EMU_UNUSED(op1))
3093 DECODE_PRINTF("MOV\t");
3094 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3096 reg32 = DECODE_RM_LONG_REGISTER(op1);
3097 srcval = fetch_long_imm();
3098 DECODE_PRINTF2(",%x\n", srcval);
3103 reg16 = DECODE_RM_WORD_REGISTER(op1);
3104 srcval = fetch_word_imm();
3105 DECODE_PRINTF2(",%x\n", srcval);
3107 *reg16 = (u16)srcval;
3109 DECODE_CLEAR_SEGOVR();
3113 /****************************************************************************
3116 ****************************************************************************/
3117 void x86emuOp_opcC0_byte_RM_MEM(u8 X86EMU_UNUSED(op1))
3126 * Yet another weirdo special case instruction format. Part of
3127 * the opcode held below in "RH". Doubly nested case would
3128 * result, except that the decoded instruction
3131 FETCH_DECODE_MODRM(mod, rh, rl);
3133 if (DEBUG_DECODE()) {
3134 /* XXX DECODE_PRINTF may be changed to something more
3135 general, so that it is important to leave the strings
3136 in the same format, even though the result is that the
3137 above test is done twice. */
3141 DECODE_PRINTF("ROL\t");
3144 DECODE_PRINTF("ROR\t");
3147 DECODE_PRINTF("RCL\t");
3150 DECODE_PRINTF("RCR\t");
3153 DECODE_PRINTF("SHL\t");
3156 DECODE_PRINTF("SHR\t");
3159 DECODE_PRINTF("SAL\t");
3162 DECODE_PRINTF("SAR\t");
3167 /* know operation, decode the mod byte to find the addressing
3170 DECODE_PRINTF("BYTE PTR ");
3171 destoffset = decode_rmXX_address(mod, rl);
3172 amt = fetch_byte_imm();
3173 DECODE_PRINTF2(",%x\n", amt);
3174 destval = fetch_data_byte(destoffset);
3176 destval = (*opcD0_byte_operation[rh]) (destval, amt);
3177 store_data_byte(destoffset, destval);
3178 } else { /* register to register */
3179 destreg = DECODE_RM_BYTE_REGISTER(rl);
3180 amt = fetch_byte_imm();
3181 DECODE_PRINTF2(",%x\n", amt);
3183 destval = (*opcD0_byte_operation[rh]) (*destreg, amt);
3186 DECODE_CLEAR_SEGOVR();
3190 /****************************************************************************
3193 ****************************************************************************/
3194 void x86emuOp_opcC1_word_RM_MEM(u8 X86EMU_UNUSED(op1))
3201 * Yet another weirdo special case instruction format. Part of
3202 * the opcode held below in "RH". Doubly nested case would
3203 * result, except that the decoded instruction
3206 FETCH_DECODE_MODRM(mod, rh, rl);
3208 if (DEBUG_DECODE()) {
3209 /* XXX DECODE_PRINTF may be changed to something more
3210 general, so that it is important to leave the strings
3211 in the same format, even though the result is that the
3212 above test is done twice. */
3216 DECODE_PRINTF("ROL\t");
3219 DECODE_PRINTF("ROR\t");
3222 DECODE_PRINTF("RCL\t");
3225 DECODE_PRINTF("RCR\t");
3228 DECODE_PRINTF("SHL\t");
3231 DECODE_PRINTF("SHR\t");
3234 DECODE_PRINTF("SAL\t");
3237 DECODE_PRINTF("SAR\t");
3242 /* know operation, decode the mod byte to find the addressing
3245 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3248 DECODE_PRINTF("DWORD PTR ");
3249 destoffset = decode_rmXX_address(mod, rl);
3250 amt = fetch_byte_imm();
3251 DECODE_PRINTF2(",%x\n", amt);
3252 destval = fetch_data_long(destoffset);
3254 destval = (*opcD1_long_operation[rh]) (destval, amt);
3255 store_data_long(destoffset, destval);
3259 DECODE_PRINTF("WORD PTR ");
3260 destoffset = decode_rmXX_address(mod, rl);
3261 amt = fetch_byte_imm();
3262 DECODE_PRINTF2(",%x\n", amt);
3263 destval = fetch_data_word(destoffset);
3265 destval = (*opcD1_word_operation[rh]) (destval, amt);
3266 store_data_word(destoffset, destval);
3268 } else { /* register to register */
3269 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3272 destreg = DECODE_RM_LONG_REGISTER(rl);
3273 amt = fetch_byte_imm();
3274 DECODE_PRINTF2(",%x\n", amt);
3276 *destreg = (*opcD1_long_operation[rh]) (*destreg, amt);
3280 destreg = DECODE_RM_WORD_REGISTER(rl);
3281 amt = fetch_byte_imm();
3282 DECODE_PRINTF2(",%x\n", amt);
3284 *destreg = (*opcD1_word_operation[rh]) (*destreg, amt);
3287 DECODE_CLEAR_SEGOVR();
3291 /****************************************************************************
3294 ****************************************************************************/
3295 void x86emuOp_ret_near_IMM(u8 X86EMU_UNUSED(op1))
3300 DECODE_PRINTF("RET\t");
3301 imm = fetch_word_imm();
3302 DECODE_PRINTF2("%x\n", imm);
3304 M.x86.R_IP = pop_word();
3305 RETURN_TRACE(M.x86.saved_cs,M.x86.saved_ip, M.x86.R_CS, M.x86.R_IP, "NEAR");
3307 DECODE_CLEAR_SEGOVR();
3311 /****************************************************************************
3314 ****************************************************************************/
3315 void x86emuOp_ret_near(u8 X86EMU_UNUSED(op1))
3318 DECODE_PRINTF("RET\n");
3320 M.x86.R_IP = pop_word();
3321 RETURN_TRACE(M.x86.saved_cs,M.x86.saved_ip, M.x86.R_CS, M.x86.R_IP, "NEAR");
3322 DECODE_CLEAR_SEGOVR();
3326 /****************************************************************************
3329 ****************************************************************************/
3330 void x86emuOp_les_R_IMM(u8 X86EMU_UNUSED(op1))
3337 DECODE_PRINTF("LES\t");
3338 FETCH_DECODE_MODRM(mod, rh, rl);
3340 dstreg = DECODE_RM_WORD_REGISTER(rh);
3342 srcoffset = decode_rmXX_address(mod, rl);
3343 DECODE_PRINTF("\n");
3345 *dstreg = fetch_data_word(srcoffset);
3346 M.x86.R_ES = fetch_data_word(srcoffset + 2);
3348 /* else UNDEFINED! register to register */
3350 DECODE_CLEAR_SEGOVR();
3354 /****************************************************************************
3357 ****************************************************************************/
3358 void x86emuOp_lds_R_IMM(u8 X86EMU_UNUSED(op1))
3365 DECODE_PRINTF("LDS\t");
3366 FETCH_DECODE_MODRM(mod, rh, rl);
3368 dstreg = DECODE_RM_WORD_REGISTER(rh);
3370 srcoffset = decode_rmXX_address(mod, rl);
3371 DECODE_PRINTF("\n");
3373 *dstreg = fetch_data_word(srcoffset);
3374 M.x86.R_DS = fetch_data_word(srcoffset + 2);
3376 /* else UNDEFINED! */
3377 DECODE_CLEAR_SEGOVR();
3381 /****************************************************************************
3384 ****************************************************************************/
3385 void x86emuOp_mov_byte_RM_IMM(u8 X86EMU_UNUSED(op1))
3393 DECODE_PRINTF("MOV\t");
3394 FETCH_DECODE_MODRM(mod, rh, rl);
3396 DECODE_PRINTF("ILLEGAL DECODE OF OPCODE c6\n");
3400 DECODE_PRINTF("BYTE PTR ");
3401 destoffset = decode_rmXX_address(mod, rl);
3402 imm = fetch_byte_imm();
3403 DECODE_PRINTF2(",%2x\n", imm);
3405 store_data_byte(destoffset, imm);
3406 } else { /* register to register */
3407 destreg = DECODE_RM_BYTE_REGISTER(rl);
3408 imm = fetch_byte_imm();
3409 DECODE_PRINTF2(",%2x\n", imm);
3413 DECODE_CLEAR_SEGOVR();
3417 /****************************************************************************
3420 ****************************************************************************/
3421 void x86emuOp_mov_word_RM_IMM(u8 X86EMU_UNUSED(op1))
3427 DECODE_PRINTF("MOV\t");
3428 FETCH_DECODE_MODRM(mod, rh, rl);
3430 DECODE_PRINTF("ILLEGAL DECODE OF OPCODE 8F\n");
3434 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3437 DECODE_PRINTF("DWORD PTR ");
3438 destoffset = decode_rmXX_address(mod, rl);
3439 imm = fetch_long_imm();
3440 DECODE_PRINTF2(",%x\n", imm);
3442 store_data_long(destoffset, imm);
3446 DECODE_PRINTF("WORD PTR ");
3447 destoffset = decode_rmXX_address(mod, rl);
3448 imm = fetch_word_imm();
3449 DECODE_PRINTF2(",%x\n", imm);
3451 store_data_word(destoffset, imm);
3453 } else { /* register to register */
3454 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3458 destreg = DECODE_RM_LONG_REGISTER(rl);
3459 imm = fetch_long_imm();
3460 DECODE_PRINTF2(",%x\n", imm);
3467 destreg = DECODE_RM_WORD_REGISTER(rl);
3468 imm = fetch_word_imm();
3469 DECODE_PRINTF2(",%x\n", imm);
3474 DECODE_CLEAR_SEGOVR();
3478 /****************************************************************************
3481 ****************************************************************************/
3482 void x86emuOp_enter(u8 X86EMU_UNUSED(op1))
3484 u16 local,frame_pointer;
3489 local = fetch_word_imm();
3490 nesting = fetch_byte_imm();
3491 DECODE_PRINTF2("ENTER %x\n", local);
3492 DECODE_PRINTF2(",%x\n", nesting);
3494 push_word(M.x86.R_BP);
3495 frame_pointer = M.x86.R_SP;
3497 for (i = 1; i < nesting; i++) {
3499 push_word(fetch_data_word_abs(M.x86.R_SS, M.x86.R_BP));
3501 push_word(frame_pointer);
3503 M.x86.R_BP = frame_pointer;
3504 M.x86.R_SP = (u16)(M.x86.R_SP - local);
3505 DECODE_CLEAR_SEGOVR();
3509 /****************************************************************************
3512 ****************************************************************************/
3513 void x86emuOp_leave(u8 X86EMU_UNUSED(op1))
3516 DECODE_PRINTF("LEAVE\n");
3518 M.x86.R_SP = M.x86.R_BP;
3519 M.x86.R_BP = pop_word();
3520 DECODE_CLEAR_SEGOVR();
3524 /****************************************************************************
3527 ****************************************************************************/
3528 void x86emuOp_ret_far_IMM(u8 X86EMU_UNUSED(op1))
3533 DECODE_PRINTF("RETF\t");
3534 imm = fetch_word_imm();
3535 DECODE_PRINTF2("%x\n", imm);
3537 M.x86.R_IP = pop_word();
3538 M.x86.R_CS = pop_word();
3539 RETURN_TRACE(M.x86.saved_cs,M.x86.saved_ip, M.x86.R_CS, M.x86.R_IP, "FAR");
3541 DECODE_CLEAR_SEGOVR();
3545 /****************************************************************************
3548 ****************************************************************************/
3549 void x86emuOp_ret_far(u8 X86EMU_UNUSED(op1))
3552 DECODE_PRINTF("RETF\n");
3554 M.x86.R_IP = pop_word();
3555 M.x86.R_CS = pop_word();
3556 RETURN_TRACE(M.x86.saved_cs,M.x86.saved_ip, M.x86.R_CS, M.x86.R_IP, "FAR");
3557 DECODE_CLEAR_SEGOVR();
3561 /****************************************************************************
3564 ****************************************************************************/
3565 void x86emuOp_int3(u8 X86EMU_UNUSED(op1))
3570 DECODE_PRINTF("INT 3\n");
3571 tmp = (u16) mem_access_word(3 * 4 + 2);
3572 /* access the segment register */
3574 if (_X86EMU_intrTab[3]) {
3575 (*_X86EMU_intrTab[3])(3);
3577 push_word((u16)M.x86.R_FLG);
3580 push_word(M.x86.R_CS);
3581 M.x86.R_CS = mem_access_word(3 * 4 + 2);
3582 push_word(M.x86.R_IP);
3583 M.x86.R_IP = mem_access_word(3 * 4);
3585 DECODE_CLEAR_SEGOVR();
3589 /****************************************************************************
3592 ****************************************************************************/
3593 void x86emuOp_int_IMM(u8 X86EMU_UNUSED(op1))
3599 DECODE_PRINTF("INT\t");
3600 intnum = fetch_byte_imm();
3601 DECODE_PRINTF2("%x\n", intnum);
3602 tmp = mem_access_word(intnum * 4 + 2);
3604 if (_X86EMU_intrTab[intnum]) {
3605 (*_X86EMU_intrTab[intnum])(intnum);
3607 push_word((u16)M.x86.R_FLG);
3610 push_word(M.x86.R_CS);
3611 M.x86.R_CS = mem_access_word(intnum * 4 + 2);
3612 push_word(M.x86.R_IP);
3613 M.x86.R_IP = mem_access_word(intnum * 4);
3615 DECODE_CLEAR_SEGOVR();
3619 /****************************************************************************
3622 ****************************************************************************/
3623 void x86emuOp_into(u8 X86EMU_UNUSED(op1))
3628 DECODE_PRINTF("INTO\n");
3630 if (ACCESS_FLAG(F_OF)) {
3631 tmp = mem_access_word(4 * 4 + 2);
3632 if (_X86EMU_intrTab[4]) {
3633 (*_X86EMU_intrTab[4])(4);
3635 push_word((u16)M.x86.R_FLG);
3638 push_word(M.x86.R_CS);
3639 M.x86.R_CS = mem_access_word(4 * 4 + 2);
3640 push_word(M.x86.R_IP);
3641 M.x86.R_IP = mem_access_word(4 * 4);
3644 DECODE_CLEAR_SEGOVR();
3648 /****************************************************************************
3651 ****************************************************************************/
3652 void x86emuOp_iret(u8 X86EMU_UNUSED(op1))
3655 DECODE_PRINTF("IRET\n");
3659 M.x86.R_IP = pop_word();
3660 M.x86.R_CS = pop_word();
3661 M.x86.R_FLG = pop_word();
3662 DECODE_CLEAR_SEGOVR();
3666 /****************************************************************************
3669 ****************************************************************************/
3670 void x86emuOp_opcD0_byte_RM_1(u8 X86EMU_UNUSED(op1))
3678 * Yet another weirdo special case instruction format. Part of
3679 * the opcode held below in "RH". Doubly nested case would
3680 * result, except that the decoded instruction
3683 FETCH_DECODE_MODRM(mod, rh, rl);
3685 if (DEBUG_DECODE()) {
3686 /* XXX DECODE_PRINTF may be changed to something more
3687 general, so that it is important to leave the strings
3688 in the same format, even though the result is that the
3689 above test is done twice. */
3692 DECODE_PRINTF("ROL\t");
3695 DECODE_PRINTF("ROR\t");
3698 DECODE_PRINTF("RCL\t");
3701 DECODE_PRINTF("RCR\t");
3704 DECODE_PRINTF("SHL\t");
3707 DECODE_PRINTF("SHR\t");
3710 DECODE_PRINTF("SAL\t");
3713 DECODE_PRINTF("SAR\t");
3718 /* know operation, decode the mod byte to find the addressing
3721 DECODE_PRINTF("BYTE PTR ");
3722 destoffset = decode_rmXX_address(mod, rl);
3723 DECODE_PRINTF(",1\n");
3724 destval = fetch_data_byte(destoffset);
3726 destval = (*opcD0_byte_operation[rh]) (destval, 1);
3727 store_data_byte(destoffset, destval);
3728 } else { /* register to register */
3729 destreg = DECODE_RM_BYTE_REGISTER(rl);
3730 DECODE_PRINTF(",1\n");
3732 destval = (*opcD0_byte_operation[rh]) (*destreg, 1);
3735 DECODE_CLEAR_SEGOVR();
3739 /****************************************************************************
3742 ****************************************************************************/
3743 void x86emuOp_opcD1_word_RM_1(u8 X86EMU_UNUSED(op1))
3749 * Yet another weirdo special case instruction format. Part of
3750 * the opcode held below in "RH". Doubly nested case would
3751 * result, except that the decoded instruction
3754 FETCH_DECODE_MODRM(mod, rh, rl);
3756 if (DEBUG_DECODE()) {
3757 /* XXX DECODE_PRINTF may be changed to something more
3758 general, so that it is important to leave the strings
3759 in the same format, even though the result is that the
3760 above test is done twice. */
3763 DECODE_PRINTF("ROL\t");
3766 DECODE_PRINTF("ROR\t");
3769 DECODE_PRINTF("RCL\t");
3772 DECODE_PRINTF("RCR\t");
3775 DECODE_PRINTF("SHL\t");
3778 DECODE_PRINTF("SHR\t");
3781 DECODE_PRINTF("SAL\t");
3784 DECODE_PRINTF("SAR\t");
3789 /* know operation, decode the mod byte to find the addressing
3792 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3795 DECODE_PRINTF("DWORD PTR ");
3796 destoffset = decode_rmXX_address(mod, rl);
3797 DECODE_PRINTF(",1\n");
3798 destval = fetch_data_long(destoffset);
3800 destval = (*opcD1_long_operation[rh]) (destval, 1);
3801 store_data_long(destoffset, destval);
3805 DECODE_PRINTF("WORD PTR ");
3806 destoffset = decode_rmXX_address(mod, rl);
3807 DECODE_PRINTF(",1\n");
3808 destval = fetch_data_word(destoffset);
3810 destval = (*opcD1_word_operation[rh]) (destval, 1);
3811 store_data_word(destoffset, destval);
3813 } else { /* register to register */
3814 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3818 destreg = DECODE_RM_LONG_REGISTER(rl);
3819 DECODE_PRINTF(",1\n");
3821 destval = (*opcD1_long_operation[rh]) (*destreg, 1);
3827 destreg = DECODE_RM_WORD_REGISTER(rl);
3828 DECODE_PRINTF(",1\n");
3830 destval = (*opcD1_word_operation[rh]) (*destreg, 1);
3834 DECODE_CLEAR_SEGOVR();
3838 /****************************************************************************
3841 ****************************************************************************/
3842 void x86emuOp_opcD2_byte_RM_CL(u8 X86EMU_UNUSED(op1))
3851 * Yet another weirdo special case instruction format. Part of
3852 * the opcode held below in "RH". Doubly nested case would
3853 * result, except that the decoded instruction
3856 FETCH_DECODE_MODRM(mod, rh, rl);
3858 if (DEBUG_DECODE()) {
3859 /* XXX DECODE_PRINTF may be changed to something more
3860 general, so that it is important to leave the strings
3861 in the same format, even though the result is that the
3862 above test is done twice. */
3865 DECODE_PRINTF("ROL\t");
3868 DECODE_PRINTF("ROR\t");
3871 DECODE_PRINTF("RCL\t");
3874 DECODE_PRINTF("RCR\t");
3877 DECODE_PRINTF("SHL\t");
3880 DECODE_PRINTF("SHR\t");
3883 DECODE_PRINTF("SAL\t");
3886 DECODE_PRINTF("SAR\t");
3891 /* know operation, decode the mod byte to find the addressing
3895 DECODE_PRINTF("BYTE PTR ");
3896 destoffset = decode_rmXX_address(mod, rl);
3897 DECODE_PRINTF(",CL\n");
3898 destval = fetch_data_byte(destoffset);
3900 destval = (*opcD0_byte_operation[rh]) (destval, amt);
3901 store_data_byte(destoffset, destval);
3902 } else { /* register to register */
3903 destreg = DECODE_RM_BYTE_REGISTER(rl);
3904 DECODE_PRINTF(",CL\n");
3906 destval = (*opcD0_byte_operation[rh]) (*destreg, amt);
3909 DECODE_CLEAR_SEGOVR();
3913 /****************************************************************************
3916 ****************************************************************************/
3917 void x86emuOp_opcD3_word_RM_CL(u8 X86EMU_UNUSED(op1))
3924 * Yet another weirdo special case instruction format. Part of
3925 * the opcode held below in "RH". Doubly nested case would
3926 * result, except that the decoded instruction
3929 FETCH_DECODE_MODRM(mod, rh, rl);
3931 if (DEBUG_DECODE()) {
3932 /* XXX DECODE_PRINTF may be changed to something more
3933 general, so that it is important to leave the strings
3934 in the same format, even though the result is that the
3935 above test is done twice. */
3938 DECODE_PRINTF("ROL\t");
3941 DECODE_PRINTF("ROR\t");
3944 DECODE_PRINTF("RCL\t");
3947 DECODE_PRINTF("RCR\t");
3950 DECODE_PRINTF("SHL\t");
3953 DECODE_PRINTF("SHR\t");
3956 DECODE_PRINTF("SAL\t");
3959 DECODE_PRINTF("SAR\t");
3964 /* know operation, decode the mod byte to find the addressing
3968 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3971 DECODE_PRINTF("DWORD PTR ");
3972 destoffset = decode_rmXX_address(mod, rl);
3973 DECODE_PRINTF(",CL\n");
3974 destval = fetch_data_long(destoffset);
3976 destval = (*opcD1_long_operation[rh]) (destval, amt);
3977 store_data_long(destoffset, destval);
3981 DECODE_PRINTF("WORD PTR ");
3982 destoffset = decode_rmXX_address(mod, rl);
3983 DECODE_PRINTF(",CL\n");
3984 destval = fetch_data_word(destoffset);
3986 destval = (*opcD1_word_operation[rh]) (destval, amt);
3987 store_data_word(destoffset, destval);
3989 } else { /* register to register */
3990 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3993 destreg = DECODE_RM_LONG_REGISTER(rl);
3994 DECODE_PRINTF(",CL\n");
3996 *destreg = (*opcD1_long_operation[rh]) (*destreg, amt);
4000 destreg = DECODE_RM_WORD_REGISTER(rl);
4001 DECODE_PRINTF(",CL\n");
4003 *destreg = (*opcD1_word_operation[rh]) (*destreg, amt);
4006 DECODE_CLEAR_SEGOVR();
4010 /****************************************************************************
4013 ****************************************************************************/
4014 void x86emuOp_aam(u8 X86EMU_UNUSED(op1))
4019 DECODE_PRINTF("AAM\n");
4020 a = fetch_byte_imm(); /* this is a stupid encoding. */
4022 DECODE_PRINTF("ERROR DECODING AAM\n");
4027 /* note the type change here --- returning AL and AH in AX. */
4028 M.x86.R_AX = aam_word(M.x86.R_AL);
4029 DECODE_CLEAR_SEGOVR();
4033 /****************************************************************************
4036 ****************************************************************************/
4037 void x86emuOp_aad(u8 X86EMU_UNUSED(op1))
4042 DECODE_PRINTF("AAD\n");
4043 a = fetch_byte_imm();
4045 M.x86.R_AX = aad_word(M.x86.R_AX);
4046 DECODE_CLEAR_SEGOVR();
4050 /* opcode 0xd6 ILLEGAL OPCODE */
4052 /****************************************************************************
4055 ****************************************************************************/
4056 void x86emuOp_xlat(u8 X86EMU_UNUSED(op1))
4061 DECODE_PRINTF("XLAT\n");
4063 addr = (u16)(M.x86.R_BX + (u8)M.x86.R_AL);
4064 M.x86.R_AL = fetch_data_byte(addr);
4065 DECODE_CLEAR_SEGOVR();
4069 /* instuctions D8 .. DF are in i87_ops.c */
4071 /****************************************************************************
4074 ****************************************************************************/
4075 void x86emuOp_loopne(u8 X86EMU_UNUSED(op1))
4080 DECODE_PRINTF("LOOPNE\t");
4081 ip = (s8) fetch_byte_imm();
4082 ip += (s16) M.x86.R_IP;
4083 DECODE_PRINTF2("%04x\n", ip);
4085 if (M.x86.mode & SYSMODE_PREFIX_ADDR)
4089 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 */
4091 DECODE_CLEAR_SEGOVR();
4095 /****************************************************************************
4098 ****************************************************************************/
4099 void x86emuOp_loope(u8 X86EMU_UNUSED(op1))
4104 DECODE_PRINTF("LOOPE\t");
4105 ip = (s8) fetch_byte_imm();
4106 ip += (s16) M.x86.R_IP;
4107 DECODE_PRINTF2("%04x\n", ip);
4109 if (M.x86.mode & SYSMODE_PREFIX_ADDR)
4113 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 */
4115 DECODE_CLEAR_SEGOVR();
4119 /****************************************************************************
4122 ****************************************************************************/
4123 void x86emuOp_loop(u8 X86EMU_UNUSED(op1))
4128 DECODE_PRINTF("LOOP\t");
4129 ip = (s8) fetch_byte_imm();
4130 ip += (s16) M.x86.R_IP;
4131 DECODE_PRINTF2("%04x\n", ip);
4133 if (M.x86.mode & SYSMODE_PREFIX_ADDR)
4137 if (((M.x86.mode & SYSMODE_PREFIX_ADDR) ? M.x86.R_ECX : M.x86.R_CX) != 0) /* (E)CX != 0 */
4139 DECODE_CLEAR_SEGOVR();
4143 /****************************************************************************
4146 ****************************************************************************/
4147 void x86emuOp_jcxz(u8 X86EMU_UNUSED(op1))
4152 /* jump to byte offset if overflow flag is set */
4154 DECODE_PRINTF("JCXZ\t");
4155 offset = (s8)fetch_byte_imm();
4156 target = (u16)(M.x86.R_IP + offset);
4157 DECODE_PRINTF2("%x\n", target);
4159 if (M.x86.R_CX == 0) {
4160 M.x86.R_IP = target;
4161 JMP_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, M.x86.R_IP, " CXZ ");
4163 DECODE_CLEAR_SEGOVR();
4167 /****************************************************************************
4170 ****************************************************************************/
4171 void x86emuOp_in_byte_AL_IMM(u8 X86EMU_UNUSED(op1))
4176 DECODE_PRINTF("IN\t");
4177 port = (u8) fetch_byte_imm();
4178 DECODE_PRINTF2("%x,AL\n", port);
4180 M.x86.R_AL = (*sys_inb)(port);
4181 DECODE_CLEAR_SEGOVR();
4185 /****************************************************************************
4188 ****************************************************************************/
4189 void x86emuOp_in_word_AX_IMM(u8 X86EMU_UNUSED(op1))
4194 DECODE_PRINTF("IN\t");
4195 port = (u8) fetch_byte_imm();
4196 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4197 DECODE_PRINTF2("EAX,%x\n", port);
4199 DECODE_PRINTF2("AX,%x\n", port);
4202 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4203 M.x86.R_EAX = (*sys_inl)(port);
4205 M.x86.R_AX = (*sys_inw)(port);
4207 DECODE_CLEAR_SEGOVR();
4211 /****************************************************************************
4214 ****************************************************************************/
4215 void x86emuOp_out_byte_IMM_AL(u8 X86EMU_UNUSED(op1))
4220 DECODE_PRINTF("OUT\t");
4221 port = (u8) fetch_byte_imm();
4222 DECODE_PRINTF2("%x,AL\n", port);
4224 (*sys_outb)(port, M.x86.R_AL);
4225 DECODE_CLEAR_SEGOVR();
4229 /****************************************************************************
4232 ****************************************************************************/
4233 void x86emuOp_out_word_IMM_AX(u8 X86EMU_UNUSED(op1))
4238 DECODE_PRINTF("OUT\t");
4239 port = (u8) fetch_byte_imm();
4240 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4241 DECODE_PRINTF2("%x,EAX\n", port);
4243 DECODE_PRINTF2("%x,AX\n", port);
4246 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4247 (*sys_outl)(port, M.x86.R_EAX);
4249 (*sys_outw)(port, M.x86.R_AX);
4251 DECODE_CLEAR_SEGOVR();
4255 /****************************************************************************
4258 ****************************************************************************/
4259 void x86emuOp_call_near_IMM(u8 X86EMU_UNUSED(op1))
4264 DECODE_PRINTF("CALL\t");
4265 ip = (s16) fetch_word_imm();
4266 ip += (s16) M.x86.R_IP; /* CHECK SIGN */
4267 DECODE_PRINTF2("%04x\n", ip);
4268 CALL_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, ip, "");
4270 push_word(M.x86.R_IP);
4272 DECODE_CLEAR_SEGOVR();
4276 /****************************************************************************
4279 ****************************************************************************/
4280 void x86emuOp_jump_near_IMM(u8 X86EMU_UNUSED(op1))
4285 DECODE_PRINTF("JMP\t");
4286 ip = (s16)fetch_word_imm();
4287 ip += (s16)M.x86.R_IP;
4288 DECODE_PRINTF2("%04x\n", ip);
4289 JMP_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, ip, " NEAR ");
4291 M.x86.R_IP = (u16)ip;
4292 DECODE_CLEAR_SEGOVR();
4296 /****************************************************************************
4299 ****************************************************************************/
4300 void x86emuOp_jump_far_IMM(u8 X86EMU_UNUSED(op1))
4305 DECODE_PRINTF("JMP\tFAR ");
4306 ip = fetch_word_imm();
4307 cs = fetch_word_imm();
4308 DECODE_PRINTF2("%04x:", cs);
4309 DECODE_PRINTF2("%04x\n", ip);
4310 JMP_TRACE(M.x86.saved_cs, M.x86.saved_ip, cs, ip, " FAR ");
4314 DECODE_CLEAR_SEGOVR();
4318 /****************************************************************************
4321 ****************************************************************************/
4322 void x86emuOp_jump_byte_IMM(u8 X86EMU_UNUSED(op1))
4328 DECODE_PRINTF("JMP\t");
4329 offset = (s8)fetch_byte_imm();
4330 target = (u16)(M.x86.R_IP + offset);
4331 DECODE_PRINTF2("%x\n", target);
4332 JMP_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, target, " BYTE ");
4334 M.x86.R_IP = target;
4335 DECODE_CLEAR_SEGOVR();
4339 /****************************************************************************
4342 ****************************************************************************/
4343 void x86emuOp_in_byte_AL_DX(u8 X86EMU_UNUSED(op1))
4346 DECODE_PRINTF("IN\tAL,DX\n");
4348 M.x86.R_AL = (*sys_inb)(M.x86.R_DX);
4349 DECODE_CLEAR_SEGOVR();
4353 /****************************************************************************
4356 ****************************************************************************/
4357 void x86emuOp_in_word_AX_DX(u8 X86EMU_UNUSED(op1))
4360 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4361 DECODE_PRINTF("IN\tEAX,DX\n");
4363 DECODE_PRINTF("IN\tAX,DX\n");
4366 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4367 M.x86.R_EAX = (*sys_inl)(M.x86.R_DX);
4369 M.x86.R_AX = (*sys_inw)(M.x86.R_DX);
4371 DECODE_CLEAR_SEGOVR();
4375 /****************************************************************************
4378 ****************************************************************************/
4379 void x86emuOp_out_byte_DX_AL(u8 X86EMU_UNUSED(op1))
4382 DECODE_PRINTF("OUT\tDX,AL\n");
4384 (*sys_outb)(M.x86.R_DX, M.x86.R_AL);
4385 DECODE_CLEAR_SEGOVR();
4389 /****************************************************************************
4392 ****************************************************************************/
4393 void x86emuOp_out_word_DX_AX(u8 X86EMU_UNUSED(op1))
4396 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4397 DECODE_PRINTF("OUT\tDX,EAX\n");
4399 DECODE_PRINTF("OUT\tDX,AX\n");
4402 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4403 (*sys_outl)(M.x86.R_DX, M.x86.R_EAX);
4405 (*sys_outw)(M.x86.R_DX, M.x86.R_AX);
4407 DECODE_CLEAR_SEGOVR();
4411 /****************************************************************************
4414 ****************************************************************************/
4415 void x86emuOp_lock(u8 X86EMU_UNUSED(op1))
4418 DECODE_PRINTF("LOCK:\n");
4420 DECODE_CLEAR_SEGOVR();
4424 /*opcode 0xf1 ILLEGAL OPERATION */
4426 /****************************************************************************
4429 ****************************************************************************/
4430 void x86emuOp_repne(u8 X86EMU_UNUSED(op1))
4433 DECODE_PRINTF("REPNE\n");
4435 M.x86.mode |= SYSMODE_PREFIX_REPNE;
4436 if (M.x86.mode & SYSMODE_PREFIX_ADDR)
4437 M.x86.mode |= SYSMODE_32BIT_REP;
4438 DECODE_CLEAR_SEGOVR();
4442 /****************************************************************************
4445 ****************************************************************************/
4446 void x86emuOp_repe(u8 X86EMU_UNUSED(op1))
4449 DECODE_PRINTF("REPE\n");
4451 M.x86.mode |= SYSMODE_PREFIX_REPE;
4452 if (M.x86.mode & SYSMODE_PREFIX_ADDR)
4453 M.x86.mode |= SYSMODE_32BIT_REP;
4454 DECODE_CLEAR_SEGOVR();
4458 /****************************************************************************
4461 ****************************************************************************/
4462 void x86emuOp_halt(u8 X86EMU_UNUSED(op1))
4465 DECODE_PRINTF("HALT\n");
4468 DECODE_CLEAR_SEGOVR();
4472 /****************************************************************************
4475 ****************************************************************************/
4476 void x86emuOp_cmc(u8 X86EMU_UNUSED(op1))
4478 /* complement the carry flag. */
4480 DECODE_PRINTF("CMC\n");
4483 DECODE_CLEAR_SEGOVR();
4487 /****************************************************************************
4490 ****************************************************************************/
4491 void x86emuOp_opcF6_byte_RM(u8 X86EMU_UNUSED(op1))
4498 /* long, drawn out code follows. Double switch for a total
4501 FETCH_DECODE_MODRM(mod, rh, rl);
4502 DECODE_PRINTF(opF6_names[rh]);
4504 DECODE_PRINTF("BYTE PTR ");
4505 destoffset = decode_rmXX_address(mod, rl);
4506 destval = fetch_data_byte(destoffset);
4509 case 0: /* test byte imm */
4511 srcval = fetch_byte_imm();
4512 DECODE_PRINTF2("%02x\n", srcval);
4514 test_byte(destval, srcval);
4517 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4521 DECODE_PRINTF("\n");
4523 destval = not_byte(destval);
4524 store_data_byte(destoffset, destval);
4527 DECODE_PRINTF("\n");
4529 destval = neg_byte(destval);
4530 store_data_byte(destoffset, destval);
4533 DECODE_PRINTF("\n");
4538 DECODE_PRINTF("\n");
4543 DECODE_PRINTF("\n");
4548 DECODE_PRINTF("\n");
4553 } else { /* mod=11 */
4554 destreg = DECODE_RM_BYTE_REGISTER(rl);
4556 case 0: /* test byte imm */
4558 srcval = fetch_byte_imm();
4559 DECODE_PRINTF2("%02x\n", srcval);
4561 test_byte(*destreg, srcval);
4564 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4568 DECODE_PRINTF("\n");
4570 *destreg = not_byte(*destreg);
4573 DECODE_PRINTF("\n");
4575 *destreg = neg_byte(*destreg);
4578 DECODE_PRINTF("\n");
4580 mul_byte(*destreg); /*!!! */
4583 DECODE_PRINTF("\n");
4585 imul_byte(*destreg);
4588 DECODE_PRINTF("\n");
4593 DECODE_PRINTF("\n");
4595 idiv_byte(*destreg);
4599 DECODE_CLEAR_SEGOVR();
4603 /****************************************************************************
4606 ****************************************************************************/
4607 void x86emuOp_opcF7_word_RM(u8 X86EMU_UNUSED(op1))
4613 FETCH_DECODE_MODRM(mod, rh, rl);
4614 DECODE_PRINTF(opF6_names[rh]);
4617 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4618 u32 destval, srcval;
4620 DECODE_PRINTF("DWORD PTR ");
4621 destoffset = decode_rmXX_address(mod, rl);
4622 destval = fetch_data_long(destoffset);
4627 srcval = fetch_long_imm();
4628 DECODE_PRINTF2("%x\n", srcval);
4630 test_long(destval, srcval);
4633 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F7\n");
4637 DECODE_PRINTF("\n");
4639 destval = not_long(destval);
4640 store_data_long(destoffset, destval);
4643 DECODE_PRINTF("\n");
4645 destval = neg_long(destval);
4646 store_data_long(destoffset, destval);
4649 DECODE_PRINTF("\n");
4654 DECODE_PRINTF("\n");
4659 DECODE_PRINTF("\n");
4664 DECODE_PRINTF("\n");
4670 u16 destval, srcval;
4672 DECODE_PRINTF("WORD PTR ");
4673 destoffset = decode_rmXX_address(mod, rl);
4674 destval = fetch_data_word(destoffset);
4677 case 0: /* test word imm */
4679 srcval = fetch_word_imm();
4680 DECODE_PRINTF2("%x\n", srcval);
4682 test_word(destval, srcval);
4685 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F7\n");
4689 DECODE_PRINTF("\n");
4691 destval = not_word(destval);
4692 store_data_word(destoffset, destval);
4695 DECODE_PRINTF("\n");
4697 destval = neg_word(destval);
4698 store_data_word(destoffset, destval);
4701 DECODE_PRINTF("\n");
4706 DECODE_PRINTF("\n");
4711 DECODE_PRINTF("\n");
4716 DECODE_PRINTF("\n");
4723 } else { /* mod=11 */
4725 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4729 destreg = DECODE_RM_LONG_REGISTER(rl);
4732 case 0: /* test word imm */
4734 srcval = fetch_long_imm();
4735 DECODE_PRINTF2("%x\n", srcval);
4737 test_long(*destreg, srcval);
4740 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4744 DECODE_PRINTF("\n");
4746 *destreg = not_long(*destreg);
4749 DECODE_PRINTF("\n");
4751 *destreg = neg_long(*destreg);
4754 DECODE_PRINTF("\n");
4756 mul_long(*destreg); /*!!! */
4759 DECODE_PRINTF("\n");
4761 imul_long(*destreg);
4764 DECODE_PRINTF("\n");
4769 DECODE_PRINTF("\n");
4771 idiv_long(*destreg);
4778 destreg = DECODE_RM_WORD_REGISTER(rl);
4781 case 0: /* test word imm */
4783 srcval = fetch_word_imm();
4784 DECODE_PRINTF2("%x\n", srcval);
4786 test_word(*destreg, srcval);
4789 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4793 DECODE_PRINTF("\n");
4795 *destreg = not_word(*destreg);
4798 DECODE_PRINTF("\n");
4800 *destreg = neg_word(*destreg);
4803 DECODE_PRINTF("\n");
4805 mul_word(*destreg); /*!!! */
4808 DECODE_PRINTF("\n");
4810 imul_word(*destreg);
4813 DECODE_PRINTF("\n");
4818 DECODE_PRINTF("\n");
4820 idiv_word(*destreg);
4825 DECODE_CLEAR_SEGOVR();
4829 /****************************************************************************
4832 ****************************************************************************/
4833 void x86emuOp_clc(u8 X86EMU_UNUSED(op1))
4835 /* clear the carry flag. */
4837 DECODE_PRINTF("CLC\n");
4840 DECODE_CLEAR_SEGOVR();
4844 /****************************************************************************
4847 ****************************************************************************/
4848 void x86emuOp_stc(u8 X86EMU_UNUSED(op1))
4850 /* set the carry flag. */
4852 DECODE_PRINTF("STC\n");
4855 DECODE_CLEAR_SEGOVR();
4859 /****************************************************************************
4862 ****************************************************************************/
4863 void x86emuOp_cli(u8 X86EMU_UNUSED(op1))
4865 /* clear interrupts. */
4867 DECODE_PRINTF("CLI\n");
4870 DECODE_CLEAR_SEGOVR();
4874 /****************************************************************************
4877 ****************************************************************************/
4878 void x86emuOp_sti(u8 X86EMU_UNUSED(op1))
4880 /* enable interrupts. */
4882 DECODE_PRINTF("STI\n");
4885 DECODE_CLEAR_SEGOVR();
4889 /****************************************************************************
4892 ****************************************************************************/
4893 void x86emuOp_cld(u8 X86EMU_UNUSED(op1))
4895 /* clear interrupts. */
4897 DECODE_PRINTF("CLD\n");
4900 DECODE_CLEAR_SEGOVR();
4904 /****************************************************************************
4907 ****************************************************************************/
4908 void x86emuOp_std(u8 X86EMU_UNUSED(op1))
4910 /* clear interrupts. */
4912 DECODE_PRINTF("STD\n");
4915 DECODE_CLEAR_SEGOVR();
4919 /****************************************************************************
4922 ****************************************************************************/
4923 void x86emuOp_opcFE_byte_RM(u8 X86EMU_UNUSED(op1))
4930 /* Yet another special case instruction. */
4932 FETCH_DECODE_MODRM(mod, rh, rl);
4934 if (DEBUG_DECODE()) {
4935 /* XXX DECODE_PRINTF may be changed to something more
4936 general, so that it is important to leave the strings
4937 in the same format, even though the result is that the
4938 above test is done twice. */
4942 DECODE_PRINTF("INC\t");
4945 DECODE_PRINTF("DEC\t");
4953 DECODE_PRINTF2("ILLEGAL OP MAJOR OP 0xFE MINOR OP %x \n", mod);
4960 DECODE_PRINTF("BYTE PTR ");
4961 destoffset = decode_rmXX_address(mod, rl);
4962 DECODE_PRINTF("\n");
4963 destval = fetch_data_byte(destoffset);
4966 destval = inc_byte(destval);
4968 destval = dec_byte(destval);
4969 store_data_byte(destoffset, destval);
4971 destreg = DECODE_RM_BYTE_REGISTER(rl);
4972 DECODE_PRINTF("\n");
4975 *destreg = inc_byte(*destreg);
4977 *destreg = dec_byte(*destreg);
4979 DECODE_CLEAR_SEGOVR();
4983 /****************************************************************************
4986 ****************************************************************************/
4987 void x86emuOp_opcFF_word_RM(u8 X86EMU_UNUSED(op1))
4990 uint destoffset = 0;
4992 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) {
5049 destval = fetch_data_long(destoffset);
5051 destval = inc_long(destval);
5052 store_data_long(destoffset, destval);
5056 destval = fetch_data_word(destoffset);
5058 destval = inc_word(destval);
5059 store_data_word(destoffset, destval);
5062 case 1: /* dec word ptr ... */
5063 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5066 destval = fetch_data_long(destoffset);
5068 destval = dec_long(destval);
5069 store_data_long(destoffset, destval);
5073 destval = fetch_data_word(destoffset);
5075 destval = dec_word(destval);
5076 store_data_word(destoffset, destval);
5079 case 2: /* call word ptr ... */
5080 destval = fetch_data_word(destoffset);
5082 push_word(M.x86.R_IP);
5083 M.x86.R_IP = destval;
5085 case 3: /* call far ptr ... */
5086 destval = fetch_data_word(destoffset);
5087 destval2 = fetch_data_word(destoffset + 2);
5089 push_word(M.x86.R_CS);
5090 M.x86.R_CS = destval2;
5091 push_word(M.x86.R_IP);
5092 M.x86.R_IP = destval;
5094 case 4: /* jmp word ptr ... */
5095 destval = fetch_data_word(destoffset);
5096 JMP_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, destval, " WORD ");
5098 M.x86.R_IP = destval;
5100 case 5: /* jmp far ptr ... */
5101 destval = fetch_data_word(destoffset);
5102 destval2 = fetch_data_word(destoffset + 2);
5103 JMP_TRACE(M.x86.saved_cs, M.x86.saved_ip, destval2, destval, " FAR ");
5105 M.x86.R_IP = destval;
5106 M.x86.R_CS = destval2;
5108 case 6: /* push word ptr ... */
5109 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5112 destval = fetch_data_long(destoffset);
5118 destval = fetch_data_word(destoffset);
5127 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5130 destreg = DECODE_RM_LONG_REGISTER(rl);
5131 DECODE_PRINTF("\n");
5133 *destreg = inc_long(*destreg);
5137 destreg = DECODE_RM_WORD_REGISTER(rl);
5138 DECODE_PRINTF("\n");
5140 *destreg = inc_word(*destreg);
5144 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5147 destreg = DECODE_RM_LONG_REGISTER(rl);
5148 DECODE_PRINTF("\n");
5150 *destreg = dec_long(*destreg);
5154 destreg = DECODE_RM_WORD_REGISTER(rl);
5155 DECODE_PRINTF("\n");
5157 *destreg = dec_word(*destreg);
5160 case 2: /* call word ptr ... */
5161 destreg = DECODE_RM_WORD_REGISTER(rl);
5162 DECODE_PRINTF("\n");
5164 push_word(M.x86.R_IP);
5165 M.x86.R_IP = *destreg;
5167 case 3: /* jmp far ptr ... */
5168 DECODE_PRINTF("OPERATION UNDEFINED 0XFF \n");
5173 case 4: /* jmp ... */
5174 destreg = DECODE_RM_WORD_REGISTER(rl);
5175 DECODE_PRINTF("\n");
5177 M.x86.R_IP = (u16) (*destreg);
5179 case 5: /* jmp far ptr ... */
5180 DECODE_PRINTF("OPERATION UNDEFINED 0XFF \n");
5185 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5188 destreg = DECODE_RM_LONG_REGISTER(rl);
5189 DECODE_PRINTF("\n");
5191 push_long(*destreg);
5195 destreg = DECODE_RM_WORD_REGISTER(rl);
5196 DECODE_PRINTF("\n");
5198 push_word(*destreg);
5203 DECODE_CLEAR_SEGOVR();
5207 /***************************************************************************
5208 * Single byte operation code table:
5209 **************************************************************************/
5210 void (*x86emu_optab[256])(u8) =
5212 /* 0x00 */ x86emuOp_genop_byte_RM_R,
5213 /* 0x01 */ x86emuOp_genop_word_RM_R,
5214 /* 0x02 */ x86emuOp_genop_byte_R_RM,
5215 /* 0x03 */ x86emuOp_genop_word_R_RM,
5216 /* 0x04 */ x86emuOp_genop_byte_AL_IMM,
5217 /* 0x05 */ x86emuOp_genop_word_AX_IMM,
5218 /* 0x06 */ x86emuOp_push_ES,
5219 /* 0x07 */ x86emuOp_pop_ES,
5221 /* 0x08 */ x86emuOp_genop_byte_RM_R,
5222 /* 0x09 */ x86emuOp_genop_word_RM_R,
5223 /* 0x0a */ x86emuOp_genop_byte_R_RM,
5224 /* 0x0b */ x86emuOp_genop_word_R_RM,
5225 /* 0x0c */ x86emuOp_genop_byte_AL_IMM,
5226 /* 0x0d */ x86emuOp_genop_word_AX_IMM,
5227 /* 0x0e */ x86emuOp_push_CS,
5228 /* 0x0f */ x86emuOp_two_byte,
5230 /* 0x10 */ x86emuOp_genop_byte_RM_R,
5231 /* 0x11 */ x86emuOp_genop_word_RM_R,
5232 /* 0x12 */ x86emuOp_genop_byte_R_RM,
5233 /* 0x13 */ x86emuOp_genop_word_R_RM,
5234 /* 0x14 */ x86emuOp_genop_byte_AL_IMM,
5235 /* 0x15 */ x86emuOp_genop_word_AX_IMM,
5236 /* 0x16 */ x86emuOp_push_SS,
5237 /* 0x17 */ x86emuOp_pop_SS,
5239 /* 0x18 */ x86emuOp_genop_byte_RM_R,
5240 /* 0x19 */ x86emuOp_genop_word_RM_R,
5241 /* 0x1a */ x86emuOp_genop_byte_R_RM,
5242 /* 0x1b */ x86emuOp_genop_word_R_RM,
5243 /* 0x1c */ x86emuOp_genop_byte_AL_IMM,
5244 /* 0x1d */ x86emuOp_genop_word_AX_IMM,
5245 /* 0x1e */ x86emuOp_push_DS,
5246 /* 0x1f */ x86emuOp_pop_DS,
5248 /* 0x20 */ x86emuOp_genop_byte_RM_R,
5249 /* 0x21 */ x86emuOp_genop_word_RM_R,
5250 /* 0x22 */ x86emuOp_genop_byte_R_RM,
5251 /* 0x23 */ x86emuOp_genop_word_R_RM,
5252 /* 0x24 */ x86emuOp_genop_byte_AL_IMM,
5253 /* 0x25 */ x86emuOp_genop_word_AX_IMM,
5254 /* 0x26 */ x86emuOp_segovr_ES,
5255 /* 0x27 */ x86emuOp_daa,
5257 /* 0x28 */ x86emuOp_genop_byte_RM_R,
5258 /* 0x29 */ x86emuOp_genop_word_RM_R,
5259 /* 0x2a */ x86emuOp_genop_byte_R_RM,
5260 /* 0x2b */ x86emuOp_genop_word_R_RM,
5261 /* 0x2c */ x86emuOp_genop_byte_AL_IMM,
5262 /* 0x2d */ x86emuOp_genop_word_AX_IMM,
5263 /* 0x2e */ x86emuOp_segovr_CS,
5264 /* 0x2f */ x86emuOp_das,
5266 /* 0x30 */ x86emuOp_genop_byte_RM_R,
5267 /* 0x31 */ x86emuOp_genop_word_RM_R,
5268 /* 0x32 */ x86emuOp_genop_byte_R_RM,
5269 /* 0x33 */ x86emuOp_genop_word_R_RM,
5270 /* 0x34 */ x86emuOp_genop_byte_AL_IMM,
5271 /* 0x35 */ x86emuOp_genop_word_AX_IMM,
5272 /* 0x36 */ x86emuOp_segovr_SS,
5273 /* 0x37 */ x86emuOp_aaa,
5275 /* 0x38 */ x86emuOp_genop_byte_RM_R,
5276 /* 0x39 */ x86emuOp_genop_word_RM_R,
5277 /* 0x3a */ x86emuOp_genop_byte_R_RM,
5278 /* 0x3b */ x86emuOp_genop_word_R_RM,
5279 /* 0x3c */ x86emuOp_genop_byte_AL_IMM,
5280 /* 0x3d */ x86emuOp_genop_word_AX_IMM,
5281 /* 0x3e */ x86emuOp_segovr_DS,
5282 /* 0x3f */ x86emuOp_aas,
5284 /* 0x40 */ x86emuOp_inc_register,
5285 /* 0x41 */ x86emuOp_inc_register,
5286 /* 0x42 */ x86emuOp_inc_register,
5287 /* 0x43 */ x86emuOp_inc_register,
5288 /* 0x44 */ x86emuOp_inc_register,
5289 /* 0x45 */ x86emuOp_inc_register,
5290 /* 0x46 */ x86emuOp_inc_register,
5291 /* 0x47 */ x86emuOp_inc_register,
5293 /* 0x48 */ x86emuOp_dec_register,
5294 /* 0x49 */ x86emuOp_dec_register,
5295 /* 0x4a */ x86emuOp_dec_register,
5296 /* 0x4b */ x86emuOp_dec_register,
5297 /* 0x4c */ x86emuOp_dec_register,
5298 /* 0x4d */ x86emuOp_dec_register,
5299 /* 0x4e */ x86emuOp_dec_register,
5300 /* 0x4f */ x86emuOp_dec_register,
5302 /* 0x50 */ x86emuOp_push_register,
5303 /* 0x51 */ x86emuOp_push_register,
5304 /* 0x52 */ x86emuOp_push_register,
5305 /* 0x53 */ x86emuOp_push_register,
5306 /* 0x54 */ x86emuOp_push_register,
5307 /* 0x55 */ x86emuOp_push_register,
5308 /* 0x56 */ x86emuOp_push_register,
5309 /* 0x57 */ x86emuOp_push_register,
5311 /* 0x58 */ x86emuOp_pop_register,
5312 /* 0x59 */ x86emuOp_pop_register,
5313 /* 0x5a */ x86emuOp_pop_register,
5314 /* 0x5b */ x86emuOp_pop_register,
5315 /* 0x5c */ x86emuOp_pop_register,
5316 /* 0x5d */ x86emuOp_pop_register,
5317 /* 0x5e */ x86emuOp_pop_register,
5318 /* 0x5f */ x86emuOp_pop_register,
5320 /* 0x60 */ x86emuOp_push_all,
5321 /* 0x61 */ x86emuOp_pop_all,
5322 /* 0x62 */ x86emuOp_illegal_op, /* bound */
5323 /* 0x63 */ x86emuOp_illegal_op, /* arpl */
5324 /* 0x64 */ x86emuOp_segovr_FS,
5325 /* 0x65 */ x86emuOp_segovr_GS,
5326 /* 0x66 */ x86emuOp_prefix_data,
5327 /* 0x67 */ x86emuOp_prefix_addr,
5329 /* 0x68 */ x86emuOp_push_word_IMM,
5330 /* 0x69 */ x86emuOp_imul_word_IMM,
5331 /* 0x6a */ x86emuOp_push_byte_IMM,
5332 /* 0x6b */ x86emuOp_imul_byte_IMM,
5333 /* 0x6c */ x86emuOp_ins_byte,
5334 /* 0x6d */ x86emuOp_ins_word,
5335 /* 0x6e */ x86emuOp_outs_byte,
5336 /* 0x6f */ x86emuOp_outs_word,
5338 /* 0x70 */ x86emuOp_jump_near_cond,
5339 /* 0x71 */ x86emuOp_jump_near_cond,
5340 /* 0x72 */ x86emuOp_jump_near_cond,
5341 /* 0x73 */ x86emuOp_jump_near_cond,
5342 /* 0x74 */ x86emuOp_jump_near_cond,
5343 /* 0x75 */ x86emuOp_jump_near_cond,
5344 /* 0x76 */ x86emuOp_jump_near_cond,
5345 /* 0x77 */ x86emuOp_jump_near_cond,
5347 /* 0x78 */ x86emuOp_jump_near_cond,
5348 /* 0x79 */ x86emuOp_jump_near_cond,
5349 /* 0x7a */ x86emuOp_jump_near_cond,
5350 /* 0x7b */ x86emuOp_jump_near_cond,
5351 /* 0x7c */ x86emuOp_jump_near_cond,
5352 /* 0x7d */ x86emuOp_jump_near_cond,
5353 /* 0x7e */ x86emuOp_jump_near_cond,
5354 /* 0x7f */ x86emuOp_jump_near_cond,
5356 /* 0x80 */ x86emuOp_opc80_byte_RM_IMM,
5357 /* 0x81 */ x86emuOp_opc81_word_RM_IMM,
5358 /* 0x82 */ x86emuOp_opc82_byte_RM_IMM,
5359 /* 0x83 */ x86emuOp_opc83_word_RM_IMM,
5360 /* 0x84 */ x86emuOp_test_byte_RM_R,
5361 /* 0x85 */ x86emuOp_test_word_RM_R,
5362 /* 0x86 */ x86emuOp_xchg_byte_RM_R,
5363 /* 0x87 */ x86emuOp_xchg_word_RM_R,
5365 /* 0x88 */ x86emuOp_mov_byte_RM_R,
5366 /* 0x89 */ x86emuOp_mov_word_RM_R,
5367 /* 0x8a */ x86emuOp_mov_byte_R_RM,
5368 /* 0x8b */ x86emuOp_mov_word_R_RM,
5369 /* 0x8c */ x86emuOp_mov_word_RM_SR,
5370 /* 0x8d */ x86emuOp_lea_word_R_M,
5371 /* 0x8e */ x86emuOp_mov_word_SR_RM,
5372 /* 0x8f */ x86emuOp_pop_RM,
5374 /* 0x90 */ x86emuOp_nop,
5375 /* 0x91 */ x86emuOp_xchg_word_AX_register,
5376 /* 0x92 */ x86emuOp_xchg_word_AX_register,
5377 /* 0x93 */ x86emuOp_xchg_word_AX_register,
5378 /* 0x94 */ x86emuOp_xchg_word_AX_register,
5379 /* 0x95 */ x86emuOp_xchg_word_AX_register,
5380 /* 0x96 */ x86emuOp_xchg_word_AX_register,
5381 /* 0x97 */ x86emuOp_xchg_word_AX_register,
5383 /* 0x98 */ x86emuOp_cbw,
5384 /* 0x99 */ x86emuOp_cwd,
5385 /* 0x9a */ x86emuOp_call_far_IMM,
5386 /* 0x9b */ x86emuOp_wait,
5387 /* 0x9c */ x86emuOp_pushf_word,
5388 /* 0x9d */ x86emuOp_popf_word,
5389 /* 0x9e */ x86emuOp_sahf,
5390 /* 0x9f */ x86emuOp_lahf,
5392 /* 0xa0 */ x86emuOp_mov_AL_M_IMM,
5393 /* 0xa1 */ x86emuOp_mov_AX_M_IMM,
5394 /* 0xa2 */ x86emuOp_mov_M_AL_IMM,
5395 /* 0xa3 */ x86emuOp_mov_M_AX_IMM,
5396 /* 0xa4 */ x86emuOp_movs_byte,
5397 /* 0xa5 */ x86emuOp_movs_word,
5398 /* 0xa6 */ x86emuOp_cmps_byte,
5399 /* 0xa7 */ x86emuOp_cmps_word,
5400 /* 0xa8 */ x86emuOp_test_AL_IMM,
5401 /* 0xa9 */ x86emuOp_test_AX_IMM,
5402 /* 0xaa */ x86emuOp_stos_byte,
5403 /* 0xab */ x86emuOp_stos_word,
5404 /* 0xac */ x86emuOp_lods_byte,
5405 /* 0xad */ x86emuOp_lods_word,
5406 /* 0xac */ x86emuOp_scas_byte,
5407 /* 0xad */ x86emuOp_scas_word,
5409 /* 0xb0 */ x86emuOp_mov_byte_register_IMM,
5410 /* 0xb1 */ x86emuOp_mov_byte_register_IMM,
5411 /* 0xb2 */ x86emuOp_mov_byte_register_IMM,
5412 /* 0xb3 */ x86emuOp_mov_byte_register_IMM,
5413 /* 0xb4 */ x86emuOp_mov_byte_register_IMM,
5414 /* 0xb5 */ x86emuOp_mov_byte_register_IMM,
5415 /* 0xb6 */ x86emuOp_mov_byte_register_IMM,
5416 /* 0xb7 */ x86emuOp_mov_byte_register_IMM,
5418 /* 0xb8 */ x86emuOp_mov_word_register_IMM,
5419 /* 0xb9 */ x86emuOp_mov_word_register_IMM,
5420 /* 0xba */ x86emuOp_mov_word_register_IMM,
5421 /* 0xbb */ x86emuOp_mov_word_register_IMM,
5422 /* 0xbc */ x86emuOp_mov_word_register_IMM,
5423 /* 0xbd */ x86emuOp_mov_word_register_IMM,
5424 /* 0xbe */ x86emuOp_mov_word_register_IMM,
5425 /* 0xbf */ x86emuOp_mov_word_register_IMM,
5427 /* 0xc0 */ x86emuOp_opcC0_byte_RM_MEM,
5428 /* 0xc1 */ x86emuOp_opcC1_word_RM_MEM,
5429 /* 0xc2 */ x86emuOp_ret_near_IMM,
5430 /* 0xc3 */ x86emuOp_ret_near,
5431 /* 0xc4 */ x86emuOp_les_R_IMM,
5432 /* 0xc5 */ x86emuOp_lds_R_IMM,
5433 /* 0xc6 */ x86emuOp_mov_byte_RM_IMM,
5434 /* 0xc7 */ x86emuOp_mov_word_RM_IMM,
5435 /* 0xc8 */ x86emuOp_enter,
5436 /* 0xc9 */ x86emuOp_leave,
5437 /* 0xca */ x86emuOp_ret_far_IMM,
5438 /* 0xcb */ x86emuOp_ret_far,
5439 /* 0xcc */ x86emuOp_int3,
5440 /* 0xcd */ x86emuOp_int_IMM,
5441 /* 0xce */ x86emuOp_into,
5442 /* 0xcf */ x86emuOp_iret,
5444 /* 0xd0 */ x86emuOp_opcD0_byte_RM_1,
5445 /* 0xd1 */ x86emuOp_opcD1_word_RM_1,
5446 /* 0xd2 */ x86emuOp_opcD2_byte_RM_CL,
5447 /* 0xd3 */ x86emuOp_opcD3_word_RM_CL,
5448 /* 0xd4 */ x86emuOp_aam,
5449 /* 0xd5 */ x86emuOp_aad,
5450 /* 0xd6 */ x86emuOp_illegal_op, /* Undocumented SETALC instruction */
5451 /* 0xd7 */ x86emuOp_xlat,
5452 /* 0xd8 */ x86emuOp_esc_coprocess_d8,
5453 /* 0xd9 */ x86emuOp_esc_coprocess_d9,
5454 /* 0xda */ x86emuOp_esc_coprocess_da,
5455 /* 0xdb */ x86emuOp_esc_coprocess_db,
5456 /* 0xdc */ x86emuOp_esc_coprocess_dc,
5457 /* 0xdd */ x86emuOp_esc_coprocess_dd,
5458 /* 0xde */ x86emuOp_esc_coprocess_de,
5459 /* 0xdf */ x86emuOp_esc_coprocess_df,
5461 /* 0xe0 */ x86emuOp_loopne,
5462 /* 0xe1 */ x86emuOp_loope,
5463 /* 0xe2 */ x86emuOp_loop,
5464 /* 0xe3 */ x86emuOp_jcxz,
5465 /* 0xe4 */ x86emuOp_in_byte_AL_IMM,
5466 /* 0xe5 */ x86emuOp_in_word_AX_IMM,
5467 /* 0xe6 */ x86emuOp_out_byte_IMM_AL,
5468 /* 0xe7 */ x86emuOp_out_word_IMM_AX,
5470 /* 0xe8 */ x86emuOp_call_near_IMM,
5471 /* 0xe9 */ x86emuOp_jump_near_IMM,
5472 /* 0xea */ x86emuOp_jump_far_IMM,
5473 /* 0xeb */ x86emuOp_jump_byte_IMM,
5474 /* 0xec */ x86emuOp_in_byte_AL_DX,
5475 /* 0xed */ x86emuOp_in_word_AX_DX,
5476 /* 0xee */ x86emuOp_out_byte_DX_AL,
5477 /* 0xef */ x86emuOp_out_word_DX_AX,
5479 /* 0xf0 */ x86emuOp_lock,
5480 /* 0xf1 */ x86emuOp_illegal_op,
5481 /* 0xf2 */ x86emuOp_repne,
5482 /* 0xf3 */ x86emuOp_repe,
5483 /* 0xf4 */ x86emuOp_halt,
5484 /* 0xf5 */ x86emuOp_cmc,
5485 /* 0xf6 */ x86emuOp_opcF6_byte_RM,
5486 /* 0xf7 */ x86emuOp_opcF7_word_RM,
5488 /* 0xf8 */ x86emuOp_clc,
5489 /* 0xf9 */ x86emuOp_stc,
5490 /* 0xfa */ x86emuOp_cli,
5491 /* 0xfb */ x86emuOp_sti,
5492 /* 0xfc */ x86emuOp_cld,
5493 /* 0xfd */ x86emuOp_std,
5494 /* 0xfe */ x86emuOp_opcFE_byte_RM,
5495 /* 0xff */ x86emuOp_opcFF_word_RM,