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))
3524 DECODE_PRINTF("INT 3\n");
3525 tmp = (u16) mem_access_word(3 * 4 + 2);
3526 /* access the segment register */
3528 if (_X86EMU_intrTab[3]) {
3529 (*_X86EMU_intrTab[3])(3);
3531 push_word((u16)M.x86.R_FLG);
3534 push_word(M.x86.R_CS);
3535 M.x86.R_CS = mem_access_word(3 * 4 + 2);
3536 push_word(M.x86.R_IP);
3537 M.x86.R_IP = mem_access_word(3 * 4);
3539 DECODE_CLEAR_SEGOVR();
3543 /****************************************************************************
3546 ****************************************************************************/
3547 void x86emuOp_int_IMM(u8 X86EMU_UNUSED(op1))
3553 DECODE_PRINTF("INT\t");
3554 intnum = fetch_byte_imm();
3555 DECODE_PRINTF2("%x\n", intnum);
3556 tmp = mem_access_word(intnum * 4 + 2);
3558 if (_X86EMU_intrTab[intnum]) {
3559 (*_X86EMU_intrTab[intnum])(intnum);
3561 push_word((u16)M.x86.R_FLG);
3564 push_word(M.x86.R_CS);
3565 M.x86.R_CS = mem_access_word(intnum * 4 + 2);
3566 push_word(M.x86.R_IP);
3567 M.x86.R_IP = mem_access_word(intnum * 4);
3569 DECODE_CLEAR_SEGOVR();
3573 /****************************************************************************
3576 ****************************************************************************/
3577 void x86emuOp_into(u8 X86EMU_UNUSED(op1))
3582 DECODE_PRINTF("INTO\n");
3584 if (ACCESS_FLAG(F_OF)) {
3585 tmp = mem_access_word(4 * 4 + 2);
3586 if (_X86EMU_intrTab[4]) {
3587 (*_X86EMU_intrTab[4])(4);
3589 push_word((u16)M.x86.R_FLG);
3592 push_word(M.x86.R_CS);
3593 M.x86.R_CS = mem_access_word(4 * 4 + 2);
3594 push_word(M.x86.R_IP);
3595 M.x86.R_IP = mem_access_word(4 * 4);
3598 DECODE_CLEAR_SEGOVR();
3602 /****************************************************************************
3605 ****************************************************************************/
3606 void x86emuOp_iret(u8 X86EMU_UNUSED(op1))
3609 DECODE_PRINTF("IRET\n");
3613 M.x86.R_IP = pop_word();
3614 M.x86.R_CS = pop_word();
3615 M.x86.R_FLG = pop_word();
3616 DECODE_CLEAR_SEGOVR();
3620 /****************************************************************************
3623 ****************************************************************************/
3624 void x86emuOp_opcD0_byte_RM_1(u8 X86EMU_UNUSED(op1))
3632 * Yet another weirdo special case instruction format. Part of
3633 * the opcode held below in "RH". Doubly nested case would
3634 * result, except that the decoded instruction
3637 FETCH_DECODE_MODRM(mod, rh, rl);
3639 if (DEBUG_DECODE()) {
3640 /* XXX DECODE_PRINTF may be changed to something more
3641 general, so that it is important to leave the strings
3642 in the same format, even though the result is that the
3643 above test is done twice. */
3646 DECODE_PRINTF("ROL\t");
3649 DECODE_PRINTF("ROR\t");
3652 DECODE_PRINTF("RCL\t");
3655 DECODE_PRINTF("RCR\t");
3658 DECODE_PRINTF("SHL\t");
3661 DECODE_PRINTF("SHR\t");
3664 DECODE_PRINTF("SAL\t");
3667 DECODE_PRINTF("SAR\t");
3672 /* know operation, decode the mod byte to find the addressing
3675 DECODE_PRINTF("BYTE PTR ");
3676 destoffset = decode_rmXX_address(mod, rl);
3677 DECODE_PRINTF(",1\n");
3678 destval = fetch_data_byte(destoffset);
3680 destval = (*opcD0_byte_operation[rh]) (destval, 1);
3681 store_data_byte(destoffset, destval);
3682 } else { /* register to register */
3683 destreg = DECODE_RM_BYTE_REGISTER(rl);
3684 DECODE_PRINTF(",1\n");
3686 destval = (*opcD0_byte_operation[rh]) (*destreg, 1);
3689 DECODE_CLEAR_SEGOVR();
3693 /****************************************************************************
3696 ****************************************************************************/
3697 void x86emuOp_opcD1_word_RM_1(u8 X86EMU_UNUSED(op1))
3703 * Yet another weirdo special case instruction format. Part of
3704 * the opcode held below in "RH". Doubly nested case would
3705 * result, except that the decoded instruction
3708 FETCH_DECODE_MODRM(mod, rh, rl);
3710 if (DEBUG_DECODE()) {
3711 /* XXX DECODE_PRINTF may be changed to something more
3712 general, so that it is important to leave the strings
3713 in the same format, even though the result is that the
3714 above test is done twice. */
3717 DECODE_PRINTF("ROL\t");
3720 DECODE_PRINTF("ROR\t");
3723 DECODE_PRINTF("RCL\t");
3726 DECODE_PRINTF("RCR\t");
3729 DECODE_PRINTF("SHL\t");
3732 DECODE_PRINTF("SHR\t");
3735 DECODE_PRINTF("SAL\t");
3738 DECODE_PRINTF("SAR\t");
3743 /* know operation, decode the mod byte to find the addressing
3746 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3749 DECODE_PRINTF("DWORD PTR ");
3750 destoffset = decode_rmXX_address(mod, rl);
3751 DECODE_PRINTF(",1\n");
3752 destval = fetch_data_long(destoffset);
3754 destval = (*opcD1_long_operation[rh]) (destval, 1);
3755 store_data_long(destoffset, destval);
3759 DECODE_PRINTF("WORD PTR ");
3760 destoffset = decode_rmXX_address(mod, rl);
3761 DECODE_PRINTF(",1\n");
3762 destval = fetch_data_word(destoffset);
3764 destval = (*opcD1_word_operation[rh]) (destval, 1);
3765 store_data_word(destoffset, destval);
3767 } else { /* register to register */
3768 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3772 destreg = DECODE_RM_LONG_REGISTER(rl);
3773 DECODE_PRINTF(",1\n");
3775 destval = (*opcD1_long_operation[rh]) (*destreg, 1);
3781 destreg = DECODE_RM_WORD_REGISTER(rl);
3782 DECODE_PRINTF(",1\n");
3784 destval = (*opcD1_word_operation[rh]) (*destreg, 1);
3788 DECODE_CLEAR_SEGOVR();
3792 /****************************************************************************
3795 ****************************************************************************/
3796 void x86emuOp_opcD2_byte_RM_CL(u8 X86EMU_UNUSED(op1))
3805 * Yet another weirdo special case instruction format. Part of
3806 * the opcode held below in "RH". Doubly nested case would
3807 * result, except that the decoded instruction
3810 FETCH_DECODE_MODRM(mod, rh, rl);
3812 if (DEBUG_DECODE()) {
3813 /* XXX DECODE_PRINTF may be changed to something more
3814 general, so that it is important to leave the strings
3815 in the same format, even though the result is that the
3816 above test is done twice. */
3819 DECODE_PRINTF("ROL\t");
3822 DECODE_PRINTF("ROR\t");
3825 DECODE_PRINTF("RCL\t");
3828 DECODE_PRINTF("RCR\t");
3831 DECODE_PRINTF("SHL\t");
3834 DECODE_PRINTF("SHR\t");
3837 DECODE_PRINTF("SAL\t");
3840 DECODE_PRINTF("SAR\t");
3845 /* know operation, decode the mod byte to find the addressing
3849 DECODE_PRINTF("BYTE PTR ");
3850 destoffset = decode_rmXX_address(mod, rl);
3851 DECODE_PRINTF(",CL\n");
3852 destval = fetch_data_byte(destoffset);
3854 destval = (*opcD0_byte_operation[rh]) (destval, amt);
3855 store_data_byte(destoffset, destval);
3856 } else { /* register to register */
3857 destreg = DECODE_RM_BYTE_REGISTER(rl);
3858 DECODE_PRINTF(",CL\n");
3860 destval = (*opcD0_byte_operation[rh]) (*destreg, amt);
3863 DECODE_CLEAR_SEGOVR();
3867 /****************************************************************************
3870 ****************************************************************************/
3871 void x86emuOp_opcD3_word_RM_CL(u8 X86EMU_UNUSED(op1))
3878 * Yet another weirdo special case instruction format. Part of
3879 * the opcode held below in "RH". Doubly nested case would
3880 * result, except that the decoded instruction
3883 FETCH_DECODE_MODRM(mod, rh, rl);
3885 if (DEBUG_DECODE()) {
3886 /* XXX DECODE_PRINTF may be changed to something more
3887 general, so that it is important to leave the strings
3888 in the same format, even though the result is that the
3889 above test is done twice. */
3892 DECODE_PRINTF("ROL\t");
3895 DECODE_PRINTF("ROR\t");
3898 DECODE_PRINTF("RCL\t");
3901 DECODE_PRINTF("RCR\t");
3904 DECODE_PRINTF("SHL\t");
3907 DECODE_PRINTF("SHR\t");
3910 DECODE_PRINTF("SAL\t");
3913 DECODE_PRINTF("SAR\t");
3918 /* know operation, decode the mod byte to find the addressing
3922 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3925 DECODE_PRINTF("DWORD PTR ");
3926 destoffset = decode_rmXX_address(mod, rl);
3927 DECODE_PRINTF(",CL\n");
3928 destval = fetch_data_long(destoffset);
3930 destval = (*opcD1_long_operation[rh]) (destval, amt);
3931 store_data_long(destoffset, destval);
3935 DECODE_PRINTF("WORD PTR ");
3936 destoffset = decode_rmXX_address(mod, rl);
3937 DECODE_PRINTF(",CL\n");
3938 destval = fetch_data_word(destoffset);
3940 destval = (*opcD1_word_operation[rh]) (destval, amt);
3941 store_data_word(destoffset, destval);
3943 } else { /* register to register */
3944 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3947 destreg = DECODE_RM_LONG_REGISTER(rl);
3948 DECODE_PRINTF(",CL\n");
3950 *destreg = (*opcD1_long_operation[rh]) (*destreg, amt);
3954 destreg = DECODE_RM_WORD_REGISTER(rl);
3955 DECODE_PRINTF(",CL\n");
3957 *destreg = (*opcD1_word_operation[rh]) (*destreg, amt);
3960 DECODE_CLEAR_SEGOVR();
3964 /****************************************************************************
3967 ****************************************************************************/
3968 void x86emuOp_aam(u8 X86EMU_UNUSED(op1))
3973 DECODE_PRINTF("AAM\n");
3974 a = fetch_byte_imm(); /* this is a stupid encoding. */
3976 DECODE_PRINTF("ERROR DECODING AAM\n");
3981 /* note the type change here --- returning AL and AH in AX. */
3982 M.x86.R_AX = aam_word(M.x86.R_AL);
3983 DECODE_CLEAR_SEGOVR();
3987 /****************************************************************************
3990 ****************************************************************************/
3991 void x86emuOp_aad(u8 X86EMU_UNUSED(op1))
3996 DECODE_PRINTF("AAD\n");
3997 a = fetch_byte_imm();
3999 M.x86.R_AX = aad_word(M.x86.R_AX);
4000 DECODE_CLEAR_SEGOVR();
4004 /* opcode 0xd6 ILLEGAL OPCODE */
4006 /****************************************************************************
4009 ****************************************************************************/
4010 void x86emuOp_xlat(u8 X86EMU_UNUSED(op1))
4015 DECODE_PRINTF("XLAT\n");
4017 addr = (u16)(M.x86.R_BX + (u8)M.x86.R_AL);
4018 M.x86.R_AL = fetch_data_byte(addr);
4019 DECODE_CLEAR_SEGOVR();
4023 /* instuctions D8 .. DF are in i87_ops.c */
4025 /****************************************************************************
4028 ****************************************************************************/
4029 void x86emuOp_loopne(u8 X86EMU_UNUSED(op1))
4034 DECODE_PRINTF("LOOPNE\t");
4035 ip = (s8) fetch_byte_imm();
4036 ip += (s16) M.x86.R_IP;
4037 DECODE_PRINTF2("%04x\n", ip);
4040 if (M.x86.R_CX != 0 && !ACCESS_FLAG(F_ZF)) /* CX != 0 and !ZF */
4042 DECODE_CLEAR_SEGOVR();
4046 /****************************************************************************
4049 ****************************************************************************/
4050 void x86emuOp_loope(u8 X86EMU_UNUSED(op1))
4055 DECODE_PRINTF("LOOPE\t");
4056 ip = (s8) fetch_byte_imm();
4057 ip += (s16) M.x86.R_IP;
4058 DECODE_PRINTF2("%04x\n", ip);
4061 if (M.x86.R_CX != 0 && ACCESS_FLAG(F_ZF)) /* CX != 0 and ZF */
4063 DECODE_CLEAR_SEGOVR();
4067 /****************************************************************************
4070 ****************************************************************************/
4071 void x86emuOp_loop(u8 X86EMU_UNUSED(op1))
4076 DECODE_PRINTF("LOOP\t");
4077 ip = (s8) fetch_byte_imm();
4078 ip += (s16) M.x86.R_IP;
4079 DECODE_PRINTF2("%04x\n", ip);
4082 if (M.x86.R_CX != 0)
4084 DECODE_CLEAR_SEGOVR();
4088 /****************************************************************************
4091 ****************************************************************************/
4092 void x86emuOp_jcxz(u8 X86EMU_UNUSED(op1))
4097 /* jump to byte offset if overflow flag is set */
4099 DECODE_PRINTF("JCXZ\t");
4100 offset = (s8)fetch_byte_imm();
4101 target = (u16)(M.x86.R_IP + offset);
4102 DECODE_PRINTF2("%x\n", target);
4104 if (M.x86.R_CX == 0)
4105 M.x86.R_IP = target;
4106 DECODE_CLEAR_SEGOVR();
4110 /****************************************************************************
4113 ****************************************************************************/
4114 void x86emuOp_in_byte_AL_IMM(u8 X86EMU_UNUSED(op1))
4119 DECODE_PRINTF("IN\t");
4120 port = (u8) fetch_byte_imm();
4121 DECODE_PRINTF2("%x,AL\n", port);
4123 M.x86.R_AL = (*sys_inb)(port);
4124 DECODE_CLEAR_SEGOVR();
4128 /****************************************************************************
4131 ****************************************************************************/
4132 void x86emuOp_in_word_AX_IMM(u8 X86EMU_UNUSED(op1))
4137 DECODE_PRINTF("IN\t");
4138 port = (u8) fetch_byte_imm();
4139 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4140 DECODE_PRINTF2("EAX,%x\n", port);
4142 DECODE_PRINTF2("AX,%x\n", port);
4145 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4146 M.x86.R_EAX = (*sys_inl)(port);
4148 M.x86.R_AX = (*sys_inw)(port);
4150 DECODE_CLEAR_SEGOVR();
4154 /****************************************************************************
4157 ****************************************************************************/
4158 void x86emuOp_out_byte_IMM_AL(u8 X86EMU_UNUSED(op1))
4163 DECODE_PRINTF("OUT\t");
4164 port = (u8) fetch_byte_imm();
4165 DECODE_PRINTF2("%x,AL\n", port);
4167 (*sys_outb)(port, M.x86.R_AL);
4168 DECODE_CLEAR_SEGOVR();
4172 /****************************************************************************
4175 ****************************************************************************/
4176 void x86emuOp_out_word_IMM_AX(u8 X86EMU_UNUSED(op1))
4181 DECODE_PRINTF("OUT\t");
4182 port = (u8) fetch_byte_imm();
4183 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4184 DECODE_PRINTF2("%x,EAX\n", port);
4186 DECODE_PRINTF2("%x,AX\n", port);
4189 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4190 (*sys_outl)(port, M.x86.R_EAX);
4192 (*sys_outw)(port, M.x86.R_AX);
4194 DECODE_CLEAR_SEGOVR();
4198 /****************************************************************************
4201 ****************************************************************************/
4202 void x86emuOp_call_near_IMM(u8 X86EMU_UNUSED(op1))
4207 DECODE_PRINTF("CALL\t");
4208 ip = (s16) fetch_word_imm();
4209 ip += (s16) M.x86.R_IP; /* CHECK SIGN */
4210 DECODE_PRINTF2("%04x\n", ip);
4211 CALL_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, ip, "");
4213 push_word(M.x86.R_IP);
4215 DECODE_CLEAR_SEGOVR();
4219 /****************************************************************************
4222 ****************************************************************************/
4223 void x86emuOp_jump_near_IMM(u8 X86EMU_UNUSED(op1))
4228 DECODE_PRINTF("JMP\t");
4229 ip = (s16)fetch_word_imm();
4230 ip += (s16)M.x86.R_IP;
4231 DECODE_PRINTF2("%04x\n", ip);
4233 M.x86.R_IP = (u16)ip;
4234 DECODE_CLEAR_SEGOVR();
4238 /****************************************************************************
4241 ****************************************************************************/
4242 void x86emuOp_jump_far_IMM(u8 X86EMU_UNUSED(op1))
4247 DECODE_PRINTF("JMP\tFAR ");
4248 ip = fetch_word_imm();
4249 cs = fetch_word_imm();
4250 DECODE_PRINTF2("%04x:", cs);
4251 DECODE_PRINTF2("%04x\n", ip);
4255 DECODE_CLEAR_SEGOVR();
4259 /****************************************************************************
4262 ****************************************************************************/
4263 void x86emuOp_jump_byte_IMM(u8 X86EMU_UNUSED(op1))
4269 DECODE_PRINTF("JMP\t");
4270 offset = (s8)fetch_byte_imm();
4271 target = (u16)(M.x86.R_IP + offset);
4272 DECODE_PRINTF2("%x\n", target);
4274 M.x86.R_IP = target;
4275 DECODE_CLEAR_SEGOVR();
4279 /****************************************************************************
4282 ****************************************************************************/
4283 void x86emuOp_in_byte_AL_DX(u8 X86EMU_UNUSED(op1))
4286 DECODE_PRINTF("IN\tAL,DX\n");
4288 M.x86.R_AL = (*sys_inb)(M.x86.R_DX);
4289 DECODE_CLEAR_SEGOVR();
4293 /****************************************************************************
4296 ****************************************************************************/
4297 void x86emuOp_in_word_AX_DX(u8 X86EMU_UNUSED(op1))
4300 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4301 DECODE_PRINTF("IN\tEAX,DX\n");
4303 DECODE_PRINTF("IN\tAX,DX\n");
4306 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4307 M.x86.R_EAX = (*sys_inl)(M.x86.R_DX);
4309 M.x86.R_AX = (*sys_inw)(M.x86.R_DX);
4311 DECODE_CLEAR_SEGOVR();
4315 /****************************************************************************
4318 ****************************************************************************/
4319 void x86emuOp_out_byte_DX_AL(u8 X86EMU_UNUSED(op1))
4322 DECODE_PRINTF("OUT\tDX,AL\n");
4324 (*sys_outb)(M.x86.R_DX, M.x86.R_AL);
4325 DECODE_CLEAR_SEGOVR();
4329 /****************************************************************************
4332 ****************************************************************************/
4333 void x86emuOp_out_word_DX_AX(u8 X86EMU_UNUSED(op1))
4336 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4337 DECODE_PRINTF("OUT\tDX,EAX\n");
4339 DECODE_PRINTF("OUT\tDX,AX\n");
4342 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4343 (*sys_outl)(M.x86.R_DX, M.x86.R_EAX);
4345 (*sys_outw)(M.x86.R_DX, M.x86.R_AX);
4347 DECODE_CLEAR_SEGOVR();
4351 /****************************************************************************
4354 ****************************************************************************/
4355 void x86emuOp_lock(u8 X86EMU_UNUSED(op1))
4358 DECODE_PRINTF("LOCK:\n");
4360 DECODE_CLEAR_SEGOVR();
4364 /*opcode 0xf1 ILLEGAL OPERATION */
4366 /****************************************************************************
4369 ****************************************************************************/
4370 void x86emuOp_repne(u8 X86EMU_UNUSED(op1))
4373 DECODE_PRINTF("REPNE\n");
4375 M.x86.mode |= SYSMODE_PREFIX_REPNE;
4376 DECODE_CLEAR_SEGOVR();
4380 /****************************************************************************
4383 ****************************************************************************/
4384 void x86emuOp_repe(u8 X86EMU_UNUSED(op1))
4387 DECODE_PRINTF("REPE\n");
4389 M.x86.mode |= SYSMODE_PREFIX_REPE;
4390 DECODE_CLEAR_SEGOVR();
4394 /****************************************************************************
4397 ****************************************************************************/
4398 void x86emuOp_halt(u8 X86EMU_UNUSED(op1))
4401 DECODE_PRINTF("HALT\n");
4404 DECODE_CLEAR_SEGOVR();
4408 /****************************************************************************
4411 ****************************************************************************/
4412 void x86emuOp_cmc(u8 X86EMU_UNUSED(op1))
4414 /* complement the carry flag. */
4416 DECODE_PRINTF("CMC\n");
4419 DECODE_CLEAR_SEGOVR();
4423 /****************************************************************************
4426 ****************************************************************************/
4427 void x86emuOp_opcF6_byte_RM(u8 X86EMU_UNUSED(op1))
4434 /* long, drawn out code follows. Double switch for a total
4437 FETCH_DECODE_MODRM(mod, rh, rl);
4438 DECODE_PRINTF(opF6_names[rh]);
4440 DECODE_PRINTF("BYTE PTR ");
4441 destoffset = decode_rmXX_address(mod, rl);
4442 destval = fetch_data_byte(destoffset);
4445 case 0: /* test byte imm */
4447 srcval = fetch_byte_imm();
4448 DECODE_PRINTF2("%02x\n", srcval);
4450 test_byte(destval, srcval);
4453 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4457 DECODE_PRINTF("\n");
4459 destval = not_byte(destval);
4460 store_data_byte(destoffset, destval);
4463 DECODE_PRINTF("\n");
4465 destval = neg_byte(destval);
4466 store_data_byte(destoffset, destval);
4469 DECODE_PRINTF("\n");
4474 DECODE_PRINTF("\n");
4479 DECODE_PRINTF("\n");
4484 DECODE_PRINTF("\n");
4489 } else { /* mod=11 */
4490 destreg = DECODE_RM_BYTE_REGISTER(rl);
4492 case 0: /* test byte imm */
4494 srcval = fetch_byte_imm();
4495 DECODE_PRINTF2("%02x\n", srcval);
4497 test_byte(*destreg, srcval);
4500 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4504 DECODE_PRINTF("\n");
4506 *destreg = not_byte(*destreg);
4509 DECODE_PRINTF("\n");
4511 *destreg = neg_byte(*destreg);
4514 DECODE_PRINTF("\n");
4516 mul_byte(*destreg); /*!!! */
4519 DECODE_PRINTF("\n");
4521 imul_byte(*destreg);
4524 DECODE_PRINTF("\n");
4529 DECODE_PRINTF("\n");
4531 idiv_byte(*destreg);
4535 DECODE_CLEAR_SEGOVR();
4539 /****************************************************************************
4542 ****************************************************************************/
4543 void x86emuOp_opcF7_word_RM(u8 X86EMU_UNUSED(op1))
4549 FETCH_DECODE_MODRM(mod, rh, rl);
4550 DECODE_PRINTF(opF6_names[rh]);
4553 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4554 u32 destval, srcval;
4556 DECODE_PRINTF("DWORD PTR ");
4557 destoffset = decode_rmXX_address(mod, rl);
4558 destval = fetch_data_long(destoffset);
4563 srcval = fetch_long_imm();
4564 DECODE_PRINTF2("%x\n", srcval);
4566 test_long(destval, srcval);
4569 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F7\n");
4573 DECODE_PRINTF("\n");
4575 destval = not_long(destval);
4576 store_data_long(destoffset, destval);
4579 DECODE_PRINTF("\n");
4581 destval = neg_long(destval);
4582 store_data_long(destoffset, destval);
4585 DECODE_PRINTF("\n");
4590 DECODE_PRINTF("\n");
4595 DECODE_PRINTF("\n");
4600 DECODE_PRINTF("\n");
4606 u16 destval, srcval;
4608 DECODE_PRINTF("WORD PTR ");
4609 destoffset = decode_rmXX_address(mod, rl);
4610 destval = fetch_data_word(destoffset);
4613 case 0: /* test word imm */
4615 srcval = fetch_word_imm();
4616 DECODE_PRINTF2("%x\n", srcval);
4618 test_word(destval, srcval);
4621 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F7\n");
4625 DECODE_PRINTF("\n");
4627 destval = not_word(destval);
4628 store_data_word(destoffset, destval);
4631 DECODE_PRINTF("\n");
4633 destval = neg_word(destval);
4634 store_data_word(destoffset, destval);
4637 DECODE_PRINTF("\n");
4642 DECODE_PRINTF("\n");
4647 DECODE_PRINTF("\n");
4652 DECODE_PRINTF("\n");
4659 } else { /* mod=11 */
4661 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4665 destreg = DECODE_RM_LONG_REGISTER(rl);
4668 case 0: /* test word imm */
4670 srcval = fetch_long_imm();
4671 DECODE_PRINTF2("%x\n", srcval);
4673 test_long(*destreg, srcval);
4676 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4680 DECODE_PRINTF("\n");
4682 *destreg = not_long(*destreg);
4685 DECODE_PRINTF("\n");
4687 *destreg = neg_long(*destreg);
4690 DECODE_PRINTF("\n");
4692 mul_long(*destreg); /*!!! */
4695 DECODE_PRINTF("\n");
4697 imul_long(*destreg);
4700 DECODE_PRINTF("\n");
4705 DECODE_PRINTF("\n");
4707 idiv_long(*destreg);
4714 destreg = DECODE_RM_WORD_REGISTER(rl);
4717 case 0: /* test word imm */
4719 srcval = fetch_word_imm();
4720 DECODE_PRINTF2("%x\n", srcval);
4722 test_word(*destreg, srcval);
4725 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4729 DECODE_PRINTF("\n");
4731 *destreg = not_word(*destreg);
4734 DECODE_PRINTF("\n");
4736 *destreg = neg_word(*destreg);
4739 DECODE_PRINTF("\n");
4741 mul_word(*destreg); /*!!! */
4744 DECODE_PRINTF("\n");
4746 imul_word(*destreg);
4749 DECODE_PRINTF("\n");
4754 DECODE_PRINTF("\n");
4756 idiv_word(*destreg);
4761 DECODE_CLEAR_SEGOVR();
4765 /****************************************************************************
4768 ****************************************************************************/
4769 void x86emuOp_clc(u8 X86EMU_UNUSED(op1))
4771 /* clear the carry flag. */
4773 DECODE_PRINTF("CLC\n");
4776 DECODE_CLEAR_SEGOVR();
4780 /****************************************************************************
4783 ****************************************************************************/
4784 void x86emuOp_stc(u8 X86EMU_UNUSED(op1))
4786 /* set the carry flag. */
4788 DECODE_PRINTF("STC\n");
4791 DECODE_CLEAR_SEGOVR();
4795 /****************************************************************************
4798 ****************************************************************************/
4799 void x86emuOp_cli(u8 X86EMU_UNUSED(op1))
4801 /* clear interrupts. */
4803 DECODE_PRINTF("CLI\n");
4806 DECODE_CLEAR_SEGOVR();
4810 /****************************************************************************
4813 ****************************************************************************/
4814 void x86emuOp_sti(u8 X86EMU_UNUSED(op1))
4816 /* enable interrupts. */
4818 DECODE_PRINTF("STI\n");
4821 DECODE_CLEAR_SEGOVR();
4825 /****************************************************************************
4828 ****************************************************************************/
4829 void x86emuOp_cld(u8 X86EMU_UNUSED(op1))
4831 /* clear interrupts. */
4833 DECODE_PRINTF("CLD\n");
4836 DECODE_CLEAR_SEGOVR();
4840 /****************************************************************************
4843 ****************************************************************************/
4844 void x86emuOp_std(u8 X86EMU_UNUSED(op1))
4846 /* clear interrupts. */
4848 DECODE_PRINTF("STD\n");
4851 DECODE_CLEAR_SEGOVR();
4855 /****************************************************************************
4858 ****************************************************************************/
4859 void x86emuOp_opcFE_byte_RM(u8 X86EMU_UNUSED(op1))
4866 /* Yet another special case instruction. */
4868 FETCH_DECODE_MODRM(mod, rh, rl);
4870 if (DEBUG_DECODE()) {
4871 /* XXX DECODE_PRINTF may be changed to something more
4872 general, so that it is important to leave the strings
4873 in the same format, even though the result is that the
4874 above test is done twice. */
4878 DECODE_PRINTF("INC\t");
4881 DECODE_PRINTF("DEC\t");
4889 DECODE_PRINTF2("ILLEGAL OP MAJOR OP 0xFE MINOR OP %x \n", mod);
4896 DECODE_PRINTF("BYTE PTR ");
4897 destoffset = decode_rmXX_address(mod, rl);
4898 DECODE_PRINTF("\n");
4899 destval = fetch_data_byte(destoffset);
4902 destval = inc_byte(destval);
4904 destval = dec_byte(destval);
4905 store_data_byte(destoffset, destval);
4907 destreg = DECODE_RM_BYTE_REGISTER(rl);
4908 DECODE_PRINTF("\n");
4911 *destreg = inc_byte(*destreg);
4913 *destreg = dec_byte(*destreg);
4915 DECODE_CLEAR_SEGOVR();
4919 /****************************************************************************
4922 ****************************************************************************/
4923 void x86emuOp_opcFF_word_RM(u8 X86EMU_UNUSED(op1))
4926 uint destoffset = 0;
4928 u16 destval,destval2;
4930 /* Yet another special case instruction. */
4932 FETCH_DECODE_MODRM(mod, rh, rl);
4934 if (DEBUG_DECODE()) {
4935 /* XXX DECODE_PRINTF may be changed to something more
4936 general, so that it is important to leave the strings
4937 in the same format, even though the result is that the
4938 above test is done twice. */
4942 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4943 DECODE_PRINTF("INC\tDWORD PTR ");
4945 DECODE_PRINTF("INC\tWORD PTR ");
4949 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4950 DECODE_PRINTF("DEC\tDWORD PTR ");
4952 DECODE_PRINTF("DEC\tWORD PTR ");
4956 DECODE_PRINTF("CALL\t ");
4959 DECODE_PRINTF("CALL\tFAR ");
4962 DECODE_PRINTF("JMP\t");
4965 DECODE_PRINTF("JMP\tFAR ");
4968 DECODE_PRINTF("PUSH\t");
4971 DECODE_PRINTF("ILLEGAL DECODING OF OPCODE FF\t");
4978 destoffset = decode_rmXX_address(mod, rl);
4979 DECODE_PRINTF("\n");
4981 case 0: /* inc word ptr ... */
4982 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4985 destval = fetch_data_long(destoffset);
4987 destval = inc_long(destval);
4988 store_data_long(destoffset, destval);
4992 destval = fetch_data_word(destoffset);
4994 destval = inc_word(destval);
4995 store_data_word(destoffset, destval);
4998 case 1: /* dec word ptr ... */
4999 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5002 destval = fetch_data_long(destoffset);
5004 destval = dec_long(destval);
5005 store_data_long(destoffset, destval);
5009 destval = fetch_data_word(destoffset);
5011 destval = dec_word(destval);
5012 store_data_word(destoffset, destval);
5015 case 2: /* call word ptr ... */
5016 destval = fetch_data_word(destoffset);
5018 push_word(M.x86.R_IP);
5019 M.x86.R_IP = destval;
5021 case 3: /* call far ptr ... */
5022 destval = fetch_data_word(destoffset);
5023 destval2 = fetch_data_word(destoffset + 2);
5025 push_word(M.x86.R_CS);
5026 M.x86.R_CS = destval2;
5027 push_word(M.x86.R_IP);
5028 M.x86.R_IP = destval;
5030 case 4: /* jmp word ptr ... */
5031 destval = fetch_data_word(destoffset);
5033 M.x86.R_IP = destval;
5035 case 5: /* jmp far ptr ... */
5036 destval = fetch_data_word(destoffset);
5037 destval2 = fetch_data_word(destoffset + 2);
5039 M.x86.R_IP = destval;
5040 M.x86.R_CS = destval2;
5042 case 6: /* push word ptr ... */
5043 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5046 destval = fetch_data_long(destoffset);
5052 destval = fetch_data_word(destoffset);
5061 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5064 destreg = DECODE_RM_LONG_REGISTER(rl);
5065 DECODE_PRINTF("\n");
5067 *destreg = inc_long(*destreg);
5071 destreg = DECODE_RM_WORD_REGISTER(rl);
5072 DECODE_PRINTF("\n");
5074 *destreg = inc_word(*destreg);
5078 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5081 destreg = DECODE_RM_LONG_REGISTER(rl);
5082 DECODE_PRINTF("\n");
5084 *destreg = dec_long(*destreg);
5088 destreg = DECODE_RM_WORD_REGISTER(rl);
5089 DECODE_PRINTF("\n");
5091 *destreg = dec_word(*destreg);
5094 case 2: /* call word ptr ... */
5095 destreg = DECODE_RM_WORD_REGISTER(rl);
5096 DECODE_PRINTF("\n");
5098 push_word(M.x86.R_IP);
5099 M.x86.R_IP = *destreg;
5101 case 3: /* jmp far ptr ... */
5102 DECODE_PRINTF("OPERATION UNDEFINED 0XFF \n");
5107 case 4: /* jmp ... */
5108 destreg = DECODE_RM_WORD_REGISTER(rl);
5109 DECODE_PRINTF("\n");
5111 M.x86.R_IP = (u16) (*destreg);
5113 case 5: /* jmp far ptr ... */
5114 DECODE_PRINTF("OPERATION UNDEFINED 0XFF \n");
5119 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5122 destreg = DECODE_RM_LONG_REGISTER(rl);
5123 DECODE_PRINTF("\n");
5125 push_long(*destreg);
5129 destreg = DECODE_RM_WORD_REGISTER(rl);
5130 DECODE_PRINTF("\n");
5132 push_word(*destreg);
5137 DECODE_CLEAR_SEGOVR();
5141 /***************************************************************************
5142 * Single byte operation code table:
5143 **************************************************************************/
5144 void (*x86emu_optab[256])(u8) =
5146 /* 0x00 */ x86emuOp_genop_byte_RM_R,
5147 /* 0x01 */ x86emuOp_genop_word_RM_R,
5148 /* 0x02 */ x86emuOp_genop_byte_R_RM,
5149 /* 0x03 */ x86emuOp_genop_word_R_RM,
5150 /* 0x04 */ x86emuOp_genop_byte_AL_IMM,
5151 /* 0x05 */ x86emuOp_genop_word_AX_IMM,
5152 /* 0x06 */ x86emuOp_push_ES,
5153 /* 0x07 */ x86emuOp_pop_ES,
5155 /* 0x08 */ x86emuOp_genop_byte_RM_R,
5156 /* 0x09 */ x86emuOp_genop_word_RM_R,
5157 /* 0x0a */ x86emuOp_genop_byte_R_RM,
5158 /* 0x0b */ x86emuOp_genop_word_R_RM,
5159 /* 0x0c */ x86emuOp_genop_byte_AL_IMM,
5160 /* 0x0d */ x86emuOp_genop_word_AX_IMM,
5161 /* 0x0e */ x86emuOp_push_CS,
5162 /* 0x0f */ x86emuOp_two_byte,
5164 /* 0x10 */ x86emuOp_genop_byte_RM_R,
5165 /* 0x11 */ x86emuOp_genop_word_RM_R,
5166 /* 0x12 */ x86emuOp_genop_byte_R_RM,
5167 /* 0x13 */ x86emuOp_genop_word_R_RM,
5168 /* 0x14 */ x86emuOp_genop_byte_AL_IMM,
5169 /* 0x15 */ x86emuOp_genop_word_AX_IMM,
5170 /* 0x16 */ x86emuOp_push_SS,
5171 /* 0x17 */ x86emuOp_pop_SS,
5173 /* 0x18 */ x86emuOp_genop_byte_RM_R,
5174 /* 0x19 */ x86emuOp_genop_word_RM_R,
5175 /* 0x1a */ x86emuOp_genop_byte_R_RM,
5176 /* 0x1b */ x86emuOp_genop_word_R_RM,
5177 /* 0x1c */ x86emuOp_genop_byte_AL_IMM,
5178 /* 0x1d */ x86emuOp_genop_word_AX_IMM,
5179 /* 0x1e */ x86emuOp_push_DS,
5180 /* 0x1f */ x86emuOp_pop_DS,
5182 /* 0x20 */ x86emuOp_genop_byte_RM_R,
5183 /* 0x21 */ x86emuOp_genop_word_RM_R,
5184 /* 0x22 */ x86emuOp_genop_byte_R_RM,
5185 /* 0x23 */ x86emuOp_genop_word_R_RM,
5186 /* 0x24 */ x86emuOp_genop_byte_AL_IMM,
5187 /* 0x25 */ x86emuOp_genop_word_AX_IMM,
5188 /* 0x26 */ x86emuOp_segovr_ES,
5189 /* 0x27 */ x86emuOp_daa,
5191 /* 0x28 */ x86emuOp_genop_byte_RM_R,
5192 /* 0x29 */ x86emuOp_genop_word_RM_R,
5193 /* 0x2a */ x86emuOp_genop_byte_R_RM,
5194 /* 0x2b */ x86emuOp_genop_word_R_RM,
5195 /* 0x2c */ x86emuOp_genop_byte_AL_IMM,
5196 /* 0x2d */ x86emuOp_genop_word_AX_IMM,
5197 /* 0x2e */ x86emuOp_segovr_CS,
5198 /* 0x2f */ x86emuOp_das,
5200 /* 0x30 */ x86emuOp_genop_byte_RM_R,
5201 /* 0x31 */ x86emuOp_genop_word_RM_R,
5202 /* 0x32 */ x86emuOp_genop_byte_R_RM,
5203 /* 0x33 */ x86emuOp_genop_word_R_RM,
5204 /* 0x34 */ x86emuOp_genop_byte_AL_IMM,
5205 /* 0x35 */ x86emuOp_genop_word_AX_IMM,
5206 /* 0x36 */ x86emuOp_segovr_SS,
5207 /* 0x37 */ x86emuOp_aaa,
5209 /* 0x38 */ x86emuOp_genop_byte_RM_R,
5210 /* 0x39 */ x86emuOp_genop_word_RM_R,
5211 /* 0x3a */ x86emuOp_genop_byte_R_RM,
5212 /* 0x3b */ x86emuOp_genop_word_R_RM,
5213 /* 0x3c */ x86emuOp_genop_byte_AL_IMM,
5214 /* 0x3d */ x86emuOp_genop_word_AX_IMM,
5215 /* 0x3e */ x86emuOp_segovr_DS,
5216 /* 0x3f */ x86emuOp_aas,
5218 /* 0x40 */ x86emuOp_inc_register,
5219 /* 0x41 */ x86emuOp_inc_register,
5220 /* 0x42 */ x86emuOp_inc_register,
5221 /* 0x43 */ x86emuOp_inc_register,
5222 /* 0x44 */ x86emuOp_inc_register,
5223 /* 0x45 */ x86emuOp_inc_register,
5224 /* 0x46 */ x86emuOp_inc_register,
5225 /* 0x47 */ x86emuOp_inc_register,
5227 /* 0x48 */ x86emuOp_dec_register,
5228 /* 0x49 */ x86emuOp_dec_register,
5229 /* 0x4a */ x86emuOp_dec_register,
5230 /* 0x4b */ x86emuOp_dec_register,
5231 /* 0x4c */ x86emuOp_dec_register,
5232 /* 0x4d */ x86emuOp_dec_register,
5233 /* 0x4e */ x86emuOp_dec_register,
5234 /* 0x4f */ x86emuOp_dec_register,
5236 /* 0x50 */ x86emuOp_push_register,
5237 /* 0x51 */ x86emuOp_push_register,
5238 /* 0x52 */ x86emuOp_push_register,
5239 /* 0x53 */ x86emuOp_push_register,
5240 /* 0x54 */ x86emuOp_push_register,
5241 /* 0x55 */ x86emuOp_push_register,
5242 /* 0x56 */ x86emuOp_push_register,
5243 /* 0x57 */ x86emuOp_push_register,
5245 /* 0x58 */ x86emuOp_pop_register,
5246 /* 0x59 */ x86emuOp_pop_register,
5247 /* 0x5a */ x86emuOp_pop_register,
5248 /* 0x5b */ x86emuOp_pop_register,
5249 /* 0x5c */ x86emuOp_pop_register,
5250 /* 0x5d */ x86emuOp_pop_register,
5251 /* 0x5e */ x86emuOp_pop_register,
5252 /* 0x5f */ x86emuOp_pop_register,
5254 /* 0x60 */ x86emuOp_push_all,
5255 /* 0x61 */ x86emuOp_pop_all,
5256 /* 0x62 */ x86emuOp_illegal_op, /* bound */
5257 /* 0x63 */ x86emuOp_illegal_op, /* arpl */
5258 /* 0x64 */ x86emuOp_segovr_FS,
5259 /* 0x65 */ x86emuOp_segovr_GS,
5260 /* 0x66 */ x86emuOp_prefix_data,
5261 /* 0x67 */ x86emuOp_prefix_addr,
5263 /* 0x68 */ x86emuOp_push_word_IMM,
5264 /* 0x69 */ x86emuOp_imul_word_IMM,
5265 /* 0x6a */ x86emuOp_push_byte_IMM,
5266 /* 0x6b */ x86emuOp_imul_byte_IMM,
5267 /* 0x6c */ x86emuOp_ins_byte,
5268 /* 0x6d */ x86emuOp_ins_word,
5269 /* 0x6e */ x86emuOp_outs_byte,
5270 /* 0x6f */ x86emuOp_outs_word,
5272 /* 0x70 */ x86emuOp_jump_near_cond,
5273 /* 0x71 */ x86emuOp_jump_near_cond,
5274 /* 0x72 */ x86emuOp_jump_near_cond,
5275 /* 0x73 */ x86emuOp_jump_near_cond,
5276 /* 0x74 */ x86emuOp_jump_near_cond,
5277 /* 0x75 */ x86emuOp_jump_near_cond,
5278 /* 0x76 */ x86emuOp_jump_near_cond,
5279 /* 0x77 */ x86emuOp_jump_near_cond,
5281 /* 0x78 */ x86emuOp_jump_near_cond,
5282 /* 0x79 */ x86emuOp_jump_near_cond,
5283 /* 0x7a */ x86emuOp_jump_near_cond,
5284 /* 0x7b */ x86emuOp_jump_near_cond,
5285 /* 0x7c */ x86emuOp_jump_near_cond,
5286 /* 0x7d */ x86emuOp_jump_near_cond,
5287 /* 0x7e */ x86emuOp_jump_near_cond,
5288 /* 0x7f */ x86emuOp_jump_near_cond,
5290 /* 0x80 */ x86emuOp_opc80_byte_RM_IMM,
5291 /* 0x81 */ x86emuOp_opc81_word_RM_IMM,
5292 /* 0x82 */ x86emuOp_opc82_byte_RM_IMM,
5293 /* 0x83 */ x86emuOp_opc83_word_RM_IMM,
5294 /* 0x84 */ x86emuOp_test_byte_RM_R,
5295 /* 0x85 */ x86emuOp_test_word_RM_R,
5296 /* 0x86 */ x86emuOp_xchg_byte_RM_R,
5297 /* 0x87 */ x86emuOp_xchg_word_RM_R,
5299 /* 0x88 */ x86emuOp_mov_byte_RM_R,
5300 /* 0x89 */ x86emuOp_mov_word_RM_R,
5301 /* 0x8a */ x86emuOp_mov_byte_R_RM,
5302 /* 0x8b */ x86emuOp_mov_word_R_RM,
5303 /* 0x8c */ x86emuOp_mov_word_RM_SR,
5304 /* 0x8d */ x86emuOp_lea_word_R_M,
5305 /* 0x8e */ x86emuOp_mov_word_SR_RM,
5306 /* 0x8f */ x86emuOp_pop_RM,
5308 /* 0x90 */ x86emuOp_nop,
5309 /* 0x91 */ x86emuOp_xchg_word_AX_register,
5310 /* 0x92 */ x86emuOp_xchg_word_AX_register,
5311 /* 0x93 */ x86emuOp_xchg_word_AX_register,
5312 /* 0x94 */ x86emuOp_xchg_word_AX_register,
5313 /* 0x95 */ x86emuOp_xchg_word_AX_register,
5314 /* 0x96 */ x86emuOp_xchg_word_AX_register,
5315 /* 0x97 */ x86emuOp_xchg_word_AX_register,
5317 /* 0x98 */ x86emuOp_cbw,
5318 /* 0x99 */ x86emuOp_cwd,
5319 /* 0x9a */ x86emuOp_call_far_IMM,
5320 /* 0x9b */ x86emuOp_wait,
5321 /* 0x9c */ x86emuOp_pushf_word,
5322 /* 0x9d */ x86emuOp_popf_word,
5323 /* 0x9e */ x86emuOp_sahf,
5324 /* 0x9f */ x86emuOp_lahf,
5326 /* 0xa0 */ x86emuOp_mov_AL_M_IMM,
5327 /* 0xa1 */ x86emuOp_mov_AX_M_IMM,
5328 /* 0xa2 */ x86emuOp_mov_M_AL_IMM,
5329 /* 0xa3 */ x86emuOp_mov_M_AX_IMM,
5330 /* 0xa4 */ x86emuOp_movs_byte,
5331 /* 0xa5 */ x86emuOp_movs_word,
5332 /* 0xa6 */ x86emuOp_cmps_byte,
5333 /* 0xa7 */ x86emuOp_cmps_word,
5334 /* 0xa8 */ x86emuOp_test_AL_IMM,
5335 /* 0xa9 */ x86emuOp_test_AX_IMM,
5336 /* 0xaa */ x86emuOp_stos_byte,
5337 /* 0xab */ x86emuOp_stos_word,
5338 /* 0xac */ x86emuOp_lods_byte,
5339 /* 0xad */ x86emuOp_lods_word,
5340 /* 0xac */ x86emuOp_scas_byte,
5341 /* 0xad */ x86emuOp_scas_word,
5343 /* 0xb0 */ x86emuOp_mov_byte_register_IMM,
5344 /* 0xb1 */ x86emuOp_mov_byte_register_IMM,
5345 /* 0xb2 */ x86emuOp_mov_byte_register_IMM,
5346 /* 0xb3 */ x86emuOp_mov_byte_register_IMM,
5347 /* 0xb4 */ x86emuOp_mov_byte_register_IMM,
5348 /* 0xb5 */ x86emuOp_mov_byte_register_IMM,
5349 /* 0xb6 */ x86emuOp_mov_byte_register_IMM,
5350 /* 0xb7 */ x86emuOp_mov_byte_register_IMM,
5352 /* 0xb8 */ x86emuOp_mov_word_register_IMM,
5353 /* 0xb9 */ x86emuOp_mov_word_register_IMM,
5354 /* 0xba */ x86emuOp_mov_word_register_IMM,
5355 /* 0xbb */ x86emuOp_mov_word_register_IMM,
5356 /* 0xbc */ x86emuOp_mov_word_register_IMM,
5357 /* 0xbd */ x86emuOp_mov_word_register_IMM,
5358 /* 0xbe */ x86emuOp_mov_word_register_IMM,
5359 /* 0xbf */ x86emuOp_mov_word_register_IMM,
5361 /* 0xc0 */ x86emuOp_opcC0_byte_RM_MEM,
5362 /* 0xc1 */ x86emuOp_opcC1_word_RM_MEM,
5363 /* 0xc2 */ x86emuOp_ret_near_IMM,
5364 /* 0xc3 */ x86emuOp_ret_near,
5365 /* 0xc4 */ x86emuOp_les_R_IMM,
5366 /* 0xc5 */ x86emuOp_lds_R_IMM,
5367 /* 0xc6 */ x86emuOp_mov_byte_RM_IMM,
5368 /* 0xc7 */ x86emuOp_mov_word_RM_IMM,
5369 /* 0xc8 */ x86emuOp_enter,
5370 /* 0xc9 */ x86emuOp_leave,
5371 /* 0xca */ x86emuOp_ret_far_IMM,
5372 /* 0xcb */ x86emuOp_ret_far,
5373 /* 0xcc */ x86emuOp_int3,
5374 /* 0xcd */ x86emuOp_int_IMM,
5375 /* 0xce */ x86emuOp_into,
5376 /* 0xcf */ x86emuOp_iret,
5378 /* 0xd0 */ x86emuOp_opcD0_byte_RM_1,
5379 /* 0xd1 */ x86emuOp_opcD1_word_RM_1,
5380 /* 0xd2 */ x86emuOp_opcD2_byte_RM_CL,
5381 /* 0xd3 */ x86emuOp_opcD3_word_RM_CL,
5382 /* 0xd4 */ x86emuOp_aam,
5383 /* 0xd5 */ x86emuOp_aad,
5384 /* 0xd6 */ x86emuOp_illegal_op, /* Undocumented SETALC instruction */
5385 /* 0xd7 */ x86emuOp_xlat,
5386 /* 0xd8 */ NULL, /*x86emuOp_esc_coprocess_d8,*/
5387 /* 0xd9 */ NULL, /*x86emuOp_esc_coprocess_d9,*/
5388 /* 0xda */ NULL, /*x86emuOp_esc_coprocess_da,*/
5389 /* 0xdb */ NULL, /*x86emuOp_esc_coprocess_db,*/
5390 /* 0xdc */ NULL, /*x86emuOp_esc_coprocess_dc,*/
5391 /* 0xdd */ NULL, /*x86emuOp_esc_coprocess_dd,*/
5392 /* 0xde */ NULL, /*x86emuOp_esc_coprocess_de,*/
5393 /* 0xdf */ NULL, /*x86emuOp_esc_coprocess_df,*/
5395 /* 0xe0 */ x86emuOp_loopne,
5396 /* 0xe1 */ x86emuOp_loope,
5397 /* 0xe2 */ x86emuOp_loop,
5398 /* 0xe3 */ x86emuOp_jcxz,
5399 /* 0xe4 */ x86emuOp_in_byte_AL_IMM,
5400 /* 0xe5 */ x86emuOp_in_word_AX_IMM,
5401 /* 0xe6 */ x86emuOp_out_byte_IMM_AL,
5402 /* 0xe7 */ x86emuOp_out_word_IMM_AX,
5404 /* 0xe8 */ x86emuOp_call_near_IMM,
5405 /* 0xe9 */ x86emuOp_jump_near_IMM,
5406 /* 0xea */ x86emuOp_jump_far_IMM,
5407 /* 0xeb */ x86emuOp_jump_byte_IMM,
5408 /* 0xec */ x86emuOp_in_byte_AL_DX,
5409 /* 0xed */ x86emuOp_in_word_AX_DX,
5410 /* 0xee */ x86emuOp_out_byte_DX_AL,
5411 /* 0xef */ x86emuOp_out_word_DX_AX,
5413 /* 0xf0 */ x86emuOp_lock,
5414 /* 0xf1 */ x86emuOp_illegal_op,
5415 /* 0xf2 */ x86emuOp_repne,
5416 /* 0xf3 */ x86emuOp_repe,
5417 /* 0xf4 */ x86emuOp_halt,
5418 /* 0xf5 */ x86emuOp_cmc,
5419 /* 0xf6 */ x86emuOp_opcF6_byte_RM,
5420 /* 0xf7 */ x86emuOp_opcF7_word_RM,
5422 /* 0xf8 */ x86emuOp_clc,
5423 /* 0xf9 */ x86emuOp_stc,
5424 /* 0xfa */ x86emuOp_cli,
5425 /* 0xfb */ x86emuOp_sti,
5426 /* 0xfc */ x86emuOp_cld,
5427 /* 0xfd */ x86emuOp_std,
5428 /* 0xfe */ x86emuOp_opcFE_byte_RM,
5429 /* 0xff */ x86emuOp_opcFF_word_RM,