1 /****************************************************************************
2 * Realmode X86 Emulator Library
4 * Copyright (C) 2007 Freescale Semiconductor, Inc.
5 * Jason Jin <Jason.jin@freescale.com>
7 * Copyright (C) 1991-2004 SciTech Software, Inc.
8 * Copyright (C) David Mosberger-Tang
9 * Copyright (C) 1999 Egbert Eich
11 * ========================================================================
13 * Permission to use, copy, modify, distribute, and sell this software and
14 * its documentation for any purpose is hereby granted without fee,
15 * provided that the above copyright notice appear in all copies and that
16 * both that copyright notice and this permission notice appear in
17 * supporting documentation, and that the name of the authors not be used
18 * in advertising or publicity pertaining to distribution of the software
19 * without specific, written prior permission. The authors makes no
20 * representations about the suitability of this software for any purpose.
21 * It is provided "as is" without express or implied warranty.
23 * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
24 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
25 * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
26 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
27 * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
28 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
29 * PERFORMANCE OF THIS SOFTWARE.
31 * ========================================================================
35 * Developer: Kendall Bennett
37 * Description: This file includes subroutines to implement the decoding
38 * and emulation of all the x86 processor instructions.
40 * There are approximately 250 subroutines in here, which correspond
41 * to the 256 byte-"opcodes" found on the 8086. The table which
42 * dispatches this is found in the files optab.[ch].
44 * Each opcode proc has a comment preceeding it which gives it's table
45 * address. Several opcodes are missing (undefined) in the table.
47 * Each proc includes information for decoding (DECODE_PRINTF and
48 * DECODE_PRINTF2), debugging (TRACE_REGS, SINGLE_STEP), and misc
49 * functions (START_OF_INSTR, END_OF_INSTR).
51 * Many of the procedures are *VERY* similar in coding. This has
52 * allowed for a very large amount of code to be generated in a fairly
53 * short amount of time (i.e. cut, paste, and modify). The result is
54 * that much of the code below could have been folded into subroutines
55 * for a large reduction in size of this file. The downside would be
56 * that there would be a penalty in execution speed. The file could
57 * also have been *MUCH* larger by inlining certain functions which
58 * were called. This could have resulted even faster execution. The
59 * prime directive I used to decide whether to inline the code or to
60 * modularize it, was basically: 1) no unnecessary subroutine calls,
61 * 2) no routines more than about 200 lines in size, and 3) modularize
62 * any code that I might not get right the first time. The fetch_*
63 * subroutines fall into the latter category. The The decode_* fall
64 * into the second category. The coding of the "switch(mod){ .... }"
65 * in many of the subroutines below falls into the first category.
66 * Especially, the coding of {add,and,or,sub,...}_{byte,word}
67 * subroutines are an especially glaring case of the third guideline.
68 * Since so much of the code is cloned from other modules (compare
69 * opcode #00 to opcode #01), making the basic operations subroutine
70 * calls is especially important; otherwise mistakes in coding an
71 * "add" would represent a nightmare in maintenance.
73 ****************************************************************************/
76 #include "x86emu/x86emui.h"
78 /*----------------------------- Implementation ----------------------------*/
80 /* constant arrays to do several instructions in just one function */
83 static char *x86emu_GenOpName[8] = {
84 "ADD", "OR", "ADC", "SBB", "AND", "SUB", "XOR", "CMP"};
87 /* used by several opcodes */
88 static u8 (*genop_byte_operation[])(u8 d, u8 s) =
100 static u16 (*genop_word_operation[])(u16 d, u16 s) =
112 static u32 (*genop_long_operation[])(u32 d, u32 s) =
124 /* used by opcodes 80, c0, d0, and d2. */
125 static u8(*opcD0_byte_operation[])(u8 d, u8 s) =
133 shl_byte, /* sal_byte === shl_byte by definition */
137 /* used by opcodes c1, d1, and d3. */
138 static u16(*opcD1_word_operation[])(u16 s, u8 d) =
146 shl_word, /* sal_byte === shl_byte by definition */
150 /* used by opcodes c1, d1, and d3. */
151 static u32 (*opcD1_long_operation[])(u32 s, u8 d) =
159 shl_long, /* sal_byte === shl_byte by definition */
165 static char *opF6_names[8] =
166 { "TEST\t", "", "NOT\t", "NEG\t", "MUL\t", "IMUL\t", "DIV\t", "IDIV\t" };
170 /****************************************************************************
172 op1 - Instruction op code
175 Handles illegal opcodes.
176 ****************************************************************************/
177 void x86emuOp_illegal_op(
181 if (M.x86.R_SP != 0) {
182 DECODE_PRINTF("ILLEGAL X86 OPCODE\n");
184 DB( printk("%04x:%04x: %02X ILLEGAL X86 OPCODE!\n",
185 M.x86.R_CS, M.x86.R_IP-1,op1));
189 /* If we get here, it means the stack pointer is back to zero
190 * so we are just returning from an emulator service call
191 * so therte is no need to display an error message. We trap
192 * the emulator with an 0xF1 opcode to finish the service
200 /****************************************************************************
202 Handles opcodes 0x00, 0x08, 0x10, 0x18, 0x20, 0x28, 0x30, 0x38
203 ****************************************************************************/
204 void x86emuOp_genop_byte_RM_R(u8 op1)
208 u8 *destreg, *srcreg;
211 op1 = (op1 >> 3) & 0x7;
214 DECODE_PRINTF(x86emu_GenOpName[op1]);
216 FETCH_DECODE_MODRM(mod, rh, rl);
218 { destoffset = decode_rmXX_address(mod,rl);
220 destval = fetch_data_byte(destoffset);
221 srcreg = DECODE_RM_BYTE_REGISTER(rh);
224 destval = genop_byte_operation[op1](destval, *srcreg);
225 store_data_byte(destoffset, destval);
228 { /* register to register */
229 destreg = DECODE_RM_BYTE_REGISTER(rl);
231 srcreg = DECODE_RM_BYTE_REGISTER(rh);
234 *destreg = genop_byte_operation[op1](*destreg, *srcreg);
236 DECODE_CLEAR_SEGOVR();
240 /****************************************************************************
242 Handles opcodes 0x01, 0x09, 0x11, 0x19, 0x21, 0x29, 0x31, 0x39
243 ****************************************************************************/
244 void x86emuOp_genop_word_RM_R(u8 op1)
249 op1 = (op1 >> 3) & 0x7;
252 DECODE_PRINTF(x86emu_GenOpName[op1]);
254 FETCH_DECODE_MODRM(mod, rh, rl);
257 destoffset = decode_rmXX_address(mod,rl);
258 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
263 destval = fetch_data_long(destoffset);
264 srcreg = DECODE_RM_LONG_REGISTER(rh);
267 destval = genop_long_operation[op1](destval, *srcreg);
268 store_data_long(destoffset, destval);
274 destval = fetch_data_word(destoffset);
275 srcreg = DECODE_RM_WORD_REGISTER(rh);
278 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 destval = (*genop_byte_operation[rh]) (*destreg, imm);
1342 DECODE_CLEAR_SEGOVR();
1346 /****************************************************************************
1349 ****************************************************************************/
1350 void x86emuOp_opc81_word_RM_IMM(u8 X86EMU_UNUSED(op1))
1356 * Weirdo special case instruction format. Part of the opcode
1357 * held below in "RH". Doubly nested case would result, except
1358 * that the decoded instruction
1361 FETCH_DECODE_MODRM(mod, rh, rl);
1363 if (DEBUG_DECODE()) {
1364 /* XXX DECODE_PRINTF may be changed to something more
1365 general, so that it is important to leave the strings
1366 in the same format, even though the result is that the
1367 above test is done twice. */
1371 DECODE_PRINTF("ADD\t");
1374 DECODE_PRINTF("OR\t");
1377 DECODE_PRINTF("ADC\t");
1380 DECODE_PRINTF("SBB\t");
1383 DECODE_PRINTF("AND\t");
1386 DECODE_PRINTF("SUB\t");
1389 DECODE_PRINTF("XOR\t");
1392 DECODE_PRINTF("CMP\t");
1398 * Know operation, decode the mod byte to find the addressing
1402 DECODE_PRINTF("DWORD PTR ");
1403 destoffset = decode_rmXX_address(mod, rl);
1404 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1408 destval = fetch_data_long(destoffset);
1409 imm = fetch_long_imm();
1410 DECODE_PRINTF2("%x\n", imm);
1412 destval = (*genop_long_operation[rh]) (destval, imm);
1414 store_data_long(destoffset, destval);
1419 destval = fetch_data_word(destoffset);
1420 imm = fetch_word_imm();
1421 DECODE_PRINTF2("%x\n", imm);
1423 destval = (*genop_word_operation[rh]) (destval, imm);
1425 store_data_word(destoffset, destval);
1427 } else { /* register to register */
1428 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1432 destreg = DECODE_RM_LONG_REGISTER(rl);
1434 imm = fetch_long_imm();
1435 DECODE_PRINTF2("%x\n", imm);
1437 destval = (*genop_long_operation[rh]) (*destreg, imm);
1444 destreg = DECODE_RM_WORD_REGISTER(rl);
1446 imm = fetch_word_imm();
1447 DECODE_PRINTF2("%x\n", imm);
1449 destval = (*genop_word_operation[rh]) (*destreg, imm);
1454 DECODE_CLEAR_SEGOVR();
1458 /****************************************************************************
1461 ****************************************************************************/
1462 void x86emuOp_opc82_byte_RM_IMM(u8 X86EMU_UNUSED(op1))
1471 * Weirdo special case instruction format. Part of the opcode
1472 * held below in "RH". Doubly nested case would result, except
1473 * that the decoded instruction Similar to opcode 81, except that
1474 * the immediate byte is sign extended to a word length.
1477 FETCH_DECODE_MODRM(mod, rh, rl);
1479 if (DEBUG_DECODE()) {
1480 /* XXX DECODE_PRINTF may be changed to something more
1481 general, so that it is important to leave the strings
1482 in the same format, even though the result is that the
1483 above test is done twice. */
1486 DECODE_PRINTF("ADD\t");
1489 DECODE_PRINTF("OR\t");
1492 DECODE_PRINTF("ADC\t");
1495 DECODE_PRINTF("SBB\t");
1498 DECODE_PRINTF("AND\t");
1501 DECODE_PRINTF("SUB\t");
1504 DECODE_PRINTF("XOR\t");
1507 DECODE_PRINTF("CMP\t");
1512 /* know operation, decode the mod byte to find the addressing
1515 DECODE_PRINTF("BYTE PTR ");
1516 destoffset = decode_rmXX_address(mod, rl);
1517 destval = fetch_data_byte(destoffset);
1518 imm = fetch_byte_imm();
1519 DECODE_PRINTF2(",%x\n", imm);
1521 destval = (*genop_byte_operation[rh]) (destval, imm);
1523 store_data_byte(destoffset, destval);
1524 } else { /* register to register */
1525 destreg = DECODE_RM_BYTE_REGISTER(rl);
1526 imm = fetch_byte_imm();
1527 DECODE_PRINTF2(",%x\n", imm);
1529 destval = (*genop_byte_operation[rh]) (*destreg, imm);
1533 DECODE_CLEAR_SEGOVR();
1537 /****************************************************************************
1540 ****************************************************************************/
1541 void x86emuOp_opc83_word_RM_IMM(u8 X86EMU_UNUSED(op1))
1547 * Weirdo special case instruction format. Part of the opcode
1548 * held below in "RH". Doubly nested case would result, except
1549 * that the decoded instruction Similar to opcode 81, except that
1550 * the immediate byte is sign extended to a word length.
1553 FETCH_DECODE_MODRM(mod, rh, rl);
1555 if (DEBUG_DECODE()) {
1556 /* XXX DECODE_PRINTF may be changed to something more
1557 general, so that it is important to leave the strings
1558 in the same format, even though the result is that the
1559 above test is done twice. */
1562 DECODE_PRINTF("ADD\t");
1565 DECODE_PRINTF("OR\t");
1568 DECODE_PRINTF("ADC\t");
1571 DECODE_PRINTF("SBB\t");
1574 DECODE_PRINTF("AND\t");
1577 DECODE_PRINTF("SUB\t");
1580 DECODE_PRINTF("XOR\t");
1583 DECODE_PRINTF("CMP\t");
1588 /* know operation, decode the mod byte to find the addressing
1591 DECODE_PRINTF("DWORD PTR ");
1592 destoffset = decode_rmXX_address(mod,rl);
1594 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1597 destval = fetch_data_long(destoffset);
1598 imm = (s8) fetch_byte_imm();
1599 DECODE_PRINTF2(",%x\n", imm);
1601 destval = (*genop_long_operation[rh]) (destval, imm);
1603 store_data_long(destoffset, destval);
1607 destval = fetch_data_word(destoffset);
1608 imm = (s8) fetch_byte_imm();
1609 DECODE_PRINTF2(",%x\n", imm);
1611 destval = (*genop_word_operation[rh]) (destval, imm);
1613 store_data_word(destoffset, destval);
1615 } else { /* register to register */
1616 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1620 destreg = DECODE_RM_LONG_REGISTER(rl);
1621 imm = (s8) fetch_byte_imm();
1622 DECODE_PRINTF2(",%x\n", imm);
1624 destval = (*genop_long_operation[rh]) (*destreg, imm);
1631 destreg = DECODE_RM_WORD_REGISTER(rl);
1632 imm = (s8) fetch_byte_imm();
1633 DECODE_PRINTF2(",%x\n", imm);
1635 destval = (*genop_word_operation[rh]) (*destreg, imm);
1640 DECODE_CLEAR_SEGOVR();
1644 /****************************************************************************
1647 ****************************************************************************/
1648 void x86emuOp_test_byte_RM_R(u8 X86EMU_UNUSED(op1))
1651 u8 *destreg, *srcreg;
1656 DECODE_PRINTF("TEST\t");
1657 FETCH_DECODE_MODRM(mod, rh, rl);
1659 destoffset = decode_rmXX_address(mod, rl);
1661 destval = fetch_data_byte(destoffset);
1662 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1663 DECODE_PRINTF("\n");
1665 test_byte(destval, *srcreg);
1666 } else { /* register to register */
1667 destreg = DECODE_RM_BYTE_REGISTER(rl);
1669 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1670 DECODE_PRINTF("\n");
1672 test_byte(*destreg, *srcreg);
1674 DECODE_CLEAR_SEGOVR();
1678 /****************************************************************************
1681 ****************************************************************************/
1682 void x86emuOp_test_word_RM_R(u8 X86EMU_UNUSED(op1))
1688 DECODE_PRINTF("TEST\t");
1689 FETCH_DECODE_MODRM(mod, rh, rl);
1691 destoffset = decode_rmXX_address(mod, rl);
1692 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1697 destval = fetch_data_long(destoffset);
1698 srcreg = DECODE_RM_LONG_REGISTER(rh);
1699 DECODE_PRINTF("\n");
1701 test_long(destval, *srcreg);
1707 destval = fetch_data_word(destoffset);
1708 srcreg = DECODE_RM_WORD_REGISTER(rh);
1709 DECODE_PRINTF("\n");
1711 test_word(destval, *srcreg);
1713 } else { /* register to register */
1714 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1715 u32 *destreg,*srcreg;
1717 destreg = DECODE_RM_LONG_REGISTER(rl);
1719 srcreg = DECODE_RM_LONG_REGISTER(rh);
1720 DECODE_PRINTF("\n");
1722 test_long(*destreg, *srcreg);
1724 u16 *destreg,*srcreg;
1726 destreg = DECODE_RM_WORD_REGISTER(rl);
1728 srcreg = DECODE_RM_WORD_REGISTER(rh);
1729 DECODE_PRINTF("\n");
1731 test_word(*destreg, *srcreg);
1734 DECODE_CLEAR_SEGOVR();
1738 /****************************************************************************
1741 ****************************************************************************/
1742 void x86emuOp_xchg_byte_RM_R(u8 X86EMU_UNUSED(op1))
1745 u8 *destreg, *srcreg;
1751 DECODE_PRINTF("XCHG\t");
1752 FETCH_DECODE_MODRM(mod, rh, rl);
1754 destoffset = decode_rmXX_address(mod, rl);
1756 destval = fetch_data_byte(destoffset);
1757 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1758 DECODE_PRINTF("\n");
1763 store_data_byte(destoffset, destval);
1764 } else { /* register to register */
1765 destreg = DECODE_RM_BYTE_REGISTER(rl);
1767 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1768 DECODE_PRINTF("\n");
1774 DECODE_CLEAR_SEGOVR();
1778 /****************************************************************************
1781 ****************************************************************************/
1782 void x86emuOp_xchg_word_RM_R(u8 X86EMU_UNUSED(op1))
1788 DECODE_PRINTF("XCHG\t");
1789 FETCH_DECODE_MODRM(mod, rh, rl);
1791 destoffset = decode_rmXX_address(mod, rl);
1793 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1797 destval = fetch_data_long(destoffset);
1798 srcreg = DECODE_RM_LONG_REGISTER(rh);
1799 DECODE_PRINTF("\n");
1804 store_data_long(destoffset, destval);
1809 destval = fetch_data_word(destoffset);
1810 srcreg = DECODE_RM_WORD_REGISTER(rh);
1811 DECODE_PRINTF("\n");
1816 store_data_word(destoffset, destval);
1818 } else { /* register to register */
1819 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1820 u32 *destreg,*srcreg;
1823 destreg = DECODE_RM_LONG_REGISTER(rl);
1825 srcreg = DECODE_RM_LONG_REGISTER(rh);
1826 DECODE_PRINTF("\n");
1832 u16 *destreg,*srcreg;
1835 destreg = DECODE_RM_WORD_REGISTER(rl);
1837 srcreg = DECODE_RM_WORD_REGISTER(rh);
1838 DECODE_PRINTF("\n");
1845 DECODE_CLEAR_SEGOVR();
1849 /****************************************************************************
1852 ****************************************************************************/
1853 void x86emuOp_mov_byte_RM_R(u8 X86EMU_UNUSED(op1))
1856 u8 *destreg, *srcreg;
1860 DECODE_PRINTF("MOV\t");
1861 FETCH_DECODE_MODRM(mod, rh, rl);
1863 destoffset = decode_rmXX_address(mod, rl);
1865 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1866 DECODE_PRINTF("\n");
1868 store_data_byte(destoffset, *srcreg);
1869 } else { /* register to register */
1870 destreg = DECODE_RM_BYTE_REGISTER(rl);
1872 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1873 DECODE_PRINTF("\n");
1877 DECODE_CLEAR_SEGOVR();
1881 /****************************************************************************
1884 ****************************************************************************/
1885 void x86emuOp_mov_word_RM_R(u8 X86EMU_UNUSED(op1))
1891 DECODE_PRINTF("MOV\t");
1892 FETCH_DECODE_MODRM(mod, rh, rl);
1894 destoffset = decode_rmXX_address(mod, rl);
1895 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1899 srcreg = DECODE_RM_LONG_REGISTER(rh);
1900 DECODE_PRINTF("\n");
1902 store_data_long(destoffset, *srcreg);
1907 srcreg = DECODE_RM_WORD_REGISTER(rh);
1908 DECODE_PRINTF("\n");
1910 store_data_word(destoffset, *srcreg);
1912 } else { /* register to register */
1913 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1914 u32 *destreg,*srcreg;
1916 destreg = DECODE_RM_LONG_REGISTER(rl);
1918 srcreg = DECODE_RM_LONG_REGISTER(rh);
1919 DECODE_PRINTF("\n");
1923 u16 *destreg,*srcreg;
1925 destreg = DECODE_RM_WORD_REGISTER(rl);
1927 srcreg = DECODE_RM_WORD_REGISTER(rh);
1928 DECODE_PRINTF("\n");
1933 DECODE_CLEAR_SEGOVR();
1937 /****************************************************************************
1940 ****************************************************************************/
1941 void x86emuOp_mov_byte_R_RM(u8 X86EMU_UNUSED(op1))
1944 u8 *destreg, *srcreg;
1949 DECODE_PRINTF("MOV\t");
1950 FETCH_DECODE_MODRM(mod, rh, rl);
1952 destreg = DECODE_RM_BYTE_REGISTER(rh);
1954 srcoffset = decode_rmXX_address(mod, rl);
1955 srcval = fetch_data_byte(srcoffset);
1956 DECODE_PRINTF("\n");
1959 } else { /* register to register */
1960 destreg = DECODE_RM_BYTE_REGISTER(rh);
1962 srcreg = DECODE_RM_BYTE_REGISTER(rl);
1963 DECODE_PRINTF("\n");
1967 DECODE_CLEAR_SEGOVR();
1971 /****************************************************************************
1974 ****************************************************************************/
1975 void x86emuOp_mov_word_R_RM(u8 X86EMU_UNUSED(op1))
1981 DECODE_PRINTF("MOV\t");
1982 FETCH_DECODE_MODRM(mod, rh, rl);
1984 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1988 destreg = DECODE_RM_LONG_REGISTER(rh);
1990 srcoffset = decode_rmXX_address(mod, rl);
1991 srcval = fetch_data_long(srcoffset);
1992 DECODE_PRINTF("\n");
1999 destreg = DECODE_RM_WORD_REGISTER(rh);
2001 srcoffset = decode_rmXX_address(mod, rl);
2002 srcval = fetch_data_word(srcoffset);
2003 DECODE_PRINTF("\n");
2007 } else { /* register to register */
2008 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2009 u32 *destreg, *srcreg;
2011 destreg = DECODE_RM_LONG_REGISTER(rh);
2013 srcreg = DECODE_RM_LONG_REGISTER(rl);
2014 DECODE_PRINTF("\n");
2018 u16 *destreg, *srcreg;
2020 destreg = DECODE_RM_WORD_REGISTER(rh);
2022 srcreg = DECODE_RM_WORD_REGISTER(rl);
2023 DECODE_PRINTF("\n");
2028 DECODE_CLEAR_SEGOVR();
2032 /****************************************************************************
2035 ****************************************************************************/
2036 void x86emuOp_mov_word_RM_SR(u8 X86EMU_UNUSED(op1))
2039 u16 *destreg, *srcreg;
2044 DECODE_PRINTF("MOV\t");
2045 FETCH_DECODE_MODRM(mod, rh, rl);
2047 destoffset = decode_rmXX_address(mod, rl);
2049 srcreg = decode_rm_seg_register(rh);
2050 DECODE_PRINTF("\n");
2053 store_data_word(destoffset, destval);
2054 } else { /* register to register */
2055 destreg = DECODE_RM_WORD_REGISTER(rl);
2057 srcreg = decode_rm_seg_register(rh);
2058 DECODE_PRINTF("\n");
2062 DECODE_CLEAR_SEGOVR();
2066 /****************************************************************************
2069 ****************************************************************************/
2070 void x86emuOp_lea_word_R_M(u8 X86EMU_UNUSED(op1))
2077 * TODO: Need to handle address size prefix!
2079 * lea eax,[eax+ebx*2] ??
2083 DECODE_PRINTF("LEA\t");
2084 FETCH_DECODE_MODRM(mod, rh, rl);
2086 srcreg = DECODE_RM_WORD_REGISTER(rh);
2088 destoffset = decode_rmXX_address(mod, rl);
2089 DECODE_PRINTF("\n");
2091 *srcreg = (u16)destoffset;
2093 /* } else { undefined. Do nothing. } */
2094 DECODE_CLEAR_SEGOVR();
2098 /****************************************************************************
2101 ****************************************************************************/
2102 void x86emuOp_mov_word_SR_RM(u8 X86EMU_UNUSED(op1))
2105 u16 *destreg, *srcreg;
2110 DECODE_PRINTF("MOV\t");
2111 FETCH_DECODE_MODRM(mod, rh, rl);
2113 destreg = decode_rm_seg_register(rh);
2115 srcoffset = decode_rmXX_address(mod, rl);
2116 srcval = fetch_data_word(srcoffset);
2117 DECODE_PRINTF("\n");
2120 } else { /* register to register */
2121 destreg = decode_rm_seg_register(rh);
2123 srcreg = DECODE_RM_WORD_REGISTER(rl);
2124 DECODE_PRINTF("\n");
2129 * Clean up, and reset all the R_xSP pointers to the correct
2130 * locations. This is about 3x too much overhead (doing all the
2131 * segreg ptrs when only one is needed, but this instruction
2132 * *cannot* be that common, and this isn't too much work anyway.
2134 DECODE_CLEAR_SEGOVR();
2138 /****************************************************************************
2141 ****************************************************************************/
2142 void x86emuOp_pop_RM(u8 X86EMU_UNUSED(op1))
2148 DECODE_PRINTF("POP\t");
2149 FETCH_DECODE_MODRM(mod, rh, rl);
2151 DECODE_PRINTF("ILLEGAL DECODE OF OPCODE 8F\n");
2155 destoffset = decode_rmXX_address(mod, rl);
2156 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2159 DECODE_PRINTF("\n");
2161 destval = pop_long();
2162 store_data_long(destoffset, destval);
2166 DECODE_PRINTF("\n");
2168 destval = pop_word();
2169 store_data_word(destoffset, destval);
2171 } else { /* register to register */
2172 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2175 destreg = DECODE_RM_LONG_REGISTER(rl);
2176 DECODE_PRINTF("\n");
2178 *destreg = pop_long();
2182 destreg = DECODE_RM_WORD_REGISTER(rl);
2183 DECODE_PRINTF("\n");
2185 *destreg = pop_word();
2188 DECODE_CLEAR_SEGOVR();
2192 /****************************************************************************
2195 ****************************************************************************/
2196 void x86emuOp_nop(u8 X86EMU_UNUSED(op1))
2199 DECODE_PRINTF("NOP\n");
2201 DECODE_CLEAR_SEGOVR();
2205 /****************************************************************************
2207 Handles opcode 0x91-0x97
2208 ****************************************************************************/
2209 void x86emuOp_xchg_word_AX_register(u8 X86EMU_UNUSED(op1))
2217 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2219 DECODE_PRINTF("XCHG\tEAX,");
2220 reg32 = DECODE_RM_LONG_REGISTER(op1);
2221 DECODE_PRINTF("\n");
2224 M.x86.R_EAX = *reg32;
2228 DECODE_PRINTF("XCHG\tAX,");
2229 reg16 = DECODE_RM_WORD_REGISTER(op1);
2230 DECODE_PRINTF("\n");
2233 M.x86.R_EAX = *reg16;
2236 DECODE_CLEAR_SEGOVR();
2240 /****************************************************************************
2243 ****************************************************************************/
2244 void x86emuOp_cbw(u8 X86EMU_UNUSED(op1))
2247 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2248 DECODE_PRINTF("CWDE\n");
2250 DECODE_PRINTF("CBW\n");
2253 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2254 if (M.x86.R_AX & 0x8000) {
2255 M.x86.R_EAX |= 0xffff0000;
2257 M.x86.R_EAX &= 0x0000ffff;
2260 if (M.x86.R_AL & 0x80) {
2266 DECODE_CLEAR_SEGOVR();
2270 /****************************************************************************
2273 ****************************************************************************/
2274 void x86emuOp_cwd(u8 X86EMU_UNUSED(op1))
2277 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2278 DECODE_PRINTF("CDQ\n");
2280 DECODE_PRINTF("CWD\n");
2282 DECODE_PRINTF("CWD\n");
2284 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2285 if (M.x86.R_EAX & 0x80000000) {
2286 M.x86.R_EDX = 0xffffffff;
2291 if (M.x86.R_AX & 0x8000) {
2292 M.x86.R_DX = 0xffff;
2297 DECODE_CLEAR_SEGOVR();
2301 /****************************************************************************
2304 ****************************************************************************/
2305 void x86emuOp_call_far_IMM(u8 X86EMU_UNUSED(op1))
2310 DECODE_PRINTF("CALL\t");
2311 faroff = fetch_word_imm();
2312 farseg = fetch_word_imm();
2313 DECODE_PRINTF2("%04x:", farseg);
2314 DECODE_PRINTF2("%04x\n", faroff);
2315 CALL_TRACE(M.x86.saved_cs, M.x86.saved_ip, farseg, faroff, "FAR ");
2319 * Hooked interrupt vectors calling into our "BIOS" will cause
2320 * problems unless all intersegment stuff is checked for BIOS
2321 * access. Check needed here. For moment, let it alone.
2324 push_word(M.x86.R_CS);
2325 M.x86.R_CS = farseg;
2326 push_word(M.x86.R_IP);
2327 M.x86.R_IP = faroff;
2328 DECODE_CLEAR_SEGOVR();
2332 /****************************************************************************
2335 ****************************************************************************/
2336 void x86emuOp_wait(u8 X86EMU_UNUSED(op1))
2339 DECODE_PRINTF("WAIT");
2342 DECODE_CLEAR_SEGOVR();
2346 /****************************************************************************
2349 ****************************************************************************/
2350 void x86emuOp_pushf_word(u8 X86EMU_UNUSED(op1))
2355 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2356 DECODE_PRINTF("PUSHFD\n");
2358 DECODE_PRINTF("PUSHF\n");
2362 /* clear out *all* bits not representing flags, and turn on real bits */
2363 flags = (M.x86.R_EFLG & F_MSK) | F_ALWAYS_ON;
2364 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2367 push_word((u16)flags);
2369 DECODE_CLEAR_SEGOVR();
2373 /****************************************************************************
2376 ****************************************************************************/
2377 void x86emuOp_popf_word(u8 X86EMU_UNUSED(op1))
2380 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2381 DECODE_PRINTF("POPFD\n");
2383 DECODE_PRINTF("POPF\n");
2386 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2387 M.x86.R_EFLG = pop_long();
2389 M.x86.R_FLG = pop_word();
2391 DECODE_CLEAR_SEGOVR();
2395 /****************************************************************************
2398 ****************************************************************************/
2399 void x86emuOp_sahf(u8 X86EMU_UNUSED(op1))
2402 DECODE_PRINTF("SAHF\n");
2404 /* clear the lower bits of the flag register */
2405 M.x86.R_FLG &= 0xffffff00;
2406 /* or in the AH register into the flags register */
2407 M.x86.R_FLG |= M.x86.R_AH;
2408 DECODE_CLEAR_SEGOVR();
2412 /****************************************************************************
2415 ****************************************************************************/
2416 void x86emuOp_lahf(u8 X86EMU_UNUSED(op1))
2419 DECODE_PRINTF("LAHF\n");
2421 M.x86.R_AH = (u8)(M.x86.R_FLG & 0xff);
2422 /*undocumented TC++ behavior??? Nope. It's documented, but
2423 you have too look real hard to notice it. */
2425 DECODE_CLEAR_SEGOVR();
2429 /****************************************************************************
2432 ****************************************************************************/
2433 void x86emuOp_mov_AL_M_IMM(u8 X86EMU_UNUSED(op1))
2438 DECODE_PRINTF("MOV\tAL,");
2439 offset = fetch_word_imm();
2440 DECODE_PRINTF2("[%04x]\n", offset);
2442 M.x86.R_AL = fetch_data_byte(offset);
2443 DECODE_CLEAR_SEGOVR();
2447 /****************************************************************************
2450 ****************************************************************************/
2451 void x86emuOp_mov_AX_M_IMM(u8 X86EMU_UNUSED(op1))
2456 offset = fetch_word_imm();
2457 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2458 DECODE_PRINTF2("MOV\tEAX,[%04x]\n", offset);
2460 DECODE_PRINTF2("MOV\tAX,[%04x]\n", offset);
2463 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2464 M.x86.R_EAX = fetch_data_long(offset);
2466 M.x86.R_AX = fetch_data_word(offset);
2468 DECODE_CLEAR_SEGOVR();
2472 /****************************************************************************
2475 ****************************************************************************/
2476 void x86emuOp_mov_M_AL_IMM(u8 X86EMU_UNUSED(op1))
2481 DECODE_PRINTF("MOV\t");
2482 offset = fetch_word_imm();
2483 DECODE_PRINTF2("[%04x],AL\n", offset);
2485 store_data_byte(offset, M.x86.R_AL);
2486 DECODE_CLEAR_SEGOVR();
2490 /****************************************************************************
2493 ****************************************************************************/
2494 void x86emuOp_mov_M_AX_IMM(u8 X86EMU_UNUSED(op1))
2499 offset = fetch_word_imm();
2500 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2501 DECODE_PRINTF2("MOV\t[%04x],EAX\n", offset);
2503 DECODE_PRINTF2("MOV\t[%04x],AX\n", offset);
2506 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2507 store_data_long(offset, M.x86.R_EAX);
2509 store_data_word(offset, M.x86.R_AX);
2511 DECODE_CLEAR_SEGOVR();
2515 /****************************************************************************
2518 ****************************************************************************/
2519 void x86emuOp_movs_byte(u8 X86EMU_UNUSED(op1))
2526 DECODE_PRINTF("MOVS\tBYTE\n");
2527 if (ACCESS_FLAG(F_DF)) /* down */
2533 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2534 /* dont care whether REPE or REPNE */
2535 /* move them until CX is ZERO. */
2538 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2541 val = fetch_data_byte(M.x86.R_SI);
2542 store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, val);
2546 DECODE_CLEAR_SEGOVR();
2550 /****************************************************************************
2553 ****************************************************************************/
2554 void x86emuOp_movs_word(u8 X86EMU_UNUSED(op1))
2561 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2562 DECODE_PRINTF("MOVS\tDWORD\n");
2563 if (ACCESS_FLAG(F_DF)) /* down */
2568 DECODE_PRINTF("MOVS\tWORD\n");
2569 if (ACCESS_FLAG(F_DF)) /* down */
2576 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2577 /* dont care whether REPE or REPNE */
2578 /* move them until CX is ZERO. */
2581 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2584 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2585 val = fetch_data_long(M.x86.R_SI);
2586 store_data_long_abs(M.x86.R_ES, M.x86.R_DI, val);
2588 val = fetch_data_word(M.x86.R_SI);
2589 store_data_word_abs(M.x86.R_ES, M.x86.R_DI, (u16)val);
2594 DECODE_CLEAR_SEGOVR();
2598 /****************************************************************************
2601 ****************************************************************************/
2602 void x86emuOp_cmps_byte(u8 X86EMU_UNUSED(op1))
2608 DECODE_PRINTF("CMPS\tBYTE\n");
2610 if (ACCESS_FLAG(F_DF)) /* down */
2615 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2617 /* move them until CX is ZERO. */
2618 while (M.x86.R_CX != 0) {
2619 val1 = fetch_data_byte(M.x86.R_SI);
2620 val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2621 cmp_byte(val1, val2);
2625 if ( (M.x86.mode & SYSMODE_PREFIX_REPE) && (ACCESS_FLAG(F_ZF) == 0) ) break;
2626 if ( (M.x86.mode & SYSMODE_PREFIX_REPNE) && ACCESS_FLAG(F_ZF) ) break;
2628 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2630 val1 = fetch_data_byte(M.x86.R_SI);
2631 val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2632 cmp_byte(val1, val2);
2636 DECODE_CLEAR_SEGOVR();
2640 /****************************************************************************
2643 ****************************************************************************/
2644 void x86emuOp_cmps_word(u8 X86EMU_UNUSED(op1))
2650 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2651 DECODE_PRINTF("CMPS\tDWORD\n");
2654 DECODE_PRINTF("CMPS\tWORD\n");
2657 if (ACCESS_FLAG(F_DF)) /* down */
2661 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2663 /* move them until CX is ZERO. */
2664 while (M.x86.R_CX != 0) {
2665 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2666 val1 = fetch_data_long(M.x86.R_SI);
2667 val2 = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
2668 cmp_long(val1, val2);
2670 val1 = fetch_data_word(M.x86.R_SI);
2671 val2 = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
2672 cmp_word((u16)val1, (u16)val2);
2677 if ( (M.x86.mode & SYSMODE_PREFIX_REPE) && ACCESS_FLAG(F_ZF) == 0 ) break;
2678 if ( (M.x86.mode & SYSMODE_PREFIX_REPNE) && ACCESS_FLAG(F_ZF) ) break;
2680 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2682 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2683 val1 = fetch_data_long(M.x86.R_SI);
2684 val2 = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
2685 cmp_long(val1, val2);
2687 val1 = fetch_data_word(M.x86.R_SI);
2688 val2 = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
2689 cmp_word((u16)val1, (u16)val2);
2694 DECODE_CLEAR_SEGOVR();
2698 /****************************************************************************
2701 ****************************************************************************/
2702 void x86emuOp_test_AL_IMM(u8 X86EMU_UNUSED(op1))
2707 DECODE_PRINTF("TEST\tAL,");
2708 imm = fetch_byte_imm();
2709 DECODE_PRINTF2("%04x\n", imm);
2711 test_byte(M.x86.R_AL, (u8)imm);
2712 DECODE_CLEAR_SEGOVR();
2716 /****************************************************************************
2719 ****************************************************************************/
2720 void x86emuOp_test_AX_IMM(u8 X86EMU_UNUSED(op1))
2725 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2726 DECODE_PRINTF("TEST\tEAX,");
2727 srcval = fetch_long_imm();
2729 DECODE_PRINTF("TEST\tAX,");
2730 srcval = fetch_word_imm();
2732 DECODE_PRINTF2("%x\n", srcval);
2734 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2735 test_long(M.x86.R_EAX, srcval);
2737 test_word(M.x86.R_AX, (u16)srcval);
2739 DECODE_CLEAR_SEGOVR();
2743 /****************************************************************************
2746 ****************************************************************************/
2747 void x86emuOp_stos_byte(u8 X86EMU_UNUSED(op1))
2752 DECODE_PRINTF("STOS\tBYTE\n");
2753 if (ACCESS_FLAG(F_DF)) /* down */
2758 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2759 /* dont care whether REPE or REPNE */
2760 /* move them until CX is ZERO. */
2761 while (M.x86.R_CX != 0) {
2762 store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AL);
2766 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2768 store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AL);
2771 DECODE_CLEAR_SEGOVR();
2775 /****************************************************************************
2778 ****************************************************************************/
2779 void x86emuOp_stos_word(u8 X86EMU_UNUSED(op1))
2785 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2786 DECODE_PRINTF("STOS\tDWORD\n");
2787 if (ACCESS_FLAG(F_DF)) /* down */
2792 DECODE_PRINTF("STOS\tWORD\n");
2793 if (ACCESS_FLAG(F_DF)) /* down */
2800 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2801 /* dont care whether REPE or REPNE */
2802 /* move them until CX is ZERO. */
2805 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2808 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2809 store_data_long_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_EAX);
2811 store_data_word_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AX);
2815 DECODE_CLEAR_SEGOVR();
2819 /****************************************************************************
2822 ****************************************************************************/
2823 void x86emuOp_lods_byte(u8 X86EMU_UNUSED(op1))
2828 DECODE_PRINTF("LODS\tBYTE\n");
2830 if (ACCESS_FLAG(F_DF)) /* down */
2834 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2835 /* dont care whether REPE or REPNE */
2836 /* move them until CX is ZERO. */
2837 while (M.x86.R_CX != 0) {
2838 M.x86.R_AL = fetch_data_byte(M.x86.R_SI);
2842 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2844 M.x86.R_AL = fetch_data_byte(M.x86.R_SI);
2847 DECODE_CLEAR_SEGOVR();
2851 /****************************************************************************
2854 ****************************************************************************/
2855 void x86emuOp_lods_word(u8 X86EMU_UNUSED(op1))
2861 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2862 DECODE_PRINTF("LODS\tDWORD\n");
2863 if (ACCESS_FLAG(F_DF)) /* down */
2868 DECODE_PRINTF("LODS\tWORD\n");
2869 if (ACCESS_FLAG(F_DF)) /* down */
2876 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2877 /* dont care whether REPE or REPNE */
2878 /* move them until CX is ZERO. */
2881 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2884 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2885 M.x86.R_EAX = fetch_data_long(M.x86.R_SI);
2887 M.x86.R_AX = fetch_data_word(M.x86.R_SI);
2891 DECODE_CLEAR_SEGOVR();
2895 /****************************************************************************
2898 ****************************************************************************/
2899 void x86emuOp_scas_byte(u8 X86EMU_UNUSED(op1))
2905 DECODE_PRINTF("SCAS\tBYTE\n");
2907 if (ACCESS_FLAG(F_DF)) /* down */
2911 if (M.x86.mode & SYSMODE_PREFIX_REPE) {
2913 /* move them until CX is ZERO. */
2914 while (M.x86.R_CX != 0) {
2915 val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2916 cmp_byte(M.x86.R_AL, val2);
2919 if (ACCESS_FLAG(F_ZF) == 0)
2922 M.x86.mode &= ~SYSMODE_PREFIX_REPE;
2923 } else if (M.x86.mode & SYSMODE_PREFIX_REPNE) {
2925 /* move them until CX is ZERO. */
2926 while (M.x86.R_CX != 0) {
2927 val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2928 cmp_byte(M.x86.R_AL, val2);
2931 if (ACCESS_FLAG(F_ZF))
2932 break; /* zero flag set means equal */
2934 M.x86.mode &= ~SYSMODE_PREFIX_REPNE;
2936 val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2937 cmp_byte(M.x86.R_AL, val2);
2940 DECODE_CLEAR_SEGOVR();
2944 /****************************************************************************
2947 ****************************************************************************/
2948 void x86emuOp_scas_word(u8 X86EMU_UNUSED(op1))
2954 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2955 DECODE_PRINTF("SCAS\tDWORD\n");
2956 if (ACCESS_FLAG(F_DF)) /* down */
2961 DECODE_PRINTF("SCAS\tWORD\n");
2962 if (ACCESS_FLAG(F_DF)) /* down */
2968 if (M.x86.mode & SYSMODE_PREFIX_REPE) {
2970 /* move them until CX is ZERO. */
2971 while (M.x86.R_CX != 0) {
2972 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2973 val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
2974 cmp_long(M.x86.R_EAX, val);
2976 val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
2977 cmp_word(M.x86.R_AX, (u16)val);
2981 if (ACCESS_FLAG(F_ZF) == 0)
2984 M.x86.mode &= ~SYSMODE_PREFIX_REPE;
2985 } else if (M.x86.mode & SYSMODE_PREFIX_REPNE) {
2987 /* move them until CX is ZERO. */
2988 while (M.x86.R_CX != 0) {
2989 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2990 val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
2991 cmp_long(M.x86.R_EAX, val);
2993 val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
2994 cmp_word(M.x86.R_AX, (u16)val);
2998 if (ACCESS_FLAG(F_ZF))
2999 break; /* zero flag set means equal */
3001 M.x86.mode &= ~SYSMODE_PREFIX_REPNE;
3003 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3004 val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
3005 cmp_long(M.x86.R_EAX, val);
3007 val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
3008 cmp_word(M.x86.R_AX, (u16)val);
3012 DECODE_CLEAR_SEGOVR();
3016 /****************************************************************************
3018 Handles opcode 0xb0 - 0xb7
3019 ****************************************************************************/
3020 void x86emuOp_mov_byte_register_IMM(u8 op1)
3025 DECODE_PRINTF("MOV\t");
3026 ptr = DECODE_RM_BYTE_REGISTER(op1 & 0x7);
3028 imm = fetch_byte_imm();
3029 DECODE_PRINTF2("%x\n", imm);
3032 DECODE_CLEAR_SEGOVR();
3036 /****************************************************************************
3038 Handles opcode 0xb8 - 0xbf
3039 ****************************************************************************/
3040 void x86emuOp_mov_word_register_IMM(u8 X86EMU_UNUSED(op1))
3047 DECODE_PRINTF("MOV\t");
3048 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3050 reg32 = DECODE_RM_LONG_REGISTER(op1);
3051 srcval = fetch_long_imm();
3052 DECODE_PRINTF2(",%x\n", srcval);
3057 reg16 = DECODE_RM_WORD_REGISTER(op1);
3058 srcval = fetch_word_imm();
3059 DECODE_PRINTF2(",%x\n", srcval);
3061 *reg16 = (u16)srcval;
3063 DECODE_CLEAR_SEGOVR();
3067 /****************************************************************************
3070 ****************************************************************************/
3071 void x86emuOp_opcC0_byte_RM_MEM(u8 X86EMU_UNUSED(op1))
3080 * Yet another weirdo special case instruction format. Part of
3081 * the opcode held below in "RH". Doubly nested case would
3082 * result, except that the decoded instruction
3085 FETCH_DECODE_MODRM(mod, rh, rl);
3087 if (DEBUG_DECODE()) {
3088 /* XXX DECODE_PRINTF may be changed to something more
3089 general, so that it is important to leave the strings
3090 in the same format, even though the result is that the
3091 above test is done twice. */
3095 DECODE_PRINTF("ROL\t");
3098 DECODE_PRINTF("ROR\t");
3101 DECODE_PRINTF("RCL\t");
3104 DECODE_PRINTF("RCR\t");
3107 DECODE_PRINTF("SHL\t");
3110 DECODE_PRINTF("SHR\t");
3113 DECODE_PRINTF("SAL\t");
3116 DECODE_PRINTF("SAR\t");
3121 /* know operation, decode the mod byte to find the addressing
3124 DECODE_PRINTF("BYTE PTR ");
3125 destoffset = decode_rmXX_address(mod, rl);
3126 amt = fetch_byte_imm();
3127 DECODE_PRINTF2(",%x\n", amt);
3128 destval = fetch_data_byte(destoffset);
3130 destval = (*opcD0_byte_operation[rh]) (destval, amt);
3131 store_data_byte(destoffset, destval);
3132 } else { /* register to register */
3133 destreg = DECODE_RM_BYTE_REGISTER(rl);
3134 amt = fetch_byte_imm();
3135 DECODE_PRINTF2(",%x\n", amt);
3137 destval = (*opcD0_byte_operation[rh]) (*destreg, amt);
3140 DECODE_CLEAR_SEGOVR();
3144 /****************************************************************************
3147 ****************************************************************************/
3148 void x86emuOp_opcC1_word_RM_MEM(u8 X86EMU_UNUSED(op1))
3155 * Yet another weirdo special case instruction format. Part of
3156 * the opcode held below in "RH". Doubly nested case would
3157 * result, except that the decoded instruction
3160 FETCH_DECODE_MODRM(mod, rh, rl);
3162 if (DEBUG_DECODE()) {
3163 /* XXX DECODE_PRINTF may be changed to something more
3164 general, so that it is important to leave the strings
3165 in the same format, even though the result is that the
3166 above test is done twice. */
3170 DECODE_PRINTF("ROL\t");
3173 DECODE_PRINTF("ROR\t");
3176 DECODE_PRINTF("RCL\t");
3179 DECODE_PRINTF("RCR\t");
3182 DECODE_PRINTF("SHL\t");
3185 DECODE_PRINTF("SHR\t");
3188 DECODE_PRINTF("SAL\t");
3191 DECODE_PRINTF("SAR\t");
3196 /* know operation, decode the mod byte to find the addressing
3199 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3202 DECODE_PRINTF("DWORD PTR ");
3203 destoffset = decode_rmXX_address(mod, rl);
3204 amt = fetch_byte_imm();
3205 DECODE_PRINTF2(",%x\n", amt);
3206 destval = fetch_data_long(destoffset);
3208 destval = (*opcD1_long_operation[rh]) (destval, amt);
3209 store_data_long(destoffset, destval);
3213 DECODE_PRINTF("WORD PTR ");
3214 destoffset = decode_rmXX_address(mod, rl);
3215 amt = fetch_byte_imm();
3216 DECODE_PRINTF2(",%x\n", amt);
3217 destval = fetch_data_word(destoffset);
3219 destval = (*opcD1_word_operation[rh]) (destval, amt);
3220 store_data_word(destoffset, destval);
3222 } else { /* register to register */
3223 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3226 destreg = DECODE_RM_LONG_REGISTER(rl);
3227 amt = fetch_byte_imm();
3228 DECODE_PRINTF2(",%x\n", amt);
3230 *destreg = (*opcD1_long_operation[rh]) (*destreg, amt);
3234 destreg = DECODE_RM_WORD_REGISTER(rl);
3235 amt = fetch_byte_imm();
3236 DECODE_PRINTF2(",%x\n", amt);
3238 *destreg = (*opcD1_word_operation[rh]) (*destreg, amt);
3241 DECODE_CLEAR_SEGOVR();
3245 /****************************************************************************
3248 ****************************************************************************/
3249 void x86emuOp_ret_near_IMM(u8 X86EMU_UNUSED(op1))
3254 DECODE_PRINTF("RET\t");
3255 imm = fetch_word_imm();
3256 DECODE_PRINTF2("%x\n", imm);
3257 RETURN_TRACE("RET",M.x86.saved_cs,M.x86.saved_ip);
3259 M.x86.R_IP = pop_word();
3261 DECODE_CLEAR_SEGOVR();
3265 /****************************************************************************
3268 ****************************************************************************/
3269 void x86emuOp_ret_near(u8 X86EMU_UNUSED(op1))
3272 DECODE_PRINTF("RET\n");
3273 RETURN_TRACE("RET",M.x86.saved_cs,M.x86.saved_ip);
3275 M.x86.R_IP = pop_word();
3276 DECODE_CLEAR_SEGOVR();
3280 /****************************************************************************
3283 ****************************************************************************/
3284 void x86emuOp_les_R_IMM(u8 X86EMU_UNUSED(op1))
3291 DECODE_PRINTF("LES\t");
3292 FETCH_DECODE_MODRM(mod, rh, rl);
3294 dstreg = DECODE_RM_WORD_REGISTER(rh);
3296 srcoffset = decode_rmXX_address(mod, rl);
3297 DECODE_PRINTF("\n");
3299 *dstreg = fetch_data_word(srcoffset);
3300 M.x86.R_ES = fetch_data_word(srcoffset + 2);
3302 /* else UNDEFINED! register to register */
3304 DECODE_CLEAR_SEGOVR();
3308 /****************************************************************************
3311 ****************************************************************************/
3312 void x86emuOp_lds_R_IMM(u8 X86EMU_UNUSED(op1))
3319 DECODE_PRINTF("LDS\t");
3320 FETCH_DECODE_MODRM(mod, rh, rl);
3322 dstreg = DECODE_RM_WORD_REGISTER(rh);
3324 srcoffset = decode_rmXX_address(mod, rl);
3325 DECODE_PRINTF("\n");
3327 *dstreg = fetch_data_word(srcoffset);
3328 M.x86.R_DS = fetch_data_word(srcoffset + 2);
3330 /* else UNDEFINED! */
3331 DECODE_CLEAR_SEGOVR();
3335 /****************************************************************************
3338 ****************************************************************************/
3339 void x86emuOp_mov_byte_RM_IMM(u8 X86EMU_UNUSED(op1))
3347 DECODE_PRINTF("MOV\t");
3348 FETCH_DECODE_MODRM(mod, rh, rl);
3350 DECODE_PRINTF("ILLEGAL DECODE OF OPCODE c6\n");
3354 DECODE_PRINTF("BYTE PTR ");
3355 destoffset = decode_rmXX_address(mod, rl);
3356 imm = fetch_byte_imm();
3357 DECODE_PRINTF2(",%2x\n", imm);
3359 store_data_byte(destoffset, imm);
3360 } else { /* register to register */
3361 destreg = DECODE_RM_BYTE_REGISTER(rl);
3362 imm = fetch_byte_imm();
3363 DECODE_PRINTF2(",%2x\n", imm);
3367 DECODE_CLEAR_SEGOVR();
3371 /****************************************************************************
3374 ****************************************************************************/
3375 void x86emuOp_mov_word_RM_IMM(u8 X86EMU_UNUSED(op1))
3381 DECODE_PRINTF("MOV\t");
3382 FETCH_DECODE_MODRM(mod, rh, rl);
3384 DECODE_PRINTF("ILLEGAL DECODE OF OPCODE 8F\n");
3388 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3391 DECODE_PRINTF("DWORD PTR ");
3392 destoffset = decode_rmXX_address(mod, rl);
3393 imm = fetch_long_imm();
3394 DECODE_PRINTF2(",%x\n", imm);
3396 store_data_long(destoffset, imm);
3400 DECODE_PRINTF("WORD PTR ");
3401 destoffset = decode_rmXX_address(mod, rl);
3402 imm = fetch_word_imm();
3403 DECODE_PRINTF2(",%x\n", imm);
3405 store_data_word(destoffset, imm);
3407 } else { /* register to register */
3408 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3412 destreg = DECODE_RM_LONG_REGISTER(rl);
3413 imm = fetch_long_imm();
3414 DECODE_PRINTF2(",%x\n", imm);
3421 destreg = DECODE_RM_WORD_REGISTER(rl);
3422 imm = fetch_word_imm();
3423 DECODE_PRINTF2(",%x\n", imm);
3428 DECODE_CLEAR_SEGOVR();
3432 /****************************************************************************
3435 ****************************************************************************/
3436 void x86emuOp_enter(u8 X86EMU_UNUSED(op1))
3438 u16 local,frame_pointer;
3443 local = fetch_word_imm();
3444 nesting = fetch_byte_imm();
3445 DECODE_PRINTF2("ENTER %x\n", local);
3446 DECODE_PRINTF2(",%x\n", nesting);
3448 push_word(M.x86.R_BP);
3449 frame_pointer = M.x86.R_SP;
3451 for (i = 1; i < nesting; i++) {
3453 push_word(fetch_data_word_abs(M.x86.R_SS, M.x86.R_BP));
3455 push_word(frame_pointer);
3457 M.x86.R_BP = frame_pointer;
3458 M.x86.R_SP = (u16)(M.x86.R_SP - local);
3459 DECODE_CLEAR_SEGOVR();
3463 /****************************************************************************
3466 ****************************************************************************/
3467 void x86emuOp_leave(u8 X86EMU_UNUSED(op1))
3470 DECODE_PRINTF("LEAVE\n");
3472 M.x86.R_SP = M.x86.R_BP;
3473 M.x86.R_BP = pop_word();
3474 DECODE_CLEAR_SEGOVR();
3478 /****************************************************************************
3481 ****************************************************************************/
3482 void x86emuOp_ret_far_IMM(u8 X86EMU_UNUSED(op1))
3487 DECODE_PRINTF("RETF\t");
3488 imm = fetch_word_imm();
3489 DECODE_PRINTF2("%x\n", imm);
3490 RETURN_TRACE("RETF",M.x86.saved_cs,M.x86.saved_ip);
3492 M.x86.R_IP = pop_word();
3493 M.x86.R_CS = pop_word();
3495 DECODE_CLEAR_SEGOVR();
3499 /****************************************************************************
3502 ****************************************************************************/
3503 void x86emuOp_ret_far(u8 X86EMU_UNUSED(op1))
3506 DECODE_PRINTF("RETF\n");
3507 RETURN_TRACE("RETF",M.x86.saved_cs,M.x86.saved_ip);
3509 M.x86.R_IP = pop_word();
3510 M.x86.R_CS = pop_word();
3511 DECODE_CLEAR_SEGOVR();
3515 /****************************************************************************
3518 ****************************************************************************/
3519 void x86emuOp_int3(u8 X86EMU_UNUSED(op1))
3522 DECODE_PRINTF("INT 3\n");
3523 (void)mem_access_word(3 * 4 + 2);
3524 /* access the segment register */
3526 if (_X86EMU_intrTab[3]) {
3527 (*_X86EMU_intrTab[3])(3);
3529 push_word((u16)M.x86.R_FLG);
3532 push_word(M.x86.R_CS);
3533 M.x86.R_CS = mem_access_word(3 * 4 + 2);
3534 push_word(M.x86.R_IP);
3535 M.x86.R_IP = mem_access_word(3 * 4);
3537 DECODE_CLEAR_SEGOVR();
3541 /****************************************************************************
3544 ****************************************************************************/
3545 void x86emuOp_int_IMM(u8 X86EMU_UNUSED(op1))
3550 DECODE_PRINTF("INT\t");
3551 intnum = fetch_byte_imm();
3552 DECODE_PRINTF2("%x\n", intnum);
3553 (void)mem_access_word(intnum * 4 + 2);
3555 if (_X86EMU_intrTab[intnum]) {
3556 (*_X86EMU_intrTab[intnum])(intnum);
3558 push_word((u16)M.x86.R_FLG);
3561 push_word(M.x86.R_CS);
3562 M.x86.R_CS = mem_access_word(intnum * 4 + 2);
3563 push_word(M.x86.R_IP);
3564 M.x86.R_IP = mem_access_word(intnum * 4);
3566 DECODE_CLEAR_SEGOVR();
3570 /****************************************************************************
3573 ****************************************************************************/
3574 void x86emuOp_into(u8 X86EMU_UNUSED(op1))
3577 DECODE_PRINTF("INTO\n");
3579 if (ACCESS_FLAG(F_OF)) {
3580 (void)mem_access_word(4 * 4 + 2);
3581 if (_X86EMU_intrTab[4]) {
3582 (*_X86EMU_intrTab[4])(4);
3584 push_word((u16)M.x86.R_FLG);
3587 push_word(M.x86.R_CS);
3588 M.x86.R_CS = mem_access_word(4 * 4 + 2);
3589 push_word(M.x86.R_IP);
3590 M.x86.R_IP = mem_access_word(4 * 4);
3593 DECODE_CLEAR_SEGOVR();
3597 /****************************************************************************
3600 ****************************************************************************/
3601 void x86emuOp_iret(u8 X86EMU_UNUSED(op1))
3604 DECODE_PRINTF("IRET\n");
3608 M.x86.R_IP = pop_word();
3609 M.x86.R_CS = pop_word();
3610 M.x86.R_FLG = pop_word();
3611 DECODE_CLEAR_SEGOVR();
3615 /****************************************************************************
3618 ****************************************************************************/
3619 void x86emuOp_opcD0_byte_RM_1(u8 X86EMU_UNUSED(op1))
3627 * Yet another weirdo special case instruction format. Part of
3628 * the opcode held below in "RH". Doubly nested case would
3629 * result, except that the decoded instruction
3632 FETCH_DECODE_MODRM(mod, rh, rl);
3634 if (DEBUG_DECODE()) {
3635 /* XXX DECODE_PRINTF may be changed to something more
3636 general, so that it is important to leave the strings
3637 in the same format, even though the result is that the
3638 above test is done twice. */
3641 DECODE_PRINTF("ROL\t");
3644 DECODE_PRINTF("ROR\t");
3647 DECODE_PRINTF("RCL\t");
3650 DECODE_PRINTF("RCR\t");
3653 DECODE_PRINTF("SHL\t");
3656 DECODE_PRINTF("SHR\t");
3659 DECODE_PRINTF("SAL\t");
3662 DECODE_PRINTF("SAR\t");
3667 /* know operation, decode the mod byte to find the addressing
3670 DECODE_PRINTF("BYTE PTR ");
3671 destoffset = decode_rmXX_address(mod, rl);
3672 DECODE_PRINTF(",1\n");
3673 destval = fetch_data_byte(destoffset);
3675 destval = (*opcD0_byte_operation[rh]) (destval, 1);
3676 store_data_byte(destoffset, destval);
3677 } else { /* register to register */
3678 destreg = DECODE_RM_BYTE_REGISTER(rl);
3679 DECODE_PRINTF(",1\n");
3681 destval = (*opcD0_byte_operation[rh]) (*destreg, 1);
3684 DECODE_CLEAR_SEGOVR();
3688 /****************************************************************************
3691 ****************************************************************************/
3692 void x86emuOp_opcD1_word_RM_1(u8 X86EMU_UNUSED(op1))
3698 * Yet another weirdo special case instruction format. Part of
3699 * the opcode held below in "RH". Doubly nested case would
3700 * result, except that the decoded instruction
3703 FETCH_DECODE_MODRM(mod, rh, rl);
3705 if (DEBUG_DECODE()) {
3706 /* XXX DECODE_PRINTF may be changed to something more
3707 general, so that it is important to leave the strings
3708 in the same format, even though the result is that the
3709 above test is done twice. */
3712 DECODE_PRINTF("ROL\t");
3715 DECODE_PRINTF("ROR\t");
3718 DECODE_PRINTF("RCL\t");
3721 DECODE_PRINTF("RCR\t");
3724 DECODE_PRINTF("SHL\t");
3727 DECODE_PRINTF("SHR\t");
3730 DECODE_PRINTF("SAL\t");
3733 DECODE_PRINTF("SAR\t");
3738 /* know operation, decode the mod byte to find the addressing
3741 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3744 DECODE_PRINTF("DWORD PTR ");
3745 destoffset = decode_rmXX_address(mod, rl);
3746 DECODE_PRINTF(",1\n");
3747 destval = fetch_data_long(destoffset);
3749 destval = (*opcD1_long_operation[rh]) (destval, 1);
3750 store_data_long(destoffset, destval);
3754 DECODE_PRINTF("WORD PTR ");
3755 destoffset = decode_rmXX_address(mod, rl);
3756 DECODE_PRINTF(",1\n");
3757 destval = fetch_data_word(destoffset);
3759 destval = (*opcD1_word_operation[rh]) (destval, 1);
3760 store_data_word(destoffset, destval);
3762 } else { /* register to register */
3763 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3767 destreg = DECODE_RM_LONG_REGISTER(rl);
3768 DECODE_PRINTF(",1\n");
3770 destval = (*opcD1_long_operation[rh]) (*destreg, 1);
3776 destreg = DECODE_RM_WORD_REGISTER(rl);
3777 DECODE_PRINTF(",1\n");
3779 destval = (*opcD1_word_operation[rh]) (*destreg, 1);
3783 DECODE_CLEAR_SEGOVR();
3787 /****************************************************************************
3790 ****************************************************************************/
3791 void x86emuOp_opcD2_byte_RM_CL(u8 X86EMU_UNUSED(op1))
3800 * Yet another weirdo special case instruction format. Part of
3801 * the opcode held below in "RH". Doubly nested case would
3802 * result, except that the decoded instruction
3805 FETCH_DECODE_MODRM(mod, rh, rl);
3807 if (DEBUG_DECODE()) {
3808 /* XXX DECODE_PRINTF may be changed to something more
3809 general, so that it is important to leave the strings
3810 in the same format, even though the result is that the
3811 above test is done twice. */
3814 DECODE_PRINTF("ROL\t");
3817 DECODE_PRINTF("ROR\t");
3820 DECODE_PRINTF("RCL\t");
3823 DECODE_PRINTF("RCR\t");
3826 DECODE_PRINTF("SHL\t");
3829 DECODE_PRINTF("SHR\t");
3832 DECODE_PRINTF("SAL\t");
3835 DECODE_PRINTF("SAR\t");
3840 /* know operation, decode the mod byte to find the addressing
3844 DECODE_PRINTF("BYTE PTR ");
3845 destoffset = decode_rmXX_address(mod, rl);
3846 DECODE_PRINTF(",CL\n");
3847 destval = fetch_data_byte(destoffset);
3849 destval = (*opcD0_byte_operation[rh]) (destval, amt);
3850 store_data_byte(destoffset, destval);
3851 } else { /* register to register */
3852 destreg = DECODE_RM_BYTE_REGISTER(rl);
3853 DECODE_PRINTF(",CL\n");
3855 destval = (*opcD0_byte_operation[rh]) (*destreg, amt);
3858 DECODE_CLEAR_SEGOVR();
3862 /****************************************************************************
3865 ****************************************************************************/
3866 void x86emuOp_opcD3_word_RM_CL(u8 X86EMU_UNUSED(op1))
3873 * Yet another weirdo special case instruction format. Part of
3874 * the opcode held below in "RH". Doubly nested case would
3875 * result, except that the decoded instruction
3878 FETCH_DECODE_MODRM(mod, rh, rl);
3880 if (DEBUG_DECODE()) {
3881 /* XXX DECODE_PRINTF may be changed to something more
3882 general, so that it is important to leave the strings
3883 in the same format, even though the result is that the
3884 above test is done twice. */
3887 DECODE_PRINTF("ROL\t");
3890 DECODE_PRINTF("ROR\t");
3893 DECODE_PRINTF("RCL\t");
3896 DECODE_PRINTF("RCR\t");
3899 DECODE_PRINTF("SHL\t");
3902 DECODE_PRINTF("SHR\t");
3905 DECODE_PRINTF("SAL\t");
3908 DECODE_PRINTF("SAR\t");
3913 /* know operation, decode the mod byte to find the addressing
3917 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3920 DECODE_PRINTF("DWORD PTR ");
3921 destoffset = decode_rmXX_address(mod, rl);
3922 DECODE_PRINTF(",CL\n");
3923 destval = fetch_data_long(destoffset);
3925 destval = (*opcD1_long_operation[rh]) (destval, amt);
3926 store_data_long(destoffset, destval);
3930 DECODE_PRINTF("WORD PTR ");
3931 destoffset = decode_rmXX_address(mod, rl);
3932 DECODE_PRINTF(",CL\n");
3933 destval = fetch_data_word(destoffset);
3935 destval = (*opcD1_word_operation[rh]) (destval, amt);
3936 store_data_word(destoffset, destval);
3938 } else { /* register to register */
3939 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3942 destreg = DECODE_RM_LONG_REGISTER(rl);
3943 DECODE_PRINTF(",CL\n");
3945 *destreg = (*opcD1_long_operation[rh]) (*destreg, amt);
3949 destreg = DECODE_RM_WORD_REGISTER(rl);
3950 DECODE_PRINTF(",CL\n");
3952 *destreg = (*opcD1_word_operation[rh]) (*destreg, amt);
3955 DECODE_CLEAR_SEGOVR();
3959 /****************************************************************************
3962 ****************************************************************************/
3963 void x86emuOp_aam(u8 X86EMU_UNUSED(op1))
3968 DECODE_PRINTF("AAM\n");
3969 a = fetch_byte_imm(); /* this is a stupid encoding. */
3971 DECODE_PRINTF("ERROR DECODING AAM\n");
3976 /* note the type change here --- returning AL and AH in AX. */
3977 M.x86.R_AX = aam_word(M.x86.R_AL);
3978 DECODE_CLEAR_SEGOVR();
3982 /****************************************************************************
3985 ****************************************************************************/
3986 void x86emuOp_aad(u8 X86EMU_UNUSED(op1))
3989 DECODE_PRINTF("AAD\n");
3990 (void)fetch_byte_imm();
3992 M.x86.R_AX = aad_word(M.x86.R_AX);
3993 DECODE_CLEAR_SEGOVR();
3997 /* opcode 0xd6 ILLEGAL OPCODE */
3999 /****************************************************************************
4002 ****************************************************************************/
4003 void x86emuOp_xlat(u8 X86EMU_UNUSED(op1))
4008 DECODE_PRINTF("XLAT\n");
4010 addr = (u16)(M.x86.R_BX + (u8)M.x86.R_AL);
4011 M.x86.R_AL = fetch_data_byte(addr);
4012 DECODE_CLEAR_SEGOVR();
4016 /* instuctions D8 .. DF are in i87_ops.c */
4018 /****************************************************************************
4021 ****************************************************************************/
4022 void x86emuOp_loopne(u8 X86EMU_UNUSED(op1))
4027 DECODE_PRINTF("LOOPNE\t");
4028 ip = (s8) fetch_byte_imm();
4029 ip += (s16) M.x86.R_IP;
4030 DECODE_PRINTF2("%04x\n", ip);
4033 if (M.x86.R_CX != 0 && !ACCESS_FLAG(F_ZF)) /* CX != 0 and !ZF */
4035 DECODE_CLEAR_SEGOVR();
4039 /****************************************************************************
4042 ****************************************************************************/
4043 void x86emuOp_loope(u8 X86EMU_UNUSED(op1))
4048 DECODE_PRINTF("LOOPE\t");
4049 ip = (s8) fetch_byte_imm();
4050 ip += (s16) M.x86.R_IP;
4051 DECODE_PRINTF2("%04x\n", ip);
4054 if (M.x86.R_CX != 0 && ACCESS_FLAG(F_ZF)) /* CX != 0 and ZF */
4056 DECODE_CLEAR_SEGOVR();
4060 /****************************************************************************
4063 ****************************************************************************/
4064 void x86emuOp_loop(u8 X86EMU_UNUSED(op1))
4069 DECODE_PRINTF("LOOP\t");
4070 ip = (s8) fetch_byte_imm();
4071 ip += (s16) M.x86.R_IP;
4072 DECODE_PRINTF2("%04x\n", ip);
4075 if (M.x86.R_CX != 0)
4077 DECODE_CLEAR_SEGOVR();
4081 /****************************************************************************
4084 ****************************************************************************/
4085 void x86emuOp_jcxz(u8 X86EMU_UNUSED(op1))
4090 /* jump to byte offset if overflow flag is set */
4092 DECODE_PRINTF("JCXZ\t");
4093 offset = (s8)fetch_byte_imm();
4094 target = (u16)(M.x86.R_IP + offset);
4095 DECODE_PRINTF2("%x\n", target);
4097 if (M.x86.R_CX == 0)
4098 M.x86.R_IP = target;
4099 DECODE_CLEAR_SEGOVR();
4103 /****************************************************************************
4106 ****************************************************************************/
4107 void x86emuOp_in_byte_AL_IMM(u8 X86EMU_UNUSED(op1))
4112 DECODE_PRINTF("IN\t");
4113 port = (u8) fetch_byte_imm();
4114 DECODE_PRINTF2("%x,AL\n", port);
4116 M.x86.R_AL = (*sys_inb)(port);
4117 DECODE_CLEAR_SEGOVR();
4121 /****************************************************************************
4124 ****************************************************************************/
4125 void x86emuOp_in_word_AX_IMM(u8 X86EMU_UNUSED(op1))
4130 DECODE_PRINTF("IN\t");
4131 port = (u8) fetch_byte_imm();
4132 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4133 DECODE_PRINTF2("EAX,%x\n", port);
4135 DECODE_PRINTF2("AX,%x\n", port);
4138 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4139 M.x86.R_EAX = (*sys_inl)(port);
4141 M.x86.R_AX = (*sys_inw)(port);
4143 DECODE_CLEAR_SEGOVR();
4147 /****************************************************************************
4150 ****************************************************************************/
4151 void x86emuOp_out_byte_IMM_AL(u8 X86EMU_UNUSED(op1))
4156 DECODE_PRINTF("OUT\t");
4157 port = (u8) fetch_byte_imm();
4158 DECODE_PRINTF2("%x,AL\n", port);
4160 (*sys_outb)(port, M.x86.R_AL);
4161 DECODE_CLEAR_SEGOVR();
4165 /****************************************************************************
4168 ****************************************************************************/
4169 void x86emuOp_out_word_IMM_AX(u8 X86EMU_UNUSED(op1))
4174 DECODE_PRINTF("OUT\t");
4175 port = (u8) fetch_byte_imm();
4176 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4177 DECODE_PRINTF2("%x,EAX\n", port);
4179 DECODE_PRINTF2("%x,AX\n", port);
4182 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4183 (*sys_outl)(port, M.x86.R_EAX);
4185 (*sys_outw)(port, M.x86.R_AX);
4187 DECODE_CLEAR_SEGOVR();
4191 /****************************************************************************
4194 ****************************************************************************/
4195 void x86emuOp_call_near_IMM(u8 X86EMU_UNUSED(op1))
4200 DECODE_PRINTF("CALL\t");
4201 ip = (s16) fetch_word_imm();
4202 ip += (s16) M.x86.R_IP; /* CHECK SIGN */
4203 DECODE_PRINTF2("%04x\n", ip);
4204 CALL_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, ip, "");
4206 push_word(M.x86.R_IP);
4208 DECODE_CLEAR_SEGOVR();
4212 /****************************************************************************
4215 ****************************************************************************/
4216 void x86emuOp_jump_near_IMM(u8 X86EMU_UNUSED(op1))
4221 DECODE_PRINTF("JMP\t");
4222 ip = (s16)fetch_word_imm();
4223 ip += (s16)M.x86.R_IP;
4224 DECODE_PRINTF2("%04x\n", ip);
4226 M.x86.R_IP = (u16)ip;
4227 DECODE_CLEAR_SEGOVR();
4231 /****************************************************************************
4234 ****************************************************************************/
4235 void x86emuOp_jump_far_IMM(u8 X86EMU_UNUSED(op1))
4240 DECODE_PRINTF("JMP\tFAR ");
4241 ip = fetch_word_imm();
4242 cs = fetch_word_imm();
4243 DECODE_PRINTF2("%04x:", cs);
4244 DECODE_PRINTF2("%04x\n", ip);
4248 DECODE_CLEAR_SEGOVR();
4252 /****************************************************************************
4255 ****************************************************************************/
4256 void x86emuOp_jump_byte_IMM(u8 X86EMU_UNUSED(op1))
4262 DECODE_PRINTF("JMP\t");
4263 offset = (s8)fetch_byte_imm();
4264 target = (u16)(M.x86.R_IP + offset);
4265 DECODE_PRINTF2("%x\n", target);
4267 M.x86.R_IP = target;
4268 DECODE_CLEAR_SEGOVR();
4272 /****************************************************************************
4275 ****************************************************************************/
4276 void x86emuOp_in_byte_AL_DX(u8 X86EMU_UNUSED(op1))
4279 DECODE_PRINTF("IN\tAL,DX\n");
4281 M.x86.R_AL = (*sys_inb)(M.x86.R_DX);
4282 DECODE_CLEAR_SEGOVR();
4286 /****************************************************************************
4289 ****************************************************************************/
4290 void x86emuOp_in_word_AX_DX(u8 X86EMU_UNUSED(op1))
4293 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4294 DECODE_PRINTF("IN\tEAX,DX\n");
4296 DECODE_PRINTF("IN\tAX,DX\n");
4299 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4300 M.x86.R_EAX = (*sys_inl)(M.x86.R_DX);
4302 M.x86.R_AX = (*sys_inw)(M.x86.R_DX);
4304 DECODE_CLEAR_SEGOVR();
4308 /****************************************************************************
4311 ****************************************************************************/
4312 void x86emuOp_out_byte_DX_AL(u8 X86EMU_UNUSED(op1))
4315 DECODE_PRINTF("OUT\tDX,AL\n");
4317 (*sys_outb)(M.x86.R_DX, M.x86.R_AL);
4318 DECODE_CLEAR_SEGOVR();
4322 /****************************************************************************
4325 ****************************************************************************/
4326 void x86emuOp_out_word_DX_AX(u8 X86EMU_UNUSED(op1))
4329 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4330 DECODE_PRINTF("OUT\tDX,EAX\n");
4332 DECODE_PRINTF("OUT\tDX,AX\n");
4335 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4336 (*sys_outl)(M.x86.R_DX, M.x86.R_EAX);
4338 (*sys_outw)(M.x86.R_DX, M.x86.R_AX);
4340 DECODE_CLEAR_SEGOVR();
4344 /****************************************************************************
4347 ****************************************************************************/
4348 void x86emuOp_lock(u8 X86EMU_UNUSED(op1))
4351 DECODE_PRINTF("LOCK:\n");
4353 DECODE_CLEAR_SEGOVR();
4357 /*opcode 0xf1 ILLEGAL OPERATION */
4359 /****************************************************************************
4362 ****************************************************************************/
4363 void x86emuOp_repne(u8 X86EMU_UNUSED(op1))
4366 DECODE_PRINTF("REPNE\n");
4368 M.x86.mode |= SYSMODE_PREFIX_REPNE;
4369 DECODE_CLEAR_SEGOVR();
4373 /****************************************************************************
4376 ****************************************************************************/
4377 void x86emuOp_repe(u8 X86EMU_UNUSED(op1))
4380 DECODE_PRINTF("REPE\n");
4382 M.x86.mode |= SYSMODE_PREFIX_REPE;
4383 DECODE_CLEAR_SEGOVR();
4387 /****************************************************************************
4390 ****************************************************************************/
4391 void x86emuOp_halt(u8 X86EMU_UNUSED(op1))
4394 DECODE_PRINTF("HALT\n");
4397 DECODE_CLEAR_SEGOVR();
4401 /****************************************************************************
4404 ****************************************************************************/
4405 void x86emuOp_cmc(u8 X86EMU_UNUSED(op1))
4407 /* complement the carry flag. */
4409 DECODE_PRINTF("CMC\n");
4412 DECODE_CLEAR_SEGOVR();
4416 /****************************************************************************
4419 ****************************************************************************/
4420 void x86emuOp_opcF6_byte_RM(u8 X86EMU_UNUSED(op1))
4427 /* long, drawn out code follows. Double switch for a total
4430 FETCH_DECODE_MODRM(mod, rh, rl);
4431 DECODE_PRINTF(opF6_names[rh]);
4433 DECODE_PRINTF("BYTE PTR ");
4434 destoffset = decode_rmXX_address(mod, rl);
4435 destval = fetch_data_byte(destoffset);
4438 case 0: /* test byte imm */
4440 srcval = fetch_byte_imm();
4441 DECODE_PRINTF2("%02x\n", srcval);
4443 test_byte(destval, srcval);
4446 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4450 DECODE_PRINTF("\n");
4452 destval = not_byte(destval);
4453 store_data_byte(destoffset, destval);
4456 DECODE_PRINTF("\n");
4458 destval = neg_byte(destval);
4459 store_data_byte(destoffset, destval);
4462 DECODE_PRINTF("\n");
4467 DECODE_PRINTF("\n");
4472 DECODE_PRINTF("\n");
4477 DECODE_PRINTF("\n");
4482 } else { /* mod=11 */
4483 destreg = DECODE_RM_BYTE_REGISTER(rl);
4485 case 0: /* test byte imm */
4487 srcval = fetch_byte_imm();
4488 DECODE_PRINTF2("%02x\n", srcval);
4490 test_byte(*destreg, srcval);
4493 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4497 DECODE_PRINTF("\n");
4499 *destreg = not_byte(*destreg);
4502 DECODE_PRINTF("\n");
4504 *destreg = neg_byte(*destreg);
4507 DECODE_PRINTF("\n");
4509 mul_byte(*destreg); /*!!! */
4512 DECODE_PRINTF("\n");
4514 imul_byte(*destreg);
4517 DECODE_PRINTF("\n");
4522 DECODE_PRINTF("\n");
4524 idiv_byte(*destreg);
4528 DECODE_CLEAR_SEGOVR();
4532 /****************************************************************************
4535 ****************************************************************************/
4536 void x86emuOp_opcF7_word_RM(u8 X86EMU_UNUSED(op1))
4542 FETCH_DECODE_MODRM(mod, rh, rl);
4543 DECODE_PRINTF(opF6_names[rh]);
4546 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4547 u32 destval, srcval;
4549 DECODE_PRINTF("DWORD PTR ");
4550 destoffset = decode_rmXX_address(mod, rl);
4551 destval = fetch_data_long(destoffset);
4556 srcval = fetch_long_imm();
4557 DECODE_PRINTF2("%x\n", srcval);
4559 test_long(destval, srcval);
4562 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F7\n");
4566 DECODE_PRINTF("\n");
4568 destval = not_long(destval);
4569 store_data_long(destoffset, destval);
4572 DECODE_PRINTF("\n");
4574 destval = neg_long(destval);
4575 store_data_long(destoffset, destval);
4578 DECODE_PRINTF("\n");
4583 DECODE_PRINTF("\n");
4588 DECODE_PRINTF("\n");
4593 DECODE_PRINTF("\n");
4599 u16 destval, srcval;
4601 DECODE_PRINTF("WORD PTR ");
4602 destoffset = decode_rmXX_address(mod, rl);
4603 destval = fetch_data_word(destoffset);
4606 case 0: /* test word imm */
4608 srcval = fetch_word_imm();
4609 DECODE_PRINTF2("%x\n", srcval);
4611 test_word(destval, srcval);
4614 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F7\n");
4618 DECODE_PRINTF("\n");
4620 destval = not_word(destval);
4621 store_data_word(destoffset, destval);
4624 DECODE_PRINTF("\n");
4626 destval = neg_word(destval);
4627 store_data_word(destoffset, destval);
4630 DECODE_PRINTF("\n");
4635 DECODE_PRINTF("\n");
4640 DECODE_PRINTF("\n");
4645 DECODE_PRINTF("\n");
4652 } else { /* mod=11 */
4654 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4658 destreg = DECODE_RM_LONG_REGISTER(rl);
4661 case 0: /* test word imm */
4663 srcval = fetch_long_imm();
4664 DECODE_PRINTF2("%x\n", srcval);
4666 test_long(*destreg, srcval);
4669 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4673 DECODE_PRINTF("\n");
4675 *destreg = not_long(*destreg);
4678 DECODE_PRINTF("\n");
4680 *destreg = neg_long(*destreg);
4683 DECODE_PRINTF("\n");
4685 mul_long(*destreg); /*!!! */
4688 DECODE_PRINTF("\n");
4690 imul_long(*destreg);
4693 DECODE_PRINTF("\n");
4698 DECODE_PRINTF("\n");
4700 idiv_long(*destreg);
4707 destreg = DECODE_RM_WORD_REGISTER(rl);
4710 case 0: /* test word imm */
4712 srcval = fetch_word_imm();
4713 DECODE_PRINTF2("%x\n", srcval);
4715 test_word(*destreg, srcval);
4718 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4722 DECODE_PRINTF("\n");
4724 *destreg = not_word(*destreg);
4727 DECODE_PRINTF("\n");
4729 *destreg = neg_word(*destreg);
4732 DECODE_PRINTF("\n");
4734 mul_word(*destreg); /*!!! */
4737 DECODE_PRINTF("\n");
4739 imul_word(*destreg);
4742 DECODE_PRINTF("\n");
4747 DECODE_PRINTF("\n");
4749 idiv_word(*destreg);
4754 DECODE_CLEAR_SEGOVR();
4758 /****************************************************************************
4761 ****************************************************************************/
4762 void x86emuOp_clc(u8 X86EMU_UNUSED(op1))
4764 /* clear the carry flag. */
4766 DECODE_PRINTF("CLC\n");
4769 DECODE_CLEAR_SEGOVR();
4773 /****************************************************************************
4776 ****************************************************************************/
4777 void x86emuOp_stc(u8 X86EMU_UNUSED(op1))
4779 /* set the carry flag. */
4781 DECODE_PRINTF("STC\n");
4784 DECODE_CLEAR_SEGOVR();
4788 /****************************************************************************
4791 ****************************************************************************/
4792 void x86emuOp_cli(u8 X86EMU_UNUSED(op1))
4794 /* clear interrupts. */
4796 DECODE_PRINTF("CLI\n");
4799 DECODE_CLEAR_SEGOVR();
4803 /****************************************************************************
4806 ****************************************************************************/
4807 void x86emuOp_sti(u8 X86EMU_UNUSED(op1))
4809 /* enable interrupts. */
4811 DECODE_PRINTF("STI\n");
4814 DECODE_CLEAR_SEGOVR();
4818 /****************************************************************************
4821 ****************************************************************************/
4822 void x86emuOp_cld(u8 X86EMU_UNUSED(op1))
4824 /* clear interrupts. */
4826 DECODE_PRINTF("CLD\n");
4829 DECODE_CLEAR_SEGOVR();
4833 /****************************************************************************
4836 ****************************************************************************/
4837 void x86emuOp_std(u8 X86EMU_UNUSED(op1))
4839 /* clear interrupts. */
4841 DECODE_PRINTF("STD\n");
4844 DECODE_CLEAR_SEGOVR();
4848 /****************************************************************************
4851 ****************************************************************************/
4852 void x86emuOp_opcFE_byte_RM(u8 X86EMU_UNUSED(op1))
4859 /* Yet another special case instruction. */
4861 FETCH_DECODE_MODRM(mod, rh, rl);
4863 if (DEBUG_DECODE()) {
4864 /* XXX DECODE_PRINTF may be changed to something more
4865 general, so that it is important to leave the strings
4866 in the same format, even though the result is that the
4867 above test is done twice. */
4871 DECODE_PRINTF("INC\t");
4874 DECODE_PRINTF("DEC\t");
4882 DECODE_PRINTF2("ILLEGAL OP MAJOR OP 0xFE MINOR OP %x \n", mod);
4889 DECODE_PRINTF("BYTE PTR ");
4890 destoffset = decode_rmXX_address(mod, rl);
4891 DECODE_PRINTF("\n");
4892 destval = fetch_data_byte(destoffset);
4895 destval = inc_byte(destval);
4897 destval = dec_byte(destval);
4898 store_data_byte(destoffset, destval);
4900 destreg = DECODE_RM_BYTE_REGISTER(rl);
4901 DECODE_PRINTF("\n");
4904 *destreg = inc_byte(*destreg);
4906 *destreg = dec_byte(*destreg);
4908 DECODE_CLEAR_SEGOVR();
4912 /****************************************************************************
4915 ****************************************************************************/
4916 void x86emuOp_opcFF_word_RM(u8 X86EMU_UNUSED(op1))
4919 uint destoffset = 0;
4921 u16 destval,destval2;
4923 /* Yet another special case instruction. */
4925 FETCH_DECODE_MODRM(mod, rh, rl);
4927 if (DEBUG_DECODE()) {
4928 /* XXX DECODE_PRINTF may be changed to something more
4929 general, so that it is important to leave the strings
4930 in the same format, even though the result is that the
4931 above test is done twice. */
4935 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4936 DECODE_PRINTF("INC\tDWORD PTR ");
4938 DECODE_PRINTF("INC\tWORD PTR ");
4942 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4943 DECODE_PRINTF("DEC\tDWORD PTR ");
4945 DECODE_PRINTF("DEC\tWORD PTR ");
4949 DECODE_PRINTF("CALL\t ");
4952 DECODE_PRINTF("CALL\tFAR ");
4955 DECODE_PRINTF("JMP\t");
4958 DECODE_PRINTF("JMP\tFAR ");
4961 DECODE_PRINTF("PUSH\t");
4964 DECODE_PRINTF("ILLEGAL DECODING OF OPCODE FF\t");
4971 destoffset = decode_rmXX_address(mod, rl);
4972 DECODE_PRINTF("\n");
4974 case 0: /* inc word ptr ... */
4975 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4978 destval = fetch_data_long(destoffset);
4980 destval = inc_long(destval);
4981 store_data_long(destoffset, destval);
4985 destval = fetch_data_word(destoffset);
4987 destval = inc_word(destval);
4988 store_data_word(destoffset, destval);
4991 case 1: /* dec word ptr ... */
4992 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4995 destval = fetch_data_long(destoffset);
4997 destval = dec_long(destval);
4998 store_data_long(destoffset, destval);
5002 destval = fetch_data_word(destoffset);
5004 destval = dec_word(destval);
5005 store_data_word(destoffset, destval);
5008 case 2: /* call word ptr ... */
5009 destval = fetch_data_word(destoffset);
5011 push_word(M.x86.R_IP);
5012 M.x86.R_IP = destval;
5014 case 3: /* call far ptr ... */
5015 destval = fetch_data_word(destoffset);
5016 destval2 = fetch_data_word(destoffset + 2);
5018 push_word(M.x86.R_CS);
5019 M.x86.R_CS = destval2;
5020 push_word(M.x86.R_IP);
5021 M.x86.R_IP = destval;
5023 case 4: /* jmp word ptr ... */
5024 destval = fetch_data_word(destoffset);
5026 M.x86.R_IP = destval;
5028 case 5: /* jmp far ptr ... */
5029 destval = fetch_data_word(destoffset);
5030 destval2 = fetch_data_word(destoffset + 2);
5032 M.x86.R_IP = destval;
5033 M.x86.R_CS = destval2;
5035 case 6: /* push word ptr ... */
5036 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5039 destval = fetch_data_long(destoffset);
5045 destval = fetch_data_word(destoffset);
5054 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5057 destreg = DECODE_RM_LONG_REGISTER(rl);
5058 DECODE_PRINTF("\n");
5060 *destreg = inc_long(*destreg);
5064 destreg = DECODE_RM_WORD_REGISTER(rl);
5065 DECODE_PRINTF("\n");
5067 *destreg = inc_word(*destreg);
5071 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5074 destreg = DECODE_RM_LONG_REGISTER(rl);
5075 DECODE_PRINTF("\n");
5077 *destreg = dec_long(*destreg);
5081 destreg = DECODE_RM_WORD_REGISTER(rl);
5082 DECODE_PRINTF("\n");
5084 *destreg = dec_word(*destreg);
5087 case 2: /* call word ptr ... */
5088 destreg = DECODE_RM_WORD_REGISTER(rl);
5089 DECODE_PRINTF("\n");
5091 push_word(M.x86.R_IP);
5092 M.x86.R_IP = *destreg;
5094 case 3: /* jmp far ptr ... */
5095 DECODE_PRINTF("OPERATION UNDEFINED 0XFF \n");
5100 case 4: /* jmp ... */
5101 destreg = DECODE_RM_WORD_REGISTER(rl);
5102 DECODE_PRINTF("\n");
5104 M.x86.R_IP = (u16) (*destreg);
5106 case 5: /* jmp far ptr ... */
5107 DECODE_PRINTF("OPERATION UNDEFINED 0XFF \n");
5112 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5115 destreg = DECODE_RM_LONG_REGISTER(rl);
5116 DECODE_PRINTF("\n");
5118 push_long(*destreg);
5122 destreg = DECODE_RM_WORD_REGISTER(rl);
5123 DECODE_PRINTF("\n");
5125 push_word(*destreg);
5130 DECODE_CLEAR_SEGOVR();
5134 /***************************************************************************
5135 * Single byte operation code table:
5136 **************************************************************************/
5137 void (*x86emu_optab[256])(u8) =
5139 /* 0x00 */ x86emuOp_genop_byte_RM_R,
5140 /* 0x01 */ x86emuOp_genop_word_RM_R,
5141 /* 0x02 */ x86emuOp_genop_byte_R_RM,
5142 /* 0x03 */ x86emuOp_genop_word_R_RM,
5143 /* 0x04 */ x86emuOp_genop_byte_AL_IMM,
5144 /* 0x05 */ x86emuOp_genop_word_AX_IMM,
5145 /* 0x06 */ x86emuOp_push_ES,
5146 /* 0x07 */ x86emuOp_pop_ES,
5148 /* 0x08 */ x86emuOp_genop_byte_RM_R,
5149 /* 0x09 */ x86emuOp_genop_word_RM_R,
5150 /* 0x0a */ x86emuOp_genop_byte_R_RM,
5151 /* 0x0b */ x86emuOp_genop_word_R_RM,
5152 /* 0x0c */ x86emuOp_genop_byte_AL_IMM,
5153 /* 0x0d */ x86emuOp_genop_word_AX_IMM,
5154 /* 0x0e */ x86emuOp_push_CS,
5155 /* 0x0f */ x86emuOp_two_byte,
5157 /* 0x10 */ x86emuOp_genop_byte_RM_R,
5158 /* 0x11 */ x86emuOp_genop_word_RM_R,
5159 /* 0x12 */ x86emuOp_genop_byte_R_RM,
5160 /* 0x13 */ x86emuOp_genop_word_R_RM,
5161 /* 0x14 */ x86emuOp_genop_byte_AL_IMM,
5162 /* 0x15 */ x86emuOp_genop_word_AX_IMM,
5163 /* 0x16 */ x86emuOp_push_SS,
5164 /* 0x17 */ x86emuOp_pop_SS,
5166 /* 0x18 */ x86emuOp_genop_byte_RM_R,
5167 /* 0x19 */ x86emuOp_genop_word_RM_R,
5168 /* 0x1a */ x86emuOp_genop_byte_R_RM,
5169 /* 0x1b */ x86emuOp_genop_word_R_RM,
5170 /* 0x1c */ x86emuOp_genop_byte_AL_IMM,
5171 /* 0x1d */ x86emuOp_genop_word_AX_IMM,
5172 /* 0x1e */ x86emuOp_push_DS,
5173 /* 0x1f */ x86emuOp_pop_DS,
5175 /* 0x20 */ x86emuOp_genop_byte_RM_R,
5176 /* 0x21 */ x86emuOp_genop_word_RM_R,
5177 /* 0x22 */ x86emuOp_genop_byte_R_RM,
5178 /* 0x23 */ x86emuOp_genop_word_R_RM,
5179 /* 0x24 */ x86emuOp_genop_byte_AL_IMM,
5180 /* 0x25 */ x86emuOp_genop_word_AX_IMM,
5181 /* 0x26 */ x86emuOp_segovr_ES,
5182 /* 0x27 */ x86emuOp_daa,
5184 /* 0x28 */ x86emuOp_genop_byte_RM_R,
5185 /* 0x29 */ x86emuOp_genop_word_RM_R,
5186 /* 0x2a */ x86emuOp_genop_byte_R_RM,
5187 /* 0x2b */ x86emuOp_genop_word_R_RM,
5188 /* 0x2c */ x86emuOp_genop_byte_AL_IMM,
5189 /* 0x2d */ x86emuOp_genop_word_AX_IMM,
5190 /* 0x2e */ x86emuOp_segovr_CS,
5191 /* 0x2f */ x86emuOp_das,
5193 /* 0x30 */ x86emuOp_genop_byte_RM_R,
5194 /* 0x31 */ x86emuOp_genop_word_RM_R,
5195 /* 0x32 */ x86emuOp_genop_byte_R_RM,
5196 /* 0x33 */ x86emuOp_genop_word_R_RM,
5197 /* 0x34 */ x86emuOp_genop_byte_AL_IMM,
5198 /* 0x35 */ x86emuOp_genop_word_AX_IMM,
5199 /* 0x36 */ x86emuOp_segovr_SS,
5200 /* 0x37 */ x86emuOp_aaa,
5202 /* 0x38 */ x86emuOp_genop_byte_RM_R,
5203 /* 0x39 */ x86emuOp_genop_word_RM_R,
5204 /* 0x3a */ x86emuOp_genop_byte_R_RM,
5205 /* 0x3b */ x86emuOp_genop_word_R_RM,
5206 /* 0x3c */ x86emuOp_genop_byte_AL_IMM,
5207 /* 0x3d */ x86emuOp_genop_word_AX_IMM,
5208 /* 0x3e */ x86emuOp_segovr_DS,
5209 /* 0x3f */ x86emuOp_aas,
5211 /* 0x40 */ x86emuOp_inc_register,
5212 /* 0x41 */ x86emuOp_inc_register,
5213 /* 0x42 */ x86emuOp_inc_register,
5214 /* 0x43 */ x86emuOp_inc_register,
5215 /* 0x44 */ x86emuOp_inc_register,
5216 /* 0x45 */ x86emuOp_inc_register,
5217 /* 0x46 */ x86emuOp_inc_register,
5218 /* 0x47 */ x86emuOp_inc_register,
5220 /* 0x48 */ x86emuOp_dec_register,
5221 /* 0x49 */ x86emuOp_dec_register,
5222 /* 0x4a */ x86emuOp_dec_register,
5223 /* 0x4b */ x86emuOp_dec_register,
5224 /* 0x4c */ x86emuOp_dec_register,
5225 /* 0x4d */ x86emuOp_dec_register,
5226 /* 0x4e */ x86emuOp_dec_register,
5227 /* 0x4f */ x86emuOp_dec_register,
5229 /* 0x50 */ x86emuOp_push_register,
5230 /* 0x51 */ x86emuOp_push_register,
5231 /* 0x52 */ x86emuOp_push_register,
5232 /* 0x53 */ x86emuOp_push_register,
5233 /* 0x54 */ x86emuOp_push_register,
5234 /* 0x55 */ x86emuOp_push_register,
5235 /* 0x56 */ x86emuOp_push_register,
5236 /* 0x57 */ x86emuOp_push_register,
5238 /* 0x58 */ x86emuOp_pop_register,
5239 /* 0x59 */ x86emuOp_pop_register,
5240 /* 0x5a */ x86emuOp_pop_register,
5241 /* 0x5b */ x86emuOp_pop_register,
5242 /* 0x5c */ x86emuOp_pop_register,
5243 /* 0x5d */ x86emuOp_pop_register,
5244 /* 0x5e */ x86emuOp_pop_register,
5245 /* 0x5f */ x86emuOp_pop_register,
5247 /* 0x60 */ x86emuOp_push_all,
5248 /* 0x61 */ x86emuOp_pop_all,
5249 /* 0x62 */ x86emuOp_illegal_op, /* bound */
5250 /* 0x63 */ x86emuOp_illegal_op, /* arpl */
5251 /* 0x64 */ x86emuOp_segovr_FS,
5252 /* 0x65 */ x86emuOp_segovr_GS,
5253 /* 0x66 */ x86emuOp_prefix_data,
5254 /* 0x67 */ x86emuOp_prefix_addr,
5256 /* 0x68 */ x86emuOp_push_word_IMM,
5257 /* 0x69 */ x86emuOp_imul_word_IMM,
5258 /* 0x6a */ x86emuOp_push_byte_IMM,
5259 /* 0x6b */ x86emuOp_imul_byte_IMM,
5260 /* 0x6c */ x86emuOp_ins_byte,
5261 /* 0x6d */ x86emuOp_ins_word,
5262 /* 0x6e */ x86emuOp_outs_byte,
5263 /* 0x6f */ x86emuOp_outs_word,
5265 /* 0x70 */ x86emuOp_jump_near_cond,
5266 /* 0x71 */ x86emuOp_jump_near_cond,
5267 /* 0x72 */ x86emuOp_jump_near_cond,
5268 /* 0x73 */ x86emuOp_jump_near_cond,
5269 /* 0x74 */ x86emuOp_jump_near_cond,
5270 /* 0x75 */ x86emuOp_jump_near_cond,
5271 /* 0x76 */ x86emuOp_jump_near_cond,
5272 /* 0x77 */ x86emuOp_jump_near_cond,
5274 /* 0x78 */ x86emuOp_jump_near_cond,
5275 /* 0x79 */ x86emuOp_jump_near_cond,
5276 /* 0x7a */ x86emuOp_jump_near_cond,
5277 /* 0x7b */ x86emuOp_jump_near_cond,
5278 /* 0x7c */ x86emuOp_jump_near_cond,
5279 /* 0x7d */ x86emuOp_jump_near_cond,
5280 /* 0x7e */ x86emuOp_jump_near_cond,
5281 /* 0x7f */ x86emuOp_jump_near_cond,
5283 /* 0x80 */ x86emuOp_opc80_byte_RM_IMM,
5284 /* 0x81 */ x86emuOp_opc81_word_RM_IMM,
5285 /* 0x82 */ x86emuOp_opc82_byte_RM_IMM,
5286 /* 0x83 */ x86emuOp_opc83_word_RM_IMM,
5287 /* 0x84 */ x86emuOp_test_byte_RM_R,
5288 /* 0x85 */ x86emuOp_test_word_RM_R,
5289 /* 0x86 */ x86emuOp_xchg_byte_RM_R,
5290 /* 0x87 */ x86emuOp_xchg_word_RM_R,
5292 /* 0x88 */ x86emuOp_mov_byte_RM_R,
5293 /* 0x89 */ x86emuOp_mov_word_RM_R,
5294 /* 0x8a */ x86emuOp_mov_byte_R_RM,
5295 /* 0x8b */ x86emuOp_mov_word_R_RM,
5296 /* 0x8c */ x86emuOp_mov_word_RM_SR,
5297 /* 0x8d */ x86emuOp_lea_word_R_M,
5298 /* 0x8e */ x86emuOp_mov_word_SR_RM,
5299 /* 0x8f */ x86emuOp_pop_RM,
5301 /* 0x90 */ x86emuOp_nop,
5302 /* 0x91 */ x86emuOp_xchg_word_AX_register,
5303 /* 0x92 */ x86emuOp_xchg_word_AX_register,
5304 /* 0x93 */ x86emuOp_xchg_word_AX_register,
5305 /* 0x94 */ x86emuOp_xchg_word_AX_register,
5306 /* 0x95 */ x86emuOp_xchg_word_AX_register,
5307 /* 0x96 */ x86emuOp_xchg_word_AX_register,
5308 /* 0x97 */ x86emuOp_xchg_word_AX_register,
5310 /* 0x98 */ x86emuOp_cbw,
5311 /* 0x99 */ x86emuOp_cwd,
5312 /* 0x9a */ x86emuOp_call_far_IMM,
5313 /* 0x9b */ x86emuOp_wait,
5314 /* 0x9c */ x86emuOp_pushf_word,
5315 /* 0x9d */ x86emuOp_popf_word,
5316 /* 0x9e */ x86emuOp_sahf,
5317 /* 0x9f */ x86emuOp_lahf,
5319 /* 0xa0 */ x86emuOp_mov_AL_M_IMM,
5320 /* 0xa1 */ x86emuOp_mov_AX_M_IMM,
5321 /* 0xa2 */ x86emuOp_mov_M_AL_IMM,
5322 /* 0xa3 */ x86emuOp_mov_M_AX_IMM,
5323 /* 0xa4 */ x86emuOp_movs_byte,
5324 /* 0xa5 */ x86emuOp_movs_word,
5325 /* 0xa6 */ x86emuOp_cmps_byte,
5326 /* 0xa7 */ x86emuOp_cmps_word,
5327 /* 0xa8 */ x86emuOp_test_AL_IMM,
5328 /* 0xa9 */ x86emuOp_test_AX_IMM,
5329 /* 0xaa */ x86emuOp_stos_byte,
5330 /* 0xab */ x86emuOp_stos_word,
5331 /* 0xac */ x86emuOp_lods_byte,
5332 /* 0xad */ x86emuOp_lods_word,
5333 /* 0xac */ x86emuOp_scas_byte,
5334 /* 0xad */ x86emuOp_scas_word,
5336 /* 0xb0 */ x86emuOp_mov_byte_register_IMM,
5337 /* 0xb1 */ x86emuOp_mov_byte_register_IMM,
5338 /* 0xb2 */ x86emuOp_mov_byte_register_IMM,
5339 /* 0xb3 */ x86emuOp_mov_byte_register_IMM,
5340 /* 0xb4 */ x86emuOp_mov_byte_register_IMM,
5341 /* 0xb5 */ x86emuOp_mov_byte_register_IMM,
5342 /* 0xb6 */ x86emuOp_mov_byte_register_IMM,
5343 /* 0xb7 */ x86emuOp_mov_byte_register_IMM,
5345 /* 0xb8 */ x86emuOp_mov_word_register_IMM,
5346 /* 0xb9 */ x86emuOp_mov_word_register_IMM,
5347 /* 0xba */ x86emuOp_mov_word_register_IMM,
5348 /* 0xbb */ x86emuOp_mov_word_register_IMM,
5349 /* 0xbc */ x86emuOp_mov_word_register_IMM,
5350 /* 0xbd */ x86emuOp_mov_word_register_IMM,
5351 /* 0xbe */ x86emuOp_mov_word_register_IMM,
5352 /* 0xbf */ x86emuOp_mov_word_register_IMM,
5354 /* 0xc0 */ x86emuOp_opcC0_byte_RM_MEM,
5355 /* 0xc1 */ x86emuOp_opcC1_word_RM_MEM,
5356 /* 0xc2 */ x86emuOp_ret_near_IMM,
5357 /* 0xc3 */ x86emuOp_ret_near,
5358 /* 0xc4 */ x86emuOp_les_R_IMM,
5359 /* 0xc5 */ x86emuOp_lds_R_IMM,
5360 /* 0xc6 */ x86emuOp_mov_byte_RM_IMM,
5361 /* 0xc7 */ x86emuOp_mov_word_RM_IMM,
5362 /* 0xc8 */ x86emuOp_enter,
5363 /* 0xc9 */ x86emuOp_leave,
5364 /* 0xca */ x86emuOp_ret_far_IMM,
5365 /* 0xcb */ x86emuOp_ret_far,
5366 /* 0xcc */ x86emuOp_int3,
5367 /* 0xcd */ x86emuOp_int_IMM,
5368 /* 0xce */ x86emuOp_into,
5369 /* 0xcf */ x86emuOp_iret,
5371 /* 0xd0 */ x86emuOp_opcD0_byte_RM_1,
5372 /* 0xd1 */ x86emuOp_opcD1_word_RM_1,
5373 /* 0xd2 */ x86emuOp_opcD2_byte_RM_CL,
5374 /* 0xd3 */ x86emuOp_opcD3_word_RM_CL,
5375 /* 0xd4 */ x86emuOp_aam,
5376 /* 0xd5 */ x86emuOp_aad,
5377 /* 0xd6 */ x86emuOp_illegal_op, /* Undocumented SETALC instruction */
5378 /* 0xd7 */ x86emuOp_xlat,
5379 /* 0xd8 */ NULL, /*x86emuOp_esc_coprocess_d8,*/
5380 /* 0xd9 */ NULL, /*x86emuOp_esc_coprocess_d9,*/
5381 /* 0xda */ NULL, /*x86emuOp_esc_coprocess_da,*/
5382 /* 0xdb */ NULL, /*x86emuOp_esc_coprocess_db,*/
5383 /* 0xdc */ NULL, /*x86emuOp_esc_coprocess_dc,*/
5384 /* 0xdd */ NULL, /*x86emuOp_esc_coprocess_dd,*/
5385 /* 0xde */ NULL, /*x86emuOp_esc_coprocess_de,*/
5386 /* 0xdf */ NULL, /*x86emuOp_esc_coprocess_df,*/
5388 /* 0xe0 */ x86emuOp_loopne,
5389 /* 0xe1 */ x86emuOp_loope,
5390 /* 0xe2 */ x86emuOp_loop,
5391 /* 0xe3 */ x86emuOp_jcxz,
5392 /* 0xe4 */ x86emuOp_in_byte_AL_IMM,
5393 /* 0xe5 */ x86emuOp_in_word_AX_IMM,
5394 /* 0xe6 */ x86emuOp_out_byte_IMM_AL,
5395 /* 0xe7 */ x86emuOp_out_word_IMM_AX,
5397 /* 0xe8 */ x86emuOp_call_near_IMM,
5398 /* 0xe9 */ x86emuOp_jump_near_IMM,
5399 /* 0xea */ x86emuOp_jump_far_IMM,
5400 /* 0xeb */ x86emuOp_jump_byte_IMM,
5401 /* 0xec */ x86emuOp_in_byte_AL_DX,
5402 /* 0xed */ x86emuOp_in_word_AX_DX,
5403 /* 0xee */ x86emuOp_out_byte_DX_AL,
5404 /* 0xef */ x86emuOp_out_word_DX_AX,
5406 /* 0xf0 */ x86emuOp_lock,
5407 /* 0xf1 */ x86emuOp_illegal_op,
5408 /* 0xf2 */ x86emuOp_repne,
5409 /* 0xf3 */ x86emuOp_repe,
5410 /* 0xf4 */ x86emuOp_halt,
5411 /* 0xf5 */ x86emuOp_cmc,
5412 /* 0xf6 */ x86emuOp_opcF6_byte_RM,
5413 /* 0xf7 */ x86emuOp_opcF7_word_RM,
5415 /* 0xf8 */ x86emuOp_clc,
5416 /* 0xf9 */ x86emuOp_stc,
5417 /* 0xfa */ x86emuOp_cli,
5418 /* 0xfb */ x86emuOp_sti,
5419 /* 0xfc */ x86emuOp_cld,
5420 /* 0xfd */ x86emuOp_std,
5421 /* 0xfe */ x86emuOp_opcFE_byte_RM,
5422 /* 0xff */ x86emuOp_opcFF_word_RM,