📄 decode.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 which are related to* instruction decoding and accessess of immediate data via IP. etc.*****************************************************************************/#include "x86emu/x86emui.h"/*----------------------------- Implementation ----------------------------*//****************************************************************************REMARKS:Handles any pending asychronous interrupts.****************************************************************************/static void x86emu_intr_handle(void){ u8 intno; if (M.x86.intr & INTR_SYNCH) { intno = M.x86.intno; if (_X86EMU_intrTab[intno]) { (*_X86EMU_intrTab[intno])(intno); } else { push_word((u16)M.x86.R_FLG); CLEAR_FLAG(F_IF); CLEAR_FLAG(F_TF); push_word(M.x86.R_CS); M.x86.R_CS = mem_access_word(intno * 4 + 2); push_word(M.x86.R_IP); M.x86.R_IP = mem_access_word(intno * 4); M.x86.intr = 0; } }}/****************************************************************************PARAMETERS:intrnum - Interrupt number to raiseREMARKS:Raise the specified interrupt to be handled before the execution of thenext instruction.****************************************************************************/void x86emu_intr_raise( u8 intrnum){ M.x86.intno = intrnum; M.x86.intr |= INTR_SYNCH;}/****************************************************************************REMARKS:Main execution loop for the emulator. We return from here when the systemhalts, which is normally caused by a stack fault when we return from theoriginal real mode call.****************************************************************************/void X86EMU_exec(void){ u8 op1; M.x86.intr = 0; DB(x86emu_end_instr();) for (;;) { DB(if (CHECK_IP_FETCH()) x86emu_check_ip_access();) /* If debugging, save the IP and CS values. */ SAVE_IP_CS(M.x86.R_CS, M.x86.R_IP); INC_DECODED_INST_LEN(1); if (M.x86.intr) { if (M.x86.intr & INTR_HALTED) { DB( printk("halted\n"); X86EMU_trace_regs();) return; } if (((M.x86.intr & INTR_SYNCH) && (M.x86.intno == 0 || M.x86.intno == 2)) || !ACCESS_FLAG(F_IF)) { x86emu_intr_handle(); } } op1 = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++)); (*x86emu_optab[op1])(op1); if (M.x86.debug & DEBUG_EXIT) { M.x86.debug &= ~DEBUG_EXIT; return; } }}/****************************************************************************REMARKS:Halts the system by setting the halted system flag.****************************************************************************/void X86EMU_halt_sys(void){ M.x86.intr |= INTR_HALTED;}/****************************************************************************PARAMETERS:mod - Mod value from decoded byteregh - Reg h value from decoded byteregl - Reg l value from decoded byteREMARKS:Raise the specified interrupt to be handled before the execution of thenext instruction.NOTE: Do not inline this function, as (*sys_rdb) is already inline!****************************************************************************/void fetch_decode_modrm( int *mod, int *regh, int *regl){ int fetched;DB( if (CHECK_IP_FETCH()) x86emu_check_ip_access();) fetched = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++)); INC_DECODED_INST_LEN(1); *mod = (fetched >> 6) & 0x03; *regh = (fetched >> 3) & 0x07; *regl = (fetched >> 0) & 0x07;}/****************************************************************************RETURNS:Immediate byte value read from instruction queueREMARKS:This function returns the immediate byte from the instruction queue, andmoves the instruction pointer to the next value.NOTE: Do not inline this function, as (*sys_rdb) is already inline!****************************************************************************/u8 fetch_byte_imm(void){ u8 fetched;DB( if (CHECK_IP_FETCH()) x86emu_check_ip_access();) fetched = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++)); INC_DECODED_INST_LEN(1); return fetched;}/****************************************************************************RETURNS:Immediate word value read from instruction queueREMARKS:This function returns the immediate byte from the instruction queue, andmoves the instruction pointer to the next value.NOTE: Do not inline this function, as (*sys_rdw) is already inline!****************************************************************************/u16 fetch_word_imm(void){ u16 fetched;DB( if (CHECK_IP_FETCH()) x86emu_check_ip_access();) fetched = (*sys_rdw)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP)); M.x86.R_IP += 2; INC_DECODED_INST_LEN(2); return fetched;}/****************************************************************************RETURNS:Immediate lone value read from instruction queueREMARKS:This function returns the immediate byte from the instruction queue, andmoves the instruction pointer to the next value.NOTE: Do not inline this function, as (*sys_rdw) is already inline!****************************************************************************/u32 fetch_long_imm(void){ u32 fetched;DB( if (CHECK_IP_FETCH()) x86emu_check_ip_access();) fetched = (*sys_rdl)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP)); M.x86.R_IP += 4; INC_DECODED_INST_LEN(4); return fetched;}/****************************************************************************RETURNS:Value of the default data segmentREMARKS:Inline function that returns the default data segment for the currentinstruction.On the x86 processor, the default segment is not always DS if there isno segment override. Address modes such as -3[BP] or 10[BP+SI] all refer toaddresses relative to SS (ie: on the stack). So, at the minimum, alldecodings of addressing modes would have to set/clear a bit describingwhether the access is relative to DS or SS. That is the function of thecpu-state-varible M.x86.mode. There are several potential states: repe prefix seen (handled elsewhere) repne prefix seen (ditto) cs segment override ds segment override es segment override fs segment override gs segment override ss segment override ds/ss select (in absense of override)Each of the above 7 items are handled with a bit in the mode field.****************************************************************************/_INLINE u32 get_data_segment(void){#define GET_SEGMENT(segment) switch (M.x86.mode & SYSMODE_SEGMASK) { case 0: /* default case: use ds register */ case SYSMODE_SEGOVR_DS: case SYSMODE_SEGOVR_DS | SYSMODE_SEG_DS_SS: return M.x86.R_DS; case SYSMODE_SEG_DS_SS: /* non-overridden, use ss register */ return M.x86.R_SS; case SYSMODE_SEGOVR_CS: case SYSMODE_SEGOVR_CS | SYSMODE_SEG_DS_SS: return M.x86.R_CS; case SYSMODE_SEGOVR_ES: case SYSMODE_SEGOVR_ES | SYSMODE_SEG_DS_SS: return M.x86.R_ES; case SYSMODE_SEGOVR_FS: case SYSMODE_SEGOVR_FS | SYSMODE_SEG_DS_SS: return M.x86.R_FS; case SYSMODE_SEGOVR_GS: case SYSMODE_SEGOVR_GS | SYSMODE_SEG_DS_SS: return M.x86.R_GS; case SYSMODE_SEGOVR_SS: case SYSMODE_SEGOVR_SS | SYSMODE_SEG_DS_SS: return M.x86.R_SS; default:#ifdef DEBUG printk("error: should not happen: multiple overrides.\n");#endif HALT_SYS(); return 0; }}/****************************************************************************PARAMETERS:offset - Offset to load data fromRETURNS:Byte value read from the absolute memory location.NOTE: Do not inline this function as (*sys_rdX) is already inline!****************************************************************************/u8 fetch_data_byte( uint offset){#ifdef DEBUG if (CHECK_DATA_ACCESS()) x86emu_check_data_access((u16)get_data_segment(), offset);#endif return (*sys_rdb)((get_data_segment() << 4) + offset);}/****************************************************************************PARAMETERS:offset - Offset to load data fromRETURNS:Word value read from the absolute memory location.NOTE: Do not inline this function as (*sys_rdX) is already inline!****************************************************************************/u16 fetch_data_word( uint offset){#ifdef DEBUG if (CHECK_DATA_ACCESS()) x86emu_check_data_access((u16)get_data_segment(), offset);#endif return (*sys_rdw)((get_data_segment() << 4) + offset);}/****************************************************************************PARAMETERS:offset - Offset to load data fromRETURNS:Long value read from the absolute memory location.NOTE: Do not inline this function as (*sys_rdX) is already inline!****************************************************************************/u32 fetch_data_long( uint offset){#ifdef DEBUG if (CHECK_DATA_ACCESS()) x86emu_check_data_access((u16)get_data_segment(), offset);#endif return (*sys_rdl)((get_data_segment() << 4) + offset);}/****************************************************************************PARAMETERS:segment - Segment to load data fromoffset - Offset to load data fromRETURNS:Byte value read from the absolute memory location.NOTE: Do not inline this function as (*sys_rdX) is already inline!****************************************************************************/u8 fetch_data_byte_abs( uint segment, uint offset){#ifdef DEBUG if (CHECK_DATA_ACCESS()) x86emu_check_data_access(segment, offset);#endif return (*sys_rdb)(((u32)segment << 4) + offset);}/****************************************************************************PARAMETERS:segment - Segment to load data fromoffset - Offset to load data fromRETURNS:Word value read from the absolute memory location.NOTE: Do not inline this function as (*sys_rdX) is already inline!****************************************************************************/u16 fetch_data_word_abs( uint segment, uint offset){#ifdef DEBUG if (CHECK_DATA_ACCESS()) x86emu_check_data_access(segment, offset);#endif return (*sys_rdw)(((u32)segment << 4) + offset);}/****************************************************************************PARAMETERS:segment - Segment to load data fromoffset - Offset to load data fromRETURNS:Long value read from the absolute memory location.NOTE: Do not inline this function as (*sys_rdX) is already inline!****************************************************************************/u32 fetch_data_long_abs( uint segment, uint offset){#ifdef DEBUG if (CHECK_DATA_ACCESS()) x86emu_check_data_access(segment, offset);#endif return (*sys_rdl)(((u32)segment << 4) + offset);}/****************************************************************************PARAMETERS:offset - Offset to store data atval - Value to storeREMARKS:Writes a word value to an segmented memory location. The segment used isthe current 'default' segment, which may have been overridden.NOTE: Do not inline this function as (*sys_wrX) is already inline!****************************************************************************/void store_data_byte( uint offset, u8 val){#ifdef DEBUG if (CHECK_DATA_ACCESS()) x86emu_check_data_access((u16)get_data_segment(), offset);#endif (*sys_wrb)((get_data_segment() << 4) + offset, val);}/****************************************************************************PARAMETERS:offset - Offset to store data atval - Value to storeREMARKS:Writes a word value to an segmented memory location. The segment used isthe current 'default' segment, which may have been overridden.NOTE: Do not inline this function as (*sys_wrX) is already inline!****************************************************************************/void store_data_word( uint offset, u16 val){#ifdef DEBUG if (CHECK_DATA_ACCESS()) x86emu_check_data_access((u16)get_data_segment(), offset);#endif (*sys_wrw)((get_data_segment() << 4) + offset, val);}/****************************************************************************PARAMETERS:offset - Offset to store data atval - Value to storeREMARKS:Writes a long value to an segmented memory location. The segment used isthe current 'default' segment, which may have been overridden.NOTE: Do not inline this function as (*sys_wrX) is already inline!****************************************************************************/void store_data_long( uint offset, u32 val){#ifdef DEBUG if (CHECK_DATA_ACCESS()) x86emu_check_data_access((u16)get_data_segment(), offset);#endif (*sys_wrl)((get_data_segment() << 4) + offset, val);}/****************************************************************************PARAMETERS:segment - Segment to store data atoffset - Offset to store data atval - Value to storeREMARKS:Writes a byte value to an absolute memory location.NOTE: Do not inline this function as (*sys_wrX) is already inline!****************************************************************************/void store_data_byte_abs( uint segment, uint offset, u8 val)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -