1 /****************************************************************************
2 * Realmode X86 Emulator Library
4 * Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved.
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 * Jason ported this file to u-boot. place all the function pointer in
74 * the got2 sector. Removed some opcode.
76 ****************************************************************************/
78 #include "x86emu/x86emui.h"
79 /*----------------------------- Implementation ----------------------------*/
81 /* constant arrays to do several instructions in just one function */
84 static char *x86emu_GenOpName[8] = {
85 "ADD", "OR", "ADC", "SBB", "AND", "SUB", "XOR", "CMP"};
88 /* used by several opcodes */
89 static u8 (*genop_byte_operation[])(u8 d, u8 s) __attribute__ ((section(".got2"))) =
101 static u16 (*genop_word_operation[])(u16 d, u16 s) __attribute__ ((section(".got2"))) =
113 static u32 (*genop_long_operation[])(u32 d, u32 s) __attribute__ ((section(".got2"))) =
125 /* used by opcodes 80, c0, d0, and d2. */
126 static u8(*opcD0_byte_operation[])(u8 d, u8 s) __attribute__ ((section(".got2"))) =
134 shl_byte, /* sal_byte === shl_byte by definition */
138 /* used by opcodes c1, d1, and d3. */
139 static u16(*opcD1_word_operation[])(u16 s, u8 d) __attribute__ ((section(".got2"))) =
147 shl_word, /* sal_byte === shl_byte by definition */
151 /* used by opcodes c1, d1, and d3. */
152 static u32 (*opcD1_long_operation[])(u32 s, u8 d) __attribute__ ((section(".got2"))) =
160 shl_long, /* sal_byte === shl_byte by definition */
166 static char *opF6_names[8] =
167 { "TEST\t", "", "NOT\t", "NEG\t", "MUL\t", "IMUL\t", "DIV\t", "IDIV\t" };
171 /****************************************************************************
173 op1 - Instruction op code
176 Handles illegal opcodes.
177 ****************************************************************************/
178 void x86emuOp_illegal_op(
182 if (M.x86.R_SP != 0) {
183 DECODE_PRINTF("ILLEGAL X86 OPCODE\n");
185 DB( printk("%04x:%04x: %02X ILLEGAL X86 OPCODE!\n",
186 M.x86.R_CS, M.x86.R_IP-1,op1));
190 /* If we get here, it means the stack pointer is back to zero
191 * so we are just returning from an emulator service call
192 * so therte is no need to display an error message. We trap
193 * the emulator with an 0xF1 opcode to finish the service
201 /****************************************************************************
203 Handles opcodes 0x00, 0x08, 0x10, 0x18, 0x20, 0x28, 0x30, 0x38
204 ****************************************************************************/
205 void x86emuOp_genop_byte_RM_R(u8 op1)
209 u8 *destreg, *srcreg;
212 op1 = (op1 >> 3) & 0x7;
215 DECODE_PRINTF(x86emu_GenOpName[op1]);
217 FETCH_DECODE_MODRM(mod, rh, rl);
219 { destoffset = decode_rmXX_address(mod,rl);
221 destval = fetch_data_byte(destoffset);
222 srcreg = DECODE_RM_BYTE_REGISTER(rh);
225 destval = genop_byte_operation[op1](destval, *srcreg);
226 store_data_byte(destoffset, destval);
229 { /* register to register */
230 destreg = DECODE_RM_BYTE_REGISTER(rl);
232 srcreg = DECODE_RM_BYTE_REGISTER(rh);
235 *destreg = genop_byte_operation[op1](*destreg, *srcreg);
237 DECODE_CLEAR_SEGOVR();
241 /****************************************************************************
243 Handles opcodes 0x01, 0x09, 0x11, 0x19, 0x21, 0x29, 0x31, 0x39
244 ****************************************************************************/
245 void x86emuOp_genop_word_RM_R(u8 op1)
250 op1 = (op1 >> 3) & 0x7;
253 DECODE_PRINTF(x86emu_GenOpName[op1]);
255 FETCH_DECODE_MODRM(mod, rh, rl);
258 destoffset = decode_rmXX_address(mod,rl);
259 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
264 destval = fetch_data_long(destoffset);
265 srcreg = DECODE_RM_LONG_REGISTER(rh);
268 destval = genop_long_operation[op1](destval, *srcreg);
269 store_data_long(destoffset, destval);
275 destval = fetch_data_word(destoffset);
276 srcreg = DECODE_RM_WORD_REGISTER(rh);
279 destval = genop_word_operation[op1](destval, *srcreg);
280 store_data_word(destoffset, destval);
282 } else { /* register to register */
283 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
284 u32 *destreg,*srcreg;
286 destreg = DECODE_RM_LONG_REGISTER(rl);
288 srcreg = DECODE_RM_LONG_REGISTER(rh);
291 *destreg = genop_long_operation[op1](*destreg, *srcreg);
293 u16 *destreg,*srcreg;
295 destreg = DECODE_RM_WORD_REGISTER(rl);
297 srcreg = DECODE_RM_WORD_REGISTER(rh);
300 *destreg = genop_word_operation[op1](*destreg, *srcreg);
303 DECODE_CLEAR_SEGOVR();
307 /****************************************************************************
309 Handles opcodes 0x02, 0x0a, 0x12, 0x1a, 0x22, 0x2a, 0x32, 0x3a
310 ****************************************************************************/
311 void x86emuOp_genop_byte_R_RM(u8 op1)
314 u8 *destreg, *srcreg;
318 op1 = (op1 >> 3) & 0x7;
321 DECODE_PRINTF(x86emu_GenOpName[op1]);
323 FETCH_DECODE_MODRM(mod, rh, rl);
325 destreg = DECODE_RM_BYTE_REGISTER(rh);
327 srcoffset = decode_rmXX_address(mod,rl);
328 srcval = fetch_data_byte(srcoffset);
329 } else { /* register to register */
330 destreg = DECODE_RM_BYTE_REGISTER(rh);
332 srcreg = DECODE_RM_BYTE_REGISTER(rl);
337 *destreg = genop_byte_operation[op1](*destreg, srcval);
339 DECODE_CLEAR_SEGOVR();
343 /****************************************************************************
345 Handles opcodes 0x03, 0x0b, 0x13, 0x1b, 0x23, 0x2b, 0x33, 0x3b
346 ****************************************************************************/
347 void x86emuOp_genop_word_R_RM(u8 op1)
351 u32 *destreg32, srcval;
354 op1 = (op1 >> 3) & 0x7;
357 DECODE_PRINTF(x86emu_GenOpName[op1]);
359 FETCH_DECODE_MODRM(mod, rh, rl);
361 srcoffset = decode_rmXX_address(mod,rl);
362 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
363 destreg32 = DECODE_RM_LONG_REGISTER(rh);
365 srcval = fetch_data_long(srcoffset);
368 *destreg32 = genop_long_operation[op1](*destreg32, srcval);
370 destreg = DECODE_RM_WORD_REGISTER(rh);
372 srcval = fetch_data_word(srcoffset);
375 *destreg = genop_word_operation[op1](*destreg, srcval);
377 } else { /* register to register */
378 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
380 destreg32 = DECODE_RM_LONG_REGISTER(rh);
382 srcreg = DECODE_RM_LONG_REGISTER(rl);
385 *destreg32 = genop_long_operation[op1](*destreg32, *srcreg);
388 destreg = DECODE_RM_WORD_REGISTER(rh);
390 srcreg = DECODE_RM_WORD_REGISTER(rl);
393 *destreg = genop_word_operation[op1](*destreg, *srcreg);
396 DECODE_CLEAR_SEGOVR();
400 /****************************************************************************
402 Handles opcodes 0x04, 0x0c, 0x14, 0x1c, 0x24, 0x2c, 0x34, 0x3c
403 ****************************************************************************/
404 void x86emuOp_genop_byte_AL_IMM(u8 op1)
408 op1 = (op1 >> 3) & 0x7;
411 DECODE_PRINTF(x86emu_GenOpName[op1]);
412 DECODE_PRINTF("\tAL,");
413 srcval = fetch_byte_imm();
414 DECODE_PRINTF2("%x\n", srcval);
416 M.x86.R_AL = genop_byte_operation[op1](M.x86.R_AL, srcval);
417 DECODE_CLEAR_SEGOVR();
421 /****************************************************************************
423 Handles opcodes 0x05, 0x0d, 0x15, 0x1d, 0x25, 0x2d, 0x35, 0x3d
424 ****************************************************************************/
425 void x86emuOp_genop_word_AX_IMM(u8 op1)
429 op1 = (op1 >> 3) & 0x7;
432 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
433 DECODE_PRINTF(x86emu_GenOpName[op1]);
434 DECODE_PRINTF("\tEAX,");
435 srcval = fetch_long_imm();
437 DECODE_PRINTF(x86emu_GenOpName[op1]);
438 DECODE_PRINTF("\tAX,");
439 srcval = fetch_word_imm();
441 DECODE_PRINTF2("%x\n", srcval);
443 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
444 M.x86.R_EAX = genop_long_operation[op1](M.x86.R_EAX, srcval);
446 M.x86.R_AX = genop_word_operation[op1](M.x86.R_AX, (u16)srcval);
448 DECODE_CLEAR_SEGOVR();
452 /****************************************************************************
455 ****************************************************************************/
456 void x86emuOp_push_ES(u8 X86EMU_UNUSED(op1))
459 DECODE_PRINTF("PUSH\tES\n");
461 push_word(M.x86.R_ES);
462 DECODE_CLEAR_SEGOVR();
466 /****************************************************************************
469 ****************************************************************************/
470 void x86emuOp_pop_ES(u8 X86EMU_UNUSED(op1))
473 DECODE_PRINTF("POP\tES\n");
475 M.x86.R_ES = pop_word();
476 DECODE_CLEAR_SEGOVR();
480 /****************************************************************************
483 ****************************************************************************/
484 void x86emuOp_push_CS(u8 X86EMU_UNUSED(op1))
487 DECODE_PRINTF("PUSH\tCS\n");
489 push_word(M.x86.R_CS);
490 DECODE_CLEAR_SEGOVR();
494 /****************************************************************************
496 Handles opcode 0x0f. Escape for two-byte opcode (286 or better)
497 ****************************************************************************/
498 void x86emuOp_two_byte(u8 X86EMU_UNUSED(op1))
500 u8 op2 = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++));
501 INC_DECODED_INST_LEN(1);
502 (*x86emu_optab2[op2])(op2);
505 /****************************************************************************
508 ****************************************************************************/
509 void x86emuOp_push_SS(u8 X86EMU_UNUSED(op1))
512 DECODE_PRINTF("PUSH\tSS\n");
514 push_word(M.x86.R_SS);
515 DECODE_CLEAR_SEGOVR();
519 /****************************************************************************
522 ****************************************************************************/
523 void x86emuOp_pop_SS(u8 X86EMU_UNUSED(op1))
526 DECODE_PRINTF("POP\tSS\n");
528 M.x86.R_SS = pop_word();
529 DECODE_CLEAR_SEGOVR();
533 /****************************************************************************
536 ****************************************************************************/
537 void x86emuOp_push_DS(u8 X86EMU_UNUSED(op1))
540 DECODE_PRINTF("PUSH\tDS\n");
542 push_word(M.x86.R_DS);
543 DECODE_CLEAR_SEGOVR();
547 /****************************************************************************
550 ****************************************************************************/
551 void x86emuOp_pop_DS(u8 X86EMU_UNUSED(op1))
554 DECODE_PRINTF("POP\tDS\n");
556 M.x86.R_DS = pop_word();
557 DECODE_CLEAR_SEGOVR();
561 /****************************************************************************
564 ****************************************************************************/
565 void x86emuOp_segovr_ES(u8 X86EMU_UNUSED(op1))
568 DECODE_PRINTF("ES:\n");
570 M.x86.mode |= SYSMODE_SEGOVR_ES;
572 * note the lack of DECODE_CLEAR_SEGOVR(r) since, here is one of 4
573 * opcode subroutines we do not want to do this.
578 /****************************************************************************
581 ****************************************************************************/
582 void x86emuOp_daa(u8 X86EMU_UNUSED(op1))
585 DECODE_PRINTF("DAA\n");
587 M.x86.R_AL = daa_byte(M.x86.R_AL);
588 DECODE_CLEAR_SEGOVR();
592 /****************************************************************************
595 ****************************************************************************/
596 void x86emuOp_segovr_CS(u8 X86EMU_UNUSED(op1))
599 DECODE_PRINTF("CS:\n");
601 M.x86.mode |= SYSMODE_SEGOVR_CS;
602 /* note no DECODE_CLEAR_SEGOVR here. */
606 /****************************************************************************
609 ****************************************************************************/
610 void x86emuOp_das(u8 X86EMU_UNUSED(op1))
613 DECODE_PRINTF("DAS\n");
615 M.x86.R_AL = das_byte(M.x86.R_AL);
616 DECODE_CLEAR_SEGOVR();
620 /****************************************************************************
623 ****************************************************************************/
624 void x86emuOp_segovr_SS(u8 X86EMU_UNUSED(op1))
627 DECODE_PRINTF("SS:\n");
629 M.x86.mode |= SYSMODE_SEGOVR_SS;
630 /* no DECODE_CLEAR_SEGOVR ! */
634 /****************************************************************************
637 ****************************************************************************/
638 void x86emuOp_aaa(u8 X86EMU_UNUSED(op1))
641 DECODE_PRINTF("AAA\n");
643 M.x86.R_AX = aaa_word(M.x86.R_AX);
644 DECODE_CLEAR_SEGOVR();
648 /****************************************************************************
651 ****************************************************************************/
652 void x86emuOp_segovr_DS(u8 X86EMU_UNUSED(op1))
655 DECODE_PRINTF("DS:\n");
657 M.x86.mode |= SYSMODE_SEGOVR_DS;
658 /* NO DECODE_CLEAR_SEGOVR! */
662 /****************************************************************************
665 ****************************************************************************/
666 void x86emuOp_aas(u8 X86EMU_UNUSED(op1))
669 DECODE_PRINTF("AAS\n");
671 M.x86.R_AX = aas_word(M.x86.R_AX);
672 DECODE_CLEAR_SEGOVR();
676 /****************************************************************************
678 Handles opcode 0x40 - 0x47
679 ****************************************************************************/
680 void x86emuOp_inc_register(u8 op1)
684 DECODE_PRINTF("INC\t");
685 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
687 reg = DECODE_RM_LONG_REGISTER(op1);
690 *reg = inc_long(*reg);
693 reg = DECODE_RM_WORD_REGISTER(op1);
696 *reg = inc_word(*reg);
698 DECODE_CLEAR_SEGOVR();
702 /****************************************************************************
704 Handles opcode 0x48 - 0x4F
705 ****************************************************************************/
706 void x86emuOp_dec_register(u8 op1)
710 DECODE_PRINTF("DEC\t");
711 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
713 reg = DECODE_RM_LONG_REGISTER(op1);
716 *reg = dec_long(*reg);
719 reg = DECODE_RM_WORD_REGISTER(op1);
722 *reg = dec_word(*reg);
724 DECODE_CLEAR_SEGOVR();
728 /****************************************************************************
730 Handles opcode 0x50 - 0x57
731 ****************************************************************************/
732 void x86emuOp_push_register(u8 op1)
736 DECODE_PRINTF("PUSH\t");
737 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
739 reg = DECODE_RM_LONG_REGISTER(op1);
745 reg = DECODE_RM_WORD_REGISTER(op1);
750 DECODE_CLEAR_SEGOVR();
754 /****************************************************************************
756 Handles opcode 0x58 - 0x5F
757 ****************************************************************************/
758 void x86emuOp_pop_register(u8 op1)
762 DECODE_PRINTF("POP\t");
763 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
765 reg = DECODE_RM_LONG_REGISTER(op1);
771 reg = DECODE_RM_WORD_REGISTER(op1);
776 DECODE_CLEAR_SEGOVR();
780 /****************************************************************************
783 ****************************************************************************/
784 void x86emuOp_push_all(u8 X86EMU_UNUSED(op1))
787 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
788 DECODE_PRINTF("PUSHAD\n");
790 DECODE_PRINTF("PUSHA\n");
793 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
794 u32 old_sp = M.x86.R_ESP;
796 push_long(M.x86.R_EAX);
797 push_long(M.x86.R_ECX);
798 push_long(M.x86.R_EDX);
799 push_long(M.x86.R_EBX);
801 push_long(M.x86.R_EBP);
802 push_long(M.x86.R_ESI);
803 push_long(M.x86.R_EDI);
805 u16 old_sp = M.x86.R_SP;
807 push_word(M.x86.R_AX);
808 push_word(M.x86.R_CX);
809 push_word(M.x86.R_DX);
810 push_word(M.x86.R_BX);
812 push_word(M.x86.R_BP);
813 push_word(M.x86.R_SI);
814 push_word(M.x86.R_DI);
816 DECODE_CLEAR_SEGOVR();
820 /****************************************************************************
823 ****************************************************************************/
824 void x86emuOp_pop_all(u8 X86EMU_UNUSED(op1))
827 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
828 DECODE_PRINTF("POPAD\n");
830 DECODE_PRINTF("POPA\n");
833 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
834 M.x86.R_EDI = pop_long();
835 M.x86.R_ESI = pop_long();
836 M.x86.R_EBP = pop_long();
837 M.x86.R_ESP += 4; /* skip ESP */
838 M.x86.R_EBX = pop_long();
839 M.x86.R_EDX = pop_long();
840 M.x86.R_ECX = pop_long();
841 M.x86.R_EAX = pop_long();
843 M.x86.R_DI = pop_word();
844 M.x86.R_SI = pop_word();
845 M.x86.R_BP = pop_word();
846 M.x86.R_SP += 2; /* skip SP */
847 M.x86.R_BX = pop_word();
848 M.x86.R_DX = pop_word();
849 M.x86.R_CX = pop_word();
850 M.x86.R_AX = pop_word();
852 DECODE_CLEAR_SEGOVR();
856 /*opcode 0x62 ILLEGAL OP, calls x86emuOp_illegal_op() */
857 /*opcode 0x63 ILLEGAL OP, calls x86emuOp_illegal_op() */
859 /****************************************************************************
862 ****************************************************************************/
863 void x86emuOp_segovr_FS(u8 X86EMU_UNUSED(op1))
866 DECODE_PRINTF("FS:\n");
868 M.x86.mode |= SYSMODE_SEGOVR_FS;
870 * note the lack of DECODE_CLEAR_SEGOVR(r) since, here is one of 4
871 * opcode subroutines we do not want to do this.
876 /****************************************************************************
879 ****************************************************************************/
880 void x86emuOp_segovr_GS(u8 X86EMU_UNUSED(op1))
883 DECODE_PRINTF("GS:\n");
885 M.x86.mode |= SYSMODE_SEGOVR_GS;
887 * note the lack of DECODE_CLEAR_SEGOVR(r) since, here is one of 4
888 * opcode subroutines we do not want to do this.
893 /****************************************************************************
895 Handles opcode 0x66 - prefix for 32-bit register
896 ****************************************************************************/
897 void x86emuOp_prefix_data(u8 X86EMU_UNUSED(op1))
900 DECODE_PRINTF("DATA:\n");
902 M.x86.mode |= SYSMODE_PREFIX_DATA;
903 /* note no DECODE_CLEAR_SEGOVR here. */
907 /****************************************************************************
909 Handles opcode 0x67 - prefix for 32-bit address
910 ****************************************************************************/
911 void x86emuOp_prefix_addr(u8 X86EMU_UNUSED(op1))
914 DECODE_PRINTF("ADDR:\n");
916 M.x86.mode |= SYSMODE_PREFIX_ADDR;
917 /* note no DECODE_CLEAR_SEGOVR here. */
921 /****************************************************************************
924 ****************************************************************************/
925 void x86emuOp_push_word_IMM(u8 X86EMU_UNUSED(op1))
930 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
931 imm = fetch_long_imm();
933 imm = fetch_word_imm();
935 DECODE_PRINTF2("PUSH\t%x\n", imm);
937 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
942 DECODE_CLEAR_SEGOVR();
946 /****************************************************************************
949 ****************************************************************************/
950 void x86emuOp_imul_word_IMM(u8 X86EMU_UNUSED(op1))
956 DECODE_PRINTF("IMUL\t");
957 FETCH_DECODE_MODRM(mod, rh, rl);
959 srcoffset = decode_rmXX_address(mod, rl);
960 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
966 destreg = DECODE_RM_LONG_REGISTER(rh);
968 srcval = fetch_data_long(srcoffset);
969 imm = fetch_long_imm();
970 DECODE_PRINTF2(",%d\n", (s32)imm);
972 imul_long_direct(&res_lo,&res_hi,(s32)srcval,(s32)imm);
973 if ((((res_lo & 0x80000000) == 0) && (res_hi == 0x00000000)) ||
974 (((res_lo & 0x80000000) != 0) && (res_hi == 0xFFFFFFFF))) {
981 *destreg = (u32)res_lo;
988 destreg = DECODE_RM_WORD_REGISTER(rh);
990 srcval = fetch_data_word(srcoffset);
991 imm = fetch_word_imm();
992 DECODE_PRINTF2(",%d\n", (s32)imm);
994 res = (s16)srcval * (s16)imm;
995 if ((((res & 0x8000) == 0) && ((res >> 16) == 0x0000)) ||
996 (((res & 0x8000) != 0) && ((res >> 16) == 0xFFFF))) {
1003 *destreg = (u16)res;
1005 } else { /* register to register */
1006 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1007 u32 *destreg,*srcreg;
1011 destreg = DECODE_RM_LONG_REGISTER(rh);
1013 srcreg = DECODE_RM_LONG_REGISTER(rl);
1014 imm = fetch_long_imm();
1015 DECODE_PRINTF2(",%d\n", (s32)imm);
1017 imul_long_direct(&res_lo,&res_hi,(s32)*srcreg,(s32)imm);
1018 if ((((res_lo & 0x80000000) == 0) && (res_hi == 0x00000000)) ||
1019 (((res_lo & 0x80000000) != 0) && (res_hi == 0xFFFFFFFF))) {
1026 *destreg = (u32)res_lo;
1028 u16 *destreg,*srcreg;
1032 destreg = DECODE_RM_WORD_REGISTER(rh);
1034 srcreg = DECODE_RM_WORD_REGISTER(rl);
1035 imm = fetch_word_imm();
1036 DECODE_PRINTF2(",%d\n", (s32)imm);
1037 res = (s16)*srcreg * (s16)imm;
1038 if ((((res & 0x8000) == 0) && ((res >> 16) == 0x0000)) ||
1039 (((res & 0x8000) != 0) && ((res >> 16) == 0xFFFF))) {
1046 *destreg = (u16)res;
1049 DECODE_CLEAR_SEGOVR();
1053 /****************************************************************************
1056 ****************************************************************************/
1057 void x86emuOp_push_byte_IMM(u8 X86EMU_UNUSED(op1))
1062 imm = (s8)fetch_byte_imm();
1063 DECODE_PRINTF2("PUSH\t%d\n", imm);
1066 DECODE_CLEAR_SEGOVR();
1070 /****************************************************************************
1073 ****************************************************************************/
1074 void x86emuOp_imul_byte_IMM(u8 X86EMU_UNUSED(op1))
1081 DECODE_PRINTF("IMUL\t");
1082 FETCH_DECODE_MODRM(mod, rh, rl);
1084 srcoffset = decode_rmXX_address(mod, rl);
1085 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1090 destreg = DECODE_RM_LONG_REGISTER(rh);
1092 srcval = fetch_data_long(srcoffset);
1093 imm = fetch_byte_imm();
1094 DECODE_PRINTF2(",%d\n", (s32)imm);
1096 imul_long_direct(&res_lo,&res_hi,(s32)srcval,(s32)imm);
1097 if ((((res_lo & 0x80000000) == 0) && (res_hi == 0x00000000)) ||
1098 (((res_lo & 0x80000000) != 0) && (res_hi == 0xFFFFFFFF))) {
1105 *destreg = (u32)res_lo;
1111 destreg = DECODE_RM_WORD_REGISTER(rh);
1113 srcval = fetch_data_word(srcoffset);
1114 imm = fetch_byte_imm();
1115 DECODE_PRINTF2(",%d\n", (s32)imm);
1117 res = (s16)srcval * (s16)imm;
1118 if ((((res & 0x8000) == 0) && ((res >> 16) == 0x0000)) ||
1119 (((res & 0x8000) != 0) && ((res >> 16) == 0xFFFF))) {
1126 *destreg = (u16)res;
1128 } else { /* register to register */
1129 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1130 u32 *destreg,*srcreg;
1133 destreg = DECODE_RM_LONG_REGISTER(rh);
1135 srcreg = DECODE_RM_LONG_REGISTER(rl);
1136 imm = fetch_byte_imm();
1137 DECODE_PRINTF2(",%d\n", (s32)imm);
1139 imul_long_direct(&res_lo,&res_hi,(s32)*srcreg,(s32)imm);
1140 if ((((res_lo & 0x80000000) == 0) && (res_hi == 0x00000000)) ||
1141 (((res_lo & 0x80000000) != 0) && (res_hi == 0xFFFFFFFF))) {
1148 *destreg = (u32)res_lo;
1150 u16 *destreg,*srcreg;
1153 destreg = DECODE_RM_WORD_REGISTER(rh);
1155 srcreg = DECODE_RM_WORD_REGISTER(rl);
1156 imm = fetch_byte_imm();
1157 DECODE_PRINTF2(",%d\n", (s32)imm);
1159 res = (s16)*srcreg * (s16)imm;
1160 if ((((res & 0x8000) == 0) && ((res >> 16) == 0x0000)) ||
1161 (((res & 0x8000) != 0) && ((res >> 16) == 0xFFFF))) {
1168 *destreg = (u16)res;
1171 DECODE_CLEAR_SEGOVR();
1175 /****************************************************************************
1178 ****************************************************************************/
1179 void x86emuOp_ins_byte(u8 X86EMU_UNUSED(op1))
1182 DECODE_PRINTF("INSB\n");
1185 DECODE_CLEAR_SEGOVR();
1189 /****************************************************************************
1192 ****************************************************************************/
1193 void x86emuOp_ins_word(u8 X86EMU_UNUSED(op1))
1196 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1197 DECODE_PRINTF("INSD\n");
1200 DECODE_PRINTF("INSW\n");
1204 DECODE_CLEAR_SEGOVR();
1208 /****************************************************************************
1211 ****************************************************************************/
1212 void x86emuOp_outs_byte(u8 X86EMU_UNUSED(op1))
1215 DECODE_PRINTF("OUTSB\n");
1218 DECODE_CLEAR_SEGOVR();
1222 /****************************************************************************
1225 ****************************************************************************/
1226 void x86emuOp_outs_word(u8 X86EMU_UNUSED(op1))
1229 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1230 DECODE_PRINTF("OUTSD\n");
1233 DECODE_PRINTF("OUTSW\n");
1237 DECODE_CLEAR_SEGOVR();
1241 /****************************************************************************
1243 Handles opcode 0x70 - 0x7F
1244 ****************************************************************************/
1245 int x86emu_check_jump_condition(u8 op);
1247 void x86emuOp_jump_near_cond(u8 op1)
1253 /* jump to byte offset if overflow flag is set */
1255 cond = x86emu_check_jump_condition(op1 & 0xF);
1256 offset = (s8)fetch_byte_imm();
1257 target = (u16)(M.x86.R_IP + (s16)offset);
1258 DECODE_PRINTF2("%x\n", target);
1261 M.x86.R_IP = target;
1262 DECODE_CLEAR_SEGOVR();
1266 /****************************************************************************
1269 ****************************************************************************/
1270 void x86emuOp_opc80_byte_RM_IMM(u8 X86EMU_UNUSED(op1))
1279 * Weirdo special case instruction format. Part of the opcode
1280 * held below in "RH". Doubly nested case would result, except
1281 * that the decoded instruction
1284 FETCH_DECODE_MODRM(mod, rh, rl);
1286 if (DEBUG_DECODE()) {
1287 /* XXX DECODE_PRINTF may be changed to something more
1288 general, so that it is important to leave the strings
1289 in the same format, even though the result is that the
1290 above test is done twice. */
1294 DECODE_PRINTF("ADD\t");
1297 DECODE_PRINTF("OR\t");
1300 DECODE_PRINTF("ADC\t");
1303 DECODE_PRINTF("SBB\t");
1306 DECODE_PRINTF("AND\t");
1309 DECODE_PRINTF("SUB\t");
1312 DECODE_PRINTF("XOR\t");
1315 DECODE_PRINTF("CMP\t");
1320 /* know operation, decode the mod byte to find the addressing
1323 DECODE_PRINTF("BYTE PTR ");
1324 destoffset = decode_rmXX_address(mod, rl);
1326 destval = fetch_data_byte(destoffset);
1327 imm = fetch_byte_imm();
1328 DECODE_PRINTF2("%x\n", imm);
1330 destval = (*genop_byte_operation[rh]) (destval, imm);
1332 store_data_byte(destoffset, destval);
1333 } else { /* register to register */
1334 destreg = DECODE_RM_BYTE_REGISTER(rl);
1336 imm = fetch_byte_imm();
1337 DECODE_PRINTF2("%x\n", imm);
1339 destval = (*genop_byte_operation[rh]) (*destreg, imm);
1343 DECODE_CLEAR_SEGOVR();
1347 /****************************************************************************
1350 ****************************************************************************/
1351 void x86emuOp_opc81_word_RM_IMM(u8 X86EMU_UNUSED(op1))
1357 * Weirdo special case instruction format. Part of the opcode
1358 * held below in "RH". Doubly nested case would result, except
1359 * that the decoded instruction
1362 FETCH_DECODE_MODRM(mod, rh, rl);
1364 if (DEBUG_DECODE()) {
1365 /* XXX DECODE_PRINTF may be changed to something more
1366 general, so that it is important to leave the strings
1367 in the same format, even though the result is that the
1368 above test is done twice. */
1372 DECODE_PRINTF("ADD\t");
1375 DECODE_PRINTF("OR\t");
1378 DECODE_PRINTF("ADC\t");
1381 DECODE_PRINTF("SBB\t");
1384 DECODE_PRINTF("AND\t");
1387 DECODE_PRINTF("SUB\t");
1390 DECODE_PRINTF("XOR\t");
1393 DECODE_PRINTF("CMP\t");
1399 * Know operation, decode the mod byte to find the addressing
1403 DECODE_PRINTF("DWORD PTR ");
1404 destoffset = decode_rmXX_address(mod, rl);
1405 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1409 destval = fetch_data_long(destoffset);
1410 imm = fetch_long_imm();
1411 DECODE_PRINTF2("%x\n", imm);
1413 destval = (*genop_long_operation[rh]) (destval, imm);
1415 store_data_long(destoffset, destval);
1420 destval = fetch_data_word(destoffset);
1421 imm = fetch_word_imm();
1422 DECODE_PRINTF2("%x\n", imm);
1424 destval = (*genop_word_operation[rh]) (destval, imm);
1426 store_data_word(destoffset, destval);
1428 } else { /* register to register */
1429 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1433 destreg = DECODE_RM_LONG_REGISTER(rl);
1435 imm = fetch_long_imm();
1436 DECODE_PRINTF2("%x\n", imm);
1438 destval = (*genop_long_operation[rh]) (*destreg, imm);
1445 destreg = DECODE_RM_WORD_REGISTER(rl);
1447 imm = fetch_word_imm();
1448 DECODE_PRINTF2("%x\n", imm);
1450 destval = (*genop_word_operation[rh]) (*destreg, imm);
1455 DECODE_CLEAR_SEGOVR();
1459 /****************************************************************************
1462 ****************************************************************************/
1463 void x86emuOp_opc82_byte_RM_IMM(u8 X86EMU_UNUSED(op1))
1472 * Weirdo special case instruction format. Part of the opcode
1473 * held below in "RH". Doubly nested case would result, except
1474 * that the decoded instruction Similar to opcode 81, except that
1475 * the immediate byte is sign extended to a word length.
1478 FETCH_DECODE_MODRM(mod, rh, rl);
1480 if (DEBUG_DECODE()) {
1481 /* XXX DECODE_PRINTF may be changed to something more
1482 general, so that it is important to leave the strings
1483 in the same format, even though the result is that the
1484 above test is done twice. */
1487 DECODE_PRINTF("ADD\t");
1490 DECODE_PRINTF("OR\t");
1493 DECODE_PRINTF("ADC\t");
1496 DECODE_PRINTF("SBB\t");
1499 DECODE_PRINTF("AND\t");
1502 DECODE_PRINTF("SUB\t");
1505 DECODE_PRINTF("XOR\t");
1508 DECODE_PRINTF("CMP\t");
1513 /* know operation, decode the mod byte to find the addressing
1516 DECODE_PRINTF("BYTE PTR ");
1517 destoffset = decode_rmXX_address(mod, rl);
1518 destval = fetch_data_byte(destoffset);
1519 imm = fetch_byte_imm();
1520 DECODE_PRINTF2(",%x\n", imm);
1522 destval = (*genop_byte_operation[rh]) (destval, imm);
1524 store_data_byte(destoffset, destval);
1525 } else { /* register to register */
1526 destreg = DECODE_RM_BYTE_REGISTER(rl);
1527 imm = fetch_byte_imm();
1528 DECODE_PRINTF2(",%x\n", imm);
1530 destval = (*genop_byte_operation[rh]) (*destreg, imm);
1534 DECODE_CLEAR_SEGOVR();
1538 /****************************************************************************
1541 ****************************************************************************/
1542 void x86emuOp_opc83_word_RM_IMM(u8 X86EMU_UNUSED(op1))
1548 * Weirdo special case instruction format. Part of the opcode
1549 * held below in "RH". Doubly nested case would result, except
1550 * that the decoded instruction Similar to opcode 81, except that
1551 * the immediate byte is sign extended to a word length.
1554 FETCH_DECODE_MODRM(mod, rh, rl);
1556 if (DEBUG_DECODE()) {
1557 /* XXX DECODE_PRINTF may be changed to something more
1558 general, so that it is important to leave the strings
1559 in the same format, even though the result is that the
1560 above test is done twice. */
1563 DECODE_PRINTF("ADD\t");
1566 DECODE_PRINTF("OR\t");
1569 DECODE_PRINTF("ADC\t");
1572 DECODE_PRINTF("SBB\t");
1575 DECODE_PRINTF("AND\t");
1578 DECODE_PRINTF("SUB\t");
1581 DECODE_PRINTF("XOR\t");
1584 DECODE_PRINTF("CMP\t");
1589 /* know operation, decode the mod byte to find the addressing
1592 DECODE_PRINTF("DWORD PTR ");
1593 destoffset = decode_rmXX_address(mod,rl);
1595 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1598 destval = fetch_data_long(destoffset);
1599 imm = (s8) fetch_byte_imm();
1600 DECODE_PRINTF2(",%x\n", imm);
1602 destval = (*genop_long_operation[rh]) (destval, imm);
1604 store_data_long(destoffset, destval);
1608 destval = fetch_data_word(destoffset);
1609 imm = (s8) fetch_byte_imm();
1610 DECODE_PRINTF2(",%x\n", imm);
1612 destval = (*genop_word_operation[rh]) (destval, imm);
1614 store_data_word(destoffset, destval);
1616 } else { /* register to register */
1617 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1621 destreg = DECODE_RM_LONG_REGISTER(rl);
1622 imm = (s8) fetch_byte_imm();
1623 DECODE_PRINTF2(",%x\n", imm);
1625 destval = (*genop_long_operation[rh]) (*destreg, imm);
1632 destreg = DECODE_RM_WORD_REGISTER(rl);
1633 imm = (s8) fetch_byte_imm();
1634 DECODE_PRINTF2(",%x\n", imm);
1636 destval = (*genop_word_operation[rh]) (*destreg, imm);
1641 DECODE_CLEAR_SEGOVR();
1645 /****************************************************************************
1648 ****************************************************************************/
1649 void x86emuOp_test_byte_RM_R(u8 X86EMU_UNUSED(op1))
1652 u8 *destreg, *srcreg;
1657 DECODE_PRINTF("TEST\t");
1658 FETCH_DECODE_MODRM(mod, rh, rl);
1660 destoffset = decode_rmXX_address(mod, rl);
1662 destval = fetch_data_byte(destoffset);
1663 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1664 DECODE_PRINTF("\n");
1666 test_byte(destval, *srcreg);
1667 } else { /* register to register */
1668 destreg = DECODE_RM_BYTE_REGISTER(rl);
1670 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1671 DECODE_PRINTF("\n");
1673 test_byte(*destreg, *srcreg);
1675 DECODE_CLEAR_SEGOVR();
1679 /****************************************************************************
1682 ****************************************************************************/
1683 void x86emuOp_test_word_RM_R(u8 X86EMU_UNUSED(op1))
1689 DECODE_PRINTF("TEST\t");
1690 FETCH_DECODE_MODRM(mod, rh, rl);
1692 destoffset = decode_rmXX_address(mod, rl);
1693 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1698 destval = fetch_data_long(destoffset);
1699 srcreg = DECODE_RM_LONG_REGISTER(rh);
1700 DECODE_PRINTF("\n");
1702 test_long(destval, *srcreg);
1708 destval = fetch_data_word(destoffset);
1709 srcreg = DECODE_RM_WORD_REGISTER(rh);
1710 DECODE_PRINTF("\n");
1712 test_word(destval, *srcreg);
1714 } else { /* register to register */
1715 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1716 u32 *destreg,*srcreg;
1718 destreg = DECODE_RM_LONG_REGISTER(rl);
1720 srcreg = DECODE_RM_LONG_REGISTER(rh);
1721 DECODE_PRINTF("\n");
1723 test_long(*destreg, *srcreg);
1725 u16 *destreg,*srcreg;
1727 destreg = DECODE_RM_WORD_REGISTER(rl);
1729 srcreg = DECODE_RM_WORD_REGISTER(rh);
1730 DECODE_PRINTF("\n");
1732 test_word(*destreg, *srcreg);
1735 DECODE_CLEAR_SEGOVR();
1739 /****************************************************************************
1742 ****************************************************************************/
1743 void x86emuOp_xchg_byte_RM_R(u8 X86EMU_UNUSED(op1))
1746 u8 *destreg, *srcreg;
1752 DECODE_PRINTF("XCHG\t");
1753 FETCH_DECODE_MODRM(mod, rh, rl);
1755 destoffset = decode_rmXX_address(mod, rl);
1757 destval = fetch_data_byte(destoffset);
1758 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1759 DECODE_PRINTF("\n");
1764 store_data_byte(destoffset, destval);
1765 } else { /* register to register */
1766 destreg = DECODE_RM_BYTE_REGISTER(rl);
1768 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1769 DECODE_PRINTF("\n");
1775 DECODE_CLEAR_SEGOVR();
1779 /****************************************************************************
1782 ****************************************************************************/
1783 void x86emuOp_xchg_word_RM_R(u8 X86EMU_UNUSED(op1))
1789 DECODE_PRINTF("XCHG\t");
1790 FETCH_DECODE_MODRM(mod, rh, rl);
1792 destoffset = decode_rmXX_address(mod, rl);
1794 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1798 destval = fetch_data_long(destoffset);
1799 srcreg = DECODE_RM_LONG_REGISTER(rh);
1800 DECODE_PRINTF("\n");
1805 store_data_long(destoffset, destval);
1810 destval = fetch_data_word(destoffset);
1811 srcreg = DECODE_RM_WORD_REGISTER(rh);
1812 DECODE_PRINTF("\n");
1817 store_data_word(destoffset, destval);
1819 } else { /* register to register */
1820 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1821 u32 *destreg,*srcreg;
1824 destreg = DECODE_RM_LONG_REGISTER(rl);
1826 srcreg = DECODE_RM_LONG_REGISTER(rh);
1827 DECODE_PRINTF("\n");
1833 u16 *destreg,*srcreg;
1836 destreg = DECODE_RM_WORD_REGISTER(rl);
1838 srcreg = DECODE_RM_WORD_REGISTER(rh);
1839 DECODE_PRINTF("\n");
1846 DECODE_CLEAR_SEGOVR();
1850 /****************************************************************************
1853 ****************************************************************************/
1854 void x86emuOp_mov_byte_RM_R(u8 X86EMU_UNUSED(op1))
1857 u8 *destreg, *srcreg;
1861 DECODE_PRINTF("MOV\t");
1862 FETCH_DECODE_MODRM(mod, rh, rl);
1864 destoffset = decode_rmXX_address(mod, rl);
1866 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1867 DECODE_PRINTF("\n");
1869 store_data_byte(destoffset, *srcreg);
1870 } else { /* register to register */
1871 destreg = DECODE_RM_BYTE_REGISTER(rl);
1873 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1874 DECODE_PRINTF("\n");
1878 DECODE_CLEAR_SEGOVR();
1882 /****************************************************************************
1885 ****************************************************************************/
1886 void x86emuOp_mov_word_RM_R(u8 X86EMU_UNUSED(op1))
1892 DECODE_PRINTF("MOV\t");
1893 FETCH_DECODE_MODRM(mod, rh, rl);
1895 destoffset = decode_rmXX_address(mod, rl);
1896 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1900 srcreg = DECODE_RM_LONG_REGISTER(rh);
1901 DECODE_PRINTF("\n");
1903 store_data_long(destoffset, *srcreg);
1908 srcreg = DECODE_RM_WORD_REGISTER(rh);
1909 DECODE_PRINTF("\n");
1911 store_data_word(destoffset, *srcreg);
1913 } else { /* register to register */
1914 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1915 u32 *destreg,*srcreg;
1917 destreg = DECODE_RM_LONG_REGISTER(rl);
1919 srcreg = DECODE_RM_LONG_REGISTER(rh);
1920 DECODE_PRINTF("\n");
1924 u16 *destreg,*srcreg;
1926 destreg = DECODE_RM_WORD_REGISTER(rl);
1928 srcreg = DECODE_RM_WORD_REGISTER(rh);
1929 DECODE_PRINTF("\n");
1934 DECODE_CLEAR_SEGOVR();
1938 /****************************************************************************
1941 ****************************************************************************/
1942 void x86emuOp_mov_byte_R_RM(u8 X86EMU_UNUSED(op1))
1945 u8 *destreg, *srcreg;
1950 DECODE_PRINTF("MOV\t");
1951 FETCH_DECODE_MODRM(mod, rh, rl);
1953 destreg = DECODE_RM_BYTE_REGISTER(rh);
1955 srcoffset = decode_rmXX_address(mod, rl);
1956 srcval = fetch_data_byte(srcoffset);
1957 DECODE_PRINTF("\n");
1960 } else { /* register to register */
1961 destreg = DECODE_RM_BYTE_REGISTER(rh);
1963 srcreg = DECODE_RM_BYTE_REGISTER(rl);
1964 DECODE_PRINTF("\n");
1968 DECODE_CLEAR_SEGOVR();
1972 /****************************************************************************
1975 ****************************************************************************/
1976 void x86emuOp_mov_word_R_RM(u8 X86EMU_UNUSED(op1))
1982 DECODE_PRINTF("MOV\t");
1983 FETCH_DECODE_MODRM(mod, rh, rl);
1985 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1989 destreg = DECODE_RM_LONG_REGISTER(rh);
1991 srcoffset = decode_rmXX_address(mod, rl);
1992 srcval = fetch_data_long(srcoffset);
1993 DECODE_PRINTF("\n");
2000 destreg = DECODE_RM_WORD_REGISTER(rh);
2002 srcoffset = decode_rmXX_address(mod, rl);
2003 srcval = fetch_data_word(srcoffset);
2004 DECODE_PRINTF("\n");
2008 } else { /* register to register */
2009 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2010 u32 *destreg, *srcreg;
2012 destreg = DECODE_RM_LONG_REGISTER(rh);
2014 srcreg = DECODE_RM_LONG_REGISTER(rl);
2015 DECODE_PRINTF("\n");
2019 u16 *destreg, *srcreg;
2021 destreg = DECODE_RM_WORD_REGISTER(rh);
2023 srcreg = DECODE_RM_WORD_REGISTER(rl);
2024 DECODE_PRINTF("\n");
2029 DECODE_CLEAR_SEGOVR();
2033 /****************************************************************************
2036 ****************************************************************************/
2037 void x86emuOp_mov_word_RM_SR(u8 X86EMU_UNUSED(op1))
2040 u16 *destreg, *srcreg;
2045 DECODE_PRINTF("MOV\t");
2046 FETCH_DECODE_MODRM(mod, rh, rl);
2048 destoffset = decode_rmXX_address(mod, rl);
2050 srcreg = decode_rm_seg_register(rh);
2051 DECODE_PRINTF("\n");
2054 store_data_word(destoffset, destval);
2055 } else { /* register to register */
2056 destreg = DECODE_RM_WORD_REGISTER(rl);
2058 srcreg = decode_rm_seg_register(rh);
2059 DECODE_PRINTF("\n");
2063 DECODE_CLEAR_SEGOVR();
2067 /****************************************************************************
2070 ****************************************************************************/
2071 void x86emuOp_lea_word_R_M(u8 X86EMU_UNUSED(op1))
2078 * TODO: Need to handle address size prefix!
2080 * lea eax,[eax+ebx*2] ??
2084 DECODE_PRINTF("LEA\t");
2085 FETCH_DECODE_MODRM(mod, rh, rl);
2087 srcreg = DECODE_RM_WORD_REGISTER(rh);
2089 destoffset = decode_rmXX_address(mod, rl);
2090 DECODE_PRINTF("\n");
2092 *srcreg = (u16)destoffset;
2094 /* } else { undefined. Do nothing. } */
2095 DECODE_CLEAR_SEGOVR();
2099 /****************************************************************************
2102 ****************************************************************************/
2103 void x86emuOp_mov_word_SR_RM(u8 X86EMU_UNUSED(op1))
2106 u16 *destreg, *srcreg;
2111 DECODE_PRINTF("MOV\t");
2112 FETCH_DECODE_MODRM(mod, rh, rl);
2114 destreg = decode_rm_seg_register(rh);
2116 srcoffset = decode_rmXX_address(mod, rl);
2117 srcval = fetch_data_word(srcoffset);
2118 DECODE_PRINTF("\n");
2121 } else { /* register to register */
2122 destreg = decode_rm_seg_register(rh);
2124 srcreg = DECODE_RM_WORD_REGISTER(rl);
2125 DECODE_PRINTF("\n");
2130 * Clean up, and reset all the R_xSP pointers to the correct
2131 * locations. This is about 3x too much overhead (doing all the
2132 * segreg ptrs when only one is needed, but this instruction
2133 * *cannot* be that common, and this isn't too much work anyway.
2135 DECODE_CLEAR_SEGOVR();
2139 /****************************************************************************
2142 ****************************************************************************/
2143 void x86emuOp_pop_RM(u8 X86EMU_UNUSED(op1))
2149 DECODE_PRINTF("POP\t");
2150 FETCH_DECODE_MODRM(mod, rh, rl);
2152 DECODE_PRINTF("ILLEGAL DECODE OF OPCODE 8F\n");
2156 destoffset = decode_rmXX_address(mod, rl);
2157 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2160 DECODE_PRINTF("\n");
2162 destval = pop_long();
2163 store_data_long(destoffset, destval);
2167 DECODE_PRINTF("\n");
2169 destval = pop_word();
2170 store_data_word(destoffset, destval);
2172 } else { /* register to register */
2173 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2176 destreg = DECODE_RM_LONG_REGISTER(rl);
2177 DECODE_PRINTF("\n");
2179 *destreg = pop_long();
2183 destreg = DECODE_RM_WORD_REGISTER(rl);
2184 DECODE_PRINTF("\n");
2186 *destreg = pop_word();
2189 DECODE_CLEAR_SEGOVR();
2193 /****************************************************************************
2196 ****************************************************************************/
2197 void x86emuOp_nop(u8 X86EMU_UNUSED(op1))
2200 DECODE_PRINTF("NOP\n");
2202 DECODE_CLEAR_SEGOVR();
2206 /****************************************************************************
2208 Handles opcode 0x91-0x97
2209 ****************************************************************************/
2210 void x86emuOp_xchg_word_AX_register(u8 X86EMU_UNUSED(op1))
2218 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2220 DECODE_PRINTF("XCHG\tEAX,");
2221 reg32 = DECODE_RM_LONG_REGISTER(op1);
2222 DECODE_PRINTF("\n");
2225 M.x86.R_EAX = *reg32;
2229 DECODE_PRINTF("XCHG\tAX,");
2230 reg16 = DECODE_RM_WORD_REGISTER(op1);
2231 DECODE_PRINTF("\n");
2234 M.x86.R_EAX = *reg16;
2237 DECODE_CLEAR_SEGOVR();
2241 /****************************************************************************
2244 ****************************************************************************/
2245 void x86emuOp_cbw(u8 X86EMU_UNUSED(op1))
2248 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2249 DECODE_PRINTF("CWDE\n");
2251 DECODE_PRINTF("CBW\n");
2254 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2255 if (M.x86.R_AX & 0x8000) {
2256 M.x86.R_EAX |= 0xffff0000;
2258 M.x86.R_EAX &= 0x0000ffff;
2261 if (M.x86.R_AL & 0x80) {
2267 DECODE_CLEAR_SEGOVR();
2271 /****************************************************************************
2274 ****************************************************************************/
2275 void x86emuOp_cwd(u8 X86EMU_UNUSED(op1))
2278 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2279 DECODE_PRINTF("CDQ\n");
2281 DECODE_PRINTF("CWD\n");
2283 DECODE_PRINTF("CWD\n");
2285 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2286 if (M.x86.R_EAX & 0x80000000) {
2287 M.x86.R_EDX = 0xffffffff;
2292 if (M.x86.R_AX & 0x8000) {
2293 M.x86.R_DX = 0xffff;
2298 DECODE_CLEAR_SEGOVR();
2302 /****************************************************************************
2305 ****************************************************************************/
2306 void x86emuOp_call_far_IMM(u8 X86EMU_UNUSED(op1))
2311 DECODE_PRINTF("CALL\t");
2312 faroff = fetch_word_imm();
2313 farseg = fetch_word_imm();
2314 DECODE_PRINTF2("%04x:", farseg);
2315 DECODE_PRINTF2("%04x\n", faroff);
2316 CALL_TRACE(M.x86.saved_cs, M.x86.saved_ip, farseg, faroff, "FAR ");
2320 * Hooked interrupt vectors calling into our "BIOS" will cause
2321 * problems unless all intersegment stuff is checked for BIOS
2322 * access. Check needed here. For moment, let it alone.
2325 push_word(M.x86.R_CS);
2326 M.x86.R_CS = farseg;
2327 push_word(M.x86.R_IP);
2328 M.x86.R_IP = faroff;
2329 DECODE_CLEAR_SEGOVR();
2333 /****************************************************************************
2336 ****************************************************************************/
2337 void x86emuOp_wait(u8 X86EMU_UNUSED(op1))
2340 DECODE_PRINTF("WAIT");
2343 DECODE_CLEAR_SEGOVR();
2347 /****************************************************************************
2350 ****************************************************************************/
2351 void x86emuOp_pushf_word(u8 X86EMU_UNUSED(op1))
2356 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2357 DECODE_PRINTF("PUSHFD\n");
2359 DECODE_PRINTF("PUSHF\n");
2363 /* clear out *all* bits not representing flags, and turn on real bits */
2364 flags = (M.x86.R_EFLG & F_MSK) | F_ALWAYS_ON;
2365 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2368 push_word((u16)flags);
2370 DECODE_CLEAR_SEGOVR();
2374 /****************************************************************************
2377 ****************************************************************************/
2378 void x86emuOp_popf_word(u8 X86EMU_UNUSED(op1))
2381 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2382 DECODE_PRINTF("POPFD\n");
2384 DECODE_PRINTF("POPF\n");
2387 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2388 M.x86.R_EFLG = pop_long();
2390 M.x86.R_FLG = pop_word();
2392 DECODE_CLEAR_SEGOVR();
2396 /****************************************************************************
2399 ****************************************************************************/
2400 void x86emuOp_sahf(u8 X86EMU_UNUSED(op1))
2403 DECODE_PRINTF("SAHF\n");
2405 /* clear the lower bits of the flag register */
2406 M.x86.R_FLG &= 0xffffff00;
2407 /* or in the AH register into the flags register */
2408 M.x86.R_FLG |= M.x86.R_AH;
2409 DECODE_CLEAR_SEGOVR();
2413 /****************************************************************************
2416 ****************************************************************************/
2417 void x86emuOp_lahf(u8 X86EMU_UNUSED(op1))
2420 DECODE_PRINTF("LAHF\n");
2422 M.x86.R_AH = (u8)(M.x86.R_FLG & 0xff);
2423 /*undocumented TC++ behavior??? Nope. It's documented, but
2424 you have too look real hard to notice it. */
2426 DECODE_CLEAR_SEGOVR();
2430 /****************************************************************************
2433 ****************************************************************************/
2434 void x86emuOp_mov_AL_M_IMM(u8 X86EMU_UNUSED(op1))
2439 DECODE_PRINTF("MOV\tAL,");
2440 offset = fetch_word_imm();
2441 DECODE_PRINTF2("[%04x]\n", offset);
2443 M.x86.R_AL = fetch_data_byte(offset);
2444 DECODE_CLEAR_SEGOVR();
2448 /****************************************************************************
2451 ****************************************************************************/
2452 void x86emuOp_mov_AX_M_IMM(u8 X86EMU_UNUSED(op1))
2457 offset = fetch_word_imm();
2458 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2459 DECODE_PRINTF2("MOV\tEAX,[%04x]\n", offset);
2461 DECODE_PRINTF2("MOV\tAX,[%04x]\n", offset);
2464 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2465 M.x86.R_EAX = fetch_data_long(offset);
2467 M.x86.R_AX = fetch_data_word(offset);
2469 DECODE_CLEAR_SEGOVR();
2473 /****************************************************************************
2476 ****************************************************************************/
2477 void x86emuOp_mov_M_AL_IMM(u8 X86EMU_UNUSED(op1))
2482 DECODE_PRINTF("MOV\t");
2483 offset = fetch_word_imm();
2484 DECODE_PRINTF2("[%04x],AL\n", offset);
2486 store_data_byte(offset, M.x86.R_AL);
2487 DECODE_CLEAR_SEGOVR();
2491 /****************************************************************************
2494 ****************************************************************************/
2495 void x86emuOp_mov_M_AX_IMM(u8 X86EMU_UNUSED(op1))
2500 offset = fetch_word_imm();
2501 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2502 DECODE_PRINTF2("MOV\t[%04x],EAX\n", offset);
2504 DECODE_PRINTF2("MOV\t[%04x],AX\n", offset);
2507 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2508 store_data_long(offset, M.x86.R_EAX);
2510 store_data_word(offset, M.x86.R_AX);
2512 DECODE_CLEAR_SEGOVR();
2516 /****************************************************************************
2519 ****************************************************************************/
2520 void x86emuOp_movs_byte(u8 X86EMU_UNUSED(op1))
2527 DECODE_PRINTF("MOVS\tBYTE\n");
2528 if (ACCESS_FLAG(F_DF)) /* down */
2534 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2535 /* dont care whether REPE or REPNE */
2536 /* move them until CX is ZERO. */
2539 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2542 val = fetch_data_byte(M.x86.R_SI);
2543 store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, val);
2547 DECODE_CLEAR_SEGOVR();
2551 /****************************************************************************
2554 ****************************************************************************/
2555 void x86emuOp_movs_word(u8 X86EMU_UNUSED(op1))
2562 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2563 DECODE_PRINTF("MOVS\tDWORD\n");
2564 if (ACCESS_FLAG(F_DF)) /* down */
2569 DECODE_PRINTF("MOVS\tWORD\n");
2570 if (ACCESS_FLAG(F_DF)) /* down */
2577 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2578 /* dont care whether REPE or REPNE */
2579 /* move them until CX is ZERO. */
2582 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2585 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2586 val = fetch_data_long(M.x86.R_SI);
2587 store_data_long_abs(M.x86.R_ES, M.x86.R_DI, val);
2589 val = fetch_data_word(M.x86.R_SI);
2590 store_data_word_abs(M.x86.R_ES, M.x86.R_DI, (u16)val);
2595 DECODE_CLEAR_SEGOVR();
2599 /****************************************************************************
2602 ****************************************************************************/
2603 void x86emuOp_cmps_byte(u8 X86EMU_UNUSED(op1))
2609 DECODE_PRINTF("CMPS\tBYTE\n");
2611 if (ACCESS_FLAG(F_DF)) /* down */
2616 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2618 /* move them until CX is ZERO. */
2619 while (M.x86.R_CX != 0) {
2620 val1 = fetch_data_byte(M.x86.R_SI);
2621 val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2622 cmp_byte(val1, val2);
2626 if ( (M.x86.mode & SYSMODE_PREFIX_REPE) && (ACCESS_FLAG(F_ZF) == 0) ) break;
2627 if ( (M.x86.mode & SYSMODE_PREFIX_REPNE) && ACCESS_FLAG(F_ZF) ) break;
2629 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2631 val1 = fetch_data_byte(M.x86.R_SI);
2632 val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2633 cmp_byte(val1, val2);
2637 DECODE_CLEAR_SEGOVR();
2641 /****************************************************************************
2644 ****************************************************************************/
2645 void x86emuOp_cmps_word(u8 X86EMU_UNUSED(op1))
2651 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2652 DECODE_PRINTF("CMPS\tDWORD\n");
2655 DECODE_PRINTF("CMPS\tWORD\n");
2658 if (ACCESS_FLAG(F_DF)) /* down */
2662 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2664 /* move them until CX is ZERO. */
2665 while (M.x86.R_CX != 0) {
2666 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2667 val1 = fetch_data_long(M.x86.R_SI);
2668 val2 = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
2669 cmp_long(val1, val2);
2671 val1 = fetch_data_word(M.x86.R_SI);
2672 val2 = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
2673 cmp_word((u16)val1, (u16)val2);
2678 if ( (M.x86.mode & SYSMODE_PREFIX_REPE) && ACCESS_FLAG(F_ZF) == 0 ) break;
2679 if ( (M.x86.mode & SYSMODE_PREFIX_REPNE) && ACCESS_FLAG(F_ZF) ) break;
2681 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2683 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2684 val1 = fetch_data_long(M.x86.R_SI);
2685 val2 = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
2686 cmp_long(val1, val2);
2688 val1 = fetch_data_word(M.x86.R_SI);
2689 val2 = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
2690 cmp_word((u16)val1, (u16)val2);
2695 DECODE_CLEAR_SEGOVR();
2699 /****************************************************************************
2702 ****************************************************************************/
2703 void x86emuOp_test_AL_IMM(u8 X86EMU_UNUSED(op1))
2708 DECODE_PRINTF("TEST\tAL,");
2709 imm = fetch_byte_imm();
2710 DECODE_PRINTF2("%04x\n", imm);
2712 test_byte(M.x86.R_AL, (u8)imm);
2713 DECODE_CLEAR_SEGOVR();
2717 /****************************************************************************
2720 ****************************************************************************/
2721 void x86emuOp_test_AX_IMM(u8 X86EMU_UNUSED(op1))
2726 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2727 DECODE_PRINTF("TEST\tEAX,");
2728 srcval = fetch_long_imm();
2730 DECODE_PRINTF("TEST\tAX,");
2731 srcval = fetch_word_imm();
2733 DECODE_PRINTF2("%x\n", srcval);
2735 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2736 test_long(M.x86.R_EAX, srcval);
2738 test_word(M.x86.R_AX, (u16)srcval);
2740 DECODE_CLEAR_SEGOVR();
2744 /****************************************************************************
2747 ****************************************************************************/
2748 void x86emuOp_stos_byte(u8 X86EMU_UNUSED(op1))
2753 DECODE_PRINTF("STOS\tBYTE\n");
2754 if (ACCESS_FLAG(F_DF)) /* down */
2759 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2760 /* dont care whether REPE or REPNE */
2761 /* move them until CX is ZERO. */
2762 while (M.x86.R_CX != 0) {
2763 store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AL);
2767 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2769 store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AL);
2772 DECODE_CLEAR_SEGOVR();
2776 /****************************************************************************
2779 ****************************************************************************/
2780 void x86emuOp_stos_word(u8 X86EMU_UNUSED(op1))
2786 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2787 DECODE_PRINTF("STOS\tDWORD\n");
2788 if (ACCESS_FLAG(F_DF)) /* down */
2793 DECODE_PRINTF("STOS\tWORD\n");
2794 if (ACCESS_FLAG(F_DF)) /* down */
2801 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2802 /* dont care whether REPE or REPNE */
2803 /* move them until CX is ZERO. */
2806 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2809 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2810 store_data_long_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_EAX);
2812 store_data_word_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AX);
2816 DECODE_CLEAR_SEGOVR();
2820 /****************************************************************************
2823 ****************************************************************************/
2824 void x86emuOp_lods_byte(u8 X86EMU_UNUSED(op1))
2829 DECODE_PRINTF("LODS\tBYTE\n");
2831 if (ACCESS_FLAG(F_DF)) /* down */
2835 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2836 /* dont care whether REPE or REPNE */
2837 /* move them until CX is ZERO. */
2838 while (M.x86.R_CX != 0) {
2839 M.x86.R_AL = fetch_data_byte(M.x86.R_SI);
2843 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2845 M.x86.R_AL = fetch_data_byte(M.x86.R_SI);
2848 DECODE_CLEAR_SEGOVR();
2852 /****************************************************************************
2855 ****************************************************************************/
2856 void x86emuOp_lods_word(u8 X86EMU_UNUSED(op1))
2862 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2863 DECODE_PRINTF("LODS\tDWORD\n");
2864 if (ACCESS_FLAG(F_DF)) /* down */
2869 DECODE_PRINTF("LODS\tWORD\n");
2870 if (ACCESS_FLAG(F_DF)) /* down */
2877 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2878 /* dont care whether REPE or REPNE */
2879 /* move them until CX is ZERO. */
2882 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2885 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2886 M.x86.R_EAX = fetch_data_long(M.x86.R_SI);
2888 M.x86.R_AX = fetch_data_word(M.x86.R_SI);
2892 DECODE_CLEAR_SEGOVR();
2896 /****************************************************************************
2899 ****************************************************************************/
2900 void x86emuOp_scas_byte(u8 X86EMU_UNUSED(op1))
2906 DECODE_PRINTF("SCAS\tBYTE\n");
2908 if (ACCESS_FLAG(F_DF)) /* down */
2912 if (M.x86.mode & SYSMODE_PREFIX_REPE) {
2914 /* move them until CX is ZERO. */
2915 while (M.x86.R_CX != 0) {
2916 val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2917 cmp_byte(M.x86.R_AL, val2);
2920 if (ACCESS_FLAG(F_ZF) == 0)
2923 M.x86.mode &= ~SYSMODE_PREFIX_REPE;
2924 } else if (M.x86.mode & SYSMODE_PREFIX_REPNE) {
2926 /* move them until CX is ZERO. */
2927 while (M.x86.R_CX != 0) {
2928 val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2929 cmp_byte(M.x86.R_AL, val2);
2932 if (ACCESS_FLAG(F_ZF))
2933 break; /* zero flag set means equal */
2935 M.x86.mode &= ~SYSMODE_PREFIX_REPNE;
2937 val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2938 cmp_byte(M.x86.R_AL, val2);
2941 DECODE_CLEAR_SEGOVR();
2945 /****************************************************************************
2948 ****************************************************************************/
2949 void x86emuOp_scas_word(u8 X86EMU_UNUSED(op1))
2955 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2956 DECODE_PRINTF("SCAS\tDWORD\n");
2957 if (ACCESS_FLAG(F_DF)) /* down */
2962 DECODE_PRINTF("SCAS\tWORD\n");
2963 if (ACCESS_FLAG(F_DF)) /* down */
2969 if (M.x86.mode & SYSMODE_PREFIX_REPE) {
2971 /* move them until CX is ZERO. */
2972 while (M.x86.R_CX != 0) {
2973 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2974 val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
2975 cmp_long(M.x86.R_EAX, val);
2977 val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
2978 cmp_word(M.x86.R_AX, (u16)val);
2982 if (ACCESS_FLAG(F_ZF) == 0)
2985 M.x86.mode &= ~SYSMODE_PREFIX_REPE;
2986 } else if (M.x86.mode & SYSMODE_PREFIX_REPNE) {
2988 /* move them until CX is ZERO. */
2989 while (M.x86.R_CX != 0) {
2990 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2991 val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
2992 cmp_long(M.x86.R_EAX, val);
2994 val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
2995 cmp_word(M.x86.R_AX, (u16)val);
2999 if (ACCESS_FLAG(F_ZF))
3000 break; /* zero flag set means equal */
3002 M.x86.mode &= ~SYSMODE_PREFIX_REPNE;
3004 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3005 val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
3006 cmp_long(M.x86.R_EAX, val);
3008 val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
3009 cmp_word(M.x86.R_AX, (u16)val);
3013 DECODE_CLEAR_SEGOVR();
3017 /****************************************************************************
3019 Handles opcode 0xb0 - 0xb7
3020 ****************************************************************************/
3021 void x86emuOp_mov_byte_register_IMM(u8 op1)
3026 DECODE_PRINTF("MOV\t");
3027 ptr = DECODE_RM_BYTE_REGISTER(op1 & 0x7);
3029 imm = fetch_byte_imm();
3030 DECODE_PRINTF2("%x\n", imm);
3033 DECODE_CLEAR_SEGOVR();
3037 /****************************************************************************
3039 Handles opcode 0xb8 - 0xbf
3040 ****************************************************************************/
3041 void x86emuOp_mov_word_register_IMM(u8 X86EMU_UNUSED(op1))
3048 DECODE_PRINTF("MOV\t");
3049 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3051 reg32 = DECODE_RM_LONG_REGISTER(op1);
3052 srcval = fetch_long_imm();
3053 DECODE_PRINTF2(",%x\n", srcval);
3058 reg16 = DECODE_RM_WORD_REGISTER(op1);
3059 srcval = fetch_word_imm();
3060 DECODE_PRINTF2(",%x\n", srcval);
3062 *reg16 = (u16)srcval;
3064 DECODE_CLEAR_SEGOVR();
3068 /****************************************************************************
3071 ****************************************************************************/
3072 void x86emuOp_opcC0_byte_RM_MEM(u8 X86EMU_UNUSED(op1))
3081 * Yet another weirdo special case instruction format. Part of
3082 * the opcode held below in "RH". Doubly nested case would
3083 * result, except that the decoded instruction
3086 FETCH_DECODE_MODRM(mod, rh, rl);
3088 if (DEBUG_DECODE()) {
3089 /* XXX DECODE_PRINTF may be changed to something more
3090 general, so that it is important to leave the strings
3091 in the same format, even though the result is that the
3092 above test is done twice. */
3096 DECODE_PRINTF("ROL\t");
3099 DECODE_PRINTF("ROR\t");
3102 DECODE_PRINTF("RCL\t");
3105 DECODE_PRINTF("RCR\t");
3108 DECODE_PRINTF("SHL\t");
3111 DECODE_PRINTF("SHR\t");
3114 DECODE_PRINTF("SAL\t");
3117 DECODE_PRINTF("SAR\t");
3122 /* know operation, decode the mod byte to find the addressing
3125 DECODE_PRINTF("BYTE PTR ");
3126 destoffset = decode_rmXX_address(mod, rl);
3127 amt = fetch_byte_imm();
3128 DECODE_PRINTF2(",%x\n", amt);
3129 destval = fetch_data_byte(destoffset);
3131 destval = (*opcD0_byte_operation[rh]) (destval, amt);
3132 store_data_byte(destoffset, destval);
3133 } else { /* register to register */
3134 destreg = DECODE_RM_BYTE_REGISTER(rl);
3135 amt = fetch_byte_imm();
3136 DECODE_PRINTF2(",%x\n", amt);
3138 destval = (*opcD0_byte_operation[rh]) (*destreg, amt);
3141 DECODE_CLEAR_SEGOVR();
3145 /****************************************************************************
3148 ****************************************************************************/
3149 void x86emuOp_opcC1_word_RM_MEM(u8 X86EMU_UNUSED(op1))
3156 * Yet another weirdo special case instruction format. Part of
3157 * the opcode held below in "RH". Doubly nested case would
3158 * result, except that the decoded instruction
3161 FETCH_DECODE_MODRM(mod, rh, rl);
3163 if (DEBUG_DECODE()) {
3164 /* XXX DECODE_PRINTF may be changed to something more
3165 general, so that it is important to leave the strings
3166 in the same format, even though the result is that the
3167 above test is done twice. */
3171 DECODE_PRINTF("ROL\t");
3174 DECODE_PRINTF("ROR\t");
3177 DECODE_PRINTF("RCL\t");
3180 DECODE_PRINTF("RCR\t");
3183 DECODE_PRINTF("SHL\t");
3186 DECODE_PRINTF("SHR\t");
3189 DECODE_PRINTF("SAL\t");
3192 DECODE_PRINTF("SAR\t");
3197 /* know operation, decode the mod byte to find the addressing
3200 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3203 DECODE_PRINTF("DWORD PTR ");
3204 destoffset = decode_rmXX_address(mod, rl);
3205 amt = fetch_byte_imm();
3206 DECODE_PRINTF2(",%x\n", amt);
3207 destval = fetch_data_long(destoffset);
3209 destval = (*opcD1_long_operation[rh]) (destval, amt);
3210 store_data_long(destoffset, destval);
3214 DECODE_PRINTF("WORD PTR ");
3215 destoffset = decode_rmXX_address(mod, rl);
3216 amt = fetch_byte_imm();
3217 DECODE_PRINTF2(",%x\n", amt);
3218 destval = fetch_data_word(destoffset);
3220 destval = (*opcD1_word_operation[rh]) (destval, amt);
3221 store_data_word(destoffset, destval);
3223 } else { /* register to register */
3224 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3227 destreg = DECODE_RM_LONG_REGISTER(rl);
3228 amt = fetch_byte_imm();
3229 DECODE_PRINTF2(",%x\n", amt);
3231 *destreg = (*opcD1_long_operation[rh]) (*destreg, amt);
3235 destreg = DECODE_RM_WORD_REGISTER(rl);
3236 amt = fetch_byte_imm();
3237 DECODE_PRINTF2(",%x\n", amt);
3239 *destreg = (*opcD1_word_operation[rh]) (*destreg, amt);
3242 DECODE_CLEAR_SEGOVR();
3246 /****************************************************************************
3249 ****************************************************************************/
3250 void x86emuOp_ret_near_IMM(u8 X86EMU_UNUSED(op1))
3255 DECODE_PRINTF("RET\t");
3256 imm = fetch_word_imm();
3257 DECODE_PRINTF2("%x\n", imm);
3258 RETURN_TRACE("RET",M.x86.saved_cs,M.x86.saved_ip);
3260 M.x86.R_IP = pop_word();
3262 DECODE_CLEAR_SEGOVR();
3266 /****************************************************************************
3269 ****************************************************************************/
3270 void x86emuOp_ret_near(u8 X86EMU_UNUSED(op1))
3273 DECODE_PRINTF("RET\n");
3274 RETURN_TRACE("RET",M.x86.saved_cs,M.x86.saved_ip);
3276 M.x86.R_IP = pop_word();
3277 DECODE_CLEAR_SEGOVR();
3281 /****************************************************************************
3284 ****************************************************************************/
3285 void x86emuOp_les_R_IMM(u8 X86EMU_UNUSED(op1))
3292 DECODE_PRINTF("LES\t");
3293 FETCH_DECODE_MODRM(mod, rh, rl);
3295 dstreg = DECODE_RM_WORD_REGISTER(rh);
3297 srcoffset = decode_rmXX_address(mod, rl);
3298 DECODE_PRINTF("\n");
3300 *dstreg = fetch_data_word(srcoffset);
3301 M.x86.R_ES = fetch_data_word(srcoffset + 2);
3303 /* else UNDEFINED! register to register */
3305 DECODE_CLEAR_SEGOVR();
3309 /****************************************************************************
3312 ****************************************************************************/
3313 void x86emuOp_lds_R_IMM(u8 X86EMU_UNUSED(op1))
3320 DECODE_PRINTF("LDS\t");
3321 FETCH_DECODE_MODRM(mod, rh, rl);
3323 dstreg = DECODE_RM_WORD_REGISTER(rh);
3325 srcoffset = decode_rmXX_address(mod, rl);
3326 DECODE_PRINTF("\n");
3328 *dstreg = fetch_data_word(srcoffset);
3329 M.x86.R_DS = fetch_data_word(srcoffset + 2);
3331 /* else UNDEFINED! */
3332 DECODE_CLEAR_SEGOVR();
3336 /****************************************************************************
3339 ****************************************************************************/
3340 void x86emuOp_mov_byte_RM_IMM(u8 X86EMU_UNUSED(op1))
3348 DECODE_PRINTF("MOV\t");
3349 FETCH_DECODE_MODRM(mod, rh, rl);
3351 DECODE_PRINTF("ILLEGAL DECODE OF OPCODE c6\n");
3355 DECODE_PRINTF("BYTE PTR ");
3356 destoffset = decode_rmXX_address(mod, rl);
3357 imm = fetch_byte_imm();
3358 DECODE_PRINTF2(",%2x\n", imm);
3360 store_data_byte(destoffset, imm);
3361 } else { /* register to register */
3362 destreg = DECODE_RM_BYTE_REGISTER(rl);
3363 imm = fetch_byte_imm();
3364 DECODE_PRINTF2(",%2x\n", imm);
3368 DECODE_CLEAR_SEGOVR();
3372 /****************************************************************************
3375 ****************************************************************************/
3376 void x86emuOp_mov_word_RM_IMM(u8 X86EMU_UNUSED(op1))
3382 DECODE_PRINTF("MOV\t");
3383 FETCH_DECODE_MODRM(mod, rh, rl);
3385 DECODE_PRINTF("ILLEGAL DECODE OF OPCODE 8F\n");
3389 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3392 DECODE_PRINTF("DWORD PTR ");
3393 destoffset = decode_rmXX_address(mod, rl);
3394 imm = fetch_long_imm();
3395 DECODE_PRINTF2(",%x\n", imm);
3397 store_data_long(destoffset, imm);
3401 DECODE_PRINTF("WORD PTR ");
3402 destoffset = decode_rmXX_address(mod, rl);
3403 imm = fetch_word_imm();
3404 DECODE_PRINTF2(",%x\n", imm);
3406 store_data_word(destoffset, imm);
3408 } else { /* register to register */
3409 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3413 destreg = DECODE_RM_LONG_REGISTER(rl);
3414 imm = fetch_long_imm();
3415 DECODE_PRINTF2(",%x\n", imm);
3422 destreg = DECODE_RM_WORD_REGISTER(rl);
3423 imm = fetch_word_imm();
3424 DECODE_PRINTF2(",%x\n", imm);
3429 DECODE_CLEAR_SEGOVR();
3433 /****************************************************************************
3436 ****************************************************************************/
3437 void x86emuOp_enter(u8 X86EMU_UNUSED(op1))
3439 u16 local,frame_pointer;
3444 local = fetch_word_imm();
3445 nesting = fetch_byte_imm();
3446 DECODE_PRINTF2("ENTER %x\n", local);
3447 DECODE_PRINTF2(",%x\n", nesting);
3449 push_word(M.x86.R_BP);
3450 frame_pointer = M.x86.R_SP;
3452 for (i = 1; i < nesting; i++) {
3454 push_word(fetch_data_word_abs(M.x86.R_SS, M.x86.R_BP));
3456 push_word(frame_pointer);
3458 M.x86.R_BP = frame_pointer;
3459 M.x86.R_SP = (u16)(M.x86.R_SP - local);
3460 DECODE_CLEAR_SEGOVR();
3464 /****************************************************************************
3467 ****************************************************************************/
3468 void x86emuOp_leave(u8 X86EMU_UNUSED(op1))
3471 DECODE_PRINTF("LEAVE\n");
3473 M.x86.R_SP = M.x86.R_BP;
3474 M.x86.R_BP = pop_word();
3475 DECODE_CLEAR_SEGOVR();
3479 /****************************************************************************
3482 ****************************************************************************/
3483 void x86emuOp_ret_far_IMM(u8 X86EMU_UNUSED(op1))
3488 DECODE_PRINTF("RETF\t");
3489 imm = fetch_word_imm();
3490 DECODE_PRINTF2("%x\n", imm);
3491 RETURN_TRACE("RETF",M.x86.saved_cs,M.x86.saved_ip);
3493 M.x86.R_IP = pop_word();
3494 M.x86.R_CS = pop_word();
3496 DECODE_CLEAR_SEGOVR();
3500 /****************************************************************************
3503 ****************************************************************************/
3504 void x86emuOp_ret_far(u8 X86EMU_UNUSED(op1))
3507 DECODE_PRINTF("RETF\n");
3508 RETURN_TRACE("RETF",M.x86.saved_cs,M.x86.saved_ip);
3510 M.x86.R_IP = pop_word();
3511 M.x86.R_CS = pop_word();
3512 DECODE_CLEAR_SEGOVR();
3516 /****************************************************************************
3519 ****************************************************************************/
3520 void x86emuOp_int3(u8 X86EMU_UNUSED(op1))
3525 DECODE_PRINTF("INT 3\n");
3526 tmp = (u16) mem_access_word(3 * 4 + 2);
3527 /* access the segment register */
3529 if (_X86EMU_intrTab[3]) {
3530 (*_X86EMU_intrTab[3])(3);
3532 push_word((u16)M.x86.R_FLG);
3535 push_word(M.x86.R_CS);
3536 M.x86.R_CS = mem_access_word(3 * 4 + 2);
3537 push_word(M.x86.R_IP);
3538 M.x86.R_IP = mem_access_word(3 * 4);
3540 DECODE_CLEAR_SEGOVR();
3544 /****************************************************************************
3547 ****************************************************************************/
3548 void x86emuOp_int_IMM(u8 X86EMU_UNUSED(op1))
3554 DECODE_PRINTF("INT\t");
3555 intnum = fetch_byte_imm();
3556 DECODE_PRINTF2("%x\n", intnum);
3557 tmp = mem_access_word(intnum * 4 + 2);
3559 if (_X86EMU_intrTab[intnum]) {
3560 (*_X86EMU_intrTab[intnum])(intnum);
3562 push_word((u16)M.x86.R_FLG);
3565 push_word(M.x86.R_CS);
3566 M.x86.R_CS = mem_access_word(intnum * 4 + 2);
3567 push_word(M.x86.R_IP);
3568 M.x86.R_IP = mem_access_word(intnum * 4);
3570 DECODE_CLEAR_SEGOVR();
3574 /****************************************************************************
3577 ****************************************************************************/
3578 void x86emuOp_into(u8 X86EMU_UNUSED(op1))
3583 DECODE_PRINTF("INTO\n");
3585 if (ACCESS_FLAG(F_OF)) {
3586 tmp = mem_access_word(4 * 4 + 2);
3587 if (_X86EMU_intrTab[4]) {
3588 (*_X86EMU_intrTab[4])(4);
3590 push_word((u16)M.x86.R_FLG);
3593 push_word(M.x86.R_CS);
3594 M.x86.R_CS = mem_access_word(4 * 4 + 2);
3595 push_word(M.x86.R_IP);
3596 M.x86.R_IP = mem_access_word(4 * 4);
3599 DECODE_CLEAR_SEGOVR();
3603 /****************************************************************************
3606 ****************************************************************************/
3607 void x86emuOp_iret(u8 X86EMU_UNUSED(op1))
3610 DECODE_PRINTF("IRET\n");
3614 M.x86.R_IP = pop_word();
3615 M.x86.R_CS = pop_word();
3616 M.x86.R_FLG = pop_word();
3617 DECODE_CLEAR_SEGOVR();
3621 /****************************************************************************
3624 ****************************************************************************/
3625 void x86emuOp_opcD0_byte_RM_1(u8 X86EMU_UNUSED(op1))
3633 * Yet another weirdo special case instruction format. Part of
3634 * the opcode held below in "RH". Doubly nested case would
3635 * result, except that the decoded instruction
3638 FETCH_DECODE_MODRM(mod, rh, rl);
3640 if (DEBUG_DECODE()) {
3641 /* XXX DECODE_PRINTF may be changed to something more
3642 general, so that it is important to leave the strings
3643 in the same format, even though the result is that the
3644 above test is done twice. */
3647 DECODE_PRINTF("ROL\t");
3650 DECODE_PRINTF("ROR\t");
3653 DECODE_PRINTF("RCL\t");
3656 DECODE_PRINTF("RCR\t");
3659 DECODE_PRINTF("SHL\t");
3662 DECODE_PRINTF("SHR\t");
3665 DECODE_PRINTF("SAL\t");
3668 DECODE_PRINTF("SAR\t");
3673 /* know operation, decode the mod byte to find the addressing
3676 DECODE_PRINTF("BYTE PTR ");
3677 destoffset = decode_rmXX_address(mod, rl);
3678 DECODE_PRINTF(",1\n");
3679 destval = fetch_data_byte(destoffset);
3681 destval = (*opcD0_byte_operation[rh]) (destval, 1);
3682 store_data_byte(destoffset, destval);
3683 } else { /* register to register */
3684 destreg = DECODE_RM_BYTE_REGISTER(rl);
3685 DECODE_PRINTF(",1\n");
3687 destval = (*opcD0_byte_operation[rh]) (*destreg, 1);
3690 DECODE_CLEAR_SEGOVR();
3694 /****************************************************************************
3697 ****************************************************************************/
3698 void x86emuOp_opcD1_word_RM_1(u8 X86EMU_UNUSED(op1))
3704 * Yet another weirdo special case instruction format. Part of
3705 * the opcode held below in "RH". Doubly nested case would
3706 * result, except that the decoded instruction
3709 FETCH_DECODE_MODRM(mod, rh, rl);
3711 if (DEBUG_DECODE()) {
3712 /* XXX DECODE_PRINTF may be changed to something more
3713 general, so that it is important to leave the strings
3714 in the same format, even though the result is that the
3715 above test is done twice. */
3718 DECODE_PRINTF("ROL\t");
3721 DECODE_PRINTF("ROR\t");
3724 DECODE_PRINTF("RCL\t");
3727 DECODE_PRINTF("RCR\t");
3730 DECODE_PRINTF("SHL\t");
3733 DECODE_PRINTF("SHR\t");
3736 DECODE_PRINTF("SAL\t");
3739 DECODE_PRINTF("SAR\t");
3744 /* know operation, decode the mod byte to find the addressing
3747 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3750 DECODE_PRINTF("DWORD PTR ");
3751 destoffset = decode_rmXX_address(mod, rl);
3752 DECODE_PRINTF(",1\n");
3753 destval = fetch_data_long(destoffset);
3755 destval = (*opcD1_long_operation[rh]) (destval, 1);
3756 store_data_long(destoffset, destval);
3760 DECODE_PRINTF("WORD PTR ");
3761 destoffset = decode_rmXX_address(mod, rl);
3762 DECODE_PRINTF(",1\n");
3763 destval = fetch_data_word(destoffset);
3765 destval = (*opcD1_word_operation[rh]) (destval, 1);
3766 store_data_word(destoffset, destval);
3768 } else { /* register to register */
3769 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3773 destreg = DECODE_RM_LONG_REGISTER(rl);
3774 DECODE_PRINTF(",1\n");
3776 destval = (*opcD1_long_operation[rh]) (*destreg, 1);
3782 destreg = DECODE_RM_WORD_REGISTER(rl);
3783 DECODE_PRINTF(",1\n");
3785 destval = (*opcD1_word_operation[rh]) (*destreg, 1);
3789 DECODE_CLEAR_SEGOVR();
3793 /****************************************************************************
3796 ****************************************************************************/
3797 void x86emuOp_opcD2_byte_RM_CL(u8 X86EMU_UNUSED(op1))
3806 * Yet another weirdo special case instruction format. Part of
3807 * the opcode held below in "RH". Doubly nested case would
3808 * result, except that the decoded instruction
3811 FETCH_DECODE_MODRM(mod, rh, rl);
3813 if (DEBUG_DECODE()) {
3814 /* XXX DECODE_PRINTF may be changed to something more
3815 general, so that it is important to leave the strings
3816 in the same format, even though the result is that the
3817 above test is done twice. */
3820 DECODE_PRINTF("ROL\t");
3823 DECODE_PRINTF("ROR\t");
3826 DECODE_PRINTF("RCL\t");
3829 DECODE_PRINTF("RCR\t");
3832 DECODE_PRINTF("SHL\t");
3835 DECODE_PRINTF("SHR\t");
3838 DECODE_PRINTF("SAL\t");
3841 DECODE_PRINTF("SAR\t");
3846 /* know operation, decode the mod byte to find the addressing
3850 DECODE_PRINTF("BYTE PTR ");
3851 destoffset = decode_rmXX_address(mod, rl);
3852 DECODE_PRINTF(",CL\n");
3853 destval = fetch_data_byte(destoffset);
3855 destval = (*opcD0_byte_operation[rh]) (destval, amt);
3856 store_data_byte(destoffset, destval);
3857 } else { /* register to register */
3858 destreg = DECODE_RM_BYTE_REGISTER(rl);
3859 DECODE_PRINTF(",CL\n");
3861 destval = (*opcD0_byte_operation[rh]) (*destreg, amt);
3864 DECODE_CLEAR_SEGOVR();
3868 /****************************************************************************
3871 ****************************************************************************/
3872 void x86emuOp_opcD3_word_RM_CL(u8 X86EMU_UNUSED(op1))
3879 * Yet another weirdo special case instruction format. Part of
3880 * the opcode held below in "RH". Doubly nested case would
3881 * result, except that the decoded instruction
3884 FETCH_DECODE_MODRM(mod, rh, rl);
3886 if (DEBUG_DECODE()) {
3887 /* XXX DECODE_PRINTF may be changed to something more
3888 general, so that it is important to leave the strings
3889 in the same format, even though the result is that the
3890 above test is done twice. */
3893 DECODE_PRINTF("ROL\t");
3896 DECODE_PRINTF("ROR\t");
3899 DECODE_PRINTF("RCL\t");
3902 DECODE_PRINTF("RCR\t");
3905 DECODE_PRINTF("SHL\t");
3908 DECODE_PRINTF("SHR\t");
3911 DECODE_PRINTF("SAL\t");
3914 DECODE_PRINTF("SAR\t");
3919 /* know operation, decode the mod byte to find the addressing
3923 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3926 DECODE_PRINTF("DWORD PTR ");
3927 destoffset = decode_rmXX_address(mod, rl);
3928 DECODE_PRINTF(",CL\n");
3929 destval = fetch_data_long(destoffset);
3931 destval = (*opcD1_long_operation[rh]) (destval, amt);
3932 store_data_long(destoffset, destval);
3936 DECODE_PRINTF("WORD PTR ");
3937 destoffset = decode_rmXX_address(mod, rl);
3938 DECODE_PRINTF(",CL\n");
3939 destval = fetch_data_word(destoffset);
3941 destval = (*opcD1_word_operation[rh]) (destval, amt);
3942 store_data_word(destoffset, destval);
3944 } else { /* register to register */
3945 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3948 destreg = DECODE_RM_LONG_REGISTER(rl);
3949 DECODE_PRINTF(",CL\n");
3951 *destreg = (*opcD1_long_operation[rh]) (*destreg, amt);
3955 destreg = DECODE_RM_WORD_REGISTER(rl);
3956 DECODE_PRINTF(",CL\n");
3958 *destreg = (*opcD1_word_operation[rh]) (*destreg, amt);
3961 DECODE_CLEAR_SEGOVR();
3965 /****************************************************************************
3968 ****************************************************************************/
3969 void x86emuOp_aam(u8 X86EMU_UNUSED(op1))
3974 DECODE_PRINTF("AAM\n");
3975 a = fetch_byte_imm(); /* this is a stupid encoding. */
3977 DECODE_PRINTF("ERROR DECODING AAM\n");
3982 /* note the type change here --- returning AL and AH in AX. */
3983 M.x86.R_AX = aam_word(M.x86.R_AL);
3984 DECODE_CLEAR_SEGOVR();
3988 /****************************************************************************
3991 ****************************************************************************/
3992 void x86emuOp_aad(u8 X86EMU_UNUSED(op1))
3997 DECODE_PRINTF("AAD\n");
3998 a = fetch_byte_imm();
4000 M.x86.R_AX = aad_word(M.x86.R_AX);
4001 DECODE_CLEAR_SEGOVR();
4005 /* opcode 0xd6 ILLEGAL OPCODE */
4007 /****************************************************************************
4010 ****************************************************************************/
4011 void x86emuOp_xlat(u8 X86EMU_UNUSED(op1))
4016 DECODE_PRINTF("XLAT\n");
4018 addr = (u16)(M.x86.R_BX + (u8)M.x86.R_AL);
4019 M.x86.R_AL = fetch_data_byte(addr);
4020 DECODE_CLEAR_SEGOVR();
4024 /* instuctions D8 .. DF are in i87_ops.c */
4026 /****************************************************************************
4029 ****************************************************************************/
4030 void x86emuOp_loopne(u8 X86EMU_UNUSED(op1))
4035 DECODE_PRINTF("LOOPNE\t");
4036 ip = (s8) fetch_byte_imm();
4037 ip += (s16) M.x86.R_IP;
4038 DECODE_PRINTF2("%04x\n", ip);
4041 if (M.x86.R_CX != 0 && !ACCESS_FLAG(F_ZF)) /* CX != 0 and !ZF */
4043 DECODE_CLEAR_SEGOVR();
4047 /****************************************************************************
4050 ****************************************************************************/
4051 void x86emuOp_loope(u8 X86EMU_UNUSED(op1))
4056 DECODE_PRINTF("LOOPE\t");
4057 ip = (s8) fetch_byte_imm();
4058 ip += (s16) M.x86.R_IP;
4059 DECODE_PRINTF2("%04x\n", ip);
4062 if (M.x86.R_CX != 0 && ACCESS_FLAG(F_ZF)) /* CX != 0 and ZF */
4064 DECODE_CLEAR_SEGOVR();
4068 /****************************************************************************
4071 ****************************************************************************/
4072 void x86emuOp_loop(u8 X86EMU_UNUSED(op1))
4077 DECODE_PRINTF("LOOP\t");
4078 ip = (s8) fetch_byte_imm();
4079 ip += (s16) M.x86.R_IP;
4080 DECODE_PRINTF2("%04x\n", ip);
4083 if (M.x86.R_CX != 0)
4085 DECODE_CLEAR_SEGOVR();
4089 /****************************************************************************
4092 ****************************************************************************/
4093 void x86emuOp_jcxz(u8 X86EMU_UNUSED(op1))
4098 /* jump to byte offset if overflow flag is set */
4100 DECODE_PRINTF("JCXZ\t");
4101 offset = (s8)fetch_byte_imm();
4102 target = (u16)(M.x86.R_IP + offset);
4103 DECODE_PRINTF2("%x\n", target);
4105 if (M.x86.R_CX == 0)
4106 M.x86.R_IP = target;
4107 DECODE_CLEAR_SEGOVR();
4111 /****************************************************************************
4114 ****************************************************************************/
4115 void x86emuOp_in_byte_AL_IMM(u8 X86EMU_UNUSED(op1))
4120 DECODE_PRINTF("IN\t");
4121 port = (u8) fetch_byte_imm();
4122 DECODE_PRINTF2("%x,AL\n", port);
4124 M.x86.R_AL = (*sys_inb)(port);
4125 DECODE_CLEAR_SEGOVR();
4129 /****************************************************************************
4132 ****************************************************************************/
4133 void x86emuOp_in_word_AX_IMM(u8 X86EMU_UNUSED(op1))
4138 DECODE_PRINTF("IN\t");
4139 port = (u8) fetch_byte_imm();
4140 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4141 DECODE_PRINTF2("EAX,%x\n", port);
4143 DECODE_PRINTF2("AX,%x\n", port);
4146 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4147 M.x86.R_EAX = (*sys_inl)(port);
4149 M.x86.R_AX = (*sys_inw)(port);
4151 DECODE_CLEAR_SEGOVR();
4155 /****************************************************************************
4158 ****************************************************************************/
4159 void x86emuOp_out_byte_IMM_AL(u8 X86EMU_UNUSED(op1))
4164 DECODE_PRINTF("OUT\t");
4165 port = (u8) fetch_byte_imm();
4166 DECODE_PRINTF2("%x,AL\n", port);
4168 (*sys_outb)(port, M.x86.R_AL);
4169 DECODE_CLEAR_SEGOVR();
4173 /****************************************************************************
4176 ****************************************************************************/
4177 void x86emuOp_out_word_IMM_AX(u8 X86EMU_UNUSED(op1))
4182 DECODE_PRINTF("OUT\t");
4183 port = (u8) fetch_byte_imm();
4184 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4185 DECODE_PRINTF2("%x,EAX\n", port);
4187 DECODE_PRINTF2("%x,AX\n", port);
4190 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4191 (*sys_outl)(port, M.x86.R_EAX);
4193 (*sys_outw)(port, M.x86.R_AX);
4195 DECODE_CLEAR_SEGOVR();
4199 /****************************************************************************
4202 ****************************************************************************/
4203 void x86emuOp_call_near_IMM(u8 X86EMU_UNUSED(op1))
4208 DECODE_PRINTF("CALL\t");
4209 ip = (s16) fetch_word_imm();
4210 ip += (s16) M.x86.R_IP; /* CHECK SIGN */
4211 DECODE_PRINTF2("%04x\n", ip);
4212 CALL_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, ip, "");
4214 push_word(M.x86.R_IP);
4216 DECODE_CLEAR_SEGOVR();
4220 /****************************************************************************
4223 ****************************************************************************/
4224 void x86emuOp_jump_near_IMM(u8 X86EMU_UNUSED(op1))
4229 DECODE_PRINTF("JMP\t");
4230 ip = (s16)fetch_word_imm();
4231 ip += (s16)M.x86.R_IP;
4232 DECODE_PRINTF2("%04x\n", ip);
4234 M.x86.R_IP = (u16)ip;
4235 DECODE_CLEAR_SEGOVR();
4239 /****************************************************************************
4242 ****************************************************************************/
4243 void x86emuOp_jump_far_IMM(u8 X86EMU_UNUSED(op1))
4248 DECODE_PRINTF("JMP\tFAR ");
4249 ip = fetch_word_imm();
4250 cs = fetch_word_imm();
4251 DECODE_PRINTF2("%04x:", cs);
4252 DECODE_PRINTF2("%04x\n", ip);
4256 DECODE_CLEAR_SEGOVR();
4260 /****************************************************************************
4263 ****************************************************************************/
4264 void x86emuOp_jump_byte_IMM(u8 X86EMU_UNUSED(op1))
4270 DECODE_PRINTF("JMP\t");
4271 offset = (s8)fetch_byte_imm();
4272 target = (u16)(M.x86.R_IP + offset);
4273 DECODE_PRINTF2("%x\n", target);
4275 M.x86.R_IP = target;
4276 DECODE_CLEAR_SEGOVR();
4280 /****************************************************************************
4283 ****************************************************************************/
4284 void x86emuOp_in_byte_AL_DX(u8 X86EMU_UNUSED(op1))
4287 DECODE_PRINTF("IN\tAL,DX\n");
4289 M.x86.R_AL = (*sys_inb)(M.x86.R_DX);
4290 DECODE_CLEAR_SEGOVR();
4294 /****************************************************************************
4297 ****************************************************************************/
4298 void x86emuOp_in_word_AX_DX(u8 X86EMU_UNUSED(op1))
4301 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4302 DECODE_PRINTF("IN\tEAX,DX\n");
4304 DECODE_PRINTF("IN\tAX,DX\n");
4307 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4308 M.x86.R_EAX = (*sys_inl)(M.x86.R_DX);
4310 M.x86.R_AX = (*sys_inw)(M.x86.R_DX);
4312 DECODE_CLEAR_SEGOVR();
4316 /****************************************************************************
4319 ****************************************************************************/
4320 void x86emuOp_out_byte_DX_AL(u8 X86EMU_UNUSED(op1))
4323 DECODE_PRINTF("OUT\tDX,AL\n");
4325 (*sys_outb)(M.x86.R_DX, M.x86.R_AL);
4326 DECODE_CLEAR_SEGOVR();
4330 /****************************************************************************
4333 ****************************************************************************/
4334 void x86emuOp_out_word_DX_AX(u8 X86EMU_UNUSED(op1))
4337 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4338 DECODE_PRINTF("OUT\tDX,EAX\n");
4340 DECODE_PRINTF("OUT\tDX,AX\n");
4343 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4344 (*sys_outl)(M.x86.R_DX, M.x86.R_EAX);
4346 (*sys_outw)(M.x86.R_DX, M.x86.R_AX);
4348 DECODE_CLEAR_SEGOVR();
4352 /****************************************************************************
4355 ****************************************************************************/
4356 void x86emuOp_lock(u8 X86EMU_UNUSED(op1))
4359 DECODE_PRINTF("LOCK:\n");
4361 DECODE_CLEAR_SEGOVR();
4365 /*opcode 0xf1 ILLEGAL OPERATION */
4367 /****************************************************************************
4370 ****************************************************************************/
4371 void x86emuOp_repne(u8 X86EMU_UNUSED(op1))
4374 DECODE_PRINTF("REPNE\n");
4376 M.x86.mode |= SYSMODE_PREFIX_REPNE;
4377 DECODE_CLEAR_SEGOVR();
4381 /****************************************************************************
4384 ****************************************************************************/
4385 void x86emuOp_repe(u8 X86EMU_UNUSED(op1))
4388 DECODE_PRINTF("REPE\n");
4390 M.x86.mode |= SYSMODE_PREFIX_REPE;
4391 DECODE_CLEAR_SEGOVR();
4395 /****************************************************************************
4398 ****************************************************************************/
4399 void x86emuOp_halt(u8 X86EMU_UNUSED(op1))
4402 DECODE_PRINTF("HALT\n");
4405 DECODE_CLEAR_SEGOVR();
4409 /****************************************************************************
4412 ****************************************************************************/
4413 void x86emuOp_cmc(u8 X86EMU_UNUSED(op1))
4415 /* complement the carry flag. */
4417 DECODE_PRINTF("CMC\n");
4420 DECODE_CLEAR_SEGOVR();
4424 /****************************************************************************
4427 ****************************************************************************/
4428 void x86emuOp_opcF6_byte_RM(u8 X86EMU_UNUSED(op1))
4435 /* long, drawn out code follows. Double switch for a total
4438 FETCH_DECODE_MODRM(mod, rh, rl);
4439 DECODE_PRINTF(opF6_names[rh]);
4441 DECODE_PRINTF("BYTE PTR ");
4442 destoffset = decode_rmXX_address(mod, rl);
4443 destval = fetch_data_byte(destoffset);
4446 case 0: /* test byte imm */
4448 srcval = fetch_byte_imm();
4449 DECODE_PRINTF2("%02x\n", srcval);
4451 test_byte(destval, srcval);
4454 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4458 DECODE_PRINTF("\n");
4460 destval = not_byte(destval);
4461 store_data_byte(destoffset, destval);
4464 DECODE_PRINTF("\n");
4466 destval = neg_byte(destval);
4467 store_data_byte(destoffset, destval);
4470 DECODE_PRINTF("\n");
4475 DECODE_PRINTF("\n");
4480 DECODE_PRINTF("\n");
4485 DECODE_PRINTF("\n");
4490 } else { /* mod=11 */
4491 destreg = DECODE_RM_BYTE_REGISTER(rl);
4493 case 0: /* test byte imm */
4495 srcval = fetch_byte_imm();
4496 DECODE_PRINTF2("%02x\n", srcval);
4498 test_byte(*destreg, srcval);
4501 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4505 DECODE_PRINTF("\n");
4507 *destreg = not_byte(*destreg);
4510 DECODE_PRINTF("\n");
4512 *destreg = neg_byte(*destreg);
4515 DECODE_PRINTF("\n");
4517 mul_byte(*destreg); /*!!! */
4520 DECODE_PRINTF("\n");
4522 imul_byte(*destreg);
4525 DECODE_PRINTF("\n");
4530 DECODE_PRINTF("\n");
4532 idiv_byte(*destreg);
4536 DECODE_CLEAR_SEGOVR();
4540 /****************************************************************************
4543 ****************************************************************************/
4544 void x86emuOp_opcF7_word_RM(u8 X86EMU_UNUSED(op1))
4550 FETCH_DECODE_MODRM(mod, rh, rl);
4551 DECODE_PRINTF(opF6_names[rh]);
4554 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4555 u32 destval, srcval;
4557 DECODE_PRINTF("DWORD PTR ");
4558 destoffset = decode_rmXX_address(mod, rl);
4559 destval = fetch_data_long(destoffset);
4564 srcval = fetch_long_imm();
4565 DECODE_PRINTF2("%x\n", srcval);
4567 test_long(destval, srcval);
4570 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F7\n");
4574 DECODE_PRINTF("\n");
4576 destval = not_long(destval);
4577 store_data_long(destoffset, destval);
4580 DECODE_PRINTF("\n");
4582 destval = neg_long(destval);
4583 store_data_long(destoffset, destval);
4586 DECODE_PRINTF("\n");
4591 DECODE_PRINTF("\n");
4596 DECODE_PRINTF("\n");
4601 DECODE_PRINTF("\n");
4607 u16 destval, srcval;
4609 DECODE_PRINTF("WORD PTR ");
4610 destoffset = decode_rmXX_address(mod, rl);
4611 destval = fetch_data_word(destoffset);
4614 case 0: /* test word imm */
4616 srcval = fetch_word_imm();
4617 DECODE_PRINTF2("%x\n", srcval);
4619 test_word(destval, srcval);
4622 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F7\n");
4626 DECODE_PRINTF("\n");
4628 destval = not_word(destval);
4629 store_data_word(destoffset, destval);
4632 DECODE_PRINTF("\n");
4634 destval = neg_word(destval);
4635 store_data_word(destoffset, destval);
4638 DECODE_PRINTF("\n");
4643 DECODE_PRINTF("\n");
4648 DECODE_PRINTF("\n");
4653 DECODE_PRINTF("\n");
4660 } else { /* mod=11 */
4662 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4666 destreg = DECODE_RM_LONG_REGISTER(rl);
4669 case 0: /* test word imm */
4671 srcval = fetch_long_imm();
4672 DECODE_PRINTF2("%x\n", srcval);
4674 test_long(*destreg, srcval);
4677 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4681 DECODE_PRINTF("\n");
4683 *destreg = not_long(*destreg);
4686 DECODE_PRINTF("\n");
4688 *destreg = neg_long(*destreg);
4691 DECODE_PRINTF("\n");
4693 mul_long(*destreg); /*!!! */
4696 DECODE_PRINTF("\n");
4698 imul_long(*destreg);
4701 DECODE_PRINTF("\n");
4706 DECODE_PRINTF("\n");
4708 idiv_long(*destreg);
4715 destreg = DECODE_RM_WORD_REGISTER(rl);
4718 case 0: /* test word imm */
4720 srcval = fetch_word_imm();
4721 DECODE_PRINTF2("%x\n", srcval);
4723 test_word(*destreg, srcval);
4726 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4730 DECODE_PRINTF("\n");
4732 *destreg = not_word(*destreg);
4735 DECODE_PRINTF("\n");
4737 *destreg = neg_word(*destreg);
4740 DECODE_PRINTF("\n");
4742 mul_word(*destreg); /*!!! */
4745 DECODE_PRINTF("\n");
4747 imul_word(*destreg);
4750 DECODE_PRINTF("\n");
4755 DECODE_PRINTF("\n");
4757 idiv_word(*destreg);
4762 DECODE_CLEAR_SEGOVR();
4766 /****************************************************************************
4769 ****************************************************************************/
4770 void x86emuOp_clc(u8 X86EMU_UNUSED(op1))
4772 /* clear the carry flag. */
4774 DECODE_PRINTF("CLC\n");
4777 DECODE_CLEAR_SEGOVR();
4781 /****************************************************************************
4784 ****************************************************************************/
4785 void x86emuOp_stc(u8 X86EMU_UNUSED(op1))
4787 /* set the carry flag. */
4789 DECODE_PRINTF("STC\n");
4792 DECODE_CLEAR_SEGOVR();
4796 /****************************************************************************
4799 ****************************************************************************/
4800 void x86emuOp_cli(u8 X86EMU_UNUSED(op1))
4802 /* clear interrupts. */
4804 DECODE_PRINTF("CLI\n");
4807 DECODE_CLEAR_SEGOVR();
4811 /****************************************************************************
4814 ****************************************************************************/
4815 void x86emuOp_sti(u8 X86EMU_UNUSED(op1))
4817 /* enable interrupts. */
4819 DECODE_PRINTF("STI\n");
4822 DECODE_CLEAR_SEGOVR();
4826 /****************************************************************************
4829 ****************************************************************************/
4830 void x86emuOp_cld(u8 X86EMU_UNUSED(op1))
4832 /* clear interrupts. */
4834 DECODE_PRINTF("CLD\n");
4837 DECODE_CLEAR_SEGOVR();
4841 /****************************************************************************
4844 ****************************************************************************/
4845 void x86emuOp_std(u8 X86EMU_UNUSED(op1))
4847 /* clear interrupts. */
4849 DECODE_PRINTF("STD\n");
4852 DECODE_CLEAR_SEGOVR();
4856 /****************************************************************************
4859 ****************************************************************************/
4860 void x86emuOp_opcFE_byte_RM(u8 X86EMU_UNUSED(op1))
4867 /* Yet another special case instruction. */
4869 FETCH_DECODE_MODRM(mod, rh, rl);
4871 if (DEBUG_DECODE()) {
4872 /* XXX DECODE_PRINTF may be changed to something more
4873 general, so that it is important to leave the strings
4874 in the same format, even though the result is that the
4875 above test is done twice. */
4879 DECODE_PRINTF("INC\t");
4882 DECODE_PRINTF("DEC\t");
4890 DECODE_PRINTF2("ILLEGAL OP MAJOR OP 0xFE MINOR OP %x \n", mod);
4897 DECODE_PRINTF("BYTE PTR ");
4898 destoffset = decode_rmXX_address(mod, rl);
4899 DECODE_PRINTF("\n");
4900 destval = fetch_data_byte(destoffset);
4903 destval = inc_byte(destval);
4905 destval = dec_byte(destval);
4906 store_data_byte(destoffset, destval);
4908 destreg = DECODE_RM_BYTE_REGISTER(rl);
4909 DECODE_PRINTF("\n");
4912 *destreg = inc_byte(*destreg);
4914 *destreg = dec_byte(*destreg);
4916 DECODE_CLEAR_SEGOVR();
4920 /****************************************************************************
4923 ****************************************************************************/
4924 void x86emuOp_opcFF_word_RM(u8 X86EMU_UNUSED(op1))
4927 uint destoffset = 0;
4929 u16 destval,destval2;
4931 /* Yet another special case instruction. */
4933 FETCH_DECODE_MODRM(mod, rh, rl);
4935 if (DEBUG_DECODE()) {
4936 /* XXX DECODE_PRINTF may be changed to something more
4937 general, so that it is important to leave the strings
4938 in the same format, even though the result is that the
4939 above test is done twice. */
4943 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4944 DECODE_PRINTF("INC\tDWORD PTR ");
4946 DECODE_PRINTF("INC\tWORD PTR ");
4950 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4951 DECODE_PRINTF("DEC\tDWORD PTR ");
4953 DECODE_PRINTF("DEC\tWORD PTR ");
4957 DECODE_PRINTF("CALL\t ");
4960 DECODE_PRINTF("CALL\tFAR ");
4963 DECODE_PRINTF("JMP\t");
4966 DECODE_PRINTF("JMP\tFAR ");
4969 DECODE_PRINTF("PUSH\t");
4972 DECODE_PRINTF("ILLEGAL DECODING OF OPCODE FF\t");
4979 destoffset = decode_rmXX_address(mod, rl);
4980 DECODE_PRINTF("\n");
4982 case 0: /* inc word ptr ... */
4983 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4986 destval = fetch_data_long(destoffset);
4988 destval = inc_long(destval);
4989 store_data_long(destoffset, destval);
4993 destval = fetch_data_word(destoffset);
4995 destval = inc_word(destval);
4996 store_data_word(destoffset, destval);
4999 case 1: /* dec word ptr ... */
5000 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5003 destval = fetch_data_long(destoffset);
5005 destval = dec_long(destval);
5006 store_data_long(destoffset, destval);
5010 destval = fetch_data_word(destoffset);
5012 destval = dec_word(destval);
5013 store_data_word(destoffset, destval);
5016 case 2: /* call word ptr ... */
5017 destval = fetch_data_word(destoffset);
5019 push_word(M.x86.R_IP);
5020 M.x86.R_IP = destval;
5022 case 3: /* call far ptr ... */
5023 destval = fetch_data_word(destoffset);
5024 destval2 = fetch_data_word(destoffset + 2);
5026 push_word(M.x86.R_CS);
5027 M.x86.R_CS = destval2;
5028 push_word(M.x86.R_IP);
5029 M.x86.R_IP = destval;
5031 case 4: /* jmp word ptr ... */
5032 destval = fetch_data_word(destoffset);
5034 M.x86.R_IP = destval;
5036 case 5: /* jmp far ptr ... */
5037 destval = fetch_data_word(destoffset);
5038 destval2 = fetch_data_word(destoffset + 2);
5040 M.x86.R_IP = destval;
5041 M.x86.R_CS = destval2;
5043 case 6: /* push word ptr ... */
5044 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5047 destval = fetch_data_long(destoffset);
5053 destval = fetch_data_word(destoffset);
5062 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5065 destreg = DECODE_RM_LONG_REGISTER(rl);
5066 DECODE_PRINTF("\n");
5068 *destreg = inc_long(*destreg);
5072 destreg = DECODE_RM_WORD_REGISTER(rl);
5073 DECODE_PRINTF("\n");
5075 *destreg = inc_word(*destreg);
5079 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5082 destreg = DECODE_RM_LONG_REGISTER(rl);
5083 DECODE_PRINTF("\n");
5085 *destreg = dec_long(*destreg);
5089 destreg = DECODE_RM_WORD_REGISTER(rl);
5090 DECODE_PRINTF("\n");
5092 *destreg = dec_word(*destreg);
5095 case 2: /* call word ptr ... */
5096 destreg = DECODE_RM_WORD_REGISTER(rl);
5097 DECODE_PRINTF("\n");
5099 push_word(M.x86.R_IP);
5100 M.x86.R_IP = *destreg;
5102 case 3: /* jmp far ptr ... */
5103 DECODE_PRINTF("OPERATION UNDEFINED 0XFF \n");
5108 case 4: /* jmp ... */
5109 destreg = DECODE_RM_WORD_REGISTER(rl);
5110 DECODE_PRINTF("\n");
5112 M.x86.R_IP = (u16) (*destreg);
5114 case 5: /* jmp far ptr ... */
5115 DECODE_PRINTF("OPERATION UNDEFINED 0XFF \n");
5120 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5123 destreg = DECODE_RM_LONG_REGISTER(rl);
5124 DECODE_PRINTF("\n");
5126 push_long(*destreg);
5130 destreg = DECODE_RM_WORD_REGISTER(rl);
5131 DECODE_PRINTF("\n");
5133 push_word(*destreg);
5138 DECODE_CLEAR_SEGOVR();
5142 /***************************************************************************
5143 * Single byte operation code table:
5144 **************************************************************************/
5145 void (*x86emu_optab[256])(u8) __attribute__ ((section(".got2"))) =
5147 /* 0x00 */ x86emuOp_genop_byte_RM_R,
5148 /* 0x01 */ x86emuOp_genop_word_RM_R,
5149 /* 0x02 */ x86emuOp_genop_byte_R_RM,
5150 /* 0x03 */ x86emuOp_genop_word_R_RM,
5151 /* 0x04 */ x86emuOp_genop_byte_AL_IMM,
5152 /* 0x05 */ x86emuOp_genop_word_AX_IMM,
5153 /* 0x06 */ x86emuOp_push_ES,
5154 /* 0x07 */ x86emuOp_pop_ES,
5156 /* 0x08 */ x86emuOp_genop_byte_RM_R,
5157 /* 0x09 */ x86emuOp_genop_word_RM_R,
5158 /* 0x0a */ x86emuOp_genop_byte_R_RM,
5159 /* 0x0b */ x86emuOp_genop_word_R_RM,
5160 /* 0x0c */ x86emuOp_genop_byte_AL_IMM,
5161 /* 0x0d */ x86emuOp_genop_word_AX_IMM,
5162 /* 0x0e */ x86emuOp_push_CS,
5163 /* 0x0f */ x86emuOp_two_byte,
5165 /* 0x10 */ x86emuOp_genop_byte_RM_R,
5166 /* 0x11 */ x86emuOp_genop_word_RM_R,
5167 /* 0x12 */ x86emuOp_genop_byte_R_RM,
5168 /* 0x13 */ x86emuOp_genop_word_R_RM,
5169 /* 0x14 */ x86emuOp_genop_byte_AL_IMM,
5170 /* 0x15 */ x86emuOp_genop_word_AX_IMM,
5171 /* 0x16 */ x86emuOp_push_SS,
5172 /* 0x17 */ x86emuOp_pop_SS,
5174 /* 0x18 */ x86emuOp_genop_byte_RM_R,
5175 /* 0x19 */ x86emuOp_genop_word_RM_R,
5176 /* 0x1a */ x86emuOp_genop_byte_R_RM,
5177 /* 0x1b */ x86emuOp_genop_word_R_RM,
5178 /* 0x1c */ x86emuOp_genop_byte_AL_IMM,
5179 /* 0x1d */ x86emuOp_genop_word_AX_IMM,
5180 /* 0x1e */ x86emuOp_push_DS,
5181 /* 0x1f */ x86emuOp_pop_DS,
5183 /* 0x20 */ x86emuOp_genop_byte_RM_R,
5184 /* 0x21 */ x86emuOp_genop_word_RM_R,
5185 /* 0x22 */ x86emuOp_genop_byte_R_RM,
5186 /* 0x23 */ x86emuOp_genop_word_R_RM,
5187 /* 0x24 */ x86emuOp_genop_byte_AL_IMM,
5188 /* 0x25 */ x86emuOp_genop_word_AX_IMM,
5189 /* 0x26 */ x86emuOp_segovr_ES,
5190 /* 0x27 */ x86emuOp_daa,
5192 /* 0x28 */ x86emuOp_genop_byte_RM_R,
5193 /* 0x29 */ x86emuOp_genop_word_RM_R,
5194 /* 0x2a */ x86emuOp_genop_byte_R_RM,
5195 /* 0x2b */ x86emuOp_genop_word_R_RM,
5196 /* 0x2c */ x86emuOp_genop_byte_AL_IMM,
5197 /* 0x2d */ x86emuOp_genop_word_AX_IMM,
5198 /* 0x2e */ x86emuOp_segovr_CS,
5199 /* 0x2f */ x86emuOp_das,
5201 /* 0x30 */ x86emuOp_genop_byte_RM_R,
5202 /* 0x31 */ x86emuOp_genop_word_RM_R,
5203 /* 0x32 */ x86emuOp_genop_byte_R_RM,
5204 /* 0x33 */ x86emuOp_genop_word_R_RM,
5205 /* 0x34 */ x86emuOp_genop_byte_AL_IMM,
5206 /* 0x35 */ x86emuOp_genop_word_AX_IMM,
5207 /* 0x36 */ x86emuOp_segovr_SS,
5208 /* 0x37 */ x86emuOp_aaa,
5210 /* 0x38 */ x86emuOp_genop_byte_RM_R,
5211 /* 0x39 */ x86emuOp_genop_word_RM_R,
5212 /* 0x3a */ x86emuOp_genop_byte_R_RM,
5213 /* 0x3b */ x86emuOp_genop_word_R_RM,
5214 /* 0x3c */ x86emuOp_genop_byte_AL_IMM,
5215 /* 0x3d */ x86emuOp_genop_word_AX_IMM,
5216 /* 0x3e */ x86emuOp_segovr_DS,
5217 /* 0x3f */ x86emuOp_aas,
5219 /* 0x40 */ x86emuOp_inc_register,
5220 /* 0x41 */ x86emuOp_inc_register,
5221 /* 0x42 */ x86emuOp_inc_register,
5222 /* 0x43 */ x86emuOp_inc_register,
5223 /* 0x44 */ x86emuOp_inc_register,
5224 /* 0x45 */ x86emuOp_inc_register,
5225 /* 0x46 */ x86emuOp_inc_register,
5226 /* 0x47 */ x86emuOp_inc_register,
5228 /* 0x48 */ x86emuOp_dec_register,
5229 /* 0x49 */ x86emuOp_dec_register,
5230 /* 0x4a */ x86emuOp_dec_register,
5231 /* 0x4b */ x86emuOp_dec_register,
5232 /* 0x4c */ x86emuOp_dec_register,
5233 /* 0x4d */ x86emuOp_dec_register,
5234 /* 0x4e */ x86emuOp_dec_register,
5235 /* 0x4f */ x86emuOp_dec_register,
5237 /* 0x50 */ x86emuOp_push_register,
5238 /* 0x51 */ x86emuOp_push_register,
5239 /* 0x52 */ x86emuOp_push_register,
5240 /* 0x53 */ x86emuOp_push_register,
5241 /* 0x54 */ x86emuOp_push_register,
5242 /* 0x55 */ x86emuOp_push_register,
5243 /* 0x56 */ x86emuOp_push_register,
5244 /* 0x57 */ x86emuOp_push_register,
5246 /* 0x58 */ x86emuOp_pop_register,
5247 /* 0x59 */ x86emuOp_pop_register,
5248 /* 0x5a */ x86emuOp_pop_register,
5249 /* 0x5b */ x86emuOp_pop_register,
5250 /* 0x5c */ x86emuOp_pop_register,
5251 /* 0x5d */ x86emuOp_pop_register,
5252 /* 0x5e */ x86emuOp_pop_register,
5253 /* 0x5f */ x86emuOp_pop_register,
5255 /* 0x60 */ x86emuOp_push_all,
5256 /* 0x61 */ x86emuOp_pop_all,
5257 /* 0x62 */ x86emuOp_illegal_op, /* bound */
5258 /* 0x63 */ x86emuOp_illegal_op, /* arpl */
5259 /* 0x64 */ x86emuOp_segovr_FS,
5260 /* 0x65 */ x86emuOp_segovr_GS,
5261 /* 0x66 */ x86emuOp_prefix_data,
5262 /* 0x67 */ x86emuOp_prefix_addr,
5264 /* 0x68 */ x86emuOp_push_word_IMM,
5265 /* 0x69 */ x86emuOp_imul_word_IMM,
5266 /* 0x6a */ x86emuOp_push_byte_IMM,
5267 /* 0x6b */ x86emuOp_imul_byte_IMM,
5268 /* 0x6c */ x86emuOp_ins_byte,
5269 /* 0x6d */ x86emuOp_ins_word,
5270 /* 0x6e */ x86emuOp_outs_byte,
5271 /* 0x6f */ x86emuOp_outs_word,
5273 /* 0x70 */ x86emuOp_jump_near_cond,
5274 /* 0x71 */ x86emuOp_jump_near_cond,
5275 /* 0x72 */ x86emuOp_jump_near_cond,
5276 /* 0x73 */ x86emuOp_jump_near_cond,
5277 /* 0x74 */ x86emuOp_jump_near_cond,
5278 /* 0x75 */ x86emuOp_jump_near_cond,
5279 /* 0x76 */ x86emuOp_jump_near_cond,
5280 /* 0x77 */ x86emuOp_jump_near_cond,
5282 /* 0x78 */ x86emuOp_jump_near_cond,
5283 /* 0x79 */ x86emuOp_jump_near_cond,
5284 /* 0x7a */ x86emuOp_jump_near_cond,
5285 /* 0x7b */ x86emuOp_jump_near_cond,
5286 /* 0x7c */ x86emuOp_jump_near_cond,
5287 /* 0x7d */ x86emuOp_jump_near_cond,
5288 /* 0x7e */ x86emuOp_jump_near_cond,
5289 /* 0x7f */ x86emuOp_jump_near_cond,
5291 /* 0x80 */ x86emuOp_opc80_byte_RM_IMM,
5292 /* 0x81 */ x86emuOp_opc81_word_RM_IMM,
5293 /* 0x82 */ x86emuOp_opc82_byte_RM_IMM,
5294 /* 0x83 */ x86emuOp_opc83_word_RM_IMM,
5295 /* 0x84 */ x86emuOp_test_byte_RM_R,
5296 /* 0x85 */ x86emuOp_test_word_RM_R,
5297 /* 0x86 */ x86emuOp_xchg_byte_RM_R,
5298 /* 0x87 */ x86emuOp_xchg_word_RM_R,
5300 /* 0x88 */ x86emuOp_mov_byte_RM_R,
5301 /* 0x89 */ x86emuOp_mov_word_RM_R,
5302 /* 0x8a */ x86emuOp_mov_byte_R_RM,
5303 /* 0x8b */ x86emuOp_mov_word_R_RM,
5304 /* 0x8c */ x86emuOp_mov_word_RM_SR,
5305 /* 0x8d */ x86emuOp_lea_word_R_M,
5306 /* 0x8e */ x86emuOp_mov_word_SR_RM,
5307 /* 0x8f */ x86emuOp_pop_RM,
5309 /* 0x90 */ x86emuOp_nop,
5310 /* 0x91 */ x86emuOp_xchg_word_AX_register,
5311 /* 0x92 */ x86emuOp_xchg_word_AX_register,
5312 /* 0x93 */ x86emuOp_xchg_word_AX_register,
5313 /* 0x94 */ x86emuOp_xchg_word_AX_register,
5314 /* 0x95 */ x86emuOp_xchg_word_AX_register,
5315 /* 0x96 */ x86emuOp_xchg_word_AX_register,
5316 /* 0x97 */ x86emuOp_xchg_word_AX_register,
5318 /* 0x98 */ x86emuOp_cbw,
5319 /* 0x99 */ x86emuOp_cwd,
5320 /* 0x9a */ x86emuOp_call_far_IMM,
5321 /* 0x9b */ x86emuOp_wait,
5322 /* 0x9c */ x86emuOp_pushf_word,
5323 /* 0x9d */ x86emuOp_popf_word,
5324 /* 0x9e */ x86emuOp_sahf,
5325 /* 0x9f */ x86emuOp_lahf,
5327 /* 0xa0 */ x86emuOp_mov_AL_M_IMM,
5328 /* 0xa1 */ x86emuOp_mov_AX_M_IMM,
5329 /* 0xa2 */ x86emuOp_mov_M_AL_IMM,
5330 /* 0xa3 */ x86emuOp_mov_M_AX_IMM,
5331 /* 0xa4 */ x86emuOp_movs_byte,
5332 /* 0xa5 */ x86emuOp_movs_word,
5333 /* 0xa6 */ x86emuOp_cmps_byte,
5334 /* 0xa7 */ x86emuOp_cmps_word,
5335 /* 0xa8 */ x86emuOp_test_AL_IMM,
5336 /* 0xa9 */ x86emuOp_test_AX_IMM,
5337 /* 0xaa */ x86emuOp_stos_byte,
5338 /* 0xab */ x86emuOp_stos_word,
5339 /* 0xac */ x86emuOp_lods_byte,
5340 /* 0xad */ x86emuOp_lods_word,
5341 /* 0xac */ x86emuOp_scas_byte,
5342 /* 0xad */ x86emuOp_scas_word,
5344 /* 0xb0 */ x86emuOp_mov_byte_register_IMM,
5345 /* 0xb1 */ x86emuOp_mov_byte_register_IMM,
5346 /* 0xb2 */ x86emuOp_mov_byte_register_IMM,
5347 /* 0xb3 */ x86emuOp_mov_byte_register_IMM,
5348 /* 0xb4 */ x86emuOp_mov_byte_register_IMM,
5349 /* 0xb5 */ x86emuOp_mov_byte_register_IMM,
5350 /* 0xb6 */ x86emuOp_mov_byte_register_IMM,
5351 /* 0xb7 */ x86emuOp_mov_byte_register_IMM,
5353 /* 0xb8 */ x86emuOp_mov_word_register_IMM,
5354 /* 0xb9 */ x86emuOp_mov_word_register_IMM,
5355 /* 0xba */ x86emuOp_mov_word_register_IMM,
5356 /* 0xbb */ x86emuOp_mov_word_register_IMM,
5357 /* 0xbc */ x86emuOp_mov_word_register_IMM,
5358 /* 0xbd */ x86emuOp_mov_word_register_IMM,
5359 /* 0xbe */ x86emuOp_mov_word_register_IMM,
5360 /* 0xbf */ x86emuOp_mov_word_register_IMM,
5362 /* 0xc0 */ x86emuOp_opcC0_byte_RM_MEM,
5363 /* 0xc1 */ x86emuOp_opcC1_word_RM_MEM,
5364 /* 0xc2 */ x86emuOp_ret_near_IMM,
5365 /* 0xc3 */ x86emuOp_ret_near,
5366 /* 0xc4 */ x86emuOp_les_R_IMM,
5367 /* 0xc5 */ x86emuOp_lds_R_IMM,
5368 /* 0xc6 */ x86emuOp_mov_byte_RM_IMM,
5369 /* 0xc7 */ x86emuOp_mov_word_RM_IMM,
5370 /* 0xc8 */ x86emuOp_enter,
5371 /* 0xc9 */ x86emuOp_leave,
5372 /* 0xca */ x86emuOp_ret_far_IMM,
5373 /* 0xcb */ x86emuOp_ret_far,
5374 /* 0xcc */ x86emuOp_int3,
5375 /* 0xcd */ x86emuOp_int_IMM,
5376 /* 0xce */ x86emuOp_into,
5377 /* 0xcf */ x86emuOp_iret,
5379 /* 0xd0 */ x86emuOp_opcD0_byte_RM_1,
5380 /* 0xd1 */ x86emuOp_opcD1_word_RM_1,
5381 /* 0xd2 */ x86emuOp_opcD2_byte_RM_CL,
5382 /* 0xd3 */ x86emuOp_opcD3_word_RM_CL,
5383 /* 0xd4 */ x86emuOp_aam,
5384 /* 0xd5 */ x86emuOp_aad,
5385 /* 0xd6 */ x86emuOp_illegal_op, /* Undocumented SETALC instruction */
5386 /* 0xd7 */ x86emuOp_xlat,
5387 /* 0xd8 */ NULL, /*x86emuOp_esc_coprocess_d8,*/
5388 /* 0xd9 */ NULL, /*x86emuOp_esc_coprocess_d9,*/
5389 /* 0xda */ NULL, /*x86emuOp_esc_coprocess_da,*/
5390 /* 0xdb */ NULL, /*x86emuOp_esc_coprocess_db,*/
5391 /* 0xdc */ NULL, /*x86emuOp_esc_coprocess_dc,*/
5392 /* 0xdd */ NULL, /*x86emuOp_esc_coprocess_dd,*/
5393 /* 0xde */ NULL, /*x86emuOp_esc_coprocess_de,*/
5394 /* 0xdf */ NULL, /*x86emuOp_esc_coprocess_df,*/
5396 /* 0xe0 */ x86emuOp_loopne,
5397 /* 0xe1 */ x86emuOp_loope,
5398 /* 0xe2 */ x86emuOp_loop,
5399 /* 0xe3 */ x86emuOp_jcxz,
5400 /* 0xe4 */ x86emuOp_in_byte_AL_IMM,
5401 /* 0xe5 */ x86emuOp_in_word_AX_IMM,
5402 /* 0xe6 */ x86emuOp_out_byte_IMM_AL,
5403 /* 0xe7 */ x86emuOp_out_word_IMM_AX,
5405 /* 0xe8 */ x86emuOp_call_near_IMM,
5406 /* 0xe9 */ x86emuOp_jump_near_IMM,
5407 /* 0xea */ x86emuOp_jump_far_IMM,
5408 /* 0xeb */ x86emuOp_jump_byte_IMM,
5409 /* 0xec */ x86emuOp_in_byte_AL_DX,
5410 /* 0xed */ x86emuOp_in_word_AX_DX,
5411 /* 0xee */ x86emuOp_out_byte_DX_AL,
5412 /* 0xef */ x86emuOp_out_word_DX_AX,
5414 /* 0xf0 */ x86emuOp_lock,
5415 /* 0xf1 */ x86emuOp_illegal_op,
5416 /* 0xf2 */ x86emuOp_repne,
5417 /* 0xf3 */ x86emuOp_repe,
5418 /* 0xf4 */ x86emuOp_halt,
5419 /* 0xf5 */ x86emuOp_cmc,
5420 /* 0xf6 */ x86emuOp_opcF6_byte_RM,
5421 /* 0xf7 */ x86emuOp_opcF7_word_RM,
5423 /* 0xf8 */ x86emuOp_clc,
5424 /* 0xf9 */ x86emuOp_stc,
5425 /* 0xfa */ x86emuOp_cli,
5426 /* 0xfb */ x86emuOp_sti,
5427 /* 0xfc */ x86emuOp_cld,
5428 /* 0xfd */ x86emuOp_std,
5429 /* 0xfe */ x86emuOp_opcFE_byte_RM,
5430 /* 0xff */ x86emuOp_opcFF_word_RM,