📄 ops.c
字号:
/****************************************************************************** Realmode X86 Emulator Library** Copyright (C) 1996-1999 SciTech Software, Inc.* Copyright (C) David Mosberger-Tang* Copyright (C) 1999 Egbert Eich** ========================================================================** Permission to use, copy, modify, distribute, and sell this software and* its documentation for any purpose is hereby granted without fee,* provided that the above copyright notice appear in all copies and that* both that copyright notice and this permission notice appear in* supporting documentation, and that the name of the authors not be used* in advertising or publicity pertaining to distribution of the software* without specific, written prior permission. The authors makes no* representations about the suitability of this software for any purpose.* It is provided "as is" without express or implied warranty.** THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR* PERFORMANCE OF THIS SOFTWARE.** ========================================================================** Language: ANSI C* Environment: Any* Developer: Kendall Bennett** Description: This file includes subroutines to implement the decoding* and emulation of all the x86 processor instructions.** There are approximately 250 subroutines in here, which correspond* to the 256 byte-"opcodes" found on the 8086. The table which* dispatches this is found in the files optab.[ch].** Each opcode proc has a comment preceeding it which gives it's table* address. Several opcodes are missing (undefined) in the table.** Each proc includes information for decoding (DECODE_PRINTF and* DECODE_PRINTF2), debugging (TRACE_REGS, SINGLE_STEP), and misc* functions (START_OF_INSTR, END_OF_INSTR).** Many of the procedures are *VERY* similar in coding. This has* allowed for a very large amount of code to be generated in a fairly* short amount of time (i.e. cut, paste, and modify). The result is* that much of the code below could have been folded into subroutines* for a large reduction in size of this file. The downside would be* that there would be a penalty in execution speed. The file could* also have been *MUCH* larger by inlining certain functions which* were called. This could have resulted even faster execution. The* prime directive I used to decide whether to inline the code or to* modularize it, was basically: 1) no unnecessary subroutine calls,* 2) no routines more than about 200 lines in size, and 3) modularize* any code that I might not get right the first time. The fetch_** subroutines fall into the latter category. The The decode_* fall* into the second category. The coding of the "switch(mod){ .... }"* in many of the subroutines below falls into the first category.* Especially, the coding of {add,and,or,sub,...}_{byte,word}* subroutines are an especially glaring case of the third guideline.* Since so much of the code is cloned from other modules (compare* opcode #00 to opcode #01), making the basic operations subroutine* calls is especially important; otherwise mistakes in coding an* "add" would represent a nightmare in maintenance.*****************************************************************************/#include "x86emu/x86emui.h"/*----------------------------- Implementation ----------------------------*//****************************************************************************PARAMETERS:op1 - Instruction op codeREMARKS:Handles illegal opcodes.****************************************************************************/void x86emuOp_illegal_op( u8 op1){ START_OF_INSTR(); DECODE_PRINTF("ILLEGAL X86 OPCODE\n"); TRACE_REGS(); printk("%04x:%04x: %02X ILLEGAL X86 OPCODE!\n", M.x86.R_CS, M.x86.R_IP-1,op1); HALT_SYS(); END_OF_INSTR();}/****************************************************************************REMARKS:Handles opcode 0x00****************************************************************************/void x86emuOp_add_byte_RM_R(u8 X86EMU_UNUSED(op1)){ int mod, rl, rh; uint destoffset; u8 *destreg, *srcreg; u8 destval; START_OF_INSTR(); DECODE_PRINTF("ADD\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: destoffset = decode_rm00_address(rl); DECODE_PRINTF(","); destval = fetch_data_byte(destoffset); srcreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = add_byte(destval, *srcreg); store_data_byte(destoffset, destval); break; case 1: destoffset = decode_rm01_address(rl); DECODE_PRINTF(","); destval = fetch_data_byte(destoffset); srcreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = add_byte(destval, *srcreg); store_data_byte(destoffset, destval); break; case 2: destoffset = decode_rm10_address(rl); DECODE_PRINTF(","); destval = fetch_data_byte(destoffset); srcreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = add_byte(destval, *srcreg); store_data_byte(destoffset, destval); break; case 3: /* register to register */ destreg = DECODE_RM_BYTE_REGISTER(rl); DECODE_PRINTF(","); srcreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = add_byte(*destreg, *srcreg); break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR();}/****************************************************************************REMARKS:Handles opcode 0x01****************************************************************************/void x86emuOp_add_word_RM_R(u8 X86EMU_UNUSED(op1)){ int mod, rl, rh; uint destoffset; START_OF_INSTR(); DECODE_PRINTF("ADD\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; u32 *srcreg; destoffset = decode_rm00_address(rl); DECODE_PRINTF(","); destval = fetch_data_long(destoffset); srcreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = add_long(destval, *srcreg); store_data_long(destoffset, destval); } else { u16 destval; u16 *srcreg; destoffset = decode_rm00_address(rl); DECODE_PRINTF(","); destval = fetch_data_word(destoffset); srcreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = add_word(destval, *srcreg); store_data_word(destoffset, destval); } break; case 1: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; u32 *srcreg; destoffset = decode_rm01_address(rl); DECODE_PRINTF(","); destval = fetch_data_long(destoffset); srcreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = add_long(destval, *srcreg); store_data_long(destoffset, destval); } else { u16 destval; u16 *srcreg; destoffset = decode_rm01_address(rl); DECODE_PRINTF(","); destval = fetch_data_word(destoffset); srcreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = add_word(destval, *srcreg); store_data_word(destoffset, destval); } break; case 2: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; u32 *srcreg; destoffset = decode_rm10_address(rl); DECODE_PRINTF(","); destval = fetch_data_long(destoffset); srcreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = add_long(destval, *srcreg); store_data_long(destoffset, destval); } else { u16 destval; u16 *srcreg; destoffset = decode_rm10_address(rl); DECODE_PRINTF(","); destval = fetch_data_word(destoffset); srcreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); destval = add_word(destval, *srcreg); store_data_word(destoffset, destval); } break; case 3: /* register to register */ if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg,*srcreg; destreg = DECODE_RM_LONG_REGISTER(rl); DECODE_PRINTF(","); srcreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = add_long(*destreg, *srcreg); } else { u16 *destreg,*srcreg; destreg = DECODE_RM_WORD_REGISTER(rl); DECODE_PRINTF(","); srcreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = add_word(*destreg, *srcreg); } break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR();}/****************************************************************************REMARKS:Handles opcode 0x02****************************************************************************/void x86emuOp_add_byte_R_RM(u8 X86EMU_UNUSED(op1)){ int mod, rl, rh; u8 *destreg, *srcreg; uint srcoffset; u8 srcval; START_OF_INSTR(); DECODE_PRINTF("ADD\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: destreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm00_address(rl); srcval = fetch_data_byte(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = add_byte(*destreg, srcval); break; case 1: destreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm01_address(rl); srcval = fetch_data_byte(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = add_byte(*destreg, srcval); break; case 2: destreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm10_address(rl); srcval = fetch_data_byte(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = add_byte(*destreg, srcval); break; case 3: /* register to register */ destreg = DECODE_RM_BYTE_REGISTER(rh); DECODE_PRINTF(","); srcreg = DECODE_RM_BYTE_REGISTER(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = add_byte(*destreg, *srcreg); break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR();}/****************************************************************************REMARKS:Handles opcode 0x03****************************************************************************/void x86emuOp_add_word_R_RM(u8 X86EMU_UNUSED(op1)){ int mod, rl, rh; uint srcoffset; START_OF_INSTR(); DECODE_PRINTF("ADD\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg; u32 srcval; destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm00_address(rl); srcval = fetch_data_long(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = add_long(*destreg, srcval); } else { u16 *destreg; u16 srcval; destreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm00_address(rl); srcval = fetch_data_word(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = add_word(*destreg, srcval); } break; case 1: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg; u32 srcval; destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm01_address(rl); srcval = fetch_data_long(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = add_long(*destreg, srcval); } else { u16 *destreg; u16 srcval; destreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm01_address(rl); srcval = fetch_data_word(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = add_word(*destreg, srcval); } break; case 2: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg; u32 srcval; destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm10_address(rl); srcval = fetch_data_long(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = add_long(*destreg, srcval); } else { u16 *destreg; u16 srcval; destreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcoffset = decode_rm10_address(rl); srcval = fetch_data_word(srcoffset); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = add_word(*destreg, srcval); } break; case 3: /* register to register */ if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *destreg,*srcreg; destreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); srcreg = DECODE_RM_LONG_REGISTER(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = add_long(*destreg, *srcreg); } else { u16 *destreg,*srcreg; destreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); srcreg = DECODE_RM_WORD_REGISTER(rl); DECODE_PRINTF("\n"); TRACE_AND_STEP(); *destreg = add_word(*destreg, *srcreg); } break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR();}/****************************************************************************REMARKS:Handles opcode 0x04****************************************************************************/void x86emuOp_add_byte_AL_IMM(u8 X86EMU_UNUSED(op1)){ u8 srcval; START_OF_INSTR(); DECODE_PRINTF("ADD\tAL,"); srcval = fetch_byte_imm(); DECODE_PRINTF2("%x\n", srcval); TRACE_AND_STEP(); M.x86.R_AL = add_byte(M.x86.R_AL, srcval); DECODE_CLEAR_SEGOVR(); END_OF_INSTR();}/****************************************************************************REMARKS:Handles opcode 0x05****************************************************************************/void x86emuOp_add_word_AX_IMM(u8 X86EMU_UNUSED(op1)){ u32 srcval; START_OF_INSTR(); if (M.x86.mode & SYSMODE_PREFIX_DATA) { DECODE_PRINTF("ADD\tEAX,"); srcval = fetch_long_imm(); } else { DECODE_PRINTF("ADD\tAX,"); srcval = fetch_word_imm(); } DECODE_PRINTF2("%x\n", srcval); TRACE_AND_STEP(); if (M.x86.mode & SYSMODE_PREFIX_DATA) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -