1 /****************************************************************************
3 * Realmode X86 Emulator Library
5 * Copyright (C) 1991-2004 SciTech Software, Inc.
6 * Copyright (C) David Mosberger-Tang
7 * Copyright (C) 1999 Egbert Eich
9 * ========================================================================
11 * Permission to use, copy, modify, distribute, and sell this software and
12 * its documentation for any purpose is hereby granted without fee,
13 * provided that the above copyright notice appear in all copies and that
14 * both that copyright notice and this permission notice appear in
15 * supporting documentation, and that the name of the authors not be used
16 * in advertising or publicity pertaining to distribution of the software
17 * without specific, written prior permission. The authors makes no
18 * representations about the suitability of this software for any purpose.
19 * It is provided "as is" without express or implied warranty.
21 * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
22 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
23 * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
24 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
25 * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
26 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
27 * PERFORMANCE OF THIS SOFTWARE.
29 * ========================================================================
33 * Developer: Kendall Bennett
35 * Description: This file includes subroutines to implement the decoding
36 * and emulation of all the x86 processor instructions.
38 * There are approximately 250 subroutines in here, which correspond
39 * to the 256 byte-"opcodes" found on the 8086. The table which
40 * dispatches this is found in the files optab.[ch].
42 * Each opcode proc has a comment preceeding it which gives it's table
43 * address. Several opcodes are missing (undefined) in the table.
45 * Each proc includes information for decoding (DECODE_PRINTF and
46 * DECODE_PRINTF2), debugging (TRACE_REGS, SINGLE_STEP), and misc
47 * functions (START_OF_INSTR, END_OF_INSTR).
49 * Many of the procedures are *VERY* similar in coding. This has
50 * allowed for a very large amount of code to be generated in a fairly
51 * short amount of time (i.e. cut, paste, and modify). The result is
52 * that much of the code below could have been folded into subroutines
53 * for a large reduction in size of this file. The downside would be
54 * that there would be a penalty in execution speed. The file could
55 * also have been *MUCH* larger by inlining certain functions which
56 * were called. This could have resulted even faster execution. The
57 * prime directive I used to decide whether to inline the code or to
58 * modularize it, was basically: 1) no unnecessary subroutine calls,
59 * 2) no routines more than about 200 lines in size, and 3) modularize
60 * any code that I might not get right the first time. The fetch_*
61 * subroutines fall into the latter category. The The decode_* fall
62 * into the second category. The coding of the "switch(mod){ .... }"
63 * in many of the subroutines below falls into the first category.
64 * Especially, the coding of {add,and,or,sub,...}_{byte,word}
65 * subroutines are an especially glaring case of the third guideline.
66 * Since so much of the code is cloned from other modules (compare
67 * opcode #00 to opcode #01), making the basic operations subroutine
68 * calls is especially important; otherwise mistakes in coding an
69 * "add" would represent a nightmare in maintenance.
71 ****************************************************************************/
73 #include "x86emu/x86emui.h"
75 /*----------------------------- Implementation ----------------------------*/
77 /* constant arrays to do several instructions in just one function */
80 static char *x86emu_GenOpName[8] = {
81 "ADD", "OR", "ADC", "SBB", "AND", "SUB", "XOR", "CMP"};
84 /* used by several opcodes */
85 static u8 (*genop_byte_operation[])(u8 d, u8 s) =
97 static u16 (*genop_word_operation[])(u16 d, u16 s) =
109 static u32 (*genop_long_operation[])(u32 d, u32 s) =
121 /* used by opcodes 80, c0, d0, and d2. */
122 static u8(*opcD0_byte_operation[])(u8 d, u8 s) =
130 shl_byte, /* sal_byte === shl_byte by definition */
134 /* used by opcodes c1, d1, and d3. */
135 static u16(*opcD1_word_operation[])(u16 s, u8 d) =
143 shl_word, /* sal_byte === shl_byte by definition */
147 /* used by opcodes c1, d1, and d3. */
148 static u32 (*opcD1_long_operation[])(u32 s, u8 d) =
156 shl_long, /* sal_byte === shl_byte by definition */
162 static char *opF6_names[8] =
163 { "TEST\t", "", "NOT\t", "NEG\t", "MUL\t", "IMUL\t", "DIV\t", "IDIV\t" };
167 /****************************************************************************
169 op1 - Instruction op code
172 Handles illegal opcodes.
173 ****************************************************************************/
174 void x86emuOp_illegal_op(
178 if (M.x86.R_SP != 0) {
179 DECODE_PRINTF("ILLEGAL X86 OPCODE\n");
181 DB( printk("%04x:%04x: %02X ILLEGAL X86 OPCODE!\n",
182 M.x86.R_CS, M.x86.R_IP-1,op1));
186 /* If we get here, it means the stack pointer is back to zero
187 * so we are just returning from an emulator service call
188 * so therte is no need to display an error message. We trap
189 * the emulator with an 0xF1 opcode to finish the service
197 /****************************************************************************
199 Handles opcodes 0x00, 0x08, 0x10, 0x18, 0x20, 0x28, 0x30, 0x38
200 ****************************************************************************/
201 void x86emuOp_genop_byte_RM_R(u8 op1)
205 u8 *destreg, *srcreg;
208 op1 = (op1 >> 3) & 0x7;
211 DECODE_PRINTF(x86emu_GenOpName[op1]);
213 FETCH_DECODE_MODRM(mod, rh, rl);
215 { destoffset = decode_rmXX_address(mod,rl);
217 destval = fetch_data_byte(destoffset);
218 srcreg = DECODE_RM_BYTE_REGISTER(rh);
221 destval = genop_byte_operation[op1](destval, *srcreg);
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);
1065 DECODE_CLEAR_SEGOVR();
1069 /****************************************************************************
1072 ****************************************************************************/
1073 void x86emuOp_imul_byte_IMM(u8 X86EMU_UNUSED(op1))
1080 DECODE_PRINTF("IMUL\t");
1081 FETCH_DECODE_MODRM(mod, rh, rl);
1083 srcoffset = decode_rmXX_address(mod, rl);
1084 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1089 destreg = DECODE_RM_LONG_REGISTER(rh);
1091 srcval = fetch_data_long(srcoffset);
1092 imm = fetch_byte_imm();
1093 DECODE_PRINTF2(",%d\n", (s32)imm);
1095 imul_long_direct(&res_lo,&res_hi,(s32)srcval,(s32)imm);
1096 if ((((res_lo & 0x80000000) == 0) && (res_hi == 0x00000000)) ||
1097 (((res_lo & 0x80000000) != 0) && (res_hi == 0xFFFFFFFF))) {
1104 *destreg = (u32)res_lo;
1110 destreg = DECODE_RM_WORD_REGISTER(rh);
1112 srcval = fetch_data_word(srcoffset);
1113 imm = fetch_byte_imm();
1114 DECODE_PRINTF2(",%d\n", (s32)imm);
1116 res = (s16)srcval * (s16)imm;
1117 if ((((res & 0x8000) == 0) && ((res >> 16) == 0x0000)) ||
1118 (((res & 0x8000) != 0) && ((res >> 16) == 0xFFFF))) {
1125 *destreg = (u16)res;
1127 } else { /* register to register */
1128 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1129 u32 *destreg,*srcreg;
1132 destreg = DECODE_RM_LONG_REGISTER(rh);
1134 srcreg = DECODE_RM_LONG_REGISTER(rl);
1135 imm = fetch_byte_imm();
1136 DECODE_PRINTF2(",%d\n", (s32)imm);
1138 imul_long_direct(&res_lo,&res_hi,(s32)*srcreg,(s32)imm);
1139 if ((((res_lo & 0x80000000) == 0) && (res_hi == 0x00000000)) ||
1140 (((res_lo & 0x80000000) != 0) && (res_hi == 0xFFFFFFFF))) {
1147 *destreg = (u32)res_lo;
1149 u16 *destreg,*srcreg;
1152 destreg = DECODE_RM_WORD_REGISTER(rh);
1154 srcreg = DECODE_RM_WORD_REGISTER(rl);
1155 imm = fetch_byte_imm();
1156 DECODE_PRINTF2(",%d\n", (s32)imm);
1158 res = (s16)*srcreg * (s16)imm;
1159 if ((((res & 0x8000) == 0) && ((res >> 16) == 0x0000)) ||
1160 (((res & 0x8000) != 0) && ((res >> 16) == 0xFFFF))) {
1167 *destreg = (u16)res;
1170 DECODE_CLEAR_SEGOVR();
1174 /****************************************************************************
1177 ****************************************************************************/
1178 void x86emuOp_ins_byte(u8 X86EMU_UNUSED(op1))
1181 DECODE_PRINTF("INSB\n");
1184 DECODE_CLEAR_SEGOVR();
1188 /****************************************************************************
1191 ****************************************************************************/
1192 void x86emuOp_ins_word(u8 X86EMU_UNUSED(op1))
1195 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1196 DECODE_PRINTF("INSD\n");
1199 DECODE_PRINTF("INSW\n");
1203 DECODE_CLEAR_SEGOVR();
1207 /****************************************************************************
1210 ****************************************************************************/
1211 void x86emuOp_outs_byte(u8 X86EMU_UNUSED(op1))
1214 DECODE_PRINTF("OUTSB\n");
1217 DECODE_CLEAR_SEGOVR();
1221 /****************************************************************************
1224 ****************************************************************************/
1225 void x86emuOp_outs_word(u8 X86EMU_UNUSED(op1))
1228 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1229 DECODE_PRINTF("OUTSD\n");
1232 DECODE_PRINTF("OUTSW\n");
1236 DECODE_CLEAR_SEGOVR();
1240 /****************************************************************************
1242 Handles opcode 0x70 - 0x7F
1243 ****************************************************************************/
1244 int x86emu_check_jump_condition(u8 op);
1246 void x86emuOp_jump_near_cond(u8 op1)
1252 /* jump to byte offset if overflow flag is set */
1254 cond = x86emu_check_jump_condition(op1 & 0xF);
1255 offset = (s8)fetch_byte_imm();
1256 target = (u16)(M.x86.R_IP + (s16)offset);
1257 DECODE_PRINTF2("%x\n", target);
1260 M.x86.R_IP = target;
1261 DECODE_CLEAR_SEGOVR();
1265 /****************************************************************************
1268 ****************************************************************************/
1269 void x86emuOp_opc80_byte_RM_IMM(u8 X86EMU_UNUSED(op1))
1278 * Weirdo special case instruction format. Part of the opcode
1279 * held below in "RH". Doubly nested case would result, except
1280 * that the decoded instruction
1283 FETCH_DECODE_MODRM(mod, rh, rl);
1285 if (DEBUG_DECODE()) {
1286 /* XXX DECODE_PRINTF may be changed to something more
1287 general, so that it is important to leave the strings
1288 in the same format, even though the result is that the
1289 above test is done twice. */
1293 DECODE_PRINTF("ADD\t");
1296 DECODE_PRINTF("OR\t");
1299 DECODE_PRINTF("ADC\t");
1302 DECODE_PRINTF("SBB\t");
1305 DECODE_PRINTF("AND\t");
1308 DECODE_PRINTF("SUB\t");
1311 DECODE_PRINTF("XOR\t");
1314 DECODE_PRINTF("CMP\t");
1319 /* know operation, decode the mod byte to find the addressing
1322 DECODE_PRINTF("BYTE PTR ");
1323 destoffset = decode_rmXX_address(mod, rl);
1325 destval = fetch_data_byte(destoffset);
1326 imm = fetch_byte_imm();
1327 DECODE_PRINTF2("%x\n", imm);
1329 destval = (*genop_byte_operation[rh]) (destval, imm);
1331 store_data_byte(destoffset, destval);
1332 } else { /* register to register */
1333 destreg = DECODE_RM_BYTE_REGISTER(rl);
1335 imm = fetch_byte_imm();
1336 DECODE_PRINTF2("%x\n", imm);
1338 *destreg = (*genop_byte_operation[rh]) (*destreg, imm);
1340 DECODE_CLEAR_SEGOVR();
1344 /****************************************************************************
1347 ****************************************************************************/
1348 void x86emuOp_opc81_word_RM_IMM(u8 X86EMU_UNUSED(op1))
1354 * Weirdo special case instruction format. Part of the opcode
1355 * held below in "RH". Doubly nested case would result, except
1356 * that the decoded instruction
1359 FETCH_DECODE_MODRM(mod, rh, rl);
1361 if (DEBUG_DECODE()) {
1362 /* XXX DECODE_PRINTF may be changed to something more
1363 general, so that it is important to leave the strings
1364 in the same format, even though the result is that the
1365 above test is done twice. */
1369 DECODE_PRINTF("ADD\t");
1372 DECODE_PRINTF("OR\t");
1375 DECODE_PRINTF("ADC\t");
1378 DECODE_PRINTF("SBB\t");
1381 DECODE_PRINTF("AND\t");
1384 DECODE_PRINTF("SUB\t");
1387 DECODE_PRINTF("XOR\t");
1390 DECODE_PRINTF("CMP\t");
1396 * Know operation, decode the mod byte to find the addressing
1400 DECODE_PRINTF("DWORD PTR ");
1401 destoffset = decode_rmXX_address(mod, rl);
1402 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1406 destval = fetch_data_long(destoffset);
1407 imm = fetch_long_imm();
1408 DECODE_PRINTF2("%x\n", imm);
1410 destval = (*genop_long_operation[rh]) (destval, imm);
1412 store_data_long(destoffset, destval);
1417 destval = fetch_data_word(destoffset);
1418 imm = fetch_word_imm();
1419 DECODE_PRINTF2("%x\n", imm);
1421 destval = (*genop_word_operation[rh]) (destval, imm);
1423 store_data_word(destoffset, destval);
1425 } else { /* register to register */
1426 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1429 destreg = DECODE_RM_LONG_REGISTER(rl);
1431 imm = fetch_long_imm();
1432 DECODE_PRINTF2("%x\n", imm);
1434 *destreg = (*genop_long_operation[rh]) (*destreg, imm);
1438 destreg = DECODE_RM_WORD_REGISTER(rl);
1440 imm = fetch_word_imm();
1441 DECODE_PRINTF2("%x\n", imm);
1443 *destreg = (*genop_word_operation[rh]) (*destreg, imm);
1446 DECODE_CLEAR_SEGOVR();
1450 /****************************************************************************
1453 ****************************************************************************/
1454 void x86emuOp_opc82_byte_RM_IMM(u8 X86EMU_UNUSED(op1))
1463 * Weirdo special case instruction format. Part of the opcode
1464 * held below in "RH". Doubly nested case would result, except
1465 * that the decoded instruction Similar to opcode 81, except that
1466 * the immediate byte is sign extended to a word length.
1469 FETCH_DECODE_MODRM(mod, rh, rl);
1471 if (DEBUG_DECODE()) {
1472 /* XXX DECODE_PRINTF may be changed to something more
1473 general, so that it is important to leave the strings
1474 in the same format, even though the result is that the
1475 above test is done twice. */
1478 DECODE_PRINTF("ADD\t");
1481 DECODE_PRINTF("OR\t");
1484 DECODE_PRINTF("ADC\t");
1487 DECODE_PRINTF("SBB\t");
1490 DECODE_PRINTF("AND\t");
1493 DECODE_PRINTF("SUB\t");
1496 DECODE_PRINTF("XOR\t");
1499 DECODE_PRINTF("CMP\t");
1504 /* know operation, decode the mod byte to find the addressing
1507 DECODE_PRINTF("BYTE PTR ");
1508 destoffset = decode_rmXX_address(mod, rl);
1509 destval = fetch_data_byte(destoffset);
1510 imm = fetch_byte_imm();
1511 DECODE_PRINTF2(",%x\n", imm);
1513 destval = (*genop_byte_operation[rh]) (destval, imm);
1515 store_data_byte(destoffset, destval);
1516 } else { /* register to register */
1517 destreg = DECODE_RM_BYTE_REGISTER(rl);
1518 imm = fetch_byte_imm();
1519 DECODE_PRINTF2(",%x\n", imm);
1521 *destreg = (*genop_byte_operation[rh]) (*destreg, imm);
1523 DECODE_CLEAR_SEGOVR();
1527 /****************************************************************************
1530 ****************************************************************************/
1531 void x86emuOp_opc83_word_RM_IMM(u8 X86EMU_UNUSED(op1))
1537 * Weirdo special case instruction format. Part of the opcode
1538 * held below in "RH". Doubly nested case would result, except
1539 * that the decoded instruction Similar to opcode 81, except that
1540 * the immediate byte is sign extended to a word length.
1543 FETCH_DECODE_MODRM(mod, rh, rl);
1545 if (DEBUG_DECODE()) {
1546 /* XXX DECODE_PRINTF may be changed to something more
1547 general, so that it is important to leave the strings
1548 in the same format, even though the result is that the
1549 above test is done twice. */
1552 DECODE_PRINTF("ADD\t");
1555 DECODE_PRINTF("OR\t");
1558 DECODE_PRINTF("ADC\t");
1561 DECODE_PRINTF("SBB\t");
1564 DECODE_PRINTF("AND\t");
1567 DECODE_PRINTF("SUB\t");
1570 DECODE_PRINTF("XOR\t");
1573 DECODE_PRINTF("CMP\t");
1578 /* know operation, decode the mod byte to find the addressing
1581 DECODE_PRINTF("DWORD PTR ");
1582 destoffset = decode_rmXX_address(mod,rl);
1584 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1587 destval = fetch_data_long(destoffset);
1588 imm = (s8) fetch_byte_imm();
1589 DECODE_PRINTF2(",%x\n", imm);
1591 destval = (*genop_long_operation[rh]) (destval, imm);
1593 store_data_long(destoffset, destval);
1597 destval = fetch_data_word(destoffset);
1598 imm = (s8) fetch_byte_imm();
1599 DECODE_PRINTF2(",%x\n", imm);
1601 destval = (*genop_word_operation[rh]) (destval, imm);
1603 store_data_word(destoffset, destval);
1605 } else { /* register to register */
1606 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1609 destreg = DECODE_RM_LONG_REGISTER(rl);
1610 imm = (s8) fetch_byte_imm();
1611 DECODE_PRINTF2(",%x\n", imm);
1613 *destreg = (*genop_long_operation[rh]) (*destreg, imm);
1617 destreg = DECODE_RM_WORD_REGISTER(rl);
1618 imm = (s8) fetch_byte_imm();
1619 DECODE_PRINTF2(",%x\n", imm);
1621 *destreg = (*genop_word_operation[rh]) (*destreg, imm);
1624 DECODE_CLEAR_SEGOVR();
1628 /****************************************************************************
1631 ****************************************************************************/
1632 void x86emuOp_test_byte_RM_R(u8 X86EMU_UNUSED(op1))
1635 u8 *destreg, *srcreg;
1640 DECODE_PRINTF("TEST\t");
1641 FETCH_DECODE_MODRM(mod, rh, rl);
1643 destoffset = decode_rmXX_address(mod, rl);
1645 destval = fetch_data_byte(destoffset);
1646 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1647 DECODE_PRINTF("\n");
1649 test_byte(destval, *srcreg);
1650 } else { /* register to register */
1651 destreg = DECODE_RM_BYTE_REGISTER(rl);
1653 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1654 DECODE_PRINTF("\n");
1656 test_byte(*destreg, *srcreg);
1658 DECODE_CLEAR_SEGOVR();
1662 /****************************************************************************
1665 ****************************************************************************/
1666 void x86emuOp_test_word_RM_R(u8 X86EMU_UNUSED(op1))
1672 DECODE_PRINTF("TEST\t");
1673 FETCH_DECODE_MODRM(mod, rh, rl);
1675 destoffset = decode_rmXX_address(mod, rl);
1676 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1681 destval = fetch_data_long(destoffset);
1682 srcreg = DECODE_RM_LONG_REGISTER(rh);
1683 DECODE_PRINTF("\n");
1685 test_long(destval, *srcreg);
1691 destval = fetch_data_word(destoffset);
1692 srcreg = DECODE_RM_WORD_REGISTER(rh);
1693 DECODE_PRINTF("\n");
1695 test_word(destval, *srcreg);
1697 } else { /* register to register */
1698 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1699 u32 *destreg,*srcreg;
1701 destreg = DECODE_RM_LONG_REGISTER(rl);
1703 srcreg = DECODE_RM_LONG_REGISTER(rh);
1704 DECODE_PRINTF("\n");
1706 test_long(*destreg, *srcreg);
1708 u16 *destreg,*srcreg;
1710 destreg = DECODE_RM_WORD_REGISTER(rl);
1712 srcreg = DECODE_RM_WORD_REGISTER(rh);
1713 DECODE_PRINTF("\n");
1715 test_word(*destreg, *srcreg);
1718 DECODE_CLEAR_SEGOVR();
1722 /****************************************************************************
1725 ****************************************************************************/
1726 void x86emuOp_xchg_byte_RM_R(u8 X86EMU_UNUSED(op1))
1729 u8 *destreg, *srcreg;
1735 DECODE_PRINTF("XCHG\t");
1736 FETCH_DECODE_MODRM(mod, rh, rl);
1738 destoffset = decode_rmXX_address(mod, rl);
1740 destval = fetch_data_byte(destoffset);
1741 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1742 DECODE_PRINTF("\n");
1747 store_data_byte(destoffset, destval);
1748 } else { /* register to register */
1749 destreg = DECODE_RM_BYTE_REGISTER(rl);
1751 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1752 DECODE_PRINTF("\n");
1758 DECODE_CLEAR_SEGOVR();
1762 /****************************************************************************
1765 ****************************************************************************/
1766 void x86emuOp_xchg_word_RM_R(u8 X86EMU_UNUSED(op1))
1772 DECODE_PRINTF("XCHG\t");
1773 FETCH_DECODE_MODRM(mod, rh, rl);
1775 destoffset = decode_rmXX_address(mod, rl);
1777 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1781 destval = fetch_data_long(destoffset);
1782 srcreg = DECODE_RM_LONG_REGISTER(rh);
1783 DECODE_PRINTF("\n");
1788 store_data_long(destoffset, destval);
1793 destval = fetch_data_word(destoffset);
1794 srcreg = DECODE_RM_WORD_REGISTER(rh);
1795 DECODE_PRINTF("\n");
1800 store_data_word(destoffset, destval);
1802 } else { /* register to register */
1803 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1804 u32 *destreg,*srcreg;
1807 destreg = DECODE_RM_LONG_REGISTER(rl);
1809 srcreg = DECODE_RM_LONG_REGISTER(rh);
1810 DECODE_PRINTF("\n");
1816 u16 *destreg,*srcreg;
1819 destreg = DECODE_RM_WORD_REGISTER(rl);
1821 srcreg = DECODE_RM_WORD_REGISTER(rh);
1822 DECODE_PRINTF("\n");
1829 DECODE_CLEAR_SEGOVR();
1833 /****************************************************************************
1836 ****************************************************************************/
1837 void x86emuOp_mov_byte_RM_R(u8 X86EMU_UNUSED(op1))
1840 u8 *destreg, *srcreg;
1844 DECODE_PRINTF("MOV\t");
1845 FETCH_DECODE_MODRM(mod, rh, rl);
1847 destoffset = decode_rmXX_address(mod, rl);
1849 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1850 DECODE_PRINTF("\n");
1852 store_data_byte(destoffset, *srcreg);
1853 } else { /* register to register */
1854 destreg = DECODE_RM_BYTE_REGISTER(rl);
1856 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1857 DECODE_PRINTF("\n");
1861 DECODE_CLEAR_SEGOVR();
1865 /****************************************************************************
1868 ****************************************************************************/
1869 void x86emuOp_mov_word_RM_R(u8 X86EMU_UNUSED(op1))
1875 DECODE_PRINTF("MOV\t");
1876 FETCH_DECODE_MODRM(mod, rh, rl);
1878 destoffset = decode_rmXX_address(mod, rl);
1879 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1883 srcreg = DECODE_RM_LONG_REGISTER(rh);
1884 DECODE_PRINTF("\n");
1886 store_data_long(destoffset, *srcreg);
1891 srcreg = DECODE_RM_WORD_REGISTER(rh);
1892 DECODE_PRINTF("\n");
1894 store_data_word(destoffset, *srcreg);
1896 } else { /* register to register */
1897 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1898 u32 *destreg,*srcreg;
1900 destreg = DECODE_RM_LONG_REGISTER(rl);
1902 srcreg = DECODE_RM_LONG_REGISTER(rh);
1903 DECODE_PRINTF("\n");
1907 u16 *destreg,*srcreg;
1909 destreg = DECODE_RM_WORD_REGISTER(rl);
1911 srcreg = DECODE_RM_WORD_REGISTER(rh);
1912 DECODE_PRINTF("\n");
1917 DECODE_CLEAR_SEGOVR();
1921 /****************************************************************************
1924 ****************************************************************************/
1925 void x86emuOp_mov_byte_R_RM(u8 X86EMU_UNUSED(op1))
1928 u8 *destreg, *srcreg;
1933 DECODE_PRINTF("MOV\t");
1934 FETCH_DECODE_MODRM(mod, rh, rl);
1936 destreg = DECODE_RM_BYTE_REGISTER(rh);
1938 srcoffset = decode_rmXX_address(mod, rl);
1939 srcval = fetch_data_byte(srcoffset);
1940 DECODE_PRINTF("\n");
1943 } else { /* register to register */
1944 destreg = DECODE_RM_BYTE_REGISTER(rh);
1946 srcreg = DECODE_RM_BYTE_REGISTER(rl);
1947 DECODE_PRINTF("\n");
1951 DECODE_CLEAR_SEGOVR();
1955 /****************************************************************************
1958 ****************************************************************************/
1959 void x86emuOp_mov_word_R_RM(u8 X86EMU_UNUSED(op1))
1965 DECODE_PRINTF("MOV\t");
1966 FETCH_DECODE_MODRM(mod, rh, rl);
1968 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1972 destreg = DECODE_RM_LONG_REGISTER(rh);
1974 srcoffset = decode_rmXX_address(mod, rl);
1975 srcval = fetch_data_long(srcoffset);
1976 DECODE_PRINTF("\n");
1983 destreg = DECODE_RM_WORD_REGISTER(rh);
1985 srcoffset = decode_rmXX_address(mod, rl);
1986 srcval = fetch_data_word(srcoffset);
1987 DECODE_PRINTF("\n");
1991 } else { /* register to register */
1992 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1993 u32 *destreg, *srcreg;
1995 destreg = DECODE_RM_LONG_REGISTER(rh);
1997 srcreg = DECODE_RM_LONG_REGISTER(rl);
1998 DECODE_PRINTF("\n");
2002 u16 *destreg, *srcreg;
2004 destreg = DECODE_RM_WORD_REGISTER(rh);
2006 srcreg = DECODE_RM_WORD_REGISTER(rl);
2007 DECODE_PRINTF("\n");
2012 DECODE_CLEAR_SEGOVR();
2016 /****************************************************************************
2019 ****************************************************************************/
2020 void x86emuOp_mov_word_RM_SR(u8 X86EMU_UNUSED(op1))
2023 u16 *destreg, *srcreg;
2028 DECODE_PRINTF("MOV\t");
2029 FETCH_DECODE_MODRM(mod, rh, rl);
2031 destoffset = decode_rmXX_address(mod, rl);
2033 srcreg = decode_rm_seg_register(rh);
2034 DECODE_PRINTF("\n");
2037 store_data_word(destoffset, destval);
2038 } else { /* register to register */
2039 destreg = DECODE_RM_WORD_REGISTER(rl);
2041 srcreg = decode_rm_seg_register(rh);
2042 DECODE_PRINTF("\n");
2046 DECODE_CLEAR_SEGOVR();
2050 /****************************************************************************
2053 ****************************************************************************/
2054 void x86emuOp_lea_word_R_M(u8 X86EMU_UNUSED(op1))
2061 * TODO: Need to handle address size prefix!
2063 * lea eax,[eax+ebx*2] ??
2067 DECODE_PRINTF("LEA\t");
2068 FETCH_DECODE_MODRM(mod, rh, rl);
2070 srcreg = DECODE_RM_WORD_REGISTER(rh);
2072 destoffset = decode_rmXX_address(mod, rl);
2073 DECODE_PRINTF("\n");
2075 *srcreg = (u16)destoffset;
2077 /* } else { undefined. Do nothing. } */
2078 DECODE_CLEAR_SEGOVR();
2082 /****************************************************************************
2085 ****************************************************************************/
2086 void x86emuOp_mov_word_SR_RM(u8 X86EMU_UNUSED(op1))
2089 u16 *destreg, *srcreg;
2094 DECODE_PRINTF("MOV\t");
2095 FETCH_DECODE_MODRM(mod, rh, rl);
2097 destreg = decode_rm_seg_register(rh);
2099 srcoffset = decode_rmXX_address(mod, rl);
2100 srcval = fetch_data_word(srcoffset);
2101 DECODE_PRINTF("\n");
2104 } else { /* register to register */
2105 destreg = decode_rm_seg_register(rh);
2107 srcreg = DECODE_RM_WORD_REGISTER(rl);
2108 DECODE_PRINTF("\n");
2113 * Clean up, and reset all the R_xSP pointers to the correct
2114 * locations. This is about 3x too much overhead (doing all the
2115 * segreg ptrs when only one is needed, but this instruction
2116 * *cannot* be that common, and this isn't too much work anyway.
2118 DECODE_CLEAR_SEGOVR();
2122 /****************************************************************************
2125 ****************************************************************************/
2126 void x86emuOp_pop_RM(u8 X86EMU_UNUSED(op1))
2132 DECODE_PRINTF("POP\t");
2133 FETCH_DECODE_MODRM(mod, rh, rl);
2135 DECODE_PRINTF("ILLEGAL DECODE OF OPCODE 8F\n");
2139 destoffset = decode_rmXX_address(mod, rl);
2140 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2143 DECODE_PRINTF("\n");
2145 destval = pop_long();
2146 store_data_long(destoffset, destval);
2150 DECODE_PRINTF("\n");
2152 destval = pop_word();
2153 store_data_word(destoffset, destval);
2155 } else { /* register to register */
2156 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2159 destreg = DECODE_RM_LONG_REGISTER(rl);
2160 DECODE_PRINTF("\n");
2162 *destreg = pop_long();
2166 destreg = DECODE_RM_WORD_REGISTER(rl);
2167 DECODE_PRINTF("\n");
2169 *destreg = pop_word();
2172 DECODE_CLEAR_SEGOVR();
2176 /****************************************************************************
2179 ****************************************************************************/
2180 void x86emuOp_nop(u8 X86EMU_UNUSED(op1))
2183 DECODE_PRINTF("NOP\n");
2185 DECODE_CLEAR_SEGOVR();
2189 /****************************************************************************
2191 Handles opcode 0x91-0x97
2192 ****************************************************************************/
2193 void x86emuOp_xchg_word_AX_register(u8 X86EMU_UNUSED(op1))
2201 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2203 DECODE_PRINTF("XCHG\tEAX,");
2204 reg32 = DECODE_RM_LONG_REGISTER(op1);
2205 DECODE_PRINTF("\n");
2208 M.x86.R_EAX = *reg32;
2212 DECODE_PRINTF("XCHG\tAX,");
2213 reg16 = DECODE_RM_WORD_REGISTER(op1);
2214 DECODE_PRINTF("\n");
2217 M.x86.R_AX = *reg16;
2220 DECODE_CLEAR_SEGOVR();
2224 /****************************************************************************
2227 ****************************************************************************/
2228 void x86emuOp_cbw(u8 X86EMU_UNUSED(op1))
2231 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2232 DECODE_PRINTF("CWDE\n");
2234 DECODE_PRINTF("CBW\n");
2237 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2238 if (M.x86.R_AX & 0x8000) {
2239 M.x86.R_EAX |= 0xffff0000;
2241 M.x86.R_EAX &= 0x0000ffff;
2244 if (M.x86.R_AL & 0x80) {
2250 DECODE_CLEAR_SEGOVR();
2254 /****************************************************************************
2257 ****************************************************************************/
2258 void x86emuOp_cwd(u8 X86EMU_UNUSED(op1))
2261 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2262 DECODE_PRINTF("CDQ\n");
2264 DECODE_PRINTF("CWD\n");
2266 DECODE_PRINTF("CWD\n");
2268 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2269 if (M.x86.R_EAX & 0x80000000) {
2270 M.x86.R_EDX = 0xffffffff;
2275 if (M.x86.R_AX & 0x8000) {
2276 M.x86.R_DX = 0xffff;
2281 DECODE_CLEAR_SEGOVR();
2285 /****************************************************************************
2288 ****************************************************************************/
2289 void x86emuOp_call_far_IMM(u8 X86EMU_UNUSED(op1))
2294 DECODE_PRINTF("CALL\t");
2295 faroff = fetch_word_imm();
2296 farseg = fetch_word_imm();
2297 DECODE_PRINTF2("%04x:", farseg);
2298 DECODE_PRINTF2("%04x\n", faroff);
2299 CALL_TRACE(M.x86.saved_cs, M.x86.saved_ip, farseg, faroff, "FAR ");
2303 * Hooked interrupt vectors calling into our "BIOS" will cause
2304 * problems unless all intersegment stuff is checked for BIOS
2305 * access. Check needed here. For moment, let it alone.
2308 push_word(M.x86.R_CS);
2309 M.x86.R_CS = farseg;
2310 push_word(M.x86.R_IP);
2311 M.x86.R_IP = faroff;
2312 DECODE_CLEAR_SEGOVR();
2316 /****************************************************************************
2319 ****************************************************************************/
2320 void x86emuOp_wait(u8 X86EMU_UNUSED(op1))
2323 DECODE_PRINTF("WAIT");
2326 DECODE_CLEAR_SEGOVR();
2330 /****************************************************************************
2333 ****************************************************************************/
2334 void x86emuOp_pushf_word(u8 X86EMU_UNUSED(op1))
2339 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2340 DECODE_PRINTF("PUSHFD\n");
2342 DECODE_PRINTF("PUSHF\n");
2346 /* clear out *all* bits not representing flags, and turn on real bits */
2347 flags = (M.x86.R_EFLG & F_MSK) | F_ALWAYS_ON;
2348 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2351 push_word((u16)flags);
2353 DECODE_CLEAR_SEGOVR();
2357 /****************************************************************************
2360 ****************************************************************************/
2361 void x86emuOp_popf_word(u8 X86EMU_UNUSED(op1))
2364 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2365 DECODE_PRINTF("POPFD\n");
2367 DECODE_PRINTF("POPF\n");
2370 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2371 M.x86.R_EFLG = pop_long();
2373 M.x86.R_FLG = pop_word();
2375 DECODE_CLEAR_SEGOVR();
2379 /****************************************************************************
2382 ****************************************************************************/
2383 void x86emuOp_sahf(u8 X86EMU_UNUSED(op1))
2386 DECODE_PRINTF("SAHF\n");
2388 /* clear the lower bits of the flag register */
2389 M.x86.R_FLG &= 0xffffff00;
2390 /* or in the AH register into the flags register */
2391 M.x86.R_FLG |= M.x86.R_AH;
2392 DECODE_CLEAR_SEGOVR();
2396 /****************************************************************************
2399 ****************************************************************************/
2400 void x86emuOp_lahf(u8 X86EMU_UNUSED(op1))
2403 DECODE_PRINTF("LAHF\n");
2405 M.x86.R_AH = (u8)(M.x86.R_FLG & 0xff);
2406 /*undocumented TC++ behavior??? Nope. It's documented, but
2407 you have too look real hard to notice it. */
2409 DECODE_CLEAR_SEGOVR();
2413 /****************************************************************************
2416 ****************************************************************************/
2417 void x86emuOp_mov_AL_M_IMM(u8 X86EMU_UNUSED(op1))
2422 DECODE_PRINTF("MOV\tAL,");
2423 offset = fetch_word_imm();
2424 DECODE_PRINTF2("[%04x]\n", offset);
2426 M.x86.R_AL = fetch_data_byte(offset);
2427 DECODE_CLEAR_SEGOVR();
2431 /****************************************************************************
2434 ****************************************************************************/
2435 void x86emuOp_mov_AX_M_IMM(u8 X86EMU_UNUSED(op1))
2440 offset = fetch_word_imm();
2441 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2442 DECODE_PRINTF2("MOV\tEAX,[%04x]\n", offset);
2444 DECODE_PRINTF2("MOV\tAX,[%04x]\n", offset);
2447 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2448 M.x86.R_EAX = fetch_data_long(offset);
2450 M.x86.R_AX = fetch_data_word(offset);
2452 DECODE_CLEAR_SEGOVR();
2456 /****************************************************************************
2459 ****************************************************************************/
2460 void x86emuOp_mov_M_AL_IMM(u8 X86EMU_UNUSED(op1))
2465 DECODE_PRINTF("MOV\t");
2466 offset = fetch_word_imm();
2467 DECODE_PRINTF2("[%04x],AL\n", offset);
2469 store_data_byte(offset, M.x86.R_AL);
2470 DECODE_CLEAR_SEGOVR();
2474 /****************************************************************************
2477 ****************************************************************************/
2478 void x86emuOp_mov_M_AX_IMM(u8 X86EMU_UNUSED(op1))
2483 offset = fetch_word_imm();
2484 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2485 DECODE_PRINTF2("MOV\t[%04x],EAX\n", offset);
2487 DECODE_PRINTF2("MOV\t[%04x],AX\n", offset);
2490 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2491 store_data_long(offset, M.x86.R_EAX);
2493 store_data_word(offset, M.x86.R_AX);
2495 DECODE_CLEAR_SEGOVR();
2499 /****************************************************************************
2502 ****************************************************************************/
2503 void x86emuOp_movs_byte(u8 X86EMU_UNUSED(op1))
2510 DECODE_PRINTF("MOVS\tBYTE\n");
2511 if (ACCESS_FLAG(F_DF)) /* down */
2517 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2518 /* dont care whether REPE or REPNE */
2519 /* move them until CX is ZERO. */
2522 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2525 val = fetch_data_byte(M.x86.R_SI);
2526 store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, val);
2530 DECODE_CLEAR_SEGOVR();
2534 /****************************************************************************
2537 ****************************************************************************/
2538 void x86emuOp_movs_word(u8 X86EMU_UNUSED(op1))
2545 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2546 DECODE_PRINTF("MOVS\tDWORD\n");
2547 if (ACCESS_FLAG(F_DF)) /* down */
2552 DECODE_PRINTF("MOVS\tWORD\n");
2553 if (ACCESS_FLAG(F_DF)) /* down */
2560 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2561 /* dont care whether REPE or REPNE */
2562 /* move them until CX is ZERO. */
2565 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2568 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2569 val = fetch_data_long(M.x86.R_SI);
2570 store_data_long_abs(M.x86.R_ES, M.x86.R_DI, val);
2572 val = fetch_data_word(M.x86.R_SI);
2573 store_data_word_abs(M.x86.R_ES, M.x86.R_DI, (u16)val);
2578 DECODE_CLEAR_SEGOVR();
2582 /****************************************************************************
2585 ****************************************************************************/
2586 void x86emuOp_cmps_byte(u8 X86EMU_UNUSED(op1))
2592 DECODE_PRINTF("CMPS\tBYTE\n");
2594 if (ACCESS_FLAG(F_DF)) /* down */
2599 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2601 /* move them until CX is ZERO. */
2602 while (M.x86.R_CX != 0) {
2603 val1 = fetch_data_byte(M.x86.R_SI);
2604 val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2605 cmp_byte(val1, val2);
2609 if ( (M.x86.mode & SYSMODE_PREFIX_REPE) && (ACCESS_FLAG(F_ZF) == 0) ) break;
2610 if ( (M.x86.mode & SYSMODE_PREFIX_REPNE) && ACCESS_FLAG(F_ZF) ) break;
2612 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2614 val1 = fetch_data_byte(M.x86.R_SI);
2615 val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2616 cmp_byte(val1, val2);
2620 DECODE_CLEAR_SEGOVR();
2624 /****************************************************************************
2627 ****************************************************************************/
2628 void x86emuOp_cmps_word(u8 X86EMU_UNUSED(op1))
2634 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2635 DECODE_PRINTF("CMPS\tDWORD\n");
2638 DECODE_PRINTF("CMPS\tWORD\n");
2641 if (ACCESS_FLAG(F_DF)) /* down */
2645 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2647 /* move them until CX is ZERO. */
2648 while (M.x86.R_CX != 0) {
2649 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2650 val1 = fetch_data_long(M.x86.R_SI);
2651 val2 = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
2652 cmp_long(val1, val2);
2654 val1 = fetch_data_word(M.x86.R_SI);
2655 val2 = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
2656 cmp_word((u16)val1, (u16)val2);
2661 if ( (M.x86.mode & SYSMODE_PREFIX_REPE) && ACCESS_FLAG(F_ZF) == 0 ) break;
2662 if ( (M.x86.mode & SYSMODE_PREFIX_REPNE) && ACCESS_FLAG(F_ZF) ) break;
2664 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2666 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2667 val1 = fetch_data_long(M.x86.R_SI);
2668 val2 = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
2669 cmp_long(val1, val2);
2671 val1 = fetch_data_word(M.x86.R_SI);
2672 val2 = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
2673 cmp_word((u16)val1, (u16)val2);
2678 DECODE_CLEAR_SEGOVR();
2682 /****************************************************************************
2685 ****************************************************************************/
2686 void x86emuOp_test_AL_IMM(u8 X86EMU_UNUSED(op1))
2691 DECODE_PRINTF("TEST\tAL,");
2692 imm = fetch_byte_imm();
2693 DECODE_PRINTF2("%04x\n", imm);
2695 test_byte(M.x86.R_AL, (u8)imm);
2696 DECODE_CLEAR_SEGOVR();
2700 /****************************************************************************
2703 ****************************************************************************/
2704 void x86emuOp_test_AX_IMM(u8 X86EMU_UNUSED(op1))
2709 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2710 DECODE_PRINTF("TEST\tEAX,");
2711 srcval = fetch_long_imm();
2713 DECODE_PRINTF("TEST\tAX,");
2714 srcval = fetch_word_imm();
2716 DECODE_PRINTF2("%x\n", srcval);
2718 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2719 test_long(M.x86.R_EAX, srcval);
2721 test_word(M.x86.R_AX, (u16)srcval);
2723 DECODE_CLEAR_SEGOVR();
2727 /****************************************************************************
2730 ****************************************************************************/
2731 void x86emuOp_stos_byte(u8 X86EMU_UNUSED(op1))
2736 DECODE_PRINTF("STOS\tBYTE\n");
2737 if (ACCESS_FLAG(F_DF)) /* down */
2742 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2743 /* dont care whether REPE or REPNE */
2744 /* move them until CX is ZERO. */
2745 while (M.x86.R_CX != 0) {
2746 store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AL);
2750 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2752 store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AL);
2755 DECODE_CLEAR_SEGOVR();
2759 /****************************************************************************
2762 ****************************************************************************/
2763 void x86emuOp_stos_word(u8 X86EMU_UNUSED(op1))
2769 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2770 DECODE_PRINTF("STOS\tDWORD\n");
2771 if (ACCESS_FLAG(F_DF)) /* down */
2776 DECODE_PRINTF("STOS\tWORD\n");
2777 if (ACCESS_FLAG(F_DF)) /* down */
2784 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2785 /* dont care whether REPE or REPNE */
2786 /* move them until CX is ZERO. */
2789 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2792 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2793 store_data_long_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_EAX);
2795 store_data_word_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AX);
2799 DECODE_CLEAR_SEGOVR();
2803 /****************************************************************************
2806 ****************************************************************************/
2807 void x86emuOp_lods_byte(u8 X86EMU_UNUSED(op1))
2812 DECODE_PRINTF("LODS\tBYTE\n");
2814 if (ACCESS_FLAG(F_DF)) /* down */
2818 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2819 /* dont care whether REPE or REPNE */
2820 /* move them until CX is ZERO. */
2821 while (M.x86.R_CX != 0) {
2822 M.x86.R_AL = fetch_data_byte(M.x86.R_SI);
2826 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2828 M.x86.R_AL = fetch_data_byte(M.x86.R_SI);
2831 DECODE_CLEAR_SEGOVR();
2835 /****************************************************************************
2838 ****************************************************************************/
2839 void x86emuOp_lods_word(u8 X86EMU_UNUSED(op1))
2845 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2846 DECODE_PRINTF("LODS\tDWORD\n");
2847 if (ACCESS_FLAG(F_DF)) /* down */
2852 DECODE_PRINTF("LODS\tWORD\n");
2853 if (ACCESS_FLAG(F_DF)) /* down */
2860 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2861 /* dont care whether REPE or REPNE */
2862 /* move them until CX is ZERO. */
2865 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2868 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2869 M.x86.R_EAX = fetch_data_long(M.x86.R_SI);
2871 M.x86.R_AX = fetch_data_word(M.x86.R_SI);
2875 DECODE_CLEAR_SEGOVR();
2879 /****************************************************************************
2882 ****************************************************************************/
2883 void x86emuOp_scas_byte(u8 X86EMU_UNUSED(op1))
2889 DECODE_PRINTF("SCAS\tBYTE\n");
2891 if (ACCESS_FLAG(F_DF)) /* down */
2895 if (M.x86.mode & SYSMODE_PREFIX_REPE) {
2897 /* move them until CX is ZERO. */
2898 while (M.x86.R_CX != 0) {
2899 val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2900 cmp_byte(M.x86.R_AL, val2);
2903 if (ACCESS_FLAG(F_ZF) == 0)
2906 M.x86.mode &= ~SYSMODE_PREFIX_REPE;
2907 } else if (M.x86.mode & SYSMODE_PREFIX_REPNE) {
2909 /* move them until CX is ZERO. */
2910 while (M.x86.R_CX != 0) {
2911 val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2912 cmp_byte(M.x86.R_AL, val2);
2915 if (ACCESS_FLAG(F_ZF))
2916 break; /* zero flag set means equal */
2918 M.x86.mode &= ~SYSMODE_PREFIX_REPNE;
2920 val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2921 cmp_byte(M.x86.R_AL, val2);
2924 DECODE_CLEAR_SEGOVR();
2928 /****************************************************************************
2931 ****************************************************************************/
2932 void x86emuOp_scas_word(u8 X86EMU_UNUSED(op1))
2938 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2939 DECODE_PRINTF("SCAS\tDWORD\n");
2940 if (ACCESS_FLAG(F_DF)) /* down */
2945 DECODE_PRINTF("SCAS\tWORD\n");
2946 if (ACCESS_FLAG(F_DF)) /* down */
2952 if (M.x86.mode & SYSMODE_PREFIX_REPE) {
2954 /* move them until CX is ZERO. */
2955 while (M.x86.R_CX != 0) {
2956 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2957 val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
2958 cmp_long(M.x86.R_EAX, val);
2960 val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
2961 cmp_word(M.x86.R_AX, (u16)val);
2965 if (ACCESS_FLAG(F_ZF) == 0)
2968 M.x86.mode &= ~SYSMODE_PREFIX_REPE;
2969 } else if (M.x86.mode & SYSMODE_PREFIX_REPNE) {
2971 /* move them until CX is ZERO. */
2972 while (M.x86.R_CX != 0) {
2973 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2974 val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
2975 cmp_long(M.x86.R_EAX, val);
2977 val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
2978 cmp_word(M.x86.R_AX, (u16)val);
2982 if (ACCESS_FLAG(F_ZF))
2983 break; /* zero flag set means equal */
2985 M.x86.mode &= ~SYSMODE_PREFIX_REPNE;
2987 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2988 val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
2989 cmp_long(M.x86.R_EAX, val);
2991 val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
2992 cmp_word(M.x86.R_AX, (u16)val);
2996 DECODE_CLEAR_SEGOVR();
3000 /****************************************************************************
3002 Handles opcode 0xb0 - 0xb7
3003 ****************************************************************************/
3004 void x86emuOp_mov_byte_register_IMM(u8 op1)
3009 DECODE_PRINTF("MOV\t");
3010 ptr = DECODE_RM_BYTE_REGISTER(op1 & 0x7);
3012 imm = fetch_byte_imm();
3013 DECODE_PRINTF2("%x\n", imm);
3016 DECODE_CLEAR_SEGOVR();
3020 /****************************************************************************
3022 Handles opcode 0xb8 - 0xbf
3023 ****************************************************************************/
3024 void x86emuOp_mov_word_register_IMM(u8 X86EMU_UNUSED(op1))
3031 DECODE_PRINTF("MOV\t");
3032 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3034 reg32 = DECODE_RM_LONG_REGISTER(op1);
3035 srcval = fetch_long_imm();
3036 DECODE_PRINTF2(",%x\n", srcval);
3041 reg16 = DECODE_RM_WORD_REGISTER(op1);
3042 srcval = fetch_word_imm();
3043 DECODE_PRINTF2(",%x\n", srcval);
3045 *reg16 = (u16)srcval;
3047 DECODE_CLEAR_SEGOVR();
3051 /****************************************************************************
3054 ****************************************************************************/
3055 void x86emuOp_opcC0_byte_RM_MEM(u8 X86EMU_UNUSED(op1))
3064 * Yet another weirdo special case instruction format. Part of
3065 * the opcode held below in "RH". Doubly nested case would
3066 * result, except that the decoded instruction
3069 FETCH_DECODE_MODRM(mod, rh, rl);
3071 if (DEBUG_DECODE()) {
3072 /* XXX DECODE_PRINTF may be changed to something more
3073 general, so that it is important to leave the strings
3074 in the same format, even though the result is that the
3075 above test is done twice. */
3079 DECODE_PRINTF("ROL\t");
3082 DECODE_PRINTF("ROR\t");
3085 DECODE_PRINTF("RCL\t");
3088 DECODE_PRINTF("RCR\t");
3091 DECODE_PRINTF("SHL\t");
3094 DECODE_PRINTF("SHR\t");
3097 DECODE_PRINTF("SAL\t");
3100 DECODE_PRINTF("SAR\t");
3105 /* know operation, decode the mod byte to find the addressing
3108 DECODE_PRINTF("BYTE PTR ");
3109 destoffset = decode_rmXX_address(mod, rl);
3110 amt = fetch_byte_imm();
3111 DECODE_PRINTF2(",%x\n", amt);
3112 destval = fetch_data_byte(destoffset);
3114 destval = (*opcD0_byte_operation[rh]) (destval, amt);
3115 store_data_byte(destoffset, destval);
3116 } else { /* register to register */
3117 destreg = DECODE_RM_BYTE_REGISTER(rl);
3118 amt = fetch_byte_imm();
3119 DECODE_PRINTF2(",%x\n", amt);
3121 destval = (*opcD0_byte_operation[rh]) (*destreg, amt);
3124 DECODE_CLEAR_SEGOVR();
3128 /****************************************************************************
3131 ****************************************************************************/
3132 void x86emuOp_opcC1_word_RM_MEM(u8 X86EMU_UNUSED(op1))
3139 * Yet another weirdo special case instruction format. Part of
3140 * the opcode held below in "RH". Doubly nested case would
3141 * result, except that the decoded instruction
3144 FETCH_DECODE_MODRM(mod, rh, rl);
3146 if (DEBUG_DECODE()) {
3147 /* XXX DECODE_PRINTF may be changed to something more
3148 general, so that it is important to leave the strings
3149 in the same format, even though the result is that the
3150 above test is done twice. */
3154 DECODE_PRINTF("ROL\t");
3157 DECODE_PRINTF("ROR\t");
3160 DECODE_PRINTF("RCL\t");
3163 DECODE_PRINTF("RCR\t");
3166 DECODE_PRINTF("SHL\t");
3169 DECODE_PRINTF("SHR\t");
3172 DECODE_PRINTF("SAL\t");
3175 DECODE_PRINTF("SAR\t");
3180 /* know operation, decode the mod byte to find the addressing
3183 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3186 DECODE_PRINTF("DWORD PTR ");
3187 destoffset = decode_rmXX_address(mod, rl);
3188 amt = fetch_byte_imm();
3189 DECODE_PRINTF2(",%x\n", amt);
3190 destval = fetch_data_long(destoffset);
3192 destval = (*opcD1_long_operation[rh]) (destval, amt);
3193 store_data_long(destoffset, destval);
3197 DECODE_PRINTF("WORD PTR ");
3198 destoffset = decode_rmXX_address(mod, rl);
3199 amt = fetch_byte_imm();
3200 DECODE_PRINTF2(",%x\n", amt);
3201 destval = fetch_data_word(destoffset);
3203 destval = (*opcD1_word_operation[rh]) (destval, amt);
3204 store_data_word(destoffset, destval);
3206 } else { /* register to register */
3207 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3210 destreg = DECODE_RM_LONG_REGISTER(rl);
3211 amt = fetch_byte_imm();
3212 DECODE_PRINTF2(",%x\n", amt);
3214 *destreg = (*opcD1_long_operation[rh]) (*destreg, amt);
3218 destreg = DECODE_RM_WORD_REGISTER(rl);
3219 amt = fetch_byte_imm();
3220 DECODE_PRINTF2(",%x\n", amt);
3222 *destreg = (*opcD1_word_operation[rh]) (*destreg, amt);
3225 DECODE_CLEAR_SEGOVR();
3229 /****************************************************************************
3232 ****************************************************************************/
3233 void x86emuOp_ret_near_IMM(u8 X86EMU_UNUSED(op1))
3238 DECODE_PRINTF("RET\t");
3239 imm = fetch_word_imm();
3240 DECODE_PRINTF2("%x\n", imm);
3241 RETURN_TRACE("RET",M.x86.saved_cs,M.x86.saved_ip);
3243 M.x86.R_IP = pop_word();
3245 DECODE_CLEAR_SEGOVR();
3249 /****************************************************************************
3252 ****************************************************************************/
3253 void x86emuOp_ret_near(u8 X86EMU_UNUSED(op1))
3256 DECODE_PRINTF("RET\n");
3257 RETURN_TRACE("RET",M.x86.saved_cs,M.x86.saved_ip);
3259 M.x86.R_IP = pop_word();
3260 DECODE_CLEAR_SEGOVR();
3264 /****************************************************************************
3267 ****************************************************************************/
3268 void x86emuOp_les_R_IMM(u8 X86EMU_UNUSED(op1))
3275 DECODE_PRINTF("LES\t");
3276 FETCH_DECODE_MODRM(mod, rh, rl);
3278 dstreg = DECODE_RM_WORD_REGISTER(rh);
3280 srcoffset = decode_rmXX_address(mod, rl);
3281 DECODE_PRINTF("\n");
3283 *dstreg = fetch_data_word(srcoffset);
3284 M.x86.R_ES = fetch_data_word(srcoffset + 2);
3286 /* else UNDEFINED! register to register */
3288 DECODE_CLEAR_SEGOVR();
3292 /****************************************************************************
3295 ****************************************************************************/
3296 void x86emuOp_lds_R_IMM(u8 X86EMU_UNUSED(op1))
3303 DECODE_PRINTF("LDS\t");
3304 FETCH_DECODE_MODRM(mod, rh, rl);
3306 dstreg = DECODE_RM_WORD_REGISTER(rh);
3308 srcoffset = decode_rmXX_address(mod, rl);
3309 DECODE_PRINTF("\n");
3311 *dstreg = fetch_data_word(srcoffset);
3312 M.x86.R_DS = fetch_data_word(srcoffset + 2);
3314 /* else UNDEFINED! */
3315 DECODE_CLEAR_SEGOVR();
3319 /****************************************************************************
3322 ****************************************************************************/
3323 void x86emuOp_mov_byte_RM_IMM(u8 X86EMU_UNUSED(op1))
3331 DECODE_PRINTF("MOV\t");
3332 FETCH_DECODE_MODRM(mod, rh, rl);
3334 DECODE_PRINTF("ILLEGAL DECODE OF OPCODE c6\n");
3338 DECODE_PRINTF("BYTE PTR ");
3339 destoffset = decode_rmXX_address(mod, rl);
3340 imm = fetch_byte_imm();
3341 DECODE_PRINTF2(",%2x\n", imm);
3343 store_data_byte(destoffset, imm);
3344 } else { /* register to register */
3345 destreg = DECODE_RM_BYTE_REGISTER(rl);
3346 imm = fetch_byte_imm();
3347 DECODE_PRINTF2(",%2x\n", imm);
3351 DECODE_CLEAR_SEGOVR();
3355 /****************************************************************************
3358 ****************************************************************************/
3359 void x86emuOp_mov_word_RM_IMM(u8 X86EMU_UNUSED(op1))
3365 DECODE_PRINTF("MOV\t");
3366 FETCH_DECODE_MODRM(mod, rh, rl);
3368 DECODE_PRINTF("ILLEGAL DECODE OF OPCODE 8F\n");
3372 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3375 DECODE_PRINTF("DWORD PTR ");
3376 destoffset = decode_rmXX_address(mod, rl);
3377 imm = fetch_long_imm();
3378 DECODE_PRINTF2(",%x\n", imm);
3380 store_data_long(destoffset, imm);
3384 DECODE_PRINTF("WORD PTR ");
3385 destoffset = decode_rmXX_address(mod, rl);
3386 imm = fetch_word_imm();
3387 DECODE_PRINTF2(",%x\n", imm);
3389 store_data_word(destoffset, imm);
3391 } else { /* register to register */
3392 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3396 destreg = DECODE_RM_LONG_REGISTER(rl);
3397 imm = fetch_long_imm();
3398 DECODE_PRINTF2(",%x\n", imm);
3405 destreg = DECODE_RM_WORD_REGISTER(rl);
3406 imm = fetch_word_imm();
3407 DECODE_PRINTF2(",%x\n", imm);
3412 DECODE_CLEAR_SEGOVR();
3416 /****************************************************************************
3419 ****************************************************************************/
3420 void x86emuOp_enter(u8 X86EMU_UNUSED(op1))
3422 u16 local,frame_pointer;
3427 local = fetch_word_imm();
3428 nesting = fetch_byte_imm();
3429 DECODE_PRINTF2("ENTER %x\n", local);
3430 DECODE_PRINTF2(",%x\n", nesting);
3432 push_word(M.x86.R_BP);
3433 frame_pointer = M.x86.R_SP;
3435 for (i = 1; i < nesting; i++) {
3437 push_word(fetch_data_word_abs(M.x86.R_SS, M.x86.R_BP));
3439 push_word(frame_pointer);
3441 M.x86.R_BP = frame_pointer;
3442 M.x86.R_SP = (u16)(M.x86.R_SP - local);
3443 DECODE_CLEAR_SEGOVR();
3447 /****************************************************************************
3450 ****************************************************************************/
3451 void x86emuOp_leave(u8 X86EMU_UNUSED(op1))
3454 DECODE_PRINTF("LEAVE\n");
3456 M.x86.R_SP = M.x86.R_BP;
3457 M.x86.R_BP = pop_word();
3458 DECODE_CLEAR_SEGOVR();
3462 /****************************************************************************
3465 ****************************************************************************/
3466 void x86emuOp_ret_far_IMM(u8 X86EMU_UNUSED(op1))
3471 DECODE_PRINTF("RETF\t");
3472 imm = fetch_word_imm();
3473 DECODE_PRINTF2("%x\n", imm);
3474 RETURN_TRACE("RETF",M.x86.saved_cs,M.x86.saved_ip);
3476 M.x86.R_IP = pop_word();
3477 M.x86.R_CS = pop_word();
3479 DECODE_CLEAR_SEGOVR();
3483 /****************************************************************************
3486 ****************************************************************************/
3487 void x86emuOp_ret_far(u8 X86EMU_UNUSED(op1))
3490 DECODE_PRINTF("RETF\n");
3491 RETURN_TRACE("RETF",M.x86.saved_cs,M.x86.saved_ip);
3493 M.x86.R_IP = pop_word();
3494 M.x86.R_CS = pop_word();
3495 DECODE_CLEAR_SEGOVR();
3499 /****************************************************************************
3502 ****************************************************************************/
3503 void x86emuOp_int3(u8 X86EMU_UNUSED(op1))
3508 DECODE_PRINTF("INT 3\n");
3509 tmp = (u16) mem_access_word(3 * 4 + 2);
3510 /* access the segment register */
3512 if (_X86EMU_intrTab[3]) {
3513 (*_X86EMU_intrTab[3])(3);
3515 push_word((u16)M.x86.R_FLG);
3518 push_word(M.x86.R_CS);
3519 M.x86.R_CS = mem_access_word(3 * 4 + 2);
3520 push_word(M.x86.R_IP);
3521 M.x86.R_IP = mem_access_word(3 * 4);
3523 DECODE_CLEAR_SEGOVR();
3527 /****************************************************************************
3530 ****************************************************************************/
3531 void x86emuOp_int_IMM(u8 X86EMU_UNUSED(op1))
3537 DECODE_PRINTF("INT\t");
3538 intnum = fetch_byte_imm();
3539 DECODE_PRINTF2("%x\n", intnum);
3540 tmp = mem_access_word(intnum * 4 + 2);
3542 if (_X86EMU_intrTab[intnum]) {
3543 (*_X86EMU_intrTab[intnum])(intnum);
3545 push_word((u16)M.x86.R_FLG);
3548 push_word(M.x86.R_CS);
3549 M.x86.R_CS = mem_access_word(intnum * 4 + 2);
3550 push_word(M.x86.R_IP);
3551 M.x86.R_IP = mem_access_word(intnum * 4);
3553 DECODE_CLEAR_SEGOVR();
3557 /****************************************************************************
3560 ****************************************************************************/
3561 void x86emuOp_into(u8 X86EMU_UNUSED(op1))
3566 DECODE_PRINTF("INTO\n");
3568 if (ACCESS_FLAG(F_OF)) {
3569 tmp = mem_access_word(4 * 4 + 2);
3570 if (_X86EMU_intrTab[4]) {
3571 (*_X86EMU_intrTab[4])(4);
3573 push_word((u16)M.x86.R_FLG);
3576 push_word(M.x86.R_CS);
3577 M.x86.R_CS = mem_access_word(4 * 4 + 2);
3578 push_word(M.x86.R_IP);
3579 M.x86.R_IP = mem_access_word(4 * 4);
3582 DECODE_CLEAR_SEGOVR();
3586 /****************************************************************************
3589 ****************************************************************************/
3590 void x86emuOp_iret(u8 X86EMU_UNUSED(op1))
3593 DECODE_PRINTF("IRET\n");
3597 M.x86.R_IP = pop_word();
3598 M.x86.R_CS = pop_word();
3599 M.x86.R_FLG = pop_word();
3600 DECODE_CLEAR_SEGOVR();
3604 /****************************************************************************
3607 ****************************************************************************/
3608 void x86emuOp_opcD0_byte_RM_1(u8 X86EMU_UNUSED(op1))
3616 * Yet another weirdo special case instruction format. Part of
3617 * the opcode held below in "RH". Doubly nested case would
3618 * result, except that the decoded instruction
3621 FETCH_DECODE_MODRM(mod, rh, rl);
3623 if (DEBUG_DECODE()) {
3624 /* XXX DECODE_PRINTF may be changed to something more
3625 general, so that it is important to leave the strings
3626 in the same format, even though the result is that the
3627 above test is done twice. */
3630 DECODE_PRINTF("ROL\t");
3633 DECODE_PRINTF("ROR\t");
3636 DECODE_PRINTF("RCL\t");
3639 DECODE_PRINTF("RCR\t");
3642 DECODE_PRINTF("SHL\t");
3645 DECODE_PRINTF("SHR\t");
3648 DECODE_PRINTF("SAL\t");
3651 DECODE_PRINTF("SAR\t");
3656 /* know operation, decode the mod byte to find the addressing
3659 DECODE_PRINTF("BYTE PTR ");
3660 destoffset = decode_rmXX_address(mod, rl);
3661 DECODE_PRINTF(",1\n");
3662 destval = fetch_data_byte(destoffset);
3664 destval = (*opcD0_byte_operation[rh]) (destval, 1);
3665 store_data_byte(destoffset, destval);
3666 } else { /* register to register */
3667 destreg = DECODE_RM_BYTE_REGISTER(rl);
3668 DECODE_PRINTF(",1\n");
3670 destval = (*opcD0_byte_operation[rh]) (*destreg, 1);
3673 DECODE_CLEAR_SEGOVR();
3677 /****************************************************************************
3680 ****************************************************************************/
3681 void x86emuOp_opcD1_word_RM_1(u8 X86EMU_UNUSED(op1))
3687 * Yet another weirdo special case instruction format. Part of
3688 * the opcode held below in "RH". Doubly nested case would
3689 * result, except that the decoded instruction
3692 FETCH_DECODE_MODRM(mod, rh, rl);
3694 if (DEBUG_DECODE()) {
3695 /* XXX DECODE_PRINTF may be changed to something more
3696 general, so that it is important to leave the strings
3697 in the same format, even though the result is that the
3698 above test is done twice. */
3701 DECODE_PRINTF("ROL\t");
3704 DECODE_PRINTF("ROR\t");
3707 DECODE_PRINTF("RCL\t");
3710 DECODE_PRINTF("RCR\t");
3713 DECODE_PRINTF("SHL\t");
3716 DECODE_PRINTF("SHR\t");
3719 DECODE_PRINTF("SAL\t");
3722 DECODE_PRINTF("SAR\t");
3727 /* know operation, decode the mod byte to find the addressing
3730 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3733 DECODE_PRINTF("DWORD PTR ");
3734 destoffset = decode_rmXX_address(mod, rl);
3735 DECODE_PRINTF(",1\n");
3736 destval = fetch_data_long(destoffset);
3738 destval = (*opcD1_long_operation[rh]) (destval, 1);
3739 store_data_long(destoffset, destval);
3743 DECODE_PRINTF("WORD PTR ");
3744 destoffset = decode_rmXX_address(mod, rl);
3745 DECODE_PRINTF(",1\n");
3746 destval = fetch_data_word(destoffset);
3748 destval = (*opcD1_word_operation[rh]) (destval, 1);
3749 store_data_word(destoffset, destval);
3751 } else { /* register to register */
3752 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3756 destreg = DECODE_RM_LONG_REGISTER(rl);
3757 DECODE_PRINTF(",1\n");
3759 destval = (*opcD1_long_operation[rh]) (*destreg, 1);
3765 destreg = DECODE_RM_WORD_REGISTER(rl);
3766 DECODE_PRINTF(",1\n");
3768 destval = (*opcD1_word_operation[rh]) (*destreg, 1);
3772 DECODE_CLEAR_SEGOVR();
3776 /****************************************************************************
3779 ****************************************************************************/
3780 void x86emuOp_opcD2_byte_RM_CL(u8 X86EMU_UNUSED(op1))
3789 * Yet another weirdo special case instruction format. Part of
3790 * the opcode held below in "RH". Doubly nested case would
3791 * result, except that the decoded instruction
3794 FETCH_DECODE_MODRM(mod, rh, rl);
3796 if (DEBUG_DECODE()) {
3797 /* XXX DECODE_PRINTF may be changed to something more
3798 general, so that it is important to leave the strings
3799 in the same format, even though the result is that the
3800 above test is done twice. */
3803 DECODE_PRINTF("ROL\t");
3806 DECODE_PRINTF("ROR\t");
3809 DECODE_PRINTF("RCL\t");
3812 DECODE_PRINTF("RCR\t");
3815 DECODE_PRINTF("SHL\t");
3818 DECODE_PRINTF("SHR\t");
3821 DECODE_PRINTF("SAL\t");
3824 DECODE_PRINTF("SAR\t");
3829 /* know operation, decode the mod byte to find the addressing
3833 DECODE_PRINTF("BYTE PTR ");
3834 destoffset = decode_rmXX_address(mod, rl);
3835 DECODE_PRINTF(",CL\n");
3836 destval = fetch_data_byte(destoffset);
3838 destval = (*opcD0_byte_operation[rh]) (destval, amt);
3839 store_data_byte(destoffset, destval);
3840 } else { /* register to register */
3841 destreg = DECODE_RM_BYTE_REGISTER(rl);
3842 DECODE_PRINTF(",CL\n");
3844 destval = (*opcD0_byte_operation[rh]) (*destreg, amt);
3847 DECODE_CLEAR_SEGOVR();
3851 /****************************************************************************
3854 ****************************************************************************/
3855 void x86emuOp_opcD3_word_RM_CL(u8 X86EMU_UNUSED(op1))
3862 * Yet another weirdo special case instruction format. Part of
3863 * the opcode held below in "RH". Doubly nested case would
3864 * result, except that the decoded instruction
3867 FETCH_DECODE_MODRM(mod, rh, rl);
3869 if (DEBUG_DECODE()) {
3870 /* XXX DECODE_PRINTF may be changed to something more
3871 general, so that it is important to leave the strings
3872 in the same format, even though the result is that the
3873 above test is done twice. */
3876 DECODE_PRINTF("ROL\t");
3879 DECODE_PRINTF("ROR\t");
3882 DECODE_PRINTF("RCL\t");
3885 DECODE_PRINTF("RCR\t");
3888 DECODE_PRINTF("SHL\t");
3891 DECODE_PRINTF("SHR\t");
3894 DECODE_PRINTF("SAL\t");
3897 DECODE_PRINTF("SAR\t");
3902 /* know operation, decode the mod byte to find the addressing
3906 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3909 DECODE_PRINTF("DWORD PTR ");
3910 destoffset = decode_rmXX_address(mod, rl);
3911 DECODE_PRINTF(",CL\n");
3912 destval = fetch_data_long(destoffset);
3914 destval = (*opcD1_long_operation[rh]) (destval, amt);
3915 store_data_long(destoffset, destval);
3919 DECODE_PRINTF("WORD PTR ");
3920 destoffset = decode_rmXX_address(mod, rl);
3921 DECODE_PRINTF(",CL\n");
3922 destval = fetch_data_word(destoffset);
3924 destval = (*opcD1_word_operation[rh]) (destval, amt);
3925 store_data_word(destoffset, destval);
3927 } else { /* register to register */
3928 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3931 destreg = DECODE_RM_LONG_REGISTER(rl);
3932 DECODE_PRINTF(",CL\n");
3934 *destreg = (*opcD1_long_operation[rh]) (*destreg, amt);
3938 destreg = DECODE_RM_WORD_REGISTER(rl);
3939 DECODE_PRINTF(",CL\n");
3941 *destreg = (*opcD1_word_operation[rh]) (*destreg, amt);
3944 DECODE_CLEAR_SEGOVR();
3948 /****************************************************************************
3951 ****************************************************************************/
3952 void x86emuOp_aam(u8 X86EMU_UNUSED(op1))
3957 DECODE_PRINTF("AAM\n");
3958 a = fetch_byte_imm(); /* this is a stupid encoding. */
3960 DECODE_PRINTF("ERROR DECODING AAM\n");
3965 /* note the type change here --- returning AL and AH in AX. */
3966 M.x86.R_AX = aam_word(M.x86.R_AL);
3967 DECODE_CLEAR_SEGOVR();
3971 /****************************************************************************
3974 ****************************************************************************/
3975 void x86emuOp_aad(u8 X86EMU_UNUSED(op1))
3980 DECODE_PRINTF("AAD\n");
3981 a = fetch_byte_imm();
3983 M.x86.R_AX = aad_word(M.x86.R_AX);
3984 DECODE_CLEAR_SEGOVR();
3988 /* opcode 0xd6 ILLEGAL OPCODE */
3990 /****************************************************************************
3993 ****************************************************************************/
3994 void x86emuOp_xlat(u8 X86EMU_UNUSED(op1))
3999 DECODE_PRINTF("XLAT\n");
4001 addr = (u16)(M.x86.R_BX + (u8)M.x86.R_AL);
4002 M.x86.R_AL = fetch_data_byte(addr);
4003 DECODE_CLEAR_SEGOVR();
4007 /* instuctions D8 .. DF are in i87_ops.c */
4009 /****************************************************************************
4012 ****************************************************************************/
4013 void x86emuOp_loopne(u8 X86EMU_UNUSED(op1))
4018 DECODE_PRINTF("LOOPNE\t");
4019 ip = (s8) fetch_byte_imm();
4020 ip += (s16) M.x86.R_IP;
4021 DECODE_PRINTF2("%04x\n", ip);
4024 if (M.x86.R_CX != 0 && !ACCESS_FLAG(F_ZF)) /* CX != 0 and !ZF */
4026 DECODE_CLEAR_SEGOVR();
4030 /****************************************************************************
4033 ****************************************************************************/
4034 void x86emuOp_loope(u8 X86EMU_UNUSED(op1))
4039 DECODE_PRINTF("LOOPE\t");
4040 ip = (s8) fetch_byte_imm();
4041 ip += (s16) M.x86.R_IP;
4042 DECODE_PRINTF2("%04x\n", ip);
4045 if (M.x86.R_CX != 0 && ACCESS_FLAG(F_ZF)) /* CX != 0 and ZF */
4047 DECODE_CLEAR_SEGOVR();
4051 /****************************************************************************
4054 ****************************************************************************/
4055 void x86emuOp_loop(u8 X86EMU_UNUSED(op1))
4060 DECODE_PRINTF("LOOP\t");
4061 ip = (s8) fetch_byte_imm();
4062 ip += (s16) M.x86.R_IP;
4063 DECODE_PRINTF2("%04x\n", ip);
4066 if (M.x86.R_CX != 0)
4068 DECODE_CLEAR_SEGOVR();
4072 /****************************************************************************
4075 ****************************************************************************/
4076 void x86emuOp_jcxz(u8 X86EMU_UNUSED(op1))
4081 /* jump to byte offset if overflow flag is set */
4083 DECODE_PRINTF("JCXZ\t");
4084 offset = (s8)fetch_byte_imm();
4085 target = (u16)(M.x86.R_IP + offset);
4086 DECODE_PRINTF2("%x\n", target);
4088 if (M.x86.R_CX == 0)
4089 M.x86.R_IP = target;
4090 DECODE_CLEAR_SEGOVR();
4094 /****************************************************************************
4097 ****************************************************************************/
4098 void x86emuOp_in_byte_AL_IMM(u8 X86EMU_UNUSED(op1))
4103 DECODE_PRINTF("IN\t");
4104 port = (u8) fetch_byte_imm();
4105 DECODE_PRINTF2("%x,AL\n", port);
4107 M.x86.R_AL = (*sys_inb)(port);
4108 DECODE_CLEAR_SEGOVR();
4112 /****************************************************************************
4115 ****************************************************************************/
4116 void x86emuOp_in_word_AX_IMM(u8 X86EMU_UNUSED(op1))
4121 DECODE_PRINTF("IN\t");
4122 port = (u8) fetch_byte_imm();
4123 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4124 DECODE_PRINTF2("EAX,%x\n", port);
4126 DECODE_PRINTF2("AX,%x\n", port);
4129 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4130 M.x86.R_EAX = (*sys_inl)(port);
4132 M.x86.R_AX = (*sys_inw)(port);
4134 DECODE_CLEAR_SEGOVR();
4138 /****************************************************************************
4141 ****************************************************************************/
4142 void x86emuOp_out_byte_IMM_AL(u8 X86EMU_UNUSED(op1))
4147 DECODE_PRINTF("OUT\t");
4148 port = (u8) fetch_byte_imm();
4149 DECODE_PRINTF2("%x,AL\n", port);
4151 (*sys_outb)(port, M.x86.R_AL);
4152 DECODE_CLEAR_SEGOVR();
4156 /****************************************************************************
4159 ****************************************************************************/
4160 void x86emuOp_out_word_IMM_AX(u8 X86EMU_UNUSED(op1))
4165 DECODE_PRINTF("OUT\t");
4166 port = (u8) fetch_byte_imm();
4167 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4168 DECODE_PRINTF2("%x,EAX\n", port);
4170 DECODE_PRINTF2("%x,AX\n", port);
4173 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4174 (*sys_outl)(port, M.x86.R_EAX);
4176 (*sys_outw)(port, M.x86.R_AX);
4178 DECODE_CLEAR_SEGOVR();
4182 /****************************************************************************
4185 ****************************************************************************/
4186 void x86emuOp_call_near_IMM(u8 X86EMU_UNUSED(op1))
4191 DECODE_PRINTF("CALL\t");
4192 ip = (s16) fetch_word_imm();
4193 ip += (s16) M.x86.R_IP; /* CHECK SIGN */
4194 DECODE_PRINTF2("%04x\n", ip);
4195 CALL_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, ip, "");
4197 push_word(M.x86.R_IP);
4199 DECODE_CLEAR_SEGOVR();
4203 /****************************************************************************
4206 ****************************************************************************/
4207 void x86emuOp_jump_near_IMM(u8 X86EMU_UNUSED(op1))
4212 DECODE_PRINTF("JMP\t");
4213 ip = (s16)fetch_word_imm();
4214 ip += (s16)M.x86.R_IP;
4215 DECODE_PRINTF2("%04x\n", ip);
4217 M.x86.R_IP = (u16)ip;
4218 DECODE_CLEAR_SEGOVR();
4222 /****************************************************************************
4225 ****************************************************************************/
4226 void x86emuOp_jump_far_IMM(u8 X86EMU_UNUSED(op1))
4231 DECODE_PRINTF("JMP\tFAR ");
4232 ip = fetch_word_imm();
4233 cs = fetch_word_imm();
4234 DECODE_PRINTF2("%04x:", cs);
4235 DECODE_PRINTF2("%04x\n", ip);
4239 DECODE_CLEAR_SEGOVR();
4243 /****************************************************************************
4246 ****************************************************************************/
4247 void x86emuOp_jump_byte_IMM(u8 X86EMU_UNUSED(op1))
4253 DECODE_PRINTF("JMP\t");
4254 offset = (s8)fetch_byte_imm();
4255 target = (u16)(M.x86.R_IP + offset);
4256 DECODE_PRINTF2("%x\n", target);
4258 M.x86.R_IP = target;
4259 DECODE_CLEAR_SEGOVR();
4263 /****************************************************************************
4266 ****************************************************************************/
4267 void x86emuOp_in_byte_AL_DX(u8 X86EMU_UNUSED(op1))
4270 DECODE_PRINTF("IN\tAL,DX\n");
4272 M.x86.R_AL = (*sys_inb)(M.x86.R_DX);
4273 DECODE_CLEAR_SEGOVR();
4277 /****************************************************************************
4280 ****************************************************************************/
4281 void x86emuOp_in_word_AX_DX(u8 X86EMU_UNUSED(op1))
4284 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4285 DECODE_PRINTF("IN\tEAX,DX\n");
4287 DECODE_PRINTF("IN\tAX,DX\n");
4290 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4291 M.x86.R_EAX = (*sys_inl)(M.x86.R_DX);
4293 M.x86.R_AX = (*sys_inw)(M.x86.R_DX);
4295 DECODE_CLEAR_SEGOVR();
4299 /****************************************************************************
4302 ****************************************************************************/
4303 void x86emuOp_out_byte_DX_AL(u8 X86EMU_UNUSED(op1))
4306 DECODE_PRINTF("OUT\tDX,AL\n");
4308 (*sys_outb)(M.x86.R_DX, M.x86.R_AL);
4309 DECODE_CLEAR_SEGOVR();
4313 /****************************************************************************
4316 ****************************************************************************/
4317 void x86emuOp_out_word_DX_AX(u8 X86EMU_UNUSED(op1))
4320 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4321 DECODE_PRINTF("OUT\tDX,EAX\n");
4323 DECODE_PRINTF("OUT\tDX,AX\n");
4326 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4327 (*sys_outl)(M.x86.R_DX, M.x86.R_EAX);
4329 (*sys_outw)(M.x86.R_DX, M.x86.R_AX);
4331 DECODE_CLEAR_SEGOVR();
4335 /****************************************************************************
4338 ****************************************************************************/
4339 void x86emuOp_lock(u8 X86EMU_UNUSED(op1))
4342 DECODE_PRINTF("LOCK:\n");
4344 DECODE_CLEAR_SEGOVR();
4348 /*opcode 0xf1 ILLEGAL OPERATION */
4350 /****************************************************************************
4353 ****************************************************************************/
4354 void x86emuOp_repne(u8 X86EMU_UNUSED(op1))
4357 DECODE_PRINTF("REPNE\n");
4359 M.x86.mode |= SYSMODE_PREFIX_REPNE;
4360 DECODE_CLEAR_SEGOVR();
4364 /****************************************************************************
4367 ****************************************************************************/
4368 void x86emuOp_repe(u8 X86EMU_UNUSED(op1))
4371 DECODE_PRINTF("REPE\n");
4373 M.x86.mode |= SYSMODE_PREFIX_REPE;
4374 DECODE_CLEAR_SEGOVR();
4378 /****************************************************************************
4381 ****************************************************************************/
4382 void x86emuOp_halt(u8 X86EMU_UNUSED(op1))
4385 DECODE_PRINTF("HALT\n");
4388 DECODE_CLEAR_SEGOVR();
4392 /****************************************************************************
4395 ****************************************************************************/
4396 void x86emuOp_cmc(u8 X86EMU_UNUSED(op1))
4398 /* complement the carry flag. */
4400 DECODE_PRINTF("CMC\n");
4403 DECODE_CLEAR_SEGOVR();
4407 /****************************************************************************
4410 ****************************************************************************/
4411 void x86emuOp_opcF6_byte_RM(u8 X86EMU_UNUSED(op1))
4418 /* long, drawn out code follows. Double switch for a total
4421 FETCH_DECODE_MODRM(mod, rh, rl);
4422 DECODE_PRINTF(opF6_names[rh]);
4424 DECODE_PRINTF("BYTE PTR ");
4425 destoffset = decode_rmXX_address(mod, rl);
4426 destval = fetch_data_byte(destoffset);
4429 case 0: /* test byte imm */
4431 srcval = fetch_byte_imm();
4432 DECODE_PRINTF2("%02x\n", srcval);
4434 test_byte(destval, srcval);
4437 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4441 DECODE_PRINTF("\n");
4443 destval = not_byte(destval);
4444 store_data_byte(destoffset, destval);
4447 DECODE_PRINTF("\n");
4449 destval = neg_byte(destval);
4450 store_data_byte(destoffset, destval);
4453 DECODE_PRINTF("\n");
4458 DECODE_PRINTF("\n");
4463 DECODE_PRINTF("\n");
4468 DECODE_PRINTF("\n");
4473 } else { /* mod=11 */
4474 destreg = DECODE_RM_BYTE_REGISTER(rl);
4476 case 0: /* test byte imm */
4478 srcval = fetch_byte_imm();
4479 DECODE_PRINTF2("%02x\n", srcval);
4481 test_byte(*destreg, srcval);
4484 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4488 DECODE_PRINTF("\n");
4490 *destreg = not_byte(*destreg);
4493 DECODE_PRINTF("\n");
4495 *destreg = neg_byte(*destreg);
4498 DECODE_PRINTF("\n");
4500 mul_byte(*destreg); /*!!! */
4503 DECODE_PRINTF("\n");
4505 imul_byte(*destreg);
4508 DECODE_PRINTF("\n");
4513 DECODE_PRINTF("\n");
4515 idiv_byte(*destreg);
4519 DECODE_CLEAR_SEGOVR();
4523 /****************************************************************************
4526 ****************************************************************************/
4527 void x86emuOp_opcF7_word_RM(u8 X86EMU_UNUSED(op1))
4533 FETCH_DECODE_MODRM(mod, rh, rl);
4534 DECODE_PRINTF(opF6_names[rh]);
4537 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4538 u32 destval, srcval;
4540 DECODE_PRINTF("DWORD PTR ");
4541 destoffset = decode_rmXX_address(mod, rl);
4542 destval = fetch_data_long(destoffset);
4547 srcval = fetch_long_imm();
4548 DECODE_PRINTF2("%x\n", srcval);
4550 test_long(destval, srcval);
4553 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F7\n");
4557 DECODE_PRINTF("\n");
4559 destval = not_long(destval);
4560 store_data_long(destoffset, destval);
4563 DECODE_PRINTF("\n");
4565 destval = neg_long(destval);
4566 store_data_long(destoffset, destval);
4569 DECODE_PRINTF("\n");
4574 DECODE_PRINTF("\n");
4579 DECODE_PRINTF("\n");
4584 DECODE_PRINTF("\n");
4590 u16 destval, srcval;
4592 DECODE_PRINTF("WORD PTR ");
4593 destoffset = decode_rmXX_address(mod, rl);
4594 destval = fetch_data_word(destoffset);
4597 case 0: /* test word imm */
4599 srcval = fetch_word_imm();
4600 DECODE_PRINTF2("%x\n", srcval);
4602 test_word(destval, srcval);
4605 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F7\n");
4609 DECODE_PRINTF("\n");
4611 destval = not_word(destval);
4612 store_data_word(destoffset, destval);
4615 DECODE_PRINTF("\n");
4617 destval = neg_word(destval);
4618 store_data_word(destoffset, destval);
4621 DECODE_PRINTF("\n");
4626 DECODE_PRINTF("\n");
4631 DECODE_PRINTF("\n");
4636 DECODE_PRINTF("\n");
4643 } else { /* mod=11 */
4645 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4649 destreg = DECODE_RM_LONG_REGISTER(rl);
4652 case 0: /* test word imm */
4654 srcval = fetch_long_imm();
4655 DECODE_PRINTF2("%x\n", srcval);
4657 test_long(*destreg, srcval);
4660 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4664 DECODE_PRINTF("\n");
4666 *destreg = not_long(*destreg);
4669 DECODE_PRINTF("\n");
4671 *destreg = neg_long(*destreg);
4674 DECODE_PRINTF("\n");
4676 mul_long(*destreg); /*!!! */
4679 DECODE_PRINTF("\n");
4681 imul_long(*destreg);
4684 DECODE_PRINTF("\n");
4689 DECODE_PRINTF("\n");
4691 idiv_long(*destreg);
4698 destreg = DECODE_RM_WORD_REGISTER(rl);
4701 case 0: /* test word imm */
4703 srcval = fetch_word_imm();
4704 DECODE_PRINTF2("%x\n", srcval);
4706 test_word(*destreg, srcval);
4709 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4713 DECODE_PRINTF("\n");
4715 *destreg = not_word(*destreg);
4718 DECODE_PRINTF("\n");
4720 *destreg = neg_word(*destreg);
4723 DECODE_PRINTF("\n");
4725 mul_word(*destreg); /*!!! */
4728 DECODE_PRINTF("\n");
4730 imul_word(*destreg);
4733 DECODE_PRINTF("\n");
4738 DECODE_PRINTF("\n");
4740 idiv_word(*destreg);
4745 DECODE_CLEAR_SEGOVR();
4749 /****************************************************************************
4752 ****************************************************************************/
4753 void x86emuOp_clc(u8 X86EMU_UNUSED(op1))
4755 /* clear the carry flag. */
4757 DECODE_PRINTF("CLC\n");
4760 DECODE_CLEAR_SEGOVR();
4764 /****************************************************************************
4767 ****************************************************************************/
4768 void x86emuOp_stc(u8 X86EMU_UNUSED(op1))
4770 /* set the carry flag. */
4772 DECODE_PRINTF("STC\n");
4775 DECODE_CLEAR_SEGOVR();
4779 /****************************************************************************
4782 ****************************************************************************/
4783 void x86emuOp_cli(u8 X86EMU_UNUSED(op1))
4785 /* clear interrupts. */
4787 DECODE_PRINTF("CLI\n");
4790 DECODE_CLEAR_SEGOVR();
4794 /****************************************************************************
4797 ****************************************************************************/
4798 void x86emuOp_sti(u8 X86EMU_UNUSED(op1))
4800 /* enable interrupts. */
4802 DECODE_PRINTF("STI\n");
4805 DECODE_CLEAR_SEGOVR();
4809 /****************************************************************************
4812 ****************************************************************************/
4813 void x86emuOp_cld(u8 X86EMU_UNUSED(op1))
4815 /* clear interrupts. */
4817 DECODE_PRINTF("CLD\n");
4820 DECODE_CLEAR_SEGOVR();
4824 /****************************************************************************
4827 ****************************************************************************/
4828 void x86emuOp_std(u8 X86EMU_UNUSED(op1))
4830 /* clear interrupts. */
4832 DECODE_PRINTF("STD\n");
4835 DECODE_CLEAR_SEGOVR();
4839 /****************************************************************************
4842 ****************************************************************************/
4843 void x86emuOp_opcFE_byte_RM(u8 X86EMU_UNUSED(op1))
4850 /* Yet another special case instruction. */
4852 FETCH_DECODE_MODRM(mod, rh, rl);
4854 if (DEBUG_DECODE()) {
4855 /* XXX DECODE_PRINTF may be changed to something more
4856 general, so that it is important to leave the strings
4857 in the same format, even though the result is that the
4858 above test is done twice. */
4862 DECODE_PRINTF("INC\t");
4865 DECODE_PRINTF("DEC\t");
4873 DECODE_PRINTF2("ILLEGAL OP MAJOR OP 0xFE MINOR OP %x \n", mod);
4880 DECODE_PRINTF("BYTE PTR ");
4881 destoffset = decode_rmXX_address(mod, rl);
4882 DECODE_PRINTF("\n");
4883 destval = fetch_data_byte(destoffset);
4886 destval = inc_byte(destval);
4888 destval = dec_byte(destval);
4889 store_data_byte(destoffset, destval);
4891 destreg = DECODE_RM_BYTE_REGISTER(rl);
4892 DECODE_PRINTF("\n");
4895 *destreg = inc_byte(*destreg);
4897 *destreg = dec_byte(*destreg);
4899 DECODE_CLEAR_SEGOVR();
4903 /****************************************************************************
4906 ****************************************************************************/
4907 void x86emuOp_opcFF_word_RM(u8 X86EMU_UNUSED(op1))
4910 uint destoffset = 0;
4912 u16 destval,destval2;
4914 /* Yet another special case instruction. */
4916 FETCH_DECODE_MODRM(mod, rh, rl);
4918 if (DEBUG_DECODE()) {
4919 /* XXX DECODE_PRINTF may be changed to something more
4920 general, so that it is important to leave the strings
4921 in the same format, even though the result is that the
4922 above test is done twice. */
4926 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4927 DECODE_PRINTF("INC\tDWORD PTR ");
4929 DECODE_PRINTF("INC\tWORD PTR ");
4933 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4934 DECODE_PRINTF("DEC\tDWORD PTR ");
4936 DECODE_PRINTF("DEC\tWORD PTR ");
4940 DECODE_PRINTF("CALL\t ");
4943 DECODE_PRINTF("CALL\tFAR ");
4946 DECODE_PRINTF("JMP\t");
4949 DECODE_PRINTF("JMP\tFAR ");
4952 DECODE_PRINTF("PUSH\t");
4955 DECODE_PRINTF("ILLEGAL DECODING OF OPCODE FF\t");
4962 destoffset = decode_rmXX_address(mod, rl);
4963 DECODE_PRINTF("\n");
4965 case 0: /* inc word ptr ... */
4966 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4969 destval = fetch_data_long(destoffset);
4971 destval = inc_long(destval);
4972 store_data_long(destoffset, destval);
4976 destval = fetch_data_word(destoffset);
4978 destval = inc_word(destval);
4979 store_data_word(destoffset, destval);
4982 case 1: /* dec word ptr ... */
4983 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4986 destval = fetch_data_long(destoffset);
4988 destval = dec_long(destval);
4989 store_data_long(destoffset, destval);
4993 destval = fetch_data_word(destoffset);
4995 destval = dec_word(destval);
4996 store_data_word(destoffset, destval);
4999 case 2: /* call word ptr ... */
5000 destval = fetch_data_word(destoffset);
5002 push_word(M.x86.R_IP);
5003 M.x86.R_IP = destval;
5005 case 3: /* call far ptr ... */
5006 destval = fetch_data_word(destoffset);
5007 destval2 = fetch_data_word(destoffset + 2);
5009 push_word(M.x86.R_CS);
5010 M.x86.R_CS = destval2;
5011 push_word(M.x86.R_IP);
5012 M.x86.R_IP = destval;
5014 case 4: /* jmp word ptr ... */
5015 destval = fetch_data_word(destoffset);
5017 M.x86.R_IP = destval;
5019 case 5: /* jmp far ptr ... */
5020 destval = fetch_data_word(destoffset);
5021 destval2 = fetch_data_word(destoffset + 2);
5023 M.x86.R_IP = destval;
5024 M.x86.R_CS = destval2;
5026 case 6: /* push word ptr ... */
5027 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5030 destval = fetch_data_long(destoffset);
5036 destval = fetch_data_word(destoffset);
5045 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5048 destreg = DECODE_RM_LONG_REGISTER(rl);
5049 DECODE_PRINTF("\n");
5051 *destreg = inc_long(*destreg);
5055 destreg = DECODE_RM_WORD_REGISTER(rl);
5056 DECODE_PRINTF("\n");
5058 *destreg = inc_word(*destreg);
5062 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5065 destreg = DECODE_RM_LONG_REGISTER(rl);
5066 DECODE_PRINTF("\n");
5068 *destreg = dec_long(*destreg);
5072 destreg = DECODE_RM_WORD_REGISTER(rl);
5073 DECODE_PRINTF("\n");
5075 *destreg = dec_word(*destreg);
5078 case 2: /* call word ptr ... */
5079 destreg = DECODE_RM_WORD_REGISTER(rl);
5080 DECODE_PRINTF("\n");
5082 push_word(M.x86.R_IP);
5083 M.x86.R_IP = *destreg;
5085 case 3: /* jmp far ptr ... */
5086 DECODE_PRINTF("OPERATION UNDEFINED 0XFF \n");
5091 case 4: /* jmp ... */
5092 destreg = DECODE_RM_WORD_REGISTER(rl);
5093 DECODE_PRINTF("\n");
5095 M.x86.R_IP = (u16) (*destreg);
5097 case 5: /* jmp far ptr ... */
5098 DECODE_PRINTF("OPERATION UNDEFINED 0XFF \n");
5103 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5106 destreg = DECODE_RM_LONG_REGISTER(rl);
5107 DECODE_PRINTF("\n");
5109 push_long(*destreg);
5113 destreg = DECODE_RM_WORD_REGISTER(rl);
5114 DECODE_PRINTF("\n");
5116 push_word(*destreg);
5121 DECODE_CLEAR_SEGOVR();
5125 /***************************************************************************
5126 * Single byte operation code table:
5127 **************************************************************************/
5128 void (*x86emu_optab[256])(u8) =
5130 /* 0x00 */ x86emuOp_genop_byte_RM_R,
5131 /* 0x01 */ x86emuOp_genop_word_RM_R,
5132 /* 0x02 */ x86emuOp_genop_byte_R_RM,
5133 /* 0x03 */ x86emuOp_genop_word_R_RM,
5134 /* 0x04 */ x86emuOp_genop_byte_AL_IMM,
5135 /* 0x05 */ x86emuOp_genop_word_AX_IMM,
5136 /* 0x06 */ x86emuOp_push_ES,
5137 /* 0x07 */ x86emuOp_pop_ES,
5139 /* 0x08 */ x86emuOp_genop_byte_RM_R,
5140 /* 0x09 */ x86emuOp_genop_word_RM_R,
5141 /* 0x0a */ x86emuOp_genop_byte_R_RM,
5142 /* 0x0b */ x86emuOp_genop_word_R_RM,
5143 /* 0x0c */ x86emuOp_genop_byte_AL_IMM,
5144 /* 0x0d */ x86emuOp_genop_word_AX_IMM,
5145 /* 0x0e */ x86emuOp_push_CS,
5146 /* 0x0f */ x86emuOp_two_byte,
5148 /* 0x10 */ x86emuOp_genop_byte_RM_R,
5149 /* 0x11 */ x86emuOp_genop_word_RM_R,
5150 /* 0x12 */ x86emuOp_genop_byte_R_RM,
5151 /* 0x13 */ x86emuOp_genop_word_R_RM,
5152 /* 0x14 */ x86emuOp_genop_byte_AL_IMM,
5153 /* 0x15 */ x86emuOp_genop_word_AX_IMM,
5154 /* 0x16 */ x86emuOp_push_SS,
5155 /* 0x17 */ x86emuOp_pop_SS,
5157 /* 0x18 */ x86emuOp_genop_byte_RM_R,
5158 /* 0x19 */ x86emuOp_genop_word_RM_R,
5159 /* 0x1a */ x86emuOp_genop_byte_R_RM,
5160 /* 0x1b */ x86emuOp_genop_word_R_RM,
5161 /* 0x1c */ x86emuOp_genop_byte_AL_IMM,
5162 /* 0x1d */ x86emuOp_genop_word_AX_IMM,
5163 /* 0x1e */ x86emuOp_push_DS,
5164 /* 0x1f */ x86emuOp_pop_DS,
5166 /* 0x20 */ x86emuOp_genop_byte_RM_R,
5167 /* 0x21 */ x86emuOp_genop_word_RM_R,
5168 /* 0x22 */ x86emuOp_genop_byte_R_RM,
5169 /* 0x23 */ x86emuOp_genop_word_R_RM,
5170 /* 0x24 */ x86emuOp_genop_byte_AL_IMM,
5171 /* 0x25 */ x86emuOp_genop_word_AX_IMM,
5172 /* 0x26 */ x86emuOp_segovr_ES,
5173 /* 0x27 */ x86emuOp_daa,
5175 /* 0x28 */ x86emuOp_genop_byte_RM_R,
5176 /* 0x29 */ x86emuOp_genop_word_RM_R,
5177 /* 0x2a */ x86emuOp_genop_byte_R_RM,
5178 /* 0x2b */ x86emuOp_genop_word_R_RM,
5179 /* 0x2c */ x86emuOp_genop_byte_AL_IMM,
5180 /* 0x2d */ x86emuOp_genop_word_AX_IMM,
5181 /* 0x2e */ x86emuOp_segovr_CS,
5182 /* 0x2f */ x86emuOp_das,
5184 /* 0x30 */ x86emuOp_genop_byte_RM_R,
5185 /* 0x31 */ x86emuOp_genop_word_RM_R,
5186 /* 0x32 */ x86emuOp_genop_byte_R_RM,
5187 /* 0x33 */ x86emuOp_genop_word_R_RM,
5188 /* 0x34 */ x86emuOp_genop_byte_AL_IMM,
5189 /* 0x35 */ x86emuOp_genop_word_AX_IMM,
5190 /* 0x36 */ x86emuOp_segovr_SS,
5191 /* 0x37 */ x86emuOp_aaa,
5193 /* 0x38 */ x86emuOp_genop_byte_RM_R,
5194 /* 0x39 */ x86emuOp_genop_word_RM_R,
5195 /* 0x3a */ x86emuOp_genop_byte_R_RM,
5196 /* 0x3b */ x86emuOp_genop_word_R_RM,
5197 /* 0x3c */ x86emuOp_genop_byte_AL_IMM,
5198 /* 0x3d */ x86emuOp_genop_word_AX_IMM,
5199 /* 0x3e */ x86emuOp_segovr_DS,
5200 /* 0x3f */ x86emuOp_aas,
5202 /* 0x40 */ x86emuOp_inc_register,
5203 /* 0x41 */ x86emuOp_inc_register,
5204 /* 0x42 */ x86emuOp_inc_register,
5205 /* 0x43 */ x86emuOp_inc_register,
5206 /* 0x44 */ x86emuOp_inc_register,
5207 /* 0x45 */ x86emuOp_inc_register,
5208 /* 0x46 */ x86emuOp_inc_register,
5209 /* 0x47 */ x86emuOp_inc_register,
5211 /* 0x48 */ x86emuOp_dec_register,
5212 /* 0x49 */ x86emuOp_dec_register,
5213 /* 0x4a */ x86emuOp_dec_register,
5214 /* 0x4b */ x86emuOp_dec_register,
5215 /* 0x4c */ x86emuOp_dec_register,
5216 /* 0x4d */ x86emuOp_dec_register,
5217 /* 0x4e */ x86emuOp_dec_register,
5218 /* 0x4f */ x86emuOp_dec_register,
5220 /* 0x50 */ x86emuOp_push_register,
5221 /* 0x51 */ x86emuOp_push_register,
5222 /* 0x52 */ x86emuOp_push_register,
5223 /* 0x53 */ x86emuOp_push_register,
5224 /* 0x54 */ x86emuOp_push_register,
5225 /* 0x55 */ x86emuOp_push_register,
5226 /* 0x56 */ x86emuOp_push_register,
5227 /* 0x57 */ x86emuOp_push_register,
5229 /* 0x58 */ x86emuOp_pop_register,
5230 /* 0x59 */ x86emuOp_pop_register,
5231 /* 0x5a */ x86emuOp_pop_register,
5232 /* 0x5b */ x86emuOp_pop_register,
5233 /* 0x5c */ x86emuOp_pop_register,
5234 /* 0x5d */ x86emuOp_pop_register,
5235 /* 0x5e */ x86emuOp_pop_register,
5236 /* 0x5f */ x86emuOp_pop_register,
5238 /* 0x60 */ x86emuOp_push_all,
5239 /* 0x61 */ x86emuOp_pop_all,
5240 /* 0x62 */ x86emuOp_illegal_op, /* bound */
5241 /* 0x63 */ x86emuOp_illegal_op, /* arpl */
5242 /* 0x64 */ x86emuOp_segovr_FS,
5243 /* 0x65 */ x86emuOp_segovr_GS,
5244 /* 0x66 */ x86emuOp_prefix_data,
5245 /* 0x67 */ x86emuOp_prefix_addr,
5247 /* 0x68 */ x86emuOp_push_word_IMM,
5248 /* 0x69 */ x86emuOp_imul_word_IMM,
5249 /* 0x6a */ x86emuOp_push_byte_IMM,
5250 /* 0x6b */ x86emuOp_imul_byte_IMM,
5251 /* 0x6c */ x86emuOp_ins_byte,
5252 /* 0x6d */ x86emuOp_ins_word,
5253 /* 0x6e */ x86emuOp_outs_byte,
5254 /* 0x6f */ x86emuOp_outs_word,
5256 /* 0x70 */ x86emuOp_jump_near_cond,
5257 /* 0x71 */ x86emuOp_jump_near_cond,
5258 /* 0x72 */ x86emuOp_jump_near_cond,
5259 /* 0x73 */ x86emuOp_jump_near_cond,
5260 /* 0x74 */ x86emuOp_jump_near_cond,
5261 /* 0x75 */ x86emuOp_jump_near_cond,
5262 /* 0x76 */ x86emuOp_jump_near_cond,
5263 /* 0x77 */ x86emuOp_jump_near_cond,
5265 /* 0x78 */ x86emuOp_jump_near_cond,
5266 /* 0x79 */ x86emuOp_jump_near_cond,
5267 /* 0x7a */ x86emuOp_jump_near_cond,
5268 /* 0x7b */ x86emuOp_jump_near_cond,
5269 /* 0x7c */ x86emuOp_jump_near_cond,
5270 /* 0x7d */ x86emuOp_jump_near_cond,
5271 /* 0x7e */ x86emuOp_jump_near_cond,
5272 /* 0x7f */ x86emuOp_jump_near_cond,
5274 /* 0x80 */ x86emuOp_opc80_byte_RM_IMM,
5275 /* 0x81 */ x86emuOp_opc81_word_RM_IMM,
5276 /* 0x82 */ x86emuOp_opc82_byte_RM_IMM,
5277 /* 0x83 */ x86emuOp_opc83_word_RM_IMM,
5278 /* 0x84 */ x86emuOp_test_byte_RM_R,
5279 /* 0x85 */ x86emuOp_test_word_RM_R,
5280 /* 0x86 */ x86emuOp_xchg_byte_RM_R,
5281 /* 0x87 */ x86emuOp_xchg_word_RM_R,
5283 /* 0x88 */ x86emuOp_mov_byte_RM_R,
5284 /* 0x89 */ x86emuOp_mov_word_RM_R,
5285 /* 0x8a */ x86emuOp_mov_byte_R_RM,
5286 /* 0x8b */ x86emuOp_mov_word_R_RM,
5287 /* 0x8c */ x86emuOp_mov_word_RM_SR,
5288 /* 0x8d */ x86emuOp_lea_word_R_M,
5289 /* 0x8e */ x86emuOp_mov_word_SR_RM,
5290 /* 0x8f */ x86emuOp_pop_RM,
5292 /* 0x90 */ x86emuOp_nop,
5293 /* 0x91 */ x86emuOp_xchg_word_AX_register,
5294 /* 0x92 */ x86emuOp_xchg_word_AX_register,
5295 /* 0x93 */ x86emuOp_xchg_word_AX_register,
5296 /* 0x94 */ x86emuOp_xchg_word_AX_register,
5297 /* 0x95 */ x86emuOp_xchg_word_AX_register,
5298 /* 0x96 */ x86emuOp_xchg_word_AX_register,
5299 /* 0x97 */ x86emuOp_xchg_word_AX_register,
5301 /* 0x98 */ x86emuOp_cbw,
5302 /* 0x99 */ x86emuOp_cwd,
5303 /* 0x9a */ x86emuOp_call_far_IMM,
5304 /* 0x9b */ x86emuOp_wait,
5305 /* 0x9c */ x86emuOp_pushf_word,
5306 /* 0x9d */ x86emuOp_popf_word,
5307 /* 0x9e */ x86emuOp_sahf,
5308 /* 0x9f */ x86emuOp_lahf,
5310 /* 0xa0 */ x86emuOp_mov_AL_M_IMM,
5311 /* 0xa1 */ x86emuOp_mov_AX_M_IMM,
5312 /* 0xa2 */ x86emuOp_mov_M_AL_IMM,
5313 /* 0xa3 */ x86emuOp_mov_M_AX_IMM,
5314 /* 0xa4 */ x86emuOp_movs_byte,
5315 /* 0xa5 */ x86emuOp_movs_word,
5316 /* 0xa6 */ x86emuOp_cmps_byte,
5317 /* 0xa7 */ x86emuOp_cmps_word,
5318 /* 0xa8 */ x86emuOp_test_AL_IMM,
5319 /* 0xa9 */ x86emuOp_test_AX_IMM,
5320 /* 0xaa */ x86emuOp_stos_byte,
5321 /* 0xab */ x86emuOp_stos_word,
5322 /* 0xac */ x86emuOp_lods_byte,
5323 /* 0xad */ x86emuOp_lods_word,
5324 /* 0xac */ x86emuOp_scas_byte,
5325 /* 0xad */ x86emuOp_scas_word,
5327 /* 0xb0 */ x86emuOp_mov_byte_register_IMM,
5328 /* 0xb1 */ x86emuOp_mov_byte_register_IMM,
5329 /* 0xb2 */ x86emuOp_mov_byte_register_IMM,
5330 /* 0xb3 */ x86emuOp_mov_byte_register_IMM,
5331 /* 0xb4 */ x86emuOp_mov_byte_register_IMM,
5332 /* 0xb5 */ x86emuOp_mov_byte_register_IMM,
5333 /* 0xb6 */ x86emuOp_mov_byte_register_IMM,
5334 /* 0xb7 */ x86emuOp_mov_byte_register_IMM,
5336 /* 0xb8 */ x86emuOp_mov_word_register_IMM,
5337 /* 0xb9 */ x86emuOp_mov_word_register_IMM,
5338 /* 0xba */ x86emuOp_mov_word_register_IMM,
5339 /* 0xbb */ x86emuOp_mov_word_register_IMM,
5340 /* 0xbc */ x86emuOp_mov_word_register_IMM,
5341 /* 0xbd */ x86emuOp_mov_word_register_IMM,
5342 /* 0xbe */ x86emuOp_mov_word_register_IMM,
5343 /* 0xbf */ x86emuOp_mov_word_register_IMM,
5345 /* 0xc0 */ x86emuOp_opcC0_byte_RM_MEM,
5346 /* 0xc1 */ x86emuOp_opcC1_word_RM_MEM,
5347 /* 0xc2 */ x86emuOp_ret_near_IMM,
5348 /* 0xc3 */ x86emuOp_ret_near,
5349 /* 0xc4 */ x86emuOp_les_R_IMM,
5350 /* 0xc5 */ x86emuOp_lds_R_IMM,
5351 /* 0xc6 */ x86emuOp_mov_byte_RM_IMM,
5352 /* 0xc7 */ x86emuOp_mov_word_RM_IMM,
5353 /* 0xc8 */ x86emuOp_enter,
5354 /* 0xc9 */ x86emuOp_leave,
5355 /* 0xca */ x86emuOp_ret_far_IMM,
5356 /* 0xcb */ x86emuOp_ret_far,
5357 /* 0xcc */ x86emuOp_int3,
5358 /* 0xcd */ x86emuOp_int_IMM,
5359 /* 0xce */ x86emuOp_into,
5360 /* 0xcf */ x86emuOp_iret,
5362 /* 0xd0 */ x86emuOp_opcD0_byte_RM_1,
5363 /* 0xd1 */ x86emuOp_opcD1_word_RM_1,
5364 /* 0xd2 */ x86emuOp_opcD2_byte_RM_CL,
5365 /* 0xd3 */ x86emuOp_opcD3_word_RM_CL,
5366 /* 0xd4 */ x86emuOp_aam,
5367 /* 0xd5 */ x86emuOp_aad,
5368 /* 0xd6 */ x86emuOp_illegal_op, /* Undocumented SETALC instruction */
5369 /* 0xd7 */ x86emuOp_xlat,
5370 /* 0xd8 */ x86emuOp_esc_coprocess_d8,
5371 /* 0xd9 */ x86emuOp_esc_coprocess_d9,
5372 /* 0xda */ x86emuOp_esc_coprocess_da,
5373 /* 0xdb */ x86emuOp_esc_coprocess_db,
5374 /* 0xdc */ x86emuOp_esc_coprocess_dc,
5375 /* 0xdd */ x86emuOp_esc_coprocess_dd,
5376 /* 0xde */ x86emuOp_esc_coprocess_de,
5377 /* 0xdf */ x86emuOp_esc_coprocess_df,
5379 /* 0xe0 */ x86emuOp_loopne,
5380 /* 0xe1 */ x86emuOp_loope,
5381 /* 0xe2 */ x86emuOp_loop,
5382 /* 0xe3 */ x86emuOp_jcxz,
5383 /* 0xe4 */ x86emuOp_in_byte_AL_IMM,
5384 /* 0xe5 */ x86emuOp_in_word_AX_IMM,
5385 /* 0xe6 */ x86emuOp_out_byte_IMM_AL,
5386 /* 0xe7 */ x86emuOp_out_word_IMM_AX,
5388 /* 0xe8 */ x86emuOp_call_near_IMM,
5389 /* 0xe9 */ x86emuOp_jump_near_IMM,
5390 /* 0xea */ x86emuOp_jump_far_IMM,
5391 /* 0xeb */ x86emuOp_jump_byte_IMM,
5392 /* 0xec */ x86emuOp_in_byte_AL_DX,
5393 /* 0xed */ x86emuOp_in_word_AX_DX,
5394 /* 0xee */ x86emuOp_out_byte_DX_AL,
5395 /* 0xef */ x86emuOp_out_word_DX_AX,
5397 /* 0xf0 */ x86emuOp_lock,
5398 /* 0xf1 */ x86emuOp_illegal_op,
5399 /* 0xf2 */ x86emuOp_repne,
5400 /* 0xf3 */ x86emuOp_repe,
5401 /* 0xf4 */ x86emuOp_halt,
5402 /* 0xf5 */ x86emuOp_cmc,
5403 /* 0xf6 */ x86emuOp_opcF6_byte_RM,
5404 /* 0xf7 */ x86emuOp_opcF7_word_RM,
5406 /* 0xf8 */ x86emuOp_clc,
5407 /* 0xf9 */ x86emuOp_stc,
5408 /* 0xfa */ x86emuOp_cli,
5409 /* 0xfb */ x86emuOp_sti,
5410 /* 0xfc */ x86emuOp_cld,
5411 /* 0xfd */ x86emuOp_std,
5412 /* 0xfe */ x86emuOp_opcFE_byte_RM,
5413 /* 0xff */ x86emuOp_opcFF_word_RM,