105b261ecSmrg/**************************************************************************** 205b261ecSmrg* 305b261ecSmrg* Realmode X86 Emulator Library 405b261ecSmrg* 505b261ecSmrg* Copyright (C) 1996-1999 SciTech Software, Inc. 605b261ecSmrg* Copyright (C) David Mosberger-Tang 705b261ecSmrg* Copyright (C) 1999 Egbert Eich 805b261ecSmrg* 905b261ecSmrg* ======================================================================== 1005b261ecSmrg* 1105b261ecSmrg* Permission to use, copy, modify, distribute, and sell this software and 1205b261ecSmrg* its documentation for any purpose is hereby granted without fee, 1305b261ecSmrg* provided that the above copyright notice appear in all copies and that 1405b261ecSmrg* both that copyright notice and this permission notice appear in 1505b261ecSmrg* supporting documentation, and that the name of the authors not be used 1605b261ecSmrg* in advertising or publicity pertaining to distribution of the software 1705b261ecSmrg* without specific, written prior permission. The authors makes no 1805b261ecSmrg* representations about the suitability of this software for any purpose. 1905b261ecSmrg* It is provided "as is" without express or implied warranty. 2005b261ecSmrg* 2105b261ecSmrg* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 2205b261ecSmrg* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 2305b261ecSmrg* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 2405b261ecSmrg* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF 2505b261ecSmrg* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 2605b261ecSmrg* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 2705b261ecSmrg* PERFORMANCE OF THIS SOFTWARE. 2805b261ecSmrg* 2905b261ecSmrg* ======================================================================== 3005b261ecSmrg* 3105b261ecSmrg* Language: ANSI C 3205b261ecSmrg* Environment: Any 3305b261ecSmrg* Developer: Kendall Bennett 3405b261ecSmrg* 3505b261ecSmrg* Description: This file includes subroutines which are related to 3605b261ecSmrg* instruction decoding and accessess of immediate data via IP. etc. 3705b261ecSmrg* 3805b261ecSmrg****************************************************************************/ 3905b261ecSmrg 4005b261ecSmrg#include <stdlib.h> 4135c4bbdfSmrg 4235c4bbdfSmrg#if defined(__sun) && defined(CS) /* avoid conflicts with Solaris sys/regset.h */ 4335c4bbdfSmrg# undef CS 4435c4bbdfSmrg# undef DS 4535c4bbdfSmrg# undef SS 4635c4bbdfSmrg# undef ES 4735c4bbdfSmrg# undef FS 4835c4bbdfSmrg# undef GS 4935c4bbdfSmrg#endif 5035c4bbdfSmrg 5105b261ecSmrg#include "x86emu/x86emui.h" 5205b261ecSmrg 5305b261ecSmrg/*----------------------------- Implementation ----------------------------*/ 5405b261ecSmrg 5505b261ecSmrg/**************************************************************************** 5605b261ecSmrgREMARKS: 5705b261ecSmrgHandles any pending asychronous interrupts. 5805b261ecSmrg****************************************************************************/ 5935c4bbdfSmrgstatic void 6035c4bbdfSmrgx86emu_intr_handle(void) 6105b261ecSmrg{ 6235c4bbdfSmrg u8 intno; 6335c4bbdfSmrg 6435c4bbdfSmrg if (M.x86.intr & INTR_SYNCH) { 6535c4bbdfSmrg intno = M.x86.intno; 6635c4bbdfSmrg if (_X86EMU_intrTab[intno]) { 6735c4bbdfSmrg (*_X86EMU_intrTab[intno]) (intno); 6835c4bbdfSmrg } 6935c4bbdfSmrg else { 7035c4bbdfSmrg push_word((u16) M.x86.R_FLG); 7135c4bbdfSmrg CLEAR_FLAG(F_IF); 7235c4bbdfSmrg CLEAR_FLAG(F_TF); 7335c4bbdfSmrg push_word(M.x86.R_CS); 7435c4bbdfSmrg M.x86.R_CS = mem_access_word(intno * 4 + 2); 7535c4bbdfSmrg push_word(M.x86.R_IP); 7635c4bbdfSmrg M.x86.R_IP = mem_access_word(intno * 4); 7735c4bbdfSmrg M.x86.intr = 0; 7835c4bbdfSmrg } 7935c4bbdfSmrg } 8005b261ecSmrg} 8105b261ecSmrg 8205b261ecSmrg/**************************************************************************** 8305b261ecSmrgPARAMETERS: 8405b261ecSmrgintrnum - Interrupt number to raise 8505b261ecSmrg 8605b261ecSmrgREMARKS: 8705b261ecSmrgRaise the specified interrupt to be handled before the execution of the 8805b261ecSmrgnext instruction. 8905b261ecSmrg****************************************************************************/ 9035c4bbdfSmrgvoid 9135c4bbdfSmrgx86emu_intr_raise(u8 intrnum) 9205b261ecSmrg{ 9335c4bbdfSmrg M.x86.intno = intrnum; 9435c4bbdfSmrg M.x86.intr |= INTR_SYNCH; 9505b261ecSmrg} 9605b261ecSmrg 9705b261ecSmrg/**************************************************************************** 9805b261ecSmrgREMARKS: 9905b261ecSmrgMain execution loop for the emulator. We return from here when the system 10005b261ecSmrghalts, which is normally caused by a stack fault when we return from the 10105b261ecSmrgoriginal real mode call. 10205b261ecSmrg****************************************************************************/ 10335c4bbdfSmrgvoid 10435c4bbdfSmrgX86EMU_exec(void) 10505b261ecSmrg{ 10635c4bbdfSmrg u8 op1; 10735c4bbdfSmrg 10835c4bbdfSmrg M.x86.intr = 0; 10935c4bbdfSmrg DB(x86emu_end_instr(); 11035c4bbdfSmrg ) 11135c4bbdfSmrg 11235c4bbdfSmrg for (;;) { 11335c4bbdfSmrg DB(if (CHECK_IP_FETCH()) 11435c4bbdfSmrg x86emu_check_ip_access();) 11535c4bbdfSmrg /* If debugging, save the IP and CS values. */ 11635c4bbdfSmrg SAVE_IP_CS(M.x86.R_CS, M.x86.R_IP); 11735c4bbdfSmrg INC_DECODED_INST_LEN(1); 11835c4bbdfSmrg if (M.x86.intr) { 11935c4bbdfSmrg if (M.x86.intr & INTR_HALTED) { 12035c4bbdfSmrg DB(if (M.x86.R_SP != 0) { 12135c4bbdfSmrg printk("halted\n"); X86EMU_trace_regs();} 12235c4bbdfSmrg else { 12335c4bbdfSmrg if (M.x86.debug) 12435c4bbdfSmrg printk("Service completed successfully\n");} 12535c4bbdfSmrg ) 12635c4bbdfSmrg return; 12705b261ecSmrg } 12835c4bbdfSmrg if (((M.x86.intr & INTR_SYNCH) && 12935c4bbdfSmrg (M.x86.intno == 0 || M.x86.intno == 2)) || 13035c4bbdfSmrg !ACCESS_FLAG(F_IF)) { 13135c4bbdfSmrg x86emu_intr_handle(); 13235c4bbdfSmrg } 13335c4bbdfSmrg } 13435c4bbdfSmrg op1 = (*sys_rdb) (((u32) M.x86.R_CS << 4) + (M.x86.R_IP++)); 13535c4bbdfSmrg (*x86emu_optab[op1]) (op1); 13605b261ecSmrg if (M.x86.debug & DEBUG_EXIT) { 13705b261ecSmrg M.x86.debug &= ~DEBUG_EXIT; 13805b261ecSmrg return; 13905b261ecSmrg } 14005b261ecSmrg } 14105b261ecSmrg} 14205b261ecSmrg 14305b261ecSmrg/**************************************************************************** 14405b261ecSmrgREMARKS: 14505b261ecSmrgHalts the system by setting the halted system flag. 14605b261ecSmrg****************************************************************************/ 14735c4bbdfSmrgvoid 14835c4bbdfSmrgX86EMU_halt_sys(void) 14905b261ecSmrg{ 15035c4bbdfSmrg M.x86.intr |= INTR_HALTED; 15105b261ecSmrg} 15205b261ecSmrg 15305b261ecSmrg/**************************************************************************** 15405b261ecSmrgPARAMETERS: 15505b261ecSmrgmod - Mod value from decoded byte 15605b261ecSmrgregh - Reg h value from decoded byte 15705b261ecSmrgregl - Reg l value from decoded byte 15805b261ecSmrg 15905b261ecSmrgREMARKS: 16005b261ecSmrgRaise the specified interrupt to be handled before the execution of the 16105b261ecSmrgnext instruction. 16205b261ecSmrg 16305b261ecSmrgNOTE: Do not inline this function, as (*sys_rdb) is already inline! 16405b261ecSmrg****************************************************************************/ 16535c4bbdfSmrgvoid 16635c4bbdfSmrgfetch_decode_modrm(int *mod, int *regh, int *regl) 16705b261ecSmrg{ 16835c4bbdfSmrg int fetched; 16935c4bbdfSmrg 17035c4bbdfSmrg DB(if (CHECK_IP_FETCH()) 17135c4bbdfSmrg x86emu_check_ip_access();) 17235c4bbdfSmrg fetched = (*sys_rdb) (((u32) M.x86.R_CS << 4) + (M.x86.R_IP++)); 17335c4bbdfSmrg INC_DECODED_INST_LEN(1); 17435c4bbdfSmrg *mod = (fetched >> 6) & 0x03; 17535c4bbdfSmrg *regh = (fetched >> 3) & 0x07; 17605b261ecSmrg *regl = (fetched >> 0) & 0x07; 17705b261ecSmrg} 17805b261ecSmrg 17905b261ecSmrg/**************************************************************************** 18005b261ecSmrgRETURNS: 18105b261ecSmrgImmediate byte value read from instruction queue 18205b261ecSmrg 18305b261ecSmrgREMARKS: 18405b261ecSmrgThis function returns the immediate byte from the instruction queue, and 18505b261ecSmrgmoves the instruction pointer to the next value. 18605b261ecSmrg 18705b261ecSmrgNOTE: Do not inline this function, as (*sys_rdb) is already inline! 18805b261ecSmrg****************************************************************************/ 18935c4bbdfSmrgu8 19035c4bbdfSmrgfetch_byte_imm(void) 19105b261ecSmrg{ 19235c4bbdfSmrg u8 fetched; 19305b261ecSmrg 19435c4bbdfSmrg DB(if (CHECK_IP_FETCH()) 19535c4bbdfSmrg x86emu_check_ip_access();) 19635c4bbdfSmrg fetched = (*sys_rdb) (((u32) M.x86.R_CS << 4) + (M.x86.R_IP++)); 19735c4bbdfSmrg INC_DECODED_INST_LEN(1); 19835c4bbdfSmrg return fetched; 19905b261ecSmrg} 20005b261ecSmrg 20105b261ecSmrg/**************************************************************************** 20205b261ecSmrgRETURNS: 20305b261ecSmrgImmediate word value read from instruction queue 20405b261ecSmrg 20505b261ecSmrgREMARKS: 20605b261ecSmrgThis function returns the immediate byte from the instruction queue, and 20705b261ecSmrgmoves the instruction pointer to the next value. 20805b261ecSmrg 20905b261ecSmrgNOTE: Do not inline this function, as (*sys_rdw) is already inline! 21005b261ecSmrg****************************************************************************/ 21135c4bbdfSmrgu16 21235c4bbdfSmrgfetch_word_imm(void) 21305b261ecSmrg{ 21435c4bbdfSmrg u16 fetched; 21535c4bbdfSmrg 21635c4bbdfSmrg DB(if (CHECK_IP_FETCH()) 21735c4bbdfSmrg x86emu_check_ip_access();) 21835c4bbdfSmrg fetched = (*sys_rdw) (((u32) M.x86.R_CS << 4) + (M.x86.R_IP)); 21935c4bbdfSmrg M.x86.R_IP += 2; 22035c4bbdfSmrg INC_DECODED_INST_LEN(2); 22135c4bbdfSmrg return fetched; 22205b261ecSmrg} 22305b261ecSmrg 22405b261ecSmrg/**************************************************************************** 22505b261ecSmrgRETURNS: 22605b261ecSmrgImmediate lone value read from instruction queue 22705b261ecSmrg 22805b261ecSmrgREMARKS: 22905b261ecSmrgThis function returns the immediate byte from the instruction queue, and 23005b261ecSmrgmoves the instruction pointer to the next value. 23105b261ecSmrg 23205b261ecSmrgNOTE: Do not inline this function, as (*sys_rdw) is already inline! 23305b261ecSmrg****************************************************************************/ 23435c4bbdfSmrgu32 23535c4bbdfSmrgfetch_long_imm(void) 23605b261ecSmrg{ 23735c4bbdfSmrg u32 fetched; 23835c4bbdfSmrg 23935c4bbdfSmrg DB(if (CHECK_IP_FETCH()) 24035c4bbdfSmrg x86emu_check_ip_access();) 24135c4bbdfSmrg fetched = (*sys_rdl) (((u32) M.x86.R_CS << 4) + (M.x86.R_IP)); 24235c4bbdfSmrg M.x86.R_IP += 4; 24335c4bbdfSmrg INC_DECODED_INST_LEN(4); 24435c4bbdfSmrg return fetched; 24505b261ecSmrg} 24605b261ecSmrg 24705b261ecSmrg/**************************************************************************** 24805b261ecSmrgRETURNS: 24905b261ecSmrgValue of the default data segment 25005b261ecSmrg 25105b261ecSmrgREMARKS: 25205b261ecSmrgInline function that returns the default data segment for the current 25305b261ecSmrginstruction. 25405b261ecSmrg 25505b261ecSmrgOn the x86 processor, the default segment is not always DS if there is 25605b261ecSmrgno segment override. Address modes such as -3[BP] or 10[BP+SI] all refer to 25705b261ecSmrgaddresses relative to SS (ie: on the stack). So, at the minimum, all 25805b261ecSmrgdecodings of addressing modes would have to set/clear a bit describing 25905b261ecSmrgwhether the access is relative to DS or SS. That is the function of the 26005b261ecSmrgcpu-state-varible M.x86.mode. There are several potential states: 26105b261ecSmrg 26205b261ecSmrg repe prefix seen (handled elsewhere) 26305b261ecSmrg repne prefix seen (ditto) 26405b261ecSmrg 26505b261ecSmrg cs segment override 26605b261ecSmrg ds segment override 26705b261ecSmrg es segment override 26805b261ecSmrg fs segment override 26905b261ecSmrg gs segment override 27005b261ecSmrg ss segment override 27105b261ecSmrg 272ed6184dfSmrg ds/ss select (in absence of override) 27305b261ecSmrg 27405b261ecSmrgEach of the above 7 items are handled with a bit in the mode field. 27505b261ecSmrg****************************************************************************/ 27635c4bbdfSmrg_INLINE u32 27735c4bbdfSmrgget_data_segment(void) 27805b261ecSmrg{ 27905b261ecSmrg#define GET_SEGMENT(segment) 28035c4bbdfSmrg switch (M.x86.mode & SYSMODE_SEGMASK) { 28135c4bbdfSmrg case 0: /* default case: use ds register */ 28235c4bbdfSmrg case SYSMODE_SEGOVR_DS: 28335c4bbdfSmrg case SYSMODE_SEGOVR_DS | SYSMODE_SEG_DS_SS: 28435c4bbdfSmrg return M.x86.R_DS; 28535c4bbdfSmrg case SYSMODE_SEG_DS_SS: /* non-overridden, use ss register */ 28635c4bbdfSmrg return M.x86.R_SS; 28735c4bbdfSmrg case SYSMODE_SEGOVR_CS: 28835c4bbdfSmrg case SYSMODE_SEGOVR_CS | SYSMODE_SEG_DS_SS: 28935c4bbdfSmrg return M.x86.R_CS; 29035c4bbdfSmrg case SYSMODE_SEGOVR_ES: 29135c4bbdfSmrg case SYSMODE_SEGOVR_ES | SYSMODE_SEG_DS_SS: 29235c4bbdfSmrg return M.x86.R_ES; 29335c4bbdfSmrg case SYSMODE_SEGOVR_FS: 29435c4bbdfSmrg case SYSMODE_SEGOVR_FS | SYSMODE_SEG_DS_SS: 29535c4bbdfSmrg return M.x86.R_FS; 29635c4bbdfSmrg case SYSMODE_SEGOVR_GS: 29735c4bbdfSmrg case SYSMODE_SEGOVR_GS | SYSMODE_SEG_DS_SS: 29835c4bbdfSmrg return M.x86.R_GS; 29935c4bbdfSmrg case SYSMODE_SEGOVR_SS: 30035c4bbdfSmrg case SYSMODE_SEGOVR_SS | SYSMODE_SEG_DS_SS: 30135c4bbdfSmrg return M.x86.R_SS; 30235c4bbdfSmrg default: 30305b261ecSmrg#ifdef DEBUG 30435c4bbdfSmrg printk("error: should not happen: multiple overrides.\n"); 30505b261ecSmrg#endif 30635c4bbdfSmrg HALT_SYS(); 30735c4bbdfSmrg return 0; 30835c4bbdfSmrg } 30905b261ecSmrg} 31005b261ecSmrg 31105b261ecSmrg/**************************************************************************** 31205b261ecSmrgPARAMETERS: 31305b261ecSmrgoffset - Offset to load data from 31405b261ecSmrg 31505b261ecSmrgRETURNS: 31605b261ecSmrgByte value read from the absolute memory location. 31705b261ecSmrg 31805b261ecSmrgNOTE: Do not inline this function as (*sys_rdX) is already inline! 31905b261ecSmrg****************************************************************************/ 32035c4bbdfSmrgu8 32135c4bbdfSmrgfetch_data_byte(uint offset) 32205b261ecSmrg{ 32305b261ecSmrg#ifdef DEBUG 32435c4bbdfSmrg if (CHECK_DATA_ACCESS()) 32535c4bbdfSmrg x86emu_check_data_access((u16) get_data_segment(), offset); 32605b261ecSmrg#endif 32735c4bbdfSmrg return (*sys_rdb) ((get_data_segment() << 4) + offset); 32805b261ecSmrg} 32905b261ecSmrg 33005b261ecSmrg/**************************************************************************** 33105b261ecSmrgPARAMETERS: 33205b261ecSmrgoffset - Offset to load data from 33305b261ecSmrg 33405b261ecSmrgRETURNS: 33505b261ecSmrgWord value read from the absolute memory location. 33605b261ecSmrg 33705b261ecSmrgNOTE: Do not inline this function as (*sys_rdX) is already inline! 33805b261ecSmrg****************************************************************************/ 33935c4bbdfSmrgu16 34035c4bbdfSmrgfetch_data_word(uint offset) 34105b261ecSmrg{ 34205b261ecSmrg#ifdef DEBUG 34335c4bbdfSmrg if (CHECK_DATA_ACCESS()) 34435c4bbdfSmrg x86emu_check_data_access((u16) get_data_segment(), offset); 34505b261ecSmrg#endif 34635c4bbdfSmrg return (*sys_rdw) ((get_data_segment() << 4) + offset); 34705b261ecSmrg} 34805b261ecSmrg 34905b261ecSmrg/**************************************************************************** 35005b261ecSmrgPARAMETERS: 35105b261ecSmrgoffset - Offset to load data from 35205b261ecSmrg 35305b261ecSmrgRETURNS: 35405b261ecSmrgLong value read from the absolute memory location. 35505b261ecSmrg 35605b261ecSmrgNOTE: Do not inline this function as (*sys_rdX) is already inline! 35705b261ecSmrg****************************************************************************/ 35835c4bbdfSmrgu32 35935c4bbdfSmrgfetch_data_long(uint offset) 36005b261ecSmrg{ 36105b261ecSmrg#ifdef DEBUG 36235c4bbdfSmrg if (CHECK_DATA_ACCESS()) 36335c4bbdfSmrg x86emu_check_data_access((u16) get_data_segment(), offset); 36405b261ecSmrg#endif 36535c4bbdfSmrg return (*sys_rdl) ((get_data_segment() << 4) + offset); 36605b261ecSmrg} 36705b261ecSmrg 36805b261ecSmrg/**************************************************************************** 36905b261ecSmrgPARAMETERS: 37005b261ecSmrgsegment - Segment to load data from 37105b261ecSmrgoffset - Offset to load data from 37205b261ecSmrg 37305b261ecSmrgRETURNS: 37405b261ecSmrgByte value read from the absolute memory location. 37505b261ecSmrg 37605b261ecSmrgNOTE: Do not inline this function as (*sys_rdX) is already inline! 37705b261ecSmrg****************************************************************************/ 37835c4bbdfSmrgu8 37935c4bbdfSmrgfetch_data_byte_abs(uint segment, uint offset) 38005b261ecSmrg{ 38105b261ecSmrg#ifdef DEBUG 38235c4bbdfSmrg if (CHECK_DATA_ACCESS()) 38335c4bbdfSmrg x86emu_check_data_access(segment, offset); 38405b261ecSmrg#endif 38535c4bbdfSmrg return (*sys_rdb) (((u32) segment << 4) + offset); 38605b261ecSmrg} 38705b261ecSmrg 38805b261ecSmrg/**************************************************************************** 38905b261ecSmrgPARAMETERS: 39005b261ecSmrgsegment - Segment to load data from 39105b261ecSmrgoffset - Offset to load data from 39205b261ecSmrg 39305b261ecSmrgRETURNS: 39405b261ecSmrgWord value read from the absolute memory location. 39505b261ecSmrg 39605b261ecSmrgNOTE: Do not inline this function as (*sys_rdX) is already inline! 39705b261ecSmrg****************************************************************************/ 39835c4bbdfSmrgu16 39935c4bbdfSmrgfetch_data_word_abs(uint segment, uint offset) 40005b261ecSmrg{ 40105b261ecSmrg#ifdef DEBUG 40235c4bbdfSmrg if (CHECK_DATA_ACCESS()) 40335c4bbdfSmrg x86emu_check_data_access(segment, offset); 40405b261ecSmrg#endif 40535c4bbdfSmrg return (*sys_rdw) (((u32) segment << 4) + offset); 40605b261ecSmrg} 40705b261ecSmrg 40805b261ecSmrg/**************************************************************************** 40905b261ecSmrgPARAMETERS: 41005b261ecSmrgsegment - Segment to load data from 41105b261ecSmrgoffset - Offset to load data from 41205b261ecSmrg 41305b261ecSmrgRETURNS: 41405b261ecSmrgLong value read from the absolute memory location. 41505b261ecSmrg 41605b261ecSmrgNOTE: Do not inline this function as (*sys_rdX) is already inline! 41705b261ecSmrg****************************************************************************/ 41835c4bbdfSmrgu32 41935c4bbdfSmrgfetch_data_long_abs(uint segment, uint offset) 42005b261ecSmrg{ 42105b261ecSmrg#ifdef DEBUG 42235c4bbdfSmrg if (CHECK_DATA_ACCESS()) 42335c4bbdfSmrg x86emu_check_data_access(segment, offset); 42405b261ecSmrg#endif 42535c4bbdfSmrg return (*sys_rdl) (((u32) segment << 4) + offset); 42605b261ecSmrg} 42705b261ecSmrg 42805b261ecSmrg/**************************************************************************** 42905b261ecSmrgPARAMETERS: 43005b261ecSmrgoffset - Offset to store data at 43105b261ecSmrgval - Value to store 43205b261ecSmrg 43305b261ecSmrgREMARKS: 43405b261ecSmrgWrites a word value to an segmented memory location. The segment used is 43505b261ecSmrgthe current 'default' segment, which may have been overridden. 43605b261ecSmrg 43705b261ecSmrgNOTE: Do not inline this function as (*sys_wrX) is already inline! 43805b261ecSmrg****************************************************************************/ 43935c4bbdfSmrgvoid 44035c4bbdfSmrgstore_data_byte(uint offset, u8 val) 44105b261ecSmrg{ 44205b261ecSmrg#ifdef DEBUG 44335c4bbdfSmrg if (CHECK_DATA_ACCESS()) 44435c4bbdfSmrg x86emu_check_data_access((u16) get_data_segment(), offset); 44505b261ecSmrg#endif 44635c4bbdfSmrg (*sys_wrb) ((get_data_segment() << 4) + offset, val); 44705b261ecSmrg} 44805b261ecSmrg 44905b261ecSmrg/**************************************************************************** 45005b261ecSmrgPARAMETERS: 45105b261ecSmrgoffset - Offset to store data at 45205b261ecSmrgval - Value to store 45305b261ecSmrg 45405b261ecSmrgREMARKS: 45505b261ecSmrgWrites a word value to an segmented memory location. The segment used is 45605b261ecSmrgthe current 'default' segment, which may have been overridden. 45705b261ecSmrg 45805b261ecSmrgNOTE: Do not inline this function as (*sys_wrX) is already inline! 45905b261ecSmrg****************************************************************************/ 46035c4bbdfSmrgvoid 46135c4bbdfSmrgstore_data_word(uint offset, u16 val) 46205b261ecSmrg{ 46305b261ecSmrg#ifdef DEBUG 46435c4bbdfSmrg if (CHECK_DATA_ACCESS()) 46535c4bbdfSmrg x86emu_check_data_access((u16) get_data_segment(), offset); 46605b261ecSmrg#endif 46735c4bbdfSmrg (*sys_wrw) ((get_data_segment() << 4) + offset, val); 46805b261ecSmrg} 46905b261ecSmrg 47005b261ecSmrg/**************************************************************************** 47105b261ecSmrgPARAMETERS: 47205b261ecSmrgoffset - Offset to store data at 47305b261ecSmrgval - Value to store 47405b261ecSmrg 47505b261ecSmrgREMARKS: 47605b261ecSmrgWrites a long value to an segmented memory location. The segment used is 47705b261ecSmrgthe current 'default' segment, which may have been overridden. 47805b261ecSmrg 47905b261ecSmrgNOTE: Do not inline this function as (*sys_wrX) is already inline! 48005b261ecSmrg****************************************************************************/ 48135c4bbdfSmrgvoid 48235c4bbdfSmrgstore_data_long(uint offset, u32 val) 48305b261ecSmrg{ 48405b261ecSmrg#ifdef DEBUG 48535c4bbdfSmrg if (CHECK_DATA_ACCESS()) 48635c4bbdfSmrg x86emu_check_data_access((u16) get_data_segment(), offset); 48705b261ecSmrg#endif 48835c4bbdfSmrg (*sys_wrl) ((get_data_segment() << 4) + offset, val); 48905b261ecSmrg} 49005b261ecSmrg 49105b261ecSmrg/**************************************************************************** 49205b261ecSmrgPARAMETERS: 49305b261ecSmrgsegment - Segment to store data at 49405b261ecSmrgoffset - Offset to store data at 49505b261ecSmrgval - Value to store 49605b261ecSmrg 49705b261ecSmrgREMARKS: 49805b261ecSmrgWrites a byte value to an absolute memory location. 49905b261ecSmrg 50005b261ecSmrgNOTE: Do not inline this function as (*sys_wrX) is already inline! 50105b261ecSmrg****************************************************************************/ 50235c4bbdfSmrgvoid 50335c4bbdfSmrgstore_data_byte_abs(uint segment, uint offset, u8 val) 50405b261ecSmrg{ 50505b261ecSmrg#ifdef DEBUG 50635c4bbdfSmrg if (CHECK_DATA_ACCESS()) 50735c4bbdfSmrg x86emu_check_data_access(segment, offset); 50805b261ecSmrg#endif 50935c4bbdfSmrg (*sys_wrb) (((u32) segment << 4) + offset, val); 51005b261ecSmrg} 51105b261ecSmrg 51205b261ecSmrg/**************************************************************************** 51305b261ecSmrgPARAMETERS: 51405b261ecSmrgsegment - Segment to store data at 51505b261ecSmrgoffset - Offset to store data at 51605b261ecSmrgval - Value to store 51705b261ecSmrg 51805b261ecSmrgREMARKS: 51905b261ecSmrgWrites a word value to an absolute memory location. 52005b261ecSmrg 52105b261ecSmrgNOTE: Do not inline this function as (*sys_wrX) is already inline! 52205b261ecSmrg****************************************************************************/ 52335c4bbdfSmrgvoid 52435c4bbdfSmrgstore_data_word_abs(uint segment, uint offset, u16 val) 52505b261ecSmrg{ 52605b261ecSmrg#ifdef DEBUG 52735c4bbdfSmrg if (CHECK_DATA_ACCESS()) 52835c4bbdfSmrg x86emu_check_data_access(segment, offset); 52905b261ecSmrg#endif 53035c4bbdfSmrg (*sys_wrw) (((u32) segment << 4) + offset, val); 53105b261ecSmrg} 53205b261ecSmrg 53305b261ecSmrg/**************************************************************************** 53405b261ecSmrgPARAMETERS: 53505b261ecSmrgsegment - Segment to store data at 53605b261ecSmrgoffset - Offset to store data at 53705b261ecSmrgval - Value to store 53805b261ecSmrg 53905b261ecSmrgREMARKS: 54005b261ecSmrgWrites a long value to an absolute memory location. 54105b261ecSmrg 54205b261ecSmrgNOTE: Do not inline this function as (*sys_wrX) is already inline! 54305b261ecSmrg****************************************************************************/ 54435c4bbdfSmrgvoid 54535c4bbdfSmrgstore_data_long_abs(uint segment, uint offset, u32 val) 54605b261ecSmrg{ 54705b261ecSmrg#ifdef DEBUG 54835c4bbdfSmrg if (CHECK_DATA_ACCESS()) 54935c4bbdfSmrg x86emu_check_data_access(segment, offset); 55005b261ecSmrg#endif 55135c4bbdfSmrg (*sys_wrl) (((u32) segment << 4) + offset, val); 55205b261ecSmrg} 55305b261ecSmrg 55405b261ecSmrg/**************************************************************************** 55505b261ecSmrgPARAMETERS: 55605b261ecSmrgreg - Register to decode 55705b261ecSmrg 55805b261ecSmrgRETURNS: 55905b261ecSmrgPointer to the appropriate register 56005b261ecSmrg 56105b261ecSmrgREMARKS: 56205b261ecSmrgReturn a pointer to the register given by the R/RM field of the 56305b261ecSmrgmodrm byte, for byte operands. Also enables the decoding of instructions. 56405b261ecSmrg****************************************************************************/ 56535c4bbdfSmrgu8 * 56635c4bbdfSmrgdecode_rm_byte_register(int reg) 56705b261ecSmrg{ 56835c4bbdfSmrg switch (reg) { 56935c4bbdfSmrg case 0: 57035c4bbdfSmrg DECODE_PRINTF("AL"); 57135c4bbdfSmrg return &M.x86.R_AL; 57235c4bbdfSmrg case 1: 57335c4bbdfSmrg DECODE_PRINTF("CL"); 57435c4bbdfSmrg return &M.x86.R_CL; 57535c4bbdfSmrg case 2: 57635c4bbdfSmrg DECODE_PRINTF("DL"); 57735c4bbdfSmrg return &M.x86.R_DL; 57835c4bbdfSmrg case 3: 57935c4bbdfSmrg DECODE_PRINTF("BL"); 58035c4bbdfSmrg return &M.x86.R_BL; 58135c4bbdfSmrg case 4: 58235c4bbdfSmrg DECODE_PRINTF("AH"); 58335c4bbdfSmrg return &M.x86.R_AH; 58435c4bbdfSmrg case 5: 58535c4bbdfSmrg DECODE_PRINTF("CH"); 58635c4bbdfSmrg return &M.x86.R_CH; 58735c4bbdfSmrg case 6: 58835c4bbdfSmrg DECODE_PRINTF("DH"); 58935c4bbdfSmrg return &M.x86.R_DH; 59035c4bbdfSmrg case 7: 59135c4bbdfSmrg DECODE_PRINTF("BH"); 59235c4bbdfSmrg return &M.x86.R_BH; 59335c4bbdfSmrg } 59435c4bbdfSmrg HALT_SYS(); 59535c4bbdfSmrg return NULL; /* NOT REACHED OR REACHED ON ERROR */ 59605b261ecSmrg} 59705b261ecSmrg 59805b261ecSmrg/**************************************************************************** 59905b261ecSmrgPARAMETERS: 60005b261ecSmrgreg - Register to decode 60105b261ecSmrg 60205b261ecSmrgRETURNS: 60305b261ecSmrgPointer to the appropriate register 60405b261ecSmrg 60505b261ecSmrgREMARKS: 60605b261ecSmrgReturn a pointer to the register given by the R/RM field of the 60705b261ecSmrgmodrm byte, for word operands. Also enables the decoding of instructions. 60805b261ecSmrg****************************************************************************/ 60935c4bbdfSmrgu16 * 61035c4bbdfSmrgdecode_rm_word_register(int reg) 61105b261ecSmrg{ 61235c4bbdfSmrg switch (reg) { 61335c4bbdfSmrg case 0: 61435c4bbdfSmrg DECODE_PRINTF("AX"); 61535c4bbdfSmrg return &M.x86.R_AX; 61635c4bbdfSmrg case 1: 61735c4bbdfSmrg DECODE_PRINTF("CX"); 61835c4bbdfSmrg return &M.x86.R_CX; 61935c4bbdfSmrg case 2: 62035c4bbdfSmrg DECODE_PRINTF("DX"); 62135c4bbdfSmrg return &M.x86.R_DX; 62235c4bbdfSmrg case 3: 62335c4bbdfSmrg DECODE_PRINTF("BX"); 62435c4bbdfSmrg return &M.x86.R_BX; 62535c4bbdfSmrg case 4: 62635c4bbdfSmrg DECODE_PRINTF("SP"); 62735c4bbdfSmrg return &M.x86.R_SP; 62835c4bbdfSmrg case 5: 62935c4bbdfSmrg DECODE_PRINTF("BP"); 63035c4bbdfSmrg return &M.x86.R_BP; 63135c4bbdfSmrg case 6: 63235c4bbdfSmrg DECODE_PRINTF("SI"); 63335c4bbdfSmrg return &M.x86.R_SI; 63435c4bbdfSmrg case 7: 63535c4bbdfSmrg DECODE_PRINTF("DI"); 63635c4bbdfSmrg return &M.x86.R_DI; 63735c4bbdfSmrg } 63835c4bbdfSmrg HALT_SYS(); 63905b261ecSmrg return NULL; /* NOTREACHED OR REACHED ON ERROR */ 64005b261ecSmrg} 64105b261ecSmrg 64205b261ecSmrg/**************************************************************************** 64305b261ecSmrgPARAMETERS: 64405b261ecSmrgreg - Register to decode 64505b261ecSmrg 64605b261ecSmrgRETURNS: 64705b261ecSmrgPointer to the appropriate register 64805b261ecSmrg 64905b261ecSmrgREMARKS: 65005b261ecSmrgReturn a pointer to the register given by the R/RM field of the 65105b261ecSmrgmodrm byte, for dword operands. Also enables the decoding of instructions. 65205b261ecSmrg****************************************************************************/ 65335c4bbdfSmrgu32 * 65435c4bbdfSmrgdecode_rm_long_register(int reg) 65505b261ecSmrg{ 65605b261ecSmrg switch (reg) { 65735c4bbdfSmrg case 0: 65835c4bbdfSmrg DECODE_PRINTF("EAX"); 65935c4bbdfSmrg return &M.x86.R_EAX; 66035c4bbdfSmrg case 1: 66135c4bbdfSmrg DECODE_PRINTF("ECX"); 66235c4bbdfSmrg return &M.x86.R_ECX; 66335c4bbdfSmrg case 2: 66435c4bbdfSmrg DECODE_PRINTF("EDX"); 66535c4bbdfSmrg return &M.x86.R_EDX; 66635c4bbdfSmrg case 3: 66735c4bbdfSmrg DECODE_PRINTF("EBX"); 66835c4bbdfSmrg return &M.x86.R_EBX; 66935c4bbdfSmrg case 4: 67035c4bbdfSmrg DECODE_PRINTF("ESP"); 67135c4bbdfSmrg return &M.x86.R_ESP; 67235c4bbdfSmrg case 5: 67335c4bbdfSmrg DECODE_PRINTF("EBP"); 67435c4bbdfSmrg return &M.x86.R_EBP; 67535c4bbdfSmrg case 6: 67635c4bbdfSmrg DECODE_PRINTF("ESI"); 67735c4bbdfSmrg return &M.x86.R_ESI; 67835c4bbdfSmrg case 7: 67935c4bbdfSmrg DECODE_PRINTF("EDI"); 68035c4bbdfSmrg return &M.x86.R_EDI; 68135c4bbdfSmrg } 68235c4bbdfSmrg HALT_SYS(); 68305b261ecSmrg return NULL; /* NOTREACHED OR REACHED ON ERROR */ 68405b261ecSmrg} 68505b261ecSmrg 68605b261ecSmrg/**************************************************************************** 68705b261ecSmrgPARAMETERS: 68805b261ecSmrgreg - Register to decode 68905b261ecSmrg 69005b261ecSmrgRETURNS: 69105b261ecSmrgPointer to the appropriate register 69205b261ecSmrg 69305b261ecSmrgREMARKS: 69405b261ecSmrgReturn a pointer to the register given by the R/RM field of the 69505b261ecSmrgmodrm byte, for word operands, modified from above for the weirdo 69605b261ecSmrgspecial case of segreg operands. Also enables the decoding of instructions. 69705b261ecSmrg****************************************************************************/ 69835c4bbdfSmrgu16 * 69935c4bbdfSmrgdecode_rm_seg_register(int reg) 70005b261ecSmrg{ 70135c4bbdfSmrg switch (reg) { 70235c4bbdfSmrg case 0: 70335c4bbdfSmrg DECODE_PRINTF("ES"); 70435c4bbdfSmrg return &M.x86.R_ES; 70535c4bbdfSmrg case 1: 70635c4bbdfSmrg DECODE_PRINTF("CS"); 70735c4bbdfSmrg return &M.x86.R_CS; 70835c4bbdfSmrg case 2: 70935c4bbdfSmrg DECODE_PRINTF("SS"); 71035c4bbdfSmrg return &M.x86.R_SS; 71135c4bbdfSmrg case 3: 71235c4bbdfSmrg DECODE_PRINTF("DS"); 71335c4bbdfSmrg return &M.x86.R_DS; 71435c4bbdfSmrg case 4: 71535c4bbdfSmrg DECODE_PRINTF("FS"); 71635c4bbdfSmrg return &M.x86.R_FS; 71735c4bbdfSmrg case 5: 71835c4bbdfSmrg DECODE_PRINTF("GS"); 71935c4bbdfSmrg return &M.x86.R_GS; 72035c4bbdfSmrg case 6: 72135c4bbdfSmrg case 7: 72235c4bbdfSmrg DECODE_PRINTF("ILLEGAL SEGREG"); 72335c4bbdfSmrg break; 72435c4bbdfSmrg } 72535c4bbdfSmrg HALT_SYS(); 72635c4bbdfSmrg return NULL; /* NOT REACHED OR REACHED ON ERROR */ 72705b261ecSmrg} 72805b261ecSmrg 72905b261ecSmrg/* 73005b261ecSmrg * 73105b261ecSmrg * return offset from the SIB Byte 73205b261ecSmrg */ 73335c4bbdfSmrgu32 73435c4bbdfSmrgdecode_sib_address(int sib, int mod) 73505b261ecSmrg{ 73605b261ecSmrg u32 base = 0, i = 0, scale = 1; 73705b261ecSmrg 73835c4bbdfSmrg switch (sib & 0x07) { 73905b261ecSmrg case 0: 74035c4bbdfSmrg DECODE_PRINTF("[EAX]"); 74135c4bbdfSmrg base = M.x86.R_EAX; 74235c4bbdfSmrg break; 74305b261ecSmrg case 1: 74435c4bbdfSmrg DECODE_PRINTF("[ECX]"); 74535c4bbdfSmrg base = M.x86.R_ECX; 74635c4bbdfSmrg break; 74705b261ecSmrg case 2: 74835c4bbdfSmrg DECODE_PRINTF("[EDX]"); 74935c4bbdfSmrg base = M.x86.R_EDX; 75035c4bbdfSmrg break; 75105b261ecSmrg case 3: 75235c4bbdfSmrg DECODE_PRINTF("[EBX]"); 75335c4bbdfSmrg base = M.x86.R_EBX; 75435c4bbdfSmrg break; 75505b261ecSmrg case 4: 75635c4bbdfSmrg DECODE_PRINTF("[ESP]"); 75735c4bbdfSmrg base = M.x86.R_ESP; 75835c4bbdfSmrg M.x86.mode |= SYSMODE_SEG_DS_SS; 75935c4bbdfSmrg break; 76005b261ecSmrg case 5: 76135c4bbdfSmrg if (mod == 0) { 76235c4bbdfSmrg base = fetch_long_imm(); 76335c4bbdfSmrg DECODE_PRINTF2("%08x", base); 76435c4bbdfSmrg } 76535c4bbdfSmrg else { 76635c4bbdfSmrg DECODE_PRINTF("[EBP]"); 76735c4bbdfSmrg base = M.x86.R_ESP; 76835c4bbdfSmrg M.x86.mode |= SYSMODE_SEG_DS_SS; 76935c4bbdfSmrg } 77035c4bbdfSmrg break; 77105b261ecSmrg case 6: 77235c4bbdfSmrg DECODE_PRINTF("[ESI]"); 77335c4bbdfSmrg base = M.x86.R_ESI; 77435c4bbdfSmrg break; 77505b261ecSmrg case 7: 77635c4bbdfSmrg DECODE_PRINTF("[EDI]"); 77735c4bbdfSmrg base = M.x86.R_EDI; 77835c4bbdfSmrg break; 77905b261ecSmrg } 78005b261ecSmrg switch ((sib >> 3) & 0x07) { 78105b261ecSmrg case 0: 78235c4bbdfSmrg DECODE_PRINTF("[EAX"); 78335c4bbdfSmrg i = M.x86.R_EAX; 78435c4bbdfSmrg break; 78505b261ecSmrg case 1: 78635c4bbdfSmrg DECODE_PRINTF("[ECX"); 78735c4bbdfSmrg i = M.x86.R_ECX; 78835c4bbdfSmrg break; 78905b261ecSmrg case 2: 79035c4bbdfSmrg DECODE_PRINTF("[EDX"); 79135c4bbdfSmrg i = M.x86.R_EDX; 79235c4bbdfSmrg break; 79305b261ecSmrg case 3: 79435c4bbdfSmrg DECODE_PRINTF("[EBX"); 79535c4bbdfSmrg i = M.x86.R_EBX; 79635c4bbdfSmrg break; 79705b261ecSmrg case 4: 79835c4bbdfSmrg i = 0; 79935c4bbdfSmrg break; 80005b261ecSmrg case 5: 80135c4bbdfSmrg DECODE_PRINTF("[EBP"); 80235c4bbdfSmrg i = M.x86.R_EBP; 80335c4bbdfSmrg break; 80405b261ecSmrg case 6: 80535c4bbdfSmrg DECODE_PRINTF("[ESI"); 80635c4bbdfSmrg i = M.x86.R_ESI; 80735c4bbdfSmrg break; 80805b261ecSmrg case 7: 80935c4bbdfSmrg DECODE_PRINTF("[EDI"); 81035c4bbdfSmrg i = M.x86.R_EDI; 81135c4bbdfSmrg break; 81205b261ecSmrg } 81305b261ecSmrg scale = 1 << ((sib >> 6) & 0x03); 81405b261ecSmrg if (((sib >> 3) & 0x07) != 4) { 81535c4bbdfSmrg if (scale == 1) { 81635c4bbdfSmrg DECODE_PRINTF("]"); 81735c4bbdfSmrg } 81835c4bbdfSmrg else { 81935c4bbdfSmrg DECODE_PRINTF2("*%d]", scale); 82035c4bbdfSmrg } 82105b261ecSmrg } 82205b261ecSmrg return base + (i * scale); 82305b261ecSmrg} 82405b261ecSmrg 82505b261ecSmrg/**************************************************************************** 82605b261ecSmrgPARAMETERS: 82705b261ecSmrgrm - RM value to decode 82805b261ecSmrg 82905b261ecSmrgRETURNS: 83005b261ecSmrgOffset in memory for the address decoding 83105b261ecSmrg 83205b261ecSmrgREMARKS: 83305b261ecSmrgReturn the offset given by mod=00 addressing. Also enables the 83405b261ecSmrgdecoding of instructions. 83505b261ecSmrg 83605b261ecSmrgNOTE: The code which specifies the corresponding segment (ds vs ss) 83705b261ecSmrg below in the case of [BP+..]. The assumption here is that at the 83805b261ecSmrg point that this subroutine is called, the bit corresponding to 83905b261ecSmrg SYSMODE_SEG_DS_SS will be zero. After every instruction 84005b261ecSmrg except the segment override instructions, this bit (as well 84105b261ecSmrg as any bits indicating segment overrides) will be clear. So 84205b261ecSmrg if a SS access is needed, set this bit. Otherwise, DS access 84305b261ecSmrg occurs (unless any of the segment override bits are set). 84405b261ecSmrg****************************************************************************/ 84535c4bbdfSmrgu32 84635c4bbdfSmrgdecode_rm00_address(int rm) 84705b261ecSmrg{ 84805b261ecSmrg u32 offset; 84905b261ecSmrg int sib; 85005b261ecSmrg 85105b261ecSmrg if (M.x86.mode & SYSMODE_PREFIX_ADDR) { 85205b261ecSmrg /* 32-bit addressing */ 85335c4bbdfSmrg switch (rm) { 85435c4bbdfSmrg case 0: 85535c4bbdfSmrg DECODE_PRINTF("[EAX]"); 85635c4bbdfSmrg return M.x86.R_EAX; 85735c4bbdfSmrg case 1: 85835c4bbdfSmrg DECODE_PRINTF("[ECX]"); 85935c4bbdfSmrg return M.x86.R_ECX; 86035c4bbdfSmrg case 2: 86135c4bbdfSmrg DECODE_PRINTF("[EDX]"); 86235c4bbdfSmrg return M.x86.R_EDX; 86335c4bbdfSmrg case 3: 86435c4bbdfSmrg DECODE_PRINTF("[EBX]"); 86535c4bbdfSmrg return M.x86.R_EBX; 86635c4bbdfSmrg case 4: 86735c4bbdfSmrg sib = fetch_byte_imm(); 86835c4bbdfSmrg return decode_sib_address(sib, 0); 86935c4bbdfSmrg case 5: 87035c4bbdfSmrg offset = fetch_long_imm(); 87135c4bbdfSmrg DECODE_PRINTF2("[%08x]", offset); 87235c4bbdfSmrg return offset; 87335c4bbdfSmrg case 6: 87435c4bbdfSmrg DECODE_PRINTF("[ESI]"); 87535c4bbdfSmrg return M.x86.R_ESI; 87635c4bbdfSmrg case 7: 87735c4bbdfSmrg DECODE_PRINTF("[EDI]"); 87835c4bbdfSmrg return M.x86.R_EDI; 87935c4bbdfSmrg } 88035c4bbdfSmrg HALT_SYS(); 88135c4bbdfSmrg } 88235c4bbdfSmrg else { 88305b261ecSmrg /* 16-bit addressing */ 88435c4bbdfSmrg switch (rm) { 88535c4bbdfSmrg case 0: 88635c4bbdfSmrg DECODE_PRINTF("[BX+SI]"); 88705b261ecSmrg return (M.x86.R_BX + M.x86.R_SI) & 0xffff; 88835c4bbdfSmrg case 1: 88935c4bbdfSmrg DECODE_PRINTF("[BX+DI]"); 89005b261ecSmrg return (M.x86.R_BX + M.x86.R_DI) & 0xffff; 89135c4bbdfSmrg case 2: 89235c4bbdfSmrg DECODE_PRINTF("[BP+SI]"); 89335c4bbdfSmrg M.x86.mode |= SYSMODE_SEG_DS_SS; 89405b261ecSmrg return (M.x86.R_BP + M.x86.R_SI) & 0xffff; 89535c4bbdfSmrg case 3: 89635c4bbdfSmrg DECODE_PRINTF("[BP+DI]"); 89735c4bbdfSmrg M.x86.mode |= SYSMODE_SEG_DS_SS; 89805b261ecSmrg return (M.x86.R_BP + M.x86.R_DI) & 0xffff; 89935c4bbdfSmrg case 4: 90035c4bbdfSmrg DECODE_PRINTF("[SI]"); 90135c4bbdfSmrg return M.x86.R_SI; 90235c4bbdfSmrg case 5: 90335c4bbdfSmrg DECODE_PRINTF("[DI]"); 90435c4bbdfSmrg return M.x86.R_DI; 90535c4bbdfSmrg case 6: 90635c4bbdfSmrg offset = fetch_word_imm(); 90735c4bbdfSmrg DECODE_PRINTF2("[%04x]", offset); 90835c4bbdfSmrg return offset; 90935c4bbdfSmrg case 7: 91035c4bbdfSmrg DECODE_PRINTF("[BX]"); 91135c4bbdfSmrg return M.x86.R_BX; 91235c4bbdfSmrg } 91335c4bbdfSmrg HALT_SYS(); 91405b261ecSmrg } 91505b261ecSmrg return 0; 91605b261ecSmrg} 91705b261ecSmrg 91805b261ecSmrg/**************************************************************************** 91905b261ecSmrgPARAMETERS: 92005b261ecSmrgrm - RM value to decode 92105b261ecSmrg 92205b261ecSmrgRETURNS: 92305b261ecSmrgOffset in memory for the address decoding 92405b261ecSmrg 92505b261ecSmrgREMARKS: 92605b261ecSmrgReturn the offset given by mod=01 addressing. Also enables the 92705b261ecSmrgdecoding of instructions. 92805b261ecSmrg****************************************************************************/ 92935c4bbdfSmrgu32 93035c4bbdfSmrgdecode_rm01_address(int rm) 93105b261ecSmrg{ 93205b261ecSmrg int displacement = 0; 93305b261ecSmrg int sib; 93405b261ecSmrg 93505b261ecSmrg /* Fetch disp8 if no SIB byte */ 93605b261ecSmrg if (!((M.x86.mode & SYSMODE_PREFIX_ADDR) && (rm == 4))) 93735c4bbdfSmrg displacement = (s8) fetch_byte_imm(); 93805b261ecSmrg 93905b261ecSmrg if (M.x86.mode & SYSMODE_PREFIX_ADDR) { 94005b261ecSmrg /* 32-bit addressing */ 94135c4bbdfSmrg switch (rm) { 94235c4bbdfSmrg case 0: 94335c4bbdfSmrg DECODE_PRINTF2("%d[EAX]", displacement); 94435c4bbdfSmrg return M.x86.R_EAX + displacement; 94535c4bbdfSmrg case 1: 94635c4bbdfSmrg DECODE_PRINTF2("%d[ECX]", displacement); 94735c4bbdfSmrg return M.x86.R_ECX + displacement; 94835c4bbdfSmrg case 2: 94935c4bbdfSmrg DECODE_PRINTF2("%d[EDX]", displacement); 95035c4bbdfSmrg return M.x86.R_EDX + displacement; 95135c4bbdfSmrg case 3: 95235c4bbdfSmrg DECODE_PRINTF2("%d[EBX]", displacement); 95335c4bbdfSmrg return M.x86.R_EBX + displacement; 95435c4bbdfSmrg case 4: 95535c4bbdfSmrg sib = fetch_byte_imm(); 95635c4bbdfSmrg displacement = (s8) fetch_byte_imm(); 95735c4bbdfSmrg DECODE_PRINTF2("%d", displacement); 95835c4bbdfSmrg return decode_sib_address(sib, 1) + displacement; 95935c4bbdfSmrg case 5: 96035c4bbdfSmrg DECODE_PRINTF2("%d[EBP]", displacement); 96135c4bbdfSmrg return M.x86.R_EBP + displacement; 96235c4bbdfSmrg case 6: 96335c4bbdfSmrg DECODE_PRINTF2("%d[ESI]", displacement); 96435c4bbdfSmrg return M.x86.R_ESI + displacement; 96535c4bbdfSmrg case 7: 96635c4bbdfSmrg DECODE_PRINTF2("%d[EDI]", displacement); 96735c4bbdfSmrg return M.x86.R_EDI + displacement; 96835c4bbdfSmrg } 96935c4bbdfSmrg HALT_SYS(); 97035c4bbdfSmrg } 97135c4bbdfSmrg else { 97205b261ecSmrg /* 16-bit addressing */ 97335c4bbdfSmrg switch (rm) { 97435c4bbdfSmrg case 0: 97535c4bbdfSmrg DECODE_PRINTF2("%d[BX+SI]", displacement); 97605b261ecSmrg return (M.x86.R_BX + M.x86.R_SI + displacement) & 0xffff; 97735c4bbdfSmrg case 1: 97835c4bbdfSmrg DECODE_PRINTF2("%d[BX+DI]", displacement); 97905b261ecSmrg return (M.x86.R_BX + M.x86.R_DI + displacement) & 0xffff; 98035c4bbdfSmrg case 2: 98135c4bbdfSmrg DECODE_PRINTF2("%d[BP+SI]", displacement); 98235c4bbdfSmrg M.x86.mode |= SYSMODE_SEG_DS_SS; 98305b261ecSmrg return (M.x86.R_BP + M.x86.R_SI + displacement) & 0xffff; 98435c4bbdfSmrg case 3: 98535c4bbdfSmrg DECODE_PRINTF2("%d[BP+DI]", displacement); 98635c4bbdfSmrg M.x86.mode |= SYSMODE_SEG_DS_SS; 98705b261ecSmrg return (M.x86.R_BP + M.x86.R_DI + displacement) & 0xffff; 98835c4bbdfSmrg case 4: 98935c4bbdfSmrg DECODE_PRINTF2("%d[SI]", displacement); 99005b261ecSmrg return (M.x86.R_SI + displacement) & 0xffff; 99135c4bbdfSmrg case 5: 99235c4bbdfSmrg DECODE_PRINTF2("%d[DI]", displacement); 99305b261ecSmrg return (M.x86.R_DI + displacement) & 0xffff; 99435c4bbdfSmrg case 6: 99535c4bbdfSmrg DECODE_PRINTF2("%d[BP]", displacement); 99635c4bbdfSmrg M.x86.mode |= SYSMODE_SEG_DS_SS; 99705b261ecSmrg return (M.x86.R_BP + displacement) & 0xffff; 99835c4bbdfSmrg case 7: 99935c4bbdfSmrg DECODE_PRINTF2("%d[BX]", displacement); 100005b261ecSmrg return (M.x86.R_BX + displacement) & 0xffff; 100135c4bbdfSmrg } 100235c4bbdfSmrg HALT_SYS(); 100305b261ecSmrg } 100405b261ecSmrg return 0; /* SHOULD NOT HAPPEN */ 100505b261ecSmrg} 100605b261ecSmrg 100705b261ecSmrg/**************************************************************************** 100805b261ecSmrgPARAMETERS: 100905b261ecSmrgrm - RM value to decode 101005b261ecSmrg 101105b261ecSmrgRETURNS: 101205b261ecSmrgOffset in memory for the address decoding 101305b261ecSmrg 101405b261ecSmrgREMARKS: 101505b261ecSmrgReturn the offset given by mod=10 addressing. Also enables the 101605b261ecSmrgdecoding of instructions. 101705b261ecSmrg****************************************************************************/ 101835c4bbdfSmrgu32 101935c4bbdfSmrgdecode_rm10_address(int rm) 102005b261ecSmrg{ 102105b261ecSmrg u32 displacement = 0; 102205b261ecSmrg int sib; 102305b261ecSmrg 102405b261ecSmrg /* Fetch disp16 if 16-bit addr mode */ 102505b261ecSmrg if (!(M.x86.mode & SYSMODE_PREFIX_ADDR)) 102635c4bbdfSmrg displacement = (u16) fetch_word_imm(); 102705b261ecSmrg else { 102835c4bbdfSmrg /* Fetch disp32 if no SIB byte */ 102935c4bbdfSmrg if (rm != 4) 103035c4bbdfSmrg displacement = (u32) fetch_long_imm(); 103105b261ecSmrg } 103205b261ecSmrg 103305b261ecSmrg if (M.x86.mode & SYSMODE_PREFIX_ADDR) { 103405b261ecSmrg /* 32-bit addressing */ 103535c4bbdfSmrg switch (rm) { 103635c4bbdfSmrg case 0: 103735c4bbdfSmrg DECODE_PRINTF2("%08x[EAX]", displacement); 103835c4bbdfSmrg return M.x86.R_EAX + displacement; 103935c4bbdfSmrg case 1: 104035c4bbdfSmrg DECODE_PRINTF2("%08x[ECX]", displacement); 104135c4bbdfSmrg return M.x86.R_ECX + displacement; 104235c4bbdfSmrg case 2: 104335c4bbdfSmrg DECODE_PRINTF2("%08x[EDX]", displacement); 104435c4bbdfSmrg M.x86.mode |= SYSMODE_SEG_DS_SS; 104535c4bbdfSmrg return M.x86.R_EDX + displacement; 104635c4bbdfSmrg case 3: 104735c4bbdfSmrg DECODE_PRINTF2("%08x[EBX]", displacement); 104835c4bbdfSmrg return M.x86.R_EBX + displacement; 104935c4bbdfSmrg case 4: 105035c4bbdfSmrg sib = fetch_byte_imm(); 105135c4bbdfSmrg displacement = (u32) fetch_long_imm(); 105235c4bbdfSmrg DECODE_PRINTF2("%08x", displacement); 105335c4bbdfSmrg return decode_sib_address(sib, 2) + displacement; 105435c4bbdfSmrg break; 105535c4bbdfSmrg case 5: 105635c4bbdfSmrg DECODE_PRINTF2("%08x[EBP]", displacement); 105735c4bbdfSmrg return M.x86.R_EBP + displacement; 105835c4bbdfSmrg case 6: 105935c4bbdfSmrg DECODE_PRINTF2("%08x[ESI]", displacement); 106035c4bbdfSmrg return M.x86.R_ESI + displacement; 106135c4bbdfSmrg case 7: 106235c4bbdfSmrg DECODE_PRINTF2("%08x[EDI]", displacement); 106335c4bbdfSmrg return M.x86.R_EDI + displacement; 106435c4bbdfSmrg } 106535c4bbdfSmrg HALT_SYS(); 106635c4bbdfSmrg } 106735c4bbdfSmrg else { 106805b261ecSmrg /* 16-bit addressing */ 106935c4bbdfSmrg switch (rm) { 107035c4bbdfSmrg case 0: 107105b261ecSmrg DECODE_PRINTF2("%04x[BX+SI]", displacement); 107205b261ecSmrg return (M.x86.R_BX + M.x86.R_SI + displacement) & 0xffff; 107335c4bbdfSmrg case 1: 107405b261ecSmrg DECODE_PRINTF2("%04x[BX+DI]", displacement); 107505b261ecSmrg return (M.x86.R_BX + M.x86.R_DI + displacement) & 0xffff; 107635c4bbdfSmrg case 2: 107735c4bbdfSmrg DECODE_PRINTF2("%04x[BP+SI]", displacement); 107835c4bbdfSmrg M.x86.mode |= SYSMODE_SEG_DS_SS; 107905b261ecSmrg return (M.x86.R_BP + M.x86.R_SI + displacement) & 0xffff; 108035c4bbdfSmrg case 3: 108135c4bbdfSmrg DECODE_PRINTF2("%04x[BP+DI]", displacement); 108235c4bbdfSmrg M.x86.mode |= SYSMODE_SEG_DS_SS; 108305b261ecSmrg return (M.x86.R_BP + M.x86.R_DI + displacement) & 0xffff; 108435c4bbdfSmrg case 4: 108505b261ecSmrg DECODE_PRINTF2("%04x[SI]", displacement); 108605b261ecSmrg return (M.x86.R_SI + displacement) & 0xffff; 108735c4bbdfSmrg case 5: 108805b261ecSmrg DECODE_PRINTF2("%04x[DI]", displacement); 108905b261ecSmrg return (M.x86.R_DI + displacement) & 0xffff; 109035c4bbdfSmrg case 6: 109135c4bbdfSmrg DECODE_PRINTF2("%04x[BP]", displacement); 109235c4bbdfSmrg M.x86.mode |= SYSMODE_SEG_DS_SS; 109305b261ecSmrg return (M.x86.R_BP + displacement) & 0xffff; 109435c4bbdfSmrg case 7: 109505b261ecSmrg DECODE_PRINTF2("%04x[BX]", displacement); 109605b261ecSmrg return (M.x86.R_BX + displacement) & 0xffff; 109735c4bbdfSmrg } 109835c4bbdfSmrg HALT_SYS(); 109905b261ecSmrg } 110005b261ecSmrg return 0; 110105b261ecSmrg /*NOTREACHED */ 110205b261ecSmrg} 1103