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 ****************************************************************************/
79 #include "x86emu/x86emui.h"
81 /*----------------------------- Implementation ----------------------------*/
83 /* constant arrays to do several instructions in just one function */
86 static char *x86emu_GenOpName[8] = {
87 "ADD", "OR", "ADC", "SBB", "AND", "SUB", "XOR", "CMP"};
90 /* used by several opcodes */
91 static u8 (*genop_byte_operation[])(u8 d, u8 s) __attribute__ ((section(GOT2_TYPE))) =
103 static u16 (*genop_word_operation[])(u16 d, u16 s) __attribute__ ((section(GOT2_TYPE))) =
115 static u32 (*genop_long_operation[])(u32 d, u32 s) __attribute__ ((section(GOT2_TYPE))) =
127 /* used by opcodes 80, c0, d0, and d2. */
128 static u8(*opcD0_byte_operation[])(u8 d, u8 s) __attribute__ ((section(GOT2_TYPE))) =
136 shl_byte, /* sal_byte === shl_byte by definition */
140 /* used by opcodes c1, d1, and d3. */
141 static u16(*opcD1_word_operation[])(u16 s, u8 d) __attribute__ ((section(GOT2_TYPE))) =
149 shl_word, /* sal_byte === shl_byte by definition */
153 /* used by opcodes c1, d1, and d3. */
154 static u32 (*opcD1_long_operation[])(u32 s, u8 d) __attribute__ ((section(GOT2_TYPE))) =
162 shl_long, /* sal_byte === shl_byte by definition */
168 static char *opF6_names[8] =
169 { "TEST\t", "", "NOT\t", "NEG\t", "MUL\t", "IMUL\t", "DIV\t", "IDIV\t" };
173 /****************************************************************************
175 op1 - Instruction op code
178 Handles illegal opcodes.
179 ****************************************************************************/
180 void x86emuOp_illegal_op(
184 if (M.x86.R_SP != 0) {
185 DECODE_PRINTF("ILLEGAL X86 OPCODE\n");
187 DB( printk("%04x:%04x: %02X ILLEGAL X86 OPCODE!\n",
188 M.x86.R_CS, M.x86.R_IP-1,op1));
192 /* If we get here, it means the stack pointer is back to zero
193 * so we are just returning from an emulator service call
194 * so therte is no need to display an error message. We trap
195 * the emulator with an 0xF1 opcode to finish the service
203 /****************************************************************************
205 Handles opcodes 0x00, 0x08, 0x10, 0x18, 0x20, 0x28, 0x30, 0x38
206 ****************************************************************************/
207 void x86emuOp_genop_byte_RM_R(u8 op1)
211 u8 *destreg, *srcreg;
214 op1 = (op1 >> 3) & 0x7;
217 DECODE_PRINTF(x86emu_GenOpName[op1]);
219 FETCH_DECODE_MODRM(mod, rh, rl);
221 { destoffset = decode_rmXX_address(mod,rl);
223 destval = fetch_data_byte(destoffset);
224 srcreg = DECODE_RM_BYTE_REGISTER(rh);
227 destval = genop_byte_operation[op1](destval, *srcreg);
228 store_data_byte(destoffset, destval);
231 { /* register to register */
232 destreg = DECODE_RM_BYTE_REGISTER(rl);
234 srcreg = DECODE_RM_BYTE_REGISTER(rh);
237 *destreg = genop_byte_operation[op1](*destreg, *srcreg);
239 DECODE_CLEAR_SEGOVR();
243 /****************************************************************************
245 Handles opcodes 0x01, 0x09, 0x11, 0x19, 0x21, 0x29, 0x31, 0x39
246 ****************************************************************************/
247 void x86emuOp_genop_word_RM_R(u8 op1)
252 op1 = (op1 >> 3) & 0x7;
255 DECODE_PRINTF(x86emu_GenOpName[op1]);
257 FETCH_DECODE_MODRM(mod, rh, rl);
260 destoffset = decode_rmXX_address(mod,rl);
261 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
266 destval = fetch_data_long(destoffset);
267 srcreg = DECODE_RM_LONG_REGISTER(rh);
270 destval = genop_long_operation[op1](destval, *srcreg);
271 store_data_long(destoffset, destval);
277 destval = fetch_data_word(destoffset);
278 srcreg = DECODE_RM_WORD_REGISTER(rh);
281 destval = genop_word_operation[op1](destval, *srcreg);
282 store_data_word(destoffset, destval);
284 } else { /* register to register */
285 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
286 u32 *destreg,*srcreg;
288 destreg = DECODE_RM_LONG_REGISTER(rl);
290 srcreg = DECODE_RM_LONG_REGISTER(rh);
293 *destreg = genop_long_operation[op1](*destreg, *srcreg);
295 u16 *destreg,*srcreg;
297 destreg = DECODE_RM_WORD_REGISTER(rl);
299 srcreg = DECODE_RM_WORD_REGISTER(rh);
302 *destreg = genop_word_operation[op1](*destreg, *srcreg);
305 DECODE_CLEAR_SEGOVR();
309 /****************************************************************************
311 Handles opcodes 0x02, 0x0a, 0x12, 0x1a, 0x22, 0x2a, 0x32, 0x3a
312 ****************************************************************************/
313 void x86emuOp_genop_byte_R_RM(u8 op1)
316 u8 *destreg, *srcreg;
320 op1 = (op1 >> 3) & 0x7;
323 DECODE_PRINTF(x86emu_GenOpName[op1]);
325 FETCH_DECODE_MODRM(mod, rh, rl);
327 destreg = DECODE_RM_BYTE_REGISTER(rh);
329 srcoffset = decode_rmXX_address(mod,rl);
330 srcval = fetch_data_byte(srcoffset);
331 } else { /* register to register */
332 destreg = DECODE_RM_BYTE_REGISTER(rh);
334 srcreg = DECODE_RM_BYTE_REGISTER(rl);
339 *destreg = genop_byte_operation[op1](*destreg, srcval);
341 DECODE_CLEAR_SEGOVR();
345 /****************************************************************************
347 Handles opcodes 0x03, 0x0b, 0x13, 0x1b, 0x23, 0x2b, 0x33, 0x3b
348 ****************************************************************************/
349 void x86emuOp_genop_word_R_RM(u8 op1)
353 u32 *destreg32, srcval;
356 op1 = (op1 >> 3) & 0x7;
359 DECODE_PRINTF(x86emu_GenOpName[op1]);
361 FETCH_DECODE_MODRM(mod, rh, rl);
363 srcoffset = decode_rmXX_address(mod,rl);
364 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
365 destreg32 = DECODE_RM_LONG_REGISTER(rh);
367 srcval = fetch_data_long(srcoffset);
370 *destreg32 = genop_long_operation[op1](*destreg32, srcval);
372 destreg = DECODE_RM_WORD_REGISTER(rh);
374 srcval = fetch_data_word(srcoffset);
377 *destreg = genop_word_operation[op1](*destreg, srcval);
379 } else { /* register to register */
380 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
382 destreg32 = DECODE_RM_LONG_REGISTER(rh);
384 srcreg = DECODE_RM_LONG_REGISTER(rl);
387 *destreg32 = genop_long_operation[op1](*destreg32, *srcreg);
390 destreg = DECODE_RM_WORD_REGISTER(rh);
392 srcreg = DECODE_RM_WORD_REGISTER(rl);
395 *destreg = genop_word_operation[op1](*destreg, *srcreg);
398 DECODE_CLEAR_SEGOVR();
402 /****************************************************************************
404 Handles opcodes 0x04, 0x0c, 0x14, 0x1c, 0x24, 0x2c, 0x34, 0x3c
405 ****************************************************************************/
406 void x86emuOp_genop_byte_AL_IMM(u8 op1)
410 op1 = (op1 >> 3) & 0x7;
413 DECODE_PRINTF(x86emu_GenOpName[op1]);
414 DECODE_PRINTF("\tAL,");
415 srcval = fetch_byte_imm();
416 DECODE_PRINTF2("%x\n", srcval);
418 M.x86.R_AL = genop_byte_operation[op1](M.x86.R_AL, srcval);
419 DECODE_CLEAR_SEGOVR();
423 /****************************************************************************
425 Handles opcodes 0x05, 0x0d, 0x15, 0x1d, 0x25, 0x2d, 0x35, 0x3d
426 ****************************************************************************/
427 void x86emuOp_genop_word_AX_IMM(u8 op1)
431 op1 = (op1 >> 3) & 0x7;
434 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
435 DECODE_PRINTF(x86emu_GenOpName[op1]);
436 DECODE_PRINTF("\tEAX,");
437 srcval = fetch_long_imm();
439 DECODE_PRINTF(x86emu_GenOpName[op1]);
440 DECODE_PRINTF("\tAX,");
441 srcval = fetch_word_imm();
443 DECODE_PRINTF2("%x\n", srcval);
445 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
446 M.x86.R_EAX = genop_long_operation[op1](M.x86.R_EAX, srcval);
448 M.x86.R_AX = genop_word_operation[op1](M.x86.R_AX, (u16)srcval);
450 DECODE_CLEAR_SEGOVR();
454 /****************************************************************************
457 ****************************************************************************/
458 void x86emuOp_push_ES(u8 X86EMU_UNUSED(op1))
461 DECODE_PRINTF("PUSH\tES\n");
463 push_word(M.x86.R_ES);
464 DECODE_CLEAR_SEGOVR();
468 /****************************************************************************
471 ****************************************************************************/
472 void x86emuOp_pop_ES(u8 X86EMU_UNUSED(op1))
475 DECODE_PRINTF("POP\tES\n");
477 M.x86.R_ES = pop_word();
478 DECODE_CLEAR_SEGOVR();
482 /****************************************************************************
485 ****************************************************************************/
486 void x86emuOp_push_CS(u8 X86EMU_UNUSED(op1))
489 DECODE_PRINTF("PUSH\tCS\n");
491 push_word(M.x86.R_CS);
492 DECODE_CLEAR_SEGOVR();
496 /****************************************************************************
498 Handles opcode 0x0f. Escape for two-byte opcode (286 or better)
499 ****************************************************************************/
500 void x86emuOp_two_byte(u8 X86EMU_UNUSED(op1))
502 u8 op2 = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++));
503 INC_DECODED_INST_LEN(1);
504 (*x86emu_optab2[op2])(op2);
507 /****************************************************************************
510 ****************************************************************************/
511 void x86emuOp_push_SS(u8 X86EMU_UNUSED(op1))
514 DECODE_PRINTF("PUSH\tSS\n");
516 push_word(M.x86.R_SS);
517 DECODE_CLEAR_SEGOVR();
521 /****************************************************************************
524 ****************************************************************************/
525 void x86emuOp_pop_SS(u8 X86EMU_UNUSED(op1))
528 DECODE_PRINTF("POP\tSS\n");
530 M.x86.R_SS = pop_word();
531 DECODE_CLEAR_SEGOVR();
535 /****************************************************************************
538 ****************************************************************************/
539 void x86emuOp_push_DS(u8 X86EMU_UNUSED(op1))
542 DECODE_PRINTF("PUSH\tDS\n");
544 push_word(M.x86.R_DS);
545 DECODE_CLEAR_SEGOVR();
549 /****************************************************************************
552 ****************************************************************************/
553 void x86emuOp_pop_DS(u8 X86EMU_UNUSED(op1))
556 DECODE_PRINTF("POP\tDS\n");
558 M.x86.R_DS = pop_word();
559 DECODE_CLEAR_SEGOVR();
563 /****************************************************************************
566 ****************************************************************************/
567 void x86emuOp_segovr_ES(u8 X86EMU_UNUSED(op1))
570 DECODE_PRINTF("ES:\n");
572 M.x86.mode |= SYSMODE_SEGOVR_ES;
574 * note the lack of DECODE_CLEAR_SEGOVR(r) since, here is one of 4
575 * opcode subroutines we do not want to do this.
580 /****************************************************************************
583 ****************************************************************************/
584 void x86emuOp_daa(u8 X86EMU_UNUSED(op1))
587 DECODE_PRINTF("DAA\n");
589 M.x86.R_AL = daa_byte(M.x86.R_AL);
590 DECODE_CLEAR_SEGOVR();
594 /****************************************************************************
597 ****************************************************************************/
598 void x86emuOp_segovr_CS(u8 X86EMU_UNUSED(op1))
601 DECODE_PRINTF("CS:\n");
603 M.x86.mode |= SYSMODE_SEGOVR_CS;
604 /* note no DECODE_CLEAR_SEGOVR here. */
608 /****************************************************************************
611 ****************************************************************************/
612 void x86emuOp_das(u8 X86EMU_UNUSED(op1))
615 DECODE_PRINTF("DAS\n");
617 M.x86.R_AL = das_byte(M.x86.R_AL);
618 DECODE_CLEAR_SEGOVR();
622 /****************************************************************************
625 ****************************************************************************/
626 void x86emuOp_segovr_SS(u8 X86EMU_UNUSED(op1))
629 DECODE_PRINTF("SS:\n");
631 M.x86.mode |= SYSMODE_SEGOVR_SS;
632 /* no DECODE_CLEAR_SEGOVR ! */
636 /****************************************************************************
639 ****************************************************************************/
640 void x86emuOp_aaa(u8 X86EMU_UNUSED(op1))
643 DECODE_PRINTF("AAA\n");
645 M.x86.R_AX = aaa_word(M.x86.R_AX);
646 DECODE_CLEAR_SEGOVR();
650 /****************************************************************************
653 ****************************************************************************/
654 void x86emuOp_segovr_DS(u8 X86EMU_UNUSED(op1))
657 DECODE_PRINTF("DS:\n");
659 M.x86.mode |= SYSMODE_SEGOVR_DS;
660 /* NO DECODE_CLEAR_SEGOVR! */
664 /****************************************************************************
667 ****************************************************************************/
668 void x86emuOp_aas(u8 X86EMU_UNUSED(op1))
671 DECODE_PRINTF("AAS\n");
673 M.x86.R_AX = aas_word(M.x86.R_AX);
674 DECODE_CLEAR_SEGOVR();
678 /****************************************************************************
680 Handles opcode 0x40 - 0x47
681 ****************************************************************************/
682 void x86emuOp_inc_register(u8 op1)
686 DECODE_PRINTF("INC\t");
687 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
689 reg = DECODE_RM_LONG_REGISTER(op1);
692 *reg = inc_long(*reg);
695 reg = DECODE_RM_WORD_REGISTER(op1);
698 *reg = inc_word(*reg);
700 DECODE_CLEAR_SEGOVR();
704 /****************************************************************************
706 Handles opcode 0x48 - 0x4F
707 ****************************************************************************/
708 void x86emuOp_dec_register(u8 op1)
712 DECODE_PRINTF("DEC\t");
713 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
715 reg = DECODE_RM_LONG_REGISTER(op1);
718 *reg = dec_long(*reg);
721 reg = DECODE_RM_WORD_REGISTER(op1);
724 *reg = dec_word(*reg);
726 DECODE_CLEAR_SEGOVR();
730 /****************************************************************************
732 Handles opcode 0x50 - 0x57
733 ****************************************************************************/
734 void x86emuOp_push_register(u8 op1)
738 DECODE_PRINTF("PUSH\t");
739 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
741 reg = DECODE_RM_LONG_REGISTER(op1);
747 reg = DECODE_RM_WORD_REGISTER(op1);
752 DECODE_CLEAR_SEGOVR();
756 /****************************************************************************
758 Handles opcode 0x58 - 0x5F
759 ****************************************************************************/
760 void x86emuOp_pop_register(u8 op1)
764 DECODE_PRINTF("POP\t");
765 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
767 reg = DECODE_RM_LONG_REGISTER(op1);
773 reg = DECODE_RM_WORD_REGISTER(op1);
778 DECODE_CLEAR_SEGOVR();
782 /****************************************************************************
785 ****************************************************************************/
786 void x86emuOp_push_all(u8 X86EMU_UNUSED(op1))
789 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
790 DECODE_PRINTF("PUSHAD\n");
792 DECODE_PRINTF("PUSHA\n");
795 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
796 u32 old_sp = M.x86.R_ESP;
798 push_long(M.x86.R_EAX);
799 push_long(M.x86.R_ECX);
800 push_long(M.x86.R_EDX);
801 push_long(M.x86.R_EBX);
803 push_long(M.x86.R_EBP);
804 push_long(M.x86.R_ESI);
805 push_long(M.x86.R_EDI);
807 u16 old_sp = M.x86.R_SP;
809 push_word(M.x86.R_AX);
810 push_word(M.x86.R_CX);
811 push_word(M.x86.R_DX);
812 push_word(M.x86.R_BX);
814 push_word(M.x86.R_BP);
815 push_word(M.x86.R_SI);
816 push_word(M.x86.R_DI);
818 DECODE_CLEAR_SEGOVR();
822 /****************************************************************************
825 ****************************************************************************/
826 void x86emuOp_pop_all(u8 X86EMU_UNUSED(op1))
829 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
830 DECODE_PRINTF("POPAD\n");
832 DECODE_PRINTF("POPA\n");
835 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
836 M.x86.R_EDI = pop_long();
837 M.x86.R_ESI = pop_long();
838 M.x86.R_EBP = pop_long();
839 M.x86.R_ESP += 4; /* skip ESP */
840 M.x86.R_EBX = pop_long();
841 M.x86.R_EDX = pop_long();
842 M.x86.R_ECX = pop_long();
843 M.x86.R_EAX = pop_long();
845 M.x86.R_DI = pop_word();
846 M.x86.R_SI = pop_word();
847 M.x86.R_BP = pop_word();
848 M.x86.R_SP += 2; /* skip SP */
849 M.x86.R_BX = pop_word();
850 M.x86.R_DX = pop_word();
851 M.x86.R_CX = pop_word();
852 M.x86.R_AX = pop_word();
854 DECODE_CLEAR_SEGOVR();
858 /*opcode 0x62 ILLEGAL OP, calls x86emuOp_illegal_op() */
859 /*opcode 0x63 ILLEGAL OP, calls x86emuOp_illegal_op() */
861 /****************************************************************************
864 ****************************************************************************/
865 void x86emuOp_segovr_FS(u8 X86EMU_UNUSED(op1))
868 DECODE_PRINTF("FS:\n");
870 M.x86.mode |= SYSMODE_SEGOVR_FS;
872 * note the lack of DECODE_CLEAR_SEGOVR(r) since, here is one of 4
873 * opcode subroutines we do not want to do this.
878 /****************************************************************************
881 ****************************************************************************/
882 void x86emuOp_segovr_GS(u8 X86EMU_UNUSED(op1))
885 DECODE_PRINTF("GS:\n");
887 M.x86.mode |= SYSMODE_SEGOVR_GS;
889 * note the lack of DECODE_CLEAR_SEGOVR(r) since, here is one of 4
890 * opcode subroutines we do not want to do this.
895 /****************************************************************************
897 Handles opcode 0x66 - prefix for 32-bit register
898 ****************************************************************************/
899 void x86emuOp_prefix_data(u8 X86EMU_UNUSED(op1))
902 DECODE_PRINTF("DATA:\n");
904 M.x86.mode |= SYSMODE_PREFIX_DATA;
905 /* note no DECODE_CLEAR_SEGOVR here. */
909 /****************************************************************************
911 Handles opcode 0x67 - prefix for 32-bit address
912 ****************************************************************************/
913 void x86emuOp_prefix_addr(u8 X86EMU_UNUSED(op1))
916 DECODE_PRINTF("ADDR:\n");
918 M.x86.mode |= SYSMODE_PREFIX_ADDR;
919 /* note no DECODE_CLEAR_SEGOVR here. */
923 /****************************************************************************
926 ****************************************************************************/
927 void x86emuOp_push_word_IMM(u8 X86EMU_UNUSED(op1))
932 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
933 imm = fetch_long_imm();
935 imm = fetch_word_imm();
937 DECODE_PRINTF2("PUSH\t%x\n", imm);
939 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
944 DECODE_CLEAR_SEGOVR();
948 /****************************************************************************
951 ****************************************************************************/
952 void x86emuOp_imul_word_IMM(u8 X86EMU_UNUSED(op1))
958 DECODE_PRINTF("IMUL\t");
959 FETCH_DECODE_MODRM(mod, rh, rl);
961 srcoffset = decode_rmXX_address(mod, rl);
962 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
968 destreg = DECODE_RM_LONG_REGISTER(rh);
970 srcval = fetch_data_long(srcoffset);
971 imm = fetch_long_imm();
972 DECODE_PRINTF2(",%d\n", (s32)imm);
974 imul_long_direct(&res_lo,&res_hi,(s32)srcval,(s32)imm);
975 if ((((res_lo & 0x80000000) == 0) && (res_hi == 0x00000000)) ||
976 (((res_lo & 0x80000000) != 0) && (res_hi == 0xFFFFFFFF))) {
983 *destreg = (u32)res_lo;
990 destreg = DECODE_RM_WORD_REGISTER(rh);
992 srcval = fetch_data_word(srcoffset);
993 imm = fetch_word_imm();
994 DECODE_PRINTF2(",%d\n", (s32)imm);
996 res = (s16)srcval * (s16)imm;
997 if ((((res & 0x8000) == 0) && ((res >> 16) == 0x0000)) ||
998 (((res & 0x8000) != 0) && ((res >> 16) == 0xFFFF))) {
1005 *destreg = (u16)res;
1007 } else { /* register to register */
1008 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1009 u32 *destreg,*srcreg;
1013 destreg = DECODE_RM_LONG_REGISTER(rh);
1015 srcreg = DECODE_RM_LONG_REGISTER(rl);
1016 imm = fetch_long_imm();
1017 DECODE_PRINTF2(",%d\n", (s32)imm);
1019 imul_long_direct(&res_lo,&res_hi,(s32)*srcreg,(s32)imm);
1020 if ((((res_lo & 0x80000000) == 0) && (res_hi == 0x00000000)) ||
1021 (((res_lo & 0x80000000) != 0) && (res_hi == 0xFFFFFFFF))) {
1028 *destreg = (u32)res_lo;
1030 u16 *destreg,*srcreg;
1034 destreg = DECODE_RM_WORD_REGISTER(rh);
1036 srcreg = DECODE_RM_WORD_REGISTER(rl);
1037 imm = fetch_word_imm();
1038 DECODE_PRINTF2(",%d\n", (s32)imm);
1039 res = (s16)*srcreg * (s16)imm;
1040 if ((((res & 0x8000) == 0) && ((res >> 16) == 0x0000)) ||
1041 (((res & 0x8000) != 0) && ((res >> 16) == 0xFFFF))) {
1048 *destreg = (u16)res;
1051 DECODE_CLEAR_SEGOVR();
1055 /****************************************************************************
1058 ****************************************************************************/
1059 void x86emuOp_push_byte_IMM(u8 X86EMU_UNUSED(op1))
1064 imm = (s8)fetch_byte_imm();
1065 DECODE_PRINTF2("PUSH\t%d\n", imm);
1068 DECODE_CLEAR_SEGOVR();
1072 /****************************************************************************
1075 ****************************************************************************/
1076 void x86emuOp_imul_byte_IMM(u8 X86EMU_UNUSED(op1))
1083 DECODE_PRINTF("IMUL\t");
1084 FETCH_DECODE_MODRM(mod, rh, rl);
1086 srcoffset = decode_rmXX_address(mod, rl);
1087 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1092 destreg = DECODE_RM_LONG_REGISTER(rh);
1094 srcval = fetch_data_long(srcoffset);
1095 imm = fetch_byte_imm();
1096 DECODE_PRINTF2(",%d\n", (s32)imm);
1098 imul_long_direct(&res_lo,&res_hi,(s32)srcval,(s32)imm);
1099 if ((((res_lo & 0x80000000) == 0) && (res_hi == 0x00000000)) ||
1100 (((res_lo & 0x80000000) != 0) && (res_hi == 0xFFFFFFFF))) {
1107 *destreg = (u32)res_lo;
1113 destreg = DECODE_RM_WORD_REGISTER(rh);
1115 srcval = fetch_data_word(srcoffset);
1116 imm = fetch_byte_imm();
1117 DECODE_PRINTF2(",%d\n", (s32)imm);
1119 res = (s16)srcval * (s16)imm;
1120 if ((((res & 0x8000) == 0) && ((res >> 16) == 0x0000)) ||
1121 (((res & 0x8000) != 0) && ((res >> 16) == 0xFFFF))) {
1128 *destreg = (u16)res;
1130 } else { /* register to register */
1131 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1132 u32 *destreg,*srcreg;
1135 destreg = DECODE_RM_LONG_REGISTER(rh);
1137 srcreg = DECODE_RM_LONG_REGISTER(rl);
1138 imm = fetch_byte_imm();
1139 DECODE_PRINTF2(",%d\n", (s32)imm);
1141 imul_long_direct(&res_lo,&res_hi,(s32)*srcreg,(s32)imm);
1142 if ((((res_lo & 0x80000000) == 0) && (res_hi == 0x00000000)) ||
1143 (((res_lo & 0x80000000) != 0) && (res_hi == 0xFFFFFFFF))) {
1150 *destreg = (u32)res_lo;
1152 u16 *destreg,*srcreg;
1155 destreg = DECODE_RM_WORD_REGISTER(rh);
1157 srcreg = DECODE_RM_WORD_REGISTER(rl);
1158 imm = fetch_byte_imm();
1159 DECODE_PRINTF2(",%d\n", (s32)imm);
1161 res = (s16)*srcreg * (s16)imm;
1162 if ((((res & 0x8000) == 0) && ((res >> 16) == 0x0000)) ||
1163 (((res & 0x8000) != 0) && ((res >> 16) == 0xFFFF))) {
1170 *destreg = (u16)res;
1173 DECODE_CLEAR_SEGOVR();
1177 /****************************************************************************
1180 ****************************************************************************/
1181 void x86emuOp_ins_byte(u8 X86EMU_UNUSED(op1))
1184 DECODE_PRINTF("INSB\n");
1187 DECODE_CLEAR_SEGOVR();
1191 /****************************************************************************
1194 ****************************************************************************/
1195 void x86emuOp_ins_word(u8 X86EMU_UNUSED(op1))
1198 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1199 DECODE_PRINTF("INSD\n");
1202 DECODE_PRINTF("INSW\n");
1206 DECODE_CLEAR_SEGOVR();
1210 /****************************************************************************
1213 ****************************************************************************/
1214 void x86emuOp_outs_byte(u8 X86EMU_UNUSED(op1))
1217 DECODE_PRINTF("OUTSB\n");
1220 DECODE_CLEAR_SEGOVR();
1224 /****************************************************************************
1227 ****************************************************************************/
1228 void x86emuOp_outs_word(u8 X86EMU_UNUSED(op1))
1231 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1232 DECODE_PRINTF("OUTSD\n");
1235 DECODE_PRINTF("OUTSW\n");
1239 DECODE_CLEAR_SEGOVR();
1243 /****************************************************************************
1245 Handles opcode 0x70 - 0x7F
1246 ****************************************************************************/
1247 int x86emu_check_jump_condition(u8 op);
1249 void x86emuOp_jump_near_cond(u8 op1)
1255 /* jump to byte offset if overflow flag is set */
1257 cond = x86emu_check_jump_condition(op1 & 0xF);
1258 offset = (s8)fetch_byte_imm();
1259 target = (u16)(M.x86.R_IP + (s16)offset);
1260 DECODE_PRINTF2("%x\n", target);
1263 M.x86.R_IP = target;
1264 DECODE_CLEAR_SEGOVR();
1268 /****************************************************************************
1271 ****************************************************************************/
1272 void x86emuOp_opc80_byte_RM_IMM(u8 X86EMU_UNUSED(op1))
1281 * Weirdo special case instruction format. Part of the opcode
1282 * held below in "RH". Doubly nested case would result, except
1283 * that the decoded instruction
1286 FETCH_DECODE_MODRM(mod, rh, rl);
1288 if (DEBUG_DECODE()) {
1289 /* XXX DECODE_PRINTF may be changed to something more
1290 general, so that it is important to leave the strings
1291 in the same format, even though the result is that the
1292 above test is done twice. */
1296 DECODE_PRINTF("ADD\t");
1299 DECODE_PRINTF("OR\t");
1302 DECODE_PRINTF("ADC\t");
1305 DECODE_PRINTF("SBB\t");
1308 DECODE_PRINTF("AND\t");
1311 DECODE_PRINTF("SUB\t");
1314 DECODE_PRINTF("XOR\t");
1317 DECODE_PRINTF("CMP\t");
1322 /* know operation, decode the mod byte to find the addressing
1325 DECODE_PRINTF("BYTE PTR ");
1326 destoffset = decode_rmXX_address(mod, rl);
1328 destval = fetch_data_byte(destoffset);
1329 imm = fetch_byte_imm();
1330 DECODE_PRINTF2("%x\n", imm);
1332 destval = (*genop_byte_operation[rh]) (destval, imm);
1334 store_data_byte(destoffset, destval);
1335 } else { /* register to register */
1336 destreg = DECODE_RM_BYTE_REGISTER(rl);
1338 imm = fetch_byte_imm();
1339 DECODE_PRINTF2("%x\n", imm);
1341 destval = (*genop_byte_operation[rh]) (*destreg, imm);
1345 DECODE_CLEAR_SEGOVR();
1349 /****************************************************************************
1352 ****************************************************************************/
1353 void x86emuOp_opc81_word_RM_IMM(u8 X86EMU_UNUSED(op1))
1359 * Weirdo special case instruction format. Part of the opcode
1360 * held below in "RH". Doubly nested case would result, except
1361 * that the decoded instruction
1364 FETCH_DECODE_MODRM(mod, rh, rl);
1366 if (DEBUG_DECODE()) {
1367 /* XXX DECODE_PRINTF may be changed to something more
1368 general, so that it is important to leave the strings
1369 in the same format, even though the result is that the
1370 above test is done twice. */
1374 DECODE_PRINTF("ADD\t");
1377 DECODE_PRINTF("OR\t");
1380 DECODE_PRINTF("ADC\t");
1383 DECODE_PRINTF("SBB\t");
1386 DECODE_PRINTF("AND\t");
1389 DECODE_PRINTF("SUB\t");
1392 DECODE_PRINTF("XOR\t");
1395 DECODE_PRINTF("CMP\t");
1401 * Know operation, decode the mod byte to find the addressing
1405 DECODE_PRINTF("DWORD PTR ");
1406 destoffset = decode_rmXX_address(mod, rl);
1407 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1411 destval = fetch_data_long(destoffset);
1412 imm = fetch_long_imm();
1413 DECODE_PRINTF2("%x\n", imm);
1415 destval = (*genop_long_operation[rh]) (destval, imm);
1417 store_data_long(destoffset, destval);
1422 destval = fetch_data_word(destoffset);
1423 imm = fetch_word_imm();
1424 DECODE_PRINTF2("%x\n", imm);
1426 destval = (*genop_word_operation[rh]) (destval, imm);
1428 store_data_word(destoffset, destval);
1430 } else { /* register to register */
1431 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1435 destreg = DECODE_RM_LONG_REGISTER(rl);
1437 imm = fetch_long_imm();
1438 DECODE_PRINTF2("%x\n", imm);
1440 destval = (*genop_long_operation[rh]) (*destreg, imm);
1447 destreg = DECODE_RM_WORD_REGISTER(rl);
1449 imm = fetch_word_imm();
1450 DECODE_PRINTF2("%x\n", imm);
1452 destval = (*genop_word_operation[rh]) (*destreg, imm);
1457 DECODE_CLEAR_SEGOVR();
1461 /****************************************************************************
1464 ****************************************************************************/
1465 void x86emuOp_opc82_byte_RM_IMM(u8 X86EMU_UNUSED(op1))
1474 * Weirdo special case instruction format. Part of the opcode
1475 * held below in "RH". Doubly nested case would result, except
1476 * that the decoded instruction Similar to opcode 81, except that
1477 * the immediate byte is sign extended to a word length.
1480 FETCH_DECODE_MODRM(mod, rh, rl);
1482 if (DEBUG_DECODE()) {
1483 /* XXX DECODE_PRINTF may be changed to something more
1484 general, so that it is important to leave the strings
1485 in the same format, even though the result is that the
1486 above test is done twice. */
1489 DECODE_PRINTF("ADD\t");
1492 DECODE_PRINTF("OR\t");
1495 DECODE_PRINTF("ADC\t");
1498 DECODE_PRINTF("SBB\t");
1501 DECODE_PRINTF("AND\t");
1504 DECODE_PRINTF("SUB\t");
1507 DECODE_PRINTF("XOR\t");
1510 DECODE_PRINTF("CMP\t");
1515 /* know operation, decode the mod byte to find the addressing
1518 DECODE_PRINTF("BYTE PTR ");
1519 destoffset = decode_rmXX_address(mod, rl);
1520 destval = fetch_data_byte(destoffset);
1521 imm = fetch_byte_imm();
1522 DECODE_PRINTF2(",%x\n", imm);
1524 destval = (*genop_byte_operation[rh]) (destval, imm);
1526 store_data_byte(destoffset, destval);
1527 } else { /* register to register */
1528 destreg = DECODE_RM_BYTE_REGISTER(rl);
1529 imm = fetch_byte_imm();
1530 DECODE_PRINTF2(",%x\n", imm);
1532 destval = (*genop_byte_operation[rh]) (*destreg, imm);
1536 DECODE_CLEAR_SEGOVR();
1540 /****************************************************************************
1543 ****************************************************************************/
1544 void x86emuOp_opc83_word_RM_IMM(u8 X86EMU_UNUSED(op1))
1550 * Weirdo special case instruction format. Part of the opcode
1551 * held below in "RH". Doubly nested case would result, except
1552 * that the decoded instruction Similar to opcode 81, except that
1553 * the immediate byte is sign extended to a word length.
1556 FETCH_DECODE_MODRM(mod, rh, rl);
1558 if (DEBUG_DECODE()) {
1559 /* XXX DECODE_PRINTF may be changed to something more
1560 general, so that it is important to leave the strings
1561 in the same format, even though the result is that the
1562 above test is done twice. */
1565 DECODE_PRINTF("ADD\t");
1568 DECODE_PRINTF("OR\t");
1571 DECODE_PRINTF("ADC\t");
1574 DECODE_PRINTF("SBB\t");
1577 DECODE_PRINTF("AND\t");
1580 DECODE_PRINTF("SUB\t");
1583 DECODE_PRINTF("XOR\t");
1586 DECODE_PRINTF("CMP\t");
1591 /* know operation, decode the mod byte to find the addressing
1594 DECODE_PRINTF("DWORD PTR ");
1595 destoffset = decode_rmXX_address(mod,rl);
1597 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1600 destval = fetch_data_long(destoffset);
1601 imm = (s8) fetch_byte_imm();
1602 DECODE_PRINTF2(",%x\n", imm);
1604 destval = (*genop_long_operation[rh]) (destval, imm);
1606 store_data_long(destoffset, destval);
1610 destval = fetch_data_word(destoffset);
1611 imm = (s8) fetch_byte_imm();
1612 DECODE_PRINTF2(",%x\n", imm);
1614 destval = (*genop_word_operation[rh]) (destval, imm);
1616 store_data_word(destoffset, destval);
1618 } else { /* register to register */
1619 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1623 destreg = DECODE_RM_LONG_REGISTER(rl);
1624 imm = (s8) fetch_byte_imm();
1625 DECODE_PRINTF2(",%x\n", imm);
1627 destval = (*genop_long_operation[rh]) (*destreg, imm);
1634 destreg = DECODE_RM_WORD_REGISTER(rl);
1635 imm = (s8) fetch_byte_imm();
1636 DECODE_PRINTF2(",%x\n", imm);
1638 destval = (*genop_word_operation[rh]) (*destreg, imm);
1643 DECODE_CLEAR_SEGOVR();
1647 /****************************************************************************
1650 ****************************************************************************/
1651 void x86emuOp_test_byte_RM_R(u8 X86EMU_UNUSED(op1))
1654 u8 *destreg, *srcreg;
1659 DECODE_PRINTF("TEST\t");
1660 FETCH_DECODE_MODRM(mod, rh, rl);
1662 destoffset = decode_rmXX_address(mod, rl);
1664 destval = fetch_data_byte(destoffset);
1665 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1666 DECODE_PRINTF("\n");
1668 test_byte(destval, *srcreg);
1669 } else { /* register to register */
1670 destreg = DECODE_RM_BYTE_REGISTER(rl);
1672 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1673 DECODE_PRINTF("\n");
1675 test_byte(*destreg, *srcreg);
1677 DECODE_CLEAR_SEGOVR();
1681 /****************************************************************************
1684 ****************************************************************************/
1685 void x86emuOp_test_word_RM_R(u8 X86EMU_UNUSED(op1))
1691 DECODE_PRINTF("TEST\t");
1692 FETCH_DECODE_MODRM(mod, rh, rl);
1694 destoffset = decode_rmXX_address(mod, rl);
1695 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1700 destval = fetch_data_long(destoffset);
1701 srcreg = DECODE_RM_LONG_REGISTER(rh);
1702 DECODE_PRINTF("\n");
1704 test_long(destval, *srcreg);
1710 destval = fetch_data_word(destoffset);
1711 srcreg = DECODE_RM_WORD_REGISTER(rh);
1712 DECODE_PRINTF("\n");
1714 test_word(destval, *srcreg);
1716 } else { /* register to register */
1717 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1718 u32 *destreg,*srcreg;
1720 destreg = DECODE_RM_LONG_REGISTER(rl);
1722 srcreg = DECODE_RM_LONG_REGISTER(rh);
1723 DECODE_PRINTF("\n");
1725 test_long(*destreg, *srcreg);
1727 u16 *destreg,*srcreg;
1729 destreg = DECODE_RM_WORD_REGISTER(rl);
1731 srcreg = DECODE_RM_WORD_REGISTER(rh);
1732 DECODE_PRINTF("\n");
1734 test_word(*destreg, *srcreg);
1737 DECODE_CLEAR_SEGOVR();
1741 /****************************************************************************
1744 ****************************************************************************/
1745 void x86emuOp_xchg_byte_RM_R(u8 X86EMU_UNUSED(op1))
1748 u8 *destreg, *srcreg;
1754 DECODE_PRINTF("XCHG\t");
1755 FETCH_DECODE_MODRM(mod, rh, rl);
1757 destoffset = decode_rmXX_address(mod, rl);
1759 destval = fetch_data_byte(destoffset);
1760 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1761 DECODE_PRINTF("\n");
1766 store_data_byte(destoffset, destval);
1767 } else { /* register to register */
1768 destreg = DECODE_RM_BYTE_REGISTER(rl);
1770 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1771 DECODE_PRINTF("\n");
1777 DECODE_CLEAR_SEGOVR();
1781 /****************************************************************************
1784 ****************************************************************************/
1785 void x86emuOp_xchg_word_RM_R(u8 X86EMU_UNUSED(op1))
1791 DECODE_PRINTF("XCHG\t");
1792 FETCH_DECODE_MODRM(mod, rh, rl);
1794 destoffset = decode_rmXX_address(mod, rl);
1796 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1800 destval = fetch_data_long(destoffset);
1801 srcreg = DECODE_RM_LONG_REGISTER(rh);
1802 DECODE_PRINTF("\n");
1807 store_data_long(destoffset, destval);
1812 destval = fetch_data_word(destoffset);
1813 srcreg = DECODE_RM_WORD_REGISTER(rh);
1814 DECODE_PRINTF("\n");
1819 store_data_word(destoffset, destval);
1821 } else { /* register to register */
1822 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1823 u32 *destreg,*srcreg;
1826 destreg = DECODE_RM_LONG_REGISTER(rl);
1828 srcreg = DECODE_RM_LONG_REGISTER(rh);
1829 DECODE_PRINTF("\n");
1835 u16 *destreg,*srcreg;
1838 destreg = DECODE_RM_WORD_REGISTER(rl);
1840 srcreg = DECODE_RM_WORD_REGISTER(rh);
1841 DECODE_PRINTF("\n");
1848 DECODE_CLEAR_SEGOVR();
1852 /****************************************************************************
1855 ****************************************************************************/
1856 void x86emuOp_mov_byte_RM_R(u8 X86EMU_UNUSED(op1))
1859 u8 *destreg, *srcreg;
1863 DECODE_PRINTF("MOV\t");
1864 FETCH_DECODE_MODRM(mod, rh, rl);
1866 destoffset = decode_rmXX_address(mod, rl);
1868 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1869 DECODE_PRINTF("\n");
1871 store_data_byte(destoffset, *srcreg);
1872 } else { /* register to register */
1873 destreg = DECODE_RM_BYTE_REGISTER(rl);
1875 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1876 DECODE_PRINTF("\n");
1880 DECODE_CLEAR_SEGOVR();
1884 /****************************************************************************
1887 ****************************************************************************/
1888 void x86emuOp_mov_word_RM_R(u8 X86EMU_UNUSED(op1))
1894 DECODE_PRINTF("MOV\t");
1895 FETCH_DECODE_MODRM(mod, rh, rl);
1897 destoffset = decode_rmXX_address(mod, rl);
1898 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1902 srcreg = DECODE_RM_LONG_REGISTER(rh);
1903 DECODE_PRINTF("\n");
1905 store_data_long(destoffset, *srcreg);
1910 srcreg = DECODE_RM_WORD_REGISTER(rh);
1911 DECODE_PRINTF("\n");
1913 store_data_word(destoffset, *srcreg);
1915 } else { /* register to register */
1916 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1917 u32 *destreg,*srcreg;
1919 destreg = DECODE_RM_LONG_REGISTER(rl);
1921 srcreg = DECODE_RM_LONG_REGISTER(rh);
1922 DECODE_PRINTF("\n");
1926 u16 *destreg,*srcreg;
1928 destreg = DECODE_RM_WORD_REGISTER(rl);
1930 srcreg = DECODE_RM_WORD_REGISTER(rh);
1931 DECODE_PRINTF("\n");
1936 DECODE_CLEAR_SEGOVR();
1940 /****************************************************************************
1943 ****************************************************************************/
1944 void x86emuOp_mov_byte_R_RM(u8 X86EMU_UNUSED(op1))
1947 u8 *destreg, *srcreg;
1952 DECODE_PRINTF("MOV\t");
1953 FETCH_DECODE_MODRM(mod, rh, rl);
1955 destreg = DECODE_RM_BYTE_REGISTER(rh);
1957 srcoffset = decode_rmXX_address(mod, rl);
1958 srcval = fetch_data_byte(srcoffset);
1959 DECODE_PRINTF("\n");
1962 } else { /* register to register */
1963 destreg = DECODE_RM_BYTE_REGISTER(rh);
1965 srcreg = DECODE_RM_BYTE_REGISTER(rl);
1966 DECODE_PRINTF("\n");
1970 DECODE_CLEAR_SEGOVR();
1974 /****************************************************************************
1977 ****************************************************************************/
1978 void x86emuOp_mov_word_R_RM(u8 X86EMU_UNUSED(op1))
1984 DECODE_PRINTF("MOV\t");
1985 FETCH_DECODE_MODRM(mod, rh, rl);
1987 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1991 destreg = DECODE_RM_LONG_REGISTER(rh);
1993 srcoffset = decode_rmXX_address(mod, rl);
1994 srcval = fetch_data_long(srcoffset);
1995 DECODE_PRINTF("\n");
2002 destreg = DECODE_RM_WORD_REGISTER(rh);
2004 srcoffset = decode_rmXX_address(mod, rl);
2005 srcval = fetch_data_word(srcoffset);
2006 DECODE_PRINTF("\n");
2010 } else { /* register to register */
2011 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2012 u32 *destreg, *srcreg;
2014 destreg = DECODE_RM_LONG_REGISTER(rh);
2016 srcreg = DECODE_RM_LONG_REGISTER(rl);
2017 DECODE_PRINTF("\n");
2021 u16 *destreg, *srcreg;
2023 destreg = DECODE_RM_WORD_REGISTER(rh);
2025 srcreg = DECODE_RM_WORD_REGISTER(rl);
2026 DECODE_PRINTF("\n");
2031 DECODE_CLEAR_SEGOVR();
2035 /****************************************************************************
2038 ****************************************************************************/
2039 void x86emuOp_mov_word_RM_SR(u8 X86EMU_UNUSED(op1))
2042 u16 *destreg, *srcreg;
2047 DECODE_PRINTF("MOV\t");
2048 FETCH_DECODE_MODRM(mod, rh, rl);
2050 destoffset = decode_rmXX_address(mod, rl);
2052 srcreg = decode_rm_seg_register(rh);
2053 DECODE_PRINTF("\n");
2056 store_data_word(destoffset, destval);
2057 } else { /* register to register */
2058 destreg = DECODE_RM_WORD_REGISTER(rl);
2060 srcreg = decode_rm_seg_register(rh);
2061 DECODE_PRINTF("\n");
2065 DECODE_CLEAR_SEGOVR();
2069 /****************************************************************************
2072 ****************************************************************************/
2073 void x86emuOp_lea_word_R_M(u8 X86EMU_UNUSED(op1))
2080 * TODO: Need to handle address size prefix!
2082 * lea eax,[eax+ebx*2] ??
2086 DECODE_PRINTF("LEA\t");
2087 FETCH_DECODE_MODRM(mod, rh, rl);
2089 srcreg = DECODE_RM_WORD_REGISTER(rh);
2091 destoffset = decode_rmXX_address(mod, rl);
2092 DECODE_PRINTF("\n");
2094 *srcreg = (u16)destoffset;
2096 /* } else { undefined. Do nothing. } */
2097 DECODE_CLEAR_SEGOVR();
2101 /****************************************************************************
2104 ****************************************************************************/
2105 void x86emuOp_mov_word_SR_RM(u8 X86EMU_UNUSED(op1))
2108 u16 *destreg, *srcreg;
2113 DECODE_PRINTF("MOV\t");
2114 FETCH_DECODE_MODRM(mod, rh, rl);
2116 destreg = decode_rm_seg_register(rh);
2118 srcoffset = decode_rmXX_address(mod, rl);
2119 srcval = fetch_data_word(srcoffset);
2120 DECODE_PRINTF("\n");
2123 } else { /* register to register */
2124 destreg = decode_rm_seg_register(rh);
2126 srcreg = DECODE_RM_WORD_REGISTER(rl);
2127 DECODE_PRINTF("\n");
2132 * Clean up, and reset all the R_xSP pointers to the correct
2133 * locations. This is about 3x too much overhead (doing all the
2134 * segreg ptrs when only one is needed, but this instruction
2135 * *cannot* be that common, and this isn't too much work anyway.
2137 DECODE_CLEAR_SEGOVR();
2141 /****************************************************************************
2144 ****************************************************************************/
2145 void x86emuOp_pop_RM(u8 X86EMU_UNUSED(op1))
2151 DECODE_PRINTF("POP\t");
2152 FETCH_DECODE_MODRM(mod, rh, rl);
2154 DECODE_PRINTF("ILLEGAL DECODE OF OPCODE 8F\n");
2158 destoffset = decode_rmXX_address(mod, rl);
2159 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2162 DECODE_PRINTF("\n");
2164 destval = pop_long();
2165 store_data_long(destoffset, destval);
2169 DECODE_PRINTF("\n");
2171 destval = pop_word();
2172 store_data_word(destoffset, destval);
2174 } else { /* register to register */
2175 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2178 destreg = DECODE_RM_LONG_REGISTER(rl);
2179 DECODE_PRINTF("\n");
2181 *destreg = pop_long();
2185 destreg = DECODE_RM_WORD_REGISTER(rl);
2186 DECODE_PRINTF("\n");
2188 *destreg = pop_word();
2191 DECODE_CLEAR_SEGOVR();
2195 /****************************************************************************
2198 ****************************************************************************/
2199 void x86emuOp_nop(u8 X86EMU_UNUSED(op1))
2202 DECODE_PRINTF("NOP\n");
2204 DECODE_CLEAR_SEGOVR();
2208 /****************************************************************************
2210 Handles opcode 0x91-0x97
2211 ****************************************************************************/
2212 void x86emuOp_xchg_word_AX_register(u8 X86EMU_UNUSED(op1))
2220 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2222 DECODE_PRINTF("XCHG\tEAX,");
2223 reg32 = DECODE_RM_LONG_REGISTER(op1);
2224 DECODE_PRINTF("\n");
2227 M.x86.R_EAX = *reg32;
2231 DECODE_PRINTF("XCHG\tAX,");
2232 reg16 = DECODE_RM_WORD_REGISTER(op1);
2233 DECODE_PRINTF("\n");
2236 M.x86.R_EAX = *reg16;
2239 DECODE_CLEAR_SEGOVR();
2243 /****************************************************************************
2246 ****************************************************************************/
2247 void x86emuOp_cbw(u8 X86EMU_UNUSED(op1))
2250 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2251 DECODE_PRINTF("CWDE\n");
2253 DECODE_PRINTF("CBW\n");
2256 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2257 if (M.x86.R_AX & 0x8000) {
2258 M.x86.R_EAX |= 0xffff0000;
2260 M.x86.R_EAX &= 0x0000ffff;
2263 if (M.x86.R_AL & 0x80) {
2269 DECODE_CLEAR_SEGOVR();
2273 /****************************************************************************
2276 ****************************************************************************/
2277 void x86emuOp_cwd(u8 X86EMU_UNUSED(op1))
2280 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2281 DECODE_PRINTF("CDQ\n");
2283 DECODE_PRINTF("CWD\n");
2285 DECODE_PRINTF("CWD\n");
2287 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2288 if (M.x86.R_EAX & 0x80000000) {
2289 M.x86.R_EDX = 0xffffffff;
2294 if (M.x86.R_AX & 0x8000) {
2295 M.x86.R_DX = 0xffff;
2300 DECODE_CLEAR_SEGOVR();
2304 /****************************************************************************
2307 ****************************************************************************/
2308 void x86emuOp_call_far_IMM(u8 X86EMU_UNUSED(op1))
2313 DECODE_PRINTF("CALL\t");
2314 faroff = fetch_word_imm();
2315 farseg = fetch_word_imm();
2316 DECODE_PRINTF2("%04x:", farseg);
2317 DECODE_PRINTF2("%04x\n", faroff);
2318 CALL_TRACE(M.x86.saved_cs, M.x86.saved_ip, farseg, faroff, "FAR ");
2322 * Hooked interrupt vectors calling into our "BIOS" will cause
2323 * problems unless all intersegment stuff is checked for BIOS
2324 * access. Check needed here. For moment, let it alone.
2327 push_word(M.x86.R_CS);
2328 M.x86.R_CS = farseg;
2329 push_word(M.x86.R_IP);
2330 M.x86.R_IP = faroff;
2331 DECODE_CLEAR_SEGOVR();
2335 /****************************************************************************
2338 ****************************************************************************/
2339 void x86emuOp_wait(u8 X86EMU_UNUSED(op1))
2342 DECODE_PRINTF("WAIT");
2345 DECODE_CLEAR_SEGOVR();
2349 /****************************************************************************
2352 ****************************************************************************/
2353 void x86emuOp_pushf_word(u8 X86EMU_UNUSED(op1))
2358 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2359 DECODE_PRINTF("PUSHFD\n");
2361 DECODE_PRINTF("PUSHF\n");
2365 /* clear out *all* bits not representing flags, and turn on real bits */
2366 flags = (M.x86.R_EFLG & F_MSK) | F_ALWAYS_ON;
2367 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2370 push_word((u16)flags);
2372 DECODE_CLEAR_SEGOVR();
2376 /****************************************************************************
2379 ****************************************************************************/
2380 void x86emuOp_popf_word(u8 X86EMU_UNUSED(op1))
2383 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2384 DECODE_PRINTF("POPFD\n");
2386 DECODE_PRINTF("POPF\n");
2389 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2390 M.x86.R_EFLG = pop_long();
2392 M.x86.R_FLG = pop_word();
2394 DECODE_CLEAR_SEGOVR();
2398 /****************************************************************************
2401 ****************************************************************************/
2402 void x86emuOp_sahf(u8 X86EMU_UNUSED(op1))
2405 DECODE_PRINTF("SAHF\n");
2407 /* clear the lower bits of the flag register */
2408 M.x86.R_FLG &= 0xffffff00;
2409 /* or in the AH register into the flags register */
2410 M.x86.R_FLG |= M.x86.R_AH;
2411 DECODE_CLEAR_SEGOVR();
2415 /****************************************************************************
2418 ****************************************************************************/
2419 void x86emuOp_lahf(u8 X86EMU_UNUSED(op1))
2422 DECODE_PRINTF("LAHF\n");
2424 M.x86.R_AH = (u8)(M.x86.R_FLG & 0xff);
2425 /*undocumented TC++ behavior??? Nope. It's documented, but
2426 you have too look real hard to notice it. */
2428 DECODE_CLEAR_SEGOVR();
2432 /****************************************************************************
2435 ****************************************************************************/
2436 void x86emuOp_mov_AL_M_IMM(u8 X86EMU_UNUSED(op1))
2441 DECODE_PRINTF("MOV\tAL,");
2442 offset = fetch_word_imm();
2443 DECODE_PRINTF2("[%04x]\n", offset);
2445 M.x86.R_AL = fetch_data_byte(offset);
2446 DECODE_CLEAR_SEGOVR();
2450 /****************************************************************************
2453 ****************************************************************************/
2454 void x86emuOp_mov_AX_M_IMM(u8 X86EMU_UNUSED(op1))
2459 offset = fetch_word_imm();
2460 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2461 DECODE_PRINTF2("MOV\tEAX,[%04x]\n", offset);
2463 DECODE_PRINTF2("MOV\tAX,[%04x]\n", offset);
2466 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2467 M.x86.R_EAX = fetch_data_long(offset);
2469 M.x86.R_AX = fetch_data_word(offset);
2471 DECODE_CLEAR_SEGOVR();
2475 /****************************************************************************
2478 ****************************************************************************/
2479 void x86emuOp_mov_M_AL_IMM(u8 X86EMU_UNUSED(op1))
2484 DECODE_PRINTF("MOV\t");
2485 offset = fetch_word_imm();
2486 DECODE_PRINTF2("[%04x],AL\n", offset);
2488 store_data_byte(offset, M.x86.R_AL);
2489 DECODE_CLEAR_SEGOVR();
2493 /****************************************************************************
2496 ****************************************************************************/
2497 void x86emuOp_mov_M_AX_IMM(u8 X86EMU_UNUSED(op1))
2502 offset = fetch_word_imm();
2503 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2504 DECODE_PRINTF2("MOV\t[%04x],EAX\n", offset);
2506 DECODE_PRINTF2("MOV\t[%04x],AX\n", offset);
2509 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2510 store_data_long(offset, M.x86.R_EAX);
2512 store_data_word(offset, M.x86.R_AX);
2514 DECODE_CLEAR_SEGOVR();
2518 /****************************************************************************
2521 ****************************************************************************/
2522 void x86emuOp_movs_byte(u8 X86EMU_UNUSED(op1))
2529 DECODE_PRINTF("MOVS\tBYTE\n");
2530 if (ACCESS_FLAG(F_DF)) /* down */
2536 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2537 /* dont care whether REPE or REPNE */
2538 /* move them until CX is ZERO. */
2541 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2544 val = fetch_data_byte(M.x86.R_SI);
2545 store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, val);
2549 DECODE_CLEAR_SEGOVR();
2553 /****************************************************************************
2556 ****************************************************************************/
2557 void x86emuOp_movs_word(u8 X86EMU_UNUSED(op1))
2564 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2565 DECODE_PRINTF("MOVS\tDWORD\n");
2566 if (ACCESS_FLAG(F_DF)) /* down */
2571 DECODE_PRINTF("MOVS\tWORD\n");
2572 if (ACCESS_FLAG(F_DF)) /* down */
2579 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2580 /* dont care whether REPE or REPNE */
2581 /* move them until CX is ZERO. */
2584 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2587 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2588 val = fetch_data_long(M.x86.R_SI);
2589 store_data_long_abs(M.x86.R_ES, M.x86.R_DI, val);
2591 val = fetch_data_word(M.x86.R_SI);
2592 store_data_word_abs(M.x86.R_ES, M.x86.R_DI, (u16)val);
2597 DECODE_CLEAR_SEGOVR();
2601 /****************************************************************************
2604 ****************************************************************************/
2605 void x86emuOp_cmps_byte(u8 X86EMU_UNUSED(op1))
2611 DECODE_PRINTF("CMPS\tBYTE\n");
2613 if (ACCESS_FLAG(F_DF)) /* down */
2618 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2620 /* move them until CX is ZERO. */
2621 while (M.x86.R_CX != 0) {
2622 val1 = fetch_data_byte(M.x86.R_SI);
2623 val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2624 cmp_byte(val1, val2);
2628 if ( (M.x86.mode & SYSMODE_PREFIX_REPE) && (ACCESS_FLAG(F_ZF) == 0) ) break;
2629 if ( (M.x86.mode & SYSMODE_PREFIX_REPNE) && ACCESS_FLAG(F_ZF) ) break;
2631 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2633 val1 = fetch_data_byte(M.x86.R_SI);
2634 val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2635 cmp_byte(val1, val2);
2639 DECODE_CLEAR_SEGOVR();
2643 /****************************************************************************
2646 ****************************************************************************/
2647 void x86emuOp_cmps_word(u8 X86EMU_UNUSED(op1))
2653 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2654 DECODE_PRINTF("CMPS\tDWORD\n");
2657 DECODE_PRINTF("CMPS\tWORD\n");
2660 if (ACCESS_FLAG(F_DF)) /* down */
2664 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2666 /* move them until CX is ZERO. */
2667 while (M.x86.R_CX != 0) {
2668 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2669 val1 = fetch_data_long(M.x86.R_SI);
2670 val2 = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
2671 cmp_long(val1, val2);
2673 val1 = fetch_data_word(M.x86.R_SI);
2674 val2 = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
2675 cmp_word((u16)val1, (u16)val2);
2680 if ( (M.x86.mode & SYSMODE_PREFIX_REPE) && ACCESS_FLAG(F_ZF) == 0 ) break;
2681 if ( (M.x86.mode & SYSMODE_PREFIX_REPNE) && ACCESS_FLAG(F_ZF) ) break;
2683 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2685 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2686 val1 = fetch_data_long(M.x86.R_SI);
2687 val2 = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
2688 cmp_long(val1, val2);
2690 val1 = fetch_data_word(M.x86.R_SI);
2691 val2 = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
2692 cmp_word((u16)val1, (u16)val2);
2697 DECODE_CLEAR_SEGOVR();
2701 /****************************************************************************
2704 ****************************************************************************/
2705 void x86emuOp_test_AL_IMM(u8 X86EMU_UNUSED(op1))
2710 DECODE_PRINTF("TEST\tAL,");
2711 imm = fetch_byte_imm();
2712 DECODE_PRINTF2("%04x\n", imm);
2714 test_byte(M.x86.R_AL, (u8)imm);
2715 DECODE_CLEAR_SEGOVR();
2719 /****************************************************************************
2722 ****************************************************************************/
2723 void x86emuOp_test_AX_IMM(u8 X86EMU_UNUSED(op1))
2728 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2729 DECODE_PRINTF("TEST\tEAX,");
2730 srcval = fetch_long_imm();
2732 DECODE_PRINTF("TEST\tAX,");
2733 srcval = fetch_word_imm();
2735 DECODE_PRINTF2("%x\n", srcval);
2737 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2738 test_long(M.x86.R_EAX, srcval);
2740 test_word(M.x86.R_AX, (u16)srcval);
2742 DECODE_CLEAR_SEGOVR();
2746 /****************************************************************************
2749 ****************************************************************************/
2750 void x86emuOp_stos_byte(u8 X86EMU_UNUSED(op1))
2755 DECODE_PRINTF("STOS\tBYTE\n");
2756 if (ACCESS_FLAG(F_DF)) /* down */
2761 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2762 /* dont care whether REPE or REPNE */
2763 /* move them until CX is ZERO. */
2764 while (M.x86.R_CX != 0) {
2765 store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AL);
2769 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2771 store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AL);
2774 DECODE_CLEAR_SEGOVR();
2778 /****************************************************************************
2781 ****************************************************************************/
2782 void x86emuOp_stos_word(u8 X86EMU_UNUSED(op1))
2788 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2789 DECODE_PRINTF("STOS\tDWORD\n");
2790 if (ACCESS_FLAG(F_DF)) /* down */
2795 DECODE_PRINTF("STOS\tWORD\n");
2796 if (ACCESS_FLAG(F_DF)) /* down */
2803 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2804 /* dont care whether REPE or REPNE */
2805 /* move them until CX is ZERO. */
2808 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2811 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2812 store_data_long_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_EAX);
2814 store_data_word_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AX);
2818 DECODE_CLEAR_SEGOVR();
2822 /****************************************************************************
2825 ****************************************************************************/
2826 void x86emuOp_lods_byte(u8 X86EMU_UNUSED(op1))
2831 DECODE_PRINTF("LODS\tBYTE\n");
2833 if (ACCESS_FLAG(F_DF)) /* down */
2837 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2838 /* dont care whether REPE or REPNE */
2839 /* move them until CX is ZERO. */
2840 while (M.x86.R_CX != 0) {
2841 M.x86.R_AL = fetch_data_byte(M.x86.R_SI);
2845 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2847 M.x86.R_AL = fetch_data_byte(M.x86.R_SI);
2850 DECODE_CLEAR_SEGOVR();
2854 /****************************************************************************
2857 ****************************************************************************/
2858 void x86emuOp_lods_word(u8 X86EMU_UNUSED(op1))
2864 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2865 DECODE_PRINTF("LODS\tDWORD\n");
2866 if (ACCESS_FLAG(F_DF)) /* down */
2871 DECODE_PRINTF("LODS\tWORD\n");
2872 if (ACCESS_FLAG(F_DF)) /* down */
2879 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2880 /* dont care whether REPE or REPNE */
2881 /* move them until CX is ZERO. */
2884 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2887 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2888 M.x86.R_EAX = fetch_data_long(M.x86.R_SI);
2890 M.x86.R_AX = fetch_data_word(M.x86.R_SI);
2894 DECODE_CLEAR_SEGOVR();
2898 /****************************************************************************
2901 ****************************************************************************/
2902 void x86emuOp_scas_byte(u8 X86EMU_UNUSED(op1))
2908 DECODE_PRINTF("SCAS\tBYTE\n");
2910 if (ACCESS_FLAG(F_DF)) /* down */
2914 if (M.x86.mode & SYSMODE_PREFIX_REPE) {
2916 /* move them until CX is ZERO. */
2917 while (M.x86.R_CX != 0) {
2918 val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2919 cmp_byte(M.x86.R_AL, val2);
2922 if (ACCESS_FLAG(F_ZF) == 0)
2925 M.x86.mode &= ~SYSMODE_PREFIX_REPE;
2926 } else if (M.x86.mode & SYSMODE_PREFIX_REPNE) {
2928 /* move them until CX is ZERO. */
2929 while (M.x86.R_CX != 0) {
2930 val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2931 cmp_byte(M.x86.R_AL, val2);
2934 if (ACCESS_FLAG(F_ZF))
2935 break; /* zero flag set means equal */
2937 M.x86.mode &= ~SYSMODE_PREFIX_REPNE;
2939 val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2940 cmp_byte(M.x86.R_AL, val2);
2943 DECODE_CLEAR_SEGOVR();
2947 /****************************************************************************
2950 ****************************************************************************/
2951 void x86emuOp_scas_word(u8 X86EMU_UNUSED(op1))
2957 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2958 DECODE_PRINTF("SCAS\tDWORD\n");
2959 if (ACCESS_FLAG(F_DF)) /* down */
2964 DECODE_PRINTF("SCAS\tWORD\n");
2965 if (ACCESS_FLAG(F_DF)) /* down */
2971 if (M.x86.mode & SYSMODE_PREFIX_REPE) {
2973 /* move them until CX is ZERO. */
2974 while (M.x86.R_CX != 0) {
2975 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2976 val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
2977 cmp_long(M.x86.R_EAX, val);
2979 val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
2980 cmp_word(M.x86.R_AX, (u16)val);
2984 if (ACCESS_FLAG(F_ZF) == 0)
2987 M.x86.mode &= ~SYSMODE_PREFIX_REPE;
2988 } else if (M.x86.mode & SYSMODE_PREFIX_REPNE) {
2990 /* move them until CX is ZERO. */
2991 while (M.x86.R_CX != 0) {
2992 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2993 val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
2994 cmp_long(M.x86.R_EAX, val);
2996 val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
2997 cmp_word(M.x86.R_AX, (u16)val);
3001 if (ACCESS_FLAG(F_ZF))
3002 break; /* zero flag set means equal */
3004 M.x86.mode &= ~SYSMODE_PREFIX_REPNE;
3006 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3007 val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
3008 cmp_long(M.x86.R_EAX, val);
3010 val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
3011 cmp_word(M.x86.R_AX, (u16)val);
3015 DECODE_CLEAR_SEGOVR();
3019 /****************************************************************************
3021 Handles opcode 0xb0 - 0xb7
3022 ****************************************************************************/
3023 void x86emuOp_mov_byte_register_IMM(u8 op1)
3028 DECODE_PRINTF("MOV\t");
3029 ptr = DECODE_RM_BYTE_REGISTER(op1 & 0x7);
3031 imm = fetch_byte_imm();
3032 DECODE_PRINTF2("%x\n", imm);
3035 DECODE_CLEAR_SEGOVR();
3039 /****************************************************************************
3041 Handles opcode 0xb8 - 0xbf
3042 ****************************************************************************/
3043 void x86emuOp_mov_word_register_IMM(u8 X86EMU_UNUSED(op1))
3050 DECODE_PRINTF("MOV\t");
3051 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3053 reg32 = DECODE_RM_LONG_REGISTER(op1);
3054 srcval = fetch_long_imm();
3055 DECODE_PRINTF2(",%x\n", srcval);
3060 reg16 = DECODE_RM_WORD_REGISTER(op1);
3061 srcval = fetch_word_imm();
3062 DECODE_PRINTF2(",%x\n", srcval);
3064 *reg16 = (u16)srcval;
3066 DECODE_CLEAR_SEGOVR();
3070 /****************************************************************************
3073 ****************************************************************************/
3074 void x86emuOp_opcC0_byte_RM_MEM(u8 X86EMU_UNUSED(op1))
3083 * Yet another weirdo special case instruction format. Part of
3084 * the opcode held below in "RH". Doubly nested case would
3085 * result, except that the decoded instruction
3088 FETCH_DECODE_MODRM(mod, rh, rl);
3090 if (DEBUG_DECODE()) {
3091 /* XXX DECODE_PRINTF may be changed to something more
3092 general, so that it is important to leave the strings
3093 in the same format, even though the result is that the
3094 above test is done twice. */
3098 DECODE_PRINTF("ROL\t");
3101 DECODE_PRINTF("ROR\t");
3104 DECODE_PRINTF("RCL\t");
3107 DECODE_PRINTF("RCR\t");
3110 DECODE_PRINTF("SHL\t");
3113 DECODE_PRINTF("SHR\t");
3116 DECODE_PRINTF("SAL\t");
3119 DECODE_PRINTF("SAR\t");
3124 /* know operation, decode the mod byte to find the addressing
3127 DECODE_PRINTF("BYTE PTR ");
3128 destoffset = decode_rmXX_address(mod, rl);
3129 amt = fetch_byte_imm();
3130 DECODE_PRINTF2(",%x\n", amt);
3131 destval = fetch_data_byte(destoffset);
3133 destval = (*opcD0_byte_operation[rh]) (destval, amt);
3134 store_data_byte(destoffset, destval);
3135 } else { /* register to register */
3136 destreg = DECODE_RM_BYTE_REGISTER(rl);
3137 amt = fetch_byte_imm();
3138 DECODE_PRINTF2(",%x\n", amt);
3140 destval = (*opcD0_byte_operation[rh]) (*destreg, amt);
3143 DECODE_CLEAR_SEGOVR();
3147 /****************************************************************************
3150 ****************************************************************************/
3151 void x86emuOp_opcC1_word_RM_MEM(u8 X86EMU_UNUSED(op1))
3158 * Yet another weirdo special case instruction format. Part of
3159 * the opcode held below in "RH". Doubly nested case would
3160 * result, except that the decoded instruction
3163 FETCH_DECODE_MODRM(mod, rh, rl);
3165 if (DEBUG_DECODE()) {
3166 /* XXX DECODE_PRINTF may be changed to something more
3167 general, so that it is important to leave the strings
3168 in the same format, even though the result is that the
3169 above test is done twice. */
3173 DECODE_PRINTF("ROL\t");
3176 DECODE_PRINTF("ROR\t");
3179 DECODE_PRINTF("RCL\t");
3182 DECODE_PRINTF("RCR\t");
3185 DECODE_PRINTF("SHL\t");
3188 DECODE_PRINTF("SHR\t");
3191 DECODE_PRINTF("SAL\t");
3194 DECODE_PRINTF("SAR\t");
3199 /* know operation, decode the mod byte to find the addressing
3202 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3205 DECODE_PRINTF("DWORD PTR ");
3206 destoffset = decode_rmXX_address(mod, rl);
3207 amt = fetch_byte_imm();
3208 DECODE_PRINTF2(",%x\n", amt);
3209 destval = fetch_data_long(destoffset);
3211 destval = (*opcD1_long_operation[rh]) (destval, amt);
3212 store_data_long(destoffset, destval);
3216 DECODE_PRINTF("WORD PTR ");
3217 destoffset = decode_rmXX_address(mod, rl);
3218 amt = fetch_byte_imm();
3219 DECODE_PRINTF2(",%x\n", amt);
3220 destval = fetch_data_word(destoffset);
3222 destval = (*opcD1_word_operation[rh]) (destval, amt);
3223 store_data_word(destoffset, destval);
3225 } else { /* register to register */
3226 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3229 destreg = DECODE_RM_LONG_REGISTER(rl);
3230 amt = fetch_byte_imm();
3231 DECODE_PRINTF2(",%x\n", amt);
3233 *destreg = (*opcD1_long_operation[rh]) (*destreg, amt);
3237 destreg = DECODE_RM_WORD_REGISTER(rl);
3238 amt = fetch_byte_imm();
3239 DECODE_PRINTF2(",%x\n", amt);
3241 *destreg = (*opcD1_word_operation[rh]) (*destreg, amt);
3244 DECODE_CLEAR_SEGOVR();
3248 /****************************************************************************
3251 ****************************************************************************/
3252 void x86emuOp_ret_near_IMM(u8 X86EMU_UNUSED(op1))
3257 DECODE_PRINTF("RET\t");
3258 imm = fetch_word_imm();
3259 DECODE_PRINTF2("%x\n", imm);
3260 RETURN_TRACE("RET",M.x86.saved_cs,M.x86.saved_ip);
3262 M.x86.R_IP = pop_word();
3264 DECODE_CLEAR_SEGOVR();
3268 /****************************************************************************
3271 ****************************************************************************/
3272 void x86emuOp_ret_near(u8 X86EMU_UNUSED(op1))
3275 DECODE_PRINTF("RET\n");
3276 RETURN_TRACE("RET",M.x86.saved_cs,M.x86.saved_ip);
3278 M.x86.R_IP = pop_word();
3279 DECODE_CLEAR_SEGOVR();
3283 /****************************************************************************
3286 ****************************************************************************/
3287 void x86emuOp_les_R_IMM(u8 X86EMU_UNUSED(op1))
3294 DECODE_PRINTF("LES\t");
3295 FETCH_DECODE_MODRM(mod, rh, rl);
3297 dstreg = DECODE_RM_WORD_REGISTER(rh);
3299 srcoffset = decode_rmXX_address(mod, rl);
3300 DECODE_PRINTF("\n");
3302 *dstreg = fetch_data_word(srcoffset);
3303 M.x86.R_ES = fetch_data_word(srcoffset + 2);
3305 /* else UNDEFINED! register to register */
3307 DECODE_CLEAR_SEGOVR();
3311 /****************************************************************************
3314 ****************************************************************************/
3315 void x86emuOp_lds_R_IMM(u8 X86EMU_UNUSED(op1))
3322 DECODE_PRINTF("LDS\t");
3323 FETCH_DECODE_MODRM(mod, rh, rl);
3325 dstreg = DECODE_RM_WORD_REGISTER(rh);
3327 srcoffset = decode_rmXX_address(mod, rl);
3328 DECODE_PRINTF("\n");
3330 *dstreg = fetch_data_word(srcoffset);
3331 M.x86.R_DS = fetch_data_word(srcoffset + 2);
3333 /* else UNDEFINED! */
3334 DECODE_CLEAR_SEGOVR();
3338 /****************************************************************************
3341 ****************************************************************************/
3342 void x86emuOp_mov_byte_RM_IMM(u8 X86EMU_UNUSED(op1))
3350 DECODE_PRINTF("MOV\t");
3351 FETCH_DECODE_MODRM(mod, rh, rl);
3353 DECODE_PRINTF("ILLEGAL DECODE OF OPCODE c6\n");
3357 DECODE_PRINTF("BYTE PTR ");
3358 destoffset = decode_rmXX_address(mod, rl);
3359 imm = fetch_byte_imm();
3360 DECODE_PRINTF2(",%2x\n", imm);
3362 store_data_byte(destoffset, imm);
3363 } else { /* register to register */
3364 destreg = DECODE_RM_BYTE_REGISTER(rl);
3365 imm = fetch_byte_imm();
3366 DECODE_PRINTF2(",%2x\n", imm);
3370 DECODE_CLEAR_SEGOVR();
3374 /****************************************************************************
3377 ****************************************************************************/
3378 void x86emuOp_mov_word_RM_IMM(u8 X86EMU_UNUSED(op1))
3384 DECODE_PRINTF("MOV\t");
3385 FETCH_DECODE_MODRM(mod, rh, rl);
3387 DECODE_PRINTF("ILLEGAL DECODE OF OPCODE 8F\n");
3391 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3394 DECODE_PRINTF("DWORD PTR ");
3395 destoffset = decode_rmXX_address(mod, rl);
3396 imm = fetch_long_imm();
3397 DECODE_PRINTF2(",%x\n", imm);
3399 store_data_long(destoffset, imm);
3403 DECODE_PRINTF("WORD PTR ");
3404 destoffset = decode_rmXX_address(mod, rl);
3405 imm = fetch_word_imm();
3406 DECODE_PRINTF2(",%x\n", imm);
3408 store_data_word(destoffset, imm);
3410 } else { /* register to register */
3411 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3415 destreg = DECODE_RM_LONG_REGISTER(rl);
3416 imm = fetch_long_imm();
3417 DECODE_PRINTF2(",%x\n", imm);
3424 destreg = DECODE_RM_WORD_REGISTER(rl);
3425 imm = fetch_word_imm();
3426 DECODE_PRINTF2(",%x\n", imm);
3431 DECODE_CLEAR_SEGOVR();
3435 /****************************************************************************
3438 ****************************************************************************/
3439 void x86emuOp_enter(u8 X86EMU_UNUSED(op1))
3441 u16 local,frame_pointer;
3446 local = fetch_word_imm();
3447 nesting = fetch_byte_imm();
3448 DECODE_PRINTF2("ENTER %x\n", local);
3449 DECODE_PRINTF2(",%x\n", nesting);
3451 push_word(M.x86.R_BP);
3452 frame_pointer = M.x86.R_SP;
3454 for (i = 1; i < nesting; i++) {
3456 push_word(fetch_data_word_abs(M.x86.R_SS, M.x86.R_BP));
3458 push_word(frame_pointer);
3460 M.x86.R_BP = frame_pointer;
3461 M.x86.R_SP = (u16)(M.x86.R_SP - local);
3462 DECODE_CLEAR_SEGOVR();
3466 /****************************************************************************
3469 ****************************************************************************/
3470 void x86emuOp_leave(u8 X86EMU_UNUSED(op1))
3473 DECODE_PRINTF("LEAVE\n");
3475 M.x86.R_SP = M.x86.R_BP;
3476 M.x86.R_BP = pop_word();
3477 DECODE_CLEAR_SEGOVR();
3481 /****************************************************************************
3484 ****************************************************************************/
3485 void x86emuOp_ret_far_IMM(u8 X86EMU_UNUSED(op1))
3490 DECODE_PRINTF("RETF\t");
3491 imm = fetch_word_imm();
3492 DECODE_PRINTF2("%x\n", imm);
3493 RETURN_TRACE("RETF",M.x86.saved_cs,M.x86.saved_ip);
3495 M.x86.R_IP = pop_word();
3496 M.x86.R_CS = pop_word();
3498 DECODE_CLEAR_SEGOVR();
3502 /****************************************************************************
3505 ****************************************************************************/
3506 void x86emuOp_ret_far(u8 X86EMU_UNUSED(op1))
3509 DECODE_PRINTF("RETF\n");
3510 RETURN_TRACE("RETF",M.x86.saved_cs,M.x86.saved_ip);
3512 M.x86.R_IP = pop_word();
3513 M.x86.R_CS = pop_word();
3514 DECODE_CLEAR_SEGOVR();
3518 /****************************************************************************
3521 ****************************************************************************/
3522 void x86emuOp_int3(u8 X86EMU_UNUSED(op1))
3527 DECODE_PRINTF("INT 3\n");
3528 tmp = (u16) mem_access_word(3 * 4 + 2);
3529 /* access the segment register */
3531 if (_X86EMU_intrTab[3]) {
3532 (*_X86EMU_intrTab[3])(3);
3534 push_word((u16)M.x86.R_FLG);
3537 push_word(M.x86.R_CS);
3538 M.x86.R_CS = mem_access_word(3 * 4 + 2);
3539 push_word(M.x86.R_IP);
3540 M.x86.R_IP = mem_access_word(3 * 4);
3542 DECODE_CLEAR_SEGOVR();
3546 /****************************************************************************
3549 ****************************************************************************/
3550 void x86emuOp_int_IMM(u8 X86EMU_UNUSED(op1))
3556 DECODE_PRINTF("INT\t");
3557 intnum = fetch_byte_imm();
3558 DECODE_PRINTF2("%x\n", intnum);
3559 tmp = mem_access_word(intnum * 4 + 2);
3561 if (_X86EMU_intrTab[intnum]) {
3562 (*_X86EMU_intrTab[intnum])(intnum);
3564 push_word((u16)M.x86.R_FLG);
3567 push_word(M.x86.R_CS);
3568 M.x86.R_CS = mem_access_word(intnum * 4 + 2);
3569 push_word(M.x86.R_IP);
3570 M.x86.R_IP = mem_access_word(intnum * 4);
3572 DECODE_CLEAR_SEGOVR();
3576 /****************************************************************************
3579 ****************************************************************************/
3580 void x86emuOp_into(u8 X86EMU_UNUSED(op1))
3585 DECODE_PRINTF("INTO\n");
3587 if (ACCESS_FLAG(F_OF)) {
3588 tmp = mem_access_word(4 * 4 + 2);
3589 if (_X86EMU_intrTab[4]) {
3590 (*_X86EMU_intrTab[4])(4);
3592 push_word((u16)M.x86.R_FLG);
3595 push_word(M.x86.R_CS);
3596 M.x86.R_CS = mem_access_word(4 * 4 + 2);
3597 push_word(M.x86.R_IP);
3598 M.x86.R_IP = mem_access_word(4 * 4);
3601 DECODE_CLEAR_SEGOVR();
3605 /****************************************************************************
3608 ****************************************************************************/
3609 void x86emuOp_iret(u8 X86EMU_UNUSED(op1))
3612 DECODE_PRINTF("IRET\n");
3616 M.x86.R_IP = pop_word();
3617 M.x86.R_CS = pop_word();
3618 M.x86.R_FLG = pop_word();
3619 DECODE_CLEAR_SEGOVR();
3623 /****************************************************************************
3626 ****************************************************************************/
3627 void x86emuOp_opcD0_byte_RM_1(u8 X86EMU_UNUSED(op1))
3635 * Yet another weirdo special case instruction format. Part of
3636 * the opcode held below in "RH". Doubly nested case would
3637 * result, except that the decoded instruction
3640 FETCH_DECODE_MODRM(mod, rh, rl);
3642 if (DEBUG_DECODE()) {
3643 /* XXX DECODE_PRINTF may be changed to something more
3644 general, so that it is important to leave the strings
3645 in the same format, even though the result is that the
3646 above test is done twice. */
3649 DECODE_PRINTF("ROL\t");
3652 DECODE_PRINTF("ROR\t");
3655 DECODE_PRINTF("RCL\t");
3658 DECODE_PRINTF("RCR\t");
3661 DECODE_PRINTF("SHL\t");
3664 DECODE_PRINTF("SHR\t");
3667 DECODE_PRINTF("SAL\t");
3670 DECODE_PRINTF("SAR\t");
3675 /* know operation, decode the mod byte to find the addressing
3678 DECODE_PRINTF("BYTE PTR ");
3679 destoffset = decode_rmXX_address(mod, rl);
3680 DECODE_PRINTF(",1\n");
3681 destval = fetch_data_byte(destoffset);
3683 destval = (*opcD0_byte_operation[rh]) (destval, 1);
3684 store_data_byte(destoffset, destval);
3685 } else { /* register to register */
3686 destreg = DECODE_RM_BYTE_REGISTER(rl);
3687 DECODE_PRINTF(",1\n");
3689 destval = (*opcD0_byte_operation[rh]) (*destreg, 1);
3692 DECODE_CLEAR_SEGOVR();
3696 /****************************************************************************
3699 ****************************************************************************/
3700 void x86emuOp_opcD1_word_RM_1(u8 X86EMU_UNUSED(op1))
3706 * Yet another weirdo special case instruction format. Part of
3707 * the opcode held below in "RH". Doubly nested case would
3708 * result, except that the decoded instruction
3711 FETCH_DECODE_MODRM(mod, rh, rl);
3713 if (DEBUG_DECODE()) {
3714 /* XXX DECODE_PRINTF may be changed to something more
3715 general, so that it is important to leave the strings
3716 in the same format, even though the result is that the
3717 above test is done twice. */
3720 DECODE_PRINTF("ROL\t");
3723 DECODE_PRINTF("ROR\t");
3726 DECODE_PRINTF("RCL\t");
3729 DECODE_PRINTF("RCR\t");
3732 DECODE_PRINTF("SHL\t");
3735 DECODE_PRINTF("SHR\t");
3738 DECODE_PRINTF("SAL\t");
3741 DECODE_PRINTF("SAR\t");
3746 /* know operation, decode the mod byte to find the addressing
3749 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3752 DECODE_PRINTF("DWORD PTR ");
3753 destoffset = decode_rmXX_address(mod, rl);
3754 DECODE_PRINTF(",1\n");
3755 destval = fetch_data_long(destoffset);
3757 destval = (*opcD1_long_operation[rh]) (destval, 1);
3758 store_data_long(destoffset, destval);
3762 DECODE_PRINTF("WORD PTR ");
3763 destoffset = decode_rmXX_address(mod, rl);
3764 DECODE_PRINTF(",1\n");
3765 destval = fetch_data_word(destoffset);
3767 destval = (*opcD1_word_operation[rh]) (destval, 1);
3768 store_data_word(destoffset, destval);
3770 } else { /* register to register */
3771 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3775 destreg = DECODE_RM_LONG_REGISTER(rl);
3776 DECODE_PRINTF(",1\n");
3778 destval = (*opcD1_long_operation[rh]) (*destreg, 1);
3784 destreg = DECODE_RM_WORD_REGISTER(rl);
3785 DECODE_PRINTF(",1\n");
3787 destval = (*opcD1_word_operation[rh]) (*destreg, 1);
3791 DECODE_CLEAR_SEGOVR();
3795 /****************************************************************************
3798 ****************************************************************************/
3799 void x86emuOp_opcD2_byte_RM_CL(u8 X86EMU_UNUSED(op1))
3808 * Yet another weirdo special case instruction format. Part of
3809 * the opcode held below in "RH". Doubly nested case would
3810 * result, except that the decoded instruction
3813 FETCH_DECODE_MODRM(mod, rh, rl);
3815 if (DEBUG_DECODE()) {
3816 /* XXX DECODE_PRINTF may be changed to something more
3817 general, so that it is important to leave the strings
3818 in the same format, even though the result is that the
3819 above test is done twice. */
3822 DECODE_PRINTF("ROL\t");
3825 DECODE_PRINTF("ROR\t");
3828 DECODE_PRINTF("RCL\t");
3831 DECODE_PRINTF("RCR\t");
3834 DECODE_PRINTF("SHL\t");
3837 DECODE_PRINTF("SHR\t");
3840 DECODE_PRINTF("SAL\t");
3843 DECODE_PRINTF("SAR\t");
3848 /* know operation, decode the mod byte to find the addressing
3852 DECODE_PRINTF("BYTE PTR ");
3853 destoffset = decode_rmXX_address(mod, rl);
3854 DECODE_PRINTF(",CL\n");
3855 destval = fetch_data_byte(destoffset);
3857 destval = (*opcD0_byte_operation[rh]) (destval, amt);
3858 store_data_byte(destoffset, destval);
3859 } else { /* register to register */
3860 destreg = DECODE_RM_BYTE_REGISTER(rl);
3861 DECODE_PRINTF(",CL\n");
3863 destval = (*opcD0_byte_operation[rh]) (*destreg, amt);
3866 DECODE_CLEAR_SEGOVR();
3870 /****************************************************************************
3873 ****************************************************************************/
3874 void x86emuOp_opcD3_word_RM_CL(u8 X86EMU_UNUSED(op1))
3881 * Yet another weirdo special case instruction format. Part of
3882 * the opcode held below in "RH". Doubly nested case would
3883 * result, except that the decoded instruction
3886 FETCH_DECODE_MODRM(mod, rh, rl);
3888 if (DEBUG_DECODE()) {
3889 /* XXX DECODE_PRINTF may be changed to something more
3890 general, so that it is important to leave the strings
3891 in the same format, even though the result is that the
3892 above test is done twice. */
3895 DECODE_PRINTF("ROL\t");
3898 DECODE_PRINTF("ROR\t");
3901 DECODE_PRINTF("RCL\t");
3904 DECODE_PRINTF("RCR\t");
3907 DECODE_PRINTF("SHL\t");
3910 DECODE_PRINTF("SHR\t");
3913 DECODE_PRINTF("SAL\t");
3916 DECODE_PRINTF("SAR\t");
3921 /* know operation, decode the mod byte to find the addressing
3925 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3928 DECODE_PRINTF("DWORD PTR ");
3929 destoffset = decode_rmXX_address(mod, rl);
3930 DECODE_PRINTF(",CL\n");
3931 destval = fetch_data_long(destoffset);
3933 destval = (*opcD1_long_operation[rh]) (destval, amt);
3934 store_data_long(destoffset, destval);
3938 DECODE_PRINTF("WORD PTR ");
3939 destoffset = decode_rmXX_address(mod, rl);
3940 DECODE_PRINTF(",CL\n");
3941 destval = fetch_data_word(destoffset);
3943 destval = (*opcD1_word_operation[rh]) (destval, amt);
3944 store_data_word(destoffset, destval);
3946 } else { /* register to register */
3947 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3950 destreg = DECODE_RM_LONG_REGISTER(rl);
3951 DECODE_PRINTF(",CL\n");
3953 *destreg = (*opcD1_long_operation[rh]) (*destreg, amt);
3957 destreg = DECODE_RM_WORD_REGISTER(rl);
3958 DECODE_PRINTF(",CL\n");
3960 *destreg = (*opcD1_word_operation[rh]) (*destreg, amt);
3963 DECODE_CLEAR_SEGOVR();
3967 /****************************************************************************
3970 ****************************************************************************/
3971 void x86emuOp_aam(u8 X86EMU_UNUSED(op1))
3976 DECODE_PRINTF("AAM\n");
3977 a = fetch_byte_imm(); /* this is a stupid encoding. */
3979 DECODE_PRINTF("ERROR DECODING AAM\n");
3984 /* note the type change here --- returning AL and AH in AX. */
3985 M.x86.R_AX = aam_word(M.x86.R_AL);
3986 DECODE_CLEAR_SEGOVR();
3990 /****************************************************************************
3993 ****************************************************************************/
3994 void x86emuOp_aad(u8 X86EMU_UNUSED(op1))
3999 DECODE_PRINTF("AAD\n");
4000 a = fetch_byte_imm();
4002 M.x86.R_AX = aad_word(M.x86.R_AX);
4003 DECODE_CLEAR_SEGOVR();
4007 /* opcode 0xd6 ILLEGAL OPCODE */
4009 /****************************************************************************
4012 ****************************************************************************/
4013 void x86emuOp_xlat(u8 X86EMU_UNUSED(op1))
4018 DECODE_PRINTF("XLAT\n");
4020 addr = (u16)(M.x86.R_BX + (u8)M.x86.R_AL);
4021 M.x86.R_AL = fetch_data_byte(addr);
4022 DECODE_CLEAR_SEGOVR();
4026 /* instuctions D8 .. DF are in i87_ops.c */
4028 /****************************************************************************
4031 ****************************************************************************/
4032 void x86emuOp_loopne(u8 X86EMU_UNUSED(op1))
4037 DECODE_PRINTF("LOOPNE\t");
4038 ip = (s8) fetch_byte_imm();
4039 ip += (s16) M.x86.R_IP;
4040 DECODE_PRINTF2("%04x\n", ip);
4043 if (M.x86.R_CX != 0 && !ACCESS_FLAG(F_ZF)) /* CX != 0 and !ZF */
4045 DECODE_CLEAR_SEGOVR();
4049 /****************************************************************************
4052 ****************************************************************************/
4053 void x86emuOp_loope(u8 X86EMU_UNUSED(op1))
4058 DECODE_PRINTF("LOOPE\t");
4059 ip = (s8) fetch_byte_imm();
4060 ip += (s16) M.x86.R_IP;
4061 DECODE_PRINTF2("%04x\n", ip);
4064 if (M.x86.R_CX != 0 && ACCESS_FLAG(F_ZF)) /* CX != 0 and ZF */
4066 DECODE_CLEAR_SEGOVR();
4070 /****************************************************************************
4073 ****************************************************************************/
4074 void x86emuOp_loop(u8 X86EMU_UNUSED(op1))
4079 DECODE_PRINTF("LOOP\t");
4080 ip = (s8) fetch_byte_imm();
4081 ip += (s16) M.x86.R_IP;
4082 DECODE_PRINTF2("%04x\n", ip);
4085 if (M.x86.R_CX != 0)
4087 DECODE_CLEAR_SEGOVR();
4091 /****************************************************************************
4094 ****************************************************************************/
4095 void x86emuOp_jcxz(u8 X86EMU_UNUSED(op1))
4100 /* jump to byte offset if overflow flag is set */
4102 DECODE_PRINTF("JCXZ\t");
4103 offset = (s8)fetch_byte_imm();
4104 target = (u16)(M.x86.R_IP + offset);
4105 DECODE_PRINTF2("%x\n", target);
4107 if (M.x86.R_CX == 0)
4108 M.x86.R_IP = target;
4109 DECODE_CLEAR_SEGOVR();
4113 /****************************************************************************
4116 ****************************************************************************/
4117 void x86emuOp_in_byte_AL_IMM(u8 X86EMU_UNUSED(op1))
4122 DECODE_PRINTF("IN\t");
4123 port = (u8) fetch_byte_imm();
4124 DECODE_PRINTF2("%x,AL\n", port);
4126 M.x86.R_AL = (*sys_inb)(port);
4127 DECODE_CLEAR_SEGOVR();
4131 /****************************************************************************
4134 ****************************************************************************/
4135 void x86emuOp_in_word_AX_IMM(u8 X86EMU_UNUSED(op1))
4140 DECODE_PRINTF("IN\t");
4141 port = (u8) fetch_byte_imm();
4142 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4143 DECODE_PRINTF2("EAX,%x\n", port);
4145 DECODE_PRINTF2("AX,%x\n", port);
4148 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4149 M.x86.R_EAX = (*sys_inl)(port);
4151 M.x86.R_AX = (*sys_inw)(port);
4153 DECODE_CLEAR_SEGOVR();
4157 /****************************************************************************
4160 ****************************************************************************/
4161 void x86emuOp_out_byte_IMM_AL(u8 X86EMU_UNUSED(op1))
4166 DECODE_PRINTF("OUT\t");
4167 port = (u8) fetch_byte_imm();
4168 DECODE_PRINTF2("%x,AL\n", port);
4170 (*sys_outb)(port, M.x86.R_AL);
4171 DECODE_CLEAR_SEGOVR();
4175 /****************************************************************************
4178 ****************************************************************************/
4179 void x86emuOp_out_word_IMM_AX(u8 X86EMU_UNUSED(op1))
4184 DECODE_PRINTF("OUT\t");
4185 port = (u8) fetch_byte_imm();
4186 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4187 DECODE_PRINTF2("%x,EAX\n", port);
4189 DECODE_PRINTF2("%x,AX\n", port);
4192 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4193 (*sys_outl)(port, M.x86.R_EAX);
4195 (*sys_outw)(port, M.x86.R_AX);
4197 DECODE_CLEAR_SEGOVR();
4201 /****************************************************************************
4204 ****************************************************************************/
4205 void x86emuOp_call_near_IMM(u8 X86EMU_UNUSED(op1))
4210 DECODE_PRINTF("CALL\t");
4211 ip = (s16) fetch_word_imm();
4212 ip += (s16) M.x86.R_IP; /* CHECK SIGN */
4213 DECODE_PRINTF2("%04x\n", ip);
4214 CALL_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, ip, "");
4216 push_word(M.x86.R_IP);
4218 DECODE_CLEAR_SEGOVR();
4222 /****************************************************************************
4225 ****************************************************************************/
4226 void x86emuOp_jump_near_IMM(u8 X86EMU_UNUSED(op1))
4231 DECODE_PRINTF("JMP\t");
4232 ip = (s16)fetch_word_imm();
4233 ip += (s16)M.x86.R_IP;
4234 DECODE_PRINTF2("%04x\n", ip);
4236 M.x86.R_IP = (u16)ip;
4237 DECODE_CLEAR_SEGOVR();
4241 /****************************************************************************
4244 ****************************************************************************/
4245 void x86emuOp_jump_far_IMM(u8 X86EMU_UNUSED(op1))
4250 DECODE_PRINTF("JMP\tFAR ");
4251 ip = fetch_word_imm();
4252 cs = fetch_word_imm();
4253 DECODE_PRINTF2("%04x:", cs);
4254 DECODE_PRINTF2("%04x\n", ip);
4258 DECODE_CLEAR_SEGOVR();
4262 /****************************************************************************
4265 ****************************************************************************/
4266 void x86emuOp_jump_byte_IMM(u8 X86EMU_UNUSED(op1))
4272 DECODE_PRINTF("JMP\t");
4273 offset = (s8)fetch_byte_imm();
4274 target = (u16)(M.x86.R_IP + offset);
4275 DECODE_PRINTF2("%x\n", target);
4277 M.x86.R_IP = target;
4278 DECODE_CLEAR_SEGOVR();
4282 /****************************************************************************
4285 ****************************************************************************/
4286 void x86emuOp_in_byte_AL_DX(u8 X86EMU_UNUSED(op1))
4289 DECODE_PRINTF("IN\tAL,DX\n");
4291 M.x86.R_AL = (*sys_inb)(M.x86.R_DX);
4292 DECODE_CLEAR_SEGOVR();
4296 /****************************************************************************
4299 ****************************************************************************/
4300 void x86emuOp_in_word_AX_DX(u8 X86EMU_UNUSED(op1))
4303 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4304 DECODE_PRINTF("IN\tEAX,DX\n");
4306 DECODE_PRINTF("IN\tAX,DX\n");
4309 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4310 M.x86.R_EAX = (*sys_inl)(M.x86.R_DX);
4312 M.x86.R_AX = (*sys_inw)(M.x86.R_DX);
4314 DECODE_CLEAR_SEGOVR();
4318 /****************************************************************************
4321 ****************************************************************************/
4322 void x86emuOp_out_byte_DX_AL(u8 X86EMU_UNUSED(op1))
4325 DECODE_PRINTF("OUT\tDX,AL\n");
4327 (*sys_outb)(M.x86.R_DX, M.x86.R_AL);
4328 DECODE_CLEAR_SEGOVR();
4332 /****************************************************************************
4335 ****************************************************************************/
4336 void x86emuOp_out_word_DX_AX(u8 X86EMU_UNUSED(op1))
4339 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4340 DECODE_PRINTF("OUT\tDX,EAX\n");
4342 DECODE_PRINTF("OUT\tDX,AX\n");
4345 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4346 (*sys_outl)(M.x86.R_DX, M.x86.R_EAX);
4348 (*sys_outw)(M.x86.R_DX, M.x86.R_AX);
4350 DECODE_CLEAR_SEGOVR();
4354 /****************************************************************************
4357 ****************************************************************************/
4358 void x86emuOp_lock(u8 X86EMU_UNUSED(op1))
4361 DECODE_PRINTF("LOCK:\n");
4363 DECODE_CLEAR_SEGOVR();
4367 /*opcode 0xf1 ILLEGAL OPERATION */
4369 /****************************************************************************
4372 ****************************************************************************/
4373 void x86emuOp_repne(u8 X86EMU_UNUSED(op1))
4376 DECODE_PRINTF("REPNE\n");
4378 M.x86.mode |= SYSMODE_PREFIX_REPNE;
4379 DECODE_CLEAR_SEGOVR();
4383 /****************************************************************************
4386 ****************************************************************************/
4387 void x86emuOp_repe(u8 X86EMU_UNUSED(op1))
4390 DECODE_PRINTF("REPE\n");
4392 M.x86.mode |= SYSMODE_PREFIX_REPE;
4393 DECODE_CLEAR_SEGOVR();
4397 /****************************************************************************
4400 ****************************************************************************/
4401 void x86emuOp_halt(u8 X86EMU_UNUSED(op1))
4404 DECODE_PRINTF("HALT\n");
4407 DECODE_CLEAR_SEGOVR();
4411 /****************************************************************************
4414 ****************************************************************************/
4415 void x86emuOp_cmc(u8 X86EMU_UNUSED(op1))
4417 /* complement the carry flag. */
4419 DECODE_PRINTF("CMC\n");
4422 DECODE_CLEAR_SEGOVR();
4426 /****************************************************************************
4429 ****************************************************************************/
4430 void x86emuOp_opcF6_byte_RM(u8 X86EMU_UNUSED(op1))
4437 /* long, drawn out code follows. Double switch for a total
4440 FETCH_DECODE_MODRM(mod, rh, rl);
4441 DECODE_PRINTF(opF6_names[rh]);
4443 DECODE_PRINTF("BYTE PTR ");
4444 destoffset = decode_rmXX_address(mod, rl);
4445 destval = fetch_data_byte(destoffset);
4448 case 0: /* test byte imm */
4450 srcval = fetch_byte_imm();
4451 DECODE_PRINTF2("%02x\n", srcval);
4453 test_byte(destval, srcval);
4456 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4460 DECODE_PRINTF("\n");
4462 destval = not_byte(destval);
4463 store_data_byte(destoffset, destval);
4466 DECODE_PRINTF("\n");
4468 destval = neg_byte(destval);
4469 store_data_byte(destoffset, destval);
4472 DECODE_PRINTF("\n");
4477 DECODE_PRINTF("\n");
4482 DECODE_PRINTF("\n");
4487 DECODE_PRINTF("\n");
4492 } else { /* mod=11 */
4493 destreg = DECODE_RM_BYTE_REGISTER(rl);
4495 case 0: /* test byte imm */
4497 srcval = fetch_byte_imm();
4498 DECODE_PRINTF2("%02x\n", srcval);
4500 test_byte(*destreg, srcval);
4503 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4507 DECODE_PRINTF("\n");
4509 *destreg = not_byte(*destreg);
4512 DECODE_PRINTF("\n");
4514 *destreg = neg_byte(*destreg);
4517 DECODE_PRINTF("\n");
4519 mul_byte(*destreg); /*!!! */
4522 DECODE_PRINTF("\n");
4524 imul_byte(*destreg);
4527 DECODE_PRINTF("\n");
4532 DECODE_PRINTF("\n");
4534 idiv_byte(*destreg);
4538 DECODE_CLEAR_SEGOVR();
4542 /****************************************************************************
4545 ****************************************************************************/
4546 void x86emuOp_opcF7_word_RM(u8 X86EMU_UNUSED(op1))
4552 FETCH_DECODE_MODRM(mod, rh, rl);
4553 DECODE_PRINTF(opF6_names[rh]);
4556 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4557 u32 destval, srcval;
4559 DECODE_PRINTF("DWORD PTR ");
4560 destoffset = decode_rmXX_address(mod, rl);
4561 destval = fetch_data_long(destoffset);
4566 srcval = fetch_long_imm();
4567 DECODE_PRINTF2("%x\n", srcval);
4569 test_long(destval, srcval);
4572 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F7\n");
4576 DECODE_PRINTF("\n");
4578 destval = not_long(destval);
4579 store_data_long(destoffset, destval);
4582 DECODE_PRINTF("\n");
4584 destval = neg_long(destval);
4585 store_data_long(destoffset, destval);
4588 DECODE_PRINTF("\n");
4593 DECODE_PRINTF("\n");
4598 DECODE_PRINTF("\n");
4603 DECODE_PRINTF("\n");
4609 u16 destval, srcval;
4611 DECODE_PRINTF("WORD PTR ");
4612 destoffset = decode_rmXX_address(mod, rl);
4613 destval = fetch_data_word(destoffset);
4616 case 0: /* test word imm */
4618 srcval = fetch_word_imm();
4619 DECODE_PRINTF2("%x\n", srcval);
4621 test_word(destval, srcval);
4624 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F7\n");
4628 DECODE_PRINTF("\n");
4630 destval = not_word(destval);
4631 store_data_word(destoffset, destval);
4634 DECODE_PRINTF("\n");
4636 destval = neg_word(destval);
4637 store_data_word(destoffset, destval);
4640 DECODE_PRINTF("\n");
4645 DECODE_PRINTF("\n");
4650 DECODE_PRINTF("\n");
4655 DECODE_PRINTF("\n");
4662 } else { /* mod=11 */
4664 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4668 destreg = DECODE_RM_LONG_REGISTER(rl);
4671 case 0: /* test word imm */
4673 srcval = fetch_long_imm();
4674 DECODE_PRINTF2("%x\n", srcval);
4676 test_long(*destreg, srcval);
4679 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4683 DECODE_PRINTF("\n");
4685 *destreg = not_long(*destreg);
4688 DECODE_PRINTF("\n");
4690 *destreg = neg_long(*destreg);
4693 DECODE_PRINTF("\n");
4695 mul_long(*destreg); /*!!! */
4698 DECODE_PRINTF("\n");
4700 imul_long(*destreg);
4703 DECODE_PRINTF("\n");
4708 DECODE_PRINTF("\n");
4710 idiv_long(*destreg);
4717 destreg = DECODE_RM_WORD_REGISTER(rl);
4720 case 0: /* test word imm */
4722 srcval = fetch_word_imm();
4723 DECODE_PRINTF2("%x\n", srcval);
4725 test_word(*destreg, srcval);
4728 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4732 DECODE_PRINTF("\n");
4734 *destreg = not_word(*destreg);
4737 DECODE_PRINTF("\n");
4739 *destreg = neg_word(*destreg);
4742 DECODE_PRINTF("\n");
4744 mul_word(*destreg); /*!!! */
4747 DECODE_PRINTF("\n");
4749 imul_word(*destreg);
4752 DECODE_PRINTF("\n");
4757 DECODE_PRINTF("\n");
4759 idiv_word(*destreg);
4764 DECODE_CLEAR_SEGOVR();
4768 /****************************************************************************
4771 ****************************************************************************/
4772 void x86emuOp_clc(u8 X86EMU_UNUSED(op1))
4774 /* clear the carry flag. */
4776 DECODE_PRINTF("CLC\n");
4779 DECODE_CLEAR_SEGOVR();
4783 /****************************************************************************
4786 ****************************************************************************/
4787 void x86emuOp_stc(u8 X86EMU_UNUSED(op1))
4789 /* set the carry flag. */
4791 DECODE_PRINTF("STC\n");
4794 DECODE_CLEAR_SEGOVR();
4798 /****************************************************************************
4801 ****************************************************************************/
4802 void x86emuOp_cli(u8 X86EMU_UNUSED(op1))
4804 /* clear interrupts. */
4806 DECODE_PRINTF("CLI\n");
4809 DECODE_CLEAR_SEGOVR();
4813 /****************************************************************************
4816 ****************************************************************************/
4817 void x86emuOp_sti(u8 X86EMU_UNUSED(op1))
4819 /* enable interrupts. */
4821 DECODE_PRINTF("STI\n");
4824 DECODE_CLEAR_SEGOVR();
4828 /****************************************************************************
4831 ****************************************************************************/
4832 void x86emuOp_cld(u8 X86EMU_UNUSED(op1))
4834 /* clear interrupts. */
4836 DECODE_PRINTF("CLD\n");
4839 DECODE_CLEAR_SEGOVR();
4843 /****************************************************************************
4846 ****************************************************************************/
4847 void x86emuOp_std(u8 X86EMU_UNUSED(op1))
4849 /* clear interrupts. */
4851 DECODE_PRINTF("STD\n");
4854 DECODE_CLEAR_SEGOVR();
4858 /****************************************************************************
4861 ****************************************************************************/
4862 void x86emuOp_opcFE_byte_RM(u8 X86EMU_UNUSED(op1))
4869 /* Yet another special case instruction. */
4871 FETCH_DECODE_MODRM(mod, rh, rl);
4873 if (DEBUG_DECODE()) {
4874 /* XXX DECODE_PRINTF may be changed to something more
4875 general, so that it is important to leave the strings
4876 in the same format, even though the result is that the
4877 above test is done twice. */
4881 DECODE_PRINTF("INC\t");
4884 DECODE_PRINTF("DEC\t");
4892 DECODE_PRINTF2("ILLEGAL OP MAJOR OP 0xFE MINOR OP %x \n", mod);
4899 DECODE_PRINTF("BYTE PTR ");
4900 destoffset = decode_rmXX_address(mod, rl);
4901 DECODE_PRINTF("\n");
4902 destval = fetch_data_byte(destoffset);
4905 destval = inc_byte(destval);
4907 destval = dec_byte(destval);
4908 store_data_byte(destoffset, destval);
4910 destreg = DECODE_RM_BYTE_REGISTER(rl);
4911 DECODE_PRINTF("\n");
4914 *destreg = inc_byte(*destreg);
4916 *destreg = dec_byte(*destreg);
4918 DECODE_CLEAR_SEGOVR();
4922 /****************************************************************************
4925 ****************************************************************************/
4926 void x86emuOp_opcFF_word_RM(u8 X86EMU_UNUSED(op1))
4929 uint destoffset = 0;
4931 u16 destval,destval2;
4933 /* Yet another special case instruction. */
4935 FETCH_DECODE_MODRM(mod, rh, rl);
4937 if (DEBUG_DECODE()) {
4938 /* XXX DECODE_PRINTF may be changed to something more
4939 general, so that it is important to leave the strings
4940 in the same format, even though the result is that the
4941 above test is done twice. */
4945 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4946 DECODE_PRINTF("INC\tDWORD PTR ");
4948 DECODE_PRINTF("INC\tWORD PTR ");
4952 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4953 DECODE_PRINTF("DEC\tDWORD PTR ");
4955 DECODE_PRINTF("DEC\tWORD PTR ");
4959 DECODE_PRINTF("CALL\t ");
4962 DECODE_PRINTF("CALL\tFAR ");
4965 DECODE_PRINTF("JMP\t");
4968 DECODE_PRINTF("JMP\tFAR ");
4971 DECODE_PRINTF("PUSH\t");
4974 DECODE_PRINTF("ILLEGAL DECODING OF OPCODE FF\t");
4981 destoffset = decode_rmXX_address(mod, rl);
4982 DECODE_PRINTF("\n");
4984 case 0: /* inc word ptr ... */
4985 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4988 destval = fetch_data_long(destoffset);
4990 destval = inc_long(destval);
4991 store_data_long(destoffset, destval);
4995 destval = fetch_data_word(destoffset);
4997 destval = inc_word(destval);
4998 store_data_word(destoffset, destval);
5001 case 1: /* dec word ptr ... */
5002 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5005 destval = fetch_data_long(destoffset);
5007 destval = dec_long(destval);
5008 store_data_long(destoffset, destval);
5012 destval = fetch_data_word(destoffset);
5014 destval = dec_word(destval);
5015 store_data_word(destoffset, destval);
5018 case 2: /* call word ptr ... */
5019 destval = fetch_data_word(destoffset);
5021 push_word(M.x86.R_IP);
5022 M.x86.R_IP = destval;
5024 case 3: /* call far ptr ... */
5025 destval = fetch_data_word(destoffset);
5026 destval2 = fetch_data_word(destoffset + 2);
5028 push_word(M.x86.R_CS);
5029 M.x86.R_CS = destval2;
5030 push_word(M.x86.R_IP);
5031 M.x86.R_IP = destval;
5033 case 4: /* jmp word ptr ... */
5034 destval = fetch_data_word(destoffset);
5036 M.x86.R_IP = destval;
5038 case 5: /* jmp far ptr ... */
5039 destval = fetch_data_word(destoffset);
5040 destval2 = fetch_data_word(destoffset + 2);
5042 M.x86.R_IP = destval;
5043 M.x86.R_CS = destval2;
5045 case 6: /* push word ptr ... */
5046 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5049 destval = fetch_data_long(destoffset);
5055 destval = fetch_data_word(destoffset);
5064 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5067 destreg = DECODE_RM_LONG_REGISTER(rl);
5068 DECODE_PRINTF("\n");
5070 *destreg = inc_long(*destreg);
5074 destreg = DECODE_RM_WORD_REGISTER(rl);
5075 DECODE_PRINTF("\n");
5077 *destreg = inc_word(*destreg);
5081 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5084 destreg = DECODE_RM_LONG_REGISTER(rl);
5085 DECODE_PRINTF("\n");
5087 *destreg = dec_long(*destreg);
5091 destreg = DECODE_RM_WORD_REGISTER(rl);
5092 DECODE_PRINTF("\n");
5094 *destreg = dec_word(*destreg);
5097 case 2: /* call word ptr ... */
5098 destreg = DECODE_RM_WORD_REGISTER(rl);
5099 DECODE_PRINTF("\n");
5101 push_word(M.x86.R_IP);
5102 M.x86.R_IP = *destreg;
5104 case 3: /* jmp far ptr ... */
5105 DECODE_PRINTF("OPERATION UNDEFINED 0XFF \n");
5110 case 4: /* jmp ... */
5111 destreg = DECODE_RM_WORD_REGISTER(rl);
5112 DECODE_PRINTF("\n");
5114 M.x86.R_IP = (u16) (*destreg);
5116 case 5: /* jmp far ptr ... */
5117 DECODE_PRINTF("OPERATION UNDEFINED 0XFF \n");
5122 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5125 destreg = DECODE_RM_LONG_REGISTER(rl);
5126 DECODE_PRINTF("\n");
5128 push_long(*destreg);
5132 destreg = DECODE_RM_WORD_REGISTER(rl);
5133 DECODE_PRINTF("\n");
5135 push_word(*destreg);
5140 DECODE_CLEAR_SEGOVR();
5144 /***************************************************************************
5145 * Single byte operation code table:
5146 **************************************************************************/
5147 void (*x86emu_optab[256])(u8) __attribute__ ((section(GOT2_TYPE))) =
5149 /* 0x00 */ x86emuOp_genop_byte_RM_R,
5150 /* 0x01 */ x86emuOp_genop_word_RM_R,
5151 /* 0x02 */ x86emuOp_genop_byte_R_RM,
5152 /* 0x03 */ x86emuOp_genop_word_R_RM,
5153 /* 0x04 */ x86emuOp_genop_byte_AL_IMM,
5154 /* 0x05 */ x86emuOp_genop_word_AX_IMM,
5155 /* 0x06 */ x86emuOp_push_ES,
5156 /* 0x07 */ x86emuOp_pop_ES,
5158 /* 0x08 */ x86emuOp_genop_byte_RM_R,
5159 /* 0x09 */ x86emuOp_genop_word_RM_R,
5160 /* 0x0a */ x86emuOp_genop_byte_R_RM,
5161 /* 0x0b */ x86emuOp_genop_word_R_RM,
5162 /* 0x0c */ x86emuOp_genop_byte_AL_IMM,
5163 /* 0x0d */ x86emuOp_genop_word_AX_IMM,
5164 /* 0x0e */ x86emuOp_push_CS,
5165 /* 0x0f */ x86emuOp_two_byte,
5167 /* 0x10 */ x86emuOp_genop_byte_RM_R,
5168 /* 0x11 */ x86emuOp_genop_word_RM_R,
5169 /* 0x12 */ x86emuOp_genop_byte_R_RM,
5170 /* 0x13 */ x86emuOp_genop_word_R_RM,
5171 /* 0x14 */ x86emuOp_genop_byte_AL_IMM,
5172 /* 0x15 */ x86emuOp_genop_word_AX_IMM,
5173 /* 0x16 */ x86emuOp_push_SS,
5174 /* 0x17 */ x86emuOp_pop_SS,
5176 /* 0x18 */ x86emuOp_genop_byte_RM_R,
5177 /* 0x19 */ x86emuOp_genop_word_RM_R,
5178 /* 0x1a */ x86emuOp_genop_byte_R_RM,
5179 /* 0x1b */ x86emuOp_genop_word_R_RM,
5180 /* 0x1c */ x86emuOp_genop_byte_AL_IMM,
5181 /* 0x1d */ x86emuOp_genop_word_AX_IMM,
5182 /* 0x1e */ x86emuOp_push_DS,
5183 /* 0x1f */ x86emuOp_pop_DS,
5185 /* 0x20 */ x86emuOp_genop_byte_RM_R,
5186 /* 0x21 */ x86emuOp_genop_word_RM_R,
5187 /* 0x22 */ x86emuOp_genop_byte_R_RM,
5188 /* 0x23 */ x86emuOp_genop_word_R_RM,
5189 /* 0x24 */ x86emuOp_genop_byte_AL_IMM,
5190 /* 0x25 */ x86emuOp_genop_word_AX_IMM,
5191 /* 0x26 */ x86emuOp_segovr_ES,
5192 /* 0x27 */ x86emuOp_daa,
5194 /* 0x28 */ x86emuOp_genop_byte_RM_R,
5195 /* 0x29 */ x86emuOp_genop_word_RM_R,
5196 /* 0x2a */ x86emuOp_genop_byte_R_RM,
5197 /* 0x2b */ x86emuOp_genop_word_R_RM,
5198 /* 0x2c */ x86emuOp_genop_byte_AL_IMM,
5199 /* 0x2d */ x86emuOp_genop_word_AX_IMM,
5200 /* 0x2e */ x86emuOp_segovr_CS,
5201 /* 0x2f */ x86emuOp_das,
5203 /* 0x30 */ x86emuOp_genop_byte_RM_R,
5204 /* 0x31 */ x86emuOp_genop_word_RM_R,
5205 /* 0x32 */ x86emuOp_genop_byte_R_RM,
5206 /* 0x33 */ x86emuOp_genop_word_R_RM,
5207 /* 0x34 */ x86emuOp_genop_byte_AL_IMM,
5208 /* 0x35 */ x86emuOp_genop_word_AX_IMM,
5209 /* 0x36 */ x86emuOp_segovr_SS,
5210 /* 0x37 */ x86emuOp_aaa,
5212 /* 0x38 */ x86emuOp_genop_byte_RM_R,
5213 /* 0x39 */ x86emuOp_genop_word_RM_R,
5214 /* 0x3a */ x86emuOp_genop_byte_R_RM,
5215 /* 0x3b */ x86emuOp_genop_word_R_RM,
5216 /* 0x3c */ x86emuOp_genop_byte_AL_IMM,
5217 /* 0x3d */ x86emuOp_genop_word_AX_IMM,
5218 /* 0x3e */ x86emuOp_segovr_DS,
5219 /* 0x3f */ x86emuOp_aas,
5221 /* 0x40 */ x86emuOp_inc_register,
5222 /* 0x41 */ x86emuOp_inc_register,
5223 /* 0x42 */ x86emuOp_inc_register,
5224 /* 0x43 */ x86emuOp_inc_register,
5225 /* 0x44 */ x86emuOp_inc_register,
5226 /* 0x45 */ x86emuOp_inc_register,
5227 /* 0x46 */ x86emuOp_inc_register,
5228 /* 0x47 */ x86emuOp_inc_register,
5230 /* 0x48 */ x86emuOp_dec_register,
5231 /* 0x49 */ x86emuOp_dec_register,
5232 /* 0x4a */ x86emuOp_dec_register,
5233 /* 0x4b */ x86emuOp_dec_register,
5234 /* 0x4c */ x86emuOp_dec_register,
5235 /* 0x4d */ x86emuOp_dec_register,
5236 /* 0x4e */ x86emuOp_dec_register,
5237 /* 0x4f */ x86emuOp_dec_register,
5239 /* 0x50 */ x86emuOp_push_register,
5240 /* 0x51 */ x86emuOp_push_register,
5241 /* 0x52 */ x86emuOp_push_register,
5242 /* 0x53 */ x86emuOp_push_register,
5243 /* 0x54 */ x86emuOp_push_register,
5244 /* 0x55 */ x86emuOp_push_register,
5245 /* 0x56 */ x86emuOp_push_register,
5246 /* 0x57 */ x86emuOp_push_register,
5248 /* 0x58 */ x86emuOp_pop_register,
5249 /* 0x59 */ x86emuOp_pop_register,
5250 /* 0x5a */ x86emuOp_pop_register,
5251 /* 0x5b */ x86emuOp_pop_register,
5252 /* 0x5c */ x86emuOp_pop_register,
5253 /* 0x5d */ x86emuOp_pop_register,
5254 /* 0x5e */ x86emuOp_pop_register,
5255 /* 0x5f */ x86emuOp_pop_register,
5257 /* 0x60 */ x86emuOp_push_all,
5258 /* 0x61 */ x86emuOp_pop_all,
5259 /* 0x62 */ x86emuOp_illegal_op, /* bound */
5260 /* 0x63 */ x86emuOp_illegal_op, /* arpl */
5261 /* 0x64 */ x86emuOp_segovr_FS,
5262 /* 0x65 */ x86emuOp_segovr_GS,
5263 /* 0x66 */ x86emuOp_prefix_data,
5264 /* 0x67 */ x86emuOp_prefix_addr,
5266 /* 0x68 */ x86emuOp_push_word_IMM,
5267 /* 0x69 */ x86emuOp_imul_word_IMM,
5268 /* 0x6a */ x86emuOp_push_byte_IMM,
5269 /* 0x6b */ x86emuOp_imul_byte_IMM,
5270 /* 0x6c */ x86emuOp_ins_byte,
5271 /* 0x6d */ x86emuOp_ins_word,
5272 /* 0x6e */ x86emuOp_outs_byte,
5273 /* 0x6f */ x86emuOp_outs_word,
5275 /* 0x70 */ x86emuOp_jump_near_cond,
5276 /* 0x71 */ x86emuOp_jump_near_cond,
5277 /* 0x72 */ x86emuOp_jump_near_cond,
5278 /* 0x73 */ x86emuOp_jump_near_cond,
5279 /* 0x74 */ x86emuOp_jump_near_cond,
5280 /* 0x75 */ x86emuOp_jump_near_cond,
5281 /* 0x76 */ x86emuOp_jump_near_cond,
5282 /* 0x77 */ x86emuOp_jump_near_cond,
5284 /* 0x78 */ x86emuOp_jump_near_cond,
5285 /* 0x79 */ x86emuOp_jump_near_cond,
5286 /* 0x7a */ x86emuOp_jump_near_cond,
5287 /* 0x7b */ x86emuOp_jump_near_cond,
5288 /* 0x7c */ x86emuOp_jump_near_cond,
5289 /* 0x7d */ x86emuOp_jump_near_cond,
5290 /* 0x7e */ x86emuOp_jump_near_cond,
5291 /* 0x7f */ x86emuOp_jump_near_cond,
5293 /* 0x80 */ x86emuOp_opc80_byte_RM_IMM,
5294 /* 0x81 */ x86emuOp_opc81_word_RM_IMM,
5295 /* 0x82 */ x86emuOp_opc82_byte_RM_IMM,
5296 /* 0x83 */ x86emuOp_opc83_word_RM_IMM,
5297 /* 0x84 */ x86emuOp_test_byte_RM_R,
5298 /* 0x85 */ x86emuOp_test_word_RM_R,
5299 /* 0x86 */ x86emuOp_xchg_byte_RM_R,
5300 /* 0x87 */ x86emuOp_xchg_word_RM_R,
5302 /* 0x88 */ x86emuOp_mov_byte_RM_R,
5303 /* 0x89 */ x86emuOp_mov_word_RM_R,
5304 /* 0x8a */ x86emuOp_mov_byte_R_RM,
5305 /* 0x8b */ x86emuOp_mov_word_R_RM,
5306 /* 0x8c */ x86emuOp_mov_word_RM_SR,
5307 /* 0x8d */ x86emuOp_lea_word_R_M,
5308 /* 0x8e */ x86emuOp_mov_word_SR_RM,
5309 /* 0x8f */ x86emuOp_pop_RM,
5311 /* 0x90 */ x86emuOp_nop,
5312 /* 0x91 */ x86emuOp_xchg_word_AX_register,
5313 /* 0x92 */ x86emuOp_xchg_word_AX_register,
5314 /* 0x93 */ x86emuOp_xchg_word_AX_register,
5315 /* 0x94 */ x86emuOp_xchg_word_AX_register,
5316 /* 0x95 */ x86emuOp_xchg_word_AX_register,
5317 /* 0x96 */ x86emuOp_xchg_word_AX_register,
5318 /* 0x97 */ x86emuOp_xchg_word_AX_register,
5320 /* 0x98 */ x86emuOp_cbw,
5321 /* 0x99 */ x86emuOp_cwd,
5322 /* 0x9a */ x86emuOp_call_far_IMM,
5323 /* 0x9b */ x86emuOp_wait,
5324 /* 0x9c */ x86emuOp_pushf_word,
5325 /* 0x9d */ x86emuOp_popf_word,
5326 /* 0x9e */ x86emuOp_sahf,
5327 /* 0x9f */ x86emuOp_lahf,
5329 /* 0xa0 */ x86emuOp_mov_AL_M_IMM,
5330 /* 0xa1 */ x86emuOp_mov_AX_M_IMM,
5331 /* 0xa2 */ x86emuOp_mov_M_AL_IMM,
5332 /* 0xa3 */ x86emuOp_mov_M_AX_IMM,
5333 /* 0xa4 */ x86emuOp_movs_byte,
5334 /* 0xa5 */ x86emuOp_movs_word,
5335 /* 0xa6 */ x86emuOp_cmps_byte,
5336 /* 0xa7 */ x86emuOp_cmps_word,
5337 /* 0xa8 */ x86emuOp_test_AL_IMM,
5338 /* 0xa9 */ x86emuOp_test_AX_IMM,
5339 /* 0xaa */ x86emuOp_stos_byte,
5340 /* 0xab */ x86emuOp_stos_word,
5341 /* 0xac */ x86emuOp_lods_byte,
5342 /* 0xad */ x86emuOp_lods_word,
5343 /* 0xac */ x86emuOp_scas_byte,
5344 /* 0xad */ x86emuOp_scas_word,
5346 /* 0xb0 */ x86emuOp_mov_byte_register_IMM,
5347 /* 0xb1 */ x86emuOp_mov_byte_register_IMM,
5348 /* 0xb2 */ x86emuOp_mov_byte_register_IMM,
5349 /* 0xb3 */ x86emuOp_mov_byte_register_IMM,
5350 /* 0xb4 */ x86emuOp_mov_byte_register_IMM,
5351 /* 0xb5 */ x86emuOp_mov_byte_register_IMM,
5352 /* 0xb6 */ x86emuOp_mov_byte_register_IMM,
5353 /* 0xb7 */ x86emuOp_mov_byte_register_IMM,
5355 /* 0xb8 */ x86emuOp_mov_word_register_IMM,
5356 /* 0xb9 */ x86emuOp_mov_word_register_IMM,
5357 /* 0xba */ x86emuOp_mov_word_register_IMM,
5358 /* 0xbb */ x86emuOp_mov_word_register_IMM,
5359 /* 0xbc */ x86emuOp_mov_word_register_IMM,
5360 /* 0xbd */ x86emuOp_mov_word_register_IMM,
5361 /* 0xbe */ x86emuOp_mov_word_register_IMM,
5362 /* 0xbf */ x86emuOp_mov_word_register_IMM,
5364 /* 0xc0 */ x86emuOp_opcC0_byte_RM_MEM,
5365 /* 0xc1 */ x86emuOp_opcC1_word_RM_MEM,
5366 /* 0xc2 */ x86emuOp_ret_near_IMM,
5367 /* 0xc3 */ x86emuOp_ret_near,
5368 /* 0xc4 */ x86emuOp_les_R_IMM,
5369 /* 0xc5 */ x86emuOp_lds_R_IMM,
5370 /* 0xc6 */ x86emuOp_mov_byte_RM_IMM,
5371 /* 0xc7 */ x86emuOp_mov_word_RM_IMM,
5372 /* 0xc8 */ x86emuOp_enter,
5373 /* 0xc9 */ x86emuOp_leave,
5374 /* 0xca */ x86emuOp_ret_far_IMM,
5375 /* 0xcb */ x86emuOp_ret_far,
5376 /* 0xcc */ x86emuOp_int3,
5377 /* 0xcd */ x86emuOp_int_IMM,
5378 /* 0xce */ x86emuOp_into,
5379 /* 0xcf */ x86emuOp_iret,
5381 /* 0xd0 */ x86emuOp_opcD0_byte_RM_1,
5382 /* 0xd1 */ x86emuOp_opcD1_word_RM_1,
5383 /* 0xd2 */ x86emuOp_opcD2_byte_RM_CL,
5384 /* 0xd3 */ x86emuOp_opcD3_word_RM_CL,
5385 /* 0xd4 */ x86emuOp_aam,
5386 /* 0xd5 */ x86emuOp_aad,
5387 /* 0xd6 */ x86emuOp_illegal_op, /* Undocumented SETALC instruction */
5388 /* 0xd7 */ x86emuOp_xlat,
5389 /* 0xd8 */ NULL, /*x86emuOp_esc_coprocess_d8,*/
5390 /* 0xd9 */ NULL, /*x86emuOp_esc_coprocess_d9,*/
5391 /* 0xda */ NULL, /*x86emuOp_esc_coprocess_da,*/
5392 /* 0xdb */ NULL, /*x86emuOp_esc_coprocess_db,*/
5393 /* 0xdc */ NULL, /*x86emuOp_esc_coprocess_dc,*/
5394 /* 0xdd */ NULL, /*x86emuOp_esc_coprocess_dd,*/
5395 /* 0xde */ NULL, /*x86emuOp_esc_coprocess_de,*/
5396 /* 0xdf */ NULL, /*x86emuOp_esc_coprocess_df,*/
5398 /* 0xe0 */ x86emuOp_loopne,
5399 /* 0xe1 */ x86emuOp_loope,
5400 /* 0xe2 */ x86emuOp_loop,
5401 /* 0xe3 */ x86emuOp_jcxz,
5402 /* 0xe4 */ x86emuOp_in_byte_AL_IMM,
5403 /* 0xe5 */ x86emuOp_in_word_AX_IMM,
5404 /* 0xe6 */ x86emuOp_out_byte_IMM_AL,
5405 /* 0xe7 */ x86emuOp_out_word_IMM_AX,
5407 /* 0xe8 */ x86emuOp_call_near_IMM,
5408 /* 0xe9 */ x86emuOp_jump_near_IMM,
5409 /* 0xea */ x86emuOp_jump_far_IMM,
5410 /* 0xeb */ x86emuOp_jump_byte_IMM,
5411 /* 0xec */ x86emuOp_in_byte_AL_DX,
5412 /* 0xed */ x86emuOp_in_word_AX_DX,
5413 /* 0xee */ x86emuOp_out_byte_DX_AL,
5414 /* 0xef */ x86emuOp_out_word_DX_AX,
5416 /* 0xf0 */ x86emuOp_lock,
5417 /* 0xf1 */ x86emuOp_illegal_op,
5418 /* 0xf2 */ x86emuOp_repne,
5419 /* 0xf3 */ x86emuOp_repe,
5420 /* 0xf4 */ x86emuOp_halt,
5421 /* 0xf5 */ x86emuOp_cmc,
5422 /* 0xf6 */ x86emuOp_opcF6_byte_RM,
5423 /* 0xf7 */ x86emuOp_opcF7_word_RM,
5425 /* 0xf8 */ x86emuOp_clc,
5426 /* 0xf9 */ x86emuOp_stc,
5427 /* 0xfa */ x86emuOp_cli,
5428 /* 0xfb */ x86emuOp_sti,
5429 /* 0xfc */ x86emuOp_cld,
5430 /* 0xfd */ x86emuOp_std,
5431 /* 0xfe */ x86emuOp_opcFE_byte_RM,
5432 /* 0xff */ x86emuOp_opcFF_word_RM,