This is a BIOS emulator, porting from SciTech for u-boot, mainly for

ATI video card BIOS. and can be used for x86 code emulation by some
modifications.

Signed-off-by: Jason Jin <Jason.jin@freescale.com>
This commit is contained in:
Jason Jin 2007-07-06 08:34:56 +08:00 committed by Wolfgang Denk
parent 5072188aca
commit ece92f8505
21 changed files with 16008 additions and 0 deletions

View file

@ -0,0 +1,30 @@
include $(TOPDIR)/config.mk
LIB := libatibiosemu.a
X86DIR = ./x86emu
OBJS = atibios.o biosemu.o besys.o bios.o \
$(X86DIR)/decode.o \
$(X86DIR)/ops2.o \
$(X86DIR)/ops.o \
$(X86DIR)/prim_ops.o \
$(X86DIR)/sys.o \
$(X86DIR)/debug.o
CFLAGS += -I. -I./include -I$(X86DIR) -I$(TOPDIR)/include \
-D__PPC__ -D__BIG_ENDIAN__
all: $(LIB)
$(LIB): $(OBJS)
$(AR) crv $@ $(OBJS)
#########################################################################
.depend: Makefile $(OBJS:.o=.c)
$(CC) -M $(CFLAGS) $(OBJS:.o=.c) > $@
sinclude .depend
#########################################################################

View file

@ -0,0 +1,340 @@
/****************************************************************************
*
* Video BOOT Graphics Card POST Module
*
* ========================================================================
* Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved.
* Jason Jin <Jason.jin@freescale.com>
*
* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
*
* This file may be distributed and/or modified under the terms of the
* GNU General Public License version 2.0 as published by the Free
* Software Foundation and appearing in the file LICENSE.GPL included
* in the packaging of this file.
*
* Licensees holding a valid Commercial License for this product from
* SciTech Software, Inc. may use this file in accordance with the
* Commercial License Agreement provided with the Software.
*
* This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING
* THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE.
*
* See http://www.scitechsoft.com/license/ for information about
* the licensing options available and how to purchase a Commercial
* License Agreement.
*
* Contact license@scitechsoft.com if any conditions of this licensing
* are not clear to you, or you have questions about licensing options.
*
* ========================================================================
*
* Language: ANSI C
* Environment: Linux Kernel
* Developer: Kendall Bennett
*
* Description: Module to implement booting PCI/AGP controllers on the
* bus. We use the x86 real mode emulator to run the BIOS on
* graphics controllers to bring the cards up.
*
* Note that at present this module does *not* support
* multiple controllers.
*
* The orignal name of this file is warmboot.c.
* Jason ported this file to u-boot to run the ATI video card
* BIOS in u-boot.
****************************************************************************/
#include <common.h>
#ifdef CONFIG_BIOSEMU
#include "biosemui.h"
#include <malloc.h>
/* Length of the BIOS image */
#define MAX_BIOSLEN (128 * 1024L)
/* Define some useful types and macros */
#define true 1
#define false 0
/* Place to save PCI BAR's that we change and later restore */
static u32 saveROMBaseAddress;
static u32 saveBaseAddress10;
static u32 saveBaseAddress14;
static u32 saveBaseAddress18;
static u32 saveBaseAddress20;
/****************************************************************************
PARAMETERS:
pcidev - PCI device info for the video card on the bus to boot
VGAInfo - BIOS emulator VGA info structure
REMARKS:
This function executes the BIOS POST code on the controller. We assume that
at this stage the controller has its I/O and memory space enabled and
that all other controllers are in a disabled state.
****************************************************************************/
static void PCI_doBIOSPOST(pci_dev_t pcidev, BE_VGAInfo * VGAInfo)
{
RMREGS regs;
RMSREGS sregs;
/* Determine the value to store in AX for BIOS POST. Per the PCI specs,
AH must contain the bus and AL must contain the devfn, encoded as
(dev << 3) | fn
*/
memset(&regs, 0, sizeof(regs));
memset(&sregs, 0, sizeof(sregs));
regs.x.ax = ((int)PCI_BUS(pcidev) << 8) |
((int)PCI_DEV(pcidev) << 3) | (int)PCI_FUNC(pcidev);
/*Setup the X86 emulator for the VGA BIOS*/
BE_setVGA(VGAInfo);
/*Execute the BIOS POST code*/
BE_callRealMode(0xC000, 0x0003, &regs, &sregs);
/*Cleanup and exit*/
BE_getVGA(VGAInfo);
}
/****************************************************************************
PARAMETERS:
pcidev - PCI device info for the video card on the bus
bar - Place to return the base address register offset to use
RETURNS:
The address to use to map the secondary BIOS (AGP devices)
REMARKS:
Searches all the PCI base address registers for the device looking for a
memory mapping that is large enough to hold our ROM BIOS. We usually end up
finding the framebuffer mapping (usually BAR 0x10), and we use this mapping
to map the BIOS for the device into. We use a mapping that is already
assigned to the device to ensure the memory range will be passed through
by any PCI->PCI or AGP->PCI bridge that may be present.
NOTE: Usually this function is only used for AGP devices, but it may be
used for PCI devices that have already been POST'ed and the BIOS
ROM base address has been zero'ed out.
NOTE: This function leaves the original memory aperture disabled by leaving
it programmed to all 1's. It must be restored to the correct value
later.
****************************************************************************/
static u32 PCI_findBIOSAddr(pci_dev_t pcidev, int *bar)
{
u32 base, size;
for (*bar = 0x10; *bar <= 0x14; (*bar) += 4) {
pci_read_config_dword(pcidev, *bar, &base);
if (!(base & 0x1)) {
pci_write_config_dword(pcidev, *bar, 0xFFFFFFFF);
pci_read_config_dword(pcidev, *bar, &size);
size = ~(size & ~0xFF) + 1;
if (size >= MAX_BIOSLEN)
return base & ~0xFF;
}
}
return 0;
}
/****************************************************************************
REMARKS:
Some non-x86 Linux kernels map PCI relocateable I/O to values that
are above 64K, which will not work with the BIOS image that requires
the offset for the I/O ports to be a maximum of 16-bits. Ideally
someone should fix the kernel to map the I/O ports for VGA compatible
devices to a different location (or just all I/O ports since it is
unlikely you can have enough devices in the machine to use up all
64K of the I/O space - a total of more than 256 cards would be
necessary).
Anyway to fix this we change all I/O mapped base registers and
chop off the top bits.
****************************************************************************/
static void PCI_fixupIObase(pci_dev_t pcidev, int reg, u32 * base)
{
if ((*base & 0x1) && (*base > 0xFFFE)) {
*base &= 0xFFFF;
pci_write_config_dword(pcidev, reg, *base);
}
}
/****************************************************************************
PARAMETERS:
pcidev - PCI device info for the video card on the bus
RETURNS:
Pointers to the mapped BIOS image
REMARKS:
Maps a pointer to the BIOS image on the graphics card on the PCI bus.
****************************************************************************/
void *PCI_mapBIOSImage(pci_dev_t pcidev)
{
u32 BIOSImagePhys;
int BIOSImageBAR;
u8 *BIOSImage;
/*Save PCI BAR registers that might get changed*/
pci_read_config_dword(pcidev, PCI_ROM_ADDRESS, &saveROMBaseAddress);
pci_read_config_dword(pcidev, PCI_BASE_ADDRESS_0, &saveBaseAddress10);
pci_read_config_dword(pcidev, PCI_BASE_ADDRESS_1, &saveBaseAddress14);
pci_read_config_dword(pcidev, PCI_BASE_ADDRESS_2, &saveBaseAddress18);
pci_read_config_dword(pcidev, PCI_BASE_ADDRESS_4, &saveBaseAddress20);
/*Fix up I/O base registers to less than 64K */
if(saveBaseAddress14 != 0)
PCI_fixupIObase(pcidev, PCI_BASE_ADDRESS_1, &saveBaseAddress14);
else
PCI_fixupIObase(pcidev, PCI_BASE_ADDRESS_4, &saveBaseAddress20);
/* Some cards have problems that stop us from being able to read the
BIOS image from the ROM BAR. To fix this we have to do some chipset
specific programming for different cards to solve this problem.
*/
if ((BIOSImagePhys = PCI_findBIOSAddr(pcidev, &BIOSImageBAR)) == 0) {
printf("Find bios addr error\n");
return NULL;
}
BIOSImage = (u8 *) BIOSImagePhys;
/*Change the PCI BAR registers to map it onto the bus.*/
pci_write_config_dword(pcidev, BIOSImageBAR, 0);
pci_write_config_dword(pcidev, PCI_ROM_ADDRESS, BIOSImagePhys | 0x1);
udelay(1);
/*Check that the BIOS image is valid. If not fail, or return the
compiled in BIOS image if that option was enabled
*/
if (BIOSImage[0] != 0x55 || BIOSImage[1] != 0xAA || BIOSImage[2] == 0) {
return NULL;
}
return BIOSImage;
}
/****************************************************************************
PARAMETERS:
pcidev - PCI device info for the video card on the bus
REMARKS:
Unmaps the BIOS image for the device and restores framebuffer mappings
****************************************************************************/
void PCI_unmapBIOSImage(pci_dev_t pcidev, void *BIOSImage)
{
pci_write_config_dword(pcidev, PCI_ROM_ADDRESS, saveROMBaseAddress);
pci_write_config_dword(pcidev, PCI_BASE_ADDRESS_0, saveBaseAddress10);
pci_write_config_dword(pcidev, PCI_BASE_ADDRESS_1, saveBaseAddress14);
pci_write_config_dword(pcidev, PCI_BASE_ADDRESS_2, saveBaseAddress18);
pci_write_config_dword(pcidev, PCI_BASE_ADDRESS_4, saveBaseAddress20);
}
/****************************************************************************
PARAMETERS:
pcidev - PCI device info for the video card on the bus to boot
VGAInfo - BIOS emulator VGA info structure
RETURNS:
True if successfully initialised, false if not.
REMARKS:
Loads and POST's the display controllers BIOS, directly from the BIOS
image we can extract over the PCI bus.
****************************************************************************/
static int PCI_postController(pci_dev_t pcidev, BE_VGAInfo * VGAInfo)
{
u32 BIOSImageLen;
uchar *mappedBIOS;
uchar *copyOfBIOS;
/*Allocate memory to store copy of BIOS from display controller*/
if ((mappedBIOS = PCI_mapBIOSImage(pcidev)) == NULL) {
printf("videoboot: Video ROM failed to map!\n");
return false;
}
BIOSImageLen = mappedBIOS[2] * 512;
if ((copyOfBIOS = malloc(BIOSImageLen)) == NULL) {
printf("videoboot: Out of memory!\n");
return false;
}
memcpy(copyOfBIOS, mappedBIOS, BIOSImageLen);
PCI_unmapBIOSImage(pcidev, mappedBIOS);
/*Save information in VGAInfo structure*/
VGAInfo->function = PCI_FUNC(pcidev);
VGAInfo->device = PCI_DEV(pcidev);
VGAInfo->bus = PCI_BUS(pcidev);
VGAInfo->pcidev = pcidev;
VGAInfo->BIOSImage = copyOfBIOS;
VGAInfo->BIOSImageLen = BIOSImageLen;
/*Now execute the BIOS POST for the device*/
if (copyOfBIOS[0] != 0x55 || copyOfBIOS[1] != 0xAA) {
printf("videoboot: Video ROM image is invalid!\n");
return false;
}
PCI_doBIOSPOST(pcidev, VGAInfo);
/*Reset the size of the BIOS image to the final size*/
VGAInfo->BIOSImageLen = copyOfBIOS[2] * 512;
return true;
}
/****************************************************************************
PARAMETERS:
pcidev - PCI device info for the video card on the bus to boot
pVGAInfo - Place to return VGA info structure is requested
cleanUp - True to clean up on exit, false to leave emulator active
REMARKS:
Boots the PCI/AGP video card on the bus using the Video ROM BIOS image
and the X86 BIOS emulator module.
****************************************************************************/
int BootVideoCardBIOS(pci_dev_t pcidev, BE_VGAInfo ** pVGAInfo, int cleanUp)
{
BE_VGAInfo *VGAInfo;
printf("videoboot: Booting PCI video card bus %d, function %d, device %d\n",
PCI_BUS(pcidev), PCI_FUNC(pcidev), PCI_DEV(pcidev));
/*Initialise the x86 BIOS emulator*/
if ((VGAInfo = malloc(sizeof(*VGAInfo))) == NULL) {
printf("videoboot: Out of memory!\n");
return false;
}
memset(VGAInfo, 0, sizeof(*VGAInfo));
BE_init(0, 65536, VGAInfo, 0);
/*Post all the display controller BIOS'es*/
PCI_postController(pcidev, VGAInfo);
/*Cleanup and exit the emulator if requested. If the BIOS emulator
is needed after booting the card, we will not call BE_exit and
leave it enabled for further use (ie: VESA driver etc).
*/
if (cleanUp) {
BE_exit();
if (VGAInfo->BIOSImage)
free(VGAInfo->BIOSImage);
free(VGAInfo);
VGAInfo = NULL;
}
/*Return VGA info pointer if the caller requested it*/
if (pVGAInfo)
*pVGAInfo = VGAInfo;
return true;
}
#endif

View file

