1ece92f85SJason Jin /**************************************************************************** 2ece92f85SJason Jin * 3ece92f85SJason Jin * Realmode X86 Emulator Library 4ece92f85SJason Jin * 5ece92f85SJason Jin * Copyright (C) 1991-2004 SciTech Software, Inc. 6ece92f85SJason Jin * Copyright (C) David Mosberger-Tang 7ece92f85SJason Jin * Copyright (C) 1999 Egbert Eich 8ece92f85SJason Jin * 9ece92f85SJason Jin * ======================================================================== 10ece92f85SJason Jin * 11ece92f85SJason Jin * Permission to use, copy, modify, distribute, and sell this software and 12ece92f85SJason Jin * its documentation for any purpose is hereby granted without fee, 13ece92f85SJason Jin * provided that the above copyright notice appear in all copies and that 14ece92f85SJason Jin * both that copyright notice and this permission notice appear in 15ece92f85SJason Jin * supporting documentation, and that the name of the authors not be used 16ece92f85SJason Jin * in advertising or publicity pertaining to distribution of the software 17ece92f85SJason Jin * without specific, written prior permission. The authors makes no 18ece92f85SJason Jin * representations about the suitability of this software for any purpose. 19ece92f85SJason Jin * It is provided "as is" without express or implied warranty. 20ece92f85SJason Jin * 21ece92f85SJason Jin * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 22ece92f85SJason Jin * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 23ece92f85SJason Jin * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 24ece92f85SJason Jin * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF 25ece92f85SJason Jin * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 26ece92f85SJason Jin * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 27ece92f85SJason Jin * PERFORMANCE OF THIS SOFTWARE. 28ece92f85SJason Jin * 29ece92f85SJason Jin * ======================================================================== 30ece92f85SJason Jin * 31ece92f85SJason Jin * Language: ANSI C 32ece92f85SJason Jin * Environment: Any 33ece92f85SJason Jin * Developer: Kendall Bennett 34ece92f85SJason Jin * 35ece92f85SJason Jin * Description: This file includes subroutines which are related to 36ece92f85SJason Jin * instruction decoding and accessess of immediate data via IP. etc. 37ece92f85SJason Jin * 38ece92f85SJason Jin ****************************************************************************/ 39*78cff50eSMichal Simek #include <common.h> 40ece92f85SJason Jin 41ce981dc8SJason Jin #if defined(CONFIG_BIOSEMU) 42ce981dc8SJason Jin 435b4de930SMichal Simek #include "x86emu/x86emui.h" 445b4de930SMichal Simek 45ece92f85SJason Jin /*----------------------------- Implementation ----------------------------*/ 46ece92f85SJason Jin 47ece92f85SJason Jin /**************************************************************************** 48ece92f85SJason Jin REMARKS: 49ece92f85SJason Jin Handles any pending asychronous interrupts. 50ece92f85SJason Jin ****************************************************************************/ 51ece92f85SJason Jin static void x86emu_intr_handle(void) 52ece92f85SJason Jin { 53ece92f85SJason Jin u8 intno; 54ece92f85SJason Jin 55ece92f85SJason Jin if (M.x86.intr & INTR_SYNCH) { 56ece92f85SJason Jin intno = M.x86.intno; 57ece92f85SJason Jin if (_X86EMU_intrTab[intno]) { 58ece92f85SJason Jin (*_X86EMU_intrTab[intno])(intno); 59ece92f85SJason Jin } else { 60ece92f85SJason Jin push_word((u16)M.x86.R_FLG); 61ece92f85SJason Jin CLEAR_FLAG(F_IF); 62ece92f85SJason Jin CLEAR_FLAG(F_TF); 63ece92f85SJason Jin push_word(M.x86.R_CS); 64ece92f85SJason Jin M.x86.R_CS = mem_access_word(intno * 4 + 2); 65ece92f85SJason Jin push_word(M.x86.R_IP); 66ece92f85SJason Jin M.x86.R_IP = mem_access_word(intno * 4); 67ece92f85SJason Jin M.x86.intr = 0; 68ece92f85SJason Jin } 69ece92f85SJason Jin } 70ece92f85SJason Jin } 71ece92f85SJason Jin 72ece92f85SJason Jin /**************************************************************************** 73ece92f85SJason Jin PARAMETERS: 74ece92f85SJason Jin intrnum - Interrupt number to raise 75ece92f85SJason Jin 76ece92f85SJason Jin REMARKS: 77ece92f85SJason Jin Raise the specified interrupt to be handled before the execution of the 78ece92f85SJason Jin next instruction. 79ece92f85SJason Jin ****************************************************************************/ 80ece92f85SJason Jin void x86emu_intr_raise( 81ece92f85SJason Jin u8 intrnum) 82ece92f85SJason Jin { 83ece92f85SJason Jin M.x86.intno = intrnum; 84ece92f85SJason Jin M.x86.intr |= INTR_SYNCH; 85ece92f85SJason Jin } 86ece92f85SJason Jin 87ece92f85SJason Jin /**************************************************************************** 88ece92f85SJason Jin REMARKS: 89ece92f85SJason Jin Main execution loop for the emulator. We return from here when the system 90ece92f85SJason Jin halts, which is normally caused by a stack fault when we return from the 91ece92f85SJason Jin original real mode call. 92ece92f85SJason Jin ****************************************************************************/ 93ece92f85SJason Jin void X86EMU_exec(void) 94ece92f85SJason Jin { 95ece92f85SJason Jin u8 op1; 96ece92f85SJason Jin 97ece92f85SJason Jin M.x86.intr = 0; 98ece92f85SJason Jin DB(x86emu_end_instr();) 99ece92f85SJason Jin 100ece92f85SJason Jin for (;;) { 101ece92f85SJason Jin DB( if (CHECK_IP_FETCH()) 102ece92f85SJason Jin x86emu_check_ip_access();) 103ece92f85SJason Jin /* If debugging, save the IP and CS values. */ 104ece92f85SJason Jin SAVE_IP_CS(M.x86.R_CS, M.x86.R_IP); 105ece92f85SJason Jin INC_DECODED_INST_LEN(1); 106ece92f85SJason Jin if (M.x86.intr) { 107ece92f85SJason Jin if (M.x86.intr & INTR_HALTED) { 108ece92f85SJason Jin DB( if (M.x86.R_SP != 0) { 109ece92f85SJason Jin printk("halted\n"); 110ece92f85SJason Jin X86EMU_trace_regs(); 111ece92f85SJason Jin } 112ece92f85SJason Jin else { 113ece92f85SJason Jin if (M.x86.debug) 114ece92f85SJason Jin printk("Service completed successfully\n"); 115ece92f85SJason Jin }) 116ece92f85SJason Jin return; 117ece92f85SJason Jin } 118ece92f85SJason Jin if (((M.x86.intr & INTR_SYNCH) && (M.x86.intno == 0 || M.x86.intno == 2)) || 119ece92f85SJason Jin !ACCESS_FLAG(F_IF)) { 120ece92f85SJason Jin x86emu_intr_handle(); 121ece92f85SJason Jin } 122ece92f85SJason Jin } 123ece92f85SJason Jin op1 = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++)); 124ece92f85SJason Jin (*x86emu_optab[op1])(op1); 125ece92f85SJason Jin if (M.x86.debug & DEBUG_EXIT) { 126ece92f85SJason Jin M.x86.debug &= ~DEBUG_EXIT; 127ece92f85SJason Jin return; 128ece92f85SJason Jin } 129ece92f85SJason Jin } 130ece92f85SJason Jin } 131ece92f85SJason Jin 132ece92f85SJason Jin /**************************************************************************** 133ece92f85SJason Jin REMARKS: 134ece92f85SJason Jin Halts the system by setting the halted system flag. 135ece92f85SJason Jin ****************************************************************************/ 136ece92f85SJason Jin void X86EMU_halt_sys(void) 137ece92f85SJason Jin { 138ece92f85SJason Jin M.x86.intr |= INTR_HALTED; 139ece92f85SJason Jin } 140ece92f85SJason Jin 141ece92f85SJason Jin /**************************************************************************** 142ece92f85SJason Jin PARAMETERS: 143ece92f85SJason Jin mod - Mod value from decoded byte 144ece92f85SJason Jin regh - Reg h value from decoded byte 145ece92f85SJason Jin regl - Reg l value from decoded byte 146ece92f85SJason Jin 147ece92f85SJason Jin REMARKS: 148ece92f85SJason Jin Raise the specified interrupt to be handled before the execution of the 149ece92f85SJason Jin next instruction. 150ece92f85SJason Jin 151ece92f85SJason Jin NOTE: Do not inline this function, as (*sys_rdb) is already inline! 152ece92f85SJason Jin ****************************************************************************/ 153ece92f85SJason Jin void fetch_decode_modrm( 154ece92f85SJason Jin int *mod, 155ece92f85SJason Jin int *regh, 156ece92f85SJason Jin int *regl) 157ece92f85SJason Jin { 158ece92f85SJason Jin int fetched; 159ece92f85SJason Jin 160ece92f85SJason Jin DB( if (CHECK_IP_FETCH()) 161ece92f85SJason Jin x86emu_check_ip_access();) 162ece92f85SJason Jin fetched = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++)); 163ece92f85SJason Jin INC_DECODED_INST_LEN(1); 164ece92f85SJason Jin *mod = (fetched >> 6) & 0x03; 165ece92f85SJason Jin *regh = (fetched >> 3) & 0x07; 166ece92f85SJason Jin *regl = (fetched >> 0) & 0x07; 167ece92f85SJason Jin } 168ece92f85SJason Jin 169ece92f85SJason Jin /**************************************************************************** 170ece92f85SJason Jin RETURNS: 171ece92f85SJason Jin Immediate byte value read from instruction queue 172ece92f85SJason Jin 173ece92f85SJason Jin REMARKS: 174ece92f85SJason Jin This function returns the immediate byte from the instruction queue, and 175ece92f85SJason Jin moves the instruction pointer to the next value. 176ece92f85SJason Jin 177ece92f85SJason Jin NOTE: Do not inline this function, as (*sys_rdb) is already inline! 178ece92f85SJason Jin ****************************************************************************/ 179ece92f85SJason Jin u8 fetch_byte_imm(void) 180ece92f85SJason Jin { 181ece92f85SJason Jin u8 fetched; 182ece92f85SJason Jin 183ece92f85SJason Jin DB( if (CHECK_IP_FETCH()) 184ece92f85SJason Jin x86emu_check_ip_access();) 185ece92f85SJason Jin fetched = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++)); 186ece92f85SJason Jin INC_DECODED_INST_LEN(1); 187ece92f85SJason Jin return fetched; 188ece92f85SJason Jin } 189ece92f85SJason Jin 190ece92f85SJason Jin /**************************************************************************** 191ece92f85SJason Jin RETURNS: 192ece92f85SJason Jin Immediate word value read from instruction queue 193ece92f85SJason Jin 194ece92f85SJason Jin REMARKS: 195ece92f85SJason Jin This function returns the immediate byte from the instruction queue, and 196ece92f85SJason Jin moves the instruction pointer to the next value. 197ece92f85SJason Jin 198ece92f85SJason Jin NOTE: Do not inline this function, as (*sys_rdw) is already inline! 199ece92f85SJason Jin ****************************************************************************/ 200ece92f85SJason Jin u16 fetch_word_imm(void) 201ece92f85SJason Jin { 202ece92f85SJason Jin u16 fetched; 203ece92f85SJason Jin 204ece92f85SJason Jin DB( if (CHECK_IP_FETCH()) 205ece92f85SJason Jin x86emu_check_ip_access();) 206ece92f85SJason Jin fetched = (*sys_rdw)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP)); 207ece92f85SJason Jin M.x86.R_IP += 2; 208ece92f85SJason Jin INC_DECODED_INST_LEN(2); 209ece92f85SJason Jin return fetched; 210ece92f85SJason Jin } 211ece92f85SJason Jin 212ece92f85SJason Jin /**************************************************************************** 213ece92f85SJason Jin RETURNS: 214ece92f85SJason Jin Immediate lone value read from instruction queue 215ece92f85SJason Jin 216ece92f85SJason Jin REMARKS: 217ece92f85SJason Jin This function returns the immediate byte from the instruction queue, and 218ece92f85SJason Jin moves the instruction pointer to the next value. 219ece92f85SJason Jin 220ece92f85SJason Jin NOTE: Do not inline this function, as (*sys_rdw) is already inline! 221ece92f85SJason Jin ****************************************************************************/ 222ece92f85SJason Jin u32 fetch_long_imm(void) 223ece92f85SJason Jin { 224ece92f85SJason Jin u32 fetched; 225ece92f85SJason Jin 226ece92f85SJason Jin DB( if (CHECK_IP_FETCH()) 227ece92f85SJason Jin x86emu_check_ip_access();) 228ece92f85SJason Jin fetched = (*sys_rdl)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP)); 229ece92f85SJason Jin M.x86.R_IP += 4; 230ece92f85SJason Jin INC_DECODED_INST_LEN(4); 231ece92f85SJason Jin return fetched; 232ece92f85SJason Jin } 233ece92f85SJason Jin 234ece92f85SJason Jin /**************************************************************************** 235ece92f85SJason Jin RETURNS: 236ece92f85SJason Jin Value of the default data segment 237ece92f85SJason Jin 238ece92f85SJason Jin REMARKS: 239ece92f85SJason Jin Inline function that returns the default data segment for the current 240ece92f85SJason Jin instruction. 241ece92f85SJason Jin 242ece92f85SJason Jin On the x86 processor, the default segment is not always DS if there is 243ece92f85SJason Jin no segment override. Address modes such as -3[BP] or 10[BP+SI] all refer to 244ece92f85SJason Jin addresses relative to SS (ie: on the stack). So, at the minimum, all 245ece92f85SJason Jin decodings of addressing modes would have to set/clear a bit describing 246ece92f85SJason Jin whether the access is relative to DS or SS. That is the function of the 247ece92f85SJason Jin cpu-state-varible M.x86.mode. There are several potential states: 248ece92f85SJason Jin 249ece92f85SJason Jin repe prefix seen (handled elsewhere) 250ece92f85SJason Jin repne prefix seen (ditto) 251ece92f85SJason Jin 252ece92f85SJason Jin cs segment override 253ece92f85SJason Jin ds segment override 254ece92f85SJason Jin es segment override 255ece92f85SJason Jin fs segment override 256ece92f85SJason Jin gs segment override 257ece92f85SJason Jin ss segment override 258ece92f85SJason Jin 259ece92f85SJason Jin ds/ss select (in absense of override) 260ece92f85SJason Jin 261ece92f85SJason Jin Each of the above 7 items are handled with a bit in the mode field. 262ece92f85SJason Jin ****************************************************************************/ 263ece92f85SJason Jin _INLINE u32 get_data_segment(void) 264ece92f85SJason Jin { 265ece92f85SJason Jin #define GET_SEGMENT(segment) 266ece92f85SJason Jin switch (M.x86.mode & SYSMODE_SEGMASK) { 267ece92f85SJason Jin case 0: /* default case: use ds register */ 268ece92f85SJason Jin case SYSMODE_SEGOVR_DS: 269ece92f85SJason Jin case SYSMODE_SEGOVR_DS | SYSMODE_SEG_DS_SS: 270ece92f85SJason Jin return M.x86.R_DS; 271ece92f85SJason Jin case SYSMODE_SEG_DS_SS: /* non-overridden, use ss register */ 272ece92f85SJason Jin return M.x86.R_SS; 273ece92f85SJason Jin case SYSMODE_SEGOVR_CS: 274ece92f85SJason Jin case SYSMODE_SEGOVR_CS | SYSMODE_SEG_DS_SS: 275ece92f85SJason Jin return M.x86.R_CS; 276ece92f85SJason Jin case SYSMODE_SEGOVR_ES: 277ece92f85SJason Jin case SYSMODE_SEGOVR_ES | SYSMODE_SEG_DS_SS: 278ece92f85SJason Jin return M.x86.R_ES; 279ece92f85SJason Jin case SYSMODE_SEGOVR_FS: 280ece92f85SJason Jin case SYSMODE_SEGOVR_FS | SYSMODE_SEG_DS_SS: 281ece92f85SJason Jin return M.x86.R_FS; 282ece92f85SJason Jin case SYSMODE_SEGOVR_GS: 283ece92f85SJason Jin case SYSMODE_SEGOVR_GS | SYSMODE_SEG_DS_SS: 284ece92f85SJason Jin return M.x86.R_GS; 285ece92f85SJason Jin case SYSMODE_SEGOVR_SS: 286ece92f85SJason Jin case SYSMODE_SEGOVR_SS | SYSMODE_SEG_DS_SS: 287ece92f85SJason Jin return M.x86.R_SS; 288ece92f85SJason Jin default: 289ece92f85SJason Jin #ifdef DEBUG 290ece92f85SJason Jin printk("error: should not happen: multiple overrides.\n"); 291ece92f85SJason Jin #endif 292ece92f85SJason Jin HALT_SYS(); 293ece92f85SJason Jin return 0; 294ece92f85SJason Jin } 295ece92f85SJason Jin } 296ece92f85SJason Jin 297ece92f85SJason Jin /**************************************************************************** 298ece92f85SJason Jin PARAMETERS: 299ece92f85SJason Jin offset - Offset to load data from 300ece92f85SJason Jin 301ece92f85SJason Jin RETURNS: 302ece92f85SJason Jin Byte value read from the absolute memory location. 303ece92f85SJason Jin 304ece92f85SJason Jin NOTE: Do not inline this function as (*sys_rdX) is already inline! 305ece92f85SJason Jin ****************************************************************************/ 306ece92f85SJason Jin u8 fetch_data_byte( 307ece92f85SJason Jin uint offset) 308ece92f85SJason Jin { 309ece92f85SJason Jin #ifdef DEBUG 310ece92f85SJason Jin if (CHECK_DATA_ACCESS()) 311ece92f85SJason Jin x86emu_check_data_access((u16)get_data_segment(), offset); 312ece92f85SJason Jin #endif 313ece92f85SJason Jin return (*sys_rdb)((get_data_segment() << 4) + offset); 314ece92f85SJason Jin } 315ece92f85SJason Jin 316ece92f85SJason Jin /**************************************************************************** 317ece92f85SJason Jin PARAMETERS: 318ece92f85SJason Jin offset - Offset to load data from 319ece92f85SJason Jin 320ece92f85SJason Jin RETURNS: 321ece92f85SJason Jin Word value read from the absolute memory location. 322ece92f85SJason Jin 323ece92f85SJason Jin NOTE: Do not inline this function as (*sys_rdX) is already inline! 324ece92f85SJason Jin ****************************************************************************/ 325ece92f85SJason Jin u16 fetch_data_word( 326ece92f85SJason Jin uint offset) 327ece92f85SJason Jin { 328ece92f85SJason Jin #ifdef DEBUG 329ece92f85SJason Jin if (CHECK_DATA_ACCESS()) 330ece92f85SJason Jin x86emu_check_data_access((u16)get_data_segment(), offset); 331ece92f85SJason Jin #endif 332ece92f85SJason Jin return (*sys_rdw)((get_data_segment() << 4) + offset); 333ece92f85SJason Jin } 334ece92f85SJason Jin 335ece92f85SJason Jin /**************************************************************************** 336ece92f85SJason Jin PARAMETERS: 337ece92f85SJason Jin offset - Offset to load data from 338ece92f85SJason Jin 339ece92f85SJason Jin RETURNS: 340ece92f85SJason Jin Long value read from the absolute memory location. 341ece92f85SJason Jin 342ece92f85SJason Jin NOTE: Do not inline this function as (*sys_rdX) is already inline! 343ece92f85SJason Jin ****************************************************************************/ 344ece92f85SJason Jin u32 fetch_data_long( 345ece92f85SJason Jin uint offset) 346ece92f85SJason Jin { 347ece92f85SJason Jin #ifdef DEBUG 348ece92f85SJason Jin if (CHECK_DATA_ACCESS()) 349ece92f85SJason Jin x86emu_check_data_access((u16)get_data_segment(), offset); 350ece92f85SJason Jin #endif 351ece92f85SJason Jin return (*sys_rdl)((get_data_segment() << 4) + offset); 352ece92f85SJason Jin } 353ece92f85SJason Jin 354ece92f85SJason Jin /**************************************************************************** 355ece92f85SJason Jin PARAMETERS: 356ece92f85SJason Jin segment - Segment to load data from 357ece92f85SJason Jin offset - Offset to load data from 358ece92f85SJason Jin 359ece92f85SJason Jin RETURNS: 360ece92f85SJason Jin Byte value read from the absolute memory location. 361ece92f85SJason Jin 362ece92f85SJason Jin NOTE: Do not inline this function as (*sys_rdX) is already inline! 363ece92f85SJason Jin ****************************************************************************/ 364ece92f85SJason Jin u8 fetch_data_byte_abs( 365ece92f85SJason Jin uint segment, 366ece92f85SJason Jin uint offset) 367ece92f85SJason Jin { 368ece92f85SJason Jin #ifdef DEBUG 369ece92f85SJason Jin if (CHECK_DATA_ACCESS()) 370ece92f85SJason Jin x86emu_check_data_access(segment, offset); 371ece92f85SJason Jin #endif 372ece92f85SJason Jin return (*sys_rdb)(((u32)segment << 4) + offset); 373ece92f85SJason Jin } 374ece92f85SJason Jin 375ece92f85SJason Jin /**************************************************************************** 376ece92f85SJason Jin PARAMETERS: 377ece92f85SJason Jin segment - Segment to load data from 378ece92f85SJason Jin offset - Offset to load data from 379ece92f85SJason Jin 380ece92f85SJason Jin RETURNS: 381ece92f85SJason Jin Word value read from the absolute memory location. 382ece92f85SJason Jin 383ece92f85SJason Jin NOTE: Do not inline this function as (*sys_rdX) is already inline! 384ece92f85SJason Jin ****************************************************************************/ 385ece92f85SJason Jin u16 fetch_data_word_abs( 386ece92f85SJason Jin uint segment, 387ece92f85SJason Jin uint offset) 388ece92f85SJason Jin { 389ece92f85SJason Jin #ifdef DEBUG 390ece92f85SJason Jin if (CHECK_DATA_ACCESS()) 391ece92f85SJason Jin x86emu_check_data_access(segment, offset); 392ece92f85SJason Jin #endif 393ece92f85SJason Jin return (*sys_rdw)(((u32)segment << 4) + offset); 394ece92f85SJason Jin } 395ece92f85SJason Jin 396ece92f85SJason Jin /**************************************************************************** 397ece92f85SJason Jin PARAMETERS: 398ece92f85SJason Jin segment - Segment to load data from 399ece92f85SJason Jin offset - Offset to load data from 400ece92f85SJason Jin 401ece92f85SJason Jin RETURNS: 402ece92f85SJason Jin Long value read from the absolute memory location. 403ece92f85SJason Jin 404ece92f85SJason Jin NOTE: Do not inline this function as (*sys_rdX) is already inline! 405ece92f85SJason Jin ****************************************************************************/ 406ece92f85SJason Jin u32 fetch_data_long_abs( 407ece92f85SJason Jin uint segment, 408ece92f85SJason Jin uint offset) 409ece92f85SJason Jin { 410ece92f85SJason Jin #ifdef DEBUG 411ece92f85SJason Jin if (CHECK_DATA_ACCESS()) 412ece92f85SJason Jin x86emu_check_data_access(segment, offset); 413ece92f85SJason Jin #endif 414ece92f85SJason Jin return (*sys_rdl)(((u32)segment << 4) + offset); 415ece92f85SJason Jin } 416ece92f85SJason Jin 417ece92f85SJason Jin /**************************************************************************** 418ece92f85SJason Jin PARAMETERS: 419ece92f85SJason Jin offset - Offset to store data at 420ece92f85SJason Jin val - Value to store 421ece92f85SJason Jin 422ece92f85SJason Jin REMARKS: 423ece92f85SJason Jin Writes a word value to an segmented memory location. The segment used is 424ece92f85SJason Jin the current 'default' segment, which may have been overridden. 425ece92f85SJason Jin 426ece92f85SJason Jin NOTE: Do not inline this function as (*sys_wrX) is already inline! 427ece92f85SJason Jin ****************************************************************************/ 428ece92f85SJason Jin void store_data_byte( 429ece92f85SJason Jin uint offset, 430ece92f85SJason Jin u8 val) 431ece92f85SJason Jin { 432ece92f85SJason Jin #ifdef DEBUG 433ece92f85SJason Jin if (CHECK_DATA_ACCESS()) 434ece92f85SJason Jin x86emu_check_data_access((u16)get_data_segment(), offset); 435ece92f85SJason Jin #endif 436ece92f85SJason Jin (*sys_wrb)((get_data_segment() << 4) + offset, val); 437ece92f85SJason Jin } 438ece92f85SJason Jin 439ece92f85SJason Jin /**************************************************************************** 440ece92f85SJason Jin PARAMETERS: 441ece92f85SJason Jin offset - Offset to store data at 442ece92f85SJason Jin val - Value to store 443ece92f85SJason Jin 444ece92f85SJason Jin REMARKS: 445ece92f85SJason Jin Writes a word value to an segmented memory location. The segment used is 446ece92f85SJason Jin the current 'default' segment, which may have been overridden. 447ece92f85SJason Jin 448ece92f85SJason Jin NOTE: Do not inline this function as (*sys_wrX) is already inline! 449ece92f85SJason Jin ****************************************************************************/ 450ece92f85SJason Jin void store_data_word( 451ece92f85SJason Jin uint offset, 452ece92f85SJason Jin u16 val) 453ece92f85SJason Jin { 454ece92f85SJason Jin #ifdef DEBUG 455ece92f85SJason Jin if (CHECK_DATA_ACCESS()) 456ece92f85SJason Jin x86emu_check_data_access((u16)get_data_segment(), offset); 457ece92f85SJason Jin #endif 458ece92f85SJason Jin (*sys_wrw)((get_data_segment() << 4) + offset, val); 459ece92f85SJason Jin } 460ece92f85SJason Jin 461ece92f85SJason Jin /**************************************************************************** 462ece92f85SJason Jin PARAMETERS: 463ece92f85SJason Jin offset - Offset to store data at 464ece92f85SJason Jin val - Value to store 465ece92f85SJason Jin 466ece92f85SJason Jin REMARKS: 467ece92f85SJason Jin Writes a long value to an segmented memory location. The segment used is 468ece92f85SJason Jin the current 'default' segment, which may have been overridden. 469ece92f85SJason Jin 470ece92f85SJason Jin NOTE: Do not inline this function as (*sys_wrX) is already inline! 471ece92f85SJason Jin ****************************************************************************/ 472ece92f85SJason Jin void store_data_long( 473ece92f85SJason Jin uint offset, 474ece92f85SJason Jin u32 val) 475ece92f85SJason Jin { 476ece92f85SJason Jin #ifdef DEBUG 477ece92f85SJason Jin if (CHECK_DATA_ACCESS()) 478ece92f85SJason Jin x86emu_check_data_access((u16)get_data_segment(), offset); 479ece92f85SJason Jin #endif 480ece92f85SJason Jin (*sys_wrl)((get_data_segment() << 4) + offset, val); 481ece92f85SJason Jin } 482ece92f85SJason Jin 483ece92f85SJason Jin /**************************************************************************** 484ece92f85SJason Jin PARAMETERS: 485ece92f85SJason Jin segment - Segment to store data at 486ece92f85SJason Jin offset - Offset to store data at 487ece92f85SJason Jin val - Value to store 488ece92f85SJason Jin 489ece92f85SJason Jin REMARKS: 490ece92f85SJason Jin Writes a byte value to an absolute memory location. 491ece92f85SJason Jin 492ece92f85SJason Jin NOTE: Do not inline this function as (*sys_wrX) is already inline! 493ece92f85SJason Jin ****************************************************************************/ 494ece92f85SJason Jin void store_data_byte_abs( 495ece92f85SJason Jin uint segment, 496ece92f85SJason Jin uint offset, 497ece92f85SJason Jin u8 val) 498ece92f85SJason Jin { 499ece92f85SJason Jin #ifdef DEBUG 500ece92f85SJason Jin if (CHECK_DATA_ACCESS()) 501ece92f85SJason Jin x86emu_check_data_access(segment, offset); 502ece92f85SJason Jin #endif 503ece92f85SJason Jin (*sys_wrb)(((u32)segment << 4) + offset, val); 504ece92f85SJason Jin } 505ece92f85SJason Jin 506ece92f85SJason Jin /**************************************************************************** 507ece92f85SJason Jin PARAMETERS: 508ece92f85SJason Jin segment - Segment to store data at 509ece92f85SJason Jin offset - Offset to store data at 510ece92f85SJason Jin val - Value to store 511ece92f85SJason Jin 512ece92f85SJason Jin REMARKS: 513ece92f85SJason Jin Writes a word value to an absolute memory location. 514ece92f85SJason Jin 515ece92f85SJason Jin NOTE: Do not inline this function as (*sys_wrX) is already inline! 516ece92f85SJason Jin ****************************************************************************/ 517ece92f85SJason Jin void store_data_word_abs( 518ece92f85SJason Jin uint segment, 519ece92f85SJason Jin uint offset, 520ece92f85SJason Jin u16 val) 521ece92f85SJason Jin { 522ece92f85SJason Jin #ifdef DEBUG 523ece92f85SJason Jin if (CHECK_DATA_ACCESS()) 524ece92f85SJason Jin x86emu_check_data_access(segment, offset); 525ece92f85SJason Jin #endif 526ece92f85SJason Jin (*sys_wrw)(((u32)segment << 4) + offset, val); 527ece92f85SJason Jin } 528ece92f85SJason Jin 529ece92f85SJason Jin /**************************************************************************** 530ece92f85SJason Jin PARAMETERS: 531ece92f85SJason Jin segment - Segment to store data at 532ece92f85SJason Jin offset - Offset to store data at 533ece92f85SJason Jin val - Value to store 534ece92f85SJason Jin 535ece92f85SJason Jin REMARKS: 536ece92f85SJason Jin Writes a long value to an absolute memory location. 537ece92f85SJason Jin 538ece92f85SJason Jin NOTE: Do not inline this function as (*sys_wrX) is already inline! 539ece92f85SJason Jin ****************************************************************************/ 540ece92f85SJason Jin void store_data_long_abs( 541ece92f85SJason Jin uint segment, 542ece92f85SJason Jin uint offset, 543ece92f85SJason Jin u32 val) 544ece92f85SJason Jin { 545ece92f85SJason Jin #ifdef DEBUG 546ece92f85SJason Jin if (CHECK_DATA_ACCESS()) 547ece92f85SJason Jin x86emu_check_data_access(segment, offset); 548ece92f85SJason Jin #endif 549ece92f85SJason Jin (*sys_wrl)(((u32)segment << 4) + offset, val); 550ece92f85SJason Jin } 551ece92f85SJason Jin 552ece92f85SJason Jin /**************************************************************************** 553ece92f85SJason Jin PARAMETERS: 554ece92f85SJason Jin reg - Register to decode 555ece92f85SJason Jin 556ece92f85SJason Jin RETURNS: 557ece92f85SJason Jin Pointer to the appropriate register 558ece92f85SJason Jin 559ece92f85SJason Jin REMARKS: 560ece92f85SJason Jin Return a pointer to the register given by the R/RM field of the 561ece92f85SJason Jin modrm byte, for byte operands. Also enables the decoding of instructions. 562ece92f85SJason Jin ****************************************************************************/ 563ece92f85SJason Jin u8* decode_rm_byte_register( 564ece92f85SJason Jin int reg) 565ece92f85SJason Jin { 566ece92f85SJason Jin switch (reg) { 567ece92f85SJason Jin case 0: 568ece92f85SJason Jin DECODE_PRINTF("AL"); 569ece92f85SJason Jin return &M.x86.R_AL; 570ece92f85SJason Jin case 1: 571ece92f85SJason Jin DECODE_PRINTF("CL"); 572ece92f85SJason Jin return &M.x86.R_CL; 573ece92f85SJason Jin case 2: 574ece92f85SJason Jin DECODE_PRINTF("DL"); 575ece92f85SJason Jin return &M.x86.R_DL; 576ece92f85SJason Jin case 3: 577ece92f85SJason Jin DECODE_PRINTF("BL"); 578ece92f85SJason Jin return &M.x86.R_BL; 579ece92f85SJason Jin case 4: 580ece92f85SJason Jin DECODE_PRINTF("AH"); 581ece92f85SJason Jin return &M.x86.R_AH; 582ece92f85SJason Jin case 5: 583ece92f85SJason Jin DECODE_PRINTF("CH"); 584ece92f85SJason Jin return &M.x86.R_CH; 585ece92f85SJason Jin case 6: 586ece92f85SJason Jin DECODE_PRINTF("DH"); 587ece92f85SJason Jin return &M.x86.R_DH; 588ece92f85SJason Jin case 7: 589ece92f85SJason Jin DECODE_PRINTF("BH"); 590ece92f85SJason Jin return &M.x86.R_BH; 591ece92f85SJason Jin } 592ece92f85SJason Jin HALT_SYS(); 593ece92f85SJason Jin return NULL; /* NOT REACHED OR REACHED ON ERROR */ 594ece92f85SJason Jin } 595ece92f85SJason Jin 596ece92f85SJason Jin /**************************************************************************** 597ece92f85SJason Jin PARAMETERS: 598ece92f85SJason Jin reg - Register to decode 599ece92f85SJason Jin 600ece92f85SJason Jin RETURNS: 601ece92f85SJason Jin Pointer to the appropriate register 602ece92f85SJason Jin 603ece92f85SJason Jin REMARKS: 604ece92f85SJason Jin Return a pointer to the register given by the R/RM field of the 605ece92f85SJason Jin modrm byte, for word operands. Also enables the decoding of instructions. 606ece92f85SJason Jin ****************************************************************************/ 607ece92f85SJason Jin u16* decode_rm_word_register( 608ece92f85SJason Jin int reg) 609ece92f85SJason Jin { 610ece92f85SJason Jin switch (reg) { 611ece92f85SJason Jin case 0: 612ece92f85SJason Jin DECODE_PRINTF("AX"); 613ece92f85SJason Jin return &M.x86.R_AX; 614ece92f85SJason Jin case 1: 615ece92f85SJason Jin DECODE_PRINTF("CX"); 616ece92f85SJason Jin return &M.x86.R_CX; 617ece92f85SJason Jin case 2: 618ece92f85SJason Jin DECODE_PRINTF("DX"); 619ece92f85SJason Jin return &M.x86.R_DX; 620ece92f85SJason Jin case 3: 621ece92f85SJason Jin DECODE_PRINTF("BX"); 622ece92f85SJason Jin return &M.x86.R_BX; 623ece92f85SJason Jin case 4: 624ece92f85SJason Jin DECODE_PRINTF("SP"); 625ece92f85SJason Jin return &M.x86.R_SP; 626ece92f85SJason Jin case 5: 627ece92f85SJason Jin DECODE_PRINTF("BP"); 628ece92f85SJason Jin return &M.x86.R_BP; 629ece92f85SJason Jin case 6: 630ece92f85SJason Jin DECODE_PRINTF("SI"); 631ece92f85SJason Jin return &M.x86.R_SI; 632ece92f85SJason Jin case 7: 633ece92f85SJason Jin DECODE_PRINTF("DI"); 634ece92f85SJason Jin return &M.x86.R_DI; 635ece92f85SJason Jin } 636ece92f85SJason Jin HALT_SYS(); 637ece92f85SJason Jin return NULL; /* NOTREACHED OR REACHED ON ERROR */ 638ece92f85SJason Jin } 639ece92f85SJason Jin 640ece92f85SJason Jin /**************************************************************************** 641ece92f85SJason Jin PARAMETERS: 642ece92f85SJason Jin reg - Register to decode 643ece92f85SJason Jin 644ece92f85SJason Jin RETURNS: 645ece92f85SJason Jin Pointer to the appropriate register 646ece92f85SJason Jin 647ece92f85SJason Jin REMARKS: 648ece92f85SJason Jin Return a pointer to the register given by the R/RM field of the 649ece92f85SJason Jin modrm byte, for dword operands. Also enables the decoding of instructions. 650ece92f85SJason Jin ****************************************************************************/ 651ece92f85SJason Jin u32* decode_rm_long_register( 652ece92f85SJason Jin int reg) 653ece92f85SJason Jin { 654ece92f85SJason Jin switch (reg) { 655ece92f85SJason Jin case 0: 656ece92f85SJason Jin DECODE_PRINTF("EAX"); 657ece92f85SJason Jin return &M.x86.R_EAX; 658ece92f85SJason Jin case 1: 659ece92f85SJason Jin DECODE_PRINTF("ECX"); 660ece92f85SJason Jin return &M.x86.R_ECX; 661ece92f85SJason Jin case 2: 662ece92f85SJason Jin DECODE_PRINTF("EDX"); 663ece92f85SJason Jin return &M.x86.R_EDX; 664ece92f85SJason Jin case 3: 665ece92f85SJason Jin DECODE_PRINTF("EBX"); 666ece92f85SJason Jin return &M.x86.R_EBX; 667ece92f85SJason Jin case 4: 668ece92f85SJason Jin DECODE_PRINTF("ESP"); 669ece92f85SJason Jin return &M.x86.R_ESP; 670ece92f85SJason Jin case 5: 671ece92f85SJason Jin DECODE_PRINTF("EBP"); 672ece92f85SJason Jin return &M.x86.R_EBP; 673ece92f85SJason Jin case 6: 674ece92f85SJason Jin DECODE_PRINTF("ESI"); 675ece92f85SJason Jin return &M.x86.R_ESI; 676ece92f85SJason Jin case 7: 677ece92f85SJason Jin DECODE_PRINTF("EDI"); 678ece92f85SJason Jin return &M.x86.R_EDI; 679ece92f85SJason Jin } 680ece92f85SJason Jin HALT_SYS(); 681ece92f85SJason Jin return NULL; /* NOTREACHED OR REACHED ON ERROR */ 682ece92f85SJason Jin } 683ece92f85SJason Jin 684ece92f85SJason Jin /**************************************************************************** 685ece92f85SJason Jin PARAMETERS: 686ece92f85SJason Jin reg - Register to decode 687ece92f85SJason Jin 688ece92f85SJason Jin RETURNS: 689ece92f85SJason Jin Pointer to the appropriate register 690ece92f85SJason Jin 691ece92f85SJason Jin REMARKS: 692ece92f85SJason Jin Return a pointer to the register given by the R/RM field of the 693ece92f85SJason Jin modrm byte, for word operands, modified from above for the weirdo 694ece92f85SJason Jin special case of segreg operands. Also enables the decoding of instructions. 695ece92f85SJason Jin ****************************************************************************/ 696ece92f85SJason Jin u16* decode_rm_seg_register( 697ece92f85SJason Jin int reg) 698ece92f85SJason Jin { 699ece92f85SJason Jin switch (reg) { 700ece92f85SJason Jin case 0: 701ece92f85SJason Jin DECODE_PRINTF("ES"); 702ece92f85SJason Jin return &M.x86.R_ES; 703ece92f85SJason Jin case 1: 704ece92f85SJason Jin DECODE_PRINTF("CS"); 705ece92f85SJason Jin return &M.x86.R_CS; 706ece92f85SJason Jin case 2: 707ece92f85SJason Jin DECODE_PRINTF("SS"); 708ece92f85SJason Jin return &M.x86.R_SS; 709ece92f85SJason Jin case 3: 710ece92f85SJason Jin DECODE_PRINTF("DS"); 711ece92f85SJason Jin return &M.x86.R_DS; 712ece92f85SJason Jin case 4: 713ece92f85SJason Jin DECODE_PRINTF("FS"); 714ece92f85SJason Jin return &M.x86.R_FS; 715ece92f85SJason Jin case 5: 716ece92f85SJason Jin DECODE_PRINTF("GS"); 717ece92f85SJason Jin return &M.x86.R_GS; 718ece92f85SJason Jin case 6: 719ece92f85SJason Jin case 7: 720ece92f85SJason Jin DECODE_PRINTF("ILLEGAL SEGREG"); 721ece92f85SJason Jin break; 722ece92f85SJason Jin } 723ece92f85SJason Jin HALT_SYS(); 724ece92f85SJason Jin return NULL; /* NOT REACHED OR REACHED ON ERROR */ 725ece92f85SJason Jin } 726ece92f85SJason Jin 727ece92f85SJason Jin /**************************************************************************** 728ece92f85SJason Jin PARAMETERS: 729ece92f85SJason Jin scale - scale value of SIB byte 730ece92f85SJason Jin index - index value of SIB byte 731ece92f85SJason Jin 732ece92f85SJason Jin RETURNS: 733ece92f85SJason Jin Value of scale * index 734ece92f85SJason Jin 735ece92f85SJason Jin REMARKS: 736ece92f85SJason Jin Decodes scale/index of SIB byte and returns relevant offset part of 737ece92f85SJason Jin effective address. 738ece92f85SJason Jin ****************************************************************************/ 739ece92f85SJason Jin unsigned decode_sib_si( 740ece92f85SJason Jin int scale, 741ece92f85SJason Jin int index) 742ece92f85SJason Jin { 743ece92f85SJason Jin scale = 1 << scale; 744ece92f85SJason Jin if (scale > 1) { 745ece92f85SJason Jin DECODE_PRINTF2("[%d*", scale); 746ece92f85SJason Jin } else { 747ece92f85SJason Jin DECODE_PRINTF("["); 748ece92f85SJason Jin } 749ece92f85SJason Jin switch (index) { 750ece92f85SJason Jin case 0: 751ece92f85SJason Jin DECODE_PRINTF("EAX]"); 752ece92f85SJason Jin return M.x86.R_EAX * index; 753ece92f85SJason Jin case 1: 754ece92f85SJason Jin DECODE_PRINTF("ECX]"); 755ece92f85SJason Jin return M.x86.R_ECX * index; 756ece92f85SJason Jin case 2: 757ece92f85SJason Jin DECODE_PRINTF("EDX]"); 758ece92f85SJason Jin return M.x86.R_EDX * index; 759ece92f85SJason Jin case 3: 760ece92f85SJason Jin DECODE_PRINTF("EBX]"); 761ece92f85SJason Jin return M.x86.R_EBX * index; 762ece92f85SJason Jin case 4: 763ece92f85SJason Jin DECODE_PRINTF("0]"); 764ece92f85SJason Jin return 0; 765ece92f85SJason Jin case 5: 766ece92f85SJason Jin DECODE_PRINTF("EBP]"); 767ece92f85SJason Jin return M.x86.R_EBP * index; 768ece92f85SJason Jin case 6: 769ece92f85SJason Jin DECODE_PRINTF("ESI]"); 770ece92f85SJason Jin return M.x86.R_ESI * index; 771ece92f85SJason Jin case 7: 772ece92f85SJason Jin DECODE_PRINTF("EDI]"); 773ece92f85SJason Jin return M.x86.R_EDI * index; 774ece92f85SJason Jin } 775ece92f85SJason Jin HALT_SYS(); 776ece92f85SJason Jin return 0; /* NOT REACHED OR REACHED ON ERROR */ 777ece92f85SJason Jin } 778ece92f85SJason Jin 779ece92f85SJason Jin /**************************************************************************** 780ece92f85SJason Jin PARAMETERS: 781ece92f85SJason Jin mod - MOD value of preceding ModR/M byte 782ece92f85SJason Jin 783ece92f85SJason Jin RETURNS: 784ece92f85SJason Jin Offset in memory for the address decoding 785ece92f85SJason Jin 786ece92f85SJason Jin REMARKS: 787ece92f85SJason Jin Decodes SIB addressing byte and returns calculated effective address. 788ece92f85SJason Jin ****************************************************************************/ 789ece92f85SJason Jin unsigned decode_sib_address( 790ece92f85SJason Jin int mod) 791ece92f85SJason Jin { 792ece92f85SJason Jin int sib = fetch_byte_imm(); 793ece92f85SJason Jin int ss = (sib >> 6) & 0x03; 794ece92f85SJason Jin int index = (sib >> 3) & 0x07; 795ece92f85SJason Jin int base = sib & 0x07; 796ece92f85SJason Jin int offset = 0; 797ece92f85SJason Jin int displacement; 798ece92f85SJason Jin 799ece92f85SJason Jin switch (base) { 800ece92f85SJason Jin case 0: 801ece92f85SJason Jin DECODE_PRINTF("[EAX]"); 802ece92f85SJason Jin offset = M.x86.R_EAX; 803ece92f85SJason Jin break; 804ece92f85SJason Jin case 1: 805ece92f85SJason Jin DECODE_PRINTF("[ECX]"); 806ece92f85SJason Jin offset = M.x86.R_ECX; 807ece92f85SJason Jin break; 808ece92f85SJason Jin case 2: 809ece92f85SJason Jin DECODE_PRINTF("[EDX]"); 810ece92f85SJason Jin offset = M.x86.R_EDX; 811ece92f85SJason Jin break; 812ece92f85SJason Jin case 3: 813ece92f85SJason Jin DECODE_PRINTF("[EBX]"); 814ece92f85SJason Jin offset = M.x86.R_EBX; 815ece92f85SJason Jin break; 816ece92f85SJason Jin case 4: 817ece92f85SJason Jin DECODE_PRINTF("[ESP]"); 818ece92f85SJason Jin offset = M.x86.R_ESP; 819ece92f85SJason Jin break; 820ece92f85SJason Jin case 5: 821ece92f85SJason Jin switch (mod) { 822ece92f85SJason Jin case 0: 823ece92f85SJason Jin displacement = (s32)fetch_long_imm(); 824ece92f85SJason Jin DECODE_PRINTF2("[%d]", displacement); 825ece92f85SJason Jin offset = displacement; 826ece92f85SJason Jin break; 827ece92f85SJason Jin case 1: 828ece92f85SJason Jin displacement = (s8)fetch_byte_imm(); 829ece92f85SJason Jin DECODE_PRINTF2("[%d][EBP]", displacement); 830ece92f85SJason Jin offset = M.x86.R_EBP + displacement; 831ece92f85SJason Jin break; 832ece92f85SJason Jin case 2: 833ece92f85SJason Jin displacement = (s32)fetch_long_imm(); 834ece92f85SJason Jin DECODE_PRINTF2("[%d][EBP]", displacement); 835ece92f85SJason Jin offset = M.x86.R_EBP + displacement; 836ece92f85SJason Jin break; 837ece92f85SJason Jin default: 838ece92f85SJason Jin HALT_SYS(); 839ece92f85SJason Jin } 840ece92f85SJason Jin DECODE_PRINTF("[EAX]"); 841ece92f85SJason Jin offset = M.x86.R_EAX; 842ece92f85SJason Jin break; 843ece92f85SJason Jin case 6: 844ece92f85SJason Jin DECODE_PRINTF("[ESI]"); 845ece92f85SJason Jin offset = M.x86.R_ESI; 846ece92f85SJason Jin break; 847ece92f85SJason Jin case 7: 848ece92f85SJason Jin DECODE_PRINTF("[EDI]"); 849ece92f85SJason Jin offset = M.x86.R_EDI; 850ece92f85SJason Jin break; 851ece92f85SJason Jin default: 852ece92f85SJason Jin HALT_SYS(); 853ece92f85SJason Jin } 854ece92f85SJason Jin offset += decode_sib_si(ss, index); 855ece92f85SJason Jin return offset; 856ece92f85SJason Jin 857ece92f85SJason Jin } 858ece92f85SJason Jin 859ece92f85SJason Jin /**************************************************************************** 860ece92f85SJason Jin PARAMETERS: 861ece92f85SJason Jin rm - RM value to decode 862ece92f85SJason Jin 863ece92f85SJason Jin RETURNS: 864ece92f85SJason Jin Offset in memory for the address decoding 865ece92f85SJason Jin 866ece92f85SJason Jin REMARKS: 867ece92f85SJason Jin Return the offset given by mod=00 addressing. Also enables the 868ece92f85SJason Jin decoding of instructions. 869ece92f85SJason Jin 870ece92f85SJason Jin NOTE: The code which specifies the corresponding segment (ds vs ss) 871ece92f85SJason Jin below in the case of [BP+..]. The assumption here is that at the 872ece92f85SJason Jin point that this subroutine is called, the bit corresponding to 873ece92f85SJason Jin SYSMODE_SEG_DS_SS will be zero. After every instruction 874ece92f85SJason Jin except the segment override instructions, this bit (as well 875ece92f85SJason Jin as any bits indicating segment overrides) will be clear. So 876ece92f85SJason Jin if a SS access is needed, set this bit. Otherwise, DS access 877ece92f85SJason Jin occurs (unless any of the segment override bits are set). 878ece92f85SJason Jin ****************************************************************************/ 879ece92f85SJason Jin unsigned decode_rm00_address( 880ece92f85SJason Jin int rm) 881ece92f85SJason Jin { 882ece92f85SJason Jin unsigned offset; 883ece92f85SJason Jin 884ece92f85SJason Jin if (M.x86.mode & SYSMODE_PREFIX_ADDR) { 885ece92f85SJason Jin /* 32-bit addressing */ 886ece92f85SJason Jin switch (rm) { 887ece92f85SJason Jin case 0: 888ece92f85SJason Jin DECODE_PRINTF("[EAX]"); 889ece92f85SJason Jin return M.x86.R_EAX; 890ece92f85SJason Jin case 1: 891ece92f85SJason Jin DECODE_PRINTF("[ECX]"); 892ece92f85SJason Jin return M.x86.R_ECX; 893ece92f85SJason Jin case 2: 894ece92f85SJason Jin DECODE_PRINTF("[EDX]"); 895ece92f85SJason Jin return M.x86.R_EDX; 896ece92f85SJason Jin case 3: 897ece92f85SJason Jin DECODE_PRINTF("[EBX]"); 898ece92f85SJason Jin return M.x86.R_EBX; 899ece92f85SJason Jin case 4: 900ece92f85SJason Jin return decode_sib_address(0); 901ece92f85SJason Jin case 5: 902ece92f85SJason Jin offset = fetch_long_imm(); 903ece92f85SJason Jin DECODE_PRINTF2("[%08x]", offset); 904ece92f85SJason Jin return offset; 905ece92f85SJason Jin case 6: 906ece92f85SJason Jin DECODE_PRINTF("[ESI]"); 907ece92f85SJason Jin return M.x86.R_ESI; 908ece92f85SJason Jin case 7: 909ece92f85SJason Jin DECODE_PRINTF("[EDI]"); 910ece92f85SJason Jin return M.x86.R_EDI; 911ece92f85SJason Jin } 912ece92f85SJason Jin } else { 913ece92f85SJason Jin /* 16-bit addressing */ 914ece92f85SJason Jin switch (rm) { 915ece92f85SJason Jin case 0: 916ece92f85SJason Jin DECODE_PRINTF("[BX+SI]"); 917ece92f85SJason Jin return (M.x86.R_BX + M.x86.R_SI) & 0xffff; 918ece92f85SJason Jin case 1: 919ece92f85SJason Jin DECODE_PRINTF("[BX+DI]"); 920ece92f85SJason Jin return (M.x86.R_BX + M.x86.R_DI) & 0xffff; 921ece92f85SJason Jin case 2: 922ece92f85SJason Jin DECODE_PRINTF("[BP+SI]"); 923ece92f85SJason Jin M.x86.mode |= SYSMODE_SEG_DS_SS; 924ece92f85SJason Jin return (M.x86.R_BP + M.x86.R_SI) & 0xffff; 925ece92f85SJason Jin case 3: 926ece92f85SJason Jin DECODE_PRINTF("[BP+DI]"); 927ece92f85SJason Jin M.x86.mode |= SYSMODE_SEG_DS_SS; 928ece92f85SJason Jin return (M.x86.R_BP + M.x86.R_DI) & 0xffff; 929ece92f85SJason Jin case 4: 930ece92f85SJason Jin DECODE_PRINTF("[SI]"); 931ece92f85SJason Jin return M.x86.R_SI; 932ece92f85SJason Jin case 5: 933ece92f85SJason Jin DECODE_PRINTF("[DI]"); 934ece92f85SJason Jin return M.x86.R_DI; 935ece92f85SJason Jin case 6: 936ece92f85SJason Jin offset = fetch_word_imm(); 937ece92f85SJason Jin DECODE_PRINTF2("[%04x]", offset); 938ece92f85SJason Jin return offset; 939ece92f85SJason Jin case 7: 940ece92f85SJason Jin DECODE_PRINTF("[BX]"); 941ece92f85SJason Jin return M.x86.R_BX; 942ece92f85SJason Jin } 943ece92f85SJason Jin } 944ece92f85SJason Jin HALT_SYS(); 945ece92f85SJason Jin return 0; 946ece92f85SJason Jin } 947ece92f85SJason Jin 948ece92f85SJason Jin /**************************************************************************** 949ece92f85SJason Jin PARAMETERS: 950ece92f85SJason Jin rm - RM value to decode 951ece92f85SJason Jin 952ece92f85SJason Jin RETURNS: 953ece92f85SJason Jin Offset in memory for the address decoding 954ece92f85SJason Jin 955ece92f85SJason Jin REMARKS: 956ece92f85SJason Jin Return the offset given by mod=01 addressing. Also enables the 957ece92f85SJason Jin decoding of instructions. 958ece92f85SJason Jin ****************************************************************************/ 959ece92f85SJason Jin unsigned decode_rm01_address( 960ece92f85SJason Jin int rm) 961ece92f85SJason Jin { 962ece92f85SJason Jin int displacement; 963ece92f85SJason Jin 964ece92f85SJason Jin if (M.x86.mode & SYSMODE_PREFIX_ADDR) { 965ece92f85SJason Jin /* 32-bit addressing */ 966ece92f85SJason Jin if (rm != 4) 967ece92f85SJason Jin displacement = (s8)fetch_byte_imm(); 968ece92f85SJason Jin else 969ece92f85SJason Jin displacement = 0; 970ece92f85SJason Jin 971ece92f85SJason Jin switch (rm) { 972ece92f85SJason Jin case 0: 973ece92f85SJason Jin DECODE_PRINTF2("%d[EAX]", displacement); 974ece92f85SJason Jin return M.x86.R_EAX + displacement; 975ece92f85SJason Jin case 1: 976ece92f85SJason Jin DECODE_PRINTF2("%d[ECX]", displacement); 977ece92f85SJason Jin return M.x86.R_ECX + displacement; 978ece92f85SJason Jin case 2: 979ece92f85SJason Jin DECODE_PRINTF2("%d[EDX]", displacement); 980ece92f85SJason Jin return M.x86.R_EDX + displacement; 981ece92f85SJason Jin case 3: 982ece92f85SJason Jin DECODE_PRINTF2("%d[EBX]", displacement); 983ece92f85SJason Jin return M.x86.R_EBX + displacement; 984ece92f85SJason Jin case 4: { 985ece92f85SJason Jin int offset = decode_sib_address(1); 986ece92f85SJason Jin displacement = (s8)fetch_byte_imm(); 987ece92f85SJason Jin DECODE_PRINTF2("[%d]", displacement); 988ece92f85SJason Jin return offset + displacement; 989ece92f85SJason Jin } 990ece92f85SJason Jin case 5: 991ece92f85SJason Jin DECODE_PRINTF2("%d[EBP]", displacement); 992ece92f85SJason Jin return M.x86.R_EBP + displacement; 993ece92f85SJason Jin case 6: 994ece92f85SJason Jin DECODE_PRINTF2("%d[ESI]", displacement); 995ece92f85SJason Jin return M.x86.R_ESI + displacement; 996ece92f85SJason Jin case 7: 997ece92f85SJason Jin DECODE_PRINTF2("%d[EDI]", displacement); 998ece92f85SJason Jin return M.x86.R_EDI + displacement; 999ece92f85SJason Jin } 1000ece92f85SJason Jin } else { 1001ece92f85SJason Jin /* 16-bit addressing */ 1002ece92f85SJason Jin displacement = (s8)fetch_byte_imm(); 1003ece92f85SJason Jin switch (rm) { 1004ece92f85SJason Jin case 0: 1005ece92f85SJason Jin DECODE_PRINTF2("%d[BX+SI]", displacement); 1006ece92f85SJason Jin return (M.x86.R_BX + M.x86.R_SI + displacement) & 0xffff; 1007ece92f85SJason Jin case 1: 1008ece92f85SJason Jin DECODE_PRINTF2("%d[BX+DI]", displacement); 1009ece92f85SJason Jin return (M.x86.R_BX + M.x86.R_DI + displacement) & 0xffff; 1010ece92f85SJason Jin case 2: 1011ece92f85SJason Jin DECODE_PRINTF2("%d[BP+SI]", displacement); 1012ece92f85SJason Jin M.x86.mode |= SYSMODE_SEG_DS_SS; 1013ece92f85SJason Jin return (M.x86.R_BP + M.x86.R_SI + displacement) & 0xffff; 1014ece92f85SJason Jin case 3: 1015ece92f85SJason Jin DECODE_PRINTF2("%d[BP+DI]", displacement); 1016ece92f85SJason Jin M.x86.mode |= SYSMODE_SEG_DS_SS; 1017ece92f85SJason Jin return (M.x86.R_BP + M.x86.R_DI + displacement) & 0xffff; 1018ece92f85SJason Jin case 4: 1019ece92f85SJason Jin DECODE_PRINTF2("%d[SI]", displacement); 1020ece92f85SJason Jin return (M.x86.R_SI + displacement) & 0xffff; 1021ece92f85SJason Jin case 5: 1022ece92f85SJason Jin DECODE_PRINTF2("%d[DI]", displacement); 1023ece92f85SJason Jin return (M.x86.R_DI + displacement) & 0xffff; 1024ece92f85SJason Jin case 6: 1025ece92f85SJason Jin DECODE_PRINTF2("%d[BP]", displacement); 1026ece92f85SJason Jin M.x86.mode |= SYSMODE_SEG_DS_SS; 1027ece92f85SJason Jin return (M.x86.R_BP + displacement) & 0xffff; 1028ece92f85SJason Jin case 7: 1029ece92f85SJason Jin DECODE_PRINTF2("%d[BX]", displacement); 1030ece92f85SJason Jin return (M.x86.R_BX + displacement) & 0xffff; 1031ece92f85SJason Jin } 1032ece92f85SJason Jin } 1033ece92f85SJason Jin HALT_SYS(); 1034ece92f85SJason Jin return 0; /* SHOULD NOT HAPPEN */ 1035ece92f85SJason Jin } 1036ece92f85SJason Jin 1037ece92f85SJason Jin /**************************************************************************** 1038ece92f85SJason Jin PARAMETERS: 1039ece92f85SJason Jin rm - RM value to decode 1040ece92f85SJason Jin 1041ece92f85SJason Jin RETURNS: 1042ece92f85SJason Jin Offset in memory for the address decoding 1043ece92f85SJason Jin 1044ece92f85SJason Jin REMARKS: 1045ece92f85SJason Jin Return the offset given by mod=10 addressing. Also enables the 1046ece92f85SJason Jin decoding of instructions. 1047ece92f85SJason Jin ****************************************************************************/ 1048ece92f85SJason Jin unsigned decode_rm10_address( 1049ece92f85SJason Jin int rm) 1050ece92f85SJason Jin { 1051ece92f85SJason Jin if (M.x86.mode & SYSMODE_PREFIX_ADDR) { 1052ece92f85SJason Jin int displacement; 1053ece92f85SJason Jin 1054ece92f85SJason Jin /* 32-bit addressing */ 1055ece92f85SJason Jin if (rm != 4) 1056ece92f85SJason Jin displacement = (s32)fetch_long_imm(); 1057ece92f85SJason Jin else 1058ece92f85SJason Jin displacement = 0; 1059ece92f85SJason Jin 1060ece92f85SJason Jin switch (rm) { 1061ece92f85SJason Jin case 0: 1062ece92f85SJason Jin DECODE_PRINTF2("%d[EAX]", displacement); 1063ece92f85SJason Jin return M.x86.R_EAX + displacement; 1064ece92f85SJason Jin case 1: 1065ece92f85SJason Jin DECODE_PRINTF2("%d[ECX]", displacement); 1066ece92f85SJason Jin return M.x86.R_ECX + displacement; 1067ece92f85SJason Jin case 2: 1068ece92f85SJason Jin DECODE_PRINTF2("%d[EDX]", displacement); 1069ece92f85SJason Jin return M.x86.R_EDX + displacement; 1070ece92f85SJason Jin case 3: 1071ece92f85SJason Jin DECODE_PRINTF2("%d[EBX]", displacement); 1072ece92f85SJason Jin return M.x86.R_EBX + displacement; 1073ece92f85SJason Jin case 4: { 1074ece92f85SJason Jin int offset = decode_sib_address(2); 1075ece92f85SJason Jin displacement = (s32)fetch_long_imm(); 1076ece92f85SJason Jin DECODE_PRINTF2("[%d]", displacement); 1077ece92f85SJason Jin return offset + displacement; 1078ece92f85SJason Jin } 1079ece92f85SJason Jin case 5: 1080ece92f85SJason Jin DECODE_PRINTF2("%d[EBP]", displacement); 1081ece92f85SJason Jin return M.x86.R_EBP + displacement; 1082ece92f85SJason Jin case 6: 1083ece92f85SJason Jin DECODE_PRINTF2("%d[ESI]", displacement); 1084ece92f85SJason Jin return M.x86.R_ESI + displacement; 1085ece92f85SJason Jin case 7: 1086ece92f85SJason Jin DECODE_PRINTF2("%d[EDI]", displacement); 1087ece92f85SJason Jin return M.x86.R_EDI + displacement; 1088ece92f85SJason Jin } 1089ece92f85SJason Jin } else { 1090ece92f85SJason Jin int displacement = (s16)fetch_word_imm(); 1091ece92f85SJason Jin 1092ece92f85SJason Jin /* 16-bit addressing */ 1093ece92f85SJason Jin switch (rm) { 1094ece92f85SJason Jin case 0: 1095ece92f85SJason Jin DECODE_PRINTF2("%d[BX+SI]", displacement); 1096ece92f85SJason Jin return (M.x86.R_BX + M.x86.R_SI + displacement) & 0xffff; 1097ece92f85SJason Jin case 1: 1098ece92f85SJason Jin DECODE_PRINTF2("%d[BX+DI]", displacement); 1099ece92f85SJason Jin return (M.x86.R_BX + M.x86.R_DI + displacement) & 0xffff; 1100ece92f85SJason Jin case 2: 1101ece92f85SJason Jin DECODE_PRINTF2("%d[BP+SI]", displacement); 1102ece92f85SJason Jin M.x86.mode |= SYSMODE_SEG_DS_SS; 1103ece92f85SJason Jin return (M.x86.R_BP + M.x86.R_SI + displacement) & 0xffff; 1104ece92f85SJason Jin case 3: 1105ece92f85SJason Jin DECODE_PRINTF2("%d[BP+DI]", displacement); 1106ece92f85SJason Jin M.x86.mode |= SYSMODE_SEG_DS_SS; 1107ece92f85SJason Jin return (M.x86.R_BP + M.x86.R_DI + displacement) & 0xffff; 1108ece92f85SJason Jin case 4: 1109ece92f85SJason Jin DECODE_PRINTF2("%d[SI]", displacement); 1110ece92f85SJason Jin return (M.x86.R_SI + displacement) & 0xffff; 1111ece92f85SJason Jin case 5: 1112ece92f85SJason Jin DECODE_PRINTF2("%d[DI]", displacement); 1113ece92f85SJason Jin return (M.x86.R_DI + displacement) & 0xffff; 1114ece92f85SJason Jin case 6: 1115ece92f85SJason Jin DECODE_PRINTF2("%d[BP]", displacement); 1116ece92f85SJason Jin M.x86.mode |= SYSMODE_SEG_DS_SS; 1117ece92f85SJason Jin return (M.x86.R_BP + displacement) & 0xffff; 1118ece92f85SJason Jin case 7: 1119ece92f85SJason Jin DECODE_PRINTF2("%d[BX]", displacement); 1120ece92f85SJason Jin return (M.x86.R_BX + displacement) & 0xffff; 1121ece92f85SJason Jin } 1122ece92f85SJason Jin } 1123ece92f85SJason Jin HALT_SYS(); 1124ece92f85SJason Jin return 0; /* SHOULD NOT HAPPEN */ 1125ece92f85SJason Jin } 1126ece92f85SJason Jin 1127ece92f85SJason Jin /**************************************************************************** 1128ece92f85SJason Jin PARAMETERS: 1129ece92f85SJason Jin mod - modifier 1130ece92f85SJason Jin rm - RM value to decode 1131ece92f85SJason Jin 1132ece92f85SJason Jin RETURNS: 1133ece92f85SJason Jin Offset in memory for the address decoding, multiplexing calls to 1134ece92f85SJason Jin the decode_rmXX_address functions 1135ece92f85SJason Jin 1136ece92f85SJason Jin REMARKS: 1137ece92f85SJason Jin Return the offset given by "mod" addressing. 1138ece92f85SJason Jin ****************************************************************************/ 1139ece92f85SJason Jin 1140ece92f85SJason Jin unsigned decode_rmXX_address(int mod, int rm) 1141ece92f85SJason Jin { 1142ece92f85SJason Jin if(mod == 0) 1143ece92f85SJason Jin return decode_rm00_address(rm); 1144ece92f85SJason Jin if(mod == 1) 1145ece92f85SJason Jin return decode_rm01_address(rm); 1146ece92f85SJason Jin return decode_rm10_address(rm); 1147ece92f85SJason Jin } 1148ce981dc8SJason Jin 1149ce981dc8SJason Jin #endif 1150