1/**************************************************************************** 2* 3* Realmode X86 Emulator Library 4* 5* Copyright (C) 1996-1999 SciTech Software, Inc. 6* Copyright (C) David Mosberger-Tang 7* Copyright (C) 1999 Egbert Eich 8* 9* ======================================================================== 10* 11* Permission to use, copy, modify, distribute, and sell this software and 12* its documentation for any purpose is hereby granted without fee, 13* provided that the above copyright notice appear in all copies and that 14* both that copyright notice and this permission notice appear in 15* supporting documentation, and that the name of the authors not be used 16* in advertising or publicity pertaining to distribution of the software 17* without specific, written prior permission. The authors makes no 18* representations about the suitability of this software for any purpose. 19* It is provided "as is" without express or implied warranty. 20* 21* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 22* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 23* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 24* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF 25* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 26* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 27* PERFORMANCE OF THIS SOFTWARE. 28* 29* ======================================================================== 30* 31* Language: ANSI C 32* Environment: Any 33* Developer: Kendall Bennett 34* 35* Description: This file includes subroutines which are related to 36* programmed I/O and memory access. Included in this module 37* are default functions with limited usefulness. For real 38* uses these functions will most likely be overriden by the 39* user library. 40* 41****************************************************************************/ 42 43#include "x86emu.h" 44#include "x86emu/x86emui.h" 45#include "x86emu/regs.h" 46#include "x86emu/debug.h" 47#include "x86emu/prim_ops.h" 48#ifndef NO_SYS_HEADERS 49#include <string.h> 50#endif 51/*------------------------- Global Variables ------------------------------*/ 52 53X86EMU_sysEnv _X86EMU_env; /* Global emulator machine state */ 54X86EMU_intrFuncs _X86EMU_intrTab[256]; 55 56 57/**************************************************************************** 58PARAMETERS: 59addr - Emulator memory address to read 60 61RETURNS: 62Byte value read from emulator memory. 63 64REMARKS: 65Reads a byte value from the emulator memory. 66****************************************************************************/ 67u8 X86API rdb( 68 u32 addr) 69{ 70 u8 val; 71 72 if (addr > M.mem_size - 1) { 73 DB(printk("mem_read: address %#lx out of range!\n", addr);) 74 HALT_SYS(); 75 } 76 val = *(u8*)(M.mem_base + addr); 77DB( if (DEBUG_MEM_TRACE()) 78 printk("%#08x 1 -> %#x\n", addr, val);) 79 return val; 80} 81 82/**************************************************************************** 83PARAMETERS: 84addr - Emulator memory address to read 85 86RETURNS: 87Word value read from emulator memory. 88 89REMARKS: 90Reads a word value from the emulator memory. 91****************************************************************************/ 92u16 X86API rdw( 93 u32 addr) 94{ 95 u16 val = 0; 96 97 if (addr > M.mem_size - 2) { 98 DB(printk("mem_read: address %#lx out of range!\n", addr);) 99 HALT_SYS(); 100 } 101#ifdef __BIG_ENDIAN__ 102 if (addr & 0x1) { 103 val = (*(u8*)(M.mem_base + addr) | 104 (*(u8*)(M.mem_base + addr + 1) << 8)); 105 } 106 else 107#endif 108 val = *(u16*)(M.mem_base + addr); 109 DB( if (DEBUG_MEM_TRACE()) 110 printk("%#08x 2 -> %#x\n", addr, val);) 111 return val; 112} 113 114/**************************************************************************** 115PARAMETERS: 116addr - Emulator memory address to read 117 118RETURNS: 119Long value read from emulator memory. 120REMARKS: 121Reads a long value from the emulator memory. 122****************************************************************************/ 123u32 X86API rdl( 124 u32 addr) 125{ 126 u32 val = 0; 127 128 if (addr > M.mem_size - 4) { 129 DB(printk("mem_read: address %#lx out of range!\n", addr);) 130 HALT_SYS(); 131 } 132#ifdef __BIG_ENDIAN__ 133 if (addr & 0x3) { 134 val = (*(u8*)(M.mem_base + addr + 0) | 135 (*(u8*)(M.mem_base + addr + 1) << 8) | 136 (*(u8*)(M.mem_base + addr + 2) << 16) | 137 (*(u8*)(M.mem_base + addr + 3) << 24)); 138 } 139 else 140#endif 141 val = *(u32*)(M.mem_base + addr); 142DB( if (DEBUG_MEM_TRACE()) 143 printk("%#08x 4 -> %#x\n", addr, val);) 144 return val; 145} 146 147/**************************************************************************** 148PARAMETERS: 149addr - Emulator memory address to read 150val - Value to store 151 152REMARKS: 153Writes a byte value to emulator memory. 154****************************************************************************/ 155void X86API wrb( 156 u32 addr, 157 u8 val) 158{ 159DB( if (DEBUG_MEM_TRACE()) 160 printk("%#08x 1 <- %#x\n", addr, val);) 161 if (addr > M.mem_size - 1) { 162 DB(printk("mem_write: address %#lx out of range!\n", addr);) 163 HALT_SYS(); 164 } 165 *(u8*)(M.mem_base + addr) = val; 166} 167 168/**************************************************************************** 169PARAMETERS: 170addr - Emulator memory address to read 171val - Value to store 172 173REMARKS: 174Writes a word value to emulator memory. 175****************************************************************************/ 176void X86API wrw( 177 u32 addr, 178 u16 val) 179{ 180DB( if (DEBUG_MEM_TRACE()) 181 printk("%#08x 2 <- %#x\n", addr, val);) 182 if (addr > M.mem_size - 2) { 183 DB(printk("mem_write: address %#lx out of range!\n", addr);) 184 HALT_SYS(); 185 } 186#ifdef __BIG_ENDIAN__ 187 if (addr & 0x1) { 188 *(u8*)(M.mem_base + addr + 0) = (val >> 0) & 0xff; 189 *(u8*)(M.mem_base + addr + 1) = (val >> 8) & 0xff; 190 } 191 else 192#endif 193 *(u16*)(M.mem_base + addr) = val; 194} 195 196/**************************************************************************** 197PARAMETERS: 198addr - Emulator memory address to read 199val - Value to store 200 201REMARKS: 202Writes a long value to emulator memory. 203****************************************************************************/ 204void X86API wrl( 205 u32 addr, 206 u32 val) 207{ 208DB( if (DEBUG_MEM_TRACE()) 209 printk("%#08x 4 <- %#x\n", addr, val);) 210 if (addr > M.mem_size - 4) { 211 DB(printk("mem_write: address %#lx out of range!\n", addr);) 212 HALT_SYS(); 213 return; 214 } 215#ifdef __BIG_ENDIAN__ 216 if (addr & 0x1) { 217 *(u8*)(M.mem_base + addr + 0) = (val >> 0) & 0xff; 218 *(u8*)(M.mem_base + addr + 1) = (val >> 8) & 0xff; 219 *(u8*)(M.mem_base + addr + 2) = (val >> 16) & 0xff; 220 *(u8*)(M.mem_base + addr + 3) = (val >> 24) & 0xff; 221 } 222 else 223#endif 224 *(u32*)(M.mem_base + addr) = val; 225} 226 227/**************************************************************************** 228PARAMETERS: 229addr - PIO address to read 230RETURN: 2310 232REMARKS: 233Default PIO byte read function. Doesn't perform real inb. 234****************************************************************************/ 235static u8 X86API p_inb( 236 X86EMU_pioAddr addr) 237{ 238DB( if (DEBUG_IO_TRACE()) 239 printk("inb %#04x \n", addr);) 240 return 0; 241} 242 243/**************************************************************************** 244PARAMETERS: 245addr - PIO address to read 246RETURN: 2470 248REMARKS: 249Default PIO word read function. Doesn't perform real inw. 250****************************************************************************/ 251static u16 X86API p_inw( 252 X86EMU_pioAddr addr) 253{ 254DB( if (DEBUG_IO_TRACE()) 255 printk("inw %#04x \n", addr);) 256 return 0; 257} 258 259/**************************************************************************** 260PARAMETERS: 261addr - PIO address to read 262RETURN: 2630 264REMARKS: 265Default PIO long read function. Doesn't perform real inl. 266****************************************************************************/ 267static u32 X86API p_inl( 268 X86EMU_pioAddr addr) 269{ 270DB( if (DEBUG_IO_TRACE()) 271 printk("inl %#04x \n", addr);) 272 return 0; 273} 274 275/**************************************************************************** 276PARAMETERS: 277addr - PIO address to write 278val - Value to store 279REMARKS: 280Default PIO byte write function. Doesn't perform real outb. 281****************************************************************************/ 282static void X86API p_outb( 283 X86EMU_pioAddr addr, 284 u8 val) 285{ 286DB( if (DEBUG_IO_TRACE()) 287 printk("outb %#02x -> %#04x \n", val, addr);) 288 return; 289} 290 291/**************************************************************************** 292PARAMETERS: 293addr - PIO address to write 294val - Value to store 295REMARKS: 296Default PIO word write function. Doesn't perform real outw. 297****************************************************************************/ 298static void X86API p_outw( 299 X86EMU_pioAddr addr, 300 u16 val) 301{ 302DB( if (DEBUG_IO_TRACE()) 303 printk("outw %#04x -> %#04x \n", val, addr);) 304 return; 305} 306 307/**************************************************************************** 308PARAMETERS: 309addr - PIO address to write 310val - Value to store 311REMARKS: 312Default PIO ;ong write function. Doesn't perform real outl. 313****************************************************************************/ 314static void X86API p_outl( 315 X86EMU_pioAddr addr, 316 u32 val) 317{ 318DB( if (DEBUG_IO_TRACE()) 319 printk("outl %#08x -> %#04x \n", val, addr);) 320 return; 321} 322 323/*------------------------- Global Variables ------------------------------*/ 324 325u8 (X86APIP sys_rdb)(u32 addr) = rdb; 326u16 (X86APIP sys_rdw)(u32 addr) = rdw; 327u32 (X86APIP sys_rdl)(u32 addr) = rdl; 328void (X86APIP sys_wrb)(u32 addr,u8 val) = wrb; 329void (X86APIP sys_wrw)(u32 addr,u16 val) = wrw; 330void (X86APIP sys_wrl)(u32 addr,u32 val) = wrl; 331u8 (X86APIP sys_inb)(X86EMU_pioAddr addr) = p_inb; 332u16 (X86APIP sys_inw)(X86EMU_pioAddr addr) = p_inw; 333u32 (X86APIP sys_inl)(X86EMU_pioAddr addr) = p_inl; 334void (X86APIP sys_outb)(X86EMU_pioAddr addr, u8 val) = p_outb; 335void (X86APIP sys_outw)(X86EMU_pioAddr addr, u16 val) = p_outw; 336void (X86APIP sys_outl)(X86EMU_pioAddr addr, u32 val) = p_outl; 337 338/*----------------------------- Setup -------------------------------------*/ 339 340/**************************************************************************** 341PARAMETERS: 342funcs - New memory function pointers to make active 343 344REMARKS: 345This function is used to set the pointers to functions which access 346memory space, allowing the user application to override these functions 347and hook them out as necessary for their application. 348****************************************************************************/ 349void X86EMU_setupMemFuncs( 350 X86EMU_memFuncs *funcs) 351{ 352 sys_rdb = funcs->rdb; 353 sys_rdw = funcs->rdw; 354 sys_rdl = funcs->rdl; 355 sys_wrb = funcs->wrb; 356 sys_wrw = funcs->wrw; 357 sys_wrl = funcs->wrl; 358} 359 360/**************************************************************************** 361PARAMETERS: 362funcs - New programmed I/O function pointers to make active 363 364REMARKS: 365This function is used to set the pointers to functions which access 366I/O space, allowing the user application to override these functions 367and hook them out as necessary for their application. 368****************************************************************************/ 369void X86EMU_setupPioFuncs( 370 X86EMU_pioFuncs *funcs) 371{ 372 sys_inb = funcs->inb; 373 sys_inw = funcs->inw; 374 sys_inl = funcs->inl; 375 sys_outb = funcs->outb; 376 sys_outw = funcs->outw; 377 sys_outl = funcs->outl; 378} 379 380/**************************************************************************** 381PARAMETERS: 382funcs - New interrupt vector table to make active 383 384REMARKS: 385This function is used to set the pointers to functions which handle 386interrupt processing in the emulator, allowing the user application to 387hook interrupts as necessary for their application. Any interrupts that 388are not hooked by the user application, and reflected and handled internally 389in the emulator via the interrupt vector table. This allows the application 390to get control when the code being emulated executes specific software 391interrupts. 392****************************************************************************/ 393void X86EMU_setupIntrFuncs( 394 X86EMU_intrFuncs funcs[]) 395{ 396 int i; 397 398 for (i=0; i < 256; i++) 399 _X86EMU_intrTab[i] = NULL; 400 if (funcs) { 401 for (i = 0; i < 256; i++) 402 _X86EMU_intrTab[i] = funcs[i]; 403 } 404} 405 406/**************************************************************************** 407PARAMETERS: 408int - New software interrupt to prepare for 409 410REMARKS: 411This function is used to set up the emulator state to exceute a software 412interrupt. This can be used by the user application code to allow an 413interrupt to be hooked, examined and then reflected back to the emulator 414so that the code in the emulator will continue processing the software 415interrupt as per normal. This essentially allows system code to actively 416hook and handle certain software interrupts as necessary. 417****************************************************************************/ 418void X86EMU_prepareForInt( 419 int num) 420{ 421 push_word((u16)M.x86.R_FLG); 422 CLEAR_FLAG(F_IF); 423 CLEAR_FLAG(F_TF); 424 push_word(M.x86.R_CS); 425 M.x86.R_CS = mem_access_word(num * 4 + 2); 426 push_word(M.x86.R_IP); 427 M.x86.R_IP = mem_access_word(num * 4); 428 M.x86.intr = 0; 429} 430