@ -0,0 +1,722 @@
/****************************************************************************
*
* BIOS emulator and interface
* to Realmode X86 Emulator Library
*
* ========================================================================
*
* Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved.
* Jason Jin<Jason.jin@freescale.com>
*
* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
*
* This file may be distributed and/or modified under the terms of the
* GNU General Public License version 2.0 as published by the Free
* Software Foundation and appearing in the file LICENSE.GPL included
* in the packaging of this file.
*
* Licensees holding a valid Commercial License for this product from
* SciTech Software, Inc. may use this file in accordance with the
* Commercial License Agreement provided with the Software.
*
* This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING
* THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE.
*
* See http://www.scitechsoft.com/license/ for information about
* the licensing options available and how to purchase a Commercial
* License Agreement.
*
* Contact license@scitechsoft.com if any conditions of this licensing
* are not clear to you, or you have questions about licensing options.
*
* ========================================================================
*
* Language: ANSI C
* Environment: Any
* Developer: Kendall Bennett
*
* Description: This file includes BIOS emulator I/O and memory access
* functions.
*
* Jason ported this file to u-boot to run the ATI video card
* BIOS in u-boot. Removed some emulate functions such as the
* timer port access. Made all the VGA port except reading 0x3c3
* be emulated. Seems like reading 0x3c3 should return the high
* 16 bit of the io port.
*
****************************************************************************/
#include "biosemui.h"
/*------------------------- Global Variables ------------------------------*/
#ifndef __i386__
static char *BE_biosDate = "08/14/99";
static u8 BE_model = 0xFC;
static u8 BE_submodel = 0x00;
#endif
/*----------------------------- Implementation ----------------------------*/
/****************************************************************************
PARAMETERS:
addr - Emulator memory address to convert
RETURNS:
Actual memory address to read or write the data
REMARKS:
This function converts an emulator memory address in a 32-bit range to
a real memory address that we wish to access. It handles splitting up the
memory address space appropriately to access the emulator BIOS image, video
memory and system BIOS etc.
****************************************************************************/
static u8 *BE_memaddr(u32 addr)
{
if (addr >= 0xC0000 && addr <= _BE_env.biosmem_limit) {
return (u8*)(_BE_env.biosmem_base + addr - 0xC0000);
} else if (addr > _BE_env.biosmem_limit && addr < 0xD0000) {
DB(printf("BE_memaddr: address %#lx may be invalid!\n", addr);)
return M.mem_base;
} else if (addr >= 0xA0000 && addr <= 0xBFFFF) {
return (u8*)(_BE_env.busmem_base + addr - 0xA0000);
}
#ifdef __i386__
else if (addr >= 0xD0000 && addr <= 0xFFFFF) {
/* We map the real System BIOS directly on real PC's */
DB(printf("BE_memaddr: System BIOS address %#lx\n", addr);)
return _BE_env.busmem_base + addr - 0xA0000;
}
#else
else if (addr >= 0xFFFF5 && addr < 0xFFFFE) {
/* Return a faked BIOS date string for non-x86 machines */
DB(printf("BE_memaddr - Returning BIOS date\n");)
return BE_biosDate + addr - 0xFFFF5;
} else if (addr == 0xFFFFE) {
/* Return system model identifier for non-x86 machines */
DB(printf("BE_memaddr - Returning model\n");)
return &BE_model;
} else if (addr == 0xFFFFF) {
/* Return system submodel identifier for non-x86 machines */
DB(printf("BE_memaddr - Returning submodel\n");)
return &BE_submodel;
}
#endif
else if (addr > M.mem_size - 1) {
HALT_SYS();
return M.mem_base;
}
return M.mem_base + addr;
}
/****************************************************************************
PARAMETERS:
addr - Emulator memory address to read
RETURNS:
Byte value read from emulator memory.
REMARKS:
Reads a byte value from the emulator memory. We have three distinct memory
regions that are handled differently, which this function handles.
****************************************************************************/
u8 X86API BE_rdb(u32 addr)
{
if (_BE_env.emulateVGA && addr >= 0xA0000 && addr <= 0xBFFFF)
return 0;
else {
u8 val = readb_le(BE_memaddr(addr));
return val;
}
}
/****************************************************************************
PARAMETERS:
addr - Emulator memory address to read
RETURNS:
Word value read from emulator memory.
REMARKS:
Reads a word value from the emulator memory. We have three distinct memory
regions that are handled differently, which this function handles.
****************************************************************************/
u16 X86API BE_rdw(u32 addr)
{
if (_BE_env.emulateVGA && addr >= 0xA0000 && addr <= 0xBFFFF)
return 0;
else {
u8 *base = BE_memaddr(addr);
u16 val = readw_le(base);
return val;
}
}
/****************************************************************************
PARAMETERS:
addr - Emulator memory address to read
RETURNS:
Long value read from emulator memory.
REMARKS:
Reads a 32-bit value from the emulator memory. We have three distinct memory
regions that are handled differently, which this function handles.
****************************************************************************/
u32 X86API BE_rdl(u32 addr)
{
if (_BE_env.emulateVGA && addr >= 0xA0000 && addr <= 0xBFFFF)
return 0;
else {
u8 *base = BE_memaddr(addr);
u32 val = readl_le(base);
return val;
}
}
/****************************************************************************
PARAMETERS:
addr - Emulator memory address to read
val - Value to store
REMARKS:
Writes a byte value to emulator memory. We have three distinct memory
regions that are handled differently, which this function handles.
****************************************************************************/
void X86API BE_wrb(u32 addr, u8 val)
{
if (!(_BE_env.emulateVGA && addr >= 0xA0000 && addr <= 0xBFFFF)) {
writeb_le(BE_memaddr(addr), val);
}
}
/****************************************************************************
PARAMETERS:
addr - Emulator memory address to read
val - Value to store
REMARKS:
Writes a word value to emulator memory. We have three distinct memory
regions that are handled differently, which this function handles.
****************************************************************************/
void X86API BE_wrw(u32 addr, u16 val)
{
if (!(_BE_env.emulateVGA && addr >= 0xA0000 && addr <= 0xBFFFF)) {
u8 *base = BE_memaddr(addr);
writew_le(base, val);
}
}
/****************************************************************************
PARAMETERS:
addr - Emulator memory address to read
val - Value to store
REMARKS:
Writes a 32-bit value to emulator memory. We have three distinct memory
regions that are handled differently, which this function handles.
****************************************************************************/
void X86API BE_wrl(u32 addr, u32 val)
{
if (!(_BE_env.emulateVGA && addr >= 0xA0000 && addr <= 0xBFFFF)) {
u8 *base = BE_memaddr(addr);
writel_le(base, val);
}
}
#if defined(DEBUG) || !defined(__i386__)
/* For Non-Intel machines we may need to emulate some I/O port accesses that
* the BIOS may try to access, such as the PCI config registers.
*/
#define IS_TIMER_PORT(port) (0x40 <= port && port <= 0x43)
#define IS_CMOS_PORT(port) (0x70 <= port && port <= 0x71)
/*#define IS_VGA_PORT(port) (_BE_env.emulateVGA && 0x3C0 <= port && port <= 0x3DA)*/
#define IS_VGA_PORT(port) (0x3C0 <= port && port <= 0x3DA)
#define IS_PCI_PORT(port) (0xCF8 <= port && port <= 0xCFF)
#define IS_SPKR_PORT(port) (port == 0x61)
/****************************************************************************
PARAMETERS:
port - Port to read from
type - Type of access to perform
REMARKS:
Performs an emulated read from the Standard VGA I/O ports. If the target
hardware does not support mapping the VGA I/O and memory (such as some
PowerPC systems), we emulate the VGA so that the BIOS will still be able to
set NonVGA display modes such as on ATI hardware.
****************************************************************************/
static u8 VGA_inpb(
const int port)
{
u8 val = 0xff;
switch (port) {
case 0x3C0:
/* 3C0 has funky characteristics because it can act as either
a data register or index register depending on the state
of an internal flip flop in the hardware. Hence we have
to emulate that functionality in here. */
if (_BE_env.flipFlop3C0 == 0) {
/* Access 3C0 as index register*/
val = _BE_env.emu3C0;
}
else {
/* Access 3C0 as data register*/
if (_BE_env.emu3C0 < ATT_C)
val = _BE_env.emu3C1[_BE_env.emu3C0];
}
_BE_env.flipFlop3C0 ^= 1;
break;
case 0x3C1:
if (_BE_env.emu3C0 < ATT_C)
return _BE_env.emu3C1[_BE_env.emu3C0];
break;
case 0x3CC:
return _BE_env.emu3C2;
case 0x3C4:
return _BE_env.emu3C4;
case 0x3C5:
if (_BE_env.emu3C4 < ATT_C)
return _BE_env.emu3C5[_BE_env.emu3C4];
break;
case 0x3C6:
return _BE_env.emu3C6;
case 0x3C7:
return _BE_env.emu3C7;
case 0x3C8:
return _BE_env.emu3C8;
case 0x3C9:
if (_BE_env.emu3C7 < PAL_C)
return _BE_env.emu3C9[_BE_env.emu3C7++];
break;
case 0x3CE:
return _BE_env.emu3CE;
case 0x3CF:
if (_BE_env.emu3CE < GRA_C)
return _BE_env.emu3CF[_BE_env.emu3CE];
break;
case 0x3D4:
if (_BE_env.emu3C2 & 0x1)
return _BE_env.emu3D4;
break;
case 0x3D5:
if ((_BE_env.emu3C2 & 0x1) && (_BE_env.emu3D4 < CRT_C))
return _BE_env.emu3D5[_BE_env.emu3D4];
break;
case 0x3DA:
_BE_env.flipFlop3C0 = 0;
val = _BE_env.emu3DA;
_BE_env.emu3DA ^= 0x9;
break;
}
return val;
}
/****************************************************************************
PARAMETERS:
port - Port to write to
type - Type of access to perform
REMARKS:
Performs an emulated write to one of the 8253 timer registers. For now
we only emulate timer 0 which is the only timer that the BIOS code appears
to use.
****************************************************************************/
static void VGA_outpb(
int port,
u8 val)
{
switch (port) {
case 0x3C0:
/* 3C0 has funky characteristics because it can act as either
a data register or index register depending on the state
of an internal flip flop in the hardware. Hence we have
to emulate that functionality in here.*/
if (_BE_env.flipFlop3C0 == 0) {
/* Access 3C0 as index register*/
_BE_env.emu3C0 = val;
}
else {
/* Access 3C0 as data register*/
if (_BE_env.emu3C0 < ATT_C)
_BE_env.emu3C1[_BE_env.emu3C0] = val;
}
_BE_env.flipFlop3C0 ^= 1;
break;
case 0x3C2:
_BE_env.emu3C2 = val;
break;
case 0x3C4:
_BE_env.emu3C4 = val;
break;
case 0x3C5:
if (_BE_env.emu3C4 < ATT_C)
_BE_env.emu3C5[_BE_env.emu3C4] = val;
break;
case 0x3C6:
_BE_env.emu3C6 = val;
break;
case 0x3C7:
_BE_env.emu3C7 = (int)val * 3;
break;
case 0x3C8:
_BE_env.emu3C8 = (int)val * 3;
break;
case 0x3C9:
if (_BE_env.emu3C8 < PAL_C)
_BE_env.emu3C9[_BE_env.emu3C8++] = val;
break;
case 0x3CE:
_BE_env.emu3CE = val;
break;
case 0x3CF:
if (_BE_env.emu3CE < GRA_C)
_BE_env.emu3CF[_BE_env.emu3CE] = val;
break;
case 0x3D4:
if (_BE_env.emu3C2 & 0x1)
_BE_env.emu3D4 = val;
break;
case 0x3D5:
if ((_BE_env.emu3C2 & 0x1) && (_BE_env.emu3D4 < CRT_C))
_BE_env.emu3D5[_BE_env.emu3D4] = val;
break;
}
}
/****************************************************************************
PARAMETERS:
regOffset - Offset into register space for non-DWORD accesses
value - Value to write to register for PCI_WRITE_* operations
func - Function to perform (PCIAccessRegFlags)
RETURNS:
Value read from configuration register for PCI_READ_* operations
REMARKS:
Accesses a PCI configuration space register by decoding the value currently
stored in the _BE_env.configAddress variable and passing it through to the
portable PCI_accessReg function.
****************************************************************************/
static u32 BE_accessReg(int regOffset, u32 value, int func)
{
#ifdef __KERNEL__
int function, device, bus;
u8 val8;
u16 val16;
u32 val32;
/* Decode the configuration register values for the register we wish to
* access
*/
regOffset += (_BE_env.configAddress & 0xFF);
function = (_BE_env.configAddress >> 8) & 0x7;
device = (_BE_env.configAddress >> 11) & 0x1F;
bus = (_BE_env.configAddress >> 16) & 0xFF;
/* Ignore accesses to all devices other than the one we're POSTing */
if ((function == _BE_env.vgaInfo.function) &&
(device == _BE_env.vgaInfo.device) &&
(bus == _BE_env.vgaInfo.bus)) {
switch (func) {
case REG_READ_BYTE:
pci_read_config_byte(_BE_env.vgaInfo.pcidev, regOffset,
&val8);
return val8;
case REG_READ_WORD:
pci_read_config_word(_BE_env.vgaInfo.pcidev, regOffset,
&val16);
return val16;
case REG_READ_DWORD:
pci_read_config_dword(_BE_env.vgaInfo.pcidev, regOffset,
&val32);
return val32;
case REG_WRITE_BYTE:
pci_write_config_byte(_BE_env.vgaInfo.pcidev, regOffset,
value);
return 0;
case REG_WRITE_WORD:
pci_write_config_word(_BE_env.vgaInfo.pcidev, regOffset,
value);
return 0;
case REG_WRITE_DWORD:
pci_write_config_dword(_BE_env.vgaInfo.pcidev,
regOffset, value);
return 0;
}
}
return 0;
#else
PCIDeviceInfo pciInfo;
pciInfo.mech1 = 1;
pciInfo.slot.i = 0;
pciInfo.slot.p.Function = (_BE_env.configAddress >> 8) & 0x7;
pciInfo.slot.p.Device = (_BE_env.configAddress >> 11) & 0x1F;
pciInfo.slot.p.Bus = (_BE_env.configAddress >> 16) & 0xFF;
pciInfo.slot.p.Enable = 1;
/* Ignore accesses to all devices other than the one we're POSTing */
if ((pciInfo.slot.p.Function ==
_BE_env.vgaInfo.pciInfo->slot.p.Function)
&& (pciInfo.slot.p.Device == _BE_env.vgaInfo.pciInfo->slot.p.Device)
&& (pciInfo.slot.p.Bus == _BE_env.vgaInfo.pciInfo->slot.p.Bus))
return PCI_accessReg((_BE_env.configAddress & 0xFF) + regOffset,
value, func, &pciInfo);
return 0;
#endif
}
/****************************************************************************
PARAMETERS:
port - Port to read from
type - Type of access to perform
REMARKS:
Performs an emulated read from one of the PCI configuration space registers.
We emulate this using our PCI_accessReg function which will access the PCI
configuration space registers in a portable fashion.
****************************************************************************/
static u32 PCI_inp(int port, int type)
{
switch (type) {
case REG_READ_BYTE:
if ((_BE_env.configAddress & 0x80000000) && 0xCFC <= port
&& port <= 0xCFF)
return BE_accessReg(port - 0xCFC, 0, REG_READ_BYTE);
break;
case REG_READ_WORD:
if ((_BE_env.configAddress & 0x80000000) && 0xCFC <= port
&& port <= 0xCFF)
return BE_accessReg(port - 0xCFC, 0, REG_READ_WORD);
break;
case REG_READ_DWORD:
if (port == 0xCF8)
return _BE_env.configAddress;
else if ((_BE_env.configAddress & 0x80000000) && port == 0xCFC)
return BE_accessReg(0, 0, REG_READ_DWORD);
break;
}
return 0;
}
/****************************************************************************
PARAMETERS:
port - Port to write to
type - Type of access to perform
REMARKS:
Performs an emulated write to one of the PCI control registers.
****************************************************************************/
static void PCI_outp(int port, u32 val, int type)
{
switch (type) {
case REG_WRITE_BYTE:
if ((_BE_env.configAddress & 0x80000000) && 0xCFC <= port
&& port <= 0xCFF)
BE_accessReg(port - 0xCFC, val, REG_WRITE_BYTE);
break;
case REG_WRITE_WORD:
if ((_BE_env.configAddress & 0x80000000) && 0xCFC <= port
&& port <= 0xCFF)
BE_accessReg(port - 0xCFC, val, REG_WRITE_WORD);
break;
case REG_WRITE_DWORD:
if (port == 0xCF8)
{
_BE_env.configAddress = val & 0x80FFFFFC;
}
else if ((_BE_env.configAddress & 0x80000000) && port == 0xCFC)
BE_accessReg(0, val, REG_WRITE_DWORD);
break;
}
}
#endif
/****************************************************************************
PARAMETERS:
port - Port to write to
RETURNS:
Value read from the I/O port
REMARKS:
Performs an emulated 8-bit read from an I/O port. We handle special cases
that we need to emulate in here, and fall through to reflecting the write
through to the real hardware if we don't need to special case it.
****************************************************************************/
u8 X86API BE_inb(X86EMU_pioAddr port)
{
u8 val = 0;
#if defined(DEBUG) || !defined(__i386__)
if (IS_VGA_PORT(port)){
/*seems reading port 0x3c3 return the high 16 bit of io port*/
if(port == 0x3c3)
val = LOG_inpb(port);
else
val = VGA_inpb(port);
}
else if (IS_TIMER_PORT(port))
DB(printf("Can not interept TIMER port now!\n");)
else if (IS_SPKR_PORT(port))
DB(printf("Can not interept SPEAKER port now!\n");)
else if (IS_CMOS_PORT(port))
DB(printf("Can not interept CMOS port now!\n");)
else if (IS_PCI_PORT(port))
val = PCI_inp(port, REG_READ_BYTE);
else if (port < 0x100) {
DB(printf("WARN: INVALID inb.%04X -> %02X\n", (u16) port, val);)
val = LOG_inpb(port);
} else
#endif
val = LOG_inpb(port);
return val;
}
/****************************************************************************
PARAMETERS:
port - Port to write to
RETURNS:
Value read from the I/O port
REMARKS:
Performs an emulated 16-bit read from an I/O port. We handle special cases
that we need to emulate in here, and fall through to reflecting the write
through to the real hardware if we don't need to special case it.
****************************************************************************/
u16 X86API BE_inw(X86EMU_pioAddr port)
{
u16 val = 0;
#if defined(DEBUG) || !defined(__i386__)
if (IS_PCI_PORT(port))
val = PCI_inp(port, REG_READ_WORD);
else if (port < 0x100) {
DB(printf("WARN: Maybe INVALID inw.%04X -> %04X\n", (u16) port, val);)
val = LOG_inpw(port);
} else
#endif
val = LOG_inpw(port);
return val;
}
/****************************************************************************
PARAMETERS:
port - Port to write to
RETURNS:
Value read from the I/O port
REMARKS:
Performs an emulated 32-bit read from an I/O port. We handle special cases
that we need to emulate in here, and fall through to reflecting the write
through to the real hardware if we don't need to special case it.
****************************************************************************/
u32 X86API BE_inl(X86EMU_pioAddr port)
{
u32 val = 0;
#if defined(DEBUG) || !defined(__i386__)
if (IS_PCI_PORT(port))
val = PCI_inp(port, REG_READ_DWORD);
else if (port < 0x100) {
val = LOG_inpd(port);
} else
#endif
val = LOG_inpd(port);
return val;
}
/****************************************************************************
PARAMETERS:
port - Port to write to
val - Value to write to port
REMARKS:
Performs an emulated 8-bit write to an I/O port. We handle special cases
that we need to emulate in here, and fall through to reflecting the write
through to the real hardware if we don't need to special case it.
****************************************************************************/
void X86API BE_outb(X86EMU_pioAddr port, u8 val)
{
#if defined(DEBUG) || !defined(__i386__)
if (IS_VGA_PORT(port))
VGA_outpb(port, val);
else if (IS_TIMER_PORT(port))
DB(printf("Can not interept TIMER port now!\n");)
else if (IS_SPKR_PORT(port))
DB(printf("Can not interept SPEAKER port now!\n");)
else if (IS_CMOS_PORT(port))
DB(printf("Can not interept CMOS port now!\n");)
else if (IS_PCI_PORT(port))
PCI_outp(port, val, REG_WRITE_BYTE);
else if (port < 0x100) {
DB(printf("WARN:Maybe INVALID outb.%04X <- %02X\n", (u16) port, val);)
LOG_outpb(port, val);
} else
#endif
LOG_outpb(port, val);
}
/****************************************************************************
PARAMETERS:
port - Port to write to
val - Value to write to port
REMARKS:
Performs an emulated 16-bit write to an I/O port. We handle special cases
that we need to emulate in here, and fall through to reflecting the write
through to the real hardware if we don't need to special case it.
****************************************************************************/
void X86API BE_outw(X86EMU_pioAddr port, u16 val)
{
#if defined(DEBUG) || !defined(__i386__)
if (IS_VGA_PORT(port)) {
VGA_outpb(port, val);
VGA_outpb(port + 1, val >> 8);
} else if (IS_PCI_PORT(port))
PCI_outp(port, val, REG_WRITE_WORD);
else if (port < 0x100) {
DB(printf("WARN: MAybe INVALID outw.%04X <- %04X\n", (u16) port,
val);)
LOG_outpw(port, val);
} else
#endif
LOG_outpw(port, val);
}
/****************************************************************************
PARAMETERS:
port - Port to write to
val - Value to write to port
REMARKS:
Performs an emulated 32-bit write to an I/O port. We handle special cases
that we need to emulate in here, and fall through to reflecting the write
through to the real hardware if we don't need to special case it.
****************************************************************************/
void X86API BE_outl(X86EMU_pioAddr port, u32 val)
{
#if defined(DEBUG) || !defined(__i386__)
if (IS_PCI_PORT(port))
PCI_outp(port, val, REG_WRITE_DWORD);
else if (port < 0x100) {
DB(printf("WARN: INVALID outl.%04X <- %08X\n", (u16) port,val);)
LOG_outpd(port, val);
} else
#endif
LOG_outpd(port, val);
}

View file

