1 /****************************************************************************
2 * Realmode X86 Emulator Library
4 * Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved.
5 * Jason Jin <Jason.jin@freescale.com>
7 * Copyright (C) 1991-2004 SciTech Software, Inc.
8 * Copyright (C) David Mosberger-Tang
9 * Copyright (C) 1999 Egbert Eich
11 * ========================================================================
13 * Permission to use, copy, modify, distribute, and sell this software and
14 * its documentation for any purpose is hereby granted without fee,
15 * provided that the above copyright notice appear in all copies and that
16 * both that copyright notice and this permission notice appear in
17 * supporting documentation, and that the name of the authors not be used
18 * in advertising or publicity pertaining to distribution of the software
19 * without specific, written prior permission. The authors makes no
20 * representations about the suitability of this software for any purpose.
21 * It is provided "as is" without express or implied warranty.
23 * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
24 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
25 * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
26 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
27 * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
28 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
29 * PERFORMANCE OF THIS SOFTWARE.
31 * ========================================================================
35 * Developer: Kendall Bennett
37 * Description: This file includes subroutines to implement the decoding
38 * and emulation of all the x86 processor instructions.
40 * There are approximately 250 subroutines in here, which correspond
41 * to the 256 byte-"opcodes" found on the 8086. The table which
42 * dispatches this is found in the files optab.[ch].
44 * Each opcode proc has a comment preceeding it which gives it's table
45 * address. Several opcodes are missing (undefined) in the table.
47 * Each proc includes information for decoding (DECODE_PRINTF and
48 * DECODE_PRINTF2), debugging (TRACE_REGS, SINGLE_STEP), and misc
49 * functions (START_OF_INSTR, END_OF_INSTR).
51 * Many of the procedures are *VERY* similar in coding. This has
52 * allowed for a very large amount of code to be generated in a fairly
53 * short amount of time (i.e. cut, paste, and modify). The result is
54 * that much of the code below could have been folded into subroutines
55 * for a large reduction in size of this file. The downside would be
56 * that there would be a penalty in execution speed. The file could
57 * also have been *MUCH* larger by inlining certain functions which
58 * were called. This could have resulted even faster execution. The
59 * prime directive I used to decide whether to inline the code or to
60 * modularize it, was basically: 1) no unnecessary subroutine calls,
61 * 2) no routines more than about 200 lines in size, and 3) modularize
62 * any code that I might not get right the first time. The fetch_*
63 * subroutines fall into the latter category. The The decode_* fall
64 * into the second category. The coding of the "switch(mod){ .... }"
65 * in many of the subroutines below falls into the first category.
66 * Especially, the coding of {add,and,or,sub,...}_{byte,word}
67 * subroutines are an especially glaring case of the third guideline.
68 * Since so much of the code is cloned from other modules (compare
69 * opcode #00 to opcode #01), making the basic operations subroutine
70 * calls is especially important; otherwise mistakes in coding an
71 * "add" would represent a nightmare in maintenance.
73 * Jason ported this file to u-boot. place all the function pointer in
74 * the got2 sector. Removed some opcode.
76 ****************************************************************************/
78 #include "x86emu/x86emui.h"
80 #if defined(CONFIG_BIOSEMU)
82 /*----------------------------- Implementation ----------------------------*/
84 /* constant arrays to do several instructions in just one function */
87 static char *x86emu_GenOpName[8] = {
88 "ADD", "OR", "ADC", "SBB", "AND", "SUB", "XOR", "CMP"};
91 /* used by several opcodes */
92 static u8 (*genop_byte_operation[])(u8 d, u8 s) __attribute__ ((section(".got2"))) =
104 static u16 (*genop_word_operation[])(u16 d, u16 s) __attribute__ ((section(".got2"))) =
116 static u32 (*genop_long_operation[])(u32 d, u32 s) __attribute__ ((section(".got2"))) =
128 /* used by opcodes 80, c0, d0, and d2. */
129 static u8(*opcD0_byte_operation[])(u8 d, u8 s) __attribute__ ((section(".got2"))) =
137 shl_byte, /* sal_byte === shl_byte by definition */
141 /* used by opcodes c1, d1, and d3. */
142 static u16(*opcD1_word_operation[])(u16 s, u8 d) __attribute__ ((section(".got2"))) =
150 shl_word, /* sal_byte === shl_byte by definition */
154 /* used by opcodes c1, d1, and d3. */
155 static u32 (*opcD1_long_operation[])(u32 s, u8 d) __attribute__ ((section(".got2"))) =
163 shl_long, /* sal_byte === shl_byte by definition */
169 static char *opF6_names[8] =
170 { "TEST\t", "", "NOT\t", "NEG\t", "MUL\t", "IMUL\t", "DIV\t", "IDIV\t" };
174 /****************************************************************************
176 op1 - Instruction op code
179 Handles illegal opcodes.
180 ****************************************************************************/
181 void x86emuOp_illegal_op(
185 if (M.x86.R_SP != 0) {
186 DECODE_PRINTF("ILLEGAL X86 OPCODE\n");
188 DB( printk("%04x:%04x: %02X ILLEGAL X86 OPCODE!\n",
189 M.x86.R_CS, M.x86.R_IP-1,op1));
193 /* If we get here, it means the stack pointer is back to zero
194 * so we are just returning from an emulator service call
195 * so therte is no need to display an error message. We trap
196 * the emulator with an 0xF1 opcode to finish the service
204 /****************************************************************************
206 Handles opcodes 0x00, 0x08, 0x10, 0x18, 0x20, 0x28, 0x30, 0x38
207 ****************************************************************************/
208 void x86emuOp_genop_byte_RM_R(u8 op1)
212 u8 *destreg, *srcreg;
215 op1 = (op1 >> 3) & 0x7;
218 DECODE_PRINTF(x86emu_GenOpName[op1]);
220 FETCH_DECODE_MODRM(mod, rh, rl);
222 { destoffset = decode_rmXX_address(mod,rl);
224 destval = fetch_data_byte(destoffset);
225 srcreg = DECODE_RM_BYTE_REGISTER(rh);
228 destval = genop_byte_operation[op1](destval, *srcreg);
229 store_data_byte(destoffset, destval);
232 { /* register to register */
233 destreg = DECODE_RM_BYTE_REGISTER(rl);
235 srcreg = DECODE_RM_BYTE_REGISTER(rh);
238 *destreg = genop_byte_operation[op1](*destreg, *srcreg);
240 DECODE_CLEAR_SEGOVR();
244 /****************************************************************************
246 Handles opcodes 0x01, 0x09, 0x11, 0x19, 0x21, 0x29, 0x31, 0x39
247 ****************************************************************************/
248 void x86emuOp_genop_word_RM_R(u8 op1)
253 op1 = (op1 >> 3) & 0x7;
256 DECODE_PRINTF(x86emu_GenOpName[op1]);
258 FETCH_DECODE_MODRM(mod, rh, rl);
261 destoffset = decode_rmXX_address(mod,rl);
262 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
267 destval = fetch_data_long(destoffset);
268 srcreg = DECODE_RM_LONG_REGISTER(rh);
271 destval = genop_long_operation[op1](destval, *srcreg);
272 store_data_long(destoffset, destval);
278 destval = fetch_data_word(destoffset);
279 srcreg = DECODE_RM_WORD_REGISTER(rh);
282 destval = genop_word_operation[op1](destval, *srcreg);
283 store_data_word(destoffset, destval);
285 } else { /* register to register */
286 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
287 u32 *destreg,*srcreg;
289 destreg = DECODE_RM_LONG_REGISTER(rl);
291 srcreg = DECODE_RM_LONG_REGISTER(rh);
294 *destreg = genop_long_operation[op1](*destreg, *srcreg);
296 u16 *destreg,*srcreg;
298 destreg = DECODE_RM_WORD_REGISTER(rl);
300 srcreg = DECODE_RM_WORD_REGISTER(rh);
303 *destreg = genop_word_operation[op1](*destreg, *srcreg);
306 DECODE_CLEAR_SEGOVR();
310 /****************************************************************************
312 Handles opcodes 0x02, 0x0a, 0x12, 0x1a, 0x22, 0x2a, 0x32, 0x3a
313 ****************************************************************************/
314 void x86emuOp_genop_byte_R_RM(u8 op1)
317 u8 *destreg, *srcreg;
321 op1 = (op1 >> 3) & 0x7;
324 DECODE_PRINTF(x86emu_GenOpName[op1]);
326 FETCH_DECODE_MODRM(mod, rh, rl);
328 destreg = DECODE_RM_BYTE_REGISTER(rh);
330 srcoffset = decode_rmXX_address(mod,rl);
331 srcval = fetch_data_byte(srcoffset);
332 } else { /* register to register */
333 destreg = DECODE_RM_BYTE_REGISTER(rh);
335 srcreg = DECODE_RM_BYTE_REGISTER(rl);
340 *destreg = genop_byte_operation[op1](*destreg, srcval);
342 DECODE_CLEAR_SEGOVR();
346 /****************************************************************************
348 Handles opcodes 0x03, 0x0b, 0x13, 0x1b, 0x23, 0x2b, 0x33, 0x3b
349 ****************************************************************************/
350 void x86emuOp_genop_word_R_RM(u8 op1)
354 u32 *destreg32, srcval;
357 op1 = (op1 >> 3) & 0x7;
360 DECODE_PRINTF(x86emu_GenOpName[op1]);
362 FETCH_DECODE_MODRM(mod, rh, rl);
364 srcoffset = decode_rmXX_address(mod,rl);
365 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
366 destreg32 = DECODE_RM_LONG_REGISTER(rh);
368 srcval = fetch_data_long(srcoffset);
371 *destreg32 = genop_long_operation[op1](*destreg32, srcval);
373 destreg = DECODE_RM_WORD_REGISTER(rh);
375 srcval = fetch_data_word(srcoffset);
378 *destreg = genop_word_operation[op1](*destreg, srcval);
380 } else { /* register to register */
381 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
383 destreg32 = DECODE_RM_LONG_REGISTER(rh);
385 srcreg = DECODE_RM_LONG_REGISTER(rl);
388 *destreg32 = genop_long_operation[op1](*destreg32, *srcreg);
391 destreg = DECODE_RM_WORD_REGISTER(rh);
393 srcreg = DECODE_RM_WORD_REGISTER(rl);
396 *destreg = genop_word_operation[op1](*destreg, *srcreg);
399 DECODE_CLEAR_SEGOVR();
403 /****************************************************************************
405 Handles opcodes 0x04, 0x0c, 0x14, 0x1c, 0x24, 0x2c, 0x34, 0x3c
406 ****************************************************************************/
407 void x86emuOp_genop_byte_AL_IMM(u8 op1)
411 op1 = (op1 >> 3) & 0x7;
414 DECODE_PRINTF(x86emu_GenOpName[op1]);
415 DECODE_PRINTF("\tAL,");
416 srcval = fetch_byte_imm();
417 DECODE_PRINTF2("%x\n", srcval);
419 M.x86.R_AL = genop_byte_operation[op1](M.x86.R_AL, srcval);
420 DECODE_CLEAR_SEGOVR();
424 /****************************************************************************
426 Handles opcodes 0x05, 0x0d, 0x15, 0x1d, 0x25, 0x2d, 0x35, 0x3d
427 ****************************************************************************/
428 void x86emuOp_genop_word_AX_IMM(u8 op1)
432 op1 = (op1 >> 3) & 0x7;
435 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
436 DECODE_PRINTF(x86emu_GenOpName[op1]);
437 DECODE_PRINTF("\tEAX,");
438 srcval = fetch_long_imm();
440 DECODE_PRINTF(x86emu_GenOpName[op1]);
441 DECODE_PRINTF("\tAX,");
442 srcval = fetch_word_imm();
444 DECODE_PRINTF2("%x\n", srcval);
446 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
447 M.x86.R_EAX = genop_long_operation[op1](M.x86.R_EAX, srcval);
449 M.x86.R_AX = genop_word_operation[op1](M.x86.R_AX, (u16)srcval);
451 DECODE_CLEAR_SEGOVR();
455 /****************************************************************************
458 ****************************************************************************/
459 void x86emuOp_push_ES(u8 X86EMU_UNUSED(op1))
462 DECODE_PRINTF("PUSH\tES\n");
464 push_word(M.x86.R_ES);
465 DECODE_CLEAR_SEGOVR();
469 /****************************************************************************
472 ****************************************************************************/
473 void x86emuOp_pop_ES(u8 X86EMU_UNUSED(op1))
476 DECODE_PRINTF("POP\tES\n");
478 M.x86.R_ES = pop_word();
479 DECODE_CLEAR_SEGOVR();
483 /****************************************************************************
486 ****************************************************************************/
487 void x86emuOp_push_CS(u8 X86EMU_UNUSED(op1))
490 DECODE_PRINTF("PUSH\tCS\n");
492 push_word(M.x86.R_CS);
493 DECODE_CLEAR_SEGOVR();
497 /****************************************************************************
499 Handles opcode 0x0f. Escape for two-byte opcode (286 or better)
500 ****************************************************************************/
501 void x86emuOp_two_byte(u8 X86EMU_UNUSED(op1))
503 u8 op2 = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++));
504 INC_DECODED_INST_LEN(1);
505 (*x86emu_optab2[op2])(op2);
508 /****************************************************************************
511 ****************************************************************************/
512 void x86emuOp_push_SS(u8 X86EMU_UNUSED(op1))
515 DECODE_PRINTF("PUSH\tSS\n");
517 push_word(M.x86.R_SS);
518 DECODE_CLEAR_SEGOVR();
522 /****************************************************************************
525 ****************************************************************************/
526 void x86emuOp_pop_SS(u8 X86EMU_UNUSED(op1))
529 DECODE_PRINTF("POP\tSS\n");
531 M.x86.R_SS = pop_word();
532 DECODE_CLEAR_SEGOVR();
536 /****************************************************************************
539 ****************************************************************************/
540 void x86emuOp_push_DS(u8 X86EMU_UNUSED(op1))
543 DECODE_PRINTF("PUSH\tDS\n");
545 push_word(M.x86.R_DS);
546 DECODE_CLEAR_SEGOVR();
550 /****************************************************************************
553 ****************************************************************************/
554 void x86emuOp_pop_DS(u8 X86EMU_UNUSED(op1))
557 DECODE_PRINTF("POP\tDS\n");
559 M.x86.R_DS = pop_word();
560 DECODE_CLEAR_SEGOVR();
564 /****************************************************************************
567 ****************************************************************************/
568 void x86emuOp_segovr_ES(u8 X86EMU_UNUSED(op1))
571 DECODE_PRINTF("ES:\n");
573 M.x86.mode |= SYSMODE_SEGOVR_ES;
575 * note the lack of DECODE_CLEAR_SEGOVR(r) since, here is one of 4
576 * opcode subroutines we do not want to do this.
581 /****************************************************************************
584 ****************************************************************************/
585 void x86emuOp_daa(u8 X86EMU_UNUSED(op1))
588 DECODE_PRINTF("DAA\n");
590 M.x86.R_AL = daa_byte(M.x86.R_AL);
591 DECODE_CLEAR_SEGOVR();
595 /****************************************************************************
598 ****************************************************************************/
599 void x86emuOp_segovr_CS(u8 X86EMU_UNUSED(op1))
602 DECODE_PRINTF("CS:\n");
604 M.x86.mode |= SYSMODE_SEGOVR_CS;
605 /* note no DECODE_CLEAR_SEGOVR here. */
609 /****************************************************************************
612 ****************************************************************************/
613 void x86emuOp_das(u8 X86EMU_UNUSED(op1))
616 DECODE_PRINTF("DAS\n");
618 M.x86.R_AL = das_byte(M.x86.R_AL);
619 DECODE_CLEAR_SEGOVR();
623 /****************************************************************************
626 ****************************************************************************/
627 void x86emuOp_segovr_SS(u8 X86EMU_UNUSED(op1))
630 DECODE_PRINTF("SS:\n");
632 M.x86.mode |= SYSMODE_SEGOVR_SS;
633 /* no DECODE_CLEAR_SEGOVR ! */
637 /****************************************************************************
640 ****************************************************************************/
641 void x86emuOp_aaa(u8 X86EMU_UNUSED(op1))
644 DECODE_PRINTF("AAA\n");
646 M.x86.R_AX = aaa_word(M.x86.R_AX);
647 DECODE_CLEAR_SEGOVR();
651 /****************************************************************************
654 ****************************************************************************/
655 void x86emuOp_segovr_DS(u8 X86EMU_UNUSED(op1))
658 DECODE_PRINTF("DS:\n");
660 M.x86.mode |= SYSMODE_SEGOVR_DS;
661 /* NO DECODE_CLEAR_SEGOVR! */
665 /****************************************************************************
668 ****************************************************************************/
669 void x86emuOp_aas(u8 X86EMU_UNUSED(op1))
672 DECODE_PRINTF("AAS\n");
674 M.x86.R_AX = aas_word(M.x86.R_AX);
675 DECODE_CLEAR_SEGOVR();
679 /****************************************************************************
681 Handles opcode 0x40 - 0x47
682 ****************************************************************************/
683 void x86emuOp_inc_register(u8 op1)
687 DECODE_PRINTF("INC\t");
688 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
690 reg = DECODE_RM_LONG_REGISTER(op1);
693 *reg = inc_long(*reg);
696 reg = DECODE_RM_WORD_REGISTER(op1);
699 *reg = inc_word(*reg);
701 DECODE_CLEAR_SEGOVR();
705 /****************************************************************************
707 Handles opcode 0x48 - 0x4F
708 ****************************************************************************/
709 void x86emuOp_dec_register(u8 op1)
713 DECODE_PRINTF("DEC\t");
714 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
716 reg = DECODE_RM_LONG_REGISTER(op1);
719 *reg = dec_long(*reg);
722 reg = DECODE_RM_WORD_REGISTER(op1);
725 *reg = dec_word(*reg);
727 DECODE_CLEAR_SEGOVR();
731 /****************************************************************************
733 Handles opcode 0x50 - 0x57
734 ****************************************************************************/
735 void x86emuOp_push_register(u8 op1)
739 DECODE_PRINTF("PUSH\t");
740 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
742 reg = DECODE_RM_LONG_REGISTER(op1);
748 reg = DECODE_RM_WORD_REGISTER(op1);
753 DECODE_CLEAR_SEGOVR();
757 /****************************************************************************
759 Handles opcode 0x58 - 0x5F
760 ****************************************************************************/
761 void x86emuOp_pop_register(u8 op1)
765 DECODE_PRINTF("POP\t");
766 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
768 reg = DECODE_RM_LONG_REGISTER(op1);
774 reg = DECODE_RM_WORD_REGISTER(op1);
779 DECODE_CLEAR_SEGOVR();
783 /****************************************************************************
786 ****************************************************************************/
787 void x86emuOp_push_all(u8 X86EMU_UNUSED(op1))
790 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
791 DECODE_PRINTF("PUSHAD\n");
793 DECODE_PRINTF("PUSHA\n");
796 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
797 u32 old_sp = M.x86.R_ESP;
799 push_long(M.x86.R_EAX);
800 push_long(M.x86.R_ECX);
801 push_long(M.x86.R_EDX);
802 push_long(M.x86.R_EBX);
804 push_long(M.x86.R_EBP);
805 push_long(M.x86.R_ESI);
806 push_long(M.x86.R_EDI);
808 u16 old_sp = M.x86.R_SP;
810 push_word(M.x86.R_AX);
811 push_word(M.x86.R_CX);
812 push_word(M.x86.R_DX);
813 push_word(M.x86.R_BX);
815 push_word(M.x86.R_BP);
816 push_word(M.x86.R_SI);
817 push_word(M.x86.R_DI);
819 DECODE_CLEAR_SEGOVR();
823 /****************************************************************************
826 ****************************************************************************/
827 void x86emuOp_pop_all(u8 X86EMU_UNUSED(op1))
830 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
831 DECODE_PRINTF("POPAD\n");
833 DECODE_PRINTF("POPA\n");
836 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
837 M.x86.R_EDI = pop_long();
838 M.x86.R_ESI = pop_long();
839 M.x86.R_EBP = pop_long();
840 M.x86.R_ESP += 4; /* skip ESP */
841 M.x86.R_EBX = pop_long();
842 M.x86.R_EDX = pop_long();
843 M.x86.R_ECX = pop_long();
844 M.x86.R_EAX = pop_long();
846 M.x86.R_DI = pop_word();
847 M.x86.R_SI = pop_word();
848 M.x86.R_BP = pop_word();
849 M.x86.R_SP += 2; /* skip SP */
850 M.x86.R_BX = pop_word();
851 M.x86.R_DX = pop_word();
852 M.x86.R_CX = pop_word();
853 M.x86.R_AX = pop_word();
855 DECODE_CLEAR_SEGOVR();
859 /*opcode 0x62 ILLEGAL OP, calls x86emuOp_illegal_op() */
860 /*opcode 0x63 ILLEGAL OP, calls x86emuOp_illegal_op() */
862 /****************************************************************************
865 ****************************************************************************/
866 void x86emuOp_segovr_FS(u8 X86EMU_UNUSED(op1))
869 DECODE_PRINTF("FS:\n");
871 M.x86.mode |= SYSMODE_SEGOVR_FS;
873 * note the lack of DECODE_CLEAR_SEGOVR(r) since, here is one of 4
874 * opcode subroutines we do not want to do this.
879 /****************************************************************************
882 ****************************************************************************/
883 void x86emuOp_segovr_GS(u8 X86EMU_UNUSED(op1))
886 DECODE_PRINTF("GS:\n");
888 M.x86.mode |= SYSMODE_SEGOVR_GS;
890 * note the lack of DECODE_CLEAR_SEGOVR(r) since, here is one of 4
891 * opcode subroutines we do not want to do this.
896 /****************************************************************************
898 Handles opcode 0x66 - prefix for 32-bit register
899 ****************************************************************************/
900 void x86emuOp_prefix_data(u8 X86EMU_UNUSED(op1))
903 DECODE_PRINTF("DATA:\n");
905 M.x86.mode |= SYSMODE_PREFIX_DATA;
906 /* note no DECODE_CLEAR_SEGOVR here. */
910 /****************************************************************************
912 Handles opcode 0x67 - prefix for 32-bit address
913 ****************************************************************************/
914 void x86emuOp_prefix_addr(u8 X86EMU_UNUSED(op1))
917 DECODE_PRINTF("ADDR:\n");
919 M.x86.mode |= SYSMODE_PREFIX_ADDR;
920 /* note no DECODE_CLEAR_SEGOVR here. */
924 /****************************************************************************
927 ****************************************************************************/
928 void x86emuOp_push_word_IMM(u8 X86EMU_UNUSED(op1))
933 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
934 imm = fetch_long_imm();
936 imm = fetch_word_imm();
938 DECODE_PRINTF2("PUSH\t%x\n", imm);
940 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
945 DECODE_CLEAR_SEGOVR();
949 /****************************************************************************
952 ****************************************************************************/
953 void x86emuOp_imul_word_IMM(u8 X86EMU_UNUSED(op1))
959 DECODE_PRINTF("IMUL\t");
960 FETCH_DECODE_MODRM(mod, rh, rl);
962 srcoffset = decode_rmXX_address(mod, rl);
963 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
969 destreg = DECODE_RM_LONG_REGISTER(rh);
971 srcval = fetch_data_long(srcoffset);
972 imm = fetch_long_imm();
973 DECODE_PRINTF2(",%d\n", (s32)imm);
975 imul_long_direct(&res_lo,&res_hi,(s32)srcval,(s32)imm);
976 if ((((res_lo & 0x80000000) == 0) && (res_hi == 0x00000000)) ||
977 (((res_lo & 0x80000000) != 0) && (res_hi == 0xFFFFFFFF))) {
984 *destreg = (u32)res_lo;
991 destreg = DECODE_RM_WORD_REGISTER(rh);
993 srcval = fetch_data_word(srcoffset);
994 imm = fetch_word_imm();
995 DECODE_PRINTF2(",%d\n", (s32)imm);
997 res = (s16)srcval * (s16)imm;
998 if ((((res & 0x8000) == 0) && ((res >> 16) == 0x0000)) ||
999 (((res & 0x8000) != 0) && ((res >> 16) == 0xFFFF))) {
1006 *destreg = (u16)res;
1008 } else { /* register to register */
1009 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1010 u32 *destreg,*srcreg;
1014 destreg = DECODE_RM_LONG_REGISTER(rh);
1016 srcreg = DECODE_RM_LONG_REGISTER(rl);
1017 imm = fetch_long_imm();
1018 DECODE_PRINTF2(",%d\n", (s32)imm);
1020 imul_long_direct(&res_lo,&res_hi,(s32)*srcreg,(s32)imm);
1021 if ((((res_lo & 0x80000000) == 0) && (res_hi == 0x00000000)) ||
1022 (((res_lo & 0x80000000) != 0) && (res_hi == 0xFFFFFFFF))) {
1029 *destreg = (u32)res_lo;
1031 u16 *destreg,*srcreg;
1035 destreg = DECODE_RM_WORD_REGISTER(rh);
1037 srcreg = DECODE_RM_WORD_REGISTER(rl);
1038 imm = fetch_word_imm();
1039 DECODE_PRINTF2(",%d\n", (s32)imm);
1040 res = (s16)*srcreg * (s16)imm;
1041 if ((((res & 0x8000) == 0) && ((res >> 16) == 0x0000)) ||
1042 (((res & 0x8000) != 0) && ((res >> 16) == 0xFFFF))) {
1049 *destreg = (u16)res;
1052 DECODE_CLEAR_SEGOVR();
1056 /****************************************************************************
1059 ****************************************************************************/
1060 void x86emuOp_push_byte_IMM(u8 X86EMU_UNUSED(op1))
1065 imm = (s8)fetch_byte_imm();
1066 DECODE_PRINTF2("PUSH\t%d\n", imm);
1069 DECODE_CLEAR_SEGOVR();
1073 /****************************************************************************
1076 ****************************************************************************/
1077 void x86emuOp_imul_byte_IMM(u8 X86EMU_UNUSED(op1))
1084 DECODE_PRINTF("IMUL\t");
1085 FETCH_DECODE_MODRM(mod, rh, rl);
1087 srcoffset = decode_rmXX_address(mod, rl);
1088 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1093 destreg = DECODE_RM_LONG_REGISTER(rh);
1095 srcval = fetch_data_long(srcoffset);
1096 imm = fetch_byte_imm();
1097 DECODE_PRINTF2(",%d\n", (s32)imm);
1099 imul_long_direct(&res_lo,&res_hi,(s32)srcval,(s32)imm);
1100 if ((((res_lo & 0x80000000) == 0) && (res_hi == 0x00000000)) ||
1101 (((res_lo & 0x80000000) != 0) && (res_hi == 0xFFFFFFFF))) {
1108 *destreg = (u32)res_lo;
1114 destreg = DECODE_RM_WORD_REGISTER(rh);
1116 srcval = fetch_data_word(srcoffset);
1117 imm = fetch_byte_imm();
1118 DECODE_PRINTF2(",%d\n", (s32)imm);
1120 res = (s16)srcval * (s16)imm;
1121 if ((((res & 0x8000) == 0) && ((res >> 16) == 0x0000)) ||
1122 (((res & 0x8000) != 0) && ((res >> 16) == 0xFFFF))) {
1129 *destreg = (u16)res;
1131 } else { /* register to register */
1132 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1133 u32 *destreg,*srcreg;
1136 destreg = DECODE_RM_LONG_REGISTER(rh);
1138 srcreg = DECODE_RM_LONG_REGISTER(rl);
1139 imm = fetch_byte_imm();
1140 DECODE_PRINTF2(",%d\n", (s32)imm);
1142 imul_long_direct(&res_lo,&res_hi,(s32)*srcreg,(s32)imm);
1143 if ((((res_lo & 0x80000000) == 0) && (res_hi == 0x00000000)) ||
1144 (((res_lo & 0x80000000) != 0) && (res_hi == 0xFFFFFFFF))) {
1151 *destreg = (u32)res_lo;
1153 u16 *destreg,*srcreg;
1156 destreg = DECODE_RM_WORD_REGISTER(rh);
1158 srcreg = DECODE_RM_WORD_REGISTER(rl);
1159 imm = fetch_byte_imm();
1160 DECODE_PRINTF2(",%d\n", (s32)imm);
1162 res = (s16)*srcreg * (s16)imm;
1163 if ((((res & 0x8000) == 0) && ((res >> 16) == 0x0000)) ||
1164 (((res & 0x8000) != 0) && ((res >> 16) == 0xFFFF))) {
1171 *destreg = (u16)res;
1174 DECODE_CLEAR_SEGOVR();
1178 /****************************************************************************
1181 ****************************************************************************/
1182 void x86emuOp_ins_byte(u8 X86EMU_UNUSED(op1))
1185 DECODE_PRINTF("INSB\n");
1188 DECODE_CLEAR_SEGOVR();
1192 /****************************************************************************
1195 ****************************************************************************/
1196 void x86emuOp_ins_word(u8 X86EMU_UNUSED(op1))
1199 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1200 DECODE_PRINTF("INSD\n");
1203 DECODE_PRINTF("INSW\n");
1207 DECODE_CLEAR_SEGOVR();
1211 /****************************************************************************
1214 ****************************************************************************/
1215 void x86emuOp_outs_byte(u8 X86EMU_UNUSED(op1))
1218 DECODE_PRINTF("OUTSB\n");
1221 DECODE_CLEAR_SEGOVR();
1225 /****************************************************************************
1228 ****************************************************************************/
1229 void x86emuOp_outs_word(u8 X86EMU_UNUSED(op1))
1232 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1233 DECODE_PRINTF("OUTSD\n");
1236 DECODE_PRINTF("OUTSW\n");
1240 DECODE_CLEAR_SEGOVR();
1244 /****************************************************************************
1246 Handles opcode 0x70 - 0x7F
1247 ****************************************************************************/
1248 int x86emu_check_jump_condition(u8 op);
1250 void x86emuOp_jump_near_cond(u8 op1)
1256 /* jump to byte offset if overflow flag is set */
1258 cond = x86emu_check_jump_condition(op1 & 0xF);
1259 offset = (s8)fetch_byte_imm();
1260 target = (u16)(M.x86.R_IP + (s16)offset);
1261 DECODE_PRINTF2("%x\n", target);
1264 M.x86.R_IP = target;
1265 DECODE_CLEAR_SEGOVR();
1269 /****************************************************************************
1272 ****************************************************************************/
1273 void x86emuOp_opc80_byte_RM_IMM(u8 X86EMU_UNUSED(op1))
1282 * Weirdo special case instruction format. Part of the opcode
1283 * held below in "RH". Doubly nested case would result, except
1284 * that the decoded instruction
1287 FETCH_DECODE_MODRM(mod, rh, rl);
1289 if (DEBUG_DECODE()) {
1290 /* XXX DECODE_PRINTF may be changed to something more
1291 general, so that it is important to leave the strings
1292 in the same format, even though the result is that the
1293 above test is done twice. */
1297 DECODE_PRINTF("ADD\t");
1300 DECODE_PRINTF("OR\t");
1303 DECODE_PRINTF("ADC\t");
1306 DECODE_PRINTF("SBB\t");
1309 DECODE_PRINTF("AND\t");
1312 DECODE_PRINTF("SUB\t");
1315 DECODE_PRINTF("XOR\t");
1318 DECODE_PRINTF("CMP\t");
1323 /* know operation, decode the mod byte to find the addressing
1326 DECODE_PRINTF("BYTE PTR ");
1327 destoffset = decode_rmXX_address(mod, rl);
1329 destval = fetch_data_byte(destoffset);
1330 imm = fetch_byte_imm();
1331 DECODE_PRINTF2("%x\n", imm);
1333 destval = (*genop_byte_operation[rh]) (destval, imm);
1335 store_data_byte(destoffset, destval);
1336 } else { /* register to register */
1337 destreg = DECODE_RM_BYTE_REGISTER(rl);
1339 imm = fetch_byte_imm();
1340 DECODE_PRINTF2("%x\n", imm);
1342 destval = (*genop_byte_operation[rh]) (*destreg, imm);
1346 DECODE_CLEAR_SEGOVR();
1350 /****************************************************************************
1353 ****************************************************************************/
1354 void x86emuOp_opc81_word_RM_IMM(u8 X86EMU_UNUSED(op1))
1360 * Weirdo special case instruction format. Part of the opcode
1361 * held below in "RH". Doubly nested case would result, except
1362 * that the decoded instruction
1365 FETCH_DECODE_MODRM(mod, rh, rl);
1367 if (DEBUG_DECODE()) {
1368 /* XXX DECODE_PRINTF may be changed to something more
1369 general, so that it is important to leave the strings
1370 in the same format, even though the result is that the
1371 above test is done twice. */
1375 DECODE_PRINTF("ADD\t");
1378 DECODE_PRINTF("OR\t");
1381 DECODE_PRINTF("ADC\t");
1384 DECODE_PRINTF("SBB\t");
1387 DECODE_PRINTF("AND\t");
1390 DECODE_PRINTF("SUB\t");
1393 DECODE_PRINTF("XOR\t");
1396 DECODE_PRINTF("CMP\t");
1402 * Know operation, decode the mod byte to find the addressing
1406 DECODE_PRINTF("DWORD PTR ");
1407 destoffset = decode_rmXX_address(mod, rl);
1408 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1412 destval = fetch_data_long(destoffset);
1413 imm = fetch_long_imm();
1414 DECODE_PRINTF2("%x\n", imm);
1416 destval = (*genop_long_operation[rh]) (destval, imm);
1418 store_data_long(destoffset, destval);
1423 destval = fetch_data_word(destoffset);
1424 imm = fetch_word_imm();
1425 DECODE_PRINTF2("%x\n", imm);
1427 destval = (*genop_word_operation[rh]) (destval, imm);
1429 store_data_word(destoffset, destval);
1431 } else { /* register to register */
1432 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1436 destreg = DECODE_RM_LONG_REGISTER(rl);
1438 imm = fetch_long_imm();
1439 DECODE_PRINTF2("%x\n", imm);
1441 destval = (*genop_long_operation[rh]) (*destreg, imm);
1448 destreg = DECODE_RM_WORD_REGISTER(rl);
1450 imm = fetch_word_imm();
1451 DECODE_PRINTF2("%x\n", imm);
1453 destval = (*genop_word_operation[rh]) (*destreg, imm);
1458 DECODE_CLEAR_SEGOVR();
1462 /****************************************************************************
1465 ****************************************************************************/
1466 void x86emuOp_opc82_byte_RM_IMM(u8 X86EMU_UNUSED(op1))
1475 * Weirdo special case instruction format. Part of the opcode
1476 * held below in "RH". Doubly nested case would result, except
1477 * that the decoded instruction Similar to opcode 81, except that
1478 * the immediate byte is sign extended to a word length.
1481 FETCH_DECODE_MODRM(mod, rh, rl);
1483 if (DEBUG_DECODE()) {
1484 /* XXX DECODE_PRINTF may be changed to something more
1485 general, so that it is important to leave the strings
1486 in the same format, even though the result is that the
1487 above test is done twice. */
1490 DECODE_PRINTF("ADD\t");
1493 DECODE_PRINTF("OR\t");
1496 DECODE_PRINTF("ADC\t");
1499 DECODE_PRINTF("SBB\t");
1502 DECODE_PRINTF("AND\t");
1505 DECODE_PRINTF("SUB\t");
1508 DECODE_PRINTF("XOR\t");
1511 DECODE_PRINTF("CMP\t");
1516 /* know operation, decode the mod byte to find the addressing
1519 DECODE_PRINTF("BYTE PTR ");
1520 destoffset = decode_rmXX_address(mod, rl);
1521 destval = fetch_data_byte(destoffset);
1522 imm = fetch_byte_imm();
1523 DECODE_PRINTF2(",%x\n", imm);
1525 destval = (*genop_byte_operation[rh]) (destval, imm);
1527 store_data_byte(destoffset, destval);
1528 } else { /* register to register */
1529 destreg = DECODE_RM_BYTE_REGISTER(rl);
1530 imm = fetch_byte_imm();
1531 DECODE_PRINTF2(",%x\n", imm);
1533 destval = (*genop_byte_operation[rh]) (*destreg, imm);
1537 DECODE_CLEAR_SEGOVR();
1541 /****************************************************************************
1544 ****************************************************************************/
1545 void x86emuOp_opc83_word_RM_IMM(u8 X86EMU_UNUSED(op1))
1551 * Weirdo special case instruction format. Part of the opcode
1552 * held below in "RH". Doubly nested case would result, except
1553 * that the decoded instruction Similar to opcode 81, except that
1554 * the immediate byte is sign extended to a word length.
1557 FETCH_DECODE_MODRM(mod, rh, rl);
1559 if (DEBUG_DECODE()) {
1560 /* XXX DECODE_PRINTF may be changed to something more
1561 general, so that it is important to leave the strings
1562 in the same format, even though the result is that the
1563 above test is done twice. */
1566 DECODE_PRINTF("ADD\t");
1569 DECODE_PRINTF("OR\t");
1572 DECODE_PRINTF("ADC\t");
1575 DECODE_PRINTF("SBB\t");
1578 DECODE_PRINTF("AND\t");
1581 DECODE_PRINTF("SUB\t");
1584 DECODE_PRINTF("XOR\t");
1587 DECODE_PRINTF("CMP\t");
1592 /* know operation, decode the mod byte to find the addressing
1595 DECODE_PRINTF("DWORD PTR ");
1596 destoffset = decode_rmXX_address(mod,rl);
1598 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1601 destval = fetch_data_long(destoffset);
1602 imm = (s8) fetch_byte_imm();
1603 DECODE_PRINTF2(",%x\n", imm);
1605 destval = (*genop_long_operation[rh]) (destval, imm);
1607 store_data_long(destoffset, destval);
1611 destval = fetch_data_word(destoffset);
1612 imm = (s8) fetch_byte_imm();
1613 DECODE_PRINTF2(",%x\n", imm);
1615 destval = (*genop_word_operation[rh]) (destval, imm);
1617 store_data_word(destoffset, destval);
1619 } else { /* register to register */
1620 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1624 destreg = DECODE_RM_LONG_REGISTER(rl);
1625 imm = (s8) fetch_byte_imm();
1626 DECODE_PRINTF2(",%x\n", imm);
1628 destval = (*genop_long_operation[rh]) (*destreg, imm);
1635 destreg = DECODE_RM_WORD_REGISTER(rl);
1636 imm = (s8) fetch_byte_imm();
1637 DECODE_PRINTF2(",%x\n", imm);
1639 destval = (*genop_word_operation[rh]) (*destreg, imm);
1644 DECODE_CLEAR_SEGOVR();
1648 /****************************************************************************
1651 ****************************************************************************/
1652 void x86emuOp_test_byte_RM_R(u8 X86EMU_UNUSED(op1))
1655 u8 *destreg, *srcreg;
1660 DECODE_PRINTF("TEST\t");
1661 FETCH_DECODE_MODRM(mod, rh, rl);
1663 destoffset = decode_rmXX_address(mod, rl);
1665 destval = fetch_data_byte(destoffset);
1666 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1667 DECODE_PRINTF("\n");
1669 test_byte(destval, *srcreg);
1670 } else { /* register to register */
1671 destreg = DECODE_RM_BYTE_REGISTER(rl);
1673 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1674 DECODE_PRINTF("\n");
1676 test_byte(*destreg, *srcreg);
1678 DECODE_CLEAR_SEGOVR();
1682 /****************************************************************************
1685 ****************************************************************************/
1686 void x86emuOp_test_word_RM_R(u8 X86EMU_UNUSED(op1))
1692 DECODE_PRINTF("TEST\t");
1693 FETCH_DECODE_MODRM(mod, rh, rl);
1695 destoffset = decode_rmXX_address(mod, rl);
1696 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1701 destval = fetch_data_long(destoffset);
1702 srcreg = DECODE_RM_LONG_REGISTER(rh);
1703 DECODE_PRINTF("\n");
1705 test_long(destval, *srcreg);
1711 destval = fetch_data_word(destoffset);
1712 srcreg = DECODE_RM_WORD_REGISTER(rh);
1713 DECODE_PRINTF("\n");
1715 test_word(destval, *srcreg);
1717 } else { /* register to register */
1718 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1719 u32 *destreg,*srcreg;
1721 destreg = DECODE_RM_LONG_REGISTER(rl);
1723 srcreg = DECODE_RM_LONG_REGISTER(rh);
1724 DECODE_PRINTF("\n");
1726 test_long(*destreg, *srcreg);
1728 u16 *destreg,*srcreg;
1730 destreg = DECODE_RM_WORD_REGISTER(rl);
1732 srcreg = DECODE_RM_WORD_REGISTER(rh);
1733 DECODE_PRINTF("\n");
1735 test_word(*destreg, *srcreg);
1738 DECODE_CLEAR_SEGOVR();
1742 /****************************************************************************
1745 ****************************************************************************/
1746 void x86emuOp_xchg_byte_RM_R(u8 X86EMU_UNUSED(op1))
1749 u8 *destreg, *srcreg;
1755 DECODE_PRINTF("XCHG\t");
1756 FETCH_DECODE_MODRM(mod, rh, rl);
1758 destoffset = decode_rmXX_address(mod, rl);
1760 destval = fetch_data_byte(destoffset);
1761 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1762 DECODE_PRINTF("\n");
1767 store_data_byte(destoffset, destval);
1768 } else { /* register to register */
1769 destreg = DECODE_RM_BYTE_REGISTER(rl);
1771 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1772 DECODE_PRINTF("\n");
1778 DECODE_CLEAR_SEGOVR();
1782 /****************************************************************************
1785 ****************************************************************************/
1786 void x86emuOp_xchg_word_RM_R(u8 X86EMU_UNUSED(op1))
1792 DECODE_PRINTF("XCHG\t");
1793 FETCH_DECODE_MODRM(mod, rh, rl);
1795 destoffset = decode_rmXX_address(mod, rl);
1797 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1801 destval = fetch_data_long(destoffset);
1802 srcreg = DECODE_RM_LONG_REGISTER(rh);
1803 DECODE_PRINTF("\n");
1808 store_data_long(destoffset, destval);
1813 destval = fetch_data_word(destoffset);
1814 srcreg = DECODE_RM_WORD_REGISTER(rh);
1815 DECODE_PRINTF("\n");
1820 store_data_word(destoffset, destval);
1822 } else { /* register to register */
1823 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1824 u32 *destreg,*srcreg;
1827 destreg = DECODE_RM_LONG_REGISTER(rl);
1829 srcreg = DECODE_RM_LONG_REGISTER(rh);
1830 DECODE_PRINTF("\n");
1836 u16 *destreg,*srcreg;
1839 destreg = DECODE_RM_WORD_REGISTER(rl);
1841 srcreg = DECODE_RM_WORD_REGISTER(rh);
1842 DECODE_PRINTF("\n");
1849 DECODE_CLEAR_SEGOVR();
1853 /****************************************************************************
1856 ****************************************************************************/
1857 void x86emuOp_mov_byte_RM_R(u8 X86EMU_UNUSED(op1))
1860 u8 *destreg, *srcreg;
1864 DECODE_PRINTF("MOV\t");
1865 FETCH_DECODE_MODRM(mod, rh, rl);
1867 destoffset = decode_rmXX_address(mod, rl);
1869 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1870 DECODE_PRINTF("\n");
1872 store_data_byte(destoffset, *srcreg);
1873 } else { /* register to register */
1874 destreg = DECODE_RM_BYTE_REGISTER(rl);
1876 srcreg = DECODE_RM_BYTE_REGISTER(rh);
1877 DECODE_PRINTF("\n");
1881 DECODE_CLEAR_SEGOVR();
1885 /****************************************************************************
1888 ****************************************************************************/
1889 void x86emuOp_mov_word_RM_R(u8 X86EMU_UNUSED(op1))
1895 DECODE_PRINTF("MOV\t");
1896 FETCH_DECODE_MODRM(mod, rh, rl);
1898 destoffset = decode_rmXX_address(mod, rl);
1899 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1903 srcreg = DECODE_RM_LONG_REGISTER(rh);
1904 DECODE_PRINTF("\n");
1906 store_data_long(destoffset, *srcreg);
1911 srcreg = DECODE_RM_WORD_REGISTER(rh);
1912 DECODE_PRINTF("\n");
1914 store_data_word(destoffset, *srcreg);
1916 } else { /* register to register */
1917 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1918 u32 *destreg,*srcreg;
1920 destreg = DECODE_RM_LONG_REGISTER(rl);
1922 srcreg = DECODE_RM_LONG_REGISTER(rh);
1923 DECODE_PRINTF("\n");
1927 u16 *destreg,*srcreg;
1929 destreg = DECODE_RM_WORD_REGISTER(rl);
1931 srcreg = DECODE_RM_WORD_REGISTER(rh);
1932 DECODE_PRINTF("\n");
1937 DECODE_CLEAR_SEGOVR();
1941 /****************************************************************************
1944 ****************************************************************************/
1945 void x86emuOp_mov_byte_R_RM(u8 X86EMU_UNUSED(op1))
1948 u8 *destreg, *srcreg;
1953 DECODE_PRINTF("MOV\t");
1954 FETCH_DECODE_MODRM(mod, rh, rl);
1956 destreg = DECODE_RM_BYTE_REGISTER(rh);
1958 srcoffset = decode_rmXX_address(mod, rl);
1959 srcval = fetch_data_byte(srcoffset);
1960 DECODE_PRINTF("\n");
1963 } else { /* register to register */
1964 destreg = DECODE_RM_BYTE_REGISTER(rh);
1966 srcreg = DECODE_RM_BYTE_REGISTER(rl);
1967 DECODE_PRINTF("\n");
1971 DECODE_CLEAR_SEGOVR();
1975 /****************************************************************************
1978 ****************************************************************************/
1979 void x86emuOp_mov_word_R_RM(u8 X86EMU_UNUSED(op1))
1985 DECODE_PRINTF("MOV\t");
1986 FETCH_DECODE_MODRM(mod, rh, rl);
1988 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
1992 destreg = DECODE_RM_LONG_REGISTER(rh);
1994 srcoffset = decode_rmXX_address(mod, rl);
1995 srcval = fetch_data_long(srcoffset);
1996 DECODE_PRINTF("\n");
2003 destreg = DECODE_RM_WORD_REGISTER(rh);
2005 srcoffset = decode_rmXX_address(mod, rl);
2006 srcval = fetch_data_word(srcoffset);
2007 DECODE_PRINTF("\n");
2011 } else { /* register to register */
2012 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2013 u32 *destreg, *srcreg;
2015 destreg = DECODE_RM_LONG_REGISTER(rh);
2017 srcreg = DECODE_RM_LONG_REGISTER(rl);
2018 DECODE_PRINTF("\n");
2022 u16 *destreg, *srcreg;
2024 destreg = DECODE_RM_WORD_REGISTER(rh);
2026 srcreg = DECODE_RM_WORD_REGISTER(rl);
2027 DECODE_PRINTF("\n");
2032 DECODE_CLEAR_SEGOVR();
2036 /****************************************************************************
2039 ****************************************************************************/
2040 void x86emuOp_mov_word_RM_SR(u8 X86EMU_UNUSED(op1))
2043 u16 *destreg, *srcreg;
2048 DECODE_PRINTF("MOV\t");
2049 FETCH_DECODE_MODRM(mod, rh, rl);
2051 destoffset = decode_rmXX_address(mod, rl);
2053 srcreg = decode_rm_seg_register(rh);
2054 DECODE_PRINTF("\n");
2057 store_data_word(destoffset, destval);
2058 } else { /* register to register */
2059 destreg = DECODE_RM_WORD_REGISTER(rl);
2061 srcreg = decode_rm_seg_register(rh);
2062 DECODE_PRINTF("\n");
2066 DECODE_CLEAR_SEGOVR();
2070 /****************************************************************************
2073 ****************************************************************************/
2074 void x86emuOp_lea_word_R_M(u8 X86EMU_UNUSED(op1))
2081 * TODO: Need to handle address size prefix!
2083 * lea eax,[eax+ebx*2] ??
2087 DECODE_PRINTF("LEA\t");
2088 FETCH_DECODE_MODRM(mod, rh, rl);
2090 srcreg = DECODE_RM_WORD_REGISTER(rh);
2092 destoffset = decode_rmXX_address(mod, rl);
2093 DECODE_PRINTF("\n");
2095 *srcreg = (u16)destoffset;
2097 /* } else { undefined. Do nothing. } */
2098 DECODE_CLEAR_SEGOVR();
2102 /****************************************************************************
2105 ****************************************************************************/
2106 void x86emuOp_mov_word_SR_RM(u8 X86EMU_UNUSED(op1))
2109 u16 *destreg, *srcreg;
2114 DECODE_PRINTF("MOV\t");
2115 FETCH_DECODE_MODRM(mod, rh, rl);
2117 destreg = decode_rm_seg_register(rh);
2119 srcoffset = decode_rmXX_address(mod, rl);
2120 srcval = fetch_data_word(srcoffset);
2121 DECODE_PRINTF("\n");
2124 } else { /* register to register */
2125 destreg = decode_rm_seg_register(rh);
2127 srcreg = DECODE_RM_WORD_REGISTER(rl);
2128 DECODE_PRINTF("\n");
2133 * Clean up, and reset all the R_xSP pointers to the correct
2134 * locations. This is about 3x too much overhead (doing all the
2135 * segreg ptrs when only one is needed, but this instruction
2136 * *cannot* be that common, and this isn't too much work anyway.
2138 DECODE_CLEAR_SEGOVR();
2142 /****************************************************************************
2145 ****************************************************************************/
2146 void x86emuOp_pop_RM(u8 X86EMU_UNUSED(op1))
2152 DECODE_PRINTF("POP\t");
2153 FETCH_DECODE_MODRM(mod, rh, rl);
2155 DECODE_PRINTF("ILLEGAL DECODE OF OPCODE 8F\n");
2159 destoffset = decode_rmXX_address(mod, rl);
2160 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2163 DECODE_PRINTF("\n");
2165 destval = pop_long();
2166 store_data_long(destoffset, destval);
2170 DECODE_PRINTF("\n");
2172 destval = pop_word();
2173 store_data_word(destoffset, destval);
2175 } else { /* register to register */
2176 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2179 destreg = DECODE_RM_LONG_REGISTER(rl);
2180 DECODE_PRINTF("\n");
2182 *destreg = pop_long();
2186 destreg = DECODE_RM_WORD_REGISTER(rl);
2187 DECODE_PRINTF("\n");
2189 *destreg = pop_word();
2192 DECODE_CLEAR_SEGOVR();
2196 /****************************************************************************
2199 ****************************************************************************/
2200 void x86emuOp_nop(u8 X86EMU_UNUSED(op1))
2203 DECODE_PRINTF("NOP\n");
2205 DECODE_CLEAR_SEGOVR();
2209 /****************************************************************************
2211 Handles opcode 0x91-0x97
2212 ****************************************************************************/
2213 void x86emuOp_xchg_word_AX_register(u8 X86EMU_UNUSED(op1))
2221 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2223 DECODE_PRINTF("XCHG\tEAX,");
2224 reg32 = DECODE_RM_LONG_REGISTER(op1);
2225 DECODE_PRINTF("\n");
2228 M.x86.R_EAX = *reg32;
2232 DECODE_PRINTF("XCHG\tAX,");
2233 reg16 = DECODE_RM_WORD_REGISTER(op1);
2234 DECODE_PRINTF("\n");
2237 M.x86.R_EAX = *reg16;
2240 DECODE_CLEAR_SEGOVR();
2244 /****************************************************************************
2247 ****************************************************************************/
2248 void x86emuOp_cbw(u8 X86EMU_UNUSED(op1))
2251 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2252 DECODE_PRINTF("CWDE\n");
2254 DECODE_PRINTF("CBW\n");
2257 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2258 if (M.x86.R_AX & 0x8000) {
2259 M.x86.R_EAX |= 0xffff0000;
2261 M.x86.R_EAX &= 0x0000ffff;
2264 if (M.x86.R_AL & 0x80) {
2270 DECODE_CLEAR_SEGOVR();
2274 /****************************************************************************
2277 ****************************************************************************/
2278 void x86emuOp_cwd(u8 X86EMU_UNUSED(op1))
2281 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2282 DECODE_PRINTF("CDQ\n");
2284 DECODE_PRINTF("CWD\n");
2286 DECODE_PRINTF("CWD\n");
2288 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2289 if (M.x86.R_EAX & 0x80000000) {
2290 M.x86.R_EDX = 0xffffffff;
2295 if (M.x86.R_AX & 0x8000) {
2296 M.x86.R_DX = 0xffff;
2301 DECODE_CLEAR_SEGOVR();
2305 /****************************************************************************
2308 ****************************************************************************/
2309 void x86emuOp_call_far_IMM(u8 X86EMU_UNUSED(op1))
2314 DECODE_PRINTF("CALL\t");
2315 faroff = fetch_word_imm();
2316 farseg = fetch_word_imm();
2317 DECODE_PRINTF2("%04x:", farseg);
2318 DECODE_PRINTF2("%04x\n", faroff);
2319 CALL_TRACE(M.x86.saved_cs, M.x86.saved_ip, farseg, faroff, "FAR ");
2323 * Hooked interrupt vectors calling into our "BIOS" will cause
2324 * problems unless all intersegment stuff is checked for BIOS
2325 * access. Check needed here. For moment, let it alone.
2328 push_word(M.x86.R_CS);
2329 M.x86.R_CS = farseg;
2330 push_word(M.x86.R_IP);
2331 M.x86.R_IP = faroff;
2332 DECODE_CLEAR_SEGOVR();
2336 /****************************************************************************
2339 ****************************************************************************/
2340 void x86emuOp_wait(u8 X86EMU_UNUSED(op1))
2343 DECODE_PRINTF("WAIT");
2346 DECODE_CLEAR_SEGOVR();
2350 /****************************************************************************
2353 ****************************************************************************/
2354 void x86emuOp_pushf_word(u8 X86EMU_UNUSED(op1))
2359 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2360 DECODE_PRINTF("PUSHFD\n");
2362 DECODE_PRINTF("PUSHF\n");
2366 /* clear out *all* bits not representing flags, and turn on real bits */
2367 flags = (M.x86.R_EFLG & F_MSK) | F_ALWAYS_ON;
2368 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2371 push_word((u16)flags);
2373 DECODE_CLEAR_SEGOVR();
2377 /****************************************************************************
2380 ****************************************************************************/
2381 void x86emuOp_popf_word(u8 X86EMU_UNUSED(op1))
2384 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2385 DECODE_PRINTF("POPFD\n");
2387 DECODE_PRINTF("POPF\n");
2390 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2391 M.x86.R_EFLG = pop_long();
2393 M.x86.R_FLG = pop_word();
2395 DECODE_CLEAR_SEGOVR();
2399 /****************************************************************************
2402 ****************************************************************************/
2403 void x86emuOp_sahf(u8 X86EMU_UNUSED(op1))
2406 DECODE_PRINTF("SAHF\n");
2408 /* clear the lower bits of the flag register */
2409 M.x86.R_FLG &= 0xffffff00;
2410 /* or in the AH register into the flags register */
2411 M.x86.R_FLG |= M.x86.R_AH;
2412 DECODE_CLEAR_SEGOVR();
2416 /****************************************************************************
2419 ****************************************************************************/
2420 void x86emuOp_lahf(u8 X86EMU_UNUSED(op1))
2423 DECODE_PRINTF("LAHF\n");
2425 M.x86.R_AH = (u8)(M.x86.R_FLG & 0xff);
2426 /*undocumented TC++ behavior??? Nope. It's documented, but
2427 you have too look real hard to notice it. */
2429 DECODE_CLEAR_SEGOVR();
2433 /****************************************************************************
2436 ****************************************************************************/
2437 void x86emuOp_mov_AL_M_IMM(u8 X86EMU_UNUSED(op1))
2442 DECODE_PRINTF("MOV\tAL,");
2443 offset = fetch_word_imm();
2444 DECODE_PRINTF2("[%04x]\n", offset);
2446 M.x86.R_AL = fetch_data_byte(offset);
2447 DECODE_CLEAR_SEGOVR();
2451 /****************************************************************************
2454 ****************************************************************************/
2455 void x86emuOp_mov_AX_M_IMM(u8 X86EMU_UNUSED(op1))
2460 offset = fetch_word_imm();
2461 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2462 DECODE_PRINTF2("MOV\tEAX,[%04x]\n", offset);
2464 DECODE_PRINTF2("MOV\tAX,[%04x]\n", offset);
2467 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2468 M.x86.R_EAX = fetch_data_long(offset);
2470 M.x86.R_AX = fetch_data_word(offset);
2472 DECODE_CLEAR_SEGOVR();
2476 /****************************************************************************
2479 ****************************************************************************/
2480 void x86emuOp_mov_M_AL_IMM(u8 X86EMU_UNUSED(op1))
2485 DECODE_PRINTF("MOV\t");
2486 offset = fetch_word_imm();
2487 DECODE_PRINTF2("[%04x],AL\n", offset);
2489 store_data_byte(offset, M.x86.R_AL);
2490 DECODE_CLEAR_SEGOVR();
2494 /****************************************************************************
2497 ****************************************************************************/
2498 void x86emuOp_mov_M_AX_IMM(u8 X86EMU_UNUSED(op1))
2503 offset = fetch_word_imm();
2504 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2505 DECODE_PRINTF2("MOV\t[%04x],EAX\n", offset);
2507 DECODE_PRINTF2("MOV\t[%04x],AX\n", offset);
2510 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2511 store_data_long(offset, M.x86.R_EAX);
2513 store_data_word(offset, M.x86.R_AX);
2515 DECODE_CLEAR_SEGOVR();
2519 /****************************************************************************
2522 ****************************************************************************/
2523 void x86emuOp_movs_byte(u8 X86EMU_UNUSED(op1))
2530 DECODE_PRINTF("MOVS\tBYTE\n");
2531 if (ACCESS_FLAG(F_DF)) /* down */
2537 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2538 /* dont care whether REPE or REPNE */
2539 /* move them until CX is ZERO. */
2542 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2545 val = fetch_data_byte(M.x86.R_SI);
2546 store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, val);
2550 DECODE_CLEAR_SEGOVR();
2554 /****************************************************************************
2557 ****************************************************************************/
2558 void x86emuOp_movs_word(u8 X86EMU_UNUSED(op1))
2565 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2566 DECODE_PRINTF("MOVS\tDWORD\n");
2567 if (ACCESS_FLAG(F_DF)) /* down */
2572 DECODE_PRINTF("MOVS\tWORD\n");
2573 if (ACCESS_FLAG(F_DF)) /* down */
2580 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2581 /* dont care whether REPE or REPNE */
2582 /* move them until CX is ZERO. */
2585 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2588 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2589 val = fetch_data_long(M.x86.R_SI);
2590 store_data_long_abs(M.x86.R_ES, M.x86.R_DI, val);
2592 val = fetch_data_word(M.x86.R_SI);
2593 store_data_word_abs(M.x86.R_ES, M.x86.R_DI, (u16)val);
2598 DECODE_CLEAR_SEGOVR();
2602 /****************************************************************************
2605 ****************************************************************************/
2606 void x86emuOp_cmps_byte(u8 X86EMU_UNUSED(op1))
2612 DECODE_PRINTF("CMPS\tBYTE\n");
2614 if (ACCESS_FLAG(F_DF)) /* down */
2619 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2621 /* move them until CX is ZERO. */
2622 while (M.x86.R_CX != 0) {
2623 val1 = fetch_data_byte(M.x86.R_SI);
2624 val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2625 cmp_byte(val1, val2);
2629 if ( (M.x86.mode & SYSMODE_PREFIX_REPE) && (ACCESS_FLAG(F_ZF) == 0) ) break;
2630 if ( (M.x86.mode & SYSMODE_PREFIX_REPNE) && ACCESS_FLAG(F_ZF) ) break;
2632 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2634 val1 = fetch_data_byte(M.x86.R_SI);
2635 val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2636 cmp_byte(val1, val2);
2640 DECODE_CLEAR_SEGOVR();
2644 /****************************************************************************
2647 ****************************************************************************/
2648 void x86emuOp_cmps_word(u8 X86EMU_UNUSED(op1))
2654 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2655 DECODE_PRINTF("CMPS\tDWORD\n");
2658 DECODE_PRINTF("CMPS\tWORD\n");
2661 if (ACCESS_FLAG(F_DF)) /* down */
2665 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2667 /* move them until CX is ZERO. */
2668 while (M.x86.R_CX != 0) {
2669 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2670 val1 = fetch_data_long(M.x86.R_SI);
2671 val2 = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
2672 cmp_long(val1, val2);
2674 val1 = fetch_data_word(M.x86.R_SI);
2675 val2 = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
2676 cmp_word((u16)val1, (u16)val2);
2681 if ( (M.x86.mode & SYSMODE_PREFIX_REPE) && ACCESS_FLAG(F_ZF) == 0 ) break;
2682 if ( (M.x86.mode & SYSMODE_PREFIX_REPNE) && ACCESS_FLAG(F_ZF) ) break;
2684 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2686 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2687 val1 = fetch_data_long(M.x86.R_SI);
2688 val2 = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
2689 cmp_long(val1, val2);
2691 val1 = fetch_data_word(M.x86.R_SI);
2692 val2 = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
2693 cmp_word((u16)val1, (u16)val2);
2698 DECODE_CLEAR_SEGOVR();
2702 /****************************************************************************
2705 ****************************************************************************/
2706 void x86emuOp_test_AL_IMM(u8 X86EMU_UNUSED(op1))
2711 DECODE_PRINTF("TEST\tAL,");
2712 imm = fetch_byte_imm();
2713 DECODE_PRINTF2("%04x\n", imm);
2715 test_byte(M.x86.R_AL, (u8)imm);
2716 DECODE_CLEAR_SEGOVR();
2720 /****************************************************************************
2723 ****************************************************************************/
2724 void x86emuOp_test_AX_IMM(u8 X86EMU_UNUSED(op1))
2729 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2730 DECODE_PRINTF("TEST\tEAX,");
2731 srcval = fetch_long_imm();
2733 DECODE_PRINTF("TEST\tAX,");
2734 srcval = fetch_word_imm();
2736 DECODE_PRINTF2("%x\n", srcval);
2738 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2739 test_long(M.x86.R_EAX, srcval);
2741 test_word(M.x86.R_AX, (u16)srcval);
2743 DECODE_CLEAR_SEGOVR();
2747 /****************************************************************************
2750 ****************************************************************************/
2751 void x86emuOp_stos_byte(u8 X86EMU_UNUSED(op1))
2756 DECODE_PRINTF("STOS\tBYTE\n");
2757 if (ACCESS_FLAG(F_DF)) /* down */
2762 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2763 /* dont care whether REPE or REPNE */
2764 /* move them until CX is ZERO. */
2765 while (M.x86.R_CX != 0) {
2766 store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AL);
2770 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2772 store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AL);
2775 DECODE_CLEAR_SEGOVR();
2779 /****************************************************************************
2782 ****************************************************************************/
2783 void x86emuOp_stos_word(u8 X86EMU_UNUSED(op1))
2789 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2790 DECODE_PRINTF("STOS\tDWORD\n");
2791 if (ACCESS_FLAG(F_DF)) /* down */
2796 DECODE_PRINTF("STOS\tWORD\n");
2797 if (ACCESS_FLAG(F_DF)) /* down */
2804 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2805 /* dont care whether REPE or REPNE */
2806 /* move them until CX is ZERO. */
2809 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2812 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2813 store_data_long_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_EAX);
2815 store_data_word_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AX);
2819 DECODE_CLEAR_SEGOVR();
2823 /****************************************************************************
2826 ****************************************************************************/
2827 void x86emuOp_lods_byte(u8 X86EMU_UNUSED(op1))
2832 DECODE_PRINTF("LODS\tBYTE\n");
2834 if (ACCESS_FLAG(F_DF)) /* down */
2838 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2839 /* dont care whether REPE or REPNE */
2840 /* move them until CX is ZERO. */
2841 while (M.x86.R_CX != 0) {
2842 M.x86.R_AL = fetch_data_byte(M.x86.R_SI);
2846 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2848 M.x86.R_AL = fetch_data_byte(M.x86.R_SI);
2851 DECODE_CLEAR_SEGOVR();
2855 /****************************************************************************
2858 ****************************************************************************/
2859 void x86emuOp_lods_word(u8 X86EMU_UNUSED(op1))
2865 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2866 DECODE_PRINTF("LODS\tDWORD\n");
2867 if (ACCESS_FLAG(F_DF)) /* down */
2872 DECODE_PRINTF("LODS\tWORD\n");
2873 if (ACCESS_FLAG(F_DF)) /* down */
2880 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2881 /* dont care whether REPE or REPNE */
2882 /* move them until CX is ZERO. */
2885 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2888 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2889 M.x86.R_EAX = fetch_data_long(M.x86.R_SI);
2891 M.x86.R_AX = fetch_data_word(M.x86.R_SI);
2895 DECODE_CLEAR_SEGOVR();
2899 /****************************************************************************
2902 ****************************************************************************/
2903 void x86emuOp_scas_byte(u8 X86EMU_UNUSED(op1))
2909 DECODE_PRINTF("SCAS\tBYTE\n");
2911 if (ACCESS_FLAG(F_DF)) /* down */
2915 if (M.x86.mode & SYSMODE_PREFIX_REPE) {
2917 /* move them until CX is ZERO. */
2918 while (M.x86.R_CX != 0) {
2919 val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2920 cmp_byte(M.x86.R_AL, val2);
2923 if (ACCESS_FLAG(F_ZF) == 0)
2926 M.x86.mode &= ~SYSMODE_PREFIX_REPE;
2927 } else if (M.x86.mode & SYSMODE_PREFIX_REPNE) {
2929 /* move them until CX is ZERO. */
2930 while (M.x86.R_CX != 0) {
2931 val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2932 cmp_byte(M.x86.R_AL, val2);
2935 if (ACCESS_FLAG(F_ZF))
2936 break; /* zero flag set means equal */
2938 M.x86.mode &= ~SYSMODE_PREFIX_REPNE;
2940 val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI);
2941 cmp_byte(M.x86.R_AL, val2);
2944 DECODE_CLEAR_SEGOVR();
2948 /****************************************************************************
2951 ****************************************************************************/
2952 void x86emuOp_scas_word(u8 X86EMU_UNUSED(op1))
2958 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2959 DECODE_PRINTF("SCAS\tDWORD\n");
2960 if (ACCESS_FLAG(F_DF)) /* down */
2965 DECODE_PRINTF("SCAS\tWORD\n");
2966 if (ACCESS_FLAG(F_DF)) /* down */
2972 if (M.x86.mode & SYSMODE_PREFIX_REPE) {
2974 /* move them until CX is ZERO. */
2975 while (M.x86.R_CX != 0) {
2976 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2977 val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
2978 cmp_long(M.x86.R_EAX, val);
2980 val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
2981 cmp_word(M.x86.R_AX, (u16)val);
2985 if (ACCESS_FLAG(F_ZF) == 0)
2988 M.x86.mode &= ~SYSMODE_PREFIX_REPE;
2989 } else if (M.x86.mode & SYSMODE_PREFIX_REPNE) {
2991 /* move them until CX is ZERO. */
2992 while (M.x86.R_CX != 0) {
2993 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2994 val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
2995 cmp_long(M.x86.R_EAX, val);
2997 val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
2998 cmp_word(M.x86.R_AX, (u16)val);
3002 if (ACCESS_FLAG(F_ZF))
3003 break; /* zero flag set means equal */
3005 M.x86.mode &= ~SYSMODE_PREFIX_REPNE;
3007 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3008 val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI);
3009 cmp_long(M.x86.R_EAX, val);
3011 val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI);
3012 cmp_word(M.x86.R_AX, (u16)val);
3016 DECODE_CLEAR_SEGOVR();
3020 /****************************************************************************
3022 Handles opcode 0xb0 - 0xb7
3023 ****************************************************************************/
3024 void x86emuOp_mov_byte_register_IMM(u8 op1)
3029 DECODE_PRINTF("MOV\t");
3030 ptr = DECODE_RM_BYTE_REGISTER(op1 & 0x7);
3032 imm = fetch_byte_imm();
3033 DECODE_PRINTF2("%x\n", imm);
3036 DECODE_CLEAR_SEGOVR();
3040 /****************************************************************************
3042 Handles opcode 0xb8 - 0xbf
3043 ****************************************************************************/
3044 void x86emuOp_mov_word_register_IMM(u8 X86EMU_UNUSED(op1))
3051 DECODE_PRINTF("MOV\t");
3052 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3054 reg32 = DECODE_RM_LONG_REGISTER(op1);
3055 srcval = fetch_long_imm();
3056 DECODE_PRINTF2(",%x\n", srcval);
3061 reg16 = DECODE_RM_WORD_REGISTER(op1);
3062 srcval = fetch_word_imm();
3063 DECODE_PRINTF2(",%x\n", srcval);
3065 *reg16 = (u16)srcval;
3067 DECODE_CLEAR_SEGOVR();
3071 /****************************************************************************
3074 ****************************************************************************/
3075 void x86emuOp_opcC0_byte_RM_MEM(u8 X86EMU_UNUSED(op1))
3084 * Yet another weirdo special case instruction format. Part of
3085 * the opcode held below in "RH". Doubly nested case would
3086 * result, except that the decoded instruction
3089 FETCH_DECODE_MODRM(mod, rh, rl);
3091 if (DEBUG_DECODE()) {
3092 /* XXX DECODE_PRINTF may be changed to something more
3093 general, so that it is important to leave the strings
3094 in the same format, even though the result is that the
3095 above test is done twice. */
3099 DECODE_PRINTF("ROL\t");
3102 DECODE_PRINTF("ROR\t");
3105 DECODE_PRINTF("RCL\t");
3108 DECODE_PRINTF("RCR\t");
3111 DECODE_PRINTF("SHL\t");
3114 DECODE_PRINTF("SHR\t");
3117 DECODE_PRINTF("SAL\t");
3120 DECODE_PRINTF("SAR\t");
3125 /* know operation, decode the mod byte to find the addressing
3128 DECODE_PRINTF("BYTE PTR ");
3129 destoffset = decode_rmXX_address(mod, rl);
3130 amt = fetch_byte_imm();
3131 DECODE_PRINTF2(",%x\n", amt);
3132 destval = fetch_data_byte(destoffset);
3134 destval = (*opcD0_byte_operation[rh]) (destval, amt);
3135 store_data_byte(destoffset, destval);
3136 } else { /* register to register */
3137 destreg = DECODE_RM_BYTE_REGISTER(rl);
3138 amt = fetch_byte_imm();
3139 DECODE_PRINTF2(",%x\n", amt);
3141 destval = (*opcD0_byte_operation[rh]) (*destreg, amt);
3144 DECODE_CLEAR_SEGOVR();
3148 /****************************************************************************
3151 ****************************************************************************/
3152 void x86emuOp_opcC1_word_RM_MEM(u8 X86EMU_UNUSED(op1))
3159 * Yet another weirdo special case instruction format. Part of
3160 * the opcode held below in "RH". Doubly nested case would
3161 * result, except that the decoded instruction
3164 FETCH_DECODE_MODRM(mod, rh, rl);
3166 if (DEBUG_DECODE()) {
3167 /* XXX DECODE_PRINTF may be changed to something more
3168 general, so that it is important to leave the strings
3169 in the same format, even though the result is that the
3170 above test is done twice. */
3174 DECODE_PRINTF("ROL\t");
3177 DECODE_PRINTF("ROR\t");
3180 DECODE_PRINTF("RCL\t");
3183 DECODE_PRINTF("RCR\t");
3186 DECODE_PRINTF("SHL\t");
3189 DECODE_PRINTF("SHR\t");
3192 DECODE_PRINTF("SAL\t");
3195 DECODE_PRINTF("SAR\t");
3200 /* know operation, decode the mod byte to find the addressing
3203 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3206 DECODE_PRINTF("DWORD PTR ");
3207 destoffset = decode_rmXX_address(mod, rl);
3208 amt = fetch_byte_imm();
3209 DECODE_PRINTF2(",%x\n", amt);
3210 destval = fetch_data_long(destoffset);
3212 destval = (*opcD1_long_operation[rh]) (destval, amt);
3213 store_data_long(destoffset, destval);
3217 DECODE_PRINTF("WORD PTR ");
3218 destoffset = decode_rmXX_address(mod, rl);
3219 amt = fetch_byte_imm();
3220 DECODE_PRINTF2(",%x\n", amt);
3221 destval = fetch_data_word(destoffset);
3223 destval = (*opcD1_word_operation[rh]) (destval, amt);
3224 store_data_word(destoffset, destval);
3226 } else { /* register to register */
3227 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3230 destreg = DECODE_RM_LONG_REGISTER(rl);
3231 amt = fetch_byte_imm();
3232 DECODE_PRINTF2(",%x\n", amt);
3234 *destreg = (*opcD1_long_operation[rh]) (*destreg, amt);
3238 destreg = DECODE_RM_WORD_REGISTER(rl);
3239 amt = fetch_byte_imm();
3240 DECODE_PRINTF2(",%x\n", amt);
3242 *destreg = (*opcD1_word_operation[rh]) (*destreg, amt);
3245 DECODE_CLEAR_SEGOVR();
3249 /****************************************************************************
3252 ****************************************************************************/
3253 void x86emuOp_ret_near_IMM(u8 X86EMU_UNUSED(op1))
3258 DECODE_PRINTF("RET\t");
3259 imm = fetch_word_imm();
3260 DECODE_PRINTF2("%x\n", imm);
3261 RETURN_TRACE("RET",M.x86.saved_cs,M.x86.saved_ip);
3263 M.x86.R_IP = pop_word();
3265 DECODE_CLEAR_SEGOVR();
3269 /****************************************************************************
3272 ****************************************************************************/
3273 void x86emuOp_ret_near(u8 X86EMU_UNUSED(op1))
3276 DECODE_PRINTF("RET\n");
3277 RETURN_TRACE("RET",M.x86.saved_cs,M.x86.saved_ip);
3279 M.x86.R_IP = pop_word();
3280 DECODE_CLEAR_SEGOVR();
3284 /****************************************************************************
3287 ****************************************************************************/
3288 void x86emuOp_les_R_IMM(u8 X86EMU_UNUSED(op1))
3295 DECODE_PRINTF("LES\t");
3296 FETCH_DECODE_MODRM(mod, rh, rl);
3298 dstreg = DECODE_RM_WORD_REGISTER(rh);
3300 srcoffset = decode_rmXX_address(mod, rl);
3301 DECODE_PRINTF("\n");
3303 *dstreg = fetch_data_word(srcoffset);
3304 M.x86.R_ES = fetch_data_word(srcoffset + 2);
3306 /* else UNDEFINED! register to register */
3308 DECODE_CLEAR_SEGOVR();
3312 /****************************************************************************
3315 ****************************************************************************/
3316 void x86emuOp_lds_R_IMM(u8 X86EMU_UNUSED(op1))
3323 DECODE_PRINTF("LDS\t");
3324 FETCH_DECODE_MODRM(mod, rh, rl);
3326 dstreg = DECODE_RM_WORD_REGISTER(rh);
3328 srcoffset = decode_rmXX_address(mod, rl);
3329 DECODE_PRINTF("\n");
3331 *dstreg = fetch_data_word(srcoffset);
3332 M.x86.R_DS = fetch_data_word(srcoffset + 2);
3334 /* else UNDEFINED! */
3335 DECODE_CLEAR_SEGOVR();
3339 /****************************************************************************
3342 ****************************************************************************/
3343 void x86emuOp_mov_byte_RM_IMM(u8 X86EMU_UNUSED(op1))
3351 DECODE_PRINTF("MOV\t");
3352 FETCH_DECODE_MODRM(mod, rh, rl);
3354 DECODE_PRINTF("ILLEGAL DECODE OF OPCODE c6\n");
3358 DECODE_PRINTF("BYTE PTR ");
3359 destoffset = decode_rmXX_address(mod, rl);
3360 imm = fetch_byte_imm();
3361 DECODE_PRINTF2(",%2x\n", imm);
3363 store_data_byte(destoffset, imm);
3364 } else { /* register to register */
3365 destreg = DECODE_RM_BYTE_REGISTER(rl);
3366 imm = fetch_byte_imm();
3367 DECODE_PRINTF2(",%2x\n", imm);
3371 DECODE_CLEAR_SEGOVR();
3375 /****************************************************************************
3378 ****************************************************************************/
3379 void x86emuOp_mov_word_RM_IMM(u8 X86EMU_UNUSED(op1))
3385 DECODE_PRINTF("MOV\t");
3386 FETCH_DECODE_MODRM(mod, rh, rl);
3388 DECODE_PRINTF("ILLEGAL DECODE OF OPCODE 8F\n");
3392 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3395 DECODE_PRINTF("DWORD PTR ");
3396 destoffset = decode_rmXX_address(mod, rl);
3397 imm = fetch_long_imm();
3398 DECODE_PRINTF2(",%x\n", imm);
3400 store_data_long(destoffset, imm);
3404 DECODE_PRINTF("WORD PTR ");
3405 destoffset = decode_rmXX_address(mod, rl);
3406 imm = fetch_word_imm();
3407 DECODE_PRINTF2(",%x\n", imm);
3409 store_data_word(destoffset, imm);
3411 } else { /* register to register */
3412 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3416 destreg = DECODE_RM_LONG_REGISTER(rl);
3417 imm = fetch_long_imm();
3418 DECODE_PRINTF2(",%x\n", imm);
3425 destreg = DECODE_RM_WORD_REGISTER(rl);
3426 imm = fetch_word_imm();
3427 DECODE_PRINTF2(",%x\n", imm);
3432 DECODE_CLEAR_SEGOVR();
3436 /****************************************************************************
3439 ****************************************************************************/
3440 void x86emuOp_enter(u8 X86EMU_UNUSED(op1))
3442 u16 local,frame_pointer;
3447 local = fetch_word_imm();
3448 nesting = fetch_byte_imm();
3449 DECODE_PRINTF2("ENTER %x\n", local);
3450 DECODE_PRINTF2(",%x\n", nesting);
3452 push_word(M.x86.R_BP);
3453 frame_pointer = M.x86.R_SP;
3455 for (i = 1; i < nesting; i++) {
3457 push_word(fetch_data_word_abs(M.x86.R_SS, M.x86.R_BP));
3459 push_word(frame_pointer);
3461 M.x86.R_BP = frame_pointer;
3462 M.x86.R_SP = (u16)(M.x86.R_SP - local);
3463 DECODE_CLEAR_SEGOVR();
3467 /****************************************************************************
3470 ****************************************************************************/
3471 void x86emuOp_leave(u8 X86EMU_UNUSED(op1))
3474 DECODE_PRINTF("LEAVE\n");
3476 M.x86.R_SP = M.x86.R_BP;
3477 M.x86.R_BP = pop_word();
3478 DECODE_CLEAR_SEGOVR();
3482 /****************************************************************************
3485 ****************************************************************************/
3486 void x86emuOp_ret_far_IMM(u8 X86EMU_UNUSED(op1))
3491 DECODE_PRINTF("RETF\t");
3492 imm = fetch_word_imm();
3493 DECODE_PRINTF2("%x\n", imm);
3494 RETURN_TRACE("RETF",M.x86.saved_cs,M.x86.saved_ip);
3496 M.x86.R_IP = pop_word();
3497 M.x86.R_CS = pop_word();
3499 DECODE_CLEAR_SEGOVR();
3503 /****************************************************************************
3506 ****************************************************************************/
3507 void x86emuOp_ret_far(u8 X86EMU_UNUSED(op1))
3510 DECODE_PRINTF("RETF\n");
3511 RETURN_TRACE("RETF",M.x86.saved_cs,M.x86.saved_ip);
3513 M.x86.R_IP = pop_word();
3514 M.x86.R_CS = pop_word();
3515 DECODE_CLEAR_SEGOVR();
3519 /****************************************************************************
3522 ****************************************************************************/
3523 void x86emuOp_int3(u8 X86EMU_UNUSED(op1))
3528 DECODE_PRINTF("INT 3\n");
3529 tmp = (u16) mem_access_word(3 * 4 + 2);
3530 /* access the segment register */
3532 if (_X86EMU_intrTab[3]) {
3533 (*_X86EMU_intrTab[3])(3);
3535 push_word((u16)M.x86.R_FLG);
3538 push_word(M.x86.R_CS);
3539 M.x86.R_CS = mem_access_word(3 * 4 + 2);
3540 push_word(M.x86.R_IP);
3541 M.x86.R_IP = mem_access_word(3 * 4);
3543 DECODE_CLEAR_SEGOVR();
3547 /****************************************************************************
3550 ****************************************************************************/
3551 void x86emuOp_int_IMM(u8 X86EMU_UNUSED(op1))
3557 DECODE_PRINTF("INT\t");
3558 intnum = fetch_byte_imm();
3559 DECODE_PRINTF2("%x\n", intnum);
3560 tmp = mem_access_word(intnum * 4 + 2);
3562 if (_X86EMU_intrTab[intnum]) {
3563 (*_X86EMU_intrTab[intnum])(intnum);
3565 push_word((u16)M.x86.R_FLG);
3568 push_word(M.x86.R_CS);
3569 M.x86.R_CS = mem_access_word(intnum * 4 + 2);
3570 push_word(M.x86.R_IP);
3571 M.x86.R_IP = mem_access_word(intnum * 4);
3573 DECODE_CLEAR_SEGOVR();
3577 /****************************************************************************
3580 ****************************************************************************/
3581 void x86emuOp_into(u8 X86EMU_UNUSED(op1))
3586 DECODE_PRINTF("INTO\n");
3588 if (ACCESS_FLAG(F_OF)) {
3589 tmp = mem_access_word(4 * 4 + 2);
3590 if (_X86EMU_intrTab[4]) {
3591 (*_X86EMU_intrTab[4])(4);
3593 push_word((u16)M.x86.R_FLG);
3596 push_word(M.x86.R_CS);
3597 M.x86.R_CS = mem_access_word(4 * 4 + 2);
3598 push_word(M.x86.R_IP);
3599 M.x86.R_IP = mem_access_word(4 * 4);
3602 DECODE_CLEAR_SEGOVR();
3606 /****************************************************************************
3609 ****************************************************************************/
3610 void x86emuOp_iret(u8 X86EMU_UNUSED(op1))
3613 DECODE_PRINTF("IRET\n");
3617 M.x86.R_IP = pop_word();
3618 M.x86.R_CS = pop_word();
3619 M.x86.R_FLG = pop_word();
3620 DECODE_CLEAR_SEGOVR();
3624 /****************************************************************************
3627 ****************************************************************************/
3628 void x86emuOp_opcD0_byte_RM_1(u8 X86EMU_UNUSED(op1))
3636 * Yet another weirdo special case instruction format. Part of
3637 * the opcode held below in "RH". Doubly nested case would
3638 * result, except that the decoded instruction
3641 FETCH_DECODE_MODRM(mod, rh, rl);
3643 if (DEBUG_DECODE()) {
3644 /* XXX DECODE_PRINTF may be changed to something more
3645 general, so that it is important to leave the strings
3646 in the same format, even though the result is that the
3647 above test is done twice. */
3650 DECODE_PRINTF("ROL\t");
3653 DECODE_PRINTF("ROR\t");
3656 DECODE_PRINTF("RCL\t");
3659 DECODE_PRINTF("RCR\t");
3662 DECODE_PRINTF("SHL\t");
3665 DECODE_PRINTF("SHR\t");
3668 DECODE_PRINTF("SAL\t");
3671 DECODE_PRINTF("SAR\t");
3676 /* know operation, decode the mod byte to find the addressing
3679 DECODE_PRINTF("BYTE PTR ");
3680 destoffset = decode_rmXX_address(mod, rl);
3681 DECODE_PRINTF(",1\n");
3682 destval = fetch_data_byte(destoffset);
3684 destval = (*opcD0_byte_operation[rh]) (destval, 1);
3685 store_data_byte(destoffset, destval);
3686 } else { /* register to register */
3687 destreg = DECODE_RM_BYTE_REGISTER(rl);
3688 DECODE_PRINTF(",1\n");
3690 destval = (*opcD0_byte_operation[rh]) (*destreg, 1);
3693 DECODE_CLEAR_SEGOVR();
3697 /****************************************************************************
3700 ****************************************************************************/
3701 void x86emuOp_opcD1_word_RM_1(u8 X86EMU_UNUSED(op1))
3707 * Yet another weirdo special case instruction format. Part of
3708 * the opcode held below in "RH". Doubly nested case would
3709 * result, except that the decoded instruction
3712 FETCH_DECODE_MODRM(mod, rh, rl);
3714 if (DEBUG_DECODE()) {
3715 /* XXX DECODE_PRINTF may be changed to something more
3716 general, so that it is important to leave the strings
3717 in the same format, even though the result is that the
3718 above test is done twice. */
3721 DECODE_PRINTF("ROL\t");
3724 DECODE_PRINTF("ROR\t");
3727 DECODE_PRINTF("RCL\t");
3730 DECODE_PRINTF("RCR\t");
3733 DECODE_PRINTF("SHL\t");
3736 DECODE_PRINTF("SHR\t");
3739 DECODE_PRINTF("SAL\t");
3742 DECODE_PRINTF("SAR\t");
3747 /* know operation, decode the mod byte to find the addressing
3750 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3753 DECODE_PRINTF("DWORD PTR ");
3754 destoffset = decode_rmXX_address(mod, rl);
3755 DECODE_PRINTF(",1\n");
3756 destval = fetch_data_long(destoffset);
3758 destval = (*opcD1_long_operation[rh]) (destval, 1);
3759 store_data_long(destoffset, destval);
3763 DECODE_PRINTF("WORD PTR ");
3764 destoffset = decode_rmXX_address(mod, rl);
3765 DECODE_PRINTF(",1\n");
3766 destval = fetch_data_word(destoffset);
3768 destval = (*opcD1_word_operation[rh]) (destval, 1);
3769 store_data_word(destoffset, destval);
3771 } else { /* register to register */
3772 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3776 destreg = DECODE_RM_LONG_REGISTER(rl);
3777 DECODE_PRINTF(",1\n");
3779 destval = (*opcD1_long_operation[rh]) (*destreg, 1);
3785 destreg = DECODE_RM_WORD_REGISTER(rl);
3786 DECODE_PRINTF(",1\n");
3788 destval = (*opcD1_word_operation[rh]) (*destreg, 1);
3792 DECODE_CLEAR_SEGOVR();
3796 /****************************************************************************
3799 ****************************************************************************/
3800 void x86emuOp_opcD2_byte_RM_CL(u8 X86EMU_UNUSED(op1))
3809 * Yet another weirdo special case instruction format. Part of
3810 * the opcode held below in "RH". Doubly nested case would
3811 * result, except that the decoded instruction
3814 FETCH_DECODE_MODRM(mod, rh, rl);
3816 if (DEBUG_DECODE()) {
3817 /* XXX DECODE_PRINTF may be changed to something more
3818 general, so that it is important to leave the strings
3819 in the same format, even though the result is that the
3820 above test is done twice. */
3823 DECODE_PRINTF("ROL\t");
3826 DECODE_PRINTF("ROR\t");
3829 DECODE_PRINTF("RCL\t");
3832 DECODE_PRINTF("RCR\t");
3835 DECODE_PRINTF("SHL\t");
3838 DECODE_PRINTF("SHR\t");
3841 DECODE_PRINTF("SAL\t");
3844 DECODE_PRINTF("SAR\t");
3849 /* know operation, decode the mod byte to find the addressing
3853 DECODE_PRINTF("BYTE PTR ");
3854 destoffset = decode_rmXX_address(mod, rl);
3855 DECODE_PRINTF(",CL\n");
3856 destval = fetch_data_byte(destoffset);
3858 destval = (*opcD0_byte_operation[rh]) (destval, amt);
3859 store_data_byte(destoffset, destval);
3860 } else { /* register to register */
3861 destreg = DECODE_RM_BYTE_REGISTER(rl);
3862 DECODE_PRINTF(",CL\n");
3864 destval = (*opcD0_byte_operation[rh]) (*destreg, amt);
3867 DECODE_CLEAR_SEGOVR();
3871 /****************************************************************************
3874 ****************************************************************************/
3875 void x86emuOp_opcD3_word_RM_CL(u8 X86EMU_UNUSED(op1))
3882 * Yet another weirdo special case instruction format. Part of
3883 * the opcode held below in "RH". Doubly nested case would
3884 * result, except that the decoded instruction
3887 FETCH_DECODE_MODRM(mod, rh, rl);
3889 if (DEBUG_DECODE()) {
3890 /* XXX DECODE_PRINTF may be changed to something more
3891 general, so that it is important to leave the strings
3892 in the same format, even though the result is that the
3893 above test is done twice. */
3896 DECODE_PRINTF("ROL\t");
3899 DECODE_PRINTF("ROR\t");
3902 DECODE_PRINTF("RCL\t");
3905 DECODE_PRINTF("RCR\t");
3908 DECODE_PRINTF("SHL\t");
3911 DECODE_PRINTF("SHR\t");
3914 DECODE_PRINTF("SAL\t");
3917 DECODE_PRINTF("SAR\t");
3922 /* know operation, decode the mod byte to find the addressing
3926 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3929 DECODE_PRINTF("DWORD PTR ");
3930 destoffset = decode_rmXX_address(mod, rl);
3931 DECODE_PRINTF(",CL\n");
3932 destval = fetch_data_long(destoffset);
3934 destval = (*opcD1_long_operation[rh]) (destval, amt);
3935 store_data_long(destoffset, destval);
3939 DECODE_PRINTF("WORD PTR ");
3940 destoffset = decode_rmXX_address(mod, rl);
3941 DECODE_PRINTF(",CL\n");
3942 destval = fetch_data_word(destoffset);
3944 destval = (*opcD1_word_operation[rh]) (destval, amt);
3945 store_data_word(destoffset, destval);
3947 } else { /* register to register */
3948 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
3951 destreg = DECODE_RM_LONG_REGISTER(rl);
3952 DECODE_PRINTF(",CL\n");
3954 *destreg = (*opcD1_long_operation[rh]) (*destreg, amt);
3958 destreg = DECODE_RM_WORD_REGISTER(rl);
3959 DECODE_PRINTF(",CL\n");
3961 *destreg = (*opcD1_word_operation[rh]) (*destreg, amt);
3964 DECODE_CLEAR_SEGOVR();
3968 /****************************************************************************
3971 ****************************************************************************/
3972 void x86emuOp_aam(u8 X86EMU_UNUSED(op1))
3977 DECODE_PRINTF("AAM\n");
3978 a = fetch_byte_imm(); /* this is a stupid encoding. */
3980 DECODE_PRINTF("ERROR DECODING AAM\n");
3985 /* note the type change here --- returning AL and AH in AX. */
3986 M.x86.R_AX = aam_word(M.x86.R_AL);
3987 DECODE_CLEAR_SEGOVR();
3991 /****************************************************************************
3994 ****************************************************************************/
3995 void x86emuOp_aad(u8 X86EMU_UNUSED(op1))
4000 DECODE_PRINTF("AAD\n");
4001 a = fetch_byte_imm();
4003 M.x86.R_AX = aad_word(M.x86.R_AX);
4004 DECODE_CLEAR_SEGOVR();
4008 /* opcode 0xd6 ILLEGAL OPCODE */
4010 /****************************************************************************
4013 ****************************************************************************/
4014 void x86emuOp_xlat(u8 X86EMU_UNUSED(op1))
4019 DECODE_PRINTF("XLAT\n");
4021 addr = (u16)(M.x86.R_BX + (u8)M.x86.R_AL);
4022 M.x86.R_AL = fetch_data_byte(addr);
4023 DECODE_CLEAR_SEGOVR();
4027 /* instuctions D8 .. DF are in i87_ops.c */
4029 /****************************************************************************
4032 ****************************************************************************/
4033 void x86emuOp_loopne(u8 X86EMU_UNUSED(op1))
4038 DECODE_PRINTF("LOOPNE\t");
4039 ip = (s8) fetch_byte_imm();
4040 ip += (s16) M.x86.R_IP;
4041 DECODE_PRINTF2("%04x\n", ip);
4044 if (M.x86.R_CX != 0 && !ACCESS_FLAG(F_ZF)) /* CX != 0 and !ZF */
4046 DECODE_CLEAR_SEGOVR();
4050 /****************************************************************************
4053 ****************************************************************************/
4054 void x86emuOp_loope(u8 X86EMU_UNUSED(op1))
4059 DECODE_PRINTF("LOOPE\t");
4060 ip = (s8) fetch_byte_imm();
4061 ip += (s16) M.x86.R_IP;
4062 DECODE_PRINTF2("%04x\n", ip);
4065 if (M.x86.R_CX != 0 && ACCESS_FLAG(F_ZF)) /* CX != 0 and ZF */
4067 DECODE_CLEAR_SEGOVR();
4071 /****************************************************************************
4074 ****************************************************************************/
4075 void x86emuOp_loop(u8 X86EMU_UNUSED(op1))
4080 DECODE_PRINTF("LOOP\t");
4081 ip = (s8) fetch_byte_imm();
4082 ip += (s16) M.x86.R_IP;
4083 DECODE_PRINTF2("%04x\n", ip);
4086 if (M.x86.R_CX != 0)
4088 DECODE_CLEAR_SEGOVR();
4092 /****************************************************************************
4095 ****************************************************************************/
4096 void x86emuOp_jcxz(u8 X86EMU_UNUSED(op1))
4101 /* jump to byte offset if overflow flag is set */
4103 DECODE_PRINTF("JCXZ\t");
4104 offset = (s8)fetch_byte_imm();
4105 target = (u16)(M.x86.R_IP + offset);
4106 DECODE_PRINTF2("%x\n", target);
4108 if (M.x86.R_CX == 0)
4109 M.x86.R_IP = target;
4110 DECODE_CLEAR_SEGOVR();
4114 /****************************************************************************
4117 ****************************************************************************/
4118 void x86emuOp_in_byte_AL_IMM(u8 X86EMU_UNUSED(op1))
4123 DECODE_PRINTF("IN\t");
4124 port = (u8) fetch_byte_imm();
4125 DECODE_PRINTF2("%x,AL\n", port);
4127 M.x86.R_AL = (*sys_inb)(port);
4128 DECODE_CLEAR_SEGOVR();
4132 /****************************************************************************
4135 ****************************************************************************/
4136 void x86emuOp_in_word_AX_IMM(u8 X86EMU_UNUSED(op1))
4141 DECODE_PRINTF("IN\t");
4142 port = (u8) fetch_byte_imm();
4143 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4144 DECODE_PRINTF2("EAX,%x\n", port);
4146 DECODE_PRINTF2("AX,%x\n", port);
4149 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4150 M.x86.R_EAX = (*sys_inl)(port);
4152 M.x86.R_AX = (*sys_inw)(port);
4154 DECODE_CLEAR_SEGOVR();
4158 /****************************************************************************
4161 ****************************************************************************/
4162 void x86emuOp_out_byte_IMM_AL(u8 X86EMU_UNUSED(op1))
4167 DECODE_PRINTF("OUT\t");
4168 port = (u8) fetch_byte_imm();
4169 DECODE_PRINTF2("%x,AL\n", port);
4171 (*sys_outb)(port, M.x86.R_AL);
4172 DECODE_CLEAR_SEGOVR();
4176 /****************************************************************************
4179 ****************************************************************************/
4180 void x86emuOp_out_word_IMM_AX(u8 X86EMU_UNUSED(op1))
4185 DECODE_PRINTF("OUT\t");
4186 port = (u8) fetch_byte_imm();
4187 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4188 DECODE_PRINTF2("%x,EAX\n", port);
4190 DECODE_PRINTF2("%x,AX\n", port);
4193 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4194 (*sys_outl)(port, M.x86.R_EAX);
4196 (*sys_outw)(port, M.x86.R_AX);
4198 DECODE_CLEAR_SEGOVR();
4202 /****************************************************************************
4205 ****************************************************************************/
4206 void x86emuOp_call_near_IMM(u8 X86EMU_UNUSED(op1))
4211 DECODE_PRINTF("CALL\t");
4212 ip = (s16) fetch_word_imm();
4213 ip += (s16) M.x86.R_IP; /* CHECK SIGN */
4214 DECODE_PRINTF2("%04x\n", ip);
4215 CALL_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, ip, "");
4217 push_word(M.x86.R_IP);
4219 DECODE_CLEAR_SEGOVR();
4223 /****************************************************************************
4226 ****************************************************************************/
4227 void x86emuOp_jump_near_IMM(u8 X86EMU_UNUSED(op1))
4232 DECODE_PRINTF("JMP\t");
4233 ip = (s16)fetch_word_imm();
4234 ip += (s16)M.x86.R_IP;
4235 DECODE_PRINTF2("%04x\n", ip);
4237 M.x86.R_IP = (u16)ip;
4238 DECODE_CLEAR_SEGOVR();
4242 /****************************************************************************
4245 ****************************************************************************/
4246 void x86emuOp_jump_far_IMM(u8 X86EMU_UNUSED(op1))
4251 DECODE_PRINTF("JMP\tFAR ");
4252 ip = fetch_word_imm();
4253 cs = fetch_word_imm();
4254 DECODE_PRINTF2("%04x:", cs);
4255 DECODE_PRINTF2("%04x\n", ip);
4259 DECODE_CLEAR_SEGOVR();
4263 /****************************************************************************
4266 ****************************************************************************/
4267 void x86emuOp_jump_byte_IMM(u8 X86EMU_UNUSED(op1))
4273 DECODE_PRINTF("JMP\t");
4274 offset = (s8)fetch_byte_imm();
4275 target = (u16)(M.x86.R_IP + offset);
4276 DECODE_PRINTF2("%x\n", target);
4278 M.x86.R_IP = target;
4279 DECODE_CLEAR_SEGOVR();
4283 /****************************************************************************
4286 ****************************************************************************/
4287 void x86emuOp_in_byte_AL_DX(u8 X86EMU_UNUSED(op1))
4290 DECODE_PRINTF("IN\tAL,DX\n");
4292 M.x86.R_AL = (*sys_inb)(M.x86.R_DX);
4293 DECODE_CLEAR_SEGOVR();
4297 /****************************************************************************
4300 ****************************************************************************/
4301 void x86emuOp_in_word_AX_DX(u8 X86EMU_UNUSED(op1))
4304 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4305 DECODE_PRINTF("IN\tEAX,DX\n");
4307 DECODE_PRINTF("IN\tAX,DX\n");
4310 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4311 M.x86.R_EAX = (*sys_inl)(M.x86.R_DX);
4313 M.x86.R_AX = (*sys_inw)(M.x86.R_DX);
4315 DECODE_CLEAR_SEGOVR();
4319 /****************************************************************************
4322 ****************************************************************************/
4323 void x86emuOp_out_byte_DX_AL(u8 X86EMU_UNUSED(op1))
4326 DECODE_PRINTF("OUT\tDX,AL\n");
4328 (*sys_outb)(M.x86.R_DX, M.x86.R_AL);
4329 DECODE_CLEAR_SEGOVR();
4333 /****************************************************************************
4336 ****************************************************************************/
4337 void x86emuOp_out_word_DX_AX(u8 X86EMU_UNUSED(op1))
4340 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4341 DECODE_PRINTF("OUT\tDX,EAX\n");
4343 DECODE_PRINTF("OUT\tDX,AX\n");
4346 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4347 (*sys_outl)(M.x86.R_DX, M.x86.R_EAX);
4349 (*sys_outw)(M.x86.R_DX, M.x86.R_AX);
4351 DECODE_CLEAR_SEGOVR();
4355 /****************************************************************************
4358 ****************************************************************************/
4359 void x86emuOp_lock(u8 X86EMU_UNUSED(op1))
4362 DECODE_PRINTF("LOCK:\n");
4364 DECODE_CLEAR_SEGOVR();
4368 /*opcode 0xf1 ILLEGAL OPERATION */
4370 /****************************************************************************
4373 ****************************************************************************/
4374 void x86emuOp_repne(u8 X86EMU_UNUSED(op1))
4377 DECODE_PRINTF("REPNE\n");
4379 M.x86.mode |= SYSMODE_PREFIX_REPNE;
4380 DECODE_CLEAR_SEGOVR();
4384 /****************************************************************************
4387 ****************************************************************************/
4388 void x86emuOp_repe(u8 X86EMU_UNUSED(op1))
4391 DECODE_PRINTF("REPE\n");
4393 M.x86.mode |= SYSMODE_PREFIX_REPE;
4394 DECODE_CLEAR_SEGOVR();
4398 /****************************************************************************
4401 ****************************************************************************/
4402 void x86emuOp_halt(u8 X86EMU_UNUSED(op1))
4405 DECODE_PRINTF("HALT\n");
4408 DECODE_CLEAR_SEGOVR();
4412 /****************************************************************************
4415 ****************************************************************************/
4416 void x86emuOp_cmc(u8 X86EMU_UNUSED(op1))
4418 /* complement the carry flag. */
4420 DECODE_PRINTF("CMC\n");
4423 DECODE_CLEAR_SEGOVR();
4427 /****************************************************************************
4430 ****************************************************************************/
4431 void x86emuOp_opcF6_byte_RM(u8 X86EMU_UNUSED(op1))
4438 /* long, drawn out code follows. Double switch for a total
4441 FETCH_DECODE_MODRM(mod, rh, rl);
4442 DECODE_PRINTF(opF6_names[rh]);
4444 DECODE_PRINTF("BYTE PTR ");
4445 destoffset = decode_rmXX_address(mod, rl);
4446 destval = fetch_data_byte(destoffset);
4449 case 0: /* test byte imm */
4451 srcval = fetch_byte_imm();
4452 DECODE_PRINTF2("%02x\n", srcval);
4454 test_byte(destval, srcval);
4457 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4461 DECODE_PRINTF("\n");
4463 destval = not_byte(destval);
4464 store_data_byte(destoffset, destval);
4467 DECODE_PRINTF("\n");
4469 destval = neg_byte(destval);
4470 store_data_byte(destoffset, destval);
4473 DECODE_PRINTF("\n");
4478 DECODE_PRINTF("\n");
4483 DECODE_PRINTF("\n");
4488 DECODE_PRINTF("\n");
4493 } else { /* mod=11 */
4494 destreg = DECODE_RM_BYTE_REGISTER(rl);
4496 case 0: /* test byte imm */
4498 srcval = fetch_byte_imm();
4499 DECODE_PRINTF2("%02x\n", srcval);
4501 test_byte(*destreg, srcval);
4504 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4508 DECODE_PRINTF("\n");
4510 *destreg = not_byte(*destreg);
4513 DECODE_PRINTF("\n");
4515 *destreg = neg_byte(*destreg);
4518 DECODE_PRINTF("\n");
4520 mul_byte(*destreg); /*!!! */
4523 DECODE_PRINTF("\n");
4525 imul_byte(*destreg);
4528 DECODE_PRINTF("\n");
4533 DECODE_PRINTF("\n");
4535 idiv_byte(*destreg);
4539 DECODE_CLEAR_SEGOVR();
4543 /****************************************************************************
4546 ****************************************************************************/
4547 void x86emuOp_opcF7_word_RM(u8 X86EMU_UNUSED(op1))
4553 FETCH_DECODE_MODRM(mod, rh, rl);
4554 DECODE_PRINTF(opF6_names[rh]);
4557 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4558 u32 destval, srcval;
4560 DECODE_PRINTF("DWORD PTR ");
4561 destoffset = decode_rmXX_address(mod, rl);
4562 destval = fetch_data_long(destoffset);
4567 srcval = fetch_long_imm();
4568 DECODE_PRINTF2("%x\n", srcval);
4570 test_long(destval, srcval);
4573 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F7\n");
4577 DECODE_PRINTF("\n");
4579 destval = not_long(destval);
4580 store_data_long(destoffset, destval);
4583 DECODE_PRINTF("\n");
4585 destval = neg_long(destval);
4586 store_data_long(destoffset, destval);
4589 DECODE_PRINTF("\n");
4594 DECODE_PRINTF("\n");
4599 DECODE_PRINTF("\n");
4604 DECODE_PRINTF("\n");
4610 u16 destval, srcval;
4612 DECODE_PRINTF("WORD PTR ");
4613 destoffset = decode_rmXX_address(mod, rl);
4614 destval = fetch_data_word(destoffset);
4617 case 0: /* test word imm */
4619 srcval = fetch_word_imm();
4620 DECODE_PRINTF2("%x\n", srcval);
4622 test_word(destval, srcval);
4625 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F7\n");
4629 DECODE_PRINTF("\n");
4631 destval = not_word(destval);
4632 store_data_word(destoffset, destval);
4635 DECODE_PRINTF("\n");
4637 destval = neg_word(destval);
4638 store_data_word(destoffset, destval);
4641 DECODE_PRINTF("\n");
4646 DECODE_PRINTF("\n");
4651 DECODE_PRINTF("\n");
4656 DECODE_PRINTF("\n");
4663 } else { /* mod=11 */
4665 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4669 destreg = DECODE_RM_LONG_REGISTER(rl);
4672 case 0: /* test word imm */
4674 srcval = fetch_long_imm();
4675 DECODE_PRINTF2("%x\n", srcval);
4677 test_long(*destreg, srcval);
4680 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4684 DECODE_PRINTF("\n");
4686 *destreg = not_long(*destreg);
4689 DECODE_PRINTF("\n");
4691 *destreg = neg_long(*destreg);
4694 DECODE_PRINTF("\n");
4696 mul_long(*destreg); /*!!! */
4699 DECODE_PRINTF("\n");
4701 imul_long(*destreg);
4704 DECODE_PRINTF("\n");
4709 DECODE_PRINTF("\n");
4711 idiv_long(*destreg);
4718 destreg = DECODE_RM_WORD_REGISTER(rl);
4721 case 0: /* test word imm */
4723 srcval = fetch_word_imm();
4724 DECODE_PRINTF2("%x\n", srcval);
4726 test_word(*destreg, srcval);
4729 DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n");
4733 DECODE_PRINTF("\n");
4735 *destreg = not_word(*destreg);
4738 DECODE_PRINTF("\n");
4740 *destreg = neg_word(*destreg);
4743 DECODE_PRINTF("\n");
4745 mul_word(*destreg); /*!!! */
4748 DECODE_PRINTF("\n");
4750 imul_word(*destreg);
4753 DECODE_PRINTF("\n");
4758 DECODE_PRINTF("\n");
4760 idiv_word(*destreg);
4765 DECODE_CLEAR_SEGOVR();
4769 /****************************************************************************
4772 ****************************************************************************/
4773 void x86emuOp_clc(u8 X86EMU_UNUSED(op1))
4775 /* clear the carry flag. */
4777 DECODE_PRINTF("CLC\n");
4780 DECODE_CLEAR_SEGOVR();
4784 /****************************************************************************
4787 ****************************************************************************/
4788 void x86emuOp_stc(u8 X86EMU_UNUSED(op1))
4790 /* set the carry flag. */
4792 DECODE_PRINTF("STC\n");
4795 DECODE_CLEAR_SEGOVR();
4799 /****************************************************************************
4802 ****************************************************************************/
4803 void x86emuOp_cli(u8 X86EMU_UNUSED(op1))
4805 /* clear interrupts. */
4807 DECODE_PRINTF("CLI\n");
4810 DECODE_CLEAR_SEGOVR();
4814 /****************************************************************************
4817 ****************************************************************************/
4818 void x86emuOp_sti(u8 X86EMU_UNUSED(op1))
4820 /* enable interrupts. */
4822 DECODE_PRINTF("STI\n");
4825 DECODE_CLEAR_SEGOVR();
4829 /****************************************************************************
4832 ****************************************************************************/
4833 void x86emuOp_cld(u8 X86EMU_UNUSED(op1))
4835 /* clear interrupts. */
4837 DECODE_PRINTF("CLD\n");
4840 DECODE_CLEAR_SEGOVR();
4844 /****************************************************************************
4847 ****************************************************************************/
4848 void x86emuOp_std(u8 X86EMU_UNUSED(op1))
4850 /* clear interrupts. */
4852 DECODE_PRINTF("STD\n");
4855 DECODE_CLEAR_SEGOVR();
4859 /****************************************************************************
4862 ****************************************************************************/
4863 void x86emuOp_opcFE_byte_RM(u8 X86EMU_UNUSED(op1))
4870 /* Yet another special case instruction. */
4872 FETCH_DECODE_MODRM(mod, rh, rl);
4874 if (DEBUG_DECODE()) {
4875 /* XXX DECODE_PRINTF may be changed to something more
4876 general, so that it is important to leave the strings
4877 in the same format, even though the result is that the
4878 above test is done twice. */
4882 DECODE_PRINTF("INC\t");
4885 DECODE_PRINTF("DEC\t");
4893 DECODE_PRINTF2("ILLEGAL OP MAJOR OP 0xFE MINOR OP %x \n", mod);
4900 DECODE_PRINTF("BYTE PTR ");
4901 destoffset = decode_rmXX_address(mod, rl);
4902 DECODE_PRINTF("\n");
4903 destval = fetch_data_byte(destoffset);
4906 destval = inc_byte(destval);
4908 destval = dec_byte(destval);
4909 store_data_byte(destoffset, destval);
4911 destreg = DECODE_RM_BYTE_REGISTER(rl);
4912 DECODE_PRINTF("\n");
4915 *destreg = inc_byte(*destreg);
4917 *destreg = dec_byte(*destreg);
4919 DECODE_CLEAR_SEGOVR();
4923 /****************************************************************************
4926 ****************************************************************************/
4927 void x86emuOp_opcFF_word_RM(u8 X86EMU_UNUSED(op1))
4930 uint destoffset = 0;
4932 u16 destval,destval2;
4934 /* Yet another special case instruction. */
4936 FETCH_DECODE_MODRM(mod, rh, rl);
4938 if (DEBUG_DECODE()) {
4939 /* XXX DECODE_PRINTF may be changed to something more
4940 general, so that it is important to leave the strings
4941 in the same format, even though the result is that the
4942 above test is done twice. */
4946 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4947 DECODE_PRINTF("INC\tDWORD PTR ");
4949 DECODE_PRINTF("INC\tWORD PTR ");
4953 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4954 DECODE_PRINTF("DEC\tDWORD PTR ");
4956 DECODE_PRINTF("DEC\tWORD PTR ");
4960 DECODE_PRINTF("CALL\t ");
4963 DECODE_PRINTF("CALL\tFAR ");
4966 DECODE_PRINTF("JMP\t");
4969 DECODE_PRINTF("JMP\tFAR ");
4972 DECODE_PRINTF("PUSH\t");
4975 DECODE_PRINTF("ILLEGAL DECODING OF OPCODE FF\t");
4982 destoffset = decode_rmXX_address(mod, rl);
4983 DECODE_PRINTF("\n");
4985 case 0: /* inc word ptr ... */
4986 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
4989 destval = fetch_data_long(destoffset);
4991 destval = inc_long(destval);
4992 store_data_long(destoffset, destval);
4996 destval = fetch_data_word(destoffset);
4998 destval = inc_word(destval);
4999 store_data_word(destoffset, destval);
5002 case 1: /* dec word ptr ... */
5003 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5006 destval = fetch_data_long(destoffset);
5008 destval = dec_long(destval);
5009 store_data_long(destoffset, destval);
5013 destval = fetch_data_word(destoffset);
5015 destval = dec_word(destval);
5016 store_data_word(destoffset, destval);
5019 case 2: /* call word ptr ... */
5020 destval = fetch_data_word(destoffset);
5022 push_word(M.x86.R_IP);
5023 M.x86.R_IP = destval;
5025 case 3: /* call far ptr ... */
5026 destval = fetch_data_word(destoffset);
5027 destval2 = fetch_data_word(destoffset + 2);
5029 push_word(M.x86.R_CS);
5030 M.x86.R_CS = destval2;
5031 push_word(M.x86.R_IP);
5032 M.x86.R_IP = destval;
5034 case 4: /* jmp word ptr ... */
5035 destval = fetch_data_word(destoffset);
5037 M.x86.R_IP = destval;
5039 case 5: /* jmp far ptr ... */
5040 destval = fetch_data_word(destoffset);
5041 destval2 = fetch_data_word(destoffset + 2);
5043 M.x86.R_IP = destval;
5044 M.x86.R_CS = destval2;
5046 case 6: /* push word ptr ... */
5047 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5050 destval = fetch_data_long(destoffset);
5056 destval = fetch_data_word(destoffset);
5065 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5068 destreg = DECODE_RM_LONG_REGISTER(rl);
5069 DECODE_PRINTF("\n");
5071 *destreg = inc_long(*destreg);
5075 destreg = DECODE_RM_WORD_REGISTER(rl);
5076 DECODE_PRINTF("\n");
5078 *destreg = inc_word(*destreg);
5082 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5085 destreg = DECODE_RM_LONG_REGISTER(rl);
5086 DECODE_PRINTF("\n");
5088 *destreg = dec_long(*destreg);
5092 destreg = DECODE_RM_WORD_REGISTER(rl);
5093 DECODE_PRINTF("\n");
5095 *destreg = dec_word(*destreg);
5098 case 2: /* call word ptr ... */
5099 destreg = DECODE_RM_WORD_REGISTER(rl);
5100 DECODE_PRINTF("\n");
5102 push_word(M.x86.R_IP);
5103 M.x86.R_IP = *destreg;
5105 case 3: /* jmp far ptr ... */
5106 DECODE_PRINTF("OPERATION UNDEFINED 0XFF \n");
5111 case 4: /* jmp ... */
5112 destreg = DECODE_RM_WORD_REGISTER(rl);
5113 DECODE_PRINTF("\n");
5115 M.x86.R_IP = (u16) (*destreg);
5117 case 5: /* jmp far ptr ... */
5118 DECODE_PRINTF("OPERATION UNDEFINED 0XFF \n");
5123 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
5126 destreg = DECODE_RM_LONG_REGISTER(rl);
5127 DECODE_PRINTF("\n");
5129 push_long(*destreg);
5133 destreg = DECODE_RM_WORD_REGISTER(rl);
5134 DECODE_PRINTF("\n");
5136 push_word(*destreg);
5141 DECODE_CLEAR_SEGOVR();
5145 /***************************************************************************
5146 * Single byte operation code table:
5147 **************************************************************************/
5148 void (*x86emu_optab[256])(u8) __attribute__ ((section(".got2"))) =
5150 /* 0x00 */ x86emuOp_genop_byte_RM_R,
5151 /* 0x01 */ x86emuOp_genop_word_RM_R,
5152 /* 0x02 */ x86emuOp_genop_byte_R_RM,
5153 /* 0x03 */ x86emuOp_genop_word_R_RM,
5154 /* 0x04 */ x86emuOp_genop_byte_AL_IMM,
5155 /* 0x05 */ x86emuOp_genop_word_AX_IMM,
5156 /* 0x06 */ x86emuOp_push_ES,
5157 /* 0x07 */ x86emuOp_pop_ES,
5159 /* 0x08 */ x86emuOp_genop_byte_RM_R,
5160 /* 0x09 */ x86emuOp_genop_word_RM_R,
5161 /* 0x0a */ x86emuOp_genop_byte_R_RM,
5162 /* 0x0b */ x86emuOp_genop_word_R_RM,
5163 /* 0x0c */ x86emuOp_genop_byte_AL_IMM,
5164 /* 0x0d */ x86emuOp_genop_word_AX_IMM,
5165 /* 0x0e */ x86emuOp_push_CS,
5166 /* 0x0f */ x86emuOp_two_byte,
5168 /* 0x10 */ x86emuOp_genop_byte_RM_R,
5169 /* 0x11 */ x86emuOp_genop_word_RM_R,
5170 /* 0x12 */ x86emuOp_genop_byte_R_RM,
5171 /* 0x13 */ x86emuOp_genop_word_R_RM,
5172 /* 0x14 */ x86emuOp_genop_byte_AL_IMM,
5173 /* 0x15 */ x86emuOp_genop_word_AX_IMM,
5174 /* 0x16 */ x86emuOp_push_SS,
5175 /* 0x17 */ x86emuOp_pop_SS,
5177 /* 0x18 */ x86emuOp_genop_byte_RM_R,
5178 /* 0x19 */ x86emuOp_genop_word_RM_R,
5179 /* 0x1a */ x86emuOp_genop_byte_R_RM,
5180 /* 0x1b */ x86emuOp_genop_word_R_RM,
5181 /* 0x1c */ x86emuOp_genop_byte_AL_IMM,
5182 /* 0x1d */ x86emuOp_genop_word_AX_IMM,
5183 /* 0x1e */ x86emuOp_push_DS,
5184 /* 0x1f */ x86emuOp_pop_DS,
5186 /* 0x20 */ x86emuOp_genop_byte_RM_R,
5187 /* 0x21 */ x86emuOp_genop_word_RM_R,
5188 /* 0x22 */ x86emuOp_genop_byte_R_RM,
5189 /* 0x23 */ x86emuOp_genop_word_R_RM,
5190 /* 0x24 */ x86emuOp_genop_byte_AL_IMM,
5191 /* 0x25 */ x86emuOp_genop_word_AX_IMM,
5192 /* 0x26 */ x86emuOp_segovr_ES,
5193 /* 0x27 */ x86emuOp_daa,
5195 /* 0x28 */ x86emuOp_genop_byte_RM_R,
5196 /* 0x29 */ x86emuOp_genop_word_RM_R,
5197 /* 0x2a */ x86emuOp_genop_byte_R_RM,
5198 /* 0x2b */ x86emuOp_genop_word_R_RM,
5199 /* 0x2c */ x86emuOp_genop_byte_AL_IMM,
5200 /* 0x2d */ x86emuOp_genop_word_AX_IMM,
5201 /* 0x2e */ x86emuOp_segovr_CS,
5202 /* 0x2f */ x86emuOp_das,
5204 /* 0x30 */ x86emuOp_genop_byte_RM_R,
5205 /* 0x31 */ x86emuOp_genop_word_RM_R,
5206 /* 0x32 */ x86emuOp_genop_byte_R_RM,
5207 /* 0x33 */ x86emuOp_genop_word_R_RM,
5208 /* 0x34 */ x86emuOp_genop_byte_AL_IMM,
5209 /* 0x35 */ x86emuOp_genop_word_AX_IMM,
5210 /* 0x36 */ x86emuOp_segovr_SS,
5211 /* 0x37 */ x86emuOp_aaa,
5213 /* 0x38 */ x86emuOp_genop_byte_RM_R,
5214 /* 0x39 */ x86emuOp_genop_word_RM_R,
5215 /* 0x3a */ x86emuOp_genop_byte_R_RM,
5216 /* 0x3b */ x86emuOp_genop_word_R_RM,
5217 /* 0x3c */ x86emuOp_genop_byte_AL_IMM,
5218 /* 0x3d */ x86emuOp_genop_word_AX_IMM,
5219 /* 0x3e */ x86emuOp_segovr_DS,
5220 /* 0x3f */ x86emuOp_aas,
5222 /* 0x40 */ x86emuOp_inc_register,
5223 /* 0x41 */ x86emuOp_inc_register,
5224 /* 0x42 */ x86emuOp_inc_register,
5225 /* 0x43 */ x86emuOp_inc_register,
5226 /* 0x44 */ x86emuOp_inc_register,
5227 /* 0x45 */ x86emuOp_inc_register,
5228 /* 0x46 */ x86emuOp_inc_register,
5229 /* 0x47 */ x86emuOp_inc_register,
5231 /* 0x48 */ x86emuOp_dec_register,
5232 /* 0x49 */ x86emuOp_dec_register,
5233 /* 0x4a */ x86emuOp_dec_register,
5234 /* 0x4b */ x86emuOp_dec_register,
5235 /* 0x4c */ x86emuOp_dec_register,
5236 /* 0x4d */ x86emuOp_dec_register,
5237 /* 0x4e */ x86emuOp_dec_register,
5238 /* 0x4f */ x86emuOp_dec_register,
5240 /* 0x50 */ x86emuOp_push_register,
5241 /* 0x51 */ x86emuOp_push_register,
5242 /* 0x52 */ x86emuOp_push_register,
5243 /* 0x53 */ x86emuOp_push_register,
5244 /* 0x54 */ x86emuOp_push_register,
5245 /* 0x55 */ x86emuOp_push_register,
5246 /* 0x56 */ x86emuOp_push_register,
5247 /* 0x57 */ x86emuOp_push_register,
5249 /* 0x58 */ x86emuOp_pop_register,
5250 /* 0x59 */ x86emuOp_pop_register,
5251 /* 0x5a */ x86emuOp_pop_register,
5252 /* 0x5b */ x86emuOp_pop_register,
5253 /* 0x5c */ x86emuOp_pop_register,
5254 /* 0x5d */ x86emuOp_pop_register,
5255 /* 0x5e */ x86emuOp_pop_register,
5256 /* 0x5f */ x86emuOp_pop_register,
5258 /* 0x60 */ x86emuOp_push_all,
5259 /* 0x61 */ x86emuOp_pop_all,
5260 /* 0x62 */ x86emuOp_illegal_op, /* bound */
5261 /* 0x63 */ x86emuOp_illegal_op, /* arpl */
5262 /* 0x64 */ x86emuOp_segovr_FS,
5263 /* 0x65 */ x86emuOp_segovr_GS,
5264 /* 0x66 */ x86emuOp_prefix_data,
5265 /* 0x67 */ x86emuOp_prefix_addr,
5267 /* 0x68 */ x86emuOp_push_word_IMM,
5268 /* 0x69 */ x86emuOp_imul_word_IMM,
5269 /* 0x6a */ x86emuOp_push_byte_IMM,
5270 /* 0x6b */ x86emuOp_imul_byte_IMM,
5271 /* 0x6c */ x86emuOp_ins_byte,
5272 /* 0x6d */ x86emuOp_ins_word,
5273 /* 0x6e */ x86emuOp_outs_byte,
5274 /* 0x6f */ x86emuOp_outs_word,
5276 /* 0x70 */ x86emuOp_jump_near_cond,
5277 /* 0x71 */ x86emuOp_jump_near_cond,
5278 /* 0x72 */ x86emuOp_jump_near_cond,
5279 /* 0x73 */ x86emuOp_jump_near_cond,
5280 /* 0x74 */ x86emuOp_jump_near_cond,
5281 /* 0x75 */ x86emuOp_jump_near_cond,
5282 /* 0x76 */ x86emuOp_jump_near_cond,
5283 /* 0x77 */ x86emuOp_jump_near_cond,
5285 /* 0x78 */ x86emuOp_jump_near_cond,
5286 /* 0x79 */ x86emuOp_jump_near_cond,
5287 /* 0x7a */ x86emuOp_jump_near_cond,
5288 /* 0x7b */ x86emuOp_jump_near_cond,
5289 /* 0x7c */ x86emuOp_jump_near_cond,
5290 /* 0x7d */ x86emuOp_jump_near_cond,
5291 /* 0x7e */ x86emuOp_jump_near_cond,
5292 /* 0x7f */ x86emuOp_jump_near_cond,
5294 /* 0x80 */ x86emuOp_opc80_byte_RM_IMM,
5295 /* 0x81 */ x86emuOp_opc81_word_RM_IMM,
5296 /* 0x82 */ x86emuOp_opc82_byte_RM_IMM,
5297 /* 0x83 */ x86emuOp_opc83_word_RM_IMM,
5298 /* 0x84 */ x86emuOp_test_byte_RM_R,
5299 /* 0x85 */ x86emuOp_test_word_RM_R,
5300 /* 0x86 */ x86emuOp_xchg_byte_RM_R,
5301 /* 0x87 */ x86emuOp_xchg_word_RM_R,
5303 /* 0x88 */ x86emuOp_mov_byte_RM_R,
5304 /* 0x89 */ x86emuOp_mov_word_RM_R,
5305 /* 0x8a */ x86emuOp_mov_byte_R_RM,
5306 /* 0x8b */ x86emuOp_mov_word_R_RM,
5307 /* 0x8c */ x86emuOp_mov_word_RM_SR,
5308 /* 0x8d */ x86emuOp_lea_word_R_M,
5309 /* 0x8e */ x86emuOp_mov_word_SR_RM,
5310 /* 0x8f */ x86emuOp_pop_RM,
5312 /* 0x90 */ x86emuOp_nop,
5313 /* 0x91 */ x86emuOp_xchg_word_AX_register,
5314 /* 0x92 */ x86emuOp_xchg_word_AX_register,
5315 /* 0x93 */ x86emuOp_xchg_word_AX_register,
5316 /* 0x94 */ x86emuOp_xchg_word_AX_register,
5317 /* 0x95 */ x86emuOp_xchg_word_AX_register,
5318 /* 0x96 */ x86emuOp_xchg_word_AX_register,
5319 /* 0x97 */ x86emuOp_xchg_word_AX_register,
5321 /* 0x98 */ x86emuOp_cbw,
5322 /* 0x99 */ x86emuOp_cwd,
5323 /* 0x9a */ x86emuOp_call_far_IMM,
5324 /* 0x9b */ x86emuOp_wait,
5325 /* 0x9c */ x86emuOp_pushf_word,
5326 /* 0x9d */ x86emuOp_popf_word,
5327 /* 0x9e */ x86emuOp_sahf,
5328 /* 0x9f */ x86emuOp_lahf,
5330 /* 0xa0 */ x86emuOp_mov_AL_M_IMM,
5331 /* 0xa1 */ x86emuOp_mov_AX_M_IMM,
5332 /* 0xa2 */ x86emuOp_mov_M_AL_IMM,
5333 /* 0xa3 */ x86emuOp_mov_M_AX_IMM,
5334 /* 0xa4 */ x86emuOp_movs_byte,
5335 /* 0xa5 */ x86emuOp_movs_word,
5336 /* 0xa6 */ x86emuOp_cmps_byte,
5337 /* 0xa7 */ x86emuOp_cmps_word,
5338 /* 0xa8 */ x86emuOp_test_AL_IMM,
5339 /* 0xa9 */ x86emuOp_test_AX_IMM,
5340 /* 0xaa */ x86emuOp_stos_byte,
5341 /* 0xab */ x86emuOp_stos_word,
5342 /* 0xac */ x86emuOp_lods_byte,
5343 /* 0xad */ x86emuOp_lods_word,
5344 /* 0xac */ x86emuOp_scas_byte,
5345 /* 0xad */ x86emuOp_scas_word,
5347 /* 0xb0 */ x86emuOp_mov_byte_register_IMM,
5348 /* 0xb1 */ x86emuOp_mov_byte_register_IMM,
5349 /* 0xb2 */ x86emuOp_mov_byte_register_IMM,
5350 /* 0xb3 */ x86emuOp_mov_byte_register_IMM,
5351 /* 0xb4 */ x86emuOp_mov_byte_register_IMM,
5352 /* 0xb5 */ x86emuOp_mov_byte_register_IMM,
5353 /* 0xb6 */ x86emuOp_mov_byte_register_IMM,
5354 /* 0xb7 */ x86emuOp_mov_byte_register_IMM,
5356 /* 0xb8 */ x86emuOp_mov_word_register_IMM,
5357 /* 0xb9 */ x86emuOp_mov_word_register_IMM,
5358 /* 0xba */ x86emuOp_mov_word_register_IMM,
5359 /* 0xbb */ x86emuOp_mov_word_register_IMM,
5360 /* 0xbc */ x86emuOp_mov_word_register_IMM,
5361 /* 0xbd */ x86emuOp_mov_word_register_IMM,
5362 /* 0xbe */ x86emuOp_mov_word_register_IMM,
5363 /* 0xbf */ x86emuOp_mov_word_register_IMM,
5365 /* 0xc0 */ x86emuOp_opcC0_byte_RM_MEM,
5366 /* 0xc1 */ x86emuOp_opcC1_word_RM_MEM,
5367 /* 0xc2 */ x86emuOp_ret_near_IMM,
5368 /* 0xc3 */ x86emuOp_ret_near,
5369 /* 0xc4 */ x86emuOp_les_R_IMM,
5370 /* 0xc5 */ x86emuOp_lds_R_IMM,
5371 /* 0xc6 */ x86emuOp_mov_byte_RM_IMM,
5372 /* 0xc7 */ x86emuOp_mov_word_RM_IMM,
5373 /* 0xc8 */ x86emuOp_enter,
5374 /* 0xc9 */ x86emuOp_leave,
5375 /* 0xca */ x86emuOp_ret_far_IMM,
5376 /* 0xcb */ x86emuOp_ret_far,
5377 /* 0xcc */ x86emuOp_int3,
5378 /* 0xcd */ x86emuOp_int_IMM,
5379 /* 0xce */ x86emuOp_into,
5380 /* 0xcf */ x86emuOp_iret,
5382 /* 0xd0 */ x86emuOp_opcD0_byte_RM_1,
5383 /* 0xd1 */ x86emuOp_opcD1_word_RM_1,
5384 /* 0xd2 */ x86emuOp_opcD2_byte_RM_CL,
5385 /* 0xd3 */ x86emuOp_opcD3_word_RM_CL,
5386 /* 0xd4 */ x86emuOp_aam,
5387 /* 0xd5 */ x86emuOp_aad,
5388 /* 0xd6 */ x86emuOp_illegal_op, /* Undocumented SETALC instruction */
5389 /* 0xd7 */ x86emuOp_xlat,
5390 /* 0xd8 */ NULL, /*x86emuOp_esc_coprocess_d8,*/
5391 /* 0xd9 */ NULL, /*x86emuOp_esc_coprocess_d9,*/
5392 /* 0xda */ NULL, /*x86emuOp_esc_coprocess_da,*/
5393 /* 0xdb */ NULL, /*x86emuOp_esc_coprocess_db,*/
5394 /* 0xdc */ NULL, /*x86emuOp_esc_coprocess_dc,*/
5395 /* 0xdd */ NULL, /*x86emuOp_esc_coprocess_dd,*/
5396 /* 0xde */ NULL, /*x86emuOp_esc_coprocess_de,*/
5397 /* 0xdf */ NULL, /*x86emuOp_esc_coprocess_df,*/
5399 /* 0xe0 */ x86emuOp_loopne,
5400 /* 0xe1 */ x86emuOp_loope,
5401 /* 0xe2 */ x86emuOp_loop,
5402 /* 0xe3 */ x86emuOp_jcxz,
5403 /* 0xe4 */ x86emuOp_in_byte_AL_IMM,
5404 /* 0xe5 */ x86emuOp_in_word_AX_IMM,
5405 /* 0xe6 */ x86emuOp_out_byte_IMM_AL,
5406 /* 0xe7 */ x86emuOp_out_word_IMM_AX,
5408 /* 0xe8 */ x86emuOp_call_near_IMM,
5409 /* 0xe9 */ x86emuOp_jump_near_IMM,
5410 /* 0xea */ x86emuOp_jump_far_IMM,
5411 /* 0xeb */ x86emuOp_jump_byte_IMM,
5412 /* 0xec */ x86emuOp_in_byte_AL_DX,
5413 /* 0xed */ x86emuOp_in_word_AX_DX,
5414 /* 0xee */ x86emuOp_out_byte_DX_AL,
5415 /* 0xef */ x86emuOp_out_word_DX_AX,
5417 /* 0xf0 */ x86emuOp_lock,
5418 /* 0xf1 */ x86emuOp_illegal_op,
5419 /* 0xf2 */ x86emuOp_repne,
5420 /* 0xf3 */ x86emuOp_repe,
5421 /* 0xf4 */ x86emuOp_halt,
5422 /* 0xf5 */ x86emuOp_cmc,
5423 /* 0xf6 */ x86emuOp_opcF6_byte_RM,
5424 /* 0xf7 */ x86emuOp_opcF7_word_RM,
5426 /* 0xf8 */ x86emuOp_clc,
5427 /* 0xf9 */ x86emuOp_stc,
5428 /* 0xfa */ x86emuOp_cli,
5429 /* 0xfb */ x86emuOp_sti,
5430 /* 0xfc */ x86emuOp_cld,
5431 /* 0xfd */ x86emuOp_std,
5432 /* 0xfe */ x86emuOp_opcFE_byte_RM,
5433 /* 0xff */ x86emuOp_opcFF_word_RM,