@ -0,0 +1,321 @@
/****************************************************************************
*
* BIOS emulator and interface
* to Realmode X86 Emulator Library
*
* Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved.
* Jason Jin <Jason.jin@freescale.com>
*
* Copyright (C) 1996-1999 SciTech Software, Inc.
*
* ========================================================================
*
* Permission to use, copy, modify, distribute, and sell this software and
* its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and that
* both that copyright notice and this permission notice appear in
* supporting documentation, and that the name of the authors not be used
* in advertising or publicity pertaining to distribution of the software
* without specific, written prior permission. The authors makes no
* representations about the suitability of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*
* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*
* ========================================================================
*
* Language: ANSI C
* Environment: Any
* Developer: Kendall Bennett
*
* Description: Module implementing the BIOS specific functions.
*
* Jason ported this file to u-boot to run the ATI video card
* video BIOS.
*
****************************************************************************/
#include "biosemui.h"
/*----------------------------- Implementation ----------------------------*/
/****************************************************************************
PARAMETERS:
intno - Interrupt number being serviced
REMARKS:
Handler for undefined interrupts.
****************************************************************************/
static void X86API undefined_intr(int intno)
{
if (BE_rdw(intno * 4 + 2) == BIOS_SEG) {
DB(printf("biosEmu: undefined interrupt %xh called!\n", intno);)
} else
X86EMU_prepareForInt(intno);
}
/****************************************************************************
PARAMETERS:
intno - Interrupt number being serviced
REMARKS:
This function handles the default system BIOS Int 10h (the default is stored
in the Int 42h vector by the system BIOS at bootup). We only need to handle
a small number of special functions used by the BIOS during POST time.
****************************************************************************/
static void X86API int42(int intno)
{
if (M.x86.R_AH == 0x12 && M.x86.R_BL == 0x32) {
if (M.x86.R_AL == 0) {
/* Enable CPU accesses to video memory */
PM_outpb(0x3c2, PM_inpb(0x3cc) | (u8) 0x02);
return;
} else if (M.x86.R_AL == 1) {
/* Disable CPU accesses to video memory */
PM_outpb(0x3c2, PM_inpb(0x3cc) & (u8) ~ 0x02);
return;
}
#ifdef DEBUG
else {
printf("int42: unknown function AH=0x12, BL=0x32, AL=%#02x\n",
M.x86.R_AL);
}
#endif
}
#ifdef DEBUG
else {
printf("int42: unknown function AH=%#02x, AL=%#02x, BL=%#02x\n",
M.x86.R_AH, M.x86.R_AL, M.x86.R_BL);
}
#endif
}
/****************************************************************************
PARAMETERS:
intno - Interrupt number being serviced
REMARKS:
This function handles the default system BIOS Int 10h. If the POST code
has not yet re-vectored the Int 10h BIOS interrupt vector, we handle this
by simply calling the int42 interrupt handler above. Very early in the
BIOS POST process, the vector gets replaced and we simply let the real
mode interrupt handler process the interrupt.
****************************************************************************/
static void X86API int10(int intno)
{
if (BE_rdw(intno * 4 + 2) == BIOS_SEG)
int42(intno);
else
X86EMU_prepareForInt(intno);
}
/* Result codes returned by the PCI BIOS */
#define SUCCESSFUL 0x00
#define FUNC_NOT_SUPPORT 0x81
#define BAD_VENDOR_ID 0x83
#define DEVICE_NOT_FOUND 0x86
#define BAD_REGISTER_NUMBER 0x87
#define SET_FAILED 0x88
#define BUFFER_TOO_SMALL 0x89
/****************************************************************************
PARAMETERS:
intno - Interrupt number being serviced
REMARKS:
This function handles the default Int 1Ah interrupt handler for the real
mode code, which provides support for the PCI BIOS functions. Since we only
want to allow the real mode BIOS code *only* see the PCI config space for
its own device, we only return information for the specific PCI config
space that we have passed in to the init function. This solves problems
when using the BIOS to warm boot a secondary adapter when there is an
identical adapter before it on the bus (some BIOS'es get confused in this
case).
****************************************************************************/
static void X86API int1A(int unused)
{
u16 pciSlot;
#ifdef __KERNEL__
u8 interface, subclass, baseclass;
/* Initialise the PCI slot number */
pciSlot = ((int)_BE_env.vgaInfo.bus << 8) |
((int)_BE_env.vgaInfo.device << 3) | (int)_BE_env.vgaInfo.function;
#else
/* Fail if no PCI device information has been registered */
if (!_BE_env.vgaInfo.pciInfo)
return;
pciSlot = (u16) (_BE_env.vgaInfo.pciInfo->slot.i >> 8);
#endif
switch (M.x86.R_AX) {
case 0xB101: /* PCI bios present? */
M.x86.R_AL = 0x00; /* no config space/special cycle generation support */
M.x86.R_EDX = 0x20494350; /* " ICP" */
M.x86.R_BX = 0x0210; /* Version 2.10 */
M.x86.R_CL = 0; /* Max bus number in system */
CLEAR_FLAG(F_CF);
break;
case 0xB102: /* Find PCI device */
M.x86.R_AH = DEVICE_NOT_FOUND;
#ifdef __KERNEL__
if (M.x86.R_DX == _BE_env.vgaInfo.VendorID &&
M.x86.R_CX == _BE_env.vgaInfo.DeviceID && M.x86.R_SI == 0) {
#else
if (M.x86.R_DX == _BE_env.vgaInfo.pciInfo->VendorID &&
M.x86.R_CX == _BE_env.vgaInfo.pciInfo->DeviceID &&
M.x86.R_SI == 0) {
#endif
M.x86.R_AH = SUCCESSFUL;
M.x86.R_BX = pciSlot;
}
CONDITIONAL_SET_FLAG((M.x86.R_AH != SUCCESSFUL), F_CF);
break;
case 0xB103: /* Find PCI class code */
M.x86.R_AH = DEVICE_NOT_FOUND;
#ifdef __KERNEL__
pci_read_config_byte(_BE_env.vgaInfo.pcidev, PCI_CLASS_PROG,
&interface);
pci_read_config_byte(_BE_env.vgaInfo.pcidev, PCI_CLASS_DEVICE,
&subclass);
pci_read_config_byte(_BE_env.vgaInfo.pcidev,
PCI_CLASS_DEVICE + 1, &baseclass);
if (M.x86.R_CL == interface && M.x86.R_CH == subclass
&& (u8) (M.x86.R_ECX >> 16) == baseclass) {
#else
if (M.x86.R_CL == _BE_env.vgaInfo.pciInfo->Interface &&
M.x86.R_CH == _BE_env.vgaInfo.pciInfo->SubClass &&
(u8) (M.x86.R_ECX >> 16) ==
_BE_env.vgaInfo.pciInfo->BaseClass) {
#endif
M.x86.R_AH = SUCCESSFUL;
M.x86.R_BX = pciSlot;
}
CONDITIONAL_SET_FLAG((M.x86.R_AH != SUCCESSFUL), F_CF);
break;
case 0xB108: /* Read configuration byte */
M.x86.R_AH = BAD_REGISTER_NUMBER;
if (M.x86.R_BX == pciSlot) {
M.x86.R_AH = SUCCESSFUL;
#ifdef __KERNEL__
pci_read_config_byte(_BE_env.vgaInfo.pcidev, M.x86.R_DI,
&M.x86.R_CL);
#else
M.x86.R_CL =
(u8) PCI_accessReg(M.x86.R_DI, 0, PCI_READ_BYTE,
_BE_env.vgaInfo.pciInfo);
#endif
}
CONDITIONAL_SET_FLAG((M.x86.R_AH != SUCCESSFUL), F_CF);
break;
case 0xB109: /* Read configuration word */
M.x86.R_AH = BAD_REGISTER_NUMBER;
if (M.x86.R_BX == pciSlot) {
M.x86.R_AH = SUCCESSFUL;
#ifdef __KERNEL__
pci_read_config_word(_BE_env.vgaInfo.pcidev, M.x86.R_DI,
&M.x86.R_CX);
#else
M.x86.R_CX =
(u16) PCI_accessReg(M.x86.R_DI, 0, PCI_READ_WORD,
_BE_env.vgaInfo.pciInfo);
#endif
}
CONDITIONAL_SET_FLAG((M.x86.R_AH != SUCCESSFUL), F_CF);
break;
case 0xB10A: /* Read configuration dword */
M.x86.R_AH = BAD_REGISTER_NUMBER;
if (M.x86.R_BX == pciSlot) {
M.x86.R_AH = SUCCESSFUL;
#ifdef __KERNEL__
pci_read_config_dword(_BE_env.vgaInfo.pcidev,
M.x86.R_DI, &M.x86.R_ECX);
#else
M.x86.R_ECX =
(u32) PCI_accessReg(M.x86.R_DI, 0, PCI_READ_DWORD,
_BE_env.vgaInfo.pciInfo);
#endif
}
CONDITIONAL_SET_FLAG((M.x86.R_AH != SUCCESSFUL), F_CF);
break;
case 0xB10B: /* Write configuration byte */
M.x86.R_AH = BAD_REGISTER_NUMBER;
if (M.x86.R_BX == pciSlot) {
M.x86.R_AH = SUCCESSFUL;
#ifdef __KERNEL__
pci_write_config_byte(_BE_env.vgaInfo.pcidev,
M.x86.R_DI, M.x86.R_CL);
#else
PCI_accessReg(M.x86.R_DI, M.x86.R_CL, PCI_WRITE_BYTE,
_BE_env.vgaInfo.pciInfo);
#endif
}
CONDITIONAL_SET_FLAG((M.x86.R_AH != SUCCESSFUL), F_CF);
break;
case 0xB10C: /* Write configuration word */
M.x86.R_AH = BAD_REGISTER_NUMBER;
if (M.x86.R_BX == pciSlot) {
M.x86.R_AH = SUCCESSFUL;
#ifdef __KERNEL__
pci_write_config_word(_BE_env.vgaInfo.pcidev,
M.x86.R_DI, M.x86.R_CX);
#else
PCI_accessReg(M.x86.R_DI, M.x86.R_CX, PCI_WRITE_WORD,
_BE_env.vgaInfo.pciInfo);
#endif
}
CONDITIONAL_SET_FLAG((M.x86.R_AH != SUCCESSFUL), F_CF);
break;
case 0xB10D: /* Write configuration dword */
M.x86.R_AH = BAD_REGISTER_NUMBER;
if (M.x86.R_BX == pciSlot) {
M.x86.R_AH = SUCCESSFUL;
#ifdef __KERNEL__
pci_write_config_dword(_BE_env.vgaInfo.pcidev,
M.x86.R_DI, M.x86.R_ECX);
#else
PCI_accessReg(M.x86.R_DI, M.x86.R_ECX, PCI_WRITE_DWORD,
_BE_env.vgaInfo.pciInfo);
#endif
}
CONDITIONAL_SET_FLAG((M.x86.R_AH != SUCCESSFUL), F_CF);
break;
default:
printf("biosEmu/bios.int1a: unknown function AX=%#04x\n",
M.x86.R_AX);
}
}
/****************************************************************************
REMARKS:
This function initialises the BIOS emulation functions for the specific
PCI display device. We insulate the real mode BIOS from any other devices
on the bus, so that it will work correctly thinking that it is the only
device present on the bus (ie: avoiding any adapters present in from of
the device we are trying to control).
****************************************************************************/
#define BE_constLE_32(v) ((((((v)&0xff00)>>8)|(((v)&0xff)<<8))<<16)|(((((v)&0xff000000)>>8)|(((v)&0x00ff0000)<<8))>>16))
void _BE_bios_init(u32 * intrTab)
{
int i;
X86EMU_intrFuncs bios_intr_tab[256];
for (i = 0; i < 256; ++i) {
intrTab[i] = BE_constLE_32(BIOS_SEG << 16);
bios_intr_tab[i] = undefined_intr;
}
bios_intr_tab[0x10] = int10;
bios_intr_tab[0x1A] = int1A;
bios_intr_tab[0x42] = int42;
bios_intr_tab[0x6D] = int10;
X86EMU_setupIntrFuncs(bios_intr_tab);
}

View file

@ -0,0 +1,370 @@
/****************************************************************************
*
* BIOS emulator and interface
* to Realmode X86 Emulator Library
*
* Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved.
* Jason Jin <Jason.jin@freescale.com>
*
* Copyright (C) 1996-1999 SciTech Software, Inc.
*
* ========================================================================
*
* Permission to use, copy, modify, distribute, and sell this software and
* its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and that
* both that copyright notice and this permission notice appear in
* supporting documentation, and that the name of the authors not be used
* in advertising or publicity pertaining to distribution of the software
* without specific, written prior permission. The authors makes no
* representations about the suitability of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*
* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*
* ========================================================================
*
* Language: ANSI C
* Environment: Any
* Developer: Kendall Bennett
*
* Description: Module implementing the system specific functions. This
* module is always compiled and linked in the OS depedent
* libraries, and never in a binary portable driver.
*
* Jason ported this file to u-boot to run the ATI video card BIOS
* in u-boot. Made all the video memory be emulated during the
* BIOS runing process which may affect the VGA function but the
* frambuffer function can work after run the BIOS.
*
****************************************************************************/
#include "biosemui.h"
#include <malloc.h>
BE_sysEnv _BE_env = {{0}};
static X86EMU_memFuncs _BE_mem __attribute__((section(".got2"))) = {
BE_rdb,
BE_rdw,
BE_rdl,
BE_wrb,
BE_wrw,
BE_wrl,
};
static X86EMU_pioFuncs _BE_pio __attribute__((section(".got2"))) = {
BE_inb,
BE_inw,
BE_inl,
BE_outb,
BE_outw,
BE_outl,
};
#define OFF(addr) (u16)(((addr) >> 0) & 0xffff)
#define SEG(addr) (u16)(((addr) >> 4) & 0xf000)
/****************************************************************************
PARAMETERS:
debugFlags - Flags to enable debugging options (debug builds only)
memSize - Amount of memory to allocate for real mode machine
info - Pointer to default VGA device information
REMARKS:
This functions initialises the BElib, and uses the passed in
BIOS image as the BIOS that is used and emulated at 0xC0000.
****************************************************************************/
int X86API BE_init(u32 debugFlags, int memSize, BE_VGAInfo * info, int shared)
{
#if !defined(__DRIVER__) && !defined(__KERNEL__)
PM_init();
#endif
memset(&M, 0, sizeof(M));
if (memSize < 20480){
printf("Emulator requires at least 20Kb of memory!\n");
return 0;
}
M.mem_base = (unsigned long)malloc(memSize);
if (M.mem_base == NULL){
printf("Biosemu:Out of memory!");
return 0;
}
M.mem_size = memSize;
_BE_env.emulateVGA = 0;
_BE_env.busmem_base = (unsigned long)malloc(128 * 1024);
if (_BE_env.busmem_base == NULL){
printf("Biosemu:Out of memory!");
return 0;
}
M.x86.debug = debugFlags;
_BE_bios_init((u32*)info->LowMem);
X86EMU_setupMemFuncs(&_BE_mem);
X86EMU_setupPioFuncs(&_BE_pio);
BE_setVGA(info);
return 1;
}
/****************************************************************************
PARAMETERS:
info - Pointer to VGA device information to make current
REMARKS:
This function sets the VGA BIOS functions in the emulator to point to the
specific VGA BIOS in use. This includes swapping the BIOS interrupt
vectors, BIOS image and BIOS data area to the new BIOS. This allows the
real mode BIOS to be swapped without resetting the entire emulator.
****************************************************************************/
void X86API BE_setVGA(BE_VGAInfo * info)
{
#ifdef __KERNEL__
_BE_env.vgaInfo.function = info->function;
_BE_env.vgaInfo.device = info->device;
_BE_env.vgaInfo.bus = info->bus;
_BE_env.vgaInfo.pcidev = info->pcidev;
#else
_BE_env.vgaInfo.pciInfo = info->pciInfo;
#endif
_BE_env.vgaInfo.BIOSImage = info->BIOSImage;
if (info->BIOSImage) {
_BE_env.biosmem_base = (ulong) info->BIOSImage;
_BE_env.biosmem_limit = 0xC0000 + info->BIOSImageLen - 1;
} else {
_BE_env.biosmem_base = _BE_env.busmem_base + 0x20000;
_BE_env.biosmem_limit = 0xC7FFF;
}
if (*((u32 *) info->LowMem) == 0)
_BE_bios_init((u32 *) info->LowMem);
memcpy((u8 *) M.mem_base, info->LowMem, sizeof(info->LowMem));
}
/****************************************************************************
PARAMETERS:
info - Pointer to VGA device information to retrieve current
REMARKS:
This function returns the VGA BIOS functions currently active in the
emulator, so they can be restored at a later date.
****************************************************************************/
void X86API BE_getVGA(BE_VGAInfo * info)
{
#ifdef __KERNEL__
info->function = _BE_env.vgaInfo.function;
info->device = _BE_env.vgaInfo.device;
info->bus = _BE_env.vgaInfo.bus;
info->pcidev = _BE_env.vgaInfo.pcidev;
#else
info->pciInfo = _BE_env.vgaInfo.pciInfo;
#endif
info->BIOSImage = _BE_env.vgaInfo.BIOSImage;
memcpy(info->LowMem, (u8 *) M.mem_base, sizeof(info->LowMem));
}
/****************************************************************************
PARAMETERS:
r_seg - Segment for pointer to convert
r_off - Offset for pointer to convert
REMARKS:
This function maps a real mode pointer in the emulator memory to a protected
mode pointer that can be used to directly access the memory.
NOTE: The memory is *always* in little endian format, son on non-x86
systems you will need to do endian translations to access this
memory.
****************************************************************************/
void *X86API BE_mapRealPointer(uint r_seg, uint r_off)
{
u32 addr = ((u32) r_seg << 4) + r_off;
if (addr >= 0xC0000 && addr <= _BE_env.biosmem_limit) {
return (void *)(_BE_env.biosmem_base + addr - 0xC0000);
} else if (addr >= 0xA0000 && addr <= 0xFFFFF) {
return (void *)(_BE_env.busmem_base + addr - 0xA0000);
}
return (void *)(M.mem_base + addr);
}
/****************************************************************************
PARAMETERS:
len - Return the length of the VESA buffer
rseg - Place to store VESA buffer segment
roff - Place to store VESA buffer offset
REMARKS:
This function returns the address of the VESA transfer buffer in real
_BE_piomode emulator memory. The VESA transfer buffer is always 1024 bytes long,
and located at 15Kb into the start of the real mode memory (16Kb is where
we put the real mode code we execute for issuing interrupts).
NOTE: The memory is *always* in little endian format, son on non-x86
systems you will need to do endian translations to access this
memory.
****************************************************************************/
void *X86API BE_getVESABuf(uint * len, uint * rseg, uint * roff)
{
*len = 1024;
*rseg = SEG(0x03C00);
*roff = OFF(0x03C00);
return (void *)(M.mem_base + ((u32) * rseg << 4) + *roff);
}
/****************************************************************************
REMARKS:
Cleans up and exits the emulator.
****************************************************************************/
void X86API BE_exit(void)
{
free(M.mem_base);
free(_BE_env.busmem_base);
}
/****************************************************************************
PARAMETERS:
seg - Segment of code to call
off - Offset of code to call
regs - Real mode registers to load
sregs - Real mode segment registers to load
REMARKS:
This functions calls a real mode far function at the specified address,
and loads all the x86 registers from the passed in registers structure.
On exit the registers returned from the call are returned in the same
structures.
****************************************************************************/
void X86API BE_callRealMode(uint seg, uint off, RMREGS * regs, RMSREGS * sregs)
{
M.x86.R_EAX = regs->e.eax;
M.x86.R_EBX = regs->e.ebx;
M.x86.R_ECX = regs->e.ecx;
M.x86.R_EDX = regs->e.edx;
M.x86.R_ESI = regs->e.esi;
M.x86.R_EDI = regs->e.edi;
M.x86.R_DS = sregs->ds;
M.x86.R_ES = sregs->es;
M.x86.R_FS = sregs->fs;
M.x86.R_GS = sregs->gs;
((u8 *) M.mem_base)[0x4000] = 0x9A;
((u8 *) M.mem_base)[0x4001] = (u8) off;
((u8 *) M.mem_base)[0x4002] = (u8) (off >> 8);
((u8 *) M.mem_base)[0x4003] = (u8) seg;
((u8 *) M.mem_base)[0x4004] = (u8) (seg >> 8);
((u8 *) M.mem_base)[0x4005] = 0xF1; /* Illegal op-code */
M.x86.R_CS = SEG(0x04000);
M.x86.R_IP = OFF(0x04000);
M.x86.R_SS = SEG(M.mem_size - 2);
M.x86.R_SP = OFF(M.mem_size - 2) + 2;
X86EMU_exec();
regs->e.cflag = M.x86.R_EFLG & F_CF;
regs->e.eax = M.x86.R_EAX;
regs->e.ebx = M.x86.R_EBX;
regs->e.ecx = M.x86.R_ECX;
regs->e.edx = M.x86.R_EDX;
regs->e.esi = M.x86.R_ESI;
regs->e.edi = M.x86.R_EDI;
sregs->ds = M.x86.R_DS;
sregs->es = M.x86.R_ES;
sregs->fs = M.x86.R_FS;
sregs->gs = M.x86.R_GS;
}
/****************************************************************************
PARAMETERS:
intno - Interrupt number to execute
in - Real mode registers to load
out - Place to store resulting real mode registers
REMARKS:
This functions calls a real mode interrupt function at the specified address,
and loads all the x86 registers from the passed in registers structure.
On exit the registers returned from the call are returned in out stucture.
****************************************************************************/
int X86API BE_int86(int intno, RMREGS * in, RMREGS * out)
{
M.x86.R_EAX = in->e.eax;
M.x86.R_EBX = in->e.ebx;
M.x86.R_ECX = in->e.ecx;
M.x86.R_EDX = in->e.edx;
M.x86.R_ESI = in->e.esi;
M.x86.R_EDI = in->e.edi;
((u8 *) M.mem_base)[0x4000] = 0xCD;
((u8 *) M.mem_base)[0x4001] = (u8) intno;
((u8 *) M.mem_base)[0x4002] = 0xF1;
M.x86.R_CS = SEG(0x04000);
M.x86.R_IP = OFF(0x04000);
M.x86.R_SS = SEG(M.mem_size - 1);
M.x86.R_SP = OFF(M.mem_size - 1) - 1;
X86EMU_exec();
out->e.cflag = M.x86.R_EFLG & F_CF;
out->e.eax = M.x86.R_EAX;
out->e.ebx = M.x86.R_EBX;
out->e.ecx = M.x86.R_ECX;
out->e.edx = M.x86.R_EDX;
out->e.esi = M.x86.R_ESI;
out->e.edi = M.x86.R_EDI;
return out->x.ax;
}
/****************************************************************************
PARAMETERS:
intno - Interrupt number to execute
in - Real mode registers to load
out - Place to store resulting real mode registers
sregs - Real mode segment registers to load
REMARKS:
This functions calls a real mode interrupt function at the specified address,
and loads all the x86 registers from the passed in registers structure.
On exit the registers returned from the call are returned in out stucture.
****************************************************************************/
int X86API BE_int86x(int intno, RMREGS * in, RMREGS * out, RMSREGS * sregs)
{
M.x86.R_EAX = in->e.eax;
M.x86.R_EBX = in->e.ebx;
M.x86.R_ECX = in->e.ecx;
M.x86.R_EDX = in->e.edx;
M.x86.R_ESI = in->e.esi;
M.x86.R_EDI = in->e.edi;
M.x86.R_DS = sregs->ds;
M.x86.R_ES = sregs->es;
M.x86.R_FS = sregs->fs;
M.x86.R_GS = sregs->gs;
((u8 *) M.mem_base)[0x4000] = 0xCD;
((u8 *) M.mem_base)[0x4001] = (u8) intno;
((u8 *) M.mem_base)[0x4002] = 0xF1;
M.x86.R_CS = SEG(0x04000);
M.x86.R_IP = OFF(0x04000);
M.x86.R_SS = SEG(M.mem_size - 1);
M.x86.R_SP = OFF(M.mem_size - 1) - 1;
X86EMU_exec();
out->e.cflag = M.x86.R_EFLG & F_CF;
out->e.eax = M.x86.R_EAX;
out->e.ebx = M.x86.R_EBX;
out->e.ecx = M.x86.R_ECX;
out->e.edx = M.x86.R_EDX;
out->e.esi = M.x86.R_ESI;
out->e.edi = M.x86.R_EDI;
sregs->ds = M.x86.R_DS;
sregs->es = M.x86.R_ES;
sregs->fs = M.x86.R_FS;
sregs->gs = M.x86.R_GS;
return out->x.ax;
}

View file

@ -0,0 +1,169 @@
/****************************************************************************
*
* BIOS emulator and interface
* to Realmode X86 Emulator Library
*
* Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved.
* Jason Jin <Jason.jin@freescale.com>
*
* Copyright (C) 1996-1999 SciTech Software, Inc.
*
* ========================================================================
*
* Permission to use, copy, modify, distribute, and sell this software and
* its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and that
* both that copyright notice and this permission notice appear in
* supporting documentation, and that the name of the authors not be used
* in advertising or publicity pertaining to distribution of the software
* without specific, written prior permission. The authors makes no
* representations about the suitability of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*
* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*
* ========================================================================
*
* Language: ANSI C
* Environment: Any
* Developer: Kendall Bennett
*
* Description: Internal header file for the BIOS emulator library.
*
* Jason ported this file to u-boot, Added some architecture
* related Macro.
*
****************************************************************************/
#ifndef __BIOSEMUI_H
#define __BIOSEMUI_H
#include "biosemu.h"
#include <asm/io.h>
/*---------------------- Macros and type definitions ----------------------*/
#ifdef DEBUG
#define DB(x) x
#else
#define DB(x) do{}while(0);
#endif
#define BIOS_SEG 0xfff0
extern X86EMU_sysEnv _X86EMU_env;
#define M _X86EMU_env
/* Macros to read and write values to x86 emulator memory. Memory is always
* considered to be little endian, so we use macros to do endian swapping
* where necessary.
*/
#ifdef __BIG_ENDIAN__
#define readb_le(base) *((u8*)(base))
#define readw_le(base) ((u16)readb_le(base) | ((u16)readb_le((base) + 1) << 8))
#define readl_le(base) ((u32)readb_le((base) + 0) | ((u32)readb_le((base) + 1) << 8) | \
((u32)readb_le((base) + 2) << 16) | ((u32)readb_le((base) + 3) << 24))
#define writeb_le(base, v) *((u8*)(base)) = (v)
#define writew_le(base, v) writeb_le(base + 0, (v >> 0) & 0xff), \
writeb_le(base + 1, (v >> 8) & 0xff)
#define writel_le(base, v) writeb_le(base + 0, (v >> 0) & 0xff), \
writeb_le(base + 1, (v >> 8) & 0xff), \
writeb_le(base + 2, (v >> 16) & 0xff), \
writeb_le(base + 3, (v >> 24) & 0xff)
#else
#define readb_le(base) *((u8*)(base))
#define readw_le(base) *((u16*)(base))
#define readl_le(base) *((u32*)(base))
#define writeb_le(base, v) *((u8*)(base)) = (v)
#define writew_le(base, v) *((u16*)(base)) = (v)
#define writel_le(base, v) *((u32*)(base)) = (v)
#endif
/****************************************************************************
REMARKS:
Function codes passed to the emulated I/O port functions to determine the
type of operation to perform.
****************************************************************************/
typedef enum {
REG_READ_BYTE = 0,
REG_READ_WORD = 1,
REG_READ_DWORD = 2,
REG_WRITE_BYTE = 3,
REG_WRITE_WORD = 4,
REG_WRITE_DWORD = 5
} RegisterFlags;
/****************************************************************************
REMARKS:
Function codes passed to the emulated I/O port functions to determine the
type of operation to perform.
****************************************************************************/
typedef enum {
PORT_BYTE = 1,
PORT_WORD = 2,
PORT_DWORD = 3,
} PortInfoFlags;
/****************************************************************************
REMARKS:
Data structure used to describe the details for the BIOS emulator system
environment as used by the X86 emulator library.
HEADER:
biosemu.h
MEMBERS:
type - Type of port access (1 = byte, 2 = word, 3 = dword)
defVal - Default power on value
finalVal - Final value
****************************************************************************/
typedef struct {
u8 type;
u32 defVal;
u32 finalVal;
} BE_portInfo;
#define PM_inpb(port) inb(port+VIDEO_IO_OFFSET)
#define PM_inpw(port) inw(port+VIDEO_IO_OFFSET)
#define PM_inpd(port) inl(port+VIDEO_IO_OFFSET)
#define PM_outpb(port,val) outb(val,port+VIDEO_IO_OFFSET)
#define PM_outpw(port,val) outw(val,port+VIDEO_IO_OFFSET)
#define PM_outpd(port,val) outl(val,port+VIDEO_IO_OFFSET)
#define LOG_inpb(port) PM_inpb(port)
#define LOG_inpw(port) PM_inpw(port)
#define LOG_inpd(port) PM_inpd(port)
#define LOG_outpb(port,val) PM_outpb(port,val)
#define LOG_outpw(port,val) PM_outpw(port,val)
#define LOG_outpd(port,val) PM_outpd(port,val)
/*-------------------------- Function Prototypes --------------------------*/
/* bios.c */
void _BE_bios_init(u32 * intrTab);
void _BE_setup_funcs(void);
/* besys.c */
#define DEBUG_IO() (M.x86.debug & DEBUG_IO_TRACE_F)
u8 X86API BE_rdb(u32 addr);
u16 X86API BE_rdw(u32 addr);
u32 X86API BE_rdl(u32 addr);
void X86API BE_wrb(u32 addr, u8 val);
void X86API BE_wrw(u32 addr, u16 val);
void X86API BE_wrl(u32 addr, u32 val);
u8 X86API BE_inb(X86EMU_pioAddr port);
u16 X86API BE_inw(X86EMU_pioAddr port);
u32 X86API BE_inl(X86EMU_pioAddr port);
void X86API BE_outb(X86EMU_pioAddr port, u8 val);
void X86API BE_outw(X86EMU_pioAddr port, u16 val);
void X86API BE_outl(X86EMU_pioAddr port, u32 val);
#endif
/* __BIOSEMUI_H */

View file

@ -0,0 +1,392 @@
/****************************************************************************
*
* BIOS emulator and interface
* to Realmode X86 Emulator Library
*
* Copyright (C) 1996-1999 SciTech Software, Inc.
*
* ========================================================================
*
* Permission to use, copy, modify, distribute, and sell this software and
* its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and that
* both that copyright notice and this permission notice appear in
* supporting documentation, and that the name of the authors not be used
* in advertising or publicity pertaining to distribution of the software
* without specific, written prior permission. The authors makes no
* representations about the suitability of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*
* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*
* ========================================================================
*
* Language: ANSI C
* Environment: Any
* Developer: Kendall Bennett
*
* Description: Header file for the real mode x86 BIOS emulator, which is
* used to warmboot any number of VGA compatible PCI/AGP
* controllers under any OS, on any processor family that
* supports PCI. We also allow the user application to call
* real mode BIOS functions and Int 10h functions (including
* the VESA BIOS).
*
****************************************************************************/
#ifndef __BIOSEMU_H
#define __BIOSEMU_H
#ifdef __KERNEL__
#include "x86emu.h"
#else
#include "x86emu.h"
#include "pmapi.h"
#include "pcilib.h"
#endif
/*---------------------- Macros and type definitions ----------------------*/
#pragma pack(1)
#ifndef __KERNEL__
/****************************************************************************
REMARKS:
Data structure used to describe the details specific to a particular VGA
controller. This information is used to allow the VGA controller to be
swapped on the fly within the BIOS emulator.
HEADER:
biosemu.h
MEMBERS:
pciInfo - PCI device information block for the controller
BIOSImage - Pointer to a read/write copy of the BIOS image
BIOSImageLen - Length of the BIOS image
LowMem - Copy of key low memory areas
****************************************************************************/
typedef struct {
PCIDeviceInfo *pciInfo;
void *BIOSImage;
ulong BIOSImageLen;
uchar LowMem[1536];
} BE_VGAInfo;
#else
/****************************************************************************
REMARKS:
Data structure used to describe the details for the BIOS emulator system
environment as used by the X86 emulator library.
HEADER:
biosemu.h
MEMBERS:
vgaInfo - VGA BIOS information structure
biosmem_base - Base of the BIOS image
biosmem_limit - Limit of the BIOS image
busmem_base - Base of the VGA bus memory
****************************************************************************/
typedef struct {
int function;
int device;
int bus;
u32 VendorID;
u32 DeviceID;
pci_dev_t pcidev;
void *BIOSImage;
u32 BIOSImageLen;
u8 LowMem[1536];
} BE_VGAInfo;
#endif /* __KERNEL__ */
#define CRT_C 24 /* 24 CRT Controller Registers */
#define ATT_C 21 /* 21 Attribute Controller Registers */
#define GRA_C 9 /* 9 Graphics Controller Registers */
#define SEQ_C 5 /* 5 Sequencer Registers */
#define PAL_C 768 /* 768 Palette Registers */
/****************************************************************************
REMARKS:
Data structure used to describe the details for the BIOS emulator system
environment as used by the X86 emulator library.
HEADER:
biosemu.h
MEMBERS:
vgaInfo - VGA BIOS information structure
biosmem_base - Base of the BIOS image
biosmem_limit - Limit of the BIOS image
busmem_base - Base of the VGA bus memory
timer - Timer used to emulate PC timer ports
timer0 - Latched value for timer 0
timer0Latched - True if timer 0 value was just latched
timer2 - Current value for timer 2
emulateVGA - True to emulate VGA I/O and memory accesses
****************************************************************************/
typedef struct {
BE_VGAInfo vgaInfo;
ulong biosmem_base;
ulong biosmem_limit;
ulong busmem_base;
u32 timer0;
int timer0Latched;
u32 timer1;
int timer1Latched;
u32 timer2;
int timer2Latched;
int emulateVGA;
u8 emu61;
u8 emu70;
int flipFlop3C0;
u32 configAddress;
u8 emu3C0;
u8 emu3C1[ATT_C];
u8 emu3C2;
u8 emu3C4;
u8 emu3C5[SEQ_C];
u8 emu3C6;
uint emu3C7;
uint emu3C8;
u8 emu3C9[PAL_C];
u8 emu3CE;
u8 emu3CF[GRA_C];
u8 emu3D4;
u8 emu3D5[CRT_C];
u8 emu3DA;
} BE_sysEnv;
#ifdef __KERNEL__
/* Define some types when compiling for the Linux kernel that normally
* come from the SciTech PM library.
*/
/****************************************************************************
REMARKS:
Structure describing the 32-bit extended x86 CPU registers
HEADER:
pmapi.h
MEMBERS:
eax - Value of the EAX register
ebx - Value of the EBX register
ecx - Value of the ECX register
edx - Value of the EDX register
esi - Value of the ESI register
edi - Value of the EDI register
cflag - Value of the carry flag
****************************************************************************/
typedef struct {
u32 eax;
u32 ebx;
u32 ecx;
u32 edx;
u32 esi;
u32 edi;
u32 cflag;
} RMDWORDREGS;
/****************************************************************************
REMARKS:
Structure describing the 16-bit x86 CPU registers
HEADER:
pmapi.h
MEMBERS:
ax - Value of the AX register
bx - Value of the BX register
cx - Value of the CX register
dx - Value of the DX register
si - Value of the SI register
di - Value of the DI register
cflag - Value of the carry flag
****************************************************************************/
#ifdef __BIG_ENDIAN__
typedef struct {
u16 ax_hi, ax;
u16 bx_hi, bx;
u16 cx_hi, cx;
u16 dx_hi, dx;
u16 si_hi, si;
u16 di_hi, di;
u16 cflag_hi, cflag;
} RMWORDREGS;
#else
typedef struct {
u16 ax, ax_hi;
u16 bx, bx_hi;
u16 cx, cx_hi;
u16 dx, dx_hi;
u16 si, si_hi;
u16 di, di_hi;
u16 cflag, cflag_hi;
} RMWORDREGS;
#endif
/****************************************************************************
REMARKS:
Structure describing the 8-bit x86 CPU registers
HEADER:
pmapi.h
MEMBERS:
al - Value of the AL register
ah - Value of the AH register
bl - Value of the BL register
bh - Value of the BH register
cl - Value of the CL register
ch - Value of the CH register
dl - Value of the DL register
dh - Value of the DH register
****************************************************************************/
#ifdef __BIG_ENDIAN__
typedef struct {
u16 ax_hi;
u8 ah, al;
u16 bx_hi;
u8 bh, bl;
u16 cx_hi;
u8 ch, cl;
u16 dx_hi;
u8 dh, dl;
} RMBYTEREGS;
#else
typedef struct {
u8 al;
u8 ah;
u16 ax_hi;
u8 bl;
u8 bh;
u16 bx_hi;
u8 cl;
u8 ch;
u16 cx_hi;
u8 dl;
u8 dh;
u16 dx_hi;
} RMBYTEREGS;
#endif
/****************************************************************************
REMARKS:
Structure describing all the x86 CPU registers
HEADER:
pmapi.h
MEMBERS:
e - Member to access registers as 32-bit values
x - Member to access registers as 16-bit values
h - Member to access registers as 8-bit values
****************************************************************************/
typedef union {
RMDWORDREGS e;
RMWORDREGS x;
RMBYTEREGS h;
} RMREGS;
/****************************************************************************
REMARKS:
Structure describing all the x86 segment registers
HEADER:
pmapi.h
MEMBERS:
es - ES segment register
cs - CS segment register
ss - SS segment register
ds - DS segment register
fs - FS segment register
gs - GS segment register
****************************************************************************/
typedef struct {
u16 es;
u16 cs;
u16 ss;
u16 ds;
u16 fs;
u16 gs;
} RMSREGS;
#endif /* __KERNEL__ */
#ifndef __KERNEL__
/****************************************************************************
REMARKS:
Structure defining all the BIOS Emulator API functions as exported from
the Binary Portable DLL.
{secret}
****************************************************************************/
typedef struct {
ulong dwSize;
ibool(PMAPIP BE_init) (u32 debugFlags, int memSize, BE_VGAInfo * info);
void (PMAPIP BE_setVGA) (BE_VGAInfo * info);
void (PMAPIP BE_getVGA) (BE_VGAInfo * info);
void *(PMAPIP BE_mapRealPointer) (uint r_seg, uint r_off);
void *(PMAPIP BE_getVESABuf) (uint * len, uint * rseg, uint * roff);
void (PMAPIP BE_callRealMode) (uint seg, uint off, RMREGS * regs,
RMSREGS * sregs);
int (PMAPIP BE_int86) (int intno, RMREGS * in, RMREGS * out);
int (PMAPIP BE_int86x) (int intno, RMREGS * in, RMREGS * out,
RMSREGS * sregs);
void *reserved1;
void (PMAPIP BE_exit) (void);
} BE_exports;
/****************************************************************************
REMARKS:
Function pointer type for the Binary Portable DLL initialisation entry point.
{secret}
****************************************************************************/
typedef BE_exports *(PMAPIP BE_initLibrary_t) (PM_imports * PMImp);
#endif
#pragma pack()
/*---------------------------- Global variables ---------------------------*/
#ifdef __cplusplus
extern "C" { /* Use "C" linkage when in C++ mode */
#endif
/* {secret} Global BIOS emulator system environment */
extern BE_sysEnv _BE_env;
/*-------------------------- Function Prototypes --------------------------*/
/* BIOS emulator library entry points */
int X86API BE_init(u32 debugFlags, int memSize, BE_VGAInfo * info,
int shared);
void X86API BE_setVGA(BE_VGAInfo * info);
void X86API BE_getVGA(BE_VGAInfo * info);
void X86API BE_setDebugFlags(u32 debugFlags);
void *X86API BE_mapRealPointer(uint r_seg, uint r_off);
void *X86API BE_getVESABuf(uint * len, uint * rseg, uint * roff);
void X86API BE_callRealMode(uint seg, uint off, RMREGS * regs,
RMSREGS * sregs);
int X86API BE_int86(int intno, RMREGS * in, RMREGS * out);
int X86API BE_int86x(int intno, RMREGS * in, RMREGS * out,
RMSREGS * sregs);
void X86API BE_exit(void);
#ifdef __cplusplus
} /* End of "C" linkage for C++ */
#endif
#endif /* __BIOSEMU_H */

View file

@ -0,0 +1,191 @@
/****************************************************************************
*
* Realmode X86 Emulator Library
*
* Copyright (C) 1996-1999 SciTech Software, Inc.
* Copyright (C) David Mosberger-Tang
* Copyright (C) 1999 Egbert Eich
*
* ========================================================================
*
* Permission to use, copy, modify, distribute, and sell this software and
* its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and that
* both that copyright notice and this permission notice appear in
* supporting documentation, and that the name of the authors not be used
* in advertising or publicity pertaining to distribution of the software
* without specific, written prior permission. The authors makes no
* representations about the suitability of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*
* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*
* ========================================================================
*
* Language: ANSI C
* Environment: Any
* Developer: Kendall Bennett
*
* Description: Header file for public specific functions.
* Any application linking against us should only
* include this header
*
****************************************************************************/
#ifndef __X86EMU_X86EMU_H
#define __X86EMU_X86EMU_H
#include <asm/types.h>
#include <common.h>
#include <pci.h>
#include <asm/io.h>
#define X86API
#define X86APIP *
typedef u16 X86EMU_pioAddr;
#include "x86emu/regs.h"
/*---------------------- Macros and type definitions ----------------------*/
#pragma pack(1)
/****************************************************************************
REMARKS:
Data structure containing ponters to programmed I/O functions used by the
emulator. This is used so that the user program can hook all programmed
I/O for the emulator to handled as necessary by the user program. By
default the emulator contains simple functions that do not do access the
hardware in any way. To allow the emualtor access the hardware, you will
need to override the programmed I/O functions using the X86EMU_setupPioFuncs
function.
HEADER:
x86emu.h
MEMBERS:
inb - Function to read a byte from an I/O port
inw - Function to read a word from an I/O port
inl - Function to read a dword from an I/O port
outb - Function to write a byte to an I/O port
outw - Function to write a word to an I/O port
outl - Function to write a dword to an I/O port
****************************************************************************/
typedef struct {
u8(X86APIP inb) (X86EMU_pioAddr addr);
u16(X86APIP inw) (X86EMU_pioAddr addr);
u32(X86APIP inl) (X86EMU_pioAddr addr);
void (X86APIP outb) (X86EMU_pioAddr addr, u8 val);
void (X86APIP outw) (X86EMU_pioAddr addr, u16 val);
void (X86APIP outl) (X86EMU_pioAddr addr, u32 val);
} X86EMU_pioFuncs;
/****************************************************************************
REMARKS:
Data structure containing ponters to memory access functions used by the
emulator. This is used so that the user program can hook all memory
access functions as necessary for the emulator. By default the emulator
contains simple functions that only access the internal memory of the
emulator. If you need specialised functions to handle access to different
types of memory (ie: hardware framebuffer accesses and BIOS memory access
etc), you will need to override this using the X86EMU_setupMemFuncs
function.
HEADER:
x86emu.h
MEMBERS:
rdb - Function to read a byte from an address
rdw - Function to read a word from an address
rdl - Function to read a dword from an address
wrb - Function to write a byte to an address
wrw - Function to write a word to an address
wrl - Function to write a dword to an address
****************************************************************************/
typedef struct {
u8(X86APIP rdb) (u32 addr);
u16(X86APIP rdw) (u32 addr);
u32(X86APIP rdl) (u32 addr);
void (X86APIP wrb) (u32 addr, u8 val);
void (X86APIP wrw) (u32 addr, u16 val);
void (X86APIP wrl) (u32 addr, u32 val);
} X86EMU_memFuncs;
/****************************************************************************
Here are the default memory read and write
function in case they are needed as fallbacks.
***************************************************************************/
extern u8 X86API rdb(u32 addr);
extern u16 X86API rdw(u32 addr);
extern u32 X86API rdl(u32 addr);
extern void X86API wrb(u32 addr, u8 val);
extern void X86API wrw(u32 addr, u16 val);
extern void X86API wrl(u32 addr, u32 val);
#pragma pack()
/*--------------------- type definitions -----------------------------------*/
typedef void (X86APIP X86EMU_intrFuncs) (int num);
extern X86EMU_intrFuncs _X86EMU_intrTab[256];
/*-------------------------- Function Prototypes --------------------------*/
#ifdef __cplusplus
extern "C" { /* Use "C" linkage when in C++ mode */
#endif
void X86EMU_setupMemFuncs(X86EMU_memFuncs * funcs);
void X86EMU_setupPioFuncs(X86EMU_pioFuncs * funcs);
void X86EMU_setupIntrFuncs(X86EMU_intrFuncs funcs[]);
void X86EMU_prepareForInt(int num);
/* decode.c */
void X86EMU_exec(void);
void X86EMU_halt_sys(void);
#ifdef DEBUG
#define HALT_SYS() \
printf("halt_sys: file %s, line %d\n", __FILE__, __LINE__), \
X86EMU_halt_sys()
#else
#define HALT_SYS() X86EMU_halt_sys()
#endif
/* Debug options */
#define DEBUG_DECODE_F 0x0001 /* print decoded instruction */
#define DEBUG_TRACE_F 0x0002 /* dump regs before/after execution */
#define DEBUG_STEP_F 0x0004
#define DEBUG_DISASSEMBLE_F 0x0008
#define DEBUG_BREAK_F 0x0010
#define DEBUG_SVC_F 0x0020
#define DEBUG_SAVE_CS_IP 0x0040
#define DEBUG_FS_F 0x0080
#define DEBUG_PROC_F 0x0100
#define DEBUG_SYSINT_F 0x0200 /* bios system interrupts. */
#define DEBUG_TRACECALL_F 0x0400
#define DEBUG_INSTRUMENT_F 0x0800
#define DEBUG_MEM_TRACE_F 0x1000
#define DEBUG_IO_TRACE_F 0x2000
#define DEBUG_TRACECALL_REGS_F 0x4000
#define DEBUG_DECODE_NOPRINT_F 0x8000
#define DEBUG_EXIT 0x10000
#define DEBUG_SYS_F (DEBUG_SVC_F|DEBUG_FS_F|DEBUG_PROC_F)
void X86EMU_trace_regs(void);
void X86EMU_trace_xregs(void);
void X86EMU_dump_memory(u16 seg, u16 off, u32 amt);
int X86EMU_trace_on(void);
int X86EMU_trace_off(void);
#ifdef __cplusplus
} /* End of "C" linkage for C++ */
#endif
#endif /* __X86EMU_X86EMU_H */

View file

@ -0,0 +1,209 @@
/****************************************************************************
*
* Realmode X86 Emulator Library
*
* Copyright (C) 1991-2004 SciTech Software, Inc.
* Copyright (C) David Mosberger-Tang
* Copyright (C) 1999 Egbert Eich
*
* ========================================================================
*
* Permission to use, copy, modify, distribute, and sell this software and
* its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and that
* both that copyright notice and this permission notice appear in
* supporting documentation, and that the name of the authors not be used
* in advertising or publicity pertaining to distribution of the software
* without specific, written prior permission. The authors makes no
* representations about the suitability of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*
* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*
* ========================================================================
*
* Language: ANSI C
* Environment: Any
* Developer: Kendall Bennett
*
* Description: Header file for debug definitions.
*
****************************************************************************/
#ifndef __X86EMU_DEBUG_H
#define __X86EMU_DEBUG_H
/*---------------------- Macros and type definitions ----------------------*/
/* checks to be enabled for "runtime" */
#define CHECK_IP_FETCH_F 0x1
#define CHECK_SP_ACCESS_F 0x2
#define CHECK_MEM_ACCESS_F 0x4 /*using regular linear pointer */
#define CHECK_DATA_ACCESS_F 0x8 /*using segment:offset */
#ifdef DEBUG
# define CHECK_IP_FETCH() (M.x86.check & CHECK_IP_FETCH_F)
# define CHECK_SP_ACCESS() (M.x86.check & CHECK_SP_ACCESS_F)
# define CHECK_MEM_ACCESS() (M.x86.check & CHECK_MEM_ACCESS_F)
# define CHECK_DATA_ACCESS() (M.x86.check & CHECK_DATA_ACCESS_F)
#else
# define CHECK_IP_FETCH()
# define CHECK_SP_ACCESS()
# define CHECK_MEM_ACCESS()
# define CHECK_DATA_ACCESS()
#endif
#ifdef DEBUG
# define DEBUG_INSTRUMENT() (M.x86.debug & DEBUG_INSTRUMENT_F)
# define DEBUG_DECODE() (M.x86.debug & DEBUG_DECODE_F)
# define DEBUG_TRACE() (M.x86.debug & DEBUG_TRACE_F)
# define DEBUG_STEP() (M.x86.debug & DEBUG_STEP_F)
# define DEBUG_DISASSEMBLE() (M.x86.debug & DEBUG_DISASSEMBLE_F)
# define DEBUG_BREAK() (M.x86.debug & DEBUG_BREAK_F)
# define DEBUG_SVC() (M.x86.debug & DEBUG_SVC_F)
# define DEBUG_SAVE_IP_CS() (M.x86.debug & DEBUG_SAVE_CS_IP)
# define DEBUG_FS() (M.x86.debug & DEBUG_FS_F)
# define DEBUG_PROC() (M.x86.debug & DEBUG_PROC_F)
# define DEBUG_SYSINT() (M.x86.debug & DEBUG_SYSINT_F)
# define DEBUG_TRACECALL() (M.x86.debug & DEBUG_TRACECALL_F)
# define DEBUG_TRACECALLREGS() (M.x86.debug & DEBUG_TRACECALL_REGS_F)
# define DEBUG_SYS() (M.x86.debug & DEBUG_SYS_F)
# define DEBUG_MEM_TRACE() (M.x86.debug & DEBUG_MEM_TRACE_F)
# define DEBUG_IO_TRACE() (M.x86.debug & DEBUG_IO_TRACE_F)
# define DEBUG_DECODE_NOPRINT() (M.x86.debug & DEBUG_DECODE_NOPRINT_F)
#else
# define DEBUG_INSTRUMENT() 0
# define DEBUG_DECODE() 0
# define DEBUG_TRACE() 0
# define DEBUG_STEP() 0
# define DEBUG_DISASSEMBLE() 0
# define DEBUG_BREAK() 0
# define DEBUG_SVC() 0
# define DEBUG_SAVE_IP_CS() 0
# define DEBUG_FS() 0
# define DEBUG_PROC() 0
# define DEBUG_SYSINT() 0
# define DEBUG_TRACECALL() 0
# define DEBUG_TRACECALLREGS() 0
# define DEBUG_SYS() 0
# define DEBUG_MEM_TRACE() 0
# define DEBUG_IO_TRACE() 0
# define DEBUG_DECODE_NOPRINT() 0
#endif
#ifdef DEBUG
# define DECODE_PRINTF(x) if (DEBUG_DECODE()) \
x86emu_decode_printf(x)
# define DECODE_PRINTF2(x,y) if (DEBUG_DECODE()) \
x86emu_decode_printf2(x,y)
/*
* The following allow us to look at the bytes of an instruction. The
* first INCR_INSTRN_LEN, is called everytime bytes are consumed in
* the decoding process. The SAVE_IP_CS is called initially when the
* major opcode of the instruction is accessed.
*/
#define INC_DECODED_INST_LEN(x) \
if (DEBUG_DECODE()) \
x86emu_inc_decoded_inst_len(x)
#define SAVE_IP_CS(x,y) \
if (DEBUG_DECODE() | DEBUG_TRACECALL() | DEBUG_BREAK() \
| DEBUG_IO_TRACE() | DEBUG_SAVE_IP_CS()) { \
M.x86.saved_cs = x; \
M.x86.saved_ip = y; \
}
#else
# define INC_DECODED_INST_LEN(x)
# define DECODE_PRINTF(x)
# define DECODE_PRINTF2(x,y)
# define SAVE_IP_CS(x,y)
#endif
#ifdef DEBUG
#define TRACE_REGS() \
if (DEBUG_DISASSEMBLE()) { \
x86emu_just_disassemble(); \
goto EndOfTheInstructionProcedure; \
} \
if (DEBUG_TRACE() || DEBUG_DECODE()) X86EMU_trace_regs()
#else
# define TRACE_REGS()
#endif
#ifdef DEBUG
# define SINGLE_STEP() if (DEBUG_STEP()) x86emu_single_step()
#else
# define SINGLE_STEP()
#endif
#define TRACE_AND_STEP() \
TRACE_REGS(); \
SINGLE_STEP()
#ifdef DEBUG
# define START_OF_INSTR()
# define END_OF_INSTR() EndOfTheInstructionProcedure: x86emu_end_instr();
# define END_OF_INSTR_NO_TRACE() x86emu_end_instr();
#else
# define START_OF_INSTR()
# define END_OF_INSTR()
# define END_OF_INSTR_NO_TRACE()
#endif
#ifdef DEBUG
# define CALL_TRACE(u,v,w,x,s) \
if (DEBUG_TRACECALLREGS()) \
x86emu_dump_regs(); \
if (DEBUG_TRACECALL()) \
printk("%04x:%04x: CALL %s%04x:%04x\n", u , v, s, w, x);
# define RETURN_TRACE(n,u,v) \
if (DEBUG_TRACECALLREGS()) \
x86emu_dump_regs(); \
if (DEBUG_TRACECALL()) \
printk("%04x:%04x: %s\n",u,v,n);
#else
# define CALL_TRACE(u,v,w,x,s)
# define RETURN_TRACE(n,u,v)
#endif
#ifdef DEBUG
#define DB(x) x
#else
#define DB(x)
#endif
/*-------------------------- Function Prototypes --------------------------*/
#ifdef __cplusplus
extern "C" { /* Use "C" linkage when in C++ mode */
#endif
extern void x86emu_inc_decoded_inst_len(int x);
extern void x86emu_decode_printf(char *x);
extern void x86emu_decode_printf2(char *x, int y);
extern void x86emu_just_disassemble(void);
extern void x86emu_single_step(void);
extern void x86emu_end_instr(void);
extern void x86emu_dump_regs(void);
extern void x86emu_dump_xregs(void);
extern void x86emu_print_int_vect(u16 iv);
extern void x86emu_instrument_instruction(void);
extern void x86emu_check_ip_access(void);
extern void x86emu_check_sp_access(void);
extern void x86emu_check_mem_access(u32 p);
extern void x86emu_check_data_access(uint s, uint o);
#ifdef __cplusplus
} /* End of "C" linkage for C++ */
#endif
#endif /* __X86EMU_DEBUG_H */

View file

@ -0,0 +1,88 @@
/****************************************************************************
*
* Realmode X86 Emulator Library
*
* Copyright (C) 1991-2004 SciTech Software, Inc.
* Copyright (C) David Mosberger-Tang
* Copyright (C) 1999 Egbert Eich
*
* ========================================================================
*
* Permission to use, copy, modify, distribute, and sell this software and
* its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and that
* both that copyright notice and this permission notice appear in
* supporting documentation, and that the name of the authors not be used
* in advertising or publicity pertaining to distribution of the software
* without specific, written prior permission. The authors makes no
* representations about the suitability of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*
* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*
* ========================================================================
*
* Language: ANSI C
* Environment: Any
* Developer: Kendall Bennett
*
* Description: Header file for instruction decoding logic.
*
****************************************************************************/
#ifndef __X86EMU_DECODE_H
#define __X86EMU_DECODE_H
/*---------------------- Macros and type definitions ----------------------*/
/* Instruction Decoding Stuff */
#define FETCH_DECODE_MODRM(mod,rh,rl) fetch_decode_modrm(&mod,&rh,&rl)
#define DECODE_RM_BYTE_REGISTER(r) decode_rm_byte_register(r)
#define DECODE_RM_WORD_REGISTER(r) decode_rm_word_register(r)
#define DECODE_RM_LONG_REGISTER(r) decode_rm_long_register(r)
#define DECODE_CLEAR_SEGOVR() M.x86.mode &= ~SYSMODE_CLRMASK
/*-------------------------- Function Prototypes --------------------------*/
#ifdef __cplusplus
extern "C" { /* Use "C" linkage when in C++ mode */
#endif
void x86emu_intr_raise (u8 type);
void fetch_decode_modrm (int *mod,int *regh,int *regl);
u8 fetch_byte_imm (void);
u16 fetch_word_imm (void);
u32 fetch_long_imm (void);
u8 fetch_data_byte (uint offset);
u8 fetch_data_byte_abs (uint segment, uint offset);
u16 fetch_data_word (uint offset);
u16 fetch_data_word_abs (uint segment, uint offset);
u32 fetch_data_long (uint offset);
u32 fetch_data_long_abs (uint segment, uint offset);
void store_data_byte (uint offset, u8 val);
void store_data_byte_abs (uint segment, uint offset, u8 val);
void store_data_word (uint offset, u16 val);
void store_data_word_abs (uint segment, uint offset, u16 val);
void store_data_long (uint offset, u32 val);
void store_data_long_abs (uint segment, uint offset, u32 val);
u8* decode_rm_byte_register(int reg);
u16* decode_rm_word_register(int reg);
u32* decode_rm_long_register(int reg);
u16* decode_rm_seg_register(int reg);
unsigned decode_rm00_address(int rm);
unsigned decode_rm01_address(int rm);
unsigned decode_rm10_address(int rm);
unsigned decode_rmXX_address(int mod, int rm);
#ifdef __cplusplus
} /* End of "C" linkage for C++ */
#endif
#endif /* __X86EMU_DECODE_H */

View file

@ -0,0 +1,45 @@
/****************************************************************************
*
* Realmode X86 Emulator Library
*
* Copyright (C) 1991-2004 SciTech Software, Inc.
* Copyright (C) David Mosberger-Tang
* Copyright (C) 1999 Egbert Eich
*
* ========================================================================
*
* Permission to use, copy, modify, distribute, and sell this software and
* its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and that
* both that copyright notice and this permission notice appear in
* supporting documentation, and that the name of the authors not be used
* in advertising or publicity pertaining to distribution of the software
* without specific, written prior permission. The authors makes no
* representations about the suitability of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*
* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*
* ========================================================================
*
* Language: ANSI C
* Environment: Any
* Developer: Kendall Bennett
*
* Description: Header file for operand decoding functions.
*
****************************************************************************/
#ifndef __X86EMU_OPS_H
#define __X86EMU_OPS_H
extern void (*x86emu_optab[0x100])(u8 op1);
extern void (*x86emu_optab2[0x100])(u8 op2);
#endif /* __X86EMU_OPS_H */

View file

@ -0,0 +1,970 @@
/****************************************************************************
*
* Realmode X86 Emulator Library
*
* Copyright (C) 1991-2004 SciTech Software, Inc.
* Copyright (C) David Mosberger-Tang
* Copyright (C) 1999 Egbert Eich
*
* ========================================================================
*
* Permission to use, copy, modify, distribute, and sell this software and
* its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and that
* both that copyright notice and this permission notice appear in
* supporting documentation, and that the name of the authors not be used
* in advertising or publicity pertaining to distribution of the software
* without specific, written prior permission. The authors makes no
* representations about the suitability of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*
* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*
* ========================================================================
*
* Language: Watcom C++ 10.6 or later
* Environment: Any
* Developer: Kendall Bennett
*
* Description: Inline assembler versions of the primitive operand
* functions for faster performance. At the moment this is
* x86 inline assembler, but these functions could be replaced
* with native inline assembler for each supported processor
* platform.
*
****************************************************************************/
#ifndef __X86EMU_PRIM_ASM_H
#define __X86EMU_PRIM_ASM_H
#ifdef __WATCOMC__
#ifndef VALIDATE
#define __HAVE_INLINE_ASSEMBLER__
#endif
u32 get_flags_asm(void);
#pragma aux get_flags_asm = \
"pushf" \
"pop eax" \
value [eax] \
modify exact [eax];
u16 aaa_word_asm(u32 * flags, u16 d);
#pragma aux aaa_word_asm = \
"push [edi]" \
"popf" \
"aaa" \
"pushf" \
"pop [edi]" \
parm [edi] [ax] \
value [ax] \
modify exact [ax];
u16 aas_word_asm(u32 * flags, u16 d);
#pragma aux aas_word_asm = \
"push [edi]" \
"popf" \
"aas" \
"pushf" \
"pop [edi]" \
parm [edi] [ax] \
value [ax] \
modify exact [ax];
u16 aad_word_asm(u32 * flags, u16 d);
#pragma aux aad_word_asm = \
"push [edi]" \
"popf" \
"aad" \
"pushf" \
"pop [edi]" \
parm [edi] [ax] \
value [ax] \
modify exact [ax];
u16 aam_word_asm(u32 * flags, u8 d);
#pragma aux aam_word_asm = \
"push [edi]" \
"popf" \
"aam" \
"pushf" \
"pop [edi]" \
parm [edi] [al] \
value [ax] \
modify exact [ax];
u8 adc_byte_asm(u32 * flags, u8 d, u8 s);
#pragma aux adc_byte_asm = \
"push [edi]" \
"popf" \
"adc al,bl" \
"pushf" \
"pop [edi]" \
parm [edi] [al] [bl] \
value [al] \
modify exact [al bl];
u16 adc_word_asm(u32 * flags, u16 d, u16 s);
#pragma aux adc_word_asm = \
"push [edi]" \
"popf" \
"adc ax,bx" \
"pushf" \
"pop [edi]" \
parm [edi] [ax] [bx] \
value [ax] \
modify exact [ax bx];
u32 adc_long_asm(u32 * flags, u32 d, u32 s);
#pragma aux adc_long_asm = \
"push [edi]" \
"popf" \
"adc eax,ebx" \
"pushf" \
"pop [edi]" \
parm [edi] [eax] [ebx] \
value [eax] \
modify exact [eax ebx];
u8 add_byte_asm(u32 * flags, u8 d, u8 s);
#pragma aux add_byte_asm = \
"push [edi]" \
"popf" \
"add al,bl" \
"pushf" \
"pop [edi]" \
parm [edi] [al] [bl] \
value [al] \
modify exact [al bl];
u16 add_word_asm(u32 * flags, u16 d, u16 s);
#pragma aux add_word_asm = \
"push [edi]" \
"popf" \
"add ax,bx" \
"pushf" \
"pop [edi]" \
parm [edi] [ax] [bx] \
value [ax] \
modify exact [ax bx];
u32 add_long_asm(u32 * flags, u32 d, u32 s);
#pragma aux add_long_asm = \
"push [edi]" \
"popf" \
"add eax,ebx" \
"pushf" \
"pop [edi]" \
parm [edi] [eax] [ebx] \
value [eax] \
modify exact [eax ebx];
u8 and_byte_asm(u32 * flags, u8 d, u8 s);
#pragma aux and_byte_asm = \
"push [edi]" \
"popf" \
"and al,bl" \
"pushf" \
"pop [edi]" \
parm [edi] [al] [bl] \
value [al] \
modify exact [al bl];
u16 and_word_asm(u32 * flags, u16 d, u16 s);
#pragma aux and_word_asm = \
"push [edi]" \
"popf" \
"and ax,bx" \
"pushf" \
"pop [edi]" \
parm [edi] [ax] [bx] \
value [ax] \
modify exact [ax bx];
u32 and_long_asm(u32 * flags, u32 d, u32 s);
#pragma aux and_long_asm = \
"push [edi]" \
"popf" \
"and eax,ebx" \
"pushf" \
"pop [edi]" \
parm [edi] [eax] [ebx] \
value [eax] \
modify exact [eax ebx];
u8 cmp_byte_asm(u32 * flags, u8 d, u8 s);
#pragma aux cmp_byte_asm = \
"push [edi]" \
"popf" \
"cmp al,bl" \
"pushf" \
"pop [edi]" \
parm [edi] [al] [bl] \
value [al] \
modify exact [al bl];
u16 cmp_word_asm(u32 * flags, u16 d, u16 s);
#pragma aux cmp_word_asm = \
"push [edi]" \
"popf" \
"cmp ax,bx" \
"pushf" \
"pop [edi]" \
parm [edi] [ax] [bx] \
value [ax] \
modify exact [ax bx];
u32 cmp_long_asm(u32 * flags, u32 d, u32 s);
#pragma aux cmp_long_asm = \
"push [edi]" \
"popf" \
"cmp eax,ebx" \
"pushf" \
"pop [edi]" \
parm [edi] [eax] [ebx] \
value [eax] \
modify exact [eax ebx];
u8 daa_byte_asm(u32 * flags, u8 d);
#pragma aux daa_byte_asm = \
"push [edi]" \
"popf" \
"daa" \
"pushf" \
"pop [edi]" \
parm [edi] [al] \
value [al] \
modify exact [al];
u8 das_byte_asm(u32 * flags, u8 d);
#pragma aux das_byte_asm = \
"push [edi]" \
"popf" \
"das" \
"pushf" \
"pop [edi]" \
parm [edi] [al] \
value [al] \
modify exact [al];
u8 dec_byte_asm(u32 * flags, u8 d);
#pragma aux dec_byte_asm = \
"push [edi]" \
"popf" \
"dec al" \
"pushf" \
"pop [edi]" \
parm [edi] [al] \
value [al] \
modify exact [al];
u16 dec_word_asm(u32 * flags, u16 d);
#pragma aux dec_word_asm = \
"push [edi]" \
"popf" \
"dec ax" \
"pushf" \
"pop [edi]" \
parm [edi] [ax] \
value [ax] \
modify exact [ax];
u32 dec_long_asm(u32 * flags, u32 d);
#pragma aux dec_long_asm = \
"push [edi]" \
"popf" \
"dec eax" \
"pushf" \
"pop [edi]" \
parm [edi] [eax] \
value [eax] \
modify exact [eax];
u8 inc_byte_asm(u32 * flags, u8 d);
#pragma aux inc_byte_asm = \
"push [edi]" \
"popf" \
"inc al" \
"pushf" \
"pop [edi]" \
parm [edi] [al] \
value [al] \
modify exact [al];
u16 inc_word_asm(u32 * flags, u16 d);
#pragma aux inc_word_asm = \
"push [edi]" \
"popf" \
"inc ax" \
"pushf" \
"pop [edi]" \
parm [edi] [ax] \
value [ax] \
modify exact [ax];
u32 inc_long_asm(u32 * flags, u32 d);
#pragma aux inc_long_asm = \
"push [edi]" \
"popf" \
"inc eax" \
"pushf" \
"pop [edi]" \
parm [edi] [eax] \
value [eax] \
modify exact [eax];
u8 or_byte_asm(u32 * flags, u8 d, u8 s);
#pragma aux or_byte_asm = \
"push [edi]" \
"popf" \
"or al,bl" \
"pushf" \
"pop [edi]" \
parm [edi] [al] [bl] \
value [al] \
modify exact [al bl];
u16 or_word_asm(u32 * flags, u16 d, u16 s);
#pragma aux or_word_asm = \
"push [edi]" \
"popf" \
"or ax,bx" \
"pushf" \
"pop [edi]" \
parm [edi] [ax] [bx] \
value [ax] \
modify exact [ax bx];
u32 or_long_asm(u32 * flags, u32 d, u32 s);
#pragma aux or_long_asm = \
"push [edi]" \
"popf" \
"or eax,ebx" \
"pushf" \
"pop [edi]" \
parm [edi] [eax] [ebx] \
value [eax] \
modify exact [eax ebx];
u8 neg_byte_asm(u32 * flags, u8 d);
#pragma aux neg_byte_asm = \
"push [edi]" \
"popf" \
"neg al" \
"pushf" \
"pop [edi]" \
parm [edi] [al] \
value [al] \
modify exact [al];
u16 neg_word_asm(u32 * flags, u16 d);
#pragma aux neg_word_asm = \
"push [edi]" \
"popf" \
"neg ax" \
"pushf" \
"pop [edi]" \
parm [edi] [ax] \
value [ax] \
modify exact [ax];
u32 neg_long_asm(u32 * flags, u32 d);
#pragma aux neg_long_asm = \
"push [edi]" \
"popf" \
"neg eax" \
"pushf" \
"pop [edi]" \
parm [edi] [eax] \
value [eax] \
modify exact [eax];
u8 not_byte_asm(u32 * flags, u8 d);
#pragma aux not_byte_asm = \
"push [edi]" \
"popf" \
"not al" \
"pushf" \
"pop [edi]" \
parm [edi] [al] \
value [al] \
modify exact [al];
u16 not_word_asm(u32 * flags, u16 d);
#pragma aux not_word_asm = \
"push [edi]" \
"popf" \
"not ax" \
"pushf" \
"pop [edi]" \
parm [edi] [ax] \
value [ax] \
modify exact [ax];
u32 not_long_asm(u32 * flags, u32 d);
#pragma aux not_long_asm = \
"push [edi]" \
"popf" \
"not eax" \
"pushf" \
"pop [edi]" \
parm [edi] [eax] \
value [eax] \
modify exact [eax];
u8 rcl_byte_asm(u32 * flags, u8 d, u8 s);
#pragma aux rcl_byte_asm = \
"push [edi]" \
"popf" \
"rcl al,cl" \
"pushf" \
"pop [edi]" \
parm [edi] [al] [cl] \
value [al] \
modify exact [al cl];
u16 rcl_word_asm(u32 * flags, u16 d, u8 s);
#pragma aux rcl_word_asm = \
"push [edi]" \
"popf" \
"rcl ax,cl" \
"pushf" \
"pop [edi]" \
parm [edi] [ax] [cl] \
value [ax] \
modify exact [ax cl];
u32 rcl_long_asm(u32 * flags, u32 d, u8 s);
#pragma aux rcl_long_asm = \
"push [edi]" \
"popf" \
"rcl eax,cl" \
"pushf" \
"pop [edi]" \
parm [edi] [eax] [cl] \
value [eax] \
modify exact [eax cl];
u8 rcr_byte_asm(u32 * flags, u8 d, u8 s);
#pragma aux rcr_byte_asm = \
"push [edi]" \
"popf" \
"rcr al,cl" \
"pushf" \
"pop [edi]" \
parm [edi] [al] [cl] \
value [al] \
modify exact [al cl];
u16 rcr_word_asm(u32 * flags, u16 d, u8 s);
#pragma aux rcr_word_asm = \
"push [edi]" \
"popf" \
"rcr ax,cl" \
"pushf" \
"pop [edi]" \
parm [edi] [ax] [cl] \
value [ax] \
modify exact [ax cl];
u32 rcr_long_asm(u32 * flags, u32 d, u8 s);
#pragma aux rcr_long_asm = \
"push [edi]" \
"popf" \
"rcr eax,cl" \
"pushf" \
"pop [edi]" \
parm [edi] [eax] [cl] \
value [eax] \
modify exact [eax cl];
u8 rol_byte_asm(u32 * flags, u8 d, u8 s);
#pragma aux rol_byte_asm = \
"push [edi]" \
"popf" \
"rol al,cl" \
"pushf" \
"pop [edi]" \
parm [edi] [al] [cl] \
value [al] \
modify exact [al cl];
u16 rol_word_asm(u32 * flags, u16 d, u8 s);
#pragma aux rol_word_asm = \
"push [edi]" \
"popf" \
"rol ax,cl" \
"pushf" \
"pop [edi]" \
parm [edi] [ax] [cl] \
value [ax] \
modify exact [ax cl];
u32 rol_long_asm(u32 * flags, u32 d, u8 s);
#pragma aux rol_long_asm = \
"push [edi]" \
"popf" \
"rol eax,cl" \
"pushf" \
"pop [edi]" \
parm [edi] [eax] [cl] \
value [eax] \
modify exact [eax cl];
u8 ror_byte_asm(u32 * flags, u8 d, u8 s);
#pragma aux ror_byte_asm = \
"push [edi]" \
"popf" \
"ror al,cl" \
"pushf" \
"pop [edi]" \
parm [edi] [al] [cl] \
value [al] \
modify exact [al cl];
u16 ror_word_asm(u32 * flags, u16 d, u8 s);
#pragma aux ror_word_asm = \
"push [edi]" \
"popf" \
"ror ax,cl" \
"pushf" \
"pop [edi]" \
parm [edi] [ax] [cl] \
value [ax] \
modify exact [ax cl];
u32 ror_long_asm(u32 * flags, u32 d, u8 s);
#pragma aux ror_long_asm = \
"push [edi]" \
"popf" \
"ror eax,cl" \
"pushf" \
"pop [edi]" \
parm [edi] [eax] [cl] \
value [eax] \
modify exact [eax cl];
u8 shl_byte_asm(u32 * flags, u8 d, u8 s);
#pragma aux shl_byte_asm = \
"push [edi]" \
"popf" \
"shl al,cl" \
"pushf" \
"pop [edi]" \
parm [edi] [al] [cl] \
value [al] \
modify exact [al cl];
u16 shl_word_asm(u32 * flags, u16 d, u8 s);
#pragma aux shl_word_asm = \
"push [edi]" \
"popf" \
"shl ax,cl" \
"pushf" \
"pop [edi]" \
parm [edi] [ax] [cl] \
value [ax] \
modify exact [ax cl];
u32 shl_long_asm(u32 * flags, u32 d, u8 s);
#pragma aux shl_long_asm = \
"push [edi]" \
"popf" \
"shl eax,cl" \
"pushf" \
"pop [edi]" \
parm [edi] [eax] [cl] \
value [eax] \
modify exact [eax cl];
u8 shr_byte_asm(u32 * flags, u8 d, u8 s);
#pragma aux shr_byte_asm = \
"push [edi]" \
"popf" \
"shr al,cl" \
"pushf" \
"pop [edi]" \
parm [edi] [al] [cl] \
value [al] \
modify exact [al cl];
u16 shr_word_asm(u32 * flags, u16 d, u8 s);
#pragma aux shr_word_asm = \
"push [edi]" \
"popf" \
"shr ax,cl" \
"pushf" \
"pop [edi]" \
parm [edi] [ax] [cl] \
value [ax] \
modify exact [ax cl];
u32 shr_long_asm(u32 * flags, u32 d, u8 s);
#pragma aux shr_long_asm = \
"push [edi]" \
"popf" \
"shr eax,cl" \
"pushf" \
"pop [edi]" \
parm [edi] [eax] [cl] \
value [eax] \
modify exact [eax cl];
u8 sar_byte_asm(u32 * flags, u8 d, u8 s);
#pragma aux sar_byte_asm = \
"push [edi]" \
"popf" \
"sar al,cl" \
"pushf" \
"pop [edi]" \
parm [edi] [al] [cl] \
value [al] \
modify exact [al cl];
u16 sar_word_asm(u32 * flags, u16 d, u8 s);
#pragma aux sar_word_asm = \
"push [edi]" \
"popf" \
"sar ax,cl" \
"pushf" \
"pop [edi]" \
parm [edi] [ax] [cl] \
value [ax] \
modify exact [ax cl];
u32 sar_long_asm(u32 * flags, u32 d, u8 s);
#pragma aux sar_long_asm = \
"push [edi]" \
"popf" \
"sar eax,cl" \
"pushf" \
"pop [edi]" \
parm [edi] [eax] [cl] \
value [eax] \
modify exact [eax cl];
u16 shld_word_asm(u32 * flags, u16 d, u16 fill, u8 s);
#pragma aux shld_word_asm = \
"push [edi]" \
"popf" \
"shld ax,dx,cl" \
"pushf" \
"pop [edi]" \
parm [edi] [ax] [dx] [cl] \
value [ax] \
modify exact [ax dx cl];
u32 shld_long_asm(u32 * flags, u32 d, u32 fill, u8 s);
#pragma aux shld_long_asm = \
"push [edi]" \
"popf" \
"shld eax,edx,cl" \
"pushf" \
"pop [edi]" \
parm [edi] [eax] [edx] [cl] \
value [eax] \
modify exact [eax edx cl];
u16 shrd_word_asm(u32 * flags, u16 d, u16 fill, u8 s);
#pragma aux shrd_word_asm = \
"push [edi]" \
"popf" \
"shrd ax,dx,cl" \
"pushf" \
"pop [edi]" \
parm [edi] [ax] [dx] [cl] \
value [ax] \
modify exact [ax dx cl];
u32 shrd_long_asm(u32 * flags, u32 d, u32 fill, u8 s);
#pragma aux shrd_long_asm = \
"push [edi]" \
"popf" \
"shrd eax,edx,cl" \
"pushf" \
"pop [edi]" \
parm [edi] [eax] [edx] [cl] \
value [eax] \
modify exact [eax edx cl];
u8 sbb_byte_asm(u32 * flags, u8 d, u8 s);
#pragma aux sbb_byte_asm = \
"push [edi]" \
"popf" \
"sbb al,bl" \
"pushf" \
"pop [edi]" \
parm [edi] [al] [bl] \
value [al] \
modify exact [al bl];
u16 sbb_word_asm(u32 * flags, u16 d, u16 s);
#pragma aux sbb_word_asm = \
"push [edi]" \
"popf" \
"sbb ax,bx" \
"pushf" \
"pop [edi]" \
parm [edi] [ax] [bx] \
value [ax] \
modify exact [ax bx];
u32 sbb_long_asm(u32 * flags, u32 d, u32 s);
#pragma aux sbb_long_asm = \
"push [edi]" \
"popf" \
"sbb eax,ebx" \
"pushf" \
"pop [edi]" \
parm [edi] [eax] [ebx] \
value [eax] \
modify exact [eax ebx];
u8 sub_byte_asm(u32 * flags, u8 d, u8 s);
#pragma aux sub_byte_asm = \
"push [edi]" \
"popf" \
"sub al,bl" \
"pushf" \
"pop [edi]" \
parm [edi] [al] [bl] \
value [al] \
modify exact [al bl];
u16 sub_word_asm(u32 * flags, u16 d, u16 s);
#pragma aux sub_word_asm = \
"push [edi]" \
"popf" \
"sub ax,bx" \
"pushf" \
"pop [edi]" \
parm [edi] [ax] [bx] \
value [ax] \
modify exact [ax bx];
u32 sub_long_asm(u32 * flags, u32 d, u32 s);
#pragma aux sub_long_asm = \
"push [edi]" \
"popf" \
"sub eax,ebx" \
"pushf" \
"pop [edi]" \
parm [edi] [eax] [ebx] \
value [eax] \
modify exact [eax ebx];
void test_byte_asm(u32 * flags, u8 d, u8 s);
#pragma aux test_byte_asm = \
"push [edi]" \
"popf" \
"test al,bl" \
"pushf" \
"pop [edi]" \
parm [edi] [al] [bl] \
modify exact [al bl];
void test_word_asm(u32 * flags, u16 d, u16 s);
#pragma aux test_word_asm = \
"push [edi]" \
"popf" \
"test ax,bx" \
"pushf" \
"pop [edi]" \
parm [edi] [ax] [bx] \
modify exact [ax bx];
void test_long_asm(u32 * flags, u32 d, u32 s);
#pragma aux test_long_asm = \
"push [edi]" \
"popf" \
"test eax,ebx" \
"pushf" \
"pop [edi]" \
parm [edi] [eax] [ebx] \
modify exact [eax ebx];
u8 xor_byte_asm(u32 * flags, u8 d, u8 s);
#pragma aux xor_byte_asm = \
"push [edi]" \
"popf" \
"xor al,bl" \
"pushf" \
"pop [edi]" \
parm [edi] [al] [bl] \
value [al] \
modify exact [al bl];
u16 xor_word_asm(u32 * flags, u16 d, u16 s);
#pragma aux xor_word_asm = \
"push [edi]" \
"popf" \
"xor ax,bx" \
"pushf" \
"pop [edi]" \
parm [edi] [ax] [bx] \
value [ax] \
modify exact [ax bx];
u32 xor_long_asm(u32 * flags, u32 d, u32 s);
#pragma aux xor_long_asm = \
"push [edi]" \
"popf" \
"xor eax,ebx" \
"pushf" \
"pop [edi]" \
parm [edi] [eax] [ebx] \
value [eax] \
modify exact [eax ebx];
void imul_byte_asm(u32 * flags, u16 * ax, u8 d, u8 s);
#pragma aux imul_byte_asm = \
"push [edi]" \
"popf" \
"imul bl" \
"pushf" \
"pop [edi]" \
"mov [esi],ax" \
parm [edi] [esi] [al] [bl] \
modify exact [esi ax bl];
void imul_word_asm(u32 * flags, u16 * ax, u16 * dx, u16 d, u16 s);
#pragma aux imul_word_asm = \
"push [edi]" \
"popf" \
"imul bx" \
"pushf" \
"pop [edi]" \
"mov [esi],ax" \
"mov [ecx],dx" \
parm [edi] [esi] [ecx] [ax] [bx]\
modify exact [esi edi ax bx dx];
void imul_long_asm(u32 * flags, u32 * eax, u32 * edx, u32 d, u32 s);
#pragma aux imul_long_asm = \
"push [edi]" \
"popf" \
"imul ebx" \
"pushf" \
"pop [edi]" \
"mov [esi],eax" \
"mov [ecx],edx" \
parm [edi] [esi] [ecx] [eax] [ebx] \
modify exact [esi edi eax ebx edx];
void mul_byte_asm(u32 * flags, u16 * ax, u8 d, u8 s);
#pragma aux mul_byte_asm = \
"push [edi]" \
"popf" \
"mul bl" \
"pushf" \
"pop [edi]" \
"mov [esi],ax" \
parm [edi] [esi] [al] [bl] \
modify exact [esi ax bl];
void mul_word_asm(u32 * flags, u16 * ax, u16 * dx, u16 d, u16 s);
#pragma aux mul_word_asm = \
"push [edi]" \
"popf" \
"mul bx" \
"pushf" \
"pop [edi]" \
"mov [esi],ax" \
"mov [ecx],dx" \
parm [edi] [esi] [ecx] [ax] [bx]\
modify exact [esi edi ax bx dx];
void mul_long_asm(u32 * flags, u32 * eax, u32 * edx, u32 d, u32 s);
#pragma aux mul_long_asm = \
"push [edi]" \
"popf" \
"mul ebx" \
"pushf" \
"pop [edi]" \
"mov [esi],eax" \
"mov [ecx],edx" \
parm [edi] [esi] [ecx] [eax] [ebx] \
modify exact [esi edi eax ebx edx];
void idiv_byte_asm(u32 * flags, u8 * al, u8 * ah, u16 d, u8 s);
#pragma aux idiv_byte_asm = \
"push [edi]" \
"popf" \
"idiv bl" \
"pushf" \
"pop [edi]" \
"mov [esi],al" \
"mov [ecx],ah" \
parm [edi] [esi] [ecx] [ax] [bl]\
modify exact [esi edi ax bl];
void idiv_word_asm(u32 * flags, u16 * ax, u16 * dx, u16 dlo, u16 dhi, u16 s);
#pragma aux idiv_word_asm = \
"push [edi]" \
"popf" \
"idiv bx" \
"pushf" \
"pop [edi]" \
"mov [esi],ax" \
"mov [ecx],dx" \
parm [edi] [esi] [ecx] [ax] [dx] [bx]\
modify exact [esi edi ax dx bx];
void idiv_long_asm(u32 * flags, u32 * eax, u32 * edx, u32 dlo, u32 dhi, u32 s);
#pragma aux idiv_long_asm = \
"push [edi]" \
"popf" \
"idiv ebx" \
"pushf" \
"pop [edi]" \
"mov [esi],eax" \
"mov [ecx],edx" \
parm [edi] [esi] [ecx] [eax] [edx] [ebx]\
modify exact [esi edi eax edx ebx];
void div_byte_asm(u32 * flags, u8 * al, u8 * ah, u16 d, u8 s);
#pragma aux div_byte_asm = \
"push [edi]" \
"popf" \
"div bl" \
"pushf" \
"pop [edi]" \
"mov [esi],al" \
"mov [ecx],ah" \
parm [edi] [esi] [ecx] [ax] [bl]\
modify exact [esi edi ax bl];
void div_word_asm(u32 * flags, u16 * ax, u16 * dx, u16 dlo, u16 dhi, u16 s);
#pragma aux div_word_asm = \
"push [edi]" \
"popf" \
"div bx" \
"pushf" \
"pop [edi]" \
"mov [esi],ax" \
"mov [ecx],dx" \
parm [edi] [esi] [ecx] [ax] [dx] [bx]\
modify exact [esi edi ax dx bx];
void div_long_asm(u32 * flags, u32 * eax, u32 * edx, u32 dlo, u32 dhi, u32 s);
#pragma aux div_long_asm = \
"push [edi]" \
"popf" \
"div ebx" \
"pushf" \
"pop [edi]" \
"mov [esi],eax" \
"mov [ecx],edx" \
parm [edi] [esi] [ecx] [eax] [edx] [ebx]\
modify exact [esi edi eax edx ebx];
#endif
#endif /* __X86EMU_PRIM_ASM_H */

View file

@ -0,0 +1,142 @@
/****************************************************************************
*
* Realmode X86 Emulator Library
*
* Copyright (C) 1991-2004 SciTech Software, Inc.
* Copyright (C) David Mosberger-Tang
* Copyright (C) 1999 Egbert Eich
*
* ========================================================================
*
* Permission to use, copy, modify, distribute, and sell this software and
* its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and that
* both that copyright notice and this permission notice appear in
* supporting documentation, and that the name of the authors not be used
* in advertising or publicity pertaining to distribution of the software
* without specific, written prior permission. The authors makes no
* representations about the suitability of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*
* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*
* ========================================================================
*
* Language: ANSI C
* Environment: Any
* Developer: Kendall Bennett
*
* Description: Header file for primitive operation functions.
*
****************************************************************************/
#ifndef __X86EMU_PRIM_OPS_H
#define __X86EMU_PRIM_OPS_H
#ifdef __cplusplus
extern "C" { /* Use "C" linkage when in C++ mode */
#endif
u16 aaa_word (u16 d);
u16 aas_word (u16 d);
u16 aad_word (u16 d);
u16 aam_word (u8 d);
u8 adc_byte (u8 d, u8 s);
u16 adc_word (u16 d, u16 s);
u32 adc_long (u32 d, u32 s);
u8 add_byte (u8 d, u8 s);
u16 add_word (u16 d, u16 s);
u32 add_long (u32 d, u32 s);
u8 and_byte (u8 d, u8 s);
u16 and_word (u16 d, u16 s);
u32 and_long (u32 d, u32 s);
u8 cmp_byte (u8 d, u8 s);
u16 cmp_word (u16 d, u16 s);
u32 cmp_long (u32 d, u32 s);
u8 daa_byte (u8 d);
u8 das_byte (u8 d);
u8 dec_byte (u8 d);
u16 dec_word (u16 d);
u32 dec_long (u32 d);
u8 inc_byte (u8 d);
u16 inc_word (u16 d);
u32 inc_long (u32 d);
u8 or_byte (u8 d, u8 s);
u16 or_word (u16 d, u16 s);
u32 or_long (u32 d, u32 s);
u8 neg_byte (u8 s);
u16 neg_word (u16 s);
u32 neg_long (u32 s);
u8 not_byte (u8 s);
u16 not_word (u16 s);
u32 not_long (u32 s);
u8 rcl_byte (u8 d, u8 s);
u16 rcl_word (u16 d, u8 s);
u32 rcl_long (u32 d, u8 s);
u8 rcr_byte (u8 d, u8 s);
u16 rcr_word (u16 d, u8 s);
u32 rcr_long (u32 d, u8 s);
u8 rol_byte (u8 d, u8 s);
u16 rol_word (u16 d, u8 s);
u32 rol_long (u32 d, u8 s);
u8 ror_byte (u8 d, u8 s);
u16 ror_word (u16 d, u8 s);
u32 ror_long (u32 d, u8 s);
u8 shl_byte (u8 d, u8 s);
u16 shl_word (u16 d, u8 s);
u32 shl_long (u32 d, u8 s);
u8 shr_byte (u8 d, u8 s);
u16 shr_word (u16 d, u8 s);
u32 shr_long (u32 d, u8 s);
u8 sar_byte (u8 d, u8 s);
u16 sar_word (u16 d, u8 s);
u32 sar_long (u32 d, u8 s);
u16 shld_word (u16 d, u16 fill, u8 s);
u32 shld_long (u32 d, u32 fill, u8 s);
u16 shrd_word (u16 d, u16 fill, u8 s);
u32 shrd_long (u32 d, u32 fill, u8 s);
u8 sbb_byte (u8 d, u8 s);
u16 sbb_word (u16 d, u16 s);
u32 sbb_long (u32 d, u32 s);
u8 sub_byte (u8 d, u8 s);
u16 sub_word (u16 d, u16 s);
u32 sub_long (u32 d, u32 s);
void test_byte (u8 d, u8 s);
void test_word (u16 d, u16 s);
void test_long (u32 d, u32 s);
u8 xor_byte (u8 d, u8 s);
u16 xor_word (u16 d, u16 s);
u32 xor_long (u32 d, u32 s);
void imul_byte (u8 s);
void imul_word (u16 s);
void imul_long (u32 s);
void imul_long_direct(u32 *res_lo, u32* res_hi,u32 d, u32 s);
void mul_byte (u8 s);
void mul_word (u16 s);
void mul_long (u32 s);
void idiv_byte (u8 s);
void idiv_word (u16 s);
void idiv_long (u32 s);
void div_byte (u8 s);
void div_word (u16 s);
void div_long (u32 s);
void ins (int size);
void outs (int size);
u16 mem_access_word (int addr);
void push_word (u16 w);
void push_long (u32 w);
u16 pop_word (void);
u32 pop_long (void);
#ifdef __cplusplus
} /* End of "C" linkage for C++ */
#endif
#endif /* __X86EMU_PRIM_OPS_H */

View file

@ -0,0 +1,340 @@
/****************************************************************************
*
* Realmode X86 Emulator Library
*
* Copyright (C) 1991-2004 SciTech Software, Inc.
* Copyright (C) David Mosberger-Tang
* Copyright (C) 1999 Egbert Eich
*
* ========================================================================
*
* Permission to use, copy, modify, distribute, and sell this software and
* its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and that
* both that copyright notice and this permission notice appear in
* supporting documentation, and that the name of the authors not be used
* in advertising or publicity pertaining to distribution of the software
* without specific, written prior permission. The authors makes no
* representations about the suitability of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*
* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*
* ========================================================================
*
* Language: ANSI C
* Environment: Any
* Developer: Kendall Bennett
*
* Description: Header file for x86 register definitions.
*
****************************************************************************/
#ifndef __X86EMU_REGS_H
#define __X86EMU_REGS_H
/*---------------------- Macros and type definitions ----------------------*/
#pragma pack(1)
/*
* General EAX, EBX, ECX, EDX type registers. Note that for
* portability, and speed, the issue of byte swapping is not addressed
* in the registers. All registers are stored in the default format
* available on the host machine. The only critical issue is that the
* registers should line up EXACTLY in the same manner as they do in
* the 386. That is:
*
* EAX & 0xff === AL
* EAX & 0xffff == AX
*
* etc. The result is that alot of the calculations can then be
* done using the native instruction set fully.
*/
#ifdef __BIG_ENDIAN__
typedef struct {
u32 e_reg;
} I32_reg_t;
typedef struct {
u16 filler0, x_reg;
} I16_reg_t;
typedef struct {
u8 filler0, filler1, h_reg, l_reg;
} I8_reg_t;
#else /* !__BIG_ENDIAN__ */
typedef struct {
u32 e_reg;
} I32_reg_t;
typedef struct {
u16 x_reg;
} I16_reg_t;
typedef struct {
u8 l_reg, h_reg;
} I8_reg_t;
#endif /* BIG_ENDIAN */
typedef union {
I32_reg_t I32_reg;
I16_reg_t I16_reg;
I8_reg_t I8_reg;
} i386_general_register;
struct i386_general_regs {
i386_general_register A, B, C, D;
};
typedef struct i386_general_regs Gen_reg_t;
struct i386_special_regs {
i386_general_register SP, BP, SI, DI, IP;
u32 FLAGS;
};
/*
* Segment registers here represent the 16 bit quantities
* CS, DS, ES, SS.
*/
#undef CS
#undef DS
#undef SS
#undef ES
#undef FS
#undef GS
struct i386_segment_regs {
u16 CS, DS, SS, ES, FS, GS;
};
/* 8 bit registers */
#define R_AH gen.A.I8_reg.h_reg
#define R_AL gen.A.I8_reg.l_reg
#define R_BH gen.B.I8_reg.h_reg
#define R_BL gen.B.I8_reg.l_reg
#define R_CH gen.C.I8_reg.h_reg
#define R_CL gen.C.I8_reg.l_reg
#define R_DH gen.D.I8_reg.h_reg
#define R_DL gen.D.I8_reg.l_reg
/* 16 bit registers */
#define R_AX gen.A.I16_reg.x_reg
#define R_BX gen.B.I16_reg.x_reg
#define R_CX gen.C.I16_reg.x_reg
#define R_DX gen.D.I16_reg.x_reg
/* 32 bit extended registers */
#define R_EAX gen.A.I32_reg.e_reg
#define R_EBX gen.B.I32_reg.e_reg
#define R_ECX gen.C.I32_reg.e_reg
#define R_EDX gen.D.I32_reg.e_reg
/* special registers */
#define R_SP spc.SP.I16_reg.x_reg
#define R_BP spc.BP.I16_reg.x_reg
#define R_SI spc.SI.I16_reg.x_reg
#define R_DI spc.DI.I16_reg.x_reg
#define R_IP spc.IP.I16_reg.x_reg
#define R_FLG spc.FLAGS
/* special registers */
#define R_SP spc.SP.I16_reg.x_reg
#define R_BP spc.BP.I16_reg.x_reg
#define R_SI spc.SI.I16_reg.x_reg
#define R_DI spc.DI.I16_reg.x_reg
#define R_IP spc.IP.I16_reg.x_reg
#define R_FLG spc.FLAGS
/* special registers */
#define R_ESP spc.SP.I32_reg.e_reg
#define R_EBP spc.BP.I32_reg.e_reg
#define R_ESI spc.SI.I32_reg.e_reg
#define R_EDI spc.DI.I32_reg.e_reg
#define R_EIP spc.IP.I32_reg.e_reg
#define R_EFLG spc.FLAGS
/* segment registers */
#define R_CS seg.CS
#define R_DS seg.DS
#define R_SS seg.SS
#define R_ES seg.ES
#define R_FS seg.FS
#define R_GS seg.GS
/* flag conditions */
#define FB_CF 0x0001 /* CARRY flag */
#define FB_PF 0x0004 /* PARITY flag */
#define FB_AF 0x0010 /* AUX flag */
#define FB_ZF 0x0040 /* ZERO flag */
#define FB_SF 0x0080 /* SIGN flag */
#define FB_TF 0x0100 /* TRAP flag */
#define FB_IF 0x0200 /* INTERRUPT ENABLE flag */
#define FB_DF 0x0400 /* DIR flag */
#define FB_OF 0x0800 /* OVERFLOW flag */
/* 80286 and above always have bit#1 set */
#define F_ALWAYS_ON (0x0002) /* flag bits always on */
/*
* Define a mask for only those flag bits we will ever pass back
* (via PUSHF)
*/
#define F_MSK (FB_CF|FB_PF|FB_AF|FB_ZF|FB_SF|FB_TF|FB_IF|FB_DF|FB_OF)
/* following bits masked in to a 16bit quantity */
#define F_CF 0x0001 /* CARRY flag */
#define F_PF 0x0004 /* PARITY flag */
#define F_AF 0x0010 /* AUX flag */
#define F_ZF 0x0040 /* ZERO flag */
#define F_SF 0x0080 /* SIGN flag */
#define F_TF 0x0100 /* TRAP flag */
#define F_IF 0x0200 /* INTERRUPT ENABLE flag */
#define F_DF 0x0400 /* DIR flag */
#define F_OF 0x0800 /* OVERFLOW flag */
#define TOGGLE_FLAG(flag) (M.x86.R_FLG ^= (flag))
#define SET_FLAG(flag) (M.x86.R_FLG |= (flag))
#define CLEAR_FLAG(flag) (M.x86.R_FLG &= ~(flag))
#define ACCESS_FLAG(flag) (M.x86.R_FLG & (flag))
#define CLEARALL_FLAG(m) (M.x86.R_FLG = 0)
#define CONDITIONAL_SET_FLAG(COND,FLAG) \
if (COND) SET_FLAG(FLAG); else CLEAR_FLAG(FLAG)
#define F_PF_CALC 0x010000 /* PARITY flag has been calced */
#define F_ZF_CALC 0x020000 /* ZERO flag has been calced */
#define F_SF_CALC 0x040000 /* SIGN flag has been calced */
#define F_ALL_CALC 0xff0000 /* All have been calced */
/*
* Emulator machine state.
* Segment usage control.
*/
#define SYSMODE_SEG_DS_SS 0x00000001
#define SYSMODE_SEGOVR_CS 0x00000002
#define SYSMODE_SEGOVR_DS 0x00000004
#define SYSMODE_SEGOVR_ES 0x00000008
#define SYSMODE_SEGOVR_FS 0x00000010
#define SYSMODE_SEGOVR_GS 0x00000020
#define SYSMODE_SEGOVR_SS 0x00000040
#define SYSMODE_PREFIX_REPE 0x00000080
#define SYSMODE_PREFIX_REPNE 0x00000100
#define SYSMODE_PREFIX_DATA 0x00000200
#define SYSMODE_PREFIX_ADDR 0x00000400
#define SYSMODE_INTR_PENDING 0x10000000
#define SYSMODE_EXTRN_INTR 0x20000000
#define SYSMODE_HALTED 0x40000000
#define SYSMODE_SEGMASK (SYSMODE_SEG_DS_SS | \
SYSMODE_SEGOVR_CS | \
SYSMODE_SEGOVR_DS | \
SYSMODE_SEGOVR_ES | \
SYSMODE_SEGOVR_FS | \
SYSMODE_SEGOVR_GS | \
SYSMODE_SEGOVR_SS)
#define SYSMODE_CLRMASK (SYSMODE_SEG_DS_SS | \
SYSMODE_SEGOVR_CS | \
SYSMODE_SEGOVR_DS | \
SYSMODE_SEGOVR_ES | \
SYSMODE_SEGOVR_FS | \
SYSMODE_SEGOVR_GS | \
SYSMODE_SEGOVR_SS | \
SYSMODE_PREFIX_DATA | \
SYSMODE_PREFIX_ADDR)
#define INTR_SYNCH 0x1
#define INTR_ASYNCH 0x2
#define INTR_HALTED 0x4
typedef struct {
struct i386_general_regs gen;
struct i386_special_regs spc;
struct i386_segment_regs seg;
/*
* MODE contains information on:
* REPE prefix 2 bits repe,repne
* SEGMENT overrides 5 bits normal,DS,SS,CS,ES
* Delayed flag set 3 bits (zero, signed, parity)
* reserved 6 bits
* interrupt # 8 bits instruction raised interrupt
* BIOS video segregs 4 bits
* Interrupt Pending 1 bits
* Extern interrupt 1 bits
* Halted 1 bits
*/
long mode;
u8 intno;
volatile int intr; /* mask of pending interrupts */
int debug;
#ifdef DEBUG
int check;
u16 saved_ip;
u16 saved_cs;
int enc_pos;
int enc_str_pos;
char decode_buf[32]; /* encoded byte stream */
char decoded_buf[256]; /* disassembled strings */
#endif
} X86EMU_regs;
/****************************************************************************
REMARKS:
Structure maintaining the emulator machine state.
MEMBERS:
x86 - X86 registers
mem_base - Base real mode memory for the emulator
mem_size - Size of the real mode memory block for the emulator
****************************************************************************/
#undef x86
typedef struct {
X86EMU_regs x86;
u8 *mem_base;
u32 mem_size;
void *private;
} X86EMU_sysEnv;
#pragma pack()
/*----------------------------- Global Variables --------------------------*/
#ifdef __cplusplus
extern "C" { /* Use "C" linkage when in C++ mode */
#endif
/* Global emulator machine state.
*
* We keep it global to avoid pointer dereferences in the code for speed.
*/
extern X86EMU_sysEnv _X86EMU_env;
#define M _X86EMU_env
/*-------------------------- Function Prototypes --------------------------*/
/* Function to log information at runtime */
#ifndef __KERNEL__
void printk(const char *fmt, ...);
#endif
#ifdef __cplusplus
} /* End of "C" linkage for C++ */
#endif
#endif /* __X86EMU_REGS_H */

View file

@ -0,0 +1,101 @@
/****************************************************************************
*
* Realmode X86 Emulator Library
*
* Copyright (C) 1991-2004 SciTech Software, Inc.
* Copyright (C) David Mosberger-Tang
* Copyright (C) 1999 Egbert Eich
*
* ========================================================================
*
* Permission to use, copy, modify, distribute, and sell this software and
* its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and that
* both that copyright notice and this permission notice appear in
* supporting documentation, and that the name of the authors not be used
* in advertising or publicity pertaining to distribution of the software
* without specific, written prior permission. The authors makes no
* representations about the suitability of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*
* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*
* ========================================================================
*
* Language: ANSI C
* Environment: Any
* Developer: Kendall Bennett
*
* Description: Header file for system specific functions. These functions
* are always compiled and linked in the OS depedent libraries,
* and never in a binary portable driver.
*
****************************************************************************/
#ifndef __X86EMU_X86EMUI_H
#define __X86EMU_X86EMUI_H
/* If we are compiling in C++ mode, we can compile some functions as
* inline to increase performance (however the code size increases quite
* dramatically in this case).
*/
#if defined(__cplusplus) && !defined(_NO_INLINE)
#define _INLINE inline
#else
#define _INLINE static
#endif
/* Get rid of unused parameters in C++ compilation mode */
#ifdef __cplusplus
#define X86EMU_UNUSED(v)
#else
#define X86EMU_UNUSED(v) v
#endif
#include "x86emu.h"
#include "x86emu/regs.h"
#include "x86emu/debug.h"
#include "x86emu/decode.h"
#include "x86emu/ops.h"
#include "x86emu/prim_ops.h"
#ifndef __KERNEL__
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#endif
#define printk printf
/*--------------------------- Inline Functions ----------------------------*/
#ifdef __cplusplus
extern "C" { /* Use "C" linkage when in C++ mode */
#endif
extern u8(X86APIP sys_rdb) (u32 addr);
extern u16(X86APIP sys_rdw) (u32 addr);
extern u32(X86APIP sys_rdl) (u32 addr);
extern void (X86APIP sys_wrb) (u32 addr, u8 val);
extern void (X86APIP sys_wrw) (u32 addr, u16 val);
extern void (X86APIP sys_wrl) (u32 addr, u32 val);
extern u8(X86APIP sys_inb) (X86EMU_pioAddr addr);
extern u16(X86APIP sys_inw) (X86EMU_pioAddr addr);
extern u32(X86APIP sys_inl) (X86EMU_pioAddr addr);
extern void (X86APIP sys_outb) (X86EMU_pioAddr addr, u8 val);
extern void (X86APIP sys_outw) (X86EMU_pioAddr addr, u16 val);
extern void (X86APIP sys_outl) (X86EMU_pioAddr addr, u32 val);
#ifdef __cplusplus
} /* End of "C" linkage for C++ */
#endif
#endif /* __X86EMU_X86EMUI_H */

View file

@ -0,0 +1,461 @@
/****************************************************************************
*
* Realmode X86 Emulator Library
*
* Copyright (C) 1991-2004 SciTech Software, Inc.
* Copyright (C) David Mosberger-Tang
* Copyright (C) 1999 Egbert Eich
*
* ========================================================================
*
* Permission to use, copy, modify, distribute, and sell this software and
* its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and that
* both that copyright notice and this permission notice appear in
* supporting documentation, and that the name of the authors not be used
* in advertising or publicity pertaining to distribution of the software
* without specific, written prior permission. The authors makes no
* representations about the suitability of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*
* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*
* ========================================================================
*
* Language: ANSI C
* Environment: Any
* Developer: Kendall Bennett
*
* Description: This file contains the code to handle debugging of the
* emulator.
*
****************************************************************************/
#include "x86emu/x86emui.h"
#include <stdarg.h>
/*----------------------------- Implementation ----------------------------*/
#ifdef DEBUG
static void print_encoded_bytes(u16 s, u16 o);
static void print_decoded_instruction(void);
static int parse_line(char *s, int *ps, int *n);
/* should look something like debug's output. */
void X86EMU_trace_regs(void)
{
if (DEBUG_TRACE()) {
x86emu_dump_regs();
}
if (DEBUG_DECODE() && !DEBUG_DECODE_NOPRINT()) {
printk("%04x:%04x ", M.x86.saved_cs, M.x86.saved_ip);
print_encoded_bytes(M.x86.saved_cs, M.x86.saved_ip);
print_decoded_instruction();
}
}
void X86EMU_trace_xregs(void)
{
if (DEBUG_TRACE()) {
x86emu_dump_xregs();
}
}
void x86emu_just_disassemble(void)
{
/*
* This routine called if the flag DEBUG_DISASSEMBLE is set kind
* of a hack!
*/
printk("%04x:%04x ", M.x86.saved_cs, M.x86.saved_ip);
print_encoded_bytes(M.x86.saved_cs, M.x86.saved_ip);
print_decoded_instruction();
}
static void disassemble_forward(u16 seg, u16 off, int n)
{
X86EMU_sysEnv tregs;
int i;
u8 op1;
/*
* hack, hack, hack. What we do is use the exact machinery set up
* for execution, except that now there is an additional state
* flag associated with the "execution", and we are using a copy
* of the register struct. All the major opcodes, once fully
* decoded, have the following two steps: TRACE_REGS(r,m);
* SINGLE_STEP(r,m); which disappear if DEBUG is not defined to
* the preprocessor. The TRACE_REGS macro expands to:
*
* if (debug&DEBUG_DISASSEMBLE)
* {just_disassemble(); goto EndOfInstruction;}
* if (debug&DEBUG_TRACE) trace_regs(r,m);
*
* ...... and at the last line of the routine.
*
* EndOfInstruction: end_instr();
*
* Up to the point where TRACE_REG is expanded, NO modifications
* are done to any register EXCEPT the IP register, for fetch and
* decoding purposes.
*
* This was done for an entirely different reason, but makes a
* nice way to get the system to help debug codes.
*/
tregs = M;
tregs.x86.R_IP = off;
tregs.x86.R_CS = seg;
/* reset the decoding buffers */
tregs.x86.enc_str_pos = 0;
tregs.x86.enc_pos = 0;
/* turn on the "disassemble only, no execute" flag */
tregs.x86.debug |= DEBUG_DISASSEMBLE_F;
/* DUMP NEXT n instructions to screen in straight_line fashion */
/*
* This looks like the regular instruction fetch stream, except
* that when this occurs, each fetched opcode, upon seeing the
* DEBUG_DISASSEMBLE flag set, exits immediately after decoding
* the instruction. XXX --- CHECK THAT MEM IS NOT AFFECTED!!!
* Note the use of a copy of the register structure...
*/
for (i = 0; i < n; i++) {
op1 = (*sys_rdb) (((u32) M.x86.R_CS << 4) + (M.x86.R_IP++));
(x86emu_optab[op1]) (op1);
}
/* end major hack mode. */
}
void x86emu_check_ip_access(void)
{
/* NULL as of now */
}
void x86emu_check_sp_access(void)
{
}
void x86emu_check_mem_access(u32 dummy)
{
/* check bounds, etc */
}
void x86emu_check_data_access(uint dummy1, uint dummy2)
{
/* check bounds, etc */
}
void x86emu_inc_decoded_inst_len(int x)
{
M.x86.enc_pos += x;
}
void x86emu_decode_printf(char *x)
{
sprintf(M.x86.decoded_buf + M.x86.enc_str_pos, "%s", x);
M.x86.enc_str_pos += strlen(x);
}
void x86emu_decode_printf2(char *x, int y)
{
char temp[100];
sprintf(temp, x, y);
sprintf(M.x86.decoded_buf + M.x86.enc_str_pos, "%s", temp);
M.x86.enc_str_pos += strlen(temp);
}
void x86emu_end_instr(void)
{
M.x86.enc_str_pos = 0;
M.x86.enc_pos = 0;
}
static void print_encoded_bytes(u16 s, u16 o)
{
int i;
char buf1[64];
for (i = 0; i < M.x86.enc_pos; i++) {
sprintf(buf1 + 2 * i, "%02x", fetch_data_byte_abs(s, o + i));
}
printk("%-20s", buf1);
}
static void print_decoded_instruction(void)
{
printk("%s", M.x86.decoded_buf);
}
void x86emu_print_int_vect(u16 iv)
{
u16 seg, off;
if (iv > 256)
return;
seg = fetch_data_word_abs(0, iv * 4);
off = fetch_data_word_abs(0, iv * 4 + 2);
printk("%04x:%04x ", seg, off);
}
void X86EMU_dump_memory(u16 seg, u16 off, u32 amt)
{
u32 start = off & 0xfffffff0;
u32 end = (off + 16) & 0xfffffff0;
u32 i;
u32 current;
current = start;
while (end <= off + amt) {
printk("%04x:%04x ", seg, start);
for (i = start; i < off; i++)
printk(" ");
for (; i < end; i++)
printk("%02x ", fetch_data_byte_abs(seg, i));
printk("\n");
start = end;
end = start + 16;
}
}
void x86emu_single_step(void)
{
char s[1024];
int ps[10];
int ntok;
int cmd;
int done;
int segment;
int offset;
static int breakpoint;
static int noDecode = 1;
char *p;
if (DEBUG_BREAK()) {
if (M.x86.saved_ip != breakpoint) {
return;
} else {
M.x86.debug &= ~DEBUG_DECODE_NOPRINT_F;
M.x86.debug |= DEBUG_TRACE_F;
M.x86.debug &= ~DEBUG_BREAK_F;
print_decoded_instruction();
X86EMU_trace_regs();
}
}
done = 0;
offset = M.x86.saved_ip;
while (!done) {
printk("-");
cmd = parse_line(s, ps, &ntok);
switch (cmd) {
case 'u':
disassemble_forward(M.x86.saved_cs, (u16) offset, 10);
break;
case 'd':
if (ntok == 2) {
segment = M.x86.saved_cs;
offset = ps[1];
X86EMU_dump_memory(segment, (u16) offset, 16);
offset += 16;
} else if (ntok == 3) {
segment = ps[1];
offset = ps[2];
X86EMU_dump_memory(segment, (u16) offset, 16);
offset += 16;
} else {
segment = M.x86.saved_cs;
X86EMU_dump_memory(segment, (u16) offset, 16);
offset += 16;
}
break;
case 'c':
M.x86.debug ^= DEBUG_TRACECALL_F;
break;
case 's':
M.x86.debug ^=
DEBUG_SVC_F | DEBUG_SYS_F | DEBUG_SYSINT_F;
break;
case 'r':
X86EMU_trace_regs();
break;
case 'x':
X86EMU_trace_xregs();
break;
case 'g':
if (ntok == 2) {
breakpoint = ps[1];
if (noDecode) {
M.x86.debug |= DEBUG_DECODE_NOPRINT_F;
} else {
M.x86.debug &= ~DEBUG_DECODE_NOPRINT_F;
}
M.x86.debug &= ~DEBUG_TRACE_F;
M.x86.debug |= DEBUG_BREAK_F;
done = 1;
}
break;
case 'q':
M.x86.debug |= DEBUG_EXIT;
return;
case 'P':
noDecode = (noDecode) ? 0 : 1;
printk("Toggled decoding to %s\n",
(noDecode) ? "FALSE" : "TRUE");
break;
case 't':
case 0:
done = 1;
break;
}
}
}
int X86EMU_trace_on(void)
{
return M.x86.debug |= DEBUG_STEP_F | DEBUG_DECODE_F | DEBUG_TRACE_F;
}
int X86EMU_trace_off(void)
{
return M.x86.debug &= ~(DEBUG_STEP_F | DEBUG_DECODE_F | DEBUG_TRACE_F);
}
static int parse_line(char *s, int *ps, int *n)
{
int cmd;
*n = 0;
while (*s == ' ' || *s == '\t')
s++;
ps[*n] = *s;
switch (*s) {
case '\n':
*n += 1;
return 0;
default:
cmd = *s;
*n += 1;
}
while (1) {
while (*s != ' ' && *s != '\t' && *s != '\n')
s++;
if (*s == '\n')
return cmd;
while (*s == ' ' || *s == '\t')
s++;
*n += 1;
}
}
#endif /* DEBUG */
void x86emu_dump_regs(void)
{
printk("\tAX=%04x ", M.x86.R_AX);
printk("BX=%04x ", M.x86.R_BX);
printk("CX=%04x ", M.x86.R_CX);
printk("DX=%04x ", M.x86.R_DX);
printk("SP=%04x ", M.x86.R_SP);
printk("BP=%04x ", M.x86.R_BP);
printk("SI=%04x ", M.x86.R_SI);
printk("DI=%04x\n", M.x86.R_DI);
printk("\tDS=%04x ", M.x86.R_DS);
printk("ES=%04x ", M.x86.R_ES);
printk("SS=%04x ", M.x86.R_SS);
printk("CS=%04x ", M.x86.R_CS);
printk("IP=%04x ", M.x86.R_IP);
if (ACCESS_FLAG(F_OF))
printk("OV "); /* CHECKED... */
else
printk("NV ");
if (ACCESS_FLAG(F_DF))
printk("DN ");
else
printk("UP ");
if (ACCESS_FLAG(F_IF))
printk("EI ");
else
printk("DI ");
if (ACCESS_FLAG(F_SF))
printk("NG ");
else
printk("PL ");
if (ACCESS_FLAG(F_ZF))
printk("ZR ");
else
printk("NZ ");
if (ACCESS_FLAG(F_AF))
printk("AC ");
else
printk("NA ");
if (ACCESS_FLAG(F_PF))
printk("PE ");
else
printk("PO ");
if (ACCESS_FLAG(F_CF))
printk("CY ");
else
printk("NC ");
printk("\n");
}
void x86emu_dump_xregs(void)
{
printk("\tEAX=%08x ", M.x86.R_EAX);
printk("EBX=%08x ", M.x86.R_EBX);
printk("ECX=%08x ", M.x86.R_ECX);
printk("EDX=%08x \n", M.x86.R_EDX);
printk("\tESP=%08x ", M.x86.R_ESP);
printk("EBP=%08x ", M.x86.R_EBP);
printk("ESI=%08x ", M.x86.R_ESI);
printk("EDI=%08x\n", M.x86.R_EDI);
printk("\tDS=%04x ", M.x86.R_DS);
printk("ES=%04x ", M.x86.R_ES);
printk("SS=%04x ", M.x86.R_SS);
printk("CS=%04x ", M.x86.R_CS);
printk("EIP=%08x\n\t", M.x86.R_EIP);
if (ACCESS_FLAG(F_OF))
printk("OV "); /* CHECKED... */
else
printk("NV ");
if (ACCESS_FLAG(F_DF))
printk("DN ");
else
printk("UP ");
if (ACCESS_FLAG(F_IF))
printk("EI ");
else
printk("DI ");
if (ACCESS_FLAG(F_SF))
printk("NG ");
else
printk("PL ");
if (ACCESS_FLAG(F_ZF))
printk("ZR ");
else
printk("NZ ");
if (ACCESS_FLAG(F_AF))
printk("AC ");
else
printk("NA ");
if (ACCESS_FLAG(F_PF))
printk("PE ");
else
printk("PO ");
if (ACCESS_FLAG(F_CF))
printk("CY ");
else
printk("NC ");
printk("\n");
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,322 @@
/****************************************************************************
*
* Realmode X86 Emulator Library
*
* Copyright (C) 1991-2004 SciTech Software, Inc.
* Copyright (C) David Mosberger-Tang
* Copyright (C) 1999 Egbert Eich
*
* ========================================================================
*
* Permission to use, copy, modify, distribute, and sell this software and
* its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and that
* both that copyright notice and this permission notice appear in
* supporting documentation, and that the name of the authors not be used
* in advertising or publicity pertaining to distribution of the software
* without specific, written prior permission. The authors makes no
* representations about the suitability of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*
* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*
* ========================================================================
*
* Language: ANSI C
* Environment: Any
* Developer: Kendall Bennett
*
* Description: This file includes subroutines which are related to
* programmed I/O and memory access. Included in this module
* are default functions that do nothing. For real uses these
* functions will have to be overriden by the user library.
*
****************************************************************************/
#include "x86emu/x86emui.h"
/*------------------------- Global Variables ------------------------------*/
X86EMU_sysEnv _X86EMU_env; /* Global emulator machine state */
X86EMU_intrFuncs _X86EMU_intrTab[256];
int debug_intr;
/*----------------------------- Implementation ----------------------------*/
/****************************************************************************
PARAMETERS:
addr - Emulator memory address to read
RETURNS:
Byte value read from emulator memory.
REMARKS:
Reads a byte value from the emulator memory.
****************************************************************************/
u8 X86API rdb(u32 addr)
{
return 0;
}
/****************************************************************************
PARAMETERS:
addr - Emulator memory address to read
RETURNS:
Word value read from emulator memory.
REMARKS:
Reads a word value from the emulator memory.
****************************************************************************/
u16 X86API rdw(u32 addr)
{
return 0;
}
/****************************************************************************
PARAMETERS:
addr - Emulator memory address to read
RETURNS:
Long value read from emulator memory.
REMARKS:
Reads a long value from the emulator memory.
****************************************************************************/
u32 X86API rdl(u32 addr)
{
return 0;
}
/****************************************************************************
PARAMETERS:
addr - Emulator memory address to read
val - Value to store
REMARKS:
Writes a byte value to emulator memory.
****************************************************************************/
void X86API wrb(u32 addr, u8 val)
{
}
/****************************************************************************
PARAMETERS:
addr - Emulator memory address to read
val - Value to store
REMARKS:
Writes a word value to emulator memory.
****************************************************************************/
void X86API wrw(u32 addr, u16 val)
{
}
/****************************************************************************
PARAMETERS:
addr - Emulator memory address to read
val - Value to store
REMARKS:
Writes a long value to emulator memory.
****************************************************************************/
void X86API wrl(u32 addr, u32 val)
{
}
/****************************************************************************
PARAMETERS:
addr - PIO address to read
RETURN:
0
REMARKS:
Default PIO byte read function. Doesn't perform real inb.
****************************************************************************/
static u8 X86API p_inb(X86EMU_pioAddr addr)
{
DB(if (DEBUG_IO_TRACE())
printk("inb %#04x \n", addr);)
return 0;
}
/****************************************************************************
PARAMETERS:
addr - PIO address to read
RETURN:
0
REMARKS:
Default PIO word read function. Doesn't perform real inw.
****************************************************************************/
static u16 X86API p_inw(X86EMU_pioAddr addr)
{
DB(if (DEBUG_IO_TRACE())
printk("inw %#04x \n", addr);)
return 0;
}
/****************************************************************************
PARAMETERS:
addr - PIO address to read
RETURN:
0
REMARKS:
Default PIO long read function. Doesn't perform real inl.
****************************************************************************/
static u32 X86API p_inl(X86EMU_pioAddr addr)
{
DB(if (DEBUG_IO_TRACE())
printk("inl %#04x \n", addr);)
return 0;
}
/****************************************************************************
PARAMETERS:
addr - PIO address to write
val - Value to store
REMARKS:
Default PIO byte write function. Doesn't perform real outb.
****************************************************************************/
static void X86API p_outb(X86EMU_pioAddr addr, u8 val)
{
DB(if (DEBUG_IO_TRACE())
printk("outb %#02x -> %#04x \n", val, addr);)
return;
}
/****************************************************************************
PARAMETERS:
addr - PIO address to write
val - Value to store
REMARKS:
Default PIO word write function. Doesn't perform real outw.
****************************************************************************/
static void X86API p_outw(X86EMU_pioAddr addr, u16 val)
{
DB(if (DEBUG_IO_TRACE())
printk("outw %#04x -> %#04x \n", val, addr);)
return;
}
/****************************************************************************
PARAMETERS:
addr - PIO address to write
val - Value to store
REMARKS:
Default PIO ;ong write function. Doesn't perform real outl.
****************************************************************************/
static void X86API p_outl(X86EMU_pioAddr addr, u32 val)
{
DB(if (DEBUG_IO_TRACE())
printk("outl %#08x -> %#04x \n", val, addr);)
return;
}
/*------------------------- Global Variables ------------------------------*/
u8(X86APIP sys_rdb) (u32 addr) = rdb;
u16(X86APIP sys_rdw) (u32 addr) = rdw;
u32(X86APIP sys_rdl) (u32 addr) = rdl;
void (X86APIP sys_wrb) (u32 addr, u8 val) = wrb;
void (X86APIP sys_wrw) (u32 addr, u16 val) = wrw;
void (X86APIP sys_wrl) (u32 addr, u32 val) = wrl;
u8(X86APIP sys_inb) (X86EMU_pioAddr addr) = p_inb;
u16(X86APIP sys_inw) (X86EMU_pioAddr addr) = p_inw;
u32(X86APIP sys_inl) (X86EMU_pioAddr addr) = p_inl;
void (X86APIP sys_outb) (X86EMU_pioAddr addr, u8 val) = p_outb;
void (X86APIP sys_outw) (X86EMU_pioAddr addr, u16 val) = p_outw;
void (X86APIP sys_outl) (X86EMU_pioAddr addr, u32 val) = p_outl;
/*----------------------------- Setup -------------------------------------*/
/****************************************************************************
PARAMETERS:
funcs - New memory function pointers to make active
REMARKS:
This function is used to set the pointers to functions which access
memory space, allowing the user application to override these functions
and hook them out as necessary for their application.
****************************************************************************/
void X86EMU_setupMemFuncs(X86EMU_memFuncs * funcs)
{
sys_rdb = funcs->rdb;
sys_rdw = funcs->rdw;
sys_rdl = funcs->rdl;
sys_wrb = funcs->wrb;
sys_wrw = funcs->wrw;
sys_wrl = funcs->wrl;
}
/****************************************************************************
PARAMETERS:
funcs - New programmed I/O function pointers to make active
REMARKS:
This function is used to set the pointers to functions which access
I/O space, allowing the user application to override these functions
and hook them out as necessary for their application.
****************************************************************************/
void X86EMU_setupPioFuncs(X86EMU_pioFuncs * funcs)
{
sys_inb = funcs->inb;
sys_inw = funcs->inw;
sys_inl = funcs->inl;
sys_outb = funcs->outb;
sys_outw = funcs->outw;
sys_outl = funcs->outl;
}
/****************************************************************************
PARAMETERS:
funcs - New interrupt vector table to make active
REMARKS:
This function is used to set the pointers to functions which handle
interrupt processing in the emulator, allowing the user application to
hook interrupts as necessary for their application. Any interrupts that
are not hooked by the user application, and reflected and handled internally
in the emulator via the interrupt vector table. This allows the application
to get control when the code being emulated executes specific software
interrupts.
****************************************************************************/
void X86EMU_setupIntrFuncs(X86EMU_intrFuncs funcs[])
{
int i;
for (i = 0; i < 256; i++)
_X86EMU_intrTab[i] = NULL;
if (funcs) {
for (i = 0; i < 256; i++)
_X86EMU_intrTab[i] = funcs[i];
}
}
/****************************************************************************
PARAMETERS:
int - New software interrupt to prepare for
REMARKS:
This function is used to set up the emulator state to exceute a software
interrupt. This can be used by the user application code to allow an
interrupt to be hooked, examined and then reflected back to the emulator
so that the code in the emulator will continue processing the software
interrupt as per normal. This essentially allows system code to actively
hook and handle certain software interrupts as necessary.
****************************************************************************/
void X86EMU_prepareForInt(int num)
{
push_word((u16) M.x86.R_FLG);
CLEAR_FLAG(F_IF);
CLEAR_FLAG(F_TF);
push_word(M.x86.R_CS);
M.x86.R_CS = mem_access_word(num * 4 + 2);
push_word(M.x86.R_IP);
M.x86.R_IP = mem_access_word(num * 4);
M.x86.intr = 0;
}